diff options
author | Peter Tribble <peter.tribble@gmail.com> | 2019-06-09 16:11:04 +0100 |
---|---|---|
committer | Peter Tribble <peter.tribble@gmail.com> | 2019-08-15 22:54:30 +0100 |
commit | c4ccc1f9004b70b07e4cdb57641c38ab607306c9 (patch) | |
tree | f5c7b05f8a893d6ea12da8819e6a7efa93059948 | |
parent | dcfeff93f67a1188722a358e0fbfcd604993e573 (diff) | |
download | illumos-joyent-c4ccc1f9004b70b07e4cdb57641c38ab607306c9.tar.gz |
11226 Remove NetraCT support
Reviewed by: Gergő Doma <domag02@gmail.com>
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Approved by: Garrett D'Amore <garrett@damore.org>
127 files changed, 30 insertions, 52302 deletions
diff --git a/exception_lists/check_rtime b/exception_lists/check_rtime index a4f7885214..d1c4b95420 100644 --- a/exception_lists/check_rtime +++ b/exception_lists/check_rtime @@ -23,6 +23,7 @@ # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2018 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2019 Peter Tribble. # # This file provides exceptions to the usual rules applied to ELF objects by @@ -244,10 +245,3 @@ FORBIDDEN_DEP usr/ucblib/ FORBIDDEN libm\.so\.1 FORBIDDEN libresolv\.so\.1 FORBIDDEN libxcurses\.so\.1 - -# The libprtdiag_psr.so.1 objects built under usr/src/lib/libprtdiag_psr -# are a family, all built using the same makefile, targeted at different -# sparc hardware variants. There are a small number of cases where this -# one size fits all approach causes an object to be linked against an -# unneeded library. -UNREF_OBJ lib/(libdevinfo|libcfgadm)\.so\.1; .*\ of\ .*SUNW,Netra-CP2300/lib/libprtdiag_psr\.so\.1 diff --git a/exception_lists/closed-bins b/exception_lists/closed-bins index 04c7421b9b..ced3be10b1 100644 --- a/exception_lists/closed-bins +++ b/exception_lists/closed-bins @@ -58,6 +58,7 @@ ./lib/sparcv9/libc_i18n.a ./platform/i86pc/kernel/cpu/cpu_ms.GenuineIntel.6.46 ./platform/i86pc/kernel/cpu/cpu_ms.GenuineIntel.6.47 +./platform/sun4u/kernel/drv/sparcv9/ctsmc ./platform/sun4v/kernel/drv/ncp.conf ./platform/sun4v/kernel/drv/n2cp.conf ./usr/has diff --git a/exception_lists/packaging b/exception_lists/packaging index ee4a68cdd5..caa19a9102 100644 --- a/exception_lists/packaging +++ b/exception_lists/packaging @@ -346,9 +346,6 @@ etc/svc/profile/platform_SUNW,SPARC-Enterprise.xml i386 etc/svc/profile/platform_SUNW,Sun-Fire-880.xml i386 etc/svc/profile/platform_SUNW,Sun-Fire-V890.xml i386 etc/svc/profile/platform_SUNW,Sun-Fire.xml i386 -etc/svc/profile/platform_SUNW,UltraSPARC-IIe-NetraCT-40.xml i386 -etc/svc/profile/platform_SUNW,UltraSPARC-IIe-NetraCT-60.xml i386 -etc/svc/profile/platform_SUNW,UltraSPARC-IIi-Netract.xml i386 # # Private libuutil files # diff --git a/usr/src/cmd/netadm/iu.ap.sh b/usr/src/cmd/netadm/iu.ap.sh index 9ac9b143d4..a7247daf2e 100644 --- a/usr/src/cmd/netadm/iu.ap.sh +++ b/usr/src/cmd/netadm/iu.ap.sh @@ -20,6 +20,7 @@ # CDDL HEADER END # # +# Copyright 2019 Peter Tribble. # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -72,7 +73,6 @@ case "$MACH" in usbsprl -1 0 ldterm ttcompat usbsksp -1 0 ldterm ttcompat usbftdi -1 0 ldterm ttcompat - ttymux -1 0 ldterm ttcompat ipsecesp -1 0 ipsecesp ipsecah -1 0 ipsecah oplmsu 0 0 ldterm ttcompat diff --git a/usr/src/cmd/picl/plugins/sun4u/Makefile b/usr/src/cmd/picl/plugins/sun4u/Makefile index b35c001756..2de3454ef2 100644 --- a/usr/src/cmd/picl/plugins/sun4u/Makefile +++ b/usr/src/cmd/picl/plugins/sun4u/Makefile @@ -22,9 +22,7 @@ # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright 2019 Peter Tribble. # # cmd/picl/plugins/sun4u/Makefile # @@ -34,11 +32,11 @@ include $(SRC)/Makefile.master SUBDIRS= lib .WAIT envmon .WAIT \ frudata grover excalibur psvc littleneck daktari \ cherrystone lw2plus lw8 taco enchilada chicago blade mpxu ents \ - chalupa silverstone sebring snowbird schumacher seattle boston .WAIT + chalupa silverstone sebring schumacher seattle boston .WAIT MSGSUBDIRS= lib frudata grover excalibur psvc littleneck daktari \ cherrystone lw2plus lw8 taco enchilada chicago blade envmon mpxu ents \ - silverstone sebring snowbird + silverstone sebring all := TARGET= all install := TARGET= install diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/Makefile deleted file mode 100644 index 6b83a0cd5c..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# include library definitions -include $(SRC)/lib/Makefile.lib -include $(SRC)/Makefile.psm - -PLATFORM = SUNW,Netra-CP2300 - -ROOTLIBDIR = $(ROOT_PLAT_PLUGINDIR) - -SUBDIRS= lib conf frutree envmond watchdog .WAIT -MSGSUBDIRS= frutree envmond watchdog - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -.KEEP_STATE: - -all clean clobber lint: $(SUBDIRS) - -install: $(SUBDIRS) - -_msg: $(MSGSUBDIRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/Makefile deleted file mode 100644 index d2bf411ca6..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include $(SRC)/Makefile.psm - -# include library definitions -include $(SRC)/lib/Makefile.lib - -PLATFORM = SUNW,Netra-CP2300 -ROOT_PLATFORM = $(USR_PLAT_DIR)/$(PLATFORM) - -include $(SRC)/cmd/picl/plugins/Makefile.com - -ROOTLIBDIR = $(ROOT_PLAT_PLUGINDIR) - -CONF_2300 = SUNW,Netra-CP2300.conf SUNW,Netra-CP2300.RTM.conf envmond.conf - -ROOTCONF_2300 = $(CONF_2300:%=$(ROOTLIBDIR)/%) -$(ROOTCONF_2300) := FILEMODE = 0644 -ROOTLINTDIR_2300 = $(ROOTLIBDIR) - -.KEEP_STATE: - -SUBDIRS= - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint - -all: - -install: $(ROOTLIBDIR) $(ROOTCONF_2300) - -$(CONF_2300): FRC - $(RM) $(ROOTLIBPLUGINDIR)/$@ - $(INS) -s -m 0644 -f $(ROOT_PLAT_PLUGINDIR) $@ - -# include library targets -include $(SRC)/lib/Makefile.targ -include $(SRC)/cmd/picl/plugins/Makefile.targ - -$(ROOTLINTDIR_2300)/%: ../% - $(INS.file) - -lint: - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/SUNW,Netra-CP2300.RTM.conf b/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/SUNW,Netra-CP2300.RTM.conf deleted file mode 100644 index 2230a177f0..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/SUNW,Netra-CP2300.RTM.conf +++ /dev/null @@ -1,100 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#pragma ident "%Z%%M% %I% %E% SMI" -VERSION 1.0 - -NODE CPU location - PROP State string r 0 "connected" - PROP SlotType string r 0 "pci" - PROP Label string r 0 "CPU" - PROP devfs-path string r 0 "/pci@1f,0" - PROP PdevProbePath string r 0 "" - PROP bus-addr string r 0 "1,1" - NODE CPU fru - PROP FRUType string r 0 "bridge/fhs" - PROP State string r 0 "configured" - PROP Condition string r 0 "unknown" - PROP AdminLock string rw 0 "disabled" - NODE PMC-1 location - PROP SlotType string r 0 "pci" - PROP Label string r 0 "PMC-A" - PROP bus-addr string r 0 "0x1" - PROP GeoAddr uint r 1 1 - PROP devfs-path string r 0 "/pci@1f,0/pci@1" - ENDNODE - NODE PMC-2 location - PROP SlotType string r 0 "pci" - PROP Label string r 0 "PMC-B" - PROP bus-addr string r 0 "0x2" - PROP GeoAddr uint r 1 2 - PROP devfs-path string r 0 "/pci@1f,0/pci@1" - ENDNODE - ENDNODE -ENDNODE -NODE RTM location - PROP State string r 0 "connected" - PROP SlotType string r 0 "rtm" - PROP Label string r 0 "RTM" - PROP PdevProbePath string r 0 "/pci@1f,0" - PROP bus-addr string r 0 "1,1" - NODE RTM fru - PROP FRUType string r 0 "RTM" - PROP State string r 0 "configured" - PROP Condition string r 0 "ok" - PROP AdminLock string rw 0 "disabled" - NODE su0 port - PROP Label string r 0 "COM-A" - PROP bus-addr string r 0 "0,3f8" - PROP GeoAddr uint r 1 1 - PROP PortType string r 0 "serial" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1/isa@7" - ENDNODE - - NODE su1 port - PROP Label string r 0 "COM-B" - PROP bus-addr string r 0 "0,2e8" - PROP GeoAddr uint r 1 2 - PROP PortType string r 0 "serial" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1/isa@7" - ENDNODE - - NODE dmfe0 port - PROP Label string r 0 "ETHERNET A" - PROP bus-addr string r 0 "1" - PROP GeoAddr uint r 1 1 - PROP PortType string r 0 "network" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1" - ENDNODE - - NODE dmfe1 port - PROP Label string r 0 "ETHERNET B" - PROP bus-addr string r 0 "2" - PROP GeoAddr uint r 1 2 - PROP PortType string r 0 "network" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1" - ENDNODE - ENDNODE -ENDNODE diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/SUNW,Netra-CP2300.conf b/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/SUNW,Netra-CP2300.conf deleted file mode 100644 index 8970f5f94c..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/SUNW,Netra-CP2300.conf +++ /dev/null @@ -1,83 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#pragma ident "%Z%%M% %I% %E% SMI" -VERSION 1.0 - -NODE CPU location - PROP State string r 0 "connected" - PROP SlotType string r 0 "pci" - PROP Label string r 0 "CPU" - PROP bus-addr string r 0 "1,1" - PROP devfs-path string r 0 "/pci@1f,0" - PROP PdevProbePath string r 0 "/pci@1f,0" - NODE CPU fru - PROP FRUType string r 0 "bridge/fhs" - PROP State string r 0 "configured" - PROP Condition string r 0 "unknown" - PROP AdminLock string rw 0 "disabled" - NODE PMC-1 location - PROP SlotType string r 0 "pci" - PROP Label string r 0 "PMC-A" - PROP bus-addr string r 0 "0x1" - PROP GeoAddr uint r 1 1 - PROP devfs-path string r 0 "/pci@1f,0/pci@1" - ENDNODE - NODE PMC-2 location - PROP SlotType string r 0 "pci" - PROP Label string r 0 "PMC-B" - PROP bus-addr string r 0 "0x2" - PROP GeoAddr uint r 1 2 - PROP devfs-path string r 0 "/pci@1f,0/pci@1" - ENDNODE - NODE su0 port - PROP Label string r 0 "COM" - PROP bus-addr string r 0 "0,3f8" - PROP GeoAddr uint r 1 1 - PROP PortType string r 0 "serial" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1/isa@7" - ENDNODE - NODE dmfe0 port - PROP Label string r 0 "ETHERNET A" - PROP bus-addr string r 0 "1" - PROP GeoAddr uint r 1 1 - PROP PortType string r 0 "network" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1" - ENDNODE - - NODE dmfe1 port - PROP Label string r 0 "ETHERNET B" - PROP bus-addr string r 0 "2" - PROP GeoAddr uint r 1 2 - PROP PortType string r 0 "network" - PROP devfs-path string r 0 "/pci@1f,0/pci@1,1" - ENDNODE - ENDNODE -ENDNODE -NODE RTM location - PROP Label string r 0 "RTM" - PROP State string r 0 "empty" - PROP SlotType string r 0 "rtm" -ENDNODE diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/envmond.conf b/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/envmond.conf deleted file mode 100644 index bb0b1e2ba2..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/conf/envmond.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#pragma ident "%Z%%M% %I% %E% SMI" -# -# The line format is: -# interval policy_name policy_args -10 alarmcard diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/Makefile deleted file mode 100644 index c2a2d7e3e7..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/Makefile +++ /dev/null @@ -1,106 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include $(SRC)/Makefile.psm - -LIBRARY = libpiclenvmond.a -VERS = .1 -PLATFORM = SUNW,Netra-CP2300 - -OBJECTS= piclenvmond.o piclsensors.o picldr.o piclplatmod.o - -# include library definitions -include $(SRC)/lib/Makefile.lib - -ROOT_PLATFORM = $(USR_PLAT_DIR)/$(PLATFORM) - -include $(SRC)/cmd/picl/plugins/Makefile.com - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -D_SNOWBIRD \ - -I$(USR_PSM_INCL_DIR) \ - -I$(SRC)/uts/sun4u/sys \ - -I$(SRC)/cmd/picl/plugins/inc \ - -I$(SRC)/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc - -SRCS= $(OBJECTS:%.o=%.c) - -LIBS = $(DYNLIB) - -ROOTLIBDIR = $(ROOT_PLAT_PLUGINDIR) - -CLEANFILES = $(LINTOUT) $(LINTLIB) - -LDLIBS += -L$(SRC)/lib/libptree/$(MACH) -LDLIBS += -L$(SRC)/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc -LDLIBS += -L$(ROOT)/usr/lib/picl/plugins -lc -lpicltree \ - -lpicl -lnvpair -lm -ldevinfo -lcfgadm \ - -lpiclfrutree -lrcm -lctsmc -LDLIBS += -R/usr/platform/$(PLATFORM)/lib -LDLIBS += -R/usr/platform/$(PLATFORM)/lib/picl/plugins -LDLIBS += -R/usr/platform/sun4u/lib/picl/plugins:/usr/lib/picl/plugins - -.KEEP_STATE: - -SUBDIRS= - -POFILE= snowbird_piclenvmond.po -POFILES= $(SRCS:%.c=%.po) - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -all: $(LIBS) $(LIBLINKS) - -install: $(ROOTLIBDIR) all $(ROOTLIBS) $(ROOTLINKS) - -$(LIBLINKS): FRC - $(RM) $@; $(SYMLINK) ./$(DYNLIB) $@ - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN)/$(POFILE) - -$(POFILE): $(POFILES) - $(CAT) $(POFILES) > $(POFILE) - -$(MSGDOMAIN): - $(INS.dir) - -# include library targets -include $(SRC)/lib/Makefile.targ -include $(SRC)/cmd/picl/plugins/Makefile.targ - -lint : - $(LINT.c) $(SRCS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/picldr.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/picldr.c deleted file mode 100644 index 9fa6a7cb27..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/picldr.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <sys/systeminfo.h> -#include <pthread.h> -#include <syslog.h> -#include <picl.h> -#include <picltree.h> -#include <picldefs.h> -#include <string.h> -#include <strings.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stropts.h> -#include <assert.h> -#include <libnvpair.h> -#include <libintl.h> -#include <poll.h> -#include <smclib.h> -#include "piclenvmond.h" -#include "picldr.h" - -/* external functions */ -extern picl_errno_t env_platmod_init(); -extern void env_platmod_handle_event(const char *, const void *, size_t); -extern picl_errno_t env_platmod_create_sensors(); -extern picl_errno_t env_platmod_setup_hotswap(); -extern picl_errno_t env_platmod_sp_monitor(); -extern picl_errno_t env_platmod_handle_bus_if_change(uint8_t); -extern picl_errno_t env_platmod_handle_latch_open(); -extern void env_platmod_handle_sensor_event(void *); -extern int process_platmod_sp_state_change_notif(void *); -extern int process_platmod_change_cpu_node_state(void *); -extern int process_platmod_change_cpci_state(void *); -extern int process_platmod_async_msg_notif(void *); -extern void process_platmod_sp_heartbeat(uint8_t); -extern picl_errno_t env_platmod_create_hotswap_prop(); -extern picl_errno_t env_create_property(int ptype, int pmode, - size_t psize, char *pname, int (*readfn)(ptree_rarg_t *, void *), - int (*writefn)(ptree_warg_t *, const void *), - picl_nodehdl_t nodeh, picl_prophdl_t *propp, void *vbuf); -extern char *strtok_r(char *s1, const char *s2, char **lasts); - -/* external variables */ -extern int env_debug; - -static char sys_name[SYS_NMLN]; -static char chassisconf_name[SYS_NMLN]; -static boolean_t parse_config_file = B_FALSE; -static int8_t alarm_check_interval = -1; -static picl_nodehdl_t frutreeh = 0; -static pthread_t polling_threadID; -static boolean_t create_polling_thr = B_TRUE; - -/* globals */ -uint8_t cpu_geo_addr = 0; -picl_nodehdl_t rooth = 0, chassis_nodehdl = 0, cpu_nodehdl = 0; -picl_nodehdl_t platformh = 0, sysmgmth = 0, cpu_lnodehdl = 0; - -/* - * envmond policy structure - */ -typedef struct _policy { - uint8_t interval; - char *pname; - char *argp; - struct _policy *nextp; -} env_policy_t; - -/* - * read_policy_configuration - extract info. from the envmond.conf - */ -static int -env_read_policy_configuration(char *conffile, env_policy_t **policypp) -{ - FILE *fp; - char buf[RECORD_MAXSIZE]; - char *token, *lasts; - env_policy_t *policyp; - - if ((fp = fopen(conffile, "r")) == NULL) { - return (-1); - } - while (fgets(buf, sizeof (buf), fp) != NULL) { - if (buf[0] && (buf[0] == '#' || buf[0] == '\n')) { - continue; - } - token = (char *)strtok_r(buf, RECORD_WHITESPACE, &lasts); - if (token == NULL) { - continue; - } - policyp = (env_policy_t *)malloc(sizeof (env_policy_t)); - if (policyp == NULL) { - goto errors; - } - policyp->interval = (uint8_t)strtoul(token, NULL, 0); - token = (char *)strtok_r(lasts, RECORD_WHITESPACE, &lasts); - if (token == NULL) { - free(policyp); - } else { - policyp->pname = strdup(token); - if (NULL == policyp->pname) { - goto errors; - } - } - if (lasts) { - policyp->argp = strdup(lasts); - if (policyp->argp == NULL) { - goto errors; - } - } else { - policyp->argp = NULL; - } - policyp->nextp = *policypp; - *policypp = policyp; - } - (void) fclose(fp); - return (0); - -errors: - (void) fclose(fp); - while (*policypp) { - policyp = *policypp; - *policypp = (*policypp)->nextp; - free(policyp->pname); - free(policyp->argp); - free(policyp); - } - return (-1); -} - -/* - * supports environmental policies - */ -static void -env_parse_config_file() -{ - char conffile[MAXPATHLEN]; - env_policy_t *policyp, *tmp; - struct stat st; - - if (parse_config_file == B_FALSE) { - return; - } - (void) snprintf(conffile, sizeof (conffile), ENV_CONFIG_FILE, - sys_name); - bzero(&st, sizeof (st)); - if (stat(conffile, &st) == -1) { - return; - } - - policyp = NULL; - if (env_read_policy_configuration(conffile, &policyp) == -1) { - return; - } - assert(policyp); - - while (policyp) { - tmp = policyp; - policyp = policyp->nextp; - if (strcmp(tmp->pname, SERVICE_PROCESSOR) == 0) { - alarm_check_interval = tmp->interval; - if (env_debug & DEBUG) - syslog(LOG_INFO, "Alarm Heartbeat frequency: " - "%d seconds", alarm_check_interval); - } - free(tmp->pname); - free(tmp->argp); - free(tmp); - } -} - -/* - * detects the presence of RTM for CPU board - */ -static boolean_t -is_rtm_present() -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t size = 0; - - req_pkt.data[0] = ENV_RTM_BUS_ID; - req_pkt.data[1] = ENV_RTM_SLAVE_ADDR; - req_pkt.data[2] = ENV_RTM_READ_SIZE; - size = ENV_RTM_PKT_LEN; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_MASTER_RW_CMD, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (B_FALSE); - } - return (B_TRUE); -} - -/* - * this routine does the following: - * 1. initializes the CPU geo-addr - * 2. gets the system name - * 3. create the chassis type property - * 4. creates the conf_file property - */ -static picl_errno_t -env_set_cpu_info() -{ - int rc = 0; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t size = 0; - char conf_name[PICL_PROPNAMELEN_MAX]; - - /* get the geo_addr */ - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_GET_GEOGRAPHICAL_ADDRESS, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (PICL_FAILURE); - } - cpu_geo_addr = rsp_pkt.data[0]; - - /* get the system name */ - if (sysinfo(SI_PLATFORM, sys_name, sizeof (sys_name)) == -1) { - return (PICL_FAILURE); - } - (void) strncpy(chassisconf_name, sys_name, - sizeof (chassisconf_name)); - - /* initialize the node handles */ - if ((rc = ptree_get_root(&rooth)) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_node_by_path(FRUTREE_PATH, &frutreeh)) != - PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, - &chassis_nodehdl)) != PICL_SUCCESS) { - return (rc); - } - - /* create the chassis type property */ - if ((rc = env_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ, PICL_PROPNAMELEN_MAX, PICL_PROP_CHASSIS_TYPE, - NULLREAD, NULLWRITE, chassis_nodehdl, (picl_prophdl_t *)NULL, - chassisconf_name)) != PICL_SUCCESS) { - return (rc); - } - - /* - * create dummy prop to inform frutree plugin abt conf file - * (rtm based or w/o rtm) - * frutree plugin removes this prop after reading the value - */ - if (is_rtm_present() == B_TRUE) { - (void) snprintf(conf_name, sizeof (conf_name), - "%s.RTM.conf", chassisconf_name); - } else { - (void) snprintf(conf_name, sizeof (conf_name), - "%s.conf", chassisconf_name); - } - - if ((rc = env_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ, PICL_PROPNAMELEN_MAX, PICL_PROP_CONF_FILE, NULLREAD, - NULLWRITE, chassis_nodehdl, (picl_prophdl_t *)NULL, - conf_name)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * initialization - */ -picl_errno_t -env_init() -{ - picl_errno_t rc = PICL_SUCCESS; - - if ((rc = env_set_cpu_info()) != PICL_SUCCESS) { - return (rc); - } - - /* parse the configuration file */ - env_parse_config_file(); - - /* - * do any platform specific intialization if required - * IMPORTANT: must post dr_incoming resource event on - * chassis after doing all the reqd checks - */ - rc = env_platmod_init(); - return (rc); -} - -/* - * sets smc global enables - */ -static int -env_set_smc_global_enables(boolean_t ipmi_enable) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t size = 0; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_GET_GLOBAL_ENABLES, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - - req_pkt.data[0] = rsp_pkt.data[0]; - req_pkt.data[1] = rsp_pkt.data[1]; - if (ipmi_enable) { - req_pkt.data[1] |= ENV_IPMI_ENABLE_MASK; - req_pkt.data[1] &= ENV_SENSOR_ENABLE_MASK; - } else { - req_pkt.data[1] &= ENV_IPMI_DISABLE_MASK; - req_pkt.data[1] |= ENV_SENSOR_DISABLE_MASK; - } - size = ENV_SET_GLOBAL_PKT_LEN; - (void) smc_init_smc_msg(&req_pkt, SMC_SET_GLOBAL_ENABLES, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - return (0); -} - -/* - * wrapper smc drv open - */ -int -env_open_smc(void) -{ - int fd; - if ((fd = open(SMC_NODE, O_RDWR)) < 0) { - return (-1); - } - return (fd); -} - -static picl_smc_event_t -env_handle_smc_local_event(void *res_datap) -{ - picl_errno_t rc = PICL_SUCCESS; - uint8_t event = SMC_LOCAL_EVENT; - uint8_t event_data = BYTE_0(res_datap); - - if (env_debug & EVENTS) - syslog(LOG_INFO, "Local Event Received, data %x\n", event_data); - - switch (event_data) { - case SMC_LOCAL_EVENT_BRIDGE_IN_RESET : /*FALLTHRU*/ - case SMC_LOCAL_EVENT_BRIDGE_OUT_OF_RESET : - if ((rc = env_platmod_handle_bus_if_change( - event_data)) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error" - " in handling bus interface change " - "event, error = %d"), rc); - } - break; - case SMC_LOCAL_EVENT_LATCH_OPENED: - syslog(LOG_INFO, gettext("LATCH OPEN DETECTED")); - if ((rc = env_platmod_handle_latch_open()) != - PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error" - " in handling latch open event, " - "error = %d"), rc); - } - break; - default: - break; - } - return (event); -} - -static void -env_handle_async_msg_event(void *res_datap) -{ - int rc = SMC_SUCCESS; - uint8_t event = BYTE_6(res_datap); - - if (env_debug & EVENTS) - syslog(LOG_INFO, "Asynchronous Event %x Received, data %x\n", - event, BYTE_7(res_datap)); - switch (event) { - /* - * This message comes to CPU when the service processor is going offline - * or online. - */ - case EVENT_MSG_AC_STATE_CHANGE: - if ((rc = process_platmod_sp_state_change_notif(res_datap)) != - SMC_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in handling" - "service processor change of state event, " - "error = %d"), rc); - } - break; - /* - * This message comes to CPU when service processor - * requests the CPU to go online or offline (shutdown). - */ - case EVENT_MSG_CHANGE_CPU_NODE_STATE: - if ((rc = process_platmod_change_cpu_node_state(res_datap)) != - SMC_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in handling" - "cpu change of state event, error = %d"), rc); - } - break; - /* - * This message comes to CPU(Satellite) when the - * other node (Host) is going online or offline. - */ - case EVENT_MSG_CHANGE_CPCI_STATE: - if ((rc = process_platmod_change_cpci_state(res_datap)) != - SMC_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in handling" - "cpci change state event, error = %d"), rc); - } - break; - /* - * This message comes from service processor to inform - * change in states for other nodes - */ - case EVENT_MSG_ASYNC_EVENT_NOTIFICATION: - if ((rc = process_platmod_async_msg_notif(res_datap)) != - SMC_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in handling" - "async event notification, error = %d"), rc); - } - break; - case MSG_GET_CPU_NODE_STATE: - /* respond to the service processor heartbeat */ - process_platmod_sp_heartbeat(BYTE_5(res_datap)); - break; - default: - event = NO_EVENT; - break; - } -} - -/*ARGSUSED*/ -static picl_smc_event_t -env_process_smc_event(int fd, void **datapp) -{ - sc_rspmsg_t rsp_msg; - picl_smc_event_t event; - void *res_datap = NULL; - - if (read(fd, (char *)&rsp_msg, SC_MSG_MAX_SIZE) < 0) { - return (NO_EVENT); - } - - if (SC_MSG_CC(&rsp_msg) != 0) { - return (NO_EVENT); - } - - res_datap = SC_MSG_DATA(&rsp_msg); - if (env_debug & EVENTS) - syslog(LOG_INFO, "Async Msg Cmd,data0,2 = %x,%x,%x\n", - SC_MSG_CMD(&rsp_msg), BYTE_0(res_datap), - BYTE_2(res_datap)); - - if (SC_MSG_CMD(&rsp_msg) == SMC_SMC_LOCAL_EVENT_NOTIF) { - event = env_handle_smc_local_event(res_datap); - } else { /* it must be an IPMI event */ - switch (BYTE_2(res_datap)) { - case 0x3: - case 0x4: - if (env_debug & DEBUG) - syslog(LOG_INFO, gettext("SUNW_envmond: " - " Sensor Event Received\n")); - /* sensor event */ - switch (BYTE_3(res_datap)) { - case TEMPERATURE_SENSOR_TYPE: - event = TEMPERATURE_SENSOR_EVENT; - env_platmod_handle_sensor_event(res_datap); - break; - default: - syslog(LOG_ERR, gettext("SUNW_envmond:Unknown " - "sensor Event:%d\n"), BYTE_3(res_datap)); - event = NO_EVENT; - break; - } - default: - env_handle_async_msg_event(res_datap); - break; - } - } - return (event); -} - -/* - * polls SMC driver for SMC events - */ -/*ARGSUSED*/ -static void * -env_polling_thread(void *args) -{ - int poll_rc; - struct pollfd poll_fds[1]; - void *datap; - int smcfd; - struct strioctl strio; - sc_cmdspec_t set; - - smcfd = env_open_smc(); - if (smcfd == -1) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in polling, " - "Open of SMC drv failed")); - create_polling_thr = B_TRUE; - return (NULL); - } - - set.args[0] = SMC_SENSOR_EVENT_ENABLE_SET; - set.attribute = SC_ATTR_SHARED; - strio.ic_cmd = SCIOC_MSG_SPEC; - strio.ic_timout = 0; - strio.ic_len = ENV_SENSOR_EV_ENABLE_PKT_LEN; - strio.ic_dp = (char *)&set; - if (ioctl(smcfd, I_STR, &strio) < 0) { - syslog(LOG_ERR, gettext("SUNW_envmond:Request for " - "Sensor events failed")); - (void) close(smcfd); - create_polling_thr = B_TRUE; - return (NULL); - } - - /* request for async messages */ - poll_fds[0].fd = smcfd; - poll_fds[0].events = POLLIN|POLLPRI; - poll_fds[0].revents = 0; - - set.attribute = SC_ATTR_SHARED; - set.args[0] = SMC_IPMI_RESPONSE_NOTIF; - set.args[1] = SMC_SMC_LOCAL_EVENT_NOTIF; - strio.ic_cmd = SCIOC_MSG_SPEC; - strio.ic_timout = 0; - strio.ic_len = ENV_IPMI_SMC_ENABLE_PKT_LEN; - strio.ic_dp = (char *)&set; - if (ioctl(smcfd, I_STR, &strio) == -1) { - syslog(LOG_ERR, gettext("SUNW_envmond:Request for" - "Async messages failed")); - (void) close(smcfd); - create_polling_thr = B_TRUE; - return (NULL); - } - - /* Now wait for SMC events to come */ - for (;;) { - poll_rc = poll(poll_fds, 1, -1); /* poll forever */ - if (poll_rc < 0) { - syslog(LOG_ERR, gettext("SUNW_envmond:Event " - "processing halted")); - break; - } - if (env_process_smc_event(smcfd, &datap) == NO_EVENT) { - syslog(LOG_ERR, gettext("SUNW_envmond:" - "wrong event data posted from SMC")); - } - } - (void) close(smcfd); - create_polling_thr = B_TRUE; - return (NULL); -} - -/* - * (to be)Called during chassis configuration. It does the following tasks. - * Set global enables on SMC - * Register for local(SMC) events and remote(IPMI) messages (State Change msgs) - * creates sensor nodes - * Initialize hotswap - * Initiallize the interaction with service processor - */ -static picl_errno_t -env_start_services(void) -{ - int rc; - if (env_debug & DEBUG) { - syslog(LOG_INFO, "env_start_services begin"); - } - - /* set the SMC global enables */ - if (env_set_smc_global_enables(B_TRUE) == -1) { - syslog(LOG_ERR, gettext("SUNW_envmond:Setting SMC " - "Globals failed")); - return (PICL_FAILURE); - } - - /* start a worker thread to poll for SMC events */ - if (create_polling_thr) { - rc = pthread_create(&polling_threadID, NULL, - &env_polling_thread, NULL); - if (rc != 0) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in " - "creating polling thread")); - return (PICL_FAILURE); - } - create_polling_thr = B_FALSE; - } - - /* create the sensor nodes */ - if ((rc = env_platmod_create_sensors()) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in creating sensor" - " nodes, error = %d"), rc); - } - - /* intialize the hotswap framework */ - if ((rc = env_platmod_setup_hotswap()) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in hotswap " - "initialization, error = %d"), rc); - } - - if ((rc = env_platmod_create_hotswap_prop()) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in creating " - "hotswap prop, error = %d"), rc); - } - - /* intialize interaction with service processor */ - if ((rc = env_platmod_sp_monitor()) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Failed to interact with" - " service processor, error = %d"), rc); - } - return (PICL_SUCCESS); -} - -static picl_errno_t -env_handle_chassis_configuring_event(char *state) -{ - picl_errno_t rc = PICL_SUCCESS; - picl_prophdl_t proph; - picl_nodehdl_t rtm_lnodehdl = 0; - char *cpu_name = PICL_NODE_CPU; - char *rtm_name = PICL_NODE_RTM; - uint64_t status_time; - - if (strcmp(state, PICLEVENTARGVAL_CONFIGURING) != 0) { - return (PICL_SUCCESS); - } - - /* initialize cpu loc node handle */ - if (cpu_lnodehdl == 0) { - if ((rc = ptree_find_node(chassis_nodehdl, - PICL_PROP_NAME, PICL_PTYPE_CHARSTRING, - cpu_name, (strlen(cpu_name) + 1), - &cpu_lnodehdl)) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond: failed " - " to get CPU nodehdl, error = %d"), rc); - return (rc); - } - } - - /* create geo-addr prop under CPU location */ - if (ptree_get_prop_by_name(cpu_lnodehdl, PICL_PROP_GEO_ADDR, - &proph) == PICL_PROPNOTFOUND) { - if ((rc = env_create_property(PICL_PTYPE_UNSIGNED_INT, - PICL_READ, sizeof (cpu_geo_addr), - PICL_PROP_GEO_ADDR, NULLREAD, NULLWRITE, - cpu_lnodehdl, &proph, - (void *)&cpu_geo_addr)) != PICL_SUCCESS) { - return (rc); - } - } - if (ptree_get_prop_by_name(cpu_lnodehdl, - PICL_PROP_STATUS_TIME, &proph) != PICL_SUCCESS) { - status_time = (uint64_t)time(NULL); - (void) env_create_property(PICL_PTYPE_TIMESTAMP, - PICL_READ, sizeof (status_time), - PICL_PROP_STATUS_TIME, NULLREAD, NULLWRITE, - cpu_lnodehdl, &proph, &status_time); - } - - /* create geo address property for RTM node (if present) */ - (void) ptree_find_node(chassis_nodehdl, - PICL_PROP_NAME, PICL_PTYPE_CHARSTRING, rtm_name, - (strlen(rtm_name) + 1), &rtm_lnodehdl); - - if (rtm_lnodehdl == 0) { /* RTM not present */ - return (PICL_SUCCESS); - } - - if (ptree_get_prop_by_name(rtm_lnodehdl, PICL_PROP_GEO_ADDR, - &proph) == PICL_PROPNOTFOUND) { - if ((rc = env_create_property(PICL_PTYPE_UNSIGNED_INT, - PICL_READ, sizeof (cpu_geo_addr), PICL_PROP_GEO_ADDR, - NULLREAD, NULLWRITE, rtm_lnodehdl, &proph, - &cpu_geo_addr)) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Failed " - "to create CPU geo-addr, error = %d"), rc); - return (rc); - } - } - if (ptree_get_prop_by_name(rtm_lnodehdl, - PICL_PROP_STATUS_TIME, &proph) != PICL_SUCCESS) { - status_time = (uint64_t)time(NULL); - (void) env_create_property(PICL_PTYPE_TIMESTAMP, - PICL_READ, sizeof (status_time), PICL_PROP_STATUS_TIME, - NULLREAD, NULLWRITE, rtm_lnodehdl, &proph, - &status_time); - } - - /* start all the environment monitoring services */ - if ((rc = env_start_services()) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * routine to handle all the picl state and condition change events - */ -void -env_handle_event(const char *ename, const void *earg, size_t size) -{ - picl_nodehdl_t nodeh = 0; - nvlist_t *nvlp; - char *value; - boolean_t state_event; - char result[PICL_PROPNAMELEN_MAX]; - - if (!ename) { - return; - } - if (strcmp(ename, PICLEVENT_STATE_CHANGE) == 0) { - state_event = B_TRUE; - } else if (strcmp(ename, PICLEVENT_CONDITION_CHANGE) == 0) { - state_event = B_FALSE; - } else { - return; - } - - /* unpack the nvlist and get the information */ - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, &nodeh) == -1) { - nvlist_free(nvlp); - return; - } - if (nvlist_lookup_string(nvlp, (state_event) ? - PICLEVENTARG_STATE : - PICLEVENTARG_CONDITION, &value) != 0) { - nvlist_free(nvlp); - return; - } - - if (env_debug & PICLEVENTS) { - if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, - result, sizeof (result)) != PICL_SUCCESS) { - syslog(LOG_ERR, " SUNW_envmond: error in getting" - " %s", PICL_PROP_NAME); - nvlist_free(nvlp); - return; - } - syslog(LOG_INFO, "SUNW_envmond: %s (%s) on %s", - ename, value, result); - } - - if (chassis_nodehdl == 0 && state_event) { - if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, - result, sizeof (result)) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - if (strcmp(result, PICL_NODE_CHASSIS) == 0) { - chassis_nodehdl = nodeh; - } - } - if (nodeh == chassis_nodehdl && state_event) { - (void) env_handle_chassis_configuring_event(value); - } - /* do any platform specific handling that is reqd */ - env_platmod_handle_event(ename, earg, size); - nvlist_free(nvlp); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/picldr.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/picldr.h deleted file mode 100644 index d3f9e6fefd..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/picldr.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PICLDR_H -#define _PICLDR_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum picl_smc_event { - NO_EVENT = 0, - TEMPERATURE_SENSOR_EVENT, - CPU_NODE_STATE_CHANGE_NOTIFICATION, - CHANGE_CPCI_STATE, /* request to config/unconfig cpci i/f */ - CHANGE_CPU_NODE_STATE, /* request on online/offline node */ - SMC_LOCAL_EVENT -} picl_smc_event_t; - -#define SMC_NODE "/dev/ctsmc" -#define SMC_BMC_ADDR 0x20 -#define CPU_NODE_STATE_ONLINE 1 -#define CPU_NODE_STATE_OFFLINE 0 - -/* event messages */ -#define EVENT_MSG_AC_STATE_CHANGE 0xf5 -#define EVENT_MSG_CHANGE_CPCI_STATE 0x65 -#define EVENT_MSG_CHANGE_CPU_NODE_STATE 0x62 -#define EVENT_MSG_ASYNC_EVENT_NOTIFICATION 0x82 -#define MSG_GET_CPU_NODE_STATE 0x61 -#define SMC_LOCAL_EVENT_BRIDGE_IN_RESET 0x00 -#define SMC_LOCAL_EVENT_BRIDGE_OUT_OF_RESET 0x01 -#define SMC_LOCAL_EVENT_LATCH_OPENED 0x06 - -#define CPCI_STATE_OFFLINE 0 -#define CPCI_STATE_ONLINE 1 -#define SATCPU_STATE_ONLINE 0x7 -#define SATCPU_STATE_OFFLINE 0x8 -#define HEALTHY_ASSERT 1 -#define HEALTHY_DEASSERT 2 - -#define SMC_MASTER_RW_CMD 0x90 -#define ENV_CONFIG_FILE "/usr/platform/%s/lib/picl/plugins/envmond.conf" -#define RECORD_MAXSIZE (256) -#define RECORD_WHITESPACE (": \t") -#define SERVICE_PROCESSOR "alarmcard" - -/* packet lengths */ -#define ENV_RTM_PKT_LEN 3 -#define ENV_SET_GLOBAL_PKT_LEN 2 -#define ENV_SENSOR_EV_ENABLE_PKT_LEN 2 -#define ENV_IPMI_SMC_ENABLE_PKT_LEN 3 - -/* rtm pkt data */ -#define ENV_RTM_BUS_ID 7 -#define ENV_RTM_SLAVE_ADDR 0xa0 -#define ENV_RTM_READ_SIZE 0xa - -/* global enables data */ -#define ENV_IPMI_ENABLE_MASK 0x10 -#define ENV_IPMI_DISABLE_MASK 0xef -#define ENV_SENSOR_ENABLE_MASK 0xfb -#define ENV_SENSOR_DISABLE_MASK 0x04 - -#ifdef __cplusplus -} -#endif - -#endif /* _PICLDR_H */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclenvmond.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclenvmond.c deleted file mode 100644 index d74a28f116..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclenvmond.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <unistd.h> -#include <picl.h> -#include <picltree.h> -#include <picldefs.h> -#include <pthread.h> -#include <syslog.h> -#include <string.h> -#include <libnvpair.h> -#include <libintl.h> -#include "piclenvmond.h" - -/* external funcs and varaibles */ -extern void env_handle_event(const char *, const void *, size_t); -extern picl_errno_t env_init(); -extern void env_platmod_fini(); -extern int sensor_fd; -extern pthread_t env_temp_thr_tid; - -/* local defines */ -#define TIMEOUT (10) - -#pragma init(piclenvmond_register) - -/* - * Plugin registration entry points - */ -static void piclenvmond_register(void); -static void piclenvmond_init(void); -static void piclenvmond_fini(void); -static void piclenvmond_evhandler(const char *, const void *, size_t, void *); - -int env_debug = 0x0; - -static picld_plugin_reg_t envmond_reg_info = { - PICLD_PLUGIN_VERSION_1, - PICLD_PLUGIN_CRITICAL, - "SUNW_piclenvmond", - piclenvmond_init, - piclenvmond_fini -}; - -typedef struct { - picl_nodehdl_t nodehdl; - char node_name[PICL_PROPNAMELEN_MAX]; -} env_callback_args_t; - -/* - * picld entry points - */ -static void -piclenvmond_register(void) -{ - (void) picld_plugin_register(&envmond_reg_info); -} - -/* - * picld entry point - * - do all the initialization - * - register for interested picl events - */ -static void -piclenvmond_init(void) -{ - picl_errno_t rc = PICL_SUCCESS; - - if ((rc = env_init()) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:envmond init failed, " - "error = %d"), rc); - return; - } - - /* register handler for state change events */ - (void) ptree_register_handler(PICLEVENT_STATE_CHANGE, - piclenvmond_evhandler, NULL); - /* register handler for condition change events */ - (void) ptree_register_handler(PICLEVENT_CONDITION_CHANGE, - piclenvmond_evhandler, NULL); - -} - -static void -piclenvmond_fini(void) -{ - void *exitval; - - /* unregister event handler */ - (void) ptree_unregister_handler(PICLEVENT_STATE_CHANGE, - piclenvmond_evhandler, NULL); - (void) ptree_unregister_handler(PICLEVENT_CONDITION_CHANGE, - piclenvmond_evhandler, NULL); - - /* cancel all the threads */ - (void) pthread_cancel(env_temp_thr_tid); - (void) pthread_join(env_temp_thr_tid, &exitval); - - /* do any platform specific cleanups required */ - env_platmod_fini(); - (void) close(sensor_fd); -} - -/*ARGSUSED*/ -static void -piclenvmond_evhandler(const char *ename, const void *earg, size_t size, - void *cookie) -{ - env_handle_event(ename, earg, size); -} - -/* - * Utility functions - */ - -/* - * create_property -- Create a PICL property - */ -picl_errno_t -env_create_property(int ptype, int pmode, size_t psize, char *pname, - int (*readfn)(ptree_rarg_t *, void *), - int (*writefn)(ptree_warg_t *, const void *), - picl_nodehdl_t nodeh, picl_prophdl_t *propp, void *vbuf) -{ - picl_errno_t rc; /* return code */ - ptree_propinfo_t propinfo; /* propinfo structure */ - picl_prophdl_t proph; - - rc = ptree_get_prop_by_name(nodeh, pname, &proph); - if (rc == PICL_SUCCESS) { /* prop. already exists */ - return (rc); - } - - rc = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, - ptype, pmode, psize, pname, readfn, writefn); - if (rc != PICL_SUCCESS) { - syslog(LOG_ERR, PTREE_INIT_PROPINFO_FAILED_MSG, rc); - return (rc); - } - - rc = ptree_create_and_add_prop(nodeh, &propinfo, vbuf, propp); - if (rc != PICL_SUCCESS) { - syslog(LOG_ERR, PTREE_CREATE_AND_ADD_PROP_FAILED_MSG, rc); - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * The picl event completion handler. - */ -/* ARGSUSED */ -static void -event_completion_handler(char *ename, void *earg, size_t size) -{ - free(earg); - free(ename); -} - -/* - * utility routine to post PICL events - */ -/*ARGSUSED*/ -static int -post_picl_event(const char *ename, char *envl, size_t elen, - picl_nodehdl_t nodeh, int cond_wait) -{ - nvlist_t *nvlp; - size_t nvl_size; - char *pack_buf = NULL; - char *evname; - - if (nodeh == 0) { - return (PICL_FAILURE); - } - if ((evname = strdup(ename)) == NULL) - return (PICL_FAILURE); - if (envl) { - if (nvlist_unpack(envl, elen, &nvlp, 0) < 0) { - nvlist_free(nvlp); - free(evname); - return (PICL_FAILURE); - } - } else { - if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) { - free(evname); - return (PICL_FAILURE); - } - } - - if (nvlist_add_uint64(nvlp, PICLEVENTARG_NODEHANDLE, nodeh) == -1) { - nvlist_free(nvlp); - free(evname); - return (PICL_FAILURE); - } - - if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { - nvlist_free(nvlp); - free(evname); - return (PICL_FAILURE); - } - nvlist_free(nvlp); - - if (env_debug & EVENTS) { - char enodename[PICL_PROPNAMELEN_MAX]; - if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, - enodename, sizeof (enodename)) == PICL_SUCCESS) - syslog(LOG_INFO, "envmond:Posting %s on %s\n", - ename, enodename); - } - - if (ptree_post_event(evname, pack_buf, nvl_size, - event_completion_handler) != 0) { - syslog(LOG_ERR, gettext("SUNW_envmond: Error posting %s PICL" - " event."), ename); - free(pack_buf); - free(evname); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -/* - * post dr_req events - */ -picl_errno_t -post_dr_req_event(picl_nodehdl_t fruh, char *dr_req_type, uint8_t wait) -{ - nvlist_t *nvlp; /* nvlist of event specific args */ - size_t nvl_size; - char *pack_buf = NULL; - char dr_ap_id[PICL_PROPNAMELEN_MAX]; - int rc = PICL_SUCCESS; - - if (env_debug & DEBUG) - syslog(LOG_DEBUG, "Post %s on %llx", dr_req_type, fruh); - if (fruh == 0) { - return (PICL_INVALIDARG); - } - if ((rc = ptree_get_propval_by_name(fruh, PICL_PROP_NAME, - dr_ap_id, sizeof (dr_ap_id))) != PICL_SUCCESS) { - return (rc); - } - - if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) { - return (PICL_FAILURE); - } - - if (nvlist_add_string(nvlp, PICLEVENTARG_AP_ID, dr_ap_id) == -1) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - if (nvlist_add_string(nvlp, PICLEVENTARG_DR_REQ_TYPE, dr_req_type) - == -1) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - nvlist_free(nvlp); - - if (env_debug & DEBUG) - syslog(LOG_DEBUG, "Posting %s on %s", dr_req_type, dr_ap_id); - rc = post_picl_event(PICLEVENT_DR_REQ, pack_buf, nvl_size, fruh, - wait); - - free(pack_buf); - return (rc); -} - -/* - * routine to post dr_ap_state change events - */ -picl_errno_t -post_dr_ap_state_change_event(picl_nodehdl_t nodehdl, char *dr_hint, - uint8_t wait) -{ - nvlist_t *nvlp; /* nvlist of event specific args */ - size_t nvl_size; - char *pack_buf = NULL; - char dr_ap_id[PICL_PROPNAMELEN_MAX]; - int rc = PICL_SUCCESS; - - if (nodehdl == 0) { - return (PICL_FAILURE); - } - if ((rc = ptree_get_propval_by_name(nodehdl, PICL_PROP_NAME, - dr_ap_id, sizeof (dr_ap_id))) != PICL_SUCCESS) { - return (rc); - } - if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) { - return (PICL_FAILURE); - } - - if (nvlist_add_string(nvlp, PICLEVENTARG_AP_ID, dr_ap_id) == -1) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - if (nvlist_add_string(nvlp, PICLEVENTARG_HINT, dr_hint) == -1) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - nvlist_free(nvlp); - rc = post_picl_event(PICLEVENT_DR_AP_STATE_CHANGE, pack_buf, - nvl_size, nodehdl, wait); - free(pack_buf); - return (rc); -} - -picl_errno_t -post_cpu_state_change_event(picl_nodehdl_t fruh, char *event_type, uint8_t wait) -{ - nvlist_t *nvlp; /* nvlist of event specific args */ - size_t nvl_size; - char *pack_buf = NULL; - int rc = PICL_SUCCESS; - - if (fruh == 0) { - return (PICL_FAILURE); - } - - if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) - return (PICL_FAILURE); - - if (nvlist_add_int64(nvlp, PICLEVENTARG_NODEHANDLE, fruh)) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - - if (nvlist_add_string(nvlp, PICLEVENTARG_CPU_EV_TYPE, - event_type) == -1) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - - if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - nvlist_free(nvlp); - rc = post_picl_event(PICLEVENT_CPU_STATE_CHANGE, pack_buf, - nvl_size, fruh, wait); - free(pack_buf); - return (rc); -} - -int -post_sensor_event(picl_nodehdl_t hdl, char *sensor_evalue, uint8_t wait) -{ - nvlist_t *nvlp; /* nvlist of event specific args */ - size_t nvl_size; - char *pack_buf = NULL; - char dr_ap_id[PICL_PROPNAMELEN_MAX]; - int rc = PICL_SUCCESS; - - if (env_debug & DEBUG) - syslog(LOG_DEBUG, "Post %s on %llx", sensor_evalue, hdl); - if (hdl == 0) - return (PICL_FAILURE); - - if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, NULL)) - return (PICL_FAILURE); - - if (nvlist_add_string(nvlp, PICLEVENTARG_CONDITION, - sensor_evalue) == -1) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - if (nvlist_pack(nvlp, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { - nvlist_free(nvlp); - return (PICL_FAILURE); - } - nvlist_free(nvlp); - - if (env_debug & DEBUG) { - if (ptree_get_propval_by_name(hdl, PICL_PROP_NAME, dr_ap_id, - sizeof (dr_ap_id)) == PICL_SUCCESS) - syslog(LOG_DEBUG, "Posting %s on %s", sensor_evalue, - dr_ap_id); - } - rc = post_picl_event(PICLEVENT_CONDITION_CHANGE, pack_buf, nvl_size, - hdl, wait); - free(pack_buf); - return (rc); -} - -/* - * return B_TRUE if admin lock is enabled - * return B_FALSE if admin lock is disabled - */ -boolean_t -env_admin_lock_enabled(picl_nodehdl_t fruh) -{ - char adminlock[PICL_PROPNAMELEN_MAX]; - - if (ptree_get_propval_by_name(fruh, PICL_PROP_ADMIN_LOCK, - adminlock, sizeof (adminlock)) - != PICL_SUCCESS) { - return (B_FALSE); - } - if (strcmp(adminlock, PICL_ADMINLOCK_ENABLED) == 0) { - return (B_TRUE); - } - return (B_FALSE); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclenvmond.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclenvmond.h deleted file mode 100644 index 017c1e5d91..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclenvmond.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PICLENVMOND_H -#define _PICLENVMOND_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* debug flags */ -#define DEBUG 0x1 /* generic debug messages */ -#define EVENTS 0x2 /* only events related debug message */ -#define PTREE 0x4 /* messages relating to picltree search */ -#define SP_MONITOR 0x8 /* AC health monitoring messages only */ -#define CHASSIS_INFO 0x10 /* Chassis related debug information */ -#define PICLEVENTS 0x20 /* Display only PICL events received */ - -#define PICL_NODE_CHASSIS "chassis" -#define PICL_NODE_CPU "CPU" -#define PICL_NODE_RTM "RTM" -#define PICL_PROP_CONF_FILE "conf_name" -#define TEMPERATURE_SENSOR_TYPE (0x1u) - -typedef enum { - LOC_STATE_UNKNOWN = 0, - LOC_STATE_EMPTY, - LOC_STATE_DISCONNECTING, - LOC_STATE_DISCONNECTED, - LOC_STATE_CONNECTING, - LOC_STATE_CONNECTED, - FRU_STATE_UNKNOWN, - FRU_STATE_UNCONFIGURING, - FRU_STATE_UNCONFIGURED, - FRU_STATE_CONFIGURING, - FRU_STATE_CONFIGURED, - FRU_COND_OK, - FRU_COND_FAILING, - FRU_COND_FAILED, - FRU_COND_DEGRADED, - FRU_COND_UNKNOWN, - FRU_COND_TESTING -} env_state_event_t; - -typedef enum {NO_COND_TIMEDWAIT = 0, COND_TIMEDWAIT, NO_WAIT} env_wait_state_t; - -#define NULLREAD (int (*)(ptree_rarg_t *, void *))0 -#define NULLWRITE (int (*)(ptree_warg_t *, const void *))0 -#define POLL_TIMEOUT 5000 -#define DEFAULT_FD -1 -#define DEFAULT_SEQN 0xff - -/* byte of pointer to signed integer */ -#define BYTE_0(_X) (*((int8_t *)(_X) + 0)) -#define BYTE_1(_X) (*((int8_t *)(_X) + 1)) -#define BYTE_2(_X) (*((int8_t *)(_X) + 2)) -#define BYTE_3(_X) (*((int8_t *)(_X) + 3)) -#define BYTE_4(_X) (*((int8_t *)(_X) + 4)) -#define BYTE_5(_X) (*((int8_t *)(_X) + 5)) -#define BYTE_6(_X) (*((int8_t *)(_X) + 6)) -#define BYTE_7(_X) (*((int8_t *)(_X) + 7)) -#define BYTE_8(_X) (*((int8_t *)(_X) + 8)) - -#define BIT_0(_X) ((_X) & 0x01) -#define BIT_1(_X) ((_X) & 0x02) -#define BIT_2(_X) ((_X) & 0x04) -#define BIT_3(_X) ((_X) & 0x08) -#define BIT_4(_X) ((_X) & 0x10) -#define BIT_5(_X) ((_X) & 0x20) -#define BIT_6(_X) ((_X) & 0x40) -#define BIT_7(_X) ((_X) & 0x80) - -#define PICL_ADMINLOCK_DISABLED "disabled" -#define PICL_ADMINLOCK_ENABLED "enabled" - -#define PTREE_INIT_PROPINFO_FAILED_MSG \ - gettext("SUNW_envmond:ptree_init_propinfo() failed, error = %d") -#define PTREE_CREATE_AND_ADD_PROP_FAILED_MSG \ - gettext("SUNW_envmond: ptree_create_and_add_prop() failed error = %d") - -#ifdef __cplusplus -} -#endif - -#endif /* _PICLENVMOND_H */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclplatmod.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclplatmod.c deleted file mode 100644 index 43c4c3d056..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclplatmod.c +++ /dev/null @@ -1,837 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <limits.h> -#include <unistd.h> -#include <sys/systeminfo.h> -#include <pthread.h> -#include <syslog.h> -#include <picl.h> -#include <picltree.h> -#include <picldefs.h> -#include <string.h> -#include <libnvpair.h> -#include <libintl.h> -#include <librcm.h> -#include <stropts.h> -#include <smclib.h> -#include <sys/sysevent/dr.h> -#include "piclenvmond.h" -#include "picldr.h" - -/* local defines */ -#define RESET_CPU "/usr/sbin/shutdown -y -g 0 -i6" -#define SHUTDOWN_CPU "/usr/sbin/shutdown -y -g 0 -i0" -#define RCM_ABSTRACT_RESOURCE "SUNW_snowbird/board0/CPU1" -#define CPU_SENSOR_GEO_ADDR 0xe -#define IS_HEALTHY 0x01 -#define PICL_NODE_SYSMGMT "sysmgmt" -#define SYSMGMT_PATH PLATFORM_PATH"/pci/pci/isa/sysmgmt" -#define BUF_SIZE 7 - -/* external functions */ -extern picl_errno_t env_create_property(int, int, size_t, char *, - int (*readfn)(ptree_rarg_t *, void *), - int (*writefn)(ptree_warg_t *, const void *), - picl_nodehdl_t, picl_prophdl_t *, void *); -extern picl_errno_t post_dr_req_event(picl_nodehdl_t, char *, uint8_t); -extern picl_errno_t post_dr_ap_state_change_event(picl_nodehdl_t, char *, - uint8_t); -extern boolean_t env_admin_lock_enabled(picl_nodehdl_t); -extern picl_errno_t env_create_temp_sensor_node(picl_nodehdl_t, uint8_t); -extern void env_handle_sensor_event(void *); -extern int env_open_smc(); - -/* external variables */ -extern int env_debug; -extern uint8_t cpu_geo_addr; -extern picl_nodehdl_t rooth, platformh, sysmgmth, sensorh; -extern picl_nodehdl_t chassis_nodehdl, cpu_nodehdl, cpu_lnodehdl; - -/* locals */ -static pthread_mutex_t env_dmc_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t env_dmc_cond = PTHREAD_COND_INITIALIZER; -static boolean_t env_reset_cpu = B_FALSE; -static boolean_t env_shutdown_system = B_FALSE; -static env_state_event_t env_chassis_state = FRU_STATE_UNKNOWN; -static char *rcm_abstr_cp2300_name = RCM_ABSTRACT_RESOURCE; -static boolean_t env_got_dmc_msg = B_FALSE; -static long env_dmc_wait_time = 15; -static pthread_t dmc_thr_tid; - -/* - * issue halt or reboot based on the reset_cpu flag - */ -/*ARGSUSED*/ -static void -shutdown_cpu(boolean_t force) -{ - if (env_shutdown_system) { - if (env_reset_cpu) { - (void) pclose(popen(RESET_CPU, "w")); - } else { - (void) pclose(popen(SHUTDOWN_CPU, "w")); - } - } -} - -/* - * inform RCM framework that the remove op is successful - */ -static void -confirm_rcm(char *abstr_name, rcm_handle_t *rhandle) -{ - rcm_notify_remove(rhandle, abstr_name, 0, NULL); -} - -/* - * inform RCM framework that the remove op is failed - */ -static void -fail_rcm(char *abstr_name, rcm_handle_t *rhandle) -{ - (void) rcm_notify_online(rhandle, abstr_name, 0, NULL); -} - -/* - * check RCM framework if it is ok to offline a device - */ -static int -check_rcm(char *rcm_abstr_cp2300_name, uint_t flags) -{ - rcm_info_t *rinfo; - rcm_handle_t *rhandle; - int rv; - - if (rcm_alloc_handle(NULL, 0, NULL, &rhandle) != RCM_SUCCESS) { - return (RCM_FAILURE); - } - - rv = rcm_request_offline(rhandle, rcm_abstr_cp2300_name, - flags, &rinfo); - - if (rv == RCM_FAILURE) { - rcm_free_info(rinfo); - fail_rcm(rcm_abstr_cp2300_name, rhandle); - rcm_free_handle(rhandle); - return (RCM_FAILURE); - } - if (rv == RCM_CONFLICT) { - rcm_free_info(rinfo); - rcm_free_handle(rhandle); - return (RCM_CONFLICT); - } - - confirm_rcm(rcm_abstr_cp2300_name, rhandle); - rcm_free_info(rinfo); - rcm_free_handle(rhandle); - return (RCM_SUCCESS); -} - -/* - * utility routine to send response to an IPMI message - */ -static int -send_response2remote_device(uint8_t ipmb_addr, uint8_t cmd, uint8_t reqseq_lun, - uint8_t cc) -{ - int rc = SMC_SUCCESS; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t data = cc; /* completion code */ - - /* make a call to ctsmc lib */ - (void) smc_init_ipmi_msg(&req_pkt, cmd, DEFAULT_FD, 1, &data, - (reqseq_lun >> 2), ipmb_addr, SMC_NETFN_APP_RSP, - (reqseq_lun & 0x03)); - rc = smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT); - - if (rc != SMC_SUCCESS) - syslog(LOG_ERR, gettext("SUNW_envmond:Error in sending response" - " to %x, error = %d"), ipmb_addr, rc); - return (rc); -} - -/* - * do all the checks like adminlock check, rcm check and initiate - * shutdown - */ -/*ARGSUSED*/ -static int -initiate_shutdown(boolean_t force) -{ - int rv; - uint_t rcmflags = 0; - struct timespec rqtp, rmtp; - - if (!env_shutdown_system) { - return (-1); - } - - /* check the adminlock prop */ - if ((!force) && (env_admin_lock_enabled(cpu_nodehdl))) { - syslog(LOG_ERR, gettext("SUNW_envmond: " - "CPU in use! Cannot shutdown")); - return (-1); - } - - if (force) { - rcmflags = RCM_FORCE; - } - - /* check with rcm framework */ - rv = check_rcm(rcm_abstr_cp2300_name, rcmflags); - - if ((rv == RCM_FAILURE) || (rv == RCM_CONFLICT)) { - syslog(LOG_ERR, gettext("SUNW_envmond: RCM error %d, Cannot" - " shutdown"), rv); - return (-1); - } - - /* - * force events on chassis node - */ - if (force) { - if (post_dr_req_event(chassis_nodehdl, DR_REQ_OUTGOING_RES, - NO_WAIT) == PICL_SUCCESS) { - /* wait a little for clean up of frutree */ - rqtp.tv_sec = 5; - rqtp.tv_nsec = 0; - (void) nanosleep(&rqtp, &rmtp); - } - /* - * If force option is set, do it right here for now - * since there is no way to pass this info via events - * to frutree framework. - */ - shutdown_cpu(force); - return (0); - } - - if (post_dr_req_event(chassis_nodehdl, DR_REQ_OUTGOING_RES, NO_WAIT) - != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:cannot shutdown " - "the host CPU.")); - return (-1); - } - return (0); -} - -/* - * get the HEALTHY# line state - * Return -1 for Error - * 0 for HEALTHY# down - * 1 for HEALTHY# up - */ -static int -env_get_healthy_status() -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t size = 0; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_GET_EXECUTION_STATE, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - return (rsp_pkt.data[0] & IS_HEALTHY); -} - -/* - * initialization - */ -picl_errno_t -env_platmod_init() -{ - picl_errno_t rc = PICL_SUCCESS; - - if (rooth == 0) { - if (ptree_get_root(&rooth) != PICL_SUCCESS) { - return (rc); - } - } - - if (chassis_nodehdl == 0) { - if ((rc = ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, - &chassis_nodehdl)) != PICL_SUCCESS) { - return (rc); - } - } - if (post_dr_req_event(chassis_nodehdl, DR_REQ_INCOMING_RES, - NO_WAIT) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond: Error in " - "Posting configure event for Chassis node")); - rc = PICL_FAILURE; - } - return (rc); -} - -/* - * release all the resources - */ -void -env_platmod_fini() -{ - cpu_geo_addr = 0; - rooth = platformh = sysmgmth = 0; - chassis_nodehdl = cpu_nodehdl = cpu_lnodehdl = 0; - env_chassis_state = FRU_STATE_UNKNOWN; - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); -} - -/* - * handle chassis state change - */ -static void -env_handle_chassis_state_event(char *state) -{ - if (strcmp(state, PICLEVENTARGVAL_CONFIGURING) == 0) { - env_chassis_state = FRU_STATE_CONFIGURING; - return; - } - - if (strcmp(state, PICLEVENTARGVAL_UNCONFIGURED) == 0) { - if (env_chassis_state == FRU_STATE_CONFIGURING || - env_chassis_state == FRU_STATE_UNKNOWN) { - /* picl intialization is failed, dont issue shutdown */ - env_chassis_state = FRU_STATE_UNCONFIGURED; - return; - } - env_chassis_state = FRU_STATE_UNCONFIGURED; - if (env_reset_cpu) { - (void) pclose(popen(RESET_CPU, "w")); - } else { - (void) pclose(popen(SHUTDOWN_CPU, "w")); - } - return; - } - - if (strcmp(state, PICLEVENTARGVAL_CONFIGURED) == 0) { - env_chassis_state = FRU_STATE_CONFIGURED; - } -} - -/* - * event handler for watchdog state change event - */ -static picl_errno_t -env_handle_watchdog_expiry(picl_nodehdl_t wd_nodehdl) -{ - picl_errno_t rc = PICL_SUCCESS; - char class[PICL_CLASSNAMELEN_MAX]; - char value[PICL_PROPNAMELEN_MAX]; - char cond[BUF_SIZE]; - - if ((rc = ptree_get_propval_by_name(wd_nodehdl, - PICL_PROP_CLASSNAME, class, - PICL_CLASSNAMELEN_MAX)) != PICL_SUCCESS) { - return (rc); - } - - /* if the event is not of watchdog-timer, return */ - if (strcmp(class, PICL_CLASS_WATCHDOG_TIMER) != 0) { - return (PICL_INVALIDARG); - } - - if ((rc = ptree_get_propval_by_name(wd_nodehdl, - PICL_PROP_WATCHDOG_ACTION, value, sizeof (value))) != - PICL_SUCCESS) { - return (rc); - } - - /* if action is none, dont do anything */ - if (strcmp(value, PICL_PROPVAL_WD_ACTION_ALARM) != 0) { - return (PICL_SUCCESS); - } - - (void) strncpy(cond, PICLEVENTARGVAL_FAILED, sizeof (cond)); - /* update CPU condition to failed */ - if ((rc = ptree_update_propval_by_name(cpu_nodehdl, - PICL_PROP_CONDITION, cond, sizeof (cond))) != PICL_SUCCESS) { - return (rc); - } - - /* post dr ap state change event */ - rc = post_dr_ap_state_change_event(cpu_nodehdl, - DR_RESERVED_ATTR, NO_COND_TIMEDWAIT); - return (rc); -} - -/* - * rotine that handles all the picl state and condition change events - */ -void -env_platmod_handle_event(const char *ename, const void *earg, size_t size) -{ - picl_errno_t rc; - picl_nodehdl_t nodeh = 0; - picl_prophdl_t proph; - nvlist_t *nvlp; - char *value; - boolean_t state_event; - env_state_event_t event; - char result[PICL_PROPNAMELEN_MAX]; - uint64_t status_time, cond_time; - char cond[BUF_SIZE]; - - if (!ename) { - return; - } - if (strcmp(ename, PICLEVENT_STATE_CHANGE) == 0) { - state_event = B_TRUE; - } else if (strcmp(ename, PICLEVENT_CONDITION_CHANGE) == 0) { - state_event = B_FALSE; - } else { - syslog(LOG_ERR, gettext("SUNW_envmond: unknown event:%s\n"), - ename); - return; - } - - /* unpack the nvlist and get the information */ - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, &nodeh) == -1) { - nvlist_free(nvlp); - return; - } - if (nvlist_lookup_string(nvlp, (state_event) ? - PICLEVENTARG_STATE : - PICLEVENTARG_CONDITION, &value) != 0) { - nvlist_free(nvlp); - return; - } - - if (env_debug & PICLEVENTS) { - if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, - result, sizeof (result)) != PICL_SUCCESS) { - syslog(LOG_ERR, " SUNW_envmond: error in getting" - " node name"); - nvlist_free(nvlp); - return; - } - syslog(LOG_INFO, "SUNW_envmond: %s (%s) on %s", - ename, value, result); - } - - if (chassis_nodehdl == 0 && state_event) { - if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, - result, sizeof (result)) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - if (strcmp(result, PICL_NODE_CHASSIS) == 0) { - chassis_nodehdl = nodeh; - } - } - - if (nodeh == chassis_nodehdl && state_event) { - env_handle_chassis_state_event(value); - nvlist_free(nvlp); - return; - } - - if (strcmp(PICLEVENTARGVAL_DISCONNECTED, value) == 0) { - event = LOC_STATE_DISCONNECTED; - } else if (strcmp(PICLEVENTARGVAL_CONNECTED, value) == 0) { - event = LOC_STATE_CONNECTED; - } else if (strcmp(PICLEVENTARGVAL_EMPTY, value) == 0) { - event = LOC_STATE_EMPTY; - } else if (strcmp(PICLEVENTARGVAL_CONFIGURED, value) == 0) { - event = FRU_STATE_CONFIGURED; - } else if (strcmp(PICLEVENTARGVAL_UNCONFIGURED, value) == 0) { - event = FRU_STATE_UNCONFIGURED; - } else if (strcmp(PICL_PROPVAL_WD_STATE_EXPIRED, value) == 0) { - /* watchdog expiry event */ - if ((rc = env_handle_watchdog_expiry(nodeh)) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in handling" - "watchdog expiry event")); - } - nvlist_free(nvlp); - return; - } else { - nvlist_free(nvlp); - return; - } - - switch (event) { - case LOC_STATE_EMPTY: - break; - - case LOC_STATE_DISCONNECTED: - if (nodeh == cpu_lnodehdl) { - (void) initiate_shutdown(B_FALSE); - } - break; - case LOC_STATE_CONNECTED: - if (nodeh != cpu_lnodehdl) { - break; - } - if (ptree_get_propval_by_name(cpu_lnodehdl, - PICL_PROP_CHILD, &cpu_nodehdl, - sizeof (picl_nodehdl_t)) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Cannot " - "initialize CPU node handle %llx"), nodeh); - cpu_nodehdl = 0; - } - break; - case FRU_STATE_CONFIGURED: - if (nodeh != cpu_nodehdl) { - break; - } - if (ptree_get_prop_by_name(cpu_nodehdl, - PICL_PROP_STATUS_TIME, &proph) != PICL_SUCCESS) { - status_time = (uint64_t)time(NULL); - (void) env_create_property(PICL_PTYPE_TIMESTAMP, - PICL_READ, sizeof (status_time), - PICL_PROP_STATUS_TIME, NULLREAD, - NULLWRITE, cpu_nodehdl, &proph, - &status_time); - } - if (ptree_get_prop_by_name(cpu_nodehdl, - PICL_PROP_CONDITION_TIME, &proph) != PICL_SUCCESS) { - cond_time = (uint64_t)time(NULL); - (void) env_create_property(PICL_PTYPE_TIMESTAMP, - PICL_READ, sizeof (cond_time), - PICL_PROP_CONDITION_TIME, NULLREAD, - NULLWRITE, cpu_nodehdl, &proph, - &cond_time); - } - env_shutdown_system = B_FALSE; - /* if HEALTHY# is UP update the condition to "ok" */ - switch (env_get_healthy_status()) { - case 0: - /* update CPU condition to failed */ - (void) strncpy(cond, PICLEVENTARGVAL_FAILED, sizeof (cond)); - break; - case 1: - /* update CPU condition to ok */ - (void) strncpy(cond, PICLEVENTARGVAL_OK, sizeof (cond)); - break; - case -1: /*FALLTHRU*/ - default: - /* update the condition to unknown */ - (void) strncpy(cond, PICLEVENTARGVAL_UNKNOWN, sizeof (cond)); - syslog(LOG_ERR, gettext("SUNW_envmond:Error in " - "reading HEALTHY# status")); - } - - if ((rc = ptree_update_propval_by_name(cpu_nodehdl, - PICL_PROP_CONDITION, cond, sizeof (cond))) != - PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in " - "updating CPU condition, error = %d"), rc); - } - break; - case FRU_STATE_UNCONFIGURED: - if (env_reset_cpu && nodeh == cpu_nodehdl) { - (void) initiate_shutdown(B_FALSE); - } - break; - default: - break; - } /* end of switch */ - nvlist_free(nvlp); -} - -/* - * This thread waits for dmc message to come, as it has to send - * response ACK back to DMC. Otherwise DMC may think that message - * is lost and issues poweroff on a node. So there is a chance for - * CPU to be powered off in the middle of shutdown process. If the - * DMC message didnt come, then process the local shutdown request. - */ -/*ARGSUSED*/ -static void * -env_wait_for_dmc_msg(void *args) -{ - struct timeval ct; - struct timespec to; - - (void) pthread_mutex_lock(&env_dmc_mutex); - if (env_got_dmc_msg == B_TRUE) { - (void) pthread_mutex_unlock(&env_dmc_mutex); - return (NULL); - } - - /* - * wait for specified time to check if dmc sends the - * shutdown request - */ - (void) gettimeofday(&ct, NULL); - to.tv_sec = ct.tv_sec + env_dmc_wait_time; - to.tv_nsec = 0; - (void) pthread_cond_timedwait(&env_dmc_cond, - &env_dmc_mutex, &to); - if (env_got_dmc_msg == B_TRUE) { - (void) pthread_mutex_unlock(&env_dmc_mutex); - return (NULL); - } - (void) pthread_mutex_unlock(&env_dmc_mutex); - - env_shutdown_system = B_TRUE; - env_reset_cpu = B_FALSE; - (void) initiate_shutdown(B_FALSE); - return (NULL); -} - -/* - * Handle the Latch open event(shutdown the node) - */ -picl_errno_t -env_platmod_handle_latch_open() -{ - /* - * create a thread to process local event after waiting for DMC CPU - * node state offline message - */ - if (pthread_create(&dmc_thr_tid, NULL, &env_wait_for_dmc_msg, - NULL) != 0) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in creating " - "dmc thread")); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -/* - * For Sanibel, hotswap initialization is not reqd. - */ -picl_errno_t -env_platmod_setup_hotswap() -{ - return (PICL_SUCCESS); -} - -/* - * For sanibel this supoort is not required - */ -picl_errno_t -env_platmod_sp_monitor() -{ - return (PICL_SUCCESS); -} - -/* - * For sanibel this supoort is not required - */ -picl_errno_t -env_platmod_create_hotswap_prop() -{ - return (PICL_SUCCESS); -} - -/* - * For sanibel this supoort is not required - */ -/*ARGSUSED*/ -void -process_platmod_sp_heartbeat(uint8_t data) -{ -} - -/* - * For sanibel this supoort is not required - */ -/*ARGSUSED*/ -int -process_platmod_async_msg_notif(void *resdatap) -{ - return (0); -} - -/* - * For sanibel this supoort is not required - */ -/*ARGSUSED*/ -int -process_platmod_change_cpci_state(void *res_datap) -{ - return (0); -} - -/* - * handle request from service processor for shutdown/online - */ -int -process_platmod_change_cpu_node_state(void *res_datap) -{ - int rc = SMC_SUCCESS; - uint8_t state = BYTE_7(res_datap); - boolean_t force_flag = B_FALSE; - - switch (state & 1) { - case CPU_NODE_STATE_OFFLINE: - (void) pthread_mutex_lock(&env_dmc_mutex); - env_got_dmc_msg = B_TRUE; - (void) pthread_cond_signal(&env_dmc_cond); - (void) pthread_mutex_unlock(&env_dmc_mutex); - env_shutdown_system = B_TRUE; - if ((state >> 2) & 1) - env_reset_cpu = B_TRUE; - if (state >> 1 & 1) { /* force flag set? */ - force_flag = B_TRUE; - } else { - force_flag = B_FALSE; - } - - if (initiate_shutdown(force_flag) == 0) { - if ((rc = send_response2remote_device(SMC_BMC_ADDR, - EVENT_MSG_CHANGE_CPU_NODE_STATE, - BYTE_5(res_datap), 0x0)) != SMC_SUCCESS) { - return (rc); - } - } else { - if ((rc = send_response2remote_device(SMC_BMC_ADDR, - EVENT_MSG_CHANGE_CPU_NODE_STATE, - BYTE_5(res_datap), 0xFF)) != SMC_SUCCESS) { - return (rc); - } - env_shutdown_system = B_FALSE; - if ((state >> 2) & 1) - env_reset_cpu = B_FALSE; - } - break; - case CPU_NODE_STATE_ONLINE: - if ((rc = send_response2remote_device(SMC_BMC_ADDR, - EVENT_MSG_CHANGE_CPU_NODE_STATE, - BYTE_5(res_datap), 0x0)) != SMC_SUCCESS) { - return (rc); - } - break; - default: - break; - } - return (0); -} - -/* - * Handle change in state of service processor - */ -int -process_platmod_sp_state_change_notif(void *res_datap) -{ - int rc = SMC_SUCCESS; - uint8_t state = BYTE_7(res_datap); - uint8_t rq_addr = BYTE_4(res_datap); - - if (rq_addr != SMC_BMC_ADDR) { - return (PICL_FAILURE); - } - - switch (state) { - case CPU_NODE_STATE_ONLINE: - /* Send ACK to service processor */ - if ((rc = send_response2remote_device(SMC_BMC_ADDR, - EVENT_MSG_AC_STATE_CHANGE, - BYTE_5(res_datap), 0x0)) != SMC_SUCCESS) { - return (rc); - } - break; - - case CPU_NODE_STATE_OFFLINE: - /* Send ACK to service processor */ - if ((rc = send_response2remote_device(SMC_BMC_ADDR, - EVENT_MSG_AC_STATE_CHANGE, - BYTE_5(res_datap), 0x0)) != SMC_SUCCESS) { - return (rc); - } - break; - - default: - if ((rc = send_response2remote_device(SMC_BMC_ADDR, - EVENT_MSG_AC_STATE_CHANGE, - BYTE_5(res_datap), 0xFF)) != SMC_SUCCESS) { - return (rc); - } - break; - } - return (0); -} - -/* - * For sanibel this supoort is not required - */ -/*ARGSUSED*/ -picl_errno_t -env_platmod_handle_bus_if_change(uint8_t data) -{ - return (PICL_SUCCESS); -} - -/* - * create the temperature sensor nodes - */ -picl_errno_t -env_platmod_create_sensors() -{ - picl_errno_t rc = PICL_SUCCESS; - - if (rooth == 0) { - if ((rc = ptree_get_root(&rooth)) != PICL_SUCCESS) { - return (rc); - } - } - - if (platformh == 0) { - if ((rc = ptree_get_node_by_path(PLATFORM_PATH, - &platformh)) != PICL_SUCCESS) { - return (rc); - } - } - - if (sysmgmth == 0) { - if ((rc = ptree_get_node_by_path(SYSMGMT_PATH, - &sysmgmth)) != PICL_SUCCESS) { - return (rc); - } - } - - rc = env_create_temp_sensor_node(sysmgmth, CPU_SENSOR_GEO_ADDR); - return (rc); -} - -/* - * handler for sensor event - */ -void -env_platmod_handle_sensor_event(void *res_datap) -{ - if (BYTE_4(res_datap) != CPU_SENSOR_GEO_ADDR) { - return; - } - env_handle_sensor_event(res_datap); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclsensors.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclsensors.c deleted file mode 100644 index 60d95e9f5a..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclsensors.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Routines in this file are used to manage CPU temperature sensor - */ - -#include <stdio.h> -#include <unistd.h> -#include <smclib.h> -#include <libintl.h> -#include <syslog.h> -#include <pthread.h> -#include <string.h> -#include <strings.h> -#include <picl.h> -#include <picltree.h> -#include <picldefs.h> -#include <pthread.h> -#include <errno.h> -#include <stropts.h> -#include "piclenvmond.h" -#include "piclsensors.h" - -#define NULLREAD (int (*)(ptree_rarg_t *, void *))0 -#define NULLWRITE (int (*)(ptree_warg_t *, const void *))0 -#define POLL_TIMEOUT 5000 -#define BUF_SIZE 50 - -/* packet lengths */ -#define ENV_GET_THRESHOLD_PKT_LEN 1 -#define ENV_SET_THRESHOLD_PKT_LEN 8 -#define ENV_READ_SENSOR_PKT_LEN 1 -#define ENV_SENSOR_EVENT_ENABLE_PKT_LEN 2 - -/* req pkt data */ -#define ENV_SENSOR_EVENT_ENABLE_MASK 0x80 - -/* ptree wrapper to create property */ -extern picl_errno_t env_create_property(int ptype, int pmode, - size_t psize, char *pname, int (*readfn)(ptree_rarg_t *, void *), - int (*writefn)(ptree_warg_t *, const void *), - picl_nodehdl_t nodeh, picl_prophdl_t *propp, void *vbuf); -extern int post_sensor_event(picl_nodehdl_t, char *, uint8_t); -extern int env_open_smc(void); -extern int env_debug; - -/* globals */ -int sensor_fd = -1; -picl_nodehdl_t sensorh = 0; -pthread_t env_temp_thr_tid; - -/* local vars */ -static env_temp_sensor_t temp_sensor; -static pthread_mutex_t sensor_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t env_temp_monitor_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t env_temp_monitor_cv = PTHREAD_COND_INITIALIZER; -static env_temp_threshold_t env_curr_state = NORMAL_THRESHOLD; -static char *env_thresholds[] = { - PICL_PROP_LOW_WARNING, - PICL_PROP_LOW_SHUTDOWN, - PICL_PROP_LOW_POWER_OFF, - PICL_PROP_HIGH_WARNING, - PICL_PROP_HIGH_SHUTDOWN, - PICL_PROP_HIGH_POWER_OFF -}; -static int cpu_sensor_geo_addr = 0; - -/* local func prototypes */ -static void *env_temp_monitor(void *args); - -/* - * Reads the threshold value from hardware - */ -static picl_errno_t -env_get_temp_threshold(int sensor_no, int threshold_no, - int8_t *threshold_reading) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - smc_errno_t rc = SMC_SUCCESS; - uint8_t size = 0; - - if (threshold_no < 1 || threshold_no > 6) { - return (PICL_INVALIDARG); - } - - req_pkt.data[0] = sensor_no; - size = ENV_GET_THRESHOLD_PKT_LEN; - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_SENSOR_THRESHOLD_GET, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT)) != SMC_SUCCESS) { - syslog(LOG_ERR, SMC_GET_SENSOR_THRES_FAILED, - sensor_no, rc); - return (PICL_FAILURE); - } - - switch (threshold_no) { - case LOW_WARNING_THRESHOLD: - if (LOW_WARNING_BIT(rsp_pkt.data[0])) { - *threshold_reading = rsp_pkt.data[1]; - } else { - return (PICL_PERMDENIED); - } - break; - case LOW_SHUTDOWN_THRESHOLD: - if (LOW_SHUTDOWN_BIT(rsp_pkt.data[0])) { - *threshold_reading = rsp_pkt.data[2]; - } else { - return (PICL_PERMDENIED); - } - break; - case LOW_POWEROFF_THRESHOLD: - if (LOW_POWEROFF_BIT(rsp_pkt.data[0])) { - *threshold_reading = rsp_pkt.data[3]; - } else { - return (PICL_PERMDENIED); - } - break; - case HIGH_WARNING_THRESHOLD: - if (HIGH_WARNING_BIT(rsp_pkt.data[0])) { - *threshold_reading = rsp_pkt.data[4]; - } else { - return (PICL_PERMDENIED); - } - break; - case HIGH_SHUTDOWN_THRESHOLD: - if (HIGH_SHUTDOWN_BIT(rsp_pkt.data[0])) { - *threshold_reading = rsp_pkt.data[5]; - } else { - return (PICL_PERMDENIED); - } - break; - case HIGH_POWEROFF_THRESHOLD: - if (HIGH_POWEROFF_BIT(rsp_pkt.data[0])) { - *threshold_reading = rsp_pkt.data[6]; - } else { - return (PICL_PERMDENIED); - } - break; - default: - return (PICL_INVALIDARG); - } - return (PICL_SUCCESS); -} - -/* - * Sets the threshold temperature specified in given sensor number - */ -static picl_errno_t -env_set_temp_threshold(int sensor_no, int threshold_no, - int8_t set_value) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - smc_errno_t rc; - uint8_t size = 0; - - if (threshold_no < 1 || threshold_no > 6) { - return (PICL_INVALIDARG); - } - - req_pkt.data[0] = (int8_t)sensor_no; - req_pkt.data[1] = 0x01 << (threshold_no - 1); /* set the bit mask */ - req_pkt.data[1 + threshold_no] = set_value; - size = ENV_SET_THRESHOLD_PKT_LEN; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_SENSOR_THRESHOLD_SET, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(sensor_fd, &req_pkt, &rsp_pkt, - POLL_TIMEOUT)) != SMC_SUCCESS) { - syslog(LOG_ERR, SMC_SET_SENSOR_THRES_FAILED, - sensor_no, rc); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -/* - * returns the sensor reading of the SMC sensor specified in sensor_no - */ -static picl_errno_t -env_get_sensor_reading(uint8_t sensor_no, int8_t *sensor_reading) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - smc_errno_t rc = SMC_SUCCESS; - uint8_t size = 0; - - req_pkt.data[0] = sensor_no; - /* initialize the request packet */ - size = ENV_READ_SENSOR_PKT_LEN; - (void) smc_init_smc_msg(&req_pkt, SMC_SENSOR_READING_GET, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT)) != SMC_SUCCESS) { - syslog(LOG_ERR, SMC_GET_SENSOR_READING_FAILED, - sensor_no, rc); - return (PICL_FAILURE); - } - *sensor_reading = rsp_pkt.data[0]; - return (PICL_SUCCESS); -} - -/* - * volatile call back function to read the current temparature - */ -static int -get_curr_temp(ptree_rarg_t *argp, void *bufp) -{ - uint8_t sensor_no; - int8_t sensor_reading; - picl_errno_t rc; - - if ((rc = ptree_get_propval_by_name(argp->nodeh, - PICL_PROP_GEO_ADDR, &sensor_no, sizeof (sensor_no))) != - PICL_SUCCESS) { - return (rc); - } - - /* read the temp from SMC f/w */ - if ((rc = env_get_sensor_reading(sensor_no, &sensor_reading)) != - PICL_SUCCESS) { - return (rc); - } - *(int8_t *)bufp = sensor_reading; - - /* update the internal cache */ - (void) pthread_mutex_lock(&sensor_mutex); - temp_sensor.curr_temp = sensor_reading; - (void) pthread_mutex_unlock(&sensor_mutex); - - return (PICL_SUCCESS); -} - -/* - * volatile function that returns the state of sensor - */ -static int -get_sensor_condition(ptree_rarg_t *argp, void *bufp) -{ - uint8_t sensor_no; - picl_errno_t rc = PICL_SUCCESS; - int8_t sensor_reading; - - if ((rc = ptree_get_propval_by_name(argp->nodeh, - PICL_PROP_GEO_ADDR, &sensor_no, sizeof (sensor_no))) != - PICL_SUCCESS) { - return (rc); - } - - /* read the curr temp from SMC f/w */ - if ((rc = env_get_sensor_reading(sensor_no, &sensor_reading)) != - PICL_SUCCESS) { - (void) pthread_mutex_lock(&sensor_mutex); - (void) strncpy(temp_sensor.state, PICLEVENTARGVAL_UNKNOWN, - sizeof (temp_sensor.state)); - (void) strncpy((char *)bufp, PICLEVENTARGVAL_UNKNOWN, - PICL_PROPNAMELEN_MAX); - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_SUCCESS); - } - - (void) pthread_mutex_lock(&sensor_mutex); - - if (sensor_reading > temp_sensor.hi_shutdown || - sensor_reading < temp_sensor.lo_shutdown) - (void) strncpy(temp_sensor.state, - PICLEVENTARGVAL_SENSOR_COND_SHUTDOWN, - sizeof (temp_sensor.state)); - else if (sensor_reading > temp_sensor.hi_warning || - sensor_reading < temp_sensor.lo_warning) - (void) strncpy(temp_sensor.state, - PICLEVENTARGVAL_SENSOR_COND_WARNING, - sizeof (temp_sensor.state)); - else - (void) strncpy(temp_sensor.state, PICLEVENTARGVAL_OK, - sizeof (temp_sensor.state)); - (void) strncpy((char *)bufp, temp_sensor.state, - PICL_PROPNAMELEN_MAX); - - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_SUCCESS); -} - -/* - * volatile property to read sensor thresholds - */ -static int -get_sensor_thr(ptree_rarg_t *argp, void *bufp) -{ - picl_errno_t rc = PICL_SUCCESS; - ptree_propinfo_t pi; - char prop_name[PICL_PROPNAMELEN_MAX]; - - if ((rc = ptree_get_propinfo(argp->proph, &pi)) != PICL_SUCCESS) { - return (rc); - } - (void) strncpy(prop_name, pi.piclinfo.name, sizeof (prop_name)); - - (void) pthread_mutex_lock(&sensor_mutex); - - if (strcmp(prop_name, PICL_PROP_LOW_WARNING) == 0) { - *(int8_t *)bufp = temp_sensor.lo_warning; - } else if (strcmp(prop_name, PICL_PROP_LOW_SHUTDOWN) == 0) { - *(int8_t *)bufp = temp_sensor.lo_shutdown; - } else if (strcmp(prop_name, PICL_PROP_LOW_POWER_OFF) == 0) { - *(int8_t *)bufp = temp_sensor.lo_poweroff; - } else if (strcmp(prop_name, PICL_PROP_HIGH_WARNING) == 0) { - *(int8_t *)bufp = temp_sensor.hi_warning; - } else if (strcmp(prop_name, PICL_PROP_HIGH_SHUTDOWN) == 0) { - *(int8_t *)bufp = temp_sensor.hi_shutdown; - } else if (strcmp(prop_name, PICL_PROP_HIGH_POWER_OFF) == 0) { - *(int8_t *)bufp = temp_sensor.hi_poweroff; - } else { - rc = PICL_INVALIDARG; - } - - (void) pthread_mutex_unlock(&sensor_mutex); - return (rc); -} - -/* - * volatile callback function to set the temp thresholds - */ -static int -set_sensor_thr(ptree_warg_t *argp, const void *bufp) -{ - picl_errno_t rc = PICL_SUCCESS; - ptree_propinfo_t pi; - int threshold_no = 0; - int8_t temp = *(int8_t *)bufp; - char cmd[BUF_SIZE]; - char prop_name[PICL_PROPNAMELEN_MAX]; - - if ((rc = ptree_get_propinfo(argp->proph, &pi)) != PICL_SUCCESS) { - return (rc); - } - (void) strncpy(prop_name, pi.piclinfo.name, sizeof (prop_name)); - cmd[0] = '\0'; - - (void) pthread_mutex_lock(&sensor_mutex); - - if (strcmp(prop_name, PICL_PROP_LOW_WARNING) == 0) { - /* warning cannot be less than shutdown threshold */ - if (temp <= temp_sensor.lo_shutdown) { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_INVALIDARG); - } - threshold_no = LOW_WARNING_THRESHOLD; - } else if (strcmp(prop_name, PICL_PROP_LOW_SHUTDOWN) == 0) { - /* shutdown cannot be greater than warning threshold */ - if (temp >= temp_sensor.lo_warning) { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_INVALIDARG); - } - threshold_no = LOW_SHUTDOWN_THRESHOLD; - } else if (strcmp(prop_name, PICL_PROP_LOW_POWER_OFF) == 0) { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_PERMDENIED); - } else if (strcmp(prop_name, PICL_PROP_HIGH_WARNING) == 0) { - if ((temp + 5) > temp_sensor.hi_shutdown) { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_INVALIDARG); - } - /* change the OBP nvram property */ - (void) snprintf(cmd, sizeof (cmd), - EEPROM_WARNING_CMD, temp); - threshold_no = HIGH_WARNING_THRESHOLD; - } else if (strcmp(prop_name, PICL_PROP_HIGH_SHUTDOWN) == 0) { - if ((temp - 5) < temp_sensor.hi_warning) { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_INVALIDARG); - } - /* change the OBP nvram property */ - (void) snprintf(cmd, sizeof (cmd), - EEPROM_SHUTDOWN_CMD, temp); - threshold_no = HIGH_SHUTDOWN_THRESHOLD; - } else if (strcmp(prop_name, PICL_PROP_HIGH_POWER_OFF) == 0) { - if (temp > MAX_POWEROFF_TEMP || - (temp - 5) < temp_sensor.hi_shutdown) { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_INVALIDARG); - } - /* change the OBP nvram property */ - threshold_no = HIGH_POWEROFF_THRESHOLD; - (void) snprintf(cmd, sizeof (cmd), - EEPROM_POWEROFF_CMD, temp); - } else { - (void) pthread_mutex_unlock(&sensor_mutex); - return (PICL_INVALIDARG); - } - (void) pthread_mutex_unlock(&sensor_mutex); - - if ((rc = env_set_temp_threshold(cpu_sensor_geo_addr, - threshold_no, temp)) != PICL_SUCCESS) { - return (rc); - } - - (void) pthread_mutex_lock(&sensor_mutex); - switch (threshold_no) { - case LOW_WARNING_THRESHOLD: - temp_sensor.lo_warning = temp; - break; - case LOW_SHUTDOWN_THRESHOLD: - temp_sensor.lo_shutdown = temp; - break; - case LOW_POWEROFF_THRESHOLD: - temp_sensor.lo_poweroff = temp; - break; - case HIGH_WARNING_THRESHOLD: - temp_sensor.hi_warning = temp; - break; - case HIGH_SHUTDOWN_THRESHOLD: - temp_sensor.hi_shutdown = temp; - break; - case HIGH_POWEROFF_THRESHOLD: - temp_sensor.hi_poweroff = temp; - break; - } - (void) pthread_mutex_unlock(&sensor_mutex); - - /* execute the cmd to change OBP nvram property */ - if (cmd[0]) { - (void) pclose(popen(cmd, "w")); - } - return (PICL_SUCCESS); -} - -/* - * this routine reads the hardware state and initialises the internal - * cache for temperature thresholds - */ -static picl_errno_t -env_init_temp_sensor_values(int sensor_no, env_temp_sensor_t *sensor) -{ - if (env_get_sensor_reading(sensor_no, &sensor->curr_temp) != - PICL_SUCCESS) { - return (PICL_FAILURE); - } - - if (env_get_temp_threshold(sensor_no, LOW_WARNING_THRESHOLD, - &sensor->lo_warning) != PICL_SUCCESS) { - syslog(LOG_ERR, SMC_GET_LWT_FAILED); - return (PICL_FAILURE); - } - - if (env_get_temp_threshold(sensor_no, LOW_SHUTDOWN_THRESHOLD, - &sensor->lo_shutdown) != PICL_SUCCESS) { - syslog(LOG_ERR, SMC_GET_LST_FAILED); - return (PICL_FAILURE); - } - - if (env_get_temp_threshold(sensor_no, LOW_POWEROFF_THRESHOLD, - &sensor->lo_poweroff) != PICL_SUCCESS) { - syslog(LOG_ERR, SMC_GET_LPT_FAILED); - return (PICL_FAILURE); - } - - if (env_get_temp_threshold(sensor_no, HIGH_WARNING_THRESHOLD, - &sensor->hi_warning) != PICL_SUCCESS) { - syslog(LOG_ERR, SMC_SET_LWT_FAILED); - return (PICL_FAILURE); - } - - if (env_get_temp_threshold(sensor_no, HIGH_SHUTDOWN_THRESHOLD, - &sensor->hi_shutdown) != PICL_SUCCESS) { - syslog(LOG_ERR, SMC_SET_LST_FAILED); - return (PICL_FAILURE); - } - - if (env_get_temp_threshold(sensor_no, HIGH_POWEROFF_THRESHOLD, - &sensor->hi_poweroff) != PICL_SUCCESS) { - syslog(LOG_ERR, SMC_SET_LPT_FAILED); - return (PICL_FAILURE); - } - - if (sensor->curr_temp > sensor->hi_shutdown || - sensor->curr_temp < sensor->lo_shutdown) { - (void) strncpy(sensor->state, - PICLEVENTARGVAL_SENSOR_COND_SHUTDOWN, - sizeof (sensor->state)); - } else if (sensor->curr_temp > sensor->hi_warning || - sensor->curr_temp < sensor->lo_warning) { - (void) strncpy(sensor->state, - PICLEVENTARGVAL_SENSOR_COND_WARNING, - sizeof (sensor->state)); - } else { - (void) strncpy(sensor->state, PICLEVENTARGVAL_OK, - sizeof (sensor->state)); - } - return (PICL_SUCCESS); -} - -/* - * sensor_event_enable_set: enables or disables Event Message generation - * from a sensor specified by sensor_no - */ -static int -sensor_event_enable_set(uint8_t sensor_no, boolean_t enable) -{ - smc_errno_t rc = SMC_SUCCESS; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t size = 0; - - req_pkt.data[0] = sensor_no; - req_pkt.data[1] = 0; - if (enable) { - req_pkt.data[1] |= ENV_SENSOR_EVENT_ENABLE_MASK; - } - size = ENV_SENSOR_EVENT_ENABLE_PKT_LEN; - - (void) smc_init_smc_msg(&req_pkt, SMC_SENSOR_EVENT_ENABLE_SET, - DEFAULT_SEQN, size); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT)) != SMC_SUCCESS) { - syslog(LOG_ERR, SMC_ENABLE_SENSOR_EVENT_FAILED, rc); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -/* - * creates temperature sensor node and all of its properties - */ -picl_errno_t -env_create_temp_sensor_node(picl_nodehdl_t parenth, uint8_t sensor_no) -{ - int i = 0; - picl_errno_t rc = PICL_SUCCESS; - int8_t sensor_reading = 0; - struct strioctl strio; - sc_cmdspec_t set; - - sensor_fd = env_open_smc(); - if (sensor_fd < 0) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in " - "opening SMC(failed to create sensor nodes)")); - return (PICL_FAILURE); - } - - /* grab exclusive access to set the thresholds */ - set.args[0] = SMC_SENSOR_THRESHOLD_SET; - set.attribute = SC_ATTR_EXCLUSIVE; - strio.ic_cmd = SCIOC_MSG_SPEC; - strio.ic_timout = 0; - strio.ic_len = 2; - strio.ic_dp = (char *)&set; - if (ioctl(sensor_fd, I_STR, &strio) < 0) { - syslog(LOG_ERR, SMC_GET_EXCLUSIVE_ERR); - (void) close(sensor_fd); - return (PICL_FAILURE); - } - - cpu_sensor_geo_addr = sensor_no; - /* create temperature sensor node */ - if ((rc = ptree_create_and_add_node(parenth, CPU_SENSOR, - PICL_CLASS_TEMPERATURE_SENSOR, &sensorh)) != - PICL_SUCCESS) { - (void) close(sensor_fd); - return (rc); - } - - /* create Label prop. */ - if ((rc = env_create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_LABEL, NULLREAD, - NULLWRITE, sensorh, (picl_prophdl_t *)NULL, - (char *)PICL_PROPVAL_LABEL_AMBIENT)) != PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (rc); - } - - /* create the geo-addr property */ - if ((rc = env_create_property(PICL_PTYPE_UNSIGNED_INT, - PICL_READ, sizeof (sensor_no), PICL_PROP_GEO_ADDR, - NULLREAD, NULLWRITE, sensorh, (picl_prophdl_t *)NULL, - &sensor_no)) != PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (rc); - } - - /* read the current temp from hardware */ - if (env_get_sensor_reading(sensor_no, &sensor_reading) != - PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (PICL_FAILURE); - } - - /* create temperature prop. */ - if ((rc = env_create_property(PICL_PTYPE_INT, - PICL_READ + PICL_VOLATILE, sizeof (sensor_reading), - PICL_PROP_TEMPERATURE, get_curr_temp, - NULLWRITE, sensorh, (picl_prophdl_t *)NULL, - &sensor_reading)) != PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (rc); - } - - /* create the threshold properties */ - for (i = 0; i < NUM_OF_THRESHOLDS; i++) { - if ((rc = env_create_property(PICL_PTYPE_INT, - PICL_READ + PICL_WRITE + PICL_VOLATILE, - sizeof (uint8_t), env_thresholds[i], - get_sensor_thr, set_sensor_thr, - sensorh, (picl_prophdl_t *)NULL, - (void *)NULL)) != PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (rc); - } - } - - /* intialise the internal cache */ - if (env_init_temp_sensor_values(cpu_sensor_geo_addr, - &temp_sensor) != PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (PICL_FAILURE); - } - - /* create STATE prop. */ - if ((rc = env_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_CONDITION, get_sensor_condition, NULLWRITE, - sensorh, (picl_prophdl_t *)NULL, - temp_sensor.state)) != PICL_SUCCESS) { - (void) ptree_delete_node(sensorh); - (void) ptree_destroy_node(sensorh); - (void) close(sensor_fd); - return (rc); - } - - /* start temperature monitoring thread */ - if (pthread_create(&env_temp_thr_tid, NULL, - &env_temp_monitor, NULL) != 0) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in " - "creating temperature monitor thread")); - } - - /* enable sensor-event */ - (void) sensor_event_enable_set(sensor_no, B_TRUE); - return (PICL_SUCCESS); -} - -/* - * handles the sensor events (post corresponding Condition picl event) - */ -void -env_handle_sensor_event(void *res_datap) -{ - uint8_t offset; - char sensor_cond[BUF_SIZE]; - - if (BYTE_4(res_datap) != cpu_sensor_geo_addr) { - return; - } - - if (BYTE_5(res_datap) != THRESHOLD_TYPE) { - return; - } - - if (env_debug & DEBUG) { - syslog(LOG_INFO, "Temperature = %d\n", BYTE_7(res_datap)); - syslog(LOG_INFO, - "Threshold changed to %d\n", BYTE_8(res_datap)); - } - - /* Threshold event */ - offset = BYTE_6(res_datap) & 0x0F; /* first 4 bits */ - switch (offset) { - case 0: - (void) pthread_mutex_lock(&env_temp_monitor_mutex); - if (env_curr_state == LOW_WARNING_THRESHOLD) { - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - return; - } - env_curr_state = LOW_WARNING_THRESHOLD; - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - (void) strncpy(sensor_cond, - PICLEVENTARGVAL_SENSOR_COND_WARNING, - sizeof (sensor_cond)); - syslog(LOG_CRIT, gettext("SUNW_envmond:current temperature (%d)" - " is below lower warning temperature (%d).\n"), - BYTE_7(res_datap), BYTE_8(res_datap)); - break; - case 2: - (void) pthread_mutex_lock(&env_temp_monitor_mutex); - if (env_curr_state == LOW_SHUTDOWN_THRESHOLD) { - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - return; - } - env_curr_state = LOW_SHUTDOWN_THRESHOLD; - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - (void) strncpy(sensor_cond, - PICLEVENTARGVAL_SENSOR_COND_SHUTDOWN, - sizeof (sensor_cond)); - syslog(LOG_CRIT, gettext("SUNW_envmond:current temperature (%d)" - " is below lower critical temperature (%d).\n"), - BYTE_7(res_datap), BYTE_8(res_datap)); - break; - case 7: - (void) pthread_mutex_lock(&env_temp_monitor_mutex); - if (env_curr_state == HIGH_WARNING_THRESHOLD) { - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - return; - } - env_curr_state = HIGH_WARNING_THRESHOLD; - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - (void) strncpy(sensor_cond, - PICLEVENTARGVAL_SENSOR_COND_WARNING, - sizeof (sensor_cond)); - syslog(LOG_CRIT, gettext("SUNW_envmond:current temperature (%d)" - " exceeds upper warning temperature (%d).\n"), - BYTE_7(res_datap), BYTE_8(res_datap)); - break; - case 9: - (void) pthread_mutex_lock(&env_temp_monitor_mutex); - if (env_curr_state == HIGH_SHUTDOWN_THRESHOLD) { - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - return; - } - env_curr_state = HIGH_SHUTDOWN_THRESHOLD; - (void) pthread_cond_signal(&env_temp_monitor_cv); - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - (void) strncpy(sensor_cond, - PICLEVENTARGVAL_SENSOR_COND_SHUTDOWN, - sizeof (sensor_cond)); - syslog(LOG_CRIT, gettext("SUNW_envmond:current temperature (%d)" - " exceeds upper critical temperature (%d).\n"), - BYTE_7(res_datap), BYTE_8(res_datap)); - break; - default: - (void) strncpy(sensor_cond, PICLEVENTARGVAL_UNKNOWN, - sizeof (sensor_cond)); - break; - } - - if (post_sensor_event(sensorh, sensor_cond, NO_COND_TIMEDWAIT) - != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in posting " - "%s event"), PICLEVENT_CONDITION_CHANGE); - } -} - -/* - * this thread monitors the temperature when the current temperature - * raises above high warning threshold - */ -/*ARGSUSED*/ -static void * -env_temp_monitor(void *args) -{ - int ret; - timespec_t to; - int8_t sensor_reading; - char sensor_cond[BUF_SIZE]; - - (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - - for (;;) { - (void) pthread_mutex_lock(&env_temp_monitor_mutex); - if (env_curr_state == NORMAL_THRESHOLD) { - pthread_cond_wait(&env_temp_monitor_cv, - &env_temp_monitor_mutex); - } - - /* check until temp drops below warning threshold */ - to.tv_sec = ENV_TEMP_MONITOR_TIME; - to.tv_nsec = 0; - ret = pthread_cond_reltimedwait_np(&env_temp_monitor_cv, - &env_temp_monitor_mutex, &to); - if (ret != ETIMEDOUT) { - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - continue; - } - - /* read the present temperature */ - if (env_get_sensor_reading(cpu_sensor_geo_addr, - &sensor_reading) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - continue; - } - - (void) pthread_mutex_lock(&sensor_mutex); - if (sensor_reading < temp_sensor.hi_warning && - sensor_reading > temp_sensor.lo_warning) { - /* temperature is ok now */ - (void) strncpy(sensor_cond, PICLEVENTARGVAL_OK, - sizeof (sensor_cond)); - env_curr_state = NORMAL_THRESHOLD; - } - (void) pthread_mutex_unlock(&sensor_mutex); - - if (env_curr_state == NORMAL_THRESHOLD) { - syslog(LOG_NOTICE, gettext("SUNW_envmond:Current " - "temperature is ok now")); - if (post_sensor_event(sensorh, sensor_cond, - NO_COND_TIMEDWAIT) != PICL_SUCCESS) { - syslog(LOG_ERR, gettext("SUNW_envmond:Error in" - " posting %s event"), - PICLEVENT_CONDITION_CHANGE); - } - } - (void) pthread_mutex_unlock(&env_temp_monitor_mutex); - } - /*NOTREACHED*/ - return (NULL); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclsensors.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclsensors.h deleted file mode 100644 index 07a1fd365a..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/envmond/piclsensors.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PICLSENSORS_H -#define _PICLSENSORS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define CPU_SENSOR "CPU-sensor" -#define EEPROM_WARNING_CMD "eeprom warning-temperature=%d" -#define EEPROM_SHUTDOWN_CMD "eeprom critical-temperature=%d" -#define EEPROM_POWEROFF_CMD "eeprom shutdown-temperature=%d" - -#define ENV_TEMP_MONITOR_TIME 60 /* 60 secs */ - -#define NUM_OF_THRESHOLDS 6 -#define MAX_POWEROFF_TEMP 84 - -typedef struct { -uint8_t sensor_no; - int8_t curr_temp; - int8_t hi_poweroff; - int8_t hi_shutdown; - int8_t hi_warning; - int8_t lo_poweroff; - int8_t lo_shutdown; - int8_t lo_warning; - char state[20]; -} env_temp_sensor_t; - -typedef enum { - NORMAL_THRESHOLD = 0x0, /* temp is within thresholds */ - LOW_WARNING_THRESHOLD = 0x1, - LOW_SHUTDOWN_THRESHOLD = 0x2, - LOW_POWEROFF_THRESHOLD = 0x3, - HIGH_WARNING_THRESHOLD = 0x4, - HIGH_SHUTDOWN_THRESHOLD = 0x5, - HIGH_POWEROFF_THRESHOLD = 0x6 -} env_temp_threshold_t; - -#define LOW_WARNING_BIT(_X) (BIT_0(_X)) -#define LOW_SHUTDOWN_BIT(_X) (BIT_1(_X)) -#define LOW_POWEROFF_BIT(_X) (BIT_2(_X)) -#define HIGH_WARNING_BIT(_X) (BIT_3(_X)) -#define HIGH_SHUTDOWN_BIT(_X) (BIT_4(_X)) -#define HIGH_POWEROFF_BIT(_X) (BIT_5(_X)) - -#define THRESHOLD_TYPE 0x1 - -#define SMC_GET_SENSOR_READING_FAILED \ - gettext("SUNW_envmond: Error in getting sensor reading, "\ - "sensor = %d, errno = %d\n") -#define SMC_GET_SENSOR_THRES_FAILED \ - gettext("SUNW_envmond: Error in getting sensor threshold, "\ - "sensor = %d, errno = %d\n") -#define SMC_SET_SENSOR_THRES_FAILED \ - gettext("SUNW_envmond: Error in setting sensor threshold, "\ - "sensor = %d, errno = %d\n") -#define SMC_GET_LWT_FAILED \ - gettext("SUNW_envmond: Error in getting low warning threshold") -#define SMC_GET_LST_FAILED \ - gettext("SUNW_envmond: Error in getting low shutdown threshold") -#define SMC_GET_LPT_FAILED \ - gettext("SUNW_envmond: Error in getting low poweroff threshold") -#define SMC_GET_HWT_FAILED \ - gettext("SUNW_envmond: Error in getting high warning threshold") -#define SMC_GET_HST_FAILED \ - gettext("SUNW_envmond: Error in getting high shutdown threshold") -#define SMC_GET_HPT_FAILED \ - gettext("SUNW_envmond: Error in getting high poweroff threshold") -#define SMC_SET_LWT_FAILED \ - gettext("SUNW_envmond: Error in setting low warning threshold") -#define SMC_SET_LST_FAILED \ - gettext("SUNW_envmond: Error in setting low shutdown threshold") -#define SMC_SET_LPT_FAILED \ - gettext("SUNW_envmond: Error in setting low poweroff threshold") -#define SMC_SET_HWT_FAILED \ - gettext("SUNW_envmond: Error in setting high warning threshold") -#define SMC_SET_HST_FAILED \ - gettext("SUNW_envmond: Error in setting high shutdown threshold") -#define SMC_SET_HPT_FAILED \ - gettext("SUNW_envmond: Error in setting high poweroff threshold") -#define SMC_ENABLE_SENSOR_EVENT_FAILED \ - gettext("SUNW_envmond: Error in enabling sesnor events, error = %d") -#define SMC_GET_EXCLUSIVE_ERR \ - gettext("SUNW_envmond:Error in getting exclusive access to set "\ - "temperature sensor thresholds") -#ifdef __cplusplus -} -#endif - -#endif /* _PICLSENSORS_H */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/Makefile deleted file mode 100644 index 26585d2071..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/Makefile +++ /dev/null @@ -1,106 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/picl/plugins/sun4u/snowbird/frutree/Makefile -# - -include $(SRC)/Makefile.psm - -LIBRARY = libpiclfrutree.a -VERS = .1 -PLATFORM = SUNW,Netra-CP2300 - -OBJECTS = piclfrutree.o picllibdevinfo.o piclkstat.o piclscsi.o - -# include library definitions -include $(SRC)/lib/Makefile.lib - -ROOT_PLATFORM = $(USR_PLAT_DIR)/$(PLATFORM) - -include $(SRC)/cmd/picl/plugins/Makefile.com - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -I$(SRC)/uts/common/ - -SRCS= $(OBJECTS:%.o=%.c) - -LIBS= $(DYNLIB) - -ROOTLIBDIR= $(ROOT_PLAT_PLUGINDIR) - -CLEANFILES= $(LINTOUT) $(LINTLIB) - -CPPFLAGS += -I$(USR_PSM_INCL_DIR) -CPPFLAGS += -I$(SRC)/cmd/picl/plugins/lib/picld_pluginutil -CPPFLAGS += -I$(SRC)/lib/libfru/include - -LDLIBS += -L$(SRC)/lib/libptree/$(MACH) -LDLIBS += -L$(SRC)/cmd/picl/plugins/lib/picld_pluginutil/$(MACH) -LDLIBS += -L$(ROOT)/usr/lib/picl/plugins -lcfgadm -lc -lpicltree \ - -lpicld_pluginutil -lfru -lnvpair -ldevinfo \ - -lkstat -lpicldevtree -LDLIBS += -R/usr/platform/sun4u/lib/picl/plugins:/usr/lib/picl/plugins - -.KEEP_STATE: - -SUBDIRS= - -POFILE= snowbird_piclfrutree.po -POFILES= $(SRCS:%.c=%.po) - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -all: $(LIBS) $(LIBLINKS) - -install: $(ROOTLIBDIR) all $(ROOTLIBS) $(ROOTLINKS) - -$(LIBLINKS): FRC - $(RM) $@; $(SYMLINK) ./$(DYNLIB) $@ - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN)/$(POFILE) - -$(POFILE): $(POFILES) - $(CAT) $(POFILES) > $(POFILE) - -$(MSGDOMAIN): - $(INS.dir) - -# include library targets -include $(SRC)/lib/Makefile.targ -include $(SRC)/cmd/picl/plugins/Makefile.targ - -lint : - $(LINT.c) $(SRCS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclfrutree.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclfrutree.c deleted file mode 100644 index f4a906c232..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclfrutree.c +++ /dev/null @@ -1,5969 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * platform independent module to manage nodes under frutree - */ - -/* - * This file has the frutree initialization code: - * 1) parse the config file to create all locations in the chassis - * 2) probe each location to find fru and probe the fru recursively to - * create locations, port nodes - * 3) handle hotswap picl events (dr_ap_state_change, dr_req) - * - update the frutree - * - send out picl-state-change, picl-condition-events - * 4) Monitor the port nodes state and condition - */ - -#include <stdlib.h> -#include <sys/param.h> -#include <strings.h> -#include <string.h> -#include <limits.h> -#include <syslog.h> -#include <pthread.h> -#include <thread.h> -#include <libintl.h> -#include <sys/systeminfo.h> -#include <sys/types.h> -#include <unistd.h> -#include <sys/stat.h> -#include <dirent.h> -#include <fcntl.h> -#include <ctype.h> -#include <time.h> -#include <poll.h> -#include <assert.h> -#include <libnvpair.h> -#include <alloca.h> -#include <stdarg.h> -#include <config_admin.h> -#include <libdevinfo.h> -#include <synch.h> -#include <sys/time.h> -#include <picl.h> -#include <picltree.h> -#include <picldefs.h> -#include <picld_pluginutil.h> -#include <libfru.h> -#include <sys/sysevent/dr.h> -#include <ptree_impl.h> -#include "piclfrutree.h" - -#pragma init(piclfrutree_register) - -/* - * following values are tunables that can be changed using - * environment variables - */ -int frutree_debug = NONE; /* debug switch */ -static int frutree_poll_timeout = 5; /* polling time to monitor ports */ -static int frutree_drwait_time = 10; /* wait time for dr operation */ - -#define PICL_PROP_CONF_FILE "conf_name" -#define PICL_ADMINLOCK_DISABLED "disabled" -#define PICL_ADMINLOCK_ENABLED "enabled" -#define HASH_TABLE_SIZE (64) -#define BUF_SIZE 25 -#define HASH_INDEX(s, x) ((int)((x) & ((s) - 1))) -#define FRUDATA_PTR(_X) ((frutree_frunode_t *)(((hashdata_t *)(_X))->data)) -#define LOCDATA_PTR(_X) ((frutree_locnode_t *)(((hashdata_t *)(_X))->data)) -#define PORTDATA_PTR(_X) ((frutree_portnode_t *)(((hashdata_t *)(_X))->data)) - -/* Hash table structure */ -typedef struct frutree_hash_elm { - picl_nodehdl_t hdl; - void *nodep; - struct frutree_hash_elm *nextp; -} frutree_hashelm_t; - -typedef struct { - int hash_size; - frutree_hashelm_t **tbl; -} frutree_hash_t; - -typedef struct { - frutree_datatype_t type; - void *data; -} hashdata_t; - -typedef int (*callback_t)(picl_nodehdl_t, void *); -typedef enum { - INIT_FRU = 0x0, - CREATE_DEVICES_ENTRIES, - CONFIGURE_FRU, - UNCONFIGURE_FRU, - CPU_OFFLINE, - CPU_ONLINE, - HANDLE_CONFIGURE, - HANDLE_UNCONFIGURE, - HANDLE_INSERT, - HANDLE_REMOVE, - HANDLE_LOCSTATE_CHANGE, - POST_COND_EVENT, - POST_EVENTS -} action_t; - -typedef struct { - action_t action; - void *data; -} frutree_dr_arg_t; - -typedef struct event_queue { - frutree_dr_arg_t arg; - struct event_queue *next; -}ev_queue_t; - -typedef struct { - char node_name[PICL_PROPNAMELEN_MAX]; - picl_nodehdl_t retnodeh; -} frutree_callback_data_t; - -typedef struct remove_list { - picl_nodehdl_t nodeh; - struct remove_list *next; -} delete_list_t; - -typedef struct { - frutree_frunode_t *frup; - delete_list_t *first; -} frutree_init_callback_arg_t; - -boolean_t frutree_connects_initiated = B_FALSE; -static ev_queue_t *queue_head = NULL; -static ev_queue_t *queue_tail = NULL; -static pthread_mutex_t ev_mutex; -static pthread_cond_t ev_cond; - -static frutree_hash_t node_hash_table = {0, NULL}; -static picl_nodehdl_t chassish = 0; -static picl_nodehdl_t frutreeh = 0; -static picl_nodehdl_t rooth = 0; -static picl_nodehdl_t platformh = 0; -static boolean_t post_picl_events = B_FALSE; -static int piclevent_pending = 0; -static char conf_file[MAXPATHLEN]; -static char sys_name[SYS_NMLN]; - -static mutex_t piclevent_mutex = DEFAULTMUTEX; -static cond_t piclevent_completed_cv = DEFAULTCV; -static rwlock_t hash_lock; - -static pthread_t tid; -static void *dr_thread(void *); - -static pthread_t init_threadID; -static pthread_t monitor_tid; -static pthread_mutex_t monitor_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t monitor_cv = PTHREAD_COND_INITIALIZER; -static int fini_called = 0; -static void *monitor_node_status(void *); -static ev_queue_t *remove_from_queue(void); -static picl_errno_t handle_chassis_configure(frutree_frunode_t *frup); - -/* - * location states. - */ -static char *loc_state[] = { - PICLEVENTARGVAL_UNKNOWN, - PICLEVENTARGVAL_EMPTY, - PICLEVENTARGVAL_CONNECTED, - PICLEVENTARGVAL_DISCONNECTED, - PICLEVENTARGVAL_CONNECTING, - PICLEVENTARGVAL_DISCONNECTING, - NULL -}; - -/* - * fru states. - */ -static char *fru_state[] = { - PICLEVENTARGVAL_UNKNOWN, - PICLEVENTARGVAL_CONFIGURED, - PICLEVENTARGVAL_UNCONFIGURED, - PICLEVENTARGVAL_CONFIGURING, - PICLEVENTARGVAL_UNCONFIGURING, - NULL -}; - -/* - * fru condition. - */ -static char *fru_cond[] = { - PICLEVENTARGVAL_UNKNOWN, - PICLEVENTARGVAL_FAILED, - PICLEVENTARGVAL_FAILING, - PICLEVENTARGVAL_OK, - PICLEVENTARGVAL_TESTING, - NULL -}; - -/* - * port states. - */ -static char *port_state[] = { - PICLEVENTARGVAL_DOWN, - PICLEVENTARGVAL_UP, - PICLEVENTARGVAL_UNKNOWN, - NULL -}; - -/* - * port condition. - */ -static char *port_cond[] = { - PICLEVENTARGVAL_OK, - PICLEVENTARGVAL_FAILING, - PICLEVENTARGVAL_FAILED, - PICLEVENTARGVAL_TESTING, - PICLEVENTARGVAL_UNKNOWN, - NULL -}; - -/* mapping between libcfgadm error codes to picl error codes */ -static const int cfg2picl_errmap[][2] = { - {CFGA_OK, PICL_SUCCESS}, - {CFGA_NACK, PICL_NORESPONSE}, - {CFGA_NOTSUPP, PICL_NOTSUPPORTED}, - {CFGA_OPNOTSUPP, PICL_NOTSUPPORTED}, - {CFGA_PRIV, PICL_FAILURE}, - {CFGA_BUSY, PICL_TREEBUSY}, - {CFGA_SYSTEM_BUSY, PICL_TREEBUSY}, - {CFGA_DATA_ERROR, PICL_FAILURE}, - {CFGA_LIB_ERROR, PICL_FAILURE}, - {CFGA_NO_LIB, PICL_FAILURE}, - {CFGA_INSUFFICENT_CONDITION, PICL_FAILURE}, - {CFGA_INVAL, PICL_INVALIDARG}, - {CFGA_ERROR, PICL_FAILURE}, - {CFGA_APID_NOEXIST, PICL_NODENOTFOUND}, - {CFGA_ATTR_INVAL, PICL_INVALIDARG} -}; - -/* local functions */ -static void piclfrutree_register(void); -static void piclfrutree_init(void); -static void piclfrutree_fini(void); -static void * init_thread(void *); -static void frutree_wd_evhandler(const char *, const void *, size_t, void *); -static void frutree_dr_apstate_change_evhandler(const char *, const void *, - size_t, void *); -static void frutree_dr_req_evhandler(const char *, const void *, - size_t, void *); -static void frutree_cpu_state_change_evhandler(const char *, const void *, - size_t, void *); -static void init_queue(void); -static void frutree_get_env(); -static picl_errno_t hash_init(void); -static picl_errno_t hash_remove_entry(picl_nodehdl_t); -static picl_errno_t hash_lookup_entry(picl_nodehdl_t, void **); -static void hash_destroy(); -static picl_errno_t initialize_frutree(); -static picl_errno_t update_loc_state(frutree_locnode_t *, boolean_t *); -static int is_autoconfig_enabled(char *); -static picl_errno_t do_action(picl_nodehdl_t, int action, void *); -static picl_errno_t probe_fru(frutree_frunode_t *, boolean_t); -static picl_errno_t handle_fru_unconfigure(frutree_frunode_t *); -static picl_errno_t update_loc_state(frutree_locnode_t *, boolean_t *); -static picl_errno_t update_fru_state(frutree_frunode_t *, boolean_t *); -static picl_errno_t update_port_state(frutree_portnode_t *, boolean_t); -static picl_errno_t configure_fru(frutree_frunode_t *, cfga_flags_t); -static picl_errno_t post_piclevent(const char *, char *, char *, - picl_nodehdl_t, frutree_wait_t); -static picl_errno_t fru_init(frutree_frunode_t *); - -/* External functions */ -extern boolean_t is_fru_present_under_location(frutree_locnode_t *); -extern int kstat_port_state(frutree_port_type_t, char *, int); -extern int kstat_port_cond(frutree_port_type_t, char *, int); -extern picl_errno_t probe_libdevinfo(frutree_frunode_t *, - frutree_device_args_t **, boolean_t); -extern picl_errno_t get_scsislot_name(char *, char *, char *); -extern picl_errno_t probe_for_scsi_frus(frutree_frunode_t *); -extern picl_errno_t get_fru_path(char *, frutree_frunode_t *); -extern picl_errno_t scsi_info_init(); -extern void scsi_info_fini(); -extern picl_errno_t get_port_info(frutree_portnode_t *); -extern char *strtok_r(char *s1, const char *s2, char **lasts); - -/* Plugin initialization */ -static picld_plugin_reg_t frutree_reg_info = { - PICLD_PLUGIN_VERSION_1, - PICLD_PLUGIN_CRITICAL, - "SUNW_piclfrutree", - piclfrutree_init, - piclfrutree_fini -}; - -/* ptree entry points */ -static void -piclfrutree_register(void) -{ - FRUTREE_DEBUG0(FRUTREE_INIT, "piclfrutree register"); - (void) picld_plugin_register(&frutree_reg_info); -} - -static void -piclfrutree_init(void) -{ - FRUTREE_DEBUG0(FRUTREE_INIT, "piclfrutree_init begin"); - (void) rwlock_init(&hash_lock, USYNC_THREAD, NULL); - fini_called = 0; - - /* read the environment variables */ - frutree_get_env(); - - if (sysinfo(SI_PLATFORM, sys_name, sizeof (sys_name)) == -1) { - return; - } - - if (hash_init() != PICL_SUCCESS) { - return; - } - if (initialize_frutree() != PICL_SUCCESS) { - return; - } - - /* initialize the event queue */ - (void) init_queue(); - - (void) pthread_cond_init(&ev_cond, NULL); - (void) pthread_mutex_init(&ev_mutex, NULL); - if (pthread_create(&tid, NULL, &dr_thread, NULL) != 0) { - return; - } - /* register for picl events */ - if (ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE, - frutree_dr_apstate_change_evhandler, NULL) != - PICL_SUCCESS) { - return; - } - - if (ptree_register_handler(PICLEVENT_DR_REQ, - frutree_dr_req_evhandler, NULL) != PICL_SUCCESS) { - return; - } - - if (ptree_register_handler(PICLEVENT_CPU_STATE_CHANGE, - frutree_cpu_state_change_evhandler, NULL) != - PICL_SUCCESS) { - return; - } - - if (ptree_register_handler(PICLEVENT_STATE_CHANGE, - frutree_wd_evhandler, NULL) != PICL_SUCCESS) { - return; - } - FRUTREE_DEBUG0(FRUTREE_INIT, "piclfrutree_init end"); -} - -static void -piclfrutree_fini(void) -{ - ev_queue_t *event = NULL; - void *exitval; - - FRUTREE_DEBUG0(EVENTS, "piclfrutree_fini begin"); - - fini_called = 1; - /* unregister event handlers */ - (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE, - frutree_dr_apstate_change_evhandler, NULL); - (void) ptree_unregister_handler(PICLEVENT_DR_REQ, - frutree_dr_req_evhandler, NULL); - (void) ptree_unregister_handler(PICLEVENT_CPU_STATE_CHANGE, - frutree_cpu_state_change_evhandler, NULL); - (void) ptree_unregister_handler(PICLEVENT_STATE_CHANGE, - frutree_wd_evhandler, NULL); - - /* flush the event queue */ - (void) pthread_mutex_lock(&ev_mutex); - event = remove_from_queue(); - while (event) { - free(event); - event = remove_from_queue(); - } - queue_head = queue_tail = NULL; - - (void) pthread_cond_broadcast(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - (void) pthread_cancel(tid); - (void) pthread_join(tid, &exitval); - (void) pthread_cancel(monitor_tid); - (void) pthread_join(monitor_tid, &exitval); - (void) pthread_cancel(init_threadID); - (void) pthread_join(init_threadID, &exitval); - - hash_destroy(); - (void) ptree_delete_node(frutreeh); - (void) ptree_destroy_node(frutreeh); - - frutree_connects_initiated = B_FALSE; - chassish = frutreeh = rooth = platformh = 0; - post_picl_events = B_FALSE; - piclevent_pending = 0; - FRUTREE_DEBUG0(EVENTS, "piclfrutree_fini end"); -} - -/* read the ENVIRONMENT variables and initialize tunables */ -static void -frutree_get_env() -{ - char *val; - int intval = 0; - - /* read frutree debug flag value */ - if (val = getenv(FRUTREE_DEBUG)) { - errno = 0; - intval = strtol(val, (char **)NULL, 0); - if (errno == 0) { - frutree_debug = intval; - FRUTREE_DEBUG1(PRINT_ALL, "SUNW_frutree:debug = %x", - frutree_debug); - } - } - - /* read poll timeout value */ - if (val = getenv(FRUTREE_POLL_TIMEOUT)) { - errno = 0; - intval = strtol(val, (char **)NULL, 0); - if (errno == 0) { - frutree_poll_timeout = intval; - } - } - - /* read drwait time value */ - if (val = getenv(FRUTREE_DRWAIT)) { - errno = 0; - intval = strtol(val, (char **)NULL, 0); - if (errno == 0) { - frutree_drwait_time = intval; - } - } -} - -/* - * callback function for ptree_walk_tree_class to get the - * node handle of node - * matches a node with same class and name - */ -static int -frutree_get_nodehdl(picl_nodehdl_t nodeh, void *c_args) -{ - picl_errno_t rc; - char name[PICL_PROPNAMELEN_MAX]; - frutree_callback_data_t *fru_arg; - - if (c_args == NULL) - return (PICL_INVALIDARG); - fru_arg = (frutree_callback_data_t *)c_args; - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, name, - sizeof (name))) != PICL_SUCCESS) { - return (rc); - } - - if (strcmp(fru_arg->node_name, name) == 0) { - fru_arg->retnodeh = nodeh; - return (PICL_WALK_TERMINATE); - } - return (PICL_WALK_CONTINUE); -} - -/* queue implementation (used to queue hotswap events) */ -static void -init_queue(void) -{ - queue_head = NULL; - queue_tail = NULL; -} - -/* add an event to the queue */ -static int -add_to_queue(frutree_dr_arg_t dr_data) -{ - ev_queue_t *new_event; - - new_event = (ev_queue_t *)malloc(sizeof (ev_queue_t)); - if (new_event == NULL) - return (PICL_NOSPACE); - - new_event->arg.action = dr_data.action; - new_event->arg.data = dr_data.data; - new_event->next = NULL; - - if (queue_head == NULL) { - queue_head = new_event; - } else { - queue_tail->next = new_event; - } - queue_tail = new_event; - - return (PICL_SUCCESS); -} - -static ev_queue_t * -remove_from_queue(void) -{ - ev_queue_t *event = NULL; - - if (queue_head == NULL) - return (NULL); - - event = queue_head; - queue_head = queue_head->next; - - if (queue_head == NULL) - queue_tail = NULL; - return (event); -} - -/* - * event handler for watchdog expiry event (picl-state-change) event on - * watchdog-timer node - */ -/* ARGSUSED */ -static void -frutree_wd_evhandler(const char *ename, const void *earg, size_t size, - void *cookie) -{ - nvlist_t *nvlp; - char *wd_state = NULL; - picl_errno_t rc; - picl_nodehdl_t wd_nodehdl; - char value[PICL_PROPNAMELEN_MAX]; - frutree_callback_data_t fru_arg; - - if (ename == NULL) - return; - - if (strncmp(ename, PICLEVENT_STATE_CHANGE, - strlen(PICLEVENT_STATE_CHANGE))) { - return; - } - - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - - if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, - &wd_nodehdl) == -1) { - nvlist_free(nvlp); - return; - } - - if (nvlist_lookup_string(nvlp, PICLEVENTARG_STATE, - &wd_state) != 0) { - nvlist_free(nvlp); - return; - } - - if ((rc = ptree_get_propval_by_name(wd_nodehdl, - PICL_PROP_CLASSNAME, value, sizeof (value))) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - /* if the event is not of watchdog-timer, return */ - if (strcmp(value, PICL_CLASS_WATCHDOG_TIMER) != 0) { - nvlist_free(nvlp); - return; - } - - FRUTREE_DEBUG1(EVENTS, "frutree:Received WD event(%s)", wd_state); - /* frutree plugin handles only watchdog expiry events */ - if (strcmp(wd_state, PICL_PROPVAL_WD_STATE_EXPIRED) != 0) { - nvlist_free(nvlp); - return; - } - - if ((rc = ptree_get_propval_by_name(wd_nodehdl, - PICL_PROP_WATCHDOG_ACTION, value, sizeof (value))) != - PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - /* if action is none, dont do anything */ - if (strcmp(value, PICL_PROPVAL_WD_ACTION_NONE) == 0) { - nvlist_free(nvlp); - return; - } - - /* find the CPU nodehdl */ - (void) strncpy(fru_arg.node_name, SANIBEL_PICLNODE_CPU, - sizeof (fru_arg.node_name)); - fru_arg.retnodeh = 0; - if ((rc = ptree_walk_tree_by_class(chassish, PICL_CLASS_FRU, - &fru_arg, frutree_get_nodehdl)) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - if (fru_arg.retnodeh == NULL) { - nvlist_free(nvlp); - return; - } - - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - PICLEVENTARGVAL_FAILED, NULL, fru_arg.retnodeh, - NO_WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - SANIBEL_PICLNODE_CPU, PICLEVENT_CONDITION_CHANGE, rc); - } - nvlist_free(nvlp); -} - -/* - * event handler for dr_ap_state_change event - * - determine the event type and queue it in dr_queue to handle it - */ -/* ARGSUSED */ -static void -frutree_dr_apstate_change_evhandler(const char *ename, const void *earg, - size_t size, void *cookie) -{ - nvlist_t *nvlp; - char *name = NULL; - char *ap_id = NULL; - char *hint = NULL; - picl_nodehdl_t nodeh, childh; - hashdata_t *hashptr = NULL; - frutree_dr_arg_t dr_arg; - frutree_frunode_t *frup = NULL; - frutree_locnode_t *locp = NULL; - frutree_callback_data_t fru_arg; - boolean_t state_changed = B_FALSE; - - if (ename == NULL) - return; - - if (strncmp(ename, PICLEVENT_DR_AP_STATE_CHANGE, - strlen(PICLEVENT_DR_AP_STATE_CHANGE)) != 0) { - return; - } - - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - - if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id) == -1) { - nvlist_free(nvlp); - return; - } - - if (nvlist_lookup_string(nvlp, PICLEVENTARG_HINT, &hint) == -1) { - nvlist_free(nvlp); - return; - } - - /* check for empty strings */ - if (!ap_id || !hint) { - FRUTREE_DEBUG0(EVENTS, "Empty hint/ap_id"); - nvlist_free(nvlp); - return; - } - - /* get the location name */ - name = strrchr(ap_id, ':'); - if (name == NULL) { - name = ap_id; - } else { - name++; - } - - /* find the loc object */ - (void) strncpy(fru_arg.node_name, name, sizeof (fru_arg.node_name)); - fru_arg.retnodeh = 0; - if (ptree_walk_tree_by_class(chassish, PICL_CLASS_LOCATION, - &fru_arg, frutree_get_nodehdl) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - if (fru_arg.retnodeh == NULL) { - nvlist_free(nvlp); - return; - } - nodeh = fru_arg.retnodeh; - - if (hash_lookup_entry(nodeh, (void **)&hashptr) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - locp = LOCDATA_PTR(hashptr); - if (locp == NULL) { - nvlist_free(nvlp); - return; - } - - if (strcmp(hint, DR_HINT_INSERT) == 0) { - dr_arg.action = HANDLE_INSERT; - dr_arg.data = locp; - (void) pthread_mutex_lock(&ev_mutex); - if (add_to_queue(dr_arg) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - - if (strcmp(hint, DR_HINT_REMOVE) == 0) { - dr_arg.action = HANDLE_REMOVE; - dr_arg.data = locp; - (void) pthread_mutex_lock(&ev_mutex); - if (add_to_queue(dr_arg) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - - if (strcmp(hint, DR_RESERVED_ATTR) != 0) { /* unknown event */ - nvlist_free(nvlp); - return; - } - - /* handle DR_RESERVED_ATTR HINT */ - /* check if this is a fru event */ - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - /* get the child fru information */ - if (hash_lookup_entry(childh, (void **)&hashptr) == - PICL_SUCCESS) { - frup = FRUDATA_PTR(hashptr); - } - } - if (frup == NULL) { - nvlist_free(nvlp); - return; - } - - (void) pthread_mutex_lock(&frup->mutex); - if (frup->dr_in_progress) { - /* dr in progress, neglect the event */ - (void) pthread_mutex_unlock(&frup->mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_mutex_unlock(&frup->mutex); - - if (update_fru_state(frup, &state_changed) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - if (state_changed) { - (void) pthread_mutex_lock(&frup->mutex); - /* figure out if this is config/unconfig operation */ - if (frup->state == FRU_STATE_CONFIGURED) { - dr_arg.action = HANDLE_CONFIGURE; - dr_arg.data = frup; - } else if (frup->state == FRU_STATE_UNCONFIGURED) { - dr_arg.action = HANDLE_UNCONFIGURE; - dr_arg.data = frup; - } - (void) pthread_mutex_unlock(&frup->mutex); - - (void) pthread_mutex_lock(&ev_mutex); - if (add_to_queue(dr_arg) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - - /* check if this event is related to location */ - (void) pthread_mutex_lock(&locp->mutex); - if (locp->dr_in_progress) { - /* dr in progress, neglect the event */ - (void) pthread_mutex_unlock(&locp->mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_mutex_unlock(&locp->mutex); - if (update_loc_state(locp, &state_changed) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - if (state_changed) { /* location state has changed */ - dr_arg.action = HANDLE_LOCSTATE_CHANGE; - dr_arg.data = locp; - - (void) pthread_mutex_lock(&ev_mutex); - if (add_to_queue(dr_arg) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - /* duplicate event */ - nvlist_free(nvlp); -} - -/* - * Event handler for dr_req event - */ -/* ARGSUSED */ -static void -frutree_dr_req_evhandler(const char *ename, const void *earg, size_t size, - void *cookie) -{ - nvlist_t *nvlp; - char *name = NULL; - char *ap_id = NULL; - char *dr_req = NULL; - picl_nodehdl_t nodeh; - frutree_dr_arg_t dr_arg; - hashdata_t *hashptr = NULL; - frutree_frunode_t *frup = NULL; - frutree_callback_data_t fru_arg; - - if (ename == NULL) - return; - - if (strncmp(ename, PICLEVENT_DR_REQ, strlen(PICLEVENT_DR_REQ)) != 0) { - return; - } - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id) == -1) { - nvlist_free(nvlp); - return; - } - if (nvlist_lookup_string(nvlp, PICLEVENTARG_DR_REQ_TYPE, - &dr_req) == -1) { - nvlist_free(nvlp); - return; - } - - if (!ap_id || !dr_req) { - FRUTREE_DEBUG0(EVENTS, "Empty dr_req/ap_id"); - nvlist_free(nvlp); - return; - } - - /* get the location name */ - name = strrchr(ap_id, ':'); - if (name == NULL) { - name = ap_id; - } else { - name++; - } - - if (name == NULL) { - nvlist_free(nvlp); - return; - } - - FRUTREE_DEBUG2(EVENTS, "DR_REQ:%s on %s", dr_req, name); - (void) strncpy(fru_arg.node_name, name, sizeof (fru_arg.node_name)); - fru_arg.retnodeh = 0; - if (ptree_walk_tree_by_class(frutreeh, PICL_CLASS_FRU, - &fru_arg, frutree_get_nodehdl) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - if (fru_arg.retnodeh == NULL) { - nvlist_free(nvlp); - return; - } - nodeh = fru_arg.retnodeh; - - /* find the fru object */ - if (hash_lookup_entry(nodeh, (void **)&hashptr) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - frup = FRUDATA_PTR(hashptr); - if (frup == NULL) { - nvlist_free(nvlp); - return; - } - - if (strcmp(dr_req, DR_REQ_INCOMING_RES) == 0) { - dr_arg.action = CONFIGURE_FRU; - dr_arg.data = frup; - - } else if (strcmp(dr_req, DR_REQ_OUTGOING_RES) == 0) { - dr_arg.action = UNCONFIGURE_FRU; - dr_arg.data = frup; - - } else { - nvlist_free(nvlp); - return; - } - - (void) pthread_mutex_lock(&ev_mutex); - if (add_to_queue(dr_arg) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); -} - -/* - * Event handler for cpu_state_change event - */ -/* ARGSUSED */ -static void -frutree_cpu_state_change_evhandler(const char *ename, const void *earg, - size_t size, void *cookie) -{ - char *hint = NULL; - nvlist_t *nvlp; - frutree_frunode_t *frup = NULL; - hashdata_t *hashptr = NULL; - picl_nodehdl_t nodeh; - frutree_dr_arg_t dr_arg; - - if (ename == NULL) - return; - - if (strncmp(ename, PICLEVENT_CPU_STATE_CHANGE, - strlen(PICLEVENT_CPU_STATE_CHANGE)) != 0) { - return; - } - - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - if (nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, &nodeh) == -1) { - nvlist_free(nvlp); - return; - } - if (nvlist_lookup_string(nvlp, PICLEVENTARG_CPU_EV_TYPE, &hint) == -1) { - nvlist_free(nvlp); - return; - } - - if (hash_lookup_entry(nodeh, (void **)&hashptr) != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - frup = FRUDATA_PTR(hashptr); - if (frup == NULL) { - nvlist_free(nvlp); - return; - } - - if (strcmp(hint, PICLEVENTARGVAL_OFFLINE) == 0) { - dr_arg.action = CPU_OFFLINE; - dr_arg.data = frup; - } else if (strcmp(hint, PICLEVENTARGVAL_ONLINE) == 0) { - dr_arg.action = CPU_ONLINE; - dr_arg.data = frup; - } else { - nvlist_free(nvlp); - return; - } - - (void) pthread_mutex_lock(&ev_mutex); - if (add_to_queue(dr_arg) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); - return; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - nvlist_free(nvlp); -} - -static void -attach_driver(char *driver) -{ - char cmd[BUF_SIZE]; - cmd[0] = '\0'; - (void) snprintf(cmd, sizeof (cmd), "%s %s", - DEVFSADM_CMD, driver); - (void) pclose(popen(cmd, "r")); -} - -/* - * Find the node in platform tree with given devfs-path. - * ptree_find_node is getting a node with devfs-path /pci@1f,0/pci@1,1 - * when we want to find node with /pci@1f,0/pci@1. The fix - * is required in libpicltree. For now use ptree_walk_tree_by_class - * to find the node. - */ -static int -find_ref_parent(picl_nodehdl_t nodeh, void *c_args) -{ - picl_prophdl_t proph; - ptree_propinfo_t propinfo; - void *vbuf; - frutree_callback_data_t *fru_arg; - - if (c_args == NULL) - return (PICL_INVALIDARG); - fru_arg = (frutree_callback_data_t *)c_args; - - if (ptree_get_prop_by_name(nodeh, PICL_PROP_DEVFS_PATH, - &proph) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if (ptree_get_propinfo(proph, &propinfo) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - vbuf = alloca(propinfo.piclinfo.size); - if (vbuf == NULL) - return (PICL_WALK_CONTINUE); - - if (ptree_get_propval(proph, vbuf, - propinfo.piclinfo.size) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - /* compare the devfs_path */ - if (strcmp(fru_arg->node_name, (char *)vbuf) == 0) { - fru_arg->retnodeh = nodeh; - return (PICL_WALK_TERMINATE); - } - return (PICL_WALK_CONTINUE); -} -/* - * Find the reference node in /platform tree - * return : 0 - if node is not found - */ -static picl_nodehdl_t -get_reference_handle(picl_nodehdl_t nodeh) -{ - picl_prophdl_t proph; - ptree_propinfo_t propinfo; - void *vbuf; - picl_errno_t rc = PICL_SUCCESS; - char devfs_path[PICL_PROPNAMELEN_MAX]; - char value[PICL_PROPNAMELEN_MAX]; - char class[PICL_PROPNAMELEN_MAX]; - frutree_callback_data_t fru_arg; - picl_nodehdl_t refhdl = 0, ref_parent = 0, nodehdl = 0; - - /* - * for fru node, get the devfspath and bus-addr of - * its parent. - */ - if (ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, - class, sizeof (class)) != PICL_SUCCESS) { - return (0); - } - - if (strcmp(class, PICL_CLASS_FRU) == 0) { - if (ptree_get_propval_by_name(nodeh, PICL_PROP_PARENT, - &nodehdl, sizeof (nodehdl)) != PICL_SUCCESS) { - return (0); - } - } else if (strcmp(class, PICL_CLASS_PORT) == 0) { - nodehdl = nodeh; - } else { - return (0); - } - - if (ptree_get_propval_by_name(nodehdl, PICL_PROP_DEVFS_PATH, - devfs_path, sizeof (devfs_path)) != PICL_SUCCESS) { - return (0); - } - if (ptree_get_propval_by_name(nodehdl, PICL_PROP_BUS_ADDR, - value, sizeof (value)) != PICL_SUCCESS) { - return (0); - } - - /* find the node with same devfs-path */ - (void) strncpy(fru_arg.node_name, devfs_path, - sizeof (fru_arg.node_name)); - fru_arg.retnodeh = 0; - if (ptree_walk_tree_by_class(platformh, NULL, - (void *)&fru_arg, find_ref_parent) != PICL_SUCCESS) { - return (0); - } - - if (fru_arg.retnodeh == NULL) - return (0); - - ref_parent = fru_arg.retnodeh; - /* traverse thru childeren and find the reference node */ - rc = ptree_get_propval_by_name(ref_parent, PICL_PROP_CHILD, - &refhdl, sizeof (picl_nodehdl_t)); - while (rc == PICL_SUCCESS) { - nodehdl = refhdl; - rc = ptree_get_propval_by_name(refhdl, PICL_PROP_PEER, - &refhdl, sizeof (picl_nodehdl_t)); - /* - * compare the bus_addr or Unit address - * format of bus_addr can be either (1,3 or 0x6) - */ - if (ptree_get_prop_by_name(nodehdl, PICL_PROP_BUS_ADDR, - &proph) != PICL_SUCCESS) { - if (ptree_get_prop_by_name(nodehdl, - PICL_PROP_UNIT_ADDRESS, &proph) != - PICL_SUCCESS) { - continue; - } - } - - if (ptree_get_propinfo(proph, &propinfo) != PICL_SUCCESS) { - continue; - } - - vbuf = alloca(propinfo.piclinfo.size); - if (vbuf == NULL) - continue; - - if (ptree_get_propval(proph, vbuf, - propinfo.piclinfo.size) != PICL_SUCCESS) { - continue; - } - - if (strchr((char *)vbuf, ',') != NULL) { - if (strcmp(value, (char *)vbuf) == 0) { - return (nodehdl); - } - } else { - if (strtoul((char *)vbuf, NULL, 16) == - strtoul(value, NULL, 16)) { - return (nodehdl); - } - } - } - return (0); -} - -/* Hash Table Management */ -static void -free_data(frutree_datatype_t type, hashdata_t *datap) -{ - frutree_frunode_t *frup = NULL; - frutree_locnode_t *locp = NULL; - frutree_portnode_t *portp = NULL; - - if (datap == NULL) { - return; - } - - switch (type) { - case FRU_TYPE: - frup = (frutree_frunode_t *)datap->data; - free(frup->name); - (void) pthread_mutex_destroy(&frup->mutex); - (void) pthread_cond_destroy(&frup->cond_cv); - (void) pthread_cond_destroy(&frup->busy_cond_cv); - free(frup); - break; - case LOC_TYPE: - locp = (frutree_locnode_t *)datap->data; - free(locp->name); - (void) pthread_mutex_destroy(&locp->mutex); - (void) pthread_cond_destroy(&locp->cond_cv); - free(locp); - break; - case PORT_TYPE: - portp = (frutree_portnode_t *)datap->data; - free(portp->name); - free(portp); - break; - } - free(datap); -} - -/* - * Initialize the hash table - */ -static picl_errno_t -hash_init(void) -{ - int i; - - FRUTREE_DEBUG0(HASHTABLE, "hash_init begin"); - node_hash_table.tbl = (frutree_hashelm_t **)malloc( - sizeof (frutree_hashelm_t *) * HASH_TABLE_SIZE); - - if (node_hash_table.tbl == NULL) { - return (PICL_NOSPACE); - } - - /* initialize each entry in hashtable */ - node_hash_table.hash_size = HASH_TABLE_SIZE; - for (i = 0; i < node_hash_table.hash_size; ++i) { - node_hash_table.tbl[i] = NULL; - } - return (PICL_SUCCESS); -} - -/* - * Destroy the hash table - */ -static void -hash_destroy(void) -{ - int i; - frutree_hashelm_t *el; - hashdata_t *datap = NULL; - - (void) rw_wrlock(&hash_lock); - if (node_hash_table.tbl == NULL) { - (void) rw_unlock(&hash_lock); - return; - } - - /* loop thru each linked list in the table and free */ - for (i = 0; i < node_hash_table.hash_size; ++i) { - while (node_hash_table.tbl[i] != NULL) { - el = node_hash_table.tbl[i]; - node_hash_table.tbl[i] = el->nextp; - datap = (hashdata_t *)el->nodep; - free_data(datap->type, datap); - el->nodep = NULL; - free(el); - el = NULL; - } - } - free(node_hash_table.tbl); - (void) rw_unlock(&hash_lock); -} - -/* - * Add an entry to the hash table - */ -static picl_errno_t -hash_add_entry(picl_nodehdl_t hdl, void *nodep) -{ - int indx; - frutree_hashelm_t *el; - - FRUTREE_DEBUG0(HASHTABLE, "hash_add_entry : begin"); - (void) rw_wrlock(&hash_lock); - - if (node_hash_table.tbl == NULL) { - (void) rw_unlock(&hash_lock); - return (PICL_NOTINITIALIZED); - } - - el = (frutree_hashelm_t *)malloc(sizeof (frutree_hashelm_t)); - if (el == NULL) { - (void) rw_unlock(&hash_lock); - return (PICL_NOSPACE); - } - - el->hdl = hdl; - el->nodep = nodep; - el->nextp = NULL; - - if (frutree_debug & HASHTABLE) { - picl_nodehdl_t nodeid; - nodeid = hdl; - cvt_ptree2picl(&nodeid); - FRUTREE_DEBUG1(HASHTABLE, "added node: %llx", nodeid); - } - - indx = HASH_INDEX(node_hash_table.hash_size, hdl); - if (node_hash_table.tbl[indx] == NULL) { - /* first element for this index */ - node_hash_table.tbl[indx] = el; - (void) rw_unlock(&hash_lock); - return (PICL_SUCCESS); - } - - el->nextp = node_hash_table.tbl[indx]; - node_hash_table.tbl[indx] = el; - (void) rw_unlock(&hash_lock); - return (PICL_SUCCESS); -} - -/* - * Remove a hash entry from the table - */ -static picl_errno_t -hash_remove_entry(picl_nodehdl_t hdl) -{ - int i; - hashdata_t *datap = NULL; - frutree_hashelm_t *prev, *cur; - - (void) rw_wrlock(&hash_lock); - - if (node_hash_table.tbl == NULL) { - (void) rw_unlock(&hash_lock); - return (PICL_NOTINITIALIZED); - } - - i = HASH_INDEX(node_hash_table.hash_size, hdl); - - /* check that the hash chain is not empty */ - if (node_hash_table.tbl[i] == NULL) { - (void) rw_wrlock(&hash_lock); - return (PICL_NODENOTFOUND); - } - - /* search hash chain for entry to be removed */ - prev = NULL; - cur = node_hash_table.tbl[i]; - while (cur) { - if (cur->hdl == hdl) { - if (prev == NULL) { /* 1st elem in hash chain */ - node_hash_table.tbl[i] = cur->nextp; - } else { - prev->nextp = cur->nextp; - } - datap = (hashdata_t *)cur->nodep; - free_data(datap->type, datap); - cur->nodep = NULL; - free(cur); - cur = NULL; - - if (frutree_debug & HASHTABLE) { - picl_nodehdl_t nodeid; - nodeid = hdl; - cvt_ptree2picl(&nodeid); - FRUTREE_DEBUG1(HASHTABLE, "removed node: %llx", - nodeid); - } - - (void) rw_unlock(&hash_lock); - return (PICL_SUCCESS); - } - prev = cur; - cur = cur->nextp; - } - - /* entry was not found */ - (void) rw_unlock(&hash_lock); - return (PICL_NODENOTFOUND); -} - -/* - * Lookup a handle in the table - */ -static picl_errno_t -hash_lookup_entry(picl_nodehdl_t hdl, void **nodepp) -{ - int i; - frutree_hashelm_t *el; - - FRUTREE_DEBUG1(HASHTABLE, "hash_lookup begin: %llx", hdl); - (void) rw_rdlock(&hash_lock); - - if (node_hash_table.tbl == NULL) { - (void) rw_unlock(&hash_lock); - return (PICL_NOTINITIALIZED); - } - if (nodepp == NULL) { - (void) rw_unlock(&hash_lock); - return (PICL_INVALIDHANDLE); - } - - i = HASH_INDEX(node_hash_table.hash_size, hdl); - - if (node_hash_table.tbl[i] == NULL) { - (void) rw_unlock(&hash_lock); - return (PICL_NODENOTFOUND); - } - - el = node_hash_table.tbl[i]; - while (el) { - if (el->hdl == hdl) { - *nodepp = el->nodep; - (void) rw_unlock(&hash_lock); - return (PICL_SUCCESS); - } - el = el->nextp; - } - (void) rw_unlock(&hash_lock); - return (PICL_NODENOTFOUND); -} - -/* create and initialize data structure for a loc node */ -static picl_errno_t -make_loc_data(char *full_name, hashdata_t **hashptr) -{ - char *name_copy; - frutree_locnode_t *locp; - hashdata_t *datap = NULL; - - datap = (hashdata_t *)malloc(sizeof (hashdata_t)); - if (datap == NULL) { - return (PICL_NOSPACE); - } - datap->type = LOC_TYPE; - - /* allocate the data */ - locp = (frutree_locnode_t *)malloc(sizeof (frutree_locnode_t)); - if (locp == NULL) { - free(datap); - return (PICL_NOSPACE); - } - - /* make a copy of the name */ - name_copy = strdup(full_name); - if (name_copy == NULL) { - free(locp); - free(datap); - return (PICL_NOSPACE); - } - - /* initialize the data */ - locp->name = name_copy; - locp->locnodeh = 0; - locp->state = LOC_STATE_UNKNOWN; - locp->prev_state = LOC_STATE_UNKNOWN; - locp->cpu_node = B_FALSE; - locp->autoconfig_enabled = B_FALSE; - locp->state_mgr = UNKNOWN; - locp->dr_in_progress = B_FALSE; - (void) pthread_mutex_init(&locp->mutex, NULL); - (void) pthread_cond_init(&locp->cond_cv, NULL); - - datap->data = locp; - *hashptr = datap; - return (PICL_SUCCESS); -} - -/* create and initialize data structure for a fru node */ -static picl_errno_t -make_fru_data(char *full_name, hashdata_t **hashptr) -{ - char *name_copy; - frutree_frunode_t *frup; - hashdata_t *datap = NULL; - - datap = (hashdata_t *)malloc(sizeof (hashdata_t)); - if (datap == NULL) { - return (PICL_NOSPACE); - } - datap->type = FRU_TYPE; - - /* allocate the data */ - frup = (frutree_frunode_t *)malloc(sizeof (frutree_frunode_t)); - if (frup == NULL) { - free(datap); - return (PICL_NOSPACE); - } - - /* make a copy of the name */ - name_copy = strdup(full_name); - if (name_copy == NULL) { - free(frup); - free(datap); - return (PICL_NOSPACE); - } - - /* initialize the data */ - frup->name = name_copy; - frup->frunodeh = 0; - frup->state = FRU_STATE_UNCONFIGURED; - frup->prev_state = FRU_STATE_UNKNOWN; - frup->cond = FRU_COND_UNKNOWN; - frup->prev_cond = FRU_COND_UNKNOWN; - frup->cpu_node = B_FALSE; - frup->autoconfig_enabled = B_FALSE; - frup->dr_in_progress = B_FALSE; - frup->busy = B_FALSE; - frup->state_mgr = UNKNOWN; - frup->fru_path[0] = '\0'; - (void) pthread_mutex_init(&frup->mutex, NULL); - (void) pthread_cond_init(&frup->cond_cv, NULL); - (void) pthread_cond_init(&frup->busy_cond_cv, NULL); - - datap->data = frup; - *hashptr = datap; - return (PICL_SUCCESS); -} - -/* create and initialize data structure for a port node */ -static picl_errno_t -make_port_data(char *full_name, hashdata_t **hashptr) -{ - char *name_copy; - frutree_portnode_t *portp; - hashdata_t *datap = NULL; - - datap = (hashdata_t *)malloc(sizeof (hashdata_t)); - if (datap == NULL) { - return (PICL_NOSPACE); - } - datap->type = PORT_TYPE; - - /* allocate the data */ - portp = (frutree_portnode_t *)malloc(sizeof (frutree_portnode_t)); - if (portp == NULL) { - free(datap); - return (PICL_NOSPACE); - } - /* make a copy of the name */ - name_copy = strdup(full_name); - if (name_copy == NULL) { - free(portp); - free(datap); - return (PICL_NOSPACE); - } - - /* initialize the data */ - portp->name = name_copy; - portp->portnodeh = 0; - portp->state = PORT_STATE_UNKNOWN; - portp->cond = PORT_COND_UNKNOWN; - datap->data = portp; - *hashptr = datap; - return (PICL_SUCCESS); -} - -/* - * utility routine to create table entries - */ -static picl_errno_t -create_table_entry(picl_prophdl_t tblhdl, picl_nodehdl_t refhdl, char *class) -{ - picl_errno_t rc; - ptree_propinfo_t propinfo; - picl_prophdl_t prophdl[2]; - char buf[PICL_CLASSNAMELEN_MAX]; - - /* first column is class */ - if ((rc = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, - PICL_PTYPE_CHARSTRING, PICL_READ, PICL_CLASSNAMELEN_MAX, - PICL_PROP_CLASS, NULLREAD, - NULLWRITE)) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_create_prop(&propinfo, class, - &prophdl[0])) != PICL_SUCCESS) { - return (rc); - } - - /* second column is reference property */ - (void) snprintf(buf, sizeof (buf), "_%s_", class); - if ((rc = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, - PICL_PTYPE_REFERENCE, PICL_READ, - sizeof (picl_nodehdl_t), buf, NULLREAD, - NULLWRITE)) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_create_prop(&propinfo, &refhdl, - &prophdl[1])) != PICL_SUCCESS) { - return (rc); - } - - /* add row to table */ - if ((rc = ptree_add_row_to_table(tblhdl, 2, prophdl)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * Utility routine to create picl property - */ -static picl_errno_t -create_property(int ptype, int pmode, size_t psize, char *pname, - int (*readfn)(ptree_rarg_t *, void *), - int (*writefn)(ptree_warg_t *, const void *), - picl_nodehdl_t nodeh, picl_prophdl_t *prophp, void *vbuf) -{ - picl_errno_t rc; - ptree_propinfo_t propinfo; - picl_prophdl_t proph; - - if (pname == NULL || vbuf == NULL) { - return (PICL_FAILURE); - } - - if (ptype == PICL_PTYPE_TABLE) { - if ((rc = ptree_create_table((picl_prophdl_t *)vbuf)) - != PICL_SUCCESS) { - return (rc); - } - } - - if ((rc = ptree_get_prop_by_name(nodeh, pname, &proph)) == - PICL_SUCCESS) { /* property already exists */ - return (rc); - } - - rc = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, - ptype, pmode, psize, pname, readfn, writefn); - if (rc != PICL_SUCCESS) { - return (rc); - } - - rc = ptree_create_and_add_prop(nodeh, &propinfo, vbuf, prophp); - if (rc != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * create frutree node, chassis node - */ -static picl_errno_t -initialize_frutree() -{ - int rc = PICL_SUCCESS; - hashdata_t *datap = NULL; - frutree_frunode_t *frup = NULL; - uint64_t ap_status_time; - - FRUTREE_DEBUG0(FRUTREE_INIT, "initialize_frutree begin"); - /* Get the root of the PICL tree */ - if ((rc = ptree_get_root(&rooth)) != PICL_SUCCESS) { - return (rc); - } - FRUTREE_DEBUG1(FRUTREE_INIT, "roothdl = %llx", rooth); - - /* create /frutree node */ - if ((rc = ptree_create_and_add_node(rooth, PICL_NODE_FRUTREE, - PICL_CLASS_PICL, &frutreeh)) != PICL_SUCCESS) { - return (rc); - } - FRUTREE_DEBUG1(FRUTREE_INIT, "frutreeh = %llx", frutreeh); - - /* create chassis node */ - if ((rc = ptree_create_node(PICL_NODE_CHASSIS, PICL_CLASS_FRU, - &chassish)) != PICL_SUCCESS) { - return (rc); - } - FRUTREE_DEBUG1(FRUTREE_INIT, "chassish = %llx", chassish); - - /* Allocate fru data */ - if ((rc = make_fru_data(PICL_NODE_CHASSIS, &datap)) != - PICL_SUCCESS) { - (void) ptree_destroy_node(chassish); - return (rc); - } - /* initialise chassis handle and parent handle */ - frup = FRUDATA_PTR(datap); - frup->frunodeh = chassish; - - /* Add the chassis node to the tree */ - if ((rc = ptree_add_node(frutreeh, chassish)) != PICL_SUCCESS) { - free_data(datap->type, datap); - (void) ptree_destroy_node(chassish); - return (rc); - } - - /* create chassis state property */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ, PICL_PROPNAMELEN_MAX, PICL_PROP_STATE, - NULLREAD, NULLWRITE, chassish, (picl_prophdl_t *)NULL, - PICLEVENTARGVAL_UNCONFIGURED)) != PICL_SUCCESS) { - free_data(datap->type, datap); - (void) ptree_delete_node(chassish); - (void) ptree_destroy_node(chassish); - return (rc); - } - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = create_property(PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (ap_status_time), PICL_PROP_STATUS_TIME, - NULLREAD, NULLWRITE, chassish, - NULL, &ap_status_time)) != PICL_SUCCESS) { - free_data(datap->type, datap); - (void) ptree_delete_node(chassish); - (void) ptree_destroy_node(chassish); - return (rc); - } - - /* save chassis info in hashtable */ - if ((rc = hash_add_entry(chassish, - (void *)datap)) != PICL_SUCCESS) { - free_data(datap->type, datap); - (void) ptree_delete_node(chassish); - (void) ptree_destroy_node(chassish); - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * Read the temporary property created by platform specific - * plugin to get the config file name. - */ -static picl_errno_t -get_configuration_file() -{ - picl_errno_t rc; - picl_prophdl_t proph; - char file_name[PICL_PROPNAMELEN_MAX]; - - if ((rc = ptree_get_prop_by_name(chassish, - PICL_PROP_CONF_FILE, &proph)) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_propval(proph, file_name, - sizeof (file_name))) != PICL_SUCCESS) { - return (rc); - } - - (void) snprintf(conf_file, sizeof (conf_file), - PICLD_PLAT_PLUGIN_DIRF"%s", sys_name, file_name); - /* delete the tmp prop created by platform specific plugin */ - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - FRUTREE_DEBUG1(EVENTS, "Using %s conf file", conf_file); - return (PICL_SUCCESS); -} - -/* - * Read the cfgadm data and get the latest information - */ -static picl_errno_t -get_cfgadm_state(cfga_list_data_t *data, char *ap_id) -{ - int nlist; - cfga_err_t ap_list_err; - cfga_list_data_t *list = NULL; - char * const *p = &ap_id; - - if (data == NULL || ap_id == NULL) { - return (PICL_INVALIDARG); - } - - ap_list_err = config_list_ext(1, p, &list, &nlist, NULL, - NULL, NULL, 0); - if (ap_list_err != CFGA_OK) { - free(list); - return (cfg2picl_errmap[ap_list_err][1]); - } - - (void) memcpy(data, list, sizeof (cfga_list_data_t)); - free(list); - return (PICL_SUCCESS); -} - -/* - * syncup with cfgadm data and read latest location state information - */ -static picl_errno_t -update_loc_state(frutree_locnode_t *locp, boolean_t *updated) -{ - int i = 0; - cfga_list_data_t *list = NULL; - picl_errno_t rc, rc1; - char valbuf[PICL_PROPNAMELEN_MAX]; - char slot_type[PICL_PROPNAMELEN_MAX]; - uint64_t ap_status_time; - - *updated = B_FALSE; - if (locp->state_mgr == PLUGIN_PVT) { - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_STATE, (void *)valbuf, - PICL_PROPNAMELEN_MAX)) != PICL_SUCCESS) { - return (rc); - } - - /* if there is a change in state, update the internal value */ - if (strcmp(loc_state[locp->state], valbuf) != 0) { - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(locp->locnodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, locp->name, rc); - } - *updated = B_TRUE; - locp->prev_state = locp->state; - for (i = 0; (loc_state[i] != NULL); i++) { - if (strcmp(loc_state[i], valbuf) == 0) { - locp->state = i; - return (PICL_SUCCESS); - } - } - } - return (PICL_SUCCESS); - } else if (locp->state_mgr == STATIC_LOC) { - return (PICL_SUCCESS); - } - - /* get the info from the libcfgadm interface */ - list = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t)); - if (list == NULL) { - return (PICL_NOSPACE); - } - - if ((rc = get_cfgadm_state(list, locp->name)) != PICL_SUCCESS) { - if ((rc1 = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_SLOT_TYPE, slot_type, - sizeof (slot_type))) != PICL_SUCCESS) { - free(list); - return (rc1); - } - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) != 0 && - strcmp(slot_type, SANIBEL_IDE_SLOT) != 0) { - free(list); - return (rc); - } - /* this is a scsi location */ - if (rc != PICL_NODENOTFOUND) { - free(list); - return (rc); - } - - /* - * for scsi locations, if node is not found, - * consider location state as empty - */ - (void) pthread_mutex_lock(&locp->mutex); - if (locp->state != LOC_STATE_EMPTY) { - *updated = B_TRUE; - locp->prev_state = locp->state; - locp->state = LOC_STATE_EMPTY; - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(locp->locnodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, locp->name, rc); - } - } - (void) pthread_mutex_unlock(&locp->mutex); - free(list); - return (PICL_SUCCESS); - } - - (void) pthread_mutex_lock(&locp->mutex); - switch (list->ap_r_state) { - case CFGA_STAT_CONNECTED: - if (locp->state != LOC_STATE_CONNECTED) { - *updated = B_TRUE; - locp->prev_state = locp->state; - locp->state = LOC_STATE_CONNECTED; - } - break; - case CFGA_STAT_DISCONNECTED: - if (locp->state != LOC_STATE_DISCONNECTED) { - *updated = B_TRUE; - locp->prev_state = locp->state; - locp->state = LOC_STATE_DISCONNECTED; - } - break; - case CFGA_STAT_EMPTY: - if (locp->state != LOC_STATE_EMPTY) { - *updated = B_TRUE; - locp->prev_state = locp->state; - locp->state = LOC_STATE_EMPTY; - } - break; - default: - if (locp->state != LOC_STATE_UNKNOWN) { - *updated = B_TRUE; - locp->prev_state = locp->state; - locp->state = LOC_STATE_UNKNOWN; - } - } - - if (*updated == B_TRUE) { - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(locp->locnodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, locp->name, rc); - } - } - - /* update the autoconfig flag */ - switch (is_autoconfig_enabled(locp->name)) { - case 1: - locp->autoconfig_enabled = B_TRUE; - break; - case 0: - default: - locp->autoconfig_enabled = B_FALSE; - break; - } - (void) pthread_mutex_unlock(&locp->mutex); - - free(list); - return (PICL_SUCCESS); -} - -/* - * volatile callback function to return the state value for a location - */ -static int -get_loc_state(ptree_rarg_t *rarg, void *buf) -{ - picl_errno_t rc; - frutree_dr_arg_t dr_arg; - hashdata_t *hashptr = NULL; - frutree_locnode_t *locp = NULL; - boolean_t state_change = B_FALSE; - - if (buf == NULL) { - return (PICL_INVALIDARG); - } - - if ((rc = hash_lookup_entry(rarg->nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - - locp = LOCDATA_PTR(hashptr); - if (locp == NULL) { - return (PICL_FAILURE); - } - - (void) pthread_mutex_lock(&locp->mutex); - if (locp->dr_in_progress == B_TRUE) { - /* return the cached value */ - (void) strncpy((char *)buf, loc_state[locp->state], - PICL_PROPNAMELEN_MAX); - (void) pthread_mutex_unlock(&locp->mutex); - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&locp->mutex); - - if ((rc = update_loc_state(locp, &state_change)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_LOC_STATE_ERR, locp->name, rc); - /* return the cached value */ - (void) strncpy((char *)buf, loc_state[locp->state], - PICL_PROPNAMELEN_MAX); - return (rc); - } - - /* if there is a state change, handle the event */ - if (state_change) { - (void) pthread_mutex_lock(&locp->mutex); - if (locp->state == LOC_STATE_EMPTY) { /* card removed */ - dr_arg.action = HANDLE_REMOVE; - } else if (locp->prev_state == LOC_STATE_EMPTY) { - dr_arg.action = HANDLE_INSERT; /* card inserted */ - } else { - /* loc state changed */ - dr_arg.action = HANDLE_LOCSTATE_CHANGE; - } - (void) pthread_mutex_unlock(&locp->mutex); - dr_arg.data = locp; - (void) pthread_mutex_lock(&ev_mutex); - if ((rc = add_to_queue(dr_arg)) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, - "dr_ap_state_change", locp->name, rc); - } else { - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - } - } - - (void) strncpy((char *)buf, loc_state[locp->state], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); -} - -/* - * syncup with cfgadm data and read latest fru state information - */ -static picl_errno_t -update_fru_state(frutree_frunode_t *frup, boolean_t *updated) -{ - int i; - picl_errno_t rc; - picl_nodehdl_t loch; - uint64_t ap_status_time; - hashdata_t *hashptr = NULL; - cfga_list_data_t *list = NULL; - frutree_locnode_t *locp = NULL; - char valbuf[PICL_PROPNAMELEN_MAX]; - - *updated = B_FALSE; - if (frup->state_mgr == PLUGIN_PVT) { - if ((rc = ptree_get_propval_by_name(frup->frunodeh, - PICL_PROP_STATE, (void *)valbuf, - PICL_PROPNAMELEN_MAX)) != PICL_SUCCESS) { - return (rc); - } - - /* if there is a change in state, update the internal value */ - if (strcmp(fru_state[frup->state], valbuf) != 0) { - *updated = B_TRUE; - frup->prev_state = frup->state; - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - if (rc == PICL_PROPNOTFOUND) { - (void) create_property( - PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (ap_status_time), - PICL_PROP_STATUS_TIME, - NULLREAD, NULLWRITE, - frup->frunodeh, - NULL, &ap_status_time); - } else { - FRUTREE_DEBUG3(EVENTS, - PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, - frup->name, rc); - } - } - for (i = 0; (fru_state[i] != NULL); i++) { - if (strcmp(fru_state[i], valbuf) == 0) { - frup->state = i; - return (PICL_SUCCESS); - } - } - } - return (PICL_SUCCESS); - } else if (frup->state_mgr == STATIC_LOC) { - frup->state = FRU_STATE_CONFIGURED; - return (PICL_SUCCESS); - } - - if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &loch, sizeof (loch))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = hash_lookup_entry(loch, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - locp = LOCDATA_PTR(hashptr); - if (locp == NULL) { - return (PICL_FAILURE); - } - - list = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t)); - if (list == NULL) { - return (PICL_NOSPACE); - } - - if ((rc = get_cfgadm_state(list, locp->name)) != PICL_SUCCESS) { - free(list); - return (rc); - } - - (void) pthread_mutex_lock(&frup->mutex); - switch (list->ap_o_state) { - case CFGA_STAT_CONFIGURED: - if (frup->state != FRU_STATE_CONFIGURED) { - *updated = B_TRUE; - frup->prev_state = frup->state; - frup->state = FRU_STATE_CONFIGURED; - } - break; - case CFGA_STAT_UNCONFIGURED: - if (frup->state != FRU_STATE_UNCONFIGURED) { - *updated = B_TRUE; - frup->prev_state = frup->state; - frup->state = FRU_STATE_UNCONFIGURED; - } - break; - default: - if (frup->state != FRU_STATE_UNKNOWN) { - *updated = B_TRUE; - frup->prev_state = frup->state; - frup->state = FRU_STATE_UNKNOWN; - } - break; - } - - /* update the fru_type property */ - if (list->ap_type) { - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_FRU_TYPE, list->ap_type, - sizeof (list->ap_type))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_FRU_TYPE, frup->name, rc); - } - } - - if (*updated == B_TRUE) { - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, frup->name, rc); - } - } - (void) pthread_mutex_unlock(&frup->mutex); - - free(list); - return (PICL_SUCCESS); -} - -/* - * syncup with cfgadm data and read latest fru condition information - */ -static picl_errno_t -update_fru_condition(frutree_frunode_t *frup, boolean_t *updated) -{ - int i = 0; - picl_errno_t rc; - picl_nodehdl_t loch; - uint64_t ap_cond_time; - hashdata_t *hashptr = NULL; - cfga_list_data_t *list = NULL; - frutree_locnode_t *locp = NULL; - char valbuf[PICL_PROPNAMELEN_MAX]; - - *updated = B_FALSE; - if (frup->state_mgr == PLUGIN_PVT) { - if ((rc = ptree_get_propval_by_name(frup->frunodeh, - PICL_PROP_CONDITION, (void *)valbuf, - PICL_PROPNAMELEN_MAX)) != PICL_SUCCESS) { - return (rc); - } - - /* - * if there is a change in condition, update the - * internal value - */ - if (strcmp(fru_cond[frup->cond], valbuf) != 0) { - *updated = B_TRUE; - ap_cond_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_CONDITION_TIME, (void *)&ap_cond_time, - sizeof (ap_cond_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_CONDITION_TIME, frup->name, - rc); - } - frup->prev_cond = frup->cond; - - for (i = 0; (fru_cond[i] != NULL); i++) { - if (strcmp(fru_cond[i], valbuf) == 0) { - frup->cond = i; - return (PICL_SUCCESS); - } - } - } - return (PICL_SUCCESS); - } else if (frup->state_mgr == STATIC_LOC) { - frup->cond = FRU_COND_OK; - return (PICL_SUCCESS); - } - - if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &loch, sizeof (loch))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = hash_lookup_entry(loch, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - - locp = LOCDATA_PTR(hashptr); - if (locp == NULL) { - return (PICL_FAILURE); - } - list = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t)); - if (list == NULL) { - return (PICL_NOSPACE); - } - - if ((rc = get_cfgadm_state(list, locp->name)) != PICL_SUCCESS) { - free(list); - return (rc); - } - - switch (list->ap_cond) { - case CFGA_COND_OK: - if (frup->cond != FRU_COND_OK) { - *updated = B_TRUE; - frup->prev_cond = frup->cond; - frup->cond = FRU_COND_OK; - } - break; - case CFGA_COND_FAILING: - if (frup->cond != FRU_COND_FAILING) { - *updated = B_TRUE; - frup->prev_cond = frup->cond; - frup->cond = FRU_COND_FAILING; - } - break; - case CFGA_COND_FAILED: - case CFGA_COND_UNUSABLE: - if (frup->cond != FRU_COND_FAILED) { - *updated = B_TRUE; - frup->prev_cond = frup->cond; - frup->cond = FRU_COND_FAILED; - } - break; - default: - if (frup->cond != FRU_COND_UNKNOWN) { - *updated = B_TRUE; - frup->prev_cond = frup->cond; - frup->cond = FRU_COND_UNKNOWN; - } - } - - if (*updated == B_TRUE) { - ap_cond_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_CONDITION_TIME, (void *)&ap_cond_time, - sizeof (ap_cond_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_CONDITION_TIME, frup->name, rc); - } - } - free(list); - return (PICL_SUCCESS); -} - -/* - * Volatile callback function to read fru state - */ -static int -get_fru_state(ptree_rarg_t *rarg, void *buf) -{ - picl_errno_t rc; - hashdata_t *hashptr = NULL; - frutree_frunode_t *frup = NULL; - boolean_t state_change = B_FALSE; - frutree_dr_arg_t dr_arg; - - if (buf == NULL) { - return (PICL_INVALIDARG); - } - - if ((rc = hash_lookup_entry(rarg->nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - - frup = FRUDATA_PTR(hashptr); - if (frup == NULL) { - return (PICL_FAILURE); - } - - /* return the cached value, if dr is in progress */ - (void) pthread_mutex_lock(&frup->mutex); - if (frup->dr_in_progress) { - (void) pthread_mutex_unlock(&frup->mutex); - (void) strncpy((char *)buf, fru_state[frup->state], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&frup->mutex); - - if ((rc = update_fru_state(frup, &state_change)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_FRU_STATE_ERR, frup->name, rc); - /* return the cached value */ - (void) strncpy((char *)buf, fru_state[frup->state], - PICL_PROPNAMELEN_MAX); - return (rc); - } - - /* if there is a state change, handle the event */ - if (state_change) { - (void) pthread_mutex_lock(&frup->mutex); - /* figure out if this is config/unconfig operation */ - if (frup->state == FRU_STATE_CONFIGURED) { - dr_arg.action = HANDLE_CONFIGURE; - dr_arg.data = frup; - } else if (frup->state == FRU_STATE_UNCONFIGURED) { - dr_arg.action = HANDLE_UNCONFIGURE; - dr_arg.data = frup; - } - (void) pthread_mutex_unlock(&frup->mutex); - - (void) pthread_mutex_lock(&ev_mutex); - if ((rc = add_to_queue(dr_arg)) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, - "dr_ap_state_chage", frup->name, rc); - } else { - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - } - } - - (void) strncpy((char *)buf, fru_state[frup->state], - PICL_PROPNAMELEN_MAX); - - return (PICL_SUCCESS); -} - -/* - * Volatile callback function to read fru condition - */ -static int -get_fru_condition(ptree_rarg_t *rarg, void *buf) -{ - picl_errno_t rc; - frutree_dr_arg_t dr_arg; - hashdata_t *hashptr = NULL; - frutree_frunode_t *frup = NULL; - boolean_t cond_changed = B_FALSE; - - if (buf == NULL) { - return (PICL_INVALIDARG); - } - - if ((rc = hash_lookup_entry(rarg->nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - - frup = FRUDATA_PTR(hashptr); - if (frup == NULL) { - return (PICL_FAILURE); - } - - /* return the cached value, if dr is in progress */ - (void) pthread_mutex_lock(&frup->mutex); - if (frup->dr_in_progress) { - (void) pthread_mutex_unlock(&frup->mutex); - (void) strncpy((char *)buf, fru_cond[frup->cond], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); - - } - (void) pthread_mutex_unlock(&frup->mutex); - - if ((rc = update_fru_condition(frup, &cond_changed)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_FRU_COND_ERR, frup->name, rc); - /* return the cached value */ - (void) strncpy((char *)buf, fru_cond[frup->cond], - PICL_PROPNAMELEN_MAX); - return (rc); - } - if (cond_changed) { - dr_arg.action = POST_COND_EVENT; - dr_arg.data = frup; - (void) pthread_mutex_lock(&ev_mutex); - if ((rc = add_to_queue(dr_arg)) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, - "condition event", frup->name, rc); - } else { - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - } - } - - /* if there is a condition change, post picl event */ - (void) strncpy((char *)buf, fru_cond[frup->cond], - PICL_PROPNAMELEN_MAX); - - return (PICL_SUCCESS); -} - -static void -free_cache(frutree_cache_t *cachep) -{ - frutree_cache_t *tmp = NULL; - if (cachep == NULL) - return; - - while (cachep != NULL) { - tmp = cachep; - cachep = cachep->next; - free(tmp); - } -} - -/* - * traverse the /platform tree in PICL tree to create logical devices table - */ -static picl_errno_t -probe_platform_tree(frutree_frunode_t *frup, frutree_device_args_t **devp) -{ - picl_errno_t rc; - picl_nodehdl_t refhdl = 0; - char class[PICL_CLASSNAMELEN_MAX]; - frutree_device_args_t *device = NULL; - picl_prophdl_t tblprophdl; - picl_prophdl_t dev_tblhdl, env_tblhdl = 0; - - if (devp == NULL) { - return (PICL_FAILURE); - } - device = *(frutree_device_args_t **)devp; - if (device == NULL) { - return (PICL_FAILURE); - } - - /* traverse thru platform tree and add entries to Devices table */ - if ((refhdl = get_reference_handle(frup->frunodeh)) == 0) { - return (PICL_NODENOTFOUND); - } - - /* create Devices table property */ - if ((rc = create_property(PICL_PTYPE_TABLE, PICL_READ, - sizeof (picl_prophdl_t), PICL_PROP_DEVICES, NULLREAD, - NULLWRITE, frup->frunodeh, &tblprophdl, &dev_tblhdl)) != - PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_propval_by_name(refhdl, PICL_PROP_CLASSNAME, - class, sizeof (class))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = create_table_entry(dev_tblhdl, refhdl, class)) != - PICL_SUCCESS) { - return (rc); - } - - /* create Environment devices table property */ - if ((rc = create_property(PICL_PTYPE_TABLE, PICL_READ, - sizeof (picl_prophdl_t), PICL_PROP_ENV, NULLREAD, - NULLWRITE, frup->frunodeh, &tblprophdl, &env_tblhdl)) != - PICL_SUCCESS) { - return (rc); - } - - device->nodeh = refhdl; - device->device_tblhdl = dev_tblhdl; - device->env_tblhdl = env_tblhdl; - device->first = NULL; - device->last = NULL; - device->create_cache = B_FALSE; - - /* probe using platform tree info */ - if ((rc = do_action(refhdl, CREATE_DEVICES_ENTRIES, - device)) != PICL_SUCCESS) { - free_cache(device->first); - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * create temp conf file to pass it to picld util lib to create - * nodes under the fru - */ -static picl_errno_t -create_fru_children(frutree_frunode_t *frup, frutree_device_args_t device) -{ - int fd; - picl_errno_t rc; - char conffile[MAXPATHLEN]; - char dir[MAXPATHLEN]; - struct stat file_stat; - char version[BUF_SIZE]; - frutree_cache_t *cachep = NULL; - - cachep = device.first; - if (cachep == NULL) { - return (PICL_SUCCESS); - } - - /* create the configuration file for the fru */ - (void) snprintf(dir, MAXPATHLEN, "%s%s", TEMP_DIR, frup->name); - bzero(&file_stat, sizeof (file_stat)); - if (stat(conffile, &file_stat) == -1) { - if (mkdir(conffile, 0755) == -1) { - return (PICL_FAILURE); - } - } - - (void) snprintf(conffile, MAXPATHLEN, "%s/%s", dir, PROBE_FILE); - if ((fd = open(conffile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { - (void) rmdir(dir); - return (PICL_FAILURE); - } - - (void) snprintf(version, sizeof (version), "VERSION %d.0", - PTREE_PROPINFO_VERSION); - if (write(fd, version, strlen(version)) != strlen(version)) { - (void) remove(conffile); - (void) rmdir(dir); - (void) close(fd); - return (PICL_FAILURE); - } - - /* traverse thru each cache entry and append to conf file */ - while (cachep != NULL) { - if (write(fd, cachep->buf, strlen(cachep->buf)) - != strlen(cachep->buf)) { - (void) close(fd); - (void) remove(conffile); - (void) rmdir(dir); - return (PICL_FAILURE); - } - cachep = cachep->next; - } - (void) close(fd); - - /* create child nodes for fru using the conffile created */ - if ((rc = picld_pluginutil_parse_config_file(frup->frunodeh, - conffile)) != PICL_SUCCESS) { - (void) remove(conffile); - (void) rmdir(dir); - return (rc); - } - (void) remove(conffile); - (void) rmdir(dir); - - if ((rc = fru_init(frup)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * probes libdevinfo and create the port nodes under a fru - * probes for any scsi devices under a fru - */ -static picl_errno_t -probe_fru(frutree_frunode_t *frup, boolean_t load_drivers) -{ - picl_errno_t rc; - picl_nodehdl_t child, loch; - char slot_type[PICL_PROPNAMELEN_MAX]; - char devfs_path[PICL_PROPNAMELEN_MAX]; - char probe_path[PICL_PROPNAMELEN_MAX]; - frutree_device_args_t *device = NULL; - - if (frup == NULL) { - return (PICL_FAILURE); - } - FRUTREE_DEBUG1(EVENTS, "probing :%s", frup->name); - - if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &loch, sizeof (loch))) != PICL_SUCCESS) { - return (rc); - } - - bzero(devfs_path, PICL_PROPNAMELEN_MAX); - bzero(probe_path, PICL_PROPNAMELEN_MAX); - if ((rc = ptree_get_propval_by_name(loch, PICL_PROP_DEVFS_PATH, - devfs_path, sizeof (devfs_path))) == PICL_SUCCESS) { - device = (frutree_device_args_t *)malloc( - sizeof (frutree_device_args_t)); - if (device == NULL) { - return (PICL_NOSPACE); - } - device->first = NULL; - device->last = NULL; - (void) probe_platform_tree(frup, &device); - free_cache(device->first); - free(device); - } - - /* - * if parent has NULL probe-path, skip probing this fru - * probe only child locations (if present). - * if probe-path is not present use devfs-path as path for - * probing the fru. - */ - rc = ptree_get_propval_by_name(loch, PICL_PROP_PROBE_PATH, - probe_path, sizeof (probe_path)); - if (rc != PICL_SUCCESS) { - if (!devfs_path[0]) { /* devfspath is also not present */ - return (PICL_SUCCESS); /* nothing to probe */ - } else { - /* use devfs-path as path for probing */ - if ((rc = get_fru_path(devfs_path, frup)) != - PICL_SUCCESS) { - return (rc); - } - } - } else { - /* NULL path, skip probing this fru */ - if (strlen(probe_path) == 0) { - rc = fru_init(frup); /* probe its children */ - return (rc); - } else { - /* valid probe-path */ - if ((rc = get_fru_path(probe_path, frup)) != - PICL_SUCCESS) { - return (rc); - } - } - } - - /* children present already, no need to probe libdevinfo */ - rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_CHILD, - &child, sizeof (picl_nodehdl_t)); - if (rc == PICL_SUCCESS) { /* child present */ - if ((rc = fru_init(frup)) != PICL_SUCCESS) { - return (rc); - } - /* now create the scsi nodes for this fru */ - if ((rc = probe_for_scsi_frus(frup)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); - } - - if (ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &loch, sizeof (loch)) != PICL_SUCCESS) { - return (rc); - } - if ((rc = ptree_get_propval_by_name(loch, PICL_PROP_SLOT_TYPE, - slot_type, sizeof (slot_type))) != PICL_SUCCESS) { - return (rc); - } - /* no need to probe further for scsi frus */ - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - return (PICL_SUCCESS); - } - - device = (frutree_device_args_t *)malloc( - sizeof (frutree_device_args_t)); - if (device == NULL) { - return (PICL_NOSPACE); - } - device->first = NULL; - device->last = NULL; - - if ((rc = probe_libdevinfo(frup, &device, load_drivers)) != - PICL_SUCCESS) { - free_cache(device->first); - free(device); - return (rc); - } - - if (device->first != NULL) { - if ((rc = create_fru_children(frup, *device)) != PICL_SUCCESS) { - free_cache(device->first); - free(device); - return (rc); - } - } - free_cache(device->first); - free(device); - - /* now create the scsi nodes for this fru */ - if ((rc = probe_for_scsi_frus(frup)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* - * callback function for ptree_walk_tree_by_class, - * used to update hashtable during DR_HINT_REMOVE event - */ -/*ARGSUSED*/ -static int -frutree_update_hash(picl_nodehdl_t nodeh, void *c_args) -{ - picl_errno_t rc = 0; - if ((rc = hash_remove_entry(nodeh)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_WALK_CONTINUE); -} - -/* - * routine to handle DR_HINT_REMOVE - */ -static picl_errno_t -handle_fru_remove(frutree_frunode_t *frup) -{ - picl_errno_t rc = PICL_SUCCESS; - - if (frup == NULL) { - return (PICL_FAILURE); - } - - if ((rc = ptree_walk_tree_by_class(frup->frunodeh, - NULL, NULL, frutree_update_hash)) != PICL_SUCCESS) { - return (rc); - } - (void) ptree_delete_node(frup->frunodeh); - (void) ptree_destroy_node(frup->frunodeh); - if ((rc = hash_remove_entry(frup->frunodeh)) != - PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/* remove State and Condition props for all the nodes under fru */ -/*ARGSUSED*/ -static int -frutree_handle_unconfigure(picl_nodehdl_t nodeh, void *c_args) -{ - picl_errno_t rc = 0; - picl_prophdl_t proph; - char class[PICL_PROPNAMELEN_MAX]; - - if (ptree_get_prop_by_name(nodeh, PICL_PROP_STATE, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - if (ptree_get_prop_by_name(nodeh, PICL_PROP_STATUS_TIME, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, - class, sizeof (class))) != PICL_SUCCESS) { - return (rc); - } - - if (strcmp(class, PICL_CLASS_PORT) == 0) { - if (ptree_get_prop_by_name(nodeh, PICL_PROP_CONDITION, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - if (ptree_get_prop_by_name(nodeh, PICL_PROP_CONDITION_TIME, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - /* delete devices table */ - if (ptree_get_prop_by_name(nodeh, PICL_PROP_DEVICES, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - } - return (PICL_WALK_CONTINUE); -} - -/* - * traverse thru each node fru node and do cleanup - */ -static picl_errno_t -handle_fru_unconfigure(frutree_frunode_t *frup) -{ - picl_errno_t rc = 0, retval = 0; - picl_prophdl_t proph; - picl_nodehdl_t childh, peerh, nodeh; - hashdata_t *hashptr = NULL; - frutree_frunode_t *child_frup = NULL; - char class[PICL_PROPNAMELEN_MAX]; - - if (frup == NULL) { - return (PICL_FAILURE); - } - - /* delete devices table */ - if (ptree_get_prop_by_name(frup->frunodeh, PICL_PROP_DEVICES, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - - /* delete Environment devices table */ - if (ptree_get_prop_by_name(frup->frunodeh, PICL_PROP_ENV, - &proph) == PICL_SUCCESS) { - (void) ptree_delete_prop(proph); - (void) ptree_destroy_prop(proph); - } - - if ((rc = ptree_walk_tree_by_class(frup->frunodeh, - NULL, NULL, frutree_handle_unconfigure)) != PICL_SUCCESS) { - return (rc); - } - - /* remove all the fru nodes under the child locations */ - retval = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_CHILD, - &peerh, sizeof (peerh)); - while (retval == PICL_SUCCESS) { - nodeh = peerh; - retval = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, - &peerh, sizeof (peerh)); - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, - class, sizeof (class))) != PICL_SUCCESS) { - return (rc); - } - - if (strcmp(class, PICL_CLASS_PORT) == 0) { - continue; - } - - /* if the child location has fru, delete the fru */ - if (ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) != PICL_SUCCESS) { - continue; - } - - /* child is present under the location */ - if ((rc = hash_lookup_entry(childh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - child_frup = FRUDATA_PTR(hashptr); - (void) handle_fru_remove(child_frup); - } - return (PICL_SUCCESS); -} - -/* - * create the properties under the fru - */ -static picl_errno_t -create_fru_props(frutree_frunode_t *frup) -{ - picl_errno_t rc; - uint64_t ap_status_time = 0; - boolean_t state_change; - - /* create state props */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_STATE, get_fru_state, NULLWRITE, - frup->frunodeh, NULL, fru_state[frup->state])) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_CREATE_PROP_FAILED, - PICL_PROP_STATE, frup->name, rc); - } - - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = create_property(PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (ap_status_time), PICL_PROP_STATUS_TIME, - NULLREAD, NULLWRITE, frup->frunodeh, - NULL, &ap_status_time)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_CREATE_PROP_FAILED, - PICL_PROP_STATUS_TIME, frup->name, rc); - } - - if ((rc = update_fru_state(frup, &state_change)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_FRU_STATE_ERR, frup->name, rc); - return (rc); - } - - /* create condition props */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_CONDITION, get_fru_condition, NULLWRITE, - frup->frunodeh, NULL, fru_cond[frup->cond])) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_CREATE_PROP_FAILED, - PICL_PROP_CONDITION, frup->name, rc); - } - if ((rc = create_property(PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (ap_status_time), PICL_PROP_CONDITION_TIME, - NULLREAD, NULLWRITE, frup->frunodeh, NULL, - &ap_status_time)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_CREATE_PROP_FAILED, - PICL_PROP_CONDITION_TIME, frup->name, rc); - } - - if ((rc = update_fru_condition(frup, &state_change)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_FRU_COND_ERR, frup->name, rc); - return (rc); - } - - /* create admin lock prop */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_WRITE, PICL_PROPNAMELEN_MAX, - PICL_PROP_ADMIN_LOCK, NULLREAD, NULLWRITE, - frup->frunodeh, NULL, PICL_ADMINLOCK_DISABLED)) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_CREATE_PROP_FAILED, - PICL_PROP_ADMIN_LOCK, frup->name, rc); - } - return (rc); -} - -/* - * calls libcfgadm API to do a connect on a location - */ -static picl_errno_t -connect_fru(frutree_locnode_t *locp) -{ - picl_errno_t rc; - cfga_err_t ap_list_err; - cfga_flags_t flags = 0; - boolean_t state_change; - uint64_t ap_status_time; - hrtime_t start; - hrtime_t end; - - if (locp == NULL) { - return (PICL_FAILURE); - } - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_CONNECTING, loc_state[locp->state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - (void) pthread_mutex_lock(&locp->mutex); - locp->dr_in_progress = B_TRUE; - (void) pthread_mutex_unlock(&locp->mutex); - - if (frutree_debug & PERF_DATA) { - start = gethrtime(); - } - ap_list_err = config_change_state(CFGA_CMD_CONNECT, 1, &(locp->name), - NULL, NULL, NULL, NULL, flags); - - if (frutree_debug & PERF_DATA) { - end = gethrtime(); - FRUTREE_DEBUG2(PERF_DATA, "time for connect on %s: %lld nsec", - locp->name, (end - start)); - } - if (ap_list_err != CFGA_OK) { - (void) pthread_mutex_lock(&locp->mutex); - locp->dr_in_progress = B_FALSE; - (void) pthread_mutex_unlock(&locp->mutex); - - /* release mutex before updating state */ - (void) update_loc_state(locp, &state_change); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], PICLEVENTARGVAL_CONNECTING, - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - if (locp->state == LOC_STATE_CONNECTED) { - /* wakeup threads sleeping on this condition */ - (void) pthread_mutex_lock(&locp->mutex); - (void) pthread_cond_broadcast(&locp->cond_cv); - (void) pthread_mutex_unlock(&locp->mutex); - return (PICL_SUCCESS); - } - return (cfg2picl_errmap[ap_list_err][1]); - } - (void) pthread_mutex_lock(&locp->mutex); - - locp->dr_in_progress = B_FALSE; - locp->prev_state = LOC_STATE_DISCONNECTED; - locp->state = LOC_STATE_CONNECTED; - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(locp->locnodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, locp->name, rc); - } - - /* wakeup threads sleeping on this condition */ - (void) pthread_cond_broadcast(&locp->cond_cv); - (void) pthread_mutex_unlock(&locp->mutex); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_CONNECTED, PICLEVENTARGVAL_CONNECTING, - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); -} - -/* - * calls libcfgadm API to do a disconnect on a location - */ -static picl_errno_t -disconnect_fru(frutree_locnode_t *locp) -{ - picl_errno_t rc; - picl_nodehdl_t childh; - hashdata_t *hashptr = NULL; - timestruc_t to; - struct timeval tp; - hrtime_t start, end; - cfga_err_t ap_list_err; - cfga_flags_t flags = 0; - boolean_t state_change; - uint64_t ap_status_time; - frutree_frunode_t *frup = NULL; - - if (locp == NULL) { - return (PICL_FAILURE); - } - - (void) pthread_mutex_lock(&locp->mutex); - if (locp->state == LOC_STATE_DISCONNECTED) { - (void) pthread_mutex_unlock(&locp->mutex); - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&locp->mutex); - - /* get the child fru information */ - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - if (hash_lookup_entry(childh, (void **)&hashptr) == - PICL_SUCCESS) { - frup = FRUDATA_PTR(hashptr); - } - } - - if (frup == NULL) { - return (PICL_SUCCESS); - } - - (void) pthread_mutex_lock(&frup->mutex); - - (void) gettimeofday(&tp, NULL); - to.tv_sec = tp.tv_sec + frutree_drwait_time; - to.tv_nsec = tp.tv_usec * 1000; - - if (frup->state != FRU_STATE_UNCONFIGURED) { - (void) pthread_cond_timedwait(&frup->cond_cv, - &frup->mutex, &to); - } - - if (frup->state != FRU_STATE_UNCONFIGURED) { - FRUTREE_DEBUG1(LOG_ERR, "SUNW_frutree:Disconnect operation on" - " %s failed", locp->name); - (void) pthread_mutex_unlock(&frup->mutex); - return (PICL_FAILURE); - } - (void) pthread_mutex_unlock(&frup->mutex); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_DISCONNECTING, loc_state[locp->state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - (void) pthread_mutex_lock(&locp->mutex); - locp->dr_in_progress = B_TRUE; - (void) pthread_mutex_unlock(&locp->mutex); - - if (frutree_debug & PERF_DATA) { - start = gethrtime(); - } - - ap_list_err = config_change_state(CFGA_CMD_DISCONNECT, 1, &(locp->name), - NULL, NULL, NULL, NULL, flags); - if (frutree_debug & PERF_DATA) { - end = gethrtime(); - FRUTREE_DEBUG2(PERF_DATA, "time for disconnect on %s: %lld ns", - locp->name, (end - start)); - } - if (ap_list_err != CFGA_OK) { - (void) pthread_mutex_lock(&locp->mutex); - locp->dr_in_progress = B_FALSE; - (void) pthread_mutex_unlock(&locp->mutex); - - /* release mutex before updating state */ - (void) update_loc_state(locp, &state_change); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], PICLEVENTARGVAL_DISCONNECTING, - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - (void) pthread_mutex_lock(&locp->mutex); - if (locp->state == LOC_STATE_DISCONNECTED) { - (void) pthread_mutex_unlock(&locp->mutex); - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&locp->mutex); - return (cfg2picl_errmap[ap_list_err][1]); - } - (void) pthread_mutex_lock(&locp->mutex); - locp->dr_in_progress = B_FALSE; - locp->prev_state = LOC_STATE_CONNECTED; - locp->state = LOC_STATE_DISCONNECTED; - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(locp->locnodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, locp->name, rc); - } - (void) pthread_mutex_unlock(&locp->mutex); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_DISCONNECTED, PICLEVENTARGVAL_DISCONNECTING, - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); -} - -/* - * Handle DR_INCOMING_RES event - */ -static void -handle_fru_configure(frutree_frunode_t *frup) -{ - picl_errno_t rc; - boolean_t cond_changed; - - if (frup == NULL) - return; - - if ((rc = probe_fru(frup, B_FALSE)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, PROBE_FRU_ERR, frup->name, rc); - } - - /* update the fru condition */ - (void) update_fru_condition(frup, &cond_changed); - if (cond_changed) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, rc); - } - } - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], fru_state[frup->prev_state], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } -} - -/* - * call libcfgadm API to configure a fru - * (Handle DR_INCOMING_RES event) - */ -static picl_errno_t -configure_fru(frutree_frunode_t *frup, cfga_flags_t flags) -{ - picl_errno_t rc; - picl_nodehdl_t parenth; - timestruc_t to; - struct timeval tp; - hrtime_t start, end; - cfga_err_t ap_list_err; - uint64_t ap_status_time; - hashdata_t *hashptr = NULL; - frutree_locnode_t *locp = NULL; - boolean_t state_change, cond_changed; - - if (frup == NULL) { - return (PICL_FAILURE); - } - - (void) pthread_mutex_lock(&frup->mutex); - if (frup->state == FRU_STATE_CONFIGURED) { - (void) pthread_mutex_unlock(&frup->mutex); - ap_list_err = config_change_state(CFGA_CMD_CONFIGURE, 1, - &(frup->name), NULL, NULL, NULL, NULL, flags); - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&frup->mutex); - - if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &parenth, sizeof (parenth))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = hash_lookup_entry(parenth, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - locp = LOCDATA_PTR(hashptr); - if (locp == NULL) { - return (PICL_FAILURE); - } - - (void) pthread_mutex_lock(&locp->mutex); - - (void) gettimeofday(&tp, NULL); - to.tv_sec = tp.tv_sec + frutree_drwait_time; - to.tv_nsec = tp.tv_usec * 1000; - - /* wait for sometime for location to get connected */ - if (locp->state != LOC_STATE_CONNECTED) { - (void) pthread_cond_timedwait(&locp->cond_cv, - &locp->mutex, &to); - } - - if (locp->state != LOC_STATE_CONNECTED) { /* give up */ - FRUTREE_DEBUG1(EVENTS, "SUNW_frutree:Configure operation on" - " %s failed as loc is not connected", locp->name); - (void) pthread_mutex_unlock(&locp->mutex); - return (PICL_FAILURE); - } - (void) pthread_mutex_unlock(&locp->mutex); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_CONFIGURING, fru_state[frup->state], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - - (void) pthread_mutex_lock(&frup->mutex); - frup->dr_in_progress = B_TRUE; - (void) pthread_mutex_unlock(&frup->mutex); - - if (frutree_debug & PERF_DATA) { - start = gethrtime(); - } - ap_list_err = config_change_state(CFGA_CMD_CONFIGURE, 1, - &(frup->name), NULL, NULL, NULL, NULL, flags); - - if (frutree_debug & PERF_DATA) { - end = gethrtime(); - FRUTREE_DEBUG2(PERF_DATA, "time for configure on %s: %lld nsec", - frup->name, (end - start)); - } - - if (ap_list_err != CFGA_OK) { - (void) pthread_mutex_lock(&frup->mutex); - frup->dr_in_progress = B_FALSE; - (void) pthread_mutex_unlock(&frup->mutex); - /* release mutex before updating state */ - (void) update_fru_state(frup, &state_change); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], PICLEVENTARGVAL_CONFIGURING, - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - /* update the fru condition */ - (void) update_fru_condition(frup, &state_change); - if (state_change) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, - rc); - } - } - return (cfg2picl_errmap[ap_list_err][1]); - } - (void) pthread_mutex_lock(&frup->mutex); - frup->dr_in_progress = B_FALSE; - frup->prev_state = FRU_STATE_UNCONFIGURED; - frup->state = FRU_STATE_CONFIGURED; - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, frup->name, rc); - } - (void) pthread_mutex_unlock(&frup->mutex); - - if ((rc = probe_fru(frup, B_FALSE)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(FRUTREE_INIT, PROBE_FRU_ERR, frup->name, rc); - } - /* update the fru condition */ - (void) update_fru_condition(frup, &cond_changed); - if (cond_changed) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, rc); - } - } - - /* send the state change event */ - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], PICLEVENTARGVAL_CONFIGURING, - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); -} - -/* - * Handle DR_OUTGOING_RES event - * (call libcfgadm API to unconfigure a fru) - */ -static picl_errno_t -unconfigure_fru(frutree_frunode_t *frup, cfga_flags_t flags) -{ - picl_errno_t rc; - cfga_err_t ap_list_err; - boolean_t state_change; - uint64_t ap_status_time; - hrtime_t start; - hrtime_t end; - - if (frup == NULL) { - return (PICL_FAILURE); - } - - (void) pthread_mutex_lock(&frup->mutex); - if (frup->state == FRU_STATE_UNCONFIGURED) { - (void) pthread_mutex_unlock(&frup->mutex); - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&frup->mutex); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_UNCONFIGURING, fru_state[frup->state], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - - (void) pthread_mutex_lock(&frup->mutex); - while (frup->busy == B_TRUE) { - (void) pthread_cond_wait(&frup->busy_cond_cv, - &frup->mutex); - } - - frup->dr_in_progress = B_TRUE; - (void) pthread_mutex_unlock(&frup->mutex); - - if (frutree_debug & PERF_DATA) { - start = gethrtime(); - } - ap_list_err = config_change_state(CFGA_CMD_UNCONFIGURE, 1, - &(frup->name), NULL, NULL, NULL, NULL, flags); - if (frutree_debug & PERF_DATA) { - end = gethrtime(); - FRUTREE_DEBUG2(PERF_DATA, "time for unconfigure on %s: %lld ns", - frup->name, (end - start)); - } - if (ap_list_err != CFGA_OK) { - /* - * call configure again (workaround for - * ENUM# to get generated for next attempt) - */ - config_change_state(CFGA_CMD_CONFIGURE, 1, - &(frup->name), NULL, NULL, NULL, NULL, flags); - - (void) pthread_mutex_lock(&frup->mutex); - frup->dr_in_progress = B_FALSE; - (void) pthread_mutex_unlock(&frup->mutex); - - /* release mutex before updating state */ - (void) update_fru_condition(frup, &state_change); - if (state_change) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, - rc); - } - } - (void) update_fru_state(frup, &state_change); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], PICLEVENTARGVAL_UNCONFIGURING, - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - return (cfg2picl_errmap[ap_list_err][1]); - } - - (void) pthread_mutex_lock(&frup->mutex); - - frup->dr_in_progress = B_FALSE; - frup->prev_state = FRU_STATE_CONFIGURED; - frup->state = FRU_STATE_UNCONFIGURED; - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(frup->frunodeh, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, frup->name, rc); - } - /* wakeup threads sleeping on this condition */ - (void) pthread_cond_broadcast(&frup->cond_cv); - (void) pthread_mutex_unlock(&frup->mutex); - - /* update the fru condition */ - if ((rc = update_fru_condition(frup, &state_change)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_FRU_STATE_ERR, - frup->name, rc); - } - if (state_change) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, rc); - } - } - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_UNCONFIGURED, PICLEVENTARGVAL_UNCONFIGURING, - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); -} - -/* creates fru nodes with basic properties and sends out intializing events */ -static int -create_fru_node(frutree_locnode_t *locp, frutree_frunode_t **child_frupp) -{ - picl_errno_t rc; - hashdata_t *fru_data = NULL; - frutree_frunode_t *frup = NULL; - picl_nodehdl_t fruh, child; - char slot_type[PICL_PROPNAMELEN_MAX]; - char fru_name[PICL_PROPNAMELEN_MAX]; - char apid_type[PICL_PROPNAMELEN_MAX]; - boolean_t fru_present = B_FALSE; - boolean_t state_changed = B_FALSE; - - if (locp->state == LOC_STATE_EMPTY) { - return (PICL_SUCCESS); - } - - /* check if fru is present or not */ - rc = ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_CHILD, - &child, sizeof (picl_nodehdl_t)); - if (rc == PICL_SUCCESS) { - fru_present = B_TRUE; - fruh = child; - (void) ptree_get_propval_by_name(child, PICL_PROP_NAME, - fru_name, sizeof (fru_name)); - } - - /* create fru node */ - if (fru_present == B_FALSE) { - (void) strncpy(fru_name, locp->name, sizeof (fru_name)); - if ((rc = ptree_create_node(fru_name, PICL_CLASS_FRU, - &fruh)) != PICL_SUCCESS) { - return (rc); - } - } - - /* initialize internal data structures */ - if ((rc = make_fru_data(fru_name, &fru_data)) != PICL_SUCCESS) { - return (rc); - } - frup = FRUDATA_PTR(fru_data); - - frup->frunodeh = fruh; - frup->cpu_node = locp->cpu_node; - frup->state_mgr = locp->state_mgr; - *child_frupp = frup; - - if ((rc = hash_add_entry(fruh, (void *)(fru_data))) != PICL_SUCCESS) { - (void) ptree_destroy_node(fruh); - free_data(FRU_TYPE, (fru_data)); - return (rc); - } - - if (locp->state_mgr == STATIC_LOC) { - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_SLOT_TYPE, slot_type, - sizeof (slot_type))) == PICL_SUCCESS) { - (void) strncpy(apid_type, slot_type, - sizeof (apid_type)); - } - } - - /* create fru type property */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_FRU_TYPE, NULLREAD, - NULLWRITE, fruh, NULL, apid_type)) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_FRU_TYPE, frup->name, rc); - } - - if (fru_present == B_FALSE) { - if ((rc = ptree_add_node(locp->locnodeh, fruh)) != - PICL_SUCCESS) { - (void) ptree_destroy_node(fruh); - (void) hash_remove_entry(fruh); - return (rc); - } - } - - if (locp->state_mgr == PLUGIN_PVT) { - (void) update_fru_state(frup, &state_changed); - return (PICL_SUCCESS); - } - - if ((rc = create_fru_props(frup)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -static picl_errno_t -add_node2cache(picl_nodehdl_t nodeh, char *class, frutree_cache_t **cacheptr) -{ - int instance; - picl_errno_t rc; - char driver[PICL_PROPNAMELEN_MAX]; - char bus_addr[PICL_PROPNAMELEN_MAX]; - char devfs_path[PICL_PROPNAMELEN_MAX]; - char node_name[PICL_PROPNAMELEN_MAX]; - char port_type[PICL_PROPNAMELEN_MAX]; - char label[PICL_PROPNAMELEN_MAX]; - frutree_cache_t *cachep = NULL; - - if (strcmp(class, SANIBEL_NETWORK_PORT) == 0) { - (void) strncpy(label, SANIBEL_NETWORK_LABEL, sizeof (label)); - (void) strncpy(node_name, PICL_CLASS_PORT, sizeof (node_name)); - (void) strncpy(port_type, SANIBEL_NETWORK_PORT, - sizeof (port_type)); - - } else if (strcmp(class, SANIBEL_SERIAL_PORT) == 0) { - (void) strncpy(label, SANIBEL_SERIAL_PORT, sizeof (label)); - (void) strncpy(node_name, PICL_CLASS_PORT, sizeof (node_name)); - (void) strncpy(port_type, SANIBEL_SERIAL_PORT, - sizeof (port_type)); - - } else if (strcmp(class, SANIBEL_PARALLEL_PORT) == 0) { - (void) strncpy(label, SANIBEL_PARALLEL_PORT, sizeof (label)); - (void) strncpy(node_name, PICL_CLASS_PORT, sizeof (node_name)); - (void) strncpy(port_type, SANIBEL_PARALLEL_PORT, - sizeof (port_type)); - - } else { - return (PICL_FAILURE); - } - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_INSTANCE, - &instance, sizeof (instance))) != PICL_SUCCESS) { - return (rc); - } - - /* load the driver */ - if (instance < 0) { - attach_driver(driver); - } - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_DEVFS_PATH, - devfs_path, sizeof (devfs_path))) != PICL_SUCCESS) { - return (rc); - } - - /* get either bus address or unit address */ - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_BUS_ADDR, bus_addr, - sizeof (bus_addr))) != PICL_SUCCESS) { - if ((rc = ptree_get_propval_by_name(nodeh, - PICL_PROP_UNIT_ADDRESS, bus_addr, - sizeof (bus_addr))) != PICL_SUCCESS) { - return (rc); - } - } - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_DRIVER_NAME, - driver, sizeof (driver))) != PICL_SUCCESS) { - return (rc); - } - - cachep = (frutree_cache_t *)malloc(sizeof (frutree_cache_t)); - if (NULL == cachep) { - return (PICL_NOSPACE); - } - cachep->buf[0] = '\0'; - - /* update the cache buffer in PICL configuration format */ - (void) snprintf(cachep->buf, sizeof (cachep->buf), - "\n%s %s%d %s\n" - "\t%s %s %s %s 0 \"%s %d\"\n" - "\t%s %s %s %s 0 \"%s\"\n" - "\t%s %s %s %s 1 %d\n" - "\t%s %s %s %s 0 \"%s\"\n" - "\t%s %s %s %s 0 \"%s\"\n" - "%s\n", - "NODE", driver, instance, node_name, - "PROP", PICL_PROP_LABEL, "string", "r", label, instance, - "PROP", PICL_PROP_BUS_ADDR, "string", "r", bus_addr, - "PROP", PICL_PROP_GEO_ADDR, "uint", "r", instance, - "PROP", PICL_PROP_PORT_TYPE, "string", "r", port_type, - "PROP", PICL_PROP_DEVFS_PATH, "string", "r", devfs_path, - "ENDNODE"); - *cacheptr = cachep; - return (PICL_SUCCESS); -} - -/* ARGSUSED */ -static int -create_device_entries(picl_nodehdl_t nodeh, void *c_args) -{ - char class[PICL_CLASSNAMELEN_MAX]; - char name[PICL_PROPNAMELEN_MAX]; - frutree_device_args_t *device = NULL; - frutree_cache_t *cachep = NULL; - - if (c_args == NULL) { /* need not create cache */ - return (PICL_INVALIDARG); - } - device = (frutree_device_args_t *)c_args; - - if (ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, - class, sizeof (class)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - /* add reference handle to Devices table */ - (void) create_table_entry(device->device_tblhdl, nodeh, class); - - /* add to Environment Devices table */ - if (strcmp(class, PICL_CLASS_TEMPERATURE_SENSOR) == 0) { - if (device->env_tblhdl) { - (void) create_table_entry(device->env_tblhdl, nodeh, - class); - } - } - - if (device->create_cache != B_TRUE) { /* dont create cache */ - return (PICL_WALK_CONTINUE); - } - - /* compare the classname and create the cache entry for the child */ - if (ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, name, - sizeof (name)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if (strcmp(name, SANIBEL_PICLNODE_PARALLEL) == 0) { - (void) strncpy(class, SANIBEL_PARALLEL_PORT, sizeof (class)); - } - - if (add_node2cache(nodeh, class, &cachep) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - /* add cache to the linked list */ - if (cachep != NULL) { - cachep->next = NULL; - if (device->first == NULL) { /* 1st node */ - device->first = cachep; - device->last = NULL; - - } else if (device->last != NULL) { /* last node */ - device->last->next = cachep; - device->last = cachep; - - } else { /* 2nd node */ - device->first->next = cachep; - device->last = cachep; - } - } - return (PICL_WALK_CONTINUE); -} - -/* - * determine the state manager for this node - */ -static picl_errno_t -get_loc_type(frutree_locnode_t *locp) -{ - picl_errno_t rc; - cfga_list_data_t *list = NULL; - char valbuf[PICL_PROPNAMELEN_MAX]; - char slot_type[PICL_PROPNAMELEN_MAX]; - - if (locp->state_mgr != UNKNOWN) - return (PICL_SUCCESS); - - rc = ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_STATE, - (void *)valbuf, PICL_PROPNAMELEN_MAX); - if (rc == PICL_SUCCESS) { /* managed by platform specific plugin */ - locp->state_mgr = PLUGIN_PVT; - return (PICL_SUCCESS); - } - - /* get the info from the libcfgadm interface */ - list = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t)); - if (list == NULL) { - return (PICL_NOSPACE); - } - - if ((rc = get_cfgadm_state(list, locp->name)) == PICL_SUCCESS) { - locp->state_mgr = CFGADM_AP; - } else { - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_SLOT_TYPE, slot_type, - sizeof (slot_type))) != PICL_SUCCESS) { - free(list); - return (rc); - } - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - /* - * for scsi locations, if cfgadm ap is - * not present, then consider it as device - * not present - */ - locp->state_mgr = CFGADM_AP; - } else { - /* - * devices like PMC card doesnt showup in cfgadm - */ - locp->state_mgr = STATIC_LOC; - } - } - free(list); - return (PICL_SUCCESS); -} - -/* - * Initialize the location node.(create all the props) - */ -static picl_errno_t -location_init(frutree_locnode_t *locp) -{ - picl_errno_t rc; - boolean_t state_change; - uint64_t ap_status_time = 0; - char valbuf[PICL_PROPNAMELEN_MAX]; - - /* check if it is a CPU location node or not */ - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_NAME, - (void *)valbuf, PICL_PROPNAMELEN_MAX) == PICL_SUCCESS) { - if (strncmp(valbuf, SANIBEL_PICLNODE_CPU, - strlen(SANIBEL_PICLNODE_CPU)) == 0) { - locp->cpu_node = B_TRUE; - } - } - /* - * Algorithm: - * if "State" prop is already created (node is managed by other plugin) - * does nothing - * else if cfgadm ap is found - * creates State prop and intializes it - * else - * find the nodes using libdevinfo under a given path - * at given geoaddr - * if node is found - * mark node state a connected - * else - * mark node state a empty - */ - (void) get_loc_type(locp); - if (locp->state_mgr == PLUGIN_PVT) { - (void) update_loc_state(locp, &state_change); - return (PICL_SUCCESS); - } - - if (locp->state_mgr == STATIC_LOC) { - /* - * in case of scsi locations,, loc state will be connected - * no need to check again if the fru is present using libdevinfo - */ - if (locp->state != LOC_STATE_CONNECTED) { - if (is_fru_present_under_location(locp) == B_TRUE) { - locp->state = LOC_STATE_CONNECTED; - } else { - locp->state = LOC_STATE_EMPTY; - } - } - } - /* create state property */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_STATE, get_loc_state, NULLWRITE, locp->locnodeh, - NULL, loc_state[locp->state])) != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_STATE, locp->name, rc); - return (rc); - } - ap_status_time = (uint64_t)(time(NULL)); - - /* create location StatusTime prop. */ - if ((rc = create_property(PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (uint64_t), PICL_PROP_STATUS_TIME, NULLREAD, - NULLWRITE, locp->locnodeh, NULL, &ap_status_time)) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_STATUS_TIME, locp->name, rc); - return (rc); - } - - if ((rc = update_loc_state(locp, &state_change)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(FRUTREE_INIT, GET_LOC_STATE_ERR, locp->name, rc); - return (rc); - } - return (PICL_SUCCESS); -} - -static frutree_port_type_t -frutree_get_port_type(frutree_portnode_t *portp) -{ - char device_type[PICL_PROPNAMELEN_MAX]; - frutree_port_type_t port_type = UNKNOWN_PORT; - - if (portp == NULL) { - return (port_type); - } - - if (ptree_get_propval_by_name(portp->portnodeh, - PICL_PROP_PORT_TYPE, device_type, - sizeof (device_type)) == PICL_SUCCESS) { - if (strcmp(device_type, SANIBEL_NETWORK_PORT) == 0) { - port_type = NETWORK_PORT; - } else if (strcmp(device_type, - SANIBEL_SERIAL_PORT) == 0) { - port_type = SERIAL_PORT; - } else if (strcmp(device_type, - SANIBEL_PARALLEL_PORT) == 0) { - port_type = PARALLEL_PORT; - } - } - return (port_type); -} - -/* volatile callback function to get port condition */ -static int -get_port_condition(ptree_rarg_t *rarg, void *buf) -{ - picl_errno_t rc; - hashdata_t *hashptr = NULL; - frutree_portnode_t *portp = NULL; - frutree_port_type_t port_type; - - if (buf == NULL) { - return (PICL_INVALIDARG); - } - - if ((rc = hash_lookup_entry(rarg->nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - - portp = PORTDATA_PTR(hashptr); - if (portp == NULL) { - return (PICL_FAILURE); - } - port_type = frutree_get_port_type(portp); - - if (port_type == UNKNOWN_PORT) { - portp->cond = PORT_COND_UNKNOWN; - (void) strncpy((char *)buf, port_cond[portp->cond], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); - } - - if ((rc = update_port_state(portp, B_TRUE)) != PICL_SUCCESS) { - return (rc); - } - - (void) strncpy((char *)buf, port_cond[portp->cond], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); -} - -/* volatile callback function to get port state */ -static int -get_port_state(ptree_rarg_t *rarg, void *buf) -{ - picl_errno_t rc; - hashdata_t *hashptr = NULL; - frutree_portnode_t *portp = NULL; - frutree_port_type_t port_type; - - if (buf == NULL) { - return (PICL_INVALIDARG); - } - if ((rc = hash_lookup_entry(rarg->nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - portp = PORTDATA_PTR(hashptr); - if (portp == NULL) { - return (PICL_FAILURE); - } - - port_type = frutree_get_port_type(portp); - if (port_type == UNKNOWN_PORT) { - portp->state = PORT_STATE_UNKNOWN; - (void) strncpy((char *)buf, port_state[portp->state], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); - } - - if ((rc = update_port_state(portp, B_TRUE)) != PICL_SUCCESS) { - return (rc); - } - (void) strncpy((char *)buf, port_state[portp->state], - PICL_PROPNAMELEN_MAX); - return (PICL_SUCCESS); -} - -/* - * Creates State and Condition property for a port node - */ -static picl_errno_t -port_init(frutree_portnode_t *portp) -{ - picl_prophdl_t proph; - ptree_propinfo_t propinfo; - void *vbuf; - picl_errno_t rc; - uint64_t status_time; - picl_nodehdl_t refhdl; - frutree_device_args_t device; - picl_prophdl_t tblprophdl, tblhdl; - char class[PICL_PROPNAMELEN_MAX]; - - if (portp == NULL) { - return (PICL_FAILURE); - } - refhdl = get_reference_handle(portp->portnodeh); - - /* traverse thru platform tree and add entries to Devices table */ - if (refhdl != 0) { - /* create Devices table property */ - if ((rc = create_property(PICL_PTYPE_TABLE, PICL_READ, - sizeof (picl_prophdl_t), PICL_PROP_DEVICES, - NULLREAD, NULLWRITE, portp->portnodeh, &tblprophdl, - &tblhdl)) != PICL_SUCCESS) { - return (rc); - } - - /* walk down the subtree and populate Devices */ - if ((rc = ptree_get_propval_by_name(refhdl, - PICL_PROP_CLASSNAME, class, - sizeof (class))) != PICL_SUCCESS) { - return (rc); - } - if ((rc = create_table_entry(tblhdl, refhdl, class)) != - PICL_SUCCESS) { - return (rc); - } - - device.nodeh = refhdl; - device.device_tblhdl = tblhdl; - device.first = NULL; - device.last = NULL; - device.create_cache = B_FALSE; - - if ((rc = do_action(refhdl, CREATE_DEVICES_ENTRIES, - (void *)&device)) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_prop_by_name(refhdl, PICL_PROP_INSTANCE, - &proph)) != PICL_SUCCESS) { - return (rc); - } - if ((rc = ptree_get_propinfo(proph, &propinfo)) != - PICL_SUCCESS) { - return (rc); - } - vbuf = alloca(propinfo.piclinfo.size); - if (vbuf == NULL) - return (PICL_NOSPACE); - - if ((rc = ptree_get_propval(proph, vbuf, - propinfo.piclinfo.size)) != PICL_SUCCESS) { - return (rc); - } - portp->instance = *(int *)vbuf; - - if ((rc = ptree_get_prop_by_name(refhdl, - PICL_PROP_DRIVER_NAME, &proph)) != PICL_SUCCESS) { - return (rc); - } - if ((rc = ptree_get_propinfo(proph, &propinfo)) != - PICL_SUCCESS) { - return (rc); - } - vbuf = alloca(propinfo.piclinfo.size); - if (vbuf == NULL) - return (PICL_NOSPACE); - - if ((rc = ptree_get_propval(proph, vbuf, - propinfo.piclinfo.size)) != PICL_SUCCESS) { - return (rc); - } - - (void) strncpy(portp->driver, (char *)vbuf, - sizeof (portp->driver)); - } else { - /* this node is created using libdevinfo or conf file */ - if ((rc = get_port_info(portp)) != PICL_SUCCESS) { - return (rc); - } - } - - /* create state and condition properties */ - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ | PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_STATE, get_port_state, NULLWRITE, portp->portnodeh, - NULL, port_state[portp->state])) != PICL_SUCCESS) { - return (rc); - } - - status_time = (uint64_t)(time(NULL)); - if ((rc = create_property(PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (uint64_t), PICL_PROP_STATUS_TIME, NULLREAD, - NULLWRITE, portp->portnodeh, NULL, &status_time)) != - PICL_SUCCESS) { - return (rc); - } - - if ((rc = create_property(PICL_PTYPE_CHARSTRING, - PICL_READ | PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_CONDITION, get_port_condition, NULLWRITE, - portp->portnodeh, NULL, port_cond[portp->cond])) != - PICL_SUCCESS) { - return (rc); - } - if ((rc = create_property(PICL_PTYPE_TIMESTAMP, PICL_READ, - sizeof (uint64_t), PICL_PROP_CONDITION_TIME, NULLREAD, - NULLWRITE, portp->portnodeh, NULL, &status_time)) != - PICL_SUCCESS) { - return (rc); - } - (void) update_port_state(portp, B_FALSE); - return (PICL_SUCCESS); -} - -/* - * This routine dynamically determines the scsi name (using libcfgadm) - * that corresponds to the node specified in configuration file - */ -static picl_errno_t -init_scsi_slot(frutree_frunode_t *frup, frutree_locnode_t **ptr2locp, - boolean_t *node_name_changed) -{ - picl_errno_t rc; - char devfs_path[PICL_PROPNAMELEN_MAX]; - char bus_addr[PICL_PROPNAMELEN_MAX]; - char label[PICL_PROPNAMELEN_MAX]; - char name[MAXPATHLEN]; - uint8_t geo_addr = 0; - frutree_locnode_t *locp = NULL, *new_locp = NULL; - hashdata_t *hashptr = NULL; - picl_nodehdl_t nodeh; - - if (ptr2locp == NULL) { - return (PICL_INVALIDARG); - } - locp = (frutree_locnode_t *)*ptr2locp; - *node_name_changed = B_FALSE; - - if (locp == NULL) { - return (PICL_FAILURE); - } - - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_DEVFS_PATH, devfs_path, - sizeof (devfs_path))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_BUS_ADDR, bus_addr, - sizeof (bus_addr))) != PICL_SUCCESS) { - return (rc); - } - - /* find the dynamic ap_id from libcfgadm */ - if ((rc = get_scsislot_name(devfs_path, bus_addr, - name)) != PICL_SUCCESS) { - /* if rc is NODENOTFOUND, then slot is empty */ - if (rc != PICL_NODENOTFOUND) { - return (rc); - } else { - return (PICL_SUCCESS); - } - } - - /* node name is same, so dont change anything */ - if (strcmp(name, locp->name) == 0) { - return (PICL_SUCCESS); - } - - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_GEO_ADDR, &geo_addr, - sizeof (geo_addr))) != PICL_SUCCESS) { - geo_addr = 0; - } - - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_LABEL, label, - sizeof (label))) != PICL_SUCCESS) { - return (rc); - } - - /* Now recreate the node with new name */ - if ((rc = ptree_create_node(name, PICL_CLASS_LOCATION, - &nodeh)) != PICL_SUCCESS) { - return (rc); - } - - /* add all the properties now */ - (void) create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_SLOT_TYPE, NULLREAD, - NULLWRITE, nodeh, (picl_prophdl_t *)NULL, - SANIBEL_SCSI_SLOT); - - (void) create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_LABEL, NULLREAD, - NULLWRITE, nodeh, (picl_prophdl_t *)NULL, - label); - - (void) create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_BUS_ADDR, NULLREAD, - NULLWRITE, nodeh, (picl_prophdl_t *)NULL, - bus_addr); - - (void) create_property(PICL_PTYPE_UNSIGNED_INT, PICL_READ, - sizeof (uint8_t), PICL_PROP_GEO_ADDR, NULLREAD, - NULLWRITE, nodeh, (picl_prophdl_t *)NULL, - &geo_addr); - - (void) create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_DEVFS_PATH, NULLREAD, - NULLWRITE, nodeh, (picl_prophdl_t *)NULL, - devfs_path); - (void) ptree_add_node(frup->frunodeh, nodeh); - - if ((rc = make_loc_data(name, &hashptr)) != PICL_SUCCESS) { - return (rc); - } - /* save data in hash table */ - if ((rc = hash_add_entry(nodeh, (void *)hashptr)) != PICL_SUCCESS) { - free_data(hashptr->type, hashptr); - return (rc); - } - - new_locp = LOCDATA_PTR(hashptr); - new_locp->locnodeh = nodeh; - *ptr2locp = new_locp; - *node_name_changed = B_TRUE; - return (PICL_SUCCESS); -} - -/* - * find the child nodes under a fru and initialize them - */ -static int -frutree_initialize_children(picl_nodehdl_t childh, void *c_args) -{ - picl_errno_t rc; - picl_nodehdl_t parenth; - boolean_t node_changed = B_FALSE; - hashdata_t *datap = NULL; - char name[PICL_PROPNAMELEN_MAX]; - char class[PICL_PROPNAMELEN_MAX]; - frutree_frunode_t *frup = NULL; - frutree_init_callback_arg_t *arg; - - if (c_args == NULL) { - return (PICL_INVALIDARG); - } - arg = (frutree_init_callback_arg_t *)c_args; - frup = arg->frup; - - if ((rc = ptree_get_propval_by_name(childh, PICL_PROP_PARENT, - &parenth, sizeof (parenth))) != PICL_SUCCESS) { - return (rc); - } - - if (parenth != frup->frunodeh) - return (PICL_WALK_CONTINUE); - - if ((rc = ptree_get_propval_by_name(childh, PICL_PROP_CLASSNAME, class, - sizeof (class))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_propval_by_name(childh, PICL_PROP_NAME, name, - sizeof (name))) != PICL_SUCCESS) { - return (rc); - } - - if (strcmp(class, PICL_CLASS_LOCATION) == 0) { - char slot_type[PICL_PROPNAMELEN_MAX]; - frutree_locnode_t *locp = NULL; - frutree_frunode_t *child_frup = NULL; - /* initialize internal data structure */ - if ((rc = make_loc_data(name, &datap)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - locp = LOCDATA_PTR(datap); - locp->locnodeh = childh; - /* save data in hash table */ - (void) hash_add_entry(childh, (void *)datap); - if ((rc = ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_SLOT_TYPE, slot_type, - sizeof (slot_type))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_GET_PROPVAL_ERR, - PICL_PROP_SLOT_TYPE, locp->name, rc); - return (PICL_WALK_CONTINUE); - } else { - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - /* - * this rountine finds the valid cfgadm - * ap_id name for a given node and - * creates a new node with that name. - * If the node name is changed, the present - * node must be added to the list of nodes - * to be deleted from tree after ptree walk. - */ - (void) init_scsi_slot(frup, &locp, - &node_changed); - if (node_changed) { - delete_list_t *nodep = NULL; - /* - * add this node to list of nodes - * to be removed - */ - nodep = (delete_list_t *)malloc( - sizeof (delete_list_t)); - if (nodep == NULL) { - return (PICL_NOSPACE); - } - nodep->nodeh = childh; - nodep->next = NULL; - - if (arg->first == NULL) { - arg->first = nodep; - } else { /* add 2 front */ - nodep->next = arg->first; - arg->first = nodep; - } - } - } - } - if ((rc = location_init(locp)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - /* if location is empty, done */ - if (locp->state == LOC_STATE_EMPTY || - locp->state == LOC_STATE_UNKNOWN) { - return (PICL_WALK_CONTINUE); - } - - /* create the fru node and initialize it */ - if ((rc = create_fru_node(locp, &child_frup)) != - PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - /* - * if fru is already configured, create the - * subtree under the child fru - */ - if (child_frup->state == FRU_STATE_CONFIGURED) { - /* initialize the fru_path */ - if ((rc = probe_fru(child_frup, B_TRUE)) != - PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, PROBE_FRU_ERR, - child_frup->name, rc); - } - } - } else if (strcmp(class, PICL_CLASS_PORT) == 0) { - frutree_portnode_t *portp = NULL; - if ((rc = make_port_data(name, &datap)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - (void) hash_add_entry(childh, (void *)datap); - portp = PORTDATA_PTR(datap); - portp->portnodeh = childh; - (void) port_init(portp); - } - return (PICL_WALK_CONTINUE); -} - -/* traverse thru all locations under fru and initiate connects */ -static int -initiate_connects(picl_nodehdl_t nodeh, void *args) -{ - picl_errno_t rc; - hashdata_t *hashptr = NULL; - picl_nodehdl_t parenth; - frutree_frunode_t *frup = NULL; - frutree_locnode_t *locp = NULL; - - if (args == NULL) { - return (PICL_INVALIDARG); - } - frup = (frutree_frunode_t *)args; - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_PARENT, - &parenth, sizeof (parenth))) != PICL_SUCCESS) { - return (rc); - } - - if (parenth != frup->frunodeh) - return (PICL_WALK_CONTINUE); - - if ((rc = hash_lookup_entry(nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - locp = LOCDATA_PTR(hashptr); - - if (locp->state == LOC_STATE_EMPTY || - locp->state == LOC_STATE_UNKNOWN || - locp->state == LOC_STATE_CONNECTED) { - return (PICL_WALK_CONTINUE); - } - - /* if loc is not connected, do a connect operation */ - if (locp->autoconfig_enabled) { - if ((rc = connect_fru(locp)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, CONNECT_FAILED_ERR, - locp->name, rc); - } - } - return (PICL_WALK_CONTINUE); -} - -/* - * Initializes the subtree under a FRU - */ -static picl_errno_t -fru_init(frutree_frunode_t *frup) -{ - picl_errno_t rc; - delete_list_t *tmp = NULL, *curr = NULL; - frutree_init_callback_arg_t arg; - - if (frup == NULL) { - return (PICL_INVALIDARG); - } - - arg.frup = frup; - arg.first = NULL; - - /* - * this routine creates internal data structures for - * all the children under this fru and initializes them - */ - if ((rc = do_action(frup->frunodeh, INIT_FRU, - (void *)&arg)) != PICL_SUCCESS) { - return (rc); - } - - /* traverse thru delete_nodes_list and delete the nodes from tree */ - curr = arg.first; - while (curr) { - tmp = curr; - (void) ptree_delete_node(tmp->nodeh); - (void) ptree_destroy_node(tmp->nodeh); - (void) hash_remove_entry(tmp->nodeh); - free(tmp); - curr = curr->next; - } - - /* - * dont post events during intialization (for other FRUs) - * chassis intialization will take care of posting events - * for complete frutree - */ - if ((frup->frunodeh == chassish) || - (post_picl_events == B_TRUE)) { - if ((rc = do_action(frup->frunodeh, POST_EVENTS, NULL)) != - PICL_SUCCESS) { - FRUTREE_DEBUG1(LOG_ERR, "SUNW_frutree:Error in " - "posting picl events(error=%d)", rc); - } - } - - if (frup->frunodeh == chassish) { - post_picl_events = B_TRUE; - frutree_connects_initiated = B_TRUE; - } - - /* initiate connects */ - if ((rc = ptree_walk_tree_by_class(frup->frunodeh, PICL_CLASS_LOCATION, - (void *)frup, initiate_connects)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -/*ARGSUSED*/ -static int -post_events(picl_nodehdl_t childh, void *c_args) -{ - int rc; - hashdata_t *hashptr = NULL; - frutree_frunode_t *frup = NULL; - frutree_locnode_t *locp = NULL; - frutree_portnode_t *portp = NULL; - char classval[PICL_CLASSNAMELEN_MAX]; - - if ((rc = ptree_get_propval_by_name(childh, PICL_PROP_CLASSNAME, - classval, sizeof (classval))) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if ((rc = hash_lookup_entry(childh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if (strcmp(classval, PICL_CLASS_LOCATION) == 0) { - locp = LOCDATA_PTR(hashptr); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], loc_state[locp->prev_state], - childh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_WALK_CONTINUE); - } - - if (strcmp(classval, PICL_CLASS_FRU) == 0) { - frup = FRUDATA_PTR(hashptr); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], fru_state[frup->prev_state], - childh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, rc); - } - return (PICL_WALK_CONTINUE); - } - - if (strcmp(classval, PICL_CLASS_PORT) == 0) { - portp = PORTDATA_PTR(hashptr); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - port_state[portp->state], NULL, - portp->portnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - portp->name, PICLEVENT_STATE_CHANGE, rc); - } - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - port_cond[portp->cond], NULL, - portp->portnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - portp->name, PICLEVENT_CONDITION_CHANGE, rc); - } - return (PICL_WALK_CONTINUE); - } - return (PICL_WALK_CONTINUE); -} - -/* - * This function is a utility function that calls the - * appropriate call back function for the all the nodes under - * the specified root node. - * future additions can be done by defining new action and callback. - */ -static picl_errno_t -do_action(picl_nodehdl_t root, int action, void *cargs) -{ - int rc; - callback_t func_ptr; - char *class = NULL; - - switch (action) { - - case INIT_FRU: - func_ptr = frutree_initialize_children; - class = NULL; - break; - case CREATE_DEVICES_ENTRIES: - func_ptr = create_device_entries; - class = NULL; - break; - case POST_EVENTS: - func_ptr = post_events; - class = NULL; - break; - default: - return (PICL_INVALIDARG); - } - - if ((rc = ptree_walk_tree_by_class(root, class, cargs, - func_ptr)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -static picl_errno_t -frutree_update_chassis_state(frutree_frustate_t state, - frutree_frustate_t prev_state) -{ - uint64_t ap_status_time; - picl_errno_t rc = 0; - char present_state[PICL_PROPNAMELEN_MAX]; - - (void) strncpy(present_state, fru_state[state], sizeof (present_state)); - (void) ptree_update_propval_by_name(chassish, - PICL_PROP_STATE, present_state, sizeof (present_state)); - - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(chassish, - PICL_PROP_STATUS_TIME, (void *)&ap_status_time, - sizeof (ap_status_time))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, PICL_NODE_CHASSIS, rc); - } - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[state], fru_state[prev_state], - chassish, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - PICL_NODE_CHASSIS, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); -} - -static picl_errno_t -frutree_init() -{ - picl_errno_t rc; - frutree_frunode_t *frup = NULL; - hashdata_t *hashptr = NULL; - - if ((rc = ptree_get_node_by_path(PLATFORM_PATH, &platformh)) != - PICL_SUCCESS) { - return (rc); - } - - if ((rc = hash_lookup_entry(chassish, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - frup = FRUDATA_PTR(hashptr); - - /* create the nodes in conf file under chassis node */ - if ((rc = picld_pluginutil_parse_config_file(chassish, - conf_file)) != PICL_SUCCESS) { - /* update chassis state to unconfigured */ - (void) frutree_update_chassis_state( - FRU_STATE_UNCONFIGURED, FRU_STATE_UNKNOWN); - return (rc); - } - - /* update chassis state to configuring */ - (void) frutree_update_chassis_state( - FRU_STATE_CONFIGURING, FRU_STATE_UNCONFIGURED); - - if (scsi_info_init() != PICL_SUCCESS) { - /* update chassis state to unconfigured */ - (void) frutree_update_chassis_state( - FRU_STATE_UNCONFIGURED, FRU_STATE_CONFIGURING); - return (PICL_FAILURE); - } - - /* traverse thru all the nodes under chassis, initialize them */ - if ((rc = fru_init(frup)) != PICL_SUCCESS) { - /* update chassis state to unconfigured */ - (void) frutree_update_chassis_state( - FRU_STATE_UNCONFIGURED, FRU_STATE_CONFIGURING); - scsi_info_fini(); - return (rc); - } - /* free the memory used during initialization */ - scsi_info_fini(); - /* start node monitoring thread */ - if (pthread_create(&monitor_tid, NULL, monitor_node_status, - NULL) != 0) { - FRUTREE_DEBUG0(EVENTS, "SUNW_frutree:Error in creating node" - " monitoring thread"); - } - - (void) pthread_mutex_lock(&frup->mutex); - frup->state = FRU_STATE_CONFIGURED; - (void) pthread_mutex_unlock(&frup->mutex); - - /* update chassis state to configured */ - (void) frutree_update_chassis_state( - FRU_STATE_CONFIGURED, FRU_STATE_CONFIGURING); - return (PICL_SUCCESS); -} - -/* ARGSUSED */ -static void * -init_thread(void *arg) -{ - picl_errno_t rc; - - FRUTREE_DEBUG0(FRUTREE_INIT, "init_thread begin"); - - (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - - if (get_configuration_file() != PICL_SUCCESS) { - return (NULL); - } - FRUTREE_DEBUG1(FRUTREE_INIT, "conf_file = %s", conf_file); - if ((rc = frutree_init()) != PICL_SUCCESS) { - FRUTREE_DEBUG1(FRUTREE_INIT, "frutree_init failed, error = %d", - rc); - } - FRUTREE_DEBUG0(FRUTREE_INIT, "init_thread end"); - return (NULL); -} - -/* ARGSUSED */ -static void -event_completion_handler(char *ename, void *earg, size_t size) -{ - if (frutree_debug & EV_COMPLETION) { - char name[PICL_PROPNAMELEN_MAX]; - nvlist_t *nvlp; - char *value = NULL; - char *arg = NULL; - picl_nodehdl_t fruhdl; - time_t current_time; - - if (strncmp(ename, PICLEVENT_STATE_CHANGE, - strlen(PICLEVENT_STATE_CHANGE)) == 0) { - arg = PICLEVENTARG_STATE; - } else if (strncmp(ename, PICLEVENT_CONDITION_CHANGE, - strlen(PICLEVENT_CONDITION_CHANGE)) == 0) { - arg = PICLEVENTARG_CONDITION; - } - - (void) nvlist_unpack((char *)earg, size, &nvlp, NULL); - (void) nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, - &fruhdl); - if (arg != NULL) - (void) nvlist_lookup_string(nvlp, arg, &value); - - (void) ptree_get_propval_by_name(fruhdl, PICL_PROP_NAME, - (void *)name, sizeof (name)); - current_time = (uint64_t)(time(NULL)); - if (value != NULL) { - FRUTREE_DEBUG4(EV_COMPLETION, "ev_completed[%s]%s(%s) " - "on %s", ctime(¤t_time), ename, value, name); - } - nvlist_free(nvlp); - } - - (void) mutex_lock(&piclevent_mutex); - piclevent_pending = 0; - (void) cond_broadcast(&piclevent_completed_cv); - (void) mutex_unlock(&piclevent_mutex); - free(earg); - free(ename); -} - -picl_errno_t -post_piclevent(const char *event, char *val1, - char *val2, picl_nodehdl_t nodeh, frutree_wait_t wait) -{ - nvlist_t *nvl; - size_t nvl_size; - char *pack_buf = NULL; - char *ename = NULL; - char *arg = NULL; - picl_errno_t rc; - timestruc_t to; - struct timeval tp; - - if (event == NULL || val1 == NULL) { - return (PICL_INVALIDARG); - } - if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) { - return (PICL_FAILURE); - } - if (nvlist_add_uint64(nvl, PICLEVENTARG_NODEHANDLE, nodeh)) { - nvlist_free(nvl); - return (PICL_FAILURE); - } - - if ((ename = strdup(event)) == NULL) { - nvlist_free(nvl); - return (PICL_NOSPACE); - } - - if (strncmp(ename, PICLEVENT_STATE_CHANGE, - strlen(PICLEVENT_STATE_CHANGE)) == 0) { - arg = PICLEVENTARG_STATE; - } else if (strncmp(ename, PICLEVENT_CONDITION_CHANGE, - strlen(PICLEVENT_CONDITION_CHANGE)) == 0) { - arg = PICLEVENTARG_CONDITION; - } else { - free(ename); - nvlist_free(nvl); - return (PICL_INVALIDARG); - } - - if (nvlist_add_string(nvl, arg, val1)) { - free(ename); - nvlist_free(nvl); - return (PICL_FAILURE); - } - - if (strncmp(ename, PICLEVENT_CONDITION_CHANGE, - strlen(PICLEVENT_CONDITION_CHANGE)) == 0) { - if (nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, - NULL)) { - free(ename); - nvlist_free(nvl); - return (PICL_FAILURE); - } - } else { /* state change event */ - - if (val2 != NULL) { - /* if there is a last state, add it to nvlist */ - if (nvlist_add_string(nvl, - PICLEVENTARG_LAST_STATE, val2)) { - free(ename); - nvlist_free(nvl); - return (PICL_FAILURE); - } - } - } - - if (nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { - free(ename); - nvlist_free(nvl); - return (PICL_FAILURE); - } - - (void) mutex_lock(&piclevent_mutex); - while (piclevent_pending) { - (void) cond_wait(&piclevent_completed_cv, - &piclevent_mutex); - } - piclevent_pending = 1; - (void) mutex_unlock(&piclevent_mutex); - - if ((rc = ptree_post_event(ename, pack_buf, nvl_size, - event_completion_handler)) != PICL_SUCCESS) { - free(ename); - free(pack_buf); - nvlist_free(nvl); - (void) mutex_lock(&piclevent_mutex); - piclevent_pending = 0; - (void) mutex_unlock(&piclevent_mutex); - return (rc); - } - - if (frutree_debug) { - char name[PICL_PROPNAMELEN_MAX]; - (void) ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, - name, sizeof (name)); - if (val2 != NULL) { - FRUTREE_DEBUG4(EVENTS, "%s(%s -> %s) on %s", ename, - val2, val1, name); - } else { - FRUTREE_DEBUG3(EVENTS, "%s(%s) on %s", ename, - val1, name); - } - } - - if (wait) { /* wait for the event to be handled */ - (void) mutex_lock(&piclevent_mutex); - while (piclevent_pending) { - (void) gettimeofday(&tp, NULL); - to.tv_sec = tp.tv_sec + 1; - to.tv_nsec = tp.tv_usec * 1000; - (void) cond_timedwait(&piclevent_completed_cv, - &piclevent_mutex, &to); - } - (void) mutex_unlock(&piclevent_mutex); - } - nvlist_free(nvl); - return (PICL_SUCCESS); -} - -/* - * return values - * -1 : error - * 0 : not enabled - * 1 : enabled - */ -/* ARGSUSED */ -static int -is_autoconfig_enabled(char *loc_name) -{ - return (1); -} - -static picl_errno_t -update_loc_type(frutree_locnode_t *locp) -{ - cfga_list_data_t *list = NULL; - /* get the info from the libcfgadm interface */ - list = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t)); - if (list == NULL) { - return (PICL_NOSPACE); - } - - if (get_cfgadm_state(list, locp->name) == PICL_SUCCESS) { - locp->state_mgr = CFGADM_AP; - free(list); - return (PICL_SUCCESS); - } - free(list); - return (PICL_NODENOTFOUND); -} - -/* - * handles DR_INCOMING_RES on chassis node - * (refresh piclfrutree tree) - */ -static int -reconfigure_chassis(picl_nodehdl_t nodeh, void *args) -{ - picl_errno_t rc; - hashdata_t *hashptr = NULL; - picl_nodehdl_t parenth, childh; - frutree_frunode_t *frup = NULL, *child_frup = NULL; - frutree_locnode_t *locp = NULL; - boolean_t state_changed = B_FALSE; - boolean_t cond_changed = B_FALSE; - frutree_dr_arg_t dr_arg; - - if (args == NULL) { - return (PICL_INVALIDARG); - } - frup = (frutree_frunode_t *)args; - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_PARENT, - &parenth, sizeof (parenth))) != PICL_SUCCESS) { - return (rc); - } - - if (parenth != frup->frunodeh) - return (PICL_WALK_CONTINUE); - - if ((rc = hash_lookup_entry(nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - locp = LOCDATA_PTR(hashptr); - - /* if the location has child fru, get its information */ - if (ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - /* get the child fru information */ - if (hash_lookup_entry(childh, (void **)&hashptr) == - PICL_SUCCESS) { - child_frup = FRUDATA_PTR(hashptr); - } - } - - /* for each location, update the state */ - if (locp->state_mgr == STATIC_LOC) { - /* check if cfgadm ap_id is present */ - rc = update_loc_type(locp); - if (rc == PICL_SUCCESS) { - if (child_frup) { - child_frup->state_mgr = locp->state_mgr; - (void) update_fru_state(child_frup, - &state_changed); - } - } - } - - state_changed = B_FALSE; - (void) update_loc_state(locp, &state_changed); - if (state_changed) { - switch (locp->state) { - case LOC_STATE_CONNECTED: - case LOC_STATE_DISCONNECTED: - if (locp->prev_state == LOC_STATE_EMPTY || - locp->prev_state == LOC_STATE_UNKNOWN) { - /* handle fru insertion */ - dr_arg.action = HANDLE_INSERT; - } else { - /* handle loc state change */ - dr_arg.action = HANDLE_LOCSTATE_CHANGE; - } - break; - case LOC_STATE_EMPTY: - /* handle fru removal */ - if (locp->prev_state == LOC_STATE_UNKNOWN) { - /* post piclevent to update led */ - dr_arg.action = HANDLE_LOCSTATE_CHANGE; - } else { - /* disconnected fru is removed */ - dr_arg.action = HANDLE_REMOVE; - } - break; - default: - return (PICL_WALK_CONTINUE); - } /* end of switch */ - - dr_arg.data = locp; - (void) pthread_mutex_lock(&ev_mutex); - if ((rc = add_to_queue(dr_arg)) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - return (PICL_WALK_CONTINUE); - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - return (PICL_WALK_CONTINUE); - } else { - /* connect the disconnect locations */ - if (locp->state == LOC_STATE_DISCONNECTED && - locp->autoconfig_enabled == B_TRUE) { - if ((rc = connect_fru(locp)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, CONNECT_FAILED_ERR, - locp->name, rc); - } - return (PICL_WALK_CONTINUE); - } - } - - /* post picl event for child fru */ - if (child_frup == NULL) { - return (PICL_WALK_CONTINUE); - } - - /* update the state */ - (void) update_fru_state(child_frup, &state_changed); - if (state_changed) { - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[child_frup->state], - fru_state[child_frup->prev_state], - child_frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - child_frup->name, PICLEVENT_STATE_CHANGE, rc); - } - } - - /* update the condition */ - (void) update_fru_condition(child_frup, &cond_changed); - if (cond_changed) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[child_frup->cond], - fru_cond[child_frup->prev_cond], - child_frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - child_frup->name, PICLEVENT_CONDITION_CHANGE, - rc); - } - } - return (PICL_WALK_CONTINUE); -} - -static picl_errno_t -handle_chassis_configure(frutree_frunode_t *frup) -{ - picl_errno_t rc; - - if (frup == NULL) { - return (PICL_INVALIDARG); - } - - (void) pthread_mutex_lock(&frup->mutex); - FRUTREE_DEBUG1(EVENTS, "DR_INCOMING_RES on %s", frup->name); - if (frup->state == FRU_STATE_UNCONFIGURED) { - frup->state = FRU_STATE_CONFIGURING; - (void) pthread_mutex_unlock(&frup->mutex); - /* initial probe/initialization */ - /* create a thread to do the initialization */ - if (pthread_create(&init_threadID, NULL, &init_thread, - NULL) != 0) { - return (PICL_FAILURE); - } - return (PICL_SUCCESS); - } - (void) pthread_mutex_unlock(&frup->mutex); - - /* - * 1. update the state of all the nodes in chassis - * 2. handle all the state changes accordingly - */ - if ((rc = ptree_walk_tree_by_class(chassish, PICL_CLASS_LOCATION, - (void *)frup, reconfigure_chassis)) != PICL_SUCCESS) { - return (rc); - } - return (PICL_SUCCESS); -} - -static picl_errno_t -handle_chassis_unconfigure(frutree_frunode_t *frup) -{ - picl_errno_t rc; - - if (frup->state == FRU_STATE_UNCONFIGURED) { - return (PICL_SUCCESS); - } - - /* do any cleanups here */ - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_UNCONFIGURING, PICLEVENTARGVAL_CONFIGURED, - chassish, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - PICL_NODE_CHASSIS, PICLEVENT_STATE_CHANGE, rc); - } - - if ((rc = ptree_update_propval_by_name(chassish, - PICL_PROP_STATE, PICLEVENTARGVAL_UNCONFIGURED, - PICL_PROPNAMELEN_MAX)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATE, PICL_NODE_CHASSIS, rc); - } - frup->prev_state = FRU_STATE_CONFIGURED; - frup->state = FRU_STATE_UNCONFIGURED; - (void) handle_fru_unconfigure(frup); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_UNCONFIGURED, PICLEVENTARGVAL_UNCONFIGURING, - chassish, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - PICL_NODE_CHASSIS, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); -} - -static picl_errno_t -configuration_fn(frutree_dr_arg_t *dr_arg) -{ - picl_errno_t rc; - picl_nodehdl_t parenth; - cfga_flags_t flags = 0; - frutree_frunode_t *frup = NULL; - frutree_locnode_t *locp = NULL; - hashdata_t *hashptr = NULL; - boolean_t state_changed = B_FALSE; - - if (dr_arg == NULL) - return (PICL_FAILURE); - - frup = (frutree_frunode_t *)dr_arg->data; - if (frup == NULL) { - free(dr_arg); - return (PICL_FAILURE); - } - - if (frup->frunodeh == chassish) { - rc = handle_chassis_configure(frup); - free(dr_arg); - return (rc); - } - - if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &parenth, sizeof (parenth))) != PICL_SUCCESS) { - free(dr_arg); - return (rc); - } - - if ((rc = hash_lookup_entry(parenth, (void **)&hashptr)) != - PICL_SUCCESS) { - free(dr_arg); - return (rc); - } - locp = LOCDATA_PTR(hashptr); - - /* - * update the location state also, as this could be - * user initiated connect operation - */ - (void) update_loc_state(locp, &state_changed); - if (state_changed) - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], loc_state[locp->prev_state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - switch (dr_arg->action) { - case CPU_ONLINE: - flags |= CFGA_FLAG_FORCE; - FRUTREE_DEBUG1(EVENTS, "CPU online on %s", frup->name); - if (locp->state != LOC_STATE_CONNECTED) { - if (locp->autoconfig_enabled) { - if ((rc = connect_fru(locp)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, - CONNECT_FAILED_ERR, - locp->name, rc); - } - } - break; - } /*FALLTHRU*/ - - /* do configure now */ - case CONFIGURE_FRU: /* dr_incoming_res */ - FRUTREE_DEBUG1(EVENTS, "DR_INCOMING_RES on %s", frup->name); - if ((rc = configure_fru(frup, flags)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, CONFIGURE_FAILED_ERR, - frup->name, rc); - break; - } - } - free(dr_arg); - return (PICL_SUCCESS); -} - -/* handles all dr related events */ -static picl_errno_t -handle_dr_event(frutree_dr_arg_t *dr_arg) -{ - picl_errno_t rc; - picl_nodehdl_t loch, childh; - hashdata_t *hashptr = NULL; - cfga_flags_t flags = 0; - frutree_dr_arg_t *arg = NULL; - frutree_dr_arg_t fru_dr_arg; - frutree_locnode_t *locp = NULL; - frutree_frunode_t *frup = NULL, *child_frup = NULL; - boolean_t state_changed = B_FALSE, cond_changed = B_FALSE; - - switch (dr_arg->action) { - case CPU_ONLINE: - case CONFIGURE_FRU: - - frup = (frutree_frunode_t *)dr_arg->data; - arg = (frutree_dr_arg_t *)malloc(sizeof (frutree_dr_arg_t)); - if (arg == NULL) { - FRUTREE_DEBUG2(EVENTS, CONFIGURE_FAILED_ERR, - frup->name, PICL_NOSPACE); - return (NULL); - } - arg->action = dr_arg->action; - arg->data = dr_arg->data; - (void) configuration_fn((void *)arg); - break; - - case CPU_OFFLINE: - flags |= CFGA_FLAG_FORCE; - frup = (frutree_frunode_t *)dr_arg->data; - if (frup == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "CPU_OFFLINE on %s", frup->name); - if ((rc = unconfigure_fru(frup, flags)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, UNCONFIG_FAILED_ERR, frup->name, rc); - break; - } - - if ((rc = handle_fru_unconfigure(frup)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, PICLEVENT_DR_REQ, - frup->name, rc); - } - break; - - case UNCONFIGURE_FRU: /* dr_outgoing_res */ - frup = (frutree_frunode_t *)dr_arg->data; - if (frup == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "DR_OUTGOING_RES on %s", frup->name); - if (frup->frunodeh == chassish) { - (void) handle_chassis_unconfigure(frup); - break; - } - - if ((rc = unconfigure_fru(frup, flags)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, UNCONFIG_FAILED_ERR, frup->name, rc); - break; - } - - if ((rc = handle_fru_unconfigure(frup)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, - PICLEVENT_DR_REQ, frup->name, rc); - } - - if (ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &loch, sizeof (loch)) != PICL_SUCCESS) { - break; - } - - if ((rc = hash_lookup_entry(loch, (void **)&hashptr)) != - PICL_SUCCESS) { - break; - } - locp = LOCDATA_PTR(hashptr); - - /* check the autoconfig flag */ - if (locp->autoconfig_enabled == B_FALSE) { - break; - } - - if ((rc = disconnect_fru(locp)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, "SUNW_frutree:Disconnect on %s " - "failed(error=%d)", locp->name, rc); - } - break; - - case HANDLE_CONFIGURE: /* basic hotswap operation */ - - frup = (frutree_frunode_t *)dr_arg->data; - if (frup == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "HANDLE CONFIGURE on %s", frup->name); - handle_fru_configure(frup); - break; - - case HANDLE_UNCONFIGURE: /* basic hotswap operation */ - - /* cleanup the internal data structures */ - - frup = (frutree_frunode_t *)dr_arg->data; - if (frup == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "HANDLE UNCONFIGURE on %s", frup->name); - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], fru_state[frup->prev_state], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - - /* update the fru condition */ - (void) update_fru_condition(frup, &state_changed); - if (state_changed) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, rc); - } - } - if ((rc = handle_fru_unconfigure(frup)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, - PICLEVENT_DR_AP_STATE_CHANGE, frup->name, rc); - } - break; - - case HANDLE_LOCSTATE_CHANGE: /* basic hotswap operation */ - /* posts state change events of location */ - locp = (frutree_locnode_t *)dr_arg->data; - if (locp == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "HANDLE LOC STATE CHANGE on %s", locp->name); - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], loc_state[locp->prev_state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - /* wakeup threads sleeping on this condition */ - (void) pthread_mutex_lock(&locp->mutex); - if (locp->state == LOC_STATE_CONNECTED) { - (void) pthread_cond_broadcast(&locp->cond_cv); - } - (void) pthread_mutex_unlock(&locp->mutex); - - /* if the location has child fru, get its information */ - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - /* get the child fru information */ - if (hash_lookup_entry(childh, (void **)&hashptr) == - PICL_SUCCESS) { - child_frup = FRUDATA_PTR(hashptr); - } - } - /* update the child fru state and handle any state changes */ - if (child_frup == NULL) { - break; - } - - if ((rc = update_fru_state(child_frup, &state_changed)) != - PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, GET_FRU_STATE_ERR, child_frup->name, rc); - break; - } - - if (state_changed == B_FALSE) { - /* - * if there is no change in state, check for condition - * changes. - * if there is a state change, handling state change - * will take care of condition changes also. - */ - (void) update_fru_condition(child_frup, &cond_changed); - if (cond_changed == B_FALSE) { - break; - } - - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[child_frup->cond], - fru_cond[child_frup->prev_cond], - child_frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - child_frup->name, - PICLEVENT_CONDITION_CHANGE, rc); - } - break; - } - - /* add to queue to handle the fru state change */ - (void) pthread_mutex_lock(&child_frup->mutex); - /* figure out if this is config/unconfig operation */ - if (child_frup->state == FRU_STATE_CONFIGURED) { - fru_dr_arg.action = HANDLE_CONFIGURE; - fru_dr_arg.data = child_frup; - } else if (child_frup->state == FRU_STATE_UNCONFIGURED) { - fru_dr_arg.action = HANDLE_UNCONFIGURE; - fru_dr_arg.data = child_frup; - } - (void) pthread_mutex_unlock(&child_frup->mutex); - - (void) pthread_mutex_lock(&ev_mutex); - if ((rc = add_to_queue(fru_dr_arg)) != PICL_SUCCESS) { - (void) pthread_mutex_unlock(&ev_mutex); - break; - } - (void) pthread_cond_signal(&ev_cond); - (void) pthread_mutex_unlock(&ev_mutex); - break; - - case HANDLE_INSERT: /* dr_apstate_change (HINT_INSERT) */ - locp = (frutree_locnode_t *)dr_arg->data; - if (locp == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "HANDLE INSERT on %s", locp->name); - /* if the location has child fru, get its information */ - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - /* get the child fru information */ - if (hash_lookup_entry(childh, (void **)&hashptr) == - PICL_SUCCESS) { - child_frup = FRUDATA_PTR(hashptr); - } - } - if (child_frup) { - /* - * if previous state is not empty, it could be a - * hint insert to retry connects - */ - (void) update_loc_state(locp, &state_changed); - if (state_changed) { - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], - loc_state[locp->prev_state], locp->locnodeh, - WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - } - - (void) update_fru_condition(child_frup, &cond_changed); - if (cond_changed == B_TRUE) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[child_frup->cond], - fru_cond[child_frup->prev_cond], - child_frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, - PTREE_POST_PICLEVENT_ERR, - child_frup->name, - PICLEVENT_CONDITION_CHANGE, rc); - } - } - if (!locp->autoconfig_enabled) { - break; - } - - if (locp->state != LOC_STATE_CONNECTED) { - if ((rc = connect_fru(locp)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, CONNECT_FAILED_ERR, - locp->name, rc); - } - } - break; - } - - (void) update_loc_state(locp, &state_changed); - if ((rc = create_fru_node(locp, &child_frup)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, EVENT_NOT_HANDLED, - PICLEVENT_DR_AP_STATE_CHANGE, locp->name, rc); - break; - } - - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], loc_state[locp->prev_state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - if (locp->autoconfig_enabled) { - if ((rc = connect_fru(locp)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, CONNECT_FAILED_ERR, - locp->name, rc); - } - } - break; - - case HANDLE_REMOVE: /* dr_apstate_change (HINT_REMOVE) */ - locp = (frutree_locnode_t *)dr_arg->data; - if (locp == NULL) { - break; - } - FRUTREE_DEBUG1(EVENTS, "HANDLE REMOVE on %s", locp->name); - - if (locp->state == LOC_STATE_EMPTY) { - break; /* discard the spurious event */ - } - - (void) update_loc_state(locp, &state_changed); - /* if the location has child fru, get its information */ - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - /* get the child fru information */ - if (hash_lookup_entry(childh, (void **)&hashptr) == - PICL_SUCCESS) { - frup = FRUDATA_PTR(hashptr); - } - } - if (frup == NULL) { - break; - } - - /* - * frutree need to post this event before handling the - * fru remove, so that other plugins (like frudata) can - * do the cleanup - */ - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], loc_state[locp->prev_state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - if ((rc = handle_fru_remove(frup)) != PICL_SUCCESS) { - FRUTREE_DEBUG2(EVENTS, "SUNW_frutree:Error in handling" - "removal of fru under %s(error=%d)", locp->name, rc); - } - break; - - case POST_COND_EVENT: - frup = (frutree_frunode_t *)dr_arg->data; - if (frup == NULL) { - break; - } - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, rc); - } - default: - break; - } - return (PICL_SUCCESS); -} - -/*ARGSUSED*/ -static void* -dr_thread(void * arg) -{ - ev_queue_t *event = NULL; - - (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - for (;;) { - if (fini_called) - break; - (void) pthread_mutex_lock(&ev_mutex); - while (queue_head == NULL) { - (void) pthread_cond_wait(&ev_cond, &ev_mutex); - } - - event = remove_from_queue(); - (void) pthread_mutex_unlock(&ev_mutex); - while (event) { - (void) handle_dr_event(&event->arg); - free(event); - event = NULL; - (void) pthread_mutex_lock(&ev_mutex); - event = remove_from_queue(); - (void) pthread_mutex_unlock(&ev_mutex); - } - } - return (NULL); -} - -static picl_errno_t -update_port_state(frutree_portnode_t *portp, boolean_t post_ev) -{ - int state, cond; - picl_errno_t rc; - uint64_t ap_status_time; - boolean_t state_changed = B_FALSE; - boolean_t cond_changed = B_FALSE; - frutree_port_type_t port_type; - - if (portp == NULL) { - return (PICL_INVALIDARG); - } - port_type = frutree_get_port_type(portp); - - if (port_type == UNKNOWN_PORT) { - return (PICL_SUCCESS); - } - state = kstat_port_state(port_type, portp->driver, - portp->instance); - cond = kstat_port_cond(port_type, portp->driver, - portp->instance); - switch (state) { - case 0: - /* DOWN */ - if (portp->state != PORT_STATE_DOWN) { - portp->state = PORT_STATE_DOWN; - state_changed = B_TRUE; - } - break; - case 1: - /* UP */ - if (portp->state != PORT_STATE_UP) { - portp->state = PORT_STATE_UP; - state_changed = B_TRUE; - } - break; - default: - /* UNKNOWN */ - if (portp->state != PORT_STATE_UNKNOWN) { - portp->state = PORT_STATE_UNKNOWN; - state_changed = B_TRUE; - } - } - - if (post_ev && state_changed) { - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(portp->portnodeh, - PICL_PROP_STATUS_TIME, &ap_status_time, - sizeof (uint64_t))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_STATUS_TIME, portp->name, rc); - - } - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - port_state[portp->state], NULL, - portp->portnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - portp->name, PICLEVENT_STATE_CHANGE, rc); - } - } - - switch (cond) { - case 0: - if (portp->cond != PORT_COND_OK) { - portp->cond = PORT_COND_OK; - cond_changed = B_TRUE; - } - break; - case 1: - if (portp->cond != PORT_COND_FAILING) { - portp->cond = PORT_COND_FAILING; - cond_changed = B_TRUE; - } - break; - case 2: - if (portp->cond != PORT_COND_FAILED) { - portp->cond = PORT_COND_FAILED; - cond_changed = B_TRUE; - } - break; - case 3: - if (portp->cond != PORT_COND_TESTING) { - portp->cond = PORT_COND_TESTING; - cond_changed = B_TRUE; - } - break; - default: - if (portp->cond != PORT_COND_UNKNOWN) { - portp->cond = PORT_COND_UNKNOWN; - cond_changed = B_TRUE; - } - } - - if (post_ev && cond_changed) { - ap_status_time = (uint64_t)(time(NULL)); - if ((rc = ptree_update_propval_by_name(portp->portnodeh, - PICL_PROP_CONDITION_TIME, &ap_status_time, - sizeof (uint64_t))) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_CONDITION_TIME, portp->name, rc); - } - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - port_cond[portp->cond], NULL, - portp->portnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - portp->name, PICLEVENT_CONDITION_CHANGE, rc); - } - } - return (PICL_SUCCESS); -} - -/* - * monitor port nodes and scsi nodes under a fru - */ -static int -monitor_nodes_under_fru(picl_nodehdl_t nodeh, void *c_args) -{ - picl_errno_t rc; - picl_nodehdl_t parenth; - hashdata_t *hashptr = NULL; - boolean_t state_changed; - frutree_portnode_t *portp = NULL; - frutree_locnode_t *locp = NULL; - frutree_frunode_t *frup = NULL; - char class[PICL_PROPNAMELEN_MAX]; - char slot_type[PICL_PROPNAMELEN_MAX]; - - if (c_args == NULL) { - return (PICL_INVALIDARG); - } - frup = (frutree_frunode_t *)c_args; - - if (ptree_get_propval_by_name(nodeh, PICL_PROP_PARENT, - &parenth, sizeof (parenth)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if (parenth != frup->frunodeh) - return (PICL_WALK_CONTINUE); - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, class, - sizeof (class))) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if ((rc = hash_lookup_entry(nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if (strcmp(class, PICL_CLASS_LOCATION) == 0) { - locp = LOCDATA_PTR(hashptr); - if (ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_SLOT_TYPE, slot_type, - sizeof (slot_type)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - return (PICL_WALK_CONTINUE); - } - (void) update_loc_state(locp, &state_changed); - if (state_changed) { - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], - loc_state[locp->prev_state], - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - } - } else if (strcmp(class, PICL_CLASS_PORT) == 0) { - portp = PORTDATA_PTR(hashptr); - (void) update_port_state(portp, B_TRUE); - } - return (PICL_WALK_CONTINUE); -} - -/* This routine monitors only port node, scsi nodes */ -/* ARGSUSED */ -static int -monitor_fru(picl_nodehdl_t nodeh, void *c_args) -{ - picl_errno_t rc; - picl_nodehdl_t loch; - hashdata_t *hashptr = NULL; - frutree_frunode_t *frup = NULL; - boolean_t state_changed, cond_changed; - char slot_type[PICL_PROPNAMELEN_MAX]; - - if (hash_lookup_entry(nodeh, (void **)&hashptr) != - PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - frup = FRUDATA_PTR(hashptr); - - (void) pthread_mutex_lock(&frup->mutex); - if (frup->dr_in_progress) { - (void) pthread_mutex_unlock(&frup->mutex); - return (PICL_WALK_CONTINUE); - } - frup->busy = B_TRUE; - (void) pthread_mutex_unlock(&frup->mutex); - - /* get the parent information to determine if it is scsi slot or not */ - if (ptree_get_propval_by_name(nodeh, PICL_PROP_PARENT, - &loch, sizeof (loch)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - if (ptree_get_propval_by_name(loch, PICL_PROP_SLOT_TYPE, slot_type, - sizeof (slot_type)) != PICL_SUCCESS) { - return (PICL_WALK_CONTINUE); - } - - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - /* scsi fru */ - (void) update_fru_state(frup, &state_changed); - (void) update_fru_condition(frup, &cond_changed); - if (state_changed) { - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[frup->state], - fru_state[frup->prev_state], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - } - if (cond_changed) { - if ((rc = post_piclevent(PICLEVENT_CONDITION_CHANGE, - fru_cond[frup->cond], fru_cond[frup->prev_cond], - frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_CONDITION_CHANGE, - rc); - } - } - (void) pthread_mutex_lock(&frup->mutex); - frup->busy = B_FALSE; - (void) pthread_cond_signal(&frup->busy_cond_cv); - (void) pthread_mutex_unlock(&frup->mutex); - return (PICL_WALK_CONTINUE); - } - - if (frup->state != FRU_STATE_CONFIGURED) { - (void) pthread_mutex_lock(&frup->mutex); - frup->busy = B_FALSE; - (void) pthread_cond_signal(&frup->busy_cond_cv); - (void) pthread_mutex_unlock(&frup->mutex); - return (PICL_WALK_CONTINUE); - } - - (void) ptree_walk_tree_by_class(chassish, - NULL, (void *)frup, monitor_nodes_under_fru); - - (void) pthread_mutex_lock(&frup->mutex); - frup->busy = B_FALSE; - (void) pthread_cond_signal(&frup->busy_cond_cv); - (void) pthread_mutex_unlock(&frup->mutex); - return (PICL_WALK_CONTINUE); -} - -/* ARGSUSED */ -static void * -monitor_node_status(void *arg) -{ - int err; - timestruc_t to; - struct timeval tp; - - (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - - FRUTREE_DEBUG0(EVENTS, "Monitoring for port status started"); - do - { - (void) pthread_mutex_lock(&monitor_mutex); - (void) gettimeofday(&tp, NULL); - to.tv_sec = tp.tv_sec + frutree_poll_timeout; - to.tv_nsec = tp.tv_usec * 1000; - err = pthread_cond_timedwait(&monitor_cv, &monitor_mutex, &to); - - (void) pthread_mutex_unlock(&monitor_mutex); - if (err == ETIMEDOUT) { /* woke up from sleep */ - (void) ptree_walk_tree_by_class(chassish, - PICL_CLASS_FRU, (void *)NULL, monitor_fru); - } - } while (fini_called == 0); - return (NULL); -} - -picl_errno_t -create_children(frutree_frunode_t *frup, char *scsi_loc, char *bus_addr, - int slot_no, char *slot_type, boolean_t is_cfgadm_ap) -{ - int i = 0; - picl_errno_t rc; - picl_nodehdl_t nodeh; - uint8_t geo_addr = 0; - hashdata_t *datap = NULL; - frutree_locnode_t *locp = NULL; - hashdata_t *hashptr = NULL; - char fru_type[PICL_PROPNAMELEN_MAX]; - frutree_frunode_t *child_frup = NULL; - frutree_callback_data_t fru_arg; - - if (frup == NULL || scsi_loc == NULL || slot_type == NULL) { - return (PICL_FAILURE); - } - - /* check if the location is already created */ - (void) strncpy(fru_arg.node_name, scsi_loc, - sizeof (fru_arg.node_name)); - fru_arg.retnodeh = 0; - if ((rc = ptree_walk_tree_by_class(chassish, PICL_CLASS_LOCATION, - &fru_arg, frutree_get_nodehdl)) == PICL_SUCCESS) { - if (fru_arg.retnodeh != 0) { /* node is already present */ - return (PICL_SUCCESS); - } - } - - /* create the location node and all its properties */ - if ((rc = ptree_create_node(scsi_loc, PICL_CLASS_LOCATION, - &nodeh)) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_SLOT_TYPE, NULLREAD, - NULLWRITE, nodeh, NULL, slot_type)) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_SLOT_TYPE, scsi_loc, rc); - } - - if ((rc = create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_LABEL, NULLREAD, - NULLWRITE, nodeh, NULL, bus_addr)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_LABEL, scsi_loc, rc); - } - - if ((rc = create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_BUS_ADDR, NULLREAD, - NULLWRITE, nodeh, NULL, bus_addr)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_BUS_ADDR, scsi_loc, rc); - } - - geo_addr = slot_no; - if ((rc = create_property(PICL_PTYPE_UNSIGNED_INT, PICL_READ, - sizeof (uint8_t), PICL_PROP_GEO_ADDR, NULLREAD, - NULLWRITE, nodeh, (picl_prophdl_t *)NULL, - &geo_addr)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_GEO_ADDR, scsi_loc, rc); - } - - if ((rc = create_property(PICL_PTYPE_CHARSTRING, PICL_READ, - PICL_PROPNAMELEN_MAX, PICL_PROP_DEVFS_PATH, NULLREAD, - NULLWRITE, nodeh, NULL, frup->fru_path)) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, PTREE_CREATE_PROP_FAILED, - PICL_PROP_DEVFS_PATH, scsi_loc, rc); - } - - if ((rc = ptree_add_node(frup->frunodeh, nodeh)) != PICL_SUCCESS) { - (void) ptree_destroy_node(nodeh); - return (rc); - } - - /* save the node in hashtable */ - if ((rc = make_loc_data(scsi_loc, &datap)) != PICL_SUCCESS) { - return (rc); - } - locp = LOCDATA_PTR(datap); - locp->locnodeh = nodeh; - /* save data in hash table */ - (void) hash_add_entry(nodeh, (void *)datap); - - if ((rc = hash_lookup_entry(nodeh, (void **)&hashptr)) != - PICL_SUCCESS) { - return (rc); - } - locp = LOCDATA_PTR(hashptr); - - if (is_cfgadm_ap != B_TRUE) { /* device found in libdevinfo */ - locp->state_mgr = STATIC_LOC; - locp->state = LOC_STATE_CONNECTED; - } - - if ((rc = location_init(locp)) != PICL_SUCCESS) { - return (rc); - } - - /* if location is empty, done */ - if (locp->state == LOC_STATE_EMPTY) { - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - PICLEVENTARGVAL_EMPTY, NULL, - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - return (PICL_SUCCESS); - } - - /* create the fru node and initilize it */ - if ((rc = create_fru_node(locp, &child_frup)) != PICL_SUCCESS) { - return (rc); - } - - /* post picl event on location (frudata is consumer for these events) */ - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - loc_state[locp->state], PICLEVENTARGVAL_EMPTY, - locp->locnodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - locp->name, PICLEVENT_STATE_CHANGE, rc); - } - - if (child_frup->state_mgr == STATIC_LOC) { - /* derive the fru_type from name */ - while (i < strlen(scsi_loc)) { - if (isdigit(scsi_loc[i])) { - (void) strncpy(fru_type, scsi_loc, i); - fru_type[i] = '\0'; - break; - } - ++i; - } - if ((rc = ptree_update_propval_by_name(child_frup->frunodeh, - PICL_PROP_FRU_TYPE, fru_type, sizeof (fru_type))) != - PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_UPDATE_PROP_ERR, - PICL_PROP_FRU_TYPE, child_frup->name, rc); - } - } - - /* post picl state change event on fru state */ - if ((rc = post_piclevent(PICLEVENT_STATE_CHANGE, - fru_state[child_frup->state], PICLEVENTARGVAL_UNKNOWN, - child_frup->frunodeh, WAIT)) != PICL_SUCCESS) { - FRUTREE_DEBUG3(EVENTS, PTREE_POST_PICLEVENT_ERR, - frup->name, PICLEVENT_STATE_CHANGE, rc); - } - /* for scsi FRUs we need not probe further */ - return (PICL_SUCCESS); -} - -/* - * recursive search in the subtree - */ -/*ARGSUSED*/ -boolean_t -is_location_present_in_subtree(frutree_frunode_t *frup, const char *name, - const char *path) -{ - frutree_callback_data_t fru_arg; - - (void) strncpy(fru_arg.node_name, name, - sizeof (fru_arg.node_name)); - fru_arg.retnodeh = 0; - if (ptree_walk_tree_by_class(frup->frunodeh, PICL_CLASS_LOCATION, - &fru_arg, frutree_get_nodehdl) == PICL_SUCCESS) { - if (fru_arg.retnodeh != 0) { /* node is already present */ - return (B_TRUE); - } - } - return (B_FALSE); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclfrutree.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclfrutree.h deleted file mode 100644 index b2c4b47829..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclfrutree.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PICLFRUTREE_H -#define _PICLFRUTREE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/param.h> -#include <syslog.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - NONE = 0x0, - FRUTREE_INIT = 0x1, - EVENTS = 0x2, - HASHTABLE = 0x4, - PERF_DATA = 0x8, - EV_COMPLETION = 0x10, - PRINT_ALL = 0xFF -} frutree_debug_t; - -#define FRUTREE_DEBUG0(lvl, fmt) \ - if (lvl & frutree_debug) { \ - syslog(LOG_DEBUG, fmt); \ - } -#define FRUTREE_DEBUG1(lvl, fmt, d1) \ - if (lvl & frutree_debug) { \ - syslog(LOG_DEBUG, fmt, d1); \ - } -#define FRUTREE_DEBUG2(lvl, fmt, d1, d2) \ - if (lvl & frutree_debug) { \ - syslog(LOG_DEBUG, fmt, d1, d2); \ - } -#define FRUTREE_DEBUG3(lvl, fmt, d1, d2, d3) \ - if (lvl & frutree_debug) { \ - syslog(LOG_DEBUG, fmt, d1, d2, d3); \ - } -#define FRUTREE_DEBUG4(lvl, fmt, d1, d2, d3, d4) \ - if (lvl & frutree_debug) {\ - syslog(LOG_DEBUG, fmt, d1, d2, d3, d4); \ - } - -/* environment variables to tune the variables */ -#define FRUTREE_DEBUG "SUNW_FRUTREE_DEBUG" -#define FRUTREE_POLL_TIMEOUT "SUNW_FRUTREE_POLL_TIMEOUT" -#define FRUTREE_DRWAIT "SUNW_FRUTREE_DRWAIT_TIME" - -/* PICL defines */ -#define PICL_NODE_CHASSIS "chassis" - -/* Sanibel specific defines */ -#define SANIBEL_PICLNODE_CPU "CPU" -#define SANIBEL_PICLNODE_PARALLEL "ecpp" -#define SANIBEL_NETWORK_LABEL "ENET" -#define SANIBEL_CPCISLOT_TYPE "cpci" -#define SANIBEL_NETWORK_PORT "network" -#define SANIBEL_SERIAL_PORT "serial" -#define SANIBEL_PARALLEL_PORT "parallel" -#define SANIBEL_SCSI_SLOT "scsi" -#define SANIBEL_IDE_SLOT "ide" -#define SANIBEL_UNKNOWN_SLOT "unknown" -#define DEVICE_CLASS_SCSI "scsi" -#define DEVICE_CLASS_IDE "dada" - -#define MAX_BUFSIZE 512 -#define SUPER_USER 0 -#define DEVFSADM_CMD "/usr/sbin/devfsadm -i" -#define TEMP_DIR "/var/tmp/" -#define PROBE_FILE "probed" -#define NULLREAD (int (*)(ptree_rarg_t *, void *))0 -#define NULLWRITE (int (*)(ptree_warg_t *, const void *))0 - -#define PTREE_CREATE_PROP_FAILED \ - gettext("SUNW_frutree:Error in creating property:%s, "\ - "under %s(error=%d)") -#define PTREE_POST_PICLEVENT_ERR \ - gettext("SUNW_frutree:Error in posting picl event %s(%s)(error=%d)") -#define PTREE_EVENT_HANDLING_ERR \ - gettext("SUNW_frutree:Error in handling %s event on %s(error=%d)") -#define GET_LOC_STATE_ERR \ - gettext("SUNW_frutree:Error in getting state info for %s"\ - "(location)(error=%d)") -#define GET_FRU_STATE_ERR \ - gettext("SUNW_frutree:Error in getting state for %s(fru)(error=%d)") -#define GET_FRU_COND_ERR \ - gettext("SUNW_frutree:Error in getting condition for %s(fru)(error=%d)") -#define CONNECT_FAILED_ERR \ - gettext("SUNW_frutree:Connect operation on %s failed(error=%d)") -#define CONFIGURE_FAILED_ERR \ - gettext("SUNW_frutree:Configure operation on %s failed(error=%d)") -#define UNCONFIG_FAILED_ERR \ - gettext("SUNW_frutree:Unconfigure operation on %s failed(error=%d)") -#define DISCONNECT_FAILED_ERR \ - gettext("SUNW_frutree:Disconnect operation on %s failed(error=%d)") -#define PROBE_FRU_ERR \ - gettext("SUNW_frutree:Error in probing fru under %s(error=%d)") -#define PTREE_UPDATE_PROP_ERR \ - gettext("SUNW_frutree:Error updating %s of %s(error=%d)") -#define PTREE_GET_PROPVAL_ERR \ - gettext("SUNW_frutree:Error in getting value of %s(%s)(error=%d)") -#define PTREE_DEVICE_CREATE_ERR \ - gettext("SUNW_frutree:Error in creating nodes under %s(error=%d)") -#define EVENT_NOT_HANDLED \ - gettext("SUNW_frutree:Error in handling %s on %s(error=%d)") -#define ERROR_REINIT \ - gettext("SUNW_frutree:Error in reinitializing %s") - -typedef enum { - NO_WAIT = 0, - WAIT -} frutree_wait_t; - -typedef uint8_t frutree_frustate_t; -typedef uint8_t frutree_frucond_t; -typedef uint8_t frutree_locstate_t; -typedef uint8_t frutree_port_type_t; -typedef uint8_t frutree_datatype_t; -typedef uint8_t frutree_loctype_t; - -/* valid fru states */ -#define FRU_STATE_UNKNOWN 0x0 -#define FRU_STATE_CONFIGURED 0x1 -#define FRU_STATE_UNCONFIGURED 0x2 -#define FRU_STATE_CONFIGURING 0x3 -#define FRU_STATE_UNCONFIGURING 0x4 - -/* valid fru condition */ -#define FRU_COND_UNKNOWN 0x0 -#define FRU_COND_FAILED 0x1 -#define FRU_COND_FAILING 0x2 -#define FRU_COND_OK 0x3 -#define FRU_COND_TESTING 0x4 - -/* port states */ -#define PORT_STATE_DOWN 0x0 -#define PORT_STATE_UP 0x1 -#define PORT_STATE_UNKNOWN 0x2 - -/* port condition */ -#define PORT_COND_OK 0x0 -#define PORT_COND_FAILING 0x1 -#define PORT_COND_FAILED 0x2 -#define PORT_COND_TESTING 0x3 -#define PORT_COND_UNKNOWN 0x4 - -/* port types */ -#define NETWORK_PORT 0x0 -#define SERIAL_PORT 0x1 -#define PARALLEL_PORT 0x2 -#define UNKNOWN_PORT 0x4 - -/* location states */ -#define LOC_STATE_UNKNOWN 0x0 -#define LOC_STATE_EMPTY 0x1 -#define LOC_STATE_CONNECTED 0x2 -#define LOC_STATE_DISCONNECTED 0x3 -#define LOC_STATE_CONNECTING 0x4 -#define LOC_STATE_DISCONNECTING 0x5 - -/* types of nodes */ -#define LOC_TYPE 0x0 -#define FRU_TYPE 0x1 -#define PORT_TYPE 0x2 - -/* location managers */ -#define CFGADM_AP 0x0 /* managed based on cfgadm data */ -#define PLUGIN_PVT 0x1 /* managed by other plugin */ -#define STATIC_LOC 0x2 /* managed based on libdevinfo */ -#define UNKNOWN 0x3 /* unknown */ - -typedef struct conf_cache { - char buf[MAX_BUFSIZE]; - struct conf_cache *next; -} frutree_cache_t; - -typedef struct { - picl_nodehdl_t nodeh; - picl_prophdl_t device_tblhdl; - picl_prophdl_t env_tblhdl; - frutree_cache_t *first; - frutree_cache_t *last; - boolean_t create_cache; -} frutree_device_args_t; - -typedef struct loc_node frutree_locnode_t; -typedef struct fru_node frutree_frunode_t; -typedef struct port_node frutree_portnode_t; - -/* information on a particular location */ -struct loc_node { - picl_nodehdl_t locnodeh; /* handle of the loc node itself */ - char *name; - boolean_t cpu_node; - boolean_t dr_in_progress; - boolean_t autoconfig_enabled; - frutree_loctype_t state_mgr; /* state manager */ - frutree_locstate_t state; /* present state */ - frutree_locstate_t prev_state; /* previous state */ - pthread_mutex_t mutex; - pthread_cond_t cond_cv; -}; - -/* information on a particular port */ -struct port_node { - picl_nodehdl_t portnodeh; - char *name; - int state; - int cond; - uint8_t instance; - char driver[MAXPATHLEN]; -}; - -/* information on a particular fru */ -struct fru_node { - /* variable data */ - picl_nodehdl_t frunodeh; - char *name; - frutree_frustate_t state; - frutree_frustate_t prev_state; - frutree_frucond_t cond; - frutree_frucond_t prev_cond; - boolean_t cpu_node; - boolean_t autoconfig_enabled; - boolean_t dr_in_progress; - boolean_t busy; - frutree_loctype_t state_mgr; - char fru_path[MAXPATHLEN]; - pthread_mutex_t mutex; - pthread_cond_t cond_cv; - pthread_cond_t busy_cond_cv; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _PICLFRUTREE_H */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclkstat.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclkstat.c deleted file mode 100644 index 60b6b99efa..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclkstat.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Implementation to get PORT nodes state and condition information - */ -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <strings.h> -#include <fcntl.h> -#include <unistd.h> -#include <stropts.h> -#include <locale.h> -#include <syslog.h> -#include <sys/types.h> -#include <sys/termios.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <kstat.h> -#include <signal.h> -#include <assert.h> -#include <config_admin.h> - -#include <picl.h> -#include "piclfrutree.h" - -#define LINK_UP "link_up" -#define DUPLEX "duplex" -#define IF_SPEED "ifspeed" -#define IERRORS "ierrors" -#define IPACKETS "ipackets" -#define OERRORS "oerrors" -#define OPACKETS "opackets" -#define NOCANPUT "nocanput" -#define RUNT_ERRORS "runt_errors" -#define COLLISIONS "collisions" - -typedef int (*funcp)(kstat_ctl_t *, char *, int); - -static kstat_named_t *kstat_name_lookup(kstat_ctl_t *, char *, int, char *); -static int kstat_network_port_state(kstat_ctl_t *kc, char *, int); -static int kstat_network_port_cond(kstat_ctl_t *kc, char *, int); -static int serial_port_state(kstat_ctl_t *, char *, int); -static int serial_port_cond(kstat_ctl_t *kc, char *, int); -static int parallel_port_state(kstat_ctl_t *, char *, int); -static int parallel_port_cond(kstat_ctl_t *kc, char *, int); -static void sig_alarm_handler(int); - -static funcp port_state[] = { - kstat_network_port_state, - serial_port_state, - parallel_port_state -}; - -static funcp port_cond[] = { - kstat_network_port_cond, - serial_port_cond, - parallel_port_cond -}; - -/* - * kstat_port_state: returns ethernet, or serial, or parallel port status - * 1 = up, 0 = down, anything else = unknown - */ -int -kstat_port_state(frutree_port_type_t port_type, char *driver_name, - int driver_instance) -{ - int rc = -1; - kstat_ctl_t *kc = NULL; - - switch (port_type) { - case NETWORK_PORT: - case SERIAL_PORT: - case PARALLEL_PORT: - if ((kc = kstat_open()) == NULL) { - return (-1); - } - rc = port_state[port_type](kc, driver_name, driver_instance); - kstat_close(kc); - return (rc); - default: - return (-1); - } -} - -/* - * kstat_port_cond: returns ethernet, or serial, or parallel port condition - */ -int -kstat_port_cond(frutree_port_type_t port_type, char *driver_name, - int driver_instance) -{ - int rc = -1; - kstat_ctl_t *kc = NULL; - switch (port_type) { - case NETWORK_PORT: - case SERIAL_PORT: - case PARALLEL_PORT: - if ((kc = kstat_open()) == NULL) { - return (-1); - } - rc = port_cond[port_type](kc, driver_name, driver_instance); - kstat_close(kc); - return (rc); - default: - return (-1); - } -} - -static kstat_named_t * -kstat_name_lookup(kstat_ctl_t *kc, char *ks_module, int ks_instance, char *name) -{ - kstat_t *ksp; - - assert(kc); - assert(ks_module); - assert(name); - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, ks_module) == 0 && - ksp->ks_instance == ks_instance && - ksp->ks_type == KSTAT_TYPE_NAMED && - kstat_read(kc, ksp, NULL) != -1 && - kstat_data_lookup(ksp, name)) { - - ksp = kstat_lookup(kc, ks_module, ks_instance, - ksp->ks_name); - if (!ksp) - return (NULL); - if (kstat_read(kc, ksp, NULL) == -1) - return (NULL); - return ((kstat_named_t *)kstat_data_lookup(ksp, name)); - } - } - return (NULL); -} - -/* - * kstat_network_port_state: returns kstat info of a network port - * 1 = up, 0 = down, anything else = unknown - */ -static int -kstat_network_port_state(kstat_ctl_t *kc, char *ks_module, int ks_instance) -{ - kstat_named_t *port_datap = NULL; - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - LINK_UP)) == NULL) { - return (-1); - } - if (port_datap == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - if (port_datap->value.ui32 == 1) { - return (1); - } else if (port_datap->value.ui32 == 0) { - return (0); - } else { - return (-1); - } - } else { - if (port_datap->value.ui64 == 1) { - return (1); - } else if (port_datap->value.ui64 == 0) { - return (0); - } else { - return (-1); - } - } -} - -/* - * kstat_network_port_cond: returns kstat info of a network port - * 0 = OK, 1 = FAILING, 2 = FAILED, 3 = TESTING, -1 = unknown - */ -static int -kstat_network_port_cond(kstat_ctl_t *kc, char *ks_module, int ks_instance) -{ - kstat_named_t *port_datap = NULL; - uint64_t collisions, runt, link_up, link_duplex; - uint64_t ifspeed, ierrors, ipackets, oerrors, opackets; - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - LINK_UP)) == NULL) { - return (-1); - } - - if (port_datap->data_type == KSTAT_DATA_UINT32) { - link_up = port_datap->value.ui32; - } else { - link_up = port_datap->value.ui64; - } - if (link_up == 0) { - return (2); - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - DUPLEX)) == NULL) { - return (-1); - } - - if (port_datap->data_type == KSTAT_DATA_UINT32) { - link_duplex = port_datap->value.ui32; - } else { - link_duplex = port_datap->value.ui64; - } - if (link_duplex == 0) { - return (2); - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - IF_SPEED)) == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - ifspeed = port_datap->value.ui32; - } else { - ifspeed = port_datap->value.ui64; - } - if (ifspeed == 0) { - return (2); - } - - /* check for FAILING conditions */ - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - IERRORS)) == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - ierrors = port_datap->value.ui32; - } else { - ierrors = port_datap->value.ui64; - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - IPACKETS)) == NULL) { - return (-1); - } - - if (port_datap->data_type == KSTAT_DATA_UINT32) { - ipackets = port_datap->value.ui32; - } else { - ipackets = port_datap->value.ui64; - } - if (ierrors > ipackets/10) { - return (1); - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - OERRORS)) == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - oerrors = port_datap->value.ui32; - } else { - oerrors = port_datap->value.ui64; - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - OPACKETS)) == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - opackets = port_datap->value.ui32; - } else { - opackets = port_datap->value.ui64; - } - if (oerrors > opackets/10) { - return (1); - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - RUNT_ERRORS)) == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - runt = port_datap->value.ui32; - } else { - runt = port_datap->value.ui64; - } - if (runt > ipackets/10) { - return (1); - } - - if ((port_datap = kstat_name_lookup(kc, ks_module, ks_instance, - COLLISIONS)) == NULL) { - return (-1); - } - if (port_datap->data_type == KSTAT_DATA_UINT32) { - collisions = port_datap->value.ui32; - } else { - collisions = port_datap->value.ui64; - } - if (collisions > (opackets+ipackets)/30) { - return (1); - } - return (0); -} - -/* - * serial_port_state: returns status a serial port - * 1 = up, 0 = down, anything else = unknown - */ - -/* ARGSUSED */ -static int -serial_port_state(kstat_ctl_t *kc, char *driver, int instance) -{ - int fd; - char device[20]; - struct termios flags; - struct sigaction old_sa, new_sa; - - (void) memset(&old_sa, 0, sizeof (old_sa)); - (void) memset(&new_sa, 0, sizeof (new_sa)); - new_sa.sa_handler = sig_alarm_handler; - (void) sigaction(SIGALRM, &new_sa, &old_sa); - (void) alarm(1); - - (void) snprintf(device, sizeof (device), "/dev/tty%c", instance+'a'); - fd = open(device, O_RDONLY|O_NDELAY|O_NONBLOCK|O_NOCTTY); - - /* Restore sig action flags */ - (void) sigaction(SIGALRM, &old_sa, (struct sigaction *)0); - /* Disable alarm */ - (void) alarm(0); - - if (fd == -1) { - return (-1); - } - - if (isatty(fd) == 0) { - (void) close(fd); - return (-1); - } - (void) memset(&flags, 0, sizeof (flags)); - if (ioctl(fd, TCGETS, &flags) != 0) { - (void) close(fd); - return (-1); - } - (void) close(fd); - return ((flags.c_cflag & TIOCM_LE) ? 1 : 0); -} - -/* ARGSUSED */ -static void -sig_alarm_handler(int signo) -{ -} - -/* - * serial_port_cond: returns status of a serial port - * 0 = OK, 1 = FAILING, 2 = FAILED, 3 = TESTING, anything else = UNKNOWN - */ -static int -serial_port_cond(kstat_ctl_t *kc, char *driver, int instance) -{ - switch (serial_port_state(kc, driver, instance)) { - case 1: - return (0); - default: - return (-1); - } -} - -/* - * parallel_port_state: returns kstat info of a serial port - * 1 = up, 0 = down, anything else = unknown - */ -static int -parallel_port_state(kstat_ctl_t *kc, char *ks_module, int ks_instance) -{ - kstat_t *ksp = NULL; - kstat_named_t *port_datap = NULL; - char *data_lookup; - char ks_name[20]; - - (void) snprintf(ks_name, sizeof (ks_name), "%s%d", ks_module, - ks_instance); - if ((ksp = kstat_lookup(kc, ks_module, ks_instance, ks_name)) == NULL) { - return (-1); - } - if (kstat_read(kc, ksp, NULL) == -1) { - return (-1); - } - data_lookup = ""; - port_datap = (kstat_named_t *)kstat_data_lookup(ksp, data_lookup); - if (port_datap == NULL) { - return (-1); - } - return (-1); -} - -/* - * parallel_port_cond: returns kstat info of a serial port - * 1 = up, 0 = down, anything else = unknown - */ -static int -parallel_port_cond(kstat_ctl_t *kc, char *ks_module, int ks_instance) -{ - return (parallel_port_state(kc, ks_module, ks_instance)); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/picllibdevinfo.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/picllibdevinfo.c deleted file mode 100644 index 091e72383e..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/picllibdevinfo.c +++ /dev/null @@ -1,853 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Implementation to interact with libdevinfo to find port nodes, - * and information regarding each node (fru, port, location). - */ - -#include <stdio.h> -#include <libdevinfo.h> -#include <picl.h> -#include <picltree.h> -#include <strings.h> -#include <stdlib.h> -#include <config_admin.h> -#include <sys/types.h> -#include <sys/obpdefs.h> -#include <sys/pci.h> -#include <picldefs.h> -#include "piclfrutree.h" - -#include <syslog.h> - -static di_prom_handle_t prom_handle = DI_PROM_HANDLE_NIL; -extern int frutree_debug; - -typedef struct { - di_node_t rnode; - char bus_addr[PICL_PROPNAMELEN_MAX]; - char path[PICL_PROPNAMELEN_MAX]; - void *arg; - picl_errno_t retval; -} frutree_devinfo_t; - -typedef struct p_info { - frutree_port_type_t type; - int geo_addr; - int instance; - char drv_name[20]; - char bus_addr[20]; - char devfs_path[MAXPATHLEN]; - struct p_info *next; -}port_info_t; - -typedef struct { - port_info_t *first; - port_info_t *last; - int n_serial; - int n_parallel; - int n_network; -} plist_t; - -static void -free_list(plist_t *listptr) -{ - port_info_t *tmp; - port_info_t *nextptr; - if (listptr == NULL) - return; - - nextptr = listptr->first; - while (nextptr != NULL) { - tmp = nextptr; - nextptr = nextptr->next; - free(tmp); - } -} - -/* (callback function for qsort) compare the bus_addr */ -static int -compare(const void *a, const void *b) -{ - port_info_t *pinfo1, *pinfo2; - port_info_t **ptr2pinfo1, **ptr2pinfo2; - - ptr2pinfo1 = (port_info_t **)a; - ptr2pinfo2 = (port_info_t **)b; - - pinfo1 = (port_info_t *)*ptr2pinfo1; - pinfo2 = (port_info_t *)*ptr2pinfo2; - return (strcmp(pinfo1->bus_addr, pinfo2->bus_addr)); -} - -/* - * assigns GeoAddr property for ports based on bus-addr - */ -static picl_errno_t -assign_geo_addr(plist_t *list, frutree_port_type_t type) -{ - - int i = 0; - port_info_t **port_info = NULL; - port_info_t *nextptr = NULL; - int num_ports = 0; - - if (list == NULL) { - return (PICL_FAILURE); - } - - if (list->first == NULL) { - return (PICL_SUCCESS); - } - - switch (type) { - case SERIAL_PORT: - if (list->n_serial == 0) { - return (PICL_SUCCESS); - } - num_ports = list->n_serial; - break; - - case PARALLEL_PORT: - if (list->n_parallel == 0) { - return (PICL_SUCCESS); - } - num_ports = list->n_parallel; - break; - - case NETWORK_PORT: - if (list->n_network == 0) { - return (PICL_SUCCESS); - } - num_ports = list->n_network; - break; - - } - - port_info = (port_info_t **)malloc( - sizeof (port_info_t *) * num_ports); - if (port_info == NULL) { - return (PICL_NOSPACE); - } - - /* traverse thru list and look for ports of given type */ - nextptr = list->first; - while (nextptr != NULL) { - if (nextptr->type != type) { - nextptr = nextptr->next; - continue; - } - port_info[i] = nextptr; - nextptr = nextptr->next; - i++; - } - - /* sort the nodes to assign geo_address */ - (void) qsort((void *)port_info, num_ports, - sizeof (port_info_t *), compare); - for (i = 0; i < num_ports; i++) { - if (port_info[i] != NULL) { - port_info[i]->geo_addr = i + 1; - } - } - free(port_info); - return (PICL_SUCCESS); -} - -static picl_errno_t -create_port_config_info(plist_t *list, frutree_device_args_t *devp) -{ - port_info_t *port_info = NULL; - frutree_cache_t *cachep = NULL; - char port_type[PICL_PROPNAMELEN_MAX]; - char label[PICL_PROPNAMELEN_MAX]; - - if (list == NULL) { - return (PICL_FAILURE); - } - - port_info = list->first; - while (port_info != NULL) { - - cachep = (frutree_cache_t *)malloc(sizeof (frutree_cache_t)); - if (cachep == NULL) { - return (PICL_NOSPACE); - } - - switch (port_info->type) { - case NETWORK_PORT: - (void) strncpy(label, SANIBEL_NETWORK_LABEL, - sizeof (label)); - (void) strncpy(port_type, SANIBEL_NETWORK_PORT, - sizeof (port_type)); - break; - case PARALLEL_PORT: - (void) strncpy(label, SANIBEL_PARALLEL_PORT, - sizeof (label)); - (void) strncpy(port_type, SANIBEL_PARALLEL_PORT, - sizeof (port_type)); - break; - case SERIAL_PORT: - (void) strncpy(label, SANIBEL_SERIAL_PORT, - sizeof (label)); - (void) strncpy(port_type, SANIBEL_SERIAL_PORT, - sizeof (port_type)); - break; - default: - port_info = port_info->next; - } - cachep->buf[0] = '\0'; - cachep->next = NULL; - (void) snprintf(cachep->buf, - sizeof (cachep->buf), - "\n%s %s%d %s\n" - "\t%s %s %s %s 0 \"%s %d\"\n" - "\t%s %s %s %s 0 \"%s\"\n" - "\t%s %s %s %s 1 %d\n" - "\t%s %s %s %s 0 \"%s\"\n" - "\t%s %s %s %s 0 \"%s\"\n" - "%s\n", - "NODE", port_info->drv_name, port_info->instance, - PICL_CLASS_PORT, - "PROP", PICL_PROP_LABEL, "string", "r", - label, (port_info->geo_addr -1), - "PROP", PICL_PROP_BUS_ADDR, "string", - "r", port_info->bus_addr, - "PROP", PICL_PROP_GEO_ADDR, "uint", - "r", port_info->geo_addr, - "PROP", PICL_PROP_PORT_TYPE, "string", - "r", port_type, - "PROP", PICL_PROP_DEVFS_PATH, "string", - "r", port_info->devfs_path, - "ENDNODE"); - - /* add to the cache */ - if (devp->first == NULL) { /* 1st node */ - devp->first = cachep; - devp->last = NULL; - } else if (devp->last != NULL) { /* last node */ - devp->last->next = cachep; - devp->last = cachep; - } else { /* 2nd node */ - devp->first->next = cachep; - devp->last = cachep; - } - port_info = port_info->next; /* advance to next node */ - } - return (PICL_SUCCESS); -} - -/*ARGSUSED*/ -static int -load_driver(di_node_t node, void *arg) -{ - char *drv_name = NULL; - char cmd[MAXPATHLEN]; - - if (di_node_state(node) >= DS_ATTACHED) { - return (DI_WALK_CONTINUE); - } - drv_name = di_driver_name(node); - if (drv_name == NULL) { - return (DI_WALK_CONTINUE); - } - - (void) snprintf(cmd, sizeof (cmd), "%s %s", - DEVFSADM_CMD, drv_name); - (void) pclose(popen(cmd, "r")); - return (DI_WALK_CONTINUE); -} - -static picl_errno_t -load_drivers(char *path) -{ - di_node_t rnode; - if (path == NULL) { - return (PICL_INVALIDARG); - } - - rnode = di_init(path, DINFOSUBTREE|DINFOMINOR); - if (rnode == DI_NODE_NIL) { - return (PICL_FAILURE); - } - - if (di_walk_node(rnode, DI_WALK_CLDFIRST, NULL, load_driver) != 0) { - di_fini(rnode); - return (PICL_FAILURE); - } - - di_fini(rnode); - return (PICL_SUCCESS); -} - -/* - * probe for port nodes - */ -static int -probe_tree(di_node_t node, void *arg) -{ - char *nodetype = NULL; - char *devfs_path = NULL; - char *bus_addr = NULL; - char *drv_name = NULL; - plist_t *listptr = NULL; - port_info_t *port_info = NULL; - frutree_port_type_t port_type = UNKNOWN_PORT; - di_minor_t minor = DI_MINOR_NIL; - - if (arg == NULL) { - return (DI_WALK_TERMINATE); - } - listptr = (plist_t *)arg; - - while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { - nodetype = di_minor_nodetype(minor); - if (nodetype == NULL) { - continue; - } - - if (strcmp(nodetype, DDI_NT_NET) == 0) { - port_type = NETWORK_PORT; - } else if (strcmp(nodetype, DDI_NT_PARALLEL) == 0) { - port_type = PARALLEL_PORT; - } else if ((strcmp(nodetype, DDI_NT_SERIAL) == 0) || - (strcmp(nodetype, DDI_NT_SERIAL_MB) == 0) || - (strcmp(nodetype, DDI_NT_SERIAL_DO) == 0) || - (strcmp(nodetype, DDI_NT_SERIAL_MB_DO) == 0)) { - port_type = SERIAL_PORT; - } else { - continue; - } - - /* found port node */ - devfs_path = di_devfs_path(node); - if (devfs_path == NULL) { - continue; - } - - bus_addr = di_bus_addr(node); - drv_name = di_driver_name(node); - - if ((bus_addr == NULL) || (drv_name == NULL)) { - di_devfs_path_free(devfs_path); - continue; - } - - port_info = malloc(sizeof (port_info_t)); - if (port_info == NULL) { - di_devfs_path_free(devfs_path); - return (PICL_NOSPACE); - } - - (void) strncpy(port_info->devfs_path, devfs_path, - sizeof (port_info->devfs_path)); - (void) strncpy(port_info->bus_addr, bus_addr, - sizeof (port_info->bus_addr)); - (void) strncpy(port_info->drv_name, drv_name, - sizeof (port_info->drv_name)); - port_info->type = port_type; - port_info->instance = di_instance(node); - port_info->geo_addr = -1; - port_info->next = NULL; - - switch (port_type) { - case NETWORK_PORT: - listptr->n_network++; - break; - case SERIAL_PORT: - listptr->n_serial++; - break; - case PARALLEL_PORT: - listptr->n_parallel++; - break; - } - - /* add to the list */ - if (listptr->first == NULL) { /* 1st node */ - listptr->first = port_info; - listptr->last = NULL; - } else if (listptr->last != NULL) { /* last node */ - listptr->last->next = port_info; - listptr->last = port_info; - } else { /* 2nd node */ - listptr->first->next = port_info; - listptr->last = port_info; - } - di_devfs_path_free(devfs_path); - return (DI_WALK_CONTINUE); - } - return (DI_WALK_CONTINUE); -} - -/* This routine probes libdevinfo for port nodes */ -picl_errno_t -probe_libdevinfo(frutree_frunode_t *frup, frutree_device_args_t ** device, - boolean_t load_drv) -{ - di_node_t rnode; - picl_errno_t rc; - plist_t list; - - if (frup == NULL) { - return (PICL_FAILURE); - } - FRUTREE_DEBUG1(EVENTS, "loading drivers for %s", frup->name); - - if (load_drv == B_TRUE) { - if ((rc = load_drivers(frup->fru_path)) != PICL_SUCCESS) { - return (rc); - } - } - FRUTREE_DEBUG1(EVENTS, "done with loading drivers for %s", frup->name); - - rnode = di_init(frup->fru_path, DINFOSUBTREE|DINFOMINOR); - if (rnode == DI_NODE_NIL) { - return (PICL_FAILURE); - } - - list.first = NULL; - list.last = NULL; - list.n_network = 0; - list.n_serial = 0; - list.n_parallel = 0; - - if (di_walk_node(rnode, DI_WALK_CLDFIRST, &list, probe_tree) != 0) { - di_fini(rnode); - free_list(&list); - return (PICL_FAILURE); - } - - if (list.n_serial > 0) - if ((rc = assign_geo_addr(&list, SERIAL_PORT)) != PICL_SUCCESS) { - di_fini(rnode); - free_list(&list); - return (rc); - } - - if (list.n_network > 0) - if ((rc = assign_geo_addr(&list, NETWORK_PORT)) != PICL_SUCCESS) { - di_fini(rnode); - free_list(&list); - return (rc); - } - - if (list.n_parallel > 0) - if ((rc = assign_geo_addr(&list, PARALLEL_PORT)) != PICL_SUCCESS) { - di_fini(rnode); - free_list(&list); - return (rc); - } - - if ((rc = create_port_config_info(&list, *device)) != PICL_SUCCESS) { - di_fini(rnode); - free_list(&list); - return (rc); - } - - di_fini(rnode); - free_list(&list); - FRUTREE_DEBUG1(EVENTS, "done with probing %s", frup->name); - return (PICL_SUCCESS); -} - -static int -get_reg_dev(di_node_t node) -{ - int *reg = NULL; - if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, OBP_REG, ®) < 0) { - if (di_prom_prop_lookup_ints(prom_handle, node, OBP_REG, - ®) < 0) { - return (-1); - } - return (PCI_REG_DEV_G(reg[0])); - } - return (PCI_REG_DEV_G(reg[0])); -} - -static int -walk_tree(di_node_t node, void *arg) -{ - char *path = NULL; - char *bus_addr = NULL; - char *char_di_bus_addr = NULL; - int busaddr = 0; - int di_busaddr = 0; - char *node_name = NULL; - frutree_devinfo_t *devinfo; - frutree_frunode_t *frup = NULL; - - devinfo = *(frutree_devinfo_t **)arg; - frup = (frutree_frunode_t *)devinfo->arg; - if (frup == NULL) { - return (DI_WALK_TERMINATE); - } - - if (devinfo->rnode == node) { /* skip the root node */ - return (DI_WALK_CONTINUE); - } - bus_addr = devinfo->bus_addr; - - char_di_bus_addr = di_bus_addr(node); - if (char_di_bus_addr == NULL) { - /* - * look for reg property - * This applies to only cPCI devices - */ - if (strstr(bus_addr, ",") != NULL) { - /* bus addr is of type 1,0 */ - /* we dont handle this case yet */ - return (DI_WALK_PRUNECHILD); - } - di_busaddr = get_reg_dev(node); - if (di_busaddr == -1) { - /* reg prop not found */ - return (DI_WALK_PRUNECHILD); - } - - /* check if the bus addresses are same */ - errno = 0; - busaddr = strtol(bus_addr, (char **)NULL, 16); - if (errno != 0) { - return (DI_WALK_TERMINATE); - } - if (di_busaddr != busaddr) { - return (DI_WALK_PRUNECHILD); - } - - /* build the fru path name */ - /* parent_path/nodename@bus_addr */ - node_name = di_node_name(node); - if (node_name == NULL) { - return (DI_WALK_TERMINATE); - } - (void) snprintf(devinfo->path, sizeof (devinfo->path), - "%s/%s@%s", frup->fru_path, node_name, bus_addr); - return (DI_WALK_TERMINATE); - } - - if (strstr(bus_addr, ",") != NULL) { /* bus addr is of type 1,0 */ - if (strcmp(bus_addr, char_di_bus_addr) != 0) { - return (DI_WALK_PRUNECHILD); - } - } else { /* bus addr is of type 0x */ - - /* check if the values are same */ - errno = 0; - busaddr = strtol(bus_addr, (char **)NULL, 16); - if (errno != 0) { - return (DI_WALK_TERMINATE); - } - - errno = 0; - di_busaddr = strtol(char_di_bus_addr, (char **)NULL, 16); - if (errno != 0) { - return (DI_WALK_TERMINATE); - } - - if (di_busaddr != busaddr) { - return (DI_WALK_PRUNECHILD); - } - } - - /* node found */ - path = di_devfs_path(node); - (void) strncpy(devinfo->path, path, sizeof (devinfo->path)); - di_devfs_path_free(path); - return (DI_WALK_TERMINATE); -} - -picl_errno_t -get_fru_path(char *parent_path, frutree_frunode_t *frup) -{ - picl_errno_t rc = 0; - picl_nodehdl_t loch; - di_node_t rnode; - frutree_devinfo_t *devinfo = NULL; - char slot_type[PICL_PROPNAMELEN_MAX]; - char probe_path[PICL_PROPNAMELEN_MAX]; - char bus_addr[PICL_PROPNAMELEN_MAX]; - - if ((rc = ptree_get_propval_by_name(frup->frunodeh, PICL_PROP_PARENT, - &loch, sizeof (loch))) != PICL_SUCCESS) { - return (rc); - } - - if ((rc = ptree_get_propval_by_name(loch, PICL_PROP_SLOT_TYPE, - slot_type, sizeof (slot_type))) != PICL_SUCCESS) { - return (rc); - } - - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - if (ptree_get_propval_by_name(loch, PICL_PROP_PROBE_PATH, - probe_path, sizeof (probe_path)) != PICL_SUCCESS) { - return (rc); - } - (void) strncpy(frup->fru_path, probe_path, - sizeof (frup->fru_path)); - return (PICL_SUCCESS); - } - - prom_handle = di_prom_init(); - rnode = di_init(parent_path, DINFOSUBTREE|DINFOMINOR); - if (rnode == DI_NODE_NIL) { - di_prom_fini(prom_handle); - return (PICL_FAILURE); - } - - devinfo = (frutree_devinfo_t *)malloc(sizeof (frutree_devinfo_t)); - if (devinfo == NULL) { - di_fini(rnode); - di_prom_fini(prom_handle); - return (PICL_NOSPACE); - } - - if (ptree_get_propval_by_name(loch, PICL_PROP_BUS_ADDR, - bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) { - free(devinfo); - di_fini(rnode); - di_prom_fini(prom_handle); - return (rc); - } - - devinfo->rnode = rnode; - (void) strncpy(devinfo->bus_addr, bus_addr, sizeof (devinfo->bus_addr)); - devinfo->path[0] = '\0'; - devinfo->arg = frup; - - if (di_walk_node(rnode, DI_WALK_SIBFIRST, &devinfo, walk_tree) != 0) { - di_fini(rnode); - di_prom_fini(prom_handle); - free(devinfo); - return (PICL_FAILURE); - } - di_fini(rnode); - di_prom_fini(prom_handle); - - if (devinfo->path[0]) { - (void) strncpy(frup->fru_path, devinfo->path, - sizeof (frup->fru_path)); - free(devinfo); - return (PICL_SUCCESS); - } else { - free(devinfo); - return (PICL_NODENOTFOUND); - } -} - -static int -find_fru_node(di_node_t node, void *arg) -{ - frutree_locnode_t *locp = NULL; - char *char_di_bus_addr = NULL; - int busaddr = 0; - int di_busaddr = 0; - char bus_addr[PICL_PROPNAMELEN_MAX]; - frutree_devinfo_t *devinfo = NULL; - - devinfo = *(frutree_devinfo_t **)arg; - locp = *(frutree_locnode_t **)devinfo->arg; - - if (devinfo->rnode == node) { - return (DI_WALK_CONTINUE); - } - - char_di_bus_addr = di_bus_addr(node); - if (char_di_bus_addr == NULL) { - return (DI_WALK_PRUNECHILD); - } - - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_BUS_ADDR, - bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) { - return (DI_WALK_PRUNECHILD); - } - - if (strstr(bus_addr, ",") != NULL) { - /* bus addr is of type 1,0 */ - if (strcmp(bus_addr, char_di_bus_addr) == 0) { - devinfo->retval = PICL_SUCCESS; - return (DI_WALK_TERMINATE); - } else { - return (DI_WALK_PRUNECHILD); - } - } else { /* bus addr is of type 0x */ - - /* check if the values are same */ - errno = 0; - busaddr = strtol(bus_addr, (char **)NULL, 16); - if (errno != 0) { - return (DI_WALK_PRUNECHILD); - } - - errno = 0; - di_busaddr = strtol(char_di_bus_addr, (char **)NULL, 16); - if (errno != 0) { - return (DI_WALK_PRUNECHILD); - } - - if (di_busaddr == busaddr) { - devinfo->retval = PICL_SUCCESS; - return (DI_WALK_TERMINATE); - } else { - return (DI_WALK_PRUNECHILD); - } - } -} - -/* - * checks if a fru is present under location using pdev-path and busaddr - */ -boolean_t -is_fru_present_under_location(frutree_locnode_t *locp) -{ - di_node_t rnode; - frutree_devinfo_t *devinfo = NULL; - char probe_path[PICL_PROPNAMELEN_MAX]; - - if (locp == NULL) { - return (B_FALSE); - } - - if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_PROBE_PATH, - probe_path, sizeof (probe_path)) != PICL_SUCCESS) { - if (ptree_get_propval_by_name(locp->locnodeh, - PICL_PROP_DEVFS_PATH, probe_path, - sizeof (probe_path)) != PICL_SUCCESS) { - return (B_FALSE); - } - } - - rnode = di_init(probe_path, DINFOSUBTREE); - if (rnode == DI_NODE_NIL) { - di_fini(rnode); - return (B_FALSE); - } - - devinfo = (frutree_devinfo_t *)malloc(sizeof (frutree_devinfo_t)); - if (devinfo == NULL) { - di_fini(rnode); - return (B_FALSE); - } - devinfo->rnode = rnode; - devinfo->arg = (frutree_locnode_t **)&locp; - devinfo->retval = PICL_FAILURE; - - if (di_walk_node(rnode, DI_WALK_SIBFIRST, &devinfo, - find_fru_node) != 0) { - di_fini(rnode); - free(devinfo); - return (B_FALSE); - } - di_fini(rnode); - - if (devinfo->retval == PICL_SUCCESS) { - free(devinfo); - return (B_TRUE); - } else { - free(devinfo); - return (B_FALSE); - } -} - -/* - * initializes the port driver and instance fields based on libdevinfo - */ -picl_errno_t -get_port_info(frutree_portnode_t *portp) -{ - picl_errno_t rc; - di_node_t rnode, curr, peer; - char devfs_path[PICL_PROPNAMELEN_MAX]; - char bus_addr[PICL_PROPNAMELEN_MAX]; - char *di_busaddr = NULL, *di_drv = NULL; - int di_int_busaddr, int_busaddr; - - if ((rc = ptree_get_propval_by_name(portp->portnodeh, - PICL_PROP_DEVFS_PATH, devfs_path, - sizeof (devfs_path))) != PICL_SUCCESS) { - return (rc); - } - - if (ptree_get_propval_by_name(portp->portnodeh, PICL_PROP_BUS_ADDR, - bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) { - return (rc); - } - - rnode = di_init(devfs_path, DINFOCPYALL); - if (rnode == DI_NODE_NIL) { - return (PICL_FAILURE); - } - - peer = di_child_node(rnode); - while (peer != DI_NODE_NIL) { - curr = peer; - peer = di_sibling_node(curr); - - di_busaddr = di_bus_addr(curr); - if (di_busaddr == NULL) { - continue; - } - - /* compare the bus_addr */ - if (strstr(bus_addr, ",") != NULL) { - /* bus addr is of type 1,0 */ - if (strcmp(bus_addr, di_busaddr) != 0) { - continue; - } - } else { /* bus addr is of type 0x */ - errno = 0; - int_busaddr = strtol(bus_addr, (char **)NULL, 16); - if (errno != 0) { - continue; - } - - errno = 0; - di_int_busaddr = strtol(di_busaddr, (char **)NULL, 16); - if (errno != 0) { - continue; - } - - if (di_int_busaddr != int_busaddr) { - continue; - } - } - di_drv = di_driver_name(curr); - if (di_drv == NULL) { - di_fini(rnode); - return (PICL_FAILURE); - } - /* initialize the driver name and instance number */ - (void) strncpy(portp->driver, di_drv, sizeof (portp->driver)); - portp->instance = di_instance(curr); - di_fini(rnode); - return (PICL_SUCCESS); - } - di_fini(rnode); - return (PICL_NODENOTFOUND); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclscsi.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclscsi.c deleted file mode 100644 index 25280a5644..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/frutree/piclscsi.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* implementation specific to scsi nodes probing */ - -#include <stdio.h> -#include <unistd.h> -#include <syslog.h> -#include <stdlib.h> -#include <sys/param.h> -#include <config_admin.h> -#include <string.h> -#include <strings.h> -#include <picl.h> -#include <picltree.h> -#include <libintl.h> -#include <libdevinfo.h> -#include <sys/types.h> -#include <picldefs.h> -#include "piclfrutree.h" - -#define SCSI_SLOT "scsi-bus" -#define SCSI_LOC_FORMAT "t%dd0" -#define TARGET "target" -#define CLASS "class" -#define BUF_SIZE 256 - -#define SCSI_INITIATOR_ID 7 -#define DRV_TYPE_DSK 1 -#define DRV_TYPE_TAPE 2 -#define NUM_DSK_TARGS 15 -/* - * No support for wide tapes for now. - * If required wide support, set this to 8 - * See st.conf. - */ -#define NUM_TAPE_TARGS 7 - -#define DIRLINK_DSK "dsk" -#define DIRLINK_RMT "rmt" -#define DRV_SCSI_DSK "sd" -#define DRV_SCSI_TAPE "st" -#define NULL_ENTRY 0 - -/* currently supported directory strings for SCSI FRUs in cfgadm APs */ -static char *scsi_dirlink_names[] = { DIRLINK_DSK, DIRLINK_RMT, NULL_ENTRY}; -/* currently supported SCSI FRU drivers */ -static struct scsi_drv_info { - char *drv_name; - uint8_t num_targets; - uint8_t drv_type; -} scsi_drv[] = { - DRV_SCSI_DSK, NUM_DSK_TARGS, DRV_TYPE_DSK, - DRV_SCSI_TAPE, NUM_TAPE_TARGS, DRV_TYPE_TAPE, - NULL_ENTRY, NULL_ENTRY, NULL_ENTRY - }; - -/* the following defs are based on defines in scsi cfgadm plugin */ -#define CDROM "CD-ROM" -#define RMM "tape" -#define DISK "disk" - -extern boolean_t is_location_present_in_subtree(frutree_frunode_t *, - const char *, const char *); -extern picl_errno_t create_children(frutree_frunode_t *, char *, char *, - int, char *, boolean_t); -extern char *strtok_r(char *s1, const char *s2, char **lasts); -extern boolean_t frutree_connects_initiated; -extern int frutree_debug; - -typedef struct node { - struct node *next; - cfga_list_data_t *data; -} node_t; - -typedef struct linked_list { - node_t *first; - int num_nodes; -} plist_t; - -typedef struct scsi_info { - frutree_frunode_t *frup; - cfga_list_data_t *cfgalist; - plist_t *list; - int num_list; - boolean_t compare_cfgadm; - int geo_addr; -} scsi_info_t; - -static plist_t *scsi_list = NULL; -static cfga_list_data_t *cfglist = NULL; -static int nlist = 0; - -static void -free_list(plist_t *list) -{ - node_t *tmp = NULL, *tmp1 = NULL; - - if (list == NULL) - return; - tmp = list->first; - while (tmp != NULL) { - free(tmp->data); - tmp1 = tmp->next; - free(tmp); - tmp = tmp1; - } -} - -/* - * This routine gets the list of scsi controllers present - */ -static cfga_err_t -populate_controllers_list(plist_t *cntrl_list, cfga_list_data_t *list, int num) -{ - int i; - node_t *nodeptr = NULL; - cfga_list_data_t *temp = NULL; - - if (cntrl_list == NULL || list == NULL) { - return (CFGA_ATTR_INVAL); - } - - cntrl_list->first = NULL; - cntrl_list->num_nodes = 0; - - if (num == 0) { - return (CFGA_OK); - } - - for (i = 0; i < num; i++) { - if (strcmp(list[i].ap_type, SCSI_SLOT) != 0) { - continue; - } - - /* scsi controller */ - temp = (cfga_list_data_t *)malloc(sizeof (cfga_list_data_t)); - if (temp == NULL) { - return (CFGA_ERROR); - } - (void) memcpy(temp, &list[i], sizeof (cfga_list_data_t)); - - nodeptr = (node_t *)malloc(sizeof (node_t)); - if (nodeptr == NULL) { - free(temp); - return (CFGA_ERROR); - } - nodeptr->data = temp; - nodeptr->next = NULL; - - /* append to the list */ - if (cntrl_list->first == NULL) { - cntrl_list->first = nodeptr; - cntrl_list->num_nodes++; - } else { - nodeptr->next = cntrl_list->first; - cntrl_list->first = nodeptr; - cntrl_list->num_nodes++; - } - } - return (CFGA_OK); -} - -picl_errno_t -scsi_info_init() -{ - cfga_err_t ap_list_err; - - ap_list_err = config_list_ext(0, NULL, &cfglist, &nlist, NULL, - NULL, NULL, CFGA_FLAG_LIST_ALL); - - if (ap_list_err != CFGA_OK) { - if (ap_list_err == CFGA_NOTSUPP) { - return (PICL_SUCCESS); - } else { - return (PICL_FAILURE); - } - } - - scsi_list = (plist_t *)malloc(sizeof (plist_t)); - if (scsi_list == NULL) { - free(cfglist); - return (PICL_NOSPACE); - } - - ap_list_err = populate_controllers_list(scsi_list, cfglist, nlist); - if (ap_list_err != CFGA_OK) { - free(cfglist); - free(scsi_list); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -void -scsi_info_fini() -{ - free(cfglist); - free_list(scsi_list); - free(scsi_list); -} - -/* - * This routine searches the controllers list to find the mapping based - * on given devfs_path. - * caller should allocate memory for ap_id - */ -static picl_errno_t -find_scsi_controller(char *devfs_path, plist_t *list, char *ap_id) -{ - node_t *tmp = NULL; - char *lasts = NULL; - char *token = NULL; - char path[MAXPATHLEN]; - - if (devfs_path == NULL || ap_id == NULL) { - return (PICL_INVALIDARG); - } - (void) snprintf((char *)path, sizeof (path), "/devices%s", devfs_path); - - tmp = list->first; - while (tmp != NULL) { - lasts = tmp->data->ap_phys_id; - token = (char *)strtok_r(lasts, (const char *)":", - (char **)&lasts); - if (token == NULL) { - tmp = tmp->next; - continue; - } - - if (strcmp(path, token) == 0) { /* match found */ - (void) strncpy(ap_id, tmp->data->ap_log_id, - sizeof (ap_id)); - return (PICL_SUCCESS); - } - tmp = tmp->next; - } - return (PICL_NODENOTFOUND); -} - -/* - * This routine dynamically determines the cfgadm attachment point - * for a given devfspath and target id. - * memory for name should be allocated by the caller. - */ -picl_errno_t -get_scsislot_name(char *devfs_path, char *bus_addr, char *name) -{ - picl_errno_t rc; - int target_id = 0; - int numlist; - plist_t list; - cfga_err_t ap_list_err; - cfga_list_data_t *cfgalist = NULL; - char controller[MAXPATHLEN]; - - ap_list_err = config_list_ext(0, NULL, &cfgalist, - &numlist, NULL, NULL, NULL, CFGA_FLAG_LIST_ALL); - if (ap_list_err != CFGA_OK) { - return (PICL_NODENOTFOUND); - } - - ap_list_err = populate_controllers_list(&list, cfgalist, - numlist); - if (ap_list_err != CFGA_OK) { - free_list(&list); - free(cfgalist); - return (PICL_NODENOTFOUND); - } - - if (list.num_nodes <= 0) { - free(cfgalist); - return (PICL_NODENOTFOUND); - } - - if ((rc = find_scsi_controller(devfs_path, &list, - controller)) != PICL_SUCCESS) { - free(cfgalist); - free_list(&list); - return (rc); - } - target_id = strtol(bus_addr, (char **)NULL, 16); - (void) sprintf(name, "%s::dsk/%st%dd0", controller, - controller, target_id); - free(cfgalist); - free_list(&list); - return (PICL_SUCCESS); -} - -/* - * Arg scsi_loc can be any of the following forms appearing in cfgadm output - * c0::dsk/c0t0d0 - * c1::sd56 - * c2::rmt/0 - * c3::st41 - * dsk/c1t1d0 - * rmt/1 - * /devices/pci@1f,0/pci@1,1/scsi@2:scsi::dsk/c0t0d0 - * - * On return, bus_addr contains the target id of the device. - * Please note that currently the target id is computed. It is better - * to eventually change this to getting from libdevinfo. - * Also, please note that SCSI_INITIATOR_ID should not - * be hardcoded, but should be dynamically retrieved from an OBP property. - */ -static void -get_bus_addr(char *scsi_loc, char **bus_addr) -{ - char *ap, *token, *p, *ap_idp; - int len = 0, i = 0; - char parse_link = 0; - char addr[BUF_SIZE], ap_id[BUF_SIZE]; - char fileinfo[BUF_SIZE], ap_id_link[BUF_SIZE]; - - (void) strncpy(ap_id, scsi_loc, sizeof (ap_id)); - ap = strrchr(ap_id, ':'); - if (!ap) - ap = ap_idp = ap_id; - else - ap_idp = ++ap; - - while (scsi_dirlink_names[i] && !len) { - len = strspn(ap, scsi_dirlink_names[i++]); - /* - * strspn may return positive len even when there is no - * complete string matches!!! hence the following check is - * necessary. So ensure the string match. - */ - if (len && strstr(ap, scsi_dirlink_names[i-1])) - break; - len = 0; - } - if (len) - parse_link = 1; - else { - i = 0; - while (scsi_drv[i].drv_name && !len) { - len = strspn(ap, scsi_drv[i++].drv_name); - if (len && strstr(ap, scsi_drv[i-1].drv_name)) - break; - len = 0; - } - } - ap += len; - if (strlen(ap) && parse_link) { - - /* slice 0 must be present in the system */ - if (strstr(ap, "/c")) { - if (strstr(ap, "s0") == NULL) - (void) strcat(ap, "s0"); - } - /* get the devlink and read the target id from minor node */ - (void) snprintf(ap_id_link, sizeof (ap_id_link), "/dev/%s", - ap_idp); - (void) bzero(fileinfo, sizeof (fileinfo)); - if (readlink(ap_id_link, fileinfo, sizeof (fileinfo)) < 0) - return; - if (!fileinfo[0]) - return; - ap = strrchr(fileinfo, '@'); - ap++; - } - token = (char *)strtok_r(ap, ",", &p); - (void) strncpy(addr, token, sizeof (addr)); - if (!parse_link) { - int drv_inst = atoi(token); - int tmp_targ_id = drv_inst % scsi_drv[i-1].num_targets; - int targ_id = scsi_drv[i-1].drv_type == DRV_TYPE_DSK ? - (tmp_targ_id < SCSI_INITIATOR_ID ? - tmp_targ_id : tmp_targ_id+1): - DRV_TYPE_TAPE ? tmp_targ_id : drv_inst; - (void) snprintf(addr, sizeof (addr), "%d", targ_id); - } - if (strlen(addr)) { - *bus_addr = (char *)malloc(strlen(addr)+1); - if ((*bus_addr) == NULL) - return; - (void) strcpy((char *)*bus_addr, addr); - } -} - -/* - * This routine determines all the scsi nodes under a FRU and - * creates a subtree of all the scsi nodes with basic properties. - */ -static picl_errno_t -dyn_probe_for_scsi_frus(frutree_frunode_t *frup, cfga_list_data_t *cfgalist, - plist_t *list, int numlist) -{ - picl_errno_t rc; - int i, geo_addr = 0; - node_t *curr = NULL; - char *bus_addr = NULL; - char path[MAXPATHLEN]; - char controller_name[MAXPATHLEN]; - - /* for each controller in the list, find if disk/fru is present */ - curr = list->first; - while (curr != NULL) { - /* compare the path */ - (void) snprintf((char *)path, sizeof (path), "/devices%s", - frup->fru_path); - if (strstr(curr->data->ap_phys_id, path) == NULL) { - curr = curr->next; - continue; - - } - (void) snprintf(controller_name, sizeof (controller_name), - "%s::", curr->data->ap_log_id); - - for (i = 0; i < numlist; i++) { - if (strcmp(cfgalist[i].ap_type, SCSI_SLOT) == 0) { - continue; - } - if (strstr(cfgalist[i].ap_log_id, - controller_name) == NULL) { - continue; - } - /* check if device is under fru */ - if (strstr(cfgalist[i].ap_phys_id, path) == NULL) { - continue; - } - - /* we found a scsi fru */ - geo_addr++; - /* check if the device is present in subtree */ - if (is_location_present_in_subtree(frup, - cfgalist[i].ap_log_id, path) == B_TRUE) { - continue; - } - get_bus_addr(cfgalist[i].ap_log_id, &bus_addr); - if (bus_addr == NULL) { - continue; - } - rc = create_children(frup, cfgalist[i].ap_log_id, - bus_addr, geo_addr, SANIBEL_SCSI_SLOT, B_TRUE); - free(bus_addr); - if (rc != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, "SUNW_frutree:" - "Error in creating node %s under %s(error=%d)", - cfgalist[i].ap_log_id, frup->name, rc); - } - } - curr = curr->next; - } - return (PICL_SUCCESS); -} - -/* - * data used here is cached information (cfglist, nlist) - */ -static picl_errno_t -cache_probe_for_scsi_frus(frutree_frunode_t *frup) -{ - int i, geo_addr = 0; - picl_errno_t rc; - node_t *curr = NULL; - char path[MAXPATHLEN]; - char controller_name[MAXPATHLEN]; - char *bus_addr = NULL; - - /* for each controller in the list, find if disk/fru is present */ - if (scsi_list == NULL) { - return (PICL_SUCCESS); - } - curr = scsi_list->first; - while (curr != NULL) { - /* compare the path */ - (void) snprintf((char *)path, sizeof (path), "/devices%s", - frup->fru_path); - if (strstr(curr->data->ap_phys_id, path) == NULL) { - curr = curr->next; - continue; - } - (void) snprintf(controller_name, sizeof (controller_name), - "%s::", curr->data->ap_log_id); - - for (i = 0; i < nlist; i++) { - if (strcmp(cfglist[i].ap_type, SCSI_SLOT) == 0) { - continue; - } - if (strstr(cfglist[i].ap_log_id, - controller_name) == NULL) { - continue; - } - /* check if the device is under fru */ - if (strstr(cfglist[i].ap_phys_id, path) == NULL) { - continue; - } - - /* we found a scsi fru */ - geo_addr++; - /* check if the device is present in subtree */ - if (is_location_present_in_subtree(frup, - cfglist[i].ap_log_id, path) == B_TRUE) { - continue; - } - get_bus_addr(cfglist[i].ap_log_id, &bus_addr); - if (bus_addr == NULL) { - continue; - } - rc = create_children(frup, cfglist[i].ap_log_id, - bus_addr, geo_addr, SANIBEL_SCSI_SLOT, B_TRUE); - free(bus_addr); - if (rc != PICL_SUCCESS) { - FRUTREE_DEBUG3(FRUTREE_INIT, "SUNW_frutree:" - "Error in creating node %s under %s(error=%d)", - cfglist[i].ap_log_id, frup->name, rc); - } - } - curr = curr->next; - } - return (PICL_SUCCESS); -} - -/* - * This routine checks if the node (scsi device) is present in cfgadm data - * Algorithm: - * 1. traverse thru list of controllers and find - * the controller of interest - * 2. go thru list of devices under controller and compare if the target is same - * 3. if yes - * - device is already represented - * 4. if No - * - The node must be repreented in PICL tree. - */ -static boolean_t -is_node_present(scsi_info_t *scsi_info, char *devfs_path, int target) -{ - node_t *curr = NULL; - char path[MAXPATHLEN]; - char controller[MAXPATHLEN]; - char *bus_addr = NULL; - char *lasts = NULL, *token = NULL; - int i = 0; - - if (scsi_info == NULL) { - return (B_FALSE); - } - - if (scsi_info->list == NULL) { - return (B_FALSE); - } - - (void) snprintf(path, sizeof (path), "/devices%s", devfs_path); - - curr = scsi_info->list->first; - while (curr != NULL) { - - lasts = curr->data->ap_phys_id; - token = (char *)strtok_r(lasts, (const char *)":", - (char **)&lasts); - if (token == NULL) { - curr = curr->next; - continue; - } - - if (strstr(path, token) == NULL) { - /* this controller is not of interest */ - curr = curr->next; - continue; - } - - (void) snprintf(controller, sizeof (controller), "%s::", - curr->data->ap_log_id); - for (i = 0; i < scsi_info->num_list; i++) { - if (strcmp(scsi_info->cfgalist[i].ap_type, - SCSI_SLOT) == 0) { - continue; - } - - if (strstr(scsi_info->cfgalist[i].ap_log_id, - controller) == NULL) { - continue; - } - - get_bus_addr(scsi_info->cfgalist[i].ap_phys_id, - &bus_addr); - /* - * compare with target value - */ - if (bus_addr == NULL) { - return (B_TRUE); - } - if (strtoul(bus_addr, NULL, 16) == target) { - /* - * this device is already represented - * in fru tree - */ - free(bus_addr); - return (B_TRUE); - } - free(bus_addr); - } - curr = curr->next; - } - return (B_FALSE); -} - -static di_prop_t -get_prop_by_name(di_node_t node, char *name) -{ - di_prop_t prop = DI_PROP_NIL; - char *prop_name = NULL; - - prop = di_prop_next(node, DI_PROP_NIL); - while (prop != DI_PROP_NIL) { - prop_name = di_prop_name(prop); - if (prop_name != NULL) { - if (strcmp(prop_name, name) == 0) { - return (prop); - } - } - prop = di_prop_next(node, prop); - } - return (DI_PROP_NIL); -} - -static int -get_geoaddr(picl_nodehdl_t nodeh, void *c_args) -{ - picl_errno_t rc; - uint8_t *geo_addr = NULL; - char slot_type[PICL_PROPNAMELEN_MAX]; - - if (c_args == NULL) - return (PICL_INVALIDARG); - geo_addr = (uint8_t *)c_args; - - if ((rc = ptree_get_propval_by_name(nodeh, PICL_PROP_SLOT_TYPE, - slot_type, sizeof (slot_type))) != PICL_SUCCESS) { - return (rc); - } - - if (strcmp(slot_type, SANIBEL_SCSI_SLOT) == 0 || - strcmp(slot_type, SANIBEL_IDE_SLOT) == 0) { - *geo_addr = *geo_addr + 1; - } - return (PICL_WALK_CONTINUE); -} - -static int -frutree_get_geoaddr(frutree_frunode_t *frup) -{ - int geo_addr = 1; - if (ptree_walk_tree_by_class(frup->frunodeh, PICL_CLASS_LOCATION, - &geo_addr, get_geoaddr) != PICL_SUCCESS) { - return (geo_addr); - } - return (geo_addr); -} - -static int -probe_disks(di_node_t node, void *arg) -{ - di_prop_t prop; - picl_errno_t rc; - int *target_val = NULL; - char *nodetype = NULL; - char *devfs_path = NULL; - char *bus_addr = NULL; - char *drv_name = NULL; - scsi_info_t *data = NULL; - di_minor_t minor = DI_MINOR_NIL; - char *class = NULL; - char node_name[BUF_SIZE]; - char slot_type[PICL_PROPNAMELEN_MAX]; - - if (arg == NULL) - return (DI_WALK_TERMINATE); - - data = *(scsi_info_t **)arg; - if (data == NULL) { - return (DI_WALK_TERMINATE); - } - - /* initialize the geo_addr value */ - if (data->geo_addr == 0) { - if (data->compare_cfgadm == B_FALSE) { - data->geo_addr = 1; - } else { - data->geo_addr = frutree_get_geoaddr(data->frup); - } - } - - while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { - nodetype = di_minor_nodetype(minor); - if (nodetype == NULL) { - continue; - } - - if (strcmp(nodetype, DDI_NT_BLOCK_CHAN) == 0 || - strcmp(nodetype, DDI_NT_BLOCK_WWN) == 0) { - (void) snprintf(node_name, sizeof (node_name), - "%s%d", DISK, data->geo_addr); - } else if (strcmp(nodetype, DDI_NT_TAPE) == 0) { - (void) snprintf(node_name, sizeof (node_name), - "%s%d", RMM, data->geo_addr); - } else if (strcmp(nodetype, DDI_NT_CD) == 0 || - strcmp(nodetype, DDI_NT_CD_CHAN) == 0) { - (void) snprintf(node_name, sizeof (node_name), - "%s%d", CDROM, data->geo_addr); - } else { - continue; - } - - devfs_path = di_devfs_path(node); - drv_name = di_driver_name(node); - bus_addr = di_bus_addr(node); - if (devfs_path == NULL) { - continue; - } - if (drv_name == NULL || bus_addr == NULL) { - di_devfs_path_free(devfs_path); - continue; - } - prop = get_prop_by_name(node, TARGET); - if (prop != DI_PROP_NIL) { - di_prop_ints(prop, &target_val); - if (data->compare_cfgadm) { - /* check if node is present in cfgadm data */ - if (is_node_present(data, devfs_path, - *target_val) == B_TRUE) { - di_devfs_path_free(devfs_path); - return (DI_WALK_CONTINUE); - } - } - - di_devfs_path_free(devfs_path); - prop = get_prop_by_name(node, CLASS); - if (prop != DI_PROP_NIL) { - di_prop_strings(prop, &class); - } - - /* determine the slot type based on class code */ - if (class != NULL) { - if (strcmp(class, DEVICE_CLASS_SCSI) == 0) { - (void) strncpy(slot_type, - SANIBEL_SCSI_SLOT, - sizeof (slot_type)); - } else if (strcmp(class, - DEVICE_CLASS_IDE) == 0) { - (void) strncpy(slot_type, - SANIBEL_IDE_SLOT, - sizeof (slot_type)); - } else { - (void) strncpy(slot_type, - SANIBEL_UNKNOWN_SLOT, - sizeof (slot_type)); - } - - } else { - (void) strncpy(slot_type, SANIBEL_UNKNOWN_SLOT, - sizeof (slot_type)); - } - - if ((rc = create_children(data->frup, node_name, - bus_addr, data->geo_addr, slot_type, - B_FALSE)) != PICL_SUCCESS) { - return (rc); - } - /* increment the geo_addr */ - data->geo_addr++; - } else { - di_devfs_path_free(devfs_path); - continue; - } - return (DI_WALK_CONTINUE); - } - return (DI_WALK_CONTINUE); -} - -static picl_errno_t -probe_scsi_in_libdevinfo(frutree_frunode_t *frup, cfga_list_data_t *cfgalist, - plist_t *list, int num_list, boolean_t compare_cfgadm) -{ - di_node_t rnode; - scsi_info_t *scsi_data = NULL; - - if (frup == NULL) { - return (PICL_FAILURE); - } - - rnode = di_init(frup->fru_path, DINFOCPYALL); - if (rnode == DI_NODE_NIL) { - return (PICL_FAILURE); - } - - scsi_data = (scsi_info_t *)malloc(sizeof (scsi_info_t)); - if (scsi_data == NULL) { - di_fini(rnode); - return (PICL_NOSPACE); - } - - scsi_data->frup = frup; - scsi_data->cfgalist = cfgalist; - scsi_data->list = list; - scsi_data->num_list = num_list; - scsi_data->compare_cfgadm = compare_cfgadm; - scsi_data->geo_addr = 0; - if (di_walk_node(rnode, DI_WALK_CLDFIRST, &scsi_data, - probe_disks) != 0) { - free(scsi_data); - di_fini(rnode); - return (PICL_FAILURE); - } - - free(scsi_data); - di_fini(rnode); - return (PICL_SUCCESS); -} - -picl_errno_t -probe_for_scsi_frus(frutree_frunode_t *frup) -{ - int numlist; - picl_errno_t rc; - plist_t list; - cfga_err_t ap_list_err; - cfga_list_data_t *cfgalist = NULL; - - if (frutree_connects_initiated == B_TRUE) { /* probing after hotswap */ - ap_list_err = config_list_ext(0, NULL, &cfgalist, - &numlist, NULL, NULL, NULL, CFGA_FLAG_LIST_ALL); - - if (ap_list_err != CFGA_OK) { - rc = probe_scsi_in_libdevinfo(frup, NULL, NULL, - 0, B_FALSE); - return (rc); - } - - /* get list of all controllers in the system */ - ap_list_err = populate_controllers_list(&list, cfgalist, - numlist); - if (ap_list_err != CFGA_OK) { - free_list(&list); - free(cfgalist); - rc = probe_scsi_in_libdevinfo(frup, NULL, NULL, - 0, B_FALSE); - return (rc); - } - - /* no controllers found */ - if (list.num_nodes <= 0) { - free_list(&list); - free(cfgalist); - rc = probe_scsi_in_libdevinfo(frup, NULL, NULL, - 0, B_FALSE); - return (rc); - } - /* - * we have to fetch cfgadm, look for scsi controllers - * dynamically - */ - (void) dyn_probe_for_scsi_frus(frup, cfgalist, &list, numlist); - rc = probe_scsi_in_libdevinfo(frup, cfgalist, &list, - numlist, B_TRUE); - free_list(&list); - free(cfgalist); - return (rc); - } else { - /* during initialization */ - /* use the cached cfgadm data */ - rc = cache_probe_for_scsi_frus(frup); - if (scsi_list && scsi_list->num_nodes > 0) { - rc = probe_scsi_in_libdevinfo(frup, cfglist, - scsi_list, nlist, B_TRUE); - } else { - rc = probe_scsi_in_libdevinfo(frup, NULL, - NULL, 0, B_FALSE); - } - return (rc); - } -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/Makefile deleted file mode 100644 index 0936b179fb..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#pragma ident "%Z%%M% %I% %E% SMI" -# -# cmd/picl/plugins/sun4u/snowbird/lib/Makefile -# - -SUBDIRS= libctsmc fruaccess .WAIT - -MSGSUBDIRS= libctsmc fruaccess .WAIT - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -.KEEP_STATE: - -all install clean clobber lint : $(SUBDIRS) - -_msg: $(MSGSUBDIRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/Makefile deleted file mode 100644 index d0ae930dca..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/Makefile +++ /dev/null @@ -1,104 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/Makefile -# - -LIBRARY= libfruaccess.a -VERS= .1 - -OBJECTS= libfruaccess.o piclsmc.o piclsdr.o piclfruaccess_platmod.o \ - crcutils.o crcmodel.o - -# include library definitions -include $(SRC)/lib/Makefile.lib -include $(SRC)/Makefile.psm -include $(SRC)/cmd/picl/plugins/Makefile.com - -ROOT_PLATFORM = $(USR_PLAT_DIR)/SUNW,Netra-CP2300 - -SRCS= libfruaccess.c piclsmc.c piclsdr.c piclfruaccess_platmod.c\ - ../../../lib/fruaccess/crcutils.c \ - ../../../lib/fruaccess/crcmodel.c - -SRCDIR= ../../../lib/fruaccess/. - -LIBS = $(DYNLIB) - -CLEANFILES= $(LINTOUT) $(LINTLIB) - -ROOTLIBDIR = $(ROOT_PLAT_LIBDIR) - -LINTSRC = $(LINTLIB:%.ln=%) -ROOTLINTDIR = $(ROOTLIBDIR) -ROOTLINT = $(LINTSRC:%=$(ROOTLINTDIR)/%) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRC)/uts/sun4u/sys -CPPFLAGS += -I$(SRC)/cmd/picl/plugins/sun4u/lib/fruaccess -CPPFLAGS += -I$(SRC)/lib/libfruutils -CPPFLAGS += -I$(SRC)/lib/libfru/include -CPPFLAGS += -I$(SRC)/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc - -LDLIBS += -L$(SRC)/lib/libpicl/$(MACH) -L$(SRC)/lib/libpicltree/$(MACH) -LDLIBS += -L $(ROOT)/usr/platform/SUNW,Netra-CP2300/lib -LDLIBS += -L$(SRC)/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc -LDLIBS += -R/usr/platform/sun4u/lib -LDLIBS += -R/usr/platform/SUNW,Netra-CP2300/lib -LDLIBS += -lc -lpicltree -lfruutils -lctsmc - -.KEEP_STATE: - -SUBDIRS= - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -all: $(LIBS) $(LIBLINKS) - -install:$(ROOTLIBDIR) all $(ROOTLIBS) $(ROOTLINKS) - -$(LIBLINKS): FRC - $(RM) $(LIBLINKS); $(SYMLINK) $(DYNLIB) $(LIBLINKS) - -_msg: - -# include library targets -include $(SRC)/cmd/picl/plugins/Makefile.targ -include $(SRC)/lib/Makefile.targ - -$(ROOTLINTDIR)/%: ../% - $(INS.file) - -lint : - $(LINT.c) $(SRCS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/fru_access_impl.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/fru_access_impl.h deleted file mode 100644 index 359fbe13e3..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/fru_access_impl.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _FRU_ACCESS_IMPL_H -#define _FRU_ACCESS_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <dial.h> -#include <strings.h> -#include <libdevinfo.h> -#include <sys/systeminfo.h> -#include <picl.h> -#include <picltree.h> -#include <syslog.h> -#include <errno.h> -#include <limits.h> -#include "picldefs.h" -#include "libfru.h" -#include "fru_tag.h" -#include "fru_access.h" - -/* converts slot# to ipmb addr */ -#define IPMB_ADDR(_X) (((_X) < 10) ? (0xb0 + 2 * ((_X) - 1)) :\ - (0xb0 + 2 * (_X))) -#define MANR_TAG 0xF80010B7 /* ManR tag */ -#define SEG_NAME_LEN 2 - -#define MANR_TIME_LEN 4 -#define MANR_FRUDESCR_LEN 80 -#define MANR_MFRLOC_LEN 64 -#define MANR_PARTNUM_LEN 7 -#define MANR_SERIALNUM_LEN 6 -#define MANR_VENDORNAME_LEN 2 -#define MANR_DASHLVL_LEN 2 -#define MANR_REVLVL_LEN 2 -#define MANR_FRUNAME_LEN 16 - -#define NO_FRUDATA 0x0 -#define IPMI_FORMAT 0x1 -#define SUN_FORMAT 0x2 - -/* These are newly introduced #defines for Snowbird */ -#define INPUT_FILE "/dev/ctsmc" -#define NUM_OF_SECTIONS 2 -#define DYNAMIC_OFFSET 0x0 -#define STATIC_OFFSET 0x1800 -#define WRITE_SECTION 0 -#define DYNAMIC_LENGTH (6 * 1024); /* 6k bytes */ -#define STATIC_LENGTH (2 * 1024); /* 2k bytes */ -#define MANR_SIZE 183 /* MANR record size in bytes */ - -#define PICL_SLOT_CPCI "cpci" -#define PICL_SLOT_PCI "pci" -#define PICL_NODE_CHASSIS "chassis" -#define SD_SEGMENT_NAME "SD" -#define SD_SEGMENT_DESCRIPTOR 0x00004924 -#define SEGMENT_TRAILER_LEN 1 -#define SEGMENT_CHKSM_LEN 4 - -/* format structure */ -typedef struct { - int format; - int sun_lun; /* this info comes from SDR */ - int sun_device_id; /* this info comes from SDR */ - uint8_t src; - uint8_t dest; -} format_t; - -/* ManR payload structure */ -typedef struct { - char timestamp[MANR_TIME_LEN]; - char fru_descr[MANR_FRUDESCR_LEN]; - char manufacture_loc[MANR_MFRLOC_LEN]; - char sun_part_no[MANR_PARTNUM_LEN]; - char sun_serial_no[MANR_SERIALNUM_LEN]; - char vendor_name[MANR_VENDORNAME_LEN]; /* JEDEC CODE */ - char inital_hw_dash_lvl[MANR_DASHLVL_LEN]; - char inital_hw_rev_lvl[MANR_REVLVL_LEN]; - char fru_short_name[MANR_FRUNAME_LEN]; -} payload_t; -/* object types */ -typedef enum {CONTAINER_TYPE, SECTION_TYPE, SEGMENT_TYPE, PACKET_TYPE} object_t; - -#define TABLE_SIZE 64 /* hash table size */ - -/* section header */ -#define SECTION_HDR_TAG 0x08 -#define SECTION_HDR_VER 0x0001 -#define SECTION_HDR_LENGTH 0x06 -#define SECTION_HDR_CRC8 0x00 -#define SECTION_HDR_VER_BIT0 0x00 -#define SECTION_HDR_VER_BIT1 0x01 - -#define READ_ONLY_SECTION 1 /* section is read-only */ - -#define GET_SEGMENT_DESCRIPTOR \ - (seg_layout->descriptor[1]|seg_layout->descriptor[0] << 16) - -#define GET_SECTION_HDR_VERSION \ - (sec_hdr.headerversion[1]|sec_hdr.headerversion[0] << 8) - -/* Segment Trailer Tag */ -#define SEG_TRAILER_TAG 0x0C - -/* defines fixed segment */ -#define SEGMENT_FIXED 1 - -#define DEFAULT_FD -1 -#define DEFAULT_SEQN -1 -#define FRUACCESS_MSG_ID 11 - -typedef union { - uint32_t all_bits; - struct { - unsigned read_only : 1; - unsigned unused : 8; - unsigned : 8; - unsigned : 8; - unsigned : 7; - } field; -} sectdescbit_t; - -typedef struct { - sectdescbit_t description; - uint32_t address; /* for SEEPROMS this is the offset */ - uint32_t size; -} sectioninfo_t; - -typedef uint16_t headerrev_t; - -#define MAX_NUMOF_SECTION 2 - -typedef struct { - headerrev_t header_ver; - int num_sections; - sectioninfo_t section_info[MAX_NUMOF_SECTION]; -} container_info_t; - -/* section header layout */ -typedef struct { - uint8_t headertag; /* section header tag */ - uint8_t headerversion[2]; /* header version (msb) */ - uint8_t headerlength; /* header length */ - uint8_t headercrc8; /* crc8 */ - uint8_t segmentcount; /* total number of segment */ -} section_layout_t; - -/* segment header layout */ -typedef struct { - uint16_t name; /* segment name */ - uint16_t descriptor[2]; /* descriptor (msb) */ - uint16_t offset; /* segment data offset */ - uint16_t length; /* segment length */ -} segment_layout_t; - -/* segment information used in finding new offset for a new segment */ -typedef struct { - int segnum; /* segment number */ - int offset; /* segment offset */ - int length; /* segment length */ - int fixed; /* fixed or non-fixed segment */ -} seg_info_t; - -typedef uint64_t handle_t; - -struct hash_obj; - -/* packet hash object */ -typedef struct { - handle_t segment_hdl; /* segment handle */ - fru_tag_t tag; - int tag_size; - uint8_t *payload; - payload_t payload_data; /* reqd for ipmi format */ - uint32_t paylen; - uint32_t payload_offset; - struct hash_obj *next; -} packet_obj_t; - -/* segment hash object */ -typedef struct { - handle_t section_hdl; /* section handle */ - int num_of_packets; /* in a segment */ - int trailer_offset; - segment_t segment; - struct hash_obj *pkt_obj_list; /* packet object list */ - struct hash_obj *next; -} segment_obj_t; - -/* section hash object */ -typedef struct { - handle_t cont_hdl; /* container handle */ - section_t section; - int num_of_segment; /* in a section */ - struct hash_obj *seg_obj_list; /* points to segment objects list */ - struct hash_obj *next; -} section_obj_t; - -/* contianer hash object */ -typedef struct { - char device_pathname[PATH_MAX]; /* device name */ - int num_of_section; /* num of section in container */ - format_t format; - struct hash_obj *sec_obj_list; /* points to section objects list */ -} container_obj_t; - -/* hash object */ -typedef struct hash_obj { - int object_type; - handle_t obj_hdl; - union { - container_obj_t *cont_obj; - section_obj_t *sec_obj; - segment_obj_t *seg_obj; - packet_obj_t *pkt_obj; - } u; - struct hash_obj *next; - struct hash_obj *prev; -} hash_obj_t; - -extern unsigned char compute_crc8(unsigned char *bytes, int length); -extern long compute_crc32(unsigned char *bytes, int length); -extern long compute_checksum32(unsigned char *bytes, int length); - -#ifdef __cplusplus -} -#endif - -#endif /* _FRU_ACCESS_IMPL_H */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/libfruaccess.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/libfruaccess.c deleted file mode 100644 index 3a48dcbf5e..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/libfruaccess.c +++ /dev/null @@ -1,3438 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <picl.h> -#include <limits.h> -#include <alloca.h> -#include <stdarg.h> -#include "smc_if.h" -#include "fru_access_impl.h" - -#pragma init(initialize_fruaccess) /* .init section */ - -/* - * This module translates all the frudata plugin requests into platform - * specific commands and provides information back to frudata plugin. - */ - -/* - * precedence for format. - * define an ENV variable (SUNW_FRUACCESS_IPMI_PRECEDENCE) to make - * ipmi format has more precedence than sun format. - */ -static int precedence = SUN_FORMAT; /* by default */ -#define FRUACCESS_PRECEDENCE "SUNW_FRUACCESS_IPMI_PRECEDENCE" - -extern ssize_t pread_new(int, void *, size_t, off_t, format_t *); -extern ssize_t pwrite_new(int, const void *, size_t, off_t, format_t *); -extern int get_manr(format_t *, payload_t *); -extern int is_fru_data_available(int, int, format_t *); -extern picl_errno_t fruaccess_platmod_init_format(uint8_t, format_t *); -extern int fruaccess_platmod_check_chassis(); -extern int fruaccess_platmod_check_fru(picl_nodehdl_t parenth); - -static container_hdl_t sun_fru_open_container(picl_nodehdl_t); -static int sun_fru_close_container(container_hdl_t); -static int sun_fru_get_num_sections(container_hdl_t, door_cred_t *); -static int sun_fru_get_sections(container_hdl_t, section_t *, - int, door_cred_t *); -static int sun_fru_get_num_segments(section_hdl_t, door_cred_t *); -static int sun_fru_get_segments(section_hdl_t, segment_t *, - int, door_cred_t *); -static int sun_fru_add_segment(section_hdl_t, segment_t *, - section_hdl_t *, door_cred_t *); -static int sun_fru_delete_segment(segment_hdl_t, section_hdl_t *, - door_cred_t *); -static ssize_t sun_fru_read_segment(segment_hdl_t, void *, size_t, - door_cred_t *); -static int sun_fru_write_segment(segment_hdl_t, const void *, size_t, - segment_hdl_t *, door_cred_t *); -static int sun_fru_get_num_packets(segment_hdl_t, door_cred_t *); -static int sun_fru_get_packets(segment_hdl_t, packet_t *, - int, door_cred_t *); -static ssize_t sun_fru_get_payload(packet_hdl_t, void *, size_t, - door_cred_t *); -static int sun_fru_update_payload(packet_hdl_t, const void *, size_t, - packet_hdl_t *, door_cred_t *); -static int sun_fru_append_packet(segment_hdl_t, packet_t *, - const void *, size_t, segment_hdl_t *, - door_cred_t *); -static int sun_fru_delete_packet(packet_hdl_t, segment_hdl_t *, door_cred_t *); - -static container_hdl_t ipmi_fru_open_container(picl_nodehdl_t); -static int ipmi_fru_close_container(container_hdl_t); -static int ipmi_fru_get_num_sections(container_hdl_t, door_cred_t *); -static int ipmi_fru_get_sections(container_hdl_t, section_t *, - int, door_cred_t *); -static int ipmi_fru_get_num_segments(section_hdl_t, door_cred_t *); -static int ipmi_fru_get_segments(section_hdl_t, segment_t *, - int, door_cred_t *); -static int ipmi_fru_add_segment(section_hdl_t, segment_t *, - section_hdl_t *, door_cred_t *); -static int ipmi_fru_delete_segment(segment_hdl_t, section_hdl_t *, - door_cred_t *); -static ssize_t ipmi_fru_read_segment(segment_hdl_t, void *, size_t, - door_cred_t *); -static int ipmi_fru_write_segment(segment_hdl_t, const void *, size_t, - segment_hdl_t *, door_cred_t *); -static int ipmi_fru_get_num_packets(segment_hdl_t, door_cred_t *); -static int ipmi_fru_get_packets(segment_hdl_t, packet_t *, - int, door_cred_t *); -static ssize_t ipmi_fru_get_payload(packet_hdl_t, void *, size_t, - door_cred_t *); -static int ipmi_fru_update_payload(packet_hdl_t, const void *, size_t, - packet_hdl_t *, door_cred_t *); -static int ipmi_fru_append_packet(segment_hdl_t, packet_t *, - const void *, size_t, segment_hdl_t *, - door_cred_t *); -static int ipmi_fru_delete_packet(packet_hdl_t, segment_hdl_t *, door_cred_t *); - -typedef struct { - container_hdl_t (* open_container)(picl_nodehdl_t); - int (* close_container)(container_hdl_t); - int (* get_num_sections)(container_hdl_t, door_cred_t *); - int (* get_sections)(container_hdl_t, section_t *, - int, door_cred_t *); - int (* get_num_segments)(section_hdl_t, door_cred_t *); - int (* get_segments)(section_hdl_t, segment_t *, - int, door_cred_t *); - int (* add_segment)(section_hdl_t, segment_t *, - section_hdl_t *, door_cred_t *); - int (* delete_segment)(segment_hdl_t, section_hdl_t *, - door_cred_t *); - ssize_t (* read_segment)(segment_hdl_t, void *, size_t, - door_cred_t *); - int (* write_segment)(segment_hdl_t, const void *, size_t, - segment_hdl_t *, door_cred_t *); - int (* get_num_packets)(segment_hdl_t, door_cred_t *); - int (* get_packets)(segment_hdl_t, packet_t *, - int, door_cred_t *); - ssize_t (* get_payload)(packet_hdl_t, void *, size_t, - door_cred_t *); - int (* update_payload)(packet_hdl_t, const void *, size_t, - packet_hdl_t *, door_cred_t *); - int (* append_packet)(segment_hdl_t, packet_t *, - const void *, size_t, segment_hdl_t *, - door_cred_t *); - int (* delete_packet)(packet_hdl_t, segment_hdl_t *, door_cred_t *); -} fruaccess_func_ptrs_t; - -static fruaccess_func_ptrs_t fruaccess_func[2] = { - { - ipmi_fru_open_container, - ipmi_fru_close_container, - ipmi_fru_get_num_sections, - ipmi_fru_get_sections, - ipmi_fru_get_num_segments, - ipmi_fru_get_segments, - ipmi_fru_add_segment, - ipmi_fru_delete_segment, - ipmi_fru_read_segment, - ipmi_fru_write_segment, - ipmi_fru_get_num_packets, - ipmi_fru_get_packets, - ipmi_fru_get_payload, - ipmi_fru_update_payload, - ipmi_fru_append_packet, - ipmi_fru_delete_packet, - }, - { - sun_fru_open_container, - sun_fru_close_container, - sun_fru_get_num_sections, - sun_fru_get_sections, - sun_fru_get_num_segments, - sun_fru_get_segments, - sun_fru_add_segment, - sun_fru_delete_segment, - sun_fru_read_segment, - sun_fru_write_segment, - sun_fru_get_num_packets, - sun_fru_get_packets, - sun_fru_get_payload, - sun_fru_update_payload, - sun_fru_append_packet, - sun_fru_delete_packet, - }, - }; - -static int is_valid_chassis = -1; -static hash_obj_t *hash_table[TABLE_SIZE]; - -static void -initialize_fruaccess(void) -{ - int count; - for (count = 0; count < TABLE_SIZE; count++) { - hash_table[count] = NULL; - } - - /* check if ipmi format has precedence */ - if (getenv(FRUACCESS_PRECEDENCE)) { - precedence = IPMI_FORMAT; - } -} - -/* called to lookup hash object for specified handle in the hash table. */ -static hash_obj_t * -lookup_handle_object(handle_t handle, int object_type) -{ - handle_t index_to_hash; - hash_obj_t *first_hash_obj; - hash_obj_t *next_hash_obj; - - index_to_hash = (handle % TABLE_SIZE); - - first_hash_obj = hash_table[index_to_hash]; - for (next_hash_obj = first_hash_obj; next_hash_obj != NULL; - next_hash_obj = next_hash_obj->next) { - if ((handle == next_hash_obj->obj_hdl) && - (object_type == next_hash_obj->object_type)) { - return (next_hash_obj); - } - } - return (NULL); -} - -/* called to allocate container hash object */ -static hash_obj_t * -create_container_hash_object(void) -{ - hash_obj_t *hash_obj; - container_obj_t *cont_obj; - - cont_obj = malloc(sizeof (container_obj_t)); - if (cont_obj == NULL) { - return (NULL); - } - - hash_obj = malloc(sizeof (hash_obj_t)); - if (hash_obj == NULL) { - free(cont_obj); - return (NULL); - } - - cont_obj->sec_obj_list = NULL; - - hash_obj->object_type = CONTAINER_TYPE; - hash_obj->u.cont_obj = cont_obj; - hash_obj->next = NULL; - hash_obj->prev = NULL; - - return (hash_obj); -} - -/* called to allocate section hash object */ -static hash_obj_t * -create_section_hash_object(void) -{ - hash_obj_t *hash_obj; - section_obj_t *sec_obj; - - sec_obj = malloc(sizeof (section_obj_t)); - if (sec_obj == NULL) { - return (NULL); - } - - hash_obj = malloc(sizeof (hash_obj_t)); - if (hash_obj == NULL) { - free(sec_obj); - return (NULL); - } - - sec_obj->next = NULL; - sec_obj->seg_obj_list = NULL; - - hash_obj->u.sec_obj = sec_obj; - hash_obj->object_type = SECTION_TYPE; - hash_obj->next = NULL; - hash_obj->prev = NULL; - - return (hash_obj); -} - -/* called to allocate segment hash object */ -static hash_obj_t * -create_segment_hash_object(void) -{ - hash_obj_t *hash_obj; - segment_obj_t *seg_obj; - - seg_obj = malloc(sizeof (segment_obj_t)); - if (seg_obj == NULL) { - return (NULL); - } - - hash_obj = malloc(sizeof (hash_obj_t)); - if (hash_obj == NULL) { - free(seg_obj); - return (NULL); - } - - seg_obj->next = NULL; - seg_obj->pkt_obj_list = NULL; - - hash_obj->object_type = SEGMENT_TYPE; - hash_obj->u.seg_obj = seg_obj; - hash_obj->next = NULL; - hash_obj->prev = NULL; - - return (hash_obj); -} - -/* called to allocate packet hash object */ -static hash_obj_t * -create_packet_hash_object(void) -{ - hash_obj_t *hash_obj; - packet_obj_t *pkt_obj; - - pkt_obj = malloc(sizeof (packet_obj_t)); - if (pkt_obj == NULL) { - return (NULL); - } - - hash_obj = malloc(sizeof (hash_obj_t)); - if (hash_obj == NULL) { - free(pkt_obj); - return (NULL); - } - - pkt_obj->next = NULL; - - hash_obj->object_type = PACKET_TYPE; - hash_obj->u.pkt_obj = pkt_obj; - hash_obj->next = NULL; - hash_obj->prev = NULL; - - return (hash_obj); -} - -/* called to add allocated hash object into the hash table */ -static void -add_hashobject_to_hashtable(hash_obj_t *hash_obj, int object_type) -{ - handle_t index_to_hash; - static uint64_t handle_count = 0; - - if (object_type != CONTAINER_TYPE) { - hash_obj->obj_hdl = ++handle_count; - } - - /* where to add ? */ - index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE); - - hash_obj->next = hash_table[index_to_hash]; - hash_table[index_to_hash] = hash_obj; /* hash obj. added */ - - if (hash_obj->next != NULL) { - hash_obj->next->prev = hash_obj; - } -} - -/* called to add section object list into the section list */ -static void -add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) -{ - hash_obj_t *next_hash; - - child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl; - if (parent_obj->u.cont_obj->sec_obj_list == NULL) { - parent_obj->u.cont_obj->sec_obj_list = child_obj; - return; - } - - for (next_hash = parent_obj->u.cont_obj->sec_obj_list; - next_hash->u.sec_obj->next != NULL; - next_hash = next_hash->u.sec_obj->next) { - ; - } - - next_hash->u.sec_obj->next = child_obj; -} - -/* called to add segment object list into segment list */ -static void -add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) -{ - hash_obj_t *next_hash; - - child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl; - if (parent_obj->u.sec_obj->seg_obj_list == NULL) { - parent_obj->u.sec_obj->seg_obj_list = child_obj; - return; - } - - for (next_hash = parent_obj->u.sec_obj->seg_obj_list; - next_hash->u.seg_obj->next != NULL; - next_hash = next_hash->u.seg_obj->next) { - ; - } - - next_hash->u.seg_obj->next = child_obj; -} - -/* called to add packet object list into packet list */ -static void -add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) -{ - hash_obj_t *next_hash; - - /* add the packet object in the end of list */ - child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl; - - if (parent_obj->u.seg_obj->pkt_obj_list == NULL) { - parent_obj->u.seg_obj->pkt_obj_list = child_obj; - return; - } - - for (next_hash = parent_obj->u.seg_obj->pkt_obj_list; - next_hash->u.pkt_obj->next != NULL; - next_hash = next_hash->u.pkt_obj->next) { - ; - } - - next_hash->u.pkt_obj->next = child_obj; -} - -/* fill the information, payload in the conatiner */ -/*ARGSUSED*/ -static int -initialize_ipmi_container(picl_nodehdl_t fru, hash_obj_t *cont_hash_obj) -{ - payload_t manr; - hash_obj_t *seg_hash_obj, *sec_hash_obj, *pkt_hash_obj; - format_t format; - - format = cont_hash_obj->u.cont_obj->format; - /* plug to SMC driver to fetch the data */ - if (get_manr(&format, &manr) != 0) { - return (-1); - } - - cont_hash_obj->u.cont_obj->num_of_section = 1; - cont_hash_obj->u.cont_obj->sec_obj_list = NULL; - - sec_hash_obj = create_section_hash_object(); - if (sec_hash_obj == NULL) { - return (-1); - } - - add_hashobject_to_hashtable(sec_hash_obj, SECTION_TYPE); - - /* create fake section info here */ - sec_hash_obj->u.sec_obj->num_of_segment = 1; - sec_hash_obj->u.sec_obj->section.handle = sec_hash_obj->obj_hdl; - sec_hash_obj->u.sec_obj->section.offset = 0; - sec_hash_obj->u.sec_obj->section.protection = READ_ONLY_SECTION; - - sec_hash_obj->u.sec_obj->section.length = STATIC_LENGTH; - sec_hash_obj->u.sec_obj->section.version = SECTION_HDR_VER; - add_to_sec_object_list(cont_hash_obj, sec_hash_obj); - - seg_hash_obj = create_segment_hash_object(); - if (seg_hash_obj == NULL) { - return (-1); - } - - add_hashobject_to_hashtable(seg_hash_obj, SEGMENT_TYPE); - - seg_hash_obj->u.seg_obj->num_of_packets = 1; - seg_hash_obj->u.seg_obj->segment.handle = seg_hash_obj->obj_hdl; - (void) strncpy(seg_hash_obj->u.seg_obj->segment.name, - SD_SEGMENT_NAME, - sizeof (seg_hash_obj->u.seg_obj->segment.name)); - seg_hash_obj->u.seg_obj->segment.descriptor = SD_SEGMENT_DESCRIPTOR; - /* tag + payload */ - seg_hash_obj->u.seg_obj->segment.length = MANR_SIZE + - SEGMENT_TRAILER_LEN + SEGMENT_CHKSM_LEN; - add_to_seg_object_list(sec_hash_obj, seg_hash_obj); - - pkt_hash_obj = create_packet_hash_object(); - if (pkt_hash_obj == NULL) { - return (-1); - } - add_hashobject_to_hashtable(pkt_hash_obj, PACKET_TYPE); - - pkt_hash_obj->u.pkt_obj->payload_data = manr; - if (mk_tag(FRU_F, 0x001, 0x0B7, &pkt_hash_obj->u.pkt_obj->tag) == 4) { - add_to_pkt_object_list(seg_hash_obj, pkt_hash_obj); - } - return (0); -} - -/* Look up the container_hdl in the PICL tree. */ -static container_hdl_t -ipmi_fru_open_container(picl_nodehdl_t fruh) -{ - int err; - hash_obj_t *cont_hash_obj; - - err = ptree_get_propval_by_name(fruh, PICL_PROP_FRUDATA_AVAIL, - NULL, NULL); - if (err != PICL_SUCCESS) { - return (0); - } - - cont_hash_obj = lookup_handle_object((handle_t)fruh, CONTAINER_TYPE); - if (cont_hash_obj == NULL) { - return (0); - } - - /* initialize the container */ - if (initialize_ipmi_container(fruh, cont_hash_obj) != 0) { - return (0); - } - return (cont_hash_obj->obj_hdl); -} - -/*ARGSUSED*/ -static int -ipmi_fru_get_num_sections(container_hdl_t container, door_cred_t *cred) -{ - hash_obj_t *cont_hash_obj; - - cont_hash_obj = lookup_handle_object((handle_t)container, - CONTAINER_TYPE); - if (cont_hash_obj == NULL) { - return (-1); - } - return (cont_hash_obj->u.cont_obj->num_of_section); -} - -/*ARGSUSED*/ -static int -ipmi_fru_get_sections(container_hdl_t container, section_t *section, - int max_sections, door_cred_t *cred) -{ - int count; - hash_obj_t *cont_object; - hash_obj_t *sec_hash; - - cont_object = lookup_handle_object((handle_t)container, - CONTAINER_TYPE); - if (cont_object == NULL) { - return (-1); - } - - if (cont_object->u.cont_obj->num_of_section > max_sections) { - return (-1); - } - sec_hash = cont_object->u.cont_obj->sec_obj_list; - - for (count = 0; count < cont_object->u.cont_obj->num_of_section && - sec_hash != NULL; count++, section++) { - /* populate section_t */ - section->handle = sec_hash->u.sec_obj->section.handle; - section->offset = sec_hash->u.sec_obj->section.offset; - section->length = sec_hash->u.sec_obj->section.length; - section->protection = sec_hash->u.sec_obj->section.protection; - section->version = sec_hash->u.sec_obj->section.version; - sec_hash = sec_hash->u.sec_obj->next; - } - return (count); -} - -/*ARGSUSED*/ -static int -ipmi_fru_get_num_segments(section_hdl_t section, door_cred_t *cred) -{ - hash_obj_t *sec_object; - - sec_object = lookup_handle_object((handle_t)section, SECTION_TYPE); - if (sec_object == NULL) { - return (-1); - } - return (sec_object->u.sec_obj->num_of_segment); -} - -/*ARGSUSED*/ -static int -ipmi_fru_get_segments(section_hdl_t section, segment_t *segment, - int max_segments, door_cred_t *cred) -{ - int count; - hash_obj_t *seg_hash; - hash_obj_t *sec_object; - - sec_object = lookup_handle_object((handle_t)section, SECTION_TYPE); - if (sec_object == NULL) { - return (-1); - } - - if (sec_object->u.sec_obj->num_of_segment > max_segments) { - return (-1); - } - - seg_hash = sec_object->u.sec_obj->seg_obj_list; - - for (count = 0; count < sec_object->u.sec_obj->num_of_segment && - seg_hash != NULL; count++, segment++) { - /* populate the segment info */ - segment->handle = seg_hash->u.seg_obj->segment.handle; - (void) memcpy(segment->name, seg_hash->u.seg_obj->segment.name, - SEG_NAME_LEN); - segment->descriptor = seg_hash->u.seg_obj->segment.descriptor; - segment->offset = seg_hash->u.seg_obj->segment.offset; - segment->length = seg_hash->u.seg_obj->segment.length; - seg_hash = seg_hash->u.seg_obj->next; - } - return (count); -} - -/*ARGSUSED*/ -static int -ipmi_fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred) -{ - hash_obj_t *seg_object; - - seg_object = lookup_handle_object((handle_t)segment, SEGMENT_TYPE); - if (seg_object == NULL) { - return (-1); - } - return (seg_object->u.seg_obj->num_of_packets); -} - -/*ARGSUSED*/ -static int -ipmi_fru_get_packets(segment_hdl_t segment, packet_t *packet, - int max_packets, door_cred_t *cred) -{ - int count; - hash_obj_t *pkt_hash; - hash_obj_t *seg_object; - - seg_object = lookup_handle_object((handle_t)segment, SEGMENT_TYPE); - if (seg_object == NULL) { - return (-1); - } - - if (seg_object->u.seg_obj->num_of_packets > max_packets) { - return (-1); - } - - pkt_hash = seg_object->u.seg_obj->pkt_obj_list; - - for (count = 0; count < seg_object->u.seg_obj->num_of_packets && - pkt_hash != NULL; count++, packet++) { - /* populate the segment info */ - packet->handle = pkt_hash->obj_hdl; - (void) memcpy(&packet->tag, &pkt_hash->u.pkt_obj->tag, 4); - pkt_hash = pkt_hash->u.pkt_obj->next; - } - - return (count); -} - -/*ARGSUSED*/ -static ssize_t -ipmi_fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes, - door_cred_t *cred) -{ - hash_obj_t *seg_hash; - hash_obj_t *pkt_hash; - - /* segment hash object */ - seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - if (seg_hash->u.seg_obj->segment.length < nbytes) { - return (-1); - } - - pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; - - if (pkt_hash == NULL) { - return (-1); - } - - (void) memcpy(buffer, &pkt_hash->u.pkt_obj->payload_data, - sizeof (payload_t)); - return (nbytes); -} - -/*ARGSUSED*/ -static ssize_t -ipmi_fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes, - door_cred_t *cred) -{ - hash_obj_t *packet_hash_obj; - - /* size = size of ManR */ - if (nbytes != MANR_SIZE) { - return (-1); - } - - /* packet hash object */ - packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE); - if (packet_hash_obj == NULL) { - return (-1); - } - - (void) memcpy(buffer, &(packet_hash_obj->u.pkt_obj->payload_data), - MANR_SIZE); - return (nbytes); -} - -/*ARGSUSED*/ -static int -ipmi_fru_add_segment(section_hdl_t section, segment_t *segment, - section_hdl_t *newsection, door_cred_t *cred) -{ - errno = ENOTSUP; - return (-1); -} - -/*ARGSUSED*/ -static int -ipmi_fru_delete_segment(segment_hdl_t segment, - section_hdl_t *newsection, door_cred_t *cred) -{ - errno = ENOTSUP; - return (-1); -} - - -/*ARGSUSED*/ -static ssize_t -ipmi_fru_write_segment(segment_hdl_t segment, const void *data, - size_t nbytes, segment_hdl_t *newsegment, door_cred_t *cred) -{ - errno = ENOTSUP; - return (-1); -} - -/*ARGSUSED*/ -static int -ipmi_fru_update_payload(packet_hdl_t packet, const void *data, - size_t nbytes, packet_hdl_t *newpacket, door_cred_t *cred) -{ - errno = ENOTSUP; - return (-1); -} - -/*ARGSUSED*/ -static int -ipmi_fru_append_packet(segment_hdl_t segment, packet_t *packet, - const void *payload, size_t nbytes, segment_hdl_t *newsegment, - door_cred_t *cred) -{ - errno = ENOTSUP; - return (-1); -} - -/*ARGSUSED*/ -static int -ipmi_fru_delete_packet(packet_hdl_t packet, - segment_hdl_t *newsegment, door_cred_t *cred) -{ - errno = ENOTSUP; - return (-1); -} - -static void -free_pkt_object_list(hash_obj_t *hash_obj) -{ - hash_obj_t *next_obj; - hash_obj_t *free_obj; - - next_obj = hash_obj->u.seg_obj->pkt_obj_list; - while (next_obj != NULL) { - free_obj = next_obj; - next_obj = next_obj->u.pkt_obj->next; - /* if prev is NULL it's the first object in the list */ - if (free_obj->prev == NULL) { - hash_table[(free_obj->obj_hdl % TABLE_SIZE)] = - free_obj->next; - if (free_obj->next != NULL) { - free_obj->next->prev = free_obj->prev; - } - } else { - free_obj->prev->next = free_obj->next; - if (free_obj->next != NULL) { - free_obj->next->prev = free_obj->prev; - } - } - - free(free_obj->u.pkt_obj); - free(free_obj); - } - - hash_obj->u.seg_obj->pkt_obj_list = NULL; -} - -static void -free_segment_hash(handle_t handle, hash_obj_t *sec_hash) -{ - hash_obj_t *seg_hash; - hash_obj_t *next_hash; - - seg_hash = sec_hash->u.sec_obj->seg_obj_list; - if (seg_hash == NULL) { - return; - } - - if (seg_hash->obj_hdl == handle) { - sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next; - } else { - while (seg_hash->obj_hdl != handle) { - next_hash = seg_hash; - seg_hash = seg_hash->u.seg_obj->next; - if (seg_hash == NULL) { - return; - } - } - next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next; - } - - if (seg_hash->prev == NULL) { - hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next; - if (seg_hash->next != NULL) { - seg_hash->next->prev = NULL; - } - } else { - seg_hash->prev->next = seg_hash->next; - if (seg_hash->next != NULL) { - seg_hash->next->prev = seg_hash->prev; - } - } - - free_pkt_object_list(seg_hash); - free(seg_hash->u.seg_obj); - free(seg_hash); -} - -static int -ipmi_fru_close_container(container_hdl_t container) -{ - hash_obj_t *hash_obj; - hash_obj_t *prev_hash; - hash_obj_t *sec_hash_obj; - handle_t obj_hdl; - - /* lookup for container hash object */ - hash_obj = lookup_handle_object(container, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (0); - } - - /* points to section object list */ - sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list; - - /* traverse section object list */ - while (sec_hash_obj != NULL) { - - /* traverse segment hash object in the section */ - while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) { - /* object handle of the segment hash object */ - obj_hdl = - sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl; - free_segment_hash(obj_hdl, sec_hash_obj); - } - - /* going to free section hash object, relink the hash object */ - if (sec_hash_obj->prev == NULL) { - hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] - = sec_hash_obj->next; - if (sec_hash_obj->next != NULL) { - sec_hash_obj->next->prev = NULL; - } - } else { - sec_hash_obj->prev->next = sec_hash_obj->next; - if (sec_hash_obj->next != NULL) { - sec_hash_obj->next->prev = sec_hash_obj->prev; - } - } - - free(sec_hash_obj->u.sec_obj); /* free section hash object */ - - prev_hash = sec_hash_obj; - - sec_hash_obj = sec_hash_obj->u.sec_obj->next; - - free(prev_hash); /* free section hash */ - } - - /* free container hash object */ - if (hash_obj->prev == NULL) { - hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] = - hash_obj->next; - if (hash_obj->next != NULL) { - hash_obj->next->prev = NULL; - } - } else { - hash_obj->prev->next = hash_obj->next; - if (hash_obj->next != NULL) { - hash_obj->next->prev = hash_obj->prev; - } - } - - free(hash_obj->u.cont_obj); - free(hash_obj); - return (0); -} - -/* opens the binary file and returns the file descriptor */ -static int -open_file() -{ - int fd; - - if ((fd = open(INPUT_FILE, O_RDWR)) == -1) { - return (-1); - } - return (fd); -} - -static void -copy_segment_layout(segment_t *seghdr, void *layout) -{ - segment_layout_t *seg_layout; - - seg_layout = (segment_layout_t *)layout; - (void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN); - seghdr->descriptor = GET_SEGMENT_DESCRIPTOR; - seghdr->offset = seg_layout->offset; - seghdr->length = seg_layout->length; -} - -static hash_obj_t * -get_container_hash_object(int object_type, handle_t handle) -{ - hash_obj_t *hash_obj; - - switch (object_type) { - case CONTAINER_TYPE : - break; - - case SECTION_TYPE : - hash_obj = lookup_handle_object(handle, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (NULL); - } - break; - case SEGMENT_TYPE : - hash_obj = lookup_handle_object(handle, SECTION_TYPE); - if (hash_obj == NULL) { - return (NULL); - } - hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - break; - case PACKET_TYPE : - - hash_obj = lookup_handle_object(handle, SEGMENT_TYPE); - if (hash_obj == NULL) { - return (NULL); - } - hash_obj = lookup_handle_object( - hash_obj->u.seg_obj->section_hdl, SECTION_TYPE); - if (hash_obj == NULL) { - return (NULL); - } - hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - break; - default : - return (NULL); - } - return (hash_obj); -} - -static void -sort_offsettbl(int segcnt, seg_info_t *offset_tbl) -{ - int cntx; - int cnty; - seg_info_t tmp; - - for (cntx = 0; cntx < segcnt+2; cntx++) { - for (cnty = cntx+1; cnty < segcnt + 2; cnty++) { - if (offset_tbl[cntx].offset > - offset_tbl[cnty].offset) { - (void) memcpy(&tmp, &offset_tbl[cnty], - sizeof (seg_info_t)); - (void) memcpy(&offset_tbl[cnty], - &offset_tbl[cntx], - sizeof (seg_info_t)); - - (void) memcpy(&offset_tbl[cntx], &tmp, - sizeof (seg_info_t)); - } - } - } -} - -/* - * Description : move_segment_data() reads the segment data and writes it - * back to the new segment offset. - */ - -static void -move_segment_data(void *seghdr, int newoffset, container_hdl_t contfd) -{ - int ret; - char *buffer; - segment_layout_t *segment; - format_t format; - hash_obj_t *cont_hash; - - segment = (segment_layout_t *)seghdr; - - buffer = alloca(segment->length); - if (buffer == NULL) { - return; - } - - cont_hash = lookup_handle_object((handle_t)contfd, CONTAINER_TYPE); - if (cont_hash == NULL) { - return; - } - - format = cont_hash->u.cont_obj->format; - - ret = pread_new(contfd, buffer, - segment->length, segment->offset, &format); - if (ret != segment->length) { - return; - } - - segment->offset = newoffset; - - ret = pwrite_new(contfd, buffer, segment->length, segment->offset, - &format); - if (ret != segment->length) { - return; - } -} - -/* - * Description : pack_segment_data() moves the segment data if there is - * a hole between two segments. - */ - -static void -pack_segment_data(char *seghdr, int segcnt, container_hdl_t contfd, - seg_info_t *offset_tbl) -{ - int cnt; - int diff; - int newoffset; - - for (cnt = segcnt + 1; cnt > 0; cnt--) { - if (!offset_tbl[cnt - 1].fixed) { - if (offset_tbl[cnt].offset - - (offset_tbl[cnt -1 ].offset - + offset_tbl[cnt - 1].length) > 0) { - - diff = offset_tbl[cnt].offset - - (offset_tbl[cnt - 1].offset - + offset_tbl[cnt - 1].length); - newoffset = offset_tbl[cnt - 1].offset - + diff; - - move_segment_data(seghdr, newoffset, - contfd); - - offset_tbl[cnt - 1].offset = newoffset; - - sort_offsettbl(segcnt, offset_tbl); - } - } - } -} - -/* - * Description : build_offset_tbl() builds the offset table by reading all the - * segment header. it makes two more entry into the table one for - * section size and another with start of the section after the - * segment header. - */ - -static int -build_offset_tbl(void *seghdr, int segcnt, int secsize, - seg_info_t *offset_tbl) -{ - int cnt; - fru_segdesc_t segdesc; - segment_layout_t *segment; - - for (cnt = 0; cnt < segcnt; cnt++) { - segment = (segment_layout_t *)(seghdr) + cnt; - - (void) memcpy(&segdesc, &segment->descriptor, - sizeof (uint32_t)); - offset_tbl[cnt].segnum = cnt; - offset_tbl[cnt].offset = segment->offset; - offset_tbl[cnt].length = segment->length; - offset_tbl[cnt].fixed = segdesc.field.fixed; - } - - /* upper boundary of segment area (lower address bytes) */ - offset_tbl[cnt].segnum = -1; - offset_tbl[cnt].offset = sizeof (section_layout_t) + ((cnt + 1) - * sizeof (segment_layout_t)); - - offset_tbl[cnt].length = 0; - offset_tbl[cnt].fixed = 1; - /* lower boundary of segment area (higher address bytes) */ - - offset_tbl[cnt+1].segnum = -1; - offset_tbl[cnt+1].offset = secsize; - offset_tbl[cnt+1].length = 0; - offset_tbl[cnt+1].fixed = 1; - return (0); -} - -static int -hole_discovery(int bytes, int segcnt, int *totsize, seg_info_t *offset_tbl) -{ - int cnt = 0; - - *totsize = 0; - for (cnt = segcnt + 1; cnt > 0; cnt--) { - if (bytes <= offset_tbl[cnt].offset - - (offset_tbl[cnt - 1].offset + - offset_tbl[cnt - 1].length)) { - return (offset_tbl[cnt].offset - bytes); - } - - *totsize += offset_tbl[cnt].offset - - (offset_tbl[cnt - 1].offset + - offset_tbl[cnt - 1].length); - } - return (0); -} - - -/* - * Description : segment_hdr_present() verify space for new segment header to - * be added. - */ - -static int -segment_hdr_present(int segoffset, int size, seg_info_t *offset_tbl) -{ - if ((segoffset + size) <= offset_tbl[0].offset) - return (0); - else - return (-1); -} - -/* - * Description : find_offset() is called from fru_add_segment routine to find - * a valid offset. - */ - -static int -find_offset(char *seghdr, int segcnt, int secsize, int *sectionoffset, - int segsize, int fix, container_hdl_t contfd) -{ - int ret; - int newoffset; - int totsize = 0; - seg_info_t *offset_tbl; - - if (segcnt == 0) { - if (!fix) { /* if not fixed segment */ - *sectionoffset = secsize - segsize; - } - return (0); - } - - /* - * two extra segment info structure are allocated for start of segment - * and other end of segment. first segment offset is first available - * space and length is 0. second segment offset is is segment length and - * offset is 0. build_offset_tbl() explains how upper boundary and lower - * boudary segment area are initialized in seg_info_t table. - */ - - offset_tbl = malloc((segcnt + 2) * sizeof (seg_info_t)); - if (offset_tbl == NULL) { - return (-1); - } - - /* read all the segment header to make offset table */ - ret = build_offset_tbl(seghdr, segcnt, secsize, offset_tbl); - if (ret != 0) { - free(offset_tbl); - return (-1); - } - - /* sort the table */ - sort_offsettbl(segcnt, offset_tbl); - - /* new segment header offset */ - newoffset = sizeof (section_layout_t) + segcnt * - sizeof (segment_layout_t); - - /* do? new segment header overlap any existing data */ - ret = segment_hdr_present(newoffset, sizeof (segment_layout_t), - offset_tbl); - if (ret != 0) { /* make room for new segment if possible */ - - /* look for hole in order to move segment data */ - if (offset_tbl[0].fixed == SEGMENT_FIXED) { /* fixed segment */ - free(offset_tbl); - return (-1); - } - - newoffset = hole_discovery(offset_tbl[0].length, - segcnt, &totsize, offset_tbl); - if (newoffset != 0) { /* found new offset */ - /* now new offset */ - offset_tbl[0].offset = newoffset; - - /* move the segment data */ - move_segment_data(seghdr, newoffset, contfd); - /* again sort the offset table */ - sort_offsettbl(segcnt, offset_tbl); - } else { - /* pack the existing hole */ - if (totsize > offset_tbl[0].length) { - pack_segment_data(seghdr, segcnt, - contfd, offset_tbl); - } else { - free(offset_tbl); - return (-1); - } - } - } - - totsize = 0; - newoffset = hole_discovery(segsize, segcnt, &totsize, offset_tbl); - - if (newoffset == 0) { /* No hole found */ - if (totsize >= segsize) { - pack_segment_data(seghdr, segcnt, contfd, - offset_tbl); - newoffset = hole_discovery(segsize, segcnt, - &totsize, offset_tbl); - if (newoffset != 0) { - *sectionoffset = newoffset; - free(offset_tbl); - return (0); - } - } - } else { - *sectionoffset = newoffset; - free(offset_tbl); - return (0); - } - free(offset_tbl); - return (-1); -} - -/* - * Description :sun_fru_open_container() opens the container associated with - * a fru. it's called by data plugin module before creating - * container property. it calls picltree library routine to get - * the device path and driver binding name for the fru to get the - * corresponding fru name that describe the fru layout. - * - * Arguments :picl_hdl_t fru - * A handle for PICL tree node of class "fru" representing the - * FRU with the container to open. - * - * Return : - * On Success, a Positive integer container handle. is returned - * for use in subsequent fru operations;on error, 0 is returned - * and "errno" is set appropriately. - */ -static container_hdl_t -sun_fru_open_container(picl_nodehdl_t fruhdl) -{ - int count; - hash_obj_t *cont_hash_obj; - hash_obj_t *sec_hash_obj; - - cont_hash_obj = lookup_handle_object((handle_t)fruhdl, CONTAINER_TYPE); - if (cont_hash_obj == NULL) { - return (NULL); - } - - cont_hash_obj->u.cont_obj->num_of_section = NUM_OF_SECTIONS; - cont_hash_obj->u.cont_obj->sec_obj_list = NULL; - - for (count = 0; count < NUM_OF_SECTIONS; count++) { - sec_hash_obj = create_section_hash_object(); - if (sec_hash_obj == NULL) { - return (NULL); - } - - add_hashobject_to_hashtable(sec_hash_obj, SECTION_TYPE); - - if (count == 0) { - sec_hash_obj->u.sec_obj->section.offset = - DYNAMIC_OFFSET; - sec_hash_obj->u.sec_obj->section.protection = - WRITE_SECTION; - sec_hash_obj->u.sec_obj->section.length = - DYNAMIC_LENGTH; - } else { - sec_hash_obj->u.sec_obj->section.offset = STATIC_OFFSET; - sec_hash_obj->u.sec_obj->section.protection = - READ_ONLY_SECTION; - sec_hash_obj->u.sec_obj->section.length = STATIC_LENGTH; - } - - sec_hash_obj->u.sec_obj->section.version = SECTION_HDR_VER; - - add_to_sec_object_list(cont_hash_obj, sec_hash_obj); - } - - return (cont_hash_obj->obj_hdl); -} - -static int -verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length) -{ - int crc_offset = 0; - unsigned char orig_crc8 = 0; - unsigned char calc_crc8 = 0; - - switch (head_ver) { - case SECTION_HDR_VER: - crc_offset = 4; - break; - default: - errno = EINVAL; - return (0); - } - - orig_crc8 = bytes[crc_offset]; - bytes[crc_offset] = 0x00; /* clear for calc */ - calc_crc8 = compute_crc8(bytes, length); - bytes[crc_offset] = orig_crc8; /* restore */ - - return (orig_crc8 == calc_crc8); -} - -/* - * Description : - * sun_fru_get_num_sections() returns number of sections in a - * container. it calls get_container_index() to get the container - * index number in the container list. - * - * Arguments : - * container_hdl_t : container handle. - * - * Return : - * int - * On success, returns number of sections in a container. - * - */ -/*ARGSUSED*/ -static int -sun_fru_get_num_sections(container_hdl_t container, door_cred_t *cred) -{ - hash_obj_t *hash_object; - - hash_object = lookup_handle_object(container, CONTAINER_TYPE); - if (hash_object == NULL) { - return (-1); - } - - return (hash_object->u.cont_obj->num_of_section); -} - -/* - * called from fru_get_sections() - */ - -static void -get_section(int fd, hash_obj_t *sec_hash, section_t *section) -{ - int retval; - int size; - int count; - uint16_t hdrver; - hash_obj_t *seg_hash; - unsigned char *buffer; - section_obj_t *sec_obj; - section_layout_t sec_hdr; - segment_layout_t *seg_hdr; - segment_layout_t *seg_buf; - format_t format; - hash_obj_t *cont_hash; - - sec_obj = sec_hash->u.sec_obj; - if (sec_obj == NULL) { - return; - } - - /* populate section_t */ - section->handle = sec_hash->obj_hdl; - section->offset = sec_obj->section.offset; - section->length = sec_obj->section.length; - section->protection = sec_obj->section.protection; - section->version = sec_obj->section.version; - sec_obj->num_of_segment = 0; - - cont_hash = get_container_hash_object(SEGMENT_TYPE, sec_hash->obj_hdl); - if (cont_hash == NULL) { - return; - } - - format = cont_hash->u.cont_obj->format; - - /* read section header layout */ - retval = pread_new(fd, &sec_hdr, sizeof (sec_hdr), - sec_obj->section.offset, &format); - if (retval != sizeof (sec_hdr)) { - return; - } - - hdrver = GET_SECTION_HDR_VERSION; - - if ((sec_hdr.headertag != SECTION_HDR_TAG) && - (hdrver != section->version)) { - return; - } - - /* size = section layout + total sizeof segment header */ - size = sizeof (sec_hdr) + ((sec_hdr.segmentcount) - * sizeof (segment_layout_t)); - buffer = alloca(size); - if (buffer == NULL) { - return; - } - - /* segment header buffer */ - seg_buf = alloca(size - sizeof (sec_hdr)); - if (seg_buf == NULL) { - return; - } - - /* read segment header */ - retval = pread_new(fd, seg_buf, size - sizeof (sec_hdr), - sec_obj->section.offset + sizeof (sec_hdr), &format); - if (retval != (size - sizeof (sec_hdr))) { - return; - } - - /* copy section header layout */ - (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr)); - - /* copy segment header layout */ - (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size - - sizeof (sec_hdr)); - - /* verify crc8 */ - retval = verify_header_crc8(hdrver, buffer, size); - if (retval != TRUE) { - return; - } - - section->version = hdrver; - sec_obj->section.version = hdrver; - - seg_hdr = (segment_layout_t *)seg_buf; - - for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) { - seg_hash = create_segment_hash_object(); - if (seg_hash == NULL) { - return; - } - - add_hashobject_to_hashtable(seg_hash, SEGMENT_TYPE); - - copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr); - - add_to_seg_object_list(sec_hash, seg_hash); - - sec_obj->num_of_segment++; - } -} - -/* - * Description : - * sun_fru_get_sections() fills an array of section structures - * passed as an argument. - * - * Arguments : - * container_hdl_t : container handle(device descriptor). - * section_t : array of section structure. - * int : maximum number of section in a container. - * - * Returns : - * int - * On success,the number of section structures written is returned; - * on error, -1 is returned and "errno" is set appropriately. - * - */ -/*ARGSUSED*/ -static int -sun_fru_get_sections(container_hdl_t container, section_t *section, int maxsec, - door_cred_t *cred) -{ - int device_fd; - int count; - hash_obj_t *cont_object; - hash_obj_t *sec_hash; - - cont_object = lookup_handle_object(container, CONTAINER_TYPE); - if (cont_object == NULL) { - return (-1); - } - - if (cont_object->u.cont_obj->num_of_section > maxsec) { - return (-1); - } - - sec_hash = cont_object->u.cont_obj->sec_obj_list; - if (sec_hash == NULL) { - return (-1); - } - - device_fd = open_file(); - - if (device_fd < 0) { - return (-1); - } - - for (count = 0; count < cont_object->u.cont_obj->num_of_section; - count++, section++) { - section->version = -1; - /* populate section_t */ - get_section(device_fd, sec_hash, section); - sec_hash = sec_hash->u.sec_obj->next; - } - - (void) close(device_fd); - - return (count); -} - -/* - * Description : - * sun_fru_get_num_segments() returns the current number of - * segments in a section. - * - * Arguments : - * section_hdl_t : section header holding section information. - * - * Return : - * int - * On success, the number of segments in the argument section is - * returned; on error -1 is returned. - */ -/*ARGSUSED*/ -static int -sun_fru_get_num_segments(section_hdl_t section, door_cred_t *cred) -{ - hash_obj_t *sec_object; - section_obj_t *sec_obj; - - sec_object = lookup_handle_object(section, SECTION_TYPE); - if (sec_object == NULL) { - return (-1); - } - - sec_obj = sec_object->u.sec_obj; - if (sec_obj == NULL) { - return (-1); - } - - return (sec_obj->num_of_segment); -} - -/* - * Description : - * sun_fru_get_segments() fills an array of structures - * representing the segments in a section. - * - * Arguments : - * section_hdl_t : holds section number. - * segment_t : on success will hold segment information. - * int : maximum number of segment. - * - * Return : - * int - * On success, the number of segment structures written is - * returned; on errno -1 is returned. - */ -/* ARGSUSED */ -static int -sun_fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg, - door_cred_t *cred) -{ - int count; - hash_obj_t *sec_object; - hash_obj_t *seg_object; - section_obj_t *sec_obj; - - sec_object = lookup_handle_object(section, SECTION_TYPE); - if (sec_object == NULL) { - return (-1); - } - - sec_obj = sec_object->u.sec_obj; - if (sec_obj == NULL) { - return (-1); - } - - if (sec_obj->num_of_segment > maxseg) { - return (-1); - } - - seg_object = sec_object->u.sec_obj->seg_obj_list; - if (seg_object == NULL) { - return (-1); - } - - for (count = 0; count < sec_obj->num_of_segment; count++) { - - /* populate segment_t */ - segment->handle = seg_object->obj_hdl; - (void) memcpy(segment->name, - seg_object->u.seg_obj->segment.name, SEG_NAME_LEN); - segment->descriptor = seg_object->u.seg_obj->segment.descriptor; - segment->offset = seg_object->u.seg_obj->segment.offset; - segment->length = seg_object->u.seg_obj->segment.length; - seg_object = seg_object->u.seg_obj->next; - segment++; - } - return (0); -} - -/* - * Description : - * sun_fru_add_segment() adds a segment to a section. - * - * Arguments : - * section_hdl_t section - * A handle for the section in which to add the segment. - * - * segment_t *segment - * On entry, the "handle" component of "segment" is ignored and the - * remaining components specify the parameters of the segment to be - * added. On return, the "handle" component is set to the handle - * for the added segment. The segment offset is mandatory for FIXED - * segments; otherwise, the offset is advisory. - * - * Return : - * int - * On success, 0 is returned; on error -1 is returned. - * - */ -static int -sun_fru_add_segment(section_hdl_t section, segment_t *segment, - section_hdl_t *newsection, door_cred_t *cred) -{ - int fd; - int retval; - int offset; - int sec_size; - int seg_cnt; - int bufsize; - int new_seg_offset; - int new_seg_length; - int fixed_segment; - char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00 }; - hash_obj_t *cont_hash; - hash_obj_t *sec_hash; - hash_obj_t *seg_hash; - fru_segdesc_t *new_seg_desc; - unsigned char *crcbuf; - section_layout_t sec_layout; - segment_layout_t *seg_layout; - segment_layout_t *segment_buf; - format_t format; - - /* check the effective uid of the client */ - if (cred->dc_euid != 0) { - errno = EPERM; - return (-1); /* not a root */ - } - - /* section hash */ - sec_hash = lookup_handle_object(section, SECTION_TYPE); - if (sec_hash == NULL) { - return (-1); - } - - /* check for read-only section */ - if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { - errno = EPERM; - return (-1); - } - - /* look for duplicate segment */ - seg_hash = sec_hash->u.sec_obj->seg_obj_list; - while (seg_hash != NULL) { - if (strncmp(segment->name, seg_hash->u.seg_obj->segment.name, - SEG_NAME_LEN) == 0) { - errno = EEXIST; - return (-1); /* can't add duplicate segment */ - } - seg_hash = seg_hash->u.seg_obj->next; - } - - /* get the container hash */ - cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - if (cont_hash == NULL) { - return (-1); - } - - format = cont_hash->u.cont_obj->format; - - /* open the container */ - fd = open_file(); - if (fd < 0) { - return (-1); - } - - /* section start here */ - offset = sec_hash->u.sec_obj->section.offset; - - /* read section header layout */ - retval = pread_new(fd, &sec_layout, sizeof (sec_layout), offset, - &format); - if (retval != sizeof (sec_layout)) { - (void) close(fd); - return (-1); - } - - /* check for valid section header */ - if (sec_layout.headertag != SECTION_HDR_TAG) { - /* write a new one */ - sec_layout.headertag = SECTION_HDR_TAG; - sec_layout.headerversion[0] = SECTION_HDR_VER_BIT0; - sec_layout.headerversion[1] = SECTION_HDR_VER_BIT1; - sec_layout.headerlength = sizeof (sec_layout); - sec_layout.segmentcount = 0; - } - - /* section size */ - sec_size = sec_hash->u.sec_obj->section.length; - - /* number of segment in the section */ - seg_cnt = sec_layout.segmentcount; - - /* total sizeof segment + new segment */ - bufsize = sizeof (segment_layout_t) * (seg_cnt + 1); - segment_buf = alloca(bufsize); - if (segment_buf == NULL) { - return (-1); - } - - /* read entire segment header */ - retval = pread_new(fd, segment_buf, - (bufsize - sizeof (segment_layout_t)), - offset + sizeof (section_layout_t), &format); - if (retval != (bufsize - sizeof (segment_layout_t))) { - (void) close(fd); - return (-1); - } - - new_seg_offset = segment->offset; /* new segment offset */ - new_seg_length = segment->length; /* new segment length */ - - new_seg_desc = (fru_segdesc_t *)&segment->descriptor; - - fixed_segment = new_seg_desc->field.fixed; - - /* get new offset for new segment to be addedd */ - retval = find_offset((char *)segment_buf, seg_cnt, sec_size, - &new_seg_offset, new_seg_length, fixed_segment, fd); - - if (retval != 0) { - (void) close(fd); - errno = EAGAIN; - return (-1); - } - - /* copy new segment data in segment layout */ - seg_layout = (segment_layout_t *)(segment_buf + seg_cnt); - (void) memcpy(&seg_layout->name, segment->name, SEG_NAME_LEN); - (void) memcpy(seg_layout->descriptor, &segment->descriptor, - sizeof (uint32_t)); - seg_layout->length = segment->length; - seg_layout->offset = new_seg_offset; /* new segment offset */ - - sec_layout.segmentcount += 1; - - crcbuf = alloca(sizeof (section_layout_t) + bufsize); - if (crcbuf == NULL) { - (void) close(fd); - return (-1); - } - - sec_layout.headercrc8 = 0; - sec_layout.headerlength += sizeof (segment_layout_t); - - (void) memcpy(crcbuf, (char *)&sec_layout, sizeof (section_layout_t)); - (void) memcpy(crcbuf + sizeof (section_layout_t), segment_buf, bufsize); - - sec_layout.headercrc8 = compute_crc8(crcbuf, bufsize + - sizeof (section_layout_t)); - - /* write section header */ - retval = pwrite_new(fd, &sec_layout, sizeof (section_layout_t), - offset, &format); - if (retval != sizeof (section_layout_t)) { - (void) close(fd); - return (-1); - } - - /* write segment header */ - retval = pwrite_new(fd, segment_buf, bufsize, offset + - sizeof (section_layout_t), &format); - if (retval != bufsize) { - (void) close(fd); - return (-1); - } - - /* write segment trailer */ - retval = pwrite_new(fd, &trailer, sizeof (trailer), new_seg_offset, - &format); - if (retval != sizeof (trailer)) { - (void) close(fd); - return (-1); - } - - (void) close(fd); - - /* create new segment hash object */ - seg_hash = create_segment_hash_object(); - if (seg_hash == NULL) { - return (-1); - } - - add_hashobject_to_hashtable(seg_hash, SEGMENT_TYPE); - - copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_layout); - - add_to_seg_object_list(sec_hash, seg_hash); - - sec_hash->u.sec_obj->num_of_segment += 1; - seg_hash->u.seg_obj->trailer_offset = new_seg_offset; - *newsection = section; /* return the new section handle */ - return (0); -} - -/* - * Description : - * sun_fru_delete_segment() deletes a segment from a section; the - * associated container data is not altered. - * - * Arguments : segment_hdl_t segment handle. - * section_hdl_t new section handle. - * - * Return : - * int - * On success, 0 returned; On error -1 is returned. - */ -static int -sun_fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection, - door_cred_t *cred) -{ - int num_of_seg; - int bufsize; - int count; - int retval; - int fd; - int segnum; - hash_obj_t *seg_hash; - hash_obj_t *sec_hash; - hash_obj_t *cont_hash; - hash_obj_t *tmp_hash; - unsigned char *buffer; - fru_segdesc_t *desc; - segment_layout_t *seg_buf; - section_layout_t *sec_layout; - segment_layout_t *seg_layout; - segment_layout_t *next_layout; - format_t format; - - /* check the effective uid of the client */ - if (cred->dc_euid != 0) { - errno = EPERM; - return (-1); /* not a root */ - } - - seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; - if (!(desc->field.field_perm & SEGMENT_DELETE)) { - errno = EPERM; - return (-1); /* can't delete this segment */ - } - - sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, - SECTION_TYPE); - if (sec_hash == NULL) { - return (-1); - } - - if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { - errno = EPERM; - return (-1); - } - - num_of_seg = sec_hash->u.sec_obj->num_of_segment; - - bufsize = (sizeof (segment_layout_t) * num_of_seg); - - seg_buf = alloca(bufsize); - if (seg_buf == NULL) { - return (-1); - } - - segnum = 0; - for (tmp_hash = sec_hash->u.sec_obj->seg_obj_list; tmp_hash != NULL; - tmp_hash = tmp_hash->u.seg_obj->next) { - if (tmp_hash->obj_hdl == segment) { - break; - } - segnum++; - } - - cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - if (cont_hash == NULL) { - return (-1); - } - format = cont_hash->u.cont_obj->format; - - fd = open_file(); - if (fd < 0) { - return (-1); - } - - sec_layout = alloca(sizeof (section_layout_t)); - if (sec_layout == NULL) { - (void) close(fd); - return (-1); - } - - /* read section layout header */ - retval = pread_new(fd, sec_layout, sizeof (section_layout_t), - sec_hash->u.sec_obj->section.offset, &format); - if (retval != sizeof (section_layout_t)) { - (void) close(fd); - return (-1); - } - - /* read segment header layout */ - retval = pread_new(fd, seg_buf, bufsize, - sec_hash->u.sec_obj->section.offset + - sizeof (section_layout_t), &format); - if (retval != bufsize) { - (void) close(fd); - return (-1); - } - - seg_layout = (segment_layout_t *)(seg_buf + segnum); - next_layout = seg_layout; - for (count = segnum; count < sec_hash->u.sec_obj->num_of_segment-1; - count++) { - next_layout++; - (void) memcpy(seg_layout, next_layout, - sizeof (segment_layout_t)); - seg_layout++; - } - - (void) memset(seg_layout, '\0', sizeof (segment_layout_t)); - - sec_layout->headercrc8 = 0; - - sec_layout->headerlength -= sizeof (segment_layout_t); - sec_layout->segmentcount -= 1; - - buffer = alloca(sec_layout->headerlength); - if (buffer == NULL) { - (void) close(fd); - return (-1); - } - - (void) memcpy(buffer, sec_layout, sizeof (section_layout_t)); - (void) memcpy(buffer + sizeof (section_layout_t), seg_buf, bufsize - - sizeof (segment_layout_t)); - sec_layout->headercrc8 = compute_crc8(buffer, - sec_layout->headerlength); - - /* write section header with update crc8 and header length */ - retval = pwrite_new(fd, sec_layout, sizeof (section_layout_t), - sec_hash->u.sec_obj->section.offset, &format); - if (retval != sizeof (section_layout_t)) { - (void) close(fd); - return (-1); - } - - /* write the update segment header */ - retval = pwrite_new(fd, seg_buf, bufsize, - sec_hash->u.sec_obj->section.offset + - sizeof (section_layout_t), &format); - (void) close(fd); - if (retval != bufsize) { - return (-1); - } - - free_segment_hash(segment, sec_hash); - - *newsection = sec_hash->obj_hdl; - sec_hash->u.sec_obj->num_of_segment = sec_layout->segmentcount; - - return (0); -} - -/* - * Description : - * sun_fru_read_segment() reads the raw contents of a segment. - * - * Arguments : segment_hdl_t : segment handle. - * void * : buffer containing segment data when function returns. - * size_t :number of bytes. - * - * Return : - * int - * On success, the number of bytes read is returned; - * - * Notes : - * Segments containing packets can be read in structured fashion - * using the fru_get_packets() and fru_get_payload() primitives;the - * entire byte range of a segment can be read using - * fru_read_segment(). - */ -/*ARGSUSED*/ -static ssize_t -sun_fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes, - door_cred_t *cred) -{ - int fd; - int retval; - hash_obj_t *seg_hash; - hash_obj_t *sec_hash; - hash_obj_t *cont_hash; - format_t format; - - /* segment hash object */ - seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - /* section hash object */ - sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, - SECTION_TYPE); - if (sec_hash == NULL) { - return (-1); - } - - /* container hash object */ - cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - if (cont_hash == NULL) { - return (-1); - } - format = cont_hash->u.cont_obj->format; - - if (seg_hash->u.seg_obj->segment.length < nbytes) { - return (-1); - } - - fd = open_file(); - if (fd < 0) { - return (-1); - } - - retval = pread_new(fd, buffer, nbytes, - seg_hash->u.seg_obj->segment.offset, &format); - (void) close(fd); - if (retval != nbytes) { - return (-1); - } - return (nbytes); -} - -/* - * Description : - * sun_fru_write_segment() writes a raw segment. - * - * Arguments : segment_hdl_t :segment handle. - * const void * : data buffer. - * size_t : number of bytes. - * segment_hdl_t : new segment handle. - * - * Returns : - * int - * On success, the number of bytes written is returned - * - */ -/*ARGSUSED*/ -static int -sun_fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes, - segment_hdl_t *newsegment, door_cred_t *cred) -{ - return (ENOTSUP); -} - - -static int -get_packet(int device_fd, void *buffer, int size, int offset, format_t *format) -{ - int retval; - - retval = pread_new(device_fd, (char *)buffer, size, offset, format); - if (retval != -1) { - return (0); - } - return (-1); -} - -static uint32_t -get_checksum_crc(hash_obj_t *seg_hash, int data_size) -{ - int protection; - int offset = 0; - uint32_t crc; - hash_obj_t *sec_hash; - hash_obj_t *pkt_hash; - unsigned char *buffer; - - sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, - SECTION_TYPE); - if (sec_hash == NULL) { - return ((uint32_t)-1); - } - - buffer = alloca(data_size); - if (buffer == NULL) { - return ((uint32_t)-1); - } - - /* traverse the packet object list for all the tags and payload */ - for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; pkt_hash != NULL; - pkt_hash = pkt_hash->u.pkt_obj->next) { - (void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag, - pkt_hash->u.pkt_obj->tag_size); - offset += pkt_hash->u.pkt_obj->tag_size; - (void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload, - pkt_hash->u.pkt_obj->paylen); - offset += pkt_hash->u.pkt_obj->paylen; - } - - protection = sec_hash->u.sec_obj->section.protection; - - if (protection == READ_ONLY_SECTION) { /* read-only section */ - crc = compute_crc32(buffer, data_size); - } else { /* read/write section */ - crc = compute_checksum32(buffer, data_size); - } - return (crc); /* computed crc */ -} - -static int -get_packets(hash_obj_t *seg_hash, int device_fd, int offset, int length) -{ - int tag_size; - int paylen; - int retval; - int seg_limit = 0; - int pktcnt = 0; - char *data; - uint32_t crc; - uint32_t origcrc; - fru_tag_t tag; - hash_obj_t *pkt_hash_obj; - fru_segdesc_t *segdesc; - fru_tagtype_t tagtype; - format_t format; - hash_obj_t *cont_hash; - - cont_hash = get_container_hash_object(PACKET_TYPE, seg_hash->obj_hdl); - if (cont_hash == NULL) { - return (NULL); - } - format = cont_hash->u.cont_obj->format; - - retval = get_packet(device_fd, &tag, sizeof (fru_tag_t), offset, - &format); - if (retval == -1) { - return (-1); - } - - seg_hash->u.seg_obj->trailer_offset = offset; - - data = (char *)&tag; - while (data[0] != SEG_TRAILER_TAG) { - tagtype = get_tag_type(&tag); /* verify tag type */ - if (tagtype == -1) { - return (-1); - } - - tag_size = get_tag_size(tagtype); - if (tag_size == -1) { - return (-1); - } - - seg_limit += tag_size; - if (seg_limit > length) { - return (-1); - } - - paylen = get_payload_length((void *)&tag); - if (paylen == -1) { - return (-1); - } - - seg_limit += paylen; - if (seg_limit > length) { - return (-1); - } - - pkt_hash_obj = create_packet_hash_object(); - if (pkt_hash_obj == NULL) { - return (-1); - } - - pkt_hash_obj->u.pkt_obj->payload = malloc(paylen); - if (pkt_hash_obj->u.pkt_obj->payload == NULL) { - free(pkt_hash_obj); - return (-1); - } - - offset += tag_size; - retval = pread_new(device_fd, pkt_hash_obj->u.pkt_obj->payload, - paylen, offset, &format); - if (retval != paylen) { - free(pkt_hash_obj->u.pkt_obj->payload); - free(pkt_hash_obj); - return (-1); - } - - /* don't change this */ - pkt_hash_obj->u.pkt_obj->tag.raw_data = 0; - (void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size); - pkt_hash_obj->u.pkt_obj->paylen = paylen; - pkt_hash_obj->u.pkt_obj->tag_size = tag_size; - pkt_hash_obj->u.pkt_obj->payload_offset = offset; - - offset += paylen; - - add_hashobject_to_hashtable(pkt_hash_obj, PACKET_TYPE); - add_to_pkt_object_list(seg_hash, pkt_hash_obj); - - pktcnt++; - - retval = get_packet(device_fd, &tag, sizeof (fru_tag_t), - offset, &format); - if (retval == -1) { - return (retval); - } - - data = (char *)&tag; - } - - segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; - - seg_hash->u.seg_obj->trailer_offset = offset; - - if (!segdesc->field.ignore_checksum) { - crc = get_checksum_crc(seg_hash, seg_limit); - offset = seg_hash->u.seg_obj->segment.offset; - - retval = pread_new(device_fd, &origcrc, sizeof (origcrc), - offset + seg_limit + 1, &format); - if (retval != sizeof (origcrc)) { - return (-1); - } - - if (origcrc != crc) { - seg_hash->u.seg_obj->trailer_offset = offset; - return (-1); - } - } - return (pktcnt); -} - -/* - * Description : - * sun_fru_get_num_packets() returns the current number of packets - * in a segment. - * - * Arguments : segment_hdl_t : segment handle. - * - * Return : - * int - * On success, the number of packets is returned; - * -1 on failure. - */ -/*ARGSUSED*/ -static int -sun_fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred) -{ - int device_fd; - int pktcnt; - int length; - uint16_t offset; - hash_obj_t *cont_hash_obj; - hash_obj_t *seg_hash; - fru_segdesc_t *segdesc; - segment_obj_t *segment_object; - - seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - segment_object = seg_hash->u.seg_obj; - if (segment_object == NULL) { - return (-1); - } - - - segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor; - if (segdesc->field.opaque) { - return (0); - } - - offset = segment_object->segment.offset; - length = segment_object->segment.length; - - cont_hash_obj = get_container_hash_object(SEGMENT_TYPE, - segment_object->section_hdl); - - if (cont_hash_obj == NULL) { - return (-1); - } - - if (seg_hash->u.seg_obj->pkt_obj_list != NULL) { - return (segment_object->num_of_packets); - } - - segment_object->num_of_packets = 0; - device_fd = open_file(); - if (device_fd < 0) { - return (-1); - } - - pktcnt = get_packets(seg_hash, device_fd, offset, - length); - if (pktcnt == -1) { - free_pkt_object_list(seg_hash); - seg_hash->u.seg_obj->pkt_obj_list = NULL; - } - - segment_object->num_of_packets = pktcnt; - (void) close(device_fd); - - return (segment_object->num_of_packets); -} - -/* - * Description : - * sun_fru_get_packets() fills an array of structures - * representing the packets in a segment. - * - * Arguments : segment_hdl_t : segment handle. - * packet_t : packet buffer. - * int : maximum number of packets. - * - * Return : - * int - * On success, the number of packet structures written is returned; - * On failure -1 is returned; - * - */ -/*ARGSUSED*/ -static int -sun_fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets, - door_cred_t *cred) -{ - int count; - hash_obj_t *seg_hash_obj; - hash_obj_t *pkt_hash_obj; - - /* segment hash object */ - seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE); - if (seg_hash_obj == NULL) { - return (-1); - } - - if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) { - return (-1); - } - - pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list; - if (pkt_hash_obj == NULL) { - return (-1); - } - - for (count = 0; count < maxpackets; count++, packet++) { - packet->handle = pkt_hash_obj->obj_hdl; - packet->tag = 0; - (void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag, - pkt_hash_obj->u.pkt_obj->tag_size); - pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next; - } - - return (0); -} - -/* - * Description : - * sun_fru_get_payload() copies the contents of a packet's payload. - * - * Arguments : packet_hdl_t : packet handle. - * void * : payload buffer. - * size_t : sizeof the buffer. - * - * Return : - * int - * On success, the number of bytes copied is returned; On error - * -1 returned. - */ -/*ARGSUSED*/ -static ssize_t -sun_fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes, - door_cred_t *cred) -{ - hash_obj_t *packet_hash_obj; - - /* packet hash object */ - packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE); - if (packet_hash_obj == NULL) { - return (-1); - } - - /* verify payload length */ - if (nbytes != packet_hash_obj->u.pkt_obj->paylen) { - return (-1); - } - - (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes); - return (nbytes); -} - -/* - * Description : - * sun_fru_update_payload() writes the contents of a packet's - * payload. - * - * Arguments : packet_hdl_t : packet handle. - * const void * : data buffer. - * size_t : buffer size. - * packet_hdl_t : new packet handle. - * - * Return : - * int - * On success, 0 is returned; on failure - * -1 is returned. - */ -/*ARGSUSED*/ -static int -sun_fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes, - packet_hdl_t *newpacket, door_cred_t *cred) -{ - int fd; - int segment_offset; - int trailer_offset; - int retval; - uint32_t crc; - hash_obj_t *pkt_hash; - hash_obj_t *seg_hash; - hash_obj_t *sec_hash; - hash_obj_t *cont_hash; - fru_segdesc_t *desc; - format_t format; - - /* check the effective uid of the client */ - if (cred->dc_euid != 0) { - errno = EPERM; - return (-1); /* not a root */ - } - - /* packet hash object */ - pkt_hash = lookup_handle_object(packet, PACKET_TYPE); - if (pkt_hash == NULL) { - return (-1); - } - - /* segment hash object */ - seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl, - SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - /* check for write perm. */ - desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; - if (!(desc->field.field_perm & SEGMENT_WRITE)) { - errno = EPERM; - return (-1); /* write not allowed */ - } - - sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, - SECTION_TYPE); - if (sec_hash == NULL) { - return (-1); - } - - if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { - errno = EPERM; - return (-1); /* read-only section */ - } - - cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - if (cont_hash == NULL) { - return (-1); - } - - format = cont_hash->u.cont_obj->format; - - if (pkt_hash->u.pkt_obj->paylen != nbytes) { - return (-1); - } - - (void) memcpy(pkt_hash->u.pkt_obj->payload, (char *)data, nbytes); - fd = open_file(); - if (fd < 0) { - return (-1); - } - - trailer_offset = seg_hash->u.seg_obj->trailer_offset; - segment_offset = seg_hash->u.seg_obj->segment.offset; - - crc = get_checksum_crc(seg_hash, (trailer_offset - segment_offset)); - retval = pwrite_new(fd, data, nbytes, - pkt_hash->u.pkt_obj->payload_offset, &format); - if (retval != nbytes) { - (void) close(fd); - return (-1); - } - - retval = pwrite_new(fd, &crc, sizeof (crc), - trailer_offset + 1, &format); - (void) close(fd); - if (retval != sizeof (crc)) { - return (-1); - } - *newpacket = packet; - return (0); -} - -/* - * Description : - * sun_fru_append_packet() appends a packet to a segment. - * - * Arguments : - * segment_hdl_t segment - * A handle for the segment to which the packet will be appended. - * - * packet_t *packet - * On entry, the "tag" component of "packet" specifies the tag - * value for the added packet; the "handle" component is ignored. - * On return, the "handle" component is set to the handle of the - * appended packet. - * - * const void *payload - * A pointer to the caller's buffer containing the payload data for - * the appended packet. - * - * size_t nbytes - * The size of the caller buffer. - * - * Return : - * int - * On success, 0 is returned; on error -1 is returned; - */ -static int -sun_fru_append_packet(segment_hdl_t segment, packet_t *packet, - const void *payload, size_t nbytes, segment_hdl_t *newsegment, - door_cred_t *cred) -{ - int trailer_offset; - int tag_size; - int fd; - int retval; - char trailer[] = {0x0c, 0x00, 0x00, 0x00, 0x00}; - uint32_t crc; - hash_obj_t *seg_hash; - hash_obj_t *sec_hash; - hash_obj_t *pkt_hash; - hash_obj_t *cont_hash; - fru_tagtype_t tagtype; - fru_segdesc_t *desc; - format_t format; - - /* check the effective uid of the client */ - if (cred->dc_euid != 0) { - errno = EPERM; - return (-1); /* not a root */ - } - - seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - /* check for write perm. */ - desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; - if (!(desc->field.field_perm & SEGMENT_WRITE)) { - errno = EPERM; - return (-1); /* write not allowed */ - } - - sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, - SECTION_TYPE); - if (sec_hash == NULL) { - return (-1); - } - - if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { - errno = EPERM; - return (-1); /* read-only section */ - } - - trailer_offset = seg_hash->u.seg_obj->trailer_offset; - - /* - * if trailer offset is 0 than parse the segment data to get the trailer - * offset to compute the remaining space left in the segment area for - * new packet to be added. - */ - if (trailer_offset == 0) { - (void) sun_fru_get_num_packets(segment, cred); - trailer_offset = seg_hash->u.seg_obj->trailer_offset; - } - - tagtype = get_tag_type((void *)&packet->tag); - if (tagtype == -1) { - return (-1); - } - - tag_size = get_tag_size(tagtype); - if (tag_size == -1) { - return (-1); - } - - if (seg_hash->u.seg_obj->segment.length > - ((trailer_offset - seg_hash->u.seg_obj->segment.offset) + - tag_size + nbytes + - sizeof (char) + sizeof (uint32_t))) { - /* create new packet hash */ - pkt_hash = create_packet_hash_object(); - if (pkt_hash == NULL) { - return (-1); - } - - /* tag initialization */ - (void) memcpy(&pkt_hash->u.pkt_obj->tag, &packet->tag, - tag_size); - pkt_hash->u.pkt_obj->tag_size = tag_size; - - /* payload inititalization */ - pkt_hash->u.pkt_obj->payload = malloc(nbytes); - if (pkt_hash->u.pkt_obj->payload == NULL) { - free(pkt_hash); - return (-1); - } - - (void) memcpy(pkt_hash->u.pkt_obj->payload, payload, nbytes); - pkt_hash->u.pkt_obj->paylen = nbytes; - pkt_hash->u.pkt_obj->payload_offset = trailer_offset + tag_size; - - /* add to hash table */ - add_hashobject_to_hashtable(pkt_hash, PACKET_TYPE); - - add_to_pkt_object_list(seg_hash, pkt_hash); - - cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - if (cont_hash == NULL) { - return (-1); - } - format = cont_hash->u.cont_obj->format; - - fd = open_file(); - if (fd < 0) { - return (-1); - } - - /* update the trailer offset */ - trailer_offset += tag_size + nbytes; - - /* calculate new checksum */ - crc = get_checksum_crc(seg_hash, (trailer_offset - - seg_hash->u.seg_obj->segment.offset)); - - retval = pwrite_new(fd, &packet->tag, tag_size, trailer_offset - - (tag_size + nbytes), &format); - if (retval != tag_size) { - (void) close(fd); - return (-1); - } - - retval = pwrite_new(fd, payload, nbytes, - trailer_offset - nbytes, &format); - if (retval != nbytes) { - (void) close(fd); - return (-1); - } - - retval = pwrite_new(fd, trailer, sizeof (trailer), - trailer_offset, &format); - if (retval != sizeof (trailer)) { - (void) close(fd); - return (-1); - } - - retval = pwrite_new(fd, &crc, sizeof (crc), - trailer_offset + 1, &format); - (void) close(fd); - if (retval != sizeof (crc)) { - return (-1); - } - - seg_hash->u.seg_obj->trailer_offset = trailer_offset; - seg_hash->u.seg_obj->num_of_packets += 1; - - *newsegment = segment; /* return new segment handle */ - return (0); - } else { - errno = EAGAIN; - } - - return (-1); -} - -static void -adjust_packets(int fd, hash_obj_t *free_obj, hash_obj_t *object_list) -{ - int retval; - uint32_t new_offset; - hash_obj_t *hash_ptr; - format_t format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(free_obj->obj_hdl, PACKET_TYPE); - if (hash_obj == NULL) { - return; - } - hash_obj = get_container_hash_object(PACKET_TYPE, - hash_obj->u.pkt_obj->segment_hdl); - if (hash_obj == NULL) { - return; - } - format = hash_obj->u.cont_obj->format; - - new_offset = free_obj->u.pkt_obj->payload_offset - - free_obj->u.pkt_obj->tag_size; - for (hash_ptr = object_list; hash_ptr != NULL; - hash_ptr = hash_ptr->u.pkt_obj->next) { - retval = pwrite_new(fd, &hash_ptr->u.pkt_obj->tag, - hash_ptr->u.pkt_obj->tag_size, new_offset, &format); - if (retval != hash_ptr->u.pkt_obj->tag_size) { - return; - } - new_offset += hash_ptr->u.pkt_obj->tag_size; - hash_ptr->u.pkt_obj->payload_offset = new_offset; - retval = pwrite_new(fd, hash_ptr->u.pkt_obj->payload, - hash_ptr->u.pkt_obj->paylen, new_offset, &format); - if (retval != hash_ptr->u.pkt_obj->paylen) { - return; - } - new_offset += hash_ptr->u.pkt_obj->paylen; - } -} - -static void -free_packet_object(handle_t handle, hash_obj_t *seg_hash) -{ - hash_obj_t *pkt_hash; - hash_obj_t *next_hash; - - pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; - if (pkt_hash == NULL) { - return; - } - - if (pkt_hash->obj_hdl == handle) { - seg_hash->u.seg_obj->pkt_obj_list = pkt_hash->u.pkt_obj->next; - } else { - while (pkt_hash->obj_hdl != handle) { - next_hash = pkt_hash; - pkt_hash = pkt_hash->u.pkt_obj->next; - if (pkt_hash == NULL) { - return; - } - } - next_hash->u.pkt_obj->next = pkt_hash->u.pkt_obj->next; - } - - if (pkt_hash->prev == NULL) { - hash_table[(pkt_hash->obj_hdl % TABLE_SIZE)] = pkt_hash->next; - if (pkt_hash->next != NULL) { - pkt_hash->next->prev = NULL; - } - } else { - pkt_hash->prev->next = pkt_hash->next; - if (pkt_hash->next != NULL) { - pkt_hash->next->prev = pkt_hash->prev; - } - } - - free(pkt_hash->u.pkt_obj->payload); - free(pkt_hash->u.pkt_obj); - free(pkt_hash); -} - -/* - * Description : - * sun_fru_delete_packet() deletes a packet from a segment. - * - * Arguments : packet_hdl_t : packet number to be deleted. - * segment_hdl_t : new segment handler. - * - * Return : - * int - * On success, 0 is returned; on error, -1. - * - * NOTES - * Packets are adjacent; thus, deleting a packet requires moving - * succeeding packets to compact the resulting hole. - */ -static int -sun_fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment, - door_cred_t *cred) -{ - int retval; - int fd; - char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00}; - uint32_t crc; - hash_obj_t *tmp_obj; - hash_obj_t *pkt_hash; - hash_obj_t *sec_hash; - hash_obj_t *cont_hash; - hash_obj_t *prev_obj; - hash_obj_t *seg_hash; - fru_segdesc_t *desc; - format_t format; - - /* check the effective uid of the client */ - if (cred->dc_euid != 0) { - errno = EPERM; - return (-1); /* not a root */ - } - - /* packet hash object */ - pkt_hash = lookup_handle_object(packet, PACKET_TYPE); - if (pkt_hash == NULL) { - return (-1); - } - - /* segment hash object */ - seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl, - SEGMENT_TYPE); - if (seg_hash == NULL) { - return (-1); - } - - /* check for write perm. */ - desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; - if (!(desc->field.field_perm & SEGMENT_WRITE)) { - errno = EPERM; - return (-1); /* write not allowed */ - } - - /* section hash object */ - sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, - SECTION_TYPE); - if (sec_hash == NULL) { - return (-1); - } - - if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { - errno = EPERM; - return (-1); /* read-only section */ - } - - prev_obj = seg_hash->u.seg_obj->pkt_obj_list; - if (prev_obj == NULL) { - return (-1); - } - - /* container hash object */ - cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, - CONTAINER_TYPE); - if (cont_hash == NULL) { - return (-1); - } - - format = cont_hash->u.cont_obj->format; - - fd = open_file(); - if (fd < 0) { - return (-1); - } - - if (prev_obj->obj_hdl == packet) { /* first object to be deleted */ - adjust_packets(fd, prev_obj, prev_obj->u.pkt_obj->next); - seg_hash->u.seg_obj->trailer_offset -= - (prev_obj->u.pkt_obj->tag_size - + prev_obj->u.pkt_obj->paylen); - free_packet_object(packet, seg_hash); - } else { - for (tmp_obj = prev_obj; - tmp_obj != NULL; tmp_obj = tmp_obj->u.pkt_obj->next) { - /* found the object */ - if (tmp_obj->obj_hdl == packet) { - adjust_packets(fd, tmp_obj, - tmp_obj->u.pkt_obj->next); - seg_hash->u.seg_obj->trailer_offset -= - (tmp_obj->u.pkt_obj->tag_size - + tmp_obj->u.pkt_obj->paylen); - free_packet_object(packet, seg_hash); - } - } - } - - seg_hash->u.seg_obj->num_of_packets -= 1; - - /* calculate checksum */ - crc = get_checksum_crc(seg_hash, (seg_hash->u.seg_obj->trailer_offset - - seg_hash->u.seg_obj->segment.offset)); - /* write trailer at new offset */ - retval = pwrite_new(fd, &trailer, sizeof (trailer), - seg_hash->u.seg_obj->trailer_offset, &format); - if (retval != sizeof (trailer)) { - (void) close(fd); - return (-1); - } - - /* write the checksum value */ - retval = pwrite_new(fd, &crc, sizeof (crc), - seg_hash->u.seg_obj->trailer_offset + 1, &format); - (void) close(fd); - if (retval != sizeof (crc)) { - return (-1); - } - - *newsegment = seg_hash->obj_hdl; /* return new segment handle */ - return (0); -} - -/* - * Description : - * sun_fru_close_container() removes the association between a - * container and its handle. this routines free's up all the - * hash object contained under container. - * - * Arguments : - * container_hdl_t holds the file descriptor of the fru. - * - * Return : - * int - * return 0. - * - */ -/* ARGSUSED */ -static int -sun_fru_close_container(container_hdl_t container) -{ - hash_obj_t *hash_obj; - hash_obj_t *prev_hash; - hash_obj_t *sec_hash_obj; - handle_t obj_hdl; - - /* lookup for container hash object */ - hash_obj = lookup_handle_object(container, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (0); - } - - /* points to section object list */ - sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list; - - /* traverse section object list */ - while (sec_hash_obj != NULL) { - - /* traverse segment hash object in the section */ - while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) { - /* object handle of the segment hash object */ - obj_hdl = - sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl; - free_segment_hash(obj_hdl, sec_hash_obj); - } - - /* going to free section hash object, relink the hash object */ - if (sec_hash_obj->prev == NULL) { - hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] - = sec_hash_obj->next; - if (sec_hash_obj->next != NULL) { - sec_hash_obj->next->prev = NULL; - } - } else { - sec_hash_obj->prev->next = sec_hash_obj->next; - if (sec_hash_obj->next != NULL) { - sec_hash_obj->next->prev = sec_hash_obj->prev; - } - } - - free(sec_hash_obj->u.sec_obj); /* free section hash object */ - - prev_hash = sec_hash_obj; - - sec_hash_obj = sec_hash_obj->u.sec_obj->next; - - free(prev_hash); /* free section hash */ - } - - /* free container hash object */ - if (hash_obj->prev == NULL) { - hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] = - hash_obj->next; - if (hash_obj->next != NULL) { - hash_obj->next->prev = NULL; - } - } else { - hash_obj->prev->next = hash_obj->next; - if (hash_obj->next != NULL) { - hash_obj->next->prev = hash_obj->prev; - } - } - - free(hash_obj->u.cont_obj); - free(hash_obj); - return (0); -} - -/* - * FRU ACCESS API - */ - -/* - * Description : - * fru_is_data_available checks if the fruid information - * is available or not on a give fru - * - * Arguments : - * picl_nodehdl_t hold picl node handle of the fru. - * - * Return : - * int - * return 0 - if fruid is not present. - * return 1 - if fruid is present. - */ -int -fru_is_data_available(picl_nodehdl_t fruh) -{ - int retval, ret; - uint8_t slot_no; - picl_nodehdl_t parenth; - format_t fru_format; - hash_obj_t *cont_hash_obj; - - if (is_valid_chassis == -1) { - if (fruaccess_platmod_check_chassis() == 0) { - is_valid_chassis = 1; - } else { - is_valid_chassis = 0; - } - } - - if (!is_valid_chassis) { - return (0); - } - - retval = ptree_get_propval_by_name(fruh, PICL_PROP_PARENT, - &parenth, sizeof (picl_nodehdl_t)); - if (retval != PICL_SUCCESS) { - return (0); - } - - if (fruaccess_platmod_check_fru(parenth) != 0) { - return (0); - } - - retval = ptree_get_propval_by_name(parenth, PICL_PROP_GEO_ADDR, - &slot_no, sizeof (uint8_t)); - if (retval != PICL_SUCCESS) { - return (0); - } - - if (fruaccess_platmod_init_format(slot_no, &fru_format) != - PICL_SUCCESS) { - return (0); - } - - ret = is_fru_data_available(precedence, slot_no, &fru_format); - if (ret && (fru_format.format != NO_FRUDATA)) { - goto create; - } else { - return (0); - } -create: - - cont_hash_obj = create_container_hash_object(); - if (cont_hash_obj == NULL) { - return (0); - } - - cont_hash_obj->obj_hdl = fruh; - cont_hash_obj->u.cont_obj->format = fru_format; - - /* if both formats are present follow the precedence */ - if (fru_format.format == 0x3) { - if (precedence == IPMI_FORMAT) { - cont_hash_obj->u.cont_obj->format.format = IPMI_FORMAT; - } else { - cont_hash_obj->u.cont_obj->format.format = SUN_FORMAT; - } - } - add_hashobject_to_hashtable(cont_hash_obj, CONTAINER_TYPE); - return (1); -} - -/* - * FRU ACCESS API - */ - -/* - * All the routines check the fruid format and redirects the call to - * to appropriate routines depending on fruid format. - * All SUN format routines start with sun_ prefix. - * All IPMI format routines start with ipmi_ prefix. - */ -container_hdl_t -fru_open_container(picl_nodehdl_t fru) -{ - hash_obj_t *hash_obj; - format_t fru_format; - - hash_obj = lookup_handle_object((handle_t)fru, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - return (fruaccess_func[fru_format.format - 1].open_container(fru)); -} - -int -fru_close_container(container_hdl_t container) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(container, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (-1); - } - - fru_format = hash_obj->u.cont_obj->format; - ret = fruaccess_func[fru_format.format - 1].close_container(container); - return (ret); -} - -int -fru_get_num_sections(container_hdl_t container, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(container, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - ret = fruaccess_func[fru_format.format - 1].get_num_sections(container, - cred); - return (ret); -} - -int -fru_get_sections(container_hdl_t container, section_t *section, - int max_sections, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(container, CONTAINER_TYPE); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].get_sections(container, - section, max_sections, cred); - return (ret); -} - -int -fru_get_num_segments(section_hdl_t section, door_cred_t *rarg) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(SEGMENT_TYPE, section); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].get_num_segments(section, - rarg); - return (ret); -} - -int -fru_get_segments(section_hdl_t section, segment_t *segment, - int max_segments, door_cred_t *rarg) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(SEGMENT_TYPE, section); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - ret = fruaccess_func[fru_format.format - 1].get_segments(section, - segment, max_segments, rarg); - return (ret); -} - -int -fru_add_segment(section_hdl_t section, segment_t *segment, - section_hdl_t *newsection, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(SEGMENT_TYPE, section); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].add_segment(section, - segment, newsection, cred); - return (ret); -} - -int -fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection, - door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(PACKET_TYPE, segment); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - ret = fruaccess_func[fru_format.format - 1].delete_segment(segment, - newsection, cred); - return (ret); -} - -ssize_t -fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes, - door_cred_t *cred) -{ - ssize_t ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(PACKET_TYPE, segment); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - ret = fruaccess_func[fru_format.format - 1].read_segment(segment, - buffer, nbytes, cred); - return (ret); -} - -int -fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes, - segment_hdl_t *newsegment, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(PACKET_TYPE, segment); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].write_segment(segment, - data, nbytes, newsegment, cred); - return (ret); -} - -int -fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(PACKET_TYPE, segment); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].get_num_packets(segment, - cred); - return (ret); -} - -int -fru_get_packets(segment_hdl_t segment, packet_t *packet, - int max_packets, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(PACKET_TYPE, segment); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].get_packets(segment, - packet, max_packets, cred); - return (ret); -} - -ssize_t -fru_get_payload(packet_hdl_t packet, void *buffer, - size_t nbytes, door_cred_t *cred) -{ - ssize_t ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(packet, PACKET_TYPE); - if (hash_obj == NULL) { - return (-1); - } - - hash_obj = get_container_hash_object(PACKET_TYPE, - hash_obj->u.pkt_obj->segment_hdl); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].get_payload(packet, buffer, - nbytes, cred); - return (ret); -} - -int -fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes, - packet_hdl_t *newpacket, door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(packet, PACKET_TYPE); - if (hash_obj == NULL) { - return (-1); - } - - hash_obj = get_container_hash_object(PACKET_TYPE, - hash_obj->u.pkt_obj->segment_hdl); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - ret = fruaccess_func[fru_format.format - 1].update_payload(packet, data, - nbytes, newpacket, cred); - return (ret); -} - -int -fru_append_packet(segment_hdl_t segment, packet_t *packet, - const void *payload, size_t nbytes, segment_hdl_t *newsegment, - door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = get_container_hash_object(PACKET_TYPE, segment); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].append_packet(segment, - packet, payload, nbytes, newsegment, cred); - return (ret); -} - -int -fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment, - door_cred_t *cred) -{ - int ret; - format_t fru_format; - hash_obj_t *hash_obj; - - hash_obj = lookup_handle_object(packet, PACKET_TYPE); - if (hash_obj == NULL) { - return (-1); - } - - hash_obj = get_container_hash_object(PACKET_TYPE, - hash_obj->u.pkt_obj->segment_hdl); - if (hash_obj == NULL) { - return (-1); - } - fru_format = hash_obj->u.cont_obj->format; - - ret = fruaccess_func[fru_format.format - 1].delete_packet(packet, - newsegment, cred); - return (ret); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclfruaccess_platmod.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclfruaccess_platmod.c deleted file mode 100644 index 2943132451..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclfruaccess_platmod.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <picl.h> -#include <picldefs.h> -#include "fru_access_impl.h" - -#define SNOWBIRD "SUNW,Netra-CP2300" - -/* - * check if the code is running on correct chassis or not. - * return : - * 0 - if we are on Snowbird - * -1 - if we are on wrong system - * if there is any error - */ -int -fruaccess_platmod_check_chassis() -{ - picl_nodehdl_t chassish; - char chassis_type[PICL_PROPNAMELEN_MAX]; - - if (ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, - &chassish) != PICL_SUCCESS) { - return (-1); - } - - if (ptree_get_propval_by_name(chassish, PICL_PROP_CHASSIS_TYPE, - chassis_type, sizeof (chassis_type)) != PICL_SUCCESS) { - return (-1); - } - - if (strcmp(chassis_type, SNOWBIRD) == 0) { - return (0); - } else { - return (-1); - } -} - -/* - * intialize the format structure, fill in src and dest addresses - */ -picl_errno_t -fruaccess_platmod_init_format(uint8_t slot_no, format_t *fru_format) -{ - /* initialize src and dest addresses */ - fru_format->src = IPMB_ADDR(slot_no); - fru_format->dest = fru_format->src; - return (PICL_SUCCESS); -} - -/* - * do all valid checks for fru - * return : 0 if we can probe for fru - * -1 if probing is not required - */ -int -fruaccess_platmod_check_fru(picl_nodehdl_t parenth) -{ - int retval; - char type[PICL_PROPSIZE_MAX]; - picl_nodehdl_t chassish, loc_parenth; - - retval = ptree_get_propval_by_name(parenth, PICL_PROP_SLOT_TYPE, - (void *)type, PICL_PROPSIZE_MAX); - if (retval != PICL_SUCCESS) { - return (-1); - } - - /* check only for pci and cpci slots */ - if ((strcmp(type, PICL_SLOT_CPCI) != 0) && - (strcmp(type, PICL_SLOT_PCI) != 0)) { - return (-1); - } - - /* check if location is direct parent of chassis or not */ - if (ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, - &chassish) != PICL_SUCCESS) { - return (-1); - } - - retval = ptree_get_propval_by_name(parenth, PICL_PROP_PARENT, - (void *)&loc_parenth, sizeof (loc_parenth)); - if (retval != PICL_SUCCESS) { - return (-1); - } - - if (chassish != loc_parenth) { - return (-1); - } - return (0); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclsdr.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclsdr.c deleted file mode 100644 index 41efb7ee61..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclsdr.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Read the SDR information on a board and get the device id to - * read the FRUID information - */ - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <time.h> -#include <poll.h> -#include <stropts.h> -#include <stdarg.h> -#include <syslog.h> -#include <smclib.h> -#include "fru_access_impl.h" - -#define POLL_TIMEOUT 10000 /* 20 sec */ -#define SEQUENCE 10 - -#define IPMI_GET_SDR_INFO 0x20 -#define IPMI_SENSOR_NETFN 0x4 -#define SDR_INFO_RESPONSE_SZ_MIN 10 - -#define NUM_OF_LUN 4 -#define SUN_FRU "SUN FRU SDR" -#define FRU_DEVICE_SDR_TYPE 0x11 -#define IPMI_SDR_VERSION 0x51 -#define IPMI_DATA_OFFSET 7 -#define IPMI_GET_SDR_INFO_CMD 0x20 -#define SDR_BUFFER_LEN_MAX 100 - -typedef struct { - uint8_t src; - uint8_t dest; - uint8_t lun; - uint8_t record_id_lsb; - uint8_t record_id_msb; - int offset; - int length; - char *buffer; -} sdr_info_t; - -static int get_sdr_info(int, int, uint8_t lun); -static int get_sdr(sdr_info_t *); -static int get_sun_sdr(int, uint8_t, uint8_t, uint8_t); - -/* - * bug in smc f/w - * - * static int lun_mask[4] = { 0x01, 0x02, 0x04, 0x08 }; - */ - -/* - * routine to read the onboard/remote device SDR information - */ -void -get_fru_data_info(int src, int dest, format_t *fru_format) -{ - int ret; - - src = IPMB_ADDR(src); - dest = IPMB_ADDR(dest); - - if (src != dest) { /* ipmi */ - int i = 0; - for (i = 0; i < NUM_OF_LUN; i++) { /* for each lun */ - ret = get_sdr_info(src, dest, i); - if (ret > 0) { - ret = get_sun_sdr(ret, src, dest, i); - if (ret > 0) { - fru_format->format |= SUN_FORMAT; - fru_format->sun_device_id = ret; - fru_format->sun_lun = i; - break; - } - } - } - } else { /* on board */ - ret = get_sdr_info(src, dest, 0); - if (ret > 0) { - ret = get_sun_sdr(ret, src, dest, 0); - if (ret > 0) { - fru_format->format |= SUN_FORMAT; - fru_format->sun_device_id = ret; - fru_format->sun_lun = 0; - } - } - } -} - -/* - * read the onboard sdr information - */ -static int -get_onboard_sdr(sdr_info_t *sdr) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - - SC_MSG_CMD(&req_pkt) = SMC_DEVICE_SDR_GET; - SC_MSG_LEN(&req_pkt) = 6; - SC_MSG_ID(&req_pkt) = SEQUENCE; - - /* data for request packet */ - req_pkt.data[0] = 0x0; - req_pkt.data[1] = 0x0; - req_pkt.data[2] = sdr->record_id_lsb; - req_pkt.data[3] = sdr->record_id_msb; - req_pkt.data[4] = sdr->offset; - req_pkt.data[5] = sdr->length; - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - - bzero(sdr->buffer, SDR_BUFFER_LEN_MAX); - (void) memcpy(sdr->buffer, res_pkt.data, res_pkt.hdr.len); - return (0); -} - -/* - * get the sdr information - */ -static int -get_sdr_info(int src, int dest, uint8_t lun) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - - if (lun >= NUM_OF_LUN) { - return (-1); - } - - if (src == dest) { /* onboard */ - SC_MSG_CMD(&req_pkt) = SMC_DEVICE_SDR_INFO_GET; - SC_MSG_LEN(&req_pkt) = 0; - SC_MSG_ID(&req_pkt) = SEQUENCE; - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - return (res_pkt.data[0]); - } - - /* ipmb access */ - (void) smc_init_ipmi_msg(&req_pkt, IPMI_GET_SDR_INFO_CMD, - FRUACCESS_MSG_ID, 0, NULL, DEFAULT_SEQN, dest, - SMC_NETFN_SENSOR_REQ, lun); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - - /* completion code */ - if (res_pkt.data[IPMI_DATA_OFFSET] != 0) { - return (-1); - } - - /* - * Known bug in SMC f/w. take this out for next release - * if ((res_pkt.data[IPMI_DATA_OFFSET + 2] & lun_mask[lun]) != 1) { - * return (0); - * } - */ - return (res_pkt.data[IPMI_DATA_OFFSET + 1]); -} - -static int -get_sun_sdr(int num_records, uint8_t src, uint8_t dest, uint8_t lun) -{ - int i, ret; - sdr_info_t sdr; - char data[SDR_BUFFER_LEN_MAX]; - uint8_t next_record_lsb; - uint8_t next_record_msb; - - sdr.src = src; - sdr.dest = dest; - sdr.lun = lun; - sdr.buffer = data; - - /* get the first record info */ - next_record_lsb = 0x0; - next_record_msb = 0x0; - sdr.length = 4; - sdr.offset = 0x0; - - if (src == dest) { /* onboard */ - for (i = 0; i < num_records; i++) { - sdr.record_id_lsb = next_record_lsb; - sdr.record_id_msb = next_record_msb; - - if ((ret = get_onboard_sdr(&sdr)) < 0) { - return (ret); - } - - next_record_lsb = data[0]; - next_record_msb = data[1]; - if (data[4] != IPMI_SDR_VERSION) { - return (-1); - } - - if (data[5] == FRU_DEVICE_SDR_TYPE) { - sdr.offset = 0x10; - sdr.length = strlen(SUN_FRU); - if ((ret = get_onboard_sdr(&sdr)) < 0) { - return (ret); - } - - /* first two bytes of response is reserv. id */ - if (strncmp(SUN_FRU, &data[2], - strlen(SUN_FRU)) == 0) { - /* found sun sdr */ - sdr.offset = 0x0; - sdr.length = 7; - if ((ret = get_onboard_sdr(&sdr)) < 0) { - return (ret); - } - return (data[8]); - } - } - } - return (-1); - } - - /* ipmb access */ - /* traverse thru all the records until we find sun sdr */ - for (i = 0; i < num_records; i++) { - - sdr.record_id_lsb = next_record_lsb; - sdr.record_id_msb = next_record_msb; - - if ((ret = get_sdr(&sdr)) < 0) { - return (ret); - } - - /* completion code */ - if (data[IPMI_DATA_OFFSET] != 0) { - return (-1); - } - next_record_lsb = data[IPMI_DATA_OFFSET + 1]; - next_record_msb = data[IPMI_DATA_OFFSET + 2]; - - if (data[IPMI_DATA_OFFSET + 5] != IPMI_SDR_VERSION) { - return (-1); - } - - if (data[IPMI_DATA_OFFSET + 6] == FRU_DEVICE_SDR_TYPE) { - - sdr.offset = 0x10; - sdr.length = strlen(SUN_FRU); - if ((ret = get_sdr(&sdr)) < 0) { - return (ret); - } - - /* completion code */ - if (data[IPMI_DATA_OFFSET] != 0) { - return (-1); - } - - if (strncmp(&data[IPMI_DATA_OFFSET+ 3], - SUN_FRU, strlen(SUN_FRU)) == 0) { - /* found sun sdr */ - sdr.offset = 0x0; - sdr.length = 7; - if ((ret = get_sdr(&sdr)) < 0) { - return (ret); - } - - /* completion code */ - if (data[IPMI_DATA_OFFSET] != 0) { - return (-1); - } - return (data[IPMI_DATA_OFFSET + 9]); - } - } - } - return (-1); -} - -static int -get_sdr(sdr_info_t *sdr) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - uint8_t datap[6]; - - if (sdr->lun > 3) { - return (-1); - } - - /* data for request packet */ - datap[0] = 0x0; /* reserved */ - datap[1] = 0x0; /* reserved */ - datap[2] = sdr->record_id_lsb; - datap[3] = sdr->record_id_msb; - datap[4] = sdr->offset; - datap[5] = sdr->length; - - (void) smc_init_ipmi_msg(&req_pkt, SMC_GET_DEVICE_SDR, - FRUACCESS_MSG_ID, 6, datap, DEFAULT_SEQN, - sdr->dest, SMC_NETFN_SENSOR_REQ, sdr->lun); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - bzero(sdr->buffer, SDR_BUFFER_LEN_MAX); - (void) memcpy(sdr->buffer, res_pkt.data, res_pkt.hdr.len); - return (0); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclsmc.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclsmc.c deleted file mode 100644 index d30e610691..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/fruaccess/piclsmc.c +++ /dev/null @@ -1,997 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * These routines in this file are used to interact with SMC driver to - * read and write FRUID data - */ - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <strings.h> -#include <stdarg.h> -#include <synch.h> -#include <thread.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <syslog.h> -#include <stropts.h> -#include <poll.h> -#include <smclib.h> -#include "fru_access_impl.h" - -#define POLL_TIMEOUT 10000 -#define FRUID_CHECK_POLL_TIMEOUT 5000 -#define SIZE_TO_READ_WRITE 20 - -/* IPMI fru spec Storage definition version 1.0, rev 1.1 */ -#define IPMI_COMMON_HEADER_SIZE 8 -#define IPMI_VERSION 1 -#define CMN_HDR_VERSION_MASK 0x0 -#define CMN_HDR_OFFSET 0x0 -#define BD_MFR_OFFSET 6 -#define BD_FIELDS_SIZE 6 -#define AREA_TERMINATION_INDICATOR 0xc1 - -/* type encoding */ -#define BINARY_TYPE 0x0 -#define BCDPLUS_TYPE 0x1 -#define SIX_BITASCII_TYPE 0x2 -#define UNICODE_TYPE 0x3 - -/* for ascii conversion */ -#define ASCII_MAP 0x20 -#define BIT_MASK1 0x3f -#define BIT_MASK2 0x0f -#define BIT_MASK3 0x03 - -#define SUN_NAME "SUN MICROSYSTEMS, INC." -#define SUN_JEDEC_CODE 0x3e -#define MANR_MAX_LENGTH 80 -#define FRU_DATA_MAX_SIZE 100 - -/* IPMI commands */ -#define IPMI_GET_DEVICE_ID 0x1 -#define FRU_DEVICE_ID 0x0 -#define READ_FRU_INVENTORY_INFO 0x10 -#define READ_FRU_INVENTORY_DATA 0x11 -#define WRITE_FRU_INVENTORY_DATA 0x12 - -#define TMP_BUFFER_SIZE 10 -#define BYTE_TO_READ_SUN_CHK 5 - -typedef struct { - uint8_t internal; /* internal use area */ - uint8_t chassis; /* chassis info area */ - uint8_t board; /* board area */ - uint8_t product; /* product info area */ - uint8_t records; /* multirecord area */ -} fruid_offset_t; - -extern void get_fru_data_info(int, int, format_t *); -static void convert_to_ascii(uint8_t [], uint8_t [], int, int); -static void bcdplus_to_ascii(uint8_t [], uint8_t [], int); -static time_t get_utc_time(uint8_t []); -static uint8_t cpu_no = 0; - -/* - * Routine to read FRUID information from BMC - */ -static int -get_alarm_fru_data(int offset, int size, void *buffer, format_t *format) -{ - uint8_t datap[5]; - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - - if (buffer == NULL) { - return (-1); - } - bzero(buffer, size); - - datap[0] = 0x7; /* bus id */ - datap[1] = 0xa0; /* slave address */ - datap[2] = size; /* count */ - datap[3] = offset >> 8; /* MSB */ - datap[4] = (uint8_t)offset; /* LSB */ - - (void) smc_init_ipmi_msg(&req_pkt, SMC_MASTER_WR_RD_I2C, - FRUACCESS_MSG_ID, 5, datap, DEFAULT_SEQN, format->dest, - SMC_NETFN_APP_REQ, SMC_BMC_LUN); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - /* check the completion code */ - if (res_pkt.data[7] != 0) { - return (-1); - } - - (void) memcpy(buffer, &(res_pkt.data[8]), size); - return (0); -} - -/* - * Routine to read FRUID information from other boards - */ -static int -get_fru_data(int offset, int size, void *buffer, format_t *format) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - uint8_t datap[4]; - int ipmi = 0; - - if (buffer == NULL) { - return (-1); - } - - /* figure out if onboard access or ipmb access */ - if (format->src == format->dest) { - ipmi = 0; - } else { - ipmi = 1; - } - - switch (ipmi) { - - case 0: /* on board info (local i2c) */ - - SC_MSG_CMD(&req_pkt) = SMC_EEPROM_READ; - SC_MSG_LEN(&req_pkt) = 4; - SC_MSG_ID(&req_pkt) = FRUACCESS_MSG_ID; - - /* data field for request */ - req_pkt.data[0] = format->sun_device_id; /* device id */ - req_pkt.data[1] = (uint8_t)offset; /* (LSB) */ - req_pkt.data[3] = size; - - if (format->format == SUN_FORMAT) { - req_pkt.data[2] = offset >> 8; - } else { - req_pkt.data[2] = 0x0; /* (MSB) always 0x0 for IPMI */ - } - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - - if (SC_MSG_LEN(&res_pkt) != size) { - return (-1); - } - (void) memcpy(buffer, res_pkt.data, size); - return (0); - - default: - - /* data for request packet */ - datap[0] = format->sun_device_id; /* device id */ - datap[1] = (uint8_t)offset; /* LSB */ - datap[3] = size; /* bytes to read */ - if (format->format == SUN_FORMAT) { - datap[2] = offset >> 8; - } else { - datap[2] = 0x0; /* (MSB) always 0x0 for IPMI */ - } - - (void) smc_init_ipmi_msg(&req_pkt, READ_FRU_INVENTORY_DATA, - FRUACCESS_MSG_ID, 4, datap, DEFAULT_SEQN, - format->dest, SMC_NETFN_STORAGE_REQ, format->sun_lun); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - /* check the completion code */ - if (res_pkt.data[7] != 0) { - return (-1); - } - - /* check the size */ - if (res_pkt.data[8] != size) { - return (-1); - } - - (void) memcpy(buffer, &(res_pkt.data[9]), size); - return (0); - } -} - -/* - * routine to read the IPMI common header field - */ -static int -read_common_header(fruid_offset_t *offset, format_t *format) -{ - int ret = 0; - uint8_t data[FRU_DATA_MAX_SIZE]; - - ret = get_fru_data(CMN_HDR_OFFSET, IPMI_COMMON_HEADER_SIZE, data, - format); - if (ret < 0) { - return (-1); - } - - /* version check */ - if ((data[0] | CMN_HDR_VERSION_MASK) != 1) { - return (-1); - } - - offset->internal = data[1] * 8; - offset->chassis = data[2] * 8; - offset->board = data[3] * 8; - offset->product = data[4] * 8; - offset->records = data[5] * 8; - - return (0); -} - -/* - * Read the values of each field based on FORMAT - */ -/* ARGSUSED */ -static int -read_bd_fields(uint8_t *field, int offset, format_t *format) -{ - - int ret, encode_type = 0x0, len, length, extra_bytes, alloc_size; - uint8_t *store; - uint8_t data[FRU_DATA_MAX_SIZE]; - - bzero(field, MANR_MAX_LENGTH); - - ret = get_fru_data(offset, BD_FIELDS_SIZE, data, format); - if (ret < 0) { - return (-1); - } - - if (data[0] == AREA_TERMINATION_INDICATOR) { - return (0); - } - - encode_type = data[0] >> 6; - len = data[0] & 0x3f; - if (len <= 0) { - return (0); - } - - ret = get_fru_data(offset+1, len, data, format); - if (ret < 0) { - return (-1); - } - - switch (encode_type) { - - case SIX_BITASCII_TYPE: - - length = len - (len % 3); - extra_bytes = len % 3; - alloc_size = ((length/3) * 4) + extra_bytes; - store = (uint8_t *)malloc(sizeof (uint8_t) * alloc_size); - if (store == NULL) { - return (-1); - } - convert_to_ascii(data, store, len, extra_bytes); - break; - - case BCDPLUS_TYPE: - - alloc_size = len * 2; - store = (uint8_t *)malloc(sizeof (uint8_t) * alloc_size); - if (store == NULL) { - return (-1); - } - - bcdplus_to_ascii(data, store, len); - break; - - case BINARY_TYPE: - case UNICODE_TYPE: - default: - return (-1); - } - - (void) memcpy(field, store, alloc_size); - free(store); - return (len); -} - -static int -read_board_info(uint8_t board_offset, payload_t *manr, format_t *format) -{ - time_t time; - uint8_t *buffer; - uint8_t mfg_time[4]; - uint8_t data[FRU_DATA_MAX_SIZE]; - int ret = 0, current_offset = 0x0; - int bd_area_len = 0; - - /* read version, length, lang code, mfg. time */ - ret = get_fru_data(board_offset, BD_FIELDS_SIZE, data, format); - - if (ret < 0) { - return (-1); - } - - /* version check */ - if ((data[0] | CMN_HDR_VERSION_MASK) != 1) { - return (-1); - } - - /* byte 2 is lang code */ - bd_area_len = data[1] * 8; - mfg_time[3] = data[3]; - mfg_time[2] = data[4]; - mfg_time[1] = data[5]; - mfg_time[0] = 0x0; - time = get_utc_time(mfg_time); - - /* fill the timestamp into manr */ - (void) memcpy(manr->timestamp, &time, MANR_TIME_LEN); - - if (bd_area_len < BD_MFR_OFFSET) { - return (-1); - } - buffer = (uint8_t *)malloc(sizeof (uint8_t) * MANR_MAX_LENGTH); - if (buffer == NULL) { - return (-1); - } - - /* read the board info */ - current_offset += board_offset + BD_MFR_OFFSET; - current_offset += read_bd_fields(buffer, current_offset, format); - - if (strncmp(SUN_NAME, (char *)buffer, sizeof (SUN_NAME)) == 0) { - manr->vendor_name[0] = 0x00; - manr->vendor_name[1] = 0x3e; - } else { - manr->vendor_name[0] = 0x00; - manr->vendor_name[1] = 0x00; - } - - current_offset += 1; /* for length/type field */ - - current_offset += read_bd_fields(buffer, current_offset, format); - current_offset += 1; /* for length/type field */ - (void) memcpy(manr->fru_short_name, buffer, MANR_FRUNAME_LEN); - - current_offset += read_bd_fields(buffer, current_offset, format); - current_offset += 1; /* for length/type field */ - (void) memcpy(manr->sun_serial_no, buffer, MANR_SERIALNUM_LEN); - - current_offset += read_bd_fields(buffer, current_offset, format); - current_offset += 1; /* for length/type field */ - (void) memcpy(manr->sun_part_no, buffer, MANR_PARTNUM_LEN); - - /* - * We dont need the FRU FILE ID, so just skip the field - * and get the offset to read the custom MFG. info fields - */ - current_offset += read_bd_fields(buffer, current_offset, format); - current_offset += 1; /* for length/type field */ - - current_offset += read_bd_fields(buffer, current_offset, format); - current_offset += 1; /* for length/type field */ - - /* read the custom mfg. info fields */ - current_offset += read_bd_fields(buffer, current_offset, format); - current_offset += 1; /* for length/type field */ - (void) memcpy(manr->manufacture_loc, buffer, MANR_MFRLOC_LEN); - - current_offset += read_bd_fields(buffer, current_offset, format); - (void) memcpy(manr->fru_descr, buffer, MANR_FRUDESCR_LEN); - - free(buffer); - return (0); -} - -/* - * Read the IPMI information from hardware and translate it into - * MANR(SUN format) - */ -int -get_manr(format_t *format, payload_t *manr) -{ - int ret = 0; - fruid_offset_t *offset = NULL; - - offset = (fruid_offset_t *)malloc(sizeof (fruid_offset_t)); - if (offset == NULL) { - return (-1); - } - - ret = read_common_header(offset, format); - if (ret != 0) { - free(offset); - return (-1); - } - - if (offset->board != 0) { - ret = read_board_info(offset->board, manr, format); - } - - free(offset); - return (ret); -} - -static void -convert_to_ascii(uint8_t data [], uint8_t store[], - int length, int extra_bytes) -{ - uint8_t x, y; - int index = 0; - int i, idx = length - (length % 3); - - for (i = 0; ; i += 3) { - - x = 0x0; - y = 0x0; - - if (i == idx && extra_bytes == 0) { - break; - } - - /* get the first six bits */ - x = (data[i] & BIT_MASK1); - x += ASCII_MAP; - store[index] = x; - - if (i == idx && extra_bytes == 1) { - break; - } - - /* - * get last 2 bits of first byte and first - * 4 bits of second byte - */ - - x = (data[i] >> 6); - y = (data[i + 1] & BIT_MASK2) << 2; - x |= y + ASCII_MAP; - store[index+1] = x; - - if (i == idx) { - break; - } - - /* get last 4 bits of second byte and 2 bits of last byte */ - x = data[i + 1] >> 4; - y = (data[i + 2] & BIT_MASK3) << 4; - x |= y + ASCII_MAP; - store[index+2] = x; - - /* get last six bits of third byte */ - store[index + 3] = (data[i + 2] >> 2) + ASCII_MAP; - index += 4; - } -} - -static void -bcdplus_to_ascii(uint8_t data[], uint8_t store[], int len) -{ - int i, j, index = 0; - uint8_t tmp = 0; - - struct { - int a:4; - int b:4; - } val; - - for (i = 0; i < len; i++) { - (void) memcpy(&val, &data[i], 1); - for (j = 0; j < 2; j++) { - if (j == 0) { - tmp = val.a; - } else - tmp = val.b; - - if (tmp <= 9) { - /* ascii conversion */ - store[index++] = tmp + 48; - continue; - } - - switch (tmp) { - - case 0xa: - store[index++] = ' '; - break; - case 0xb: - store[index++] = '-'; - break; - case 0xc: - store[index++] = '.'; - break; - default: - store[index++] = ' '; - } - } - } -} - -/* converts ipmi format time to UTC time (unix 32 bit timestamp) */ -static time_t -get_utc_time(uint8_t data []) -{ - time_t time; - struct tm tm1; - uint32_t ipmi_time; - - (void) memcpy(&ipmi_time, data, 4); - - ipmi_time *= 60; /* convert into seconds */ - - /* get UTC time for 0:00 1/1/96 (ipmi epoch) */ - tm1.tm_sec = 0; - tm1.tm_min = 0; - tm1.tm_hour = 0; - tm1.tm_mday = 1; - tm1.tm_mon = 0; - tm1.tm_year = 96; - - time = mktime(&tm1); - time += ipmi_time; - - return (time); -} - -/* - * routine to write information to BMC - */ -static int -write_alarm_fru_data(const void *buffer, size_t size, - off_t offset, format_t *format) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - uint8_t *datap = NULL; - - if (buffer == NULL) { - return (-1); - } - datap = (uint8_t *)malloc(sizeof (uint8_t) * (size + 5)); - if (datap == NULL) { - return (-1); - } - - datap[0] = 0x7; /* bus id */ - datap[1] = 0xa0; /* slave address */ - datap[2] = 0; /* count */ - datap[3] = offset >> 8; /* MSB */ - datap[4] = (uint8_t)offset; /* LSB */ - (void) memcpy((void *)&(datap[5]), buffer, size); - - /* initialize ipmi request packet */ - (void) smc_init_ipmi_msg(&req_pkt, SMC_MASTER_WR_RD_I2C, - FRUACCESS_MSG_ID, (5 + size), datap, DEFAULT_SEQN, - format->dest, SMC_NETFN_APP_REQ, SMC_BMC_LUN); - free(datap); - - /* send ipmi request packet */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - /* check the completion code */ - if (res_pkt.data[7] != 0) { - return (-1); - } - return (0); -} - -static int -write_fru_data(const void *buffer, size_t size, - off_t offset, format_t *format) -{ - int ipmi = 0; - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - uint8_t *datap = NULL; - - if (buffer == NULL) { - return (-1); - } - - if (format->src == format->dest) { - ipmi = 0; - } else { - ipmi = 1; - } - - switch (ipmi) { - - case 0: /* on board info (local i2c) */ - - SC_MSG_CMD(&req_pkt) = SMC_EEPROM_WRITE; - SC_MSG_LEN(&req_pkt) = 4 + size; - SC_MSG_ID(&req_pkt) = FRUACCESS_MSG_ID; - - /* data field for request */ - req_pkt.data[0] = format->sun_device_id; /* device id */ - req_pkt.data[1] = offset; /* (LSB) */ - req_pkt.data[3] = size; - if (format->format == SUN_FORMAT) { - req_pkt.data[2] = offset >> 8; - } else { - req_pkt.data[2] = 0x0; /* (MSB) always 0x0 for IPMI */ - } - (void) memcpy((void *)&(req_pkt.data[4]), buffer, size); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - break; - - default: /* read data from remote device (ipmi) */ - datap = (uint8_t *)malloc(sizeof (uint8_t) * (size + 4)); - if (datap == NULL) { - return (-1); - } - - datap[0] = format->sun_device_id; /* device id */ - datap[1] = offset; /* LSB */ - datap[3] = size; /* nbytes */ - if (format->format == SUN_FORMAT) { - datap[2] = offset >> 8; - } else { - datap[2] = 0x0; /* (MSB) always 0x0 for IPMI */ - } - (void) memcpy((void *)&(datap[4]), buffer, size); - - (void) smc_init_ipmi_msg(&req_pkt, WRITE_FRU_INVENTORY_DATA, - FRUACCESS_MSG_ID, (4 + size), datap, DEFAULT_SEQN, - format->dest, SMC_NETFN_STORAGE_REQ, format->sun_lun); - free(datap); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - /* check the completion code */ - if (res_pkt.data[7] != 0) { - return (-1); - } - break; - } /* end of switch */ - return (0); -} - -/* - * This routine splits the data to write into smaller chunks and - * write it to FRUID chip using SMC drv APIs - */ - -/* ARGSUSED */ -ssize_t -pwrite_new(int fd, const void *buffer, size_t size, - off_t offset, format_t *format) -{ - int ret; - int index = 0; - size_t bytes = 0; - off_t next_offset = 0x0; - off_t curr_offset = offset; - size_t bytes_to_write = size; - uint8_t *data; - int retry = 3; - int (* func_ptr)(const void *, size_t, off_t, format_t *); - - if (format->dest == 0x20) { - func_ptr = write_alarm_fru_data; - } else { - func_ptr = write_fru_data; - } - - data = (uint8_t *)buffer; - while (bytes_to_write != 0) { - - retry = 3; - ret = 1; - - if (bytes_to_write > SIZE_TO_READ_WRITE) { - bytes = SIZE_TO_READ_WRITE; - next_offset = curr_offset + SIZE_TO_READ_WRITE; - } else { - bytes = bytes_to_write; - } - - bytes_to_write = bytes_to_write - bytes; - while ((ret != 0) && (retry != 0)) { - ret = (*func_ptr)((void *)&data[index], - bytes, curr_offset, format); - retry--; - } - if (ret != 0) { - return (ret); - } - index = index + bytes; - curr_offset = next_offset; - } - return (size); -} - -/* - * This routine reads the data in smaller chunks and - * sends it to upper layer(frudata plugin) in the sw stack - */ -/* ARGSUSED */ -ssize_t -pread_new(int fd, void *buffer, size_t size, - off_t offset, format_t *format) -{ - int ret; - int index = 0; - size_t bytes = 0; - off_t next_offset = 0x0; - off_t curr_offset = offset; - size_t bytes_to_read = size; - uint8_t *data; - int retry = 3; - int (* func_ptr)(int, int, void *, format_t *); - - if (format->dest == 0x20) { - func_ptr = get_alarm_fru_data; - } else { - func_ptr = get_fru_data; - } - - data = (uint8_t *)buffer; - - while (bytes_to_read != 0) { - - retry = 3; - ret = 1; - - if (bytes_to_read > SIZE_TO_READ_WRITE) { - bytes = SIZE_TO_READ_WRITE; - next_offset = curr_offset + SIZE_TO_READ_WRITE; - } else { - bytes = bytes_to_read; - } - - bytes_to_read = bytes_to_read - bytes; - - while ((ret != 0) && (retry != 0)) { - ret = (* func_ptr)(curr_offset, bytes, - (void *) &data[index], format); - retry--; - } - if (ret != 0) { - return (ret); - } - index = index + bytes; - curr_offset = next_offset; - } - return (size); -} - -/* - * routine to check if IPMI fruid info is available, - * return 0: IPMI fruid not present - * return 1: IPMI fruid present - */ -static int -is_ipmi_fru_data_available(int src, int dest) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - uint8_t datap[5]; - - /* on board access */ - if (src == dest) { - - SC_MSG_CMD(&req_pkt) = SMC_EEPROM_READ; - SC_MSG_LEN(&req_pkt) = 4; - SC_MSG_ID(&req_pkt) = FRUACCESS_MSG_ID; - - /* data field for request */ - req_pkt.data[0] = 0x0; /* eeprom number (ipmi format) */ - req_pkt.data[1] = CMN_HDR_OFFSET; /* (LSB) */ - req_pkt.data[2] = 0x0; /* (MSB) always 0x0 for IPMI */ - req_pkt.data[3] = IPMI_COMMON_HEADER_SIZE; - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (0); - } - - /* version check */ - if (res_pkt.data[0] != IPMI_VERSION) { - return (0); - } else { - return (1); - } - } - - /* ipmi access */ - datap[0] = FRU_DEVICE_ID; /* fru device id - always */ - datap[1] = 0x0; /* LSB */ - datap[2] = 0x0; /* MSB */ - datap[3] = 8; /* bytes to read */ - - (void) smc_init_ipmi_msg(&req_pkt, READ_FRU_INVENTORY_DATA, - FRUACCESS_MSG_ID, 4, datap, DEFAULT_SEQN, - IPMB_ADDR(dest), SMC_NETFN_STORAGE_REQ, SMC_BMC_LUN); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - FRUID_CHECK_POLL_TIMEOUT) != SMC_SUCCESS) { - return (0); - } - - if (res_pkt.data[9] == IPMI_VERSION) { - return (1); - } else { - return (0); - } -} - -/* - * routine to check if fruid info is available on BMC, - * return 0: fruid not present - * return 1: fruid present - */ -static int -is_alarm_frudata_available(format_t *fru_format) -{ - int ret; - char buffer[TMP_BUFFER_SIZE]; - int fd = -1; - format_t format; - - bzero(buffer, sizeof (buffer)); - format.src = fru_format->src; - format.dest = fru_format->dest; - format.sun_device_id = 0x0; - format.sun_lun = 0x0; - format.format |= SUN_FORMAT; - - /* passing dummy fd */ - /* for now read the first 3 bytes and check the info */ - ret = pread_new(fd, (void *) buffer, 3, STATIC_OFFSET, &format); - if (ret < 0) { - return (0); - } - - if (buffer[0] != SECTION_HDR_TAG) { - fru_format->format = NO_FRUDATA; - return (0); - } - - fru_format->format = SUN_FORMAT; - fru_format->sun_device_id = 0x0; - fru_format->sun_lun = 0x0; - return (1); -} - -/* - * checks if the remote device intelligent device (IPMI capable) or not - * return 0: not ipmi capable - * return 1: ipmi capable - */ -static int -is_ipmi_capable(int src, int dest) -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t res_pkt; - - if (src == dest) { - return (1); - } - - (void) smc_init_ipmi_msg(&req_pkt, IPMI_GET_DEVICE_ID, - FRUACCESS_MSG_ID, 0, NULL, DEFAULT_SEQN, - IPMB_ADDR(dest), SMC_NETFN_APP_REQ, SMC_BMC_LUN); - - if (smc_send_msg(DEFAULT_FD, &req_pkt, &res_pkt, - FRUID_CHECK_POLL_TIMEOUT) != SMC_SUCCESS) { - return (0); - } - return (1); /* got response */ -} - -int -is_fru_data_available(int precedence, int slot_no, format_t *fru_format) -{ - int ret, fd = 0; - uint8_t data[TMP_BUFFER_SIZE]; - - fru_format->format = NO_FRUDATA; - if (fru_format->dest == 0x20) { /* alarm card */ - ret = is_alarm_frudata_available(fru_format); - return (ret); - } - - if (cpu_no == 0) { /* get the geo_addr */ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t size = 0; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, - SMC_GET_GEOGRAPHICAL_ADDRESS, DEFAULT_SEQN, size); - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - POLL_TIMEOUT) != SMC_SUCCESS) { - return (0); - } - if (SC_MSG_LEN(&rsp_pkt) == 0) { - return (0); - } - cpu_no = rsp_pkt.data[0]; - } - - /* check if it is IPMI intelligent or not */ - if (slot_no != cpu_no) { - ret = is_ipmi_capable(cpu_no, slot_no); - if (ret == 0) { /* dumb I/O card */ - return (0); - } - } - - /* check if ipmi frudata is present or not */ - ret = is_ipmi_fru_data_available(cpu_no, slot_no); - if (ret == 1) { - fru_format->format |= IPMI_FORMAT; - fru_format->sun_device_id = 0x0; - fru_format->sun_lun = 0x0; - - /* no need to look for sun format */ - if (precedence == IPMI_FORMAT) { - return (fru_format->format); - } - } - - /* check if sun fruid is present */ - get_fru_data_info(cpu_no, slot_no, fru_format); - /* check the hdr version */ - if (fru_format->format & SUN_FORMAT) { - ret = pread_new(fd, &data, BYTE_TO_READ_SUN_CHK, - STATIC_OFFSET, fru_format); - if (ret != BYTE_TO_READ_SUN_CHK) { - fru_format->format = fru_format->format & - (~ (SUN_FORMAT)); - fru_format->sun_device_id = 0x0; - fru_format->sun_lun = 0x0; - } - if (data[0] != SECTION_HDR_TAG) { - fru_format->format = fru_format->format & - (~ (SUN_FORMAT)); - fru_format->sun_device_id = 0x0; - fru_format->sun_lun = 0x0; - } - } - return (fru_format->format); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/Makefile deleted file mode 100644 index f6531cd3d7..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/picl/plugins/sun4u/snowbird/lib/smc_util/Makefile -# - -LIBRARY = libctsmc.a -VERS = .1 -PLATFORM = SUNW,Netra-CP2300 - -OBJECTS= libctsmc.o - -# include library definitions -include $(SRC)/lib/Makefile.lib -include $(SRC)/Makefile.psm -include $(SRC)/cmd/picl/plugins/Makefile.com - -ROOT_PLATFORM = $(USR_PLAT_DIR)/$(PLATFORM) - -SRCS= $(OBJECTS:%.o=%.c) - -LIBS = $(DYNLIB) - -CLEANFILES= $(LINTOUT) $(LINTLIB) - -ROOTLIBDIR = $(ROOT_PLAT_LIBDIR) - -LINTSRC = $(LINTLIB:%.ln=%) -ROOTLINTDIR = $(ROOTLIBDIR) -ROOTLINT = $(LINTSRC:%=$(ROOTLINTDIR)/%) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -D_SNOWBIRD -I$(SRC)/uts/sun4u/sys -LDLIBS += -L $(ROOT)/usr/platform/$(PLATFORM)/lib -LDLIBS += -R/usr/platform/sun4u/lib -LDLIBS += -lc - -.KEEP_STATE: - -SUBDIRS= - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -all:$(LIBS) $(LIBLINKS) - -install:$(ROOTLIBDIR) all $(ROOTLIBS) $(ROOTLINKS) - -$(LIBLINKS): FRC - $(RM) $(LIBLINKS); $(SYMLINK) $(DYNLIB) $(LIBLINKS) -_msg: - -# include library targets -include $(SRC)/cmd/picl/plugins/Makefile.targ -include $(SRC)/lib/Makefile.targ - -$(ROOTLINTDIR)/%: ../% - $(INS.file) - -lint : - $(LINT.c) $(SRCS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/libctsmc.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/libctsmc.c deleted file mode 100644 index 7bd71245c4..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/libctsmc.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This is utility library that provides APIs to interact with SMC driver - */ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <poll.h> -#include <assert.h> -#include <unistd.h> -#include <string.h> -#include <strings.h> -#include <stdarg.h> -#include <stropts.h> -#include <syslog.h> -#include "smclib.h" - -static int debug_on = 0; - -/* Error messages */ -#define SMC_ERRMSG_OPEN "SMC open failed, cmd = %x\n" -#define SMC_ERRMSG_WRITE "SMC write failed, cmd = %x\n" -#define SMC_ERRMSG_POLLTIMEOUT "SMC poll timed out, cmd = %x\n" -#define SMC_ERRMSG_POLLFAILED "SMC poll failed, cmd = %x\n" -#define SMC_ERRMSG_POLL_T "SMC poll timed out, dest = %x\n" -#define SMC_ERRMSG_POLL_F "SMC poll failed, dest = %x\n" -#define SMC_ERRMSG_READ "SMC read response failed, cmd = %x\n" -#define SMC_ERRMSG_ERROR "SMC error, cc = %d, msg_id = %x\n" -#define SMC_ERRMSG_SETATTR "SMC setting read attribute failed\n" -#define SMC_ERRMSG_GET_SEQN "SMC error in getting seqn for %x\n" -#define SMC_ERRMSG_IPMI_ERR "SMC IPMI invalid cc:%x, dest = %x\n" -#define SMC_ERRMSG_GET_GEO "SMC get GeoAddr failed\n" - -/* Macros */ -#define REQ_SA(_X) (((_X) < 10) ? (0xb0 + 2 * ((_X) - 1)) :\ - (0xb0 + 2 * (_X))) -#define LUN_BITMASK 0x03 /* last two bits */ -#define RESPONSE_MSG 0x01 /* last bit */ - -#define SMC_LOCAL_SEQ_NO 10 -#define SMC_POLL_TIME 1000 /* 1 sec */ -#define NORMAL_COMPLETION_CODE 0 -#define IPMI_MSG_CHANNEL_0 0x0 -#define IPMI_REQ_HDR_LEN 0x8 /* includes command & data checksum */ -#define IPMI_RSP_HDR_LEN 0x8 -#define SMC_NETFN_SEQ_OFFSET 5 -#define SMC_CMD_OFFSET 6 - -#define SMC_NODE ("/dev/ctsmc") -#define DEFAULT_FD -1 -#define DEFAULT_SEQN 128 - -/* - * IPMI packet header - */ -typedef struct { - uint8_t channel_no; /* channel num */ - uint8_t rs_addr; /* dest addr */ - uint8_t netfn_lun; /* netfn and lun */ - uint8_t checksum; /* checksum for dest and netfn_lun */ - uint8_t rq_addr; /* sender addr */ - uint8_t seq_num; /* sequence number */ - uint8_t cmd; /* ipmi cmd */ -} smc_ipmi_header_t; - -/* - * debug printf - */ -static void -dbg_print(const char *fmt, ...) -{ - if (debug_on > 0) { - va_list ap; - va_start(ap, fmt); - (void) vprintf(fmt, ap); - va_end(ap); - } -} - -/* - * send a local command to SMC - */ -static smc_errno_t -smc_send_local_cmd(int fd, sc_reqmsg_t *req_pkt, sc_rspmsg_t *rsp_pkt, - int poll_time) -{ - int poll_rc; - struct pollfd poll_fds[1]; - - poll_fds[0].fd = fd; - poll_fds[0].events = POLLIN|POLLPRI; - poll_fds[0].revents = 0; - - /* send the command to SMC */ - if (write(fd, req_pkt, SC_SEND_HEADER + SC_MSG_LEN(req_pkt)) < 0) { - dbg_print(SMC_ERRMSG_WRITE, SC_MSG_CMD(req_pkt)); - return (SMC_REQ_FAILURE); - } - - poll_rc = poll(poll_fds, 1, poll_time); - if (poll_rc == 0) { - dbg_print(SMC_ERRMSG_POLLTIMEOUT, SC_MSG_CMD(req_pkt)); - return (SMC_ACK_FAILURE); - } else if (poll_rc == -1) { - dbg_print(SMC_ERRMSG_POLLFAILED, SC_MSG_CMD(req_pkt)); - return (SMC_ACK_FAILURE); - } - - /* read the response from SMC */ - if (read(fd, rsp_pkt, SC_MSG_MAX_SIZE) == -1) { - dbg_print(SMC_ERRMSG_READ, SC_MSG_CMD(req_pkt)); - return (SMC_ACK_FAILURE); - } - - /* check if response is valid */ - if (SC_MSG_ID(rsp_pkt) != SC_MSG_ID(req_pkt)) { - dbg_print(SMC_ERRMSG_ERROR, SC_MSG_CC(rsp_pkt), - SC_MSG_ID(rsp_pkt)); - return (SMC_INVALID_SEQ); - } - - if (SC_MSG_CC(rsp_pkt) != 0) { - return (SMC_FAILURE); - } - - return (SMC_SUCCESS); -} - -/* - * get_geo_addr -- returns the geographical address of a CPU board - */ -static int -get_geo_addr(uint8_t *geo_addr) -{ - int fd, rc; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - if ((fd = open(SMC_NODE, O_RDWR)) < 0) { - dbg_print(SMC_ERRMSG_OPEN, - SMC_GET_GEOGRAPHICAL_ADDRESS); - return (SMC_FAILURE); - } - - SC_MSG_CMD(&req_pkt) = SMC_GET_GEOGRAPHICAL_ADDRESS; - SC_MSG_LEN(&req_pkt) = 0; - SC_MSG_ID(&req_pkt) = SMC_LOCAL_SEQ_NO; - - /* no request data */ - if ((rc = smc_send_local_cmd(fd, &req_pkt, &rsp_pkt, - SMC_POLL_TIME)) != SMC_SUCCESS) { - (void) close(fd); - return (rc); - } - - *geo_addr = rsp_pkt.data[0]; - (void) close(fd); - return (SMC_SUCCESS); -} - -/* - * checksum - returns a 2-complement check sum - */ -static uint8_t -checksum(uint8_t buf[], int start, int end) -{ - int i; - uint8_t sum = 0x0; - - for (i = start; i <= end; i++) { - sum += buf[i]; - } - sum = ~sum + 1; - return (sum); -} - -/* - * func to send IPMI messages - */ -static smc_errno_t -smc_send_ipmi_message(int fd, sc_reqmsg_t *req_pkt, sc_rspmsg_t *rsp_pkt, - int poll_time) -{ - int result, nbytes, i = 0; - struct pollfd fds; - uint8_t cc, netfn; - boolean_t is_response = B_FALSE; - char data[SC_MSG_MAX_SIZE], *p; - - if (debug_on) { - bzero(data, SC_MSG_MAX_SIZE); - p = data; - for (i = 0; i < SC_MSG_LEN(req_pkt); i++) { - (void) sprintf(p, "%02x ", req_pkt->data[i]); - p = data + strlen(data); - } - p = data; - syslog(LOG_ERR, "REQ> %s", p); - } - - netfn = req_pkt->data[2] >> 2; - if (netfn & RESPONSE_MSG) { - is_response = B_TRUE; - } - - if ((nbytes = write(fd, (char *)req_pkt, SC_SEND_HEADER + - SC_MSG_LEN(req_pkt))) < 0) { - dbg_print(SMC_ERRMSG_WRITE, SMC_SEND_MESSAGE); - return (SMC_REQ_FAILURE); - } - - if ((nbytes = read(fd, (char *)rsp_pkt, SC_MSG_MAX_SIZE)) < 0) { - dbg_print(SMC_ERRMSG_READ, SMC_SEND_MESSAGE); - return (SMC_ACK_FAILURE); - } - - if (SC_MSG_CC(rsp_pkt) != 0) { - dbg_print(SMC_ERRMSG_ERROR, SC_MSG_CC(rsp_pkt), - SC_MSG_ID(rsp_pkt)); - return (SMC_ACK_FAILURE); - } - - if (is_response) { /* need not wait for response */ - return (SMC_SUCCESS); - } - - fds.fd = fd; - fds.events = POLLIN | POLLPRI; - fds.revents = 0; - result = poll(&fds, 1, poll_time); - - if (result == 0) { - dbg_print(SMC_ERRMSG_POLL_T, req_pkt->data[1]); - return (SMC_RSP_TIMEOUT); - } else if (result < 0) { - dbg_print(SMC_ERRMSG_POLL_F, req_pkt->data[1]); - return (SMC_RSP_ERROR); - } - - nbytes = read(fd, rsp_pkt, SC_MSG_MAX_SIZE); - if (nbytes < 0) { - dbg_print(SMC_ERRMSG_READ, SMC_SEND_MESSAGE); - return (SMC_RSP_ERROR); - } - - if (debug_on) { - bzero(data, SC_MSG_MAX_SIZE); - p = data; - for (i = 0; i < nbytes; i++) { - (void) sprintf(p, "%02x ", rsp_pkt->data[i]); - p = data + strlen(data); - } - p = data; - syslog(LOG_DEBUG, "RES> %s, seq = %x, cmd = %x, len = %x," - "cc = %x", p, SC_MSG_ID(rsp_pkt), SC_MSG_CMD(rsp_pkt), - SC_MSG_LEN(rsp_pkt), SC_MSG_CC(rsp_pkt)); - } - - if (SC_MSG_CC(rsp_pkt) != 0) { - dbg_print(SMC_ERRMSG_IPMI_ERR, rsp_pkt->hdr.cc, - req_pkt->data[SMC_CMD_OFFSET]); - return (SMC_RSP_ERROR); - } - - if (req_pkt->data[SMC_NETFN_SEQ_OFFSET] != - rsp_pkt->data[SMC_NETFN_SEQ_OFFSET]) { - dbg_print("SMC: Invalid sequence number in" - " IPMI Response (sent %x, received %x)\n", - req_pkt->data[5], rsp_pkt->data[SMC_NETFN_SEQ_OFFSET]); - } - - if ((cc = rsp_pkt->data[IPMI_RSP_HDR_LEN-1]) != 0) { - dbg_print("SMC:IPMI response completion " - "error %x, command = %x\n", - cc, req_pkt->data[SMC_CMD_OFFSET]); - } - return (SMC_SUCCESS); -} - -/* - * Initializes the IPMI request packet - */ -smc_errno_t -smc_init_ipmi_msg(sc_reqmsg_t *req_msg, uint8_t cmd, uint8_t msg_id, - uint8_t msg_data_size, uint8_t *msg_data_buf, int8_t seq_num, - int ipmb_addr, smc_netfn_t netfn, smc_lun_t lun) -{ - static uint8_t geo_addr = 0; - smc_ipmi_header_t ipmi_header; - uint8_t data[2]; - if (msg_data_size > 0) { - if ((msg_data_size > (SC_SEND_DSIZE - IPMI_REQ_HDR_LEN)) || - (msg_data_buf == NULL)) { - return (SMC_FAILURE); - } - } - - /* get the geo addr for first time */ - if (geo_addr == 0) { - if (get_geo_addr(&geo_addr) != SMC_SUCCESS) { - dbg_print(SMC_ERRMSG_GET_GEO); - return (SMC_FAILURE); - } - } - - SC_MSG_CMD(req_msg) = SMC_SEND_MESSAGE; - SC_MSG_ID(req_msg) = msg_id; - SC_MSG_LEN(req_msg) = IPMI_REQ_HDR_LEN + msg_data_size; - ipmi_header.channel_no = IPMI_MSG_CHANNEL_0; - ipmi_header.rs_addr = data[0] = ipmb_addr; - ipmi_header.netfn_lun = data[1] = (netfn << 2) | lun; - ipmi_header.checksum = checksum(data, 0, 1); - ipmi_header.rq_addr = REQ_SA(geo_addr); - ipmi_header.cmd = cmd; - if (seq_num >= 0 && seq_num < 64) { - ipmi_header.seq_num = (seq_num << 2) | SMC_SMS_LUN; - } else { - ipmi_header.seq_num = DEFAULT_SEQN; - } - - /* copy the header */ - (void) bcopy((void *)&ipmi_header, SC_MSG_DATA(req_msg), - sizeof (ipmi_header)); - - /* copy the msg data into request packet */ - (void) bcopy((void *)msg_data_buf, (void *)((uchar_t *)req_msg->data + - (IPMI_REQ_HDR_LEN - 1)), msg_data_size); - return (SMC_SUCCESS); -} - -/* - * Initialize a SMC packet - */ -smc_errno_t -smc_init_smc_msg(sc_reqmsg_t *req_msg, smc_app_command_t cmd, - uint8_t msg_id, uint8_t msg_data_size) -{ - if (msg_data_size > SC_SEND_DSIZE) { - return (SMC_FAILURE); - } - - /* fill the packet */ - SC_MSG_CMD(req_msg) = cmd; - SC_MSG_LEN(req_msg) = msg_data_size; - SC_MSG_ID(req_msg) = msg_id; - return (SMC_SUCCESS); -} - -/* - * Sends SMC(local) and IPMI messages - */ -smc_errno_t -smc_send_msg(int fd, sc_reqmsg_t *req_msg, sc_rspmsg_t *rsp_msg, - int poll_time) -{ - int rc = SMC_SUCCESS; - uint8_t dsize, dest; - boolean_t close_fd = B_FALSE; - boolean_t free_seqn = B_FALSE; - struct strioctl scioc; - sc_seqdesc_t smc_seq; - int8_t seq_no; - - if (req_msg == NULL || rsp_msg == NULL) { - return (SMC_FAILURE); - } - - if (fd < 0) { - close_fd = B_TRUE; - if ((fd = open(SMC_NODE, O_RDWR)) < 0) { - dbg_print(SMC_ERRMSG_OPEN, - SC_MSG_CMD(req_msg)); - return (SMC_FAILURE); - } - } - - if (ioctl(fd, I_SRDOPT, RMSGD) < 0) { - dbg_print(SMC_ERRMSG_SETATTR); - if (close_fd) - (void) close(fd); - return (SMC_FAILURE); - } - - if (SC_MSG_CMD(req_msg) != SMC_SEND_MESSAGE) { - rc = smc_send_local_cmd(fd, req_msg, rsp_msg, poll_time); - if (close_fd) { - (void) close(fd); - } - return (rc); - } - - /* This is an IPMI message */ - dsize = SC_MSG_LEN(req_msg) - IPMI_REQ_HDR_LEN; - if (dsize > (SC_SEND_DSIZE - IPMI_REQ_HDR_LEN)) { - if (close_fd) { - (void) close(fd); - } - return (SMC_FAILURE); - } - - /* check if sequence num is valid or not */ - if (req_msg->data[SMC_NETFN_SEQ_OFFSET] == DEFAULT_SEQN) { - free_seqn = B_TRUE; - bzero(&smc_seq, sizeof (sc_seqdesc_t)); - dest = smc_seq.d_addr = req_msg->data[1]; /* dest */ - smc_seq.n_seqn = 1; - smc_seq.seq_numbers[0] = 0; - scioc.ic_cmd = SCIOC_RESERVE_SEQN; - scioc.ic_timout = 0; - scioc.ic_len = sizeof (sc_seqdesc_t); - scioc.ic_dp = (char *)&smc_seq; - if (ioctl(fd, I_STR, &scioc) < 0) { - dbg_print(SMC_ERRMSG_GET_SEQN, dest); - if (close_fd) { - (void) close(fd); - } - return (SMC_FAILURE); - } - seq_no = smc_seq.seq_numbers[0]; - req_msg->data[SMC_NETFN_SEQ_OFFSET] = - (seq_no << 2) | SMC_SMS_LUN; - } - - req_msg->data[(IPMI_REQ_HDR_LEN-1)+dsize] = - checksum(req_msg->data, 4, (IPMI_REQ_HDR_LEN-2)+dsize); - - rc = smc_send_ipmi_message(fd, req_msg, rsp_msg, poll_time); - - if (free_seqn) { /* free seqn if library reserved it */ - smc_seq.d_addr = dest; - smc_seq.n_seqn = 1; - smc_seq.seq_numbers[0] = seq_no; - scioc.ic_cmd = SCIOC_FREE_SEQN; - scioc.ic_timout = 0; - scioc.ic_len = sizeof (sc_seqdesc_t); - scioc.ic_dp = (char *)&smc_seq; - if (ioctl(fd, I_STR, &scioc) < 0) { - dbg_print("SMC:Error in releasing sequence " - "number\n"); - rc = SMC_FAILURE; - } - } - if (close_fd) { - (void) close(fd); - } - return (rc); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/smclib.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/smclib.h deleted file mode 100644 index d950a8c293..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc/smclib.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef __SMCLIB_H__ -#define __SMCLIB_H__ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <smc_if.h> -#include <smc_commands.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SMC error codes - */ -typedef enum { - SMC_SUCCESS = 0x0, - SMC_FAILURE = 0x1, - SMC_REQ_FAILURE = 0x2, - SMC_ACK_TIMEOUT = 0x3, - SMC_ACK_FAILURE = 0x4, - SMC_RSP_FAILURE = 0x5, - SMC_RSP_TIMEOUT = 0x6, - SMC_INVALID_SEQ = 0x7, - SMC_RSP_ERROR = 0x8 -} smc_errno_t; - -extern smc_errno_t smc_init_smc_msg(sc_reqmsg_t *req_msg, smc_app_command_t cmd, - uint8_t msg_id, uint8_t msg_data_size); - -extern smc_errno_t smc_init_ipmi_msg(sc_reqmsg_t *req_msg, uint8_t cmd, - uint8_t msg_id, uint8_t msg_data_size, uint8_t *msg_data_buf, - int8_t seq_num, int ipmb_addr, smc_netfn_t netfn, smc_lun_t lun); - -extern smc_errno_t smc_send_msg(int fd, sc_reqmsg_t *req_pkt, - sc_rspmsg_t *rsp_pkt, int poll_time); - -#ifdef __cplusplus -} -#endif - -#endif /* __SMCLIB_H__ */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/Makefile b/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/Makefile deleted file mode 100644 index d24e64f171..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/Makefile +++ /dev/null @@ -1,102 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY= libpiclwd.a -VERS= .1 - -OBJECTS= piclwatchdog.o piclwd_platmod.o - -# include library definitions -include $(SRC)/lib/Makefile.lib -include $(SRC)/Makefile.psm -include $(SRC)/cmd/picl/plugins/Makefile.com - -SRCS= $(OBJECTS:%.o=%.c) - -LIBS = $(DYNLIB) - -ROOT_PLATFORM = $(USR_PLAT_DIR)/SUNW,Netra-CP2300 - -CLEANFILES= $(LINTOUT) $(LINTLIB) - -ROOTLIBDIR = $(ROOT_PLAT_PLUGINDIR) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRC)/uts/sun4u/sys -I$(SRC)/uts/common -CPPFLAGS += -I$(SRC)/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc -CPPFLAGS += -I$(SRC)/uts/common - -LDLIBS += -R/usr/platform/SUNW,Netra-CP2300/lib/picl/plugins -LDLIBS += -R/usr/platform/SUNW,Netra-CP2300/lib -LDLIBS += -R/usr/platform/sun4u/lib -LDLIBS += -L$(SRC)/lib/libpicl/$(MACH) -L$(SRC)/lib/libpicltree/$(MACH) -LDLIBS += -L $(ROOT)/usr/platform/$(PLATFORM)/lib -LDLIBS += -L$(ROOT_PLATFORM)/lib/picl/plugins -LDLIBS += -L$(SRC)/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc -LDLIBS += -L$(ROOT)/usr/lib/picl/plugins -lnvpair -lpicltree -LDLIBS += -ldevinfo -lctsmc -lpiclfrutree -lc - -.KEEP_STATE: - -SUBDIRS= - -POFILE= snowbird_piclwatchdog.po -POFILES= $(SRCS:%.c=%.po) - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -_msg := TARGET= _msg - -all: $(LIBS) $(LIBLINKS) - -install: $(ROOTLIBDIR) all $(ROOTLIBS) $(ROOTLINKS) - -$(LIBLINKS): FRC - $(RM) $@; $(SYMLINK) $(DYNLIB) $@ - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN)/$(POFILE) - -$(POFILE): $(POFILES) - $(CAT) $(POFILES) > $(POFILE) - -$(MSGDOMAIN): - $(INS.dir) - -# include library targets -include $(SRC)/cmd/picl/plugins/Makefile.targ -include $(SRC)/lib/Makefile.targ - -lint : - $(LINT.c) $(SRCS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwatchdog.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwatchdog.c deleted file mode 100644 index 00af353d0e..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwatchdog.c +++ /dev/null @@ -1,1837 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This module is used to monitor and control watchdog timer for - * UltraSPARC-IIi CPU in Snowbird - */ - -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdarg.h> -#include <strings.h> -#include <string.h> -#include <ctype.h> -#include <alloca.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <libintl.h> -#include <syslog.h> -#include <locale.h> -#include <picl.h> -#include <picltree.h> -#include <libnvpair.h> -#include <poll.h> -#include <errno.h> -#include <syslog.h> -#include <sys/priocntl.h> -#include <sys/rtpriocntl.h> -#include <sys/tspriocntl.h> -#include <sys/fsspriocntl.h> -#include <stropts.h> -#include <synch.h> -#include <signal.h> -#include <thread.h> -#include <picldefs.h> -#include <smclib.h> -#include "piclwatchdog.h" - -#pragma init(wd_picl_register) /* init section */ - -/* debug variables */ -static int wd_debug = 0; -static hrtime_t start1, end1; -static int count = 0; -typedef struct { /* used to keep track of time taken for last 5 pats */ - int res_seq; - int req_seq; - int64_t time; -} wd_time_t; - -#define NUMBER_OF_READINGS 5 -static wd_time_t time1[NUMBER_OF_READINGS]; - -/* global declarations */ -static int wd_fd = -1; /* fd used to send watchdog commands */ -static int polling_fd = -1; /* polling thread that snoops for events */ -static int wd_enable = 1; -static int state_configured = 0; /* chassis state */ -static int props_created = 0; -static int wd_pat_thr_priority = -1; -static pid_t pid = -1; /* PID that owns watchdog services */ -static cond_t patting_cv; -static mutex_t data_lock; -static mutex_t patting_lock; -static int32_t pat_time = 0; -static thread_t polling_thr_tid; -static thread_t patting_thr_tid; -static wd_data_t wd_data; -static char wd_conf[MAXPATHLEN]; - -#define NULLREAD (int (*)(ptree_rarg_t *, void *))0 -#define NULLWRITE (int (*)(ptree_warg_t *, const void *))0 - -/* ptree interface */ -static void wd_picl_register(void); -static void wd_picl_init(void); -static void wd_picl_fini(void); -static void wd_state_change_evhandler(const char *, - const void *, size_t, void *); - -/* local functions */ -static int wd_write_timeout(ptree_warg_t *, const void *); -static int wd_write_action(ptree_warg_t *, const void *); -static int wd_read_action(ptree_rarg_t *, void *); -static int wd_read_timeout(ptree_rarg_t *, void *); -extern char *strtok_r(char *s1, const char *s2, char **lasts); -extern int wd_get_chassis_type(); - -static picld_plugin_reg_t wd_reg_info = { - PICLD_PLUGIN_VERSION_1, - PICLD_PLUGIN_CRITICAL, - "SUNW_picl_watchdog", - wd_picl_init, - wd_picl_fini, -}; - -/* - * This function parses wd.conf file to set the tunables - * tunables at present: patting thread priority, pat time, wd_enable - */ -static void -wd_parse_config_file(char *wd_conf) -{ - FILE *fp; - char buf[WD_CONF_MAXSIZE]; - char *token, *last, *value; - - if ((fp = fopen(wd_conf, "r")) == NULL) { - return; - } - - while (fgets(buf, sizeof (buf), fp) != NULL) { - if (buf[0] == '\0' || buf[0] == '#') { - continue; - } - token = last = value = NULL; - value = (char *)strtok_r((char *)buf, WD_DELIMETER, &last); - if (last) { - token = (char *)strtok_r(last, WD_DELIMETER, &last); - } else { - continue; - } - - if (value == NULL || token == NULL) { - continue; - } - if (strcmp(token, WD_PAT_THREAD_PRIORITY) == 0) { - wd_pat_thr_priority = strtol(value, - (char **)NULL, 10); - } else if (strcmp(token, WD_PATTING_TIME) == 0) { - errno = 0; - pat_time = strtol(value, (char **)NULL, 10); - if (errno != 0) { - pat_time = 0; - } - } else if (strcmp(token, WD_ENABLE) == 0) { - if (strcmp(value, "false") == 0) { - wd_enable = 0; - } - } else { /* unknown token */ - continue; - } - } - (void) fclose(fp); -} - -/* - * read the SMC watchdog registers - */ -static int -wd_get_reg_dump(uint8_t buffer[]) -{ - int rc = 0, i; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_GET_WATCHDOG_TIMER, - DEFAULT_SEQN, 0); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - WD_POLL_TIMEOUT)) != SMC_SUCCESS) { - WD_DEBUG1(WD_PICL_GET_ERR, rc); - return (PICL_FAILURE); - } - - /* read 8 bytes */ - bzero(buffer, WD_REGISTER_LEN); - for (i = 0; i < WD_REGISTER_LEN; i++) { - buffer[i] = rsp_pkt.data[i]; - } - return (PICL_SUCCESS); -} - -/* - * get the HEALTHY# line state - * Return -1 for Error - * 0 for HEALTHY# down - * 1 for HEALTHY# up - */ -static int -wd_get_healthy_status() -{ - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_GET_EXECUTION_STATE, - DEFAULT_SEQN, 0); - - /* make a call to smc library to send cmd */ - if (smc_send_msg(DEFAULT_FD, &req_pkt, &rsp_pkt, - WD_POLL_TIMEOUT) != SMC_SUCCESS) { - return (-1); - } - - return ((rsp_pkt.data[0] & IS_HEALTHY) ? WD_HEALTHY_UP : - WD_HEALTHY_DOWN); -} - -/*ARGSUSED*/ -static void -event_completion_handler(char *ename, void *earg, size_t size) -{ - free(ename); - free(earg); -} - -/* - * posts picl-state-change event if there is change in watchdog-timer state - */ -static picl_errno_t -post_wd_state_event(picl_nodehdl_t nodeh, char *state) -{ - nvlist_t *nvl; - size_t nvl_size; - char *pack_buf = NULL; - picl_errno_t rc; - char *ename = PICLEVENT_STATE_CHANGE, *evname = NULL; - - if (state == NULL) { - return (PICL_FAILURE); - } - - if ((evname = strdup(ename)) == NULL) { - return (PICL_NOSPACE); - } - - if ((rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) != 0) { - free(evname); - syslog(LOG_ERR, WD_NVLIST_ERR, rc); - return (PICL_FAILURE); - } - - if ((rc = nvlist_add_uint64(nvl, PICLEVENTARG_NODEHANDLE, - nodeh)) != 0) { - nvlist_free(nvl); - free(evname); - syslog(LOG_ERR, WD_NVLIST_ERR, rc); - return (PICL_FAILURE); - } - - if ((rc = nvlist_add_string(nvl, PICLEVENTARG_STATE, - state)) != 0) { - nvlist_free(nvl); - free(evname); - syslog(LOG_ERR, WD_NVLIST_ERR, rc); - return (PICL_FAILURE); - } - - if ((rc = nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, - NULL)) != 0) { - nvlist_free(nvl); - free(evname); - syslog(LOG_ERR, WD_NVLIST_ERR, rc); - return (PICL_FAILURE); - } - - if ((rc = ptree_post_event(evname, pack_buf, nvl_size, - event_completion_handler)) != PICL_SUCCESS) { - free(pack_buf); - free(evname); - nvlist_free(nvl); - return (rc); - } - nvlist_free(nvl); - return (PICL_SUCCESS); -} - -/* - * Updates the State value in picl tree and posts a state-change event - */ -static void -wd_picl_update_state(int level, uint8_t stat) -{ - picl_errno_t rc; - char state[PICL_PROPNAMELEN_MAX]; - - switch (stat) { - case WD_ARMED: - (void) strncpy(state, PICL_PROPVAL_WD_STATE_ARMED, - sizeof (state)); - break; - case WD_DISARMED: - (void) strncpy(state, PICL_PROPVAL_WD_STATE_DISARMED, - sizeof (state)); - break; - case WD_EXPIRED: - (void) strncpy(state, PICL_PROPVAL_WD_STATE_EXPIRED, - sizeof (state)); - break; - default: - return; - } - - (void) mutex_lock(&data_lock); - switch (level) { - case WD1: - wd_data.wd1_run_state = stat; - break; - case WD2: - wd_data.wd2_run_state = stat; - break; - case WD1_2: - wd_data.wd1_run_state = stat; - wd_data.wd2_run_state = stat; - break; - default: - return; - } - (void) mutex_unlock(&data_lock); - - if (!state_configured) { - return; - } - - switch (level) { - case WD1: - if ((rc = post_wd_state_event(wd_data.wd1_nodehdl, - state)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_POST_EVENT_ERR, rc); - } - break; - case WD2: - if ((rc = post_wd_state_event(wd_data.wd2_nodehdl, - state)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_POST_EVENT_ERR, rc); - } - break; - - case WD1_2: - if ((rc = post_wd_state_event(wd_data.wd1_nodehdl, - state)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_POST_EVENT_ERR, rc); - } - if ((rc = post_wd_state_event(wd_data.wd2_nodehdl, - state)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_POST_EVENT_ERR, rc); - } - break; - } -} - -/* - * Sends a command to SMC to reset the watchdog-timers - */ -static int -wd_pat() -{ - int rc = 0; - static uint8_t seq = 1; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - if (seq < WD_MAX_SEQN) { - req_pkt.hdr.msg_id = seq++; - } else { - seq = 1; - req_pkt.hdr.msg_id = seq; - } - - if (wd_debug & WD_TIME_DEBUG) { - start1 = gethrtime(); - } - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_RESET_WATCHDOG_TIMER, - DEFAULT_SEQN, 0); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(wd_fd, &req_pkt, &rsp_pkt, - WD_POLL_TIMEOUT)) != SMC_SUCCESS) { - syslog(LOG_CRIT, WD_PICL_PAT_ERR, rc); - return (PICL_FAILURE); - } - - if (wd_debug & WD_TIME_DEBUG) { - end1 = gethrtime(); - time1[count].res_seq = SC_MSG_ID(&rsp_pkt); - time1[count].req_seq = SC_MSG_ID(&req_pkt); - time1[count].time = (end1 - start1); - - if (count < (NUMBER_OF_READINGS - 1)) { - count++; - } else { - count = 0; - } - } - return (PICL_SUCCESS); -} - -/* used to set the new values for watchdog and start the watchdog */ -static int -wd_start(uchar_t action_1, uchar_t action_2, - uchar_t timeout_2, uchar_t *timeout_1, uint8_t patting_option) -{ - int rc = 0; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - if (timeout_1 == NULL) { - return (PICL_FAILURE); - } - - req_pkt.data[0] = WD_USEFLAG_OS; - req_pkt.data[1] = action_1 | action_2; /* actions */ - req_pkt.data[2] = timeout_2; /* wd timeout 2 */ - req_pkt.data[3] = WD_XPR_FLG_CLR_OS; /* expiration flags */ - req_pkt.data[4] = timeout_1[1]; /* LSB for wd timeout 1 */ - req_pkt.data[5] = timeout_1[0]; /* MSB for wd timeout 1 */ - - if (patting_option == ENABLE_AUTO_PAT) { - req_pkt.data[0] |= WD_ENABLE_AUTO_PAT; - } - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_SET_WATCHDOG_TIMER, - DEFAULT_SEQN, WD_SET_CMD_DATA_LEN); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(wd_fd, &req_pkt, &rsp_pkt, - WD_POLL_TIMEOUT)) != SMC_SUCCESS) { - WD_DEBUG1(WD_PICL_START_ERR, rc); - return (PICL_FAILURE); - } - - /* reset the watchdog timer */ - (void) smc_init_smc_msg(&req_pkt, SMC_RESET_WATCHDOG_TIMER, - DEFAULT_SEQN, 0); - if ((rc = smc_send_msg(wd_fd, &req_pkt, &rsp_pkt, - WD_POLL_TIMEOUT)) != SMC_SUCCESS) { - WD_DEBUG1(WD_PICL_START_ERR, rc); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -/* - * Validates timeout and action fields and arms the watchdog-timers - */ -static int -wd_arm(uint8_t patting_option) -{ - int rc; - uint16_t wd_time1; - uint8_t wd_time2, wd1_action, wd2_action; - uint8_t timeout1[2]; - - if (wd_data.wd1_timeout >= 0) { - wd_time1 = wd_data.wd1_timeout/WD_L1_RESOLUTION; - } else { - wd_time1 = 0; - } - - if (wd_data.wd2_timeout >= 0) { - wd_time2 = wd_data.wd2_timeout/WD_L2_RESOLUTION; - } else { - wd_time2 = 0; - } - - timeout1[0] = wd_time1 >> 8; /* MSB */ - timeout1[1] = wd_time1 & 0x00ff; /* LSB */ - - /* check the HELATHY# status if action is alarm */ - if (wd_data.wd1_action == WD_ACTION_HEALTHY_DOWN_HOST || - wd_data.wd1_action == WD_ACTION_HEALTHY_DOWN_SAT) { - rc = wd_get_healthy_status(); - if (rc == WD_HEALTHY_DOWN) { - WD_DEBUG0(WD_HEALTHY_ERR); - return (PICL_FAILURE); - } else if (rc == -1) { - syslog(LOG_ERR, WD_GET_HEALTH_ERR); - return (PICL_FAILURE); - } - } - - if (wd_data.wd1_timeout == -1) { - wd1_action = WD_ACTION_NONE2; - } else { - wd1_action = wd_data.wd1_action; - } - - if (wd_data.wd2_timeout == -1) { - wd2_action = WD_ACTION_NONE2; - } else { - wd2_action = wd_data.wd2_action; - } - - rc = wd_start(wd1_action, wd2_action, - wd_time2, timeout1, patting_option); - return (rc); -} - -/* - * This is thread is a RealTime class thread. This thread pats the - * watchdog-timers in regular intervals before the expiry. - */ -/*ARGSUSED*/ -static void * -wd_patting_thread(void *args) -{ - time_t sec; - pcinfo_t pci; - long nano_sec; - timestruc_t to; - long sleep_time; - struct timeval tp; - int err, state; - - for (;;) { - (void) mutex_lock(&patting_lock); - while (wd_data.wd_pat_state == WD_NORESET) { - (void) cond_wait(&patting_cv, &patting_lock); - } - (void) mutex_unlock(&patting_lock); - - /* reset pat-time to zero */ - pat_time = 0; /* tunable */ - wd_parse_config_file(wd_conf); - - if (wd_pat_thr_priority < 0 || wd_pat_thr_priority > 59) { - wd_pat_thr_priority = WD_DEFAULT_THREAD_PRIORITY; - } - - /* change the priority of thread to realtime class */ - (void) strncpy(pci.pc_clname, "RT", sizeof (pci.pc_clname)); - if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) { - pcparms_t pcp; - rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms; - rtp->rt_pri = wd_pat_thr_priority; - rtp->rt_tqsecs = 0; - rtp->rt_tqnsecs = RT_TQDEF; - pcp.pc_cid = pci.pc_cid; - if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, - (caddr_t)&pcp) != 0) { - syslog(LOG_ERR, WD_PICL_RT_THRD_FAIL); - } - } else { - syslog(LOG_ERR, WD_PICL_RT_THRD_NO_PERM_ERR); - } - - switch (wd_data.wd1_timeout) { - case 0: - if (wd_arm(DISABLE_AUTO_PAT) == PICL_SUCCESS) { - wd_picl_update_state(WD1, WD_ARMED); - if (wd_data.wd2_timeout >= 0) { - wd_picl_update_state(WD2, WD_ARMED); - } - } else { - syslog(LOG_ERR, WD_PICL_START_ERR, - PICL_FAILURE); - } - /* no need to pat */ - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) mutex_unlock(&patting_lock); - continue; - case -1: - if (wd_data.wd2_timeout < 0) { - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) mutex_unlock(&patting_lock); - continue; - } - if (wd_arm(DISABLE_AUTO_PAT) == PICL_SUCCESS) { - wd_picl_update_state(WD2, WD_ARMED); - } else { - syslog(LOG_ERR, WD_PICL_START_ERR, - PICL_FAILURE); - } - /* no need to pat */ - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) mutex_unlock(&patting_lock); - continue; - default: - break; - } - - if (pat_time == 0) { - if (wd_data.wd1_timeout > WD_PAT_TIME) { - pat_time = WD_PAT_TIME; - } else { - pat_time = wd_data.wd1_timeout - 80; - } - } - if (pat_time <= 0) { - WD_DEBUG0(WD_PICL_PAT_TIME_ERR); - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) mutex_unlock(&patting_lock); - continue; - } - sleep_time = wd_data.wd1_timeout - pat_time; - - if (wd_data.wd1_timeout <= 0 || sleep_time <= 0) { - WD_DEBUG0(WD_PICL_ARM_PAT_ERR); - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) mutex_unlock(&patting_lock); - continue; - } else { - wd_picl_update_state(WD1, WD_ARMED); - } - - if (wd_data.wd2_timeout >= 0) { - wd_picl_update_state(WD2, WD_ARMED); - } - - sec = sleep_time/1000; - nano_sec = (sleep_time - (sec * 1000)) * 1000000; - - if (wd_arm(ENABLE_AUTO_PAT) != PICL_SUCCESS) { - wd_picl_update_state(WD1_2, WD_DISARMED); - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) mutex_unlock(&patting_lock); - syslog(LOG_ERR, WD_PICL_START_ERR, PICL_FAILURE); - continue; - } - - do /* pat the watchdog until expiry or user disarm */ - { - (void) mutex_lock(&patting_lock); - state = wd_data.wd_pat_state; - if (state == WD_NORESET) { - (void) mutex_unlock(&patting_lock); - break; - } - (void) gettimeofday(&tp, NULL); - to.tv_sec = tp.tv_sec + sec; - if ((nano_sec + (tp.tv_usec * 1000)) >= 1000000000) { - to.tv_sec += 1; - to.tv_nsec = (nano_sec + - (tp.tv_usec * 1000)) - 1000000000; - } else { - to.tv_nsec = nano_sec + (tp.tv_usec * 1000); - } - - err = cond_timedwait(&patting_cv, &patting_lock, &to); - (void) mutex_unlock(&patting_lock); - - if (err == ETIME) { /* woke up from sleep */ - (void) wd_pat(); - } - } while (state == WD_RESET); - } - /*NOTREACHED*/ - return (NULL); -} - -/* - * returns 0 if owner is not alive - * returns 1 if owner is alive - * returns -1 if there is no active owner - */ -static int -is_owner_alive() -{ - char strpid[50]; - struct stat buf; - - if (pid == -1) { - return (-1); - } - - /* check if the file exists or not */ - (void) snprintf(strpid, sizeof (pid), "/proc/%ld/status", pid); - errno = 0; - if (stat(strpid, &buf) == 0) { - return (1); - } - if (errno == ENOENT) { - return (0); - } else { - syslog(LOG_ERR, WD_GET_OWN_FAILED, errno); - } - return (-1); -} - -/* - * Sends a cmd to SMC to stop watchdog timers - */ -static int -wd_stop() -{ - int rc = 0; - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t buffer[8]; - - if (wd_get_reg_dump(buffer) != 0) { - return (PICL_FAILURE); - } - /* clear the expiration flags */ - buffer[3] = 0xff; /* expiration flags */ - - (void) memcpy(SC_MSG_DATA(&req_pkt), buffer, - WD_SET_CMD_DATA_LEN); - - /* initialize the request packet */ - (void) smc_init_smc_msg(&req_pkt, SMC_SET_WATCHDOG_TIMER, - DEFAULT_SEQN, WD_SET_CMD_DATA_LEN); - - /* make a call to smc library to send cmd */ - if ((rc = smc_send_msg(wd_fd, &req_pkt, &rsp_pkt, - WD_POLL_TIMEOUT)) != SMC_SUCCESS) { - syslog(LOG_ERR, WD_PICL_STOP_ERR, rc); - return (PICL_FAILURE); - } - return (PICL_SUCCESS); -} - -/* - * Function used by volatile callback function for wd-op property - * under controller. This is used to arm, disarm the watchdog-timers - * in response to user actions - */ -static int -wd_worker_function(uint8_t flag, pid_t proc_id) -{ - int rc = PICL_SUCCESS; - int wd1_state, wd2_state; - - (void) mutex_lock(&data_lock); - wd1_state = wd_data.wd1_run_state; - wd2_state = wd_data.wd2_run_state; - (void) mutex_unlock(&data_lock); - - switch (flag) { - - case USER_ARMED_WD: - - /* watchdog can only be armed if all the timers are disarmed */ - if (wd1_state != WD_DISARMED) { - WD_DEBUG0(WD_PICL_WD1_RUNNING_ERR); - rc = PICL_FAILURE; - break; - } - if (wd2_state != WD_DISARMED) { - WD_DEBUG0(WD_PICL_WD2_RUNNING_ERR); - rc = PICL_FAILURE; - break; - } - - /* check the HELATHY# status if action is alarm */ - if (wd_data.wd1_timeout >= 0) { - if (wd_data.wd1_action == WD_ACTION_HEALTHY_DOWN_HOST || - wd_data.wd1_action == WD_ACTION_HEALTHY_DOWN_SAT) { - rc = wd_get_healthy_status(); - if (rc == WD_HEALTHY_DOWN) { - WD_DEBUG0(WD_HEALTHY_ERR); - return (PICL_FAILURE); - } else if (rc == -1) { - syslog(LOG_ERR, WD_GET_HEALTH_ERR); - return (PICL_FAILURE); - } else { - rc = PICL_SUCCESS; - } - } - } - - /* signal the patting thread */ - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_RESET; - (void) cond_signal(&patting_cv); - (void) mutex_unlock(&patting_lock); - break; - - case USER_DISARMED_WD: - - /* - * if the caller doesnot own watchdog services, - * check to see if the owner is still alive using procfs - */ - if (proc_id != pid) { - switch (is_owner_alive()) { - case -1: - if ((wd1_state != WD_DISARMED) || - (wd2_state != WD_DISARMED)) { - break; - } - /* watchdog is already disarmed */ - WD_DEBUG0(WD_PICL_NO_WD_ERR); - return (PICL_FAILURE); - case 1: - /* owner is still alive, deny the operation */ - WD_DEBUG0(WD_PICL_PERM_DENIED); - return (PICL_PERMDENIED); - default: - break; - } - } - - /* watchdog is running */ - if ((rc = wd_stop()) == PICL_SUCCESS) { - wd_picl_update_state(WD1_2, WD_DISARMED); - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) cond_signal(&patting_cv); - (void) mutex_unlock(&patting_lock); - } - break; - - case USER_ARMED_PAT_WD: /* for debug purposes only */ - - /* - * first arm-pat operation is used for arming the watchdog - * subsequent arm-pat operations will be used for patting - * the watchdog - */ - /* WD is stopped */ - if (wd1_state == WD_DISARMED && wd2_state == WD_DISARMED) { - if ((rc = wd_arm(DISABLE_AUTO_PAT)) == PICL_SUCCESS) { - if (wd_data.wd1_timeout >= 0) { - wd_picl_update_state(WD1, WD_ARMED); - } - - if (wd_data.wd2_timeout >= 0) { - wd_picl_update_state(WD2, WD_ARMED); - } - } else { - return (rc); - } - } else { /* WD is running */ - if (wd1_state != WD_ARMED) { - WD_DEBUG0(WD_PICL_NO_WD_ERR); - return (PICL_INVALIDARG); - } - - /* check if OS is patting the watchdog or not */ - (void) mutex_lock(&patting_lock); - if (wd_data.wd_pat_state == WD_RESET) { - WD_DEBUG0(WD_PICL_TRY_PAT_ERR); - (void) mutex_unlock(&patting_lock); - return (PICL_INVALIDARG); - } - - /* check if the process owns the WD services */ - if (proc_id != pid) { - WD_DEBUG0(WD_PICL_PERM_DENIED); - return (PICL_PERMDENIED); - } - rc = wd_pat(); - } - break; - - default: - rc = PICL_INVALIDARG; - break; - - } /* switch */ - - return (rc); -} - -/*ARGSUSED*/ -static int -wd_write_op(ptree_warg_t *parg, const void *buf) -{ - int rc = PICL_INVALIDARG; - uint8_t flag; - - /* only after state is configured */ - if (!state_configured) { - if (parg->cred.dc_pid != getpid()) { - WD_DEBUG0(WD_PICL_STATE_INVALID); - return (PICL_PERMDENIED); - } - } - - /* only super user can write this property */ - if (parg->cred.dc_euid != SUPER_USER) { - WD_DEBUG0(WD_NO_ROOT_PERM); - return (PICL_PERMDENIED); - } - - if (strcmp((char *)buf, PICL_PROPVAL_WD_OP_ARM) == 0) { - flag = USER_ARMED_WD; - rc = PICL_SUCCESS; - } - - if (strcmp((char *)buf, PICL_PROPVAL_WD_OP_DISARM) == 0) { - flag = USER_DISARMED_WD; - rc = PICL_SUCCESS; - } - - /* for debug purpose only */ - if (strcmp((char *)buf, WD_ARM_PAT) == 0) { - flag = USER_ARMED_PAT_WD; - rc = PICL_SUCCESS; - } - - if (rc == PICL_SUCCESS) { - rc = wd_worker_function(flag, parg->cred.dc_pid); - } else { - rc = PICL_INVALIDARG; - } - - if (rc == PICL_SUCCESS) { - - switch (flag) { - case USER_ARMED_PAT_WD: - case USER_ARMED_WD: - - /* get the process id of client */ - if (parg->cred.dc_pid != getpid()) { - pid = parg->cred.dc_pid; - } else { - pid = -1; - } - break; - case USER_DISARMED_WD: - /* reset the pid */ - pid = -1; - default: - break; - } - } - return (rc); -} - -/* volatile call back function to read the watchdog L1 status */ -/*ARGSUSED*/ -static int -wd1_read_status(ptree_rarg_t *parg, void *buf) -{ - int rc = PICL_SUCCESS; - - (void) mutex_lock(&data_lock); - - switch (wd_data.wd1_run_state) { - - case WD_EXPIRED: - (void) strncpy((char *)buf, PICL_PROPVAL_WD_STATE_EXPIRED, - PICL_PROPNAMELEN_MAX); - break; - - case WD_DISARMED: - (void) strncpy((char *)buf, PICL_PROPVAL_WD_STATE_DISARMED, - PICL_PROPNAMELEN_MAX); - break; - - case WD_ARMED: - (void) strncpy((char *)buf, PICL_PROPVAL_WD_STATE_ARMED, - PICL_PROPNAMELEN_MAX); - break; - - default: - rc = PICL_FAILURE; - } - (void) mutex_unlock(&data_lock); - return (rc); -} - -/* - * this function is used to read the state of L2 timer - */ -static int -wd_get_wd2_status(int *present_status) -{ - int rc; - uchar_t buffer[WD_REGISTER_LEN]; - - bzero(buffer, WD_REGISTER_LEN); - (void) mutex_lock(&data_lock); - *present_status = wd_data.wd2_run_state; - if (wd_data.wd2_run_state != WD_ARMED) { - /* we already have the latest state */ - (void) mutex_unlock(&data_lock); - return (PICL_SUCCESS); - } - (void) mutex_unlock(&data_lock); - - /* read watchdog registers */ - if ((rc = wd_get_reg_dump(buffer)) != 0) { - return (rc); - } - - if (buffer[0] & WD_WD_RUNNING) { - *present_status = WD_ARMED; - return (PICL_SUCCESS); - } - - if (buffer[3] != 0) { - (void) mutex_lock(&data_lock); - *present_status = wd_data.wd2_run_state = WD_EXPIRED; - (void) mutex_unlock(&data_lock); - } - return (PICL_SUCCESS); -} - -/* volatile call back function to read the watchdog L2 status */ -/*ARGSUSED*/ -static int -wd2_read_status(ptree_rarg_t *parg, void *buf) -{ - int present_status, rc; - - if ((rc = wd_get_wd2_status(&present_status)) != - PICL_SUCCESS) { - return (rc); - } - - /* copy the present state in user buffer */ - switch (present_status) { - case WD_ARMED: - (void) strncpy((char *)buf, PICL_PROPVAL_WD_STATE_ARMED, - PICL_PROPNAMELEN_MAX); - break; - case WD_EXPIRED: - (void) strncpy((char *)buf, PICL_PROPVAL_WD_STATE_EXPIRED, - PICL_PROPNAMELEN_MAX); - break; - case WD_DISARMED: - (void) strncpy((char *)buf, PICL_PROPVAL_WD_STATE_DISARMED, - PICL_PROPNAMELEN_MAX); - break; - } - return (PICL_SUCCESS); -} - -/* this thread listens for watchdog expiry events */ -/*ARGSUSED*/ -static void * -wd_polling(void *args) -{ - uint8_t stat; - int poll_retval; - struct pollfd fds; - sc_rspmsg_t rsp_pkt; - int i; - - fds.fd = polling_fd; - fds.events = POLLIN | POLLPRI; - fds.revents = 0; - - for (;;) { - poll_retval = poll(&fds, 1, -1); - if (props_created == 0) - continue; - switch (poll_retval) { - case 0: - break; - - case -1: - syslog(LOG_ERR, WD_PICL_POLL_ERR); - break; - - default: - /* something happened */ - if ((read(polling_fd, &rsp_pkt, - sizeof (sc_rspmsg_t))) < 0) { - syslog(LOG_ERR, WD_PICL_SMC_READ_ERR); - break; - } - - if (rsp_pkt.hdr.cmd == SMC_EXPIRED_WATCHDOG_NOTIF) { - - (void) mutex_lock(&data_lock); - stat = wd_data.wd1_run_state; - (void) mutex_unlock(&data_lock); - - if (stat != WD_ARMED) { - continue; - } - - wd_picl_update_state(WD1, WD_EXPIRED); - - (void) mutex_lock(&patting_lock); - wd_data.wd_pat_state = WD_NORESET; - (void) cond_signal(&patting_cv); - - (void) mutex_unlock(&patting_lock); - syslog(LOG_WARNING, WD_WD1_EXPIRED); - if (wd_debug & WD_TIME_DEBUG) { - syslog(LOG_ERR, " latest count : %d", count); - for (i = 0; i < NUMBER_OF_READINGS; i++) { - syslog(LOG_ERR, "i = %d, req_seq = %d," - "res_seq = %d, time = %lld nsec", - i, time1[i].req_seq, - time1[i].res_seq, - time1[i].time); - } - } - if (wd_data.reboot_action) { - wd_data.reboot_action = 0; - (void) system(SHUTDOWN_CMD); - } - } - break; - - } /* switch */ - } - /*NOTREACHED*/ - return (NULL); -} - -/* - * This function reads the hardware state and gets the status of - * watchdog-timers - */ -static int -wd_get_status(wd_state_t *state) -{ - picl_errno_t rc; - uchar_t buffer[WD_REGISTER_LEN]; - - bzero(buffer, WD_REGISTER_LEN); - /* read watchdog registers */ - if ((rc = wd_get_reg_dump(buffer)) != 0) { - return (rc); - } - - /* get action */ - state->action1 = buffer[1] & 0xF0; /* most significant 4 bits */ - if (state->action1 == 0x0) { - state->action1 = WD_ACTION_NONE1; - } - state->action2 = buffer[1] & 0x0F; /* least significant 4 bits */ - if (state->action2 == 0x0) { - state->action2 = WD_ACTION_NONE2; - } - - state->timeout2 = buffer[2]; - state->timeout1[0] = buffer[5]; /* MSB */ - state->timeout1[1] = buffer[4]; /* LSB */ - - state->present_t1[0] = buffer[7]; /* MSB */ - state->present_t1[1] = buffer[6]; /* LSB */ - - if (buffer[0] & WD_WD_RUNNING) { - state->present_state = WD_ARMED; - return (PICL_SUCCESS); - } - - if (buffer[3] != 0) { - state->present_state = WD_EXPIRED; - return (PICL_SUCCESS); - } else { - state->present_state = WD_DISARMED; - return (PICL_SUCCESS); - } -} - -/* read the smc hardware and intialize the internal state */ -static void -wd_set_init_state() -{ - wd_state_t state; - uint16_t tmp1, tmp2, wd_time1; - - if (wd_get_status(&state) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_GET_STAT_ERR); - /* defualt state is expired ??? */ - state.present_state = WD_EXPIRED; - } - - switch (state.present_state) { - case WD_EXPIRED: - case WD_DISARMED: - if (state.present_state == WD_EXPIRED) - wd_picl_update_state(WD1_2, WD_EXPIRED); - else - wd_picl_update_state(WD1_2, WD_DISARMED); - wd_data.wd_pat_state = WD_NORESET; - wd_data.wd1_action = state.action1; - wd_data.wd2_action = state.action2; - tmp1 = state.timeout1[0] << 8; - tmp2 = state.timeout1[1]; - wd_time1 = tmp1 | tmp2; - wd_data.wd1_timeout = wd_time1 * WD_L1_RESOLUTION; - wd_data.wd2_timeout = state.timeout2 * WD_L2_RESOLUTION; - break; - case WD_ARMED: - /* - * get the present values and restart the - * watchdog from os level and continue to pat - */ - wd_picl_update_state(WD1_2, WD_ARMED); - wd_data.wd_pat_state = WD_RESET; - wd_data.wd1_action = (state.action1 << 4); - wd_data.wd2_action = state.action2; - - tmp1 = state.timeout1[0] << 8; - tmp2 = state.timeout1[1]; - wd_time1 = tmp1 | tmp2; - wd_data.wd1_timeout = wd_time1 * WD_L1_RESOLUTION; - wd_data.wd2_timeout = state.timeout2 * WD_L2_RESOLUTION; - (void) wd_stop(); - } -} - -/* - * wrapper for ptree interface to create property - */ -static int -wd_create_property( - int ptype, /* PICL property type */ - int pmode, /* PICL access mode */ - size_t psize, /* size of PICL property */ - char *pname, /* property name */ - int (*readfn)(ptree_rarg_t *, void *), - int (*writefn)(ptree_warg_t *, const void *), - picl_nodehdl_t nodeh, /* node for property */ - picl_prophdl_t *propp, /* pointer to prop_handle */ - void *vbuf) /* initial value */ -{ - picl_errno_t rc; - ptree_propinfo_t propinfo; - - rc = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, - ptype, pmode, psize, pname, readfn, writefn); - if (rc != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_PROP_INIT_ERR, rc); - return (rc); - } - - rc = ptree_create_and_add_prop(nodeh, &propinfo, vbuf, propp); - if (rc != PICL_SUCCESS) { - return (rc); - } - - return (PICL_SUCCESS); -} - -/* Create and add Watchdog properties */ -static void -wd_create_add_props() -{ - int rc; - picl_nodehdl_t rooth, sysmgmt_h, platformh; - int32_t timeout1 = 0; - int32_t timeout2 = 0; - char buf[PICL_WD_PROPVAL_MAX]; - - /* get picl root node handle */ - if ((rc = ptree_get_root(&rooth)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 1, rc); - return; - } - - /* get picl platform node handle */ - if ((rc = ptree_get_node_by_path(PLATFORM_PATH, - &platformh)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 2, rc); - return; - } - - /* get the picl sysmgmt node handle */ - if ((rc = ptree_find_node(platformh, PICL_PROP_NAME, - PICL_PTYPE_CHARSTRING, - PICL_NODE_SYSMGMT, strlen(PICL_NODE_SYSMGMT), - &sysmgmt_h)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 3, rc); - return; - } - - /* start creating the watchdog nodes and properties */ - if ((rc = ptree_create_and_add_node(sysmgmt_h, PICL_NODE_WD_CONTROLLER, - PICL_CLASS_WATCHDOG_CONTROLLER, - &(wd_data.wd_ctrl_nodehdl))) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 4, rc); - return; - } - - /* Add wd-op property to watchdog controller node */ - (void) strncpy(buf, "", sizeof (buf)); - if ((rc = wd_create_property(PICL_PTYPE_CHARSTRING, - PICL_WRITE + PICL_VOLATILE, - PICL_PROPNAMELEN_MAX, PICL_PROP_WATCHDOG_OPERATION, - NULL, wd_write_op, - wd_data.wd_ctrl_nodehdl, - &(wd_data.wd_ops_hdl), - (void *)buf)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 5, rc); - return; - } - - /* create L1 node and add to controller */ - if ((rc = ptree_create_and_add_node(wd_data.wd_ctrl_nodehdl, - PICL_NODE_WD_L1, PICL_CLASS_WATCHDOG_TIMER, - &(wd_data.wd1_nodehdl))) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 6, rc); - return; - } - - /* create L2 node and add to controller */ - if ((rc = ptree_create_and_add_node(wd_data.wd_ctrl_nodehdl, - PICL_NODE_WD_L2, PICL_CLASS_WATCHDOG_TIMER, - &(wd_data.wd2_nodehdl))) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 7, rc); - return; - } - - /* create watchdog properties */ - /* create state property here */ - (void) strncpy(buf, PICL_PROPVAL_WD_STATE_DISARMED, - sizeof (buf)); - if ((rc = wd_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_STATE, wd1_read_status, NULLWRITE, - wd_data.wd1_nodehdl, - &(wd_data.wd1_state_hdl), (void *)buf)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 8, rc); - return; - } - - if ((rc = wd_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_VOLATILE, PICL_PROPNAMELEN_MAX, - PICL_PROP_STATE, wd2_read_status, NULLWRITE, - wd_data.wd2_nodehdl, - &(wd_data.wd2_state_hdl), (void *)buf)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 9, rc); - return; - } - - /* create timeout property here */ - if ((rc = wd_create_property(PICL_PTYPE_UNSIGNED_INT, - PICL_READ + PICL_WRITE + PICL_VOLATILE, - sizeof (timeout1), PICL_PROP_WATCHDOG_TIMEOUT, - wd_read_timeout, wd_write_timeout, wd_data.wd1_nodehdl, - &(wd_data.wd1_timeout_hdl), (void *)&(timeout1))) != - PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 10, rc); - return; - } - - if ((rc = wd_create_property(PICL_PTYPE_UNSIGNED_INT, - PICL_READ + PICL_WRITE + PICL_VOLATILE, - sizeof (wd_data.wd2_timeout), PICL_PROP_WATCHDOG_TIMEOUT, - wd_read_timeout, wd_write_timeout, wd_data.wd2_nodehdl, - &(wd_data.wd2_timeout_hdl), (void *)&(timeout2))) != - PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 11, rc); - return; - } - - /* create wd_action property here */ - (void) strncpy(buf, PICL_PROPVAL_WD_ACTION_NONE, - sizeof (buf)); - if ((rc = wd_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_WRITE + PICL_VOLATILE, - PICL_PROPNAMELEN_MAX, PICL_PROP_WATCHDOG_ACTION, - wd_read_action, wd_write_action, - wd_data.wd1_nodehdl, &(wd_data.wd1_action_hdl), - (void *)buf)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 12, rc); - return; - } - - if ((rc = wd_create_property(PICL_PTYPE_CHARSTRING, - PICL_READ + PICL_WRITE + PICL_VOLATILE, - PICL_PROPNAMELEN_MAX, PICL_PROP_WATCHDOG_ACTION, - wd_read_action, wd_write_action, - wd_data.wd2_nodehdl, &(wd_data.wd2_action_hdl), - (void *)buf)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_NODE_INIT_ERR, 13, rc); - return; - } -} - -static int -wd_ioctl(int fd, int cmd, int len, char *buf) -{ - int rtnval; - struct strioctl sioc; - sioc.ic_cmd = cmd; - sioc.ic_timout = 60; - sioc.ic_len = len; - sioc.ic_dp = buf; - rtnval = ioctl(fd, I_STR, &sioc); - return (rtnval); -} - -static int -wd_open(int attr) -{ - int cc; - sc_cmdspec_t wd_cmdspec; - - if ((wd_fd = open(SMC_NODE, attr)) < 0) { - return (-1); - } - - /* get exclusive access for set and reset commands of watchdog */ - wd_cmdspec.args[0] = SMC_SET_WATCHDOG_TIMER; - wd_cmdspec.args[1] = SMC_RESET_WATCHDOG_TIMER; - wd_cmdspec.attribute = SC_ATTR_EXCLUSIVE; - - cc = wd_ioctl(wd_fd, SCIOC_MSG_SPEC, 3, - (char *)&wd_cmdspec); - if (cc < 0) { - syslog(LOG_ERR, WD_PICL_EXCLUSIVE_ACCESS_ERR); - return (-1); - } - return (wd_fd); -} - -static int -wd_open_pollfd(int attr) -{ - int cc; - sc_cmdspec_t wd_cmdspec; - - if ((polling_fd = open(SMC_NODE, attr)) < 0) { - return (-1); - } - - /* request for watchdog expiry notification */ - wd_cmdspec.args[0] = SMC_EXPIRED_WATCHDOG_NOTIF; - wd_cmdspec.attribute = SC_ATTR_EXCLUSIVE; - - cc = wd_ioctl(polling_fd, SCIOC_MSG_SPEC, 2, - (char *)&wd_cmdspec); - if (cc < 0) { - syslog(LOG_ERR, WD_PICL_SET_ATTR_FAILED); - return (-1); - } - return (polling_fd); -} - -/* read the ENVIRONMENT variables and initialize tunables */ -static void -wd_get_env() -{ - char *val; - int intval = 0; - - /* read frutree debug flag value */ - if (val = getenv(WATCHDOG_DEBUG)) { - errno = 0; - intval = strtol(val, (char **)NULL, 0); - if (errno == 0) { - wd_debug = intval; - } - } -} - -/* - * PTREE Entry Points - */ - -/* picl-state-change event handler */ -/*ARGSUSED*/ -static void -wd_state_change_evhandler(const char *ename, const void *earg, - size_t size, void *cookie) -{ - char *value; - picl_errno_t rc; - nvlist_t *nvlp; - picl_nodehdl_t fruhdl; - static int spawn_threads = 1; - char name[PICL_PROPNAMELEN_MAX]; - - if (strcmp(ename, PICLEVENT_STATE_CHANGE)) { - return; - } - - /* neglect all events if wd props are already created */ - if (props_created && state_configured) { - return; - } - - if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) { - return; - } - if ((nvlist_lookup_uint64(nvlp, PICLEVENTARG_NODEHANDLE, - &fruhdl)) == -1) { - nvlist_free(nvlp); - return; - } - if (nvlist_lookup_string(nvlp, PICLEVENTARG_STATE, &value)) { - nvlist_free(nvlp); - return; - } - - rc = ptree_get_propval_by_name(fruhdl, PICL_PROP_NAME, - (void *)name, sizeof (name)); - if (rc != PICL_SUCCESS) { - nvlist_free(nvlp); - return; - } - - /* care for only events on chassis node */ - if (strcmp(name, PICL_NODE_CHASSIS) != 0) { - nvlist_free(nvlp); - return; - } - - if (strcmp(value, PICLEVENTARGVAL_CONFIGURED) == 0) { - state_configured = 1; - nvlist_free(nvlp); - return; - } - - if (strcmp(value, PICLEVENTARGVAL_CONFIGURING) != 0) { - nvlist_free(nvlp); - return; - } - - if (wd_fd < 0) { - if ((wd_fd = wd_open(O_RDWR)) < 0) { - syslog(LOG_CRIT, WD_PICL_SMC_OPEN_ERR); - nvlist_free(nvlp); - return; - } - } - - if (polling_fd < 0) { - if ((polling_fd = wd_open_pollfd(O_RDWR)) < 0) { - syslog(LOG_CRIT, WD_PICL_SMC_OPEN_ERR); - nvlist_free(nvlp); - return; - } - } - - switch (wd_get_chassis_type()) { - case WD_HOST: /* is host */ - wd_data.is_host = B_TRUE; - break; - case WD_STANDALONE: /* is satellite */ - wd_data.is_host = B_FALSE; - break; - default: - nvlist_free(nvlp); - return; - } - - (void) wd_create_add_props(); /* create and add properties */ - props_created = 1; - - /* read the hardware and initialize values */ - (void) wd_set_init_state(); - - /* initialize wd-conf value */ - (void) snprintf(wd_conf, sizeof (wd_conf), "%s/%s", - PICL_CONFIG_DIR, WD_CONF_FILE); - - if (spawn_threads == 0) { - /* threads are already created */ - nvlist_free(nvlp); - return; - } - - /* start monitoring for the events */ - if (thr_create(NULL, NULL, wd_polling, - NULL, THR_BOUND, &polling_thr_tid) != 0) { - syslog(LOG_ERR, WD_PICL_THREAD_CREATE_FAILED, - "polling"); - nvlist_free(nvlp); - return; - } - - /* thread used to pat watchdog */ - if (thr_create(NULL, NULL, wd_patting_thread, - NULL, THR_BOUND, &patting_thr_tid) != 0) { - syslog(LOG_ERR, WD_PICL_THREAD_CREATE_FAILED, - "patting"); - nvlist_free(nvlp); - return; - } - spawn_threads = 0; - nvlist_free(nvlp); -} - -static void -wd_picl_register(void) -{ - int rc = 0; - if ((rc = picld_plugin_register(&wd_reg_info)) != PICL_SUCCESS) { - syslog(LOG_ERR, WD_PICL_REG_ERR, rc); - } -} - -/* entry point (initialization) */ -static void -wd_picl_init(void) -{ - /* initialize the wd_conf path and name */ - (void) snprintf(wd_conf, sizeof (wd_conf), "%s/%s", - PICL_CONFIG_DIR, WD_CONF_FILE); - - /* parse configuration file and set tunables */ - wd_parse_config_file(wd_conf); - - /* if watchdog-enable is set to false dont intialize wd subsystem */ - if (wd_enable == 0) { - return; - } - - /* read watchdog related environment variables */ - wd_get_env(); - - /* event handler for state change notifications from frutree */ - (void) ptree_register_handler(PICLEVENT_STATE_CHANGE, - wd_state_change_evhandler, NULL); -} - -static void -wd_picl_fini(void) -{ - (void) ptree_unregister_handler(PICLEVENT_STATE_CHANGE, - wd_state_change_evhandler, NULL); - - state_configured = 0; /* chassis state */ - props_created = 0; - (void) ptree_delete_node(wd_data.wd_ctrl_nodehdl); - (void) ptree_destroy_node(wd_data.wd_ctrl_nodehdl); -} - -/* - * volatile function to read the timeout - */ -static int -wd_read_timeout(ptree_rarg_t *parg, void *buf) -{ - /* update the buffer provided by user */ - (void) mutex_lock(&data_lock); - if (parg->proph == wd_data.wd1_timeout_hdl) { - *(int32_t *)buf = wd_data.wd1_timeout; - } else if (parg->proph == wd_data.wd2_timeout_hdl) { - *(int32_t *)buf = wd_data.wd2_timeout; - } - (void) mutex_unlock(&data_lock); - return (PICL_SUCCESS); -} - -/* - * volatile function to read the action - */ -static int -wd_read_action(ptree_rarg_t *parg, void *buf) -{ - (void) mutex_lock(&data_lock); - if (parg->proph == wd_data.wd1_action_hdl) { - switch (wd_data.wd1_action) { - case WD_ACTION_HEALTHY_DOWN_HOST: - case WD_ACTION_HEALTHY_DOWN_SAT: - (void) strcpy((char *)buf, - PICL_PROPVAL_WD_ACTION_ALARM); - break; - case WD_ACTION_NONE1: - case WD_ACTION_NONE2: - if (wd_data.reboot_action == 1) { - (void) strcpy((char *)buf, - PICL_PROPVAL_WD_ACTION_REBOOT); - } else { - (void) strcpy((char *)buf, - PICL_PROPVAL_WD_ACTION_NONE); - } - break; - } - } else if (parg->proph == wd_data.wd2_action_hdl) { - switch (wd_data.wd2_action) { - case WD_ACTION_HARD_RESET: - (void) strcpy((char *)buf, - PICL_PROPVAL_WD_ACTION_RESET); - break; - case WD_ACTION_NONE2: - (void) strcpy((char *)buf, PICL_PROPVAL_WD_ACTION_NONE); - break; - } - } - (void) mutex_unlock(&data_lock); - return (PICL_SUCCESS); -} - -/* - * volatile function to write the action - * this function validates the user value before programming the - * action property. Properties can be modified only when watchdog - * is in disarmed state. - */ -static int -wd_write_action(ptree_warg_t *parg, const void *buf) -{ - int flag = 0x0; - picl_errno_t rc = PICL_SUCCESS; - char wd_action[PICL_WD_PROPVAL_MAX]; - - /* only super user can write this property */ - if (parg->cred.dc_euid != SUPER_USER) { - return (PICL_PERMDENIED); - } - - if (parg->proph == wd_data.wd1_action_hdl) { - flag = WD1; - } else if (parg->proph == wd_data.wd2_action_hdl) { - flag = WD2; - } - - /* dont allow any write operations when watchdog is armed */ - (void) mutex_lock(&data_lock); - if (wd_data.wd1_run_state != WD_DISARMED || - wd_data.wd2_run_state != WD_DISARMED) { - (void) mutex_unlock(&data_lock); - return (PICL_PERMDENIED); - } - - /* validate the values and store in internal cache */ - (void) strcpy(wd_action, (char *)buf); - switch (flag) { - case WD1: - if (strcmp(wd_action, PICL_PROPVAL_WD_ACTION_ALARM) == 0) { - if (wd_data.is_host) - wd_data.wd1_action = WD_ACTION_HEALTHY_DOWN_HOST; - else - wd_data.wd1_action = WD_ACTION_HEALTHY_DOWN_SAT; - wd_data.reboot_action = 0; - } else if (strcmp(wd_action, PICL_PROPVAL_WD_ACTION_NONE) == 0) { - wd_data.wd1_action = WD_ACTION_NONE1; - wd_data.reboot_action = 0; - } else if (strcmp(wd_action, PICL_PROPVAL_WD_ACTION_REBOOT) == 0) { - wd_data.wd1_action = WD_ACTION_NONE1; - wd_data.reboot_action = 1; - } else { - rc = PICL_INVALIDARG; - } - break; - - case WD2: - if (strcmp(wd_action, PICL_PROPVAL_WD_ACTION_RESET) == 0) { - wd_data.wd2_action = WD_ACTION_HARD_RESET; - } else if (strcmp(wd_action, PICL_PROPVAL_WD_ACTION_NONE) == 0) { - wd_data.wd2_action = WD_ACTION_NONE2; - } else { - rc = PICL_INVALIDARG; - } - break; - } - (void) mutex_unlock(&data_lock); - return (rc); -} - -/* - * volatile function to write the timeout - * this function validates the user value before programming the - * timeout property. Properties can be modified only when watchdog - * is in disarmed state. - */ -static int -wd_write_timeout(ptree_warg_t *parg, const void *buf) -{ - int32_t timeout; - int flag = 0x0; - - /* only super user can write this property */ - if (parg->cred.dc_euid != SUPER_USER) { - return (PICL_PERMDENIED); - } - - /* dont allow any write operations when watchdog is armed */ - (void) mutex_lock(&data_lock); - if (wd_data.wd1_run_state != WD_DISARMED || - wd_data.wd2_run_state != WD_DISARMED) { - (void) mutex_unlock(&data_lock); - return (PICL_PERMDENIED); - } - (void) mutex_unlock(&data_lock); - - if (parg->proph == wd_data.wd1_timeout_hdl) { - flag = WD1; - } else if (parg->proph == wd_data.wd2_timeout_hdl) { - flag = WD2; - } - - /* validate the timeout values */ - timeout = *(int32_t *)buf; - if (timeout < -1) { - return (PICL_INVALIDARG); - } - - if (timeout > 0) { - switch (flag) { - case WD1: - if ((timeout % WD_L1_RESOLUTION) != 0) { - return (PICL_INVALIDARG); - } - if ((timeout/WD_L1_RESOLUTION) > WD_MAX_L1) { - return (PICL_INVALIDARG); - } - break; - case WD2: - if ((timeout % WD_L2_RESOLUTION) != 0) { - return (PICL_INVALIDARG); - } - if ((timeout/WD_L2_RESOLUTION) > WD_MAX_L2) { - /* 255 sec */ - return (PICL_INVALIDARG); - } - } - } - - /* update the internal cache */ - (void) mutex_lock(&data_lock); - switch (flag) { - case WD1: - wd_data.wd1_timeout = timeout; - break; - case WD2: - wd_data.wd2_timeout = timeout; - break; - } - (void) mutex_unlock(&data_lock); - return (PICL_SUCCESS); -} diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwatchdog.h b/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwatchdog.h deleted file mode 100644 index 7870fc0363..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwatchdog.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _PICL_WATCHDOG_H -#define _PICL_WATCHDOG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <libintl.h> -#include <sys/inttypes.h> -#include <smclib.h> - -#define WD_DEBUG0(fmt) \ - if (wd_debug) { \ - syslog(LOG_DEBUG, fmt); \ - } -#define WD_DEBUG1(fmt, d1) \ - if (wd_debug) { \ - syslog(LOG_DEBUG, fmt, d1); \ - } - -/* environment variable defs */ -#define WATCHDOG_DEBUG "SUNW_WATCHDOG_DEBUG" - -/* debug flags */ -#define WD_GENERAL_MSGS 0x1 -#define WD_TIME_DEBUG 0x2 - -/* tunables */ -#define WD_DEFAULT_THREAD_PRIORITY 0 -#define WD_POLL_TIMEOUT 10000 /* 10 sec */ -#define WD_PAT_TIME 5000 - -/* constants */ -#define WD_SET_CMD_DATA_LEN 6 /* size for set cmd */ -#define PICL_WD_PROPVAL_MAX 20 -#define SUPER_USER 0 - -/* watchdog status */ -#define WD_ARMED 0x1 /* watchdog is running */ -#define WD_EXPIRED 0x2 /* watchdog is expired */ -#define WD_DISARMED 0x4 /* watchdog is stopped */ - -/* patting status */ -#define WD_RESET 0x8 /* client chose to pat. */ -#define WD_NORESET 0x0 /* pat state initial value. */ - -/* auto pat feature for SMC f/w */ -#define ENABLE_AUTO_PAT 0x1 -#define DISABLE_AUTO_PAT 0x0 - -/* flags used to track user actions */ -#define USER_ARMED_WD 0x1 /* user armed the watchdog */ -#define USER_ARMED_PAT_WD 0x2 /* debug feature */ -#define USER_PAT_WD 0x3 /* debug feature */ -#define USER_DISARMED_WD 0x4 /* user disarmed watchdog */ - -/* bit masks */ -#define WD_ACTION_NONE1 0x30 /* action none with interrupt */ -#define WD_ACTION_NONE2 0x00 /* no action */ -#define WD_ACTION_HARD_RESET 0x01 /* hard reset */ -#define WD_ACTION_HEALTHY_DOWN_HOST 0x50 /* dont put bridge in reset */ -#define WD_ACTION_HEALTHY_DOWN_SAT 0x40 /* healthy down, bridge reset */ -#define WD_USEFLAG_OS 0x04 /* set os as user of wd */ -#define WD_XPR_FLG_CLR_OS 0x10 /* to clear sms/os expiry bit */ -#define WD_WD_RUNNING 0x40 /* to check wd running or not */ -#define WD_ENABLE_AUTO_PAT 0x20 /* enable auto pat feature */ - -/* timer max values */ -#define WD_MAX_L2 0xff /* 255 sec */ -#define WD_MAX_L1 0xffff /* 109.22 min */ -#define WD_L1_RESOLUTION 100 /* 100ms/cnt */ -#define WD_L2_RESOLUTION 1000 /* 1000ms/cnt */ - -#define WD1 0x1 /* wd level 1 */ -#define WD2 0x2 /* wd level 2 */ -#define WD1_2 0x3 /* wd level 1 and level 2 */ -#define WD_MAX_SEQN 255 - -/* PICL node names */ -#define PICL_NODE_CHASSIS "chassis" -#define PICL_NODE_SYSMGMT "sysmgmt" -#define PICL_NODE_WD_CONTROLLER "watchdog" -#define PICL_NODE_WD_L1 "watchdog-level1" -#define PICL_NODE_WD_L2 "watchdog-level2" - -/* debug value for wd_op */ -#define WD_ARM_PAT "arm-pat" - -/* HEALTHY# status */ -#define WD_HEALTHY_DOWN 0x0 -#define WD_HEALTHY_UP 0x1 - -#define SHUTDOWN_CMD "shutdown -y -i 6 -g 60 watchdog "\ - "expired.. rebooting" -/* watchdog config file variables */ -#define PICL_CONFIG_DIR "/etc/picl/config" -#define WD_CONF_FILE "watchdog.conf" -#define WD_CONF_MAXSIZE 100 -#define WD_DELIMETER " \t\n" - -/* The following values can be tuned using config file */ -#define WD_PAT_THREAD_PRIORITY "wd_thread_priority" -#define WD_PATTING_TIME "wd_pat_time" -#define WD_ENABLE "watchdog-enable" - -#define WD_HOST 1 -#define WD_STANDALONE 2 - -/* HEALTHY# bitmask */ -#define IS_HEALTHY 0x01 - -#define DEFAULT_SEQN 15 -#define DEFAULT_FD -1 -#define SMC_NODE "/dev/ctsmc" - -#define WD_REGISTER_LEN 8 - -typedef struct { - /* properties values */ - uint8_t wd1_run_state; /* L1 status */ - uint8_t wd1_action; /* L1 action */ - uint8_t wd2_run_state; /* L2 status */ - uint8_t wd2_action; /* L2 action */ - int32_t wd1_timeout; /* L1 timeout */ - int32_t wd2_timeout; /* L2 timeout */ - uchar_t wd_pat_state; /* pat state */ - boolean_t reboot_action; /* is reboot action set */ - boolean_t is_host; /* is a host or standalone CPU */ - - /* Cache for PICL handles */ - picl_nodehdl_t wd_ctrl_nodehdl; /* watchdog controller */ - /* prop handle for op */ - picl_prophdl_t wd_ops_hdl; - - picl_prophdl_t wd1_state_hdl; - picl_prophdl_t wd1_timeout_hdl; - picl_prophdl_t wd1_action_hdl; - picl_nodehdl_t wd1_nodehdl; /* L1 node handle */ - - picl_prophdl_t wd2_state_hdl; - picl_prophdl_t wd2_timeout_hdl; - picl_prophdl_t wd2_action_hdl; - picl_nodehdl_t wd2_nodehdl; /* L2 node handle */ -} wd_data_t; - -/* structure to hold watchdog status */ -typedef struct { - int present_state; - uint8_t action1; - uint8_t action2; - uint8_t timeout1[2]; - uint8_t timeout2; - uint8_t present_t1[2]; -} wd_state_t; - -/* Error messages */ -#define WD_PICL_NOSPACE \ - gettext("SUNW_piclwatchdog: Error in memory allocation") -#define WD_PICL_REG_ERR \ - gettext("SUNW_piclwatchdog: Failed to register with picl framework,"\ - " error = %d") -#define WD_PICL_SMC_OPEN_ERR \ - gettext("SUNW_piclwatchdog: Error in opening SMC drv") -#define WD_PICL_EXCLUSIVE_ACCESS_ERR \ - gettext("SUNW_piclwatchdog: Error in getting exclusive access "\ - "for watchdog commands") -#define WD_PICL_THREAD_CREATE_FAILED \ - gettext("SUNW_piclwatchdog: Error in creating %s thread") -#define WD_PICL_PROP_INIT_ERR \ - gettext("SUNW_piclwatchdog: ptree prop init call failed:%d") -#define WD_NODE_INIT_ERR \ - gettext("SUNW_piclwatchdog: Error in creating watchdog nodes(%d):%d") -#define WD_PICL_GET_STAT_ERR \ - gettext("SUNW_piclwatchdog: Error in getting the watchdog status") -#define WD_PICL_GET_ERR \ - gettext("SUNW_piclwatchdog: Error in getting watchdog status,"\ - " error = %d") -#define WD_PICL_PAT_ERR \ - gettext("SUNW_piclwatchdog: Error in patting the watchdog"\ - " error = %d") -#define WD_PICL_START_ERR \ - gettext("SUNW_piclwatchdog: Error in starting the watchdog, error = %d") -#define WD_PICL_STOP_ERR \ - gettext("SUNW_piclwatchdog: Error in stopping the watchdog,"\ - " error = %d") -#define WD_PICL_SET_ATTR_FAILED \ - gettext("SUNW_piclwatchdog: Error in setting attributes for a stream") -#define WD_PICL_RT_THRD_FAIL \ - gettext("SUNW_piclwatchdog: Error in creating real time thread") -#define WD_PICL_RT_THRD_NO_PERM_ERR \ - gettext("SUNW_piclwatchdog: No perm to change the priority of thread") -#define WD_PICL_NO_WD_ERR \ - gettext("SUNW_piclwatchdog: Watchdog is not running") -#define WD_PICL_WD1_RUNNING_ERR \ - gettext("SUNW_piclwatchdog: Disarm the Watchdog level 1") -#define WD_PICL_WD2_RUNNING_ERR \ - gettext("SUNW_piclwatchdog: Disarm the Watchdog level 2") -#define WD_PICL_SMC_READ_ERR \ - gettext("SUNW_piclwatchdog: Error in reading from SMC") -#define WD_PICL_SMC_WRITE_ERR \ - gettext("SUNW_piclwatchdog: Error in writing to SMC") -#define WD_NO_ROOT_PERM \ - gettext("SUNW_piclwatchdog: Root perm are reqd to perform this op.") -#define WD_PICL_POLL_ERR \ - gettext("SUNW_piclwatchdog: Error in poll system call") -#define WD_PICL_INVALID_T1 \ - gettext("SUNW_piclwatchdog: Invalid timeout value for wd level 1") -#define WD_PICL_INVALID_T2 \ - gettext("SUNW_piclwatchdog: Invalid timeout value for wd level 2") -#define WD_PICL_TMOUT_LV1_LV2_SETTO_0 \ - gettext("SUNW_piclwatchdog: Invalid timeout val for wd level 1 & 2") -#define WD_PICL_INVALID_ACTION1 \ - gettext("SUNW_piclwatchdog: Invalid action for level one") -#define WD_PICL_INVALID_ACTION2 \ - gettext("SUNW_piclwatchdog: Invalid action for level two") -#define WD_PICL_CLEAR_EXCL_ERR \ - gettext("SUNW_piclwatchdog: Error in clearing exclusive "\ - "access for watchdog commands") -#define WD_PICL_POST_EVENT_ERR \ - gettext("SUNW_piclwatchdog: Error in posting wd expiry event,"\ - " error = %d") -#define WD_PICL_COND_SIGNAL_ERR \ - gettext("SUNW_piclwatchdog: Error in cond_signal") -#define WD_PICL_IS_NOT_SUPPORTED \ - gettext("SUNW_piclwatchdog: This feature is not supported") -#define WD_PICL_TRY_PAT_ERR \ - gettext("SUNW_piclwatchdog: OS is already patting the watchdog") -#define WD_PICL_GET_TIMEOUT_ERR \ - gettext("SUNW_piclwatchdog: Error in getting the timeout values") -#define WD_PICL_ARM_PAT_ERR \ - gettext("SUNW_piclwatchdog: Illegal timeout values for arm-pat op") -#define WD_PICL_PERM_DENIED \ - gettext("SUNW_piclwatchdog: This client is not the owner of watchdog") -#define WD_PICL_PAT_TIME_ERR \ - gettext("SUNW_piclwatchdog: Negative value for pat_time \ - is not allowed") -#define WD_PICL_STATE_INVALID \ - gettext("SUNW_piclwatchdog: WD operations not allowed while "\ - "chassis state is configuring") -#define WD_HEALTHY_ERR \ - gettext("SUNW_piclwatchdog: Cannot arm the watchdog, "\ - "action already taken") -#define WD_GET_OWN_FAILED \ - gettext("SUNW_piclwatchdog: Error in finding active owner of watchdog,"\ - " error = %d") -#define WD_NVLIST_ERR \ - gettext("SUNW_piclwatchdog: Error in posting watchdog event"\ - "(nvlist error), error = %d") -#define WD_GET_HEALTH_ERR \ - gettext("SUNW_piclwatchdog: Error in getting HEALTHY# status") -#define WD_UPDATE_STATE_ERR \ - gettext("SUNW_piclwatchdog: Error in updating watchdog state,"\ - "error = %d") -#define WD_WD1_EXPIRED \ - gettext("SUNW_piclwatchdog: watchdog level 1 expired") -#ifdef __cplusplus -} -#endif - -#endif /* _PICL_WATCHDOG_H */ diff --git a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwd_platmod.c b/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwd_platmod.c deleted file mode 100644 index 4b00529f54..0000000000 --- a/usr/src/cmd/picl/plugins/sun4u/snowbird/watchdog/piclwd_platmod.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <picl.h> -#include <picltree.h> -#include <picldefs.h> -#include <string.h> -#include <syslog.h> -#include "piclwatchdog.h" - -#define NETRA_CP2300 "SUNW,Netra-CP2300" - -int -wd_get_chassis_type() -{ - picl_nodehdl_t chassis_h; - char chassis_type[PICL_PROPNAMELEN_MAX]; - - if (ptree_get_node_by_path(PICL_FRUTREE_CHASSIS, - &chassis_h) != PICL_SUCCESS) { - return (-1); - } - - if (ptree_get_propval_by_name(chassis_h, PICL_PROP_CHASSIS_TYPE, - chassis_type, sizeof (chassis_type)) != PICL_SUCCESS) { - return (-1); - } - - if (strcmp(chassis_type, NETRA_CP2300) == 0) { - return (WD_STANDALONE); - } else { - return (-1); - } -} diff --git a/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c b/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c index fa3e985b00..f02c7af356 100644 --- a/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c +++ b/usr/src/cmd/picl/plugins/sun4v/mdesc/mdescplugin.c @@ -22,6 +22,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2019 Peter Tribble. */ /* @@ -220,11 +222,7 @@ signal_devtree(void) return; /* - * Right now (Aug. 2007) snowbird is the only other platform - * which uses this event. Since that's a sun4u platform and - * this is sun4v we do not have to worry about possible confusion - * or interference between the two by grabbing this event for - * our own use here. This event is consumed by the devtree + * This event is consumed by the devtree * plug-in. The event signals the plug-in to re-run its * cpu initialization function, which will cause it to add * additional information to the cpu devtree nodes (particularly, diff --git a/usr/src/cmd/rcm_daemon/Makefile.com b/usr/src/cmd/rcm_daemon/Makefile.com index 621e1cbfb9..017606f830 100644 --- a/usr/src/cmd/rcm_daemon/Makefile.com +++ b/usr/src/cmd/rcm_daemon/Makefile.com @@ -23,6 +23,7 @@ # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2016 Nexenta Systems, Inc. # Copyright (c) 2018, Joyent, Inc. +# Copyright 2019 Peter Tribble. # include ../../Makefile.cmd @@ -61,8 +62,6 @@ COMMON_MOD_SRC = \ $(COMMON)/ip_anon_rcm.c \ $(COMMON)/bridge_rcm.c -sparc_MOD_SRC = $(COMMON)/ttymux_rcm.c - COMMON_PERL_SCRIPT_SRC = sparc_PERL_SCRIPT_SRC = SUNW,vdevices.pl @@ -86,8 +85,6 @@ COMMON_MOD_OBJ = \ ip_anon_rcm.o \ bridge_rcm.o -sparc_MOD_OBJ = ttymux_rcm.o - RCM_DAEMON = rcm_daemon COMMON_RCM_MODS = \ @@ -106,8 +103,6 @@ COMMON_RCM_MODS = \ SUNW_ip_anon_rcm.so \ SUNW_bridge_rcm.so -sparc_RCM_MODS = SUNW_ttymux_rcm.so - RCM_DIR = rcm MOD_DIR = modules SCRIPT_DIR = scripts diff --git a/usr/src/cmd/rcm_daemon/common/ttymux_rcm.c b/usr/src/cmd/rcm_daemon/common/ttymux_rcm.c deleted file mode 100644 index 5b50679a3e..0000000000 --- a/usr/src/cmd/rcm_daemon/common/ttymux_rcm.c +++ /dev/null @@ -1,1434 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <assert.h> -#include <string.h> -#include <limits.h> -#include <synch.h> -#include <libintl.h> -#include <errno.h> -#include <libdevinfo.h> -#include <sys/uio.h> -#include <sys/sysmacros.h> -#include <sys/types.h> -#include <stropts.h> -#include <sys/stream.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/mkdev.h> - -#include <sys/param.h> -#include <sys/openpromio.h> -#include <sys/ttymuxuser.h> - -#include "ttymux_rcm_impl.h" -#include "rcm_module.h" - -#define TTYMUX_OFFLINE_ERR gettext("Resource is in use by") -#define TTYMUX_UNKNOWN_ERR gettext("Unknown Operation attempted") -#define TTYMUX_ONLINE_ERR gettext("Failed to connect under multiplexer") -#define TTYMUX_INVALID_ERR gettext("Invalid Operation on this resource") -#define TTYMUX_OFFLINE_FAIL gettext("Failed to disconnect from multiplexer") -#define TTYMUX_MEMORY_ERR gettext("TTYMUX: strdup failure\n") - - -static int msglvl = 6; /* print messages less than this level */ -#define TEST(cond, stmt) { if (cond) stmt; } -#define _msg(lvl, args) TEST(msglvl > (lvl), trace args) - -static int oflags = O_EXCL|O_RDWR|O_NONBLOCK|O_NOCTTY; -static dev_t cn_dev = NODEV; -static rsrc_t *cn_rsrc = NULL; -static rsrc_t cache_head; -static rsrc_t cache_tail; -static mutex_t cache_lock; -static char muxctl[PATH_MAX] = {0}; -static char muxcon[PATH_MAX] = {0}; -static int muxfd; -static boolean_t register_rsrcs; - -/* module interface routines */ -static int tty_register(rcm_handle_t *); -static int tty_unregister(rcm_handle_t *); -static int tty_getinfo(rcm_handle_t *, char *, id_t, uint_t, char **, - char **, nvlist_t *, rcm_info_t **); -static int tty_suspend(rcm_handle_t *, char *, id_t, - timespec_t *, uint_t, char **, rcm_info_t **); -static int tty_resume(rcm_handle_t *, char *, id_t, uint_t, char **, - rcm_info_t **); -static int tty_offline(rcm_handle_t *, char *, id_t, uint_t, char **, - rcm_info_t **); -static int tty_online(rcm_handle_t *, char *, id_t, uint_t, char **, - rcm_info_t **); -static int tty_remove(rcm_handle_t *, char *, id_t, uint_t, char **, - rcm_info_t **); - -static int get_devpath(char *, char **, dev_t *); - -/* - * Module-Private data - */ -static struct rcm_mod_ops tty_ops = { - RCM_MOD_OPS_VERSION, - tty_register, - tty_unregister, - tty_getinfo, - tty_suspend, - tty_resume, - tty_offline, - tty_online, - tty_remove, - NULL, - NULL -}; - -/*PRINTFLIKE1*/ -static void -trace(char *fmt, ...) -{ - va_list args; - char buf[256]; - int sz; - - va_start(args, fmt); - sz = vsnprintf(buf, sizeof (buf), fmt, args); - va_end(args); - - if (sz < 0) - rcm_log_message(RCM_TRACE1, - _("TTYMUX: vsnprintf parse error\n")); - else if (sz > sizeof (buf)) { - char *b = malloc(sz + 1); - - if (b != NULL) { - va_start(args, fmt); - sz = vsnprintf(b, sz + 1, fmt, args); - va_end(args); - if (sz > 0) - rcm_log_message(RCM_TRACE1, _("%s"), b); - free(b); - } - } else { - rcm_log_message(RCM_TRACE1, _("%s"), buf); - } -} - -/* - * CACHE MANAGEMENT - * Resources managed by this module are stored in a list of rsrc_t - * structures. - */ - -/* - * cache_lookup() - * - * Get a cache node for a resource. Call with cache lock held. - */ -static rsrc_t * -cache_lookup(const char *resource) -{ - rsrc_t *rsrc; - rsrc = cache_head.next; - while (rsrc != &cache_tail) { - if (rsrc->id && strcmp(resource, rsrc->id) == 0) { - return (rsrc); - } - rsrc = rsrc->next; - } - return (NULL); -} - -/* - * Get a cache node for a minor node. Call with cache lock held. - */ -static rsrc_t * -cache_lookup_bydevt(dev_t devt) -{ - rsrc_t *rsrc; - rsrc = cache_head.next; - while (rsrc != &cache_tail) { - if (rsrc->dev == devt) - return (rsrc); - rsrc = rsrc->next; - } - return (NULL); -} - -/* - * free_node() - * - * Free a node. Make sure it isn't in the list! - */ -static void -free_node(rsrc_t *node) -{ - if (node) { - if (node->id) { - free(node->id); - } - free(node); - } -} - -/* - * cache_insert() - * - * Call with the cache_lock held. - */ -static void -cache_insert(rsrc_t *node) -{ - /* insert at the head for best performance */ - node->next = cache_head.next; - node->prev = &cache_head; - - node->next->prev = node; - node->prev->next = node; -} - -/* - * cache_create() - * - * Call with the cache_lock held. - */ -static rsrc_t * -cache_create(const char *resource, dev_t dev) -{ - rsrc_t *rsrc = malloc(sizeof (rsrc_t)); - - if (rsrc != NULL) { - if ((rsrc->id = strdup(resource)) != NULL) { - rsrc->dev = dev; - rsrc->flags = 0; - rsrc->dependencies = NULL; - cache_insert(rsrc); - } else { - free(rsrc); - rsrc = NULL; - } - } else { - _msg(0, ("TTYMUX: malloc failure for resource %s.\n", - resource)); - } - return (rsrc); -} - -/* - * cache_get() - * - * Call with the cache_lock held. - */ -static rsrc_t * -cache_get(const char *resource) -{ - rsrc_t *rsrc = cache_lookup(resource); - if (rsrc == NULL) { - dev_t dev; - - (void) get_devpath((char *)resource, NULL, &dev); - rsrc = cache_create(resource, dev); - } - return (rsrc); -} - -/* - * cache_remove() - * - * Call with the cache_lock held. - */ -static void -cache_remove(rsrc_t *node) -{ - node->next->prev = node->prev; - node->prev->next = node->next; - node->next = NULL; - node->prev = NULL; -} - -/* - * Open a file identified by fname with the given open flags. - * If the request is to open a file with exclusive access and the open - * fails then backoff exponentially and then retry the open. - * Do not wait for longer than about a second (since this may be an rcm - * framework thread). - */ -static int -open_file(char *fname, int flags) -{ - int fd, cnt; - struct timespec ts; - - if ((flags & O_EXCL) == 0) - return (open(fname, flags)); - - ts.tv_sec = 0; - ts.tv_nsec = 16000000; /* 16 milliseconds */ - - for (cnt = 0; cnt < 5 && (fd = open(fname, flags)) == -1; cnt++) { - (void) nanosleep(&ts, NULL); - ts.tv_nsec *= 2; - } - return (fd); -} - -/* - * No-op for creating an association between a pair of resources. - */ -/*ARGSUSED*/ -static int -nullconnect(link_t *link) -{ - return (0); -} - -/* - * No-op for destroying an association between a pair of resources. - */ -/*ARGSUSED*/ -static int -nulldisconnect(link_t *link) -{ - return (0); -} - -/* - * Record an actual or desired association between two resources - * identified by their rsrc_t structures. - */ -static link_t * -add_dependency(rsrc_t *user, rsrc_t *used) -{ - link_t *linkhead; - link_t *link; - - if (user == NULL || used == NULL) - return (NULL); - - if (user->id && used->id && strcmp(user->id, used->id) == 0) { - _msg(2, ("TTYMUX: attempt to connect devices created by " - "the same driver\n")); - return (NULL); - } - - /* - * Search for all resources that this resource user is depending - * upon. - */ - linkhead = user->dependencies; - for (link = linkhead; link != NULL; link = link->next) { - /* - * Does the using resource already depends on the used - * resource - */ - if (link->used == used) - return (link); - } - - link = malloc(sizeof (link_t)); - - if (link == NULL) { - rcm_log_message(RCM_ERROR, _("TTYMUX: Out of memory\n")); - return (NULL); - } - - _msg(6, ("TTYMUX: New link user %s used %s\n", user->id, used->id)); - - link->user = user; - link->used = used; - link->linkid = 0; - link->state = UNKNOWN; - link->flags = 0; - - link->connect = nullconnect; - link->disconnect = nulldisconnect; - link->next = linkhead; - - user->dependencies = link; - - return (link); -} - -/* - * Send an I_STR stream ioctl to a device - */ -static int -istrioctl(int fd, int cmd, void *data, int datalen, int *bytes) { - struct strioctl ios; - int rval; - - ios.ic_timout = 0; /* use the default */ - ios.ic_cmd = cmd; - ios.ic_dp = (char *)data; - ios.ic_len = datalen; - - rval = ioctl(fd, I_STR, (char *)&ios); - if (bytes) - *bytes = ios.ic_len; - return (rval); -} - -/* - * Streams link the driver identified by fd underneath a mux - * identified by ctrl_fd. - */ -static int -plink(int ctrl_fd, int fd) -{ - int linkid; - - /* - * pop any modules off the lower stream. - */ - while (ioctl(fd, I_POP, 0) == 0) - ; - - if ((linkid = ioctl(ctrl_fd, I_PLINK, fd)) < 0) - rcm_log_message(RCM_ERROR, - _("TTYMUX: I_PLINK error %d.\n"), errno); - return (linkid); -} - -/* - * Streams unlink the STREAM identified by linkid from a mux - * identified by ctrl_fd. - */ -static int -punlink(int ctrl_fd, int linkid) -{ - if (ioctl(ctrl_fd, I_PUNLINK, linkid) < 0) - return (errno); - else - return (0); -} - -/* - * Connect a pair of resources by establishing the dependency association. - * Only works for devices that support the TTYMUX ioctls. - */ -static int -mux_connect(link_t *link) -{ - int lfd; - int rv; - ttymux_assoc_t as; - uint8_t ioflags; - - _msg(6, ("TTYMUX: mux_connect (%ld:%ld<->%ld:%ld %s <-> %s\n", - major(link->user->dev), minor(link->user->dev), - major(link->used->dev), minor(link->used->dev), - link->user->id, link->used->id)); - - _msg(12, ("TTYMUX: struct size = %d (plen %d)\n", - sizeof (as), PATH_MAX)); - - if (link->user->dev == NODEV || link->used->dev == NODEV) { - /* - * One of the resources in the association is not - * present (wait for the online notification before - * attempting to establish the dependency association. - */ - return (EAGAIN); - } - if (major(link->user->dev) == major(link->used->dev)) { - _msg(2, ("TTYMUX: attempt to link devices created by " - "the same driver\n")); - return (EINVAL); - } - /* - * Explicitly check for attempts to plumb the system console - - * required becuase not all serial devices support the - * O_EXCL open flag. - */ - if (link->used->dev == cn_dev) { - rcm_log_message(RCM_WARNING, _("TTYMUX: Request to link the " - " system console under another device not allowed!\n")); - - return (EPERM); - } - - /* - * Ensure that the input/output mode of the dependent is reasonable - */ - if ((ioflags = link->flags & FORIO) == 0) - ioflags = FORIO; - - /* - * Open each resource participating in the association. - */ - lfd = open(link->used->id, O_EXCL|O_RDWR|O_NONBLOCK|O_NOCTTY); - if (lfd == -1) { - if (errno == EBUSY) { - rcm_log_message(RCM_WARNING, _("TTYMUX: device %s is " - " busy - " " cannot connect to %s\n"), - link->used->id, link->user->id); - } else { - rcm_log_message(RCM_WARNING, - _("TTYMUX: open error %d for device %s\n"), - errno, link->used->id); - } - return (errno); - } - /* - * Note: Issuing the I_PLINK and TTYMUX_ASSOC request on the 'using' - * resource is more generic: - * muxfd = open(link->user->id, oflags); - * However using the ctl (MUXCTLLINK) node means that any current opens - * on the 'using' resource are uneffected. - */ - - /* - * Figure out if the 'used' resource is already associated with - * some resource - if so tell the caller to try again later. - * More generally if any user or kernel thread has the resource - * open then the association should not be made. - * The ttymux driver makes this check (but it should be done here). - */ - as.ttymux_linkid = 0; - as.ttymux_ldev = link->used->dev; - - if (istrioctl(muxfd, TTYMUX_GETLINK, - (void *)&as, sizeof (as), NULL) == 0) { - - _msg(7, ("TTYMUX: %ld:%ld (%d) (udev %ld:%ld) already linked\n", - major(as.ttymux_ldev), minor(as.ttymux_ldev), - as.ttymux_linkid, major(as.ttymux_udev), - minor(as.ttymux_udev))); - link->linkid = as.ttymux_linkid; - if (as.ttymux_udev != NODEV) { - (void) close(lfd); - return (EAGAIN); - } - } - - /* - * Now link and associate the used resource under the using resource. - */ - as.ttymux_udev = link->user->dev; - as.ttymux_ldev = link->used->dev; - as.ttymux_tag = 0ul; - as.ttymux_ioflag = ioflags; - - _msg(6, ("TTYMUX: connecting %ld:%ld to %ld:%ld\n", - major(as.ttymux_ldev), minor(as.ttymux_ldev), - major(as.ttymux_udev), minor(as.ttymux_udev))); - - if (as.ttymux_udev == cn_dev) { - struct termios tc; - - if (ioctl(lfd, TCGETS, &tc) != -1) { - tc.c_cflag |= CREAD; - if (ioctl(lfd, TCSETSW, &tc) == -1) { - rcm_log_message(RCM_WARNING, - _("TTYMUX: error %d whilst enabling the " - "receiver on device %d:%d\n"), - errno, major(as.ttymux_ldev), - minor(as.ttymux_ldev)); - } - } - } - - if (as.ttymux_linkid <= 0 && (as.ttymux_linkid = - plink(muxfd, lfd)) <= 0) { - rcm_log_message(RCM_WARNING, - _("TTYMUX: Link error %d for device %s\n"), - errno, link->used->id); - rv = errno; - goto out; - } - link->linkid = as.ttymux_linkid; - - _msg(6, ("TTYMUX: associating\n")); - if (istrioctl(muxfd, TTYMUX_ASSOC, (void *)&as, sizeof (as), 0) != 0) { - rv = errno; - goto out; - } - _msg(6, ("TTYMUX: Succesfully connected %ld:%ld to %ld:%ld\n", - major(as.ttymux_ldev), minor(as.ttymux_ldev), - major(as.ttymux_udev), minor(as.ttymux_udev))); - link->state = CONNECTED; - (void) close(lfd); - return (0); -out: - rcm_log_message(RCM_WARNING, - _("TTYMUX: Error [%d] connecting %d:%d to %d:%d\n"), - rv, major(as.ttymux_ldev), minor(as.ttymux_ldev), - major(as.ttymux_udev), minor(as.ttymux_udev)); - - (void) close(lfd); - if (as.ttymux_linkid > 0) { - /* - * There was an error so unwind the I_PLINK step - */ - if (punlink(muxfd, as.ttymux_linkid) != 0) - rcm_log_message(RCM_WARNING, - _("TTYMUX: Unlink error %d (%s).\n"), - errno, link->used->id); - } - return (rv); -} - -/* - * Disconnect a pair of resources by destroying the dependency association. - * Only works for devices that support the TTYMUX ioctls. - */ -static int -mux_disconnect(link_t *link) -{ - int rv; - ttymux_assoc_t as; - - _msg(6, ("TTYMUX: mux_disconnect %s<->%s (%ld:%ld<->%ld:%ld)\n", - link->user->id, link->used->id, - major(link->user->dev), minor(link->user->dev), - major(link->used->dev), minor(link->used->dev))); - - as.ttymux_ldev = link->used->dev; - - if (istrioctl(muxfd, TTYMUX_GETLINK, - (void *)&as, sizeof (as), NULL) != 0) { - - _msg(1, ("TTYMUX: %ld:%ld not linked [err %d]\n", - major(link->used->dev), minor(link->used->dev), errno)); - return (0); - - /* - * Do not disassociate console resources - simply - * unlink them so that they remain persistent. - */ - } else if (as.ttymux_udev != cn_dev && - istrioctl(muxfd, TTYMUX_DISASSOC, (void *)&as, - sizeof (as), 0) == -1) { - - rv = errno; - rcm_log_message(RCM_WARNING, - _("TTYMUX: Dissassociate error %d for %s\n"), - rv, link->used->id); - - } else if (punlink(muxfd, as.ttymux_linkid) != 0) { - rv = errno; - rcm_log_message(RCM_WARNING, - _("TTYMUX: Error %d unlinking %d:%d\n"), - errno, major(link->used->dev), minor(link->used->dev)); - } else { - _msg(6, ("TTYMUX: %s<->%s disconnected.\n", - link->user->id, link->used->id)); - - link->state = DISCONNECTED; - link->linkid = 0; - rv = 0; - } - return (rv); -} - -/* PESISTENCY */ - -/* - * Given a special device file system path return the /devices path - * and/or the device number (dev_t) of the device. - */ -static int -get_devpath(char *dev, char **cname, dev_t *devt) -{ - struct stat sb; - - if (cname != NULL) - *cname = NULL; - - if (devt != NULL) - *devt = NODEV; - - if (lstat(dev, &sb) < 0) { - return (errno); - } else if ((sb.st_mode & S_IFMT) == S_IFLNK) { - int lsz; - char linkbuf[PATH_MAX+1]; - - if (stat(dev, &sb) < 0) - return (errno); - - lsz = readlink(dev, linkbuf, PATH_MAX); - - if (lsz <= 0) - return (ENODEV); - linkbuf[lsz] = '\0'; - dev = strstr(linkbuf, "/devices"); - if (dev == NULL) - return (ENODEV); - } - - if (cname != NULL) - *cname = strdup(dev); - - if (devt != NULL) - *devt = sb.st_rdev; - - return (0); -} - -/* - * See routine locate_node - */ -static int -locate_dev(di_node_t node, di_minor_t minor, void *arg) -{ - char *devfspath; - char resource[PATH_MAX]; - rsrc_t *rsrc; - - if (di_minor_devt(minor) != (dev_t)arg) - return (DI_WALK_CONTINUE); - - if ((devfspath = di_devfs_path(node)) == NULL) - return (DI_WALK_TERMINATE); - - if (snprintf(resource, sizeof (resource), "/devices%s:%s", - devfspath, di_minor_name(minor)) > sizeof (resource)) { - di_devfs_path_free(devfspath); - return (DI_WALK_TERMINATE); - } - - di_devfs_path_free(devfspath); - - rsrc = cache_lookup(resource); - if (rsrc == NULL && - (rsrc = cache_create(resource, di_minor_devt(minor))) == NULL) - return (DI_WALK_TERMINATE); - - rsrc->dev = di_minor_devt(minor); - rsrc->flags |= PRESENT; - rsrc->flags &= ~UNKNOWN; - return (DI_WALK_TERMINATE); -} - -/* - * Find a devinfo node that matches the device argument (dev). - * This is an expensive search of the whole device tree! - */ -static rsrc_t * -locate_node(dev_t dev, di_node_t *root) -{ - rsrc_t *rsrc; - - assert(root != NULL); - - if ((rsrc = cache_lookup_bydevt(dev)) != NULL) - return (rsrc); - - (void) di_walk_minor(*root, NULL, 0, (void*)dev, locate_dev); - - return (cache_lookup_bydevt(dev)); -} - -/* - * Search for any existing dependency relationships managed by this - * RCM module. - */ -static int -probe_dependencies() -{ - ttymux_assocs_t links; - ttymux_assoc_t *asp; - int cnt, n; - rsrc_t *ruser; - rsrc_t *used; - link_t *link; - di_node_t root; - - cnt = istrioctl(muxfd, TTYMUX_LIST, (void *)0, 0, 0); - - _msg(8, ("TTYMUX: Probed %d links [%d]\n", cnt, errno)); - - if (cnt <= 0) - return (0); - - if ((links.ttymux_assocs = calloc(cnt, sizeof (ttymux_assoc_t))) == 0) - return (EAGAIN); - - links.ttymux_nlinks = cnt; - - n = istrioctl(muxfd, TTYMUX_LIST, (void *)&links, sizeof (links), 0); - - if (n == -1) { - _msg(2, ("TTYMUX: Probe error %s\n", strerror(errno))); - free(links.ttymux_assocs); - return (0); - } - - asp = (ttymux_assoc_t *)links.ttymux_assocs; - - if ((root = di_init("/", DINFOSUBTREE|DINFOMINOR)) == DI_NODE_NIL) - return (errno); - - (void) mutex_lock(&cache_lock); - for (; cnt--; asp++) { - _msg(7, ("TTYMUX: Probed: %ld %ld %ld:%ld <-> %ld:%ld\n", - asp->ttymux_udev, asp->ttymux_ldev, - major(asp->ttymux_udev), minor(asp->ttymux_udev), - major(asp->ttymux_ldev), minor(asp->ttymux_ldev))); - /* - * The TTYMUX_LIST ioctl can return links relating - * to potential devices. Such devices are identified - * in the path field. - */ - if (asp->ttymux_ldev == NODEV) { - char buf[PATH_MAX]; - - if (asp->ttymux_path == NULL || - *asp->ttymux_path != '/') - continue; - - if (snprintf(buf, sizeof (buf), "/devices%s", - asp->ttymux_path) > sizeof (buf)) - continue; - - used = cache_get(buf); - } else { - used = locate_node(asp->ttymux_ldev, &root); - } - if ((ruser = locate_node(asp->ttymux_udev, &root)) == NULL) { - _msg(7, ("TTYMUX: Probe: %ld:%ld not present\n", - major(asp->ttymux_udev), minor(asp->ttymux_udev))); - continue; - } - if (used == NULL) { - _msg(7, ("TTYMUX: Probe: %ld:%ld not present\n", - major(asp->ttymux_ldev), minor(asp->ttymux_ldev))); - continue; - } - _msg(6, ("TTYMUX: Probe: Restore %s <-> %s (id %d)\n", - ruser->id, used->id, asp->ttymux_linkid)); - - link = add_dependency(ruser, used); - - if (link != NULL) { - link->flags = (uint_t)asp->ttymux_ioflag; - link->linkid = asp->ttymux_linkid; - link->state = CONNECTED; - link->connect = mux_connect; - link->disconnect = mux_disconnect; - } - } - di_fini(root); - (void) mutex_unlock(&cache_lock); - free(links.ttymux_assocs); - return (0); -} - -/* - * A resource has become available. Re-establish any associations involving - * the resource. - */ -static int -rsrc_available(rsrc_t *rsrc) -{ - link_t *link; - rsrc_t *rs; - - if (rsrc->dev == NODEV) { - /* - * Now that the resource is present obtain its device number. - * For this to work the node must be present in the /devices - * tree (see devfsadm(1M) or drvconfig(1M)). - * We do not use libdevinfo because the node must be present - * under /devices for the connect step below to work - * (the node needs to be opened). - */ - (void) get_devpath(rsrc->id, NULL, &rsrc->dev); - if (rsrc->dev == NODEV) { - _msg(4, - ("Device node %s does not exist\n", rsrc->id)); - /* - * What does RCM do with failed online notifications. - */ - return (RCM_FAILURE); - } - } - for (rs = cache_head.next; rs != &cache_tail; rs = rs->next) { - for (link = rs->dependencies; - link != NULL; - link = link->next) { - if (link->user == rsrc || link->used == rsrc) { - _msg(6, ("TTYMUX: re-connect\n")); - (void) link->connect(link); - } - } - } - return (RCM_SUCCESS); -} - -/* - * A resource is going away. Tear down any associations involving - * the resource. - */ -static int -rsrc_unavailable(rsrc_t *rsrc) -{ - link_t *link; - rsrc_t *rs; - - for (rs = cache_head.next; rs != &cache_tail; rs = rs->next) { - for (link = rs->dependencies; - link != NULL; - link = link->next) { - if (link->user == rsrc || link->used == rsrc) { - _msg(6, ("TTYMUX: unavailable %s %s\n", - link->user->id, link->used->id)); - (void) link->disconnect(link); - } - } - } - - return (RCM_SUCCESS); -} - -/* - * Find any resources that are using a given resource (identified by - * the rsrc argument). The search begins after the resource identified - * by the next argument. If next is NULL start at the first resource - * in this RCM modules resource list. If the redundancy argument is - * greater than zero then a resource which uses rsrc will only be - * returned if it is associated with >= redundancy dependents. - * - * Thus, provided that the caller keeps the list locked it can iterate - * through all the resources in the cache that depend upon rsrc. - */ -static rsrc_t * -get_next_user(rsrc_t *next, rsrc_t *rsrc, int redundancy) -{ - rsrc_t *src; - link_t *link; - int cnt = 0; - boolean_t inuse; - - src = (next != NULL) ? next->next : cache_head.next; - - while (src != &cache_tail) { - inuse = B_FALSE; - - for (link = src->dependencies, cnt = 0; - link != NULL; - link = link->next) { - - if (link->state == CONNECTED) - cnt++; - - if (link->used == rsrc) - inuse = B_TRUE; - } - if (inuse == B_TRUE && - (redundancy <= 0 || cnt == redundancy)) { - return (src); - } - - src = src->next; - } - - _msg(8, ("TTYMUX: count_users(%s) res %d.\n", rsrc->id, cnt)); - return (NULL); -} - -/* - * Common handler for RCM notifications. - */ -/*ARGSUSED*/ -static int -rsrc_change_common(rcm_handle_t *hd, int op, const char *rsrcid, uint_t flag, - char **reason, rcm_info_t **dependent_reason, void *arg) -{ - rsrc_t *rsrc, *user; - int rv, len; - char *tmp = NULL; - - (void) mutex_lock(&cache_lock); - rsrc = cache_lookup(rsrcid); - if (rsrc == NULL) { - /* shouldn't happen because rsrc has been registered */ - (void) mutex_unlock(&cache_lock); - return (RCM_SUCCESS); - } - if ((muxfd = open_file(muxctl, oflags)) == -1) { - rcm_log_message(RCM_ERROR, _("TTYMUX: %s unavailable: %s\n"), - muxctl, strerror(errno)); - (void) mutex_unlock(&cache_lock); - return (RCM_SUCCESS); - } - switch (op) { - - case TTYMUX_SUSPEND: - rv = RCM_FAILURE; - _msg(4, ("TTYMUX: SUSPEND %s operation refused.\n", - rsrc->id)); - if ((*reason = strdup(TTYMUX_INVALID_ERR)) == NULL) { - rcm_log_message(RCM_ERROR, TTYMUX_MEMORY_ERR); - } - break; - - case TTYMUX_REMOVE: - rsrc->flags |= UNKNOWN; - rsrc->flags &= ~(PRESENT | REGISTERED); - rv = RCM_SUCCESS; - break; - - case TTYMUX_OFFLINE: - user = get_next_user(NULL, rsrc, 1); - if (flag & RCM_QUERY) { - rv = ((flag & RCM_FORCE) || (user == NULL)) ? - RCM_SUCCESS : RCM_FAILURE; - if (rv == RCM_FAILURE) { - tmp = TTYMUX_OFFLINE_ERR; - assert(tmp != NULL); - len = strlen(tmp) + strlen(user->id) + 2; - if ((*reason = (char *)malloc(len)) != NULL) { - (void) snprintf(*reason, len, - "%s %s", tmp, user->id); - } else { - rcm_log_message(RCM_ERROR, TTYMUX_MEMORY_ERR); - } - } - - } else if (flag & RCM_FORCE) { - rv = rsrc_unavailable(rsrc); - - if (rv == RCM_FAILURE) { - if ((*reason = strdup(TTYMUX_OFFLINE_FAIL)) == - NULL) { - rcm_log_message(RCM_ERROR, - TTYMUX_MEMORY_ERR); - } - } - - } else if (user != NULL) { - rv = RCM_FAILURE; - tmp = TTYMUX_OFFLINE_ERR; - assert(tmp != NULL); - len = strlen(tmp) + strlen(user->id) + 2; - if ((*reason = (char *)malloc(len)) != NULL) { - (void) snprintf(*reason, len, - "%s %s", tmp, user->id); - } else { - rcm_log_message(RCM_ERROR, TTYMUX_MEMORY_ERR); - } - - } else { - rv = rsrc_unavailable(rsrc); - if (rv == RCM_FAILURE) { - if ((*reason = strdup(TTYMUX_OFFLINE_FAIL)) == - NULL) { - rcm_log_message(RCM_ERROR, - TTYMUX_MEMORY_ERR); - } - } - } - - if (rv == RCM_FAILURE) { - _msg(4, ("TTYMUX: OFFLINE %s operation refused.\n", - rsrc->id)); - - } else { - _msg(4, ("TTYMUX: OFFLINE %s res %d.\n", rsrc->id, rv)); - } - break; - - case TTYMUX_RESUME: - rv = RCM_FAILURE; - _msg(4, ("TTYMUX: RESUME %s operation refused.\n", - rsrc->id)); - if ((*reason = strdup(TTYMUX_INVALID_ERR)) == NULL) { - rcm_log_message(RCM_ERROR, TTYMUX_MEMORY_ERR); - } - break; - - case TTYMUX_ONLINE: - _msg(4, ("TTYMUX: ONLINE %s res %d.\n", rsrc->id, rv)); - rv = rsrc_available(rsrc); - if (rv == RCM_FAILURE) { - if ((*reason = strdup(TTYMUX_ONLINE_ERR)) == NULL) { - rcm_log_message(RCM_ERROR, TTYMUX_MEMORY_ERR); - } - } - break; - default: - rv = RCM_FAILURE; - if ((*reason = strdup(TTYMUX_UNKNOWN_ERR)) == NULL) { - rcm_log_message(RCM_ERROR, TTYMUX_MEMORY_ERR); - } - } - - (void) close(muxfd); - (void) mutex_unlock(&cache_lock); - return (rv); -} - -static boolean_t -find_mux_nodes(char *drv) -{ - di_node_t root, node; - di_minor_t dim; - char *devfspath; - char muxctlname[] = "ctl"; - char muxconname[] = "con"; - int nminors = 0; - - (void) strcpy(muxctl, MUXCTLLINK); - (void) strcpy(muxcon, MUXCONLINK); - cn_rsrc = NULL; - - if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { - rcm_log_message(RCM_WARNING, _("di_init error\n")); - return (B_FALSE); - } - - node = di_drv_first_node(drv, root); - if (node == DI_NODE_NIL) { - _msg(4, ("no node for %s\n", drv)); - di_fini(root); - return (B_FALSE); - } - /* - * If the device is not a prom node do not continue. - */ - if (di_nodeid(node) != DI_PROM_NODEID) { - di_fini(root); - return (B_FALSE); - } - if ((devfspath = di_devfs_path(node)) == NULL) { - di_fini(root); - return (B_FALSE); - } - - /* - * Loop through all the minor nodes the driver (drv) looking - * for the ctl node (this is the device on which - * to issue ioctls). - */ - dim = DI_MINOR_NIL; - while ((dim = di_minor_next(node, dim)) != DI_MINOR_NIL) { - - _msg(7, ("MUXNODES: minor %s\n", di_minor_name(dim))); - - if (strcmp(di_minor_name(dim), muxctlname) == 0) { - if (snprintf(muxctl, sizeof (muxctl), - "/devices%s:%s", devfspath, - di_minor_name(dim)) > sizeof (muxctl)) { - _msg(1, ("muxctl:snprintf error\n")); - } - if (++nminors == 2) - break; - } else if (strcmp(di_minor_name(dim), muxconname) == 0) { - if (snprintf(muxcon, sizeof (muxcon), - "/devices%s:%s", devfspath, - di_minor_name(dim)) > sizeof (muxcon)) { - _msg(1, ("muxcon:snprintf error\n")); - } - if (++nminors == 2) - break; - } - } - - di_devfs_path_free(devfspath); - di_fini(root); - - if ((muxfd = open_file(muxctl, oflags)) != -1) { - - if (istrioctl(muxfd, TTYMUX_CONSDEV, (void *)&cn_dev, - sizeof (cn_dev), 0) != 0) { - cn_dev = NODEV; - } else { - _msg(8, ("MUXNODES: found sys console: %ld:%ld\n", - major(cn_dev), minor(cn_dev))); - - cn_rsrc = cache_create(muxcon, cn_dev); - if (cn_rsrc != NULL) { - cn_rsrc->flags |= PRESENT; - cn_rsrc->flags &= ~UNKNOWN; - } - } - (void) close(muxfd); - - if (cn_dev != NODEV) - return (B_TRUE); - } else { - _msg(1, ("TTYMUX: %s unavailable: %s\n", - muxctl, strerror(errno))); - } - - return (B_FALSE); -} - -/* - * Update registrations, and return the ops structure. - */ -struct rcm_mod_ops * -rcm_mod_init() -{ - _msg(4, ("TTYMUX: mod_init:\n")); - cache_head.next = &cache_tail; - cache_head.prev = NULL; - cache_tail.prev = &cache_head; - cache_tail.next = NULL; - (void) mutex_init(&cache_lock, NULL, NULL); - - /* - * Find the multiplexer ctl and con nodes - */ - register_rsrcs = find_mux_nodes(TTYMUX_DRVNAME); - - return (&tty_ops); -} - -/* - * Save state and release resources. - */ -int -rcm_mod_fini() -{ - rsrc_t *rsrc; - link_t *link, *nlink; - - _msg(7, ("TTYMUX: freeing cache.\n")); - (void) mutex_lock(&cache_lock); - rsrc = cache_head.next; - while (rsrc != &cache_tail) { - cache_remove(rsrc); - - for (link = rsrc->dependencies; link != NULL; ) { - nlink = link->next; - free(link); - link = nlink; - } - - free_node(rsrc); - rsrc = cache_head.next; - } - (void) mutex_unlock(&cache_lock); - - (void) mutex_destroy(&cache_lock); - return (RCM_SUCCESS); -} - -/* - * Return a string describing this module. - */ -const char * -rcm_mod_info() -{ - return ("Serial mux device module 1.1"); -} - -/* - * RCM Notification Handlers - */ - -static int -tty_register(rcm_handle_t *hd) -{ - rsrc_t *rsrc; - link_t *link; - int rv; - - if (register_rsrcs == B_FALSE) - return (RCM_SUCCESS); - - if ((muxfd = open_file(muxctl, oflags)) == -1) { - rcm_log_message(RCM_ERROR, _("TTYMUX: %s unavailable: %s\n"), - muxctl, strerror(errno)); - return (RCM_SUCCESS); - } - /* - * Search for any new dependencies since the last notification or - * since module was initialisated. - */ - (void) probe_dependencies(); - - /* - * Search the whole cache looking for any unregistered used resources - * and register them. Note that the 'using resource' (a ttymux device - * node) is not subject to DR operations so there is no need to - * register them with the RCM framework. - */ - (void) mutex_lock(&cache_lock); - for (rsrc = cache_head.next; rsrc != &cache_tail; rsrc = rsrc->next) { - _msg(6, ("TTYMUX: REGISTER rsrc %s flags %d\n", - rsrc->id, rsrc->flags)); - - if (rsrc->dependencies != NULL && - (rsrc->flags & REGISTERED) == 0) { - _msg(6, ("TTYMUX: Registering rsrc %s\n", rsrc->id)); - rv = rcm_register_interest(hd, rsrc->id, 0, NULL); - if (rv == RCM_SUCCESS) - rsrc->flags |= REGISTERED; - } - - for (link = rsrc->dependencies; link != NULL; - link = link->next) { - if ((link->used->flags & REGISTERED) != 0) - continue; - - _msg(6, ("TTYMUX: Registering rsrc %s\n", - link->used->id)); - rv = rcm_register_interest(hd, link->used->id, - 0, NULL); - if (rv != RCM_SUCCESS) - rcm_log_message(RCM_WARNING, - _("TTYMUX: err %d registering %s\n"), - rv, link->used->id); - else - link->used->flags |= REGISTERED; - } - } - - (void) mutex_unlock(&cache_lock); - (void) close(muxfd); - return (RCM_SUCCESS); -} - -/* - * Unregister all registrations. - */ -static int -tty_unregister(rcm_handle_t *hd) -{ - rsrc_t *rsrc; - - (void) mutex_lock(&cache_lock); - /* - * Search every resource in the cache and if it has been registered - * then unregister it from the RCM framework. - */ - for (rsrc = cache_head.next; rsrc != &cache_tail; rsrc = rsrc->next) { - if ((rsrc->flags & REGISTERED) == 0) - continue; - - if (rcm_unregister_interest(hd, rsrc->id, 0) != RCM_SUCCESS) - rcm_log_message(RCM_WARNING, - _("TTYMUX: Failed to unregister %s\n"), rsrc->id); - else - rsrc->flags &= ~REGISTERED; - } - (void) mutex_unlock(&cache_lock); - return (RCM_SUCCESS); -} - -/* - * Report resource usage information. - */ -/*ARGSUSED*/ -static int -tty_getinfo(rcm_handle_t *hd, char *rsrcid, id_t id, uint_t flag, char **info, - char **errstr, nvlist_t *proplist, rcm_info_t **depend_info) -{ - rsrc_t *rsrc, *user; - char *ru; - size_t sz; - - (void) mutex_lock(&cache_lock); - rsrc = cache_lookup(rsrcid); - - if (rsrc == NULL) { - (void) mutex_unlock(&cache_lock); - *errstr = strdup(gettext("Unmanaged resource")); - return (RCM_FAILURE); - } - - ru = strdup(gettext("Resource Users")); - user = NULL; - while ((user = get_next_user(user, rsrc, -1)) != NULL) { - *info = ru; - sz = strlen(*info) + strlen(user->id) + 2; - ru = malloc(sz); - if (ru == NULL) { - free(*info); - *info = NULL; - break; - } - if (snprintf(ru, sz, ": %s%s", *info, user->id) > sz) { - _msg(4, ("tty_getinfo: snprintf error.\n")); - } - - free(*info); - } - *info = ru; - - if (*info == NULL) { - (void) mutex_unlock(&cache_lock); - *errstr = strdup(gettext("Short of memory resources")); - return (RCM_FAILURE); - } - - (void) mutex_unlock(&cache_lock); - return (RCM_SUCCESS); -} - -/*ARGSUSED*/ -static int -tty_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, - char **reason, rcm_info_t **dependent_reason) -{ - return (rsrc_change_common(hd, TTYMUX_OFFLINE, rsrc, flags, - reason, dependent_reason, NULL)); -} - -/*ARGSUSED*/ -static int -tty_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, - char **reason, rcm_info_t **dependent_reason) -{ - return (rsrc_change_common(hd, TTYMUX_REMOVE, rsrc, flags, - reason, dependent_reason, NULL)); -} - -/*ARGSUSED*/ -static int -tty_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval, - uint_t flag, char **reason, rcm_info_t **dependent_reason) -{ - return (rsrc_change_common(hd, TTYMUX_SUSPEND, rsrc, flag, - reason, dependent_reason, (void *)interval)); -} - -/*ARGSUSED*/ -static int -tty_online(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, - char **reason, rcm_info_t **dependent_reason) -{ - return (rsrc_change_common(hd, TTYMUX_ONLINE, rsrc, flags, - reason, dependent_reason, NULL)); -} - -/*ARGSUSED*/ -static int -tty_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, - char **reason, rcm_info_t **dependent_reason) -{ - return (rsrc_change_common(hd, TTYMUX_RESUME, rsrc, flags, - reason, dependent_reason, NULL)); -} diff --git a/usr/src/cmd/rcm_daemon/common/ttymux_rcm_impl.h b/usr/src/cmd/rcm_daemon/common/ttymux_rcm_impl.h deleted file mode 100644 index e1ae3acfb8..0000000000 --- a/usr/src/cmd/rcm_daemon/common/ttymux_rcm_impl.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _TTYMUX_RCM_IMPL_H -#define _TTYMUX_RCM_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef lint -#define _(x) gettext(x) -#else -#define _(x) x -#endif - -#define UNKNOWN 1 /* flags */ -#define PRESENT 2 /* flags */ -#define REGISTERED 4 /* flags */ -#define CONNECTED 8 /* flags */ -#define DISCONNECTED 0x10 /* flags */ - -/* RCM operations */ -#define TTYMUX_OFFLINE 1 -#define TTYMUX_ONLINE 2 -#define TTYMUX_REMOVE 3 -#define TTYMUX_SUSPEND 4 -#define TTYMUX_RESUME 5 - -/* - * Representation of a resource. - * All resources are placed in a cache structured as a doubly linked list - * (ie the next and prev fields). - * The dependencies list identifies which resources this resource is - * depending upon. - */ -typedef struct rsrc { - char *id; - dev_t dev; - int flags; - struct rsrc *next; - struct rsrc *prev; - struct link *dependencies; -} rsrc_t; - -/* - * Representation of a pair of resources participating in a - * dependency relationship - * The dependency is cast in terms of a resource that is using - * another resource in order to provide a service. - * This structure is used to represent a ttymux minor node that - * has another serial device multiplexed under it. In this - * case user resource would correspond to the ttymux minor node and the - * the used resource would correspond to the multiplexed serial device. - * The linkid field refers to the STREAM's link identifier. - */ -typedef struct link { - rsrc_t *user; /* the using resource */ - rsrc_t *used; /* the used resource */ - int linkid; /* STREAM's link identifier */ - uint_t state; - int flags; - int (*connect)(struct link *); - int (*disconnect)(struct link *); - struct link *next; -} link_t; - -#define MUXCTLLINK "/devices/multiplexer@0,0:ctl" -#define MUXCONLINK "/devices/multiplexer@0,0:con" - -#ifdef __cplusplus -} -#endif - -#endif /* _TTYMUX_RCM_IMPL_H */ diff --git a/usr/src/cmd/svc/profile/Makefile b/usr/src/cmd/svc/profile/Makefile index 32ec303879..2b00542413 100644 --- a/usr/src/cmd/svc/profile/Makefile +++ b/usr/src/cmd/svc/profile/Makefile @@ -44,7 +44,6 @@ PROFILESRCS = \ platform_SUNW,SPARC-Enterprise.xml \ platform_SUNW,Sun-Fire-880.xml \ platform_SUNW,Sun-Fire.xml \ - platform_SUNW,UltraSPARC-IIi-Netract.xml \ platform_none.xml \ platform_sun4v.xml @@ -66,13 +65,6 @@ install: all $(PROFILES) $(RM) $(ROOTPROFILE)/platform_SUNW,Sun-Fire-V890.xml $(LN) $(ROOTPROFILE)/platform_SUNW,Sun-Fire-880.xml \ $(ROOTPROFILE)/platform_SUNW,Sun-Fire-V890.xml - # SUNW,UltraSPARC-IIe-NetraCT-[46]0 - $(RM) $(ROOTPROFILE)/platform_SUNW,UltraSPARC-IIe-NetraCT-40.xml - $(RM) $(ROOTPROFILE)/platform_SUNW,UltraSPARC-IIe-NetraCT-60.xml - $(LN) $(ROOTPROFILE)/platform_SUNW,UltraSPARC-IIi-Netract.xml \ - $(ROOTPROFILE)/platform_SUNW,UltraSPARC-IIe-NetraCT-40.xml - $(LN) $(ROOTPROFILE)/platform_SUNW,UltraSPARC-IIi-Netract.xml \ - $(ROOTPROFILE)/platform_SUNW,UltraSPARC-IIe-NetraCT-60.xml $(ROOTPROFILE)/%: % $(INS.file) diff --git a/usr/src/cmd/svc/profile/platform_SUNW,UltraSPARC-IIi-Netract.xml b/usr/src/cmd/svc/profile/platform_SUNW,UltraSPARC-IIi-Netract.xml deleted file mode 100644 index 50ae263b90..0000000000 --- a/usr/src/cmd/svc/profile/platform_SUNW,UltraSPARC-IIi-Netract.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version='1.0'?> -<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'> -<!-- - Copyright 2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - CDDL HEADER START - - The contents of this file are subject to the terms of the - Common Development and Distribution License, Version 1.0 only - (the "License"). You may not use this file except in compliance - with the License. - - You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - or http://www.opensolaris.org/os/licensing. - See the License for the specific language governing permissions - and limitations under the License. - - When distributing Covered Code, include this CDDL HEADER in each - file and include the License file at usr/src/OPENSOLARIS.LICENSE. - If applicable, add the following below this CDDL HEADER, with the - fields enclosed by brackets "[]" replaced with your own identifying - information: Portions Copyright [yyyy] [name of copyright owner] - - CDDL HEADER END - - ident "%Z%%M% %I% %E% SMI" - - NOTE: This service profile is not editable; its contents will be - overwritten by package or patch operations, including operating - system upgrade. - - Profile for NetraCT and related platforms. ---> -<service_bundle type='profile' name='default'> - <service name='platform/sun4u/efdaemon' version='1' - type='service'> - <instance name='default' enabled='true'/> - </service> -</service_bundle> diff --git a/usr/src/lib/cfgadm_plugins/Makefile.com b/usr/src/lib/cfgadm_plugins/Makefile.com index 7cfd1df65c..142d4f3314 100644 --- a/usr/src/lib/cfgadm_plugins/Makefile.com +++ b/usr/src/lib/cfgadm_plugins/Makefile.com @@ -38,9 +38,6 @@ LINKED_PLATFORMS = SUNW,Ultra-2 LINKED_PLATFORMS += SUNW,Ultra-4 LINKED_PLATFORMS += SUNW,Ultra-250 LINKED_PLATFORMS += SUNW,Ultra-Enterprise -LINKED_PLATFORMS += SUNW,UltraSPARC-IIi-Netract -LINKED_PLATFORMS += SUNW,UltraSPARC-IIe-NetraCT-40 -LINKED_PLATFORMS += SUNW,UltraSPARC-IIe-NetraCT-60 LINKED_PLATFORMS += SUNW,Sun-Blade-100 LINKED_PLATFORMS += SUNW,Sun-Blade-1000 LINKED_PLATFORMS += SUNW,Sun-Blade-1500 @@ -60,7 +57,6 @@ LINKED_PLATFORMS += SUNW,Sun-Fire-V490 LINKED_PLATFORMS += SUNW,Serverblade1 LINKED_PLATFORMS += SUNW,Netra-T12 LINKED_PLATFORMS += SUNW,Netra-T4 -LINKED_PLATFORMS += SUNW,Netra-CP2300 LINKED_PLATFORMS += SUNW,Netra-CP3010 LINKED_DIRS = $(LINKED_PLATFORMS:%=$(USR_PLAT_DIR)/%) diff --git a/usr/src/lib/libprtdiag_psr/sparc/Makefile b/usr/src/lib/libprtdiag_psr/sparc/Makefile index 3961e8fd4d..2755dcd558 100644 --- a/usr/src/lib/libprtdiag_psr/sparc/Makefile +++ b/usr/src/lib/libprtdiag_psr/sparc/Makefile @@ -26,8 +26,8 @@ # lib/libprtdiag_psr/sparc/Makefile PRTDIAG_PLATFORMS= desktop tazmo javelin sunfire serengeti \ - montecarlo littleneck daktari cherrystone \ - lw8 snowbird ontario schumacher opl montoya monza + littleneck daktari cherrystone \ + lw8 ontario schumacher opl montoya monza all := TARGET= all lint := TARGET= lint diff --git a/usr/src/lib/libprtdiag_psr/sparc/montecarlo/Makefile b/usr/src/lib/libprtdiag_psr/sparc/montecarlo/Makefile deleted file mode 100644 index a9b0ef79a2..0000000000 --- a/usr/src/lib/libprtdiag_psr/sparc/montecarlo/Makefile +++ /dev/null @@ -1,104 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# lib/libprtdiag_psr/sparc/montecarlo/Makefile - -LIBBASE = ../../../../../src/lib -UTSBASE = ../../../../uts -PLATFORM_OBJECTS= montecarlo.o - -include ../Makefile.com - -IFLAGS = -I$(USR_PLAT_DIR)/sun4u/include -I../../../libprtdiag/inc -I$(LIBBASE)/libdevinfo -IFLAGS += -I$(UTSBASE)/sun4u/sys -IFLAGS += -I$(UTSBASE)/sun4u/montecarlo/sys -LINTFLAGS += $(IFLAGS) -LDLIBS += -L$(LIBBASE)/libdevinfo -ldevinfo -L$(LIBBASE)/libcfgadm -lcfgadm \ - -lkstat -# -# links in /usr/platform -# -LINKED_PLATFORMS = SUNW,UltraSPARC-IIe-NetraCT-40 - -LINKED_DIRS = $(LINKED_PLATFORMS:%=$(USR_PLAT_DIR)/%) -LINKED_LIB_DIRS = $(LINKED_PLATFORMS:%=$(USR_PLAT_DIR)/%/lib) -LINKED_PRTDIAG_DIRS = \ - $(LINKED_PLATFORMS:%=$(USR_PLAT_DIR)/%/lib/libprtdiag_psr.so.1) - -# -# SUNW,UltraSPARC-IIi-Netract and SUNW,UltraSPARC-IIe-NetraCT-40 platform -# should install into SUNW,UltraSPARC-IIi-Netract. -# SUNW,UltraSPARC-IIe-NetraCT-40 platform can link to -# /usr/platform/SUNW,UltraSPARC-IIi-Netract/lib/libprtdiag_psr.so -# -PLATFORM=SUNW,UltraSPARC-IIi-Netract - -$(USR_PLAT_DIR)/$(PLATFORM)/lib/libprtdiag_psr.so.1 := FILEMODE= 0755 - -.KEEP_STATE: - -PLATLIBS= $(PLATFORM:%=$(USR_PLAT_DIR)/%/lib/) - -install: all $(PLATLIBS) $(USR_PSM_LIBS) \ - $(LINKED_PRTDIAG_DIRS) - -# -# install rules for SUNW,UltraSPARC-IIi-Netract/lib/libprtdiag_psr.so -# -$(PLATLIBS): - $(INS.dir) - -$(USR_PSM_LIB_DIR): - cd $(UTSBASE)/sun4u/montecarlo; $(MAKE) $(USR_PSM_LIB_DIR) - -$(USR_PSM_LIB_DIR)/%: % $(USR_PSM_LIB_DIR) - $(INS.file) - -$(LINKED_DIRS): $(USR_PLAT_DIR) - -$(INS.dir) - -$(LINKED_LIB_DIRS): $(LINKED_DIRS) - -$(INS.dir) - -$(LINKED_PRTDIAG_DIRS): $(LINKED_LIB_DIRS) - -$(INS.slink6) - - -# New additions to generate msg file -POFILE = libprtdiag_psr_montecarlo.po -POFILES = montecarlo.po - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN) - -$(POFILE): $(POFILES) - $(RM) $@ - $(CAT) $(POFILES) > $@ - -$(POFILES): - $(RM) messages.po - $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext common/montecarlo.c` - $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ - $(RM) messages.po diff --git a/usr/src/lib/libprtdiag_psr/sparc/montecarlo/common/montecarlo.c b/usr/src/lib/libprtdiag_psr/sparc/montecarlo/common/montecarlo.c deleted file mode 100644 index dce27e6fe0..0000000000 --- a/usr/src/lib/libprtdiag_psr/sparc/montecarlo/common/montecarlo.c +++ /dev/null @@ -1,2451 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Netract Platform specific functions. - * - * called when : - * machine_type == MTYPE_MONTECARLO - */ - -/* includes */ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <strings.h> -#include <stropts.h> -#include <fcntl.h> -#include <kvm.h> -#include <kstat.h> -#include <sys/types.h> -#include <sys/utsname.h> -#include <sys/openpromio.h> -#include <sys/sunddi.h> -#include <sys/ddi_impldefs.h> -#include <sys/devinfo_impl.h> -#include <sys/ioccom.h> -#include <sys/systeminfo.h> -#include <libintl.h> -#include <config_admin.h> -#include "pdevinfo.h" -#include "display.h" -#include "pdevinfo_sun4u.h" -#include "display_sun4u.h" -#include "libprtdiag.h" -#include "libdevinfo.h" - -/* MC specific header, might just include from MC space */ -#include "mct_topology.h" -#include "envctrl_gen.h" -#include "pcf8574_nct.h" -#include "netract_gen.h" -#include "hscimpl.h" -#include "scsbioctl.h" - -#if !defined(TEXT_DOMAIN) -#define TEXT_DOMAIN "SYS_TEST" -#endif - -/* globals */ -#define MAXNAMESZ 128 -#define MAX_NODE_NAME_SZ 32 - -/* this values equates to Max Tree depth for now */ -#define MAXIMUM_DEVS 64 - -typedef char device_info_t[MAX_NODE_NAME_SZ]; - -typedef struct { - cfga_list_data_t *ldatap; - int req; /* If set, this list_data was requested by user */ -} ap_out_t; - - -typedef struct { - uint_t slot_addr; - uint_t slot_stat; - uint_t slot_cond; - device_info_t devs_info[MAXIMUM_DEVS]; - uint_t number_devs; -} mc_slot_info_t; - -typedef struct { - mc_slot_info_t mc_slot_info[MC_MAX_SLOTS]; -} slot_data_t; - - -extern char *progname; -extern int print_flag; - -/* These are used to store all force loads of the drivers */ -static int ps_fd[MC_MAX_PS]; -static int oprom_fd; -static int slot_index = 0; -static int idx_minuscpu = 0; -static int num_devs = 0; -static int sd_instances[MC_MAX_SLOTS*15]; -static int gpio_instances[MC_MAX_PS+MC_MAX_FAN]; -static int sd_count = 0; -static int st_instance; -static int gpio_count = 0; -static int slot_table_not_found = 0; - -/* default not present */ -static int alarm_card_present = 0; -static int cpu_ftm_present = 0; - -/* - * We will store all kstat in globals so that - * we can browse thru them later - */ -static int fail_syssoft_prop = 0; -static int fail_drv_prop = 0; -di_node_t rootnode; /* root nexus */ -slot_data_t mc_slots_data; - -/* scsb driver kstats */ -scsb_ks_leddata_t scsb_ks_leddata; -scsb_ks_state_t scsb_ks_state; -mct_topology_t scsb_ks_topo; - -/* pcf8574(gpio) driver kstats */ -envctrl_cpuvoltage_t pcf8574_ks_cpuv; -envctrl_pwrsupp_t pcf8574_ks_ps1; -envctrl_fantray_t pcf8574_ks_fant1; -envctrl_pwrsupp_t pcf8574_ks_ps2; -envctrl_fantray_t pcf8574_ks_fant2; - -/* pcf8591(adc-dac) driver kstats */ -envctrl_temp_t pcf8591_ks_temp; - -hsc_slot_table_t hotswap_slot_table[MC_MAX_SLOTS]; -hsc_prom_slot_table_t prom_slot_table[MC_MAX_SLOTS]; - -static char *hotswap_mode = NULL; -static char *slot_auto_config[MC_MAX_SLOTS]; -static int slot_table_size; - -/* - * use this to ascertain what's the system, - * default is tonga, we can add more for future variations - * 0=tonga, 1=montecarlo - * we need also to figure out what the system version is - * 0 = 1.5, 1 = 1.0, 0.6 etc. - */ -int montecarlo = 0; -int version_p15_and_p20 = 0; - -#define MAX_PRTDIAG_INFO_LENGTH 1024 -#define MAX_PRTDIAG_FRUS 22 -#define BIT_TEST(X, N) ((X) & (1 << (N))) -#define SLOT1_OK_BIT 0 -#define SLOT2_OK_BIT 1 -#define SLOT3_OK_BIT 2 -#define SLOT4_OK_BIT 3 -#define SLOT5_OK_BIT 4 -#define SLOT6_OK_BIT 5 -#define SLOT7_OK_BIT 6 -#define SLOT8_OK_BIT 7 -#define PDU1_OK_BIT SLOT2_OK_BIT -#define PDU2_OK_BIT SLOT4_OK_BIT -#define FTM_OK_BIT SLOT5_OK_BIT -#define SCB_OK_BIT SLOT6_OK_BIT -#define FAN1_OK_BIT SLOT1_OK_BIT -#define FAN2_OK_BIT SLOT2_OK_BIT -#define DISK1_OK_BIT SLOT4_OK_BIT -#define DISK2_OK_BIT SLOT5_OK_BIT -#define DISK3_OK_BIT SLOT6_OK_BIT -#define PS1_OK_BIT SLOT7_OK_BIT -#define PS2_OK_BIT SLOT8_OK_BIT -#define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0) -#define ENVC_DEBUG_MODE 0x03 -#define OPENPROMDEV "/dev/openprom" -#define I2C_PCF8591_NAME "adc-dac" -#define I2C_KSTAT_CPUTEMP "adc_temp" -#define SCSB_DEV "scsb" -#define SDERR "sderr" -#define STERR "sterr" -#define OK "ok" -#define NOK "Not ok" -#define ON "on" -#define OFF "off" -#define BLINK "blink" -#define NA "Not Available" -#define UK "Unknown " -#define YES "Yes" -#define NO "No " -#define LO "low" -#define HI "high" -#define BLANK " " -#define SYSSOFT_PROP "System software" -#define DRV_PROP "Driver" -#define HSC_PROP_NAME "hsc-slot-map" -#define HSC_MODE "hotswap-mode" -#define PCI_ROOT_AP "pci" -#define PROPS "Properties:" -#define BOARDTYPE "Board Type:" -#define DEVS "Devices:" -#define CPCI_IO "CompactPCI IO Slot" -#define AC_CARD "Alarm Card" -#define CPU_FTM "Front Transition Module" -#define SCTRL_PROM_P06 0x00 -#define SCTRL_PROM_P10 0x01 -#define SCTRL_PROM_P15 0x02 -#define SCTRL_PROM_P20 0x03 - -#define RMM_NUMBER 3 - -#define MONTECARLO_PLATFORM "SUNW,UltraSPARC-IIi-Netract" -#define MAKAHA_PLATFORM "SUNW,UltraSPARC-IIe-NetraCT-40" - -/* - * The follow table is indexed with the enum's defined by mct_slot_occupant_t - * OC_UNKN OC_CPU OC_AC OC_BHS OC_FHS OC_HAHS - * OC_QFE OC_FRCH OC_COMBO OC_PMC OC_ATM - * - * But "scsb" can currently identify only CPU and Alarm Cards by known - * slot numbers. - */ -char *slot_occupants[] = { - CPCI_IO, - "CPU board ", - CPCI_IO, - "Basic HotSwap Board", - "Full HotSwap Board", - "HA Board", - "QFE Board", - "Fresh Choice Board", - "SUN Combo Board", - "PMC Board", - "ATM Board" - }; - -static char *prtdiag_fru_types[] = { - "I/O ", /* 0 */ - "CPU ", - "PSU ", - "HDD ", - "FAN ", - "Alarm Card ", - "SCB ", - "SSB ", - "CFTM ", - "CRTM ", - "PRTM ", - "Midplane " /* 11 */ - }; - -char prtdiag_fru_info[MAX_PRTDIAG_FRUS][MAX_PRTDIAG_INFO_LENGTH]; - -#define SCB_REG_READ 1 -#define SCB_REG_WRITE 2 - -/* Standard Device nodes - hardwired for now */ -/* will include fan tray later, cpu voltage not impl */ -static char *scsb_node = NULL; -static char **ps_node = NULL; -static char *temp_node = NULL; - -static char *mc_scsb_node = -"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/sysctrl@0,80:scsb"; - -static char *ot_scsb_node = -"/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/sysctrl@0,80:scsb"; - -static char *mc_ps_node[] = { -"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7c:pwrsuppply", -"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7e:pwrsuppply" -}; - -static char *ot_ps_node[] = { -"/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7c:pwrsuppply", -"/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7e:pwrsuppply" -}; - -static char *mc_temp_node = -"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/adc-dac@0,9e:cputemp"; - -/* - * these functions will overlay the symbol table of libprtdiag - * at runtime (netract systems only) - * display functions - */ -int display(Sys_tree *, Prom_node *, struct system_kstat_data *, int); -/* local functions */ -/* - * prom function - */ -static void gather_diaginfo(int flag); -static int extract_slot_table_from_obp(); -static int mc_next(int id); -static void mc_walk(int id); -static int mc_child(int id); -static void mc_dump_node(int id); -static int mc_getpropval(struct openpromio *opp); - -#ifdef REDUNDANT_INFO -static int mc_get_cpu_freq(Prom_node *node); -static int mc_get_ecache_size(Prom_node *node); -static void mc_display_cpus(Board_node *board); -static void mc_display_cpu_devices(Sys_tree *tree); -#endif /* REDUNDANT_INFO */ - -static void netract_disp_prom_version(); - -/* - * Since we do not have a system wide kstat for MC/Tg - * here we have to do specific kstats to drivers that - * post this information - MC/Tg specific drivers - * that post kstat here are : scsb, pcf8574(gpio) and pcf8591 - */ -static int analyze_nodes(di_node_t, void*); -static void analyze_pcipci_siblings(di_node_t); -static void display_mc_prtdiag_info(); -static int dump_devs(di_node_t, void *); -static void prtdiag_devinfo(void); -static void force_load_drivers(); -static int dump_prop_list(char *name, - di_node_t node, di_prop_t (*nxtprop)()); -static void *config_calloc_check(size_t nelem, size_t elsize); -static void explore_slot_occupants(); -static void do_scsb_kstat(); -static void do_pcf8574_kstat(); -static void do_pcf8591_kstat(); -static void do_promversion(); -static int mc_promopen(int oflag); -static int scsi_disk_status(int disk_number); -static void alarm_card_occupant(); -static int scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode); -static int scsb_ioc_reg_read(int fd, uchar_t index, - scsb_ioc_rdwr_t *ioc_rd, int num); - -static int check_platform(); - -int -display(Sys_tree *tree, - Prom_node *root, - struct system_kstat_data *kstats, - int syserrlog) -{ - int exit_code = 0; /* init to all OK */ - void *value; /* used for opaque PROM data */ - struct mem_total memory_total; /* Total memory in system */ - struct grp_info grps; /* Info on all groups in system */ -#ifdef lint - syserrlog = syserrlog; -#endif - sys_clk = -1; /* System clock freq. (in MHz) */ - /* - * Now display the machine's configuration. We do this if we - * are not logging or exit_code is set (machine is broke). - */ - if (!logging || exit_code) { - struct utsname uts_buf; - - /* - * Display system banner - */ - (void) uname(&uts_buf); - - log_printf(dgettext(TEXT_DOMAIN, - "System Configuration: Oracle Corporation" - " %s %s\n"), uts_buf.machine, - get_prop_val(find_prop(root, "banner-name")), 0); - - /* display system clock frequency */ - value = get_prop_val(find_prop(root, "clock-frequency")); - if (value != NULL) { - sys_clk = ((*((int *)value)) + 500000) / 1000000; - log_printf(dgettext(TEXT_DOMAIN, - "System clock frequency: " - "%d MHz\n"), sys_clk, 0); - } - - /* Display the Memory Size */ - display_memorysize(tree, kstats, &grps, &memory_total); - /* Lets make sure we have all the needed drivers loaded */ - /* display Montecarlo/Tonga FRU information */ - if (!extract_slot_table_from_obp()) - log_printf(dgettext(TEXT_DOMAIN, - "\r\nslot-table not available\r\n"), 0); - do_scsb_kstat(); - force_load_drivers(); - gather_diaginfo(print_flag && !logging); - /* figure out if ac is present */ - alarm_card_occupant(); - /* platform specific display mod */ - display_mc_prtdiag_info(); - di_fini(rootnode); - netract_disp_prom_version(); - } /* if (!logging || exit_code) */ - - return (exit_code); - -} /* display(....) */ - -static int -check_platform() -{ - char si_platform[SYS_NMLN]; - - /* - * Check for the platform: Montecarlo or Makaha/CP2040 based - */ - if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) { - return (-1); - } - - if ((strncmp(si_platform, MONTECARLO_PLATFORM, - strlen(MONTECARLO_PLATFORM))) == 0) { - scsb_node = mc_scsb_node; - ps_node = mc_ps_node; - temp_node = mc_temp_node; - } else if ((strncmp(si_platform, MAKAHA_PLATFORM, - strlen(MAKAHA_PLATFORM))) == 0) { - scsb_node = ot_scsb_node; - ps_node = ot_ps_node; - temp_node = NULL; - } else { - return (-1); - } - - return (0); -} - -void -force_load_drivers() -{ - int i; - - if (NULL == scsb_node || NULL == ps_node) { - if (check_platform() == -1) { - return; - } - } - - /* check scb/ssb presence */ - if (scsb_ks_state.scb_present || scsb_ks_state.ssb_present) { - if (open(scsb_node, O_RDONLY) < 0) - log_printf(dgettext(TEXT_DOMAIN, - "\nscsb open FAILED!"), 0); - } - - /* check the num of PS we have */ - for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) { - if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) { - if ((ps_fd[i] = open(ps_node[i], O_RDONLY)) < 0) - log_printf(dgettext(TEXT_DOMAIN, - "\npowersupply%d open failed"), - i, 0); - } - } /* for */ - - /* open the cpu temp driver */ - if (temp_node) { - if (open(temp_node, O_RDONLY) < 0) - log_printf(dgettext(TEXT_DOMAIN, - "\ncputemp open FAILED!"), 0); - } -} - - -void -explore_slot_occupants() -{ - char *cp = NULL; - int index; - int ret = CFGA_ERROR; - char *estrp = NULL; - cfga_list_data_t *list_array = NULL; - ap_out_t *out_array = NULL; - int nlist = 0; - char *prefilt_optp = NULL; - int dyn_exp = 1; - char *plat_opts = NULL; - - ret = config_list_ext(0, NULL, &list_array, - &nlist, plat_opts, prefilt_optp, &estrp, - dyn_exp ? CFGA_FLAG_LIST_ALL : 0); - if (ret != CFGA_OK) { - log_printf(dgettext(TEXT_DOMAIN, - "\ncannot explore configuration"), 0); - return; - } - assert(nlist != 0); - out_array = config_calloc_check(nlist, sizeof (*out_array)); - if (out_array == NULL) { - ret = CFGA_LIB_ERROR; - goto bail; - } - /* create a list of output stat data */ - for (index = 0; index < nlist; index++) { - out_array[index].ldatap = &list_array[index]; - out_array[index].req = 0; - } - - for (index = 0; index < nlist; index++) { - if ((cp = strstr(out_array[index].ldatap->ap_phys_id, - "cpci_slot")) != NULL) { - mc_slots_data.mc_slot_info[idx_minuscpu].slot_stat - = out_array[index].ldatap->ap_o_state; - mc_slots_data.mc_slot_info[idx_minuscpu].slot_cond - = out_array[index].ldatap->ap_cond; - idx_minuscpu++; - } - } -bail: - S_FREE(list_array); - S_FREE(out_array); -} - - -/* - * config_calloc_check - perform allocation, check result and - * set error indicator - */ -void * -config_calloc_check( - size_t nelem, - size_t elsize) -{ - void *p; - static char alloc_fail[] = - "%s: memory allocation failed (%d*%d bytes)\n"; - - p = calloc(nelem, elsize); - if (p == NULL) { - log_printf(dgettext(TEXT_DOMAIN, alloc_fail), nelem, elsize, 0); - } - return (p); -} - - -void -do_scsb_kstat() -{ - kstat_ctl_t *kc; - kstat_t *ksp_leddata; - kstat_t *ksp_state; - kstat_t *ksp_topo; - scsb_ks_leddata_t *pks_leddata; - scsb_ks_state_t *pks_state; - mct_topology_t *pks_topo; - int i; - -#ifdef DEBUG_TEMP1 - int index; -#endif - if (!(kc = kstat_open())) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_open failed", 0); -#endif - return; - } -#ifdef lint - kc = kc; -#endif - /* get kstat on scsb led data */ - if ((ksp_leddata = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_LEDDATA)) - == NULL) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_lookup for scsb_leddata failed", 0); -#endif - return; - } - if (kstat_read(kc, ksp_leddata, NULL) == -1) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_read for scsb_leddata failed", 0); -#endif - return; - } - pks_leddata = (scsb_ks_leddata_t *)ksp_leddata->ks_data; - scsb_ks_leddata = *pks_leddata; /* set the globals for future */ -#ifdef DEBUG_LEDS - /* dump the kstat leddata */ - printf("\nDumping LED regs: "); - for (i = 0; i < SCSB_LEDDATA_REGISTERS; ++i) { - log_printf("0x%x ", pks_leddata->scb_led_regs[i] & 0xff, 0); - } - log_printf("\n", 0); -#endif - /* get kstat on scsb states */ - if ((ksp_state = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_STATE)) - == NULL) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_lookup for scsb_state failed", 0); -#endif - return; - } - if (kstat_read(kc, ksp_state, NULL) == -1) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_read for scsb_state failed", 0); -#endif - return; - } - pks_state = (scsb_ks_state_t *)ksp_state->ks_data; - scsb_ks_state = *pks_state; /* set the global for future */ -#ifdef DEBUG_TEMP1 - /* dump the kstat state */ - log_printf("\tSCB is%spresent\n", - pks_state->scb_present ? " " : " not ", 0); - log_printf("\tSSB is%spresent\n", - pks_state->ssb_present ? " " : " not ", 0); - log_printf("\tscsb is%sfrozen\n", - pks_state->scsb_frozen ? " " : " not ", 0); - log_printf("\tscsb mode: ", 0); - switch (pks_state->scsb_mode) { - case ENVC_DEBUG_MODE: - log_printf("DEBUG MODE\n", 0); - break; - case ENVCTRL_DIAG_MODE: - log_printf("DIAGNOSTIC MODE\n", 0); - break; - case ENVCTRL_NORMAL_MODE: - log_printf("NORMAL MODE\n", 0); - break; - } - log_printf("\tscsb event code: 0x%x\n", pks_state->event_code, 0); -#endif /* DEBUG_TEMP1 */ - - if ((ksp_topo = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_TOPOLOGY)) - == NULL) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_lookup for scsb_topo failed", 0); -#endif - return; - } - if (kstat_read(kc, ksp_topo, NULL) == -1) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_read for scsb_topo failed", 0); -#endif - return; - } - pks_topo = (mct_topology_t *)ksp_topo->ks_data; - scsb_ks_topo = *pks_topo; /* set the global for future */ - /* - * we need to set this so that we can get status info - * for the 2 powersupplies in MC as we need to get - * kstat from both driver instances for environment - */ - if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF) - montecarlo = 1; /* Monte Carlo */ - /* - * HW version 0.6 and 1.0 had different led maps - * its assumed that HW 2.0 would not change this - * need to modify if it does - */ - if ((pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P15) || - (pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P20)) { - version_p15_and_p20 = 1; - } - - /* set flag to note that CFTM is present */ - for (i = 0; i < pks_topo->max_units[CFTM]; ++i) { - if (pks_topo->mct_cftm[i].fru_status == FRU_PRESENT) - cpu_ftm_present = 1; - } - -#ifdef DEBUG_TEMP1 - /* - * Midplane - */ - log_printf("Midplane type: ", 0); - if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF) - log_printf("Netra ct800 server\n", 0); - else - log_printf("Netra ct400 server%s\n", - pks_topo->mid_plane.fru_id == - SCTRL_MPID_QUARTER_NODSK ? ", no disk" : " with disk", 0); - log_printf("Midplane version: %d\n", - pks_topo->mid_plane.fru_version, 0); - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_scb[0].fru_type, - pks_topo->mct_scb[0].fru_unit, - pks_topo->mct_scb[0].fru_id, - pks_topo->mct_scb[0].fru_version, 0); - /* - * Slots - */ - log_printf("Slots present out of maximum %d\n", - pks_topo->max_units[SLOT], 0); - for (i = 0; i < pks_topo->max_units[SLOT]; ++i) { - if (pks_topo->mct_slots[i].fru_status != FRU_PRESENT) - continue; - index = (int)pks_topo->mct_slots[i].fru_type; - log_printf("\tSlot %d occupant: %s;", - pks_topo->mct_slots[i].fru_unit, slot_occupants[index], 0); - log_printf(" ID 0x%x; VER 0x%x ; ", - pks_topo->mct_slots[i].fru_id, - pks_topo->mct_slots[i].fru_version, 0); - log_printf(" Slot health %d\n", - pks_topo->mct_slots[i].fru_health, 0); - /* pks_topo->mct_slots[i].fru_health */ - } - - /* - * PDU - */ - log_printf("PDUs present out of maximum %d\n", - pks_topo->max_units[PDU], 0); - for (i = 0; i < pks_topo->max_units[PDU]; ++i) { - if (pks_topo->mct_pdu[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_pdu[i].fru_type, - pks_topo->mct_pdu[i].fru_unit, - pks_topo->mct_pdu[i].fru_id, - pks_topo->mct_pdu[i].fru_version, 0); - /* pks_topo->mct_pdu[i].fru_health */ - } - - /* - * Power Supplies - */ - log_printf("Power Supplies present out of maximum %d\n", - pks_topo->max_units[PS], 0); - for (i = 0; i < pks_topo->max_units[PS]; ++i) { - if (pks_topo->mct_ps[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_ps[i].fru_type, - pks_topo->mct_ps[i].fru_unit, - pks_topo->mct_ps[i].fru_id, - pks_topo->mct_ps[i].fru_version, 0); - } - - /* - * Disks - */ - log_printf("Disks present out of maximum %d\n", - pks_topo->max_units[DISK], 0); - for (i = 0; i < pks_topo->max_units[DISK]; ++i) { - if (pks_topo->mct_disk[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_disk[i].fru_type, - pks_topo->mct_disk[i].fru_unit, - pks_topo->mct_disk[i].fru_id, - pks_topo->mct_disk[i].fru_version, 0); - } - - /* - * Fans - */ - log_printf("Fans present out of maximum %d\n", - pks_topo->max_units[FAN], 0); - for (i = 0; i < pks_topo->max_units[FAN]; ++i) { - if (pks_topo->mct_fan[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_fan[i].fru_type, - pks_topo->mct_fan[i].fru_unit, - pks_topo->mct_fan[i].fru_id, - pks_topo->mct_fan[i].fru_version, 0); - } - - /* - * SCBs - */ - log_printf("SCBs present out of maximum %d\n", - pks_topo->max_units[SCB], 0); - for (i = 0; i < pks_topo->max_units[SCB]; ++i) { - if (pks_topo->mct_scb[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_scb[i].fru_type, - pks_topo->mct_scb[i].fru_unit, - pks_topo->mct_scb[i].fru_id, - pks_topo->mct_scb[i].fru_version, 0); - } - - /* - * SSBs - */ - log_printf("SSBs present out of maximum %d\n", - pks_topo->max_units[SSB], 0); - for (i = 0; i < pks_topo->max_units[SSB]; ++i) { - if (pks_topo->mct_ssb[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_ssb[i].fru_type, - pks_topo->mct_ssb[i].fru_unit, - pks_topo->mct_ssb[i].fru_id, - pks_topo->mct_ssb[i].fru_version, 0); - } - - /* - * Alarms Cards - */ - log_printf("Alarm Cards present out of maximum %d\n", - pks_topo->max_units[ALARM], 0); - for (i = 0; i < pks_topo->max_units[ALARM]; ++i) { - if (pks_topo->mct_alarm[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d; unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_alarm[i].fru_type, - pks_topo->mct_alarm[i].fru_unit, - pks_topo->mct_alarm[i].fru_id, - pks_topo->mct_alarm[i].fru_version, 0); - } - - /* - * CFTMs - */ - log_printf("CFTMs present out of maximum %d\n", - pks_topo->max_units[CFTM], 0); - for (i = 0; i < pks_topo->max_units[CFTM]; ++i) { - if (pks_topo->mct_cftm[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_cftm[i].fru_type, - pks_topo->mct_cftm[i].fru_unit, - pks_topo->mct_cftm[i].fru_id, - pks_topo->mct_cftm[i].fru_version, 0); - } - - /* - * CRTMs - */ - log_printf("CRTMs present out of maximum %d\n", - pks_topo->max_units[CRTM], 0); - for (i = 0; i < pks_topo->max_units[CRTM]; ++i) { - if (pks_topo->mct_crtm[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_crtm[i].fru_type, - pks_topo->mct_crtm[i].fru_unit, - pks_topo->mct_crtm[i].fru_id, - pks_topo->mct_crtm[i].fru_version, 0); - } - - /* - * PRTMs - */ - log_printf("PRTMs present out of maximum %d\n", - pks_topo->max_units[PRTM], 0); - for (i = 0; i < pks_topo->max_units[PRTM]; ++i) { - if (pks_topo->mct_prtm[i].fru_status != FRU_PRESENT) - continue; - log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", - pks_topo->mct_prtm[i].fru_type, - pks_topo->mct_prtm[i].fru_unit, - pks_topo->mct_prtm[i].fru_id, - pks_topo->mct_prtm[i].fru_version, 0); - } -#endif /* DEBUG_TEMP1 */ - -} /* do_scsb_kstat(...) */ - - -void -do_pcf8574_kstat() -{ - kstat_ctl_t *kc; - kstat_t *ksp_ps; - kstat_t *ksp_fan; - envctrl_pwrsupp_t *pks_ps; - envctrl_fantray_t *pks_fan; - int i; - char *kstat_name = NULL; - - if (!(kc = kstat_open())) { -#ifdef DEBUG_TEMP - log_printf("\nkstat_open for pcf8574 failed", 0); -#endif - return; - } - -#ifdef lint - kc = kc; -#endif - /* get kstat on gpio powersupply and fan states */ - for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) { - if (i == 1) { - kstat_name = I2C_KSTAT_PWRSUPPLY; - strncat(kstat_name, "1", 1); - } else { - kstat_name = I2C_KSTAT_PWRSUPPLY; - strncat(kstat_name, "2", 1); - } - if ((ksp_ps = kstat_lookup(kc, I2C_PCF8574_NAME, 0, kstat_name)) - == NULL) { -#ifdef DEBUG_TEMP - log_printf("\nks lookup for pwrsupply%d failed", - i+1, 0); -#endif - return; - } - if (kstat_read(kc, ksp_ps, NULL) == -1) { -#ifdef DEBUG_TEMP - log_printf("\nks read for pwrsupply%d failed", i+1, 0); -#endif - return; - } - pks_ps = (envctrl_pwrsupp_t *)ksp_ps->ks_data; - if (i == 1) - pcf8574_ks_ps1 = *pks_ps; /* ps 1 */ - else - pcf8574_ks_ps2 = *pks_ps; /* ps 2 */ - } /* for */ - for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) { - if (i == 1) { - kstat_name = I2C_KSTAT_FANTRAY; - strncat(kstat_name, "1", 1); - } else { - kstat_name = I2C_KSTAT_FANTRAY; - strncat(kstat_name, "2", 1); - } - if ((ksp_fan = kstat_lookup(kc, I2C_PCF8574_NAME, - 0, kstat_name)) == NULL) { -#ifdef DEBUG_TEMP - log_printf("\nks lookup for fantray%d failed", - i+1, 0); -#endif - return; - } - if (kstat_read(kc, ksp_fan, NULL) == -1) { -#ifdef DEBUG_TEMP - log_printf("\nks read for fantray%d failed", i+1, 0); -#endif - return; - } - pks_fan = (envctrl_fantray_t *)ksp_fan->ks_data; - if (i == 1) - pcf8574_ks_fant1 = *pks_fan; /* fan 1 */ - else - pcf8574_ks_fant2 = *pks_fan; /* fan 2 */ - } /* for */ - kstat_close(kc); - -} /* do_pcf8574_kstat(...) */ - -void -do_pcf8591_kstat() -{ - kstat_ctl_t *kc; - kstat_t *ksp_temp; - - envctrl_temp_t *pks_temp; - - if (!(kc = kstat_open())) { -#ifdef DEBUG_TEMP - log_printf("ks open for pcf8591 failed", 0); -#endif - return; - } -#ifdef lint - kc = kc; -#endif - /* get kstat on adc driver's CPU temperature data */ - if ((ksp_temp = kstat_lookup(kc, I2C_PCF8591_NAME, - -1, I2C_KSTAT_CPUTEMP)) - == NULL) { -#ifdef DEBUG_TEMP - log_printf("ks lookup for adc_temp failed", 0); -#endif - return; - } - if (kstat_read(kc, ksp_temp, NULL) == -1) { -#ifdef DEBUG_TEMP - log_printf("ks read for adc_temp failed", 0); -#endif - return; - } - pks_temp = (envctrl_temp_t *)ksp_temp->ks_data; - pcf8591_ks_temp = *pks_temp; - kstat_close(kc); -} /* do_pcf8591_kstat(.) */ - - -void -gather_diaginfo(int flag) -{ - if (flag) { - /* gather system environmental conditions. */ - /* obtain kstat info from gpio & temp. driver */ - do_pcf8574_kstat(); - do_pcf8591_kstat(); - explore_slot_occupants(); /* fill in some occupant info */ - prtdiag_devinfo(); - analyze_pcipci_siblings(rootnode); - } - -} /* display_diaginfo(...) */ - -void -netract_disp_prom_version() -{ - /* Display Prom revision header */ - log_printf(dgettext(TEXT_DOMAIN, "System Board PROM revision:\n"), 0); - log_printf("---------------------------\n", 0); - do_promversion(); - -} /* netract_disp_prom_version(.) */ - - -/* - * Get and print the PROM version. - */ -void -do_promversion(void) -{ - Oppbuf oppbuf; - struct openpromio *opp = &(oppbuf.opp); - - if (mc_promopen(O_RDONLY)) { - log_printf(dgettext(TEXT_DOMAIN, - "\nCannot open openprom device"), 0); - return; - } - - opp->oprom_size = MAXVALSIZE; - if (ioctl(oprom_fd, OPROMGETVERSION, opp) < 0) { - perror("\nOPROMGETVERSION ioctl failed"); - return; - } - log_printf("%s\n", opp->oprom_array, 0); - - if (close(oprom_fd) < 0) { - log_printf(dgettext(TEXT_DOMAIN, - "\nclose error on %s"), OPENPROMDEV, 0); - return; - } -} /* do_promversion() */ - -int -mc_promopen(int oflag) -{ - for (;;) { - if ((oprom_fd = open(OPENPROMDEV, oflag)) < 0) { - if (errno == EAGAIN) { - (void) sleep(5); - continue; - } - if (errno == ENXIO) - return (-1); - log_printf(dgettext(TEXT_DOMAIN, - "\ncannot open %s"), OPENPROMDEV, 0); - return (1); - } else - return (0); - } -} - - -/* - * This will return -1 for status unknown, 0 for OK, and 1 for failed (scsi - * hard errors) - * swiped from envmon policies - */ -int -scsi_disk_status(int disk_number) -{ - kstat_ctl_t *kc; - kstat_t *ksp_disk; - kstat_named_t *disk_data; - - int i; - int nlist = 0; - cfga_list_data_t *list_array = NULL; - char *ap_ids[] = {"c0"}; - - if ((kc = kstat_open()) == NULL) { - log_printf(dgettext(TEXT_DOMAIN, "\nks open failed"), 0); - return (-1); - } - - if (disk_number == RMM_NUMBER) { /* RMM */ - if (config_list_ext(1, ap_ids, &list_array, &nlist, - NULL, NULL, NULL, CFGA_FLAG_LIST_ALL) != CFGA_OK) { - kstat_close(kc); - return (-1); - } - for (i = 0; i < nlist; i++) { - if (strstr(list_array[i].ap_phys_id, "rmt/0") != NULL) { - /* Tape drive */ - if (list_array[i].ap_o_state == - CFGA_STAT_UNCONFIGURED) { - kstat_close(kc); - return (-1); - } - if ((ksp_disk = kstat_lookup(kc, STERR, - st_instance, NULL)) == NULL) { - kstat_close(kc); - return (-1); - } - break; - } else if (strstr(list_array[i].ap_phys_id, - "dsk/c0t6d0") != NULL) { - /* CD_ROM */ - if (list_array[i].ap_o_state == - CFGA_STAT_UNCONFIGURED) { - kstat_close(kc); - return (-1); - } - if ((ksp_disk = kstat_lookup(kc, SDERR, - sd_instances[disk_number-1], NULL)) == - NULL) { - kstat_close(kc); - return (-1); - } - break; - } - } - } else { /* Hard disk */ - if ((ksp_disk = kstat_lookup(kc, SDERR, - sd_instances[disk_number-1], NULL)) == NULL) { - kstat_close(kc); - return (-1); - } - } - - if (kstat_read(kc, ksp_disk, NULL) == -1) { - log_printf(dgettext(TEXT_DOMAIN, - "\nks read error for disk%d, drv inst%d"), - disk_number, sd_instances[disk_number-1], 0); - kstat_close(kc); - return (-1); - } - disk_data = KSTAT_NAMED_PTR(ksp_disk); - /* - * if disk_data[].value is >0, we have a problem - */ - if (disk_data[1].value.ui32 == 0) { - kstat_close(kc); - return (0); - } else { - kstat_close(kc); - return (1); - } -} - - -void -prtdiag_devinfo(void) -{ - uint_t flag; - /* lets get everything we can from kernel */ - flag = DINFOSUBTREE|DINFOPROP; - rootnode = di_init("/", flag); - if (rootnode == DI_NODE_NIL) { - log_printf(dgettext(TEXT_DOMAIN, - "\nprtdiag_devinfo: di_init() failed"), 0); - return; - } - (void) di_walk_node(rootnode, DI_WALK_CLDFIRST, NULL, - dump_devs); -} - - -/* - * gather information about this node, returns appropriate code. - * specific information we seek are driver names, instances - * we will initialize some globals depending on what we find - * from the kernel device tree info and may be private data - * if required - */ -/*ARGSUSED1*/ -int -dump_devs(di_node_t node, void *arg) -{ - char *driver_name; - - driver_name = di_driver_name(node); - /* we will initialize our globals here */ - if ((di_instance(node) >= 0) && - (driver_name != NULL) && - (!(di_state(node) & DI_DRIVER_DETACHED))) { - if (strcmp(driver_name, "pcf8574") == 0) { - gpio_instances[gpio_count] = di_instance(node); - gpio_count++; - } else if (strcmp(driver_name, "sd") == 0) { - sd_instances[sd_count] = di_instance(node); - sd_count++; - } else if (strcmp(driver_name, "st") == 0) { - st_instance = di_instance(node); - } - } - - if (strcmp(di_node_name(node), "pseudo") == 0) - return (DI_WALK_PRUNECHILD); - else - return (DI_WALK_CONTINUE); -} - - - -/* - * Returns 0 if error , 1 otherwise - */ -int -dump_prop_list(char *name, di_node_t node, di_prop_t (*nxtprop)()) -{ - int prop_len, i, k, max_slots_minus_cpu, n; - uchar_t *prop_data; - char *p; - char *temp_s; - di_prop_t prop, next; - int ret_value = 0; - - max_slots_minus_cpu = scsb_ks_topo.max_units[SLOT]-1; - - if ((next = nxtprop(node, DI_PROP_NIL)) == DI_PROP_NIL) - return (0); - while (next != DI_PROP_NIL) { - int maybe_str = 1, npossible_strs = 0; - prop = next; - next = nxtprop(node, prop); - /* - * get prop length and value: - * private interface--always success - */ - prop_len = di_prop_rawdata(prop, &prop_data); - if (di_prop_type(prop) == DDI_PROP_UNDEF_IT) { - continue; - } - - if (prop_len == 0) { - continue; - } - if (prop_data[prop_len - 1] != '\0') { - maybe_str = 0; - } else { - /* - * Every character must be a string character or a \0, - * and there must not be two \0's in a row. - */ - for (i = 0; i < prop_len; i++) { - if (prop_data[i] == '\0') { - npossible_strs++; - } else if (!isascii(prop_data[i]) || - iscntrl(prop_data[i])) { - maybe_str = 0; - break; - } - - if ((i > 0) && (prop_data[i] == '\0') && - (prop_data[i - 1] == '\0')) { - maybe_str = 0; - break; - } - } - } - - if (maybe_str) { - p = (char *)prop_data; - for (i = 0; i < npossible_strs - 1; i++) { - if ((strcmp(name, SYSSOFT_PROP) == 0) && - (strcmp(di_prop_name(prop), - HSC_PROP_NAME) == 0)) { - temp_s = p; - temp_s += strlen(temp_s) + 1; - } - p += strlen(p) + 1; - } - - if ((strcmp(name, SYSSOFT_PROP) == 0) && - (strcmp(di_prop_name(prop), HSC_PROP_NAME) == 0)) { - temp_s = temp_s - prop_len+2; - for (k = 0, n = 0; k < prop_len; k++) { - if (temp_s[k] == 0) { - n++; - } - } - if (n % 4) { - log_printf(dgettext(TEXT_DOMAIN, - "\nbad slot-table(%d)\n"), n); - slot_table_not_found = 0; - return (ret_value); - } - slot_table_size = n / 4; - /* - * NOTE : We save slot table info in order - */ - for (k = 0; k < slot_table_size; k++) { - char *nexus, *pcidev, *phys_slotname; - char *ga; - /* - * Pick off pointer to nexus - * path or PROM handle - */ - nexus = temp_s; - while (*temp_s != NULL) - temp_s++; - temp_s++; - - /* - * Pick off pointer to the - * pci device number - */ - pcidev = temp_s; - while (*temp_s != NULL) - temp_s++; - temp_s++; - - /* Pick off physical slot no */ - phys_slotname = temp_s; - while (*temp_s != NULL) - temp_s++; - temp_s++; - - /* - * Pick off GA bits which - * we dont use for now. - */ - ga = temp_s; - while (*temp_s != NULL) - temp_s++; - temp_s++; - - hotswap_slot_table[k].pslotnum - = atoi(phys_slotname); - hotswap_slot_table[k].ga = atoi(ga); - hotswap_slot_table[k].pci_devno - = atoi(pcidev); - strcpy(hotswap_slot_table[k].nexus, - nexus); - } /* for (k = 0; k < slot_table_size; k++) */ - - ret_value = 1; - } else /* (strcmp(name, SYSSOFT_PROP) */ - slot_table_not_found = 1; - - /* - * now we want to save off the info - * we would use later - */ - if ((strcmp(name, DRV_PROP) == 0) && - (strcmp(di_prop_name(prop), HSC_MODE) == 0)) { - hotswap_mode = p; - ret_value = 1; - } else if ((strcmp(name, DRV_PROP) == 0) && - (strcmp(di_prop_name(prop), HSC_MODE) != 0)) { - /* save it in order in the right index */ - slot_auto_config[max_slots_minus_cpu] = p; - max_slots_minus_cpu--; - ret_value = 1; - } - - } else { - for (i = 0; i < prop_len; ++i) { -#if 0 - unsigned char byte; - byte = (unsigned char)prop_data[i]; - log_printf("%2.2x", byte, 0); -#endif - } - } - } - return (ret_value); -} - - -void -display_mc_prtdiag_info() -{ - int i, index; - int s_index, i1; - int tg_cpu_index = 0; - char *mcfru_type, *status, *mc_ok_led, *mc_nok_led; - char *misc_info, *health, *board_type; - - log_printf("===============================", 0); - log_printf(dgettext(TEXT_DOMAIN, - " FRU Information ================================\n"), 0); - log_printf(dgettext(TEXT_DOMAIN, - "FRU FRU FRU Green Amber"), 0); - log_printf(dgettext(TEXT_DOMAIN, " Miscellaneous\n"), 0); - log_printf(dgettext(TEXT_DOMAIN, - "Type Unit# Present LED LED"), 0); - log_printf(dgettext(TEXT_DOMAIN, " Information\n"), 0); - - log_printf("---------- ----- ------- ----- -----", 0); - log_printf(" ----------------------------------\n", 0); - - if (scsb_ks_topo.mid_plane.fru_id == SCTRL_MPID_HALF) - misc_info = "Netra ct800"; - else { - misc_info = "Netra ct400"; - } - mcfru_type = prtdiag_fru_types[MIDPLANE]; - switch (scsb_ks_topo.mid_plane.fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; break; - default: - status = NA; break; - } - mc_ok_led = " "; - mc_nok_led = " "; - - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mid_plane.fru_unit, - status, mc_ok_led, mc_nok_led, - misc_info, 0); - log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0); - log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK, - scsb_ks_topo.mid_plane.fru_version, 0); - log_printf(dgettext(TEXT_DOMAIN, "%49sMaximum Slots=%d\n"), BLANK, - scsb_ks_topo.max_units[SLOT], 0); - - /* SCB & SSB */ - mcfru_type = prtdiag_fru_types[SCB]; - for (i = 0; i < scsb_ks_topo.max_units[SCB]; ++i) { - misc_info = "System Controller Board"; - if (version_p15_and_p20) { - mc_ok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1] - & 0xff), SCB_OK_BIT) ? BLINK : - (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1] - & 0xff), SCB_OK_BIT) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1] - & 0xff), SCB_OK_BIT) ? ON:OFF; - } else { - /* - * support for 1.0 systems - - * Hack! - should use tables ? - */ - mc_ok_led = - (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2] - & 0xff), 0) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2] - & 0xff), 0) ? ON:OFF; - } - switch (scsb_ks_topo.mct_scb[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mct_scb[i].fru_unit, - status, mc_ok_led, mc_nok_led, misc_info, 0); - log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0); - log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK, - scsb_ks_topo.mct_scb[0].fru_version, 0); - if (fail_drv_prop == 1) - log_printf(dgettext(TEXT_DOMAIN, - "%49s%s=%s\n"), BLANK, HSC_MODE, - hotswap_mode, 0); - } /* for */ - - mcfru_type = prtdiag_fru_types[SSB]; - for (i = 0; i < scsb_ks_topo.max_units[SSB]; ++i) { - misc_info = "System Status Panel"; - switch (scsb_ks_topo.mct_ssb[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mct_ssb[i].fru_unit, - status, BLANK, BLANK, misc_info, 0); - } /* for */ - - /* Slots */ - for (i = 0; i < scsb_ks_topo.max_units[SLOT]; ++i) { - if (montecarlo) { - if (scsb_ks_topo.mct_slots[i].fru_unit == 1) - mcfru_type = prtdiag_fru_types[1]; - else - mcfru_type = prtdiag_fru_types[SLOT]; - /* - * Another way this could have been done is, - * to read the sub system id - * it is 0x6722 for Alarm Card - * but this id is only valid for the new ACs - * older ACs still have the same susbsystem - * id as most other Sun PCI cards - * We cannot completely rely on this. - * Also,it turns out that Sun OpenBoot does not - * always follow IEEE 1275 std, hence in a few - * systems, the "subsystem-id" published by the - * PROM could not be found - * We know the AC slot# if present on both MC&Tg - * Hence we check on both - now we are sure - * that we have found an AC - */ - if ((scsb_ks_topo.mct_slots[i].fru_unit == 8) && - (alarm_card_present == 1)) - board_type = AC_CARD; - else - board_type = UK; - } else { - if (scsb_ks_topo.mct_slots[i].fru_unit == 3) - mcfru_type = prtdiag_fru_types[1]; - else - mcfru_type = prtdiag_fru_types[SLOT]; - /* - * Another way this could have been done is, - * to read the sub system id - * it is 0x6722 for Alarm Card - * but this id is only valid for the new ACs - * older ACs still have the same susbsystem - * id as most other Sun PCI cards - * We cannot completely rely on this. - * Also,it turns out that Sun OpenBoot does not - * always follow IEEE 1275 std, hence in a few - * systems, the "subsystem-id" published by the - * PROM could not be found - * We know the AC slot# if present on both MC&Tg - * Hence we check on both - now we are sure - * that we have found an AC - */ - if ((scsb_ks_topo.mct_slots[i].fru_unit == 1) && - (alarm_card_present == 1)) - board_type = AC_CARD; - else - board_type = UK; - } - if (version_p15_and_p20) { - mc_ok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[0] - & 0xff), i) ? BLINK : - (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[0] - & 0xff), i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[0] - & 0xff), i) ? ON:OFF; - } else { - /* - * support for 1.0 systems - - * Hack! - should use tables ? - */ - if (scsb_ks_topo.mct_slots[i].fru_unit == 7) { - mc_ok_led = - BIT_TEST( - (scsb_ks_leddata.leds.p10.blink_leds[1] - & 0xff), 0) ? BLINK : - (BIT_TEST( - (scsb_ks_leddata.leds.p10.ok_leds[1] - & 0xff), 0) ? ON:OFF); - mc_nok_led = - BIT_TEST( - (scsb_ks_leddata.leds.p10.nok_leds[1] - & 0xff), 0) ? ON:OFF; - } else if (scsb_ks_topo.mct_slots[i].fru_unit == 8) { - mc_ok_led = - BIT_TEST( - (scsb_ks_leddata.leds.p10.blink_leds[1] - & 0xff), 1) ? BLINK : - (BIT_TEST( - (scsb_ks_leddata.leds.p10.ok_leds[1] - & 0xff), 1) ? ON:OFF); - mc_nok_led = - BIT_TEST( - (scsb_ks_leddata.leds.p10.nok_leds[1] - & 0xff), 1) ? ON:OFF; - } else { - /* - * for all other slots offset, - * index are the same - */ - mc_ok_led = - BIT_TEST( - (scsb_ks_leddata.leds.p10.blink_leds[0] - & 0xff), i) ? BLINK : - (BIT_TEST( - (scsb_ks_leddata.leds.p10.ok_leds[0] - & 0xff), i) ? ON:OFF); - mc_nok_led = - BIT_TEST( - (scsb_ks_leddata.leds.p10.nok_leds[0] - & 0xff), i) ? ON:OFF; - } - - } /* else if (!version_p15_and_p20) */ - - switch (scsb_ks_topo.mct_slots[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - - index = (int)scsb_ks_topo.mct_slots[i].fru_type; - if (montecarlo) { - if (scsb_ks_topo.mct_slots[i].fru_unit == 1) { - /* cpu slot */ - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, mc_nok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), - mc_nok_led, - slot_occupants[index], 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49stemperature(celsius):%d\n"), - BLANK, - pcf8591_ks_temp.value, 0); -#ifdef NEVER - log_printf(dgettext(TEXT_DOMAIN, - "%49sminimum temperature:%d\n"), - BLANK, - pcf8591_ks_temp.min, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49swarning temp. threshold:%d\n"), - BLANK, - pcf8591_ks_temp.warning_threshold, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sshutdown temp.threshold:%d\n"), - BLANK, - pcf8591_ks_temp.shutdown_threshold, 0); -#endif /* NEVER */ - } else if ((scsb_ks_topo.mct_slots[i].fru_unit == 2) && - (cpu_ftm_present == 1)) { - /* CFTM slot */ - /* - * The CFTM can only be present in Slot 2 - * for Netract-800, for Netract-400 the FTM - * is not sitted in a Slot. Hence, this is - * another special case and we need to handle - * this differently than other slots - */ - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, mc_nok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), - mc_nok_led, - CPU_FTM, 0); - } else { - if (fail_drv_prop == 1) { - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%-5s %s\n"), - mc_nok_led, - slot_occupants[index], 0); - log_printf(dgettext(TEXT_DOMAIN, - "%46s%s\n"), BLANK, - PROPS, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sauto-config=%s\n"), - BLANK, - slot_auto_config[i], 0); - } else { - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), - mc_nok_led, - slot_occupants[index], 0); - } - } - } else { /* tonga */ - if (scsb_ks_topo.mct_slots[i].fru_unit == 3) { - /* cpu slot */ - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), - mc_nok_led, - slot_occupants[index], 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49stemperature(celsius):%d\n"), - BLANK, - pcf8591_ks_temp.value, 0); -#ifdef NEVER - - log_printf(dgettext(TEXT_DOMAIN, - "%49sminimum temperature:%d\n"), - BLANK, - pcf8591_ks_temp.min, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49swarning temp. threshold:%d\n"), - BLANK, - pcf8591_ks_temp.warning_threshold, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sshutdown temp. threshold:%d\n"), - BLANK, - pcf8591_ks_temp.shutdown_threshold, 0); -#endif /* NEVER */ - } else { - if (fail_drv_prop == 1) { - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%-5s %s\n"), - mc_nok_led, - slot_occupants[index], 0); - - log_printf(dgettext(TEXT_DOMAIN, - "%46s%s\n"), BLANK, PROPS, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sauto-config=%s\n"), - BLANK, - slot_auto_config[tg_cpu_index+1], - 0); - if (scsb_ks_topo.mct_slots[i].fru_unit - != 3) - tg_cpu_index++; - } else { - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s "), - mcfru_type, - scsb_ks_topo.mct_slots[i].fru_unit, - status, mc_ok_led, 0); - log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), - mc_nok_led, - slot_occupants[index], 0); - } - } - } - /* we first match the correct slot numbers */ - for (s_index = 0; s_index < slot_table_size; s_index++) { - if (slot_table_not_found == 1) { - /* use prom table */ - if (scsb_ks_topo.mct_slots[i].fru_unit == - prom_slot_table[s_index].pslotnum) { - /* - * search for the addr/pci num - * in all slot info structs - */ - for (i1 = 0; i1 < slot_index; - i1++) { - if (prom_slot_table[s_index].pci_devno == - mc_slots_data.mc_slot_info[i1].slot_addr) { - int nd; - log_printf(dgettext(TEXT_DOMAIN, - "%46s%s%s\n"), BLANK, - BOARDTYPE, board_type, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%46s%s\n"), BLANK, DEVS, 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49s%s\n"), BLANK, - PCI_ROOT_AP, 0); - for (nd = 0; - nd < mc_slots_data.mc_slot_info[i1].number_devs; - nd++) { - log_printf(dgettext(TEXT_DOMAIN, "%52s%s\n"), BLANK, - mc_slots_data.mc_slot_info[i1].devs_info[nd], - 0); - } /* for */ - - } /* if */ - - } /* for(i1) */ - - } /* if */ - - } else { - /* use solaris lot table */ - if (fail_syssoft_prop == 1) { - if (scsb_ks_topo.mct_slots[i].fru_unit == - hotswap_slot_table[s_index].pslotnum) { - /* - * search for the addr/pci - * num in all slot info structs - */ - for (i1 = 0; i1 < slot_index; i1++) { - if (hotswap_slot_table[s_index].pci_devno == - mc_slots_data.mc_slot_info[i1].slot_addr) { - int nd; - for (nd = 0; - nd < mc_slots_data.mc_slot_info[i1].number_devs; - nd++) { - log_printf(dgettext(TEXT_DOMAIN, "%49s%s\n"), BLANK, - mc_slots_data.mc_slot_info[i1].devs_info[nd], - 0); - } - } /* if */ - - } /* for(i1) */ - - } /* if */ - - } /* (fail_syssoft_prop == 1) */ - - } /* (slot_table_not_found == 1) */ - - } /* for(s_index) */ - - } /* for */ - mcfru_type = "PDU"; - misc_info = "Power Distribution Unit"; - for (i = 0; i < scsb_ks_topo.max_units[PDU]; ++i) { - if (version_p15_and_p20) { - mc_ok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1] - & 0xff), PDU1_OK_BIT+i*2) ? BLINK : - (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1] - & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1] - & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF; - } - switch (scsb_ks_topo.mct_pdu[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - if (version_p15_and_p20) { - log_printf(dgettext(TEXT_DOMAIN, - "%-10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit, - status, mc_ok_led, mc_nok_led, misc_info, 0); - } else { - log_printf(dgettext(TEXT_DOMAIN, - "%-10s %-5d %-7s%18s%s\n"), - mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit, - status, BLANK, misc_info, 0); - } - } /* for */ - - /* PS */ - mcfru_type = prtdiag_fru_types[PS]; - misc_info = "Power Supply Unit"; - for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) { - if (version_p15_and_p20) { - mc_ok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2] - & 0xff), PS1_OK_BIT+i) ? BLINK : - (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2] - & 0xff), PS1_OK_BIT+i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2] - & 0xff), PS1_OK_BIT+i) ? ON:OFF; - } else { - /* - * support for 1.0 systems - - * Hack! - should use tables ? - */ - mc_ok_led = - (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2] - & 0xff), 1+i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2] - & 0xff), 1+i) ? ON:OFF; - } - switch (scsb_ks_topo.mct_ps[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mct_ps[i].fru_unit, - status, mc_ok_led, mc_nok_led, - misc_info, 0); - if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) { - if (scsb_ks_topo.mct_ps[i].fru_unit == 1) { - log_printf(dgettext(TEXT_DOMAIN, - "%49scondition:%s\n"), BLANK, - ((pcf8574_ks_ps1.ps_ok)? NOK:OK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49stemperature:%s\n"), BLANK, - ((pcf8574_ks_ps1.temp_ok)? NOK:OK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sps fan:%s\n"), BLANK, - ((pcf8574_ks_ps1.psfan_ok)? NOK:OK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49ssupply:%s\n"), BLANK, - ((pcf8574_ks_ps1.on_state)? OFF:ON), 0); - } else { - log_printf(dgettext(TEXT_DOMAIN, - "%49scondition:%s\n"), BLANK, - ((pcf8574_ks_ps2.ps_ok)? NOK:OK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49stemperature:%s\n"), BLANK, - ((pcf8574_ks_ps2.temp_ok)? NOK:OK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sps fan:%s\n"), BLANK, - ((pcf8574_ks_ps2.psfan_ok)? NOK:OK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49ssupply:%s\n"), BLANK, - ((pcf8574_ks_ps2.on_state)? OFF:ON), 0); - } /* if */ - } - - } /* for */ - - /* Fan tray */ - mcfru_type = prtdiag_fru_types[FAN]; - misc_info = "Fan Tray"; - for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) { - if (version_p15_and_p20) { - mc_ok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2] - & 0xff), FAN1_OK_BIT+i) ? BLINK : - (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2] - & 0xff), FAN1_OK_BIT+i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2] - & 0xff), FAN1_OK_BIT+i) ? ON:OFF; - } else { - /* - * support for 1.0 systems - - * Hack! - should use tables ? - */ - mc_ok_led = - (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[3] - & 0xff), 3+i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[3] - & 0xff), 3+i) ? ON:OFF; - } - switch (scsb_ks_topo.mct_fan[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mct_fan[i].fru_unit, - status, mc_ok_led, mc_nok_led, - misc_info, 0); - if (scsb_ks_topo.mct_fan[i].fru_status == FRU_PRESENT) { - if (scsb_ks_topo.mct_fan[i].fru_unit == 1) { - log_printf(dgettext(TEXT_DOMAIN, - "%49scondition:%s\n"), BLANK, - ((pcf8574_ks_fant1.fan_ok)? OK:NOK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sfan speed:%s\n"), BLANK, - ((pcf8574_ks_fant1.fanspeed)? HI:LO), 0); - } else { - log_printf(dgettext(TEXT_DOMAIN, - "%49scondition:%s\n"), BLANK, - ((pcf8574_ks_fant2.fan_ok)? OK:NOK), 0); - log_printf(dgettext(TEXT_DOMAIN, - "%49sfan speed:%s\n"), BLANK, - ((pcf8574_ks_fant2.fanspeed)? HI:LO), 0); - } - } - - } /* for */ - - /* DISKS */ - for (i = 0; i < scsb_ks_topo.max_units[DISK]; ++i) { - if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) - mcfru_type = prtdiag_fru_types[DISK]; - else - mcfru_type = "RMM "; - switch (scsb_ks_topo.mct_disk[i].fru_status) { - case FRU_PRESENT: - status = YES; - break; - case FRU_NOT_PRESENT: - status = NO; - break; - case FRU_NOT_AVAILABLE: - status = NA; - break; - default: - status = NA; - break; - } - if (version_p15_and_p20) { - mc_ok_led = - BIT_TEST((scsb_ks_leddata.scb_led_regs[8] - & 0xff), DISK1_OK_BIT+i) ? BLINK : - (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2] - & 0xff), DISK1_OK_BIT+i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2] - & 0xff), DISK1_OK_BIT+i) ? ON:OFF; - } else { - /* - * support for 1.0 systems - - * Hack! - should use tables ? - */ - mc_ok_led = - (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2] - & 0xff), DISK1_OK_BIT+i) ? ON:OFF); - mc_nok_led = - BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2] - & 0xff), DISK1_OK_BIT+i) ? ON:OFF; - } - /* print everything except condition */ - if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) { - misc_info = "Hard Disk Drive"; - log_printf(dgettext(TEXT_DOMAIN, - "%10s %-5d %-7s %-5s %-5s %s\n"), - mcfru_type, scsb_ks_topo.mct_disk[i].fru_unit-1, - status, mc_ok_led, mc_nok_led, misc_info, 0); - } else { - misc_info = "Removable Media Module"; - log_printf(dgettext(TEXT_DOMAIN, - "%10s %5s %-7s %-5s %-5s %s\n"), - mcfru_type, BLANK, - status, mc_ok_led, mc_nok_led, misc_info, 0); - } - - /* find out fru health from the SCSI drivers */ - if (scsb_ks_topo.mct_disk[i].fru_status == FRU_PRESENT) { - switch ( - scsi_disk_status( - scsb_ks_topo.mct_disk[i].fru_unit)) { - case 0: - health = OK; - break; - case 1: - health = NOK; - break; - case -1: - health = UK; - break; - default: - health = NA; - break; - } - log_printf(dgettext(TEXT_DOMAIN, - "%49scondition:%s\n"), BLANK, health, 0); - } - - } /* for */ - - log_printf(dgettext(TEXT_DOMAIN, "\n"), 0); - -} /* display_mc_prtdiag_info() */ - - -void -analyze_pcipci_siblings(di_node_t node) -{ - di_node_t lc_node; - /* we will find all the dev info for slots first */ - lc_node = di_drv_first_node("pci_pci", node); - lc_node = di_child_node(lc_node); - /* we are at "pci" node now */ - do { - if (di_walk_node(lc_node, DI_WALK_CLDFIRST, - NULL, analyze_nodes) != 0) { - return; - } - } while ((lc_node = di_sibling_node(lc_node)) != DI_NODE_NIL); - - /* now we wll gather info on sysctrl */ - lc_node = di_drv_first_node(SCSB_DEV, node); - if (lc_node != DI_NODE_NIL) - analyze_nodes(lc_node, "sysctrl"); -} /* analyze_pcipci_siblings(.) */ - - -int -analyze_nodes(di_node_t l_node, void *arg) -{ - char *temp; - char *name, *pname; - di_node_t parent; - /* - * we will figure out whether the parent node is "pci" type - * we will save info only in this case as we only want to - * print out the nodes under AP and not others - */ - parent = di_parent_node(l_node); - pname = di_node_name(parent); - name = di_node_name(l_node); - /* - * if this is PCI bridge, we know that this is the AP for slots - * hence, we will save off the address(to convert to slot mapping) - * later, and also we will start saving off slot info struct for - * reporting later - * we will save the immediate childs of this bridge only - */ - if (strcmp(name, "pci") == 0) { - num_devs = 0; - if ((temp = di_bus_addr(l_node)) != NULL) { - mc_slots_data.mc_slot_info[slot_index].slot_addr - = (int)strtol(temp, (char **)NULL, 16); - } - slot_index++; - } else { - if (strcmp(pname, "pci") == 0) { - if ((mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs]) - != NULL) { - (void) strcat( - mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs], - name); - } else { - (void) strcpy( - mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs], - name); - } /* if ((mc_slots_data.mc_slot_inf */ - - num_devs++; - mc_slots_data.mc_slot_info[slot_index-1].number_devs - = num_devs; - } /* if parent is pci */ - - } /* if node is pci */ - if (arg != NULL) { - if (strcmp((char *)arg, "sysctrl") == 0) { - if (dump_prop_list("System", l_node, - di_prop_sys_next)) { - (void) dump_prop_list(NULL, l_node, - di_prop_global_next); - } else { - fail_syssoft_prop = - dump_prop_list(SYSSOFT_PROP, - l_node, di_prop_global_next); - } - - fail_drv_prop = - dump_prop_list(DRV_PROP, l_node, - di_prop_drv_next); - /* - * (void) dump_prop_list("Hardware", - * l_node, di_prop_hw_next); - */ - /* dump_priv_data(l_node); */ - } - } - - return (0); - -} /* analyze_nodes(..) */ - - - -/* - * To get the slot information, - * The OBP defines the 'slot-table' property. But the OS - * can override it with 'hsc-slot-map' property - * through the .conf file. - * Since the formats are different, 2 different property names - * are chosen. - * The OBP property format is - * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits> - * The OS property format is (ga-bits is not used however) - * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits> - * returns 0 on error, 1 otherwise - */ -int -extract_slot_table_from_obp() -{ - if (mc_promopen(O_RDONLY)) { - log_printf(dgettext(TEXT_DOMAIN, - "\ncannot open openprom device"), 0); - return (0); - } - - if (mc_next(0) == 0) - return (0); - mc_walk(mc_next(0)); - - if (close(oprom_fd) < 0) { - log_printf(dgettext(TEXT_DOMAIN, - "\nclose error on %s"), OPENPROMDEV, 0); - return (0); - } - - return (1); - -} /* extract_slot_table_from_obp() */ - - -int -mc_next(int id) -{ - Oppbuf oppbuf; - struct openpromio *opp = &(oppbuf.opp); - - bzero(oppbuf.buf, BUFSIZE); - opp->oprom_size = MAXVALSIZE; - opp->oprom_node = id; - if (ioctl(oprom_fd, OPROMNEXT, opp) < 0) { - log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMNEXT"), 0); - return (0); - } - return (opp->oprom_node); - -} /* mc_next(.) */ - - -void -mc_walk(int id) -{ - int curnode; - mc_dump_node(id); - if (curnode = mc_child(id)) - mc_walk(curnode); - if (curnode = mc_next(id)) - mc_walk(curnode); -} /* mc_walk(.) */ - -int -mc_child(int id) -{ - Oppbuf oppbuf; - struct openpromio *opp = &(oppbuf.opp); - - bzero(oppbuf.buf, BUFSIZE); - opp->oprom_size = MAXVALSIZE; - opp->oprom_node = id; - if (ioctl(oprom_fd, OPROMCHILD, opp) < 0) { - perror("\nOPROMCHILD"); - exit(0); - } - return (opp->oprom_node); - -} /* mc_child(.) */ - - -/* - * Print all properties and values - */ -void -mc_dump_node(int id) -{ - int k; - Oppbuf oppbuf; - hsc_prom_slot_table_t *hpstp; - struct openpromio *opp = &(oppbuf.opp); - - /* get first prop by asking for null string */ - bzero(oppbuf.buf, BUFSIZE); - for (;;) { - /* - * get next property name - */ - opp->oprom_size = MAXNAMESZ; - - if (ioctl(oprom_fd, OPROMNXTPROP, opp) < 0) { - perror("\nOPROMNXTPROP"); - return; - } - if (opp->oprom_size == 0) - break; - if (strcmp(opp->oprom_array, "slot-table") == 0) { - if (mc_getpropval(opp) || opp->oprom_size - == (uint_t)-1) { - log_printf(dgettext(TEXT_DOMAIN, - "\ndata not available"), 0); - return; - } else { - slot_table_size = - opp->oprom_size / - sizeof (hsc_prom_slot_table_t); - hpstp = - (hsc_prom_slot_table_t *)opp->oprom_array; - for (k = 0; k < slot_table_size; k++, hpstp++) { - prom_slot_table[k].pslotnum = - hpstp->pslotnum; - prom_slot_table[k].ga = - hpstp->ga; - prom_slot_table[k].pci_devno = - hpstp->pci_devno; - prom_slot_table[k].phandle = - hpstp->phandle; - } /* for (k = 0; k < slot_table_size; k++) */ - - } - } - } - -} /* mc_dump_node(.) */ - - -int -mc_getpropval(struct openpromio *opp) -{ - opp->oprom_size = MAXVALSIZE; - if (ioctl(oprom_fd, OPROMGETPROP, opp) < 0) { - log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMGETPROP"), 0); - return (1); - } - return (0); - -} /* mc_getpropval(.) */ - - - -/* - * This function returns nothing. - */ -void -alarm_card_occupant() -{ - int scsb_fd; - scsb_ioc_rdwr_t ioc_read; - uint8_t new_mode = 0; - uint8_t old_mode = 0; - uchar_t reg_index; - - if (NULL == scsb_node) { - if (check_platform() == -1) { - return; - } - } - - if (version_p15_and_p20 == 1) - reg_index = 0xe9; /* config status reg offset on SCB */ - else - reg_index = 0xd7; /* config status reg offset on SCB */ - - if ((scsb_fd = open(scsb_node, O_RDONLY)) < 0) { - log_printf(dgettext(TEXT_DOMAIN, - "\n%s open failed"), scsb_node, 0); - return; - } - - /* save off the old mode */ - if (scsb_mode(scsb_fd, GET, &old_mode) == 0) - return; - /* we put scsb in diag mode to read this specific ioctl */ - new_mode = ENVCTRL_DIAG_MODE; - if (scsb_mode(scsb_fd, SET, &new_mode) == 0) - return; - /* now lets read the config register */ - if (scsb_ioc_reg_read(scsb_fd, reg_index, &ioc_read, 1) == 0) - return; - /* restore the original mode */ - if (scsb_mode(scsb_fd, SET, &old_mode) == 0) - return; - alarm_card_present = (BIT_TEST(ioc_read.ioc_rbuf[0]&0xff, 0) ? 1:0); - -} /* alarm_card_occupant() */ - - -/* - * This function changes the SCSB mode to the desired one - * 1 on sucess, 0 otherwise - */ -int -scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode) -{ - struct strioctl sioc; - - if (sop == GET) - sioc.ic_cmd = ENVC_IOC_GETMODE; - else - sioc.ic_cmd = ENVC_IOC_SETMODE; - - sioc.ic_timout = 0; - sioc.ic_len = sizeof (uint8_t); - sioc.ic_dp = (char *)new_mode; - - - if (ioctl(fd, I_STR, &sioc) == -1) { - log_printf(dgettext(TEXT_DOMAIN, - "\nscsb_mode():scsb ioctl() failed"), 0); - return (0); - } - return (1); - -} /* scsb_mode(...) */ - - -/* - * 1 on success, 0 otherwise - */ -int -scsb_ioc_reg_read(int fd, uchar_t index, scsb_ioc_rdwr_t *ioc_rd, int num) -{ - struct strioctl sioc; - scsb_ioc_rdwr_t *rdwrp; - - rdwrp = ioc_rd; - sioc.ic_timout = 0; - sioc.ic_len = sizeof (scsb_ioc_rdwr_t); - sioc.ic_dp = (char *)rdwrp; - /* setup read command before ioctl */ - sioc.ic_cmd = SCSBIOC_REG_READ; - rdwrp->ioc_wlen = 0; - rdwrp->ioc_rlen = num; - rdwrp->ioc_regindex = index; - if (ioctl(fd, I_STR, &sioc) == -1) { - log_printf(dgettext(TEXT_DOMAIN, - "scsb_ioc_reg_read(): scsb ioctl() failed\n"), 0); - return (0); - } - return (1); - -} /* scsb_ioc_reg_read(....) */ diff --git a/usr/src/lib/libprtdiag_psr/sparc/snowbird/Makefile b/usr/src/lib/libprtdiag_psr/sparc/snowbird/Makefile deleted file mode 100644 index 471bad4ac6..0000000000 --- a/usr/src/lib/libprtdiag_psr/sparc/snowbird/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# lib/libprtdiag_psr/sparc/snowbird/Makefile -# -# Need to make libctsmc library first. -# -LIBCTSMC = ../../../../../src/cmd/picl/plugins/sun4u/snowbird/lib/libctsmc -all: ctsmclib -ctsmclib: $(LIBCTSMC)/libctsmc.c $(LIBCTSMC)/smclib.h - cd $(LIBCTSMC); $(MAKE) - -LIBBASE = ../../../../../src/lib -UTSBASE = ../../../../uts -SUN4U_INC_BASE = $(UTSBASE)/sun4u/sys -SB_INC_BASE = $(UTSBASE)/sun4u/snowbird/sys - -PLATFORM_OBJECTS= snowbird.o - -include ../Makefile.com - -IFLAGS = -I$(USR_PLAT_DIR)/sun4u/include -I../../../libprtdiag/inc -I$(LIBBASE)/libdevinfo -IFLAGS += -I$(SUN4U_INC_BASE) -I$(SB_INC_BASE) -I$(SRC)/cmd/picl/plugins/inc -IFLAGS += -I$(LIBCTSMC) -LINTFLAGS += $(IFLAGS) -LDLIBS += -L$(LIBCTSMC) -LDLIBS += -L$(LIBBASE)/libdevinfo -ldevinfo -L$(LIBBASE)/libcfgadm \ - -lcfgadm -lpicl -lctsmc -DYNFLAGS += -R/usr/platform/SUNW,Netra-CP2300/lib - - -# -# SUNW,Netra-CP2300 platform can link to -# /usr/platform/SUNW,Netra-CP2300/lib/libprtdiag_psr.so -# -PLATFORM=SUNW,Netra-CP2300 - -$(USR_PLAT_DIR)/$(PLATFORM)/lib/libprtdiag_psr.so.1 := FILEMODE= 0755 - -.KEEP_STATE: - -PLATLIBS= $(PLATFORM:%=$(USR_PLAT_DIR)/%/lib/) - -install: all $(PLATLIBS) $(USR_PSM_LIBS) - -# -# install rules for SUNW,Netra-CP2300/lib/libprtdiag_psr.so -# -$(PLATLIBS): - $(INS.dir) - -$(USR_PSM_LIB_DIR): - cd $(UTSBASE)/sun4u/snowbird; $(MAKE) $(USR_PSM_LIB_DIR) - -$(USR_PSM_LIB_DIR)/%: % $(USR_PSM_LIB_DIR) - $(INS.file) - -# New additions to generate msg file -POFILE = libprtdiag_psr_snowbird.po -POFILES = snowbird.po - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN) - -$(POFILE): $(POFILES) - $(RM) $@ - $(CAT) $(POFILES) > $@ - -$(POFILES): - $(RM) messages.po - $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext common/snowbird.c` - $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ - $(RM) messages.po diff --git a/usr/src/lib/libprtdiag_psr/sparc/snowbird/common/snowbird.c b/usr/src/lib/libprtdiag_psr/sparc/snowbird/common/snowbird.c deleted file mode 100644 index 2d23399c4d..0000000000 --- a/usr/src/lib/libprtdiag_psr/sparc/snowbird/common/snowbird.c +++ /dev/null @@ -1,1116 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - */ - - -/* - * This program prints the diagnostics of Sanibel system. It - * also prints other miscellaneous information about watchdog, temperature - * of CPU sensor, firmware versions of SMC and, micro controller role - * etc. The basic sources of output is PICL, and SMC. - */ - -/* includes */ - -#include <stdio.h> -#include <strings.h> -#include <ctype.h> -#include <string.h> -#include <time.h> -#include <dirent.h> -#include <sys/param.h> -#include <picl.h> -#include <libintl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/systeminfo.h> -#include <sys/openpromio.h> -#include <fcntl.h> -#include <smc_if.h> -#include <stropts.h> -#include <alloca.h> -#include <errno.h> -#include <poll.h> -#include <stdlib.h> -#include <unistd.h> -#include <kstat.h> -#include <sys/utsname.h> -#include <stddef.h> -#include <pdevinfo.h> -#include <display_sun4u.h> -#include <libprtdiag.h> -#include <smclib.h> -#include <smc_commands.h> -#include <picldefs.h> - -/* #defines for the PICL library API usage and local static variables */ -#define PD_CPCI_SLOT_TYPE "cpci" -#define PD_PCI_SLOT_TYPE "pci" -#define PD_PRESENT 1 -#define PD_BLANK " " -#define PD_ENABLED 1 -#define PD_DISABLED 0 -#define SNOWBIRD "SUNW,Netra-CP2300" -#define CHASSIS_NODE_NAME "chassis" - -/* #defines for the SMC and IPMI commands */ -#define POLL_TIMEOUT 10000 -#define DEFAULT_SEQN 0xff - -/* SMC driver */ -#define PD_SMC_DRV_PATH "/dev/ctsmc" - -/* Constants */ -#define OBP_PROP_BANNER_NAME "banner-name" -#define OBP_PROP_CLOCK_FREQ "clock-frequency" - - - -/* #defines for local usage */ -#define PD_SUCCESS 0 -#define PD_FAILURE 1 -#define PD_INTERNAL_FAILURE 2 -#define PD_ERROR -1 - -/* static global variables */ -static int pd_print_option; -static uint8_t pd_smc_glbl_enabl_rsp[2]; -static boolean_t pd_hdr_prt = B_TRUE; -static int pd_smc_fd = 0; - - -/* function declarations used in this program */ -static uint32_t pd_check_for_snowbird(); -static uint32_t pd_prt_snowbird_diag(); -static uint32_t pd_check_cpu_health(); -static uint32_t pd_check_tty_debug_mode(); -static uint32_t pd_query_SMC_firmware_version(); -static uint32_t pd_check_slots(); -int32_t pd_prt_slot_info(picl_nodehdl_t, void *); -int do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag); -static uint32_t pd_query_watchdog_state(); -int pd_check_wd_state(picl_nodehdl_t, void *); -static uint32_t pd_print_fruinfo_hdr(); -static uint32_t pd_print_device_info(int); -static uint32_t pd_get_role_information(); -static uint32_t pd_get_message_flags(); -static uint32_t pd_get_reset_mode(); -static uint32_t pd_get_sensor_reading(); -static uint32_t pd_get_sensor_threshold(); -static uint32_t pd_prt_cpci_condition(picl_nodehdl_t nodeh); -static uint32_t pd_check_location_parent(picl_nodehdl_t nodeh); -static uint64_t -picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret); -static int picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq); -static int display_system_clock(picl_nodehdl_t plafh); - -/* - * return the value of the uint prop - */ -static uint64_t -picldiag_get_uint_propval(picl_nodehdl_t modh, char *prop_name, int *ret) -{ - int err; - picl_prophdl_t proph; - picl_propinfo_t pinfo; - uint8_t uint8v; - uint16_t uint16v; - uint32_t uint32v; - uint64_t uint64v; - - err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); - if (err != PICL_SUCCESS) { - *ret = err; - return (0); - } - - /* - * If it is not an int or uint prop, return failure - */ - if ((pinfo.type != PICL_PTYPE_INT) && - (pinfo.type != PICL_PTYPE_UNSIGNED_INT)) { - *ret = PICL_FAILURE; - return (0); - } - - /* uint prop */ - - switch (pinfo.size) { - case sizeof (uint8_t): - err = picl_get_propval(proph, &uint8v, sizeof (uint8v)); - *ret = err; - return (uint8v); - case sizeof (uint16_t): - err = picl_get_propval(proph, &uint16v, sizeof (uint16v)); - *ret = err; - return (uint16v); - case sizeof (uint32_t): - err = picl_get_propval(proph, &uint32v, sizeof (uint32v)); - *ret = err; - return (uint32v); - case sizeof (uint64_t): - err = picl_get_propval(proph, &uint64v, sizeof (uint64v)); - *ret = err; - return (uint64v); - default: /* not supported size */ - *ret = PICL_FAILURE; - return (0); - } -} - - - -/* - * get the clock frequency - */ -static int -picldiag_get_clock_freq(picl_nodehdl_t modh, uint32_t *freq) -{ -#define ROUND_TO_MHZ(x) (((x) + 500000)/ 1000000) - - int err; - uint64_t clk_freq; - - clk_freq = picldiag_get_uint_propval(modh, OBP_PROP_CLOCK_FREQ, &err); - if (err != PICL_SUCCESS) - return (err); - - *freq = ROUND_TO_MHZ(clk_freq); - - return (PICL_SUCCESS); -} - - -/* - * display the clock frequency - */ -static int -display_system_clock(picl_nodehdl_t plafh) -{ - uint32_t system_clk; - int err; - - err = picldiag_get_clock_freq(plafh, &system_clk); - if (err != PICL_SUCCESS) - return (err); - - log_printf(dgettext(TEXT_DOMAIN, - "System clock frequency: %d MHZ\n"), system_clk); - - return (PICL_SUCCESS); -} - - -/* - * get the value by the property name of the string prop - * Caller must free the outbuf - */ -static int -picldiag_get_string_propval(picl_nodehdl_t modh, char *prop_name, char **outbuf) -{ - int err; - picl_prophdl_t proph; - picl_propinfo_t pinfo; - char *prop_value; - - err = picl_get_propinfo_by_name(modh, prop_name, &pinfo, &proph); - if (err != PICL_SUCCESS) - return (err); - - /* - * If it is not a string prop, return NULL - */ - if (pinfo.type != PICL_PTYPE_CHARSTRING) - return (PICL_FAILURE); - - prop_value = malloc(pinfo.size); - if (prop_value == NULL) - return (PICL_FAILURE); - - err = picl_get_propval(proph, prop_value, pinfo.size); - if (err != PICL_SUCCESS) { - free(prop_value); - return (err); - } - - *outbuf = prop_value; - return (PICL_SUCCESS); -} - - - -/* - * display platform banner - */ -static int -display_platform_banner(picl_nodehdl_t plafh) -{ - char *platform; - char *banner_name; - int err; - - /* - * get PICL_PROP_MACHINE and PICL_PROP_BANNER_NAME - */ - log_printf(dgettext(TEXT_DOMAIN, - "System Configuration: Oracle Corporation "), 0); - err = picldiag_get_string_propval(plafh, PICL_PROP_MACHINE, - &platform); - if (err != PICL_SUCCESS) - return (err); - log_printf(" %s", platform, 0); - free(platform); - - err = picldiag_get_string_propval(plafh, OBP_PROP_BANNER_NAME, - &banner_name); - if (err != PICL_SUCCESS) - return (err); - log_printf(" %s", banner_name, 0); - free(banner_name); - - log_printf("\n", 0); - return (PICL_SUCCESS); -} - -/* - * search children to get the node by the nodename - */ -static int -picldiag_get_node_by_name(picl_nodehdl_t rooth, char *name, - picl_nodehdl_t *nodeh) -{ - picl_nodehdl_t childh; - int err; - char *nodename; - - nodename = alloca(strlen(name) + 1); - if (nodename == NULL) - return (PICL_FAILURE); - - err = picl_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh, - sizeof (picl_nodehdl_t)); - - while (err == PICL_SUCCESS) { - err = picl_get_propval_by_name(childh, PICL_PROP_NAME, - nodename, (strlen(name) + 1)); - if (err != PICL_SUCCESS) { - err = picl_get_propval_by_name(childh, PICL_PROP_PEER, - &childh, sizeof (picl_nodehdl_t)); - continue; - } - - if (strcmp(nodename, name) == 0) { - *nodeh = childh; - return (PICL_SUCCESS); - } - - err = picl_get_propval_by_name(childh, PICL_PROP_PEER, - &childh, sizeof (picl_nodehdl_t)); - } - - return (err); -} - - -/* - * This routine is invoked when prtdiag starts execution. It prints - * system configuration, memory size, initializes PICL and acts as - * a driver routine for prtdiag output for Snowbird. - */ -/* ARGSUSED */ -int -do_prominfo(int syserrlog, char *pname, int log_flag, int prt_flag) -{ - - struct mem_total memory_total; /* total memory in system */ - struct grp_info grps; - uint8_t status = PD_SUCCESS; - picl_nodehdl_t rooth; - picl_nodehdl_t plafh; - struct system_kstat_data *kstats = NULL; - Sys_tree *tree = NULL; - - sys_clk = -1; - pd_print_option = syserrlog; - - if ((status = picl_initialize()) != PICL_SUCCESS) { - log_printf("prtdiag: failed to initialize the PICL\n", 0); - exit(1); - } - - if ((status = picl_get_root(&rooth)) != PICL_SUCCESS) { - log_printf("prtdiag: failed\n", 0); - exit(1); - } - - status = picldiag_get_node_by_name(rooth, PICL_NODE_PLATFORM, &plafh); - if (status != PICL_SUCCESS) - return (status); - - if (!log_flag) { - - status = display_platform_banner(plafh); - if (status != PICL_SUCCESS) - return (status); - - status = display_system_clock(plafh); - if (status != PICL_SUCCESS) - return (status); - - /* display the memory Size */ - display_memorysize(tree, kstats, &grps, &memory_total); - } - - if ((pd_smc_fd = open(PD_SMC_DRV_PATH, O_RDWR)) == -1) - return (PD_FAILURE); - - if ((status = pd_check_for_snowbird()) != PD_SUCCESS) - return (status); - - if ((status = pd_prt_snowbird_diag()) != PD_SUCCESS) - return (status); - - (void) close(pd_smc_fd); - - if (picl_shutdown() != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - return (PD_SUCCESS); - -} - -/* - * This routine prints out the platform name. - */ - -static uint32_t -pd_check_for_snowbird() -{ - - char si_platform[30]; - - if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) { - return (PD_FAILURE); - } - /* is it a Snowbird? */ - if (strcmp(si_platform, SNOWBIRD) != 0) - return (PD_FAILURE); - - log_printf("platform Type : %s\n", si_platform, 0); - return (PD_SUCCESS); - -} - - -/* - * Driver routine for satellite specific output. This is also used by - * host driver routine as all satellite information is printed by host. - * It also prints some host specific information for formatting purposes - */ - -static uint32_t -pd_prt_snowbird_diag() -{ - uint8_t status = PD_SUCCESS; - if ((status = pd_check_cpu_health()) != PD_SUCCESS) { - return (status); - } - if (pd_print_option) { - - log_printf( - "\n %11s Other Miscellaneous Information \n", - PD_BLANK, 0); - log_printf( - "%12s ------------------------------- \n", - PD_BLANK, 0); - - if ((status = pd_get_role_information()) != PD_SUCCESS) { - return (status); - } - - if (pd_smc_glbl_enabl_rsp[1] & 0x10) { - log_printf( - "IPMI Response Notification\t\tEnabled\n", 0); - } else { - log_printf( - "IPMI Response Notification\t\tDisabled\n", 0); - } - if ((status = pd_query_SMC_firmware_version()) != PD_SUCCESS) { - return (status); - } - - if ((status = pd_check_tty_debug_mode()) != PD_SUCCESS) { - return (status); - } - - if ((status = pd_get_reset_mode()) != PD_SUCCESS) { - return (status); - } - - if ((status = pd_get_message_flags()) != PD_SUCCESS) { - return (status); - } - - if ((status = pd_query_watchdog_state()) != PD_SUCCESS) { - return (status); - } - - if ((status = pd_get_sensor_reading()) != PD_SUCCESS) { - return (status); - } - - if ((status = pd_get_sensor_threshold()) != PD_SUCCESS) { - return (status); - } - - } - return (status); - -} - -/* - * This routine prints the mode in which SMC is running. It uses the - * response from SMC global enables to determine the mode - */ -static uint32_t -pd_check_tty_debug_mode() -{ - - if (pd_smc_glbl_enabl_rsp[1] & 0x20) { - log_printf("SMC verbose mode\t\t\tON\n", 0); - } else { - log_printf("SMC verbose mode\t\t\tOFF\n", 0); - } - - return (PD_SUCCESS); -} - -/* This routine prints SMC f/w version */ -static uint32_t -pd_query_SMC_firmware_version() -{ - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t ver, rev, bldrev; - - - smc_init_smc_msg(&req_pkt, SMC_QUERY_FIRMWARE_VERSION, - DEFAULT_SEQN, 0); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - ver = (rsp_pkt.data[0] & 0xf0) >> 4; - rev = rsp_pkt.data[0] & 0x0f; - bldrev = rsp_pkt.data[2] & 0x3f; - - log_printf("SMC f/w version is\t\t\t%d.%d.%d\n", ver, rev, bldrev, 0); - - return (PD_SUCCESS); - -} - -/* - * This routine checks CPU's health by using SMC self test results command - * It acts as driver routine for printing cPCI slot information - */ -static uint32_t -pd_check_cpu_health() -{ - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t dev_id = 0x1f; -#ifdef DEBUG - uint8_t i2c_chk = 0x40; -#endif - uint8_t mem_test = 0x20; - - smc_init_smc_msg(&req_pkt, SMC_GET_SMC_SELF_TEST_RESULT, - DEFAULT_SEQN, 0); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - - dev_id = rsp_pkt.data[0] & dev_id; - -#ifdef DEBUG - if (rsp_pkt.data[0] & i2c_chk) { - pd_print_device_info(dev_id); - } -#endif - if (rsp_pkt.data[0] & mem_test) { - pd_print_device_info(dev_id); - } - return (pd_check_slots()); - -} - -/* - * This routine decodes error message for CPU failures and prints details - * of the failure - */ -static uint32_t -pd_print_device_info(int dev_id) -{ - - switch (dev_id) { - case 1: - log_printf("Mux Philip 9540\n", 0); - break; - case 2: - log_printf("cpu temp max1617\n", 0); - break; - case 3: - log_printf("pmc temp max 1617\n", 0); - break; - case 4: - log_printf("MB HS temp max 1617\n", 0); - break; - case 5: - log_printf("MB mem temp max1617\n", 0); - break; - case 6: - log_printf("MB gpio Philip8574\n", 0); - break; - case 7: - log_printf("MB Fru ID ID i2c eep\n", 0); - break; - case 8: - log_printf("MB enet ID ID i2d eep\n", 0); - break; - case 9: - log_printf("MB gpio Philip8574A\n", 0); - break; - case 10: - log_printf("SDRAM mod1 temp max1617\n", 0); - break; - case 11: - log_printf("SDRAM mod ID ID i2c eep\n", 0); - break; - case 12: - log_printf("SDRAM mod2 temp max1617\n", 0); - break; - case 13: - log_printf("SDRAM mod ID ID i2c eep\n", 0); - break; - case 14: - log_printf("Power mod temp ds1721\n", 0); - break; - case 15: - log_printf("Power mod gpio Philip 8574\n", 0); - break; - case 16: - log_printf("Power mod ID eep ST M24C01\n", 0); - break; - case 17: - log_printf("SMC ID i2c eep\n", 0); - break; - - default: - log_printf("device id unknown\n", 0); - break; - - } - - return (PD_SUCCESS); - -} - -/* - * This routine walks PICL tree by "Location" class and calls prt_slot_info - * routine to print the slot information - */ - -/*ARGSUSED*/ -static uint32_t -pd_check_slots() -{ - - picl_nodehdl_t nodeh; - char *c_args = NULL; - - if (picl_get_root(&nodeh) != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - - if (picl_walk_tree_by_class(nodeh, PICL_CLASS_LOCATION, - (void *)c_args, pd_prt_slot_info) != PICL_SUCCESS) { - return (PD_INTERNAL_FAILURE); - } - - return (PD_SUCCESS); - -} - - -/*ARGSUSED*/ -int32_t - -pd_prt_slot_info(picl_nodehdl_t nodeh, void *c_args) -{ - - char *valbuf; - char label_txt[30]; - int unit_no = -1, ctr = 0; - picl_nodehdl_t childh; - picl_propinfo_t propinfo; - picl_prophdl_t proph; - - /* if not immediate child of "chassis" node, ignore it */ - if (pd_check_location_parent(nodeh) != PD_SUCCESS) - return (PD_INTERNAL_FAILURE); - - - /* get the label on the location */ - if (picl_get_prop_by_name(nodeh, PICL_PROP_LABEL, - &proph) != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - if (picl_get_propinfo(proph, &propinfo) != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - valbuf = (char *) malloc(sizeof (char) * (propinfo.size)); - if (valbuf == NULL) - return (PD_INTERNAL_FAILURE); - - if (picl_get_propval(proph, (void *)valbuf, propinfo.size) - != PICL_SUCCESS) { - free(valbuf); - return (PD_INTERNAL_FAILURE); - } - - while (valbuf[ctr] != ' ' && valbuf[ctr] != NULL) { - label_txt[ctr] = valbuf[ctr]; - ++ctr; - } - - label_txt[ctr++] = '\0'; - - if (valbuf[ctr] != NULL) { - unit_no = atoi(valbuf+ctr); - } - - free(valbuf); - - /* get the slot type for the location */ - if (picl_get_prop_by_name(nodeh, PICL_PROP_SLOT_TYPE, - &proph) != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - if (picl_get_propinfo(proph, & propinfo) != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - valbuf = (char *) malloc(sizeof (char) * (propinfo.size)); - if (valbuf == NULL) - return (PD_INTERNAL_FAILURE); - - if (picl_get_propval(proph, (void *)valbuf, - propinfo.size) != PICL_SUCCESS) { - free(valbuf); - return (PD_INTERNAL_FAILURE); - } - - if ((strcmp(valbuf, PD_CPCI_SLOT_TYPE) == 0) || - (strcmp(valbuf, PD_PCI_SLOT_TYPE) == 0)) { - (void) pd_print_fruinfo_hdr(); - log_printf("\n%s ", label_txt, 0); - - /* For Snowbird no unit number is present on the label */ - unit_no = 1; - log_printf(" %d Yes cPSB IO Slot\n", unit_no, 0); - - if (picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, - &childh, sizeof (childh)) == PICL_SUCCESS) { - pd_prt_cpci_condition(childh); - } - /* For Snowbird auto configuration is always enabled */ - log_printf("%29s Properties:\n", PD_BLANK, 0); - log_printf("%31s auto-config = enabled\n", PD_BLANK, 0); - } - - - free(valbuf); - return (PD_SUCCESS); - -} - - - -static uint32_t -pd_print_fruinfo_hdr() -{ - - log_printf( - "\n %19s FRU Information \n", - PD_BLANK, 0); - log_printf( - "%11s ------------------------------------------------\n", - PD_BLANK, 0); - - log_printf(dgettext(TEXT_DOMAIN, - "FRU FRU FRU Miscellaneous\n"), 0); - log_printf(dgettext(TEXT_DOMAIN, - "Type Unit# Present Information\n"), 0); - log_printf("---- ----- -------", 0); - log_printf(" --------------------------------\n", 0); - return (PD_SUCCESS); - -} - -static uint32_t -pd_check_location_parent(picl_nodehdl_t nodeh) -{ - - picl_nodehdl_t parenth; - char *prop_name; - - if (picl_get_propval_by_name(nodeh, PICL_PROP_PARENT, - &parenth, sizeof (parenth)) != PICL_SUCCESS) { - return (PD_FAILURE); - } - - prop_name = (char *) malloc(sizeof (char) * PICL_PROPNAMELEN_MAX); - if (prop_name == NULL) { - return (PD_FAILURE); - } - - if (picl_get_propval_by_name(parenth, PICL_PROP_NAME, (void *)prop_name, - PICL_PROPNAMELEN_MAX) != PICL_SUCCESS) { - free(prop_name); - return (PD_FAILURE); - } - - if (strcmp(prop_name, CHASSIS_NODE_NAME) == 0) { - free(prop_name); - return (PD_SUCCESS); - } else { - free(prop_name); - return (PD_FAILURE); - } - -} - - -/*ARGSUSED*/ -static uint32_t -pd_query_watchdog_state() -{ - - picl_nodehdl_t nodehandle; - char *c_args = NULL; - - if (picl_get_root(&nodehandle) != PICL_SUCCESS) { - return (PD_INTERNAL_FAILURE); - } - - if (picl_walk_tree_by_class(nodehandle, PICL_CLASS_WATCHDOG_TIMER, - (void *)c_args, pd_check_wd_state) != PICL_SUCCESS) - return (PD_INTERNAL_FAILURE); - - return (PD_SUCCESS); - -} - -/*ARGSUSED*/ -int -pd_check_wd_state(picl_nodehdl_t nodeh, void *c_args) -{ - - char *prop_name, *valbuf; - picl_propinfo_t propinfo; - picl_prophdl_t proph; - - prop_name = (char *) malloc(sizeof (char) * PICL_PROPNAMELEN_MAX); - if (prop_name == NULL) { - return (PICL_WALK_TERMINATE); - } - - if (picl_get_propval_by_name(nodeh, PICL_PROP_NAME, - (void *)prop_name, PICL_PROPNAMELEN_MAX) != PICL_SUCCESS) { - free(prop_name); - return (PICL_WALK_TERMINATE); - } - - if ((picl_get_prop_by_name(nodeh, PICL_PROP_STATE, - &proph)) != PICL_SUCCESS) { - free(prop_name); - return (PICL_WALK_TERMINATE); - } - - if ((picl_get_propinfo(proph, &propinfo)) != PICL_SUCCESS) { - free(prop_name); - return (PICL_WALK_TERMINATE); - } - - valbuf = (char *) malloc(sizeof (char) * (propinfo.size)); - if (valbuf == NULL) { - free(prop_name); - return (PICL_WALK_TERMINATE); - } - - if ((picl_get_propval(proph, (void *)valbuf, - propinfo.size)) != PICL_SUCCESS) { - free(valbuf); - free(prop_name); - return (PICL_WALK_TERMINATE); - } - - if (pd_hdr_prt) { - log_printf("\n Watch Dog Status \n", 0); - log_printf(" ---------------- \n", 0); - log_printf("Node Status\n", 0); - log_printf("---- ------\n", 0); - pd_hdr_prt = B_FALSE; - } - - log_printf("%s ", prop_name, 0); - log_printf("%s\n", valbuf, 0); - - free(prop_name); - free(valbuf); - return (PICL_WALK_CONTINUE); - -} - - -static uint32_t -pd_get_role_information() -{ - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t usparc_role; - - smc_init_smc_msg(&req_pkt, SMC_GET_ROLE_INFO, - DEFAULT_SEQN, 0); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - usparc_role = rsp_pkt.data[1]; - - log_printf(dgettext(TEXT_DOMAIN, - "UltraSPARC Host Role\t\t\t"), 0); - if (usparc_role & 0x80) { - log_printf( - dgettext(TEXT_DOMAIN, - "System Board Computer (SBC)\n"), 0); - } - if (usparc_role & 0x40) { - log_printf(dgettext(TEXT_DOMAIN, - "Standby System Board Computer (Standby SBC)\n"), 0); - } - if (usparc_role & 0x20) { - log_printf(dgettext(TEXT_DOMAIN, - "Alternate System Board Computer (Alternate SBC)\n"), 0); - } - if (usparc_role & 0x10) { - log_printf(dgettext(TEXT_DOMAIN, - "Satellite Board Computer (SAT)\n"), 0); - } - return (PD_SUCCESS); - -} - - -static uint32_t -pd_get_message_flags() -{ - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - smc_init_smc_msg(&req_pkt, SMC_GET_MESSAGE_FLAGS, - DEFAULT_SEQN, 0); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - - if (rsp_pkt.data[0] & 0x01) { - log_printf("Messages Available in queue Recieving\n", 0); - } else { - log_printf("No messages in queue for Recieving\n", 0); - } - - return (PD_SUCCESS); - - -} - - - -static uint32_t -pd_get_reset_mode() -{ - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - - smc_init_smc_msg(&req_pkt, SMC_GET_CONFIG_BLOCK, - DEFAULT_SEQN, 0); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - - log_printf("Reset Mode\t\t\t\t%x \n", rsp_pkt.data[2], 0); - - return (PD_SUCCESS); - -} - - -static uint32_t -pd_get_sensor_reading() -{ - - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - - req_pkt.data[0] = 0x0e; - - smc_init_smc_msg(&req_pkt, SMC_SENSOR_READING_GET, - DEFAULT_SEQN, 1); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - log_printf("\nCPU Node Temperature Information\n", PD_BLANK, 0); - log_printf("--------------------------------\n", PD_BLANK, 0); - log_printf("Temperature Reading: %d\n\n", rsp_pkt.data[0], 0); - - return (PD_SUCCESS); - -} - - -static uint32_t -pd_get_sensor_threshold() -{ - - - sc_reqmsg_t req_pkt; - sc_rspmsg_t rsp_pkt; - uint8_t thres_mask; - req_pkt.data[0] = 0x0e; - - smc_init_smc_msg(&req_pkt, SMC_SENSOR_THRESHOLD_GET, - DEFAULT_SEQN, 1); - smc_send_msg(-1, &req_pkt, &rsp_pkt, POLL_TIMEOUT); - log_printf("Critical Threshold Information\n", 0); - log_printf("------------------------------\n", 0); - - thres_mask = rsp_pkt.data[0]; - - if (thres_mask & 0x20) { - log_printf("High Power-Off Threshold %9s", PD_BLANK, 0); - if (rsp_pkt.data[6] & 0x80) { - log_printf("-%d\n", - (int)((uint8_t)~rsp_pkt.data[6] + 1), 0); - } else { - log_printf(" %d\n", rsp_pkt.data[6], 0); - } - } - - if (thres_mask & 0x10) { - log_printf("High Shutdown Threshold %10s", PD_BLANK, 0); - if (rsp_pkt.data[5] & 0x80) { - log_printf("-%d\n", - (int)((uint8_t)~rsp_pkt.data[5] + 1), 0); - } else { - log_printf(" %d\n", rsp_pkt.data[5], 0); - } - } - - - if (thres_mask & 0x08) { - log_printf("High Warning Threshold %11s", PD_BLANK, 0); - if (rsp_pkt.data[4] & 0x80) { - log_printf("-%d\n", - (int)((uint8_t)~rsp_pkt.data[4] + 1), 0); - } else { - log_printf(" %d\n", rsp_pkt.data[4], 0); - } - } - - if (thres_mask & 0x04) { - log_printf("Low Power Off Threshold %10s", PD_BLANK, 0); - if (rsp_pkt.data[3] & 0x80) { - log_printf("-%d\n", - (int)((uint8_t)~rsp_pkt.data[3] + 1), 0); - } else { - log_printf(" %d\n", rsp_pkt.data[3], 0); - } - } - - if (thres_mask & 0x02) { - log_printf("Low Shutdown Threshold %11s", PD_BLANK, 0); - if (rsp_pkt.data[2] & 0x80) { - log_printf("-%d\n", - (int)((uint8_t)~rsp_pkt.data[2] + 1), 0); - } else { - log_printf(" %d\n", rsp_pkt.data[2], 0); - } - } - - if (thres_mask & 0x01) { - log_printf("Low Warning Threshold %12s", PD_BLANK, 0); - if (rsp_pkt.data[1] & 0x80) { - log_printf("-%d\n", - (int)((uint8_t)~rsp_pkt.data[1] + 1), 0); - } else { - log_printf(" %d\n", rsp_pkt.data[1], 0); - } - } - - return (PD_SUCCESS); - -} - - - -static uint32_t -pd_prt_cpci_condition(picl_nodehdl_t nodeh) -{ - - picl_propinfo_t propinfo; - picl_prophdl_t proph; - char *valbuf; - - - if (picl_get_prop_by_name(nodeh, PICL_PROP_CONDITION, - &proph) != PICL_SUCCESS) { - return (PD_FAILURE); - } - - if (picl_get_propinfo(proph, &propinfo) != PICL_SUCCESS) { - return (PD_FAILURE); - } - - valbuf = (char *) malloc(sizeof (char) * (propinfo.size)); - if (valbuf == NULL) { - return (PD_FAILURE); - } - - if (picl_get_propval(proph, (void *)valbuf, - propinfo.size) != PICL_SUCCESS) { - free(valbuf); - return (PD_FAILURE); - } - - - log_printf("%29s Condition : %s\n", PD_BLANK, valbuf, 0); - - free(valbuf); - return (PD_SUCCESS); - - -} diff --git a/usr/src/man/man7d/Makefile b/usr/src/man/man7d/Makefile index 8522deb37b..612461a7e8 100644 --- a/usr/src/man/man7d/Makefile +++ b/usr/src/man/man7d/Makefile @@ -124,7 +124,6 @@ _MANFILES= aac.7d \ systrace.7d \ ticlts.7d \ tty.7d \ - ttymux.7d \ tzmon.7d \ ufm.7d \ ugen.7d \ @@ -151,7 +150,6 @@ _MANFILES= aac.7d \ sparc_MANFILES= audiocs.7d \ bbc_beep.7d \ - ctsmc.7d \ dad.7d \ dm2s.7d \ dr.7d \ diff --git a/usr/src/man/man7d/ctsmc.7d b/usr/src/man/man7d/ctsmc.7d deleted file mode 100644 index 773bd07be6..0000000000 --- a/usr/src/man/man7d/ctsmc.7d +++ /dev/null @@ -1,72 +0,0 @@ -'\" te -.\" Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved -.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. -.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. -.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CTSMC 7D "Dec 7, 2003" -.SH NAME -ctsmc \- System Management Controller driver -.SH DESCRIPTION -.sp -.LP -The \fBctsmc\fR system management controller driver is a multithreaded, -loadable, clonable STREAMS hardware driver that supports communication with the -system management controller device on SUNW,NetraCT-410, SUNW,NetraCT-810 and -SUNW,Netra-CP2300 platforms. -.sp -.LP -The \fBsmc\fR device provides a Keyboard Controller Style (KCS) interface as -described in the \fIIntelligent Platform Management Interface (IPMI) Version -1.5\fR specification. The \fBctsmc\fR driver enables user-land and kernel-land -clients to access services provided by \fBsmc\fR hardware. -.SH FILES -.sp -.ne 2 -.na -\fB\fB/dev/ctsmc\fR\fR -.ad -.sp .6 -.RS 4n -\fBctsmc\fR special character device -.RE - -.sp -.ne 2 -.na -\fB\fB/platform/sun4u/kernel/drv/sparcv9/ctsmc\fR\fR -.ad -.sp .6 -.RS 4n -64 bit ELF kernel driver -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Architecture SPARC -.TE - -.SH SEE ALSO -.sp -.LP -\fBattributes\fR(5) -.sp -.LP -\fISTREAMS Programmers Guide\fR -.sp -.LP -\fIWriting Device Drivers\fR -.sp -.LP -\fIIntelligent Platform Management Interface (IPMI). Version 1.5\fR - PICMIG, -February, 2001 diff --git a/usr/src/man/man7d/ttymux.7d b/usr/src/man/man7d/ttymux.7d deleted file mode 100644 index 6d746a1c1b..0000000000 --- a/usr/src/man/man7d/ttymux.7d +++ /dev/null @@ -1,91 +0,0 @@ -'\" te -.\" Copyright 2009, Sun Microsystems, Inc. -.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. -.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with -.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH TTYMUX 7D "Apr 9, 2009" -.SH NAME -ttymux \- Serial I/O multiplexing STREAMS device driver -.SH SYNOPSIS -.LP -.nf -multiplexer@0,0:input -.fi - -.LP -.nf -multiplexer@0,0:output -.fi - -.SH DESCRIPTION -.sp -.LP -\fBttymux\fR is a STREAMS multiplexer driver that connects multiple serial -devices to the system console. Using this driver, input from multiple physical -devices can be multiplexed onto a single input stream for the system console. -Output written to the console can be distributed to multiple physical devices -to provide redundant console interfaces to a system. Input and output can be -multiplexed to or from a separate list of devices. -.sp -.LP -\fBttymux\fR is a STREAMS multiplexer for serial drivers (such as \fBse\fR(7D)) -that comply with the Solaris terminal subsystem interface. -.sp -.LP -Currently, multiplexer interfaces are provided for system console I/O only and -not for general serial I/O multiplexing. Multiplexer interfaces are currently -not available for all platforms. Please see NOTES. -.SH FILES -.sp -.ne 2 -.na -\fB\fB/kernel/drv/sparcv9/ttymux\fR\fR -.ad -.RS 30n -64- bit ELF kernel module -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Architecture SPARC (NetraCT series only) -.TE - -.SH SEE ALSO -.sp -.LP -\fBse\fR(7D), \fBtermio\fR(7I) -.sp -.LP -\fIWriting Device Drivers\fR -.SH NOTES -.sp -.LP -Successful loading of this driver and its services depends on the \fBEEPROM\fR -or \fBNVRAM\fR settings in effect at the most recent system reboot. Without the -platform firmware support, this feature cannot be enabled. Currently, this -support is provided only on a NetraCT product family. -.sp -.LP -Use caution when enabling this feature to perform console input multiplexing, -particularly during super-user login. Because no security measures are enabled -when the driver is in operation, you must clearly understand the security -implications involved in using this feature and take appropriate measures to -provide maximum protection to the host. This can include such steps as enabling -input to physically secured console devices only. -.sp -.LP -The \fBttymux\fR driver does not handle the behavioral differences in control -characteristics of different terminal types (for example, an ESCAPE sequence.) -As a result, multiple terminal types are not supported simultaneously. Please -refer to the platform user guide for more information. diff --git a/usr/src/pkg/manifests/SUNWcs.mf b/usr/src/pkg/manifests/SUNWcs.mf index 3492b64e22..0996fd045d 100644 --- a/usr/src/pkg/manifests/SUNWcs.mf +++ b/usr/src/pkg/manifests/SUNWcs.mf @@ -453,9 +453,6 @@ $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire-880.xml \ group=sys mode=0444 $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire.xml group=sys \ mode=0444 -$(sparc_ONLY)file \ - path=etc/svc/profile/platform_SUNW,UltraSPARC-IIi-Netract.xml group=sys \ - mode=0444 file path=etc/svc/profile/platform_none.xml group=sys mode=0444 $(sparc_ONLY)file path=etc/svc/profile/platform_sun4v.xml group=sys mode=0444 file path=etc/sysevent/config/README group=sys mode=0444 @@ -1198,7 +1195,6 @@ file path=usr/lib/rcm/modules/SUNW_ip_rcm.so mode=0555 file path=usr/lib/rcm/modules/SUNW_mpxio_rcm.so mode=0555 file path=usr/lib/rcm/modules/SUNW_network_rcm.so mode=0555 file path=usr/lib/rcm/modules/SUNW_swap_rcm.so mode=0555 -$(sparc_ONLY)file path=usr/lib/rcm/modules/SUNW_ttymux_rcm.so mode=0555 file path=usr/lib/rcm/modules/SUNW_vlan_rcm.so mode=0555 file path=usr/lib/rcm/modules/SUNW_vnic_rcm.so mode=0555 file path=usr/lib/rcm/rcm_daemon mode=0555 @@ -1423,12 +1419,6 @@ hardlink path=etc/rc2.d/S20sysetup target=../../etc/init.d/sysetup hardlink path=etc/rc2.d/S89PRESERVE target=../../etc/init.d/PRESERVE $(sparc_ONLY)hardlink path=etc/svc/profile/platform_SUNW,Sun-Fire-V890.xml \ target=./platform_SUNW,Sun-Fire-880.xml -$(sparc_ONLY)hardlink \ - path=etc/svc/profile/platform_SUNW,UltraSPARC-IIe-NetraCT-40.xml \ - target=./platform_SUNW,UltraSPARC-IIi-Netract.xml -$(sparc_ONLY)hardlink \ - path=etc/svc/profile/platform_SUNW,UltraSPARC-IIe-NetraCT-60.xml \ - target=./platform_SUNW,UltraSPARC-IIi-Netract.xml hardlink path=sbin/rc5 target=../sbin/rc0 hardlink path=sbin/rc6 target=../sbin/rc0 hardlink path=usr/bin/$(ARCH32)/encrypt target=decrypt diff --git a/usr/src/pkg/manifests/developer-apptrace-platform.mf b/usr/src/pkg/manifests/developer-apptrace-platform.mf index 7b5d068301..ac3c5a93bd 100644 --- a/usr/src/pkg/manifests/developer-apptrace-platform.mf +++ b/usr/src/pkg/manifests/developer-apptrace-platform.mf @@ -34,8 +34,6 @@ dir path=usr group=sys dir path=usr/platform group=sys dir path=usr/platform/SUNW,A70 group=sys dir path=usr/platform/SUNW,A70/lib -dir path=usr/platform/SUNW,Netra-CP2300 group=sys -dir path=usr/platform/SUNW,Netra-CP2300/lib dir path=usr/platform/SUNW,Netra-CP3010 group=sys dir path=usr/platform/SUNW,Netra-CP3010/lib dir path=usr/platform/SUNW,Netra-T12 group=sys @@ -82,12 +80,6 @@ dir path=usr/platform/SUNW,Ultra-4 group=sys dir path=usr/platform/SUNW,Ultra-4/lib dir path=usr/platform/SUNW,Ultra-Enterprise group=sys dir path=usr/platform/SUNW,Ultra-Enterprise/lib -dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys -dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib -dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60 group=sys -dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/lib -dir path=usr/platform/SUNW,UltraSPARC-IIi-Netract group=sys -dir path=usr/platform/SUNW,UltraSPARC-IIi-Netract/lib legacy pkg=SUNWpstl.u arch=$(ARCH).sun4u \ desc="Apptrace processor specific shared objects" \ name="Platform specific apptrace support" diff --git a/usr/src/pkg/manifests/service-picl.mf b/usr/src/pkg/manifests/service-picl.mf index 7c15402da5..65e45e1d4a 100644 --- a/usr/src/pkg/manifests/service-picl.mf +++ b/usr/src/pkg/manifests/service-picl.mf @@ -23,6 +23,7 @@ # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2012 Nexenta Systems, Inc. All rights reserved. # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2019 Peter Tribble. # set name=pkg.fmri value=pkg:/service/picl@$(PKGVERS) @@ -46,11 +47,6 @@ $(sparc_ONLY)dir path=usr/platform/SUNW,A70 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib/picl group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib/picl/plugins group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/lib/picl group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins \ - group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/lib/picl group=sys @@ -171,27 +167,6 @@ $(sparc_ONLY)file path=usr/platform/SUNW,A70/lib/picl/plugins/libpiclenvd.so.1 \ group=sys $(sparc_ONLY)file path=usr/platform/SUNW,A70/lib/picl/plugins/piclfrutree.conf \ group=sys -$(sparc_ONLY)file path=usr/platform/SUNW,Netra-CP2300/lib/libctsmc.so.1 \ - group=sys -$(sparc_ONLY)file path=usr/platform/SUNW,Netra-CP2300/lib/libprtdiag_psr.so.1 -$(sparc_ONLY)file \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/SUNW,Netra-CP2300.RTM.conf \ - group=sys -$(sparc_ONLY)file \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/SUNW,Netra-CP2300.conf \ - group=sys -$(sparc_ONLY)file \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/envmond.conf \ - group=sys -$(sparc_ONLY)file \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/libpiclenvmond.so.1 \ - group=sys -$(sparc_ONLY)file \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/libpiclfrutree.so.1 \ - group=sys -$(sparc_ONLY)file \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/libpiclwd.so.1 \ - group=sys $(sparc_ONLY)file \ path=usr/platform/SUNW,Netra-CP3010/lib/picl/plugins/piclfrutree.conf \ group=sys @@ -713,17 +688,6 @@ $(sparc_ONLY)link path=usr/platform/SUNW,A70/lib/libprtdiag_psr.so.1 \ target=../../SUNW,Sun-Blade-100/lib/libprtdiag_psr.so.1 $(sparc_ONLY)link path=usr/platform/SUNW,A70/lib/picl/plugins/libpiclenvd.so \ target=./libpiclenvd.so.1 -$(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP2300/lib/libctsmc.so \ - target=libctsmc.so.1 -$(sparc_ONLY)link \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/libpiclenvmond.so \ - target=libpiclenvmond.so.1 -$(sparc_ONLY)link \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/libpiclfrutree.so \ - target=libpiclfrutree.so.1 -$(sparc_ONLY)link \ - path=usr/platform/SUNW,Netra-CP2300/lib/picl/plugins/libpiclwd.so \ - target=libpiclwd.so.1 $(sparc_ONLY)link \ path=usr/platform/SUNW,Netra-T12/lib/picl/plugins/libpiclfrutree.so \ target=libpiclfrutree.so.1 diff --git a/usr/src/pkg/manifests/system-fru-id-platform.mf b/usr/src/pkg/manifests/system-fru-id-platform.mf index a9d20355f0..cbeff44ab8 100644 --- a/usr/src/pkg/manifests/system-fru-id-platform.mf +++ b/usr/src/pkg/manifests/system-fru-id-platform.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2019 Peter Tribble. # set name=pkg.fmri value=pkg:/system/fru-id/platform@$(PKGVERS) @@ -39,9 +40,6 @@ $(sparc_ONLY)dir path=usr/platform/SUNW,A70 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib/picl group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib/picl/plugins group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/sbin $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/lib/picl group=sys @@ -139,8 +137,6 @@ dir path=usr/share/man/man1m $(i386_ONLY)file path=usr/lib/picl/plugins/fru_container.conf group=sys $(sparc_ONLY)file \ path=usr/platform/SUNW,A70/lib/picl/plugins/libpiclfrudata.conf group=sys -$(sparc_ONLY)file path=usr/platform/SUNW,Netra-CP2300/lib/libfruaccess.so.1 \ - group=sys $(sparc_ONLY)file \ path=usr/platform/SUNW,Netra-CP3010/lib/picl/plugins/libpiclfrudata.conf \ group=sys @@ -209,10 +205,6 @@ $(sparc_ONLY)legacy pkg=SUNWfruip.u arch=$(ARCH).sun4u \ name="FRU ID Platform Modules (Usr)" license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL -$(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP2300/lib/libfruaccess.so \ - target=libfruaccess.so.1 -$(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP2300/sbin/fruadm \ - target=../../sun4u/sbin/fruadm $(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP3010/sbin/fruadm \ target=../../sun4u/sbin/fruadm $(sparc_ONLY)link path=usr/platform/SUNW,Netra-T12/lib/libfruaccess.so \ diff --git a/usr/src/pkg/manifests/system-header.mf b/usr/src/pkg/manifests/system-header.mf index db0e188609..7badd66986 100644 --- a/usr/src/pkg/manifests/system-header.mf +++ b/usr/src/pkg/manifests/system-header.mf @@ -127,8 +127,6 @@ $(sparc_ONLY)dir path=usr/include/v9/sys dir path=usr/include/vm dir path=usr/platform group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/include $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/include $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-T12 group=sys @@ -154,9 +152,6 @@ $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-2 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-250 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-4 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIi-Netract group=sys $(i386_ONLY)dir path=usr/platform/i86pc group=sys $(i386_ONLY)dir path=usr/platform/i86pc/include $(i386_ONLY)dir path=usr/platform/i86pc/include/sys @@ -1533,8 +1528,6 @@ file path=usr/include/sys/ttold.h file path=usr/include/sys/tty.h file path=usr/include/sys/ttychars.h file path=usr/include/sys/ttydev.h -$(sparc_ONLY)file path=usr/include/sys/ttymux.h -$(sparc_ONLY)file path=usr/include/sys/ttymuxuser.h file path=usr/include/sys/tuneable.h file path=usr/include/sys/turnstile.h file path=usr/include/sys/types.h @@ -1769,7 +1762,6 @@ $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/prom_plat.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/pte.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/sbd_ioctl.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/scb.h -$(sparc_ONLY)file path=usr/platform/sun4u/include/sys/scsb_led.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/simmstat.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/smt.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/spitregs.h @@ -2012,12 +2004,6 @@ $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-4/include \ target=../sun4u/include $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise/include \ target=../sun4u/include -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/include \ - target=../sun4u/include -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/include \ - target=../sun4u/include -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIi-Netract/include \ - target=../sun4u/include link path=usr/share/man/man3head/LIST_CLASS_ENTRY.3head target=queue.h.3head link path=usr/share/man/man3head/LIST_CLASS_HEAD.3head target=queue.h.3head link path=usr/share/man/man3head/LIST_CONCAT.3head target=queue.h.3head diff --git a/usr/src/pkg/manifests/system-kernel-platform-netra.mf b/usr/src/pkg/manifests/system-kernel-platform-netra.mf index bea797da77..5e548e8f0f 100644 --- a/usr/src/pkg/manifests/system-kernel-platform-netra.mf +++ b/usr/src/pkg/manifests/system-kernel-platform-netra.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2019 Peter Tribble. # # @@ -30,82 +31,6 @@ # <include global_zone_only_component> set name=pkg.fmri value=pkg:/system/kernel/platform/netra@$(PKGVERS) -set name=pkg.description \ - value="I2C and System Controller and Status Drivers for Netra ct cPCI platform" -set name=pkg.summary value="Netra ct I2C and System Drivers" -set name=info.classification value=org.opensolaris.category.2008:System/Core +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true set name=variant.arch value=sparc -dir path=platform group=sys -dir path=platform/SUNW,Netra-CP2300 group=sys -dir path=platform/SUNW,Netra-CP2300/kernel group=sys -dir path=platform/SUNW,Netra-CP2300/kernel/dacf group=sys -dir path=platform/SUNW,Netra-CP2300/kernel/dacf/$(ARCH64) group=sys -dir path=platform/SUNW,Netra-CP2300/kernel/drv group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/dacf group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/dacf/$(ARCH64) \ - group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/$(ARCH64) \ - group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-60 group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel/dacf group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel/dacf/$(ARCH64) \ - group=sys -dir path=platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel/drv group=sys -dir path=platform/SUNW,UltraSPARC-IIi-Netract group=sys -dir path=platform/SUNW,UltraSPARC-IIi-Netract/kernel group=sys -dir path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/dacf group=sys -dir path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/dacf/$(ARCH64) group=sys -dir path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv group=sys -dir path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64) group=sys -driver name=acebus -driver name=scsb alias=nct-ATML,at27c64 -file path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/acebus.conf \ - group=sys -file \ - path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/dacf/$(ARCH64)/ttymux_dacf \ - group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/acebus \ - group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/pcf8574 \ - group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/pcf8591 \ - group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/scsb \ - group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/scsb.conf group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/se.conf group=sys -file path=platform/SUNW,UltraSPARC-IIi-Netract/kernel/drv/ttymux.conf \ - group=sys -legacy pkg=SUNWcti2.u arch=$(ARCH).sun4u \ - desc="I2C and System Controller and Status Drivers for Netra ct cPCI platform" \ - name="Netra ct I2C and System Drivers" -license cr_Sun license=cr_Sun -license lic_CDDL license=lic_CDDL -link path=platform/SUNW,Netra-CP2300/kernel/dacf/$(ARCH64)/ttymux_dacf \ - target=../../../../SUNW,UltraSPARC-IIi-Netract/kernel/dacf/$(ARCH64)/ttymux_dacf -link path=platform/SUNW,Netra-CP2300/kernel/drv/ttymux.conf \ - target=../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/ttymux.conf -link \ - path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/dacf/$(ARCH64)/ttymux_dacf \ - target=../../../../SUNW,UltraSPARC-IIi-Netract/kernel/dacf/$(ARCH64)/ttymux_dacf -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/$(ARCH64)/acebus \ - target=../../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/acebus -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/$(ARCH64)/pcf8574 \ - target=../../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/pcf8574 -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/$(ARCH64)/scsb \ - target=../../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/$(ARCH64)/scsb -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/scsb.conf \ - target=../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/scsb.conf -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/se.conf \ - target=../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/se.conf -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-40/kernel/drv/ttymux.conf \ - target=../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/ttymux.conf -link \ - path=platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel/dacf/$(ARCH64)/ttymux_dacf \ - target=../../../../SUNW,UltraSPARC-IIi-Netract/kernel/dacf/$(ARCH64)/ttymux_dacf -link path=platform/SUNW,UltraSPARC-IIe-NetraCT-60/kernel/drv/ttymux.conf \ - target=../../../SUNW,UltraSPARC-IIi-Netract/kernel/drv/ttymux.conf diff --git a/usr/src/pkg/manifests/system-kernel-platform.mf b/usr/src/pkg/manifests/system-kernel-platform.mf index 3e02272e42..23d97f1a3e 100644 --- a/usr/src/pkg/manifests/system-kernel-platform.mf +++ b/usr/src/pkg/manifests/system-kernel-platform.mf @@ -46,14 +46,6 @@ $(sparc_ONLY)dir path=platform/SUNW,A70/kernel/crypto/$(ARCH64) group=sys $(sparc_ONLY)dir path=platform/SUNW,A70/kernel/drv group=sys $(sparc_ONLY)dir path=platform/SUNW,A70/kernel/misc group=sys $(sparc_ONLY)dir path=platform/SUNW,A70/kernel/misc/$(ARCH64) group=sys -$(sparc_ONLY)dir path=platform/SUNW,Netra-CP2300 group=sys -$(sparc_ONLY)dir path=platform/SUNW,Netra-CP2300/kernel group=sys -$(sparc_ONLY)dir path=platform/SUNW,Netra-CP2300/kernel/misc group=sys -$(sparc_ONLY)dir path=platform/SUNW,Netra-CP2300/kernel/misc/$(ARCH64) \ - group=sys -$(sparc_ONLY)dir path=platform/SUNW,Netra-CP2300/kernel/tod group=sys -$(sparc_ONLY)dir path=platform/SUNW,Netra-CP2300/kernel/tod/$(ARCH64) \ - group=sys $(sparc_ONLY)dir path=platform/SUNW,Netra-CP3010 group=sys $(sparc_ONLY)dir path=platform/SUNW,Netra-CP3010/kernel group=sys $(sparc_ONLY)dir path=platform/SUNW,Netra-CP3010/kernel/crypto group=sys @@ -341,7 +333,6 @@ $(i386_ONLY)driver name=balloon perms="* 0444 root sys" $(sparc_ONLY)driver name=bbc_beep alias=SUNW,bbc-beep $(sparc_ONLY)driver name=central $(i386_ONLY)driver name=cpudrv alias=cpu -$(sparc_ONLY)driver name=ctsmc alias=nct-ds80ch11-smc $(sparc_ONLY)driver name=db21554 \ alias=pci108e,6300 \ alias=pci108e,6301 \ @@ -524,12 +515,6 @@ $(sparc_ONLY)file path=platform/SUNW,A70/kernel/drv/ppm.conf group=sys $(sparc_ONLY)file path=platform/SUNW,A70/kernel/misc/$(ARCH64)/platmod \ group=sys mode=0755 $(sparc_ONLY)file \ - path=platform/SUNW,Netra-CP2300/kernel/misc/$(ARCH64)/platmod group=sys \ - mode=0755 -$(sparc_ONLY)file \ - path=platform/SUNW,Netra-CP2300/kernel/tod/$(ARCH64)/todds1307 group=sys \ - mode=0755 -$(sparc_ONLY)file \ path=platform/SUNW,Netra-CP3010/kernel/misc/$(ARCH64)/platmod group=sys \ mode=0755 $(sparc_ONLY)file path=platform/SUNW,Netra-T12/kernel/drv/$(ARCH64)/lw8 \ @@ -851,7 +836,6 @@ $(sparc_ONLY)file path=platform/sun4u/kernel/crypto/$(ARCH64)/sha1 group=sys \ $(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/adm1026 group=sys $(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/adm1031 group=sys $(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/bbc_beep group=sys -$(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/ctsmc group=sys $(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/db21554 group=sys $(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/ebus group=sys $(sparc_ONLY)file path=platform/sun4u/kernel/drv/$(ARCH64)/epic group=sys @@ -1002,7 +986,6 @@ $(sparc_ONLY)file path=platform/sun4v/kernel/misc/$(ARCH64)/vis group=sys \ $(sparc_ONLY)file path=usr/share/man/man4/sbus.4 $(i386_ONLY)file path=usr/share/man/man4/sysbus.4 $(sparc_ONLY)file path=usr/share/man/man7d/bbc_beep.7d -$(sparc_ONLY)file path=usr/share/man/man7d/ctsmc.7d $(sparc_ONLY)file path=usr/share/man/man7d/dr.7d $(sparc_ONLY)file path=usr/share/man/man7d/fd.7d $(sparc_ONLY)file path=usr/share/man/man7d/gpio_87317.7d diff --git a/usr/src/pkg/manifests/system-kernel.man7d.inc b/usr/src/pkg/manifests/system-kernel.man7d.inc index 07da55bde8..d891935067 100644 --- a/usr/src/pkg/manifests/system-kernel.man7d.inc +++ b/usr/src/pkg/manifests/system-kernel.man7d.inc @@ -12,6 +12,7 @@ # # Copyright 2011, Richard Lowe # Copyright 2016 Nexenta Systems, Inc. +# Copyright 2019 Peter Tribble. # Copyright 2019 Joyent, Inc. # @@ -45,7 +46,6 @@ file path=usr/share/man/man7d/st.7d file path=usr/share/man/man7d/sysmsg.7d file path=usr/share/man/man7d/ticlts.7d file path=usr/share/man/man7d/tty.7d -file path=usr/share/man/man7d/ttymux.7d file path=usr/share/man/man7d/tzmon.7d file path=usr/share/man/man7d/ufm.7d file path=usr/share/man/man7d/virtualkm.7d diff --git a/usr/src/pkg/manifests/system-kernel.mf b/usr/src/pkg/manifests/system-kernel.mf index 70fa5dd1dc..0aea96988d 100644 --- a/usr/src/pkg/manifests/system-kernel.mf +++ b/usr/src/pkg/manifests/system-kernel.mf @@ -25,6 +25,7 @@ # Copyright 2015 Nexenta Systems, Inc. All rights reserved. # Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> # Copyright 2017 James S Blachly, MD <james.blachly@gmail.com> +# Copyright 2019 Peter Tribble. # Copyright 2019 RackTop Systems # Copyright 2019 Joyent, Inc. # @@ -276,7 +277,6 @@ driver name=tcp perms="tcp 0666 root sys" driver name=tcp6 perms="tcp6 0666 root sys" driver name=tl perms="* 0666 root sys" clone_perms="ticlts 0666 root sys" \ clone_perms="ticots 0666 root sys" clone_perms="ticotsord 0666 root sys" -$(sparc_ONLY)driver name=ttymux alias=multiplexer $(i386_ONLY)driver name=tzmon $(sparc_ONLY)driver name=uata \ alias=pci1095,646 \ @@ -402,7 +402,6 @@ file path=kernel/drv/$(ARCH64)/sysmsg group=sys file path=kernel/drv/$(ARCH64)/tcp group=sys file path=kernel/drv/$(ARCH64)/tcp6 group=sys file path=kernel/drv/$(ARCH64)/tl group=sys -$(sparc_ONLY)file path=kernel/drv/$(ARCH64)/ttymux group=sys $(i386_ONLY)file path=kernel/drv/$(ARCH64)/tzmon group=sys $(sparc_ONLY)file path=kernel/drv/$(ARCH64)/uata group=sys $(i386_ONLY)file path=kernel/drv/$(ARCH64)/ucode group=sys diff --git a/usr/src/pkg/manifests/system-library-platform.mf b/usr/src/pkg/manifests/system-library-platform.mf index e68878430c..7e18e29ce4 100644 --- a/usr/src/pkg/manifests/system-library-platform.mf +++ b/usr/src/pkg/manifests/system-library-platform.mf @@ -34,9 +34,6 @@ dir path=usr group=sys dir path=usr/platform group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,A70/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP2300/sbin $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Netra-CP3010/sbin @@ -116,12 +113,6 @@ $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-4 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-4/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/lib -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIi-Netract group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIi-Netract/lib $(i386_ONLY)dir path=usr/platform/i86pc group=sys $(i386_ONLY)dir path=usr/platform/i86pc/lib $(sparc_ONLY)dir path=usr/platform/sun4u group=sys @@ -170,8 +161,6 @@ $(sparc_ONLY)file path=usr/platform/SUNW,Ultra-250/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file path=usr/platform/SUNW,Ultra-4/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file \ path=usr/platform/SUNW,Ultra-Enterprise/lib/libprtdiag_psr.so.1 -$(sparc_ONLY)file \ - path=usr/platform/SUNW,UltraSPARC-IIi-Netract/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file path=usr/platform/sun4u/lib/cfgadm/$(ARCH64)/ac.so.1 $(sparc_ONLY)file path=usr/platform/sun4u/lib/cfgadm/$(ARCH64)/sbd.so.1 $(sparc_ONLY)file path=usr/platform/sun4u/lib/cfgadm/$(ARCH64)/sysctrl.so.1 @@ -212,12 +201,6 @@ $(sparc_ONLY)link path=usr/platform/SUNW,A70/sbin target=../sun4u/sbin $(sparc_ONLY)link path=usr/platform/SUNW,Netra-210 target=SUNW,Sun-Fire-V240 $(sparc_ONLY)link path=usr/platform/SUNW,Netra-240 target=SUNW,Sun-Fire-V240 $(sparc_ONLY)link path=usr/platform/SUNW,Netra-440 target=SUNW,Sun-Fire-V440 -$(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP2300/lib/cfgadm \ - target=../../sun4u/lib/cfgadm -$(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP2300/lib/fs \ - target=../../sun4u/lib/fs -$(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP2300/sbin/prtdiag \ - target=../../sun4u/sbin/prtdiag $(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP3010/lib/cfgadm \ target=../../sun4u/lib/cfgadm $(sparc_ONLY)link path=usr/platform/SUNW,Netra-CP3010/lib/fs \ @@ -500,27 +483,6 @@ $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise/lib/fs \ $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise/sbin \ target=../sun4u/sbin $(sparc_ONLY)link path=usr/platform/SUNW,UltraAX-i2 target=sun4u -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib/cfgadm \ - target=../../sun4u/lib/cfgadm -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib/fs \ - target=../../sun4u/lib/fs -$(sparc_ONLY)link \ - path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib/libprtdiag_psr.so.1 \ - target=../../SUNW,UltraSPARC-IIi-Netract/lib/libprtdiag_psr.so.1 -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/sbin \ - target=../sun4u/sbin -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/lib/cfgadm \ - target=../../sun4u/lib/cfgadm -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/lib/fs \ - target=../../sun4u/lib/fs -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60/sbin \ - target=../sun4u/sbin -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIi-Netract/lib/cfgadm \ - target=../../sun4u/lib/cfgadm -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIi-Netract/lib/fs \ - target=../../sun4u/lib/fs -$(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIi-Netract/sbin \ - target=../sun4u/sbin $(sparc_ONLY)link path=usr/platform/sun4u/lib/cfgadm/$(ARCH64)/ac.so \ target=./ac.so.1 $(sparc_ONLY)link path=usr/platform/sun4u/lib/cfgadm/$(ARCH64)/sbd.so \ diff --git a/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile index fffd4a6789..0f3024822c 100644 --- a/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile +++ b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile @@ -34,9 +34,6 @@ PLATLINKS = SUNW,Ultra-2 PLATLINKS += SUNW,Ultra-250 PLATLINKS += SUNW,Ultra-4 PLATLINKS += SUNW,Ultra-Enterprise -PLATLINKS += SUNW,UltraSPARC-IIi-Netract -PLATLINKS += SUNW,UltraSPARC-IIe-NetraCT-40 -PLATLINKS += SUNW,UltraSPARC-IIe-NetraCT-60 PLATLINKS += SUNW,Sun-Blade-100 PLATLINKS += SUNW,Sun-Blade-1000 PLATLINKS += SUNW,Sun-Blade-1500 @@ -56,7 +53,6 @@ PLATLINKS += SUNW,Sun-Fire-V490 PLATLINKS += SUNW,Serverblade1 PLATLINKS += SUNW,Netra-T12 PLATLINKS += SUNW,Netra-T4 -PLATLINKS += SUNW,Netra-CP2300 PLATLINKS += SUNW,Netra-CP3010 PLATLINKS += SUNW,SPARC-Enterprise diff --git a/usr/src/uts/sparc/Makefile.sparc b/usr/src/uts/sparc/Makefile.sparc index 912362ffbc..a37de46509 100644 --- a/usr/src/uts/sparc/Makefile.sparc +++ b/usr/src/uts/sparc/Makefile.sparc @@ -25,6 +25,7 @@ # Copyright 2019 Joyent, Inc. # Copyright 2016 Gary Mills # Copyright 2016 Nexenta Systems, Inc. +# Copyright 2019 Peter Tribble. # Copyright 2019 RackTop Systems # @@ -221,7 +222,7 @@ DRV_KMODS += log logindmux kssl mm nca physmem pm poll pool DRV_KMODS += pseudo ptc ptm pts ptsl ramdisk random rsm rts sad DRV_KMODS += simnet softmac sppp sppptun sy sysevent sysmsg DRV_KMODS += spdsock -DRV_KMODS += tcp tcp6 timerfd tl tnf ttymux udp udp6 wc winlock zcons +DRV_KMODS += tcp tcp6 timerfd tl tnf udp udp6 wc winlock zcons DRV_KMODS += ippctl DRV_KMODS += dld DRV_KMODS += ipd diff --git a/usr/src/uts/sparc/os/dacf.conf b/usr/src/uts/sparc/os/dacf.conf index 971f50f751..83ec3d1abb 100644 --- a/usr/src/uts/sparc/os/dacf.conf +++ b/usr/src/uts/sparc/os/dacf.conf @@ -21,6 +21,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # # NOTICE: This file contains important KERNEL STATE. Do not edit this file. @@ -32,7 +33,7 @@ # # Configure and/or unconfigure a keyboard into the keyboard console stream. # pushmod is the STREAMS module to be pushed on the minor node specified by -# driver-minorname. The pushmod varies based on the keyboard hardware. +# driver-minorname. The pushmod varies based on the keyboard hardware. # driver-minorname="hid:internal_keyboard" consconfig_dacf:kb_config post-attach - pushmod="usbkbm" driver-minorname="hid:internal_keyboard" consconfig_dacf:kb_config pre-detach - pushmod="usbkbm" @@ -40,7 +41,7 @@ driver-minorname="hid:internal_keyboard" consconfig_dacf:kb_config pre-detach - # # Configure and/or unconfigure a mouse into the mouse console stream. pushmod # is the STREAMS module to be pushed on the minor node specified by -# driver-minorname. The pushmod varies based on the mouse hardware. +# driver-minorname. The pushmod varies based on the mouse hardware. # driver-minorname="hid:internal_mouse" consconfig_dacf:ms_config post-attach - pushmod="usbms" driver-minorname="hid:internal_mouse" consconfig_dacf:ms_config pre-detach - pushmod="usbms" @@ -51,11 +52,6 @@ driver-minorname="mouse8042:internal_mouse" consconfig_dacf:ms_config pre-detach driver-minorname="su_pnp:mouse" consconfig_dacf:ms_config post-attach - pushmod="ms" # -# Configure and/or unconfigure a console into the termio compliant streams for Monte Carlo -# -driver-minorname="ttymux:con" ttymux_dacf:ttymux_config post-attach - - -# # Devices directly supporting the keyboard API need no device-specific module, # but do need to be linked to the console stream. # diff --git a/usr/src/uts/sparc/ttymux/Makefile b/usr/src/uts/sparc/ttymux/Makefile deleted file mode 100644 index e798f51c21..0000000000 --- a/usr/src/uts/sparc/ttymux/Makefile +++ /dev/null @@ -1,117 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the ttymux driver -# kernel module. -# -# sparc implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = ttymux -OBJECTS = $(TTYMUX_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(TTYMUX_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sparc/Makefile.sparc - -# -#Overrides -# -ALL_BUILDS = $(ALL_BUILDSONLY64) -DEF_BUILDS = $(DEF_BUILDSONLY64) -CLEANLINTFILES += $(LINT32_FILES) - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Override defaults to build a unique, local modstubs.o. -# -MODSTUBS_DIR = $(OBJS_DIR) -$(MODSTUBS_O) := AS_CPPFLAGS += -DTTYMUX_MODULE -CLEANFILES += $(MODSTUBS_O) - - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON - -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized -CERRWARN += -_gcc=-Wno-type-limits - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) lint32 - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sparc/Makefile.targ diff --git a/usr/src/uts/sun/Makefile.files b/usr/src/uts/sun/Makefile.files index b8a819672b..d31bda8f11 100644 --- a/usr/src/uts/sun/Makefile.files +++ b/usr/src/uts/sun/Makefile.files @@ -22,6 +22,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # uts/sun/Makefile.files # @@ -67,19 +68,13 @@ DADA_OBJS += dcd_hba.o dcd_transport.o \ SSD_OBJS += sd.o sd_xbuf.o -WSDRV_OBJS += wsdrv.o +WSDRV_OBJS += wsdrv.o ZS_OBJS += zs_async.o zs_common.o ZSH_OBJS += zs_hdlc.o # -# streams modules -# - -TTYMUX_OBJS += ttymux.o ttymux_ioctl.o - -# # Section 3: Misc. # LINT_DEFS += -Dsun diff --git a/usr/src/uts/sun/Makefile.rules b/usr/src/uts/sun/Makefile.rules index ed0d87a09b..3394bde438 100644 --- a/usr/src/uts/sun/Makefile.rules +++ b/usr/src/uts/sun/Makefile.rules @@ -22,6 +22,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # uts/sun/Makefile.rules # @@ -53,10 +54,6 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/sun/io/eri/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/sun/io/ttymux/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - $(OBJS_DIR)/%.o: $(UTSBASE)/sun/io/dada/conf/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -77,7 +74,7 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/sun/io/scsi/targets/%.c $(COMPILE.c) -I. -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/scsi/adapters/%.c +$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/scsi/adapters/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -110,6 +107,3 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/sun/io/dada/targets/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/scsi/adapters/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun/io/ttymux/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/sun/io/ttymux/ttymux.c b/usr/src/uts/sun/io/ttymux/ttymux.c deleted file mode 100644 index 22862fe8d9..0000000000 --- a/usr/src/uts/sun/io/ttymux/ttymux.c +++ /dev/null @@ -1,2879 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -/* - * DESCRIPTION - * - * ttymux - Multiplexer driver for multiplexing termio compliant streams onto - * a single upper stream. - * - * ADD2FRONT macro can be used to specify the order in which a console - * device is put in the queue of multiplexed physical serial devices, - * during the association and disassociation of a console interface. - * When this macro is defined, the device is placed in front of the queue, - * otherwise by default it is placed at the end. - * Console I/O happens to each of the physical devices in the order of - * their position in this queue. - */ - -#include <sys/types.h> -#include <sys/file.h> -#include <sys/stream.h> -#include <sys/strsubr.h> -#include <sys/strlog.h> -#include <sys/strsun.h> -#include <sys/modctl.h> -#include <sys/debug.h> -#include <sys/kbio.h> -#include <sys/devops.h> -#include <sys/errno.h> -#include <sys/stat.h> -#include <sys/kmem.h> -#include <sys/ddi.h> -#include <sys/consdev.h> -#include <sys/tty.h> -#include <sys/ptyvar.h> -#include <sys/termio.h> -#include <sys/fcntl.h> -#include <sys/mkdev.h> -#include <sys/ser_sync.h> -#include <sys/esunddi.h> -#include <sys/policy.h> - -#include <sys/ttymux.h> -#include "ttymux_impl.h" - -/* - * Extern declarations - */ -extern mblk_t *mkiocb(uint_t); -extern int nulldev(); -extern uintptr_t space_fetch(char *key); - -extern int sm_ioctl_cmd(sm_uqi_t *, mblk_t *); -extern int ttymux_abort_ioctl(mblk_t *); -extern int ttymux_device_fini(sm_lqi_t *); -extern int ttymux_device_init(sm_lqi_t *); - -/* - * Exported interfaces - */ -int sm_disassociate(int, sm_lqi_t *, ulong_t); -int sm_associate(int, sm_lqi_t *, ulong_t, uint_t, char *); - -/* - * Variables defined here and visible only internally - */ -sm_ss_t *sm_ssp = 0; -static int sm_instance = 0; -static int smctlunit; - -static uint_t sm_default_trflag = 0; -uint_t sm_max_units = 6; -uint_t sm_minor_cnt = 0; -static uint_t sm_refuse_opens = 0; - -/* - * Local definitions. - */ - -/* force these flags to be unset on console devices */ -static ulong_t sm_cmask = (ulong_t)(CRTSXOFF|CRTSCTS); - -/* - * SECTION - * Implementation Section: - */ -void -sm_debug(char *msg, ...) -{ - va_list args; - char buf[256]; - int sz; - - va_start(args, msg); - sz = vsnprintf(buf, sizeof (buf), msg, args); - va_end(args); - - if (sz < 0) - (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance, 1, - SL_TRACE, "vsnprintf parse error\n"); - else if (sz > sizeof (buf)) { - char *b; - size_t len = sz + 1; - - b = kmem_alloc(len, KM_SLEEP); - va_start(args, msg); - sz = vsnprintf(b, len, msg, args); - va_end(args); - if (sz > 0) - (void) strlog(ddi_driver_major(sm_ssp->sm_dip), - sm_instance, 1, SL_TRACE, b); - kmem_free(b, len); - } else { - - (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance, - 1, SL_TRACE, buf); - } -} - -void -sm_log(char *msg, ...) -{ - va_list args; - char buf[128]; - int sz; - - va_start(args, msg); - sz = vsnprintf(buf, sizeof (buf), msg, args); - va_end(args); - - if (sz < 0) - (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance, 1, - SL_TRACE, "vsnprintf parse error\n"); - else if (sz > sizeof (buf)) { - char *b; - size_t len = sz + 1; - - b = kmem_alloc(len, KM_SLEEP); - va_start(args, msg); - sz = vsnprintf(b, len, msg, args); - va_end(args); - if (sz > 0) - (void) strlog(ddi_driver_major(sm_ssp->sm_dip), - sm_instance, 1, SL_NOTE, b); - kmem_free(b, len); - } else { - - (void) strlog(ddi_driver_major(sm_ssp->sm_dip), sm_instance, - 1, SL_NOTE, buf); - } -} - -/* - * Should only be called if the caller can guarantee that the vnode - * and/or the stream won't disappear while finding the dip. - * This routine is only called during an I_PLINK request so it's safe. - * The routine obtains the dev_t for a linked se stream. - */ -static void -sm_setdip(queue_t *q, sm_lqi_t *lqi) -{ - lqi->sm_dev = q && STREAM(q) ? STREAM(q)->sd_vnode->v_rdev : NODEV; -} - -/* - * Called from driver close, state change reports and I_PUNLINK ioctl. - * A lower stream has been unlinked - clean up the state associated with it. - */ -void -sm_lqifree(sm_lqi_t *lqi) -{ - int mu_owned; - sm_lqi_t **pplqi; - - ASSERT(mutex_owned(lqi->sm_umutex)); - ASSERT(SM_RQ(lqi) != 0); - - /* - * Clear all state associated with this lower queue except - * the identity of the queues themselves and the link id which - * can only be cleared by issuing a streams I_PUNLINK ioctl. - * - * The association of a lower queue is a two step process: - * 1. initialise the lower q data structure on I_PLINK - * 2. associate an upper q with the lower q on SM_CMD_ASSOCIATE. - * - * If step 2 has ocurred then - * remove this lower queue info from the logical unit. - */ - if (lqi->sm_uqi) { - sm_dbg('Y', ("lqifree unit %d, ", lqi->sm_uqi->sm_lunit)); - if ((mu_owned = mutex_owned(lqi->sm_uqi->sm_umutex)) == 0) - LOCK_UNIT(lqi->sm_uqi); - - pplqi = &lqi->sm_uqi->sm_lqs; - while (*pplqi != lqi) { - ASSERT(*pplqi); - pplqi = &((*pplqi)->sm_nlqi); - } - *pplqi = lqi->sm_nlqi; - lqi->sm_uqi->sm_nlqs--; - - if (mu_owned == 0) - UNLOCK_UNIT(lqi->sm_uqi); - - lqi->sm_uqi = 0; - } -} - -/* - * Given a q return the associated lower queue data structure or NULL. - * Return the data locked. - */ -static sm_lqi_t * -get_lqi_byq(queue_t *q) -{ - int i; - sm_lqi_t *lqi, *flqi = 0; - - for (i = 0; i < MAX_LQS; i++) { - lqi = &sm_ssp->sm_lqs[i]; - LOCK_UNIT(lqi); - if (flqi == 0 && lqi->sm_linkid == 0) /* assumes muxids != 0 */ - flqi = lqi; - else if (SM_RQ(lqi) == q || SM_WQ(lqi) == q) { - if (flqi) - UNLOCK_UNIT(flqi); - return (lqi); - } - else - UNLOCK_UNIT(lqi); - } - return (flqi); -} - -/* - * Given a streams link identifier return the associated lower queue data - * structure or NULL. - */ -sm_lqi_t * -get_lqi_byid(int linkid) -{ - int i; - sm_lqi_t *lqi; - - if (linkid == 0) - return (NULL); - for (i = 0; i < MAX_LQS; i++) { - lqi = &sm_ssp->sm_lqs[i]; - if (lqi->sm_linkid == linkid) - return (lqi); - } - return (NULL); -} - -/* - * Given a dev_t for a lower stream return the associated lower queue data - * structure or NULL. - */ -sm_lqi_t * -get_lqi_bydevt(dev_t dev) -{ - int i; - sm_lqi_t *lqi; - - if (dev == NODEV) - return (NULL); - - for (i = 0; i < MAX_LQS; i++) { - lqi = &sm_ssp->sm_lqs[i]; - if (lqi->sm_dev == dev) - return (lqi); - } - return (NULL); -} - -/* - * Determine whether the input flag is set on at least - * howmany queues. - */ -static int -sm_is_flag_set(sm_uqi_t *uqi, uint_t flag, uint_t howmany) -{ - sm_lqi_t *lqi; - - if (howmany == 0) - return (0); - - for (lqi = uqi->sm_lqs; lqi; lqi = lqi->sm_nlqi) { - if (lqi->sm_flags & flag) - if (--howmany == 0) - return (1); - } - return (0); -} - -/* - * How many usable queues are associated with a given upper stream - */ -static int -sm_uwq_error(sm_uqi_t *uqi) -{ - return (sm_is_flag_set(uqi, (WERROR_MODE|HANGUP_MODE), uqi->sm_nlqs)); -} - -/* - * How many of the queues associated with a given upper stream - * - do not - have the given flags set. - */ -static int -sm_q_count(sm_uqi_t *uqi, uint_t flag) -{ - sm_lqi_t *lqi; - int count = 0; - - for (lqi = uqi->sm_lqs; lqi; lqi = lqi->sm_nlqi) { - if ((lqi->sm_flags & flag) == 0) - count++; - } - return (count); -} - -/* - * How many of the queues associated with a given upper stream - * - do not - have the given flags set. - */ -static int -sm_qs_without(sm_uqi_t *uqi, uint_t flag, uint_t ioflag) -{ - sm_lqi_t *lqi; - int count = 0; - - for (lqi = uqi->sm_lqs; lqi; lqi = lqi->sm_nlqi) { - if ((lqi->sm_flags & flag) == 0 && - (lqi->sm_ioflag & ioflag) == 0) - count++; - } - return (count); -} - -/* - * How many usable queues are associated with a given upper stream - */ -static int -sm_good_qs(sm_uqi_t *uqi) -{ - return (sm_q_count(uqi, (WERROR_MODE|HANGUP_MODE))); -} - -static int -sm_cnt_oqs(sm_uqi_t *uqi) -{ - return (sm_qs_without(uqi, (WERROR_MODE|HANGUP_MODE), - (uint_t)FOROUTPUT)); -} - -/* - * Send an ioctl downstream and remember that it was sent so that - * its response can be caught on the way back up. - */ -static void -sm_issue_ioctl(void *arg) -{ - sm_lqi_t *lqi = arg; - uint_t cmdflag = 0; - queue_t *q = SM_WQ(lqi); - int iocmd, size; - - LOCK_UNIT(lqi); - - lqi->sm_bid = 0; - if ((lqi->sm_flags & (WERROR_MODE|HANGUP_MODE)) == 0 && - (lqi->sm_flags & (WANT_CDSTAT|WANT_TCSET))) { - mblk_t *pioc; - - if (lqi->sm_flags & WANT_TCSET) { - lqi->sm_flags &= ~WANT_TCSET; - iocmd = TCSETS; - cmdflag = WANT_TCSET; - } else if (lqi->sm_flags & WANT_SC) { - lqi->sm_flags &= ~WANT_SC; - iocmd = TIOCGSOFTCAR; - cmdflag = WANT_SC; - } else if (lqi->sm_flags & WANT_CD) { - lqi->sm_flags &= ~WANT_CD; - iocmd = TIOCMGET; - } else if (lqi->sm_flags & WANT_CL) { - lqi->sm_flags &= ~WANT_CL; - iocmd = TCGETS; - cmdflag = WANT_CL; - } else { - UNLOCK_UNIT(lqi); - return; - } - - if (pioc = mkiocb(iocmd)) { - if (cmdflag == WANT_TCSET) { - pioc->b_cont = - sm_allocb(sizeof (struct termios), - BPRI_MED); - if (pioc->b_cont == 0) { - freemsg(pioc); - pioc = 0; - } else { - struct termios *tc = (struct termios *) - pioc->b_cont->b_wptr; - - bzero((caddr_t)tc, - sizeof (struct termios)); - tc->c_cflag = lqi->sm_ttycommon-> - t_cflag; - pioc->b_cont->b_rptr = - pioc->b_cont->b_wptr; - pioc->b_cont->b_wptr += - sizeof (struct termios); - } - size = sizeof (struct iocblk) + - sizeof (struct termios); - } - else - size = sizeof (struct iocblk); - } - else - size = sizeof (struct iocblk); - - if (pioc != 0) { - - lqi->sm_piocid = ((struct iocblk *)pioc->b_rptr)-> - ioc_id; - lqi->sm_flags |= SM_IOCPENDING; - - /* lqi->sm_flags |= cmdflag; */ - UNLOCK_UNIT(lqi); - (void) putq(q, pioc); - } else { - UNLOCK_UNIT(lqi); - lqi->sm_bid = qbufcall(WR(q), size, BPRI_MED, - sm_issue_ioctl, lqi); - } - } - else - UNLOCK_UNIT(lqi); -} - -/* - * Associate one of the drivers minor nodes with a serial device. - */ -int -sm_associate(int unit, sm_lqi_t *plqi, ulong_t tag, uint_t ioflag, char *dp) -{ - sm_uqi_t *uqi; - int rval = 0; - - sm_dbg('Y', ("sm_associate(%d, %d, %d): ", - (plqi) ? plqi->sm_linkid : 0, unit, ioflag)); - /* - * Check the data is valid. - * Associate a lower queue with a logical unit. - */ - - if (unit < 0 || unit >= NLUNITS || plqi == 0 || - (uqi = get_uqi(sm_ssp, unit)) == 0) { - sm_dbg('@', (" invalid: lqi=0x%p lui=0x%p:", plqi, uqi)); - rval = EINVAL; - } else { - if ((ioflag & FORIO) == 0) - ioflag = FORIO; - - LOCK_UNIT(plqi); - - if (plqi->sm_uqi) { - if (plqi->sm_uqi->sm_lunit == unit) { - if ((ioflag & (uint_t)FORIO) != 0) - plqi->sm_ioflag = - (ioflag & (uint_t)FORIO); - rval = 0; - } else { - sm_dbg('@', ("already associated with unit %d:", - plqi->sm_uqi->sm_lunit)); - rval = EINVAL; - } - } else { - - LOCK_UNIT(uqi); - - if ((ioflag & (uint_t)FORIO) != 0) - plqi->sm_ioflag = (ioflag & (uint_t)FORIO); - - plqi->sm_ttycommon->t_cflag = uqi->sm_ttycommon-> - t_cflag; - plqi->sm_ttycommon->t_flags = uqi->sm_ttycommon-> - t_flags; - plqi->sm_uqi = uqi; - plqi->sm_mbits = 0; - plqi->sm_tag = tag; - - if (*dp == '/') - (void) strncpy(plqi->sm_path, dp, MAXPATHLEN); - else - *(plqi->sm_path) = '\0'; - - plqi->sm_flags |= WANT_TCSET; -#ifdef ADD2FRONT - plqi->sm_nlqi = uqi->sm_lqs; - uqi->sm_lqs = plqi; -#else - plqi->sm_nlqi = 0; - if (uqi->sm_lqs) { - sm_lqi_t *lq; - for (lq = uqi->sm_lqs; lq->sm_nlqi; - lq = lq->sm_nlqi) { - } - lq->sm_nlqi = plqi; - } else - uqi->sm_lqs = plqi; -#endif - uqi->sm_nlqs++; - - (void) ttymux_device_init(plqi); - - UNLOCK_UNIT(uqi); - rval = 0; - /* - * Everything looks good so it's now ok to enable lower - * queue processing. - * Note the lower queue should be enabled as soon as - * I_PLINK returns (used in sm_get_ttymodes etc). - * Schedule ioctls to obtain the terminal settings. - */ - - if ((uqi->sm_flags & FULLY_OPEN) || uqi->sm_waitq) - plqi->sm_uqflags |= SM_UQVALID; - - qenable(SM_RQ(plqi)); - if (plqi->sm_flags & (WANT_CDSTAT|WANT_TCSET)) { - /* - * Bypass the lower half of the driver (hence - * no qwriter) and apply the current termio - * settings on the lower stream. - */ - UNLOCK_UNIT(plqi); - if (plqi->sm_bid) { - qunbufcall(SM_WQ(plqi), plqi->sm_bid); - plqi->sm_bid = 0; - } - /* - * Only set cflags on the lower q if we know - * the settings on any other lower queue. - */ - sm_issue_ioctl(plqi); - LOCK_UNIT(plqi); - - } - } - - UNLOCK_UNIT(plqi); - } - sm_dbg('Y', ("sm_associate: rval=%d.\n", rval)); - return (rval); -} - -/* - * Break an association between one of the driver's minor nodes and - * a serial device. - */ -int -sm_disassociate(int unit, sm_lqi_t *plqi, ulong_t tag) -{ - sm_uqi_t *uqi; - int rval = 0; - - sm_dbg('Y', ("sm_disassociate: link %d, unit %d: ", - (plqi) ? plqi->sm_linkid : 0, unit)); - /* - * Check the data is valid. - * Disassociate a lower queue with a logical unit. - */ - if (unit < 0 || unit >= NLUNITS || plqi == 0 || - (uqi = get_uqi(sm_ssp, unit)) == 0) { - sm_dbg('@', ("invalid: lqi=0x%p lui=0x%p", plqi, uqi)); - rval = EINVAL; - } else { - LOCK_UNIT(plqi); - - if (plqi->sm_uqi == NULL) { - sm_dbg('@', ("unit not associated")); - rval = EINVAL; - } else if (plqi->sm_uqi->sm_lunit != unit) { - sm_dbg('@', ("unit and linkid not related", - plqi->sm_uqi->sm_lunit)); - rval = EINVAL; - } else if (plqi->sm_tag != tag) { - sm_dbg('@', - ("Invalid tag for TTYMUX_DISASSOC ioctl\n")); - rval = EPERM; - } else { - sm_dbg('Y', ("disassociating ")); - - (void) ttymux_device_fini(plqi); - - /* - * Indicate that carrier status is no - * longer required and that the upper - * queue should not be used by plqi - */ - plqi->sm_flags &= ~(WANT_CDSTAT|WANT_TCSET); - plqi->sm_uqflags &= ~(SM_UQVALID|SM_OBPCNDEV); - plqi->sm_ioflag = 0u; - - sm_lqifree(plqi); - rval = 0; - } - UNLOCK_UNIT(plqi); - } - sm_dbg('Y', (" rval=%d.\n", rval)); - return (rval); - -} - -/* - * Streams helper routines; - */ - -/* - * Schedule a qbufcall for an upper queue. - * Must be called within the perimiter of the parameter q. - * fn must reenable the q. - * Called: - * whenever a message must be placed on multiple queues and allocb fails; - */ -static void -sm_sched_uqcb(queue_t *q, int memreq, int pri, void (*fn)()) -{ - sm_uqi_t *uqi = q->q_ptr; - - if (uqi->sm_ttybid != 0) - qunbufcall(q, uqi->sm_ttybid); - - noenable(q); - - uqi->sm_ttybid = qbufcall(q, memreq, pri, fn, uqi); -} - -/* - * qbufcall routine to restart the queues when memory is available. - */ -static void -sm_reenable_q(sm_uqi_t *uqi) -{ - queue_t *wq = SM_WQ(uqi); - - if ((uqi->sm_flags & SM_STOPPED) == 0) { - enableok(wq); - qenable(wq); - } -} - -/* - * Place a message on the write queue of each stream associated with - * the given upper stream. - */ -static void -sm_senddown(sm_uqi_t *uqi) -{ - sm_lqi_t *lqi; - - for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) { - if (lqi->sm_mp != 0) { - putnext(SM_WQ(lqi), lqi->sm_mp); - lqi->sm_mp = 0; - } - } -} - -/* - * For each lower device that should receive a write message duplicate - * the message block. - */ -static int -sm_dupmsg(sm_uqi_t *uqi, mblk_t *mp) -{ - sm_lqi_t *lqi; - mblk_t *origmp = mp; - - for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) { - lqi->sm_mp = 0; - if (lqi->sm_flags & WERROR_MODE) { - continue; - } - if ((lqi->sm_ioflag & (uint_t)FOROUTPUT) == 0) { - if (DB_TYPE(mp) == M_DATA) - continue; - } - if (lqi->sm_nlqi == 0) { - lqi->sm_mp = mp; - origmp = NULL; - } else if ((lqi->sm_mp = sm_copymsg(mp)) == 0) { - sm_lqi_t *flqi; - - for (flqi = uqi->sm_lqs; flqi != lqi; - flqi = flqi->sm_nlqi) { - if (lqi->sm_mp) { - /* must have been sm_copymsg */ - sm_freemsg(lqi->sm_mp); - lqi->sm_mp = 0; - } - } - return (sm_cnt_oqs(uqi) * msgdsize(mp)); - } - } - if (origmp != NULL) - freemsg(origmp); - return (0); -} - -/* - * Return 1 if all associated lower devices have room for another message - * otherwise return 0. - */ -static int -sm_cansenddown(sm_uqi_t *uqi) -{ - - register sm_lqi_t *lqi; - - if (uqi->sm_lqs == 0) - return (0); - - for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) { - if ((lqi->sm_flags & WERROR_MODE) == 0 && - canputnext(SM_WQ(lqi)) == 0) - return (0); - } - return (1); -} - -/* - * Put a message down all associated lower queues. - * Return 1 if the q function was called. - */ -static int -sm_putqs(queue_t *q, mblk_t *mp, int (*qfn)()) -{ - register sm_uqi_t *uqi = (sm_uqi_t *)q->q_ptr; - register int memreq; - int pri = (DB_TYPE(mp) < QPCTL) ? BPRI_MED : BPRI_HI; - int rval = 0; - - if (uqi->sm_lqs == 0 || (uqi->sm_flags & WERROR_MODE)) { - - sm_dbg('Q', ("sm_putqs: freeing (0x%p 0x%p).\n", uqi->sm_lqs, - uqi->sm_flags)); - freemsg(mp); - } else if (pri != BPRI_HI && sm_cansenddown(uqi) == 0) { - /* a lower q is flow controlled */ - (void) qfn(q, mp); - rval = 1; - } else if ((memreq = sm_dupmsg(uqi, mp)) == 0) { - - sm_senddown(uqi); - - } else { - sm_log("sm_putqs: msg 0x%x - can't alloc %d bytes (pri %d).\n", - DB_TYPE(mp), memreq, pri); - sm_sched_uqcb(q, memreq, pri, sm_reenable_q); - - (void) qfn(q, mp); - rval = 1; - - } - - return (rval); -} - -/* - * Service a streams link and unlink requests. - */ -static void -sm_link_req(queue_t *wq, mblk_t *mp) -{ - struct linkblk *linkp; - int rval; - int cmd; - sm_lqi_t *plqi; - - ASSERT(DB_TYPE(mp) == M_IOCTL); - - cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd; - switch (cmd) { - - case I_LINK: - case I_PLINK: - sm_dbg('G', ("sm_link_req: M_IOCTL %x (I_PLINK).\n", cmd)); - - linkp = (struct linkblk *)mp->b_cont->b_rptr; - - /* - * 1. Sanity check the link block. - * 2. Validate that the queue is not already linked - * (and resources available). - * 3. Validate that the lower queue is not associated with - * a logical unit. - * 4. Remember that this lower queue is linked to the driver. - */ - if ((linkp == NULL) || (MBLKL(mp) < sizeof (*linkp)) || - linkp->l_qbot == NULL) { - sm_dbg('I', ("sm_link_req: invalid link block.\n")); - rval = EINVAL; - } else if ((plqi = get_lqi_byq(linkp->l_qbot)) == 0) { - sm_dbg('I', ("sm_link_req: out of resources.\n")); - rval = EBUSY; /* out of resources */ - } else if (plqi->sm_uqi) { - UNLOCK_UNIT(plqi); /* was aquired by get_lqi_byq */ - sm_dbg('I', ("sm_link_req: already associated.\n")); - rval = EBUSY; /* already linked */ - } else { - SM_WQ(plqi) = linkp->l_qbot; - SM_RQ(plqi) = OTHERQ(linkp->l_qbot); - - linkp->l_qbot->q_ptr = - OTHERQ(linkp->l_qbot)->q_ptr = plqi; - plqi->sm_linkid = linkp->l_index; - UNLOCK_UNIT(plqi); /* was aquired by get_lqi_byq */ - - sm_dbg('H', ("sm_link_req: linkid = %d.\n", - linkp->l_index)); - - sm_setdip(linkp->l_qbot, plqi); - plqi->sm_ttycommon->t_flags = 0; - plqi->sm_ttycommon->t_cflag = 0; - plqi->sm_mbits = 0; - (void) ttymux_device_init(plqi); - rval = 0; - } - - break; - - case I_UNLINK: - case I_PUNLINK: - sm_dbg('G', ("sm_link_req: M_IOCTL (I_PUNLINK).\n")); - - linkp = (struct linkblk *)mp->b_cont->b_rptr; - - if ((linkp == NULL) || - (MBLKL(mp) < sizeof (*linkp)) || - linkp->l_qbot == NULL) { - rval = EINVAL; - } else if ((plqi = get_lqi_byid(linkp->l_index)) == 0) { - rval = EINVAL; - } else { - sm_uqi_t *uqi; - int werrmode; - - /* - * Mark the lower q as invalid. - */ - sm_dbg('G', ("I_PUNLINK: freeing link %d\n", - linkp->l_index)); - - if (plqi->sm_bid) { - qunbufcall(SM_RQ(plqi), plqi->sm_bid); - plqi->sm_bid = 0; - } - if (plqi->sm_ttybid) { - qunbufcall(SM_RQ(plqi), plqi->sm_ttybid); - plqi->sm_ttybid = 0; - } - - uqi = plqi->sm_uqi; - - - (void) ttymux_device_fini(plqi); - - if (uqi) - (void) sm_disassociate(uqi->sm_lunit, - plqi, plqi->sm_tag); - - LOCK_UNIT(plqi); - - plqi->sm_piocid = 0; - - werrmode = (plqi->sm_flags & (WERROR_MODE|HANGUP_MODE)) - ? 1 : 0; - - plqi->sm_mbits = 0; - plqi->sm_flags = 0; - - ttycommon_close(plqi->sm_ttycommon); - /* SM_RQ(plqi) = SM_WQ(plqi) = 0; */ - plqi->sm_ttycommon->t_flags = 0; - plqi->sm_ttycommon->t_cflag = 0; - plqi->sm_ttycommon->t_iflag = 0; - plqi->sm_linkid = 0; - plqi->sm_dev = NODEV; - plqi->sm_hadkadbchar = 0; - plqi->sm_nachar = sm_ssp->sm_abs; - - UNLOCK_UNIT(plqi); - if (uqi && - werrmode && - (uqi->sm_flags & FULLY_OPEN) && - sm_uwq_error(uqi) && - putnextctl(SM_RQ(uqi), M_HANGUP) == 0) { - sm_log("sm_link_req: putnextctl(M_HANGUP)" - " failed.\n"); - } - - rval = 0; - } - - break; - default: - rval = EINVAL; - } - if (rval != 0) - miocnak(wq, mp, 0, rval); - else - miocack(wq, mp, 0, 0); -} - -static int -sm_getiocinfo(mblk_t *mp, struct sm_iocinfo *info) -{ - switch (DB_TYPE(mp)) { - case M_COPYOUT: - info->sm_id = ((struct copyreq *)mp->b_rptr)->cq_id; - info->sm_cmd = ((struct copyreq *)mp->b_rptr)->cq_cmd; - info->sm_data = (((struct copyreq *)mp->b_rptr)->cq_size && - mp->b_cont) ? (void *)mp->b_cont->b_rptr : 0; - break; - case M_COPYIN: - info->sm_id = ((struct copyresp *)mp->b_rptr)->cp_id; - info->sm_cmd = ((struct copyresp *)mp->b_rptr)->cp_cmd; - info->sm_data = 0; - break; - case M_IOCACK: - info->sm_id = ((struct iocblk *)mp->b_rptr)->ioc_id; - info->sm_cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd; - /* the se driver has bug so we cannot use ioc_count */ - info->sm_data = (((struct iocblk *)mp->b_rptr)-> - ioc_error == 0 && mp->b_cont) ? - (void *)mp->b_cont->b_rptr : 0; - break; - case M_IOCNAK: - info->sm_id = ((struct iocblk *)mp->b_rptr)->ioc_id; - info->sm_cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd; - info->sm_data = 0; - break; - case M_IOCDATA: - info->sm_id = ((struct copyresp *)mp->b_rptr)->cp_id; - info->sm_cmd = ((struct copyresp *)mp->b_rptr)->cp_cmd; - info->sm_data = (((struct copyresp *)mp->b_rptr)-> - cp_rval == 0 && mp->b_cont) ? - (void *)mp->b_cont->b_rptr : 0; - break; - case M_IOCTL: - info->sm_id = ((struct iocblk *)mp->b_rptr)->ioc_id; - info->sm_cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd; - info->sm_data = 0; - break; - default: - return (EINVAL); - } - return (0); -} - -/* - * Record the termio settings that have been set on the upper stream - */ -static int -sm_update_ttyinfo(mblk_t *mp, sm_uqi_t *uqi) -{ - int err; - struct sm_iocinfo info; - - if ((err = sm_getiocinfo(mp, &info)) != 0) - return (err); - - switch (info.sm_cmd) { - case TIOCSPPS: - case TIOCGPPS: - case TIOCGPPSEV: - return (ENOTSUP); - case TIOCGWINSZ: - case TIOCSWINSZ: - break; - case TCSBRK: - case TIOCSBRK: - case TIOCCBRK: - break; - case TCSETSF: - uqi->sm_flags |= FLUSHR_PEND; - sm_dbg('I', ("TCSETSF: FLUSH is pending\n")); - /*FALLTHROUGH*/ - case TCSETSW: - case TCSETS: - case TCGETS: - if (info.sm_data != 0) { - ((struct termios *)info.sm_data)->c_cflag &= - (tcflag_t)(~uqi->sm_cmask); - uqi->sm_ttycommon->t_cflag = - ((struct termios *)info.sm_data)->c_cflag; - } - break; - case TCSETAF: - sm_dbg('I', ("TCSETAF: FLUSH is pending\n")); - uqi->sm_flags |= FLUSHR_PEND; - /*FALLTHROUGH*/ - case TCSETAW: - case TCSETA: - case TCGETA: - if (info.sm_data != 0) { - ((struct termio *)info.sm_data)->c_cflag &= - (tcflag_t)(~uqi->sm_cmask); - uqi->sm_ttycommon->t_cflag = - (tcflag_t)((struct termio *)info.sm_data)->c_cflag; - } - break; - case TIOCSSOFTCAR: - case TIOCGSOFTCAR: - if (info.sm_data != 0) { - if (*(int *)info.sm_data == 1) - uqi->sm_ttycommon->t_flags |= TS_SOFTCAR; - else - uqi->sm_ttycommon->t_flags &= ~TS_SOFTCAR; - } - break; - case TIOCMSET: - case TIOCMGET: - if (info.sm_data != 0) - uqi->sm_mbits = *(int *)info.sm_data; - break; - case TIOCMBIS: - if (info.sm_data != 0) - uqi->sm_mbits |= *(int *)info.sm_data; - break; - case TIOCMBIC: - if (info.sm_data != 0) - uqi->sm_mbits &= ~(*(int *)info.sm_data); - break; - default: - return (EINVAL); - /* NOTREACHED */ - } /* end switch cmd */ - - if ((uqi->sm_mbits & TIOCM_CD) || - (uqi->sm_ttycommon->t_flags & TS_SOFTCAR) || - (uqi->sm_ttycommon->t_cflag & CLOCAL)) - uqi->sm_flags |= SM_CARON; - else - uqi->sm_flags &= ~SM_CARON; - - return (0); -} - -/* - * SECTION - * STREAM's interface to the OS. - * Routines directly callable from the OS. - */ - -/* - * Processes high priority messages comming from modules above the - * multiplexor. - * Return 1 if the queue was disabled. - */ -static int -sm_hp_uwput(queue_t *wq, mblk_t *mp) -{ - sm_uqi_t *uqi = (sm_uqi_t *)(wq->q_ptr); - int rval = 0; - sm_lqi_t *plqi; - int msgtype = DB_TYPE(mp); - - switch (msgtype) { - - case M_FLUSH: - /* - * How to flush the bottom half: - * putctl1(SM_WQ(plqi), *mp->b_rptr) - * will work on the bottom half but if FLUSHR is set - * when is the right time to flush the upper read queue. - * - * Could set uqi->sm_flags & WANT_FLUSH but then what happens - * if FLUSHR is set and the driver sends up a FLUSHR - * before it handles the current FLUSHR request - * (if only there was an id for the message that could - * be matched when it returns back from the drivers. - * - * Thus I'm going by the book - the bottom half acts like - * a stream head and turns around FLUSHW back down to - * the driver (see lrput). The upper half acts like a - * driver and turns around FLUSHR: - */ - - sm_dbg('I', ("sm_hp_uwput: FLUSH request 0x%x\n", *mp->b_rptr)); - /* flush the upper write queue */ - if (*mp->b_rptr & FLUSHW) - flushq(wq, FLUSHDATA); - - /* - * flush each associated lower write queue - * and pass down the driver (ignore the FLUSHR and deal with - * it when it comes back up the read side. - */ - for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) { - if ((plqi->sm_flags & WERROR_MODE) == 0 && - SM_WQ(plqi)) { - sm_dbg('I', ("flush lq 0x%p\n", SM_WQ(plqi))); - if (*mp->b_rptr & FLUSHW) - flushq(SM_WQ(plqi), FLUSHDATA); - (void) putnextctl1(SM_WQ(plqi), M_FLUSH, - *mp->b_rptr); - } - } - break; - - case M_STARTI: - for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) { - plqi->sm_flags &= ~SM_ISTOPPED; - if ((plqi->sm_flags & WERROR_MODE) == 0) - (void) putnextctl(SM_WQ(plqi), msgtype); - } - break; - - case M_STOPI: - for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) { - plqi->sm_flags |= SM_ISTOPPED; - if ((plqi->sm_flags & WERROR_MODE) == 0) - (void) putnextctl(SM_WQ(plqi), msgtype); - } - break; - - case M_STOP: /* must never be queued */ - uqi->sm_flags |= SM_STOPPED; - noenable(wq); - for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) - if ((plqi->sm_flags & WERROR_MODE) == 0) - (void) putnextctl(SM_WQ(plqi), msgtype); - - rval = 1; - break; - - case M_START: /* never be queued */ - uqi->sm_flags &= ~SM_STOPPED; - enableok(wq); - qenable(wq); - for (plqi = uqi->sm_lqs; plqi != 0; plqi = plqi->sm_nlqi) - if ((plqi->sm_flags & WERROR_MODE) == 0) - (void) putnextctl(SM_WQ(plqi), msgtype); - - break; - - case M_PCSIG: - case M_COPYOUT: - case M_COPYIN: - case M_IOCACK: - case M_IOCNAK: - /* Wrong direction for message */ - break; - case M_READ: - break; - case M_PCPROTO: - case M_PCRSE: - default: - sm_dbg('I', ("sm_hp_uwput: default case %d.\n", msgtype)); - break; - } /* end switch on high pri message type */ - - freemsg(mp); - return (rval); -} - -static int -sm_default_uwioctl(queue_t *wq, mblk_t *mp, int (*qfn)()) -{ - int err; - struct iocblk *iobp; - sm_uqi_t *uqi; - - uqi = (sm_uqi_t *)(wq->q_ptr); - iobp = (struct iocblk *)mp->b_rptr; - - switch (iobp->ioc_cmd) { - case TIOCEXCL: - case TIOCNXCL: - case TIOCSTI: - /* - * The three ioctl types we support do not require any - * additional allocation and should not return a pending - * ioctl state. For this reason it is safe for us to ignore - * the return value from ttycommon_ioctl(). - * Additionally, we translate any error response from - * ttycommon_ioctl() into EINVAL. - */ - (void) ttycommon_ioctl(uqi->sm_ttycommon, wq, mp, &err); - if (err < 0) - miocnak(wq, mp, 0, EINVAL); - else - miocack(wq, mp, 0, 0); - return (0); - default: - break; - } - if ((err = sm_update_ttyinfo(mp, uqi)) != 0) { - miocnak(wq, mp, 0, err); - return (0); - } - - /* - * If uqi->sm_siocdata.sm_iocid just overwrite it since the stream - * head will have timed it out - */ - uqi->sm_siocdata.sm_iocid = iobp->ioc_id; - uqi->sm_siocdata.sm_acked = 0; - uqi->sm_siocdata.sm_nacks = sm_good_qs(uqi); - uqi->sm_siocdata.sm_acnt = 0; - uqi->sm_siocdata.sm_policy = uqi->sm_policy; - uqi->sm_siocdata.sm_flags = 0; - sm_dbg('Z', (" want %d acks for id %d.\n", - uqi->sm_siocdata.sm_nacks, iobp->ioc_id)); - - return (sm_putqs(wq, mp, qfn)); -} - -/* - * - * sm_uwput - put function for an upper STREAM write. - */ -static int -sm_uwput(queue_t *wq, mblk_t *mp) -{ - sm_uqi_t *uqi; - uchar_t msgtype; - int cmd; - struct iocblk *iobp; - - uqi = (sm_uqi_t *)(wq->q_ptr); - msgtype = DB_TYPE(mp); - - ASSERT(uqi != 0 && sm_ssp != 0); - - if (msgtype >= QPCTL && msgtype != M_IOCDATA) { - (void) sm_hp_uwput(wq, mp); - return (0); - } - - switch (DB_TYPE(mp)) { - case M_DATA: - case M_DELAY: - case M_BREAK: - default: - (void) sm_putqs(wq, mp, putq); - break; - - case M_CTL: - if (((struct iocblk *)mp->b_rptr)->ioc_cmd == MC_CANONQUERY) { - (void) putnextctl1(OTHERQ(wq), M_CTL, MC_NOCANON); - } - freemsg(mp); - break; - case M_IOCDATA: /* not handled as high pri because may need to putbq */ - sm_dbg('M', ("sm_uwput(M_IOCDATA)\n")); - /*FALLTHROUGH*/ - case M_IOCTL: - cmd = (msgtype == M_IOCDATA) ? - ((struct copyresp *)mp->b_rptr)->cp_cmd : - ((struct iocblk *)mp->b_rptr)->ioc_cmd; - - iobp = (struct iocblk *)mp->b_rptr; - iobp->ioc_rval = 0; - - sm_dbg('M', ("sm_uwput(M_IOCTL:%d)\n", cmd)); - - switch (cmd) { - - case CONSGETABORTENABLE: - iobp->ioc_error = ttymux_abort_ioctl(mp); - DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK; - qreply(wq, mp); - break; - case CONSSETABORTENABLE: - iobp->ioc_error = - secpolicy_sys_config(iobp->ioc_cr, B_FALSE) != 0 ? - EPERM : ttymux_abort_ioctl(mp); - DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK; - qreply(wq, mp); - break; - case TTYMUX_SETABORT: - if (secpolicy_sys_config(iobp->ioc_cr, B_FALSE) != 0) { - iobp->ioc_error = EPERM; - DB_TYPE(mp) = M_IOCNAK; - qreply(wq, mp); - break; - } - /*FALLTHROUGH*/ - case TTYMUX_GETABORT: - case TTYMUX_GETABORTSTR: - case TTYMUX_ASSOC: - case TTYMUX_DISASSOC: - case TTYMUX_SETCTL: - case TTYMUX_GETLINK: - case TTYMUX_CONSDEV: - case TTYMUX_GETCTL: - case TTYMUX_LIST: - (void) sm_ioctl_cmd(uqi, mp); - qreply(wq, mp); - break; - case I_LINK: - case I_PLINK: - case I_UNLINK: - case I_PUNLINK: - qwriter(wq, mp, sm_link_req, PERIM_OUTER); - break; - case TCSETSW: - case TCSETSF: - case TCSETAW: - case TCSETAF: - case TCSBRK: - if (wq->q_first) { - sm_dbg('A', ("sm_uwput: TCSET-> on srv q.\n")); - /* keep message order intact */ - (void) putq(wq, mp); - break; - } - /*FALLTHROUGH*/ - default: - (void) sm_default_uwioctl(wq, mp, putq); - break; - } - - break; /* M_IOCTL */ - - } /* end switch on message type */ - - return (0); -} - -/* - * sm_uwsrv - service function for an upper STREAM write. - * 'sm_uwsrv' takes a q parameter. The q parameter specifies the queue - * which is to be serviced. This function reads the messages which are on - * this service queue and passes them to the appropriate lower driver queue. - */ -static int -sm_uwsrv(queue_t *q) -{ - mblk_t *mp; - sm_uqi_t *uqi = (sm_uqi_t *)(q->q_ptr); - int msgtype; - - ASSERT(q == SM_WQ(uqi)); - - /* - * Empty the queue unless explicitly stopped. - */ - while (mp = getq(q)) { - msgtype = DB_TYPE(mp); - - if (msgtype >= QPCTL && msgtype != M_IOCDATA) - if (sm_hp_uwput(q, mp)) { - sm_dbg('T', ("sm_uwsrv: flowcontrolled.\n")); - break; /* indicates that the is disabled */ - } - else - continue; - - if (uqi->sm_flags & SM_STOPPED) { - (void) putbq(q, mp); - sm_dbg('T', ("sm_uwsrv: SM_STOPPED.\n")); - break; - } - - /* - * Read any ttycommon data that may - * change (TS_SOFTCAR, CREAD, etc.). - */ - switch (DB_TYPE(mp)) { - case M_IOCTL: - case M_IOCDATA: - if (sm_default_uwioctl(q, mp, putbq)) - return (0); - break; - - default: - if (sm_putqs(q, mp, putbq)) - return (0); - } - } - return (0); -} - -/* - * Lower write side service routine used for backenabling upstream - * flow control. - */ -static int -sm_lwsrv(queue_t *q) -{ - sm_lqi_t *lqi = (sm_lqi_t *)q->q_ptr; - queue_t *uwq; - - LOCK_UNIT(lqi); - if (lqi->sm_uqflags & SM_UQVALID) { - /* - * It's safe to lock uqi since lwsrv runs asynchronously - * with the upper write routines so this cannot be an - * upper half thread. While holding the lqi lock and - * if SM_UQVALID is set we are guaranteed that - * lqi->sm_uqi will be valid. - */ - sm_dbg('I', ("sm_lwsrv: re-enabling upper queue.\n")); - - uwq = SM_WQ(lqi->sm_uqi); - UNLOCK_UNIT(lqi); - qenable(uwq); - } else { - UNLOCK_UNIT(lqi); - } - return (0); -} - -/* - * Upper read queue ioctl response handler for messages - * passed from the lower half of the driver. - */ -static int -sm_uriocack(queue_t *rq, mblk_t *mp) -{ - sm_uqi_t *uqi = (sm_uqi_t *)rq->q_ptr; - int err, flag; - sm_iocdata_t *iodp; - struct sm_iocinfo info; - - if ((err = sm_getiocinfo(mp, &info)) != 0) { - sm_dbg('I', ("Unknown ioctl response\n")); - return (err); - } - - if (info.sm_id == uqi->sm_piocdata.sm_iocid) { - iodp = &uqi->sm_piocdata; - } else if (info.sm_id == uqi->sm_siocdata.sm_iocid) { - iodp = &uqi->sm_siocdata; - } else { - sm_log("Unexpected ioctl response\n"); - sm_dbg('I', ("Unexpected ioctl response (id %d)\n", - info.sm_id)); - - /* - * If the response is sent up it will result in - * duplicate ioctl responses. The ioctl has probably been - * timed out by the stream head so dispose of the response - * (since it has arrived too late. - */ - goto out; - } - - flag = SM_COPYIN; - - switch (DB_TYPE(mp)) { - case M_COPYOUT: - flag = SM_COPYOUT; - /*FALLTHRU*/ - case M_COPYIN: - if (iodp->sm_flags & flag) - goto out; - iodp->sm_flags |= flag; - - break; - case M_IOCACK: - iodp->sm_ackcnt += 1; - iodp->sm_acnt += 1; - if (iodp->sm_policy == FIRSTACK) { - if (iodp->sm_acnt == iodp->sm_nacks) - iodp->sm_iocid = 0; - if (iodp->sm_acnt == 1) - iodp->sm_acked = 1; - else - goto out; - } else { - if (iodp->sm_acnt == iodp->sm_nacks) { - iodp->sm_iocid = 0; - iodp->sm_acked = 1; - } else - goto out; - } - break; - case M_IOCNAK: - iodp->sm_nakcnt += 1; - iodp->sm_acnt += 1; - if (iodp->sm_acnt == iodp->sm_nacks) { - iodp->sm_iocid = 0; - if (iodp->sm_acked == 0) { - iodp->sm_acked = 1; - break; - } - } - goto out; - default: - goto out; - } - - /* - * Merge the tty settings each of the associated lower streams. - */ - if (info.sm_data) - (void) sm_update_ttyinfo(mp, uqi); - - if (iodp == &uqi->sm_piocdata) { - if (iodp->sm_iocid == 0) { - uqi->sm_flags &= ~SM_IOCPENDING; - } - } else { - sm_dbg('I', ("sm_uriocack: forwarding response for %d.\n", - info.sm_id)); - putnext(rq, mp); - return (0); - } -out: - sm_dbg('I', ("sm_uriocack: freeing response for %d.\n", info.sm_id)); - freemsg(mp); - return (0); -} - -/* - * Transfer a message from the lower read side of the multiplexer onto - * the associated upper stream. - */ -static int -sm_ursendup(queue_t *q, mblk_t *mp) -{ - sm_uqi_t *uqi = (sm_uqi_t *)q->q_ptr; - - if (!canputnext(q) && DB_TYPE(mp) < QPCTL) { - sm_dbg('I', ("sm_ursendup: flow controlled.\n")); - return (1); - } - - switch (DB_TYPE(mp)) { - case M_COPYIN: - case M_COPYOUT: - case M_IOCACK: - case M_IOCNAK: - (void) sm_uriocack(q, mp); - break; - case M_HANGUP: - if (sm_uwq_error(uqi)) { - /* there are no usable lower q's */ - uqi->sm_flags &= ~SM_CARON; - putnext(q, mp); - } else { - /* there are still usable q's - don't send up */ - freemsg(mp); - } - break; - case M_ERROR: - if (sm_uwq_error(uqi)) { - /* there are no usable lower q's */ - uqi->sm_flags &= ~SM_CARON; - putnext(q, mp); - } else if (*mp->b_rptr == NOERROR) { - /* the error has cleared */ - uqi->sm_flags &= ~ERROR_MODE; - putnext(q, mp); - } else { - /* there are still usable q's - don't send up */ - freemsg(mp); - } - break; - case M_FLUSH: - flushq(q, FLUSHDATA); - putnext(q, mp); /* time to use FLUSHR_PEND flag */ - break; - case M_CTL: - /* wrong direction - must have come from sm_close */ - uqi->sm_flags |= SM_CLOSE; - sm_dbg('I', ("sm_ursrv: had SM_CLOSE.\n")); - freemsg(mp); - break; - case M_UNHANGUP: - /* just pass them all up - they're harmless */ - uqi->sm_flags |= SM_CARON; - /* FALLTHROUGH */ - default: - putnext(q, mp); - break; - } - - return (0); -} - -/* - * sm_urput - put function for a lower STREAM read. - */ -static int -sm_urput(queue_t *q, mblk_t *mp) -{ - if (sm_ursendup(q, mp) != 0) - (void) putq(q, mp); - - return (0); -} - -/* - * Upper read side service routine. - * Read side needs to be fast so only check for duplicate M_IOCTL acks. - */ -static int -sm_ursrv(queue_t *q) -{ - sm_uqi_t *uqi = (sm_uqi_t *)q->q_ptr; - mblk_t *mp; - int flags = uqi->sm_flags; - - while ((mp = getq(q))) { - if (sm_ursendup(q, mp) != 0) { - sm_dbg('I', ("sm_ursrv: flow controlled.\n")); - (void) putbq(q, mp); - uqi->sm_flags |= WANT_RENB; - break; - } - } - - /* - * If the q service was called because it was no longer - * flow controled then enable each of the driver queues. - */ - if ((flags & WANT_RENB) && !(uqi->sm_flags & WANT_RENB)) { - sm_lqi_t *lqi; - queue_t *drq; /* read q of linked driver */ - - uqi->sm_flags &= ~WANT_RENB; - for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) { - drq = SM_RQ(lqi)->q_next; - if (drq && drq->q_first != 0) - qenable(drq); - } - } - - return (0); -} - -/* - * Check a message sent from a linked device for abort requests and - * for flow control. - */ -static int -sm_lrmsg_check(queue_t *q, mblk_t *mp) -{ - sm_lqi_t *lqi = (sm_lqi_t *)q->q_ptr; - - switch (DB_TYPE(mp)) { - case M_DATA: - LOCK_UNIT(lqi); - /* - * check for abort - only allow abort on I/O consoles - * known to OBP - - * fix it when we do polled io - */ - if ((lqi->sm_ioflag & (uint_t)FORINPUT) == 0) { - freemsg(mp); - UNLOCK_UNIT(lqi); - return (1); - } - if ((lqi->sm_uqflags & SM_OBPCNDEV) && - lqi->sm_ctrla_abort_on && - abort_enable == KIOCABORTALTERNATE) { - - uchar_t *rxc; - boolean_t aborted = B_FALSE; - - for (rxc = mp->b_rptr; - rxc != mp->b_wptr; - rxc++) - - if (*rxc == *lqi->sm_nachar) { - lqi->sm_nachar++; - if (*lqi->sm_nachar == '\0') { - abort_sequence_enter( - (char *)NULL); - lqi->sm_nachar = sm_ssp->sm_abs; - aborted = B_TRUE; - } - } else - lqi->sm_nachar = (*rxc == *sm_ssp-> - sm_abs) ? - sm_ssp-> - sm_abs + 1 : - sm_ssp->sm_abs; - - if (aborted) { - freemsg(mp); - UNLOCK_UNIT(lqi); - return (1); - } - } - UNLOCK_UNIT(lqi); - break; - case M_BREAK: /* we'll eventually see this as a flush */ - LOCK_UNIT(lqi); - /* - * Only allow abort on OBP devices. When polled I/O is - * supported allow abort on any console device. - * Parity errors are reported upstream as breaks so - * ensure that there is no data in the message before - * deciding whether to abort. - */ - if ((lqi->sm_uqflags & SM_OBPCNDEV) && /* console stream */ - (mp->b_wptr - mp->b_rptr == 0 && - msgdsize(mp) == 0)) { /* not due to parity */ - - if (lqi->sm_break_abort_on && - abort_enable != KIOCABORTALTERNATE) - abort_sequence_enter((char *)NULL); - - freemsg(mp); - UNLOCK_UNIT(lqi); - return (1); - } else { - UNLOCK_UNIT(lqi); - } - break; - default: - break; - } - - if (DB_TYPE(mp) >= QPCTL) - return (0); - - LOCK_UNIT(lqi); /* lock out the upper half */ - if ((lqi->sm_uqflags & SM_UQVALID) && SM_RQ(lqi->sm_uqi)) { - UNLOCK_UNIT(lqi); - if (!canput(SM_RQ(lqi->sm_uqi))) { - sm_dbg('I', ("sm_lrmsg_check: flow controlled.\n")); - (void) putq(q, mp); - return (1); - } - } else { - UNLOCK_UNIT(lqi); - } - - return (0); -} - -/* - * sm_sendup - deliver a message to the upper read side of the multiplexer - */ -static int -sm_sendup(queue_t *q, mblk_t *mp) -{ - sm_lqi_t *lqi = (sm_lqi_t *)q->q_ptr; - - if (sm_ssp == NULL) { - freemsg(mp); - return (0); - } - - /* - * Check for CD status change messages from driver. - * (Remark: this is an se driver thread running at soft interupt - * priority and the waiters are in user context). - */ - switch (DB_TYPE(mp)) { - case M_DATA: - case M_BREAK: /* we'll eventually see this as a flush */ - break; - - /* high priority messages */ - case M_IOCACK: - case M_IOCNAK: - if ((lqi->sm_flags & SM_IOCPENDING) && lqi->sm_piocid == - ((struct iocblk *)mp->b_rptr)->ioc_id) { - freemsg(mp); - lqi->sm_flags &= ~SM_IOCPENDING; - sm_issue_ioctl(lqi); - return (0); - } - break; - case M_UNHANGUP: - /* - * If the driver can send an M_UNHANGUP it must be able to - * accept messages from above (ie clear WERROR_MODE if set). - */ - sm_dbg('E', ("lrput: M_UNHANGUP\n")); - lqi->sm_mbits |= TIOCM_CD; - lqi->sm_flags &= ~(WERROR_MODE|HANGUP_MODE); - - break; - - case M_HANGUP: - sm_dbg('E', ("lrput: MHANGUP\n")); - lqi->sm_mbits &= ~TIOCM_CD; - lqi->sm_flags |= (WERROR_MODE|HANGUP_MODE); - break; - - case M_ERROR: - - sm_dbg('E', ("lrput: MERROR\n")); - /* - * Tell the driver to flush rd/wr queue if its read/write error. - * if its a read/write error flush rq/wq (type in first bytes). - */ - if ((mp->b_wptr - mp->b_rptr) == 2) { - uchar_t rw = 0; - - if (*mp->b_rptr == NOERROR) { - /* not in error anymore */ - lqi->sm_flags &= ~ERROR_MODE; - lqi->sm_flags |= WANT_CD; - } else { - if (*mp->b_rptr != 0) { - /* read error */ - rw |= FLUSHR; - lqi->sm_flags |= RERROR_MODE; - } - mp->b_rptr++; - if (*mp->b_rptr != 0) { - /* write error */ - rw |= FLUSHW; - lqi->sm_flags |= WERROR_MODE; - } - - mp->b_rptr--; - /* has next driver done qprocsoff */ - if (rw && OTHERQ(q)->q_next != NULL) { - (void) putnextctl1(OTHERQ(q), M_FLUSH, - rw); - } - } - } else if (*mp->b_rptr != 0 && OTHERQ(q)->q_next != NULL) { - sm_dbg('E', ("lrput: old style MERROR (?)\n")); - - lqi->sm_flags |= (RERROR_MODE | WERROR_MODE); - (void) putnextctl1(OTHERQ(q), M_FLUSH, FLUSHRW); - } - break; - - case M_PCSIG: - case M_SIG: - break; - case M_COPYOUT: - case M_COPYIN: - break; - case M_FLUSH: - /* flush the read queue and pass on up */ - flushq(q, FLUSHDATA); - break; - default: - break; - } - - LOCK_UNIT(lqi); /* lock out the upper half */ - if (lqi->sm_uqflags & SM_UQVALID && SM_RQ(lqi->sm_uqi)) { - UNLOCK_UNIT(lqi); - (void) putq(SM_RQ(lqi->sm_uqi), mp); - return (0); - } else { - sm_dbg('I', ("sm_sendup: uq not valid\n")); - freemsg(mp); - } - UNLOCK_UNIT(lqi); - - return (0); -} - -/* - * sm_lrput - put function for a lower STREAM read. - */ -static int -sm_lrput(queue_t *q, mblk_t *mp) -{ - if (sm_lrmsg_check(q, mp) == 0) - (void) sm_sendup(q, mp); - return (0); -} - -/* - * sm_lrsrv - service function for the lower read STREAM. - */ -static int -sm_lrsrv(queue_t *q) -{ - mblk_t *mp; - - sm_dbg('I', ("sm_lrsrv: not controlled.\n")); - while (mp = getq(q)) - (void) sm_sendup(q, mp); - - return (0); -} - -/* - * Check whether a thread is allowed to open the requested device. - */ -static int -sm_ok_to_open(sm_uqi_t *uqi, int protocol, cred_t *credp, int *abort_waiters) -{ - int rval = 0; - int proto; - - *abort_waiters = 0; - - switch (protocol) { - case ASYNC_DEVICE: /* Standard async protocol */ - if ((uqi->sm_protocol == NULL_PROTOCOL) || - (uqi->sm_protocol == ASYN_PROTOCOL)) { - /* - * Lock out other incompatible protocol requests. - */ - proto = ASYN_PROTOCOL; - rval = 0; - } else - rval = EBUSY; - break; - - case OUTLINE: /* Outdial protocol */ - if ((uqi->sm_protocol == NULL_PROTOCOL) || - (uqi->sm_protocol == OUTD_PROTOCOL)) { - proto = OUTD_PROTOCOL; - rval = 0; - } else if (uqi->sm_protocol == ASYN_PROTOCOL) { - /* - * check for dialout request on a line that is already - * open for dial in: - * kick off any thread that is waiting to fully open - */ - if (uqi->sm_flags & FULLY_OPEN) - rval = EBUSY; - else { - proto = OUTD_PROTOCOL; - *abort_waiters = 1; - } - } else - rval = EBUSY; - break; - default: - rval = ENOTSUP; - } - - if (rval == 0 && - (uqi->sm_ttycommon->t_flags & TS_XCLUDE) && - secpolicy_excl_open(credp) != 0) { - - if (uqi->sm_flags & FULLY_OPEN) { - rval = EBUSY; /* exclusive device already open */ - } else { - /* NB TS_XCLUDE cant be set during open so NOTREACHED */ - /* force any waiters to yield TS_XCLUDE */ - *abort_waiters = 1; - } - } - - if (rval == 0) - uqi->sm_protocol = proto; - - sm_dbg('A', ("ok_to_open (0x%p, %d) proto=%d rval %d (wabort=%d)", - uqi, protocol, uqi->sm_protocol, rval, *abort_waiters)); - - return (rval); -} - -/* wait for memory to become available whilst performing a qwait */ -/*ARGSUSED*/ -static void dummy_callback(void *arg) -{} - -/* ARGSUSED */ -static int -sm_dump_msg(queue_t *q, mblk_t *mp) -{ - freemsg(mp); - return (0); -} - -/* - * Wait for a message to arrive - must be called with exclusive - * access at the outer perimiter. - */ -static int -sm_qwait_sig(sm_uqi_t *uqi, queue_t *q) -{ - int err; - - sm_dbg('C', ("sm_qwait_sig: waiting.\n")); - - uqi->sm_waitq = q; - uqi->sm_nwaiters++; /* required by the close routine */ - err = qwait_sig(q); - if (--uqi->sm_nwaiters == 0) - uqi->sm_waitq = 0; - - if (err == 0) - err = EINTR; - else if (q->q_ptr == 0) /* can happen if there are multiple waiters */ - err = -1; - else if (uqi->sm_flags & SM_CLOSE) { - uqi->sm_flags &= ~SM_CLOSE; - err = 1; /* a different protocol has closed its stream */ - } - else - err = 0; /* was worth waiting for */ - - sm_dbg('C', ("sm_qwait_sig: rval %d\n", err)); - return (err); -} - -/* - * Defer the opening of one the drivers devices until the state of each - * associated lower stream is known. - */ -static int -sm_defer_open(sm_uqi_t *uqi, queue_t *q) -{ - uint_t cmdflags = WANT_CDSTAT; - int err, nqs; - - while ((nqs = sm_good_qs(uqi)) == 0) { - sm_dbg('C', ("sm_defer_open: no good qs\n")); - if (err = sm_qwait_sig(uqi, q)) - return (err); - } - - while ((uqi->sm_flags & SM_CARON) == 0) { - int iocmd; - mblk_t *pioc; - - sm_dbg('C', ("sm_defer_open: flags 0x%x cmdflags 0x%x\n", - uqi->sm_flags, cmdflags)); - if (cmdflags == 0) { - if (err = sm_qwait_sig(uqi, q)) - return (err); - continue; /* waiting for an M_UNHANGUP */ - } else if (cmdflags & WANT_SC) { - cmdflags &= ~WANT_SC; - iocmd = TIOCGSOFTCAR; - } else if (cmdflags & WANT_CD) { - cmdflags &= ~WANT_CD; - iocmd = TIOCMGET; - } else if (cmdflags & WANT_CL) { - cmdflags &= ~WANT_CL; - iocmd = TCGETS; - } - - if (uqi->sm_piocdata.sm_iocid == 0) { - while ((pioc = mkiocb(iocmd)) == 0) { - bufcall_id_t id = - qbufcall(q, sizeof (struct iocblk), - BPRI_MED, dummy_callback, 0); - if (err = sm_qwait_sig(uqi, q)) { - /* wait for the bufcall */ - qunbufcall(q, id); - return (err); - } - qunbufcall(q, id); - } - - uqi->sm_flags |= SM_IOCPENDING; - - uqi->sm_piocdata.sm_iocid = - ((struct iocblk *)pioc->b_rptr)->ioc_id; - uqi->sm_piocdata.sm_acked = 0; - uqi->sm_piocdata.sm_nacks = nqs; - uqi->sm_piocdata.sm_acnt = 0; - uqi->sm_piocdata.sm_ackcnt = uqi-> - sm_piocdata.sm_nakcnt = 0; - uqi->sm_piocdata.sm_policy = uqi->sm_policy; - uqi->sm_piocdata.sm_flags = SM_INTERNALIOC; - if (sm_putqs(WR(q), pioc, sm_dump_msg) != 0) { - uqi->sm_piocdata.sm_iocid = 0; - sm_log("sm_defer_open: bad putqs\n"); - return (-1); - } - } - - sm_dbg('C', ("sm_defer_open: flags 0x%x\n", uqi->sm_flags)); - while ((uqi->sm_flags & SM_CARON) == 0 && - (uqi->sm_flags & SM_IOCPENDING) != 0) - if (err = sm_qwait_sig(uqi, q)) - return (err); - - sm_dbg('C', ("defer_open: uq flags 0x%x.\n", uqi->sm_flags)); - } - sm_dbg('C', ("defer_open: return 0.\n")); - return (0); -} - -static int -sm_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp) -{ - int ftstat; - int unit; - int protocol; - sm_uqi_t *uqi; - int abort_waiters; - - if (sm_ssp == NULL) - return (ENXIO); - /* - * sflag = 0 => streams device. - */ - if (sflag != 0 || DEV_TO_UNIT(*devp) >= NLUNITS) { - sm_dbg('C', ("open: sflag=%d or bad dev_t.\n", sflag)); - return (ENXIO); - } - - unit = DEV_TO_UNIT(*devp); - protocol = DEV_TO_PROTOBITS(*devp); - - uqi = get_uqi(sm_ssp, unit); - - sm_dbg('C', ("open(0x%p, %d, 0x%x) :- unit=%d, proto=%d, uqi=0x%p\n", - rq, *devp, flag, unit, protocol, uqi)); - - if (uqi == 0) - return (ENXIO); - - if (sm_refuse_opens && unit > smctlunit && uqi->sm_nlqs == 0) - return (ENXIO); - - if (uqi->sm_flags & EXCL_OPEN && (flag & FEXCL)) { - return (EBUSY); /* device in use */ - } - - if ((flag & FEXCL)) { - if (secpolicy_excl_open(credp) != 0) - return (EPERM); - - if ((uqi->sm_flags & FULLY_OPEN) || uqi->sm_nwaiters > 0) - return (EBUSY); /* device in use */ - - uqi->sm_flags |= EXCL_OPEN; - } - - if (uqi->sm_protocol == NULL_PROTOCOL) { - struct termios *termiosp; - int len; - - if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), - DDI_PROP_NOTPROM, "ttymodes", (caddr_t)&termiosp, &len) - == DDI_PROP_SUCCESS && - (len == sizeof (struct termios))) { - - sm_dbg('C', ("open: c_cflag=0x%x\n", - termiosp->c_cflag)); - - uqi->sm_ttycommon->t_iflag = termiosp->c_iflag; - uqi->sm_ttycommon->t_cflag = termiosp->c_cflag; - uqi->sm_ttycommon->t_stopc = termiosp->c_cc[VSTOP]; - uqi->sm_ttycommon->t_startc = termiosp->c_cc[VSTART]; - - /* - * IGNBRK,BRKINT,INPCK,IXON,IXANY,IXOFF - drivers - * PARMRK,IGNPAR,ISTRIP - how to report parity - * INLCR,IGNCR,ICRNL,IUCLC - ldterm (sophisticated I/O) - * IXON, IXANY, IXOFF - flow control input - * CBAUD,CSIZE,CS5-8,CSTOPB,PARENB,PARODD,HUPCL, - * RCV1EN,XMT1EN,LOBLK,XCLUDE,CRTSXOFF,CRTSCTS, - * CIBAUD,PAREXT,CBAUDEXT,CIBAUDEXT,CREAD,CLOCAL - */ - - kmem_free(termiosp, len); - } - else - bzero((caddr_t)uqi->sm_ttycommon, - sizeof (uqi->sm_ttycommon)); - - if (*devp == rconsdev) { - uqi->sm_cmask = sm_cmask; - uqi->sm_ttycommon->t_flags |= TS_SOFTCAR; - } else { - uqi->sm_ttycommon->t_flags &= ~TS_SOFTCAR; - } - - /* - * Clear the default CLOCAL and TS_SOFTCAR flags since - * they must correspond to the settings on the real devices. - */ - - uqi->sm_ttycommon->t_cflag &= ~(uqi->sm_cmask|CLOCAL); - uqi->sm_mbits = 0; - uqi->sm_policy = FIRSTACK; - if (unit == 0 && sm_ssp->sm_ms == 0) - sm_ssp->sm_ms = (sm_mux_state_t *) - space_fetch(TTYMUXPTR); - if (sm_ssp->sm_ms) { - if (sm_ssp->sm_ms->sm_cons_stdin.sm_dev == *devp || - sm_ssp->sm_ms->sm_cons_stdout.sm_dev == *devp) - sm_ssp->sm_lconsole = uqi; - } - } - - /* - * Does this thread need to wait? - */ - - sm_dbg('C', ("sm_open: %d %d 0x%p 0x%x\n", - !(flag & (FNDELAY|FNONBLOCK)), !(protocol == OUTLINE), uqi->sm_lqs, - uqi->sm_flags)); - -tryopen: - - abort_waiters = 0; - if (ftstat = sm_ok_to_open(uqi, protocol, credp, &abort_waiters)) { - sm_dbg('C', ("open failed stat=%d.\n", ftstat)); - - if ((uqi->sm_flags & FULLY_OPEN) == 0 && uqi->sm_nwaiters == 0) - uqi->sm_protocol = NULL_PROTOCOL; - if (flag & FEXCL) - uqi->sm_flags &= ~EXCL_OPEN; - return (ftstat); - } - - if (abort_waiters) { - uqi->sm_dev = *devp; - /* different device wants to use the unit */ - SM_RQ(uqi) = rq; - SM_WQ(uqi) = WR(rq); - } - if (rq->q_ptr == 0) { - sm_lqi_t *lqi; - - uqi->sm_dev = *devp; - rq->q_ptr = WR(rq)->q_ptr = uqi; - SM_RQ(uqi) = rq; - SM_WQ(uqi) = WR(rq); - qprocson(rq); - for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) { - LOCK_UNIT(lqi); - lqi->sm_uqflags |= SM_UQVALID; - UNLOCK_UNIT(lqi); - } - - sm_dbg('C', ("sm_open: SM_UQVALID set on lqs.\n")); - } - - if (*devp != rconsdev && BLOCKING(uqi, protocol, flag)) { - - uqi->sm_flags |= WANT_CDSTAT; - - do { - /* - * Wait for notifications of changes in the CLOCAL - * and TS_SOFTCAR flags and a TIOCM_CD flag of a - * TIOCMGET request (come in on the write side queue). - */ - - if ((ftstat = sm_defer_open(uqi, rq)) != EINTR) { - if (ftstat) { - goto tryopen; - } else { - continue; - } - } - - if (uqi->sm_nwaiters == 0) { /* clean up */ - /* - * only opens on an asynchronous - * protocols reach here so checking - * nwaiters == 0 is sufficient to - * ensure that no other thread - * is waiting on this logical unit - */ - if ((uqi->sm_flags & FULLY_OPEN) == 0) { - - sm_lqi_t *lqi; - - uqi->sm_dev = NODEV; - sm_dbg('C', ("sm_open FULLY_OPEN=0\n")); - for (lqi = uqi->sm_lqs; lqi != 0; - lqi = lqi->sm_nlqi) { - LOCK_UNIT(lqi); - lqi->sm_uqflags &= ~SM_UQVALID; - UNLOCK_UNIT(lqi); - } - - qprocsoff(rq); - rq->q_ptr = WR(rq)->q_ptr = 0; - SM_RQ(uqi) = 0; - SM_WQ(uqi) = 0; - } - } - if ((uqi->sm_flags & FULLY_OPEN) == 0 && - uqi->sm_nwaiters == 0) - uqi->sm_protocol = NULL_PROTOCOL; - if (flag & FEXCL) - uqi->sm_flags &= ~EXCL_OPEN; - sm_dbg('C', ("sm_open: done (ret %d).\n", ftstat)); - return (ftstat); - } while (BLOCKING(uqi, protocol, flag)); - } - - uqi->sm_flags |= FULLY_OPEN; - - sm_dbg('C', ("sm_open done (ret %d).\n", ftstat)); - return (ftstat); -} - -/* - * Multiplexer device close routine. - */ -/*ARGSUSED*/ -static int -sm_close(queue_t *rq, int flag, cred_t *credp) -{ - sm_uqi_t *uqi = (sm_uqi_t *)rq->q_ptr; - sm_lqi_t *lqi; - - if (sm_ssp == NULL) - return (ENXIO); - - if (uqi == NULL) { - sm_dbg('C', ("close: WARN:- q 0x%p already closed.\n", rq)); - return (ENXIO); - } - - sm_dbg('C', ("close: uqi=0x%p unit=%d q=0x%p)\n", uqi, uqi->sm_lunit, - rq)); - - if (SM_RQ(uqi) != rq) - sm_dbg('C', ("sm_close: rq != current uqi queue\n")); - - if (uqi->sm_ttybid) { - qunbufcall(SM_RQ(uqi), uqi->sm_ttybid); - uqi->sm_ttybid = 0; - } - - /* - * Tell all the linked queues that the upper queue has gone - * Note close will never get called on a stream while there is a - * thread blocked trying to open the same stream. - * If there is a blocked open on a different stream but on - * the same logical unit it will reset the lower queue flags. - */ - for (lqi = uqi->sm_lqs; lqi != 0; lqi = lqi->sm_nlqi) { - LOCK_UNIT(lqi); - lqi->sm_uqflags &= ~SM_UQVALID; - UNLOCK_UNIT(lqi); - } - - /* - * Turn off the STREAMs queue processing for this queue. - */ - qprocsoff(rq); - - /* - * Similarly we will never get here if there is thread trying to - * open ths stream. - */ - LOCK_UNIT(uqi); - if (uqi->sm_waitq == 0) - uqi->sm_flags = (uqi->sm_flags & SM_OBPCNDEV) ? SM_OBPCNDEV : - 0U; - - uqi->sm_dev = NODEV; - uqi->sm_protocol = NULL_PROTOCOL; - ttycommon_close(uqi->sm_ttycommon); - /* it just frees any pending ioctl */ - - uqi->sm_ttycommon->t_cflag = 0; - uqi->sm_ttycommon->t_flags = 0; - - /* - * Reset the queue pointers to NULL. - * If a thread is qwaiting in the open routine it will recheck - * the q_ptr. - */ - rq->q_ptr = NULL; - WR(rq)->q_ptr = NULL; - UNLOCK_UNIT(uqi); - - if (sm_ssp->sm_lconsole == uqi) { - /* this will never be the outdial device closing */ - sm_ssp->sm_lconsole = 0; - } - /* - * If there is another thread waiting for this close then unblock - * the thread by putting a message on its read queue. - */ - if (uqi->sm_waitq) { - sm_dbg('C', ("close(0x%p): doing putctl on 0x%p\n", - rq, uqi->sm_waitq)); - if (rq == uqi->sm_waitq) - sm_log("close: waitq and closeq are same q\n"); - (void) putctl(uqi->sm_waitq, M_CTL); - } - - uqi->sm_flags &= ~(EXCL_OPEN | FULLY_OPEN); - sm_dbg('C', ("close: returning ok.\n")); - return (0); -} - -/* - * Initialise the software abort sequence for use when one of the - * driver's nodes provides the system console. - */ -static void -sm_set_abort() -{ - char ds[3] = { '\r', '~', CNTRL('b') }; - char as[SM_MAX_ABSLEN]; - int len = SM_MAX_ABSLEN; - - if (ddi_prop_op(DDI_DEV_T_ANY, sm_ssp->sm_dip, PROP_LEN_AND_VAL_BUF, 0, - "abort-str", as, &len) != DDI_PROP_SUCCESS || - (len = strlen(as)) < SM_MIN_ABSLEN) { - (void) strcpy(as, ds); - len = strlen(as); - } else { - char *s; - int i; - - for (s = as, i = 0; i < len-1; i++, s++) { - if (as[i] == '^' && as[i+1] >= 'a' && as[i+1] <= 'z') { - *s = as[i+1] - 'a' + 1; - i++; - } else { - *s = as[i]; - } - } - *s++ = as[i]; - *s = '\0'; - len = strlen(as); - } - - if (len < SM_MIN_ABSLEN) - (void) strcpy(sm_ssp->sm_abs, ds); - else - (void) strcpy(sm_ssp->sm_abs, as); -} - -/* - * - * sm_attach - initialisation routine per driver instance. - */ -static int -sm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int unit; - char name[32]; - sm_uqi_t *uqi; - sm_lqi_t *lqip; - - /* - * Is this an attach? - */ - if (cmd != DDI_ATTACH) { - return (DDI_FAILURE); - } - - /* - * Validate the instance number (sm is a single instance driver). - */ - if (sm_ssp) { /* only one instance allowed */ - return (DDI_FAILURE); - } - - sm_instance = ddi_get_instance(dip); - - /* - * Create the default minor node which will become the console. - * (create it with three different names).: - * con which appears in the /dev filesystem; - * input which matches the prom /multiplexer:input node; - * output which matches the prom /multiplexer:input node - * Create a minor node for control operations. - */ - if (ddi_create_minor_node(dip, "con", S_IFCHR, 0, - DDI_PSEUDO, 0) != DDI_SUCCESS || - ddi_create_minor_node(dip, "input", S_IFCHR, 0, - DDI_PSEUDO, 0) != DDI_SUCCESS || - ddi_create_minor_node(dip, "output", S_IFCHR, 0, - DDI_PSEUDO, 0) != DDI_SUCCESS || - ddi_create_minor_node(dip, "ctl", S_IFCHR, 1, - DDI_PSEUDO, 0) != DDI_SUCCESS) { - - cmn_err(CE_WARN, "sm_attach: create minors failed.\n"); - ddi_remove_minor_node(dip, NULL); - return (DDI_FAILURE); - } - - smctlunit = 1; - - /* - * Allocate private state for this instance. - */ - sm_ssp = (sm_ss_t *)kmem_zalloc(sizeof (sm_ss_t), KM_SLEEP); - - /* - * Initialise per instance data. - */ - sm_ssp->sm_dip = dip; - - /* - * Get required debug level. - */ - sm_ssp->sm_trflag = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "sm-trlv", sm_default_trflag); - - sm_max_units = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "sm-max-units", sm_max_units); - sm_minor_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "sm-minor-cnt", 0); - - sm_refuse_opens = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "sm-refuse-opens", sm_refuse_opens); - - sm_ssp->sm_ctrla_abort_on = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "sm-ctrla-abort-on", 1); - sm_ssp->sm_break_abort_on = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "sm-break-abort-on", 0); - - sm_set_abort(); - - sm_ssp->sm_lqs = (sm_lqi_t *)kmem_zalloc(sizeof (sm_lqi_t) * MAX_LQS, - KM_SLEEP); - sm_ssp->sm_uqs = (sm_uqi_t *)kmem_zalloc(sizeof (sm_uqi_t) * NLUNITS, - KM_SLEEP); - - for (unit = 2; unit < NLUNITS && unit < sm_minor_cnt + 2; unit++) { - - if (snprintf(name, sizeof (name), "sm%c", 'a' + unit-2) > - sizeof (name)) { - cmn_err(CE_WARN, - "sm_attach: create device for unit %d failed.\n", - unit); - } else if (ddi_create_minor_node(dip, name, S_IFCHR, - unit, DDI_NT_SERIAL, NULL) != DDI_SUCCESS) { - ddi_remove_minor_node(dip, NULL); - return (DDI_FAILURE); - } - - if (snprintf(name, sizeof (name), "sm%c,cu", 'a' + unit-2) > - sizeof (name)) { - cmn_err(CE_WARN, - "sm_attach: create cu device for unit %d failed.\n", - unit); - continue; - } else if (ddi_create_minor_node(dip, name, S_IFCHR, - unit|OUTLINE, DDI_NT_SERIAL_DO, NULL) != DDI_SUCCESS) { - ddi_remove_minor_node(dip, NULL); - return (DDI_FAILURE); - } - } - - for (unit = 0; unit < NLUNITS; unit++) { - - uqi = get_uqi(sm_ssp, unit); - uqi->sm_lqs = 0; - uqi->sm_dev = NODEV; - uqi->sm_nlqs = 0; - uqi->sm_lunit = unit; - uqi->sm_protocol = NULL_PROTOCOL; - mutex_init(uqi->sm_umutex, NULL, MUTEX_DRIVER, NULL); - cv_init(uqi->sm_ucv, NULL, CV_DRIVER, NULL); - mutex_init(&uqi->sm_ttycommon->t_excl, NULL, - MUTEX_DRIVER, NULL); - } - - for (unit = 0; unit < MAX_LQS; unit++) { - lqip = get_lqi(sm_ssp, unit); - lqip->sm_unit = unit; - lqip->sm_hadkadbchar = 0; - lqip->sm_nachar = sm_ssp->sm_abs; - lqip->sm_ioflag = FORIO; - lqip->sm_ctrla_abort_on = sm_ssp->sm_ctrla_abort_on; - lqip->sm_break_abort_on = sm_ssp->sm_break_abort_on; - mutex_init(lqip->sm_umutex, NULL, MUTEX_DRIVER, NULL); - cv_init(lqip->sm_ucv, NULL, CV_DRIVER, NULL); - mutex_init(&lqip->sm_ttycommon->t_excl, NULL, - MUTEX_DRIVER, NULL); - } - - return (DDI_SUCCESS); -} - -/* - * - * sm_detach - detach routine per driver instance. - */ -static int -sm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - sm_uqi_t *lu; - sm_lqi_t *pu; - int unit; - - /* - * Is this a detach request for instance 0 (single instance driver). - */ - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - - if (sm_ssp == NULL) - return (DDI_FAILURE); - - sm_dbg('V', ("detach ...")); - - - /* - * Check that all the upper and lower queues are closed. - */ - - for (unit = 0; unit < NLUNITS; unit++) { - lu = &sm_ssp->sm_uqs[unit]; - if (lu && lu->sm_protocol != NULL_PROTOCOL) { - sm_dbg('V', ("detach: upper unit still open.\n")); - return (DDI_FAILURE); - } - } - for (unit = 0; unit < MAX_LQS; unit++) { - pu = &sm_ssp->sm_lqs[unit]; - if (pu && pu->sm_linkid != 0) { - sm_dbg('V', ("detach: lower unit still linked (%d)\n", - pu->sm_linkid)); - return (DDI_FAILURE); - } - } - - for (unit = 0; unit < NLUNITS; unit++) { - lu = &sm_ssp->sm_uqs[unit]; - mutex_destroy(lu->sm_umutex); - cv_destroy(lu->sm_ucv); - mutex_destroy(&lu->sm_ttycommon->t_excl); - } - for (unit = 0; unit < MAX_LQS; unit++) { - pu = &sm_ssp->sm_lqs[unit]; - mutex_destroy(pu->sm_umutex); - cv_destroy(pu->sm_ucv); - mutex_destroy(&pu->sm_ttycommon->t_excl); - } - - /* - * Tidy up per instance state. - */ - kmem_free(sm_ssp->sm_lqs, sizeof (sm_lqi_t) * MAX_LQS); - kmem_free(sm_ssp->sm_uqs, sizeof (sm_uqi_t) * NLUNITS); - kmem_free(sm_ssp, sizeof (sm_ss_t)); - - sm_ssp = 0; - - /* - * Remove all of the devices created in attach. - */ - ddi_remove_minor_node(dip, NULL); - - return (DDI_SUCCESS); -} - -/* - * SECTION - * Driver interface to the OS. - */ - -/* - * The driver is responsible for managing the mapping between the file system - * device types (major/minor pairs) and the corresponding instance of the driver - * or device information pointer (dip). - * sm_info - return the instance or dip corresponding to the dev_t. - */ -/*ARGSUSED*/ -static int -sm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - int res = DDI_SUCCESS; - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if (sm_ssp == NULL) - res = DDI_FAILURE; - else - *result = (void *)sm_ssp->sm_dip; - break; - - case DDI_INFO_DEVT2INSTANCE: - *result = (void*)0; /* single instance driver */ - break; - - default: - res = DDI_FAILURE; - break; - } - - return (res); -} - -/* - * End of driver implementation - */ - -/* - * Loadable module interface to the kernel - */ - -/* - * Firstly the Streams specific interface - */ - -/* - * Solaris driver/STREAM initialisation structures. - */ -static struct module_info uinfo = -{ - SM_MOD_ID, - TTYMUX_DRVNAME, - 0, /* min packet size */ - INFPSZ, /* max packet size */ - 2048, /* high water mark */ - 256, /* low water mark */ -}; - -/* - * Use zero water marks becuase the lower queues are used only for flow control. - */ -static struct module_info linfo = -{ - SM_MOD_ID, - TTYMUX_DRVNAME, - 0, /* min packet size */ - INFPSZ, /* max packet size */ - 0, /* high water mark */ - 0 /* low water mark */ -}; - - -/* - * Solaris upper read STREAM initialisation structure. - */ -static struct qinit urinit = -{ - sm_urput, /* put */ - sm_ursrv, /* service */ - sm_open, /* open */ - sm_close, /* close */ - NULL, /* admin */ - &uinfo, /* module info */ - NULL /* stats */ -}; - -/* - * Solaris upper write STREAM initialisation structure. - */ -static struct qinit uwinit = -{ - sm_uwput, - sm_uwsrv, - NULL, - NULL, - NULL, - &uinfo, - NULL -}; - -/* - * Solaris lower read STREAM initialisation structure. - */ -static struct qinit lrinit = -{ - sm_lrput, - sm_lrsrv, - NULL, - NULL, NULL, - &linfo, - NULL -}; - -/* - * Solaris lower write STREAM initialisation structure. - */ -static struct qinit lwinit = -{ - putq, - sm_lwsrv, - NULL, - NULL, - NULL, - &linfo, - NULL -}; - -/* - * Multiplexing STREAM structure. - */ -struct streamtab sm_streamtab = -{ - &urinit, - &uwinit, - &lrinit, - &lwinit -}; - -/* - * Driver operations structure (struct cb_ops) and - * driver dynamic loading functions (struct dev_ops). - */ - -/* - * Fold the Stream interface to the kernel into the driver interface - * to the OS. - */ - -DDI_DEFINE_STREAM_OPS(sm_ops, \ - nulldev, nulldev, \ - sm_attach, sm_detach, nodev, \ - sm_info, (D_NEW | D_MTQPAIR|D_MTOUTPERIM|D_MTOCEXCL | D_MP), - &sm_streamtab, ddi_quiesce_not_supported); - -/* - * Driver module information. - */ -extern struct mod_ops mod_driverops; -static struct modldrv modldrv = -{ - &mod_driverops, - "serial mux driver", - &sm_ops -}; - -static struct modlinkage modlinkage = -{ - MODREV_1, - &modldrv, - NULL -}; - -/* - * Define the body of our interface to the OS. - */ - -/* - * '_init' is called by Solaris to initialise any driver - * specific state and to install the driver. - */ -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -/* - * _info - return this drivers interface to the kernel. - */ -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* - * _fini - the OS is finished with the services provided by the driver. - * remove ourself and then remove any footprint that remains. - */ -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} diff --git a/usr/src/uts/sun/io/ttymux/ttymux_impl.h b/usr/src/uts/sun/io/ttymux/ttymux_impl.h deleted file mode 100644 index d0a44e81f5..0000000000 --- a/usr/src/uts/sun/io/ttymux/ttymux_impl.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _TTYMUX_IMPL_H -#define _TTYMUX_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types32.h> -#include <sys/param.h> - -/* - * Local definitions. - */ -#define SM_TRBIT(code) (1 << (code)-'@') - -extern uint_t sm_max_units; - -#define MAX_LQS (sm_max_units) -#define NLUNITS (MAX_LQS + 2) - -/* - * Re-use minor device encoding used by the se(7D) driver. - */ -#define ASYNC_DEVICE (0) -#define OUTLINE (1 << (NBITSMINOR32 - 1)) -#define NULL_PROTOCOL 0 -#define ASYN_PROTOCOL 1 -#define OUTD_PROTOCOL 2 - -#define DEV_TO_UNIT(dev) (getminor(dev) & ~OUTLINE) -#define DEV_TO_PROTOBITS(dev) (getminor(dev) & OUTLINE) - -/* - * Driver id - */ -#define SM_MOD_ID 0x534d - -/* - * Access modes of the two halves to each others flags - * Q uq->flags lq->flags - * uq rw r - * lq - rw - */ -/* - * A lower queue is associated with an upper queue - * (used for synchronising dissasociate reqests with the lower half) - * A lower q will not forward messages if SM_UQVALID is set in uqflags. - */ -#define SM_UQVALID (0x1) /* written by an upper q read by a lower q */ -#define SM_OBPCNDEV (0x2) /* set when this device is an OBP console */ - -/* - * unused flags - */ -#define FLUSHR_PEND (0x1) /* M_FLUSH is expected on all the lr q's */ - -/* - * An open has completed on this stream. - */ -#define FULLY_OPEN (0x2) -#define EXCL_OPEN (0x4) - -#define SM_CARON (0x8) -/* - * Flags to disable queues controlled from below. - */ -#define HANGUP_MODE (0x10) /* not used (sets WERROR_MODE instead) */ -#define RERROR_MODE (0x20) /* read error on stream (unset by closing) */ -#define WERROR_MODE (0x40) /* write side error on the stream (set by */ - /* M_HANGUP/M_ERROR */ - /* unset by M_UNHANGUP/M_ERROR) */ -#define ERROR_MODE (0x60) /* read error on stream (unset by M_ERROR) */ - -/* - * Flags to disable queues controlled from above. - * Also used by set on queues which are OBP consoles - */ -#define SM_STOPPED (0x080) /* M_STOP has been seen */ -#define SM_ISTOPPED (0x100) /* M_STOPI has been seen */ - -/* - * A stream wants something. - */ -#define WANT_SC (0x200) /* carrier status of a stream required */ -#define WANT_CL (0x400) /* CLOCAL status of a stream required */ -#define WANT_CD (0x800) /* CD modem status of a line required */ -#define WANT_CDSTAT (0xe00) -#define WANT_TCSET (0x20000) /* send down initial termios settings */ - -#define WANT_RENB (0x40000) /* read q is flowcontrolled */ - -#define SM_IOCPENDING (0x80000) -#define SM_CLOSE (0x100000) -#define SM_INTERNALIOC (0x200000) - -#define SM_LOGINREQ (0x400000) - -#define LOCK_UNIT(u) (mutex_enter(u->sm_umutex)) /* Lock per-stream data */ -#define UNLOCK_UNIT(u) (mutex_exit(u->sm_umutex)) /* Unlock per-stream data */ - -/* - * Checks whether an open could potentially block. - */ -#define BLOCKING(unitp, proto, flag) \ - (!(flag & (FNDELAY|FNONBLOCK)) && \ - !(proto == OUTLINE) && \ - unitp->sm_lqs && \ - (unitp->sm_flags & SM_CARON) == 0) - -/* - * Update termios style control flag with a termio style flag. - */ -#define SM_SETCFLAG(qi, tc) \ - qi->sm_ttycommon->t_cflag = \ - (qi->sm_ttycommon->t_cflag & 0xffff0000 | (tc)->c_cflag) -#define SM_SETLFLAG(qi, tc) \ - qi->sm_ttycommon->t_iflag = \ - (qi->sm_ttycommon->t_iflag & 0xffff0000 | (tc)->c_iflag) - -#define SM_WQ(qi) (qi->sm_ttycommon->t_writeq) -#define SM_RQ(qi) (qi->sm_ttycommon->t_readq) - -/* - * - */ -struct sm_iocinfo { - int sm_id; - int sm_cmd; - void *sm_data; -}; - -/* - * Perform a per instance search for a specified per stream structure. - */ -#define get_lqi(ssp, unit) \ - ((unit < MAX_LQS) ? &ssp->sm_lqs[unit] : 0) - -#define get_uqi(ssp, unit) \ - ((unit < NLUNITS) ? &ssp->sm_uqs[unit] : NULL) - -#define CNTRL(c) ((c)&037) - -#define sm_allocb(size, pri) allocb(size, pri) -#define sm_copymsg(mp) ((DB_TYPE(mp) == M_DATA) ? dupmsg(mp) : copymsg(mp)) -#define sm_freemsg(mp) freemsg(mp) - -/* - * macro to improve performance. The cond is checked before deciding whether - * to create a new stack frame for the debug call - * Calls to sm_dbg should not occur in hanging statements - alternatively - * bracket SM_CMD with a do .... while (0) - */ - -#define SM_CMD(cond, stmt) { if (cond) stmt; } -#define sm_dbg(lvl, args) SM_CMD(sm_ssp->sm_trflag & SM_TRBIT(lvl), \ - sm_debug args) - -#define SM_SLOT_RED 3 -#define SM_MAX_SLOT_WAIT 3 - -#define sm_dev2unit(dev) (getminor(dev) & ~OUTLINE) - -#define LQI2ASSOC(a, l) \ - (a)->ttymux_linkid = (l)->sm_linkid; \ - (a)->ttymux_tag = (l)->sm_tag; \ - (a)->ttymux_ioflag = (l)->sm_ioflag; \ - (a)->ttymux_ldev = (l)->sm_dev; \ - (a)->ttymux_udev = ((l)->sm_uqi == 0) ? NODEV : \ - makedevice(ddi_driver_major(sm_ssp->sm_dip), \ - (l)->sm_uqi->sm_lunit); \ - (void) strncpy((a)->ttymux_path, (l)->sm_path, MAXPATHLEN) - -#define LQI2ASSOC32(a, l) \ - (a)->ttymux32_linkid = (l)->sm_linkid; \ - (a)->ttymux32_tag = (uint32_t)(l)->sm_tag; \ - (a)->ttymux32_ioflag = (l)->sm_ioflag; \ - (void) cmpldev(&(a)->ttymux32_ldev, (l)->sm_dev);\ - (a)->ttymux32_udev = ((l)->sm_uqi == 0) ? NODEV32 : \ - ((void) cmpldev(&(a)->ttymux32_udev, \ - makedevice(ddi_driver_major(sm_ssp->sm_dip), \ - (l)->sm_uqi->sm_lunit)), \ - (a)->ttymux32_udev); \ - (void) strncpy((a)->ttymux32_path, (l)->sm_path, MAXPATHLEN) - -#define CNTRL(c) ((c)&037) - -/* - * 32 bit eqivalents of structures defined in sys/ttymuxuser.h - */ -typedef struct ttymux_association32 { - - dev32_t ttymux32_udev; /* the upper device to be associated */ - dev32_t ttymux32_ldev; - /* the device type of a linked lower stream */ - int ttymux32_linkid; - /* the linkid of a linked lower stream */ - uint32_t ttymux32_tag; /* tagged association */ - uint_t ttymux32_ioflag; /* FORINPUT FOROUTPUT FORIO */ - char ttymux32_path[MAXPATHLEN]; /* device path */ -} ttymux_assoc32_t; - -typedef struct ttymux_associations32 { - uint32_t ttymux32_nlinks; - caddr32_t ttymux32_assocs; -} ttymux_assocs32_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _TTYMUX_IMPL_H */ diff --git a/usr/src/uts/sun/io/ttymux/ttymux_ioctl.c b/usr/src/uts/sun/io/ttymux/ttymux_ioctl.c deleted file mode 100644 index dd03a8a842..0000000000 --- a/usr/src/uts/sun/io/ttymux/ttymux_ioctl.c +++ /dev/null @@ -1,1358 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * DESCRIPTION - * - * ttymux_ioctl - Handler for ttymux specific ioctl calls. - * - */ - -#include <sys/types.h> -#include <sys/strsubr.h> -#include <sys/strsun.h> -#include <sys/errno.h> -#include <sys/stat.h> -#include <sys/kmem.h> -#include <sys/ddi.h> -#include <sys/termio.h> -#include <sys/mkdev.h> -#include <sys/sunddi.h> -#include <sys/esunddi.h> -#include <sys/consdev.h> -#include <sys/promif.h> - -#include <sys/ttymux.h> -#include "ttymux_impl.h" - -/* - * Extern declarations - */ -extern mblk_t *mkiocb(uint_t); -extern int nulldev(); -extern uintptr_t space_fetch(char *key); -extern void prom_interpret(char *, uintptr_t, uintptr_t, uintptr_t, - uintptr_t, uintptr_t); - -/* - * Imported ttymux routines - */ -extern void sm_debug(char *, ...); -extern void sm_log(char *, ...); -extern sm_lqi_t *get_lqi_byid(int); -extern sm_lqi_t *get_lqi_bydevt(dev_t); -extern int sm_associate(int, sm_lqi_t *, ulong_t, uint_t, char *); -extern int sm_disassociate(int, sm_lqi_t *, ulong_t); - -/* - * Exported ttymux routines - */ -int ttymux_abort_ioctl(mblk_t *); -int ttymux_device_init(sm_lqi_t *); -int ttymux_device_fini(sm_lqi_t *); -int sm_ioctl_cmd(sm_uqi_t *, mblk_t *); - -/* - * Imported ttymux variables - */ -extern sm_ss_t *sm_ssp; - -static int -mblk2assoc(mblk_t *mp, ttymux_assoc_t *assoc) -{ - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - - sm_dbg('M', ("mblk2assoc:\n")); - if (mp->b_cont == NULL) - return (EINVAL); - -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - ttymux_assoc32_t *assoc32; - - sm_dbg('I', ("mblk2assoc: b_cont 0x%p count %d (sz %d)\n", - mp->b_cont, iobp->ioc_count, sizeof (*assoc32))); - - if (iobp->ioc_count < sizeof (ttymux_assoc32_t)) - return (EINVAL); - - assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr; - assoc->ttymux_udev = expldev(assoc32->ttymux32_udev); - assoc->ttymux_ldev = expldev(assoc32->ttymux32_ldev); - assoc->ttymux_linkid = assoc32->ttymux32_linkid; - assoc->ttymux_tag = assoc32->ttymux32_tag; - assoc->ttymux_ioflag = assoc32->ttymux32_ioflag; - (void) strncpy(assoc->ttymux_path, assoc32->ttymux32_path, - MAXPATHLEN); - - } else -#endif - if (iobp->ioc_count < sizeof (*assoc)) { - return (EINVAL); - } else { - *assoc = *(ttymux_assoc_t *)mp->b_cont->b_rptr; - } - sm_dbg('M', ("mblk2assoc (%d): dev %d:%d not found\n", - assoc->ttymux_linkid, getmajor(assoc->ttymux_ldev), - getminor(assoc->ttymux_ldev))); - return (0); -} - -/* - * Given a device path return an OBP alias for it if it exists. - */ -static char * -val2alias(pnode_t node, char *path) -{ - char *buf1; - char *buf2; - char *propname, *propval; - int proplen; - - if (node == OBP_BADNODE) - return (NULL); - - sm_dbg('A', ("Looking for an alias for: %s (len %d)\n", - path, strlen(path))); - - /* - * Ask for first property by passing a NULL string - */ - buf1 = kmem_alloc(OBP_MAXPROPNAME, KM_SLEEP); - buf2 = kmem_zalloc(OBP_MAXPROPNAME, KM_SLEEP); - buf1[0] = '\0'; - - while (propname = (char *)prom_nextprop(node, buf1, buf2)) { - if (strlen(propname) == 0) - break; /* end of prop list */ - - (void) strcpy(buf1, propname); - - proplen = prom_getproplen(node, propname); - if (proplen == 0) - continue; - propval = kmem_zalloc(proplen + 1, KM_SLEEP); - (void) prom_getprop(node, propname, propval); - - if (strcmp(propval, path) == 0) { - kmem_free(propval, proplen + 1); - kmem_free(buf1, OBP_MAXPROPNAME); - sm_dbg('A', ("Alias is : %s\n", buf2)); - return (buf2); - } - - kmem_free(propval, proplen + 1); - bzero(buf2, OBP_MAXPROPNAME); - } - - kmem_free(buf1, OBP_MAXPROPNAME); - kmem_free(buf2, OBP_MAXPROPNAME); - - return (NULL); -} - -/* - * Tell OBP that this device is now usable - */ -static void -enable_device(sm_mux_state_t *ms, sm_console_t *cn) -{ - char *enb_str = "\" enable-device\" rot $call-method"; - - if (!cn->sm_obp_con) - return; - - sm_dbg('A', ("ttymux: enabling %d:%d\n", - getmajor(cn->sm_dev), getminor(cn->sm_dev))); - - if (cn->sm_i_ihdl != 0) - prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl, - (caddr32_t)cn->sm_i_ihdl, 0, 0, 0); - - if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl) - prom_interpret(enb_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl, - (caddr32_t)cn->sm_o_ihdl, 0, 0, 0); -} - -/* - * Tell OBP that this device is no longer usable - */ -static void -disable_device(sm_mux_state_t *ms, sm_console_t *cn) -{ - char *dis_str = "\" disable-device\" rot $call-method"; - - if (!cn->sm_obp_con) - return; - - sm_dbg('A', ("ttymux: disabling %d:%d\n", - getmajor(cn->sm_dev), getminor(cn->sm_dev))); - - if (cn->sm_i_ihdl != 0) - prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdin.sm_i_ihdl, - (caddr32_t)cn->sm_i_ihdl, 0, 0, 0); - if (cn->sm_o_ihdl != 0 && cn->sm_o_ihdl != cn->sm_i_ihdl) - prom_interpret(dis_str, (caddr32_t)ms->sm_cons_stdout.sm_o_ihdl, - (caddr32_t)cn->sm_o_ihdl, 0, 0, 0); -} - -static void -device_init_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi) -{ - uint_t flags = 0; - dev_info_t *ldip; - - sm_dbg('I', ("device_init_impl:\n")); - - if (plqi == NULL || cn == NULL) - return; - - flags = (uint_t)cn->sm_mode; - sm_dbg('I', ("device_init_impl: flgs %d con %d\n", flags, - cn->sm_obp_con)); - if (ldip = e_ddi_hold_devi_by_dev(cn->sm_dev, 0)) { - - /* - * Indicate to the linked device that it is - * providing a multiplexed console. - */ - if (flags & (uint_t)FORINPUT) - (void) e_ddi_prop_create(cn->sm_dev, ldip, - DDI_PROP_CANSLEEP, "obp-input-console", 0, 0); - if (flags & (uint_t)FOROUTPUT) - (void) e_ddi_prop_create(cn->sm_dev, ldip, - DDI_PROP_CANSLEEP, "obp-output-console", 0, 0); - - ddi_release_devi(ldip); - } - - if (flags) { - plqi->sm_ioflag = flags; - if (cn->sm_obp_con) - plqi->sm_uqflags |= SM_OBPCNDEV; - plqi->sm_ctrla_abort_on = sm_ssp->sm_ctrla_abort_on; - plqi->sm_break_abort_on = sm_ssp->sm_break_abort_on; - } - - /* - * Tell OBP that its ok to use this console - */ - enable_device(ms, cn); -} - -static void -device_fini_impl(sm_mux_state_t *ms, sm_console_t *cn, sm_lqi_t *plqi) -{ - dev_info_t *ldip; - - if (plqi == NULL || cn == NULL) - return; - /* - * Indicate to the linked device that it is no longer - * providing a multiplexed console. - */ - if (ldip = e_ddi_hold_devi_by_dev(plqi->sm_dev, 0)) { - if (plqi->sm_ioflag & (uint_t)FORINPUT) - (void) e_ddi_prop_remove(plqi->sm_dev, - ldip, "obp-input-console"); - if (plqi->sm_ioflag & (uint_t)FOROUTPUT) - (void) e_ddi_prop_remove(plqi->sm_dev, - ldip, "obp-output-console"); - - ddi_release_devi(ldip); - } - plqi->sm_ioflag = 0; - plqi->sm_uqflags &= ~SM_OBPCNDEV; - disable_device(ms, cn); -} - -static int -read_prop(pnode_t node, char *propname, char **propval) -{ - int proplen = prom_getproplen(node, propname); - - if (proplen < 0) - return (proplen); - *propval = kmem_zalloc(proplen + 1, KM_SLEEP); - if (proplen > 0) - (void) prom_getprop(node, propname, *propval); - else - *propval = 0; - - return (proplen); -} - -/* - * Parse a list of tokens - */ -static char * -sm_strtok_r(char *p, char *sep, char **lasts) -{ - char *e, *tok = NULL; - - if (p == 0 || *p == 0) - return (NULL); - - e = p + strlen(p); - - do { - if (strchr(sep, *p) != NULL) { - if (tok != NULL) { - *p = 0; - *lasts = p + 1; - return (tok); - } - } else if (tok == NULL) { - tok = p; - } - } while (++p < e); - - *lasts = NULL; - if (tok != NULL) - return (tok); - return (NULL); -} - -/* - * Add or remove an alias from a property list of aliases: - * path: an OBP device path - * pname: property name containing a space separated list of aliases - * append: if true include the alias for path in the property list - * otherwise remove the alias from the list. - */ -static int -upd_config(boolean_t append, char *pname, char *path) -{ - pnode_t onode, anode; - size_t plen; /* length of property name */ - char *pval; /* value of property */ - char *tok, *lasts; - char *aliases[TTYMUX_MAX_LINKS]; - size_t i, cnt, len; - boolean_t found; - char *nval, *alias = NULL; - - if ((anode = prom_alias_node()) == OBP_BADNODE || - (onode = prom_optionsnode()) == OBP_BADNODE) { - sm_dbg('I', ("upd_config: no alias or options node.\n")); - return (1); - } - - if ((plen = read_prop(onode, pname, &pval)) < 0) - return (1); - - sm_dbg('I', ("upd_config: %s=%s (%s)\n", pname, pval, path)); - found = B_FALSE; - for (len = 0, cnt = 0, tok = sm_strtok_r(pval, " \t", &lasts); - tok != NULL && cnt < TTYMUX_MAX_LINKS; - tok = sm_strtok_r(lasts, " \t", &lasts)) { - char *aval; - size_t alen; - - if ((alen = read_prop(anode, tok, &aval)) < 0) - continue; - - /* does this alias match the requested path */ - if (strcmp(aval, path) == 0 || - (strstr(path, aval) != NULL && - strchr(aval, ':') == NULL && strchr(path, ':') != NULL && - strcmp(strchr(path, ':'), ":a") == 0)) { - if (!found && append) { - kmem_free(aval, alen + 1); - goto out; - } - found = B_TRUE; - } else { - aliases[cnt++] = tok; - len += strlen(tok) + 1; - } - kmem_free(aval, alen + 1); - } - - sm_dbg('I', ("%d aliases\n", cnt)); - if (append) { - if (cnt + 1 == TTYMUX_MAX_LINKS) - goto out; - - if ((alias = val2alias(anode, path)) == NULL) { - char *mnode = strstr(path, ":a"); - - if (mnode != 0) { - *mnode = '\0'; - alias = val2alias(anode, path); - *mnode = ':'; - } - } - if (alias == NULL) { - sm_dbg('I', ("No alias for %s\n", path)); - goto out; - } - aliases[cnt++] = alias; - len += strlen(alias) + 1; - } else if (!found) { - goto out; - } - - sm_dbg('I', ("%d aliases (len %d)\n", cnt, len)); - if (len == 0) - goto out; - ASSERT(len > 1 && cnt > 0); - - nval = kmem_zalloc(len, KM_SLEEP); - for (i = 0; ; ) { - ASSERT(strlen(nval) + strlen(aliases[i]) + 1 <= len); - sm_dbg('I', ("alias %s\n", aliases[i])); - (void) strcat(nval, aliases[i]); - if (++i == cnt) - break; - (void) strcat(nval, " "); - } - - sm_dbg('I', ("setprop: %s=%s (%d)\n", pname, nval, len)); - - (void) prom_setprop(onode, pname, nval, len); - - kmem_free(nval, len); - - if (alias != NULL) - kmem_free(alias, OBP_MAXPROPNAME); -out: - sm_dbg('I', ("upd_config: returning.\n")); - kmem_free(pval, plen + 1); - return (0); -} - -/* - * - */ -static int -update_config(sm_mux_state_t *ms, char *path, io_mode_t mode, int cmd) -{ - sm_dbg('I', ("update_config: path %s io %d\n", path ? path : "", mode)); - if (path == 0 || *path == 0) { - sm_dbg('I', ("update_config: EINVAL - no path\n")); - return (1); - } - if (prom_is_openprom() == 0) - return (0); - - if ((mode & FORINPUT) && ms->sm_ialias != NULL) - (void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_ialias, path); - if ((mode & FOROUTPUT) && ms->sm_oalias != NULL) - (void) upd_config((cmd == TTYMUX_ASSOC), ms->sm_oalias, path); - return (0); -} - -/* - * Convert a dev_t to a device path - */ -static char * -sm_di_path(dev_t dev) -{ - char *p, *path; - - if (dev == NODEV) - return (NULL); - - p = kmem_zalloc(MAXPATHLEN + 1, KM_SLEEP); - if (ddi_dev_pathname(dev, S_IFCHR, p) == DDI_SUCCESS) { - path = kmem_alloc(strlen(p) + 1, KM_SLEEP); - (void) strcpy(path, p); - } - kmem_free(p, MAXPATHLEN + 1); - - return (path); -} - -static int -console_cmd(int cmd, ttymux_assoc_t *assoc) -{ - sm_mux_state_t *ms; - sm_console_t *cn; - uint_t j; - - sm_dbg('I', ("console_cmd ENTER: %s\n", cmd == TTYMUX_DISASSOC ? - "TTYMUX_DISASSOC" : "TTYMUX_ASSOC")); - - if (assoc->ttymux_ldev == NODEV && *assoc->ttymux_path != '/') { - sm_lqi_t *lqi = get_lqi_byid(assoc->ttymux_linkid); - if (lqi == 0 || lqi->sm_dev == NODEV) { - sm_dbg('I', ("console_cmd: no id link %d cmd %d\n", - assoc->ttymux_linkid, cmd)); - return (EINVAL); - } - assoc->ttymux_ldev = lqi->sm_dev; - } - - sm_dbg('I', ("console_cmd: path %s\n", assoc->ttymux_path)); - - if ((ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR)) == 0) { - sm_dbg('I', ("console_cmd: No muxstate\n")); - return (0); - } - - mutex_enter(&ms->sm_cons_mutex); - - for (cn = ms->sm_cons_links, j = 0; - j < ms->sm_cons_cnt; cn++, j++) { - if (assoc->ttymux_ldev != NODEV && assoc->ttymux_ldev == - cn->sm_dev) { - break; - } else if (cn->sm_path != NULL && - strncmp(cn->sm_path, assoc->ttymux_path, MAXPATHLEN) == 0) { - break; - } - } - - assoc->ttymux_path[MAXPATHLEN - 1] = 0; - if (cmd == TTYMUX_DISASSOC) { - if (j == ms->sm_cons_cnt) { - mutex_exit(&ms->sm_cons_mutex); - return (0); - } - - /* - * Disable the console in OBP and then delete this console - * this console - note that this also deletes OBP - * information - i.e. once it is disassociated it cannot - * be reused as an OBP console - roll on polled I/O! - */ - sm_dbg('I', ("console_cmd: cleaning up\n")); - device_fini_impl(ms, cn, get_lqi_bydevt(assoc->ttymux_ldev)); - - if (cn->sm_path == NULL) { - if (assoc->ttymux_ldev != NODEV) - cn->sm_path = sm_di_path(assoc->ttymux_ldev); - else - (void) update_config(ms, assoc->ttymux_path, - assoc->ttymux_ioflag, cmd); - } - if (cn->sm_path) { - (void) update_config(ms, cn->sm_path, cn->sm_mode, cmd); - kmem_free(cn->sm_path, strlen(cn->sm_path) + 1); - cn->sm_path = NULL; - } - ms->sm_cons_cnt -= 1; - if (ms->sm_cons_cnt > 0) - *cn = ms->sm_cons_links[ms->sm_cons_cnt]; - - sm_dbg('I', ("console_cmd: console %d removed (cnt %d)\n", - j, ms->sm_cons_cnt)); - - } else if (cmd == TTYMUX_ASSOC) { - - if (j == ms->sm_cons_cnt) { - - if (j == TTYMUX_MAX_LINKS) { - mutex_exit(&ms->sm_cons_mutex); - return (ENOMEM); - } - - ms->sm_cons_cnt += 1; - - bzero((caddr_t)cn, sizeof (*cn)); - cn->sm_dev = assoc->ttymux_ldev; - cn->sm_muxid = assoc->ttymux_linkid; - cn->sm_mode = assoc->ttymux_ioflag; - device_init_impl(ms, cn, - get_lqi_bydevt(assoc->ttymux_ldev)); - } else { - cn->sm_dev = assoc->ttymux_ldev; - cn->sm_muxid = assoc->ttymux_linkid; - cn->sm_mode = assoc->ttymux_ioflag; - } - - if (assoc->ttymux_ldev != NODEV) { - cn->sm_path = sm_di_path(assoc->ttymux_ldev); - } else { - cn->sm_path = kmem_alloc(strlen(assoc->ttymux_path) + 1, - KM_SLEEP); - (void) strcpy(cn->sm_path, assoc->ttymux_path); - } - if (cn->sm_path != NULL) - (void) update_config(ms, cn->sm_path, cn->sm_mode, cmd); - else - sm_dbg('I', ("console_cmd: ASSOC No path info")); - } - mutex_exit(&ms->sm_cons_mutex); - sm_dbg('I', ("console_cmd EXIT: %s\n", cmd == TTYMUX_DISASSOC ? - "TTYMUX_DISASSOC" : "TTYMUX_ASSOC")); - return (0); -} - -static int -get_unconfigured_consoles(sm_mux_state_t *ms, ttymux_assoc_t *a) -{ - sm_console_t *cn; - int j, cnt; - - if (ms == 0) - return (0); - - mutex_enter(&ms->sm_cons_mutex); - for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; - cn++, j++) { - if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) { - a->ttymux_linkid = cn->sm_muxid; - a->ttymux_tag = (uint_t)0; - a->ttymux_ioflag = cn->sm_mode; - a->ttymux_udev = cn->sm_mode & FORINPUT ? - ms->sm_cons_stdin.sm_dev : - ms->sm_cons_stdout.sm_dev; - a->ttymux_ldev = NODEV; - (void) strncpy(a->ttymux_path, cn->sm_path, MAXPATHLEN); - cnt++; - a++; - } - } - mutex_exit(&ms->sm_cons_mutex); - return (cnt); -} - -#ifdef _SYSCALL32_IMPL -/* - * Look for any consoles that are not currently plumbed under the multiplexer. - */ -static int -get_unconfigured_consoles32(sm_mux_state_t *ms, ttymux_assoc32_t *a) -{ - sm_console_t *cn; - int j, cnt; - - if (ms == 0) - return (0); - - mutex_enter(&ms->sm_cons_mutex); - for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; - cn++, j++) { - sm_dbg('I', ("get_unconfigured_consoles: check %s (%d:%d)", - cn->sm_path ? cn->sm_path : "NULL", - getmajor(cn->sm_dev), getminor(cn->sm_dev))); - if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) { - a->ttymux32_linkid = 0; - a->ttymux32_tag = (uint32_t)0; - a->ttymux32_ioflag = (uint32_t)cn->sm_mode; - a->ttymux32_ldev = NODEV32; - (void) cmpldev(&a->ttymux32_udev, cn->sm_mode & - FORINPUT ? ms->sm_cons_stdin.sm_dev : - ms->sm_cons_stdout.sm_dev); - - (void) strncpy(a->ttymux32_path, cn->sm_path, - MAXPATHLEN); - cnt++; - a++; - } - } - mutex_exit(&ms->sm_cons_mutex); - return (cnt); -} -#endif - -static int -count_unconfigured_consoles(sm_mux_state_t *ms) -{ - sm_console_t *cn; - int j, cnt; - - if (ms == 0) - return (0); - - mutex_enter(&ms->sm_cons_mutex); - for (cn = ms->sm_cons_links, cnt = j = 0; j < ms->sm_cons_cnt; - cn++, j++) { - sm_dbg('I', ("cnt_unconfigured_consoles: check %s (%d:%d)", - cn->sm_path ? cn->sm_path : "NULL", - getmajor(cn->sm_dev), getminor(cn->sm_dev))); - if (cn->sm_path && get_lqi_bydevt(cn->sm_dev) == NULL) - cnt++; - } - mutex_exit(&ms->sm_cons_mutex); - return (cnt); -} - -/* - * Exported interfaces - */ - -/* - * A console device is no longer associated. - */ -int -ttymux_device_fini(sm_lqi_t *plqi) -{ - int j; - sm_mux_state_t *ms; - - ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR); - - if (plqi == NULL || ms == NULL) - return (0); - - mutex_enter(&ms->sm_cons_mutex); - - for (j = 0; j < ms->sm_cons_cnt; j++) { - - if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) { - - device_fini_impl(ms, &ms->sm_cons_links[j], plqi); - - mutex_exit(&ms->sm_cons_mutex); - return (0); - } - } - mutex_exit(&ms->sm_cons_mutex); - - return (1); -} - -/* - * A console device is being introduced. - */ -int -ttymux_device_init(sm_lqi_t *plqi) -{ - int j; - sm_mux_state_t *ms; - - ms = (sm_mux_state_t *)space_fetch(TTYMUXPTR); - - if (ms == NULL) - return (0); - - mutex_enter(&ms->sm_cons_mutex); - - for (j = 0; j < ms->sm_cons_cnt; j++) { - - if (ms->sm_cons_links[j].sm_dev == plqi->sm_dev) { - - device_init_impl(ms, &ms->sm_cons_links[j], plqi); - - mutex_exit(&ms->sm_cons_mutex); - return (0); - } - } - mutex_exit(&ms->sm_cons_mutex); - return (1); -} - -/* - * Process a TTYMUX_ASSOCIATE or TTYMUX_DISASSOCIATE ioctl. - */ -static int -ttymux_link_ioctl(mblk_t *mp) -{ - ttymux_assoc_t assoc; - int err; - sm_lqi_t *lqi; - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - dev_t cidev, codev; - - sm_dbg('I', ("ttymux_link_ioctl:\n")); - if ((err = mblk2assoc(mp, &assoc)) != 0) - return (err); - - sm_dbg('I', ("uminor is %d\n", getminor(assoc.ttymux_udev))); - - if (assoc.ttymux_udev == NODEV) - return (EINVAL); - - err = 0; - - if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL) { - if (assoc.ttymux_linkid < 0) - err = EINVAL; - else if ((lqi = get_lqi_byid(assoc.ttymux_linkid)) == 0) - err = ENOLINK; - } - - if (sm_ssp->sm_ms) { - mutex_enter(&sm_ssp->sm_ms->sm_cons_mutex); - cidev = sm_ssp->sm_ms->sm_cons_stdin.sm_dev; - codev = sm_ssp->sm_ms->sm_cons_stdout.sm_dev; - mutex_exit(&sm_ssp->sm_ms->sm_cons_mutex); - } else { - cidev = codev = NODEV; - } - - if (err != 0) { - if (assoc.ttymux_udev != cidev && assoc.ttymux_udev != codev) - return (err); - (void) console_cmd(iobp->ioc_cmd, &assoc); - return (0); - } else if (assoc.ttymux_udev == cidev || assoc.ttymux_udev == codev) { - (void) console_cmd(iobp->ioc_cmd, &assoc); - } - - if (iobp->ioc_cmd == TTYMUX_ASSOC) - return (sm_associate(sm_dev2unit(assoc.ttymux_udev), - lqi, assoc.ttymux_tag, assoc.ttymux_ioflag, - assoc.ttymux_path)); - else if (iobp->ioc_cmd == TTYMUX_DISASSOC) - return (sm_disassociate(sm_dev2unit(assoc.ttymux_udev), - lqi, assoc.ttymux_tag)); - - return (0); -} - -/* - * Process a TTYMUX_GETLINK ioctl. - */ -int -ttymux_query_link_ioctl(mblk_t *mp) -{ - sm_lqi_t *lqi; - - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - - sm_dbg('I', ("ttymux_query_link_ioctl:\n")); - - if (mp->b_cont == NULL) - return (EINVAL); - -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - ttymux_assoc32_t *assoc32; - ttymux_assoc_t assoc; - - if (mblk2assoc(mp, &assoc) != 0) - return (EINVAL); - - if ((lqi = get_lqi_bydevt(assoc.ttymux_ldev)) == NULL && - (lqi = get_lqi_byid(assoc.ttymux_linkid)) == NULL) { - sm_dbg('M', ("Query Link (%d): dev %d:%d not found\n", - assoc.ttymux_linkid, - getmajor(assoc.ttymux_ldev), - getminor(assoc.ttymux_ldev))); - return (ENOLINK); - } - assoc32 = (ttymux_assoc32_t *)mp->b_cont->b_rptr; - LQI2ASSOC32(assoc32, lqi); - } else -#endif - { - ttymux_assoc_t *assoc; - - if (iobp->ioc_count < sizeof (ttymux_assoc_t)) - return (EINVAL); - - assoc = (ttymux_assoc_t *)mp->b_cont->b_rptr; - if ((lqi = get_lqi_bydevt(assoc->ttymux_ldev)) == NULL && - (lqi = get_lqi_byid(assoc->ttymux_linkid)) == NULL) { - return (ENOLINK); - } - LQI2ASSOC(assoc, lqi); - } - return (0); -} - -/* - * Response to receiving an M_IOCDATA message for the TTYMUX_LIST ioctl. - */ -static int -sm_iocresp(mblk_t *mp) -{ - struct copyresp *csp = (struct copyresp *)mp->b_rptr; - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - mblk_t *pmp; - - sm_dbg('M', ("(M_IOCDATA: cmd %d)\n", csp->cp_cmd)); - - if (csp->cp_cmd != TTYMUX_LIST) { - sm_dbg('M', ("(M_IOCDATA: unknown cmd)\n")); - DB_TYPE(mp) = M_IOCNAK; - return (EINVAL); - } - if (csp->cp_rval) { - if (csp->cp_private) - freemsg((mblk_t *)csp->cp_private); - - sm_dbg('M', ("M_IOCDATA: result is %d\n", csp->cp_rval)); - DB_TYPE(mp) = M_IOCNAK; - iobp->ioc_error = (int)(uintptr_t)csp->cp_rval; - iobp->ioc_rval = 0; - return (iobp->ioc_error); - } - - pmp = (mblk_t *)csp->cp_private; - -#ifdef _SYSCALL32_IMPL - if ((csp->cp_flag & IOC_MODELS) != IOC_NATIVE) { - iobp->ioc_count = sizeof (ttymux_assocs32_t); - iobp->ioc_rval = pmp == NULL ? 0 : - ((ttymux_assocs32_t *)pmp->b_rptr)->ttymux32_nlinks; - } else -#endif - { - iobp->ioc_count = sizeof (ttymux_assocs_t); - iobp->ioc_rval = pmp == NULL ? 0 : - ((ttymux_assocs_t *)pmp->b_rptr)->ttymux_nlinks; - - } - - DB_TYPE(mp) = (pmp) ? M_IOCACK : M_IOCNAK; - mp->b_wptr = mp->b_rptr + sizeof (struct iocblk); - - if (mp->b_cont) - freemsg(unlinkb(mp)); - if (pmp) - linkb(mp, pmp); - else - iobp->ioc_count = 0; - - iobp->ioc_error = 0; - - sm_dbg('M', ("(M_IOCDATA: rval %d cnt %d private 0x%p)\n", - iobp->ioc_rval, iobp->ioc_count, pmp)); - return (0); -} - -/* - * Process a TTYMUX_LIST ioctl. - */ -int -ttymux_query_links_ioctl(mblk_t *mp) -{ - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - struct copyreq *cqp; - int unit; - sm_lqi_t *lqi; - mblk_t *nmp; - int cnt; - void *asl; - void *uaddr; - size_t sz; - - if (DB_TYPE(mp) == M_IOCDATA) { - return (sm_iocresp(mp)); - } - /* - * Is this a query for the number of linked devices? - */ - if (iobp->ioc_count == 0) { - - for (unit = 0, iobp->ioc_rval = 0; - unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); - unit++) - if (lqi->sm_linkid != 0) - iobp->ioc_rval += 1; - - iobp->ioc_rval += count_unconfigured_consoles(sm_ssp->sm_ms); - DB_TYPE(mp) = M_IOCACK; - iobp->ioc_error = 0; - - return (0); - } - - if (mp->b_cont == NULL) { - sm_dbg('Y', ("TTYMUX_LIST: b_cont is NULL\n")); - DB_TYPE(mp) = M_IOCNAK; - iobp->ioc_error = EINVAL; - return (EINVAL); - } - - asl = mp->b_cont->b_rptr; - -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - cnt = ((ttymux_assocs32_t *)asl)->ttymux32_nlinks; - sz = cnt * sizeof (ttymux_assoc32_t); - uaddr = (void *)(uintptr_t) - ((ttymux_assocs32_t *)asl)->ttymux32_assocs; - } else -#endif - { - cnt = ((ttymux_assocs_t *)asl)->ttymux_nlinks; - sz = cnt * sizeof (ttymux_assoc_t); - uaddr = (void *)((ttymux_assocs_t *)asl)->ttymux_assocs; - } - if ((nmp = sm_allocb(sz, BPRI_MED)) == NULL) { - DB_TYPE(mp) = M_IOCNAK; - iobp->ioc_error = EINVAL; - return (EAGAIN); - } - - sm_dbg('Y', ("TTYMUX_LIST: cnt %d sz %d uaddr 0x%p\n", cnt, sz, uaddr)); - - iobp->ioc_rval = 0; - -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - ttymux_assoc32_t *assoc; - - sm_dbg('Y', ("!Native: %d structures\n", cnt)); - assoc = (ttymux_assoc32_t *)nmp->b_rptr; - - for (unit = 0; - unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); - unit++) { - if (lqi->sm_linkid != 0) { - if (cnt-- == 0) - break; - LQI2ASSOC32(assoc, lqi); - assoc++; - iobp->ioc_rval += 1; - } - } - if (cnt > 0) { - /* see if there are unconfigured consoles */ - iobp->ioc_rval += - get_unconfigured_consoles32(sm_ssp->sm_ms, assoc); - sm_dbg('I', ("%d unconfigured consoles\n", - iobp->ioc_rval)); - } else { - sm_dbg('I', ("no more space in user addr\n")); - } - ((ttymux_assocs32_t *)asl)->ttymux32_nlinks = iobp->ioc_rval; - } else -#endif - { - ttymux_assoc_t *assoc; - - sm_dbg('Y', ("!Native: %d structures\n", cnt)); - assoc = (ttymux_assoc_t *)nmp->b_wptr; - - for (unit = 0; - unit < MAX_LQS && (lqi = get_lqi(sm_ssp, unit)); - unit++) { - if (lqi->sm_linkid != 0) { - if (cnt-- == 0) - break; - LQI2ASSOC(assoc, lqi); - assoc++; - iobp->ioc_rval += 1; - } - } - if (cnt > 0) { - /* see if there are unconfigured consoles */ - iobp->ioc_rval += - get_unconfigured_consoles(sm_ssp->sm_ms, assoc); - sm_dbg('I', ("%d unconfigured consoles\n", - iobp->ioc_rval)); - } else { - sm_dbg('I', ("no more space in user addr\n")); - } - ((ttymux_assocs_t *)asl)->ttymux_nlinks = iobp->ioc_rval; - } - - cqp = (struct copyreq *)mp->b_rptr; - cqp->cq_addr = uaddr; - cqp->cq_size = sz; - cqp->cq_flag = 0; - cqp->cq_private = mp->b_cont; - mp->b_cont = nmp; - nmp->b_wptr = nmp->b_rptr + sz; - - DB_TYPE(mp) = M_COPYOUT; - mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); - - return (0); -} - -/* - * Process a TTYMUX_CONSDEV ioctl. - */ -static int -ttymux_console_ioctl(mblk_t *mp) -{ - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - int err = EINVAL; - - sm_dbg('I', ("ttymux_console_ioctl:\n")); -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - if (mp->b_cont && iobp->ioc_count >= sizeof (dev32_t)) { - dev32_t dev; - - (void) cmpldev(&dev, rconsdev); - - *(dev32_t *)mp->b_cont->b_rptr = dev; - mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (dev); - iobp->ioc_count = sizeof (dev); - err = 0; - } else { - sm_dbg('I', ("TTYMUX_CONSDEV: b_cont 0x%p count %d\n", - mp->b_cont, iobp->ioc_count)); - } - } else -#endif - if (mp->b_cont && iobp->ioc_count >= sizeof (dev_t)) { - *(dev_t *)mp->b_cont->b_rptr = rconsdev; - mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof (rconsdev); - iobp->ioc_count = sizeof (rconsdev); - err = 0; - } - return (err); -} - -/* - * Process a ioctl relating to aborting on the console. - */ -int -ttymux_abort_ioctl(mblk_t *mp) -{ - struct iocblk *iobp; - int cmd, err = 0; - sm_lqi_t *lqi; - ttymux_abort_t *abreq; -#ifdef _SYSCALL32_IMPL - struct ttymux_abort32 { - dev32_t ldev; - enum ttymux_break_type method; - uint32_t enable; - } *abreq32; -#endif - dev_t ldev; - enum ttymux_break_type method; - uint_t enable; - - iobp = (struct iocblk *)mp->b_rptr; - cmd = iobp->ioc_cmd; - - iobp->ioc_error = 0; - iobp->ioc_rval = 0; - sm_dbg('I', ("ttymux_abort_ioctl:\n")); - switch (cmd) { - case CONSSETABORTENABLE: - lqi = (sm_ssp->sm_lconsole) ? sm_ssp->sm_lconsole->sm_lqs : 0; - enable = (*(intptr_t *)mp->b_cont->b_rptr) ? 1 : 0; - sm_ssp->sm_ctrla_abort_on = sm_ssp->sm_break_abort_on = enable; - for (; lqi != 0; lqi = lqi->sm_nlqi) { - lqi->sm_ctrla_abort_on = enable; - lqi->sm_break_abort_on = enable; - } - break; - case CONSGETABORTENABLE: - if (mp->b_cont == 0 || iobp->ioc_count < sizeof (intptr_t)) { - iobp->ioc_error = EINVAL; - iobp->ioc_rval = -1; - } else { - *(intptr_t *)mp->b_cont->b_rptr = - (sm_ssp->sm_ctrla_abort_on || - sm_ssp->sm_break_abort_on); - mp->b_cont->b_wptr = - mp->b_cont->b_rptr + sizeof (intptr_t); - iobp->ioc_count = sizeof (intptr_t); - } - break; - case TTYMUX_GETABORTSTR: - - if (iobp->ioc_count < strlen(sm_ssp->sm_abs) + 1 || - mp->b_cont == 0 || - mp->b_cont->b_cont) { - iobp->ioc_error = EINVAL; - iobp->ioc_rval = -1; - } else { - (void) strcpy((char *)mp->b_cont->b_rptr, - sm_ssp->sm_abs); - iobp->ioc_count = strlen(sm_ssp->sm_abs) + 1; - mp->b_cont->b_wptr = - mp->b_cont->b_rptr + iobp->ioc_count; - } - break; - case TTYMUX_GETABORT: - case TTYMUX_SETABORT: - - lqi = 0; -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - if (iobp->ioc_count < sizeof (*abreq32) || - mp->b_cont == 0) { - err = EINVAL; - } else { - abreq32 = (struct ttymux_abort32 *) - mp->b_cont->b_rptr; - ldev = expldev(abreq32->ldev); - method = abreq32->method; - enable = (uint_t)abreq32->enable; - iobp->ioc_count = sizeof (*abreq32); - } - } else -#endif - if (iobp->ioc_count < sizeof (*abreq) || - mp->b_cont == 0) { - err = EINVAL; - } else { - abreq = (ttymux_abort_t *)mp->b_cont->b_rptr; - ldev = abreq->ttymux_ldev; - method = abreq->ttymux_method; - enable = abreq->ttymux_enable; - iobp->ioc_count = sizeof (*abreq); - } - - if (err != 0) { - iobp->ioc_rval = -1; - return ((iobp->ioc_error = err)); - } - - sm_dbg('Y', ("ttymux_abort_ioctl: type %d how %d ldev %d:%d\n", - method, enable, getmajor(ldev), getminor(ldev))); - - lqi = get_lqi_bydevt(ldev); - if (ldev != NODEV && lqi == 0) { - err = ENOLINK; - } else if (cmd == TTYMUX_GETABORT && lqi == 0) { - err = ENODEV; - } else if (cmd == TTYMUX_GETABORT) { - if (lqi->sm_break_abort_on == 0 && - lqi->sm_ctrla_abort_on == 0) { - method = SOFTHARD_BREAK; - enable = 0; - } else { - enable = 1; - if (lqi->sm_break_abort_on == 0) - method = SOFTWARE_BREAK; - else if (lqi->sm_ctrla_abort_on == 0) - method = HARDWARE_BREAK; - else - method = SOFTHARD_BREAK; - } - -#ifdef _SYSCALL32_IMPL - if ((iobp->ioc_flag & IOC_MODELS) != IOC_NATIVE) { - abreq32->method = method; - abreq32->enable = (uint32_t)enable; - } else -#endif - { - abreq->ttymux_method = method; - abreq->ttymux_enable = enable; - } - } else { - iobp->ioc_count = 0; - sm_dbg('I', ("lqi is 0x%p\n", lqi)); - if (lqi == 0) { - if (method == HARDWARE_BREAK) - sm_ssp->sm_break_abort_on = enable; - else if (method == SOFTWARE_BREAK) - sm_ssp->sm_ctrla_abort_on = enable; - else if (method == SOFTHARD_BREAK) { - sm_ssp->sm_break_abort_on = enable; - sm_ssp->sm_ctrla_abort_on = enable; - } else { - sm_dbg('I', ("%d - invalid\n", method)); - iobp->ioc_rval = -1; - return ((iobp->ioc_error = EINVAL)); - } - - if (sm_ssp->sm_lconsole) { - sm_dbg('I', ("lconsole 0x%p (0x%p)\n", - sm_ssp->sm_lconsole, - sm_ssp->sm_lconsole->sm_lqs)); - } else { - sm_dbg('I', ("lconsole is null\n")); - } - - lqi = (sm_ssp->sm_lconsole) ? - sm_ssp->sm_lconsole->sm_lqs : 0; - } - while (lqi) { - if (method == HARDWARE_BREAK) - lqi->sm_break_abort_on = enable; - else if (method == SOFTWARE_BREAK) - lqi->sm_ctrla_abort_on = enable; - else if (method == SOFTHARD_BREAK) { - lqi->sm_break_abort_on = enable; - lqi->sm_ctrla_abort_on = enable; - } else { - sm_dbg('I', ("%d: invalid\n", method)); - iobp->ioc_rval = -1; - return ((iobp->ioc_error = EINVAL)); - } - - lqi = (ldev == NODEV) ? lqi->sm_nlqi : 0; - } - } - iobp->ioc_rval = err ? -1 : 0; - iobp->ioc_error = err; - break; - default: - iobp->ioc_rval = -1; - iobp->ioc_error = EINVAL; - } - return (iobp->ioc_error); -} - -/* - * Process ioctls specific to the ttymux driver. - */ -/*ARGSUSED*/ -int -sm_ioctl_cmd(sm_uqi_t *uqi, mblk_t *mp) -{ - struct iocblk *iobp = (struct iocblk *)mp->b_rptr; - - iobp->ioc_rval = 0; - - /* - * This routine does not support transparent ioctls - */ - if (iobp->ioc_count == TRANSPARENT) { - sm_dbg('Y', ("sm_ioctl_cmd: unsupported ioctl\n")); - iobp->ioc_error = ENOTSUP; - DB_TYPE(mp) = M_IOCNAK; - if (mp->b_cont) - freemsg(unlinkb(mp)); - return (ENOTSUP); - } - - switch (iobp->ioc_cmd) { - case TTYMUX_CONSDEV: - iobp->ioc_error = ttymux_console_ioctl(mp); - break; - case TTYMUX_ASSOC: - case TTYMUX_DISASSOC: - iobp->ioc_error = ttymux_link_ioctl(mp); - break; - case TTYMUX_GETLINK: - iobp->ioc_error = ttymux_query_link_ioctl(mp); - break; - case TTYMUX_LIST: - return (ttymux_query_links_ioctl(mp)); - case TTYMUX_SETCTL: - case TTYMUX_GETCTL: - iobp->ioc_error = ENOTSUP; - break; - case TTYMUX_GETABORTSTR: - case TTYMUX_SETABORT: - case TTYMUX_GETABORT: - iobp->ioc_error = ttymux_abort_ioctl(mp); - break; - default: - iobp->ioc_error = EINVAL; - break; - } - - DB_TYPE(mp) = iobp->ioc_error ? M_IOCNAK : M_IOCACK; - - if ((iobp->ioc_error || iobp->ioc_count == 0) && mp->b_cont) - freemsg(unlinkb(mp)); - - sm_dbg('I', ("TTYMUX IOCTL: err %d rval %d count %d\n", - iobp->ioc_error, iobp->ioc_rval, iobp->ioc_count)); - - return (iobp->ioc_error); -} diff --git a/usr/src/uts/sun/sys/Makefile b/usr/src/uts/sun/sys/Makefile index 778e8394f4..a85f7bae30 100644 --- a/usr/src/uts/sun/sys/Makefile +++ b/usr/src/uts/sun/sys/Makefile @@ -22,6 +22,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # include global definitions include ../../../Makefile.master @@ -36,7 +37,6 @@ promif.h promimpl.h \ ser_async.h ser_zscc.h \ socalio.h socalreg.h \ socal_cq_defs.h socalmap.h socalvar.h \ -ttymux.h ttymuxuser.h \ zsdev.h SCSIADHDRS= \ @@ -103,7 +103,7 @@ devops.check := CSTYLE_TAIL = | grep -v "line > 80 characters" | true $(ROOTSCSIADHDRS) $(ROOTSCSITARGHDRS) $(ROOTXHDRS) \ $(ROOTFCHDRS) -install_h: $(ROOTDIRS) .WAIT $(ROOTHDRS) \ +install_h: $(ROOTDIRS) .WAIT $(ROOTHDRS) \ $(ROOTAUDHDRS) $(ROOTAUDIMPLHDRS) \ $(ROOTSCSIADHDRS) $(ROOTSCSITARGHDRS) $(ROOTFCHDRS) diff --git a/usr/src/uts/sun/sys/ttymux.h b/usr/src/uts/sun/sys/ttymux.h deleted file mode 100644 index 56596a66dc..0000000000 --- a/usr/src/uts/sun/sys/ttymux.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _TTYMUX_H -#define _TTYMUX_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/obpdefs.h> -#include <sys/tty.h> -#include <sys/ttymuxuser.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define SM_MAX_ABSLEN 24 /* maximum length for the s/w abort sequence */ -#define SM_MIN_ABSLEN 2 - -#define SM_COPYIN 0x1 -#define SM_COPYOUT 0x2 - -typedef -struct sm_iocdata { - int sm_iocid; - int sm_nacks; /* number of responses expected */ - int sm_ackcnt; /* number of ACKs received */ - int sm_nakcnt; /* number of NAKs received */ - int sm_acnt; /* number of responses received */ - int sm_acked; /* has the message been acked (only one of them) */ - int sm_policy; /* which policy is used for acknowleding this ioctl */ - uint_t sm_flags; - /* indicates when copyin/out has been sent upstream */ - ulong_t sm_timeval; -} sm_iocdata_t; - -/* - * Each minor (refered to as a logical device) created by the multiplexor - * maps onto multiple real devices. - * I/O on a logical device is duplicated across multiple real devices. - * i.e. input from any of the real devices (identified by lqs) is funneled - * through the queue identified in the ttycommon field of a logical unit. - * output arriving on the queue identified in the ttycommon field of a logical - * unit is distributed to all real devices identified by lqs. - * - * When a logical unit is open there is a unique queue upstream (identified - * by ttycommon). - * When a real unit is open there is a unique lower queue to the h/w driver - * (identified by ttycommon). - * - * If the control lines on RS232 port for a physical unit are unknown and - * a request for their status has been issued then flags contains the bits - * TIOCM_PEND and tiocmgetid contains the id of the M_IOCTL streams message - * sent down the write queue to obtain the current status (placed in mbits). - */ -typedef -struct sm_uqi { - int sm_lunit; /* logical unit */ - int sm_protocol; /* in use for this protocol */ - uint_t sm_flags; /* flags */ - uint_t sm_mbits; /* consolidated status of modem lines */ - tcflag_t sm_cmask; /* ignore these control bits */ - uint_t sm_policy; /* ioctl response policy */ - struct sm_lqi *sm_lqs; /* lower queues mapped to this lunit */ - int sm_nlqs; - kmutex_t sm_umutex[1]; /* protects uflags */ - kcondvar_t sm_ucv[1]; /* waiting for uflags to change */ - bufcall_id_t sm_ttybid; /* ttycommon bufcall */ - dev_t sm_dev; /* currently attached device */ - int sm_nwaiters; /* no. of threads waiting for carrier */ - queue_t *sm_waitq; /* identity of blocked queue */ - tty_common_t sm_ttycommon[1]; - /* queue common data when is open */ - sm_iocdata_t sm_siocdata; /* active ioctl */ - sm_iocdata_t sm_piocdata; /* active private ioctl */ -} sm_uqi_t; - -typedef -struct sm_lqi { - struct sm_lqi *sm_nlqi; /* chain units together into lists */ - sm_uqi_t *sm_uqi; /* this lunit and uqi are associated */ - int sm_linkid; /* mux id for the link */ - uint64_t sm_tag; /* tag for the link */ - uint_t sm_flags; /* flags */ - uint_t sm_uqflags; /* written by an upper queue */ - io_mode_t sm_ioflag; /* input and/or output stream */ - int sm_ctrla_abort_on; - int sm_break_abort_on; - uint_t sm_mbits; /* status of the modem control lines */ - tcflag_t sm_cmask; /* ignore these control bits */ - mblk_t *sm_mp; /* mblk for next write */ - bufcall_id_t sm_bid; /* bufcall id */ - bufcall_id_t sm_ttybid; /* ttymodes changed bufcall */ - kmutex_t sm_umutex[1]; /* protects open code */ - kcondvar_t sm_ucv[1]; - dev_info_t *sm_dip; - dev_t sm_dev; - int sm_unit; - unsigned char *sm_hadkadbchar; - char *sm_nachar; - int sm_piocid; - tty_common_t sm_ttycommon[1]; - /* queue common data when open */ - char sm_path[MAXPATHLEN]; -} sm_lqi_t; - -/* - * This structure maintains the state of the console. - */ -typedef struct console { - dev_t sm_dev; /* the minor node of a console */ - int sm_muxid; /* STREAM's link identifier */ - io_mode_t sm_mode; /* I/O mode */ - boolean_t sm_obp_con; /* is it an OBP console */ - ihandle_t sm_i_ihdl; /* ihandle of the OBP input device */ - ihandle_t sm_o_ihdl; /* ihandle of the OBP output device */ - char *sm_path; /* device tree device path */ - char *sm_alias; /* device path alias */ -} sm_console_t; - -/* - * This structure contains the information for an open device. - * If an instance of it exists it is available as a named pointer: - */ -#define TTYMUXPTR "ttymuxconfig" - -typedef struct mux_state { - - /* protects ttymux configuration */ - kmutex_t sm_cons_mutex; - - /* Information about the standard I/O devices */ - sm_console_t sm_cons_stdin; - sm_console_t sm_cons_stdout; - - /* List of multiplexed serial consoles */ - uint_t sm_cons_cnt; - char *sm_ialias; - char *sm_oalias; - sm_console_t sm_cons_links[TTYMUX_MAX_LINKS]; - -} sm_mux_state_t; - -/* - * Driver instance private information. - */ -typedef -struct sm_ss -{ - dev_info_t *sm_dip; /* device tree information */ - uint_t sm_trflag; /* debug and information levels */ - sm_uqi_t *sm_lconsole; /* the current logical console */ - sm_mux_state_t *sm_ms; /* state associated with a console */ - - sm_lqi_t *sm_lqs; - sm_uqi_t *sm_uqs; - uint_t sm_break_abort_on; - uint_t sm_ctrla_abort_on; - - int sm_min_redundancy; - char sm_abs[SM_MAX_ABSLEN]; - -} sm_ss_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _TTYMUX_H */ diff --git a/usr/src/uts/sun/sys/ttymuxuser.h b/usr/src/uts/sun/sys/ttymuxuser.h deleted file mode 100644 index deb0d7b2e8..0000000000 --- a/usr/src/uts/sun/sys/ttymuxuser.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _TTYMUXUSER_H -#define _TTYMUXUSER_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/termios.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define TTYMUX_MOD_ID (0x540d) /* T^m */ -#define TTYMUX_DRVNAME "ttymux" - -#define TTYMUX_MAX_LINKS (16) -/* - * Generic serial multiplexor ioctls. - */ -#define _TTYMUXIOC (TTYMUX_MOD_ID<<8) -#define TTYMUX_ASSOC (_TTYMUXIOC | 1) -#define TTYMUX_DISASSOC (_TTYMUXIOC | 2) -#define TTYMUX_LIST (_TTYMUXIOC | 3) -#define TTYMUX_GETLINK (_TTYMUXIOC | 4) -/* - * Ioctls for serial multiplexors acting as the system console. - */ -#define TTYMUX_SETABORT (_TTYMUXIOC | 100) -#define TTYMUX_GETABORT (_TTYMUXIOC | 101) -#define TTYMUX_CONSDEV (_TTYMUXIOC | 102) -#define TTYMUX_GETABORTSTR (_TTYMUXIOC | 103) -#define TTYMUX_GETCONSOLES (_TTYMUXIOC | 104) -/* - * Optional control ioctl. - */ -#define TTYMUX_SETCTL (_TTYMUXIOC | 200) -#define TTYMUX_GETCTL (_TTYMUXIOC | 201) - -typedef enum {FORINPUT = 1, FOROUTPUT = 2, FORIO = 3} io_mode_t; - -/* - * Create or destroy associations TTYMUX_ASSOC and TTYMUX_DISASSOC - */ -#define AMSTAG (0x414d5354) -typedef struct ttymux_association { - dev_t ttymux_udev; /* the upper device to be associated */ - /* the device type of a linked lower stream */ - dev_t ttymux_ldev; - /* the linkid of a linked lower stream */ - int ttymux_linkid; - ulong_t ttymux_tag; /* tagged association */ - io_mode_t ttymux_ioflag; /* FORINPUT FOROUTPUT FORIO */ - /* OBP device path of ldev */ - char ttymux_path[MAXPATHLEN]; -} ttymux_assoc_t; - -/* - * List all links known to a mux driver TTYMUX_LIST - * If the user ioctl arg is NULL the return value is the - * number of links in the driver (to facilitate the user - * allocating enough space for the link information. - * Otherwise the ioctl arg should point to the following - * structure. nlinks indicates how many entries the user - * has allocated in the array. The return value indicates the - * number of entries that have been filled in. - * EINVAL if nlinks is < 1 - * EAGAIN if no resources. - */ -typedef struct ttymux_associations { - ulong_t ttymux_nlinks; - ttymux_assoc_t *ttymux_assocs; -} ttymux_assocs_t; - -/* - * Enable or disable aborting to the system monitor - * TTYMUX_SETABORT and TTYMUX_GETABORT - */ -enum ttymux_break_type {SOFTWARE_BREAK, HARDWARE_BREAK, SOFTHARD_BREAK}; - -typedef struct ttymux_abort { - /* apply request to this device */ - dev_t ttymux_ldev; - enum ttymux_break_type ttymux_method; - uint_t ttymux_enable; -} ttymux_abort_t; - -/* - * Ioctl acknowledgement policies. - */ -#define FIRSTACK 0 -#define LASTACK 1 -#define CONSENSUS 2 -#define PERIOCTL 3 - -/* - * Set or get the ioctl acknowledgement policy and masking of control bits - * TTYMUX_SETCTL and TTYMUX_GETCTL - */ - -struct ttymux_policy { - dev_t ttymux_udev; /* apply the request to this device */ - /* determines the method used to ack M_IOCTLS */ - int ttymux_policy; - tcflag_t ttymux_cmask; /* never set these control bits */ -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _TTYMUXUSER_H */ diff --git a/usr/src/uts/sun4u/Makefile.sun4u b/usr/src/uts/sun4u/Makefile.sun4u index 98b8ef8832..3d86669afd 100644 --- a/usr/src/uts/sun4u/Makefile.sun4u +++ b/usr/src/uts/sun4u/Makefile.sun4u @@ -167,13 +167,11 @@ IMPLEMENTATIONS += enchilada IMPLEMENTATIONS += taco IMPLEMENTATIONS += mpxu IMPLEMENTATIONS += excalibur -IMPLEMENTATIONS += montecarlo IMPLEMENTATIONS += serengeti IMPLEMENTATIONS += littleneck IMPLEMENTATIONS += daktari IMPLEMENTATIONS += cherrystone IMPLEMENTATIONS += fjlite -IMPLEMENTATIONS += snowbird IMPLEMENTATIONS += schumacher IMPLEMENTATIONS += blade IMPLEMENTATIONS += boston @@ -181,7 +179,6 @@ IMPLEMENTATIONS += seattle IMPLEMENTATIONS += chicago IMPLEMENTATIONS += sunfire IMPLEMENTATIONS += lw8 -IMPLEMENTATIONS += makaha IMPLEMENTATIONS += opl IMPLEMENTATIONS += lw2plus diff --git a/usr/src/uts/sun4u/makaha/Makefile b/usr/src/uts/sun4u/makaha/Makefile deleted file mode 100644 index 39130fb82b..0000000000 --- a/usr/src/uts/sun4u/makaha/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# uts/sun4u/makaha/Makefile -# -# This makefile drives the production of all Makaha system -# dependent modules for the sun4u architecture. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/makaha/Makefile.makaha - -def := TARGET= def -all := TARGET= all -install := TARGET= install -install_h := TARGET= install_h -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -lintlib := TARGET= lintlib -modlintlib := TARGET= modlintlib -modlist := TARGET= modlist -modlist := NO_STATE= -K $$MODSTATE$$$$ -clean.lint := TARGET= clean.lint -check := TARGET= check - -# -# Default build targets. -# -.KEEP_STATE: - -def all clean.lint clean clobber modlist: $(MAKAHA_KMODS) - -modlintlib: $(MAKAHA_KMODS) - -install: $(ROOT_MAKAHA_DIR) $(USR_MAKAHA_DIR) \ - $(USR_MAKAHA_INC_DIR) \ - $(USR_MAKAHA_SBIN_DIR) \ - $(USR_MAKAHA_LIB_DIR) \ - $(ROOT_SPUTNIK_DIR) \ - $(USR_SPUTNIK_DIR) \ - $(USR_SPUTNIK_INC_DIR) \ - $(USR_SPUTNIK_SBIN_DIR) \ - $(USR_SPUTNIK_LIB_DIR) \ - .WAIT $(MAKAHA_KMODS) \ - scsb acebus pcf8574 \ - acebus.conf se.conf scsb.conf \ - ttymux_dacf ttymux.conf - -acebus.conf: $(ROOT_MAKAHA_DRV_DIR_32) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_32)/$@ - $(CP) $(UTSBASE)/sun4u/makaha/io/$@ \ - $(ROOT_MAKAHA_DRV_DIR_32)/$@ - $(CHMOD) $(CFILEMODE) $(ROOT_MAKAHA_DRV_DIR_32)/$@ - -pcf8574: $(ROOT_MAKAHA_DRV_DIR_64) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_64)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_64)/$@ \ - $(ROOT_MAKAHA_DRV_DIR_64)/$@ - -acebus: $(ROOT_MAKAHA_DRV_DIR_64) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_64)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_64)/$@ \ - $(ROOT_MAKAHA_DRV_DIR_64)/$@ - -scsb: $(ROOT_MAKAHA_DRV_DIR_64) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_64)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_64)/$@ \ - $(ROOT_MAKAHA_DRV_DIR_64)/$@ - -scsb.conf: $(ROOT_MAKAHA_DRV_DIR_32) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_32)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_32)/$@ \ - $(ROOT_MAKAHA_DRV_DIR_32)/$@ - -se.conf: $(ROOT_MAKAHA_DRV_DIR_32) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_32)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_32)/$@ \ - $(ROOT_MAKAHA_DRV_DIR_32)/$@ - -ttymux_dacf: $(ROOT_MAKAHA_DACF_DIR_64) \ - $(ROOT_SPUTNIK_DACF_DIR_64) - -@$(RM) $(ROOT_MAKAHA_DACF_DIR_64)/$@ - -@$(RM) $(ROOT_SPUTNIK_DACF_DIR_64)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DACF_LINK_64)/$@ \ - $(ROOT_MAKAHA_DACF_DIR_64)/$@ - $(SYMLINK) $(ROOT_SPUTNIK_DACF_LINK_64)/$@ \ - $(ROOT_SPUTNIK_DACF_DIR_64)/$@ - - -ttymux.conf: $(ROOT_MAKAHA_DRV_DIR_32) $(ROOT_SPUTNIK_DRV_DIR_32) - -@$(RM) $(ROOT_MAKAHA_DRV_DIR_32)/$@ - -@$(RM) $(ROOT_SPUTNIK_DRV_DIR_32)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_32)/$@ \ - $(ROOT_MAKAHA_DRV_DIR_32)/$@ - $(SYMLINK) $(ROOT_MAKAHA_DRV_LINK_32)/$@ \ - $(ROOT_SPUTNIK_DRV_DIR_32)/$@ - -install_h check: - -lint: modlintlib - -# -# The 'lint.platmod' target lints the makaha platform module against -# the sun4u kernel. This ends up doing all the kernel cross-checks, -# so it takes a couple of minutes. -# Due to the low ROI, it's not run by default, but it's a good -# idea to run this if you change os/makaha.c. -# -LINT_LIBS = $(LINT_LIB) \ - -L$(MAKAHA_LINT_LIB_DIR) \ - -L$(LINT_LIB_DIR) $(LINT_KMODS:%=-l%) \ - $(CLOSED_LINT_KMODS:%=-l%) \ - -L$(SPARC_LIB_DIR) $(SPARC_LINTS:%=-l%) - -lint.platmod: modlintlib - @-$(ECHO) "\nMakaha Platform-dependent module: global crosschecks:" - @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) - -$(MAKAHA_KMODS): FRC - @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/makaha/Makefile.targ diff --git a/usr/src/uts/sun4u/makaha/Makefile.files b/usr/src/uts/sun4u/makaha/Makefile.files deleted file mode 100644 index 75c46641f3..0000000000 --- a/usr/src/uts/sun4u/makaha/Makefile.files +++ /dev/null @@ -1,43 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# uts/sun4u/makaha/Makefile.files -# -# -# This Makefile defines all file modules for the directory -# ust/sun4u/makaha and it's children. These are the source files -# which are sun4u "implementation architecture" dependent. -# - -# -# object lists -# -# Makaha specific driver relate modules -# -# -# Miscellaneous -# -INC_PATH += -I$(UTSBASE)/sun4u/makaha diff --git a/usr/src/uts/sun4u/makaha/Makefile.makaha b/usr/src/uts/sun4u/makaha/Makefile.makaha deleted file mode 100644 index e357e379e0..0000000000 --- a/usr/src/uts/sun4u/makaha/Makefile.makaha +++ /dev/null @@ -1,137 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# -# uts/sun4u/makaha/Makefile.makaha -# -# This makefile contains the common definitions for the -# sun4u Makaha system dependent modules. -# - -# -# Define directories. -# -MONTECARLO = SUNW,UltraSPARC-IIi-Netract -MAKAHA = SUNW,UltraSPARC-IIe-NetraCT-40 -SPUTNIK = SUNW,UltraSPARC-IIe-NetraCT-60 -ROOT_MAKAHA_DIR = $(ROOT_PLAT_DIR)/$(MAKAHA) -ROOT_MAKAHA_MOD_DIR = $(ROOT_MAKAHA_DIR)/kernel - -ROOT_MAKAHA_KERN_DIR_32 = $(ROOT_MAKAHA_MOD_DIR) -ROOT_MAKAHA_KERN_DIR_64 = $(ROOT_MAKAHA_MOD_DIR)/$(SUBDIR64) -ROOT_MAKAHA_DRV_DIR_32 = $(ROOT_MAKAHA_MOD_DIR)/drv -ROOT_MAKAHA_DRV_DIR_64 = $(ROOT_MAKAHA_MOD_DIR)/drv/$(SUBDIR64) -ROOT_MAKAHA_DRV_LINK_32 = $(ROOT_MAKAHA_DRV_DIR_32:$(ROOT_MAKAHA_DIR)%=../../../$(MONTECARLO)%) -ROOT_MAKAHA_DRV_LINK_64 = $(ROOT_MAKAHA_DRV_DIR_64:$(ROOT_MAKAHA_DIR)%=../../../../$(MONTECARLO)%) -ROOT_MAKAHA_MISC_DIR_32 = $(ROOT_MAKAHA_MOD_DIR)/misc -ROOT_MAKAHA_MISC_DIR_64 = $(ROOT_MAKAHA_MOD_DIR)/misc/$(SUBDIR64) -ROOT_MAKAHA_MISC_LINK_32 = $(ROOT_MAKAHA_MISC_DIR_32:$(ROOT_MAKAHA_DIR)%=../../../$(MONTECARLO)%) -ROOT_MAKAHA_MISC_LINK_64 = $(ROOT_MAKAHA_MISC_DIR_64:$(ROOT_MAKAHA_DIR)%=../../../../$(MONTECARLO)%) -ROOT_MAKAHA_DACF_DIR_32 = $(ROOT_MAKAHA_MOD_DIR)/dacf -ROOT_MAKAHA_DACF_DIR_64 = $(ROOT_MAKAHA_MOD_DIR)/dacf/$(SUBDIR64) -ROOT_MAKAHA_DACF_LINK_64 = $(ROOT_MAKAHA_DACF_DIR_64:$(ROOT_MAKAHA_DIR)%=../../../../$(MONTECARLO)%) - -ROOT_MAKAHA_KERN_DIR = $(ROOT_MAKAHA_KERN_DIR_$(CLASS)) -ROOT_MAKAHA_MISC_DIR = $(ROOT_MAKAHA_MISC_DIR_$(CLASS)) -ROOT_MAKAHA_DRV_DIR = $(ROOT_MAKAHA_DRV_DIR_$(CLASS)) -ROOT_MAKAHA_DACF_DIR = $(ROOT_MAKAHA_DACF_DIR_$(CLASS)) -ROOT_MAKAHA_DRV_LINK = $(ROOT_MAKAHA_DRV_LINK_$(CLASS)) -ROOT_MAKAHA_MISC_LINK = $(ROOT_MAKAHA_MISC_LINK_$(CLASS)) -ROOT_MAKAHA_DACF_LINK = $(ROOT_MAKAHA_DACF_LINK_$(CLASS)) - -ROOT_PLAT_MOD_DIRS += $(ROOT_MAKAHA_MOD_DIR) -ROOT_PLAT_MISC_DIRS += $(ROOT_MAKAHA_MISC_DIR) -ROOT_PLAT_MISC_DIRS_32 += $(ROOT_MAKAHA_MISC_DIR_32) -ROOT_PLAT_DRV_DIRS = $(ROOT_MAKAHA_DRV_DIR) - -USR_MAKAHA_DIR = $(USR_PLAT_DIR)/$(MAKAHA) -USR_MAKAHA_INC_DIR = $(USR_MAKAHA_DIR)/include -USR_MAKAHA_SBIN_DIR = $(USR_MAKAHA_DIR)/sbin -USR_MAKAHA_LIB_DIR = $(USR_MAKAHA_DIR)/lib -USR_MAKAHA_ISYS_DIR = $(USR_MAKAHA_INC_DIR)/sys - -MAKAHA_LINT_LIB_DIR= $(UTSBASE)/$(PLATFORM)/makaha/lint-libs/$(OBJS_DIR) -# -# Definitions for Sputnik, SUNW,UltraSPARC-IIe-NetraCT-60 platform -# -ROOT_SPUTNIK_DIR = $(ROOT_PLAT_DIR)/$(SPUTNIK) -ROOT_SPUTNIK_MOD_DIR = $(ROOT_SPUTNIK_DIR)/kernel - -ROOT_SPUTNIK_KERN_DIR_32 = $(ROOT_SPUTNIK_MOD_DIR) -ROOT_SPUTNIK_KERN_DIR_64 = $(ROOT_SPUTNIK_MOD_DIR)/$(SUBDIR64) -ROOT_SPUTNIK_DRV_DIR_32 = $(ROOT_SPUTNIK_MOD_DIR)/drv -ROOT_SPUTNIK_DRV_DIR_64 = $(ROOT_SPUTNIK_MOD_DIR)/drv/$(SUBDIR64) -ROOT_SPUTNIK_DRV_LINK_32 = $(ROOT_SPUTNIK_DRV_DIR_32:$(ROOT_SPUTNIK_DIR)%=../../../$(MAKAHA)%) -ROOT_SPUTNIK_DRV_LINK_64 = $(ROOT_SPUTNIK_DRV_DIR_64:$(ROOT_SPUTNIK_DIR)%=../../../../$(MAKAHA)%) -ROOT_SPUTNIK_MISC_DIR_32 = $(ROOT_SPUTNIK_MOD_DIR)/misc -ROOT_SPUTNIK_MISC_DIR_64 = $(ROOT_SPUTNIK_MOD_DIR)/misc/$(SUBDIR64) -ROOT_SPUTNIK_DACF_DIR_32 = $(ROOT_SPUTNIK_MOD_DIR)/dacf -ROOT_SPUTNIK_DACF_DIR_64 = $(ROOT_SPUTNIK_MOD_DIR)/dacf/$(SUBDIR64) -ROOT_SPUTNIK_DACF_LINK_64 = $(ROOT_SPUTNIK_DACF_DIR_64:$(ROOT_SPUTNIK_DIR)%=../../../../$(MONTECARLO)%) - -ROOT_SPUTNIK_KERN_DIR = $(ROOT_SPUTNIK_KERN_DIR_$(CLASS)) -ROOT_SPUTNIK_MISC_DIR = $(ROOT_SPUTNIK_MISC_DIR_$(CLASS)) -ROOT_SPUTNIK_DRV_DIR = $(ROOT_SPUTNIK_DRV_DIR_$(CLASS)) -ROOT_SPUTNIK_DACF_DIR = $(ROOT_SPUTNIK_DACF_DIR_$(CLASS)) -ROOT_SPUTNIK_DRV_LINK = $(ROOT_SPUTNIK_DRV_LINK_$(CLASS)) -ROOT_SPUTNIK_DACF_LINK = $(ROOT_SPUTNIK_DACF_LINK_$(CLASS)) - -ROOT_PLAT_MOD_DIRS += $(ROOT_SPUTNIK_MOD_DIR) -ROOT_PLAT_MISC_DIRS += $(ROOT_SPUTNIK_MISC_DIR) -ROOT_PLAT_MISC_DIRS_32 += $(ROOT_SPUTNIK_MISC_DIR_32) -ROOT_PLAT_DRV_DIRS = $(ROOT_SPUTNIK_DRV_DIR) - -USR_SPUTNIK_DIR = $(USR_PLAT_DIR)/$(SPUTNIK) -USR_SPUTNIK_INC_DIR = $(USR_SPUTNIK_DIR)/include -USR_SPUTNIK_SBIN_DIR = $(USR_SPUTNIK_DIR)/sbin -USR_SPUTNIK_LIB_DIR = $(USR_SPUTNIK_DIR)/lib -USR_SPUTNIK_ISYS_DIR = $(USR_SPUTNIK_INC_DIR)/sys - -# -# Montecarlo platform definitions for symbolic links -# -ROOT_MONTECARLO_DIR = $(ROOT_PLAT_DIR)/SUNW,UltraSPARC-IIi-Netract -ROOT_MONTECARLO_MOD_DIR = $(ROOT_MONTECARLO_DIR)/kernel -ROOT_MONTECARLO_KERN_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR) -ROOT_MONTECARLO_KERN_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/$(SUBDIR64) -ROOT_MONTECARLO_DRV_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR)/drv -ROOT_MONTECARLO_DRV_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/drv/$(SUBDIR64) -ROOT_MONTECARLO_MISC_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR)/misc -ROOT_MONTECARLO_MISC_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/misc/$(SUBDIR64) -ROOT_MONTECARLO_DACF_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR)/dacf -ROOT_MONTECARLO_DACF_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/dacf/$(SUBDIR64) - -ROOT_MONTECARLO_KERN_DIR = $(ROOT_MONTECARLO_KERN_DIR_$(CLASS)) -ROOT_MONTECARLO_MISC_DIR = $(ROOT_MONTECARLO_MISC_DIR_$(CLASS)) -ROOT_MONTECARLO_DRV_DIR = $(ROOT_MONTECARLO_DRV_DIR_$(CLASS)) -ROOT_MONTECARLO_DACF_DIR = $(ROOT_MONTECARLO_DACF_DIR_$(CLASS)) - -include $(UTSBASE)/sun4u/makaha/Makefile.files - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/Makefile.sun4u diff --git a/usr/src/uts/sun4u/makaha/Makefile.targ b/usr/src/uts/sun4u/makaha/Makefile.targ deleted file mode 100644 index dfdaf2bc75..0000000000 --- a/usr/src/uts/sun4u/makaha/Makefile.targ +++ /dev/null @@ -1,146 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# -# Common targets for sun4u MAKAHA implementation specific modules. -# -# -# Platform targets -# -$(ROOT_MAKAHA_DIR): $(ROOT_PLAT_DIR) - -$(INS.dir) - -.KEEP_STATE: - -# -# Rules for implementation subdirectories. -# -$(ROOT_MAKAHA_MOD_DIR): $(ROOT_MAKAHA_DIR) - -$(INS.dir) - -$(ROOT_MAKAHA_DRV_DIR_32): $(ROOT_MAKAHA_MOD_DIR) - -$(INS.dir) - -$(ROOT_MAKAHA_DRV_DIR_64): $(ROOT_MAKAHA_DRV_DIR_32) - -$(INS.dir) - -$(ROOT_MAKAHA_MISC_DIR_32): $(ROOT_MAKAHA_MOD_DIR) - -$(INS.dir) - -$(ROOT_MAKAHA_MISC_DIR_64): $(ROOT_MAKAHA_MISC_DIR_32) - -$(INS.dir) - -$(USR_MAKAHA_DIR): $(USR_PLAT_DIR) - -$(INS.dir) - -$(USR_MAKAHA_INC_DIR): $(USR_MAKAHA_DIR) - -$(INS.slink4) - -$(USR_MAKAHA_SBIN_DIR): $(USR_MAKAHA_DIR) - -$(INS.slink5) - -$(USR_MAKAHA_LIB_DIR): $(USR_MAKAHA_DIR) - -$(INS.dir) - -$(USR_MAKAHA_ISYS_DIR): $(USR_MAKAHA_DIR) - -$(INS.dir) - -$(ROOT_MAKAHA_MOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_MAKAHA_MOD_DIR) - $(INS.file) - -$(ROOT_MAKAHA_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_MAKAHA_MISC_DIR) - $(INS.file) - -$(ROOT_MAKAHA_DACF_DIR_32): $(ROOT_MAKAHA_MOD_DIR) - -$(INS.dir) - -$(ROOT_MAKAHA_DACF_DIR_64): $(ROOT_MAKAHA_DACF_DIR_32) - -$(INS.dir) - -$(ROOT_MAKAHA_DACF_DIR)/%: $(OBJS_DIR)/% $(ROOT_MAKAHA_DACF_DIR) - $(INS.file) - -$(ROOT_MAKAHA_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_MAKAHA_DRV_DIR) FRC - $(INS.file) - -# -# Create Sputnik platform directories -# -$(ROOT_SPUTNIK_DIR): $(ROOT_PLAT_DIR) - -$(INS.dir) - -$(ROOT_SPUTNIK_MOD_DIR): $(ROOT_SPUTNIK_DIR) - -$(INS.dir) - -$(ROOT_SPUTNIK_DRV_DIR_32): $(ROOT_SPUTNIK_MOD_DIR) - -$(INS.dir) - -$(ROOT_SPUTNIK_DRV_DIR_64): $(ROOT_SPUTNIK_DRV_DIR_32) - -$(INS.dir) - -$(ROOT_SPUTNIK_MISC_DIR_32): $(ROOT_SPUTNIK_MOD_DIR) - -$(INS.dir) - -$(ROOT_SPUTNIK_MISC_DIR_64): $(ROOT_SPUTNIK_MISC_DIR_32) - -$(INS.dir) - -$(USR_SPUTNIK_DIR): $(USR_PLAT_DIR) - -$(INS.dir) - -$(USR_SPUTNIK_INC_DIR): $(USR_SPUTNIK_DIR) - -$(INS.slink4) - -$(USR_SPUTNIK_SBIN_DIR): $(USR_SPUTNIK_DIR) - -$(INS.slink5) - -$(USR_SPUTNIK_LIB_DIR): $(USR_SPUTNIK_DIR) - -$(INS.dir) - -$(USR_SPUTNIK_ISYS_DIR): $(USR_SPUTNIK_DIR) - -$(INS.dir) - -$(ROOT_SPUTNIK_MOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_SPUTNIK_MOD_DIR) - $(INS.file) - -$(ROOT_SPUTNIK_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_SPUTNIK_MISC_DIR) - $(INS.file) - -$(ROOT_SPUTNIK_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_SPUTNIK_DRV_DIR) - $(INS.file) - -$(ROOT_SPUTNIK_DACF_DIR_32): $(ROOT_SPUTNIK_MOD_DIR) - -$(INS.dir) - -$(ROOT_SPUTNIK_DACF_DIR_64): $(ROOT_SPUTNIK_DACF_DIR_32) - -$(INS.dir) - -$(ROOT_SPUTNIK_DACF_DIR)/%: $(OBJS_DIR)/% $(ROOT_SPUTNIK_DACF_DIR) - $(INS.file) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4u/makaha/io/acebus.conf b/usr/src/uts/sun4u/makaha/io/acebus.conf deleted file mode 100644 index b35403edb6..0000000000 --- a/usr/src/uts/sun4u/makaha/io/acebus.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2001 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# Configuration file for Alarm card ebus driver. -# -ac-interrupt-map=0x14,0x400000,1,0,3; diff --git a/usr/src/uts/sun4u/montecarlo/Makefile b/usr/src/uts/sun4u/montecarlo/Makefile deleted file mode 100644 index 6c0dd673c7..0000000000 --- a/usr/src/uts/sun4u/montecarlo/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of all MonteCarlo system -# dependent modules for the sun4u architecture. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.montecarlo - -def := TARGET= def -all := TARGET= all -install := TARGET= install -install_h := TARGET= install_h -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -#lintlib := TARGET= lintlib -modlintlib := TARGET= modlintlib -modlist := TARGET= modlist -modlist := NO_STATE= -K $$MODSTATE$$$$ -clean.lint := TARGET= clean.lint -check := TARGET= check - -# -# Default build targets. -# -.KEEP_STATE: - -def all clean.lint clean clobber modlist: $(MONTECARLO_KMODS) - -modlintlib: $(MONTECARLO_KMODS) - -install: $(ROOT_MONTECARLO_DIR) \ - $(USR_MONTECARLO_DIR) \ - $(USR_MONTECARLO_INC_DIR) \ - $(USR_MONTECARLO_SBIN_DIR) \ - $(USR_MONTECARLO_LIB_DIR) \ - .WAIT $(MONTECARLO_KMODS) \ - se.conf ttymux.conf - -se.conf: $(ROOT_MONTECARLO_DRV_DIR_32) - -@$(RM) $(ROOT_MONTECARLO_DRV_DIR_32)/$@ - $(CP) $(UTSBASE)/sun4u/montecarlo/io/$@ \ - $(ROOT_MONTECARLO_DRV_DIR_32)/$@ - $(CHMOD) $(CFILEMODE) $(ROOT_MONTECARLO_DRV_DIR_32)/$@ - -ttymux.conf: $(ROOT_MONTECARLO_DRV_DIR_32) - -@$(RM) $(ROOT_MONTECARLO_DRV_DIR_32)/$@ - $(CP) $(UTSBASE)/sun4u/montecarlo/io/$@ \ - $(ROOT_MONTECARLO_DRV_DIR_32)/$@ - $(CHMOD) $(CFILEMODE) $(ROOT_MONTECARLO_DRV_DIR_32)/$@ - -install_h check: FRC - @cd sys; pwd; $(MAKE) $(TARGET) - -lint: modlintlib - -# -# The 'lint.platmod' target lints the montecarlo platform module against -# the sun4u kernel. This ends up doing all the kernel cross-checks, -# so it takes a couple of minutes. -# Due to the low ROI, it's not run by default, but it's a good -# idea to run this if you change os/montecarlo.c. -# -LINT_LIBS = $(LINT_LIB) \ - -L$(MONTECARLO_LINT_LIB_DIR) \ - -L$(LINT_LIB_DIR) $(LINT_KMODS:%=-l%) \ - $(CLOSED_LINT_KMODS:%=-l%) \ - -L$(SPARC_LIB_DIR) $(SPARC_LINTS:%=-l%) - -lint.platmod: modlintlib - @-$(ECHO) "\nMonteCarlo Platform-dependent module: global crosschecks:" - @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) - -$(MONTECARLO_KMODS): FRC - @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/Makefile.files b/usr/src/uts/sun4u/montecarlo/Makefile.files deleted file mode 100644 index 6058f93212..0000000000 --- a/usr/src/uts/sun4u/montecarlo/Makefile.files +++ /dev/null @@ -1,52 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines all file modules for the directory -# ust/sun4u/montecarlo and it's children. These are the source files -# which are sun4u "implementation architecture" dependent. -# - -# -# object lists -# -# Montecarlo specific modules -# -# Format: -# XXX_OBJS = xxx.o [yyy.o ...] -# - -ACEBUS_OBJS = acebus.o -TTYMUX_DACF_OBJS = ttymux_dacf.o ttymux_dacf_util.o -PCF8574_NCT_OBJS = pcf8574_nct.o -PCF8591_NCT_OBJS = pcf8591_nct.o -SCSB_OBJS = scsb.o hsc.o - -# -# Miscellaneous -# -INC_PATH += -I$(UTSBASE)/sun4u/montecarlo \ - -I$(UTSBASE)/sun4u \ - -I$(UTSBASE)/common diff --git a/usr/src/uts/sun4u/montecarlo/Makefile.montecarlo b/usr/src/uts/sun4u/montecarlo/Makefile.montecarlo deleted file mode 100644 index 91bc30f4c0..0000000000 --- a/usr/src/uts/sun4u/montecarlo/Makefile.montecarlo +++ /dev/null @@ -1,98 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile contains the common definitions for the -# sun4u MonteCarlo system dependent modules. -# - -# -# Define directories. -# -ROOT_MONTECARLO_DIR = $(ROOT_PLAT_DIR)/SUNW,UltraSPARC-IIi-Netract -ROOT_MONTECARLO_MOD_DIR = $(ROOT_MONTECARLO_DIR)/kernel - -ROOT_MONTECARLO_KERN_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR) -ROOT_MONTECARLO_KERN_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/$(SUBDIR64) -ROOT_MONTECARLO_DRV_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR)/drv -ROOT_MONTECARLO_DACF_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR)/dacf -ROOT_MONTECARLO_DACF_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/dacf/$(SUBDIR64) -ROOT_MONTECARLO_DRV_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/drv/$(SUBDIR64) -ROOT_MONTECARLO_MISC_DIR_32 = $(ROOT_MONTECARLO_MOD_DIR)/misc -ROOT_MONTECARLO_MISC_DIR_64 = $(ROOT_MONTECARLO_MOD_DIR)/misc/$(SUBDIR64) - -ROOT_MONTECARLO_KERN_DIR = $(ROOT_MONTECARLO_KERN_DIR_$(CLASS)) -ROOT_MONTECARLO_MISC_DIR = $(ROOT_MONTECARLO_MISC_DIR_$(CLASS)) -ROOT_MONTECARLO_DRV_DIR = $(ROOT_MONTECARLO_DRV_DIR_$(CLASS)) -ROOT_MONTECARLO_DACF_DIR = $(ROOT_MONTECARLO_DACF_DIR_$(CLASS)) - -ROOT_PLAT_MOD_DIRS += $(ROOT_MONTECARLO_MOD_DIR) -ROOT_PLAT_MISC_DIRS += $(ROOT_MONTECARLO_MISC_DIR) -ROOT_PLAT_MISC_DIRS_32 += $(ROOT_MONTECARLO_MISC_DIR_32) -ROOT_PLAT_DRV_DIRS = $(ROOT_MONTECARLO_DRV_DIR) -ROOT_PLAT_DACF_DIRS = $(ROOT_MONTECARLO_DACF_DIR) - -USR_MONTECARLO_DIR = $(USR_PLAT_DIR)/SUNW,UltraSPARC-IIi-Netract -USR_MONTECARLO_INC_DIR = $(USR_MONTECARLO_DIR)/include -USR_MONTECARLO_SBIN_DIR = $(USR_MONTECARLO_DIR)/sbin -USR_MONTECARLO_LIB_DIR = $(USR_MONTECARLO_DIR)/lib -USR_MONTECARLO_ISYS_DIR = $(USR_MONTECARLO_INC_DIR)/sys - -MONTECARLO_LINT_LIB_DIR= $(UTSBASE)/$(PLATFORM)/montecarlo/lint-libs/$(OBJS_DIR) - -# -# Define objects. -# - -include $(UTSBASE)/sun4u/montecarlo/Makefile.files - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/Makefile.sun4u - -# -# Define modules -# -MONTECARLO_KMODS = acebus pcf8574_nct pcf8591_nct scsb ttymux_dacf - -# -# we need the official MONTECARLO name here, and for the sun4u/montecarlo -# directory and Makefile.montecarlo -# for now we'll use montecarlo for workspace file/dir names -# and NORDICA_CP1500 for conditional code compiles, since that's our current -# test platform -# -MACHINE_DEFS += -DNORDICA_CP1500 - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED -LINTTAGS += -erroff=E_STATIC_UNUSED -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV diff --git a/usr/src/uts/sun4u/montecarlo/Makefile.rules b/usr/src/uts/sun4u/montecarlo/Makefile.rules deleted file mode 100644 index e5370ad1ac..0000000000 --- a/usr/src/uts/sun4u/montecarlo/Makefile.rules +++ /dev/null @@ -1,57 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines the build rules for the directory -# uts/sun4u/montecarlo and its children. -# -# The following two-level ordering must be maintained in this file. -# Lines are sorted first in order of decreasing specificity based on -# the first directory component. That is, sun4u rules come before -# sparc rules come before common rules. -# -# Lines whose initial directory components are equal are sorted -# alphabetically by the remaining components. - -# -# Section 1a: C object build rules -# -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/montecarlo/io/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/montecarlo/io/ttymux_dacf/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# -# Section 1b: Lint `object' build rules -# -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/montecarlo/io/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/montecarlo/io/ttymux_dacf/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/sun4u/montecarlo/Makefile.targ b/usr/src/uts/sun4u/montecarlo/Makefile.targ deleted file mode 100644 index 481d036cc5..0000000000 --- a/usr/src/uts/sun4u/montecarlo/Makefile.targ +++ /dev/null @@ -1,92 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# Common targets for sun4u MonteCarlo implementation specific modules. -# -# -# Platform targets -# -$(ROOT_MONTECARLO_DIR): $(ROOT_PLAT_DIR) - -$(INS.dir) - -.KEEP_STATE: - -# -# Rules for implementation subdirectories. -# -$(ROOT_MONTECARLO_MOD_DIR): $(ROOT_MONTECARLO_DIR) - -$(INS.dir) - -$(ROOT_MONTECARLO_DACF_DIR_32): $(ROOT_MONTECARLO_MOD_DIR) - -$(INS.dir) - -$(ROOT_MONTECARLO_DACF_DIR_64): $(ROOT_MONTECARLO_DACF_DIR_32) - -$(INS.dir) - -$(ROOT_MONTECARLO_DRV_DIR_32): $(ROOT_MONTECARLO_MOD_DIR) - -$(INS.dir) - -$(ROOT_MONTECARLO_DRV_DIR_64): $(ROOT_MONTECARLO_DRV_DIR_32) - -$(INS.dir) - -$(ROOT_MONTECARLO_MISC_DIR_32): $(ROOT_MONTECARLO_MOD_DIR) - -$(INS.dir) - -$(ROOT_MONTECARLO_MISC_DIR_64): $(ROOT_MONTECARLO_MISC_DIR_32) - -$(INS.dir) - -$(USR_MONTECARLO_DIR): $(USR_PLAT_DIR) - -$(INS.dir) - -$(USR_MONTECARLO_INC_DIR): $(USR_MONTECARLO_DIR) - -$(INS.slink4) - -$(USR_MONTECARLO_SBIN_DIR): $(USR_MONTECARLO_DIR) - -$(INS.slink5) - -$(USR_MONTECARLO_LIB_DIR): $(USR_MONTECARLO_DIR) - -$(INS.dir) - -$(USR_MONTECARLO_ISYS_DIR): $(USR_MONTECARLO_INC_DIR) - -$(INS.dir) - -$(ROOT_MONTECARLO_MOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_MONTECARLO_MOD_DIR) FRC - $(INS.file) - -$(ROOT_MONTECARLO_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_MONTECARLO_MISC_DIR) FRC - $(INS.file) - -$(ROOT_MONTECARLO_DACF_DIR)/%: $(OBJS_DIR)/% $(ROOT_MONTECARLO_DACF_DIR) - $(INS.file) - -$(ROOT_MONTECARLO_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_MONTECARLO_DRV_DIR) FRC - $(INS.file) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.rules -include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/acebus/Makefile b/usr/src/uts/sun4u/montecarlo/acebus/Makefile deleted file mode 100644 index 03b756c375..0000000000 --- a/usr/src/uts/sun4u/montecarlo/acebus/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the acebus driver kernel module -# for the Alarm Card. -# -# sun4u implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = acebus -OBJECTS = $(ACEBUS_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(ACEBUS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MONTECARLO_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.montecarlo - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -DNORDICA_CP1500 -DACEBUS_HOTPLUG -CERRWARN += -_gcc=-Wno-switch - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# Add our depedencies to LDFLAGS -# -LDFLAGS += -dy - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -LINT_LIB_DIR = $(MONTECARLO_LINT_LIB_DIR) -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/io/acebus.c b/usr/src/uts/sun4u/montecarlo/io/acebus.c deleted file mode 100644 index f1c92ea5b2..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/acebus.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. - */ - - -#include <sys/types.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/ddi_impldefs.h> -#include <sys/ddi_subrdefs.h> -#include <sys/pci.h> -#include <sys/pci/pci_nexus.h> -#include <sys/autoconf.h> -#include <sys/cmn_err.h> -#include <sys/errno.h> -#include <sys/kmem.h> -#include <sys/debug.h> -#include <sys/sysmacros.h> -#include <sys/acebus.h> - -#ifdef DEBUG -static uint_t acebus_debug_flags = 0; -#endif - -/* - * The values of the following variables are used to initialize - * the cache line size and latency timer registers in the ebus - * configuration header. Variables are used instead of constants - * to allow tuning from the /etc/system file. - */ -static uint8_t acebus_cache_line_size = 0x10; /* 64 bytes */ -static uint8_t acebus_latency_timer = 0x40; /* 64 PCI cycles */ - -/* - * function prototypes for bus ops routines: - */ -static int -acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, - off_t offset, off_t len, caddr_t *addrp); -static int -acebus_ctlops(dev_info_t *dip, dev_info_t *rdip, - ddi_ctl_enum_t op, void *arg, void *result); -static int -acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, - ddi_intr_handle_impl_t *hdlp, void *result); - -/* - * function prototypes for dev ops routines: - */ -static int acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); -static int acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); - -/* - * general function prototypes: - */ -static int acebus_config(ebus_devstate_t *ebus_p); -static int acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip, - ebus_regspec_t *ebus_rp, pci_regspec_t *rp); -static int acebus_get_ranges_prop(ebus_devstate_t *ebus_p); -#ifdef ACEBUS_HOTPLUG -static int acebus_update_props(ebus_devstate_t *ebus_p); -static int acebus_set_imap(dev_info_t *dip); -#endif - -#define getprop(dip, name, addr, intp) \ - ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \ - (name), (caddr_t)(addr), (intp)) - -/* - * bus ops and dev ops structures: - */ -static struct bus_ops acebus_bus_ops = { - BUSO_REV, - acebus_map, - NULL, - NULL, - NULL, - i_ddi_map_fault, - NULL, - ddi_dma_allochdl, - ddi_dma_freehdl, - ddi_dma_bindhdl, - ddi_dma_unbindhdl, - ddi_dma_flush, - ddi_dma_win, - ddi_dma_mctl, - acebus_ctlops, - ddi_bus_prop_op, - 0, /* (*bus_get_eventcookie)(); */ - 0, /* (*bus_add_eventcall)(); */ - 0, /* (*bus_remove_eventcall)(); */ - 0, /* (*bus_post_event)(); */ - 0, /* (*bus_intr_ctl)(); */ - NULL, /* (*bus_config)(); */ - NULL, /* (*bus_unconfig)(); */ - NULL, /* (*bus_fm_init)(); */ - NULL, /* (*bus_fm_fini)(); */ - NULL, /* (*bus_fm_access_enter)(); */ - NULL, /* (*bus_fm_access_fini)(); */ - NULL, /* (*bus_power)(); */ - acebus_intr_ops /* (*bus_intr_op)(); */ -}; - -static struct dev_ops acebus_ops = { - DEVO_REV, - 0, - ddi_no_info, - nulldev, - nulldev, - acebus_attach, - acebus_detach, - nodev, - (struct cb_ops *)0, - &acebus_bus_ops, - NULL, - ddi_quiesce_not_supported, /* devo_quiesce */ -}; - -/* - * module definitions: - */ -#include <sys/modctl.h> -extern struct mod_ops mod_driverops; - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "Alarm Card ebus nexus", /* Name of module. */ - &acebus_ops, /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, (void *)&modldrv, NULL -}; - -/* - * driver global data: - */ -static void *per_acebus_state; /* per-ebus soft state pointer */ - - -int -_init(void) -{ - int e; - - /* - * Initialize per-ebus soft state pointer. - */ - e = ddi_soft_state_init(&per_acebus_state, sizeof (ebus_devstate_t), 1); - if (e != 0) - return (e); - - /* - * Install the module. - */ - e = mod_install(&modlinkage); - if (e != 0) - ddi_soft_state_fini(&per_acebus_state); - return (e); -} - -int -_fini(void) -{ - int e; - - /* - * Remove the module. - */ - e = mod_remove(&modlinkage); - if (e != 0) - return (e); - - /* - * Free the soft state info. - */ - ddi_soft_state_fini(&per_acebus_state); - return (e); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* device driver entry points */ - -/* - * attach entry point: - * - * normal attach: - * - * create soft state structure (dip, reg, nreg and state fields) - * map in configuration header - * make sure device is properly configured - * report device - */ -static int -acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - ebus_devstate_t *ebus_p; /* per ebus state pointer */ - int instance; - - DBG1(D_ATTACH, NULL, "dip=%x\n", dip); - switch (cmd) { - case DDI_ATTACH: - - /* - * Allocate soft state for this instance. - */ - instance = ddi_get_instance(dip); - if (ddi_soft_state_zalloc(per_acebus_state, instance) - != DDI_SUCCESS) { - DBG(D_ATTACH, NULL, "failed to alloc soft state\n"); - return (DDI_FAILURE); - } - ebus_p = get_acebus_soft_state(instance); - ebus_p->dip = dip; - - /* - * Make sure the master enable and memory access enable - * bits are set in the config command register. - */ - if (!acebus_config(ebus_p)) { - free_acebus_soft_state(instance); - return (DDI_FAILURE); - } - - (void) ddi_prop_create(DDI_DEV_T_NONE, dip, - DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0); - /* Get our ranges property for mapping child registers. */ - if (acebus_get_ranges_prop(ebus_p) != DDI_SUCCESS) { - free_acebus_soft_state(instance); - return (DDI_FAILURE); - } - - /* - * Make the state as attached and report the device. - */ - ebus_p->state = ATTACHED; - ddi_report_dev(dip); - DBG(D_ATTACH, ebus_p, "returning\n"); - return (DDI_SUCCESS); - - case DDI_RESUME: - - instance = ddi_get_instance(dip); - ebus_p = get_acebus_soft_state(instance); - - /* - * Make sure the master enable and memory access enable - * bits are set in the config command register. - */ - if (!acebus_config(ebus_p)) { - free_acebus_soft_state(instance); - return (DDI_FAILURE); - } - - ebus_p->state = RESUMED; - return (DDI_SUCCESS); - } - return (DDI_FAILURE); -} - -/* - * detach entry point: - */ -static int -acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - ebus_devstate_t *ebus_p = get_acebus_soft_state(instance); - - switch (cmd) { - case DDI_DETACH: - DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip); - ddi_prop_remove_all(dip); - kmem_free(ebus_p->rangep, ebus_p->range_cnt * - sizeof (struct ebus_pci_rangespec)); - free_acebus_soft_state(instance); - return (DDI_SUCCESS); - - case DDI_SUSPEND: - DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip); - ebus_p->state = SUSPENDED; - return (DDI_SUCCESS); - } - return (DDI_FAILURE); -} - - -static int -acebus_get_ranges_prop(ebus_devstate_t *ebus_p) -{ - struct ebus_pci_rangespec *rangep; - int nrange, range_len; - - if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip, DDI_PROP_DONTPASS, - "ranges", (caddr_t)&rangep, &range_len) != DDI_SUCCESS) { - - cmn_err(CE_WARN, "%s%d: can't get ranges property", - ddi_get_name(ebus_p->dip), ddi_get_instance(ebus_p->dip)); - return (DDI_ME_REGSPEC_RANGE); - } - - nrange = range_len / sizeof (struct ebus_pci_rangespec); - - if (nrange == 0) { - kmem_free(rangep, range_len); - return (DDI_FAILURE); - } - -#ifdef DEBUG - { - int i; - - for (i = 0; i < nrange; i++) { - DBG5(D_MAP, ebus_p, - "ebus range addr 0x%x.0x%x PCI range " - "addr 0x%x.0x%x.0x%x ", rangep[i].ebus_phys_hi, - rangep[i].ebus_phys_low, rangep[i].pci_phys_hi, - rangep[i].pci_phys_mid, rangep[i].pci_phys_low); - DBG1(D_MAP, ebus_p, "Size 0x%x\n", rangep[i].rng_size); - } - } -#endif /* DEBUG */ - - ebus_p->rangep = rangep; - ebus_p->range_cnt = nrange; - - return (DDI_SUCCESS); -} - - -/* bus driver entry points */ - -/* - * bus map entry point: - * - * if map request is for an rnumber - * get the corresponding regspec from device node - * build a new regspec in our parent's format - * build a new map_req with the new regspec - * call up the tree to complete the mapping - */ -static int -acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, - off_t off, off_t len, caddr_t *addrp) -{ - ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); - ebus_regspec_t *ebus_rp, *ebus_regs; - pci_regspec_t pci_reg; - ddi_map_req_t p_map_request; - int rnumber, i, n; - int rval = DDI_SUCCESS; - - /* - * Handle the mapping according to its type. - */ - DBG4(D_MAP, ebus_p, "rdip=%s%d: off=%x len=%x\n", - ddi_get_name(rdip), ddi_get_instance(rdip), off, len); - switch (mp->map_type) { - case DDI_MT_REGSPEC: - - /* - * We assume the register specification is in ebus format. - * We must convert it into a PCI format regspec and pass - * the request to our parent. - */ - DBG3(D_MAP, ebus_p, "rdip=%s%d: REGSPEC - handlep=%x\n", - ddi_get_name(rdip), ddi_get_instance(rdip), - mp->map_handlep); - ebus_rp = (ebus_regspec_t *)mp->map_obj.rp; - break; - - case DDI_MT_RNUMBER: - - /* - * Get the "reg" property from the device node and convert - * it to our parent's format. - */ - rnumber = mp->map_obj.rnumber; - DBG4(D_MAP, ebus_p, "rdip=%s%d: rnumber=%x handlep=%x\n", - ddi_get_name(rdip), ddi_get_instance(rdip), - rnumber, mp->map_handlep); - - if (getprop(rdip, "reg", &ebus_regs, &i) != DDI_SUCCESS) { - DBG(D_MAP, ebus_p, "can't get reg property\n"); - return (DDI_ME_RNUMBER_RANGE); - } - n = i / sizeof (ebus_regspec_t); - - if (rnumber < 0 || rnumber >= n) { - DBG(D_MAP, ebus_p, "rnumber out of range\n"); - return (DDI_ME_RNUMBER_RANGE); - } - ebus_rp = &ebus_regs[rnumber]; - break; - - default: - return (DDI_ME_INVAL); - - } - - /* Adjust our reg property with offset and length */ - ebus_rp->addr_low += off; - if (len) - ebus_rp->size = len; - - /* - * Now we have a copy the "reg" entry we're attempting to map. - * Translate this into our parents PCI address using the ranges - * property. - */ - rval = acebus_apply_range(ebus_p, rdip, ebus_rp, &pci_reg); - - if (mp->map_type == DDI_MT_RNUMBER) - kmem_free((caddr_t)ebus_regs, i); - - if (rval != DDI_SUCCESS) - return (rval); - -#ifdef ACEBUS_HOTPLUG - /* - * The map operation provides a translated (not a re-assigned, or - * relocated) ebus address for the child in its address space(range). - * Ebus address space is relocatible but its child address space - * is not. As specified by their 'reg' properties, they reside - * at a fixed offset in their parent's (ebus's) space. - * - * By setting this bit, we will not run into HostPCI nexus - * trying to relocate a translated ebus address (which is already - * relocated) and failing the operation. - * The reason for doing this here is that the PCI hotplug configurator - * always marks the ebus space as relocatible (unlike OBP) and that - * information is implied for the child too, which is wrong. - */ - pci_reg.pci_phys_hi |= PCI_RELOCAT_B; -#endif -#ifdef DEBUG - DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n", - pci_reg.pci_phys_hi, - pci_reg.pci_phys_mid, - pci_reg.pci_phys_low, - pci_reg.pci_size_hi, - pci_reg.pci_size_low); -#endif - - p_map_request = *mp; - p_map_request.map_type = DDI_MT_REGSPEC; - p_map_request.map_obj.rp = (struct regspec *)&pci_reg; - rval = ddi_map(dip, &p_map_request, 0, 0, addrp); - DBG1(D_MAP, ebus_p, "parent returned %x\n", rval); - return (rval); -} - - -static int -acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip, - ebus_regspec_t *ebus_rp, pci_regspec_t *rp) -{ - int b; - int rval = DDI_SUCCESS; - struct ebus_pci_rangespec *rangep = ebus_p->rangep; - int nrange = ebus_p->range_cnt; - static const char out_of_range[] = - "Out of range register specification from device node <%s>"; - - DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n", - ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size); - - for (b = 0; b < nrange; ++b, ++rangep) { - - /* Check for the correct space */ - if (ebus_rp->addr_hi == rangep->ebus_phys_hi) - /* See if we fit in this range */ - if ((ebus_rp->addr_low >= - rangep->ebus_phys_low) && - ((ebus_rp->addr_low + ebus_rp->size - 1) - <= (rangep->ebus_phys_low + - rangep->rng_size - 1))) { - uint_t addr_offset = ebus_rp->addr_low - - rangep->ebus_phys_low; - /* - * Use the range entry to translate - * the EBUS physical address into the - * parents PCI space. - */ - rp->pci_phys_hi = - rangep->pci_phys_hi; - rp->pci_phys_mid = rangep->pci_phys_mid; - rp->pci_phys_low = - rangep->pci_phys_low + addr_offset; - rp->pci_size_hi = 0; - rp->pci_size_low = - min(ebus_rp->size, (rangep->rng_size - - addr_offset)); - - DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ", - rangep->ebus_phys_hi, - rangep->ebus_phys_low); - DBG4(D_MAP, ebus_p, "Parent hi0x%x " - "mid0x%x lo0x%x size 0x%x\n", - rangep->pci_phys_hi, - rangep->pci_phys_mid, - rangep->pci_phys_low, - rangep->rng_size); - - break; - } - } - - if (b == nrange) { - cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip)); - return (DDI_ME_REGSPEC_RANGE); - } - - return (rval); -} - - -/* - * control ops entry point: - * - * Requests handled completely: - * DDI_CTLOPS_INITCHILD - * DDI_CTLOPS_UNINITCHILD - * DDI_CTLOPS_REPORTDEV - * DDI_CTLOPS_REGSIZE - * DDI_CTLOPS_NREGS - * - * All others passed to parent. - */ -static int -acebus_ctlops(dev_info_t *dip, dev_info_t *rdip, - ddi_ctl_enum_t op, void *arg, void *result) -{ -#ifdef DEBUG - ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); -#endif - ebus_regspec_t *ebus_rp; - int32_t reglen; - int i, n; - char name[10]; - - switch (op) { - case DDI_CTLOPS_INITCHILD: { - dev_info_t *child = (dev_info_t *)arg; - /* - * Set the address portion of the node name based on the - * address/offset. - */ - DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n", - ddi_get_name(child), ddi_get_instance(child)); - - if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, - "reg", (caddr_t)&ebus_rp, ®len) != DDI_SUCCESS) { - - DBG(D_CTLOPS, ebus_p, "can't get reg property\n"); - return (DDI_FAILURE); - - } - - (void) sprintf(name, "%x,%x", ebus_rp->addr_hi, - ebus_rp->addr_low); - ddi_set_name_addr(child, name); - kmem_free((caddr_t)ebus_rp, reglen); - - ddi_set_parent_data(child, NULL); - - return (DDI_SUCCESS); - - } - - case DDI_CTLOPS_UNINITCHILD: - DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n", - ddi_get_name((dev_info_t *)arg), - ddi_get_instance((dev_info_t *)arg)); - ddi_set_name_addr((dev_info_t *)arg, NULL); - ddi_remove_minor_node((dev_info_t *)arg, NULL); - impl_rem_dev_props((dev_info_t *)arg); - return (DDI_SUCCESS); - - case DDI_CTLOPS_REPORTDEV: - - DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n", - ddi_get_name(rdip), ddi_get_instance(rdip)); - cmn_err(CE_CONT, "?%s%d at %s%d: offset %s\n", - ddi_driver_name(rdip), ddi_get_instance(rdip), - ddi_driver_name(dip), ddi_get_instance(dip), - ddi_get_name_addr(rdip)); - return (DDI_SUCCESS); - - case DDI_CTLOPS_REGSIZE: - - DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n", - ddi_get_name(rdip), ddi_get_instance(rdip)); - if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) { - DBG(D_CTLOPS, ebus_p, "can't get reg property\n"); - return (DDI_FAILURE); - } - n = i / sizeof (ebus_regspec_t); - if (*(int *)arg < 0 || *(int *)arg >= n) { - DBG(D_MAP, ebus_p, "rnumber out of range\n"); - kmem_free((caddr_t)ebus_rp, i); - return (DDI_FAILURE); - } - *((off_t *)result) = ebus_rp[*(int *)arg].size; - kmem_free((caddr_t)ebus_rp, i); - return (DDI_SUCCESS); - - case DDI_CTLOPS_NREGS: - - DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_NREGS: rdip=%s%d\n", - ddi_get_name(rdip), ddi_get_instance(rdip)); - if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) { - DBG(D_CTLOPS, ebus_p, "can't get reg property\n"); - return (DDI_FAILURE); - } - *((uint_t *)result) = i / sizeof (ebus_regspec_t); - kmem_free((caddr_t)ebus_rp, i); - return (DDI_SUCCESS); - } - - /* - * Now pass the request up to our parent. - */ - DBG2(D_CTLOPS, ebus_p, "passing request to parent: rdip=%s%d\n", - ddi_get_name(rdip), ddi_get_instance(rdip)); - return (ddi_ctlops(dip, rdip, op, arg, result)); -} - -struct ebus_string_to_pil { - int8_t *string; - uint32_t pil; -}; - -static struct ebus_string_to_pil acebus_name_to_pil[] = {{"SUNW,CS4231", 9}, - {"fdthree", 8}, - {"ecpp", 3}, - {"su", 12}, - {"se", 12}, - {"power", 14}}; - -static struct ebus_string_to_pil acebus_device_type_to_pil[] = {{"serial", 12}, - {"block", 8}}; - -static int -acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, - ddi_intr_handle_impl_t *hdlp, void *result) -{ -#ifdef DEBUG - ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); -#endif - int8_t *name, *device_type; - int32_t i, max_children, max_device_types, len; - - /* - * NOTE: These ops below will never be supported in this nexus - * driver, hence they always return immediately. - */ - switch (intr_op) { - case DDI_INTROP_GETCAP: - *(int *)result = DDI_INTR_FLAG_LEVEL; - return (DDI_SUCCESS); - case DDI_INTROP_SUPPORTED_TYPES: - *(int *)result = i_ddi_get_intx_nintrs(rdip) ? - DDI_INTR_TYPE_FIXED : 0; - return (DDI_SUCCESS); - case DDI_INTROP_SETCAP: - case DDI_INTROP_SETMASK: - case DDI_INTROP_CLRMASK: - case DDI_INTROP_GETPENDING: - return (DDI_ENOTSUP); - default: - break; - } - - if (hdlp->ih_pri) - goto done; - - /* - * This is a hack to set the PIL for the devices under ebus. - * We first look up a device by it's specific name, if we can't - * match the name, we try and match it's device_type property. - * Lastly we default a PIL level of 1. - */ - DBG1(D_INTR, ebus_p, "ebus_p %p\n", ebus_p); - - name = ddi_get_name(rdip); - max_children = sizeof (acebus_name_to_pil) / - sizeof (struct ebus_string_to_pil); - - for (i = 0; i < max_children; i++) { - if (strcmp(acebus_name_to_pil[i].string, name) == 0) { - DBG2(D_INTR, ebus_p, "child name %s; match PIL %d\n", - acebus_name_to_pil[i].string, - acebus_name_to_pil[i].pil); - - hdlp->ih_pri = acebus_name_to_pil[i].pil; - goto done; - } - } - - if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, - "device_type", (caddr_t)&device_type, &len) == DDI_SUCCESS) { - - max_device_types = sizeof (acebus_device_type_to_pil) / - sizeof (struct ebus_string_to_pil); - - for (i = 0; i < max_device_types; i++) { - if (strcmp(acebus_device_type_to_pil[i].string, - device_type) == 0) { - DBG2(D_INTR, ebus_p, - "Device type %s; match PIL %d\n", - acebus_device_type_to_pil[i].string, - acebus_device_type_to_pil[i].pil); - - hdlp->ih_pri = acebus_device_type_to_pil[i].pil; - break; - } - } - - kmem_free(device_type, len); - } - - /* - * If we get here, we need to set a default value - * for the PIL. - */ - if (hdlp->ih_pri == 0) { - hdlp->ih_pri = 1; - cmn_err(CE_WARN, "%s%d assigning default interrupt level %d " - "for device %s%d", ddi_driver_name(dip), - ddi_get_instance(dip), hdlp->ih_pri, ddi_driver_name(rdip), - ddi_get_instance(rdip)); - } - -done: - /* Pass up the request to our parent. */ - return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)); -} - - -static int -acebus_config(ebus_devstate_t *ebus_p) -{ - ddi_acc_handle_t conf_handle; - uint16_t comm; -#ifdef ACEBUS_HOTPLUG - int tcr_reg; - caddr_t csr_io; - ddi_device_acc_attr_t csr_attr = { /* CSR map attributes */ - DDI_DEVICE_ATTR_V0, - DDI_STRUCTURE_LE_ACC, - DDI_STRICTORDER_ACC - }; - ddi_acc_handle_t csr_handle; -#endif - - /* - * Make sure the master enable and memory access enable - * bits are set in the config command register. - */ - if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS) - return (0); - - comm = pci_config_get16(conf_handle, PCI_CONF_COMM), -#ifdef DEBUG - DBG1(D_ATTACH, ebus_p, "command register was 0x%x\n", comm); -#endif - comm |= (PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_SERR_ENABLE| - PCI_COMM_PARITY_DETECT); - pci_config_put16(conf_handle, PCI_CONF_COMM, comm), -#ifdef DEBUG - DBG1(D_MAP, ebus_p, "command register is now 0x%x\n", - pci_config_get16(conf_handle, PCI_CONF_COMM)); -#endif - pci_config_put8(conf_handle, PCI_CONF_CACHE_LINESZ, - (uchar_t)acebus_cache_line_size); - pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER, - (uchar_t)acebus_latency_timer); - pci_config_teardown(&conf_handle); - -#ifdef ACEBUS_HOTPLUG - if (acebus_update_props(ebus_p) != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s%d: Could not update special properties.", - ddi_driver_name(ebus_p->dip), - ddi_get_instance(ebus_p->dip)); - return (0); - } - - if (ddi_regs_map_setup(ebus_p->dip, CSR_IO_RINDEX, - (caddr_t *)&csr_io, 0, CSR_SIZE, &csr_attr, - &csr_handle) != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s%d: Could not map Ebus CSR.", - ddi_driver_name(ebus_p->dip), - ddi_get_instance(ebus_p->dip)); - } -#ifdef DEBUG - if (acebus_debug_flags) { - DBG3(D_ATTACH, ebus_p, "tcr[123] = %x,%x,%x\n", - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR1_OFF)), - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR2_OFF)), - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR3_OFF))); - DBG2(D_ATTACH, ebus_p, "pmd-aux=%x, freq-aux=%x\n", - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - PMD_AUX_OFF)), - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - FREQ_AUX_OFF))); -#ifdef ACEBUS_DEBUG - for (comm = 0; comm < 4; comm++) - prom_printf("dcsr%d=%x, dacr%d=%x, dbcr%d=%x\n", comm, - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - 0x700000+(0x2000*comm))), comm, - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - 0x700000+(0x2000*comm)+4)), comm, - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - 0x700000+(0x2000*comm)+8))); -#endif - } /* acebus_debug_flags */ -#endif - /* If TCR registers are not initialized, initialize them here */ - tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR1_OFF)); - if ((tcr_reg == 0) || (tcr_reg == -1)) - ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF), - TCR1_REGVAL); - tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR2_OFF)); - if ((tcr_reg == 0) || (tcr_reg == -1)) - ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF), - TCR2_REGVAL); - tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR3_OFF)); - if ((tcr_reg == 0) || (tcr_reg == -1)) - ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF), - TCR3_REGVAL); -#ifdef DEBUG - if (acebus_debug_flags) { - DBG3(D_ATTACH, ebus_p, "wrote tcr[123] = %x,%x,%x\n", - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR1_OFF)), - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR2_OFF)), - ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + - TCR3_OFF))); - } -#endif - - ddi_regs_map_free(&csr_handle); -#endif /* ACEBUS_HOTPLUG */ - return (1); /* return success */ -} - -#ifdef DEBUG -extern void prom_printf(const char *, ...); - -static void -acebus_debug(uint_t flag, ebus_devstate_t *ebus_p, char *fmt, - uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5) -{ - char *s; - - if (acebus_debug_flags & flag) { - switch (flag) { - case D_ATTACH: - s = "attach"; break; - case D_DETACH: - s = "detach"; break; - case D_MAP: - s = "map"; break; - case D_CTLOPS: - s = "ctlops"; break; - case D_INTR: - s = "intr"; break; - } - if (ebus_p) - cmn_err(CE_CONT, "%s%d: %s: ", - ddi_get_name(ebus_p->dip), - ddi_get_instance(ebus_p->dip), s); - else - cmn_err(CE_CONT, "ebus: "); - cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); - } -} -#endif - -#ifdef ACEBUS_HOTPLUG -#define EBUS_CHILD_PHYS_LOW_RANGE 0x10 -#define EBUS_CHILD_PHYS_HI_RANGE 0x14 - -static int -acebus_update_props(ebus_devstate_t *ebus_p) -{ - dev_info_t *dip = ebus_p->dip; - struct ebus_pci_rangespec er[2], *erp; - pci_regspec_t *pci_rp, *prp; - int length, rnums, imask[3], i, found = 0; - - /* - * If "ranges" property is found, then the device is initialized - * by OBP, hence simply return. - * Otherwise we create all the properties here. - */ - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "ranges", (int **)&erp, (uint_t *)&length) == DDI_PROP_SUCCESS) { - ddi_prop_free(erp); - return (DDI_SUCCESS); - } - - /* - * interrupt-map is the only property that comes from a .conf file. - * Since it doesn't have the nodeid field set, it must be done here. - * Other properties can come from OBP or created here. - */ - if (acebus_set_imap(dip) != DDI_SUCCESS) { - return (DDI_FAILURE); - } - - /* - * Create the "ranges" property. - * Ebus has BAR0 and BAR1 allocated (both in memory space). - * Other BARs are 0. - * Hence there are 2 memory ranges it operates in. (one for each BAR). - * ie. there are 2 entries in its ranges property. - */ - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "assigned-addresses", - (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, "%s%d: Could not get assigned-addresses", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_FAILURE); - } - /* - * Create the 1st mem range in which it operates corresponding - * to BAR0 - */ - er[0].ebus_phys_hi = EBUS_CHILD_PHYS_LOW_RANGE; - rnums = (length * sizeof (int))/sizeof (pci_regspec_t); - for (i = 0; i < rnums; i++) { - prp = pci_rp + i; - if (PCI_REG_REG_G(prp->pci_phys_hi) == er[0].ebus_phys_hi) { - found = 1; - break; - } - } - if (!found) { - cmn_err(CE_WARN, "No assigned space for memory range 0."); - ddi_prop_free(pci_rp); - return (DDI_FAILURE); - } - found = 0; - er[0].ebus_phys_low = 0; - er[0].pci_phys_hi = prp->pci_phys_hi; - er[0].pci_phys_mid = prp->pci_phys_mid; - er[0].pci_phys_low = prp->pci_phys_low; - er[0].rng_size = prp->pci_size_low; - - /* - * Create the 2nd mem range in which it operates corresponding - * to BAR1 - */ - er[1].ebus_phys_hi = EBUS_CHILD_PHYS_HI_RANGE; - for (i = 0; i < rnums; i++) { - prp = pci_rp + i; - if (PCI_REG_REG_G(prp->pci_phys_hi) == er[1].ebus_phys_hi) { - found = 1; - break; - } - } - if (!found) { - cmn_err(CE_WARN, "No assigned space for memory range 1."); - ddi_prop_free(pci_rp); - return (DDI_FAILURE); - } - er[1].ebus_phys_low = 0; - er[1].pci_phys_hi = prp->pci_phys_hi; - er[1].pci_phys_mid = prp->pci_phys_mid; - er[1].pci_phys_low = prp->pci_phys_low; - er[1].rng_size = prp->pci_size_low; - - ddi_prop_free(pci_rp); - length = sizeof (er) / sizeof (int); - if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, - "ranges", (int *)er, length) != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, "%s%d: Could not create ranges property", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_FAILURE); - } - /* The following properties are as defined by PCI 1275 bindings. */ - if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, - "#address-cells", 2) != DDI_PROP_SUCCESS) - return (DDI_FAILURE); - if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, - "#size-cells", 1) != DDI_PROP_SUCCESS) - return (DDI_FAILURE); - if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, - "#interrupt-cells", 1) != DDI_PROP_SUCCESS) - return (DDI_FAILURE); - - imask[0] = 0x1f; - imask[1] = 0x00ffffff; - imask[2] = 0x00000003; - length = sizeof (imask) / sizeof (int); - if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, - "interrupt-map-mask", (int *)imask, length) != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, "%s%d: Could not update imap mask property", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -/* - * This function takes in the ac-interrupt-map property from the .conf file, - * fills in the 'nodeid' information and then creates the 'interrupt-map' - * property. - */ -static int -acebus_set_imap(dev_info_t *dip) -{ - int *imapp, *timapp, length, num, i, default_ival = 0; - dev_info_t *tdip = dip; - int *port_id, imap_ok = 1; - int ilength; - int acebus_default_se_imap[5]; - - /* - * interrupt-map is specified via .conf file in hotplug mode, - * since the child configuration is static. - * It could even be hardcoded in the driver. - */ - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "ac-interrupt-map", (int **)&imapp, (uint_t *)&ilength) != - DDI_PROP_SUCCESS) { - /* assume default implementation */ - acebus_default_se_imap[0] = 0x14; - acebus_default_se_imap[1] = 0x400000; - acebus_default_se_imap[2] = 1; - acebus_default_se_imap[3] = 0; - acebus_default_se_imap[4] = 2; - imapp = acebus_default_se_imap; - ilength = 5; - default_ival = 1; - } - num = ilength / 5; /* there are 5 integer cells in our property */ - timapp = imapp; - for (i = 0; i < num; i++) { - if (*(timapp+i*5+3) == 0) - imap_ok = 0; - } - if (imap_ok) { - if (!default_ival) - ddi_prop_free(imapp); - return (DDI_SUCCESS); - } - - while (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tdip, - DDI_PROP_DONTPASS, "upa-portid", (int **)&port_id, - (uint_t *)&length) != DDI_PROP_SUCCESS) { - tdip = ddi_get_parent(tdip); - if (tdip == NULL) { - cmn_err(CE_WARN, "%s%d: Could not get imap parent", - ddi_driver_name(dip), ddi_get_instance(dip)); - if (!default_ival) - ddi_prop_free(imapp); - return (DDI_FAILURE); - } - } - timapp = imapp; - for (i = 0; i < num; i++) { - *(timapp+i*5+3) = ddi_get_nodeid(tdip); - } - - if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, - "interrupt-map", imapp, ilength) != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, "%s%d: Could not update AC imap property", - ddi_driver_name(dip), ddi_get_instance(dip)); - if (!default_ival) - ddi_prop_free(imapp); - return (DDI_FAILURE); - } - if (!default_ival) - ddi_prop_free(imapp); - return (DDI_SUCCESS); -} -#endif /* ACEBUS_HOTPLUG */ diff --git a/usr/src/uts/sun4u/montecarlo/io/hsc.c b/usr/src/uts/sun4u/montecarlo/io/hsc.c deleted file mode 100644 index 00f88aa636..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/hsc.c +++ /dev/null @@ -1,2170 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * MonteCarlo HotSwap Controller functionality - */ - -#include <sys/types.h> -#include <sys/stropts.h> -#include <sys/stream.h> -#include <sys/strsun.h> -#include <sys/kmem.h> -#include <sys/cmn_err.h> -#include <sys/errno.h> -#include <sys/cpuvar.h> -#include <sys/open.h> -#include <sys/stat.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/modctl.h> -#include <sys/promif.h> -#include <sys/hotplug/hpcsvc.h> - -#include <sys/hscimpl.h> -#include <sys/hsc.h> - -#include <sys/mct_topology.h> -#include <sys/scsbioctl.h> -#include <sys/scsb.h> - -#define HOTSWAP_MODE_PROP "hotswap-mode" -#define ALARM_CARD_ON_SLOT 1 -#define SCSB_HSC_FORCE_REMOVE 1 /* force remove enum intr handler */ - -/* TUNABLE PARAMETERS. Some are Debug Only. Please take care when using. */ - -/* - * Set this flag to 1, to enable full hotswap mode at boot time. - * Since HPS is threaded, it is not recommended that we set this flag - * to 1 because enabling full hotswap interrupt can invoke the ENUM - * event handler accessing the slot data structure which may have not - * been initialized in the hotplug framework since the HPS may not yet - * have called the slot registration function with the bus nexus. - */ -static int scsb_hsc_enable_fhs = 0; - -/* - * Every time a slot is registered with the hotswap framework, the - * framework calls back. This variable keeps a count on how many - * callbacks are done. - */ -static int scsb_hsc_numReg = 0; -/* - * When this flag is set, the board is taken offline (put in reset) after - * a unconfigure operation, in Basic Hotswap mode. - */ -static int scsb_hsc_bhs_slot_reset = 1; -/* - * When this flag is set, we take the board to reset after unconfigure - * operation when operating in full hotswap mode. - */ -static int scsb_hsc_fhs_slot_reset = 1; -/* - * Implementation of this counter will work only on Montecarlo since - * the ENUM# Interrupt line is not shared with other interrupts. - * When the hardware routing changes, then there may be need to remove - * or change this functionality. - * This functionality is provided so that a bad or non friendly full hotswap - * board does not hang the system in full hotswap mode. Atleast the - * intent is that! Eventually Solaris kernel will provide similar support - * for recovering from a stuck interrupt line. Till then, lets do this. - */ -static int scsb_hsc_max_intr_count = 8; -/* - * Since the hardware does not support enabling/disabling ENUM#, the - * following flag can be used for imitating that behaviour. - * Currently we can set this flag and use the remove op to remove the - * interrupt handler from the system. Care must be taken when using this - * function since trying to remove the interrupt handler when the interrupts - * are pending may hang the system permanently. - * Since the hardware does not support this functionality, we adopt this - * approach for debugs. - */ -static int scsb_hsc_enum_switch = 0; - -/* - * When the board loses Healthy# at runtime (with the board being configured), - * cPCI specs states that a Reset has to be asserted immediately. - * We dont do this currently, until satellite processor support is given - * and the implications of such a act is fully understood. - * To adopt the cPCI specs recommendation, set this flag to 1. - */ -static int scsb_hsc_healthy_reset = 0; - -/* - * According to PCI 2.2 specification, once a board comes out of PCI_RST#, - * it may take upto 2^25 clock cycles to respond to config cycles. For - * montecarlo using a 33MHz cPCI bus, it's around 1.024 s. The variable - * will specify the time in ms to wait before attempting config access. - */ -static int scsb_connect_delay = 1025; - -/* - * slot map property for MC should be - * - * hsc-slot-map="/pci@1f,0/pci@1/pci@1","15","2", - * "/pci@1f,0/pci@1/pci@1","14","3", - * "/pci@1f,0/pci@1/pci@1","13","4", - * "/pci@1f,0/pci@1/pci@1","12","5" - * "/pci@1f,0/pci@1/pci@1","11","6" - * "/pci@1f,0/pci@1/pci@1","10","7" - * "/pci@1f,0/pci@1/pci@1","8","8"; - * - * slot map property for Tonga should be - * hsc-slot-map="/pci@1f,0/pci@1/pci@1","8","1" - * "/pci@1f,0/pci@1/pci@1", "15", "2" - * "/pci@1f,0/pci@1/pci@1", "14", "4" - * "/pci@1f,0/pci@1/pci@1", "13", "5" - * - * Please note that the CPU slot number is 3 for Tonga. - */ - -/* - * Services we require from the SCSB - */ -extern int scsb_get_slot_state(void *, int, int *); -extern int scsb_read_bhealthy(scsb_state_t *scsb); -extern int scsb_read_slot_health(scsb_state_t *scsb, int pslotnum); -extern int scsb_connect_slot(void *, int, int); -extern int scsb_disconnect_slot(void *, int, int); - -static void *hsc_state; - -static uint_t hsc_enum_intr(char *); -static hsc_slot_t *hsc_get_slot_info(hsc_state_t *, int); -static int scsb_enable_enum(hsc_state_t *); -static int scsb_disable_enum(hsc_state_t *, int); -static int atoi(const char *); -static int isdigit(int); -static hsc_slot_t *hsc_find_slot(int); -static void hsc_led_op(hsc_slot_t *, int, hpc_led_t, hpc_led_state_t); -static int hsc_led_state(hsc_slot_t *, int, hpc_led_info_t *); -static int scsb_hsc_disable_slot(hsc_slot_t *); -static int scsb_hsc_enable_slot(hsc_slot_t *); -#ifndef lint -static int hsc_clear_all_enum(hsc_state_t *); -#endif -static int hsc_slot_register(hsc_state_t *, char *, uint16_t, uint_t, - boolean_t); -static int hsc_slot_unregister(int); -static int scsb_hsc_init_slot_state(hsc_state_t *, hsc_slot_t *); -static int hsc_slot_autoconnect(hsc_slot_t *); - -static hpc_slot_ops_t *hsc_slotops; -static hsc_slot_t *hsc_slot_list; /* linked list of slots */ - -/* - * This mutex protects the following variables: - * hsc_slot_list - */ -static kmutex_t hsc_mutex; - - -/* ARGSUSED */ -static int -hsc_connect(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags) -{ - hsc_slot_t *hsp = (hsc_slot_t *)ops_arg; - int rc, rstate; - hsc_state_t *hsc; - - DEBUG2("hsc_connect: slot %d, healthy %d", hsp->hs_slot_number, - hsp->hs_board_healthy); - - if (!(hsp->hs_flags & (HSC_ENABLED|HSC_SLOT_ENABLED))) - return (HPC_ERR_FAILED); - /* if SCB hotswapped, do not allow connect operations */ - if (hsp->hs_flags & HSC_SCB_HOTSWAPPED) - return (HPC_ERR_FAILED); - /* - * if previous occupant stayed configured, do not allow another - * occupant to be connected. - * This behaviour is an indication that the slot state - * is not clean. - */ - if (hsp->hs_flags & HSC_SLOT_BAD_STATE) { - /* - * In the current implementation, we turn both fault - * and active LEDs to ON state in this situation. - */ - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_ON); - return (HPC_ERR_FAILED); - } - /* - * Get the actual status from the i2c bus - */ - rc = scsb_get_slot_state(hsp->hs_hpchandle, hsp->hs_slot_number, - &rstate); - if (rc != DDI_SUCCESS) - return (HPC_ERR_FAILED); - - hsp->hs_slot_state = rstate; - if (hsp->hs_slot_state == HPC_SLOT_EMPTY) { -#ifdef DEBUG - cmn_err(CE_CONT, - "?hsc_connect: slot %d is empty\n", - hsp->hs_slot_number); -#endif - return (HPC_ERR_FAILED); - } - - if (hsp->hs_slot_state == HPC_SLOT_CONNECTED) - return (HPC_SUCCESS); - - rc = HPC_SUCCESS; - /* - * call scsb to connect the slot. This also makes sure board is healthy - */ - if (scsb_connect_slot(hsp->hs_hpchandle, hsp->hs_slot_number, - hsp->hs_board_healthy) != DDI_SUCCESS) { - DEBUG1("hsc_connect: slot %d connection failed", - hsp->hs_slot_number); - rc = HPC_ERR_FAILED; - } else { - if (hsp->hs_slot_state != HPC_SLOT_CONNECTED) { - if (hsp->hs_board_healthy == B_FALSE) { - cmn_err(CE_NOTE, "HEALTHY# not asserted on " - " slot %d", hsp->hs_slot_number); - return (HPC_ERR_FAILED); - } - hsc = hsp->hsc; - hsc->hsp_last = hsp; - if (scsb_reset_slot(hsp->hs_hpchandle, - hsp->hs_slot_number, SCSB_UNRESET_SLOT) != 0) { - - return (HPC_ERR_FAILED); - } - /* - * Unresetting a board may have caused an interrupt - * burst in case of non friendly boards. So it is - * important to make sure that the ISR has not - * put this board back to disconnect state. - */ - delay(1); - if (hsp->hs_flags & HSC_ENUM_FAILED) { - hsp->hs_flags &= ~HSC_ENUM_FAILED; - return (HPC_ERR_FAILED); - } - DEBUG1("hsc_connect: slot %d connected", - hsp->hs_slot_number); - rc = HPC_SUCCESS; - hsp->hs_slot_state = HPC_SLOT_CONNECTED; - (void) hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_OFF); - } - } - - /* - * PCI 2.2 specs recommend that the probe software wait - * for upto 2^25 PCI clock cycles after deassertion of - * PCI_RST# before the board is able to respond to config - * cycles. So, before we return, we wait for ~1 sec. - */ - delay(drv_usectohz(scsb_connect_delay * 1000)); - return (rc); -} - - -/* ARGSUSED */ -static int -hsc_disconnect(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags) -{ - hsc_slot_t *hsp = (hsc_slot_t *)ops_arg; - hsc_state_t *hsc; -#ifdef DEBUG - static const char func[] = "hsc_disconnect"; -#endif - - DEBUG1("hsc_disconnect: slot %d", hsp->hs_slot_number); - - if (hsp->hs_board_configured) { -#ifdef DEBUG - cmn_err(CE_NOTE, - "%s: cannot disconnect configured board in slot %d", - func, hsp->hs_slot_number); -#endif - return (HPC_ERR_FAILED); - } - - if (hsp->hs_slot_state == HPC_SLOT_EMPTY) { -#ifdef DEBUG - cmn_err(CE_NOTE, "%s: slot %d is empty", - func, hsp->hs_slot_number); -#endif - return (HPC_SUCCESS); - } - - if (hsp->hs_slot_state == HPC_SLOT_DISCONNECTED) { - /* - * if already disconnected, just return success - * Duplicate disconnect messages should not be failed! - */ - return (HPC_SUCCESS); - } - /* if SCB hotswapped, do not allow disconnect operations */ - if (hsp->hs_flags & HSC_SCB_HOTSWAPPED) - return (HPC_ERR_FAILED); - - /* call scsb to disconnect the slot */ - if (scsb_disconnect_slot(hsp->hs_hpchandle, B_TRUE, hsp->hs_slot_number) - != DDI_SUCCESS) - return (HPC_ERR_FAILED); - hsc = hsp->hsc; - if (hsc->hsp_last == hsp) - hsc->hsp_last = NULL; - - return (HPC_SUCCESS); -} - - -/* - * In the cPCI world, this operation is not applicable. - * However, we use this function to enable full hotswap mode in debug mode. - */ -/* ARGSUSED */ -static int -hsc_insert(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags) -{ - hsc_slot_t *hsp = (hsc_slot_t *)ops_arg; - - if (scsb_hsc_enum_switch && - (scsb_enable_enum(hsp->hsc) == DDI_SUCCESS)) { - return (HPC_SUCCESS); - } - return (HPC_ERR_NOTSUPPORTED); -} - - -/* - * In the cPCI world, this operation is not applicable. - * However, we use this function to disable full hotswap mode in debug mode. - */ -/* ARGSUSED */ -static int -hsc_remove(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags) -{ - hsc_slot_t *hsp = (hsc_slot_t *)ops_arg; - - if (scsb_hsc_enum_switch && - (scsb_disable_enum(hsp->hsc, SCSB_HSC_FORCE_REMOVE) - == DDI_SUCCESS)) { - hsp->hs_flags &= ~HSC_ENUM_FAILED; - return (HPC_SUCCESS); - } - return (HPC_ERR_NOTSUPPORTED); -} - -static void -hsc_led_op(hsc_slot_t *hsp, int cmd, hpc_led_t led, hpc_led_state_t led_state) -{ - hpc_led_info_t ledinfo; - - ledinfo.led = led; - ledinfo.state = led_state; - (void) hsc_led_state(hsp, cmd, &ledinfo); -} - -static int -hsc_led_state(hsc_slot_t *hsp, int cmd, hpc_led_info_t *hlip) -{ - hpc_led_state_t *hlsp; - scsb_uinfo_t sunit; - int res; - - DEBUG3("hsc_led_state: slot %d, led %x, state %x", - hsp->hs_slot_number, hlip->led, hlip->state); - - sunit.unit_type = SLOT; - sunit.unit_number = hsp->hs_slot_number; - /* - * We ignore operations on LEDs that we don't support - */ - switch (hlip->led) { - case HPC_FAULT_LED: - sunit.led_type = NOK; - hlsp = &hsp->hs_fault_led_state; - break; - case HPC_ACTIVE_LED: - sunit.led_type = OK; - hlsp = &hsp->hs_active_led_state; - break; - default: - return (HPC_ERR_NOTSUPPORTED); - } - - switch (hlip->state) { - case HPC_LED_BLINK: - sunit.unit_state = BLINK; - if (hlip->led != HPC_ACTIVE_LED) - return (HPC_ERR_NOTSUPPORTED); - break; - case HPC_LED_ON: - sunit.unit_state = ON; - break; - case HPC_LED_OFF: - sunit.unit_state = OFF; - break; - default: - break; - } - - switch (cmd) { - case HPC_CTRL_SET_LED_STATE: - res = scsb_led_set(hsp->hs_hpchandle, &sunit, sunit.led_type); - if (res != 0) - return (HPC_ERR_FAILED); - *hlsp = (hpc_led_state_t)sunit.unit_state; - break; - - case HPC_CTRL_GET_LED_STATE: - res = scsb_led_get(hsp->hs_hpchandle, &sunit, sunit.led_type); - if (res) - return (HPC_ERR_FAILED); - /* hlip->state = sunit.unit_state; */ - break; - - default: - return (HPC_ERR_INVALID); - } - - return (HPC_SUCCESS); - -} - - -static int -hsc_get_slot_state(hsc_slot_t *hsp, hpc_slot_state_t *hssp) -{ - int rstate = 0; - int rc; -#ifdef DEBUG - int orstate; /* original rstate */ -#endif - - DEBUG1("hsc_get_slot_state: slot %d", hsp->hs_slot_number); - rc = scsb_get_slot_state(hsp->hs_hpchandle, hsp->hs_slot_number, - &rstate); - if (rc != DDI_SUCCESS) - return (HPC_ERR_FAILED); -#ifdef DEBUG - orstate = hsp->hs_slot_state; -#endif - hsp->hs_slot_state = rstate; - switch (hsp->hs_slot_state) { - case HPC_SLOT_EMPTY: - DEBUG0("empty"); - break; - case HPC_SLOT_CONNECTED: - DEBUG0("connected"); - break; - case HPC_SLOT_DISCONNECTED: - DEBUG0("disconnected"); - break; - } - - *hssp = hsp->hs_slot_state; - - /* doing get-state above may have caused a freeze operation */ - if ((hsp->hs_flags & HSC_SCB_HOTSWAPPED) && - (rstate == HPC_SLOT_DISCONNECTED)) { - /* freeze puts disconnected boards to connected state */ - *hssp = HPC_SLOT_CONNECTED; -#if 0 - /* in FHS, deassertion of reset may have configured the board */ - if (hsp->hs_board_configured == B_TRUE) { - hsp->hs_slot_state = *hssp; - } -#endif - } -#ifdef DEBUG - /* a SCB hotswap may have forced a state change on the receptacle */ - if (orstate != *hssp) { - cmn_err(CE_NOTE, "hsc_get_state: slot%d state change due" - " to SCB hotswap!", hsp->hs_slot_number); - } -#endif - return (HPC_SUCCESS); -} - - -static int -hsc_set_config_state(hsc_slot_t *hsp, int cmd) -{ - hsc_state_t *hsc = hsp->hsc; - - DEBUG1("hsc_set_config_state: slot %d", hsp->hs_slot_number); - - switch (cmd) { - case HPC_CTRL_DEV_CONFIGURED: - /* - * Closing of the Ejector switch in configured/busy state can - * cause duplicate CONFIGURED messages to come down. - * Make sure our LED states are fine. - */ - if (hsp->hs_board_configured == B_TRUE) { - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_ON); - break; - } - hsp->hs_board_configured = B_TRUE; - hsp->hs_board_configuring = B_FALSE; - if ((hsc->state & HSC_ATTACHED) == HSC_ATTACHED && - hsp->hs_flags & HSC_ALARM_CARD_PRES) - (void) scsb_hsc_ac_op(hsp->hs_hpchandle, - hsp->hs_slot_number, SCSB_HSC_AC_CONFIGURED); - /* LED must be OFF on the occupant. */ - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_SLOT_BLUE_LED_OFF, 0); - if (hsp->hs_flags & HSC_AUTOCFG) - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_ENABLE_ENUM, 0); - else - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_DISABLE_ENUM, 0); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_ON); - if (hsc->hsp_last == hsp) - hsc->hsp_last = NULL; - break; - case HPC_CTRL_DEV_UNCONFIGURED: - hsp->hs_board_configured = B_FALSE; - hsp->hs_board_unconfiguring = B_FALSE; - hsp->hs_flags &= ~HSC_SLOT_BAD_STATE; - if (hsp->hs_flags & HSC_ALARM_CARD_PRES) - (void) scsb_hsc_ac_op(hsp->hs_hpchandle, - hsp->hs_slot_number, SCSB_HSC_AC_UNCONFIGURED); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_BLINK); - if (((hsc->state & HSC_ENUM_ENABLED) && - scsb_hsc_fhs_slot_reset) || - (((hsc->state & HSC_ENUM_ENABLED) != HSC_ENUM_ENABLED) && - scsb_hsc_bhs_slot_reset) || - ((hsp->hs_flags & HSC_AUTOCFG) != - HSC_AUTOCFG)) { - if (scsb_reset_slot(hsp->hs_hpchandle, - hsp->hs_slot_number, SCSB_RESET_SLOT) == 0) { - - hsp->hs_slot_state = HPC_SLOT_DISCONNECTED; - hsp->hs_board_healthy = B_FALSE; - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_ON); - } - } - break; - case HPC_CTRL_DEV_CONFIG_FAILURE: - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_BLINK); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_ON); - break; - case HPC_CTRL_DEV_UNCONFIG_FAILURE: - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_ON); - break; - case HPC_CTRL_DEV_CONFIG_START: - case HPC_CTRL_DEV_UNCONFIG_START: - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_OFF); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_BLINK); - break; - default: - return (HPC_ERR_INVALID); - } - - if (cmd != HPC_CTRL_DEV_CONFIG_START && - cmd != HPC_CTRL_DEV_UNCONFIG_START && - hsc->regDone == B_FALSE && - scsb_hsc_numReg < hsc->n_registered_occupants) { - scsb_hsc_numReg++; - - /* - * If the callback is invoked for all registered slots, - * enable ENUM. - */ - if (((hsc->state & HSC_ATTACHED) == HSC_ATTACHED) && - (scsb_hsc_numReg == hsc->n_registered_occupants)) { - hsc->regDone = B_TRUE; - if (hsc->hotswap_mode == HSC_HOTSWAP_MODE_FULL) { -#ifdef DEBUG - cmn_err(CE_CONT, "%s%d: Enabling full hotswap" - ":%d non-empty slots\n", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - hsc->n_registered_occupants); -#endif - if (scsb_enable_enum(hsc) != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s#%d: Cannot enable " - "Full Hotswap", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip)); - - return (HPC_ERR_FAILED); - } - } - } - } - - return (HPC_SUCCESS); -} - - -/*ARGSUSED*/ -static int -hsc_get_board_type(hsc_slot_t *hsp, hpc_board_type_t *hbtp) -{ - *hbtp = hsp->hs_board_type; - return (HPC_SUCCESS); -} - - -/* ARGSUSED */ -static int -hsc_autoconfig(hsc_slot_t *hsp, int cmd) -{ - int res = HPC_SUCCESS, enum_disable = B_TRUE, i; - char slotautocfg_prop[18]; - hsc_state_t *hsc; - - DEBUG1("hsc_autoconfig: slot %d", hsp->hs_slot_number); - (void) sprintf(slotautocfg_prop, "slot%d-autoconfig", - hsp->hs_slot_number); - - if (cmd == HPC_CTRL_ENABLE_AUTOCFG) { - hsp->hs_flags |= HSC_AUTOCFG; - (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsp->hsc->dip, - slotautocfg_prop, "enabled"); - if ((res = scsb_enable_enum(hsp->hsc)) == DDI_SUCCESS) { - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_ENABLE_ENUM, 0); - } - } else { - (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsp->hsc->dip, - slotautocfg_prop, "disabled"); - hsp->hs_flags &= ~HSC_AUTOCFG; - hsc = hsp->hsc; - if (hsc->state & HSC_ATTACHED) { - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_DISABLE_ENUM, 0); - for (i = 0; i < hsc->slot_table_size; i++) { - hsc_slot_t *thsp; - int slotnum; - - slotnum = hsc->slot_table_prop[i].pslotnum; - thsp = hsc_find_slot(slotnum); - if (thsp == NULL) { - cmn_err(CE_WARN, "%s#%d: hsc_autocfg:" - "No Slot Info for slot %d", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - slotnum); - continue; - } - if (thsp->hs_flags & HSC_AUTOCFG) { - enum_disable = B_FALSE; - break; - } - } - if (enum_disable == B_TRUE) - (void) scsb_disable_enum(hsc, - SCSB_HSC_FORCE_REMOVE); - } - } - return (res); -} - - -/* - * This function is invoked to enable/disable a slot - */ -/* ARGSUSED */ -#ifndef lint -static int -hsc_slot_enable(hsc_slot_t *hsp, boolean_t enabled) -{ - scsb_uinfo_t sunit; - int res; - - DEBUG1("hsc_slot_enable: slot %d", hsp->hs_slot_number); - - sunit.unit_type = SLOT; - sunit.unit_number = hsp->hs_slot_number; - if (enabled) - sunit.unit_state = ON; - else - sunit.unit_state = OFF; - - res = scsb_reset_unit(hsp->hs_hpchandle, &sunit); - if (res == 0) - return (HPC_SUCCESS); - else if (res == EINVAL) - return (HPC_ERR_INVALID); - else - return (HPC_ERR_FAILED); -} -#endif - - -/*ARGSUSED*/ -static int -hsc_control(caddr_t ops_arg, hpc_slot_t slot_hdl, int request, caddr_t arg) -{ - hsc_slot_t *hsp = (hsc_slot_t *)ops_arg; - int rc = HPC_SUCCESS; - - DEBUG2("hsc_control: slot %d, op=%x\n", hsp->hs_slot_number, request); - - switch (request) { - case HPC_CTRL_GET_LED_STATE: - return (hsc_led_state(hsp, - HPC_CTRL_GET_LED_STATE, (hpc_led_info_t *)arg)); - - case HPC_CTRL_SET_LED_STATE: - return (hsc_led_state(hsp, - HPC_CTRL_SET_LED_STATE, (hpc_led_info_t *)arg)); - - case HPC_CTRL_GET_SLOT_STATE: - return (hsc_get_slot_state(hsp, (hpc_slot_state_t *)arg)); - - case HPC_CTRL_DEV_CONFIGURED: - return (hsc_set_config_state(hsp, HPC_CTRL_DEV_CONFIGURED)); - - case HPC_CTRL_DEV_UNCONFIGURED: - return (hsc_set_config_state(hsp, HPC_CTRL_DEV_UNCONFIGURED)); - - case HPC_CTRL_DEV_CONFIG_FAILURE: - return (hsc_set_config_state(hsp, HPC_CTRL_DEV_CONFIG_FAILURE)); - - case HPC_CTRL_DEV_UNCONFIG_FAILURE: - return (hsc_set_config_state(hsp, - HPC_CTRL_DEV_UNCONFIG_FAILURE)); - - case HPC_CTRL_DEV_CONFIG_START: - case HPC_CTRL_DEV_UNCONFIG_START: - return (hsc_set_config_state(hsp, request)); - - case HPC_CTRL_GET_BOARD_TYPE: - return (hsc_get_board_type(hsp, (hpc_board_type_t *)arg)); - - case HPC_CTRL_DISABLE_AUTOCFG: - return (hsc_autoconfig(hsp, HPC_CTRL_DISABLE_AUTOCFG)); - - case HPC_CTRL_ENABLE_AUTOCFG: - return (hsc_autoconfig(hsp, HPC_CTRL_ENABLE_AUTOCFG)); - - case HPC_CTRL_DISABLE_SLOT: - /* - * No hardware support for disabling the slot. - * Just imitate a disable_autoconfig operation for now - */ - if (hsp->hs_board_configured == B_TRUE) - return (HPC_ERR_FAILED); - if (scsb_hsc_disable_slot(hsp) != DDI_SUCCESS) - rc = HPC_ERR_FAILED; - return (rc); - - case HPC_CTRL_ENABLE_SLOT: - if (scsb_hsc_enable_slot(hsp) != DDI_SUCCESS) - rc = HPC_ERR_FAILED; - return (rc); - - case HPC_CTRL_ENABLE_ENUM: - return (scsb_enable_enum(hsp->hsc)); - - case HPC_CTRL_DISABLE_ENUM: - return (scsb_disable_enum(hsp->hsc, 0)); - - default: - return (HPC_ERR_INVALID); - } -} - -static int -scsb_hsc_disable_slot(hsc_slot_t *hsp) -{ - int rc; - char slot_disable_prop[18]; - - DEBUG1("hsc_disable_slot: slot %d", hsp->hs_slot_number); - (void) sprintf(slot_disable_prop, "slot%d-status", hsp->hs_slot_number); - - rc = scsb_reset_slot(hsp->hs_hpchandle, hsp->hs_slot_number, - SCSB_RESET_SLOT); - if (rc == DDI_SUCCESS) { - (void) hsc_autoconfig(hsp, HPC_CTRL_DISABLE_AUTOCFG); - hsp->hs_flags &= ~HSC_SLOT_ENABLED; - (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsp->hsc->dip, - slot_disable_prop, "disabled"); - } else - rc = DDI_FAILURE; - return (rc); -} - -static int -scsb_hsc_enable_slot(hsc_slot_t *hsp) -{ - int rc; - char slot_disable_prop[18]; - - DEBUG1("hsc_disable_slot: slot %d", hsp->hs_slot_number); - (void) sprintf(slot_disable_prop, "slot%d-status", hsp->hs_slot_number); - - rc = scsb_reset_slot(hsp->hs_hpchandle, hsp->hs_slot_number, - SCSB_UNRESET_SLOT); - if (rc == DDI_SUCCESS) { - (void) hsc_autoconfig(hsp, HPC_CTRL_ENABLE_AUTOCFG); - hsp->hs_flags |= HSC_SLOT_ENABLED; - (void) ddi_prop_remove(DDI_DEV_T_NONE, hsp->hsc->dip, - slot_disable_prop); - } else - rc = HPC_ERR_FAILED; - return (rc); -} - -#define NEW(type) (type *) kmem_zalloc(sizeof (type), KM_SLEEP) - -static hsc_slot_t * -hsc_alloc_slot( - uint16_t device_number, - int slot_number, - boolean_t board_in_slot) -{ - hpc_slot_info_t *hsip; - hsc_slot_t *hsp = NEW(hsc_slot_t); - - DEBUG2("hsc_alloc_slot: slot %d %s", slot_number, - board_in_slot ? "occupied" : "empty"); - - if (hsp == NULL) { - cmn_err(CE_NOTE, - "hsc_alloc_slot: allocation failed for slot %d", - slot_number); - return (NULL); - } - - hsip = &hsp->hs_info; - - hsip->version = HPC_SLOT_INFO_VERSION; - hsip->slot_type = HPC_SLOT_TYPE_CPCI; - hsip->pci_dev_num = device_number; - hsip->pci_slot_capabilities = 0; - hsip->slot_flags = HPC_SLOT_CREATE_DEVLINK; - /* - * Note: the name *must* be 'pci' so that the correct cfgadm plug-in - * library is selected - */ - (void) sprintf(hsip->pci_slot_name, "cpci_slot%d", slot_number); - - /* - * We assume that the following LED settings reflect - * the hardware state. - * After we register the slot, we will be invoked by the nexus - * if the slot is occupied, and we will turn on the LED then. - */ - hsp->hs_active_led_state = HPC_LED_OFF; - hsp->hs_fault_led_state = HPC_LED_OFF; - - hsp->hs_board_configured = B_FALSE; - hsp->hs_board_healthy = B_FALSE; - hsp->hs_board_type = HPC_BOARD_UNKNOWN; - - hsp->hs_flags = HSC_ENABLED | HSC_SLOT_ENABLED; - hsp->hs_slot_number = slot_number; - - /* - * we should just set this to connected, - * as MC slots are always connected. - */ - if (board_in_slot) - hsp->hs_slot_state = HPC_SLOT_CONNECTED; - else - hsp->hs_slot_state = HPC_SLOT_EMPTY; - - return (hsp); -} - - -static void -hsc_free_slot(hsc_slot_t *hsp) -{ - DEBUG0("hsc_free_slot"); - - kmem_free(hsp, sizeof (*hsp)); -} - - -/* - * This function is invoked to register a slot - */ -static int -hsc_slot_register( - hsc_state_t *hsc, - char *bus_path, /* PCI nexus pathname */ - uint16_t device_number, /* PCI device number */ - uint_t slot_number, /* physical slot number */ - boolean_t board_in_slot) /* receptacle status */ -{ - int rc = HPC_SUCCESS; - hsc_slot_t *hsp; - - DEBUG2("hsc_slot_register: slot number %d, device number %d", - slot_number, device_number); - - hsp = hsc_alloc_slot(device_number, slot_number, - board_in_slot); - - if (hsp == NULL) { -#ifdef DEBUG - cmn_err(CE_NOTE, "hsc_slot_register: hsc_alloc_slot failed"); -#endif - return (HPC_ERR_FAILED); - } - - hsp->hs_hpchandle = hsc->scsb_handle; /* handle for call backs */ - hsp->hsc = hsc; - - rc = scsb_hsc_init_slot_state(hsc, hsp); - if (rc != DDI_SUCCESS) - return (HPC_ERR_FAILED); - - /* slot autoconfiguration by default. */ - if (hsc->hotswap_mode == HSC_HOTSWAP_MODE_FULL) - (void) hsc_autoconfig(hsp, HPC_CTRL_ENABLE_AUTOCFG); - else - (void) hsc_autoconfig(hsp, HPC_CTRL_DISABLE_AUTOCFG); - - /* - * Append to our list - */ - mutex_enter(&hsc_mutex); - hsp->hs_next = hsc_slot_list; - hsc_slot_list = hsp; - mutex_exit(&hsc_mutex); - - rc = hpc_slot_register(hsc->dip, - bus_path, - &hsp->hs_info, - &hsp->hs_slot_handle, /* return value */ - hsc_slotops, - (caddr_t)hsp, - 0); - - if (rc != HPC_SUCCESS) { - cmn_err(CE_WARN, "%s#%d: failed to register slot %s:%d", - ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip), - bus_path, device_number); - hsc_free_slot(hsp); - return (rc); - } - - DEBUG0("hsc_slot_register: hpc_slot_register successful"); - - return (rc); -} - - -static int -hsc_slot_unregister(int slot_number) -{ - hsc_slot_t *hsp, *prev; - - DEBUG1("hsc_slot_unregister: slot number %d", slot_number); - - mutex_enter(&hsc_mutex); - hsp = prev = NULL; - for (hsp = hsc_slot_list; hsp != NULL; hsp = hsp->hs_next) { - if (hsp->hs_slot_number == slot_number) { - if (prev == NULL) /* first entry */ - hsc_slot_list = hsc_slot_list->hs_next; - else - prev->hs_next = hsp->hs_next; - hsp->hs_next = NULL; - break; - } - prev = hsp; - } - mutex_exit(&hsc_mutex); - - if (hsp != NULL) { - (void) hpc_slot_unregister(&hsp->hs_slot_handle); - if ((hsp->hsc->state & HSC_ATTACHED) != HSC_ATTACHED && - hsp->hs_slot_state != HPC_SLOT_EMPTY) { - hsp->hsc->n_registered_occupants--; - } - hsc_free_slot(hsp); - return (0); - } - return (1); -} - -static int -scsb_hsc_init_slot_state(hsc_state_t *hsc, hsc_slot_t *hsp) -{ - int rc, rstate; - int slot_number = hsp->hs_slot_number; - scsb_state_t *scsb = (scsb_state_t *)hsc->scsb_handle; - - rc = scsb_get_slot_state(hsc->scsb_handle, slot_number, &rstate); - if (rc != DDI_SUCCESS) - return (DDI_FAILURE); - - /* - * Set the healthy status for this slot - */ - hsp->hs_board_healthy = scsb_read_slot_health(scsb, slot_number); - hsp->hs_slot_state = rstate; - switch (rstate) { - case HPC_SLOT_EMPTY: - /* - * this will clear any state differences between - * SCB Freeze operations. - */ - hsp->hs_slot_state = HPC_SLOT_EMPTY; - /* slot empty. */ - (void) scsb_reset_slot(hsc->scsb_handle, slot_number, - SCSB_RESET_SLOT); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_OFF); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_OFF); - break; - case HPC_SLOT_DISCONNECTED: - /* - * this will clear any state differences between - * SCB Freeze operations. - */ - hsp->hs_slot_state = HPC_SLOT_DISCONNECTED; - /* check recovery from SCB freeze */ - if (hsp->hs_board_configured != B_TRUE) { - /* - * Force a disconnect just in case there are - * differences between healthy and reset states. - */ - (void) scsb_reset_slot(hsc->scsb_handle, - slot_number, SCSB_RESET_SLOT); - /* - * Slot in reset. OBP has not probed this - * device. Hence it is ok to remove this board. - */ - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_ACTIVE_LED, HPC_LED_BLINK); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_ON); - break; - } - /*FALLTHROUGH*/ - case HPC_SLOT_CONNECTED: - /* - * this will clear any state differences between - * SCB Freeze operations. - */ - hsp->hs_slot_state = HPC_SLOT_CONNECTED; - /* - * OBP should have probed this device, unless - * it was plugged in during the boot operation - * before the driver was loaded. In any case, - * no assumption is made and hence we take - * the conservative approach by keeping fault - * led off so board removal is not allowed. - */ - if (hsp->hs_board_configured == B_TRUE) - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_ACTIVE_LED, HPC_LED_ON); - else - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_ACTIVE_LED, HPC_LED_BLINK); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_OFF); - /* - * Netra ct alarm card hotswap support - */ - if (slot_number == scsb->ac_slotnum && - scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES) { - hsp->hs_flags |= HSC_ALARM_CARD_PRES; - DEBUG0("Xscsb_hsc_init_slot_state: " - "set HSC_ALARM_CARD_PRES"); - } - break; - default: - break; - } - return (rc); -} - -static hsc_slot_t * -hsc_get_slot_info(hsc_state_t *hsc, int pci_devno) -{ - int i; - - for (i = 0; i < hsc->slot_table_size; i++) { - - if (hsc->slot_table_prop[i].pci_devno == pci_devno) - return ((hsc_slot_t *)hsc_find_slot( - hsc->slot_table_prop[i].pslotnum)); - } - return (NULL); -} - -static hsc_slot_t * -hsc_find_slot(int slot_number) -{ - hsc_slot_t *hsp; - - mutex_enter(&hsc_mutex); - for (hsp = hsc_slot_list; hsp != NULL; hsp = hsp->hs_next) { - if (hsp->hs_slot_number == slot_number) - break; - } - mutex_exit(&hsc_mutex); - return (hsp); -} - - -/* - * This function is invoked by the SCSB when an interrupt - * happens to indicate that a board has been inserted-in/removed-from - * the specified slot. - */ -int -hsc_slot_occupancy(int slot_number, boolean_t occupied, int flags, int healthy) -{ - static const char func[] = "hsc_slot_occupancy"; - hsc_slot_t *hsp; - int rc = DDI_SUCCESS; - - DEBUG4("hsc_slot_occupancy: slot %d %s, ac=%d, healthy=%d", - slot_number, occupied ? "occupied" : "not occupied", - (flags == ALARM_CARD_ON_SLOT) ? 1:0, healthy); - - hsp = hsc_find_slot(slot_number); - - if (hsp == NULL) { - cmn_err(CE_NOTE, - "%s: cannot map slot number %d to a hsc_slot_t", - func, slot_number); - return (DDI_FAILURE); - } - - hsp->hs_board_healthy = healthy; - if (occupied) { - /* - * A board was just inserted. We are disconnected at this point. - */ - if (hsp->hs_slot_state == HPC_SLOT_EMPTY) - hsp->hs_board_type = HPC_BOARD_CPCI_HS; - hsp->hs_slot_state = HPC_SLOT_DISCONNECTED; - if (flags == ALARM_CARD_ON_SLOT) { - hsp->hs_flags |= HSC_ALARM_CARD_PRES; - DEBUG0("Xhsc_slot_occupancy: set HSC_ALARM_CARD_PRES"); - } - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_ON); - /* - * if previous occupant stayed configured, do not allow another - * occupant to be connected. - * So as soon as the board is plugged in, we turn both LEDs On. - * This behaviour is an indication that the slot state - * is not clean. - */ - if (hsp->hs_flags & HSC_SLOT_BAD_STATE) { - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_ON); - return (DDI_SUCCESS); - } - - /* Do not allow connect if slot is disabled */ - if ((hsp->hs_flags & HSC_SLOT_ENABLED) != HSC_SLOT_ENABLED) - return (DDI_SUCCESS); - /* if no healthy, we stay disconnected. */ - if (healthy == B_FALSE) { - return (DDI_SUCCESS); - } - rc = hsc_slot_autoconnect(hsp); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_BLINK); - } else { - /* - * A board was just removed - */ - hsp->hs_slot_state = HPC_SLOT_EMPTY; - hsp->hs_board_type = HPC_BOARD_UNKNOWN; - hsp->hs_flags &= ~HSC_ENUM_FAILED; - if (hsp->hs_flags & HSC_ALARM_CARD_PRES) { - hsp->hs_flags &= ~HSC_ALARM_CARD_PRES; - DEBUG0("Xhsc_slot_occupancy:clear HSC_ALARM_CARD_PRES"); - } - if (hsp->hs_board_configured == B_TRUE) { - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_SLOT_NOT_HEALTHY, 0); - cmn_err(CE_WARN, "%s#%d: ALERT! Surprise Removal " - " on Slot %d, Occupant Online!!", - ddi_driver_name(hsp->hsc->dip), - ddi_get_instance(hsp->hsc->dip), - slot_number); - cmn_err(CE_WARN, "%s#%d: ALERT! System now in " - " Inconsistent State! Slot disabled. Halt!", - ddi_driver_name(hsp->hsc->dip), - ddi_get_instance(hsp->hsc->dip)); - /* Slot in reset and disabled */ - (void) scsb_hsc_disable_slot(hsp); - hsp->hs_flags |= HSC_SLOT_BAD_STATE; - /* the following works for P1.0 only. */ - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_ON); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_ON); - } else { - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_OFF); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_ACTIVE_LED, - HPC_LED_OFF); - } - } - return (rc); -} - - -/* - * This function is invoked by the SCSB when the health status of - * a board changes. - */ -/*ARGSUSED*/ -int -scsb_hsc_board_healthy(int slot_number, boolean_t healthy) -{ - hsc_slot_t *hsp; - hsc_state_t *hsc; - - DEBUG2("hsc_board_healthy: slot %d = %d\n", slot_number, healthy); - - hsp = hsc_find_slot(slot_number); - if (hsp == NULL) { - cmn_err(CE_NOTE, "hsc_board_healthy: No Slot Info."); - return (DDI_FAILURE); - } - - hsc = hsp->hsc; - if (hsp->hs_slot_state == HPC_SLOT_EMPTY) { -#ifdef DEBUG - cmn_err(CE_NOTE, "%s#%d: Healthy# %s on " - "empty slot %d", ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - healthy == B_TRUE ? "On" : "Off", slot_number); -#endif - return (DDI_FAILURE); - } - if (hsp->hs_slot_state == HPC_SLOT_DISCONNECTED) { - DEBUG2("healthy %s on disconnected slot %d\n", - healthy == B_TRUE ? "On":"Off", slot_number); - /* - * Connect the slot if board healthy and in autoconfig mode. - */ - hsp->hs_board_healthy = healthy; - if (healthy == B_TRUE) - return (hsc_slot_autoconnect(hsp)); - } - - /* - * the board is connected. The result could be seviour depending - * on the occupant state. - */ - if (healthy == B_TRUE) { - if (hsp->hs_board_healthy != B_TRUE) { - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, HPC_FAULT_LED, - HPC_LED_OFF); - /* Regained HEALTHY# at Run Time...!!! */ - cmn_err(CE_NOTE, "%s#%d: slot %d Occupant " - "%s, Regained HEALTHY#!", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), slot_number, - hsp->hs_board_configured == B_TRUE ? - "configured" : "Unconfigured"); - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_SLOT_HEALTHY_OK, 0); - } - } else { - if (hsp->hs_board_configured == B_TRUE) { - /* Lost HEALTHY# at Run Time...Serious Condition. */ - cmn_err(CE_WARN, "%s#%d: ALERT! Lost HEALTHY#" - " on Slot %d, Occupant %s", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), slot_number, - hsp->hs_board_configured == B_TRUE ? - "Online!!!" : "Offline"); - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_SLOT_NOT_HEALTHY, 0); - } - if ((hsp->hs_board_configured != B_TRUE) || - scsb_hsc_healthy_reset) { - if (scsb_reset_slot(hsp->hs_hpchandle, - slot_number, SCSB_RESET_SLOT) == 0) { - /* signal Ok to remove board. */ - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_ON); - cmn_err(CE_WARN, "%s#%d: Slot %d " - "successfully taken offline", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - slot_number); - } - } - } - hsp->hs_board_healthy = healthy; - return (DDI_SUCCESS); -} - -static int -hsc_slot_autoconnect(hsc_slot_t *hsp) -{ - hsc_state_t *hsc = hsp->hsc; - int rc = DDI_SUCCESS; - /* - * Keep slot in reset unless autoconfiguration is enabled - * Ie. for Basic Hotswap mode, we stay disconnected at - * insertion. For full hotswap mode, we automatically - * go into connected state at insertion, so that occupant - * autoconfiguration is possible. - */ - if (((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) && - (hsp->hs_flags & HSC_AUTOCFG)) { - /* this statement must be here before unreset. */ - hsc->hsp_last = hsp; - if ((rc = scsb_reset_slot(hsp->hs_hpchandle, - hsp->hs_slot_number, SCSB_UNRESET_SLOT)) == 0) { - - hsp->hs_slot_state = HPC_SLOT_CONNECTED; - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_OFF); - } else { - hsc->hsp_last = NULL; - rc = DDI_FAILURE; - } - } - return (rc); -} - -/* - * The SCSB code should invoke this function from its _init() function. - */ -int -hsc_init() -{ - int rc; - - rc = ddi_soft_state_init(&hsc_state, sizeof (hsc_state_t), 1); - if (rc != 0) - return (rc); - - hsc_slotops = hpc_alloc_slot_ops(KM_SLEEP); - - hsc_slotops->hpc_version = HPC_SLOT_OPS_VERSION; - hsc_slotops->hpc_op_connect = hsc_connect; - hsc_slotops->hpc_op_disconnect = hsc_disconnect; - hsc_slotops->hpc_op_insert = hsc_insert; - hsc_slotops->hpc_op_remove = hsc_remove; - hsc_slotops->hpc_op_control = hsc_control; - - return (DDI_SUCCESS); -} - - -/* - * The SCSB code should invoke this function from its _fini() function. - */ -int -hsc_fini() -{ - if (hsc_slotops != NULL) { - hpc_free_slot_ops(hsc_slotops); - hsc_slotops = NULL; - } - ddi_soft_state_fini(&hsc_state); - return (DDI_SUCCESS); -} - -static int -scsb_enable_enum(hsc_state_t *hsc) -{ - DEBUG0("hsc: Enable ENUM#\n"); - - if ((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) - return (DDI_SUCCESS); - if ((hsc->state & HSC_ATTACHED) != HSC_ATTACHED) - return (DDI_FAILURE); - - if (ddi_add_intr(hsc->dip, 1, NULL, NULL, - hsc_enum_intr, (caddr_t)hsc) != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s#%d: failed ENUM# interrupt registration", - ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip)); - return (DDI_FAILURE); - } - cmn_err(CE_CONT, "?%s%d: Successfully Upgraded to " - "Full Hotswap Mode\n", ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip)); - hsc->state |= HSC_ENUM_ENABLED; - (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsc->dip, - HOTSWAP_MODE_PROP, "full"); - return (DDI_SUCCESS); - -} - -/*ARGSUSED*/ -static int -scsb_disable_enum(hsc_state_t *hsc, int op) -{ - - DEBUG0("hsc: Disable ENUM#\n"); - if (op == SCSB_HSC_FORCE_REMOVE) { - /* - * Clear all pending interrupts before unregistering - * the interrupt. Otherwise the system will hang. - * - * Due to the hang problem, we'll not turn off or disable - * interrupts because if there's a non-friendly full hotswap - * device out there, the ENUM# will be kept asserted and - * hence hsc_clear_all_enum() can never deassert ENUM#. - * So the system will hang. - */ - if ((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) { - /* hsc_clear_all_enum(hsc); */ - ddi_remove_intr(hsc->dip, 1, NULL); - hsc->state &= ~HSC_ENUM_ENABLED; - cmn_err(CE_CONT, "?%s%d: Successfully Downgraded to " - "Basic Hotswap Mode\n", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip)); - } - (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsc->dip, - HOTSWAP_MODE_PROP, "basic"); - return (DDI_SUCCESS); - } else - /* No programming interface for disabling ENUM# on MC/Tonga */ - return (HPC_ERR_NOTSUPPORTED); -} - -#ifndef lint -static int -hsc_clear_all_enum(hsc_state_t *hsc) -{ - int i, rc; - hsc_slot_t *hsp; - - for (i = 0; i < hsc->slot_table_size; i++) { - - hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum); - if (hsp == NULL) - continue; - rc = hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_CLEAR_ENUM, - HPC_EVENT_SYNCHRONOUS); - if (rc == HPC_EVENT_UNCLAIMED) - break; /* no pending interrupts across the bus */ - DEBUG1("Pending Intr on slot %d\n", - hsc->slot_table_prop[i].pslotnum); - } - return (0); -} -#endif - -int -scsb_hsc_attach(dev_info_t *dip, void *scsb_handle, int instance) -{ - int i, n, prop_len; - int prom_prop = 0; /* default: OS property gives slot-table */ - int rc; - char *hotswap_model; - hsc_state_t *hsc; - scsb_state_t *scsb = (scsb_state_t *)scsb_handle; - caddr_t hpc_slot_table_data, s; - int hpc_slot_table_size; - hsc_prom_slot_table_t *hpstp; - int rstate; - - DEBUG0("hsc_attach: enter\n"); - /* - * To get the slot information, - * The OBP defines the 'slot-table' property. But the OS - * can override it with 'hsc-slot-map' property - * through the .conf file. - * Since the formats are different, 2 different property names - * are chosen. - * The OBP property format is - * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits> - * The OS property format is (ga-bits is not used however) - * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits> - */ - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "hsc-slot-map", (caddr_t)&hpc_slot_table_data, - &hpc_slot_table_size); - if (rc != DDI_PROP_SUCCESS) { - prom_prop = 1; - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "slot-table", (caddr_t)&hpc_slot_table_data, - &hpc_slot_table_size); - if (rc != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, "%s#%d: 'slot-table' property " - "missing!", ddi_driver_name(dip), - ddi_get_instance(dip)); - return (DDI_FAILURE); - } - } - rc = ddi_soft_state_zalloc(hsc_state, instance); - if (rc != DDI_SUCCESS) - return (DDI_FAILURE); - - hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance); - hsc->scsb_handle = scsb_handle; - hsc->dip = dip; - hsc->instance = instance; - hsc->n_registered_occupants = 0; - hsc->regDone = B_FALSE; - /* hsc->slot_info = hsc_slot_list; */ - - /* - * Check whether the system should be in basic or full - * hotswap mode. The PROM property always says full, so - * look at the .conf file property whether this is "full" - */ - if (scsb_hsc_enable_fhs) { - hsc->hotswap_mode = HSC_HOTSWAP_MODE_FULL; - } else { - hsc->hotswap_mode = HSC_HOTSWAP_MODE_BASIC; - } - - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "default-hotswap-mode", (caddr_t)&hotswap_model, &prop_len); - - if (rc == DDI_PROP_SUCCESS) { - if (strcmp(hotswap_model, "full") == 0) { - hsc->hotswap_mode = HSC_HOTSWAP_MODE_FULL; - } else if (strcmp(hotswap_model, "basic") == 0) { - hsc->hotswap_mode = HSC_HOTSWAP_MODE_BASIC; - } - - kmem_free(hotswap_model, prop_len); - } - - /* - * Determine the size of the slot table from the property and - * allocate the slot table arrary..Decoding is different for - * OS and PROM property. - */ - if (!prom_prop) { /* OS .conf property */ - for (i = 0, n = 0; i < hpc_slot_table_size; i++) { - if (hpc_slot_table_data[i] == 0) { - n++; - } - } - - /* There should be four elements per entry */ - if (n % 4) { - cmn_err(CE_WARN, "%s#%d: bad format for " - "slot-table(%d)", ddi_driver_name(dip), - ddi_get_instance(dip), n); - kmem_free(hpc_slot_table_data, hpc_slot_table_size); - ddi_soft_state_free(hsc_state, instance); - return (DDI_FAILURE); - } - - hsc->slot_table_size = n / 4; - } else { - hsc->slot_table_size = hpc_slot_table_size / - sizeof (hsc_prom_slot_table_t); - n = hpc_slot_table_size % sizeof (hsc_prom_slot_table_t); - if (n) { - cmn_err(CE_WARN, "%s#%d: bad format for " - "slot-table(%d)", ddi_driver_name(dip), - ddi_get_instance(dip), hpc_slot_table_size); - kmem_free(hpc_slot_table_data, hpc_slot_table_size); - ddi_soft_state_free(hsc_state, instance); - return (DDI_FAILURE); - } - } - - /* - * Netract800 FTC (formerly known as CFTM) workaround. - * Leave Slot 2 out of the HS table if FTC is present in Slot 2 - */ - if (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES) { - hsc->slot_table_size -= 1; - } - DEBUG1("hsc_attach: %d hotplug slots on bus\n", hsc->slot_table_size); - /* - * Create enough space for each slot table entry - * based on how many entries in the property - */ - hsc->slot_table_prop = (hsc_slot_table_t *) - kmem_zalloc(hsc->slot_table_size * - sizeof (hsc_slot_table_t), KM_SLEEP); - - if (!prom_prop) { - s = hpc_slot_table_data; - for (i = 0; i < hsc->slot_table_size; i++) { - - char *nexus, *pcidev, *phys_slotname, *ga; - - /* Pick off pointer to nexus path or PROM handle */ - nexus = s; - while (*s != NULL) - s++; - s++; - - /* Pick off pointer to the pci device number */ - pcidev = s; - while (*s != NULL) - s++; - s++; - - /* Pick off physical slot no */ - phys_slotname = s; - while (*s != NULL) - s++; - s++; - - /* Pick off GA bits which we dont use for now. */ - ga = s; - while (*s != NULL) - s++; - s++; - - if (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES && - atoi(phys_slotname) == SC_MC_CTC_SLOT) { - --i; - continue; - } - hsc->slot_table_prop[i].pslotnum = atoi(phys_slotname); - hsc->slot_table_prop[i].ga = atoi(ga); - hsc->slot_table_prop[i].pci_devno = atoi(pcidev); - (void) strcpy(hsc->slot_table_prop[i].nexus, nexus); - } - } else { - hpstp = (hsc_prom_slot_table_t *)hpc_slot_table_data; - for (i = 0; i < hsc->slot_table_size; i++, hpstp++) { - if (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES && - hpstp->pslotnum == SC_MC_CTC_SLOT) { - --i; - continue; - } - hsc->slot_table_prop[i].pslotnum = hpstp->pslotnum; - hsc->slot_table_prop[i].ga = hpstp->ga; - hsc->slot_table_prop[i].pci_devno = hpstp->pci_devno; - - if (prom_phandle_to_path((uint_t)hpstp->phandle, - hsc->slot_table_prop[i].nexus, - sizeof (hsc->slot_table_prop[i].nexus)) - == -1) { - cmn_err(CE_WARN, "%s#%d: Cannot get phandle " - "to nexus path", ddi_driver_name(dip), - ddi_get_instance(dip)); - kmem_free(hsc->slot_table_prop, - (hsc->slot_table_size * - sizeof (hsc_slot_table_t))); - kmem_free(hpc_slot_table_data, - hpc_slot_table_size); - ddi_soft_state_free(hsc_state, instance); - return (DDI_FAILURE); - } - } - } - - /* keep healthy register cache uptodate before reading slot state */ - if (scsb_read_bhealthy(scsb_handle) != 0) { - cmn_err(CE_WARN, "%s#%d: hsc_attach: Cannot read " - "Healthy Registers", ddi_driver_name(dip), - ddi_get_instance(dip)); - kmem_free(hsc->slot_table_prop, - (hsc->slot_table_size * - sizeof (hsc_slot_table_t))); - kmem_free(hpc_slot_table_data, - hpc_slot_table_size); - ddi_soft_state_free(hsc_state, instance); - return (DDI_FAILURE); - } - - /* - * Before we start registering the slots, calculate how many - * slots are occupied. - */ - - for (i = 0; i < hsc->slot_table_size; i++) { - if (scsb_get_slot_state(scsb_handle, - hsc->slot_table_prop[i].pslotnum, &rstate) != - DDI_SUCCESS) - return (rc); - if (rstate != HPC_SLOT_EMPTY) - hsc->n_registered_occupants++; - } - - mutex_init(&hsc->hsc_mutex, NULL, MUTEX_DRIVER, NULL); - for (i = 0; i < hsc->slot_table_size; i++) { - - DEBUG2("Registering on nexus [%s] cPCI device [%d]\n", - hsc->slot_table_prop[i].nexus, - hsc->slot_table_prop[i].pci_devno); - - if (hsc_slot_register(hsc, hsc->slot_table_prop[i].nexus, - hsc->slot_table_prop[i].pci_devno, - hsc->slot_table_prop[i].pslotnum, B_FALSE) != - HPC_SUCCESS) { - - cmn_err(CE_WARN, "%s#%d: Slot Registration Failure", - ddi_driver_name(dip), ddi_get_instance(dip)); - while (i) { - i--; - n = hsc->slot_table_prop[i].pslotnum; - if (hsc_slot_unregister(n) != 0) { - cmn_err(CE_WARN, - "%s#%d: failed to unregister" - " slot %d", - ddi_driver_name(dip), - ddi_get_instance(dip), n); - - } - } - mutex_destroy(&hsc->hsc_mutex); - kmem_free(hsc->slot_table_prop, (hsc->slot_table_size * - sizeof (hsc_slot_table_t))); - kmem_free(hpc_slot_table_data, hpc_slot_table_size); - ddi_soft_state_free(hsc_state, instance); - return (DDI_FAILURE); - } - } - - hsc->hsp_last = NULL; - hsc->hsc_intr_counter = 0; - kmem_free(hpc_slot_table_data, hpc_slot_table_size); - (void) ddi_prop_update_string(DDI_DEV_T_NONE, hsc->dip, - HOTSWAP_MODE_PROP, "basic"); - hsc->state |= (HSC_ATTACHED|HSC_SCB_CONNECTED); - - /* - * We enable full hotswap right here if all the slots are empty. - */ - if ((hsc->regDone == B_FALSE && hsc->n_registered_occupants == 0) || - scsb_hsc_numReg == hsc->n_registered_occupants) { - hsc->regDone = B_TRUE; - if (hsc->hotswap_mode == HSC_HOTSWAP_MODE_FULL) { - if (scsb_enable_enum(hsc) != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s#%d: Cannot enable " - "Full Hotswap", ddi_driver_name(dip), - ddi_get_instance(dip)); - } - } - } - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -int -scsb_hsc_detach(dev_info_t *dip, void *scsb_handle, int instance) -{ - int i = 0; - hsc_state_t *hsc; - char slotautocfg_prop[18]; - - DEBUG0("hsc_detach: enter\n"); - hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance); - if (hsc == NULL) { - DEBUG2("%s#%d: hsc_detach: Soft state NULL", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_FAILURE); - } - - if ((hsc->state & HSC_ATTACHED) != HSC_ATTACHED) - return (DDI_FAILURE); - /* - * let's unregister the hotpluggable slots with hotplug service. - */ - for (i = 0; i < hsc->slot_table_size; i++) { - - hsc_slot_t *hsp; - - hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum); - if (hsp == NULL) { - cmn_err(CE_WARN, "%s#%d: hsc_detach: No Slot Info", - ddi_driver_name(dip), ddi_get_instance(dip)); - } else { - hpc_led_info_t aledinfo; /* active led info. */ - hpc_led_info_t fledinfo; /* fault led info. */ - - aledinfo.led = HPC_ACTIVE_LED; - aledinfo.state = HPC_LED_BLINK; - fledinfo.led = HPC_FAULT_LED; - fledinfo.state = HPC_LED_OFF; - (void) hsc_led_state(hsp, HPC_CTRL_SET_LED_STATE, - &aledinfo); - (void) hsc_led_state(hsp, HPC_CTRL_SET_LED_STATE, - &fledinfo); - } - (void) sprintf(slotautocfg_prop, "slot%d-autoconfig", - hsp->hs_slot_number); - (void) ddi_prop_remove(DDI_DEV_T_NONE, hsc->dip, - slotautocfg_prop); - if (hsc_slot_unregister(hsc->slot_table_prop[i].pslotnum) - != 0) { - cmn_err(CE_NOTE, "%s#%d: failed to unregister" - " slot %d\n", ddi_driver_name(dip), - ddi_get_instance(dip), - hsc->slot_table_prop[i].pslotnum); - return (DDI_FAILURE); - } - } - kmem_free(hsc->slot_table_prop, (hsc->slot_table_size * - sizeof (hsc_slot_table_t))); - if ((hsc->state & HSC_ENUM_ENABLED) == HSC_ENUM_ENABLED) { - ddi_remove_intr(hsc->dip, 1, hsc->enum_iblock); - hsc->state &= ~HSC_ENUM_ENABLED; - } - mutex_destroy(&hsc->hsc_mutex); - (void) ddi_prop_remove(DDI_DEV_T_NONE, hsc->dip, HOTSWAP_MODE_PROP); - hsc->state &= ~(HSC_ATTACHED|HSC_SCB_CONNECTED); - ddi_soft_state_free(hsc_state, instance); - return (DDI_SUCCESS); -} - -/* - * The following function is called when the SCSB is hot extracted from - * the system. - */ -int -scsb_hsc_freeze(dev_info_t *dip) -{ - hsc_state_t *hsc; - int instance = ddi_get_instance(dip); - int i; - hsc_slot_t *hsp; - - hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance); - if (hsc == NULL) { - DEBUG2("%s#%d: Soft state NULL", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_SUCCESS); - } - if ((hsc->state & HSC_ATTACHED) != HSC_ATTACHED) - return (DDI_SUCCESS); - hsc->state &= ~HSC_SCB_CONNECTED; - - for (i = 0; i < hsc->slot_table_size; i++) { - hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum); - - if (hsp == NULL) { - cmn_err(CE_NOTE, "hsc_freeze: " - " Cannot map slot number %d to a hsc_slot_t", - hsc->slot_table_prop[i].pslotnum); - continue; - } - /* - * Since reset lines are pulled low, lets mark these - * slots and not allow a connect operation. - * Note that we still keep the slot as slot disconnected, - * although it is connected from the hardware standpoint. - * As soon as the SCB is plugged back in, we check these - * states and put the hardware state back to its original - * state. - */ - if (hsp->hs_slot_state == HPC_SLOT_DISCONNECTED) { - cmn_err(CE_WARN, "%s#%d: Slot %d Now out of Reset!", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - hsp->hs_slot_number); - } - hsp->hs_flags |= HSC_SCB_HOTSWAPPED; - } - - return (DDI_SUCCESS); -} - -/* - * The following function is called when the SCSB is hot inserted from - * the system. We must update the LED status and set the RST# registers - * again. - */ -int -scsb_hsc_restore(dev_info_t *dip) -{ - int i; - hsc_state_t *hsc; - hsc_slot_t *hsp; - int instance = ddi_get_instance(dip); - - hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance); - if (hsc == NULL) { - DEBUG2("%s#%d: Soft state NULL", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_SUCCESS); - } - - if ((hsc->state & HSC_ATTACHED) != HSC_ATTACHED) - return (DDI_SUCCESS); - hsc->state |= HSC_SCB_CONNECTED; - for (i = 0; i < hsc->slot_table_size; i++) { - hsp = hsc_find_slot(hsc->slot_table_prop[i].pslotnum); - - if (hsp == NULL) { - cmn_err(CE_NOTE, "%s#%d: hsc_restore: " - " Cannot map slot number %d to a hsc_slot_t", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - hsc->slot_table_prop[i].pslotnum); - continue; - } - if ((hsp->hs_slot_state == HPC_SLOT_DISCONNECTED) && - (hsp->hs_board_configured == B_FALSE)) { - if (scsb_reset_slot(hsp->hs_hpchandle, - hsp->hs_slot_number, - SCSB_RESET_SLOT) != 0) { - cmn_err(CE_WARN, "%s#%d: hsc_restore: " - " Cannot reset disconnected slot %d", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - hsp->hs_slot_number); - } - } - - if (scsb_hsc_init_slot_state(hsc, hsp) != DDI_SUCCESS) { - - cmn_err(CE_WARN, "%s#%d: hsc_freeze: Cannot init" - " slot%d state", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - hsp->hs_slot_number); - } - hsp->hs_flags &= ~HSC_SCB_HOTSWAPPED; - } - return (DDI_SUCCESS); -} - -#ifndef lint -int -scsb_hsc_freeze_check(dev_info_t *dip) -{ - hsc_state_t *hsc; - int instance = ddi_get_instance(dip); - - hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance); - if (hsc == NULL) { - DEBUG2("%s#%d: Soft state NULL", - ddi_driver_name(dip), ddi_get_instance(dip)); - return (DDI_SUCCESS); - } - if ((hsc->state & HSC_ATTACHED) != HSC_ATTACHED) - return (DDI_SUCCESS); - return (DDI_SUCCESS); -} -#endif - -/* - * update info about Alarm Card insert/remove mechanism. - */ -void -hsc_ac_op(int instance, int pslotnum, int op, void *arg) -{ - hsc_slot_t *hsp; - hsc_state_t *hsc; - - hsc = (hsc_state_t *)ddi_get_soft_state(hsc_state, instance); - if (hsc == NULL) { - cmn_err(CE_WARN, "%s#%d: hsc_ac_op: No Soft State Info", - ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip)); - return; - } - - hsp = hsc_find_slot(pslotnum); - if (hsp == NULL) { - cmn_err(CE_WARN, "%s#%d: hsc_ac_op: No Slot Info", - ddi_driver_name(hsc->dip), ddi_get_instance(hsc->dip)); - return; - } - - switch (op) { - case SCSB_HSC_AC_UNCONFIGURE : - /* - * If ENUM# is enabled, then action is pending on - * this slot, just send a event. - */ - if (hsc->state & HSC_ENUM_ENABLED) - (void) hpc_slot_event_notify( - hsp->hs_slot_handle, - HPC_EVENT_PROCESS_ENUM, 0); - break; - case SCSB_HSC_AC_GET_SLOT_INFO : - *(hsc_slot_t **)arg = hsp; - break; - default : - break; - } -} - -static uint_t -hsc_enum_intr(caddr_t iarg) -{ - int rc; - hsc_state_t *hsc = (hsc_state_t *)iarg; - hsc_slot_t *hsp; - - DEBUG0("!E!"); - if ((hsc->state & HSC_ATTACHED) == 0) - return (DDI_INTR_UNCLAIMED); - - hsp = hsc_find_slot(hsc->slot_table_prop[0].pslotnum); - if (hsp == NULL) /* No slots registered */ - return (DDI_INTR_UNCLAIMED); - - /* - * The following must be done to clear interrupt (synchronous event). - * To process the interrupt, we send an asynchronous event. - */ - rc = hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_CLEAR_ENUM, - HPC_EVENT_SYNCHRONOUS); - if (rc == HPC_EVENT_UNCLAIMED) { - /* - * possible support for handling insertion of non friendly - * full hotswap boards, otherwise the system hangs due - * to uncleared interrupt bursts. - */ - DEBUG2("!E>counter %d, last op@slot %lx\n", - hsc->hsc_intr_counter, hsc->hsp_last); - hsc->hsc_intr_counter ++; - if (hsc->hsc_intr_counter == scsb_hsc_max_intr_count) { - if (!hsc->hsp_last) { - cmn_err(CE_WARN, "%s#%d: hsc_enum_intr: " - " No Last Board Insertion Info.", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip)); - hsc->hsc_intr_counter = 0; - return (DDI_INTR_UNCLAIMED); - } - hsp = hsc->hsp_last; - cmn_err(CE_WARN, "%s#%d: Bad (non friendly ?) Board " - "in Slot %d ? Taking it Offline.", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), - hsp->hs_slot_number); - /* - * this should put just inserted board back in - * reset, thus deasserting the ENUM# and the - * system hang. - */ - if (scsb_reset_slot(hsp->hs_hpchandle, - hsp->hs_slot_number, - SCSB_RESET_SLOT) == 0) { - /* Enumeration failed on this board */ - hsp->hs_flags |= HSC_ENUM_FAILED; - if (hsp->hs_board_configured == B_TRUE) - cmn_err(CE_WARN, "%s#%d: ALERT! System" - " now in Inconsistent State." - " Halt!", - ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip)); - hsc_led_op(hsp, HPC_CTRL_SET_LED_STATE, - HPC_FAULT_LED, HPC_LED_ON); - } - hsc->hsc_intr_counter = 0; - } - return (DDI_INTR_UNCLAIMED); - } - hsc->hsc_intr_counter = 0; - /* - * if interrupt success, rc denotes the PCI device number which - * generated the ENUM# interrupt. - */ - hsp = hsc_get_slot_info(hsc, rc); - if (hsp == NULL) { - cmn_err(CE_WARN, "%s#%d: hsc_enum_intr: no slot info for " - "dev %x", ddi_driver_name(hsc->dip), - ddi_get_instance(hsc->dip), rc); - return (DDI_INTR_CLAIMED); /* interrupt already cleared */ - } - /* if this is Alarm Card and if it is busy, dont process event */ - if (hsp->hs_flags & HSC_ALARM_CARD_PRES) { - if (scsb_hsc_ac_op(hsp->hs_hpchandle, hsp->hs_slot_number, - SCSB_HSC_AC_BUSY) == B_TRUE) { - /* - * Busy means we need to inform (envmond)alarmcard.so - * that it should save the AC configuration, stop the - * heartbeat, and shutdown the RSC link. - */ - (void) scsb_hsc_ac_op(hsp->hs_hpchandle, - hsp->hs_slot_number, - SCSB_HSC_AC_REMOVAL_ALERT); - return (DDI_INTR_CLAIMED); - } - } - /* - * If SCB was swapped out, dont process ENUM#. We put this slot - * back in reset after SCB is inserted. - */ - if ((hsp->hs_flags & HSC_SCB_HOTSWAPPED) && - (hsp->hs_slot_state == HPC_SLOT_DISCONNECTED)) - return (DDI_INTR_CLAIMED); - - (void) hpc_slot_event_notify(hsp->hs_slot_handle, - HPC_EVENT_PROCESS_ENUM, 0); - return (DDI_INTR_CLAIMED); -} -/* - * A routine to convert a number (represented as a string) to - * the integer value it represents. - */ - -static int -isdigit(int ch) -{ - return (ch >= '0' && ch <= '9'); -} - -#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') -#define bad(val) (val == NULL || !isdigit(*val)) - -static int -atoi(const char *p) -{ - int n; - int c, neg = 0; - - if (!isdigit(c = *p)) { - while (isspace(c)) - c = *++p; - switch (c) { - case '-': - neg++; - /* FALLTHROUGH */ - case '+': - c = *++p; - } - if (!isdigit(c)) - return (0); - } - for (n = '0' - c; isdigit(c = *++p); ) { - n *= 10; /* two steps to avoid unnecessary overflow */ - n += '0' - c; /* accum neg to avoid surprises at MAX */ - } - return (neg ? n : -n); -} diff --git a/usr/src/uts/sun4u/montecarlo/io/pcf8574_nct.c b/usr/src/uts/sun4u/montecarlo/io/pcf8574_nct.c deleted file mode 100644 index 409d50a8d8..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/pcf8574_nct.c +++ /dev/null @@ -1,1881 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2011 Bayard G. Bell. All rights reserved. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/signal.h> -#include <sys/errno.h> -#include <sys/file.h> -#include <sys/termio.h> -#include <sys/termios.h> -#include <sys/cmn_err.h> -#include <sys/stream.h> -#include <sys/strsun.h> -#include <sys/stropts.h> -#include <sys/strtty.h> -#include <sys/debug.h> -#include <sys/eucioctl.h> -#include <sys/cred.h> -#include <sys/uio.h> -#include <sys/stat.h> -#include <sys/kmem.h> - -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/obpdefs.h> -#include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */ -#include <sys/modctl.h> /* for modldrv */ -#include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */ -#include <sys/open.h> /* for open params. */ -#include <sys/uio.h> /* for read/write */ - -#include <sys/i2c/misc/i2c_svc.h> -#include <sys/mct_topology.h> -#include <sys/envctrl_gen.h> /* must be before netract_gen.h */ -#include <sys/netract_gen.h> -#include <sys/pcf8574_nct.h> -#include <sys/scsb_cbi.h> - -#ifdef DEBUG -#define dbg_print(level, str) cmn_err(level, str); - static int pcf8574_debug = 0x00000102; -#else -#define dbg_print(level, str) {; } -#endif - -#define CV_LOCK(retval) \ -{ \ - mutex_enter(&unitp->umutex); \ - while (unitp->pcf8574_flags == PCF8574_BUSY) { \ - if (cv_wait_sig(&unitp->pcf8574_cv, \ - &unitp->umutex) <= 0) { \ - mutex_exit(&unitp->umutex); \ - return (retval); \ - } \ - } \ - unitp->pcf8574_flags = PCF8574_BUSY; \ - mutex_exit(&unitp->umutex); \ -} - -#define CV_UNLOCK \ -{ \ - mutex_enter(&unitp->umutex); \ - unitp->pcf8574_flags = 0; \ - cv_signal(&unitp->pcf8574_cv); \ - mutex_exit(&unitp->umutex); \ -} - -static int nct_p10fan_patch = 0; /* Fan patch for P1.0 */ -static void *pcf8574_soft_statep; - -/* - * cb ops (only need open,close,read,write,ioctl) - */ -static int pcf8574_open(dev_t *, int, int, cred_t *); -static int pcf8574_close(dev_t, int, int, cred_t *); -static int pcf8574_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); -static int pcf8574_read(dev_t dev, struct uio *uiop, cred_t *cred_p); -static int pcf8574_chpoll(dev_t, short, int, short *, struct pollhead **); -static uint_t pcf8574_intr(caddr_t arg); -static int pcf8574_io(dev_t, struct uio *, int); - -static struct cb_ops pcf8574_cbops = { - pcf8574_open, /* open */ - pcf8574_close, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - pcf8574_read, /* read */ - nodev, /* write */ - pcf8574_ioctl, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - pcf8574_chpoll, /* poll */ - ddi_prop_op, /* cb_prop_op */ - NULL, /* streamtab */ - D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ - CB_REV, /* rev */ - nodev, /* int (*cb_aread)() */ - nodev /* int (*cb_awrite)() */ -}; - -/* - * dev ops - */ -static int pcf8574_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); -static int pcf8574_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); - -/* kstat routines */ -static int pcf8574_add_kstat(struct pcf8574_unit *, scsb_fru_status_t); -static void pcf8574_delete_kstat(struct pcf8574_unit *); -static int pcf8574_kstat_update(kstat_t *, int); -static int pcf8574_read_chip(struct pcf8574_unit *unitp, - uint16_t size); -static int pcf8574_write_chip(struct pcf8574_unit *unitp, - uint16_t size, uint8_t bitpattern); -static int pcf8574_read_props(struct pcf8574_unit *unitp); -static int pcf8574_init_chip(struct pcf8574_unit *unitp, int); -/* - * SCSB callback function - */ -static void pcf8574_callback(void *, scsb_fru_event_t, scsb_fru_status_t); -extern int scsb_intr_register(uint_t (*intr_handler)(caddr_t), caddr_t, - fru_id_t); -extern int scsb_intr_unregister(fru_id_t); - -extern int nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran); - -static struct dev_ops pcf8574_ops = { - DEVO_REV, - 0, - ddi_getinfo_1to1, - nulldev, - nulldev, - pcf8574_attach, - pcf8574_detach, - nodev, - &pcf8574_cbops, - NULL, /* bus_ops */ - NULL, /* power */ - ddi_quiesce_not_supported, /* devo_quiesce */ -}; - -extern struct mod_ops mod_driverops; - -static struct modldrv pcf8574_modldrv = { - &mod_driverops, /* type of module - driver */ - "Netract pcf8574 (gpio)", - &pcf8574_ops, -}; - -static struct modlinkage pcf8574_modlinkage = { - MODREV_1, - &pcf8574_modldrv, - 0 -}; - -int -_init(void) -{ - register int error; - - error = mod_install(&pcf8574_modlinkage); - if (!error) { - (void) ddi_soft_state_init(&pcf8574_soft_statep, - sizeof (struct pcf8574_unit), PCF8574_MAX_DEVS); - } - - return (error); -} - -int -_fini(void) -{ - register int error; - - error = mod_remove(&pcf8574_modlinkage); - if (!error) - ddi_soft_state_fini(&pcf8574_soft_statep); - - return (error); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&pcf8574_modlinkage, modinfop)); -} - -/*ARGSUSED*/ -static int -pcf8574_open(dev_t *devp, int flags, int otyp, cred_t *credp) -{ - struct pcf8574_unit *unitp; - register int instance; - int err = DDI_SUCCESS; - - instance = getminor(*devp); - if (instance < 0) { - return (ENXIO); - } - - unitp = (struct pcf8574_unit *) - ddi_get_soft_state(pcf8574_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - if (otyp != OTYP_CHR) { - return (EINVAL); - } - - mutex_enter(&unitp->umutex); - - if (flags & FEXCL) { - if (unitp->pcf8574_oflag != 0) { - err = EBUSY; - } else { - unitp->pcf8574_oflag = FEXCL; - } - } else { - if (unitp->pcf8574_oflag == FEXCL) { - err = EBUSY; - } else { - unitp->pcf8574_oflag = FOPEN; - } - } - - mutex_exit(&unitp->umutex); - - return (err); -} - -/*ARGSUSED*/ -static int -pcf8574_close(dev_t dev, int flags, int otyp, cred_t *credp) -{ - struct pcf8574_unit *unitp; - register int instance; - -#ifdef lint - flags = flags; - otyp = otyp; -#endif - - instance = getminor(dev); - - if (instance < 0) { - return (ENXIO); - } - - unitp = (struct pcf8574_unit *) - ddi_get_soft_state(pcf8574_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - mutex_enter(&unitp->umutex); - - unitp->pcf8574_oflag = 0; - - mutex_exit(&unitp->umutex); - - return (DDI_SUCCESS); -} - - -/*ARGSUSED*/ -static int -pcf8574_read(dev_t dev, struct uio *uiop, cred_t *cred_p) -{ - return (pcf8574_io(dev, uiop, B_READ)); -} - -static int -pcf8574_io(dev_t dev, struct uio *uiop, int rw) -{ - struct pcf8574_unit *unitp; - register int instance; - uint16_t bytes_to_rw; - int err = DDI_SUCCESS; - - err = 0; - instance = getminor(dev); - - if (instance < 0) { - return (ENXIO); - } - - unitp = (struct pcf8574_unit *) - ddi_get_soft_state(pcf8574_soft_statep, instance); - if (unitp == NULL) { - return (ENXIO); - } - if ((bytes_to_rw = uiop->uio_resid) > PCF8574_TRAN_SIZE) { - return (EINVAL); - } - - CV_LOCK(EINTR) - - if (rw == B_WRITE) { - err = uiomove(unitp->i2c_tran->i2c_wbuf, - bytes_to_rw, UIO_WRITE, uiop); - - if (!err) { - err = pcf8574_write_chip(unitp, bytes_to_rw, - unitp->writemask); - } - - } else { - err = pcf8574_read_chip(unitp, bytes_to_rw); - if (!err) { - err = uiomove(unitp->i2c_tran->i2c_rbuf, - bytes_to_rw, UIO_READ, uiop); - } - } - - CV_UNLOCK - if (err) - err = EIO; - - return (err); -} - -static int -pcf8574_do_resume(dev_info_t *dip) -{ - int instance = ddi_get_instance(dip); - struct pcf8574_unit *unitp = - ddi_get_soft_state(pcf8574_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - CV_UNLOCK - - return (DDI_SUCCESS); -} - -static int -pcf8574_do_detach(dev_info_t *dip) -{ - struct pcf8574_unit *unitp; - int instance; - uint_t attach_flag; - - instance = ddi_get_instance(dip); - unitp = ddi_get_soft_state(pcf8574_soft_statep, instance); - - attach_flag = unitp->attach_flag; - - if (attach_flag & PCF8574_INTR_ADDED) { - (void) scsb_intr_unregister( - (fru_id_t)unitp->props.slave_address); - } - - if (attach_flag & PCF8574_KSTAT_INIT) { - pcf8574_delete_kstat(unitp); - } - - if (attach_flag & PCF8574_LOCK_INIT) { - mutex_destroy(&unitp->umutex); - cv_destroy(&unitp->pcf8574_cv); - } - - scsb_fru_unregister((void *)unitp, - (fru_id_t)unitp->props.slave_address); - - if (attach_flag & PCF8574_ALLOC_TRANSFER) { - /* - * restore the lengths to allocated lengths - * before freeing. - */ - unitp->i2c_tran->i2c_wlen = MAX_WLEN; - unitp->i2c_tran->i2c_rlen = MAX_RLEN; - i2c_transfer_free(unitp->pcf8574_hdl, unitp->i2c_tran); - } - - if (attach_flag & PCF8574_REGISTER_CLIENT) { - i2c_client_unregister(unitp->pcf8574_hdl); - } - - if (attach_flag & PCF8574_MINORS_CREATED) { - ddi_remove_minor_node(dip, NULL); - } - - if (attach_flag & PCF8574_PROPS_READ) { - if (unitp->pcf8574_type == PCF8574_ADR_CPUVOLTAGE && - unitp->props.num_chans_used != 0) { - ddi_prop_free(unitp->props.channels_in_use); - } else { - (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, - "interrupt-priorities"); - } - } - - if (attach_flag & PCF8574_SOFT_STATE_ALLOC) { - ddi_soft_state_free(pcf8574_soft_statep, instance); - } - - return (DDI_SUCCESS); -} - -/* - * NOTE**** - * The OBP will create device tree node for all I2C devices which - * may be present in a system. This means, even if the device is - * not physically present, the device tree node exists. We also - * will succeed the attach routine, since currently there is no - * hotplug support in the I2C bus, and the FRUs need to be hot - * swappable. Only during an I2C transaction we figure out whether - * the particular I2C device is actually present in the system - * by looking at the system controller board register. The fantray - * and power-supply devices may be swapped any time after system - * reboot, and the way we can make sure that the device is attached - * to the driver, is by always keeping the driver loaded, and report - * an error during the actual transaction. - */ -static int -pcf8574_do_attach(dev_info_t *dip) -{ - register struct pcf8574_unit *unitp; - int instance; - char name[MAXNAMELEN]; - int i; - pcf8574_channel_t *chp; - scsb_fru_status_t dev_presence; - - instance = ddi_get_instance(dip); -#ifdef DEBUG - if (pcf8574_debug & 0x04) - cmn_err(CE_NOTE, "pcf8574_attach: instance=%d\n", - instance); -#endif /* DEBUG */ - - if (ddi_soft_state_zalloc(pcf8574_soft_statep, instance) != - DDI_SUCCESS) { - return (DDI_FAILURE); - } - unitp = ddi_get_soft_state(pcf8574_soft_statep, instance); - - if (unitp == NULL) { - ddi_soft_state_free(pcf8574_soft_statep, instance); - return (DDI_FAILURE); - } - - unitp->dip = dip; - - unitp->attach_flag = PCF8574_SOFT_STATE_ALLOC; - - if (pcf8574_read_props(unitp) != DDI_PROP_SUCCESS) { - ddi_soft_state_free(pcf8574_soft_statep, instance); - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8574_PROPS_READ; - - /* - * Set the current operating mode to NORMAL_MODE. - */ - unitp->current_mode = ENVCTRL_NORMAL_MODE; - - (void) snprintf(unitp->pcf8574_name, PCF8574_NAMELEN, - "%s%d", ddi_driver_name(dip), instance); - - if (unitp->pcf8574_type == PCF8574_TYPE_PWRSUPP) { - (void) sprintf(name, "pwrsuppply"); - if (ddi_create_minor_node(dip, name, S_IFCHR, instance, - PCF8574_NODE_TYPE, NULL) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - (void) pcf8574_do_detach(dip); - - return (DDI_FAILURE); - } - } - else - if (unitp->pcf8574_type == PCF8574_TYPE_FANTRAY) { - (void) sprintf(name, "fantray"); - if (ddi_create_minor_node(dip, name, S_IFCHR, instance, - PCF8574_NODE_TYPE, NULL) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - (void) pcf8574_do_detach(dip); - - return (DDI_FAILURE); - } - } - else - if (unitp->pcf8574_type == PCF8574_TYPE_CPUVOLTAGE) { - (void) sprintf(name, "cpuvoltage"); - if (ddi_create_minor_node(dip, name, S_IFCHR, instance, - PCF8574_NODE_TYPE, NULL) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - (void) pcf8574_do_detach(dip); - - return (DDI_FAILURE); - } - } else { - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8574_MINORS_CREATED; - - /* - * Now we need read/write masks since all the 8574 bits can be either - * read/written, but some ports are intended to be RD/WR only, or RW - * If no channels-in-use propoerty, set default values. - */ - if (unitp->pcf8574_type == PCF8574_TYPE_FANTRAY) { - unitp->readmask = PCF8574_FAN_READMASK; - unitp->writemask = PCF8574_FAN_WRITEMASK; - } - if (unitp->pcf8574_type == PCF8574_TYPE_PWRSUPP) { - unitp->readmask = PCF8574_PS_READMASK; - unitp->writemask = PCF8574_PS_WRITEMASK; - } - - for (i = unitp->props.num_chans_used, - chp = unitp->props.channels_in_use; i; --i, ++chp) { - unitp->readmask |= (uint8_t)( - (chp->io_dir == I2C_PROP_IODIR_IN || - chp->io_dir == I2C_PROP_IODIR_INOUT) << chp->port); - unitp->writemask |= (uint8_t)( - (chp->io_dir == I2C_PROP_IODIR_OUT || - chp->io_dir == I2C_PROP_IODIR_INOUT) << chp->port); - } - -#ifdef DEBUG - cmn_err(CE_NOTE, "pcf8574_do_attach: readmask = 0x%x \ - writemask = 0x%x\n", unitp->readmask, unitp->writemask); -#endif /* DEBUG */ - - if (i2c_client_register(dip, &unitp->pcf8574_hdl) - != I2C_SUCCESS) { - (void) pcf8574_do_detach(dip); - return (DDI_FAILURE); - } - unitp->attach_flag |= PCF8574_REGISTER_CLIENT; - - /* - * Allocate the I2C_transfer structure. The same structure - * is used throughout the driver. - */ - if (i2c_transfer_alloc(unitp->pcf8574_hdl, &unitp->i2c_tran, - MAX_WLEN, MAX_RLEN, KM_SLEEP) != I2C_SUCCESS) { - (void) pcf8574_do_detach(dip); - return (DDI_FAILURE); - } - unitp->attach_flag |= PCF8574_ALLOC_TRANSFER; - - /* - * To begin with we set the mode to I2C_RD. - */ - unitp->i2c_tran->i2c_flags = I2C_RD; - unitp->i2c_tran->i2c_version = I2C_XFER_REV; - - /* - * Set the busy flag and open flag to 0. - */ - unitp->pcf8574_flags = 0; - unitp->pcf8574_oflag = 0; - - mutex_init(&unitp->umutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&unitp->pcf8574_cv, NULL, CV_DRIVER, NULL); - - unitp->attach_flag |= PCF8574_LOCK_INIT; - - /* - * Register out callback function with the SCSB driver, and save - * the returned value to check that the device instance exists. - */ - dev_presence = scsb_fru_register(pcf8574_callback, (void *)unitp, - (fru_id_t)unitp->props.slave_address); - if (dev_presence == FRU_NOT_AVAILABLE) { - scsb_fru_unregister((void *)unitp, - (fru_id_t)unitp->props.slave_address); - } - - /* - * Add the kstats. First we need to get the property values - * depending on the device type. For example, for the fan - * tray there will be a different set of properties, and there - * will be another for the powersupplies, and another one for - * the CPU voltage monitor. Initialize the kstat structures with - * these values. - */ - - if (pcf8574_add_kstat(unitp, dev_presence) != DDI_SUCCESS) { - (void) pcf8574_do_detach(dip); - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8574_KSTAT_INIT; - - /* - * Due to observed behavior on Solaris 8, the handler must be - * registered before any interrupts are enabled, - * in spite of what the ddi_get_iblock_cookie() manual says. - * As per the HW/SW spec, by default interrupts are disabled. - */ - - if (dev_presence == FRU_PRESENT) { /* program the chip */ - (void) pcf8574_init_chip(unitp, 0); /* Disable intr first */ - } - - if (unitp->pcf8574_canintr == PCF8574_INTR_ON) { -#ifdef DEBUG - if (pcf8574_debug & 0x0004) - cmn_err(CE_NOTE, "registering pcf9574 interrupt " - "handler"); -#endif /* DEBUG */ - if (scsb_intr_register(pcf8574_intr, (void *)unitp, - (fru_id_t)unitp->props.slave_address) == DDI_SUCCESS) { - unitp->pcf8574_canintr |= PCF8574_INTR_ENABLED; - unitp->attach_flag |= PCF8574_INTR_ADDED; - } else { - (void) pcf8574_do_detach(dip); - return (DDI_FAILURE); - } - } - - ddi_report_dev(dip); - - return (DDI_SUCCESS); -} - -static int -pcf8574_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - switch (cmd) { - case DDI_ATTACH: - return (pcf8574_do_attach(dip)); - case DDI_RESUME: - return (pcf8574_do_resume(dip)); - default: - return (DDI_FAILURE); - } -} - -static int -pcf8574_do_suspend(dev_info_t *dip) -{ - int instance = ddi_get_instance(dip); - struct pcf8574_unit *unitp = - ddi_get_soft_state(pcf8574_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - /* - * Set the busy flag so that future transactions block - * until resume. - */ - CV_LOCK(ENXIO) - - return (DDI_SUCCESS); -} - -static int -pcf8574_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - switch (cmd) { - case DDI_DETACH: - return (pcf8574_do_detach(dip)); - case DDI_SUSPEND: - return (pcf8574_do_suspend(dip)); - default: - return (DDI_FAILURE); - } -} - -static int -pcf8574_chpoll(dev_t dev, short events, int anyyet, short *reventsp, - struct pollhead **phpp) -{ - struct pcf8574_unit *unitp; - int instance; - - instance = getminor(dev); - if ((unitp = (struct pcf8574_unit *)ddi_get_soft_state( - pcf8574_soft_statep, instance)) == NULL) { - return (ENXIO); - } - *reventsp = 0; - mutex_enter(&unitp->umutex); - if (unitp->poll_event) { - *reventsp = unitp->poll_event; - unitp->poll_event = 0; - } else if ((events & POLLIN) && !anyyet) - *phpp = &unitp->poll; - mutex_exit(&unitp->umutex); - return (0); -} - -/* - * In normal scenarios, this function should never get called. - * But, we will still come back and call this function if scsb - * interrupt sources does not indicate an scsb interrupt. We may - * come to this situation when SunVTS env4test is independently - * changing the device registers. - */ -uint_t -pcf8574_intr(caddr_t arg) -{ - int ic; - uint8_t value; - struct pcf8574_unit *unitp = (struct pcf8574_unit *)(void *)arg; - scsb_fru_status_t dev_presence; - i2c_transfer_t *tp = unitp->i2c_tran; - - ic = DDI_INTR_CLAIMED; -#ifdef DEBUG - cmn_err(CE_NOTE, " In the interrupt service routine, %x", - unitp->props.slave_address); -#endif - - /* - * Initiate an I2C transaction to find out - * whether this is the device which interrupted. - */ - mutex_enter(&unitp->umutex); - while (unitp->pcf8574_flags == PCF8574_BUSY) { - if (cv_wait_sig(&unitp->pcf8574_cv, &unitp->umutex) <= 0) { - mutex_exit(&unitp->umutex); - return (DDI_INTR_UNCLAIMED); - } - } - - unitp->pcf8574_flags = PCF8574_BUSY; - mutex_exit(&unitp->umutex); - - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_CPUVOLTAGE: { - dev_presence = FRU_PRESENT; - break; - } - case PCF8574_TYPE_PWRSUPP: { - envctrl_pwrsupp_t *envp = - (envctrl_pwrsupp_t *)unitp->envctrl_kstat; - dev_presence = envp->ps_present; - break; - } - case PCF8574_TYPE_FANTRAY: { - envctrl_fantray_t *envp = - (envctrl_fantray_t *)unitp->envctrl_kstat; - dev_presence = envp->fan_present; - break; - } - } - if (dev_presence != FRU_PRESENT) { - ic = DDI_INTR_UNCLAIMED; - goto intr_exit; - } - if (pcf8574_read_chip(unitp, 1) != I2C_SUCCESS) { - ic = DDI_INTR_UNCLAIMED; - goto intr_exit; - } - value = unitp->i2c_tran->i2c_rbuf[0]; - /* - * If interrupt is already masked, return - */ - if (value & PCF8574_INTRMASK_BIT) { - ic = DDI_INTR_UNCLAIMED; - goto intr_exit; - } - - /* - * In case a fault bit is set, claim the interrupt. - */ - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_PWRSUPP: - { - envctrl_pwrsupp_t *envp = - (envctrl_pwrsupp_t *)unitp->envctrl_kstat; - - if (PCF8574_PS_FAULT(value) || - PCF8574_PS_TEMPOK(value) || - PCF8574_PS_ONOFF(value) || - PCF8574_PS_FANOK(value)) { - - envp->ps_ok = PCF8574_PS_FAULT(value); - envp->temp_ok = PCF8574_PS_TEMPOK(value); - envp->psfan_ok = PCF8574_PS_FANOK(value); - envp->on_state = PCF8574_PS_ONOFF(value); - envp->ps_ver = PCF8574_PS_TYPE(value); - - tp->i2c_wbuf[0] = - PCF8574_PS_DEFAULT | PCF8574_PS_MASKINTR; - tp->i2c_wlen = 1; - tp->i2c_rlen = 0; - tp->i2c_flags = I2C_WR; - - unitp->i2c_status = - nct_i2c_transfer(unitp->pcf8574_hdl, tp); - - unitp->poll_event = POLLIN; - pollwakeup(&unitp->poll, POLLIN); - } else { - ic = DDI_INTR_UNCLAIMED; - } - } - break; - - case PCF8574_TYPE_FANTRAY: - { - envctrl_fantray_t *envp = - (envctrl_fantray_t *)unitp->envctrl_kstat; - - if (!PCF8574_FAN_FAULT(value)) { - - envp->fan_ver = PCF8574_FAN_TYPE(value); - envp->fan_ok = PCF8574_FAN_FAULT(value); - envp->fanspeed = PCF8574_FAN_FANSPD(value); - - tp->i2c_wbuf[0] = - PCF8574_FAN_DEFAULT | PCF8574_FAN_MASKINTR; - tp->i2c_wlen = 1; - tp->i2c_rlen = 0; - tp->i2c_flags = I2C_WR; - - unitp->i2c_status = - nct_i2c_transfer(unitp->pcf8574_hdl, tp); - - unitp->poll_event = POLLIN; - pollwakeup(&unitp->poll, POLLIN); - - } else { - ic = DDI_INTR_UNCLAIMED; - } - } - break; - - default: - ic = DDI_INTR_UNCLAIMED; - } /* switch */ - -intr_exit: - mutex_enter(&unitp->umutex); - unitp->pcf8574_flags = 0; - cv_signal(&unitp->pcf8574_cv); - mutex_exit(&unitp->umutex); - - return (ic); -} - -static int -call_copyin(caddr_t arg, struct pcf8574_unit *unitp, int mode) -{ - uchar_t *wbuf; - uchar_t *rbuf; - i2c_transfer_t i2ct; - i2c_transfer_t *i2ctp = unitp->i2c_tran; - - - if (ddi_copyin((void *)arg, (caddr_t)&i2ct, - sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * Save the read and write buffer pointers in the transfer - * structure, otherwise these will get overwritten when we - * do a bcopy. Restore once done. - */ - - wbuf = i2ctp->i2c_wbuf; - rbuf = i2ctp->i2c_rbuf; - - bcopy(&i2ct, i2ctp, sizeof (i2c_transfer_t)); - - i2ctp->i2c_wbuf = wbuf; - i2ctp->i2c_rbuf = rbuf; - - /* - * copyin the read and write buffers to the saved buffers. - */ - - if (i2ct.i2c_wlen != 0) { - if (ddi_copyin(i2ct.i2c_wbuf, (caddr_t)i2ctp->i2c_wbuf, - i2ct.i2c_wlen, mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - } - - return (I2C_SUCCESS); -} - -static int -call_copyout(caddr_t arg, struct pcf8574_unit *unitp, int mode) -{ - i2c_transfer_t i2ct; - i2c_transfer_t *i2ctp = unitp->i2c_tran; - - /* - * We will copyout the last three fields only, skipping - * the remaining ones, before copying the rbuf to the - * user buffer. - */ - - int uskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t), - kskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t); - - /* - * First copyin the user structure to the temporary i2ct, - * so that we have the wbuf and rbuf addresses in it. - */ - - uskip = sizeof (i2c_transfer_t) - 3 * (sizeof (uint16_t)); - - /* - * copyout the last three out fields now. - */ - - if (ddi_copyout((void *)((intptr_t)i2ctp+kskip), (void *) - ((intptr_t)arg + uskip), 3*sizeof (uint16_t), mode) - != DDI_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * In case we have something to write, get the address of the read - * buffer. - */ - - if (i2ctp->i2c_rlen > i2ctp->i2c_r_resid) { - - if (ddi_copyin((void *)arg, &i2ct, - sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * copyout the read buffer to the saved user buffer in i2ct. - */ - - if (ddi_copyout(i2ctp->i2c_rbuf, i2ct.i2c_rbuf, - i2ctp->i2c_rlen - i2ctp->i2c_r_resid, mode) - != DDI_SUCCESS) { - return (I2C_FAILURE); - } - } - - return (I2C_SUCCESS); -} - -/*ARGSUSED*/ -static int -pcf8574_ioctl(dev_t dev, int cmd, intptr_t arg, - int mode, cred_t *credp, int *rvalp) -{ - struct pcf8574_unit *unitp; - register int instance; - int err = 0; - uint8_t value, inval, outval; - scsb_fru_status_t dev_presence; - - instance = getminor(dev); - - if (instance < 0) { - return (ENXIO); - } - unitp = (struct pcf8574_unit *) - ddi_get_soft_state(pcf8574_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - dev_presence = - scsb_fru_status((uchar_t)unitp->props.slave_address); - - CV_LOCK(EINTR) - - switch (cmd) { - case ENVC_IOC_INTRMASK: - if (dev_presence == FRU_NOT_PRESENT) { - break; - } - - if (ddi_copyin((caddr_t)arg, (caddr_t)&inval, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - break; - } - - if (inval != 0 && inval != 1) { - err = EINVAL; - } else { - unitp->i2c_tran->i2c_wbuf[0] = - PCF8574_INT_MASK(inval); - if (pcf8574_write_chip(unitp, 1, PCF8574_INTRMASK_BIT) - != I2C_SUCCESS) { - err = EFAULT; - } - } - break; - - case ENVC_IOC_SETFAN: - if (unitp->pcf8574_type != PCF8574_TYPE_FANTRAY) { - err = EINVAL; - break; - } - if (dev_presence == FRU_NOT_PRESENT) { - err = EINVAL; - break; - } - if (ddi_copyin((caddr_t)arg, (caddr_t)&inval, sizeof (uint8_t), - mode) != DDI_SUCCESS) { - err = EFAULT; - break; - } - if (inval != PCF8574_FAN_SPEED_LOW && - inval != PCF8574_FAN_SPEED_HIGH) { - err = EINVAL; - break; - } - - unitp->i2c_tran->i2c_wbuf[0] = PCF8574_FAN_SPEED(inval); - - if (pcf8574_write_chip(unitp, 1, PCF8574_FANSPEED_BIT) - != I2C_SUCCESS) { - err = EFAULT; - } - break; - - case ENVC_IOC_SETSTATUS: - /* - * Allow this ioctl only in DIAG mode. - */ - if (unitp->current_mode != ENVCTRL_DIAG_MODE) { - err = EINVAL; - } else { - if (dev_presence == FRU_NOT_PRESENT) { - err = EINVAL; - break; - } - if (ddi_copyin((caddr_t)arg, (caddr_t)&inval, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - } else { - unitp->i2c_tran->i2c_wbuf[0] = inval & 0xff; - if (pcf8574_write_chip(unitp, 1, 0xff) - != I2C_SUCCESS) { - err = EFAULT; - } - } - } - break; - - case ENVC_IOC_GETFAN: - case ENVC_IOC_GETSTATUS: - case ENVC_IOC_GETTYPE: - case ENVC_IOC_GETFAULT: - case ENVC_IOC_PSTEMPOK: - case ENVC_IOC_PSFANOK: - case ENVC_IOC_PSONOFF: { - if (dev_presence == FRU_NOT_PRESENT) { - err = EINVAL; - break; - } - if (pcf8574_read_chip(unitp, 1) - != I2C_SUCCESS) { - err = EFAULT; - break; - } - value = unitp->i2c_tran->i2c_rbuf[0]; - if (cmd == ENVC_IOC_GETFAN) { - if (unitp->pcf8574_type != PCF8574_TYPE_FANTRAY) { - err = EINVAL; - break; - } else { - outval = PCF8574_FAN_FANSPD(value); - } - } - else - if (cmd == ENVC_IOC_GETSTATUS) { - outval = value; - } - else - if (cmd == ENVC_IOC_GETTYPE) { - if (unitp->pcf8574_type == PCF8574_TYPE_PWRSUPP) - outval = PCF8574_PS_TYPE(value); - if (unitp->pcf8574_type == PCF8574_TYPE_FANTRAY) - outval = PCF8574_FAN_TYPE(value); - } - else - if (cmd == ENVC_IOC_GETFAULT) { - if (unitp->pcf8574_type == PCF8574_TYPE_PWRSUPP) - outval = PCF8574_PS_FAULT(value); - if (unitp->pcf8574_type == PCF8574_TYPE_FANTRAY) - outval = PCF8574_PS_FAULT(value); - } - else - if (cmd == ENVC_IOC_PSTEMPOK) { - outval = PCF8574_PS_TEMPOK(value); - } - else - if (cmd == ENVC_IOC_PSFANOK) { - outval = PCF8574_PS_FANOK(value); - } - else - if (cmd == ENVC_IOC_PSONOFF) { - outval = PCF8574_PS_ONOFF(value); - } else { - outval = 0; - } - - if (ddi_copyout((caddr_t)&outval, (caddr_t)arg, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - } - } - break; - - case ENVC_IOC_GETMODE: { - uint8_t curr_mode = unitp->current_mode; - - if (ddi_copyout((caddr_t)&curr_mode, (caddr_t)arg, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - } - break; - } - - case ENVC_IOC_SETMODE: { - uint8_t curr_mode; - if (ddi_copyin((caddr_t)arg, (caddr_t)&curr_mode, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - break; - } - if (curr_mode == ENVCTRL_DIAG_MODE || - curr_mode == ENVCTRL_NORMAL_MODE) { - unitp->current_mode = curr_mode; /* Don't do anything */ - } - break; - } - - - case I2CDEV_TRAN: - if (call_copyin((caddr_t)arg, unitp, mode) != DDI_SUCCESS) { - err = EFAULT; - break; - } - unitp->i2c_status = err = - nct_i2c_transfer(unitp->pcf8574_hdl, unitp->i2c_tran); - - if (err != I2C_SUCCESS) { - err = EIO; - } else { - if (call_copyout((caddr_t)arg, unitp, mode) - != DDI_SUCCESS) { - err = EFAULT; - break; - } - } - break; - - default: - err = EINVAL; - } - - CV_UNLOCK - - return (err); -} - -static int -pcf8574_add_kstat(struct pcf8574_unit *unitp, scsb_fru_status_t dev_presence) -{ - char ksname[50]; - int id; - uint8_t i2c_address = unitp->props.slave_address; - - /* - * We create the kstat depending on the device function, - * allocate the kstat placeholder and initialize the - * values. - */ - unitp->envctrl_kstat = NULL; - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_CPUVOLTAGE: - { - if ((unitp->kstatp = kstat_create(I2C_PCF8574_NAME, - unitp->instance, I2C_KSTAT_CPUVOLTAGE, "misc", - KSTAT_TYPE_RAW, sizeof (envctrl_cpuvoltage_t), - KSTAT_FLAG_PERSISTENT)) != NULL) { - - if ((unitp->envctrl_kstat = kmem_zalloc( - sizeof (envctrl_cpuvoltage_t), KM_NOSLEEP)) == - NULL) { - kstat_delete(unitp->kstatp); - return (DDI_FAILURE); - } - } else { - return (DDI_FAILURE); - } - - break; - } - case PCF8574_TYPE_PWRSUPP: - { - envctrl_pwrsupp_t *envp; - if (i2c_address == PCF8574_ADR_PWRSUPPLY1) { - id = 1; - } else if (i2c_address == PCF8574_ADR_PWRSUPPLY2) { - id = 2; - } else { - id = i2c_address - PCF8574_ADR_PWRSUPPLY1; - } - (void) sprintf(ksname, "%s%d", I2C_KSTAT_PWRSUPPLY, id); - if ((unitp->kstatp = kstat_create(I2C_PCF8574_NAME, - unitp->instance, ksname, "misc", - KSTAT_TYPE_RAW, sizeof (envctrl_pwrsupp_t), - KSTAT_FLAG_PERSISTENT)) != NULL) { - - if ((unitp->envctrl_kstat = kmem_zalloc( - sizeof (envctrl_pwrsupp_t), KM_NOSLEEP)) == - NULL) { - kstat_delete(unitp->kstatp); - return (DDI_FAILURE); - } - /* - * Initialize the kstat fields. Need to initialize - * the present field from SCSB info (dev_presence) - */ - envp = (envctrl_pwrsupp_t *)unitp->envctrl_kstat; - - envp->ps_present = dev_presence; - envp->ps_ok = 0; - envp->temp_ok = 0; - envp->psfan_ok = 0; - envp->on_state = 0; - envp->ps_ver = 0; - } else { - return (DDI_FAILURE); - } - - break; - } - case PCF8574_TYPE_FANTRAY: - { - envctrl_fantray_t *envp; - if (i2c_address == PCF8574_ADR_FANTRAY1) { - id = 1; - } else if (i2c_address == PCF8574_ADR_FANTRAY2) { - id = 2; - } else { - id = i2c_address - PCF8574_ADR_FANTRAY1; - } - (void) sprintf(ksname, "%s%d", I2C_KSTAT_FANTRAY, id); - if ((unitp->kstatp = kstat_create(I2C_PCF8574_NAME, - unitp->instance, ksname, "misc", - KSTAT_TYPE_RAW, sizeof (envctrl_fantray_t), - KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) != NULL) { - - if ((unitp->envctrl_kstat = kmem_zalloc( - sizeof (envctrl_fantray_t), KM_NOSLEEP)) == - NULL) { - kstat_delete(unitp->kstatp); - return (DDI_FAILURE); - } - - /* - * Initialize the kstat fields. Need to initialize - * the present field from SCSB info (dev_presence) - */ - envp = (envctrl_fantray_t *)unitp->envctrl_kstat; - - envp->fan_present = dev_presence; - envp->fan_ok = 0; - envp->fanspeed = PCF8574_FAN_SPEED60; - envp->fan_ver = 0; - } else { - return (DDI_FAILURE); - } - - break; - } - default: - return (DDI_FAILURE); - } - - unitp->kstatp->ks_private = (void *)unitp; - unitp->kstatp->ks_update = pcf8574_kstat_update; - - kstat_install(unitp->kstatp); - - return (DDI_SUCCESS); -} - -/* - * This function reads a single byte from the pcf8574 chip, for use by the - * kstat routines. The protocol for read will depend on the function. - */ - -static int -pcf8574_read_chip(struct pcf8574_unit *unitp, uint16_t size) -{ - int retval, i; - i2c_transfer_t *tp = unitp->i2c_tran; - - - tp->i2c_flags = I2C_RD; - tp->i2c_rlen = size; - tp->i2c_wlen = 0; - - /* - * Read the bytes from the pcf8574, mask off the - * non-read bits and return the value. Block with - * the driverwide lock. - */ - unitp->i2c_status = retval = - nct_i2c_transfer(unitp->pcf8574_hdl, unitp->i2c_tran); - - if (retval != I2C_SUCCESS) { - return (retval); - } - - for (i = 0; i < size; i++) { - tp->i2c_rbuf[i] &= unitp->readmask; - } - - return (I2C_SUCCESS); -} - -/* - * This function writes a single byte to the pcf8574 chip, for use by the - * ioctl routines. The protocol for write will depend on the function. - * The bitpattern tells which bits are being modified, by setting these - * bits in bitpattern to 1, e.g for fanspeed, bitpattern = 0x08, fanspeed - * and intr 0x0c, only intr 0x04. - */ - -static int -pcf8574_write_chip(struct pcf8574_unit *unitp, - uint16_t size, uint8_t bitpattern) -{ - i2c_transfer_t *tp = unitp->i2c_tran; - int i; - - /* - * pcf8574_write - * - * First read the byte, modify only the writable - * ports, then write back the modified data. - */ - tp->i2c_wlen = 0; - tp->i2c_rlen = size; - tp->i2c_flags = I2C_RD; - - unitp->i2c_status = nct_i2c_transfer(unitp->pcf8574_hdl, tp); - - if (unitp->i2c_status != I2C_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * Our concern is when we have to write only a few bits. - * We need to make sure we write the same value to those - * bit positions which does not appear in bitpattern. - */ - - /* - * 1) Ignore all bits than the one we are writing - * 2) Now 0 the bits we intend to modify in the value - * read from the chip, preserving all others. - * 3) Now turn all non-writable ( read only/reserved ) - * bits to 1. The value now should contain: - * 1 in all non-writable bits. - * 0 in the bis(s) we intend to modify. - * no change in the writable bits we don't modify. - * 4) Now OR it with the bits we got before, i.e. after - * ignoring all bits other than one we are writing. - */ - - for (i = 0; i < size; i++) { - tp->i2c_rbuf[i] &= ~(bitpattern); - - tp->i2c_rbuf[i] |= ~(unitp->writemask); - - tp->i2c_wbuf[i] = tp->i2c_rbuf[i] | - (tp->i2c_wbuf[i] & bitpattern); - } - - tp->i2c_rlen = 0; - tp->i2c_wlen = size; - tp->i2c_flags = I2C_WR; - - unitp->i2c_status = nct_i2c_transfer(unitp->pcf8574_hdl, tp); - - return (unitp->i2c_status); -} - -static int -pcf8574_kstat_update(kstat_t *ksp, int rw) -{ - struct pcf8574_unit *unitp; - char *kstatp; - uint8_t value; - int err = DDI_SUCCESS; - scsb_fru_status_t dev_presence; - - unitp = (struct pcf8574_unit *)ksp->ks_private; - if (unitp->envctrl_kstat == NULL) { /* May be detaching */ - return (err); - } - - CV_LOCK(EINTR) - - /* - * Need to call scsb to find whether device is present. - * For I2C devices, the I2C address is used as a FRU ID. - */ - if (unitp->pcf8574_type == PCF8574_TYPE_CPUVOLTAGE) { - dev_presence = FRU_PRESENT; - } else { - dev_presence = - scsb_fru_status((uchar_t)unitp->props.slave_address); - } - - kstatp = (char *)ksp->ks_data; - - /* - * We could have write on the power supply and the fantray - * pcf8574 chips. For masking the interrupt on both, or - * controlling the fan speed on the fantray. But write - * will not be allowed through the kstat interface. For - * the present field, call SCSB. - */ - - if (rw == KSTAT_WRITE) { - if (unitp->pcf8574_type != PCF8574_TYPE_FANTRAY) { - err = EACCES; - goto kstat_exit; - } - value = ((envctrl_fantray_t *)kstatp)->fanspeed; - if (value != PCF8574_FAN_SPEED_LOW && - value != PCF8574_FAN_SPEED_HIGH) { - err = EINVAL; - goto kstat_exit; - } - - unitp->i2c_tran->i2c_wbuf[0] = PCF8574_FAN_SPEED(value); - - if (dev_presence == FRU_PRESENT && - pcf8574_write_chip(unitp, 1, PCF8574_FANSPEED_BIT) - != I2C_SUCCESS) { - err = EFAULT; - goto kstat_exit; - } - - } else { - /* - * First make sure that the FRU exists by checking the SCSB - * dev_presence info. If not present, set the change field, - * clear the kstat fields and make sure the kstat *_present - * field is set to dev_presence from the SCSB driver. - */ - if (dev_presence == FRU_PRESENT && - pcf8574_read_chip(unitp, 1) != I2C_SUCCESS) { - /* - * Looks like a real IO error. - */ - err = EIO; - CV_UNLOCK - - return (err); - } - if (dev_presence == FRU_PRESENT) - value = unitp->i2c_tran->i2c_rbuf[0]; - else - value = 0; - - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_CPUVOLTAGE: { - envctrl_cpuvoltage_t *envp = - (envctrl_cpuvoltage_t *)unitp->envctrl_kstat; - envp->value = value; - bcopy((caddr_t)envp, kstatp, - sizeof (envctrl_cpuvoltage_t)); - - break; - } - case PCF8574_TYPE_PWRSUPP: { - envctrl_pwrsupp_t *envp = - (envctrl_pwrsupp_t *)unitp->envctrl_kstat; - - envp->ps_present = dev_presence; - envp->ps_ok = PCF8574_PS_FAULT(value); - envp->temp_ok = PCF8574_PS_TEMPOK(value); - envp->psfan_ok = PCF8574_PS_FANOK(value); - envp->on_state = PCF8574_PS_ONOFF(value); - envp->ps_ver = PCF8574_PS_TYPE(value); - - bcopy((caddr_t)envp, kstatp, - sizeof (envctrl_pwrsupp_t)); - - break; - } - case PCF8574_TYPE_FANTRAY: { - envctrl_fantray_t *envp = - (envctrl_fantray_t *)unitp->envctrl_kstat; - - envp->fan_present = dev_presence; - envp->fan_ver = PCF8574_FAN_TYPE(value); - envp->fan_ok = PCF8574_FAN_FAULT(value); - envp->fanspeed = PCF8574_FAN_FANSPD(value); - - bcopy((caddr_t)unitp->envctrl_kstat, kstatp, - sizeof (envctrl_fantray_t)); - - break; - } - - default: - break; - } - } - -kstat_exit: - - CV_UNLOCK - - return (err); -} - -static void -pcf8574_delete_kstat(struct pcf8574_unit *unitp) -{ - /* - * Depending on the function, deallocate the correct - * kernel allocated memory. - */ - if (unitp->kstatp != NULL) { - kstat_delete(unitp->kstatp); - } - - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_CPUVOLTAGE: { - if (unitp->envctrl_kstat != NULL) { - kmem_free(unitp->envctrl_kstat, - sizeof (envctrl_cpuvoltage_t)); - } - break; - } - case PCF8574_TYPE_PWRSUPP: { - if (unitp->envctrl_kstat != NULL) { - kmem_free(unitp->envctrl_kstat, - sizeof (envctrl_pwrsupp_t)); - } - - break; - } - case PCF8574_TYPE_FANTRAY: { - if (unitp->envctrl_kstat != NULL) { - kmem_free(unitp->envctrl_kstat, - sizeof (envctrl_fantray_t)); - } - break; - } - default: - break; - } - - unitp->envctrl_kstat = NULL; -} - -static int -pcf8574_read_props(struct pcf8574_unit *unitp) -{ - dev_info_t *dip = unitp->dip; - int retval = 0, prop_len; - uint32_t *prop_value = NULL; - uint8_t i2c_address; - char *function; - - /* - * read the pcf8574_function property. If this property is not - * found, return ERROR. Else, make sure it's either powersupply - * or fantray. - */ - - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "pcf8574_function", &function) != DDI_SUCCESS) { - dbg_print(CE_WARN, "Couldn't find pcf8574_function property"); - - return (DDI_FAILURE); - } - - if (strcmp(function, "fantray") == 0) { - unitp->pcf8574_type = PCF8574_TYPE_FANTRAY; - /* - * Will fail the fantray attach if patch - 1. - */ - if (nct_p10fan_patch) { -#ifdef DEBUG - cmn_err(CE_WARN, "nct_p10fan_patch set: will not load " - "fantary:address %x,%x", unitp->props.i2c_bus, - unitp->props.slave_address); -#endif - ddi_prop_free(function); - return (DDI_FAILURE); - } - } else - if (strcmp(function, "powersupply") == 0) { - unitp->pcf8574_type = PCF8574_TYPE_PWRSUPP; - } else { - dbg_print(CE_WARN, "Neither powersupply nor fantray"); - ddi_prop_free(function); - - return (DDI_FAILURE); - } - - ddi_prop_free(function); - - retval = ddi_getlongprop(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, - "reg", (caddr_t)&prop_value, &prop_len); - if (retval == DDI_PROP_SUCCESS) { - unitp->props.i2c_bus = (uint16_t)prop_value[0]; - unitp->props.slave_address = i2c_address = - (uint8_t)prop_value[1]; - kmem_free(prop_value, prop_len); - - if (i2c_address>>4 == 7) - unitp->sensor_type = PCF8574A; - else if (i2c_address>>4 == 4) - unitp->sensor_type = PCF8574; - else { - unitp->sensor_type = PCF8574A; - dbg_print(CE_WARN, "Not a pcf8574/a device"); - } - - } else { - unitp->props.i2c_bus = (uint16_t)-1; - unitp->props.slave_address = (uint16_t)-1; - } - - /* - * Get the Property information that the driver will be using - * see typedef struct pcf8574_properties_t; - */ - - unitp->pcf8574_canintr = 0; - retval = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "interrupts", -1); - if (retval >= 0) { - int prop_len, intr_pri = 4; - unitp->pcf8574_canintr |= PCF8574_INTR_ON; - if (ddi_getproplen(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "interrupt-priorities", - &prop_len) == DDI_PROP_NOT_FOUND) { - retval = ddi_prop_create(DDI_DEV_T_NONE, dip, - DDI_PROP_CANSLEEP, "interrupt-priorities", - (caddr_t)&intr_pri, sizeof (int)); -#ifdef DEBUG - if (retval != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, "Failed to create interrupt- \ - priorities property, retval %d", retval); - } -#endif /* DEBUG */ - } - } - - /* - * No channels-in-use property for the fan and powersupplies. - */ - unitp->props.num_chans_used = 0; - if (i2c_address == PCF8574_ADR_CPUVOLTAGE) { - if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "channels-in-use", &prop_len) == DDI_PROP_SUCCESS) { - retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, - dip, DDI_PROP_DONTPASS, - "channels-in-use", - (uchar_t **)&unitp->props.channels_in_use, - &unitp->props.num_chans_used); - if (retval != DDI_PROP_SUCCESS) { - unitp->props.num_chans_used = 0; - } else { - unitp->props.num_chans_used /= - sizeof (pcf8574_channel_t); - } - } - } - - return (DDI_PROP_SUCCESS); -} - -/* - * callback function to register with the SCSB driver in order to be - * informed about changes in device instance presence. - */ -/*ARGSUSED*/ -void -pcf8574_callback(void *softstate, scsb_fru_event_t cb_event, - scsb_fru_status_t dev_presence) -{ - struct pcf8574_unit *unitp = (struct pcf8574_unit *)softstate; -#ifdef DEBUG - if (pcf8574_debug & 0x00800001) - cmn_err(CE_NOTE, "pcf8574_callback(unitp,%d,%d)", - (int)cb_event, (int)dev_presence); -#endif /* DEBUG */ - - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_CPUVOLTAGE: { - /* - * This Unit is not Field Replacable and will not - * generate any events at the SCB. - */ - break; - } - case PCF8574_TYPE_PWRSUPP: { - envctrl_pwrsupp_t *envp; - - envp = (envctrl_pwrsupp_t *)unitp->envctrl_kstat; - if (dev_presence == FRU_NOT_PRESENT) { - envp->ps_ok = 0; - envp->temp_ok = 0; - envp->psfan_ok = 0; - envp->on_state = 0; - envp->ps_ver = 0; - } else - if (dev_presence == FRU_PRESENT && - envp->ps_present == FRU_NOT_PRESENT) { - (void) pcf8574_init_chip(unitp, 0); - } - envp->ps_present = dev_presence; - unitp->poll_event = POLLIN; - pollwakeup(&unitp->poll, POLLIN); - break; - } - case PCF8574_TYPE_FANTRAY: { - envctrl_fantray_t *envp; - - envp = (envctrl_fantray_t *)unitp->envctrl_kstat; - - if (dev_presence == FRU_NOT_PRESENT) { - envp->fan_ok = 0; - envp->fanspeed = PCF8574_FAN_SPEED60; - envp->fan_ver = 0; - } else - if (dev_presence == FRU_PRESENT && - envp->fan_present == FRU_NOT_PRESENT) { - (void) pcf8574_init_chip(unitp, 0); - } - envp->fan_present = dev_presence; - unitp->poll_event = POLLIN; - pollwakeup(&unitp->poll, POLLIN); - break; - } - } -} - -/* - * Initializes the chip after attach or after being inserted. - * intron = 0 => disable interrupt. - * intron = 1 => read register, enable interrupt if no fault. - */ - -static int -pcf8574_init_chip(struct pcf8574_unit *unitp, int intron) -{ - int ret = I2C_SUCCESS; - i2c_transfer_t *tp = unitp->i2c_tran; - uint8_t value = 0; - boolean_t device_faulty = B_FALSE; /* true is faulty */ - - if (unitp->pcf8574_type != PCF8574_TYPE_PWRSUPP && - unitp->pcf8574_type != PCF8574_TYPE_FANTRAY) { - return (ret); - } - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_PWRSUPP: - tp->i2c_wbuf[0] = PCF8574_PS_DEFAULT; - - break; - case PCF8574_TYPE_FANTRAY: - tp->i2c_wbuf[0] = PCF8574_FAN_DEFAULT; - - break; - default: - break; - } - - /* - * First, read the device. If the device is faulty, it does - * not make sense to enable the interrupt, so in this case - * keep interrupt maskked inspite of what "intron" says. - */ - - tp->i2c_wlen = 0; - tp->i2c_rlen = 1; - tp->i2c_flags = I2C_RD; - - unitp->i2c_status = ret = nct_i2c_transfer(unitp->pcf8574_hdl, tp); - - if (ret != I2C_SUCCESS) { - return (ret); - } - - value = tp->i2c_rbuf[0]; - - switch (unitp->pcf8574_type) { - case PCF8574_TYPE_PWRSUPP: - { - envctrl_pwrsupp_t *envp = - (envctrl_pwrsupp_t *)unitp->envctrl_kstat; - - envp->ps_ok = PCF8574_PS_FAULT(value); - envp->temp_ok = PCF8574_PS_TEMPOK(value); - envp->psfan_ok = PCF8574_PS_FANOK(value); - envp->on_state = PCF8574_PS_ONOFF(value); - envp->ps_ver = PCF8574_PS_TYPE(value); - - if (envp->ps_ok || envp->temp_ok || - envp->psfan_ok || envp->on_state) - device_faulty = B_TRUE; - - break; - } - case PCF8574_TYPE_FANTRAY: - { - envctrl_fantray_t *envp = - (envctrl_fantray_t *)unitp->envctrl_kstat; - - envp->fan_ver = PCF8574_FAN_TYPE(value); - envp->fan_ok = PCF8574_FAN_FAULT(value); - envp->fanspeed = PCF8574_FAN_FANSPD(value); - - if (!envp->fan_ok) - device_faulty = B_TRUE; /* remember, 0 is faulty */ - - break; - } - default: - break; - } - /* - * Mask interrupt, if intron = 0. - */ - if (!intron || device_faulty == B_TRUE) { - tp->i2c_wbuf[0] |= PCF8574_INTRMASK_BIT; - } - - tp->i2c_wlen = 1; - tp->i2c_rlen = 0; - tp->i2c_flags = I2C_WR; - - unitp->i2c_status = nct_i2c_transfer(unitp->pcf8574_hdl, tp); - - return (unitp->i2c_status); -} diff --git a/usr/src/uts/sun4u/montecarlo/io/pcf8591_nct.c b/usr/src/uts/sun4u/montecarlo/io/pcf8591_nct.c deleted file mode 100644 index 2ec1b326ab..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/pcf8591_nct.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2011 Bayard G. Bell. All rights reserved. - */ - -/* - * I2C leaf driver for the PCF8591 - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/signal.h> -#include <sys/errno.h> -#include <sys/file.h> -#include <sys/termio.h> -#include <sys/termios.h> -#include <sys/cmn_err.h> -#include <sys/stream.h> -#include <sys/strsun.h> -#include <sys/stropts.h> -#include <sys/strtty.h> -#include <sys/debug.h> -#include <sys/eucioctl.h> -#include <sys/cred.h> -#include <sys/uio.h> -#include <sys/stat.h> -#include <sys/kmem.h> - -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/obpdefs.h> -#include <sys/conf.h> -#include <sys/modctl.h> -#include <sys/stat.h> -#include <sys/open.h> -#include <sys/uio.h> - -#include <sys/i2c/misc/i2c_svc.h> -#include <sys/envctrl_gen.h> -#include <sys/netract_gen.h> -#include <sys/pcf8591_nct.h> - - -/* - * CONTROL OF CHIP - * PCF8591 Temp sensing control register definitions - * - * --------------------------------------------- - * | 0 | AOE | X | X | 0 | AIF | X | X | - * --------------------------------------------- - * AOE = Analog out enable.. not used on out implementation - * 5 & 4 = Analog Input Programming.. see data sheet for bits.. - * - * AIF = Auto increment flag - * bits 1 & 0 are for the Chennel number. - */ - - -#define I2CTRANS_DATA 0 -#define I2CRAW_DATA 1 -#define TEMP_TABLE_SIZE 256 - -#define SHUTDOWN_TEMP_MIN 55 -#define SHUTDOWN_TEMP_MAX 85 - -#ifdef DEBUG -#define dbg_print(level, str) cmn_err(level, str); -#else -#define dbg_print(level, str) {; } -#endif - - -extern int nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran); -static uchar_t _cpu_temps[TEMP_TABLE_SIZE + 4]; /* see attach */ - -static void *pcf8591_soft_statep; - -/* - * cb ops (only need ioctl) - */ -static int pcf8591_open(dev_t *, int, int, cred_t *); -static int pcf8591_close(dev_t, int, int, cred_t *); -static int pcf8591_read(dev_t dev, struct uio *uiop, cred_t *cred_p); -static int pcf8591_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); - -static struct cb_ops pcf8591_cbops = { - pcf8591_open, /* open */ - pcf8591_close, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - pcf8591_read, /* read */ - nodev, /* write */ - pcf8591_ioctl, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, /* cb_prop_op */ - NULL, /* streamtab */ - D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ - CB_REV, /* rev */ - nodev, /* int (*cb_aread)() */ - nodev /* int (*cb_awrite)() */ -}; - -/* - * dev ops - */ -static int pcf8591_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, - void **result); -static int pcf8591_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); -static int pcf8591_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); - -/* kstat routines */ -static int pcf8591_add_kstats(struct pcf8591_unit *); -static void pcf8591_delete_kstats(struct pcf8591_unit *); -static int pcf8591_temp_kstat_update(kstat_t *, int); -static int pcf8591_read_chip(struct pcf8591_unit *, uint8_t, int); -static int pcf8591_read_props(struct pcf8591_unit *unitp); - -static struct dev_ops pcf8591_ops = { - DEVO_REV, - 0, - pcf8591_info, - nulldev, - nulldev, - pcf8591_attach, - pcf8591_detach, - nodev, - &pcf8591_cbops, - NULL, - NULL, - ddi_quiesce_not_supported, /* devo_quiesce */ -}; - -extern struct mod_ops mod_driverops; - -static struct modldrv pcf8591_modldrv = { - &mod_driverops, /* type of module - driver */ - "Netract pcf8591 (adio)", - &pcf8591_ops, -}; - -static struct modlinkage pcf8591_modlinkage = { - MODREV_1, - &pcf8591_modldrv, - 0 -}; - -int pcf8591_debug = 0x02; -static uint8_t translate_cputemp(uint8_t value); - -int -_init(void) -{ - register int error; - - error = mod_install(&pcf8591_modlinkage); - if (error == 0) { - (void) ddi_soft_state_init(&pcf8591_soft_statep, - sizeof (struct pcf8591_unit), PCF8591_MAX_DEVS); - } - - return (error); -} - -int -_fini(void) -{ - register int error; - - error = mod_remove(&pcf8591_modlinkage); - if (error == 0) { - ddi_soft_state_fini(&pcf8591_soft_statep); - } - - return (error); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&pcf8591_modlinkage, modinfop)); -} - -/*ARGSUSED*/ -static int -pcf8591_open(dev_t *devp, int flags, int otyp, cred_t *credp) -{ - int err = 0; - struct pcf8591_unit *unitp; - minor_t minor = getminor(*devp); - - int instance = PCF8591_MINOR_TO_DEVINST(minor); - int channel = PCF8591_MINOR_TO_CHANNEL(minor); - - if (instance < 0) { - return (ENXIO); - } - - unitp = (struct pcf8591_unit *) - ddi_get_soft_state(pcf8591_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - if (otyp != OTYP_CHR) { - return (EINVAL); - } - - mutex_enter(&unitp->umutex); - - if (flags & FEXCL) { - if (unitp->pcf8591_oflag[channel] != 0) { - err = EBUSY; - } else { - unitp->pcf8591_oflag[channel] = FEXCL; - } - } else { - if (unitp->pcf8591_oflag[channel] == FEXCL) { - err = EBUSY; - } else { - unitp->pcf8591_oflag[channel] = FOPEN; - } - } - - mutex_exit(&unitp->umutex); - - return (err); -} - -/*ARGSUSED*/ -static int -pcf8591_close(dev_t devp, int flags, int otyp, cred_t *credp) -{ - struct pcf8591_unit *unitp; - minor_t minor = getminor(devp); - - int instance = PCF8591_MINOR_TO_DEVINST(minor); - int channel = PCF8591_MINOR_TO_CHANNEL(minor); - -#ifdef lint - flags = flags; - otyp = otyp; -#endif - - if (instance < 0) { - return (ENXIO); - } - - unitp = (struct pcf8591_unit *) - ddi_get_soft_state(pcf8591_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - mutex_enter(&unitp->umutex); - - unitp->pcf8591_oflag[channel] = 0; - - mutex_exit(&unitp->umutex); - - return (DDI_SUCCESS); -} - -static int -pcf8591_io(dev_t dev, struct uio *uiop, int rw) -{ - int err = 0; - struct pcf8591_unit *unitp; - minor_t minor = getminor(dev); - - int instance = PCF8591_MINOR_TO_DEVINST(minor); - int channel = PCF8591_MINOR_TO_CHANNEL(minor); - - int bytes_to_rw; - int translate = 0; - - /* - * At this point we don't have a write operation to pcf8591. - */ - if (rw == B_WRITE) { - return (EACCES); - } - - if (instance < 0) { - return (ENXIO); - } - - unitp = (struct pcf8591_unit *) - ddi_get_soft_state(pcf8591_soft_statep, instance); - if (unitp == NULL) { - return (ENXIO); - } - - if ((bytes_to_rw = uiop->uio_resid) > PCF8591_TRAN_SIZE) { - return (EINVAL); - } - - /* - * Need to serialize all read operations, since there is a single - * i2c_transfer_t structure allocated for all read and write ops. - * We can't share the i2c bus among multiple transactions anyway, - * so this does not affect performance. - */ - mutex_enter(&unitp->umutex); - while (unitp->pcf8591_flags == PCF8591_BUSY) { - if (cv_wait_sig(&unitp->pcf8591_cv, &unitp->umutex) <= 0) { - mutex_exit(&unitp->umutex); - - return (EINTR); - } - } - unitp->pcf8591_flags = PCF8591_BUSY; - mutex_exit(&unitp->umutex); - - if (bytes_to_rw == 1) - translate = 1; - /* - * Event sequence: - * 1. set up the control register write, for now we'll always read - * channel 0, which is the only active 8591 port on the Nordica - * TODO: We'll need a minor node for each port that is used. - * 2. increment read count to read the throw-away byte - * 3. start the write/read of control/data registers - * 4. throw the first byte away - * 5. then return the data - */ - - unitp->i2c_tran->i2c_flags = I2C_WR_RD; - unitp->i2c_tran->i2c_wlen = 1; - unitp->i2c_tran->i2c_wbuf[0] = (unitp->pcf8591_inprog | - channel); - /* - * read extra byte to throw away the first, (PCF8591 datasheet) - */ - unitp->i2c_tran->i2c_rlen = bytes_to_rw + 1; - - if (nct_i2c_transfer(unitp->pcf8591_hdl, - unitp->i2c_tran) != I2C_SUCCESS) { - err = EIO; - } else { - /* - * Throw away the first byte according to PCF8591 datasheet - * If translating, use the second byte. - */ - if (translate) { - unitp->i2c_tran->i2c_rbuf[0] = - translate_cputemp(unitp->i2c_tran->i2c_rbuf[1]); - } else { - unitp->i2c_tran->i2c_rbuf[0] = - unitp->i2c_tran->i2c_rbuf[1]; - unitp->i2c_tran->i2c_rbuf[1] = 0; - } - - err = uiomove(unitp->i2c_tran->i2c_rbuf, - bytes_to_rw, - UIO_READ, - uiop); - } - mutex_enter(&unitp->umutex); - unitp->pcf8591_flags = 0; - cv_signal(&unitp->pcf8591_cv); - mutex_exit(&unitp->umutex); - - return (err); -} - -/*ARGSUSED*/ -static int -pcf8591_read(dev_t dev, struct uio *uiop, cred_t *cred_p) -{ - return (pcf8591_io(dev, uiop, B_READ)); -} - -static int -call_copyin(caddr_t arg, struct pcf8591_unit *unitp, int mode) -{ - uchar_t *wbuf; - uchar_t *rbuf; - i2c_transfer_t i2ct; - i2c_transfer_t *i2ctp = unitp->i2c_tran; - - - if (ddi_copyin((void *)arg, (caddr_t)&i2ct, - sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * Save the read and write buffer pointers in the transfer - * structure, otherwise these will get overwritten when we - * do a bcopy. Restore once done. - */ - - wbuf = i2ctp->i2c_wbuf; - rbuf = i2ctp->i2c_rbuf; - - bcopy(&i2ct, i2ctp, sizeof (i2c_transfer_t)); - - i2ctp->i2c_wbuf = wbuf; - i2ctp->i2c_rbuf = rbuf; - - /* - * copyin the read and write buffers to the saved buffers. - */ - - if (i2ct.i2c_wlen != 0) { - if (ddi_copyin(i2ct.i2c_wbuf, (caddr_t)i2ctp->i2c_wbuf, - i2ct.i2c_wlen, mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - } - - return (I2C_SUCCESS); -} - -static int -call_copyout(caddr_t arg, struct pcf8591_unit *unitp, int mode) -{ - i2c_transfer_t i2ct; - i2c_transfer_t *i2ctp = unitp->i2c_tran; - uint16_t i2c_actlen; - - /* - * We will copyout the last three fields only, skipping - * the remaining ones, before copying the rbuf to the - * user buffer. - */ - - int uskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t), - kskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t); - - /* - * First copyin the user structure to the temporary i2ct, - * so that we have the wbuf and rbuf addresses in it. - */ - - uskip = sizeof (i2c_transfer_t) - 3 * (sizeof (uint16_t)); - - /* - * copyout the last three out fields now. - */ - - if (ddi_copyout((void *)((intptr_t)i2ctp+kskip), (void *) - ((intptr_t)arg + uskip), 3*sizeof (uint16_t), mode) - != DDI_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * In case we have something to write, get the address of the read - * buffer. - */ - - if (i2ctp->i2c_rlen - i2ctp->i2c_r_resid > 0) { - - if (ddi_copyin((void *)arg, &i2ct, - sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - - /* - * copyout the read buffer to the saved user buffer in i2ct. - */ - - i2c_actlen = i2ctp->i2c_rlen - i2ctp->i2c_r_resid; - if (ddi_copyout(i2ctp->i2c_rbuf, i2ct.i2c_rbuf, - i2c_actlen, mode) != DDI_SUCCESS) { - return (I2C_FAILURE); - } - } - - return (I2C_SUCCESS); -} - -/* - * The ioctls will use the same name as the Javelin ioctls. We - * will have a very restricted set for MC, and unlike Javelin - * will not have a envctrl_chip structure to return values - * from the driver. All we will have is a uint8_t value to - * get or set values from the driver. Also, unlike the Javelin, - * where 'index' is used to specify the input port from where - * temperature is collected, here different minor nodes will be - * created by the driver for each port, eliminating the need for - * 'index' - leaving us with only the value to pass. - */ - -/*ARGSUSED*/ -static int -pcf8591_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, - cred_t *credp, int *rvalp) -{ - int err = 0; - struct pcf8591_unit *unitp; - minor_t minor = getminor(dev); - - int instance = PCF8591_MINOR_TO_DEVINST(minor); - int channel = PCF8591_MINOR_TO_CHANNEL(minor); - - unitp = (struct pcf8591_unit *) - ddi_get_soft_state(pcf8591_soft_statep, instance); - - mutex_enter(&unitp->umutex); - while (unitp->pcf8591_flags == PCF8591_BUSY) { - if (cv_wait_sig(&unitp->pcf8591_cv, &unitp->umutex) <= 0) { - mutex_exit(&unitp->umutex); - - return (EINTR); - } - } - unitp->pcf8591_flags = PCF8591_BUSY; - mutex_exit(&unitp->umutex); - - switch (cmd) { - - case ENVC_IOC_GETTEMP: { - /* - * Read the status byte from pcf8591 chip. The value will - * be already converted to Celcius by translate_cputemp. - */ - (void) pcf8591_read_chip(unitp, channel, 1); - if (ddi_copyout(unitp->i2c_tran->i2c_rbuf, - (caddr_t)arg, sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - } - break; - } - - case ENVC_IOC_GETMODE: { - uint8_t curr_mode = unitp->current_mode; - - if (ddi_copyout((caddr_t)&curr_mode, (caddr_t)arg, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - } - break; - } - - case ENVC_IOC_SETMODE: { - uint8_t curr_mode; - if (ddi_copyin((caddr_t)arg, (caddr_t)&curr_mode, - sizeof (uint8_t), mode) != DDI_SUCCESS) { - err = EFAULT; - break; - } - if (curr_mode == ENVCTRL_DIAG_MODE || - curr_mode == ENVCTRL_NORMAL_MODE) { - unitp->current_mode = curr_mode; /* Don't do anything */ - } - break; - } - - /* Testing, may be removed */ - case I2CDEV_TRAN: - if (call_copyin((caddr_t)arg, unitp, mode) != I2C_SUCCESS) { - err = EFAULT; - break; - } - if (nct_i2c_transfer(unitp->pcf8591_hdl, unitp->i2c_tran) - != I2C_SUCCESS) { - err = EFAULT; - break; - } - if (call_copyout((caddr_t)arg, unitp, mode) != I2C_SUCCESS) { - err = EFAULT; - break; - } - break; - - /* - * TESTING TRANSLATION from "adc" "table" property - * translate thermistor index into temp Celcius - */ - case I2CDEV_GETTEMP: { - struct i2c_transfer *tp; - if (call_copyin((caddr_t)arg, unitp, mode) != I2C_SUCCESS) { - err = EFAULT; - break; - } - tp = unitp->i2c_tran; - if (tp->i2c_rlen != 1) { - err = EINVAL; - break; - } - /* - * Throw away the first byte according to PCF8591 datasheet, - * so read two bytes - */ - tp->i2c_rlen = 2; - if (nct_i2c_transfer(unitp->pcf8591_hdl, unitp->i2c_tran) - != I2C_SUCCESS) { - err = EFAULT; - break; - } -#ifdef DEBUG - if (pcf8591_debug & 0x0010) - cmn_err(CE_NOTE, - "pcf8591_ioctl: i2c_rlen=%d; " - "i2c_rbuf[0,1]=0x%x,0x%x\n", - tp->i2c_rlen, tp->i2c_rbuf[0], tp->i2c_rbuf[1]); -#endif /* DEBUG */ - /* - * Throw away the first byte according to PCF8591 datasheet - */ - if ((tp->i2c_rbuf[0] = translate_cputemp(tp->i2c_rbuf[1])) - == 0) { - err = EINVAL; - break; - } - tp->i2c_rbuf[1] = 0; - - if (call_copyout((caddr_t)arg, unitp, mode) != I2C_SUCCESS) { - err = EFAULT; - break; - } - break; - } - - case I2CDEV_GETTABLES: { - break; - } - default: - err = EINVAL; - } - - mutex_enter(&unitp->umutex); - unitp->pcf8591_flags = 0; - cv_signal(&unitp->pcf8591_cv); - mutex_exit(&unitp->umutex); - - return (err); -} - -static int -pcf8591_do_detach(dev_info_t *dip) -{ - register struct pcf8591_unit *unitp; - int instance; - uint_t attach_flag; - - instance = ddi_get_instance(dip); - unitp = ddi_get_soft_state(pcf8591_soft_statep, instance); - attach_flag = unitp->attach_flag; - - if (attach_flag & PCF8591_KSTAT_INIT) { - pcf8591_delete_kstats(unitp); - } - - if (attach_flag & PCF8591_LOCK_INIT) { - mutex_destroy(&unitp->umutex); - cv_destroy(&unitp->pcf8591_cv); - } - - /* - * Restore the lengths of the rbuf and wbuf, which was originally - * allocated so that the appropriate amount of rbuf and wbuf are - * freed. - */ - if (attach_flag & PCF8591_ALLOC_TRANSFER) { - unitp->i2c_tran->i2c_wlen = MAX_WLEN; - unitp->i2c_tran->i2c_rlen = MAX_RLEN; - i2c_transfer_free(unitp->pcf8591_hdl, unitp->i2c_tran); - } - - if (attach_flag & PCF8591_REGISTER_CLIENT) { - i2c_client_unregister(unitp->pcf8591_hdl); - } - - if (attach_flag & PCF8591_MINORS_CREATED) { - ddi_remove_minor_node(dip, NULL); - } - - /* - * Free the memory allocated for the properties. - */ - if (attach_flag & PCF8591_PROPS_READ) { - ddi_prop_free(unitp->props.name); - if (unitp->props.num_chans_used) { - ddi_prop_free(unitp->props.channels_in_use); - } - - if (unitp->props.channels_description) { - ddi_prop_free(unitp->props.channels_description); - } - } - - if (attach_flag & PCF8591_SOFT_STATE_ALLOC) { - ddi_soft_state_free(pcf8591_soft_statep, instance); - } - - return (DDI_SUCCESS); -} - -static int -pcf8591_do_suspend(dev_info_t *dip) -{ - int instance = ddi_get_instance(dip); - struct pcf8591_unit *unitp = (struct pcf8591_unit *) - ddi_get_soft_state(pcf8591_soft_statep, instance); - - if (unitp == NULL) { - return (ENXIO); - } - - /* - * Set the busy flag so that future transactions block - * until resume. - */ - mutex_enter(&unitp->umutex); - while (unitp->pcf8591_flags == PCF8591_BUSY) { - if (cv_wait_sig(&unitp->pcf8591_cv, - &unitp->umutex) <= 0) { - mutex_exit(&unitp->umutex); - - return (DDI_FAILURE); - } - } - unitp->pcf8591_flags = PCF8591_BUSY; - mutex_exit(&unitp->umutex); - - return (DDI_SUCCESS); -} - -static int -pcf8591_do_resume(dev_info_t *dip) -{ - int instance = ddi_get_instance(dip); - struct pcf8591_unit *unitp = (struct pcf8591_unit *) - ddi_get_soft_state(pcf8591_soft_statep, instance); - if (unitp == NULL) { - return (ENXIO); - } - - mutex_enter(&unitp->umutex); - unitp->pcf8591_flags = 0; - cv_signal(&unitp->pcf8591_cv); - mutex_exit(&unitp->umutex); - - return (DDI_SUCCESS); -} - -static int -pcf8591_do_attach(dev_info_t *dip) -{ - register struct pcf8591_unit *unitp; - int i, instance; - char name[MAXNAMELEN]; - minor_t minor; - - instance = ddi_get_instance(dip); - - if (ddi_soft_state_zalloc(pcf8591_soft_statep, instance) != 0) { - return (DDI_FAILURE); - } - - unitp = ddi_get_soft_state(pcf8591_soft_statep, instance); - - if (unitp == NULL) { - return (DDI_FAILURE); - } - - unitp->dip = dip; - - unitp->attach_flag = PCF8591_SOFT_STATE_ALLOC; - - if (pcf8591_read_props(unitp) != DDI_PROP_SUCCESS) { - (void) pcf8591_do_detach(dip); - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8591_PROPS_READ; - - /* - * Set the current operating mode to NORMAL_MODE. - */ - unitp->current_mode = ENVCTRL_NORMAL_MODE; /* normal mode */ - - (void) snprintf(unitp->pcf8591_name, PCF8591_NAMELEN, - "%s%d", ddi_driver_name(dip), instance); - - /* - * Create a minor node corresponding to channel 0 to 3 - */ - for (i = 0; i < PCF8591_MAX_CHANS; i++) { - if (i == 0) { - (void) sprintf(name, "cputemp"); - } else { - (void) sprintf(name, "%d", i); - } - minor = PCF8591_MINOR_NUM(instance, i); - if (ddi_create_minor_node(dip, name, S_IFCHR, minor, - PCF8591_NODE_TYPE, NULL) == DDI_FAILURE) { - ddi_remove_minor_node(dip, NULL); - (void) pcf8591_do_detach(dip); - return (DDI_FAILURE); - } - } - - unitp->attach_flag |= PCF8591_MINORS_CREATED; - - if (i2c_client_register(dip, &unitp->pcf8591_hdl) - != I2C_SUCCESS) { - (void) pcf8591_do_detach(dip); - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8591_REGISTER_CLIENT; - - /* - * We allocate a single i2c_transfer_t structure for all - * i2c transactions. - */ - if (i2c_transfer_alloc(unitp->pcf8591_hdl, &unitp->i2c_tran, - MAX_WLEN, MAX_RLEN, KM_SLEEP) != I2C_SUCCESS) { - (void) pcf8591_do_detach(dip); - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8591_ALLOC_TRANSFER; - - /* - * The flags will be set to I2C_WR because for all reads from - * the 8591 we need to also write the control byte. - */ - unitp->i2c_tran->i2c_flags = I2C_WR; - unitp->i2c_tran->i2c_version = I2C_XFER_REV; - - - /* - * Set the analog programming mode to default. Upper nibble - * in control byte. Four single ended inputs, output not enabled. - */ - unitp->pcf8591_inprog = PCF8591_4SINGLE | PCF8591_ANALOG_INPUT_EN; - - /* - * Set the open flag for each channel to 0. - */ - for (i = 0; i < PCF8591_MAX_CHANS; i++) { - unitp->pcf8591_oflag[i] = 0; - } - - /* - * Set the busy flag to 0. - */ - unitp->pcf8591_flags = 0; - - mutex_init(&unitp->umutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&unitp->pcf8591_cv, NULL, CV_DRIVER, NULL); - - unitp->attach_flag |= PCF8591_LOCK_INIT; - - if (pcf8591_add_kstats(unitp) != DDI_SUCCESS) { - (void) pcf8591_do_detach(dip); - return (DDI_FAILURE); - } - - unitp->attach_flag |= PCF8591_KSTAT_INIT; - - ddi_report_dev(dip); - - return (DDI_SUCCESS); -} - -/* ARGSUSED */ -static int -pcf8591_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - dev_t dev; - int instance; - - if (infocmd == DDI_INFO_DEVT2INSTANCE) { - dev = (dev_t)arg; - instance = PCF8591_MINOR_TO_DEVINST(getminor(dev)); - *result = (void *)(uintptr_t)instance; - return (DDI_SUCCESS); - } - return (DDI_FAILURE); -} - -static int -pcf8591_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - switch (cmd) { - case DDI_ATTACH: - return (pcf8591_do_attach(dip)); - case DDI_RESUME: - return (pcf8591_do_resume(dip)); - default: - return (DDI_FAILURE); - } -} - -static int -pcf8591_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - switch (cmd) { - case DDI_DETACH: - return (pcf8591_do_detach(dip)); - case DDI_SUSPEND: - return (pcf8591_do_suspend(dip)); - default: - return (DDI_FAILURE); - } -} - -static uint8_t -translate_cputemp(uint8_t value) -{ - return (_cpu_temps[value]); -} - -static int -pcf8591_add_kstats(struct pcf8591_unit *unitp) -{ - if ((unitp->tempksp = kstat_create(I2C_PCF8591_NAME, - unitp->instance, I2C_KSTAT_CPUTEMP, "misc", - KSTAT_TYPE_RAW, sizeof (unitp->temp_kstats), - KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) { - - return (DDI_FAILURE); - } - - /* - * The kstat fields are already initialized in the attach routine.. - */ - - unitp->tempksp->ks_update = pcf8591_temp_kstat_update; - unitp->tempksp->ks_private = (void *)unitp; - - (void) strcpy(unitp->temp_kstats.label, - unitp->props.channels_description[0]); - unitp->temp_kstats.type = ENVC_NETRACT_CPU_SENSOR; - - kstat_install(unitp->tempksp); - - return (DDI_SUCCESS); -} - -static void -pcf8591_delete_kstats(struct pcf8591_unit *unitp) -{ - kstat_delete(unitp->tempksp); -} - -static int -pcf8591_temp_kstat_update(kstat_t *ksp, int rw) -{ - struct pcf8591_unit *unitp; - char *kstatp; - int err = 0; - int channel = 0; - int warn_temp = 0; - int shutdown_temp = 0; - - unitp = (struct pcf8591_unit *)ksp->ks_private; - - mutex_enter(&unitp->umutex); - while (unitp->pcf8591_flags == PCF8591_BUSY) { - if (cv_wait_sig(&unitp->pcf8591_cv, - &unitp->umutex) <= 0) { - mutex_exit(&unitp->umutex); - - return (EINTR); - } - } - - unitp->pcf8591_flags = PCF8591_BUSY; - mutex_exit(&unitp->umutex); - - kstatp = (char *)ksp->ks_data; - - if (rw == KSTAT_WRITE) { - - /* check for the size of buffer */ - if (ksp->ks_data_size != sizeof (unitp->temp_kstats)) { - err = EIO; - goto bail; - } - - warn_temp = ((envctrl_temp_t *)kstatp)->warning_threshold; - shutdown_temp = ((envctrl_temp_t *)kstatp)->shutdown_threshold; - - if (shutdown_temp < SHUTDOWN_TEMP_MIN || shutdown_temp > - SHUTDOWN_TEMP_MAX) { - err = EIO; - goto bail; - } - - if (warn_temp < 0 || shutdown_temp <= warn_temp) { - err = EIO; - goto bail; - } - - /* write into kstat fields */ - unitp->temp_kstats.warning_threshold = warn_temp; - unitp->temp_kstats.shutdown_threshold = shutdown_temp; - - } else { - (void) pcf8591_read_chip(unitp, channel, 1); - unitp->temp_kstats.value = - unitp->i2c_tran->i2c_rbuf[0]; - bcopy((caddr_t)&unitp->temp_kstats, kstatp, - sizeof (unitp->temp_kstats)); - } - -bail: - - mutex_enter(&unitp->umutex); - unitp->pcf8591_flags = 0; - cv_signal(&unitp->pcf8591_cv); - mutex_exit(&unitp->umutex); - - return (err); -} - -static int -pcf8591_read_chip(struct pcf8591_unit *unitp, uint8_t channel, -int size) -{ - int retval = I2C_SUCCESS; - - /* - * We need to read an extra byte, since as per specification - * the first byte read should be discarded. - */ - i2c_transfer_t *tp = unitp->i2c_tran; - tp->i2c_flags = I2C_WR_RD; - tp->i2c_rlen = size+1; - tp->i2c_wlen = 1; - tp->i2c_wbuf[0] = (unitp->pcf8591_inprog | - channel); - - retval = nct_i2c_transfer(unitp->pcf8591_hdl, tp); - if (retval == I2C_SUCCESS) { - tp->i2c_rbuf[0] = translate_cputemp(tp->i2c_rbuf[1]); - } - - if (tp->i2c_rbuf[0] == 0) { - retval = I2C_FAILURE; - } - - return (retval); -} - -/* - * Reads the properties of the pcf8591 device. - */ -static int -pcf8591_read_props(struct pcf8591_unit *unitp) -{ - dev_info_t *dip = unitp->dip; - int i, retval = 0, prop_len; - int instance = ddi_get_instance(dip); - int warning_temp, shutdown_temp; - uint32_t *prop_value = NULL; - uchar_t *creg_prop; - char *function; - uint_t tblsz; - -#ifdef lint - instance = instance; -#endif - /* - * Check for the pcf8591_function property, and make sure it's - * cputemp. - */ - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "pcf8591_function", &function) != DDI_SUCCESS) { - dbg_print(CE_WARN, "Couldn't find pcf8591_function property"); - - return (DDI_FAILURE); - } - - if (strcmp(function, "cputemp") != 0) { - dbg_print(CE_WARN, "pcf8591_function is not cputemp"); - ddi_prop_free(function); - - return (DDI_FAILURE); - } - - ddi_prop_free(function); - - retval = ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "name", &unitp->props.name); - if (retval != DDI_PROP_SUCCESS) { - - return (retval); - } -#ifdef DEBUG - else if (pcf8591_debug & 0x02) - cmn_err(CE_NOTE, - "pcf8591_read_props:ddi_prop_lookup_string(%s): \ - found %s ", "name", unitp->props.name); -#endif /* DEBUG */ - - retval = ddi_getlongprop(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, - "reg", (caddr_t)&prop_value, &prop_len); - if (retval == DDI_PROP_SUCCESS) { - unitp->props.i2c_bus = (uint16_t)prop_value[0]; - unitp->props.slave_address = (uint16_t)prop_value[1]; - kmem_free(prop_value, prop_len); -#ifdef DEBUG - if (pcf8591_debug & 0x02) - cmn_err(CE_NOTE, - "pcf8591:ddi_getlongprop(%s) returns %d," - " i2c_bus,slave=0x%x,0x%x", - "reg", retval, unitp->props.i2c_bus, - unitp->props.slave_address); -#endif /* DEBUG */ - } else { - unitp->props.i2c_bus = (uint16_t)-1; - unitp->props.slave_address = (uint16_t)-1; -#ifdef DEBUG - cmn_err(CE_WARN, - "pcf8591_read_props:ddi_getlongprop(%s) returns %d," - " default it to 0x%x:0x%X", - "reg", retval, unitp->props.i2c_bus, - unitp->props.slave_address); -#endif /* DEBUG */ - } - (void) ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "channels-in-use", &prop_len); - retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, - dip, DDI_PROP_DONTPASS, - "channels-in-use", - (uchar_t **)&unitp->props.channels_in_use, - &unitp->props.num_chans_used); - if (retval == DDI_PROP_SUCCESS) { - unitp->props.num_chans_used /= sizeof (pcf8591_channel_t); - } else { - unitp->props.num_chans_used = 0; - } - -#ifdef DEBUG - if (pcf8591_debug & 0x0002) - cmn_err(CE_NOTE, - "pcf8591_read_props:ddi_prop_lookup_byte_array(%s)" - "returns %d\n" - "\t\tlength=%d, #elements=%d", - "channels-in-use", retval, - prop_len, unitp->props.num_chans_used); -#endif /* DEBUG */ - - retval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "channels-description", - (char ***)&unitp->props.channels_description, - (uint_t *)&prop_len); - - if (retval != DDI_PROP_SUCCESS) { - prop_len = 0; - unitp->props.channels_description = NULL; - } - -#ifdef DEBUG - if (pcf8591_debug & 0x0002) { - cmn_err(CE_NOTE, - "pcf8591_read_props:ddi_prop_lookup_string_array(%s)" - "returns %d, length=%d", - "channels-description", retval, prop_len); - for (i = 0; i < prop_len; ++i) { - cmn_err(CE_NOTE, "channels-description[%d]=<%s>", - i, unitp->props.channels_description[i]); - } - } -#endif /* DEBUG */ - - /* - * The following code was borrowed from envctrltwo.c - * I haven't yet investigated why the copy target is index + 2 - */ - retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "tables", &creg_prop, (uint_t *)&prop_len); - - if (retval != DDI_PROP_SUCCESS) { -#ifdef DEBUG - cmn_err(CE_WARN, "%s%d: Unable to read pcf8591 tables property", - ddi_get_name(dip), instance); -#endif /* DEBUG */ - - return (DDI_NOT_WELL_FORMED); - } - - tblsz = (sizeof (_cpu_temps) / sizeof (uchar_t)); - if (prop_len <= tblsz) { - for (i = 0; i < prop_len; i++) { - _cpu_temps[i] = creg_prop[i]; - } - } -#ifdef DEBUG - if (pcf8591_debug & 0x0002) - cmn_err(CE_NOTE, "pcf8591_read_props: _cpu_temps size=%d; " - "tables prop_len=%d\n", tblsz, prop_len); -#endif /* DEBUG */ - - ddi_prop_free(creg_prop); - - /* - * Read shutdown temp and warning temp properties. - */ - warning_temp = (int)ddi_getprop(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "warning-temp", PCF8591_WARNING_TEMP); - - shutdown_temp = (int)ddi_getprop(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "shutdown-temp", PCF8591_SHUTDOWN_TEMP); - - /* - * Fill up the warning and shutdown temp values in kstat structure. - */ - unitp->temp_kstats.warning_threshold = warning_temp; - unitp->temp_kstats.shutdown_threshold = shutdown_temp; - - return (DDI_PROP_SUCCESS); -} diff --git a/usr/src/uts/sun4u/montecarlo/io/scsb.c b/usr/src/uts/sun4u/montecarlo/io/scsb.c deleted file mode 100644 index 75fd61d128..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/scsb.c +++ /dev/null @@ -1,7444 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2019 Peter Tribble. - */ - -/* - * Netra ct800 and Netra ct400 (MonteCarlo/Tonga) - * System Controller and Status Boards STREAMS driver. - * - * This driver handles all communications with the Netra ct400 and ct800 - * System Controller Boards. - * I/O to the SCB is through the PCF8584 I2C controller. - * The SCB I2C interface and driver interface are provided by the - * Xilinx XCS40XL. - * - * N.B.: The design choice of using STREAMS was dictated because - * the original system monitor card had to multiplex 2 pcf8574's - * as one device. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/cred.h> -#include <sys/log.h> -#include <sys/uio.h> -#include <sys/stat.h> -#include <sys/vnode.h> -#include <sys/file.h> -#include <sys/open.h> -#include <sys/kmem.h> -#include <sys/kstat.h> -#include <sys/signal.h> - -#include <sys/stream.h> -#include <sys/strsubr.h> -#include <sys/strsun.h> -#include <sys/poll.h> - -#include <sys/debug.h> - -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/modctl.h> - -#include <sys/i2c/misc/i2c_svc.h> - -#include <sys/mct_topology.h> -#include <sys/netract_gen.h> -#include <sys/scsbioctl.h> -#include <sys/scsb.h> -#include <sys/scsb_cbi.h> - -#include <sys/hotplug/hpctrl.h> -#include <sys/hsc.h> -#include <sys/hscimpl.h> - -#define CPCI_HOTSWAP_SUPPORT - -#define ALARM_CARD_ON_SLOT 1 -#define SCSB_FRU_OP_GET_REG 1 -#define SCSB_FRU_OP_SET_REGBIT 2 -#define SCSB_FRU_OP_GET_BITVAL 3 -#define SCSB_FRU_OP_GET_REGDATA 4 - -/* - * (internal only) - * scsb build version format is "CCYYMMDD" - * for integer compares. - */ -#define SCSB_BUILD_VERSION "20001206" - -#define MUTEX_UNINIT 0 -#define MUTEX_INIT 2 - -static int scsb_err_threshold = 0; /* max allowed i2c errors */ -static int scsb_freeze_count = 3; /* #I2C errors to indicate SCB removal */ -static int scsb_shutdown_count = 5; /* #polls before passing shutdown evt */ -static int scsb_in_postintr = 0; /* 1 if scsb is processing intr */ -static kmutex_t *scb_intr_mutex; /* SCSB interrupt mutex */ -static int nct_mutex_init = MUTEX_UNINIT; - -extern int scsb_hsc_board_healthy(); - -static char *scsb_name = SCSB_DEVICE_NAME; -static char *scsb_clone_name = SCSB_DEVICE_NAME "clone"; -static char *scsb_build_version = SCSB_BUILD_VERSION; -/* - * cb_ops section of scsb driver. - */ -static int sm_open(queue_t *, dev_t *, int, int, cred_t *); -static int sm_close(queue_t *, int, cred_t *); - -static int sm_rput(queue_t *, mblk_t *); /* from i2c below */ -static int sm_wput(queue_t *, mblk_t *); /* from above */ - -uint_t scsb_intr_preprocess(caddr_t arg); -void scsb_intr(caddr_t arg); -static void smf_ioctl(queue_t *, mblk_t *); -static void sm_ioc_rdwr(queue_t *, mblk_t *, int); - -static int scsb_info(dev_info_t *, ddi_info_cmd_t, void *, void **); -static int scsb_attach(dev_info_t *, ddi_attach_cmd_t); -static int scsb_detach(dev_info_t *, ddi_detach_cmd_t); -static int initialize_scb(scsb_state_t *); - -static dev_info_t *scsb_dip; /* private copy of devinfo pointer */ - -static struct module_info info = { - 0, SCSB_DEVICE_NAME, 0, INFPSZ, 512, 128 -}; - -static struct qinit sm_rinit = { - sm_rput, NULL, sm_open, sm_close, NULL, &info -}; - -static struct qinit sm_winit = { - sm_wput, NULL, sm_open, sm_close, NULL, &info -}; - -struct streamtab sm_st = { - &sm_rinit, &sm_winit, NULL, NULL -}; - -static struct cb_ops scsb_cb_ops = { - - nulldev, /* open */ - nulldev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - nodev, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, /* cb_prop_op */ - &sm_st, /* streamtab */ - D_MP, /* Driver compatibility flag */ - CB_REV, /* rev */ - nodev, /* int (*cb_aread)() */ - nodev /* int (*cb_awrite)() */ -}; - -static struct dev_ops scsb_ops = { - - DEVO_REV, /* devo_rev, */ - 0, /* refcnt */ - scsb_info, /* info */ - nulldev, /* identify */ - nulldev, /* probe */ - scsb_attach, /* attach */ - scsb_detach, /* detach */ - nodev, /* reset */ - &scsb_cb_ops, /* driver operations */ - (struct bus_ops *)0, /* bus operations */ - NULL, /* power */ - ddi_quiesce_not_supported, /* devo_quiesce */ -}; - -/* - * Module linkage information for the kernel. - */ - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a pseudo driver */ -#ifdef DEBUG - "SCB/SSB driver DBG" SCSB_BUILD_VERSION, -#else - "v1.33 Netra ct System Control/Status Board driver", -#endif - &scsb_ops, /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - (void *)&modldrv, - NULL -}; - -/* - * local declarations and definitions - */ -#if defined(DEBUG) - uint32_t scsb_debug = 0x00000000; -#else -static uint32_t scsb_debug = 0; -#endif - -static hrtime_t scb_pre_s, scb_pre_e, scb_post_s, scb_post_e; - -static int scsb_pil = SCSB_INTR_PIL; -static int hsc_pil = SCSB_INTR_PIL; -static void *scsb_state; -static uint32_t scsb_global_state; -static uint32_t scsb_event_code; /* for event polling */ -static struct system_info mct_system_info; -static int scsb_healthy_poll_count = 16; - -static fru_id_t fru_id_table[MCT_MAX_FRUS]; -static uchar_t scb_intr_regs[SCTRL_MAX_GROUP_NUMREGS]; - -static uint32_t evc_fifo[EVC_FIFO_SIZE]; -static uint32_t evc_fifo_count = 0; -static uint32_t *evc_rptr = evc_fifo; -static uint32_t *evc_wptr = evc_fifo; -static void *evc_procs[EVC_PROCS_MAX]; -static int evc_proc_count = 0; -static timeout_id_t scsb_intr_tid; - -int nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran); - -/* - * kstat functions - */ -static int scsb_alloc_kstats(scsb_state_t *); -static void scsb_free_kstats(scsb_state_t *); -static int update_ks_leddata(kstat_t *, int); -static int update_ks_state(kstat_t *, int); -static int update_ks_topology(kstat_t *, int); -static int update_ks_evcreg(kstat_t *, int); - -/* - * local functions - */ -static void free_resources(dev_info_t *, scsb_state_t *, int); -static i2c_transfer_t *scsb_alloc_i2ctx(i2c_client_hdl_t, uint_t); -static fru_info_t *find_fru_info(fru_id_t fru_id); -static int scsb_fake_intr(scsb_state_t *, uint32_t); -static int scsb_get_status(scsb_state_t *, scsb_status_t *); -static int scsb_leds_switch(scsb_state_t *, scsb_ustate_t); -static void scsb_freeze(scsb_state_t *scsb); -static void scsb_freeze_check(scsb_state_t *scsb); -static void scsb_restore(scsb_state_t *scsb); -static int scsb_polled_int(scsb_state_t *, int, uint32_t *); -static int scsb_check_config_status(scsb_state_t *scsb); -static int scsb_set_scfg_pres_leds(scsb_state_t *, fru_info_t *); -static void scsb_set_topology(scsb_state_t *); -static void scsb_free_topology(scsb_state_t *); -int scsb_read_bhealthy(scsb_state_t *scsb); -int scsb_read_slot_health(scsb_state_t *, int); -static void tonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip); -static int tonga_psl_to_ssl(scsb_state_t *scsb, int slotnum); -static uchar_t tonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data); -static int scsb_clear_intptrs(scsb_state_t *scsb); -static int scsb_clear_intmasks(scsb_state_t *scsb); -static int scsb_setall_intmasks(scsb_state_t *scsb); -static int scsb_write_mask(scsb_state_t *, uchar_t, uchar_t, uchar_t, - uchar_t); -static int scsb_rdwr_register(scsb_state_t *, int, uchar_t, int, - uchar_t *, int); -static int scsb_readall_regs(scsb_state_t *); -static int scsb_get_led_regnum(scsb_state_t *, scsb_uinfo_t *, uchar_t *, - int *, scsb_led_t); -static void scsb_free_i2ctx(i2c_client_hdl_t, i2c_transfer_t *); -static void check_fru_info(scsb_state_t *, int); -static void update_fru_info(scsb_state_t *, fru_info_t *); -static int event_to_index(uint32_t); -static void add_event_code(scsb_state_t *, uint32_t); -static uint32_t del_event_code(); -static uint32_t get_event_code(); -static int add_event_proc(scsb_state_t *, pid_t); -static int del_event_proc(scsb_state_t *, pid_t); -static void rew_event_proc(scsb_state_t *); -static int event_proc_count(scsb_state_t *); -static int find_evc_proc(pid_t pid); -static void signal_evc_procs(scsb_state_t *); -static int check_event_procs(); -static int scsb_is_alarm_card_slot(scsb_state_t *, int); - int scsb_get_slot_state(scsb_state_t *, int, int *); -static int scsb_fru_op(scsb_state_t *, scsb_utype_t, int, int, int); -static int scsb_queue_put(queue_t *, int, uint32_t *, char *); -static int scsb_queue_ops(scsb_state_t *, int, int, void *, char *); -static int scsb_blind_read(scsb_state_t *, int, uchar_t, int, uchar_t *, int); -static int scsb_toggle_psmint(scsb_state_t *, int); -static int scsb_quiesce_psmint(scsb_state_t *); -static int scsb_invoke_intr_chain(); -int scsb_intr_register(int (*)(void *), void *, fru_id_t); -void scsb_intr_unregister(fru_id_t); - -#ifdef DEBUG -static void mct_topology_dump(scsb_state_t *, int); -static void scsb_failing_event(scsb_state_t *scsb); -#endif - -int -_init(void) -{ - int i, status; - - if (scsb_debug & 0x0005) - cmn_err(CE_NOTE, "scsb: _init()"); - (void) ddi_soft_state_init(&scsb_state, sizeof (scsb_state_t), - SCSB_NO_OF_BOARDS); - (void) hsc_init(); - if ((status = mod_install(&modlinkage)) != 0) { - if (scsb_debug & 0x0006) - cmn_err(CE_NOTE, "scsb: _init(): mod_install failed"); - ddi_soft_state_fini(&scsb_state); - (void) hsc_fini(); - return (status); - } - /* - * initialize the FRU ID Table, using real FRU IDs where available - * such as I2C Addresses for FRUs with I2C support - */ - for (i = 0; i < MCT_MAX_FRUS; ++i) - fru_id_table[i] = i + 1; - fru_id_table[event_to_index(SCTRL_EVENT_PS1)] = (fru_id_t)MCT_I2C_PS1; - fru_id_table[event_to_index(SCTRL_EVENT_PS2)] = (fru_id_t)MCT_I2C_PS2; - fru_id_table[event_to_index(SCTRL_EVENT_FAN1)] = (fru_id_t)MCT_I2C_FAN1; - fru_id_table[event_to_index(SCTRL_EVENT_FAN2)] = (fru_id_t)MCT_I2C_FAN2; - fru_id_table[event_to_index(SCTRL_EVENT_FAN3)] = (fru_id_t)MCT_I2C_FAN3; - fru_id_table[event_to_index(SCTRL_EVENT_SCB)] = (fru_id_t)MCT_I2C_SCB; - return (status); -} - -int -_fini(void) -{ - int status; - - if (scsb_debug & 0x0005) - cmn_err(CE_NOTE, "scsb: _fini()"); - - if ((status = mod_remove(&modlinkage)) == 0) { - ddi_soft_state_fini(&scsb_state); - (void) hsc_fini(); - } - if (scsb_debug & 0x0006) - cmn_err(CE_NOTE, "scsb: _fini, error %x\n", status); - - return (status); -} - -int -_info(struct modinfo *modinfop) -{ - if (scsb_debug & 0x0005) - cmn_err(CE_NOTE, "scsb: _info()"); - - return (mod_info(&modlinkage, modinfop)); -} - -static int -scsb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int instance; - scsb_state_t *scsb; - register int i; - int *regs; - uint_t len; - uchar_t reg, wdata, rmask; - - instance = ddi_get_instance(dip); - - if (scsb_debug & 0x0005) - cmn_err(CE_NOTE, "scsb_attach[%d]", instance); - - if (cmd != DDI_ATTACH) { - if (scsb_debug & 0x0006) - cmn_err(CE_NOTE, - "scsb_attach[%d]: cmd 0x%x != DDI_ATTACH", - instance, cmd); - return (DDI_FAILURE); - } - - if (ddi_soft_state_zalloc(scsb_state, instance) != DDI_SUCCESS) { - cmn_err(CE_WARN, "scsb%d: cannot allocate soft state", - instance); - return (DDI_FAILURE); - } - - scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance); - if (scsb == NULL) { - cmn_err(CE_WARN, "scsb%d: cannot get soft state", instance); - ddi_soft_state_free(scsb_state, instance); - return (DDI_FAILURE); - } - scsb->scsb_instance = instance; - scsb->scsb_state = 0; /* just checking strange mutex behavior */ - - /* - * make sure this is the SCB's known address - */ - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, - "reg", ®s, &len) != DDI_PROP_SUCCESS) { - cmn_err(CE_WARN, - "scsb%d: Failed to get \"reg\" property", instance); - ddi_soft_state_free(scsb_state, instance); - return (DDI_FAILURE); - } - scsb->scsb_i2c_addr = regs[1] & SCSB_I2C_ADDR_MASK; - if (scsb->scsb_i2c_addr != SCSB_I2C_ADDR) { - cmn_err(CE_WARN, "scsb%d: I2C Addr reg %x %x must be %x", - instance, regs[0], regs[1], SCSB_I2C_ADDR); - ddi_soft_state_free(scsb_state, instance); - ddi_prop_free(regs); - return (DDI_FAILURE); - } - /* done with array lookup, free resource */ - ddi_prop_free(regs); - /* - * initialize synchronization mutex and condition var. - * for this instance. - */ - mutex_init(&scsb->scsb_mutex, NULL, MUTEX_DRIVER, NULL); - scsb->scsb_state |= SCSB_UMUTEX; - cv_init(&scsb->scsb_cv, NULL, CV_DRIVER, NULL); - scsb->scsb_state |= SCSB_CONDVAR; - - /* - * 1. Read interrupt property of the board and register its handler. - * 2. Get scsb private handle for communication via I2C Services. - * 3. Allocate and save an i2c_transfer_t for I2C transfers. - */ - /* 1 */ - if (ddi_prop_exists(DDI_DEV_T_ANY, dip, - DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, - "interrupt-priorities") != 1) { - int tmp[2]; - tmp[0] = scsb_pil; - tmp[1] = hsc_pil; - (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, - "interrupt-priorities", tmp, 2); - scsb->scsb_state |= SCSB_PROP_CREATE; - } - if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "interrupts", -1)) >= 0) - scsb->scsb_state |= SCSB_P06_INTR_ON; - else - scsb->scsb_state |= SCSB_P06_NOINT_KLUGE; - - /* - * Look for the device-err-threshold property which specifies - * on how many errors will scsb send a warning event about it's - * health. The scsb_err_threshold is 10 by default. - */ - if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "device-err-threshold", -1)) >= 0) { - scsb_err_threshold = i; -#ifdef DEBUG - cmn_err(CE_NOTE, "?scsb_attach: Found device-err-threshold" - " property, value %d", scsb_err_threshold); -#endif - } - scsb->scsb_i2c_errcnt = 0; - scsb->scsb_err_flag = B_FALSE; - scsb->scsb_kstat_flag = B_FALSE; - - /* - * If all went well, create the minor node for user level access. - */ - if (ddi_create_minor_node(dip, scsb_name, S_IFCHR, instance, - "ddi_ctl:pcihpc", NULL) == DDI_FAILURE) { - cmn_err(CE_WARN, "scsb_attach: Failed to create minor node"); - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - scsb->scsb_state |= SCSB_MINOR_NODE; - scsb->scsb_dev = dip; - if (ddi_create_minor_node(dip, scsb_clone_name, S_IFCHR, - instance|SCSB_CLONE, "ddi_ctl:pcihpc", NULL) - == DDI_FAILURE) { - cmn_err(CE_WARN, "scsb_attach: Failed to create clone node"); - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - /* CLONE */ - bzero(scsb->clone_devs, sizeof (clone_dev_t) * SCSB_CLONES_MAX); - /* 2 */ - if (i2c_client_register(dip, &scsb->scsb_phandle) != I2C_SUCCESS) { - cmn_err(CE_WARN, - "scsb_attach: Failed I2C Services registration"); - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - scsb->scsb_state |= SCSB_I2C_PHANDLE; - /* 3 */ - if ((scsb->scsb_i2ctp = scsb_alloc_i2ctx(scsb->scsb_phandle, - I2C_SLEEP)) == NULL) { - cmn_err(CE_WARN, - "scsb%d: i2c_transfer allocation failed", instance); - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - scsb->scsb_state |= SCSB_I2C_TRANSFER; - /* - * Now it's time to INITIALIZE the boards. - * - * 1. make sure we can do I2C bus transfers to/from the SCB. - * Read the SCB PROM version for a check. - * 2. set SCB_INITIALIZED bit in SysCommand registers (SYS_CMD_BASE) - * 3. clear all LED Data registers (8) by writing 0's to turn off - * all LEDs on the SSB. - * 4. read System Configuration Status registers (SCTRL_CFG) - * to find present FRUs and set corresponding FRU bits at - * LED_DATA_BASE. - * Also enable devices in Topology map for the current MP_ID - * and set the OK LEDs on the SSB. - * 5. read Brd_Hlthy registers (2 @ BRD_HLTHY_BASE) - * 6. Disable PSM Interrupts during initialization, mask all - * interrupts, and clear Interrupt Pointer registers - * by writing 0xFF to each register. - * 7. set SCB EEPROM address bits SPA2-SPA0 at SYS_CMD_BASE + 1 - * 8. Install the interrupt handler if appropriate. - * 9. clear appropriate bits in Interrupt Mask register for those - * devices that can be present for this MP_ID Topology. - * 10. enable PSM Interrupt by writing '1' to PSM_INT_EN bit at - * SYS_CMD_BASE + 1 - * Also update all shadow registers for test utility - * if scsb_debug is set. - * 11. Check if Alarm Card present at boot and set flags - * 12. Call hsc_attach() for slot registration. - * 13. Allocate, initialze, and install the kstat structures. - * 14. Set scsb_state_t flags to indicate SCB is ready - * and announce the driver is loaded. - */ - - /* 1. through 7. */ - if (initialize_scb(scsb) != DDI_SUCCESS) { - if (!(scsb_debug)) { - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } - /* 8. */ - /* - * P0.6 No Interrupt Support - * Instead of installing the handler, it will be called from a user - * program via smf_ioctl(). This flag provides knowledge of the - * necessary workarounds to several scsb routines. - */ - /* - * Now Install interrupt handler - */ - if (scsb->scsb_state & SCSB_P06_INTR_ON) { - if (ddi_get_iblock_cookie(dip, instance, - &scsb->scsb_iblock) == DDI_SUCCESS) { - mutex_init(&scsb->scsb_imutex, NULL, MUTEX_DRIVER, - (void *)scsb->scsb_iblock); - scsb->scsb_state |= SCSB_IMUTEX; - if (ddi_add_intr(dip, instance, &scsb->scsb_iblock, - NULL, scsb_intr_preprocess, - (caddr_t)scsb) != DDI_SUCCESS) { - cmn_err(CE_WARN, - "scsb_attach: failed interrupt " - "handler registration"); - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - scb_intr_mutex = &scsb->scsb_imutex; - nct_mutex_init |= MUTEX_INIT; - } else { - cmn_err(CE_WARN, "scsb_attach: failed interrupt " - "mutex initialization"); - if (scsb_debug) { - scsb->scsb_state |= SCSB_P06_NOINT_KLUGE; - scsb->scsb_state &= ~SCSB_P06_INTR_ON; - } else { - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } - } - /* 9. */ - if (i = scsb_clear_intmasks(scsb)) { - cmn_err(CE_WARN, - "scsb%d: I2C TRANSFER Failed", instance); - if (!scsb_debug) { - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } - - /* 10. */ - /* - * For P0.6 No Interrupt Support, don't enable PSM Interrupt - */ - if (!(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) { - rmask = 0x00; - wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); - i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, - SCTRL_SYS_CMD_BASE); - reg = SCSB_REG_ADDR(i); - if (i = scsb_write_mask(scsb, reg, rmask, wdata, (uchar_t)0)) { - cmn_err(CE_WARN, - "scsb%d: I2C TRANSFER Failed", instance); - if (!scsb_debug) { - free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } else - scsb->scsb_state |= SCSB_PSM_INT_ENABLED; - } - if (scsb_debug) { - /* - * For smctrl test utility, - * so all data is available in shadow registers - * - * DEBUG_MODE enables private testing interfaces - * DIAGS_MODE permits limited testing interfaces - */ - scsb->scsb_state |= SCSB_DEBUG_MODE; - mutex_enter(&scsb->scsb_mutex); - if (scsb_readall_regs(scsb)) - cmn_err(CE_WARN, - "scsb_attach: scsb_readall FAILED"); - mutex_exit(&scsb->scsb_mutex); - } - /* 11. */ - /* Check if Alarm Card present at boot and set flags */ - if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL)) - scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES; - - /* 12. */ - if (scsb_debug & 0x0004) - cmn_err(CE_NOTE, - "scsb_attach: registering cPCI slots"); - if (scsb_hsc_attach(dip, scsb, instance) != DDI_SUCCESS) { - if (scsb_debug & 0x00008000) { - cmn_err(CE_WARN, - "scsb: Hotswap controller initialisation" - " failed\n"); - } - } else - scsb->scsb_hsc_state |= SCSB_HSC_INIT; - /* 13. */ - /* - * allocate and install the kstat data structures - */ - if (scsb_alloc_kstats(scsb) != DDI_SUCCESS) { - if (scsb_debug & 0x0006) - cmn_err(CE_WARN, "scsb_attach: ERROR adding kstats"); - } - /* 14. */ - scsb->scsb_state |= SCSB_UP; - scsb_global_state |= SCSB_UP; - ddi_report_dev(scsb->scsb_dev); - cmn_err(CE_CONT, "?%s%d: " - "Prom Version %s, Midplane Id %x\n", - ddi_driver_name(scsb->scsb_dev), - scsb->scsb_instance, - (scsb->scsb_state & SCSB_P06_PROM) ? "0.6" : - (scsb->scsb_state & SCSB_P10_PROM) ? "1.0" : - (scsb->scsb_state & SCSB_P15_PROM) ? "1.5" : - (scsb->scsb_state & SCSB_P20_PROM) ? "2.0" : "Unknown", - mct_system_info.mid_plane.fru_id); - return (DDI_SUCCESS); -} - -/* - * This funciton is called from scsb_attach(), and from scsb_intr() as part - * of Hot Insertion support, to check the SCB PROM ID register and set - * scsb_state bits and register table pointers as necessary. - */ -static int -scb_check_version(scsb_state_t *scsb) -{ - int hotswap = 0; - uchar_t data; - if (scsb->scsb_state & SCSB_UP) { - /* - * If driver is UP, then this call is from scsb_intr() - * as part of Hot Insertion support. - */ - hotswap = 1; - } - /* Read the SCB PROM ID */ - if (scsb_rdwr_register(scsb, I2C_WR_RD, (uchar_t)SCTRL_PROM_VERSION, 1, - &data, 1)) { - if (!(hotswap && scsb->scsb_state & SCSB_FROZEN)) - cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", - scsb->scsb_instance); - if (scsb_debug & 0x0006) { - cmn_err(CE_WARN, - "scsb_attach(%d): failed read of PROM ID", - scsb->scsb_instance); - } - return (DDI_FAILURE); - } - /* - * compare with stored version number, and if different, - * report a warning and keep the driver FROZEN - */ - if (hotswap) { - if (((mct_system_info.fru_info_list[SCB])[0].fru_version & 0xf) - == (data & 0xf)) { - return (DDI_SUCCESS); - } - if (scsb_debug & 0x00020000) { - cmn_err(CE_NOTE, - "scb_check_version: SCB version %d " - "replacing version %d", data, - (mct_system_info.fru_info_list[SCB])[0]. - fru_version & 0xf); - } - } - if ((data & 0xf) == SCTRL_PROM_P06) { - scsb->scsb_state |= SCSB_P06_PROM; - } else if ((data & 0xf) == SCTRL_PROM_P10) { - scsb->scsb_state |= SCSB_P10_PROM; - } else if ((data & 0xf) == SCTRL_PROM_P15) { - scsb->scsb_state |= SCSB_P15_PROM; - } else if ((data & 0xf) == SCTRL_PROM_P20) { - scsb->scsb_state |= SCSB_P20_PROM; - } - if (!(scsb->scsb_state & SCSB_SCB_PRESENT)) - scsb->scsb_state |= SCSB_SCB_PRESENT; - if (IS_SCB_P10) { - scb_reg_index = scb_10_reg_index; - scb_numregs = scb_10_numregs; - scb_fru_offset = scb_10_fru_offset; - scb_sys_offset = scb_10_sys_offset; - } else { /* if (IS_SCB_P15) */ - scb_reg_index = scb_15_reg_index; - scb_numregs = scb_15_numregs; - scb_fru_offset = scb_15_fru_offset; - scb_sys_offset = scb_15_sys_offset; - } - if (!(IS_SCB_P15) && !(IS_SCB_P10)) { - cmn_err(CE_WARN, "scsb%d: SCB Version %d not recognized", - scsb->scsb_instance, data); - if (hotswap) - scsb->scsb_state |= SCSB_FROZEN; - if (!(scsb_debug)) { - return (DDI_FAILURE); - } - /* - * DEBUG: Assume SCB15 - */ - scsb->scsb_state |= SCSB_P15_PROM; - } - return (DDI_SUCCESS); -} - -/* - * SCB initialization steps to be called from scsb_attach() - * or from scsb_intr() calling scsb_restore() on Hot Insertion. - */ -static int -initialize_scb(scsb_state_t *scsb) -{ - register int i; - uchar_t reg, wdata, rmask; - /* - * If called from scsb_intr(), we've already done this - */ - if (!(scsb->scsb_state & SCSB_IN_INTR)) - if (scb_check_version(scsb) != DDI_SUCCESS) - return (DDI_FAILURE); - /* - * 2. Set the SCB_INIT bit in the System Command register - */ - rmask = 0x00; /* P1.0: 0x60; */ - wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT); - i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE); - reg = SCSB_REG_ADDR(i); - if (i = scsb_write_mask(scsb, reg, rmask, wdata, 0)) { - cmn_err(CE_WARN, - "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance); - if (scsb_debug & 0x0006) { - cmn_err(CE_NOTE, - "scsb_attach: failed to set SCB_INIT"); - } - return (DDI_FAILURE); - } - /* 3. For P1.0 and previous system, turn off all LEDs */ - if (IS_SCB_P10) { - if (scsb_debug & 0x0004) { - cmn_err(CE_NOTE, "scsb_attach(%d): turning LEDs off", - scsb->scsb_instance); - } - if (i = scsb_leds_switch(scsb, OFF)) { - cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", - scsb->scsb_instance); - return (DDI_FAILURE); - } - } - /* 4. Read the SYSCFG registers, update FRU info and SSB LEDs */ - if (scsb_debug & 0x0004) - cmn_err(CE_NOTE, "scsb_attach(%d): reading config registers", - scsb->scsb_instance); - if ((i = scsb_check_config_status(scsb)) == 0) { - if (!(scsb->scsb_state & SCSB_TOPOLOGY)) { - scsb_set_topology(scsb); - if (scsb_debug & 0x0004) - cmn_err(CE_NOTE, "scsb_attach(%d): mpid = 0x%x", - scsb->scsb_instance, - mct_system_info.mid_plane.fru_id); - } else { - fru_info_t *fru_ptr; - /* - * walk through FRUs and update FRU info - */ - for (i = 0; i < SCSB_UNIT_TYPES; ++i) { - fru_ptr = mct_system_info.fru_info_list[i]; - while (fru_ptr != NULL) { - update_fru_info(scsb, fru_ptr); - fru_ptr = fru_ptr->next; - } - } - } - i = scsb_set_scfg_pres_leds(scsb, NULL); - } - if (i) { - cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", - scsb->scsb_instance); - return (DDI_FAILURE); - } - /* 5. read the Board Healthy registers */ - if (scsb_debug & 0x0004) - cmn_err(CE_NOTE, "scsb_attach(%d): reading Brd_Hlthy registers", - scsb->scsb_instance); - i = scsb_read_bhealthy(scsb); - if (i) { - cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", - scsb->scsb_instance); - return (DDI_FAILURE); - } - /* 6. Clear Interrupt Source registers */ - /* - * Due to some registration problems, we must first disable - * global interrupts which may be the default reset value - * itself. However, this is a safe step to do in case of - * implementation changes. - * - * Disable Global SCB Interrupts now - */ - rmask = 0x00; /* P1.0: 0x60; */ - wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); - i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE); - reg = SCSB_REG_ADDR(i); - if (i = scsb_write_mask(scsb, reg, rmask, (uchar_t)0, wdata)) { - cmn_err(CE_WARN, "scsb%d: Cannot turn off PSM_INT", - scsb->scsb_instance); - return (DDI_FAILURE); - } - /* Mask all interrupt sources */ - if (i = scsb_setall_intmasks(scsb)) { - cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", - scsb->scsb_instance); - return (DDI_FAILURE); - } - /* Clear any latched interrupts */ - if (i = scsb_clear_intptrs(scsb)) { - cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", - scsb->scsb_instance); - return (DDI_FAILURE); - } - /* 7. set SCB EEPROM address: NOT USED */ - return (DDI_SUCCESS); -} - -/* - * Based on MC conditions, scsb_detach should eventually be made to always - * return FAILURE, as the driver should not be allowed to detach after some - * hs slots have been used. - */ -static int -scsb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - int instance; - scsb_state_t *scsb; - uchar_t reg, wdata; - - /* - * TBD: make sure there are no outstanding operations on the system - * monitor card before detaching. - */ - instance = ddi_get_instance(dip); - if (scsb_debug & 0x0005) - cmn_err(CE_NOTE, "scsb_detach[%d]", instance); - if (cmd != DDI_DETACH) { - if (scsb_debug & 0x0006) - cmn_err(CE_NOTE, - "scsb_detach(%d): command %x is not DDI_DETACH\n", - instance, cmd); - return (DDI_FAILURE); - } - scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance); - scsb->scsb_state &= ~SCSB_UP; - scsb_global_state &= ~SCSB_UP; - if (scsb->scsb_hsc_state & SCSB_HSC_INIT) { - (void) scsb_hsc_detach(dip, scsb, instance); - scsb->scsb_hsc_state &= ~SCSB_HSC_INIT; - } - if (scsb->scsb_state & SCSB_PSM_INT_ENABLED) { - /* - * Disable Global SCB Interrupts now - */ - wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); - reg = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, - SCTRL_SYS_CMD_BASE); - if (scsb_write_mask(scsb, reg, (uchar_t)0, (uchar_t)0, wdata)) { - cmn_err(CE_WARN, - "scsb%d: Cannot turn off PSM_INT", instance); - if (!scsb_debug) { - (void) free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } - /* Mask all interrupts */ - if (scsb_setall_intmasks(scsb)) { - cmn_err(CE_WARN, - "scsb%d: I2C TRANSFER Failed", instance); - if (!scsb_debug) { - (void) free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } - /* Clear all latched interrupts */ - if (scsb_clear_intptrs(scsb)) { - cmn_err(CE_WARN, - "scsb%d: I2C TRANSFER Failed", instance); - if (!scsb_debug) { - (void) free_resources(dip, scsb, instance); - return (DDI_FAILURE); - } - } - } - if (scsb->scsb_opens && scsb->scsb_rq != NULL) - qprocsoff(scsb->scsb_rq); - /* CLONE */ - (void) scsb_queue_ops(scsb, QPROCSOFF, 0, NULL, NULL); - /* - * free the allocated resources - */ - free_resources(dip, scsb, instance); - return (DDI_SUCCESS); -} - -static void -free_resources(dev_info_t *dip, scsb_state_t *scsb, int instance) -{ - if (scsb_debug & 0x0005) { - cmn_err(CE_NOTE, "free_resources[%d], scsb_state=0x%x", - instance, scsb->scsb_state); - drv_usecwait(500000); - } - if (scsb->scsb_state & SCSB_P06_INTR_ON && - scsb->scsb_state & SCSB_IMUTEX) { - scsb->scsb_state &= ~SCSB_P06_INTR_ON; - ddi_remove_intr(dip, 0, scsb->scsb_iblock); - } - if (scsb->scsb_state & SCSB_KSTATS) { - scsb_free_kstats(scsb); - scsb->scsb_state &= ~SCSB_KSTATS; - } - if (scsb->scsb_state & SCSB_TOPOLOGY) { - scsb_free_topology(scsb); - scsb->scsb_state &= ~SCSB_TOPOLOGY; - } - - nct_mutex_init = MUTEX_UNINIT; - if (scsb->scsb_state & SCSB_IMUTEX) { - scsb->scsb_state &= ~SCSB_IMUTEX; - mutex_destroy(&scsb->scsb_imutex); - } - if (scsb->scsb_state & SCSB_I2C_TRANSFER) { - scsb->scsb_state &= ~SCSB_I2C_TRANSFER; - i2c_transfer_free(scsb->scsb_phandle, scsb->scsb_i2ctp); - } - if (scsb->scsb_state & SCSB_I2C_PHANDLE) { - scsb->scsb_state &= ~SCSB_I2C_PHANDLE; - i2c_client_unregister(scsb->scsb_phandle); - } - if (scsb->scsb_state & SCSB_MINOR_NODE) { - scsb->scsb_state &= ~SCSB_MINOR_NODE; - ddi_remove_minor_node(dip, NULL); - } - if (scsb->scsb_state & SCSB_PROP_CREATE) { - scsb->scsb_state &= ~SCSB_PROP_CREATE; - (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, - "interrupt-priorities"); - } - /* ddi_prop_remove_all(dip); */ - if (scsb->scsb_state & SCSB_CONDVAR) { - scsb->scsb_state &= ~SCSB_CONDVAR; - cv_destroy(&scsb->scsb_cv); - } - if (scsb->scsb_state & SCSB_UMUTEX) { - scsb->scsb_state &= ~SCSB_UMUTEX; - mutex_destroy(&scsb->scsb_mutex); - } - ddi_soft_state_free(scsb_state, instance); -} - -/* - * Just for testing scsb's poll function - */ -static int -scsb_fake_intr(scsb_state_t *scsb, uint32_t evcode) -{ - if (evcode == 0) - evcode = scsb_event_code; - else - scsb_event_code = evcode; - if (scsb_debug & 0x4001) { - cmn_err(CE_NOTE, "scsb_fake_intr: event = 0x%x, scsb_rq=0x%p", - scsb_event_code, (void *)scsb->scsb_rq); - } - /* - * Allow access to shadow registers even though SCB is removed - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (EAGAIN); - * } - */ - if (scsb_debug & 0x00040000) { - check_fru_info(scsb, evcode); - add_event_code(scsb, evcode); - } - /* just inform user-level via poll about this event */ - if (scsb_queue_ops(scsb, QPUT_INT32, 1, &evcode, "scsb_fake_intr") - == QOP_FAILED) - return (ENOMEM); - return (0); -} - -/* ARGSUSED */ -static int -scsb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - int retval = DDI_FAILURE; - - if (scsb_debug & 0x0001) - cmn_err(CE_NOTE, "scsb_info()"); - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if (getminor((dev_t)arg) == 0 && scsb_dip != NULL) { - *result = (void *) scsb_dip; - retval = DDI_SUCCESS; - } - break; - - case DDI_INFO_DEVT2INSTANCE: - if (getminor((dev_t)arg) == 0) { - *result = (void *)0; - retval = DDI_SUCCESS; - } - break; - - default: - break; - } - - return (retval); -} - - -/* - * SCSB STREAMS routines - */ -/*ARGSUSED*/ -static int -sm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) -{ - int instance, clone; - minor_t minor_dev; - clone_dev_t *clptr; - scsb_state_t *scsb; - - minor_dev = getminor(*devp); - instance = SCSB_GET_INSTANCE(minor_dev); - scsb = ddi_get_soft_state(scsb_state, instance); - if (scsb == NULL) - return (ENXIO); - - if (scsb_debug & 0x0009) { - cmn_err(CE_NOTE, "sm_open(%d) q=0x%p", instance, (void *)q); - } - if (!(scsb->scsb_state & SCSB_UP)) { - return (ENODEV); - } - /* - * Don't fail the open if SCB removed since we still want to satisfy - * read requests from the shadow registers, the last know register - * contents. On new SCB insertion, all will be re-initialized, - * including envmond and it's policies. - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (EAGAIN); - * } - */ - ASSERT(credp != NULL); - /* - * XXX check for root access here, return EPERM if not root open - */ - if (sflag == MODOPEN) { - /* scsb module is being pushed */ - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, "sm_open(%d): MODOPEN", instance); - /* - * this is no longer supported - */ - return (ENXIO); - } else if (sflag == CLONEOPEN) { - /* scsb is being opened as a clonable driver */ - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, "sm_open(%d): CLONEOPEN", instance); - /* - * The cloned stream is not handled via the clone driver. - * See the minor device code below. - */ - return (ENXIO); - } else if (minor_dev & SCSB_CLONE) { - /* - * First check for the SCSB_CLONE device. - * Find an available clone_devs[] entry, or return ENXIO. - * Make new dev_t and store in *devp. - */ - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, - "sm_open(%d): SCSB_CLONE OPEN", instance); - mutex_enter(&scsb->scsb_mutex); - if ((clone = scsb_queue_ops(scsb, QFIRST_AVAILABLE, 0, NULL, - "scsb_open")) == QOP_FAILED) { - mutex_exit(&scsb->scsb_mutex); - return (ENXIO); - } - clptr = &scsb->clone_devs[clone]; - clptr->cl_flags = SCSB_OPEN; - clptr->cl_rq = RD(q); - clptr->cl_minor = SCSB_MAKE_MINOR(instance, clone); - *devp = makedevice(getmajor(*devp), clptr->cl_minor); - scsb->scsb_clopens++; - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, - "sm_open(%d): new clone device minor: 0x%x" - " stream queue is 0x%p", - instance, clptr->cl_minor, (void *)q); - } else { - /* scsb is being opened as a regular driver */ - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, "sm_open(%d): DEVOPEN", instance); - mutex_enter(&scsb->scsb_mutex); - if (scsb->scsb_state & SCSB_EXCL) { - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, - "sm_open(%d): can't open, state is EXCL", - instance); - mutex_exit(&scsb->scsb_mutex); - return (EBUSY); - } - if (flag & FEXCL) { - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, "sm_open(%d): is EXCL", - instance); - if (scsb->scsb_state & SCSB_OPEN) { - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, - "sm_open(%d): cannot open EXCL", - instance); - mutex_exit(&scsb->scsb_mutex); - return (EBUSY); - } - scsb->scsb_state |= SCSB_EXCL; - } - if (scsb->scsb_opens && scsb->scsb_rq != NULL && - scsb->scsb_rq != RD(q)) { - if (scsb_debug & 0x000a) - cmn_err(CE_WARN, "sm_open[%d]: q (0x%p) != " - "scsb_rq (0x%p)", - instance, (void *)RD(q), - (void *)scsb->scsb_rq); - } - scsb->scsb_rq = RD(q); - scsb->scsb_opens++; - } - scsb->scsb_state |= SCSB_OPEN; - mutex_exit(&scsb->scsb_mutex); - RD(q)->q_ptr = WR(q)->q_ptr = scsb; - qprocson(q); - return (0); -} - -/*ARGSUSED*/ -static int -sm_close(queue_t *q, int flag, cred_t *credp) -{ - scsb_state_t *scsb; - int clone; - clone_dev_t *clptr = NULL; - - scsb = (scsb_state_t *)q->q_ptr; - if (scsb_debug & 0x0009) - cmn_err(CE_NOTE, "sm_close[%d](0x%p)", scsb->scsb_instance, - (void *)q); - if (scsb->scsb_clopens) { - mutex_enter(&scsb->scsb_mutex); - if ((clone = scsb_queue_ops(scsb, QFIND_QUEUE, 0, - (void *) RD(q), "scsb_close")) != QOP_FAILED) { - clptr = &scsb->clone_devs[clone]; - clptr->cl_flags = 0; - clptr->cl_rq = NULL; - scsb->scsb_clopens--; - } - mutex_exit(&scsb->scsb_mutex); - if (scsb_debug & 0x0008 && clone < SCSB_CLONES_MAX && - clone >= SCSB_CLONES_FIRST) - cmn_err(CE_NOTE, "sm_close(%d): SCSB_CLONE 0x%x", - scsb->scsb_instance, clptr->cl_minor); - } - if (clptr == NULL && scsb->scsb_opens) { - if (scsb_debug & 0x0008) - cmn_err(CE_NOTE, "sm_close(%d): DEVOPEN, opens=%d", - scsb->scsb_instance, scsb->scsb_opens); - if (RD(q) != scsb->scsb_rq) { - if (scsb_debug & 0x0008) - cmn_err(CE_WARN, - "sm_close(%d): DEVOPEN, q != scsb_rq", - scsb->scsb_instance); - } - mutex_enter(&scsb->scsb_mutex); - scsb->scsb_opens = 0; - if (scsb->scsb_state & SCSB_EXCL) { - scsb->scsb_state &= ~SCSB_EXCL; - } - scsb->scsb_rq = (queue_t *)NULL; - mutex_exit(&scsb->scsb_mutex); - } - if (scsb->scsb_opens == 0 && scsb->scsb_clopens == 0) { - scsb->scsb_state &= ~SCSB_OPEN; - } - RD(q)->q_ptr = WR(q)->q_ptr = NULL; - qprocsoff(q); - return (0); -} - -/*ARGSUSED*/ -static int -sm_rput(queue_t *q, mblk_t *mp) -{ - if (scsb_debug & 0x0010) - cmn_err(CE_NOTE, "sm_rput"); - return (0); -} - -static int -sm_wput(queue_t *q, mblk_t *mp) -{ - scsb_state_t *scsb = (scsb_state_t *)WR(q)->q_ptr; - - if (scsb_debug & 0x0010) - cmn_err(CE_NOTE, "sm_wput(%d): mp %p", scsb->scsb_instance, - (void *)mp); - - switch (mp->b_datap->db_type) { - default: - freemsg(mp); - break; - - case M_FLUSH: /* canonical flush handling */ - if (*mp->b_rptr & FLUSHW) { - flushq(q, FLUSHDATA); - /* free any messages tied to scsb */ - } - - if (*mp->b_rptr & FLUSHR) { - *mp->b_rptr &= ~FLUSHW; - qreply(q, mp); - } else - freemsg(mp); - break; - - case M_IOCTL: - if (scsb_debug & 0x0010) - cmn_err(CE_NOTE, "sm_wput(%d): M_IOCTL", - scsb->scsb_instance); - /* do ioctl */ - smf_ioctl(q, mp); - break; - - case M_DATA: - if (scsb_debug & 0x0010) - cmn_err(CE_NOTE, "sm_wput(%d): M_DATA", - scsb->scsb_instance); - if (!(scsb->scsb_state & SCSB_UP)) { - freemsg(mp); - return (0); - } - freemsg(mp); - break; - - case M_CTL: - if (scsb_debug & 0x0010) - cmn_err(CE_NOTE, "sm_wput(%d): M_CTL", - scsb->scsb_instance); - freemsg(mp); - break; - } - - return (0); -} - - -/* - * These are the system monitor upper ioctl functions. - */ -static void -smf_ioctl(queue_t *q, mblk_t *mp) -{ - scsb_state_t *scsb = (scsb_state_t *)q->q_ptr; - struct iocblk *iocp = (struct iocblk *)mp->b_rptr; - - if (scsb_debug & 0x0020) - cmn_err(CE_NOTE, "smf_ioctl(%d): (%p)->cmd=%x", - scsb->scsb_instance, (void *)mp, iocp->ioc_cmd); - - if (!(scsb->scsb_state & SCSB_UP)) { - miocnak(q, mp, 0, ENXIO); - return; - } - /* - * Don't fail ALL commands if the SCB removed, since we still want to - * satisfy some requests from the shadow registers, the last known - * register contents. - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * iocp->ioc_error = EAGAIN; - * mp->b_datap->db_type = M_IOCNAK; - * qreply(q, mp); - * return; - * } - */ - - iocp->ioc_error = 0; - switch (iocp->ioc_cmd) { - default: - /* if we don't understand the ioctl */ - if (scsb_debug & 0x0022) - cmn_err(CE_NOTE, "smf_ioctl(%d):unkown ioctl %x", - scsb->scsb_instance, iocp->ioc_cmd); - iocp->ioc_error = EINVAL; - break; - - case ENVC_IOC_GETMODE: - { - uint8_t *curr_mode; - - iocp->ioc_error = miocpullup(mp, sizeof (uint8_t)); - if (iocp->ioc_error != 0) - break; - - curr_mode = (uint8_t *)mp->b_cont->b_rptr; - if (scsb->scsb_state & SCSB_DEBUG_MODE) - *curr_mode = (uint8_t)ENVC_DEBUG_MODE; - else if (scsb->scsb_state & SCSB_DIAGS_MODE) - *curr_mode = (uint8_t)ENVCTRL_DIAG_MODE; - else - *curr_mode = (uint8_t)ENVCTRL_NORMAL_MODE; - - if (scsb_debug & 0x20) { - cmn_err(CE_NOTE, "IOC_GETMODE: returning mode 0x%x", - *curr_mode); - } - break; - } - - case ENVC_IOC_SETMODE: - { - uint8_t *curr_mode; - - iocp->ioc_error = miocpullup(mp, sizeof (uint8_t)); - if (iocp->ioc_error != 0) - break; - - curr_mode = (uint8_t *)mp->b_cont->b_rptr; - switch (*curr_mode) { - case ENVCTRL_NORMAL_MODE: - scsb->scsb_state &= - ~(SCSB_DEBUG_MODE | SCSB_DIAGS_MODE); - break; - case ENVCTRL_DIAG_MODE: - scsb->scsb_state |= SCSB_DIAGS_MODE; - scsb->scsb_state &= ~SCSB_DEBUG_MODE; - break; - case ENVC_DEBUG_MODE: - if (scsb->scsb_state & - (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)) { - scsb->scsb_state &= ~SCSB_DIAGS_MODE; - scsb->scsb_state |= SCSB_DEBUG_MODE; - } else { - iocp->ioc_error = EACCES; - } - break; - default: - if (scsb_debug & 0x22) { - cmn_err(CE_WARN, - "IOC_SETMODE: Invalid mode 0x%x", - *curr_mode); - } - iocp->ioc_error = EINVAL; - break; - } - break; - } - - case ENVC_IOC_ACQUIRE_SLOT_LED_CTRL: - if (scsb->scsb_state & SCSB_APP_SLOTLED_CTRL) - iocp->ioc_error = EAGAIN; - else { - scsb->scsb_state |= SCSB_APP_SLOTLED_CTRL; - iocp->ioc_error = 0; - } - break; - - case ENVC_IOC_RELEASE_SLOT_LED_CTRL: - scsb->scsb_state &= ~SCSB_APP_SLOTLED_CTRL; - iocp->ioc_error = 0; - break; - - /* - * Not an exposed interface, only used by development utilities. - */ - case SCSBIOC_GET_VERSIONS: - { - uint8_t *ppromid, promid; - scsb_ids_t *sids; - - if (iocp->ioc_count == sizeof (uint8_t)) { - iocp->ioc_error = miocpullup(mp, sizeof (uint8_t)); - if (iocp->ioc_error != 0) - break; - - ppromid = (uint8_t *)mp->b_cont->b_rptr; - *ppromid = (uint8_t)(mct_system_info. - fru_info_list[SCB])->fru_version; - promid = *ppromid; - } else { - iocp->ioc_error = miocpullup(mp, sizeof (scsb_ids_t)); - if (iocp->ioc_error != 0) - break; - - sids = (scsb_ids_t *)mp->b_cont->b_rptr; - bcopy(modldrv.drv_linkinfo, sids->modldrv_string, - SCSB_MODSTR_LEN); - bcopy(scsb_build_version, sids->scsb_version, - SCSB_VERSTR_LEN); - sids->promid = (uint8_t)(mct_system_info. - fru_info_list[SCB])->fru_version; - - promid = sids->promid; - if (scsb_debug & 0x20) { - cmn_err(CE_NOTE, - "IOC_GET_VERSIONS: sizeof(scsb_ids_t) " - "= %lu", sizeof (scsb_ids_t)); - } - } - if (scsb_debug & 0x20) { - cmn_err(CE_NOTE, - "IOC_GET_VERSIONS: SCB PROMID = 0x%x", promid); - } - break; - } - -#ifdef DEBUG - case ENVC_IOC_REGISTER_PID: - iocp->ioc_error = miocpullup(mp, sizeof (pid_t)); - if (iocp->ioc_error == 0) { - if (add_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr)) - iocp->ioc_error = ENOMEM; - } - break; - - case ENVC_IOC_UNREGISTER_PID: - iocp->ioc_error = miocpullup(mp, sizeof (pid_t)); - if (iocp->ioc_error == 0) { - if (del_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr)) - iocp->ioc_error = EINVAL; - } - break; - - case SCSBIOC_VALUE_MODE: - { - uint32_t *mode_vals; - int three_vals = 0; - - if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) { - iocp->ioc_error = EINVAL; - break; - } - - if (iocp->ioc_count == sizeof (uint32_t) * 3) - three_vals = 1; - else if (iocp->ioc_count != sizeof (uint32_t) * 2) { - iocp->ioc_error = EINVAL; - break; - } - - iocp->ioc_error = miocpullup(mp, iocp->ioc_count); - if (iocp->ioc_error != 0) - break; - - /* - * check mode_vals[0] for get/set option. setting - * scsb_state is not valid for now. 0 == GET, 1 == SET - */ - mode_vals = (uint32_t *)mp->b_cont->b_rptr; - if (mode_vals[0]) { - scsb_debug = mode_vals[1]; - } else { - mode_vals[0] = scsb->scsb_state; - if (three_vals) { - mode_vals[1] = scsb->scsb_hsc_state; - mode_vals[2] = scsb_debug; - } else - mode_vals[1] = scsb_debug; - } - if ((scsb_debug & 0x20) && three_vals) { - cmn_err(CE_NOTE, "IOC_VALUE_MODE: mode_vals: " - "0x%x/0x%x/0x%x; ioc_count = 0x%lx", - mode_vals[0], mode_vals[1], mode_vals[2], - iocp->ioc_count); - } - break; - } - -#ifdef DEBUG - case SCSBIOC_GET_SLOT_INFO: - { - hsc_slot_t *slot_info = NULL; - uint32_t *slot_vals; - int pslotnum; - - if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) { - iocp->ioc_error = EINVAL; - break; - } - - iocp->ioc_error = miocpullup(mp, sizeof (uint32_t) * 2); - if (iocp->ioc_error != 0) - break; - - slot_vals = (uint32_t *)mp->b_cont->b_rptr; - pslotnum = (int)*slot_vals; - hsc_ac_op((int)scsb->scsb_instance, pslotnum, - SCSB_HSC_AC_GET_SLOT_INFO, &slot_info); - if (slot_info == NULL) { - iocp->ioc_error = ENODEV; - break; - } - *slot_vals = (uint32_t)slot_info->hs_flags; - *(++slot_vals) = (uint32_t)slot_info->hs_slot_state; - if (scsb_debug & 0x20) { - cmn_err(CE_NOTE, "IOC_GET_SLOT_STATE: slot_vals: " - "0x%x/0x%x; ioc_count = 0x%lx", - slot_vals[0], slot_vals[1], iocp->ioc_count); - } - break; - } -#endif /* DEBUG */ - - case SCSBIOC_GET_FAN_STATUS: - case SCSBIOC_GET_INTR_ARRAY: - /* for now we don't understand these ioctls */ - if (scsb_debug & 0x0022) - cmn_err(CE_NOTE, "smf_ioctl(%d):unknown ioctl %x", - scsb->scsb_instance, iocp->ioc_cmd); - iocp->ioc_error = EINVAL; - break; -#endif /* DEBUG */ - - case SCSBIOC_LED_OK_GET: - case SCSBIOC_LED_NOK_GET: - case SCSBIOC_LED_OK_SET: - case SCSBIOC_LED_NOK_SET: - case SCSBIOC_BHEALTHY_GET: - case SCSBIOC_SLOT_OCCUPANCY: - case SCSBIOC_RESET_UNIT: - if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) { - iocp->ioc_error = EACCES; - break; - } - /*FALLTHROUGH*/ - - case ENVC_IOC_GETDSKLED: - case ENVC_IOC_SETDSKLED: - case ENVC_IOC_SETFSP: - { - scsb_uinfo_t *suip; - - iocp->ioc_error = miocpullup(mp, sizeof (scsb_uinfo_t)); - if (iocp->ioc_error != 0) - break; - - suip = (scsb_uinfo_t *)mp->b_cont->b_rptr; - switch (iocp->ioc_cmd) { - case SCSBIOC_LED_OK_GET: - iocp->ioc_error = scsb_led_get(scsb, suip, OK); - break; - case SCSBIOC_LED_NOK_GET: - iocp->ioc_error = scsb_led_get(scsb, suip, NOK); - break; - case SCSBIOC_LED_OK_SET: - iocp->ioc_error = scsb_led_set(scsb, suip, OK); - break; - case SCSBIOC_LED_NOK_SET: - iocp->ioc_error = scsb_led_set(scsb, suip, NOK); - break; - case SCSBIOC_BHEALTHY_GET: - iocp->ioc_error = scsb_bhealthy_slot(scsb, suip); - break; - case SCSBIOC_SLOT_OCCUPANCY: - iocp->ioc_error = scsb_slot_occupancy(scsb, suip); - break; - case SCSBIOC_RESET_UNIT: - iocp->ioc_error = scsb_reset_unit(scsb, suip); - break; - case ENVC_IOC_GETDSKLED: - if (suip->unit_type != DISK) { - iocp->ioc_error = EINVAL; - break; - } - iocp->ioc_error = scsb_led_get(scsb, suip, NOUSE); - break; - case ENVC_IOC_SETDSKLED: - if (suip->unit_type != DISK) { - iocp->ioc_error = EINVAL; - break; - } - iocp->ioc_error = scsb_led_set(scsb, suip, NOUSE); - break; - case ENVC_IOC_SETFSP: - if (scsb->scsb_state & SCSB_FROZEN) { - iocp->ioc_error = EAGAIN; - break; - } - iocp->ioc_error = scsb_led_set(scsb, suip, NOUSE); - break; - } - break; - } - - case SCSBIOC_FAKE_INTR: { - uint32_t ui; - - if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) { - iocp->ioc_error = EINVAL; - break; - } - if (mp->b_cont == NULL) - ui = 0; - else { - iocp->ioc_error = miocpullup(mp, sizeof (uint32_t)); - if (iocp->ioc_error != 0) - break; - ui = *(uint32_t *)mp->b_cont->b_rptr; - } - iocp->ioc_error = scsb_fake_intr(scsb, ui); - break; - } - - case SCSBIOC_GET_STATUS : - if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) { - iocp->ioc_error = EINVAL; - break; - } - iocp->ioc_error = miocpullup(mp, sizeof (scsb_status_t)); - if (iocp->ioc_error == 0) - iocp->ioc_error = scsb_get_status(scsb, - (scsb_status_t *)mp->b_cont->b_rptr); - break; - - case SCSBIOC_ALL_LEDS_ON : - if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) - iocp->ioc_error = EACCES; - else - iocp->ioc_error = scsb_leds_switch(scsb, ON); - break; - - case SCSBIOC_ALL_LEDS_OFF : - if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) - iocp->ioc_error = EACCES; - else - iocp->ioc_error = scsb_leds_switch(scsb, OFF); - break; - - case SCSBIOC_REG_READ: - case SCSBIOC_REG_WRITE: - if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) { - iocp->ioc_error = EACCES; - } else { - scsb_ioc_rdwr_t *iocrdwrp; - - if (scsb->scsb_state & SCSB_FROZEN && - !(scsb->scsb_state & SCSB_DEBUG_MODE)) { - iocp->ioc_error = EAGAIN; - break; - } - - iocp->ioc_error = miocpullup(mp, sizeof (*iocrdwrp)); - if (iocp->ioc_error == 0) { - iocrdwrp = - (scsb_ioc_rdwr_t *)mp->b_cont->b_rptr; - - if (iocp->ioc_cmd == SCSBIOC_REG_READ) { - if (iocrdwrp->ioc_rlen > 0) { - sm_ioc_rdwr(q, mp, I2C_WR_RD); - return; - } - } else { - if (iocrdwrp->ioc_wlen > 0) { - sm_ioc_rdwr(q, mp, I2C_WR); - return; - } - } - iocp->ioc_error = EINVAL; - break; - } - } - break; - - case SCSBIOC_SHUTDOWN_POLL: - case SCSBIOC_INTEVENT_POLL: - if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) { - iocp->ioc_error = EINVAL; - break; - } - iocp->ioc_error = miocpullup(mp, sizeof (uint32_t)); - if (iocp->ioc_error == 0) - iocp->ioc_error = scsb_polled_int(scsb, iocp->ioc_cmd, - (uint32_t *)mp->b_cont->b_rptr); - break; - - case SCSBIOC_RESTORE : - if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) - iocp->ioc_error = EACCES; - else { - scsb_restore(scsb); - (void) scsb_toggle_psmint(scsb, 1); - iocp->ioc_error = 0; - } - break; - - case SCSBIOC_FREEZE : - if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) - iocp->ioc_error = EACCES; - else { - scsb_freeze_check(scsb); - scsb_freeze(scsb); - iocp->ioc_error = 0; - } - break; - - /* - * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_INSERTION - */ - case ENVC_IOC_ACCONF_RESTORED: - (void) scsb_hsc_ac_op(scsb, scsb->ac_slotnum, - SCSB_HSC_AC_SET_BUSY); - break; - - /* - * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_REMOVAL - */ - case ENVC_IOC_ACCONF_STORED: - if (scsb->scsb_state & SCSB_FROZEN) { - iocp->ioc_error = EAGAIN; - break; - } - (void) scsb_hsc_ac_op(scsb, scsb->ac_slotnum, - SCSB_HSC_AC_UNCONFIGURE); - break; - -#ifdef DEBUG - case SCSBIOC_TOPOLOGY_DUMP: - if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) - iocp->ioc_error = EINVAL; - else { - mct_topology_dump(scsb, 1); - iocp->ioc_error = 0; - } - break; -#endif - } - if (iocp->ioc_error) - mp->b_datap->db_type = M_IOCNAK; - else - mp->b_datap->db_type = M_IOCACK; - qreply(q, mp); -} - -static fru_info_t * -find_fru_info(fru_id_t fru_id) -{ - int i; - fru_info_t *fru_ptr; - - if (scsb_debug & 0x00100001) - cmn_err(CE_NOTE, "find_fru_info(0x%x)", fru_id); - if (fru_id == (fru_id_t)0) - return ((fru_info_t *)NULL); - for (i = 0; i < SCSB_UNIT_TYPES; ++i) { - fru_ptr = mct_system_info.fru_info_list[i]; - while (fru_ptr != NULL) { - if (fru_ptr->fru_id == fru_id) - return (fru_ptr); - fru_ptr = fru_ptr->next; - } - } - return ((fru_info_t *)NULL); -} - - -struct scsb_cb_entry { - void *cb_softstate_ptr; - fru_id_t cb_fru_id; - scsb_fru_event_t cb_event; - void (*cb_func) - (void *, scsb_fru_event_t, scsb_fru_status_t); - fru_info_t *cb_fru_ptr; - struct scsb_cb_entry *cb_next; -}; - -#ifdef DEBUG -int scsb_cb_count = 0; -#else -static -#endif -struct scsb_cb_entry *scsb_cb_table; - -/* - * global function for interested FRU drivers to register a callback function, - * to be called when FRU presence status changes. - */ -scsb_fru_status_t -scsb_fru_register(void (*cb_func)(void *, scsb_fru_event_t, scsb_fru_status_t), - void *soft_ptr, fru_id_t fru_id) -{ - struct scsb_cb_entry *cbe_ptr; - - if (scsb_debug & 0x00800001) { - cmn_err(CE_NOTE, - "scsb_fru_register: FRU_ID 0x%x", (int)fru_id); - } - if (!(scsb_global_state & SCSB_UP)) { - return (FRU_NOT_AVAILABLE); - } - if (cb_func == NULL || fru_id == (fru_id_t)0) - return (FRU_NOT_AVAILABLE); - if (scsb_cb_table == NULL) - scsb_cb_table = (struct scsb_cb_entry *) - kmem_zalloc(sizeof (struct scsb_cb_entry), KM_SLEEP); - cbe_ptr = scsb_cb_table; - while (cbe_ptr->cb_softstate_ptr != NULL) { - if (cbe_ptr->cb_next == (struct scsb_cb_entry *)NULL) { - cbe_ptr->cb_next = (struct scsb_cb_entry *) - kmem_zalloc(sizeof (struct scsb_cb_entry), - KM_SLEEP); - cbe_ptr = cbe_ptr->cb_next; - break; - } - cbe_ptr = cbe_ptr->cb_next; - } - cbe_ptr->cb_softstate_ptr = soft_ptr; - cbe_ptr->cb_fru_id = fru_id; - cbe_ptr->cb_func = cb_func; - cbe_ptr->cb_next = (struct scsb_cb_entry *)NULL; - cbe_ptr->cb_fru_ptr = find_fru_info(fru_id); -#ifdef DEBUG - scsb_cb_count++; -#endif - if (scsb_debug & 0x00800000) { - cmn_err(CE_NOTE, - "scsb_fru_register: FRU_ID 0x%x, status=%d", - (int)fru_id, - (cbe_ptr->cb_fru_ptr == (fru_info_t *)NULL) ? - 0xff : cbe_ptr->cb_fru_ptr->fru_status); - } - if (cbe_ptr->cb_fru_ptr == (fru_info_t *)NULL) - return (FRU_NOT_AVAILABLE); - if (cbe_ptr->cb_fru_ptr->fru_status & FRU_PRESENT) - return (FRU_PRESENT); - return (FRU_NOT_PRESENT); -} - -void -scsb_fru_unregister(void *soft_ptr, fru_id_t fru_id) -{ - struct scsb_cb_entry *prev_ptr, *cbe_ptr; - - if (scsb_debug & 0x00800001) { - cmn_err(CE_NOTE, "scsb_fru_unregister(0x%p, 0x%x)", - soft_ptr, (int)fru_id); - } - if ((cbe_ptr = scsb_cb_table) == NULL || fru_id == (fru_id_t)0) - return; - prev_ptr = cbe_ptr; - do { - if (cbe_ptr->cb_softstate_ptr == soft_ptr && - cbe_ptr->cb_fru_id == fru_id) { - if (cbe_ptr == scsb_cb_table) - scsb_cb_table = cbe_ptr->cb_next; - else - prev_ptr->cb_next = cbe_ptr->cb_next; - kmem_free(cbe_ptr, sizeof (struct scsb_cb_entry)); -#ifdef DEBUG - scsb_cb_count--; -#endif - return; - } - prev_ptr = cbe_ptr; - } while ((cbe_ptr = cbe_ptr->cb_next) != NULL); -} - -/* - * global function for interested FRU drivers to call to check - * FRU presence status. - */ -scsb_fru_status_t -scsb_fru_status(uchar_t fru_id) -{ - fru_info_t *fru_ptr; - - fru_ptr = find_fru_info(fru_id); - if (scsb_debug & 0x00800001) { - cmn_err(CE_NOTE, "scsb_fru_status(0x%x): status=0x%x", - fru_id, (fru_ptr == (fru_info_t *)NULL) ? 0xff : - (int)fru_ptr->fru_status); - } - if (fru_ptr == (fru_info_t *)NULL) - return (FRU_NOT_AVAILABLE); - return (fru_ptr->fru_status); -} - -/* - * Global function for the other interruptible FRU device sharing the - * same interrupt line to register the interrupt handler with scsb. - * This enables all the handlers to be called whenever the interrupt - * line is asserted by anyone shaing the interrupt line. - */ - -/* - * The interrupt handler table is currently a linked list. probably a - * hash table will be more efficient. Usage of these facilities can - * happen even before scsb is attached, so do not depend on scsb - * structure being present. - */ -struct fru_intr_entry { - void *softstate_ptr; - int (*fru_intr_handler)(void *); - fru_id_t fru_id; - struct fru_intr_entry *fru_intr_next; -} *fru_intr_table = NULL; - -int -scsb_intr_register(int (*intr_handler)(void *), void * soft_ptr, - fru_id_t fru_id) -{ - struct fru_intr_entry *intr_table_entry; - intr_table_entry = (struct fru_intr_entry *) - kmem_zalloc(sizeof (struct fru_intr_entry), KM_SLEEP); - - if (intr_table_entry == NULL) { - return (DDI_FAILURE); - } - - if (intr_handler == NULL || soft_ptr == NULL || fru_id == 0) { - kmem_free(intr_table_entry, sizeof (struct fru_intr_entry)); - return (DDI_FAILURE); - } - - intr_table_entry->softstate_ptr = soft_ptr; - intr_table_entry->fru_intr_handler = intr_handler; - intr_table_entry->fru_id = fru_id; - intr_table_entry->fru_intr_next = fru_intr_table; - fru_intr_table = intr_table_entry; - - return (DDI_SUCCESS); -} - -/* - * Removed interrupt_handler of fru from interrupt call chain - */ -void -scsb_intr_unregister(fru_id_t fru_id) -{ - struct fru_intr_entry *intr_entry = fru_intr_table, - *prev_entry = intr_entry; - - if (fru_id == 0) { - return; - } - - do { - if (intr_entry->fru_id == fru_id) { - /* found a match, remove entry */ - if (intr_entry == fru_intr_table) - fru_intr_table = intr_entry->fru_intr_next; - else - prev_entry->fru_intr_next = - intr_entry->fru_intr_next; - - kmem_free(intr_entry, - sizeof (struct fru_intr_entry)); - return; - } - prev_entry = intr_entry; - - } while ((intr_entry = intr_entry->fru_intr_next) != NULL); -} - -/* - * Invoke all the registered interrupt handlers, whenever scsb_intr - * is called. This function will go through the list of entries - * in the fru interrupt table and invoke each function. Returns - * whether interrupt is claimed or unclaimed. - */ -static int -scsb_invoke_intr_chain() -{ - int retval = DDI_INTR_UNCLAIMED; - struct fru_intr_entry *intr_entry = fru_intr_table; - - while (intr_entry != NULL) { - retval = (*intr_entry-> - fru_intr_handler)(intr_entry->softstate_ptr); - if (retval == DDI_INTR_CLAIMED) { - return (retval); - } - - intr_entry = intr_entry->fru_intr_next; - } - - return (retval); -} - - -/* - * The scsb_ioc_rdwr_t is similar enough to an i2c_transfer_t that we can - * translate the structures and use the i2c_transfer() service. - */ -static void -sm_ioc_rdwr(queue_t *q, mblk_t *mp, int op) -{ - scsb_state_t *scsb = (scsb_state_t *)q->q_ptr; - struct iocblk *iocp = (struct iocblk *)mp->b_rptr; - scsb_ioc_rdwr_t *iocrdwrp; - int len, error; - uchar_t *uc, reg; - - if (scsb_debug & 0x0040) - cmn_err(CE_CONT, "sm_ioc_rdwr[%d]:", scsb->scsb_instance); - iocrdwrp = (scsb_ioc_rdwr_t *)mp->b_cont->b_rptr; - if (op == I2C_WR) { - len = iocrdwrp->ioc_wlen; - uc = iocrdwrp->ioc_wbuf; - } else { - len = iocrdwrp->ioc_rlen; - uc = iocrdwrp->ioc_rbuf; - } - /* - * Check SCB register index boundries and requested len of read/write - */ - reg = iocrdwrp->ioc_regindex; - if (reg < SCSB_REG_ADDR_START || (reg + len) > - (SCSB_REG_ADDR_START + SCTRL_TOTAL_NUMREGS)) - error = EINVAL; - else - error = scsb_rdwr_register(scsb, op, reg, len, uc, 1); - if (error) { - if (scsb_debug & 0x0042) - cmn_err(CE_WARN, - "sm_ioc_rdwr: rdwr_register failure: %d", error); - mp->b_datap->db_type = M_IOCNAK; - } else - mp->b_datap->db_type = M_IOCACK; - iocp->ioc_error = error; - qreply(q, mp); -} - -/* - * names for (scsb_utype_t) FRU types - */ -static char *led_name[SCSB_LED_TYPES] = { "NOK", "OK" }; -static char *unit_type_name[SCSB_UNIT_TYPES] = { - "SLOT", "PDU", "POWER SUPPLY", "DISK", "FAN", "ALARM", - "SCB", "SSB", "CFTM", "CRTM", "PRTM" -}; - -/* - * Discover the register and bit-offset for LEDs and Reset registers, - * according to unit_type, unit_number, and led_type. - */ -static int -scsb_get_led_regnum(scsb_state_t *scsb, - scsb_uinfo_t *suip, - uchar_t *regptr, - int *unitptr, - scsb_led_t led_type) -{ - int code, base, error; - - /* OK here means presence (OK) LEDs */ - if (led_type == OK) - base = (SCTRL_LED_OK_BASE); - else - base = (SCTRL_LED_NOK_BASE); - error = 0; - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "get_led_regnum: suip <%x, %x, %x, %x>\n", - suip->unit_type, suip->unit_number, - led_type, suip->unit_state); - } - /* - * It was requested that the scsb driver allow accesses to SCB device - * registers for FRUs that cannot be present. - * So except for SLOTs, if the unit_number check fails, we now - * just log a message, but ONLY if scsb_debug error messages are - * enabled. - */ - switch (suip->unit_type) { - case SLOT: - if (suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_SLOTS : MC_MAX_SLOTS)) { - error = EINVAL; - break; - } - code = FRU_UNIT_TO_EVCODE(SLOT, suip->unit_number); - break; - - case PDU: - if (suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_PDU : MC_MAX_PDU)) { - if (scsb_debug & 0x0002) { - cmn_err(CE_WARN, - "get_led_regnum: unit number %d " - "is out of range", suip->unit_number); - } - error = EINVAL; - break; - } - code = FRU_UNIT_TO_EVCODE(PDU, suip->unit_number); - break; - - case PS: - if ((suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_PS : MC_MAX_PS))) { - if (scsb_debug & 0x0002) { - cmn_err(CE_WARN, - "get_led_regnum: unit number %d " - "is out of range", suip->unit_number); - } - error = EINVAL; - break; - } - code = FRU_UNIT_TO_EVCODE(PS, suip->unit_number); - break; - - case DISK: - if ((suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_DISK : MC_MAX_DISK))) { - if (scsb_debug & 0x0002) { - cmn_err(CE_WARN, - "get_led_regnum: unit number %d " - "is out of range", suip->unit_number); - } - if (!(scsb_debug & 0x20000000)) { - error = EINVAL; - break; - } - } - code = FRU_UNIT_TO_EVCODE(DISK, suip->unit_number); - break; - - case FAN: - if (suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_FAN : MC_MAX_FAN)) { - if (scsb_debug & 0x0002) { - cmn_err(CE_WARN, - "get_led_regnum: unit number %d " - "is out of range", suip->unit_number); - } - error = EINVAL; - break; - } - code = FRU_UNIT_TO_EVCODE(FAN, suip->unit_number); - break; - - case CFTM: - if (suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_CFTM : MC_MAX_CFTM)) { - if (scsb_debug & 0x0002) { - cmn_err(CE_WARN, - "get_led_regnum: unit number %d " - "is out of range", suip->unit_number); - } - error = EINVAL; - break; - } - code = FRU_UNIT_TO_EVCODE(CFTM, suip->unit_number); - break; - - case SCB: - if (suip->unit_number < 1 || suip->unit_number > - ((scsb->scsb_state & SCSB_IS_TONGA) ? - TG_MAX_SCB : MC_MAX_SCB)) { - if (scsb_debug & 0x0002) { - cmn_err(CE_WARN, - "get_led_regnum: unit number %d " - "is out of range", suip->unit_number); - } - error = EINVAL; - break; - } - code = FRU_UNIT_TO_EVCODE(SCB, suip->unit_number); - break; - - case ALARM: - error = EINVAL; - break; - - default: - if (scsb_debug & 0x0102) { - cmn_err(CE_WARN, - "scsb_get_led_regnum(): unknown unit type %d", - suip->unit_type); - } - error = EINVAL; - break; - } - if (!error) { - *unitptr = FRU_OFFSET(code, base); - *regptr = FRU_REG_ADDR(code, base); - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "get_led_regnum: unitptr=%x, " - "regptr=%x, code = %x\n", - *unitptr, *regptr, code); - } - } - return (error); -} - -/* - * P1.0 and P1.5 - * Map 1.0 Tonga Slot Numbers: SCB to user interface and back. - * User interface means positional slot numbers, as on P1.0 SSB, - * which are used by hpcsvc/hsc and kstat/ioctl interfaces. - */ - -/* HSC slotnum (Positional SLotnum) to SCB CFG bit-offset */ -static int psl2sco[TG_MAX_SLOTS + 1] = { -1 }; - -/* - * MAP Positional (HSC) slot number to SCB CFG register bit-offset - */ -static int -tonga_pslotnum_to_cfgbit(scsb_state_t *scsb, int sln) -{ - int base = SCTRL_SYSCFG_BASE; - if (!(scsb->scsb_state & SCSB_IS_TONGA)) { - return (sln); - } - if (sln < 1 || sln > TG_MAX_SLOTS) { - return (sln); - } - /* - * Should move this to _init(), but for now, - * check for initialized table - */ - if (psl2sco[0]) { - psl2sco[0] = 0; - psl2sco[1] = FRU_OFFSET(SCTRL_EVENT_SLOT5, base); - psl2sco[2] = FRU_OFFSET(SCTRL_EVENT_SLOT2, base); - psl2sco[3] = FRU_OFFSET(SCTRL_EVENT_SLOT1, base); - psl2sco[4] = FRU_OFFSET(SCTRL_EVENT_SLOT3, base); - psl2sco[5] = FRU_OFFSET(SCTRL_EVENT_SLOT4, base); - } -#ifdef DEBUG - if (scsb_debug & 0x10000000) { - cmn_err(CE_NOTE, "tonga_pslotnum_to_cfgbit: old/new: %d/%d", - sln, psl2sco[sln]); - } -#endif - return (psl2sco[sln]); -} - -/* positional slotnum to SCB slotnum */ -static int psl2ssl[6] = { - 0, 5, 2, 1, 3, 4 -}; - -/* SCB slotnum to positional slotnum */ -static int ssl2psl[6] = { - 0, 3, 2, 4, 5, 1 -}; - -/* - * P1.0 and P1.5 - * HSC Slot numbers (physical positions or positional slotnum) - * to - * SCB slot numbers (reset,present,healthy) - * - * These requests come mainly from application interface and - * HSC using the scsb_uinfo_t structure. - */ -static void -tonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip) -{ - if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state & - (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) { - return; - } - if (suip->unit_number < 1 || suip->unit_number > TG_MAX_SLOTS) { - return; - } -#ifdef DEBUG - if (scsb_debug & 0x10000000) { - cmn_err(CE_NOTE, "tonga_slotnum_check: old/new: %d/%d", - suip->unit_number, psl2ssl[suip->unit_number]); - } -#endif - suip->unit_number = psl2ssl[suip->unit_number]; -} - -/* - * P1.0 and P1.5 - */ -static int -tonga_psl_to_ssl(scsb_state_t *scsb, int slotnum) -{ - if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state & - (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) { - return (slotnum); - } - if (slotnum < 1 || slotnum > TG_MAX_SLOTS) { - return (slotnum); - } -#ifdef DEBUG - if (scsb_debug & 0x10000000) { - cmn_err(CE_NOTE, "tonga_psl_to_ssl: old/new: %d/%d", - slotnum, psl2ssl[slotnum]); - } -#endif - return (psl2ssl[slotnum]); -} - -/* - * P1.0 and P1.5 - */ -static int -tonga_ssl_to_psl(scsb_state_t *scsb, int slotnum) -{ - if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state & - (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) { - return (slotnum); - } - if (slotnum < 1 || slotnum > TG_MAX_SLOTS) { - return (slotnum); - } -#ifdef DEBUG - if (scsb_debug & 0x10000000) { - cmn_err(CE_NOTE, "tonga_ssl_to_psl: old/new: %d/%d", - slotnum, ssl2psl[slotnum]); - } -#endif - return (ssl2psl[slotnum]); -} -/* - * tonga_slotnum_led_shift: this function remaps slot bits ONLY for Slots 1-5 - * and ONLY for the register sets in bit-offset groups 1,2: - * LEDs, Confg/Status, Reset, BrdHlthy - * - * IN bits: SCB slot numbers (led,reset,present,healthy) - * to - * OUT bits: HSC Slot numbers (positional slot numbers as marked on the SSB) - */ -static uchar_t -tonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data) -{ - int i; - uchar_t mask, new_data = 0; -#ifdef DEBUG - uchar_t old_data = data; -#endif - if (!(scsb->scsb_state & SCSB_IS_TONGA)) { - return (data); - } - /* - * P1.0 and P1.5 slot 1-5 offsets are the same - */ - for (i = 1; i <= TG_MAX_SLOTS; ++i) { - mask = 1 << (i - 1); - switch (i) { - case 1: /* map to slot 3 */ - new_data |= (data & mask) << 2; - data &= ~(mask); - break; - case 2: /* map to slot 2 */ - new_data |= (data & mask); - data &= ~(mask); - break; - case 3: /* map to slot 4 */ - case 4: /* map to slot 5 */ - new_data |= (data & mask) << 1; - data &= ~(mask); - break; - case 5: /* map to slot 1 */ - new_data |= (data & mask) >> 4; - data &= ~(mask); - break; - } - } - new_data |= data; /* set any remaining bits */ -#ifdef DEBUG - if (scsb_debug & 0x10000000) { - cmn_err(CE_NOTE, "tonga_slotnum_led_shift: old/new: 0x%x/0x%x", - old_data, new_data); - } -#endif - return (new_data); -} - -/* - * P1.0 and P1.5 - */ -int -scsb_led_get(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type) -{ - int error; - int unit_number; - uchar_t reg; - int index; - - /* - * Allow access to shadow registers even though SCB is removed - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (EAGAIN); - * } - */ - if (suip == NULL) { - return (EFAULT); - } - if (led_type == NOUSE) { - led_type = suip->led_type; - } - if (led_type != OK && led_type != NOK) { - cmn_err(CE_NOTE, "scsb_led_get(%d): unknown led type %x", - scsb->scsb_instance, led_type); - return (EINVAL); - } - error = 0; - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "scsb_led_get: %s %s %d", - led_name[led_type], unit_type_name[suip->unit_type], - suip->unit_number); - } - /* - * Map to Tonga Slot Number, if NOT P1.0 SCB - * P1.0 SSB workaround - */ - if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) { - tonga_slotnum_check(scsb, suip); - } - /* discover the register and index we need to operate on */ - if ((error = scsb_get_led_regnum(scsb, suip, ®, &unit_number, - led_type)) == 0) { - index = SCSB_REG_INDEX(reg); - mutex_enter(&scsb->scsb_mutex); - if (scsb->scsb_data_reg[index] & (1 << unit_number)) { - suip->unit_state = ON; - if (led_type == OK) { - int code = FRU_UNIT_TO_EVCODE(suip->unit_type, - suip->unit_number); - reg = FRU_REG_ADDR(code, SCTRL_BLINK_OK_BASE); - index = SCSB_REG_INDEX(reg); - if (scsb->scsb_data_reg[index] & - (1 << unit_number)) - suip->unit_state = BLINK; - } - } else { - suip->unit_state = OFF; - } - mutex_exit(&scsb->scsb_mutex); - } - return (error); -} - -int -scsb_led_set(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type) -{ - int error; - int unit_number; - uchar_t reg; - int code, index; - - /* we should really allow led state changes while frozen... */ - if (scsb->scsb_state & SCSB_FROZEN) - return (EAGAIN); - - if (suip == NULL) { - return (EFAULT); - } - - /* - * Sanity check, make sure we got plausible values for set command. - * Also check for application only control of slot leds using NOUSE - * interface - */ - if (led_type == NOUSE) { - led_type = suip->led_type; - } else if (suip->unit_type == SLOT && - scsb->scsb_state & SCSB_APP_SLOTLED_CTRL && - !(scsb->scsb_state & - (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) { - /* - * kernel modules using this interface need to think they are - * succeeding, so we won't return an error for this - * application configuration - */ - return (0); - } - if (led_type != OK && led_type != NOK) { - return (EINVAL); - } - if (suip->unit_state != OFF && suip->unit_state != ON && - suip->unit_state != BLINK) { - return (EINVAL); - } - if (suip->unit_state == BLINK) { - if (led_type != OK) - return (EINVAL); - if (suip->unit_type != SLOT && scsb->scsb_state & - (SCSB_P06_PROM | SCSB_P10_PROM)) - return (EINVAL); - } - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, - "scsb_led_set: led %s, type %s, unit %d, state %s", - led_name[led_type], - unit_type_name[suip->unit_type], suip->unit_number, - suip->unit_state == ON ? "ON": - suip->unit_state == OFF ? "OFF": "BLINK"); - } - /* - * Map to Tonga Slot Number, if NOT P1.0 SCB - * P1.0 SSB workaround - */ - if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) { - tonga_slotnum_check(scsb, suip); - } - /* - * discover the register and index we need to access - */ - if ((error = scsb_get_led_regnum(scsb, suip, ®, &unit_number, - led_type)) == 0) { - index = SCSB_REG_INDEX(reg); - mutex_enter(&scsb->scsb_mutex); - if (suip->unit_state == ON || suip->unit_state == BLINK) - scsb->scsb_data_reg[index] |= (1 << unit_number); - else - scsb->scsb_data_reg[index] &= ~(1 << unit_number); - - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "Writing %x to Reg %x", - scsb->scsb_data_reg[index], reg); - } - error = scsb_rdwr_register(scsb, I2C_WR, reg, 1, - &scsb->scsb_data_reg[index], 1); - if (error) { - cmn_err(CE_WARN, "%s#%d: Could not Update %s LEDs.", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev), - led_name[led_type]); - goto ledset_done; - } - if (led_type != OK || - (IS_SCB_P10 && suip->unit_type != SLOT) || - suip->unit_type == ALARM || - suip->unit_type == SSB || - suip->unit_type == CRTM || - suip->unit_type == PRTM) { - goto ledset_done; - } - code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number); - reg = FRU_REG_ADDR(code, SCTRL_BLINK_OK_BASE); - index = SCSB_REG_INDEX(reg); - if (suip->unit_state == BLINK) - scsb->scsb_data_reg[index] |= (1 << unit_number); - else - scsb->scsb_data_reg[index] &= ~(1 << unit_number); - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "Writing %x to Reg %x", - scsb->scsb_data_reg[index], reg); - } - error = scsb_rdwr_register(scsb, I2C_WR, reg, 1, - &scsb->scsb_data_reg[index], 1); - if (error) { - cmn_err(CE_WARN, "%s#%d: Could not Blink %s LEDs.", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev), - led_name[led_type]); - } -ledset_done: - mutex_exit(&scsb->scsb_mutex); - } - return (error); -} - -struct ps_auto_on { - scsb_state_t *scsb; - scsb_utype_t utype; - scsb_unum_t unit; -}; - -static struct ps_auto_on pao; - -static void -scsb_ps_auto_on(void *arg) -{ - struct ps_auto_on *ppao = (struct ps_auto_on *)arg; - uchar_t rmask = 0; - uchar_t ondata, sysreg; - int tmp, bit_index; - /* - * Turn on the PSU. - * Notice: not checking Power Supply unit number - */ - bit_index = SCTRL_SYS_PS_ON_BASE + (ppao->unit - 1); - ondata = 1 << SYS_OFFSET(bit_index); - tmp = SYS_REG_INDEX(bit_index, SCTRL_SYS_CMD_BASE); - sysreg = SCSB_REG_ADDR(tmp); - if (scsb_write_mask(ppao->scsb, sysreg, rmask, ondata, (uchar_t)0)) { - cmn_err(CE_WARN, "scsb%d: " "I2C TRANSFER Failed", - ppao->scsb->scsb_instance); - } - ppao->scsb->scsb_btid = 0; -} - -/* - * called with mutex held from - * scsb_attach() with int_fru_ptr == NULL - * scsb_intr() with int_fru_ptr == info for FRU that caused interrupt - */ -static int -scsb_set_scfg_pres_leds(scsb_state_t *scsb, fru_info_t *int_fru_ptr) -{ - int i, error = 0; - int cfg_idx, led_idx, blink_idx, lid, bid; - int cfg_bit, led_bit; - uchar_t *puc, reg, led_reg, led_data[SCSB_LEDDATA_REGISTERS]; - uchar_t blink_bit, blink_reg, blink[SCSB_LEDDATA_REGISTERS]; - uchar_t update_reg = 0; - scsb_utype_t fru_type; - fru_info_t *fru_ptr; - - if (scsb->scsb_state & SCSB_FROZEN && - !(scsb->scsb_state & SCSB_IN_INTR)) { - return (EAGAIN); - } - for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) { - led_data[i] = 0; - blink[i] = 0; - } - led_reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE); - reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE); - lid = SCSB_REG_INDEX(led_reg); /* the LED Index Delta */ - bid = SCSB_REG_INDEX(reg); /* the Blink Index Delta */ - blink_reg = 0; - if (int_fru_ptr != NULL) { - update_reg = int_fru_ptr->i2c_info->ledata_reg; - } - for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) { - int is_present; - fru_ptr = mct_system_info.fru_info_list[fru_type]; - for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) { - is_present = 0; - if (fru_type == SLOT && (scsb->scsb_state & - SCSB_APP_SLOTLED_CTRL)) - break; - if (fru_ptr->i2c_info == NULL) - continue; - if ((led_reg = fru_ptr->i2c_info->ledata_reg) == 0) { - /* - * No LED exceptions: SSB,CRTM,PRTM - */ - continue; - } - if (update_reg && update_reg != led_reg) - continue; - led_idx = SCSB_REG_INDEX(led_reg) - lid; - led_bit = fru_ptr->i2c_info->ledata_bit; - if ((reg = fru_ptr->i2c_info->syscfg_reg) == 0) { - if (fru_type != SCB) - continue; - /* - * exception: SCB - */ - if (scsb->scsb_state & SCSB_SCB_PRESENT) { - led_data[led_idx] |= 1 << led_bit; - is_present = 1; - } else { - led_data[led_idx] &= ~(1 << led_bit); - } - if (IS_SCB_P10) - continue; - } else { - cfg_idx = SCSB_REG_INDEX(reg); - cfg_bit = fru_ptr->i2c_info->syscfg_bit; - if (scsb->scsb_data_reg[cfg_idx] & - (1 << cfg_bit)) { - is_present = 1; - } - } - if (is_present) { - /* - * If the FRU is a Power Supply, AND - * the call is from scsb_attach() OR - * from scsb_intr() and FRUs match, - * turn it on. - */ - if (fru_type == PS && (int_fru_ptr == NULL || - (int_fru_ptr == fru_ptr))) { - pao.scsb = scsb; - pao.utype = fru_type; - pao.unit = fru_ptr->fru_unit; -#ifdef PS_ON_DELAY - /* - * HW recommended not implementing - * this delay for now. - * The code is tested on PSUs: - * -06 - * -07 rev 2 - * -08 plus - */ - if (int_fru_ptr) { - /* - * Hot insertion, so give it - * the 3 seconds it needs to - * become stable - */ - if (!scsb->scsb_btid) - scsb->scsb_btid = - timeout( - scsb_ps_auto_on, - &pao, (4 * - drv_usectohz( - 1000000))); - } else -#endif /* PS_ON_DELAY */ - scsb_ps_auto_on((void *)&pao); - } - /* - * Special SLOT handling. - * Make sure the OK LED is on for the CPU Slot - * and for the FTC (CFTM) Slot for MonteCarlo. - * Both will report as FRU_PRESENT. - */ - if (fru_type != SLOT || (fru_type == SLOT && - (fru_ptr->fru_type == - (scsb_utype_t)OC_CPU || - fru_ptr->fru_type == - (scsb_utype_t)OC_CTC))) { - /* - * Set OK (green) LED register bit - */ - led_data[led_idx] |= 1 << led_bit; - } - if (IS_SCB_P10) - continue; - /* - * Turn off BLINK register bit. - * If single register update, then save the - * corresponding blink register in blink_reg. - */ - reg = fru_ptr->i2c_info->blink_reg; - if (!reg) - continue; - blink_bit = fru_ptr->i2c_info->blink_bit; - blink_idx = SCSB_REG_INDEX(reg) - bid; - blink[blink_idx] |= 1 << blink_bit; - if (update_reg && update_reg == led_reg) - blink_reg = reg; - } - } - } - if (update_reg) { - reg = update_reg; - i = SCSB_REG_INDEX(reg); - puc = &led_data[i - lid]; - i = 1; - } else { - reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE); - puc = led_data; - i = SCTRL_LED_OK_NUMREGS; - } - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "scsb_set_scfg_pres(): writing %d bytes " - "to 0x%x", i, reg); - } - if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, i, puc, 1)) != 0) { - if (scsb_debug & 0x0102) - cmn_err(CE_NOTE, "scsb_set_scfg_pres(): " - "I2C write to 0x%x failed", reg); - error = EIO; - } else { - /* - * Now see which BLINK bits need to be turned off for the - * corresponding OK LED bits. - */ - reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE); - for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i, ++reg) { - if (blink_reg && blink_reg != reg) - continue; - if (!blink[i]) { - continue; - } - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "scsb_set_scfg_pres(): turn " - "OFF Blink bits 0x%x in 0x%x", - blink[i], reg); - } - if (scsb_write_mask(scsb, reg, 0, 0, blink[i])) { - if (scsb_debug & 0x0102) - cmn_err(CE_NOTE, - "scsb_set_scfg_pres(): " - "Write to 0x%x failed", reg); - error = EIO; - break; - } - } - } - return (error); -} - -static int -scsb_check_config_status(scsb_state_t *scsb) -{ - int error; - uchar_t reg; - int index, p06; - - if (scsb_debug & 0x0201) { - cmn_err(CE_NOTE, "scsb_check_config_status:"); - } - /* - * Base of register set - */ - reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE); - index = SCSB_REG_INDEX(reg); - /* - * SCB P0.6 workaround: read registers twice, use 2nd value set - */ - mutex_enter(&scsb->scsb_mutex); - p06 = 2; - do { - if (error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, - SCTRL_CFG_NUMREGS, &scsb->scsb_data_reg[index], 1)) { - break; - } - if (p06 == 1) { - if (scsb_debug & 0x0200) - cmn_err(CE_NOTE, - "scsb_check_config_status: P0.6 workaround"); - } - /* - * If not P0.6 PROM, just break here - */ - if (!(scsb->scsb_state & SCSB_P06_PROM)) - break; - } while (--p06); - mutex_exit(&scsb->scsb_mutex); - - if (error == 0) { - if (!(scsb->scsb_state & SCSB_SCB_PRESENT)) - scsb->scsb_state |= SCSB_SCB_PRESENT; - if (scsb_fru_op(scsb, SSB, 1, SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL)) - scsb->scsb_state |= SCSB_SSB_PRESENT; - else - scsb->scsb_state &= ~SCSB_SSB_PRESENT; - } - return (error); -} - -static void -scsb_set_topology(scsb_state_t *scsb) -{ - int i, t, index, unit, is_tonga = 0; - int alarm_slot_num, cpu_slot_num, ctc_slot_num; - fru_info_t *fru_ptr, *last_ptr, *acslot_ptr, *ctcslot_ptr; - uchar_t syscfg, led_reg, blink_reg, t_uchar; - uchar_t bit_num, led_bit, blink_bit; - int pad = 0; - - /* - * Get the presence status from the SysConfigStatus shadow registers - * in scsb->scsb_data_reg[] - */ - /* Mid Plane */ - i = SYS_REG_INDEX(SCTRL_CFG_MPID0, SCTRL_SYSCFG_BASE); - t_uchar = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(t_uchar); - mct_system_info.mid_plane.fru_type = MIDPLANE; - mct_system_info.mid_plane.fru_version = (fru_version_t)0; - t = SYS_OFFSET(SCTRL_CFG_MPID0); - mct_system_info.mid_plane.fru_id = (int)((scsb->scsb_data_reg[index] & - (SCTRL_MPID_MASK << t)) >> t); - switch (mct_system_info.mid_plane.fru_id) { - case SCTRL_MPID_HALF: /* Monte Carlo */ - if (scsb_debug & 0x00100005) - cmn_err(CE_NOTE, "scsb_set_topology: Monte Carlo"); - cpu_slot_num = SC_MC_CPU_SLOT; - ctc_slot_num = SC_MC_CTC_SLOT; - alarm_slot_num = scsb->ac_slotnum = SC_MC_AC_SLOT; - mct_system_info.max_units[SLOT] = MC_MAX_SLOTS; - mct_system_info.max_units[ALARM] = MC_MAX_AC; - mct_system_info.max_units[DISK] = MC_MAX_DISK; - mct_system_info.max_units[FAN] = MC_MAX_FAN; - mct_system_info.max_units[PS] = MC_MAX_PS; - mct_system_info.max_units[PDU] = MC_MAX_PDU; - mct_system_info.max_units[SCB] = MC_MAX_SCB; - mct_system_info.max_units[SSB] = MC_MAX_SCB; - mct_system_info.max_units[CFTM] = MC_MAX_CFTM; - mct_system_info.max_units[CRTM] = MC_MAX_CRTM; - mct_system_info.max_units[PRTM] = MC_MAX_PRTM; - break; - case SCTRL_MPID_QUARTER_NODSK: /* Tonga w/o disk */ - case SCTRL_MPID_QUARTER: /* Tonga w/ disk */ - scsb->scsb_state |= SCSB_IS_TONGA; - is_tonga = 1; - ctc_slot_num = -1; - ctcslot_ptr = NULL; - if (scsb_debug & 0x00100005) - cmn_err(CE_NOTE, "scsb_set_topology: Tonga%s", - mct_system_info.mid_plane.fru_id == - SCTRL_MPID_QUARTER_NODSK ? - ", no disk" : " with disk"); - cpu_slot_num = SC_TG_CPU_SLOT; - alarm_slot_num = scsb->ac_slotnum = SC_TG_AC_SLOT; - mct_system_info.max_units[SLOT] = TG_MAX_SLOTS; - mct_system_info.max_units[ALARM] = TG_MAX_AC; - mct_system_info.max_units[DISK] = TG_MAX_DISK; - mct_system_info.max_units[FAN] = TG_MAX_FAN; - mct_system_info.max_units[PS] = TG_MAX_PS; - mct_system_info.max_units[PDU] = TG_MAX_PDU; - mct_system_info.max_units[SCB] = TG_MAX_SCB; - mct_system_info.max_units[SSB] = TG_MAX_SCB; - mct_system_info.max_units[CFTM] = TG_MAX_CFTM; - mct_system_info.max_units[CRTM] = TG_MAX_CRTM; - mct_system_info.max_units[PRTM] = TG_MAX_PRTM; - break; - default: - cmn_err(CE_WARN, "%s#%d: Unknown MidPlane Id %x", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev), - mct_system_info.mid_plane.fru_id); - if (scsb_debug & 0x00100005) - cmn_err(CE_NOTE, "scsb_set_topology: 0x%x: unknown!", - mct_system_info.mid_plane.fru_id); - return; - } - /* - * cPCI Slots - * - * NOTE: The Tonga slot fru_unit needs to get mapped to the logical - * slot number in slot_table[]. The field is not in the slot_table - * at least until we know the format of the OBP slot table for the FCS - * release. - */ - mct_system_info.fru_info_list[SLOT] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[SLOT] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[SLOT]; - for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) { - int iunit; - if (unit == cpu_slot_num) { - fru_ptr->fru_type = (scsb_utype_t)OC_CPU; - } else if (unit == ctc_slot_num) { - /* fru_ptr saved for Transition Card Presence check */ - ctcslot_ptr = fru_ptr; - fru_ptr->fru_type = (scsb_utype_t)OC_UNKN; - } else if (unit == alarm_slot_num) { - /* fru_ptr saved for Alarm Card Presence check below */ - acslot_ptr = fru_ptr; - fru_ptr->fru_type = (scsb_utype_t)OC_UNKN; - } else { - fru_ptr->fru_type = (scsb_utype_t)OC_UNKN; - } - /* - * Get the slot event code (t), then use it to get the - * slot bit-offsets for LED, BLINK, and SYSCFG registers. - * On a P1.5 Tonga, the internal slot number must be used to - * find the event code. - * The P1.0 Tonga does not get mapped due to a SSB difference. - */ - if (IS_SCB_P15) { - iunit = tonga_psl_to_ssl(scsb, unit); - t = FRU_UNIT_TO_EVCODE(SLOT, iunit); - } else { - t = FRU_UNIT_TO_EVCODE(SLOT, unit); - } - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - blink_reg = FRU_REG_ADDR(t, SCTRL_BLINK_OK_BASE); - if (is_tonga && unit <= TG_MAX_SLOTS) { - bit_num = tonga_pslotnum_to_cfgbit(scsb, unit); - } else { - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - } - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - syscfg = FRU_REG_ADDR(t, SCTRL_SYSCFG_BASE); - index = SCSB_REG_INDEX(syscfg); - led_reg = FRU_REG_ADDR(t, SCTRL_LED_OK_BASE); - /* - * check and set presence status - */ - if (scsb->scsb_state & SCSB_P06_PROM) { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } else if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index( - FRU_UNIT_TO_EVCODE(SLOT, unit))]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - last_ptr = fru_ptr; - fru_ptr++; - last_ptr->next = fru_ptr; - } - last_ptr->next = (fru_info_t *)NULL; - /* - * PDU - */ - mct_system_info.fru_info_list[PDU] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[PDU] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[PDU]; - for (unit = 1; unit <= mct_system_info.max_units[PDU]; ++unit) { - fru_ptr->fru_type = PDU; - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(PDU, unit); - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - if (IS_SCB_P15) { - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE); - blink_reg = SCSB_REG_ADDR(i); - } else { - blink_bit = 0; - blink_reg = 0; - } - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE); - led_reg = SCSB_REG_ADDR(i); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - fru_ptr->fru_version = (fru_version_t)0; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - fru_ptr->fru_version = (fru_version_t)0; - } - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - last_ptr = fru_ptr; - fru_ptr++; - last_ptr->next = fru_ptr; - } - last_ptr->next = (fru_info_t *)NULL; - /* - * Power Supplies - */ - mct_system_info.fru_info_list[PS] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[PS] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[PS]; - for (unit = 1; unit <= mct_system_info.max_units[PS]; ++unit) { - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(PS, unit); - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - if (IS_SCB_P15) { - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE); - blink_reg = SCSB_REG_ADDR(i); - } else { - blink_bit = 0; - blink_reg = 0; - } - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE); - led_reg = SCSB_REG_ADDR(i); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = PS; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - last_ptr = fru_ptr; - fru_ptr++; - last_ptr->next = fru_ptr; - } - last_ptr->next = (fru_info_t *)NULL; - /* - * SCSI Disks and removable media - */ - mct_system_info.fru_info_list[DISK] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[DISK] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[DISK]; - for (unit = 1; unit <= mct_system_info.max_units[DISK]; ++unit) { - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(DISK, unit); - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - if (IS_SCB_P15) { - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE); - blink_reg = SCSB_REG_ADDR(i); - } else { - blink_bit = 0; - blink_reg = 0; - } - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE); - led_reg = SCSB_REG_ADDR(i); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - fru_ptr->fru_version = (fru_version_t)0; - } else - fru_ptr->fru_status = FRU_NOT_PRESENT; - fru_ptr->fru_type = DISK; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - last_ptr = fru_ptr; - fru_ptr++; - last_ptr->next = fru_ptr; - } - last_ptr->next = (fru_info_t *)NULL; - /* - * Fan Trays - */ - mct_system_info.fru_info_list[FAN] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[FAN] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[FAN]; - for (unit = 1; unit <= mct_system_info.max_units[FAN]; ++unit) { - int bit_num; - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(FAN, unit); - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - if (IS_SCB_P15) { - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE); - blink_reg = SCSB_REG_ADDR(i); - } else { - blink_bit = 0; - blink_reg = 0; - } - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE); - led_reg = SCSB_REG_ADDR(i); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = FAN; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - last_ptr = fru_ptr; - fru_ptr++; - last_ptr->next = fru_ptr; - } - last_ptr->next = (fru_info_t *)NULL; - /* - * Alarm Cards - */ - mct_system_info.fru_info_list[ALARM] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[ALARM] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[ALARM]; - for (unit = 1; unit <= mct_system_info.max_units[ALARM]; ++unit) { - int bit_num; - - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for SYSCFG register - */ - t = FRU_UNIT_TO_EVCODE(ALARM, unit); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - if (acslot_ptr != NULL && acslot_ptr->fru_status == - FRU_PRESENT) { - acslot_ptr->fru_type = (scsb_utype_t)OC_AC; - /* - * acslot_ptr->fru_id = - * fru_id_table[event_to_index(t)]; - */ - } - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - - fru_ptr->fru_type = ALARM; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = 0; - fru_ptr->i2c_info->ledata_bit = 0; - fru_ptr->i2c_info->blink_reg = 0; - fru_ptr->i2c_info->blink_bit = 0; - last_ptr = fru_ptr; - fru_ptr++; - last_ptr->next = fru_ptr; - } - last_ptr->next = (fru_info_t *)NULL; - /* - * SCB - */ - mct_system_info.fru_info_list[SCB] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[SCB] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[SCB]; - unit = 1; - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offset for LED register - */ - t = FRU_UNIT_TO_EVCODE(SCB, unit); - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE); - led_reg = SCSB_REG_ADDR(i); - if (IS_SCB_P15) { - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE); - blink_reg = SCSB_REG_ADDR(i); - } else { - blink_bit = 0; - blink_reg = 0; - } - i = SYS_REG_INDEX(SCTRL_SCBID0, SCTRL_SCBID_BASE); - index = SCSB_REG_ADDR(i); - /* - * check and set presence status - */ - if (scsb->scsb_state & SCSB_SCB_PRESENT) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = SCB; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - /* get PROM_VERSION from shadow registers */ - if (scsb_rdwr_register(scsb, I2C_WR_RD, index, 1, &t_uchar, 1)) - fru_ptr->fru_version = (fru_version_t)0; - else - fru_ptr->fru_version = (fru_version_t)t_uchar; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = 0; - fru_ptr->i2c_info->syscfg_bit = 0; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - fru_ptr->next = (fru_info_t *)NULL; - /* - * SSB - */ - mct_system_info.fru_info_list[SSB] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[SSB] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[SSB]; - unit = 1; - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offset for SYSCFG register - */ - t = FRU_UNIT_TO_EVCODE(SSB, unit); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = SSB; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = 0; - fru_ptr->i2c_info->ledata_bit = 0; - fru_ptr->i2c_info->blink_reg = 0; - fru_ptr->i2c_info->blink_bit = 0; - fru_ptr->next = (fru_info_t *)NULL; - /* - * CFTM - */ - mct_system_info.fru_info_list[CFTM] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[CFTM] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[CFTM]; - unit = 1; - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(CFTM, unit); - led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - if (IS_SCB_P15) { - blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE); - i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE); - blink_reg = SCSB_REG_ADDR(i); - } else { - blink_bit = 0; - blink_reg = 0; - } - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE); - led_reg = SCSB_REG_ADDR(i); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - if (ctcslot_ptr != NULL && ctcslot_ptr->fru_status == - FRU_PRESENT) { - ctcslot_ptr->fru_type = (scsb_utype_t)OC_CTC; - scsb->scsb_hsc_state |= SCSB_HSC_CTC_PRES; - } - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = CFTM; - fru_ptr->fru_unit = (scsb_unum_t)1; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = led_reg; - fru_ptr->i2c_info->ledata_bit = led_bit; - fru_ptr->i2c_info->blink_reg = blink_reg; - fru_ptr->i2c_info->blink_bit = blink_bit; - fru_ptr->next = (fru_info_t *)NULL; - /* - * CRTM - */ - mct_system_info.fru_info_list[CRTM] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[CRTM] + pad), - KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[CRTM]; - unit = 1; - /* SCB15 */ - /* - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(CRTM, unit); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = CRTM; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = 0; - fru_ptr->i2c_info->ledata_bit = 0; - fru_ptr->i2c_info->blink_reg = 0; - fru_ptr->i2c_info->blink_bit = 0; - fru_ptr->next = (fru_info_t *)NULL; - /* - * PRTM - */ - mct_system_info.fru_info_list[PRTM] = (fru_info_t *) - kmem_zalloc(sizeof (fru_info_t) * - (mct_system_info.max_units[PRTM] + pad), KM_SLEEP); - fru_ptr = mct_system_info.fru_info_list[PRTM]; - unit = 1; - /* - * SCB15 - * get the FRU event code (t), then use it to get the - * FRU bit-offsets for LED and SYSCFG registers - */ - t = FRU_UNIT_TO_EVCODE(PRTM, unit); - bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE); - /* - * get the registers addresses and shadow register index for - * the SYSCFG register - */ - i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE); - syscfg = SCSB_REG_ADDR(i); - index = SCSB_REG_INDEX(syscfg); - /* - * check and set presence status - */ - if (scsb->scsb_data_reg[index] & (1 << bit_num)) { - fru_ptr->fru_status = FRU_PRESENT; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - } - fru_ptr->fru_type = PRTM; - fru_ptr->fru_unit = (scsb_unum_t)unit; - fru_ptr->fru_id = fru_id_table[event_to_index(t)]; - fru_ptr->fru_version = (fru_version_t)0; - fru_ptr->type_list = (fru_options_t *)NULL; - fru_ptr->i2c_info = (fru_i2c_info_t *) - kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP); - fru_ptr->i2c_info->syscfg_reg = syscfg; - fru_ptr->i2c_info->syscfg_bit = bit_num; - fru_ptr->i2c_info->ledata_reg = 0; - fru_ptr->i2c_info->ledata_bit = 0; - fru_ptr->i2c_info->blink_reg = 0; - fru_ptr->i2c_info->blink_bit = 0; - fru_ptr->next = (fru_info_t *)NULL; - - scsb->scsb_state |= SCSB_TOPOLOGY; -#ifdef DEBUG - mct_topology_dump(scsb, 0); -#endif -} - -/*ARGSUSED*/ -static void -scsb_free_topology(scsb_state_t *scsb) -{ - int i; - fru_info_t *fru_ptr; - - if (scsb_debug & 0x00100005) - cmn_err(CE_NOTE, "scsb_free_topology:"); - for (i = 0; i < SCSB_UNIT_TYPES; ++i) { - fru_ptr = mct_system_info.fru_info_list[i]; - while (fru_ptr != NULL) { - if (fru_ptr->i2c_info != (fru_i2c_info_t *)NULL) - kmem_free(fru_ptr->i2c_info, - sizeof (fru_i2c_info_t)); - fru_ptr = fru_ptr->next; - } - if ((fru_ptr = mct_system_info.fru_info_list[i]) != - (fru_info_t *)NULL) { - kmem_free(fru_ptr, sizeof (fru_info_t) * - mct_system_info.max_units[i]); - mct_system_info.fru_info_list[i] = (fru_info_t *)NULL; - } - } -} - -#ifdef DEBUG -static void -mct_topology_dump(scsb_state_t *scsb, int force) -{ - int i; - fru_info_t *fru_ptr; - - if (!force && !(scsb_debug & 0x00200000)) - return; - if (force && !(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) - return; - if (!(scsb->scsb_state & SCSB_TOPOLOGY)) { - cmn_err(CE_NOTE, "mct_topology_dump: Topology not set!"); - return; - } - for (i = 0; i < SCSB_UNIT_TYPES; ++i) { - fru_ptr = mct_system_info.fru_info_list[i]; - switch ((scsb_utype_t)i) { - case SLOT: - cmn_err(CE_NOTE, "MCT: Number of Slots: %d", - mct_system_info.max_units[SLOT]); - break; - case ALARM: - cmn_err(CE_NOTE, "MCT: MAX Number of Alarm Cards: %d", - mct_system_info.max_units[ALARM]); - break; - case DISK: - cmn_err(CE_NOTE, "MCT: MAX Number of SCSI Devices: %d", - mct_system_info.max_units[DISK]); - break; - case FAN: - cmn_err(CE_NOTE, "MCT: MAX Number of Fan Trays: %d", - mct_system_info.max_units[FAN]); - break; - case PDU: - cmn_err(CE_NOTE, "MCT: MAX Number of PDUs: %d", - mct_system_info.max_units[PDU]); - break; - case PS: - cmn_err(CE_NOTE, - "MCT: MAX Number of Power Supplies: %d", - mct_system_info.max_units[PS]); - break; - case SCB: - cmn_err(CE_NOTE, "MCT: MAX Number of SCBs: %d", - mct_system_info.max_units[SCB]); - break; - case SSB: - cmn_err(CE_NOTE, "MCT: MAX Number of SSBs: %d", - mct_system_info.max_units[SSB]); - break; - } - while (fru_ptr != NULL) { - if (fru_ptr->fru_status & FRU_PRESENT) { - cmn_err(CE_NOTE, - "MCT: type=%d, unit=%d, id=0x%x, " - "version=0x%x", - fru_ptr->fru_type, - fru_ptr->fru_unit, - fru_ptr->fru_id, - fru_ptr->fru_version); - } - fru_ptr = fru_ptr->next; - } - } -} - -/* - * Sends an event when the system controller board I2C errors - * exceed the threshold. - */ -static void -scsb_failing_event(scsb_state_t *scsb) -{ - uint32_t scsb_event_code = SCTRL_EVENT_SCB; - - add_event_code(scsb, scsb_event_code); - (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code, - "scsb_intr"); -} -#endif - -int -scsb_read_bhealthy(scsb_state_t *scsb) -{ - int error; - uchar_t reg; - int index; - - if (scsb_debug & 0x8001) { - cmn_err(CE_NOTE, "scsb_read_bhealthy()"); - } - reg = SCSB_REG_ADDR(SCTRL_BHLTHY_BASE); - index = SCSB_REG_INDEX(reg); - error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, - SCTRL_BHLTHY_NUMREGS, &scsb->scsb_data_reg[index], 1); - return (error); -} - -/* - * Returns the health status of a slot - */ -int -scsb_read_slot_health(scsb_state_t *scsb, int pslotnum) -{ - int slotnum = tonga_psl_to_ssl(scsb, pslotnum); - return (scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_BHLTHY_BASE, SCSB_FRU_OP_GET_BITVAL)); -} - -/* - * DIAGNOSTIC and DEBUG only. - * Called from ioctl command (SCSBIOC_BHEALTHY_GET) - */ -int -scsb_bhealthy_slot(scsb_state_t *scsb, scsb_uinfo_t *suip) -{ - int error = 0; - int base, code, unit_number; - uchar_t reg; - int index; - - if (scsb->scsb_state & SCSB_FROZEN) - return (EAGAIN); - - /* operation valid for slots only */ - if (suip == NULL || suip->unit_type != SLOT) { - return (EINVAL); - } - - if (scsb_debug & 0x8001) - cmn_err(CE_NOTE, "scsb_bhealthy_slot: slot %d", - suip->unit_number); - if (suip->unit_number > mct_system_info.max_units[SLOT]) { - return (EINVAL); - } - /* - * Map 1.0 Tonga Slot Number, if necessary - */ - tonga_slotnum_check(scsb, suip); - base = SCTRL_BHLTHY_BASE; - code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number); - unit_number = FRU_OFFSET(code, base); - index = FRU_REG_INDEX(code, base); - reg = SCSB_REG_ADDR(index); - index = SCSB_REG_INDEX(reg); /* shadow index */ - - if (scsb->scsb_state & SCSB_P10_PROM) { - error = scsb_read_bhealthy(scsb); - } - /* else shadow regs are updated by interrupt handler */ - if (error == 0) { - if (scsb->scsb_data_reg[index] & (1 << unit_number)) - suip->unit_state = ON; - else - suip->unit_state = OFF; - } - return (error); -} - -/* - * Called from HSC and ioctl command (SCSBIOC_RESET_UNIT) - * to reset one specified slot - */ -int -scsb_reset_unit(scsb_state_t *scsb, scsb_uinfo_t *suip) -{ - int error; - int unit_number; - uchar_t reg; - int index, slotnum, reset_state; - - if (scsb->scsb_state & SCSB_FROZEN) - return (EAGAIN); - if (scsb_debug & 0x8001) { - cmn_err(CE_NOTE, "scsb_reset_slot(%d): slot %d, state %d\n", - scsb->scsb_instance, suip->unit_number, - suip->unit_state); - } - if (suip->unit_type != ALARM && !(scsb->scsb_state & - (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) { - return (EINVAL); - } - if (suip->unit_state != ON && suip->unit_state != OFF) { - return (EINVAL); - } - error = 0; - switch (suip->unit_type) { - case ALARM: - { - int i, code; - if (suip->unit_number != 1) - return (EINVAL); - code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number); - unit_number = FRU_OFFSET(code, SCTRL_RESET_BASE); - i = ALARM_RESET_REG_INDEX(code, SCTRL_RESET_BASE); - reg = SCSB_REG_ADDR(i); - break; - } - case SLOT: - slotnum = suip->unit_number; - reset_state = (suip->unit_state == ON) ? SCSB_RESET_SLOT : - SCSB_UNRESET_SLOT; - if (scsb->scsb_state & SCSB_IS_TONGA) { - if (slotnum > TG_MAX_SLOTS || - slotnum == SC_TG_CPU_SLOT) { - return (EINVAL); - } - } else { - if (slotnum > MC_MAX_SLOTS || - slotnum == SC_MC_CPU_SLOT || - (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES && - slotnum == SC_MC_CTC_SLOT)) { - return (EINVAL); - } - } - return (scsb_reset_slot(scsb, slotnum, reset_state)); - default: - return (EINVAL); - } - index = SCSB_REG_INDEX(reg); - mutex_enter(&scsb->scsb_mutex); - if (suip->unit_state == ON) - scsb->scsb_data_reg[index] |= (1 << unit_number); - else /* OFF */ - scsb->scsb_data_reg[index] &= ~(1 << unit_number); - if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, 1, - &scsb->scsb_data_reg[index], 0)) != 0) { - if (scsb_debug & 0x8002) - cmn_err(CE_WARN, - "scsb_leds: write failure to 0x%x", reg); - return (error); - } - mutex_exit(&scsb->scsb_mutex); - return (error); -} - -/* - * Diagnostic and DEBUG - * This is a helper function for the helper ioctl to pretend that - * scsb h/w is doing its job!!! - */ -int -scsb_slot_occupancy(scsb_state_t *scsb, scsb_uinfo_t *suip) -{ - int error; - int saved_unit_number; - - if (!(scsb->scsb_state & (SCSB_DEBUG_MODE | SCSB_DIAGS_MODE))) - return (EACCES); - if (scsb->scsb_state & SCSB_FROZEN) { - return (EAGAIN); - } - error = 0; - switch (suip->unit_type) { - case ALARM: - if (suip->unit_number != - (mct_system_info.fru_info_list[ALARM])->fru_unit) { - return (EINVAL); - } - break; - - case SLOT: - /* - * All slots are acceptable, except slots 11 & 12. - */ - if (suip->unit_number < 1 || suip->unit_number > - mct_system_info.max_units[ALARM]) { - error = EINVAL; - break; - } - /* Map 1.0 Tonga Slot Numbers if necessary */ - saved_unit_number = suip->unit_number; - tonga_slotnum_check(scsb, suip); - break; - - default: - error = EINVAL; - break; - } - - if (error) - return (error); - if (suip->unit_state == ON) { - if (hsc_slot_occupancy(saved_unit_number, B_TRUE, 0, B_TRUE) - != 0) - error = EFAULT; - } else { - if (hsc_slot_occupancy(saved_unit_number, B_FALSE, 0, B_FALSE) - != 0) - error = EFAULT; - } - - return (error); -} - -static int -scsb_clear_intptrs(scsb_state_t *scsb) -{ - int i, error; - uchar_t wbuf[SCTRL_MAX_GROUP_NUMREGS]; - error = 0; - for (i = 1; i <= SCTRL_INTR_NUMREGS; ++i) { - wbuf[i] = 0xff; - } - if (error = scsb_rdwr_register(scsb, I2C_WR, - SCSB_REG_ADDR(SCTRL_INTSRC_BASE), - SCTRL_INTR_NUMREGS, wbuf, 1)) { - if (scsb_debug & 0x0402) - cmn_err(CE_NOTE, "scsb_clear_intptrs(): " - "write to 0x%x failed", - SCSB_REG_ADDR(SCTRL_INTSRC_BASE)); - } - return (error); -} - -static int -scsb_setall_intmasks(scsb_state_t *scsb) -{ - int error; - uchar_t reg, wdata, rmask; - int i; - - /* - * write loop for Interrupt Mask registers - */ - if (scsb_debug & 0x0401) - cmn_err(CE_NOTE, "setall_intmasks()"); - error = 0; - rmask = 0; - wdata = 0xff; - reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE); - for (i = 0; i < SCTRL_MASK_NUMREGS; ++i, ++reg) { - if (error = scsb_write_mask(scsb, reg, rmask, wdata, 0)) { - if (scsb_debug & 0x0402) - cmn_err(CE_NOTE, "scsb_setall_intmasks: " - "write to 0x%x failed: %d", reg, error); - error = EIO; - break; - } - } - return (error); -} - - -/* - * Clear Interrupt masks based on the FRUs that could be installed - * for this particular topology, determined by the MidPlane ID - * from SCTRL_SYSCFG registers - * case SCTRL_MPID_HALF: - * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 2 PS, 3 FAN, 3 SCSI, 8 Slots - * case SCTRL_MPID_QUARTER: - * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 1 SCSI, 4 Slots - * case SCTRL_MPID_QUARTER_NODSK: - * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 0 SCSI, 4 Slots - */ -static int -scsb_clear_intmasks(scsb_state_t *scsb) -{ - int error; - uchar_t msk_reg, reg, wdata, rmask; - uchar_t mask_data[SCTRL_MAX_GROUP_NUMREGS]; - int tmp, idx, code, unit, offset, mbid; - scsb_utype_t fru_type; - fru_info_t *fru_ptr; - - if (scsb->scsb_state & SCSB_FROZEN && - !(scsb->scsb_state & SCSB_IN_INTR)) { - return (EAGAIN); - } - error = 0; - for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp) - mask_data[tmp] = 0; - msk_reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE); - mbid = SCSB_REG_INDEX(msk_reg); /* the Mask Base Index Delta */ - if (scsb_debug & 0x0400) { - cmn_err(CE_NOTE, "clear_intmasks: msk_reg=0x%x; mbid=%d", - msk_reg, mbid); - } - for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) { - if (fru_type == SCB) - continue; /* handle below, 2 reg offsets */ - fru_ptr = mct_system_info.fru_info_list[fru_type]; - for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) { - unit = fru_ptr->fru_unit; - code = FRU_UNIT_TO_EVCODE(fru_type, unit); - offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE); - reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE); - idx = SCSB_REG_INDEX(reg); - tmp = idx - mbid; - mask_data[tmp] |= (1 << offset); - if (scsb_debug & 0x0400) - cmn_err(CE_NOTE, - "clear_intmasks:%d:%d: PRES mask[%d]:0x%x", - fru_type, unit, tmp, mask_data[tmp]); - if ((fru_type == SLOT) && (IS_SCB_P15)) { - /* - * Unmask the corresponding Slot HLTHY mask - * Use Slot bit and register offsets, - * but with SCTRL_INTMASK_HLTHY_BASE - */ - reg = FRU_REG_ADDR(code, - SCTRL_INTMASK_HLTHY_BASE); - idx = SCSB_REG_INDEX(reg); - tmp = idx - mbid; - mask_data[tmp] |= (1 << offset); - if (scsb_debug & 0x0400) { - cmn_err(CE_NOTE, - "clear_intmasks:Slot:%d: HLTHY mask[%d]:0x%x" - "; reg=0x%x, idx=%d, mbid=%d", - unit, tmp, mask_data[tmp], - reg, idx, mbid); - } - } - } - } - /* - * Now unmask these non-fru interrupt events - * SCTRL_EVENT_PWRDWN (almost normal) - * SCTRL_EVENT_REPLACE (not used) - * SCTRL_EVENT_ALARM_INT (not working in P0.6/P1.0) - * SCTRL_EVENT_SCB (SCB 1.5 ONLY; plus SCB_INT_OFFSET) - */ - code = SCTRL_EVENT_PWRDWN; - offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE); - reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE); - idx = SCSB_REG_INDEX(reg); - tmp = idx - mbid; - mask_data[tmp] |= (1 << offset); - if (IS_SCB_P15) { - code = SCTRL_EVENT_SCB; - offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE); - reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE) + SCB_INT_OFFSET; - idx = SCSB_REG_INDEX(reg); - tmp = idx - mbid; - mask_data[tmp] |= (1 << offset); - code = SCTRL_EVENT_ALARM_INT; - offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE); - reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE); - idx = SCSB_REG_INDEX(reg); - tmp = idx - mbid; - mask_data[tmp] |= (1 << offset); - } - for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp) { - rmask = 0; - wdata = mask_data[tmp]; - if (scsb_debug & 0x0400) - cmn_err(CE_NOTE, "clear_intmasks:0x%x: ~(0x%x),0x%x", - msk_reg, (~wdata) & 0xff, wdata); - mutex_enter(&scsb->scsb_mutex); - if (error = scsb_write_mask(scsb, msk_reg, rmask, - (~wdata) & 0xff, wdata)) { - mutex_exit(&scsb->scsb_mutex); - if (scsb_debug & 0x0402) - cmn_err(CE_NOTE, "scsb_clear_intmasks: " - "write to 0x%x failed: %d", - msk_reg, error); - error = EIO; - break; - } - mutex_exit(&scsb->scsb_mutex); - ++msk_reg; - } - return (error); -} - -static int -scsb_get_status(scsb_state_t *scsb, scsb_status_t *smp) -{ - register int i; - - if (smp == NULL) { - return (EFAULT); - } - if (scsb_debug & 0x40000000 && - (scsb->scsb_state & SCSB_DEBUG_MODE || - scsb->scsb_state & SCSB_DIAGS_MODE)) { - if (scsb->scsb_state & SCSB_FROZEN) { - return (EAGAIN); - } - mutex_enter(&scsb->scsb_mutex); - if (scsb_debug & 0x80000000) { - if ((i = scsb_readall_regs(scsb)) != 0 && - scsb->scsb_state & SCSB_DEBUG_MODE) - cmn_err(CE_WARN, "scsb_get_status: " - "scsb_readall_regs() FAILED"); - } else { - if ((i = scsb_check_config_status(scsb)) == 0) { - i = scsb_set_scfg_pres_leds(scsb, NULL); - } - } - mutex_exit(&scsb->scsb_mutex); - if (i) { - cmn_err(CE_WARN, - "scsb_get_status: FAILED Presence LEDs update"); - return (EIO); - } - } - for (i = 0; i < SCSB_DATA_REGISTERS; ++i) - smp->scsb_reg[i] = scsb->scsb_data_reg[i]; - return (0); -} - -/* - * scsb_freeze_check: - * Turn all the leds off on the system monitor card, without changing - * the state of what we have for scsb. This routine is called only when - * replacing system monitor card, so the state of the card leds could be - * restored, using scsb_restore(). - * Also, set state to SCSB_FROZEN which denies access to scsb while in - * freeze mode. - */ -static char *BAD_BOARD_MSG = - "SCSB: Should NOT remove SCB(%d) while cPCI Slot %d is " - "in RESET with a possible bad board."; -static int slots_in_reset[SCTRL_MAX_GROUP_NUMREGS]; - -static void -scsb_freeze_check(scsb_state_t *scsb) -{ - register int i; - int offset; - int unit, slotnum; - int index; - fru_info_t *fru_ptr; - uint32_t code; - uchar_t reg; - - if (scsb_debug & 0x20001) - cmn_err(CE_NOTE, "scsb_freeze_check(%d):", scsb->scsb_instance); - - if (scsb->scsb_state & SCSB_FROZEN) { - return; - } - mutex_enter(&scsb->scsb_mutex); - for (i = 0; i < SCTRL_MAX_GROUP_NUMREGS; ++i) - slots_in_reset[i] = 0; - /* - * We allow the SCB to be removed only if none of - * the cPCI resets are asserted for occupied slots. - * There shouldn't be a bad board plugged in the system - * while swapping the SCB. - */ - fru_ptr = mct_system_info.fru_info_list[SLOT]; - for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) { - if (IS_SCB_P15) { - slotnum = tonga_psl_to_ssl(scsb, unit); - } else { - slotnum = unit; - } - code = FRU_UNIT_TO_EVCODE(SLOT, slotnum); - offset = FRU_OFFSET(code, SCTRL_RESET_BASE); - reg = FRU_REG_ADDR(code, SCTRL_RESET_BASE); - index = SCSB_REG_INDEX(reg); - if (scsb->scsb_data_reg[index] & (1 << offset)) { - if (fru_ptr[unit - 1].fru_status == FRU_PRESENT) { - slots_in_reset[unit - 1] = unit; - cmn_err(CE_NOTE, BAD_BOARD_MSG, - scsb->scsb_instance, unit); - } - } - } - mutex_exit(&scsb->scsb_mutex); -} - -static void -scsb_freeze(scsb_state_t *scsb) -{ - uint32_t code; - if (scsb_debug & 0x00020002) { - cmn_err(CE_WARN, "scsb_freeze: SCB%d possibly removed", - scsb->scsb_instance); - } - if (scsb->scsb_state & SCSB_FROZEN) - return; - scsb->scsb_state |= SCSB_FROZEN; - scsb->scsb_state &= ~SCSB_SCB_PRESENT; - (void) scsb_hsc_freeze(scsb->scsb_dev); - /* - * Send the EVENT_SCB since there is evidence that the - * System Controller Board has been removed. - */ - code = SCTRL_EVENT_SCB; - if (!(scsb->scsb_state & SCSB_IN_INTR)) - scsb_event_code = code; - check_fru_info(scsb, code); - add_event_code(scsb, code); - (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &code, "scsb_freeze"); -} - -/* - * scsb_restore will only be called from the interrupt handler context on - * INIT_SCB interrupt for newly inserted SCB. - * Called with mutex held. - */ -static void -scsb_restore(scsb_state_t *scsb) -{ - if (scsb_debug & 0x20001) - cmn_err(CE_NOTE, "scsb_restore(%d):", scsb->scsb_instance); - - if (initialize_scb(scsb) != DDI_SUCCESS) { - if (scsb_debug & 0x00020002) { - cmn_err(CE_WARN, "scsb_restore: INIT Failed"); - return; - } - } - /* 9. Clear all Interrupts */ - if (scsb_clear_intmasks(scsb)) { - cmn_err(CE_WARN, - "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance); - if (scsb_debug & 0x00020002) { - cmn_err(CE_WARN, "scsb_restore: clear_intmasks Failed"); - } - return; - } - - /* 10. */ - /* Check if Alarm Card present at boot and set flags */ - if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL)) - scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES; - else - scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES; - - scsb->scsb_state &= ~SCSB_FROZEN; - (void) scsb_hsc_restore(scsb->scsb_dev); -} - -/* - * Given an Event Code, - * Return: - * FRU type in LSByte - * unit number in MSByte - */ -uint16_t -event_to_type(uint32_t evcode) -{ - int i, li, unit; - uint32_t ec; - uint16_t ret; - for (i = li = 0; i < SCSB_UNIT_TYPES; ++i) { - if (evcode == type_to_code1[i]) { - ret = (uint16_t)(0x0100 | i); - return (ret); - } - if (evcode < type_to_code1[i]) { - unit = 1; - ec = type_to_code1[li]; - while (ec < evcode) - ec = ec << 1, ++unit; - ret = (unit << 8) | li; - return (ret); - } - li = i; - } - return ((uint16_t)0xffff); -} - -/* - * scsb interrupt handler for (MC) PSM_INT vector - * P0.6: HW shipped to beta customers - * 1. did not have Slot Occupant Presense support - * 2. I2C interrupt-map properties not yet tested, using polling daemon - * 3. Polling detects each event reliably twice. - * clr_bits# are used to keep track of events to be ignored 2nd time - * - * retval flags allow all events to be checked, and still returning the - * correct DDI value. - * - */ -#define SCSB_INTR_CLAIMED 1 -#define SCSB_INTR_UNCLAIMED 2 -#define SCSB_INTR_EVENT 4 - -/* - * Does preprocessing of the interrupt. The only thing this - * needs to do is to ask scsb to release the interrupt line. - * and then schedule delayed actual processing using timeout() - */ -uint_t -scsb_intr_preprocess(caddr_t arg) -{ - scsb_state_t *scsb = (scsb_state_t *)arg; - - scb_pre_s = gethrtime(); - - /* - * If SCSB_IN_INTR is already set in scsb_state, - * it means we are being interrupted by someone else. This can - * happen only if the interrupt does not belong to scsb, and some - * other device, e.g. a FAN or PS is interrupting. So, we - * cancel the previous timeout(). - */ - - if (scsb->scsb_state & SCSB_IN_INTR) { - (void) untimeout(scsb_intr_tid); - (void) scsb_invoke_intr_chain(); - (void) scsb_toggle_psmint(scsb, 1); - scsb->scsb_state &= ~SCSB_IN_INTR; - goto intr_end; - } - scsb->scsb_state |= SCSB_IN_INTR; - - /* - * Stop scsb from interrupting first. - */ - if (scsb_quiesce_psmint(scsb) != DDI_SUCCESS) { - goto intr_end; - } - - /* - * Schedule a timeout to actually process the - * interrupt. - */ - scsb_intr_tid = timeout((void (*)(void *))scsb_intr, arg, - drv_usectohz(1000)); - -intr_end: - - scb_pre_e = gethrtime(); - return (DDI_INTR_CLAIMED); -} - -static void scsb_healthy_intr(scsb_state_t *scsb, int pslotnum); -void -scsb_intr(caddr_t arg) -{ - scsb_state_t *scsb = (scsb_state_t *)arg; - int i, idx, offset, unit, numregs, error; - int intr_idx, index, offset_base, retval, slotnum, val; - uint32_t code; - uchar_t intr_reg, tmp_reg, intr_addr, clr_bits = 0; - uchar_t ac_slot = B_FALSE; - uchar_t *int_masks; - uchar_t cstatus_regs[SCTRL_MAX_GROUP_NUMREGS]; - scsb_utype_t fru_type; - fru_info_t *fru_ptr; - int ac_present; - - /* - * Avoid mayhem, make sure we have only one timeout thread running. - */ - mutex_enter(&scsb->scsb_mutex); - while (scsb_in_postintr) - cv_wait(&scsb->scsb_cv, &scsb->scsb_mutex); - scsb_in_postintr = 1; - mutex_exit(&scsb->scsb_mutex); - - scb_post_s = gethrtime(); - if (scsb_debug & 0x00002000) - cmn_err(CE_NOTE, "scsb_intr(%d)", scsb->scsb_instance); - retval = 0; - tmp_reg = 0; - /* - * XXX: Problem, when we want to support swapping between SCB - * versions, then we need to check the SCB PROM ID (CF) register here - * before assuming the same SCB version was re-inserted. - * We will have to duplicate some of the scb_initialization() - * code to set the scsb_state PROM ID bits and to set up the - * register table pointers. - * - * Only if NOT SSB_PRESENT, check the SCB PROM ID - */ - if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) { - if (scb_check_version(scsb) != DDI_SUCCESS) { -#ifdef DEBUG - if (scsb->scsb_state & SCSB_SSB_PRESENT && - scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb_failing_event(scsb); -#endif - goto intr_error; - } - } - if (IS_SCB_P15) { - int_masks = scb_15_int_masks; - } else { - int_masks = scb_10_int_masks; - } - /* - * Now check the INTSRC registers for set bits. - * Do a quick check by OR'ing INTSRC registers together as we copy - * them from the transfer buffer. For P1.0 or earlier we had already - * read the interrupt source registers and wrote them back to stop - * interrupt. So we need to do this step only for P1.5 or later. - * We already read INTSRC6 to take care of SCB insertion case, so - * do not read INTSRC6 again. - */ - - if (IS_SCB_P15) { - intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE); - /* read the interrupt register from scsb */ - if (scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr, - SCTRL_INTR_NUMREGS - 1, scb_intr_regs, 1)) { - cmn_err(CE_WARN, "scsb_intr: " - " Failed read of interrupt registers."); -#ifdef DEBUG - if (scsb->scsb_state & SCSB_SSB_PRESENT && - scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb_failing_event(scsb); -#endif - goto intr_error; - } - } - - /* - * We have seen that an interrupt source bit can be set - * even though the corresponding interrupt mask bit - * has been set to mask the interrupt. So we must - * clear all bits set in the interrupt source register. - */ - for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) { - retval |= scb_intr_regs[i]; /* Quick INTSRC check */ -#ifdef DEBUG - if (scsb_debug & 0x08000000) { - if (tmp_reg || scb_intr_regs[i]) { - cmn_err(CE_NOTE, "scsb_intr: INTSRC%d=0x%x", - i + 1, scb_intr_regs[i]); - ++tmp_reg; - } - } -#endif - } - /* - * Any bits from quick check? If this is not our interrupt, - * something is wrong. FAN/PS interrupts are supposed to be - * blocked, but we can not be sure. So, go ahead and call the - * emergency interrupt handlers for FAN/PS devices and mask - * their interrupts, if they aren't already masked. - */ - if (retval == 0) { - goto intr_error; - } - - retval = 0; - - /* - * If SCB 1.5 or 2.0, check for the INIT_SCB Interrupt - * to support Hot SCB Insertion. - * The check was moved here during debugging of the SCB hot insertion. - * Theoretically, this code could be moved back to the check for - * SCTRL_EVENT_SCB in the processing loop below. - */ - if (IS_SCB_P15) { - int iid; - iid = SCSB_REG_INDEX(intr_addr); - offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE); - tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15); - intr_idx = SCSB_REG_INDEX(tmp_reg) - iid; - clr_bits = 1 << offset; - if (scb_intr_regs[intr_idx] & clr_bits) { - /* - * Must be newly inserted SCB - * Time to re-initialize. - */ - if (scsb_debug & 0x00023000) { - cmn_err(CE_NOTE, - "scsb_intr(%d): INIT_SCB INT", - scsb->scsb_instance); - } - scsb_restore(scsb); - retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT); - /* - * The INTSRC bit will be cleared by the - * scsb_restore() function. - * Also, leave the bit set in scb_intr_regs[] so we can - * report the event code as we check for other - * interrupt source bits. - * - * scsb_write_mask(scsb, tmp_reg, 0, clr_bits, 0); - * scb_intr_regs[intr_idx] &= ~clr_bits; - */ - } - /* - * In case this is a power down interrupt, check the validity - * of the request to make sure it's not an I2C noise - */ - offset = FRU_OFFSET(SCTRL_EVENT_PWRDWN, - SCTRL_INTPTR_BASE); - clr_bits = 1 << offset; - intr_reg = scb_intr_regs[intr_idx]; - if (intr_reg & clr_bits) { - /* - * A shutdown request has been detected. Poll - * the corresponding register ? more times to - * make sure it's a genuine shutdown request. - */ - for (i = 0; i < scsb_shutdown_count; i++) { - drv_usecwait(1000); - if (scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg, - 1, &intr_reg, 1)) { - cmn_err(CE_WARN, "Failed to read " - " interrupt register"); - goto intr_error; - } - if (scsb_debug & 0x08000000) { - cmn_err(CE_NOTE, "scsb_intr: " - " INTSRC6[%d]=0x%x", i, - intr_reg); - } - if (!(intr_reg & clr_bits)) { - scb_intr_regs[intr_idx] &= ~clr_bits; - break; - } - } - } - } - /* - * if retval == 0, then we didn't call scsb_restore, - * so we update the shadow copy of SYSCFG registers - * We *MUST* read the syscfg registers before any attempt - * to clear the interrupt source registers is made. - */ - if (retval == 0 && scsb_check_config_status(scsb)) { - cmn_err(CE_WARN, - "scsb_intr: Failed read of config/status registers"); - if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) { - if (!scsb_debug) { - goto intr_error; - } - } -#ifdef DEBUG - if (scsb->scsb_state & SCSB_SSB_PRESENT && - scsb->scsb_i2c_errcnt > scsb_err_threshold) { - scsb_failing_event(scsb); - } -#endif - /* - * Allow to go on so we clear the INTSRC bits - */ - } - - /* - * Read the board healthy registers here, if any of the healthy - * interrupts are set. - */ - if (IS_SCB_P15) { - intr_idx = intr_reg = 0; - intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE); - index = SCSB_REG_INDEX(intr_addr); - for (i = 0; i < SCTRL_BHLTHY_NUMREGS; ++i, ++intr_idx) { - scsb->scsb_data_reg[index++] = - scb_intr_regs[intr_idx] & int_masks[intr_idx]; - intr_reg |= scb_intr_regs[i]; - } - - if (intr_reg && scsb_read_bhealthy(scsb) != 0) { - cmn_err(CE_WARN, "%s#%d: Error Reading Healthy# " - " Registers", ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev)); -#ifdef DEBUG - if (scsb->scsb_state & SCSB_SSB_PRESENT && - scsb->scsb_i2c_errcnt > scsb_err_threshold) { - scsb_failing_event(scsb); - } -#endif - goto intr_error; - } - } - - /* - * We clear the interrupt source registers now itself so that - * future interrupts can be latched quickly, instead of after - * finishing processing of all interrupt conditions. The global - * interrupt mask however remain disabled. - */ - if (IS_SCB_P15) { - if (scsb_rdwr_register(scsb, I2C_WR, intr_addr, - SCTRL_INTR_NUMREGS, scb_intr_regs, 1)) { - cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt" - " registers."); -#ifdef DEBUG - if (scsb->scsb_state & SCSB_SSB_PRESENT && - scsb->scsb_i2c_errcnt > scsb_err_threshold) { - scsb_failing_event(scsb); - } -#endif - goto intr_error; - } - } - - /* - * At this point, all interrupt source registers are read. - * We only handle interrups which are not masked - */ - for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) { - scb_intr_regs[i] &= int_masks[i]; - } - - /* - * We are here means that there was some bit set in the interrupt - * source register. So we must claim the interrupt no matter - * whatever error we may encounter in the course of processing. - */ - retval |= SCSB_INTR_CLAIMED; - - /* store config status data */ - tmp_reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE); - index = SCSB_REG_INDEX(tmp_reg); - for (i = 0; i < SCTRL_CFG_NUMREGS; ++i) - cstatus_regs[i] = scsb->scsb_data_reg[index + i]; - /* - * Clear the event code, - * then check to see what kind(s) of events we were interrupted for. - * Check all SCTRL_INTSRC registers - */ - scsb_event_code = 0; - clr_bits = 0; - intr_idx = 0; - numregs = SCTRL_INTR_NUMREGS; - index = SCSB_REG_INDEX(intr_addr); - /* - * If SCB 1.5, adjust some variables to skip the SCTRL_BHLTHY_REGS - * which will be handled last in this function. - */ - if (IS_SCB_P15) { - i = SCTRL_BHLTHY_NUMREGS; - intr_idx += i; - intr_addr += i; - index += i; - } - /* - * For the rest of the INTSRC registers, we walk through the - * scb_fru_offset[] table, matching register offsets with our offset - * counter. Then we check for the scb_fru_offset[] bit in intr_reg. - * The scb_fru_offset[] index is now the SCTRL_EVENT code. - * The code is then compared to type_to_code1[] entries to find the - * fru_type. The fru_type will help us recognize when to do - * SLOT Hot Swap processing. - * - * offset_base: the appropriate scb_fru_offset[] base index - * for the INTPTR_BASE register group - * offset: bit offset found in INTSRC register - * intr_idx: index to temporary INTSRC register copies - * intr: modified copy of current INTR register - * intr_addr: SCB register address of current INTR register - * index: index to current INTR shadow register - * idx: bit-number of current INTR event bit - * uc: uchar_t from scb_fru_offset[] table, - * containing register and FRU offsets. - * j: used to walk fru_offset[] table, which is also - * the bit-number of the current event code - * code: manufactured event code for current INT event - */ - offset_base = FRU_OFFSET_BASE(SCTRL_INTPTR_BASE); - for (offset = 0; intr_idx < numregs; - ++offset, ++intr_idx, ++intr_addr, ++index) { - scsb->scsb_data_reg[index] = scb_intr_regs[intr_idx]; - intr_reg = scb_intr_regs[intr_idx]; - while (intr_reg) { /* for each INTSRC bit that's set */ - int j; - uint16_t ui; - uchar_t uc; - idx = event_to_index((uint32_t)intr_reg); /* offset */ - code = (1 << idx); /* back to bit mask */ - clr_bits |= code; - intr_reg = intr_reg & ~code; /* clear this one */ - for (j = 0; j < MCT_MAX_FRUS; ++j) { - /* - * Get register offset from table and check - * for a match with our loop offset counter. - * Then check for intr_reg bit-offset match - * with bit-offset from table entry. - */ - uc = scb_fru_offset[offset_base + j]; - if (offset != ((uc >> 4) & 0xf)) { - if (IS_SCB_P10) - continue; - if (j != FRU_INDEX(SCTRL_EVENT_SCB)) - continue; - if (offset != ((uc >> 4) & 0xf) - + SCB_INT_OFFSET) - continue; - } - if (idx == (uc & 0xf)) - break; - } - if (uc == 0xff) { - /* - * bit idx not recognized, check another. - */ - continue; - } - /* - * We found the fru_offset[] entry, now use the index - * to get the event code. - */ - code = (uint32_t)(1 << j); - if (scsb_debug & 0x00002000) { - cmn_err(CE_NOTE, "scsb_intr: code=0x%x", code); - } - /* - * Now check for the NON-FRU type events. - */ - if (code == SCTRL_EVENT_PWRDWN) { - if (scsb_debug & 0x1002) { - cmn_err(CE_NOTE, - "scsb_intr(%d): power down req." - " INT.", scsb->scsb_instance); - } - scsb_event_code |= code; - if (scsb->scsb_state & SCSB_OPEN && - scsb->scsb_rq != (queue_t *)NULL) { - /* - * inform applications using poll(2) - * about this event, and provide the - * event code to EnvMon scsb policy - */ - if (!(scsb_debug & 0x00040000)) - (void) scsb_queue_put(scsb->scsb_rq, 1, - &scsb_event_code, "scsb_intr"); - goto intr_error; - } - continue; - } else if (code == SCTRL_EVENT_REPLACE) { - if (scsb_debug & 0x1002) { - cmn_err(CE_NOTE, - "scsb_intr(%d): replacement " - "req. INT.", - scsb->scsb_instance); - } - scsb_freeze_check(scsb); - scsb_freeze(scsb); - scsb_event_code |= code; - retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT); - continue; - } else if (code == SCTRL_EVENT_SCB) { - int tmp; - /* - * Must be newly inserted SCB - * Time to re-initialize. - */ - if (scsb_debug & 0x1002) { - cmn_err(CE_NOTE, - "scsb_intr(%d): INIT SCB INTR", - scsb->scsb_instance); - } - /* - * SCB initialization already handled, but we - * set the event code bit here in order to - * report the event to interested utilities. - * - * scsb_restore(scsb); - * The INTSRC bit is already cleared, - * so we won't do it again. - */ - tmp = FRU_OFFSET(SCTRL_EVENT_SCB, - SCTRL_INTPTR_BASE); - clr_bits &= ~(1 << tmp); - scsb_event_code |= code; - retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT); - continue; - } else if (code == SCTRL_EVENT_ALARM_INT) { - /* - * P0.6/P1.0: SCTRL_INTR_ALARM_INT is always - * set and cannot be cleared, so ignore it. - */ - if (!IS_SCB_P15) { - continue; - } - if (scsb_debug & 0x1002) { - cmn_err(CE_NOTE, - "scsb_intr(%d): Alarm INT.", - scsb->scsb_instance); - } - scsb_event_code |= code; - retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT); - /* - * XXX: - * Must service the Alarm INT by clearing INT - * condition on Alarm Card, - * then clear the SCTRL_INTR_ALARM_INT bit here. - * Waiting for specs and test environment. - */ - continue; - } else if ((ui = event_to_type(code)) == 0xffff) { - /* - * FRU type not found - */ - break; - } - /* - * Check for special processing - * now that we found the FRU type. - */ - fru_type = (scsb_utype_t)(ui & 0xff); - unit = (ui >> 8) & 0xff; - if (scsb_debug & 0x00002000) { - cmn_err(CE_NOTE, "scsb_intr: " - "FRU type/unit/code %d/%d/0x%x", - fru_type, unit, code); - } - switch (fru_type) { - case PDU: - break; - case PS: - break; - case DISK: - break; - case FAN: - break; - case SSB: - /* - * in check_fru_info() below, we see if the - * SSB has been removed, then check for - * occupied slots in reset to see if we should - * WARN agains SCB removal - */ - break; - case CFTM: - break; - case CRTM: - break; - case PRTM: - break; - case SLOT: - slotnum = tonga_ssl_to_psl(scsb, unit); - if (scsb_debug & 0x00002000) { - cmn_err(CE_NOTE, "scsb_intr: " - "unit/slot %d/%d", - unit, slotnum); - } - - /* - * If the slot number is not valid, continue. - */ - if (scsb->scsb_state & SCSB_IS_TONGA) { - if (slotnum > TG_MAX_SLOTS || - slotnum == SC_TG_CPU_SLOT) { - continue; - } - /* - * For a tonga, we need to return - * the code corresponding to the - * actual physical slot - */ - code = FRU_UNIT_TO_EVCODE(SLOT, - slotnum); - } else { - if (slotnum > MC_MAX_SLOTS || - slotnum == SC_MC_CPU_SLOT || - (scsb->scsb_hsc_state & - SCSB_HSC_CTC_PRES && - slotnum == SC_MC_CTC_SLOT)) { - continue; - } - } - /* FALLTHROUGH */ - case ALARM: - /* - * INDENT CHEATING, 2 indentations - */ - ac_present = 0; - /* - * If it is an Alarm Card Interrupt, we just do some sanity - * checks and then wait for the slot interrupt to take - * connect or disconnect action. - * XXX - Is there a gaurantee that ALARM int will occur first ? - */ - if (fru_type == ALARM) { - DEBUG2("AC Intr %d(%d)\n", scsb->ac_slotnum, idx+1); - val = scsb_fru_op(scsb, SLOT, - tonga_ssl_to_psl(scsb, scsb->ac_slotnum), - SCTRL_SYSCFG_BASE, SCSB_FRU_OP_GET_BITVAL); - ac_present = scsb_fru_op(scsb, ALARM, 1, - SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL); - /* - * It is observed that slot presence and Alarm - * presence bits do not go ON at the same time. - * Hence we wait till both events happen. - */ -#ifdef DEBUG - if ((((val) && (!ac_present)) || - ((!val) && (ac_present))) && - (scsb->scsb_hsc_state & - SCSB_AC_SLOT_INTR_DONE)) - - cmn_err(CE_WARN, "?Alarm and Slot presence " - "state bits do not match! (%x,%x)", - val, ac_present); -#endif - if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE) - scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE; - else - scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE; - break; /* we break and wait for slot interrupt. */ - } - - /* - * cPCI slot interrupt event - */ - if (scsb->scsb_state & SCSB_IS_TONGA) { - if (slotnum > TG_MAX_SLOTS || - slotnum == SC_TG_CPU_SLOT) { - continue; - } - } else { - if (slotnum > MC_MAX_SLOTS || - slotnum == SC_MC_CPU_SLOT || - (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES && - slotnum == SC_MC_CTC_SLOT)) { - continue; - } - } - if (scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) { - DEBUG2("AC slot Intr %d(%d)\n", slotnum, idx+1); - ac_slot = B_TRUE; - } - val = scsb_fru_op(scsb, SLOT, unit, SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL); - if (ac_slot == B_TRUE) { - ac_present = scsb_fru_op(scsb, ALARM, 1, - SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL); -#ifdef DEBUG - if ((((val) && (!ac_present)) || - ((!val) && (ac_present))) && - (scsb->scsb_hsc_state & - SCSB_AC_SLOT_INTR_DONE)) { - - cmn_err(CE_WARN, "?Alarm and Slot presence " - "state bits do not match! (%x,%x)", - val, ac_present); - } -#endif - if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE) - scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE; - else - scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE; - } - if (val) { - if (ac_present) { - DEBUG1("AC insertion on slot %d!\n", slotnum); - if (scsb_debug & 0x00010000) { - cmn_err(CE_NOTE, "scsb_intr: " - "AC_PRES slot %d", slotnum); - } - scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES; - } -#ifndef lint - else - DEBUG1("IO Insertion on slot %d!\n", slotnum); -#endif - /* - * Special case : check MPID type. - * If MC midplane type, - * check to make sure the Alarm Card present - * bit is ON. If not, this is a regular IO card. - */ - (void) scsb_connect_slot(scsb, slotnum, B_FALSE); - } else { - if ((ac_slot == B_TRUE) && - (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) { - - DEBUG1("AC Removal on slot %d!\n", slotnum); -#ifdef DEBUG - if (scsb_debug & 0x00010000) { - cmn_err(CE_NOTE, "scsb_intr: " - "!AC_PRES slot %d", - slotnum); - } -#endif /* DEBUG */ - scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES; - } -#ifndef lint - else - DEBUG1("IO Removal on slot %d!\n", slotnum); -#endif - (void) scsb_disconnect_slot(scsb, B_FALSE, slotnum); - } - /* - * END INDENT CHEATING, 2 indentations - */ - - break; - default: - /* - * ERROR: Did not find cause of INTSRC bit - */ - if (scsb_debug & 0x00000002) { - cmn_err(CE_WARN, - "scsb_intr: FRU type %d" - " not recognized", fru_type); - } - continue; - } - scsb_event_code |= code; - retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT); - if (fru_type == SLOT) - continue; - error = 0; - fru_ptr = mct_system_info.fru_info_list[fru_type]; - for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) { - if (unit != fru_ptr->fru_unit) - continue; - if (fru_ptr->i2c_info == NULL || - (tmp_reg = fru_ptr->i2c_info-> - ledata_reg) == 0) - continue; - error = scsb_set_scfg_pres_leds(scsb, fru_ptr); - if (error) { - cmn_err(CE_WARN, "scsb_intr(): " - "I2C write error to 0x%x", - tmp_reg); - if (!(scsb->scsb_state & - SCSB_DEBUG_MODE)) { - goto intr_error; - } - } - break; - } - } - if (clr_bits) { - clr_bits = 0; - } - } - /* - * Check for SCB 1.5 interrupt for SLOT HEALTHY changes - */ - clr_bits = 0; - intr_idx = 0; - numregs = SCTRL_INTR_NUMREGS; - intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE); - index = SCSB_REG_INDEX(intr_addr); - if (IS_SCB_P15) { - for (i = 0; i < SCTRL_BHLTHY_NUMREGS; - ++i, ++intr_idx, ++intr_addr) { - scsb->scsb_data_reg[index++] = scb_intr_regs[intr_idx]; - intr_reg = scb_intr_regs[i]; - while (intr_reg) { - idx = event_to_index((uint32_t)intr_reg); - code = (1 << idx); - clr_bits |= code; - intr_reg = intr_reg & ~code; - /* idx + 1 because bit 0 is for Slot 1 */ - slotnum = tonga_ssl_to_psl(scsb, idx + 1); - if (scsb->scsb_state & SCSB_IS_TONGA) { - if (slotnum > TG_MAX_SLOTS || - slotnum == SC_TG_CPU_SLOT) { - continue; - } - } else { - if (slotnum > MC_MAX_SLOTS || - slotnum == SC_MC_CPU_SLOT || - (scsb->scsb_hsc_state & - SCSB_HSC_CTC_PRES && - slotnum == SC_MC_CTC_SLOT)) { - continue; - } - } - scsb_healthy_intr(scsb, slotnum); - } - if (clr_bits) { - clr_bits = 0; - } - } - } - code = scsb_event_code; - if (retval & SCSB_INTR_EVENT && - !(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) { - check_fru_info(scsb, code); - add_event_code(scsb, code); - (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code, - "scsb_intr"); - } -intr_error: - scb_post_e = gethrtime(); - - if (scsb_debug & 0x8000000) - cmn_err(CE_NOTE, "Summary of times in nsec: pre_time %llu, \ - post_time %llu", scb_pre_e - scb_pre_s, - scb_post_e - scb_post_s); - - - mutex_enter(&scsb->scsb_mutex); - scsb_in_postintr = 0; - cv_broadcast(&scsb->scsb_cv); - mutex_exit(&scsb->scsb_mutex); - - /* - * Re-enable interrupt now. - */ - (void) scsb_toggle_psmint(scsb, 1); - scsb->scsb_state &= ~SCSB_IN_INTR; -} - -static int -scsb_polled_int(scsb_state_t *scsb, int cmd, uint32_t *set) -{ - if (scsb_debug & 0x4000) - cmn_err(CE_NOTE, "scsb_polled_int(scsb,0x%x)", cmd); - *set = 0; - if (cmd == SCSBIOC_SHUTDOWN_POLL) { - return (EINVAL); - } - if (cmd != SCSBIOC_INTEVENT_POLL) { - return (EINVAL); - } - if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) { - /* - * scsb_intr() may modify scsb_event_code - */ - scsb_event_code = SCTRL_EVENT_NONE; - (void) scsb_intr((caddr_t)scsb); - *set = scsb_event_code; - scsb_event_code = 0; - } else { - /* - * SCSB_P06_INTR_ON, we know there was an event - * and we're retrieving the event code from the event FIFO. - */ - *set = get_event_code(); - } - if (scsb_debug & 0x01004000) { - cmn_err(CE_NOTE, "scsb_polled_int: event_code = 0x%x", *set); - } - return (0); -} - -static int -scsb_leds_switch(scsb_state_t *scsb, scsb_ustate_t op) -{ - register int i; - int index; - uchar_t reg, idata, rwbuf[SCTRL_MAX_GROUP_NUMREGS]; - - if (scsb->scsb_state & SCSB_FROZEN && - !(scsb->scsb_state & SCSB_IN_INTR)) { - return (EAGAIN); - } - if (scsb_debug & 0x0101) { - cmn_err(CE_NOTE, "scsb_leds_switch(%s):", - op == ON ? "ON" : "OFF"); - } - /* Step 1: turn ON/OFF all NOK LEDs. */ - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "scsb%d: turning all NOK LEDs %s", - scsb->scsb_instance, - op == ON ? "ON" : "OFF"); - } - if (op == ON) - idata = 0xff; - else /* off */ - idata = 0x00; - reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE); - index = SCSB_REG_INDEX(reg); - for (i = 0; i < SCTRL_LED_NOK_NUMREGS; ++i) { - rwbuf[i] = idata; - scsb->scsb_data_reg[index + i] = idata; - } - mutex_enter(&scsb->scsb_mutex); - i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_NOK_NUMREGS, - rwbuf, 1); - mutex_exit(&scsb->scsb_mutex); - if (i) { - if (scsb_debug & 0x0102) - cmn_err(CE_WARN, "scsb_leds_switch(): " - "Failed to turn %s NOK LEDs", - op == ON ? "ON" : "OFF"); - } - /* Step 2: turn ON/OFF all OK LEDs. */ - if (scsb_debug & 0x0100) { - cmn_err(CE_NOTE, "scsb%d: turning all OK LEDs %s", - scsb->scsb_instance, - op == ON ? "ON" : "OFF"); - } - reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE); - index = SCSB_REG_INDEX(reg); - for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) { - rwbuf[i] = idata; - scsb->scsb_data_reg[index + i] = idata; - } - mutex_enter(&scsb->scsb_mutex); - i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_OK_NUMREGS, - rwbuf, 1); - mutex_exit(&scsb->scsb_mutex); - if (i) { - if (scsb_debug & 0x0102) - cmn_err(CE_WARN, "scsb_leds_switch(): " - "Failed to turn %s NOK LEDs", - op == ON ? "ON" : "OFF"); - } - /* Step 3: turn OFF all BLINK LEDs. */ - if (op == OFF) { - reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE); - index = SCSB_REG_INDEX(reg); - for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i) { - rwbuf[i] = idata; - scsb->scsb_data_reg[index + i] = idata; - } - mutex_enter(&scsb->scsb_mutex); - i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_BLINK_NUMREGS, - rwbuf, 1); - mutex_exit(&scsb->scsb_mutex); - if (i) { - if (scsb_debug & 0x0102) - cmn_err(CE_WARN, "scsb_leds_switch(): " - "Failed to turn %s BLINK BITs", - op == ON ? "ON" : "OFF"); - } - } - return (0); -} - -static int -scsb_readall_regs(scsb_state_t *scsb) -{ - int error; - int index; - uchar_t reg; - - if (!(scsb_debug & 0x40000000)) - return (0); - if (scsb_debug & 0x0005) { - cmn_err(CE_NOTE, "scsb_readall_regs:"); - } - if (scsb->scsb_state & SCSB_FROZEN) { - return (EAGAIN); - } - reg = SCSB_REG_ADDR_START; /* 1st register in set */ - index = SCSB_REG_INDEX(reg); - error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, SCSB_DATA_REGISTERS, - &scsb->scsb_data_reg[index], 1); - return (error); -} - - -/* - * read 1-byte register, mask with read bits (rmask), - * turn ON bits in on_mask, turn OFF bits in off_mask - * write the byte back to register - * NOTE: MUST be called with mutex held - */ -static int -scsb_write_mask(scsb_state_t *scsb, - uchar_t reg, - uchar_t rmask, - uchar_t on_mask, - uchar_t off_mask) -{ - i2c_transfer_t *i2cxferp; - int index, error = 0; - uchar_t reg_data; - - if (scsb_debug & 0x0800) { - cmn_err(CE_NOTE, "scsb_write_mask(,%x,,%x,%x):", - reg, on_mask, off_mask); - } - if (scsb->scsb_state & SCSB_FROZEN && - !(scsb->scsb_state & SCSB_IN_INTR)) { - return (EAGAIN); - } - /* select the register address and read the register */ - i2cxferp = (i2c_transfer_t *)scsb->scsb_i2ctp; - i2cxferp->i2c_flags = I2C_WR_RD; - i2cxferp->i2c_wlen = 1; - i2cxferp->i2c_rlen = 1; - i2cxferp->i2c_wbuf[0] = reg; - i2cxferp->i2c_rbuf[0] = 0; - scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */ - if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) { - error = EIO; - goto wm_error; - } - scsb->scsb_i2c_errcnt = 0; - if (scsb_debug & 0x0800) - cmn_err(CE_NOTE, "scsb_write_mask() read 0x%x", - i2cxferp->i2c_rbuf[0]); - reg_data = i2cxferp->i2c_rbuf[0]; - if (rmask) - reg_data &= rmask; - if (off_mask) - reg_data &= ~off_mask; - if (on_mask) - reg_data |= on_mask; - i2cxferp->i2c_flags = I2C_WR; - i2cxferp->i2c_wlen = 2; - i2cxferp->i2c_wbuf[0] = reg; - i2cxferp->i2c_wbuf[1] = reg_data; - if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) { - error = EIO; - goto wm_error; - } - /* keep shadow registers updated */ - index = SCSB_REG_INDEX(reg); - scsb->scsb_data_reg[index] = reg_data; - if (scsb_debug & 0x0800) - cmn_err(CE_NOTE, "scsb_write_mask() wrote 0x%x", reg_data); - scsb->scsb_i2c_errcnt = 0; - return (error); -wm_error: - scsb->scsb_i2c_errcnt++; - if (scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb->scsb_err_flag = B_TRUE; /* latch error */ - if (scsb->scsb_state & SCSB_SSB_PRESENT) { - if (scsb_debug & 0x0802) - cmn_err(CE_WARN, - "scsb_write_mask(): reg %x %s error, data=%x", - reg, - i2cxferp->i2c_flags & I2C_WR ? "write" : "read", - i2cxferp->i2c_flags & I2C_WR ? - i2cxferp->i2c_wbuf[1] : i2cxferp->i2c_rbuf[0]); - } else { - if (scsb->scsb_i2c_errcnt >= scsb_freeze_count) - scsb_freeze(scsb); - return (EAGAIN); - } - return (error); -} - -/* - * read/write len consecutive single byte registers to/from rbuf - * NOTE: should be called with mutex held - */ -static int -scsb_rdwr_register(scsb_state_t *scsb, int op, uchar_t reg, int len, - uchar_t *rwbuf, int i2c_alloc) -{ - i2c_transfer_t *i2cxferp; - int i, rlen, wlen, index, error = 0; - - if (scsb_debug & 0x0800) { - cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):", - (op == I2C_WR) ? "write" : "read", reg, len); - } - if (scsb->scsb_state & SCSB_FROZEN && - !(scsb->scsb_state & SCSB_IN_INTR)) { - return (EAGAIN); - } - if (i2c_alloc) { - i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP); - if (i2cxferp == NULL) { - if (scsb_debug & 0x0042) - cmn_err(CE_WARN, "scsb_rdwr_register: " - "i2ctx allocation failure"); - return (ENOMEM); - } - } else { - i2cxferp = scsb->scsb_i2ctp; - } - index = SCSB_REG_INDEX(reg); - switch (op) { - case I2C_WR: - wlen = len + 1; /* add the address */ - rlen = 0; - i2cxferp->i2c_wbuf[0] = reg; - for (i = 0; i < len; ++i) { - scsb->scsb_data_reg[index + i] = - i2cxferp->i2c_wbuf[1 + i] = rwbuf[i]; - if (scsb_debug & 0x0080) - cmn_err(CE_NOTE, - "scsb_rdwr_register: writing rwbuf[%d]=0x%x", - i, rwbuf[i]); - } - break; - case I2C_WR_RD: - wlen = 1; /* for the address */ - rlen = len; - i2cxferp->i2c_wbuf[0] = reg; - break; - default: - if (i2c_alloc) - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - return (EINVAL); - } - /* select the register address */ - i2cxferp->i2c_flags = op; - i2cxferp->i2c_rlen = rlen; - i2cxferp->i2c_wlen = wlen; - i2cxferp->i2c_wbuf[0] = reg; - scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */ - if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) { - error = EIO; - } else if (rlen) { - /* copy to rwbuf[] and keep shadow registers updated */ - for (i = 0; i < len; ++i) { - scsb->scsb_data_reg[index + i] = rwbuf[i] = - i2cxferp->i2c_rbuf[i]; - if (scsb_debug & 0x0080) - cmn_err(CE_NOTE, - "scsb_rdwr_register: read rwbuf[%d]=0x%x", - i, rwbuf[i]); - } - } - if (i2c_alloc) - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - if (error) { - scsb->scsb_i2c_errcnt++; - if (scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb->scsb_err_flag = B_TRUE; /* latch error */ - if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) { - if (scsb->scsb_i2c_errcnt >= scsb_freeze_count) - scsb_freeze(scsb); - return (EAGAIN); - } else { - cmn_err(CE_WARN, - "scsb_rdwr_register(): I2C read error from %x", - reg); - } - } else { - scsb->scsb_i2c_errcnt = 0; - } - - return (error); -} - -/* - * Called from scsb_intr() - * First find the fru_info for this fru_id, and set fru_status for callback. - * Then check for a registered call_back entry for this fru_id, - * and if found, call it. - * Recursize call until no EVENTS left in evcode. - */ -static void -check_fru_info(scsb_state_t *scsb, int evcode) -{ - struct scsb_cb_entry *cbe_ptr; - fru_info_t *fru_ptr; - fru_id_t fru_id; - scsb_fru_status_t fru_status; - int i, new_evcode; - - if (scsb_debug & 0x00100001) - cmn_err(CE_NOTE, "check_fru_info(scsb,0x%x)", evcode); - if (evcode == 0) - return; - i = event_to_index((uint32_t)evcode); - new_evcode = evcode & ~(1 << i); - if (i > MCT_MAX_FRUS) { - if (scsb_debug & 0x00100000) - cmn_err(CE_NOTE, - "check_fru_info: index %d out of range", i); - check_fru_info(scsb, new_evcode); - return; - } - fru_id = fru_id_table[i]; - fru_ptr = find_fru_info(fru_id); - if (fru_ptr == (fru_info_t *)NULL) { - check_fru_info(scsb, new_evcode); - return; - } - update_fru_info(scsb, fru_ptr); - if (fru_ptr->fru_status & FRU_PRESENT) { - fru_status = FRU_PRESENT; - } else { - fru_status = FRU_NOT_PRESENT; - if (fru_ptr->fru_type == SSB) { - /* - * WARN against SCB removal if any - * occupied slots are in reset - */ - scsb_freeze_check(scsb); - } - } - /* - * check for an entry in the CallBack table - */ - for (cbe_ptr = scsb_cb_table; cbe_ptr != NULL; - cbe_ptr = cbe_ptr->cb_next) { - if (cbe_ptr->cb_fru_id == fru_id && - cbe_ptr->cb_fru_ptr == fru_ptr) { - if (scsb_debug & 0x00800000) - cmn_err(CE_NOTE, - "check_fru_info: callback for FRU_ID " - "0x%x; device is %spresent", - (int)fru_id, - fru_status == FRU_PRESENT ? - "" : "not "); - (*cbe_ptr->cb_func)( - cbe_ptr->cb_softstate_ptr, - cbe_ptr->cb_event, - fru_status); - break; - } - } - check_fru_info(scsb, new_evcode); -} - -/* - * ----------------------------- - * scsb kstat support functions. - * ----------------------------- - */ -/* - * Create and initialize the kstat data structures - */ -static int -scsb_alloc_kstats(scsb_state_t *scsb) -{ - kstat_named_t *kn; - /* - * scsb_ks_leddata_t for "scsb_leddata" - */ - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, - "scsb_alloc_kstats: create scsb_leddata: %lu bytes", - sizeof (scsb_ks_leddata_t)); - if ((scsb->ks_leddata = kstat_create(scsb_name, scsb->scsb_instance, - SCSB_KS_LEDDATA, "misc", KSTAT_TYPE_RAW, - sizeof (scsb_ks_leddata_t), KSTAT_FLAG_PERSISTENT)) - == NULL) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - scsb->ks_leddata->ks_update = update_ks_leddata; - scsb->ks_leddata->ks_private = (void *)scsb; - if (update_ks_leddata(scsb->ks_leddata, KSTAT_READ) != DDI_SUCCESS) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - kstat_install(scsb->ks_leddata); - /* - * scsb_ks_state_t for "scsb_state" - */ - if (scsb_debug & 0x00080000) - cmn_err(CE_NOTE, - "scsb_alloc_kstats: create scsb_state: %lu bytes", - sizeof (scsb_ks_state_t)); - if ((scsb->ks_state = kstat_create(scsb_name, scsb->scsb_instance, - SCSB_KS_STATE, "misc", KSTAT_TYPE_RAW, - sizeof (scsb_ks_state_t), KSTAT_FLAG_PERSISTENT)) - == NULL) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - scsb->ks_state->ks_update = update_ks_state; - scsb->ks_state->ks_private = (void *)scsb; - if (update_ks_state(scsb->ks_state, KSTAT_READ) != DDI_SUCCESS) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - kstat_install(scsb->ks_state); - /* - * mct_topology_t for "env_topology" - */ - if (scsb_debug & 0x00080000) - cmn_err(CE_NOTE, - "scsb_alloc_kstats: create env_toploogy: %lu bytes", - sizeof (mct_topology_t)); - if ((scsb->ks_topology = kstat_create(scsb_name, scsb->scsb_instance, - SCSB_KS_TOPOLOGY, "misc", KSTAT_TYPE_RAW, - sizeof (mct_topology_t), KSTAT_FLAG_PERSISTENT)) - == NULL) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - scsb->ks_topology->ks_update = update_ks_topology; - scsb->ks_topology->ks_private = (void *)scsb; - if (update_ks_topology(scsb->ks_topology, KSTAT_READ) != DDI_SUCCESS) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - kstat_install(scsb->ks_topology); - /* - * kstat_named_t * 2 for "scsb_evc_register" - */ - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, - "scsb_alloc_kstats: create scsb_evc_register: %lu bytes", - sizeof (kstat_named_t) * 2); - if ((scsb->ks_evcreg = kstat_create(scsb_name, scsb->scsb_instance, - SCSB_KS_EVC_REGISTER, "misc", KSTAT_TYPE_NAMED, 2, - KSTAT_FLAG_PERSISTENT|KSTAT_FLAG_WRITABLE)) == NULL) { - scsb->scsb_state |= SCSB_KSTATS; - scsb_free_kstats(scsb); - return (DDI_FAILURE); - } - scsb->ks_evcreg->ks_update = update_ks_evcreg; - scsb->ks_evcreg->ks_private = (void *)scsb; - kn = KSTAT_NAMED_PTR(scsb->ks_evcreg); - kstat_named_init(&kn[0], "pid_register", KSTAT_DATA_INT64); - kstat_named_init(&kn[1], "pid_unregister", KSTAT_DATA_INT64); - kstat_install(scsb->ks_evcreg); - /* - * Done, set the flag for scsb_detach() and other checks - */ - scsb->scsb_state |= SCSB_KSTATS; - return (DDI_SUCCESS); -} - -static int -update_ks_leddata(kstat_t *ksp, int rw) -{ - scsb_state_t *scsb; - scsb_ks_leddata_t *pks_leddata; - int i, numregs, index, error = DDI_SUCCESS; - uchar_t reg; - - scsb = (scsb_state_t *)ksp->ks_private; - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, "update_ks_leddata: KS_UPDATE%sset", - scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not "); - /* - * Since this is satisfied from the shadow registers, let it succeed - * even if the SCB is not present. It would be nice to return the - * shadow values with a warning. - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (DDI_FAILURE); - * } - */ - if (rw == KSTAT_WRITE) { - return (EACCES); - } - mutex_enter(&scsb->scsb_mutex); - while (scsb->scsb_state & SCSB_KS_UPDATE) { - if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) { - mutex_exit(&scsb->scsb_mutex); - return (EINTR); - } - } - scsb->scsb_state |= SCSB_KS_UPDATE; - mutex_exit(&scsb->scsb_mutex); - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, "update_ks_leddata: updating data"); - pks_leddata = (scsb_ks_leddata_t *)ksp->ks_data; - /* - * Call tonga_slotnum_led_shift() for each register that - * contains Slot 1-5 information, the first register at each base: - * NOK_BASE, OK_BASE, BLINK_OK_BASE - * XXX: breaking register table access rules by not using macros. - */ - /* NOK */ - reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE); - index = SCSB_REG_INDEX(reg); - numregs = SCTRL_LED_NOK_NUMREGS; - i = 0; - if (IS_SCB_P15) - reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]); - else - reg = scsb->scsb_data_reg[index]; - pks_leddata->scb_led_regs[i] = reg; - for (++i, ++index; i < numregs; ++i, ++index) - pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index]; - /* OK */ - reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE); - index = SCSB_REG_INDEX(reg); - numregs += SCTRL_LED_OK_NUMREGS; - if (IS_SCB_P15) - reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]); - else - reg = scsb->scsb_data_reg[index]; - pks_leddata->scb_led_regs[i] = reg; - for (++i, ++index; i < numregs; ++i, ++index) - pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index]; - /* BLINK */ - reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE); - index = SCSB_REG_INDEX(reg); - numregs += SCTRL_BLINK_NUMREGS; - if (IS_SCB_P15) - reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]); - else - reg = scsb->scsb_data_reg[index]; - pks_leddata->scb_led_regs[i] = reg; - for (++i, ++index; i < numregs; ++i, ++index) - pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index]; - mutex_enter(&scsb->scsb_mutex); - scsb->scsb_state &= ~SCSB_KS_UPDATE; - cv_signal(&scsb->scsb_cv); - mutex_exit(&scsb->scsb_mutex); - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, "update_ks_leddata: returning"); - return (error); -} - -static int -update_ks_evcreg(kstat_t *ksp, int rw) -{ - scsb_state_t *scsb; - int error = 0; - kstat_named_t *kn = KSTAT_NAMED_PTR(ksp); - pid_t pid; - - scsb = (scsb_state_t *)ksp->ks_private; - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, "update_ks_evcreg: %s(%d), KS_UPDATE%sset", - rw == KSTAT_READ ? "read" : "write", rw, - scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not "); - /* - * Let this registration succeed - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (DDI_FAILURE); - * } - */ - mutex_enter(&scsb->scsb_mutex); - while (scsb->scsb_state & SCSB_KS_UPDATE) { - if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) { - mutex_exit(&scsb->scsb_mutex); - return (EINTR); - } - } - scsb->scsb_state |= SCSB_KS_UPDATE; - mutex_exit(&scsb->scsb_mutex); - if (rw == KSTAT_READ) { - kn[0].value.i64 = (int64_t)0; - kn[1].value.i64 = (int64_t)0; - } else if (rw == KSTAT_WRITE) { - /* - * kn[0] is "pid_register", kn[1] is "pid_unregister" - */ - if (kn[0].value.i64 != 0 && kn[1].value.i64 == 0) { - pid = (pid_t)kn[0].value.i64; - if (add_event_proc(scsb, pid)) { - if (scsb_debug & 0x02000002) { - cmn_err(CE_WARN, - "update_ks_evcreg: " - "process add failed for %d", - pid); - } - error = EOVERFLOW; - } - } else if (kn[0].value.i64 == 0 && kn[1].value.i64 != 0) { - pid = (pid_t)kn[1].value.i64; - if (del_event_proc(scsb, pid)) { - if (scsb_debug & 0x02000000) { - cmn_err(CE_NOTE, - "update_ks_evcreg: " - "process delete failed for %d", - pid); - } - error = EOVERFLOW; - } - } else if (kn[0].value.i64 == 0 && kn[1].value.i64 == 0) { - /* - * rewind the pointers and counts, zero the table. - */ - rew_event_proc(scsb); - } else { - error = EINVAL; - } - } else { - error = EINVAL; - } - mutex_enter(&scsb->scsb_mutex); - scsb->scsb_state &= ~SCSB_KS_UPDATE; - cv_signal(&scsb->scsb_cv); - mutex_exit(&scsb->scsb_mutex); - return (error); -} - -static int -update_ks_state(kstat_t *ksp, int rw) -{ - scsb_state_t *scsb; - scsb_ks_state_t *pks_state; - int error = DDI_SUCCESS; - uint32_t current_evc; - - scsb = (scsb_state_t *)ksp->ks_private; - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, "update_ks_state: KS_UPDATE%sset", - scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not "); - /* - * Let this succeed based on last known data - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (DDI_FAILURE); - * } - */ - if (rw == KSTAT_WRITE) { - return (EACCES); - } - mutex_enter(&scsb->scsb_mutex); - while (scsb->scsb_state & SCSB_KS_UPDATE) { - if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) { - mutex_exit(&scsb->scsb_mutex); - return (EINTR); - } - } - scsb->scsb_state |= SCSB_KS_UPDATE; - /* - * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence - * by initiating an I2C read from the SCB. If an error occurs, - * scsb_freeze() will be called to update SCB info and scsb state. - */ - if (!(scsb->scsb_state & SCSB_SSB_PRESENT) && - !(scsb->scsb_state & SCSB_FROZEN)) { - uchar_t data; - /* Read the SCB PROM ID */ - if (data = scsb_rdwr_register(scsb, I2C_WR_RD, - (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1)) - if (scsb_debug & 0x00080002) - cmn_err(CE_NOTE, "update_ks_state: SCB/I2C " - "failure %d", data); - } - mutex_exit(&scsb->scsb_mutex); - pks_state = (scsb_ks_state_t *)ksp->ks_data; - pks_state->scb_present = (scsb->scsb_state & SCSB_SCB_PRESENT) ? 1 : 0; - pks_state->ssb_present = (scsb->scsb_state & SCSB_SSB_PRESENT) ? 1 : 0; - pks_state->scsb_frozen = (scsb->scsb_state & SCSB_FROZEN) ? 1 : 0; - if (scsb->scsb_state & SCSB_DEBUG_MODE) - pks_state->scsb_mode = (uint8_t)ENVC_DEBUG_MODE; - else if (scsb->scsb_state & SCSB_DIAGS_MODE) - pks_state->scsb_mode = (uint8_t)ENVCTRL_DIAG_MODE; - else - pks_state->scsb_mode = (uint8_t)ENVCTRL_NORMAL_MODE; - /* - * If scsb_attach() has not completed the kstat installs, - * then there are no event processes to check for. - */ - if (scsb->scsb_state & SCSB_KSTATS) { - switch (check_event_procs(¤t_evc)) { - case EVC_NO_EVENT_CODE: - pks_state->event_code = 0; - break; - case EVC_NEW_EVENT_CODE: - /* FALLTHROUGH */ - case EVC_NO_CURR_PROC: - pks_state->event_code = current_evc; - break; - case EVC_OR_EVENT_CODE: - pks_state->event_code |= current_evc; - break; - case EVC_FAILURE: - pks_state->event_code = 0; - error = DDI_FAILURE; - break; - } - } else { - pks_state->event_code = 0; - } - mutex_enter(&scsb->scsb_mutex); - scsb->scsb_state &= ~SCSB_KS_UPDATE; - cv_signal(&scsb->scsb_cv); - mutex_exit(&scsb->scsb_mutex); - return (error); -} - -static int -update_ks_topology(kstat_t *ksp, int rw) -{ - scsb_state_t *scsb; - mct_topology_t *pks_topo; - fru_info_t *fru_ptr; - int i, val, error = DDI_SUCCESS, slotnum; - - scsb = (scsb_state_t *)ksp->ks_private; - if (scsb_debug & 0x00080001) - cmn_err(CE_NOTE, "update_ks_topology: KS_UPDATE%sset", - scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not "); - /* - * Let this succeed based on last known data - * - * if (scsb->scsb_state & SCSB_FROZEN) { - * return (DDI_FAILURE); - * } - */ - if (rw == KSTAT_WRITE) { - return (EACCES); - } - mutex_enter(&scsb->scsb_mutex); - while (scsb->scsb_state & SCSB_KS_UPDATE) { - if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) { - mutex_exit(&scsb->scsb_mutex); - return (EINTR); - } - } - scsb->scsb_state |= SCSB_KS_UPDATE; - /* - * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence - * by initiating an I2C read from the SCB. If an error occurs, - * scsb_freeze() will be called to update SCB info and scsb state. - */ - if (!(scsb->scsb_state & SCSB_SSB_PRESENT) && - !(scsb->scsb_state & SCSB_FROZEN)) { - uchar_t data; - /* Read the SCB PROM ID */ - if (data = scsb_rdwr_register(scsb, I2C_WR_RD, - (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1)) - if (scsb_debug & 0x00080002) - cmn_err(CE_NOTE, "update_ks_topology: SCB/I2C " - "failure %d", data); - } - mutex_exit(&scsb->scsb_mutex); - pks_topo = (mct_topology_t *)ksp->ks_data; - for (i = SLOT; i < SCSB_UNIT_TYPES; ++i) { - pks_topo->max_units[i] = mct_system_info.max_units[i]; - } - - pks_topo->mid_plane.fru_status = FRU_PRESENT; - pks_topo->mid_plane.fru_unit = (scsb_unum_t)1; - pks_topo->mid_plane.fru_type = mct_system_info.mid_plane.fru_type; - pks_topo->mid_plane.fru_id = mct_system_info.mid_plane.fru_id; - pks_topo->mid_plane.fru_version = mct_system_info.mid_plane.fru_version; - pks_topo->mid_plane.fru_health = MCT_HEALTH_OK; - fru_ptr = mct_system_info.fru_info_list[SLOT]; - for (i = 0; i < pks_topo->max_units[SLOT]; ++i, ++fru_ptr) { - pks_topo->mct_slots[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_slots[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_slots[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_slots[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_slots[i].fru_version = fru_ptr->fru_version; - /* - * XXX: need to check healthy regs to set fru_health - */ - slotnum = tonga_psl_to_ssl(scsb, i+1); - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE, - SCSB_FRU_OP_GET_BITVAL); - pks_topo->mct_slots[i].fru_health = (val) ? - MCT_HEALTH_OK : MCT_HEALTH_NOK; - } - fru_ptr = mct_system_info.fru_info_list[PDU]; - for (i = 0; i < pks_topo->max_units[PDU]; ++i, ++fru_ptr) { - pks_topo->mct_pdu[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_pdu[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_pdu[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_pdu[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_pdu[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_pdu[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[PS]; - for (i = 0; i < pks_topo->max_units[PS]; ++i, ++fru_ptr) { - pks_topo->mct_ps[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_ps[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_ps[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_ps[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_ps[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_ps[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[DISK]; - for (i = 0; i < pks_topo->max_units[DISK]; ++i, ++fru_ptr) { - pks_topo->mct_disk[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_disk[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_disk[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_disk[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_disk[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_disk[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[FAN]; - for (i = 0; i < pks_topo->max_units[FAN]; ++i, ++fru_ptr) { - pks_topo->mct_fan[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_fan[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_fan[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_fan[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_fan[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_fan[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[SCB]; - for (i = 0; i < pks_topo->max_units[SCB]; ++i, ++fru_ptr) { - pks_topo->mct_scb[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_scb[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_scb[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_scb[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_scb[i].fru_version = fru_ptr->fru_version; - /* - * To get the scsb health, if there was no i2c transaction - * until this read, generate an i2c transaction. - */ - if (scsb->scsb_kstat_flag == B_FALSE) { - uchar_t data; - (void) scsb_blind_read(scsb, I2C_WR_RD, - (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1); - } - pks_topo->mct_scb[i].fru_health = ((scsb->scsb_err_flag == - B_TRUE || scsb->scsb_i2c_errcnt > scsb_err_threshold) - ? MCT_HEALTH_NOK : MCT_HEALTH_OK); -#ifdef DEBUG - if (pks_topo->mct_scb[i].fru_health == MCT_HEALTH_NOK) - cmn_err(CE_WARN, "SCSB kstat health:%d", pks_topo-> - mct_scb[i].fru_health); -#endif - scsb->scsb_err_flag = B_FALSE; /* clear error flag once read */ - scsb->scsb_kstat_flag = B_FALSE; /* false? read from i2c */ - } - fru_ptr = mct_system_info.fru_info_list[SSB]; - for (i = 0; i < pks_topo->max_units[SSB]; ++i, ++fru_ptr) { - pks_topo->mct_ssb[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_ssb[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_ssb[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_ssb[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_ssb[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_ssb[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[ALARM]; - for (i = 0; i < pks_topo->max_units[ALARM]; ++i, ++fru_ptr) { - pks_topo->mct_alarm[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_alarm[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_alarm[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_alarm[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_alarm[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_alarm[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[CFTM]; - for (i = 0; i < pks_topo->max_units[CFTM]; ++i, ++fru_ptr) { - pks_topo->mct_cftm[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_cftm[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_cftm[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_cftm[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_cftm[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_cftm[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[CRTM]; - for (i = 0; i < pks_topo->max_units[CRTM]; ++i, ++fru_ptr) { - pks_topo->mct_crtm[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_crtm[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_crtm[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_crtm[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_crtm[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_crtm[i].fru_health = MCT_HEALTH_NA; - } - fru_ptr = mct_system_info.fru_info_list[PRTM]; - for (i = 0; i < pks_topo->max_units[PRTM]; ++i, ++fru_ptr) { - pks_topo->mct_prtm[i].fru_status = fru_ptr->fru_status; - pks_topo->mct_prtm[i].fru_type = fru_ptr->fru_type; - pks_topo->mct_prtm[i].fru_unit = fru_ptr->fru_unit; - pks_topo->mct_prtm[i].fru_id = fru_ptr->fru_id; - pks_topo->mct_prtm[i].fru_version = fru_ptr->fru_version; - pks_topo->mct_prtm[i].fru_health = MCT_HEALTH_NA; - } - mutex_enter(&scsb->scsb_mutex); - scsb->scsb_state &= ~SCSB_KS_UPDATE; - cv_signal(&scsb->scsb_cv); - mutex_exit(&scsb->scsb_mutex); - return (error); -} - -static void -scsb_free_kstats(scsb_state_t *scsb) -{ - if (!(scsb->scsb_state & SCSB_KSTATS)) - return; - /* - * free the allocated kstat data - */ - if (scsb->ks_evcreg != NULL) { - kstat_delete(scsb->ks_evcreg); - } - if (scsb->ks_topology != NULL) { - kstat_delete(scsb->ks_topology); - } - if (scsb->ks_state != NULL) { - kstat_delete(scsb->ks_state); - } - if (scsb->ks_leddata != NULL) { - kstat_delete(scsb->ks_leddata); - } - scsb->ks_leddata = NULL; - scsb->ks_state = NULL; - scsb->ks_topology = NULL; - scsb->ks_evcreg = NULL; - scsb->scsb_state &= ~SCSB_KSTATS; -} - - -/* - * -------------------------------------- - * Miscellaneous scsb internal functions. - * -------------------------------------- - * - * allocate I2C transfer structure - */ -static i2c_transfer_t * -scsb_alloc_i2ctx(i2c_client_hdl_t phandle, uint_t sleep) -{ - i2c_transfer_t *tp; - - if (i2c_transfer_alloc(phandle, &tp, SCSB_DATA_REGISTERS + 2, - SCSB_DATA_REGISTERS + 2, sleep) == I2C_FAILURE) { - return (NULL); - } - return (tp); -} - -/* - * free I2C transfer structure - */ -static void -scsb_free_i2ctx(i2c_client_hdl_t phandle, i2c_transfer_t *tp) -{ - i2c_transfer_free(phandle, tp); -} - -static void -update_fru_info(scsb_state_t *scsb, fru_info_t *fru_ptr) -{ - int index; - uchar_t reg, bit; - fru_info_t *acslot_ptr = NULL; - fru_id_t acslot_id = 0; - if (scsb_debug & 0x00100001) - cmn_err(CE_NOTE, "update_fru_info(scsb,0x%p)", (void *)fru_ptr); - if (fru_ptr == (fru_info_t *)NULL || - fru_ptr->i2c_info == (fru_i2c_info_t *)NULL) - return; - /* - * If this is an Alarm Card update, then we also need to get - * Alarm Card Slot fru_ptr to update it's fru_type, and maybe fru_id - */ - if (fru_ptr->fru_id == fru_id_table[FRU_INDEX(SCTRL_EVENT_ALARM)]) { - /* - * SCTRL_EVENT_SLOT1 == 0x01 so - * fru_id_table[] index for Slot 1 == 0 - */ - acslot_id = fru_id_table[(scsb->ac_slotnum - 1)]; - acslot_ptr = find_fru_info(acslot_id); - } - reg = fru_ptr->i2c_info->syscfg_reg; - bit = fru_ptr->i2c_info->syscfg_bit; - if (reg == 0 && fru_ptr->fru_type == SCB) { - if (scsb->scsb_state & SCSB_SCB_PRESENT) - fru_ptr->fru_status = FRU_PRESENT; - else - fru_ptr->fru_status = FRU_NOT_PRESENT; - } else if (reg) { - index = SCSB_REG_INDEX(reg); - if (scsb->scsb_data_reg[index] & (1 << bit)) { - fru_ptr->fru_status = FRU_PRESENT; - /* - * XXX: need to add version register, and maybe a - * method, to the fru_ptr->i2c_info structure. - * - * fru_ptr->fru_version = (fru_version_t)0; - */ - /* - * Because scsb_intr() sometimes gets the AC present - * INT before the ACSLOT present INT, - * do not check the ACSLOT fru_status - * - * if (acslot_ptr != NULL && acslot_ptr->fru_status == - * FRU_PRESENT) - */ - if (acslot_ptr != NULL) - acslot_ptr->fru_type = (scsb_utype_t)OC_AC; - } else { - fru_ptr->fru_status = FRU_NOT_PRESENT; - /* - * fru_ptr->fru_version = (fru_version_t)0; - */ - if (acslot_ptr != NULL) { - /* AC just removed, but AC Slot is occupied? */ - if (acslot_ptr->fru_status == FRU_PRESENT) - /* for now it's unknown */ - acslot_ptr->fru_type = - (scsb_utype_t)OC_UNKN; - else - acslot_ptr->fru_type = - (scsb_utype_t)OC_UNKN; - } - } - } - if (scsb_debug & 0x00100000) - cmn_err(CE_NOTE, - "update_fru_info: type %d unit %d is %spresent", - fru_ptr->fru_type, fru_ptr->fru_unit, - fru_ptr->fru_status == FRU_PRESENT - ? "" : "not "); -} - -/* - * Convert EVENT code to FRU index - * by finding the highest bit number in 32 bit word - */ -static int -event_to_index(uint32_t evcode) -{ - int i = 0; - if (evcode == 0) - return (MCT_MAX_FRUS - 1); - for (; (evcode >>= 1); i++) - ; - return (i); -} - -#ifdef DEBUG -void -scsb_debug_prnt(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3, - uintptr_t a4, uintptr_t a5) -{ - if (scsb_debug & 0x8000 || - (*fmt == 'X' && scsb_debug & 0x00010000)) { - if (*fmt == 'X') - ++fmt; - prom_printf("scsb: "); - prom_printf(fmt, a1, a2, a3, a4, a5); - prom_printf("\n"); - } -} -#endif - -/* - * event code functions to deliver event codes - * and to manage: - * the event code fifo - * the process handle table for registered processes interested in - * event codes - */ -/* - * Send signal to processes registered for event code delivery - */ -static void -signal_evc_procs(scsb_state_t *scsb) -{ - int i = 0, c = 0; - if (evc_proc_count == 0) - return; - for (; i < EVC_PROCS_MAX; ++i) { - if (evc_procs[i] != NULL) { - if (proc_signal(evc_procs[i], SIGPOLL)) { - if (scsb_debug & 0x02000002) - cmn_err(CE_WARN, - "scsb:signal_evc_procs: " - "signal to %d failed", - ((struct pid *) - evc_procs[i])->pid_id); - (void) del_event_proc(scsb, - ((struct pid *)evc_procs[i])->pid_id); - } - if (++c >= evc_proc_count) { - if (scsb_debug & 0x02000000) { - cmn_err(CE_NOTE, - "signal_evc_procs: signaled " - "%d/%d processes", c, - evc_proc_count); - } - break; - } - } - } -} - -/* - * bump FIFO ptr, taking care of wrap around - */ -static uint32_t * -inc_fifo_ptr(uint32_t *ptr) -{ - if (++ptr >= evc_fifo + EVC_FIFO_SIZE) - ptr = evc_fifo; - return (ptr); -} - -/* ARGSUSED */ -static void -reset_evc_fifo(scsb_state_t *scsb) -{ - evc_wptr = evc_fifo; - evc_rptr = evc_fifo; - evc_fifo_count = 0; -} - -/* - * Called from scsb_intr() when a new event occurs, to put new code in FIFO, - * and signal any interested processes in evc_procs[]. - * Always succeeds. - */ -static void -add_event_code(scsb_state_t *scsb, uint32_t event_code) -{ - if (event_proc_count(scsb) == 0) { - return; - } - *evc_wptr = event_code; - evc_wptr = inc_fifo_ptr(evc_wptr); - if (++evc_fifo_count > EVC_FIFO_SIZE) { - --evc_fifo_count; /* lose the oldest event */ - evc_rptr = inc_fifo_ptr(evc_rptr); - } - if (scsb_debug & 0x01000000) { - cmn_err(CE_NOTE, "add_event_code: 0x%x, FIFO size = %d", - event_code, evc_fifo_count); - } - signal_evc_procs(scsb); -} - -/* - * called from check_event_procs() when the last registered process - * retrieved the oldest event - */ -static uint32_t -del_event_code() -{ - uint32_t evc = 0; - if (!evc_fifo_count) - return (scsb_event_code); - evc = *evc_rptr; - evc_rptr = inc_fifo_ptr(evc_rptr); - --evc_fifo_count; - if (scsb_debug & 0x01000000) { - cmn_err(CE_NOTE, "del_event_code: 0x%x, FIFO size = %d", - evc, evc_fifo_count); - } - return (evc); -} - -/* - * called from check_event_procs() to retrieve the current event code - */ -static uint32_t -get_event_code() -{ - if (!evc_fifo_count) - return (0); - return (*evc_rptr); -} - -/* - * called from an application interface (ie: an ioctl command) - * to register a process id interested in SCB events. - * NOTE: proc_ref() must be called from USER context, so since this is a - * streams driver, a kstat interface is used for process registration. - * return: - * 0 = event_proc was added - * 1 = out of space - */ -/* ARGSUSED */ -static int -add_event_proc(scsb_state_t *scsb, pid_t pid) -{ - int i = 0; - void *curr_proc; - pid_t curr_pid; - if (evc_proc_count >= EVC_PROCS_MAX) - return (1); - curr_proc = proc_ref(); - curr_pid = (pid_t)(((struct pid *)curr_proc)->pid_id); - if (curr_pid != pid) { - if (scsb_debug & 0x02000000) { - cmn_err(CE_WARN, - "add_event_proc: current %d != requestor %d", - curr_pid, pid); - } else { - proc_unref(curr_proc); - return (1); - } - } - for (; i < EVC_PROCS_MAX; ++i) { - if (evc_procs[i] == NULL) { - evc_procs[i] = curr_proc; - evc_proc_count++; - if (scsb_debug & 0x02000000) { - cmn_err(CE_NOTE, - "add_event_proc: %d; evc_proc_count=%d", - pid, evc_proc_count); - } - return (0); - } - } - proc_unref(curr_proc); - return (1); -} - -/* - * called from an application interface (ie: an ioctl command) - * to unregister a process id interested in SCB events. - * return: - * 0 = event_proc was deleted - * 1 = event_proc was not found, or table was empty - */ -/* ARGSUSED */ -static int -del_event_proc(scsb_state_t *scsb, pid_t pid) -{ - int i = 0; - int cnt = 0; - void *this_proc; - if (evc_proc_count == 0) - return (1); - for (; i < EVC_PROCS_MAX; ++i) { - if (evc_procs[i] == NULL) - continue; - this_proc = evc_procs[i]; - if (pid == ((struct pid *)this_proc)->pid_id) { - evc_procs[i] = NULL; - if (--evc_proc_count == 0) { - /* - * reset evc fifo cound and pointers - */ - reset_evc_fifo(scsb); - } - if (scsb_debug & 0x02000000) { - cmn_err(CE_NOTE, - "del_event_proc: %d; evc_proc_count=%d", - pid, evc_proc_count); - } - proc_unref(this_proc); - return (0); - } - if (++cnt >= evc_proc_count) - break; - } - return (1); -} - -/* - * Can be called from an application interface - * to rewind the pointers and counters, and zero the table - * return: - */ -/* ARGSUSED */ -static void -rew_event_proc(scsb_state_t *scsb) -{ - int i = 0; - if (scsb_debug & 0x02000001) { - cmn_err(CE_NOTE, "rew_event_proc: evc_proc_count=%d", - evc_proc_count); - } - for (; i < EVC_PROCS_MAX; ++i) { - if (evc_procs[i] != NULL) { - proc_unref(evc_procs[i]); - evc_procs[i] = NULL; - } - } - evc_proc_count = 0; -} - -/* ARGSUSED */ -static int -event_proc_count(scsb_state_t *scsb) -{ - return (evc_proc_count); -} - -/* - * return: - * 1 = pid was found - * 0 = pid was not found, or table was empty - */ -static int -find_evc_proc(pid_t pid) -{ - int i = 0; - int cnt = 0; - if (evc_proc_count == 0) - return (0); - for (; i < EVC_PROCS_MAX; ++i) { - if (evc_procs[i] == NULL) - continue; - if (pid == ((struct pid *)evc_procs[i])->pid_id) - return (1); - if (++cnt >= evc_proc_count) - break; - } - return (0); -} - -/* - * called from update_ks_state() to compare evc_proc_count with - * evc_requests, also mainted by this same function - * This function could check the current process id, since this will be a user - * context call, and only bump evc_requests if the calling process is - * registered for event code delivery. - * return: - * EVC_NO_EVENT_CODE : no event_code on fifo - * EVC_NO_CURR_PROC : current process not in table, - * but have an event_code - * EVC_NEW_EVENT_CODE : return_evc is new ks_state->event_code - * EVC_OR_EVENT_CODE : OR return_evc with ks_state->event_code - * EVC_FAILURE : unrecoverable error condition. - */ -static int -check_event_procs(uint32_t *return_evc) -{ - void *curr_proc; - pid_t curr_pid = 0; - int return_val = 0; - static int evc_requests = 0; - /* - * get current process handle, and check the event_procs table - */ - if (evc_proc_count == 0) { - *return_evc = del_event_code(); - return_val = EVC_NO_CURR_PROC; - } else { - curr_proc = proc_ref(); - curr_pid = ((struct pid *)curr_proc)->pid_id; - proc_unref(curr_proc); - if (!find_evc_proc(curr_pid)) { - *return_evc = get_event_code(); - return_val = EVC_NO_CURR_PROC; - } else if (++evc_requests >= evc_proc_count) { - evc_requests = 0; - *return_evc = del_event_code(); - return_val = EVC_NEW_EVENT_CODE; - } else { - *return_evc = get_event_code(); - } - if (!return_val) - return_val = EVC_OR_EVENT_CODE; - } - if (scsb_debug & 0x02000000) { - cmn_err(CE_NOTE, "check_event_procs: pid=%d, evc=0x%x, " - "requests=%d, returning 0x%x", curr_pid, - *return_evc, evc_requests, return_val); - } - return (return_val); -} - -static int -scsb_queue_put(queue_t *rq, int count, uint32_t *data, char *caller) -{ - mblk_t *mp; - if (scsb_debug & 0x4001) { - cmn_err(CE_NOTE, "scsb_queue_put(0x%p, %d, 0x%x, %s)", - (void *)rq, count, *data, caller); - } - mp = allocb(sizeof (uint32_t) * count, BPRI_HI); - if (mp == NULL) { - cmn_err(CE_WARN, "%s: allocb failed", - caller); - return (B_FALSE); - } - while (count--) { - *((uint32_t *)mp->b_wptr) = *data; - mp->b_wptr += sizeof (*data); - ++data; - } - putnext(rq, mp); - return (B_TRUE); -} - -/* CLONE */ -static int -scsb_queue_ops(scsb_state_t *scsb, - int op, - int oparg, - void *opdata, - char *caller) -{ - clone_dev_t *clptr; - int clone, find_open, find_available, retval = QOP_FAILED; - - switch (op) { - case QPUT_INT32: - if (scsb->scsb_opens && scsb->scsb_rq != NULL && - scsb_queue_put(scsb->scsb_rq, oparg, - (uint32_t *)opdata, caller) == B_FALSE) { - return (QOP_FAILED); - } - /*FALLTHROUGH*/ /* to look for opened clones */ - case QPROCSOFF: - retval = QOP_OK; - /*FALLTHROUGH*/ - case QFIRST_OPEN: - case QFIND_QUEUE: - find_open = 1; - find_available = 0; - break; - case QFIRST_AVAILABLE: - find_available = 1; - find_open = 0; - break; - } - for (clone = SCSB_CLONES_FIRST; clone < SCSB_CLONES_MAX; clone++) { - clptr = &scsb->clone_devs[clone]; - if (find_open && clptr->cl_flags & SCSB_OPEN) { - if (clptr->cl_rq == NULL) { - cmn_err(CE_WARN, "%s: Clone %d has no queue", - caller, clptr->cl_minor); - return (QOP_FAILED); - } - switch (op) { - case QPROCSOFF: - qprocsoff(clptr->cl_rq); - break; - case QPUT_INT32: - if (scsb_queue_put(clptr->cl_rq, oparg, - (uint32_t *)opdata, caller) - == B_FALSE) { - retval = QOP_FAILED; - } - break; - case QFIRST_OPEN: - return (clone); - case QFIND_QUEUE: - if (clptr->cl_rq == (queue_t *)opdata) { - return (clone); - } - break; - } - } else if (find_available && clptr->cl_flags == 0) { - switch (op) { - case QFIRST_AVAILABLE: - return (clone); - } - } - } - return (retval); -} - -/* - * Find out if a bit is set for the FRU type and unit number in the register - * set defined by the register base table index, base. - * Returns TRUE if bit is set, or FALSE. - */ -static int -scsb_fru_op(scsb_state_t *scsb, scsb_utype_t fru_type, int unit, int base, - int op) -{ - int rc; - uchar_t reg; - int tmp, idx, code, offset; - -#if 0 - reg = SCSB_REG_ADDR(i); - ac_mask = 1 << FRU_OFFSET(SCTRL_EVENT_ALARM, SCTRL_RESET_BASE); - ac_val = scsb->scsb_data_reg[index+1] & ac_mask; -#endif - /* get the event code based on which we get the reg and bit offsets */ - code = FRU_UNIT_TO_EVCODE(fru_type, unit); - /* get the bit offset in the 8bit register corresponding to the event */ - offset = FRU_OFFSET(code, base); - /* register offset from the base register, based on the event code */ - if ((fru_type == ALARM) && (base == SCTRL_RESET_BASE)) - tmp = ALARM_RESET_REG_INDEX(code, base); - else - tmp = FRU_REG_INDEX(code, base); - /* get the global offset of the register in the parent address space */ - reg = SCSB_REG_ADDR(tmp); - /* get the global index of the register in this SCSB's address space */ - idx = SCSB_REG_INDEX(reg); - DEBUG4("scsb_fru_op(start): code=%x, offset=%x, tmp=%x, reg=%x\n", - code, offset, tmp, reg); - switch (op) { - case SCSB_FRU_OP_GET_REG: - rc = reg; - break; - case SCSB_FRU_OP_GET_BITVAL: - rc = (scsb->scsb_data_reg[idx] & (1 << offset)) - >> offset; - break; - case SCSB_FRU_OP_GET_REGDATA: - rc = scsb->scsb_data_reg[idx]; - break; - case SCSB_FRU_OP_SET_REGBIT: - rc = (1 << offset) & 0xff; - break; - default: - break; - } - DEBUG4("scsb_fru_op: unit=%x, base=%x, op=%d, rc=%x\n", unit, base, - op, rc); - return (rc); -} - -/* - * All HSC related functions can fail, but an attempt is made to atleast - * return the right shadow state on get-state function when SCB is removed. - */ -int -scsb_get_slot_state(scsb_state_t *scsb, int pslotnum, int *rstate) -{ - int slotnum, val = 0, rc; - - /* - * When SCB is removed, we could be called with the lock held. - * We call check_config_status anyway since it is a read-only operation - * and HSC could be invoking this function at interrupt context. - * If scsb is already in the doing interrupt postprocess, wait.. - */ - - rc = scsb_check_config_status(scsb); - - /* check if error is because SCB is removed */ - if ((rc != EAGAIN) && (rc != DDI_SUCCESS)) - return (DDI_FAILURE); - slotnum = tonga_psl_to_ssl(scsb, pslotnum); - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_SYSCFG_BASE, - SCSB_FRU_OP_GET_BITVAL); - if (! val) { - *rstate = HPC_SLOT_EMPTY; - return (0); - } - /* - * now, lets determine if it is connected or disconnected. - * If reset is asserted, then the slot is disconnected. - */ - rc = scsb_reset_slot(scsb, pslotnum, SCSB_GET_SLOT_RESET_STATUS); - /* check if error is because SCB is removed */ - if ((rc != EAGAIN) && (rc != DDI_SUCCESS)) - return (DDI_FAILURE); - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_BITVAL); - if (val) - *rstate = HPC_SLOT_DISCONNECTED; - else { - if (scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE, - SCSB_FRU_OP_GET_BITVAL)) { - *rstate = HPC_SLOT_CONNECTED; - } else { - cmn_err(CE_WARN, "%s#%d: Reset Not Asserted on " - "Healthy# Failed slot %d!", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev), slotnum); - *rstate = HPC_SLOT_DISCONNECTED; - } - } - return (0); -} - -int -scsb_reset_slot(scsb_state_t *scsb, int pslotnum, int reset_flag) -{ - int slotnum, error, val, alarm_card = 0; - i2c_transfer_t *i2cxferp; - uchar_t reg; - int index, condition_exists = 0, ac_val; - - if (scsb_debug & 0x8001) - cmn_err(CE_NOTE, "scsb_reset_slot(%d), flag %x", pslotnum, - reset_flag); - if (scsb->scsb_state & SCSB_FROZEN) - return (EAGAIN); - if ((i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, - I2C_NOSLEEP)) == NULL) { - return (ENOMEM); - } - slotnum = tonga_psl_to_ssl(scsb, pslotnum); - - if (scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) { - DEBUG0("alarm card reset/unreset op:\n"); - alarm_card = 1; - } - reg = SCSB_REG_ADDR(SCTRL_RESET_BASE); - index = SCSB_REG_INDEX(reg); - - mutex_enter(&scsb->scsb_mutex); - i2cxferp->i2c_flags = I2C_WR_RD; - i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS; - i2cxferp->i2c_wbuf[0] = reg; - i2cxferp->i2c_wlen = 1; - scsb->scsb_kstat_flag = B_TRUE; /* we did an i2c transaction */ - if ((error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) == 0) { - scsb->scsb_i2c_errcnt = 0; - /* - * XXX: following statements assume 2 reset registers, - * which is the case for our current SCB revisions. - */ - scsb->scsb_data_reg[index] = i2cxferp->i2c_rbuf[0]; - scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1]; - } else { - scsb->scsb_i2c_errcnt++; - if (scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb->scsb_err_flag = B_TRUE; /* latch until kstat */ - if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) { - if (scsb->scsb_i2c_errcnt >= scsb_freeze_count) - mutex_exit(&scsb->scsb_mutex); - scsb_freeze(scsb); - mutex_enter(&scsb->scsb_mutex); - } - cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error" - " reading Reset regs\n", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev)); - error = DDI_FAILURE; - } - - DEBUG2("pre-reset regs = %x,%x\n", scsb->scsb_data_reg[index], - scsb->scsb_data_reg[index+1]); - if ((reset_flag == SCSB_GET_SLOT_RESET_STATUS) || (error)) { - mutex_exit(&scsb->scsb_mutex); - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - return (error); - } - - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_BITVAL); - if (alarm_card) { - ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_BITVAL); - } - if (val && (reset_flag == SCSB_RESET_SLOT)) { - if (alarm_card) { - if (ac_val) { - condition_exists = 1; - DEBUG0("Alarm_RST# already active.\n"); - } -#ifndef lint - else - DEBUG1("Alarm_RST# not active! " - "Slot%d_RST# active!\n", pslotnum); -#endif - } else { - condition_exists = 1; - DEBUG1("Slot%d_RST# already active!\n", pslotnum); - } - } - else - if ((val == 0) && (reset_flag == SCSB_UNRESET_SLOT)) { - if (alarm_card) { - if (!ac_val) { - DEBUG0("Alarm_RST# not active.\n"); - condition_exists = 1; - } -#ifndef lint - else - DEBUG1("Alarm_RST# active" - " Slot%d_RST# not active!\n", - pslotnum); -#endif - } else { - condition_exists = 1; - DEBUG1("Slot%d_RST# already not active!\n", - pslotnum); - } - } - - if (! condition_exists) { - i2cxferp->i2c_flags = I2C_WR; - i2cxferp->i2c_wlen = 2; - i2cxferp->i2c_wbuf[0] = scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, SCSB_FRU_OP_GET_REG); - if (reset_flag == SCSB_RESET_SLOT) { - i2cxferp->i2c_wbuf[1] = - scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_REGDATA) | - scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, - SCSB_FRU_OP_SET_REGBIT); -#ifdef DEBUG /* dont reset Alarm Card line unless in debug mode */ - if (alarm_card) - i2cxferp->i2c_wbuf[1] |= - scsb_fru_op(scsb, ALARM, 1, - SCTRL_RESET_BASE, - SCSB_FRU_OP_SET_REGBIT); -#endif - } else { - i2cxferp->i2c_wbuf[1] = - scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_REGDATA) & - ~(scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, - SCSB_FRU_OP_SET_REGBIT)); -#ifdef DEBUG /* dont Unreset Alarm Card line unless in debug mode */ - if (alarm_card) - i2cxferp->i2c_wbuf[1] &= - scsb_fru_op(scsb, ALARM, 1, - SCTRL_RESET_BASE, - SCSB_FRU_OP_SET_REGBIT); -#endif - } - - if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) { - scsb->scsb_i2c_errcnt++; - if (scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb->scsb_err_flag = B_TRUE; /* latch error */ - mutex_exit(&scsb->scsb_mutex); - if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) { - if (scsb->scsb_i2c_errcnt >= scsb_freeze_count) - scsb_freeze(scsb); - } - cmn_err(CE_WARN, "%s#%d: reset_slot: error writing to" - " Reset regs (op=%d, data=%x)\n", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev), - reset_flag, i2cxferp->i2c_wbuf[1]); - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - return (DDI_FAILURE); - } - - scsb->scsb_i2c_errcnt = 0; - /* now read back and update our scsb structure */ - i2cxferp->i2c_flags = I2C_WR_RD; - i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS; - i2cxferp->i2c_wbuf[0] = reg; - i2cxferp->i2c_wlen = 1; - if ((error = nct_i2c_transfer(scsb->scsb_phandle, - i2cxferp)) == 0) { - scsb->scsb_i2c_errcnt = 0; - scsb->scsb_data_reg[index] = i2cxferp->i2c_rbuf[0]; - scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1]; - } else { - scsb->scsb_i2c_errcnt++; - if (scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb->scsb_err_flag = B_TRUE; /* latch error */ - mutex_exit(&scsb->scsb_mutex); - if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) { - if (scsb->scsb_i2c_errcnt >= scsb_freeze_count) - scsb_freeze(scsb); - } - cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error" - " reading Reset regs (post reset)\n", - ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev)); - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - return (DDI_FAILURE); - } - /* XXX: P1.5 */ - DEBUG2("post-reset regs = %x,%x\n", scsb->scsb_data_reg[index], - scsb->scsb_data_reg[index+1]); - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_BITVAL); -#ifdef DEBUG - if (alarm_card) - ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_BITVAL); -#endif - if (val && (reset_flag == SCSB_UNRESET_SLOT)) { - cmn_err(CE_WARN, "Cannot UnReset Slot %d (reg=%x)\n", - pslotnum, - scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_REGDATA)); -#ifdef DEBUG - if (alarm_card) { - if (ac_val) - cmn_err(CE_WARN, "Cannot Unreset " - "Alarm_RST#.\n"); - } -#endif - } - else - if ((val == 0) && (reset_flag == SCSB_RESET_SLOT)) { - cmn_err(CE_WARN, "Cannot Reset Slot %d, " - "reg=%x\n", pslotnum, - scsb_fru_op(scsb, SLOT, slotnum, - SCTRL_RESET_BASE, - SCSB_FRU_OP_GET_REGDATA)); -#ifdef DEBUG - if (alarm_card) { - if (!ac_val) - cmn_err(CE_WARN, "Cannot reset " - "Alarm_RST#.\n"); - } -#endif - } - } - - mutex_exit(&scsb->scsb_mutex); - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - - return (error); -} - -int -scsb_connect_slot(scsb_state_t *scsb, int pslotnum, int healthy) -{ - int slotnum, count = 0, val; - int slot_flag = 0; - - /* - * If Power needs to be handled, it should be done here. - * Since there is no power handling for now, lets disable - * reset, wait for healthy to come on and then call it - * connected. - * If HLTHY# does not come on (in how long is the question) - * then we stay disconnected. - */ - slotnum = tonga_psl_to_ssl(scsb, pslotnum); - - /* - * P1.5 doesnt require polling healthy as we get an - * interrupt. So we could just update our state as disconnected - * and return waiting for the healthy# interrupt. To make it - * more efficient, lets poll for healthy# a short while since we are - * in the interrupt context anyway. If we dont get a healthy# we - * return, and then wait for the interrupt. Probably the warning - * message needs to be removed then. Need a PROM check flag here. - */ - while ((healthy == B_FALSE) && (count < scsb_healthy_poll_count)) { - if (scsb_read_bhealthy(scsb) != 0) - return (DDI_FAILURE); - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE, - SCSB_FRU_OP_GET_BITVAL); - if (val) { - healthy = B_TRUE; - break; - } - count++; - drv_usecwait(100); /* cant delay(9f) in intr context */ - } - - if (healthy == B_FALSE && count == scsb_healthy_poll_count) { - if (scsb_debug & 0x00004000) - cmn_err(CE_WARN, "%s#%d: no HEALTHY# signal on" - " slot %d", ddi_driver_name(scsb->scsb_dev), - ddi_get_instance(scsb->scsb_dev), pslotnum); - } - - if ((scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) && - (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) - slot_flag = ALARM_CARD_ON_SLOT; - return (hsc_slot_occupancy(pslotnum, 1, slot_flag, healthy)); -} - -int -scsb_disconnect_slot(scsb_state_t *scsb, int occupied, int slotnum) -{ - int slot_flag = 0; - - /* Reset is must at extraction. Move on even if failure. */ - if (scsb_reset_slot(scsb, slotnum, SCSB_RESET_SLOT) != 0) { - /* - * If board is still in slot, which means there is a manual - * disconnection in progress, return failure. - * Otherwise, a board was removed anyway; so we need to - * update the status and move on. - */ - if (occupied == B_TRUE) - return (DDI_FAILURE); - } - /* - * the following bug needs to be fixed. - * When this function is called from scsb_intr, scsb_state already - * clears the 'AC card present' bit. - * However, hsc module doesn't depend on slot_flag during removal. - */ - if ((scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) && - (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) - slot_flag = ALARM_CARD_ON_SLOT; - return (hsc_slot_occupancy(slotnum, occupied, slot_flag, B_FALSE)); -} - -static int -scsb_is_alarm_card_slot(scsb_state_t *scsb, int slotnum) -{ - return ((scsb->ac_slotnum == slotnum)? B_TRUE:B_FALSE); -} - -/* - * Invoked both by the hsc and the scsb module to exchanges necessary - * information regarding the alarm card. - * scsb calls this function to unconfigure the alarm card while the - * hsc calls this function at different times to check busy status, - * and during post hotswap insert operation so that the user process - * if one waiting can configure the alarm card. - */ -int -scsb_hsc_ac_op(scsb_state_t *scsb, int pslotnum, int op) -{ - int rc = B_FALSE; - uint32_t event_code; - - if (!(scsb->scsb_hsc_state & SCSB_HSC_INIT && - scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) { - cmn_err(CE_WARN, - "scsb: HSC not initialized or AC not present!"); - return (rc); - } - switch (op) { - /* hsc -> scsb */ - case SCSB_HSC_AC_BUSY: - if (scsb->scsb_hsc_state & SCSB_ALARM_CARD_IN_USE) - rc = B_TRUE; - break; - - /* API -> scsb */ - /* - * NOTE: this could be called multiple times from envmond if - * the daemon is reinitialized with SIGHUP, or stopped and - * restarted. - */ - case SCSB_HSC_AC_SET_BUSY: - DEBUG0("AC SET BUSY\n"); - if (scsb_debug & 0x00010000) { - cmn_err(CE_NOTE, - "scsb_hsc_ac_op(SCSB_HSC_AC_SET_BUSY)"); - } - scsb->scsb_hsc_state |= SCSB_ALARM_CARD_IN_USE; - rc = B_TRUE; - break; - - /* hsc -> scsb */ - case SCSB_HSC_AC_CONFIGURED: - DEBUG0("AC configured\n"); - if (scsb_debug & 0x00010000) { - cmn_err(CE_NOTE, - "scsb_hsc_ac_op(SCSB_HSC_AC_CONFIGURED)"); - } - /* - * wakeup anyone waiting on AC to be configured - * Send the ALARM_CARD_CONFIGURE Event to all scsb - * open streams. - */ - event_code = SCTRL_EVENT_ALARM_INSERTION; - (void) scsb_queue_ops(scsb, QPUT_INT32, 1, - &event_code, "scsb_hsc_ac_op"); - rc = B_TRUE; - break; - - /* hsc -> scsb */ - case SCSB_HSC_AC_REMOVAL_ALERT: - DEBUG0("AC removal alert\n"); - if (scsb_debug & 0x00010000) { - cmn_err(CE_NOTE, - "scsb_hsc_ac_op(SCSB_HSC_AC_REMOVAL_ALERT)"); - } - /* - * Inform (envmond)alarmcard.so that it should save - * the AC configuration, stop the - * heartbeat, and shutdown the RSC link. - */ - event_code = SCTRL_EVENT_ALARM_REMOVAL; - (void) scsb_queue_ops(scsb, QPUT_INT32, 1, - &event_code, "scsb_hsc_ac_op"); - rc = B_TRUE; - break; - - /* API -> scsb -> hsc */ - case SCSB_HSC_AC_UNCONFIGURE: - DEBUG0("AC unconfigure\n"); - if (scsb_debug & 0x00010000) { - cmn_err(CE_NOTE, - "scsb_hsc_ac_op(SCSB_HSC_AC_UNCONFIG" - "URE), AC NOT BUSY"); - } - /* - * send notification back to HSC to - * unconfigure the AC, now that the env monitor - * has given permission to do so. - */ - scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_IN_USE; - hsc_ac_op((int)scsb->scsb_instance, pslotnum, - SCSB_HSC_AC_UNCONFIGURE, NULL); - rc = B_TRUE; - break; - default: - break; - } - - return (rc); -} - -static void -scsb_healthy_intr(scsb_state_t *scsb, int pslotnum) -{ - int val, slotnum; - int healthy = B_FALSE; - - DEBUG1("Healthy Intr on slot %d\n", pslotnum); - /* - * The interrupt source register can have the healthy - * bit set for non-existing slot, e.g slot 7 on Tonga. - * It can also be seen on the Tonga CPU slot. So we make - * sure we have a valid slot before proceeding. - */ - if (scsb->scsb_state & SCSB_IS_TONGA) { - if (pslotnum > TG_MAX_SLOTS || pslotnum == SC_TG_CPU_SLOT) { - if (scsb_debug & 0x08000000) - cmn_err(CE_NOTE, "Healthy interrupt bit set for" - " slot %d", pslotnum); - return; - } - } else { - if (pslotnum > MC_MAX_SLOTS || pslotnum == SC_MC_CPU_SLOT || - (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES && - pslotnum == SC_MC_CTC_SLOT)) { - if (scsb_debug & 0x08000000) - cmn_err(CE_NOTE, "Healthy interrupt bit set for" - " slot %d", pslotnum); - return; - } - } - - /* - * The board healthy registers are already read before entering - * this routine - */ - slotnum = tonga_psl_to_ssl(scsb, pslotnum); - - /* - * P1.5. Following works since slots 1 through 8 are in the same reg - */ - val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE, - SCSB_FRU_OP_GET_BITVAL); - if (val) - healthy = B_TRUE; - (void) scsb_hsc_board_healthy(pslotnum, healthy); -} - -/* - * This function will try to read from scsb irrespective of whether - * SSB is present or SCB is frozen, to get the health kstat information. - */ -static int -scsb_blind_read(scsb_state_t *scsb, int op, uchar_t reg, int len, - uchar_t *rwbuf, int i2c_alloc) -{ - i2c_transfer_t *i2cxferp; - int i, rlen, wlen, error = 0; - - if (scsb_debug & 0x0800) { - cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):", - (op == I2C_WR) ? "write" : "read", reg, len); - } - - if (i2c_alloc) { - i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP); - if (i2cxferp == NULL) { - if (scsb_debug & 0x0042) - cmn_err(CE_WARN, "scsb_rdwr_register: " - "i2ctx allocation failure"); - return (ENOMEM); - } - } else { - i2cxferp = scsb->scsb_i2ctp; - } - switch (op) { - case I2C_WR: - wlen = len + 1; /* add the address */ - rlen = 0; - i2cxferp->i2c_wbuf[0] = reg; - for (i = 0; i < len; ++i) { - i2cxferp->i2c_wbuf[1 + i] = rwbuf[i]; - if (scsb_debug & 0x0080) - cmn_err(CE_NOTE, - "scsb_rdwr_register: writing rwbuf[%d]=0x%x", - i, rwbuf[i]); - } - break; - case I2C_WR_RD: - wlen = 1; /* for the address */ - rlen = len; - i2cxferp->i2c_wbuf[0] = reg; - break; - default: - if (i2c_alloc) - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - return (EINVAL); - } - /* select the register address */ - i2cxferp->i2c_flags = op; - i2cxferp->i2c_rlen = rlen; - i2cxferp->i2c_wlen = wlen; - i2cxferp->i2c_wbuf[0] = reg; - scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */ - if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) { - error = EIO; - } else if (rlen) { - /* copy to rwbuf[] */ - for (i = 0; i < len; ++i) { - rwbuf[i] = i2cxferp->i2c_rbuf[i]; - if (scsb_debug & 0x0080) - cmn_err(CE_NOTE, - "scsb_rdwr_register: read rwbuf[%d]=0x%x", - i, rwbuf[i]); - } - } - if (i2c_alloc) - scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp); - if (error) { - scsb->scsb_i2c_errcnt++; - if (scsb->scsb_i2c_errcnt > scsb_err_threshold) - scsb->scsb_err_flag = B_TRUE; /* latch error */ - } else { - scsb->scsb_i2c_errcnt = 0; - } - - return (error); -} - -/* - * This function will quiesce the PSM_INT line by masking the - * global PSM_INT and writing 1 to SCB_INIT ( for P1.5 and later ) - * This effectively translates to writing 0x20 to 0xE1 register. - */ -static int -scsb_quiesce_psmint(scsb_state_t *scsb) -{ - register int i; - uchar_t reg, wdata = 0; - uchar_t tmp_reg, intr_addr, clr_bits = 0; - int error, iid, intr_idx, offset; - - /* - * For P1.5, set the SCB_INIT bit in the System Command register, - * and disable global PSM_INT. Before this we need to read the - * interrupt source register corresponding to INIT_SCB and - * clear if set. - */ - if (IS_SCB_P15) { - /* - * Read INTSRC6 and write back 0x20 in case INIT_SCB is set - */ - intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE); - tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15); - iid = SCSB_REG_INDEX(intr_addr); - intr_idx = SCSB_REG_INDEX(tmp_reg) - iid; - offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE); - clr_bits = 1 << offset; - - error = scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg, - 1, &scb_intr_regs[intr_idx], 0); - /* - * Now mask the global PSM_INT and write INIT_SCB in case - * this is an INIT_SCB interrupt - */ - wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT); - i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE); - reg = SCSB_REG_ADDR(i); - error = scsb_rdwr_register(scsb, I2C_WR, reg, 1, - &wdata, 0); - - if (scb_intr_regs[intr_idx] & clr_bits) { - /* - * There is an SCB_INIT interrupt, which we must clear - * first to keep SCB_INIT from keeping PSM_INT asserted. - */ - error = scsb_rdwr_register(scsb, I2C_WR, tmp_reg, - 1, &clr_bits, 0); - } - - if (error) { - cmn_err(CE_WARN, "scsb%d:scsb_quiesce_psmint: " - " I2C TRANSFER Failed", scsb->scsb_instance); - if (scsb_debug & 0x0006) { - cmn_err(CE_NOTE, "scsb_attach: " - " failed to set SCB_INIT"); - } - } - scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED; - } else { /* P1.0 or earlier */ - /* - * read the interrupt source registers, and then - * write them back. - */ - /* read the interrupt register from scsb */ - if (error = scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr, - SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) { - cmn_err(CE_WARN, "scsb_intr: " - " Failed read of interrupt registers."); - scsb->scsb_state &= ~SCSB_IN_INTR; - } - - /* - * Write to the interrupt source registers to stop scsb - * from interrupting. - */ - if (error = scsb_rdwr_register(scsb, I2C_WR, intr_addr, - SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) { - cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt" - " registers."); - scsb->scsb_state &= ~SCSB_IN_INTR; - } - - } - - if (error) - return (DDI_FAILURE); - else - return (DDI_SUCCESS); -} - -/* - * Enables or disables the global PSM_INT interrupt for P1.5, depending - * on the flag, flag = 0 => disable, else enable. - */ -static int -scsb_toggle_psmint(scsb_state_t *scsb, int enable) -{ - int i; - uchar_t reg, on = 0, rmask = 0x0, off = 0; - - if (enable == B_TRUE) { - on = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); - } else { - off = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); - } - - i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE); - reg = SCSB_REG_ADDR(i); - if (scsb_write_mask(scsb, reg, rmask, on, off)) { - cmn_err(CE_WARN, "scsb_toggle_psmint: Cannot turn %s PSM_INT", - enable == 1 ? "on" : "off"); - return (DDI_FAILURE); - } - if (enable == 0) { - scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED; - } else { - scsb->scsb_state |= SCSB_PSM_INT_ENABLED; - } - - return (DDI_SUCCESS); -} - -/* - * This routine is to be used by all the drivers using this i2c bus - * to synchronize their transfer operations. - */ -int -nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran) -{ - int retval, initmux = nct_mutex_init; - - /* - * If scsb interrupt mutex is initialized, also hold the - * interrupt mutex to let the i2c_transfer() to complete - */ - - if (initmux & MUTEX_INIT) { - mutex_enter(scb_intr_mutex); - } - - retval = i2c_transfer(i2c_hdl, i2c_tran); - - if (initmux & MUTEX_INIT) { - mutex_exit(scb_intr_mutex); - } - - return (retval); -} diff --git a/usr/src/uts/sun4u/montecarlo/io/scsb.conf b/usr/src/uts/sun4u/montecarlo/io/scsb.conf deleted file mode 100644 index fb856c4325..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/scsb.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2001 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# force attach driver to support hotplug activity -# -ddi-forceattach=1; diff --git a/usr/src/uts/sun4u/montecarlo/io/se.conf b/usr/src/uts/sun4u/montecarlo/io/se.conf deleted file mode 100644 index 3011f6cfcb..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/se.conf +++ /dev/null @@ -1,39 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 1999-2000 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" -# -# Configuration file for Alarm Card Serial Port driver only. -# All these properties are laid atop OBP created properties at cold swap -# or by Solaris during hotswap. -# -interrupts=1 -reg=0x14,0x400000,0x80 -ssp-console-modes="115200,8,n,1,-" -ssp-control-modes="115200,8,n,1,-" -interrupt-priorities=8 -ssp-control=1 -ssp-console=0 -device_type="serial"; diff --git a/usr/src/uts/sun4u/montecarlo/io/ttymux.conf b/usr/src/uts/sun4u/montecarlo/io/ttymux.conf deleted file mode 100644 index eb73d455dd..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/ttymux.conf +++ /dev/null @@ -1,38 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#pragma ident "%Z%%M% %I% %E% SMI" -# - -# Global properties - -upa-portid = 0x0; -sm-trlv = 0x0; # debug trace. -sm-max-units = 6; # max no. of linked lower streams. -sm-minor-cnt = 0; # number of extra device minors. -sm-refuse-opens = 0; # unless associated -sm-ctrla-abort-on = 1; # software break sequence enabled -sm-break-abort-on = 0; # hardware break disabled -abort-str = "^m~^b"; # the software break sequence diff --git a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c b/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c deleted file mode 100644 index 0a090a050c..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.c +++ /dev/null @@ -1,930 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * This is a dacf module based upon the Extensions to Device Autoconfiguration - * project. See PSARC/1998/212 for more details. - * - * This module provides the dacf functions - * to be called after a driver has attached and before it detaches. - * The post attach functionality is used to autoconfigure a serial console - * multiplexer if the OBP console is a multiplexer. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/cmn_err.h> -#include <sys/user.h> -#include <sys/vfs.h> -#include <sys/vnode.h> -#include <sys/systm.h> -#include <sys/file.h> -#include <sys/klwp.h> -#include <sys/stropts.h> -#include <sys/stream.h> -#include <sys/strsubr.h> - -#include <sys/consdev.h> -#include <sys/kbio.h> -#include <sys/debug.h> -#include <sys/reboot.h> -#include <sys/termios.h> -#include <sys/clock.h> - -#include <sys/kstr.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/sunndi.h> -#include <sys/modctl.h> -#include <sys/ddi_impldefs.h> -#include <sys/ndi_impldefs.h> - -#include <sys/errno.h> -#include <sys/devops.h> -#include <sys/note.h> -#include <sys/open.h> -#include <sys/kmem.h> -#include <sys/dacf.h> -#include <sys/promif.h> - -#include "ttymux_dacf.h" - -#pragma weak find_platform_consoles -extern char *find_platform_consoles(sm_mux_state_t *_m, dev_info_t *_di, - dev_t _d, uint_t _f); - -#define platform_consoles(_m, _di, _d, _f) \ - (find_platform_consoles != NULL \ - ? find_platform_consoles(_m, _di, _d, _f) \ - : (nulldev(_m, _di, _d, _f), (char *)0)) - -/* - * External functions - */ -extern uintptr_t space_fetch(char *key); -extern int space_store(char *key, uintptr_t ptr); -extern void ttymux_dprintf(int l, const char *fmt, ...); -extern int prom_ihandle_to_path(ihandle_t, char *, uint_t); -extern void prom_interpret(char *, uintptr_t, uintptr_t, uintptr_t, - uintptr_t, uintptr_t); -extern ihandle_t prom_stdin_ihandle(); -extern ihandle_t prom_stdout_ihandle(); - -extern vnode_t *rconsvp; /* redirection device */ - -/* - * Dacf entry points - */ -static int ttymux_config(dacf_infohdl_t, dacf_arghdl_t, int); - -/* - * Internal functions - */ -static dacf_op_t ttymuxconfig_op[] = { - { DACF_OPID_POSTATTACH, ttymux_config }, - { DACF_OPID_END, NULL }, -}; - -static dacf_opset_t opsets[] = { - { "ttymux_config", ttymuxconfig_op }, - { NULL, NULL } -}; - -struct dacfsw dacfsw = { - DACF_MODREV_1, - opsets, -}; - -struct modldacf modldacf = { - &mod_dacfops, /* Type of module */ - "ttymux DACF", - &dacfsw -}; - -struct modlinkage modlinkage = { - MODREV_1, (void *)&modldacf, NULL -}; - -/*LINTLIBRARY*/ - -/* - * The following minor nodes can be linked underneath the serial - * console multiplexer. - * These are the only ones currently tested. - * (NOTE: Devices of device_type serial are also allowed to be used as - * additional consoles). - * Disallow plumbing of untested node types. - */ -static const char * const supported_types[] = { - DDI_NT_SERIAL, (char *const)NULL -}; - -#define OFLAGS FREAD|FWRITE|FNOCTTY|FNONBLOCK - -#define INPUT_ALIAS "multiplexer-input-devices" -#define OUTPUT_ALIAS "multiplexer-output-devices" -#define OBPDEV 0x100 -#define FORTH_STRINGLEN 1024 -#define MUXDEVTYPE "SUNW,serial-multiplexer" - -static char fth_fmt[] = -"\" get-device-list\" " /* ( method-str method-len ) */ -"h# %p " /* ( method-str method-len ihandle ) */ -"$call-method " /* ( ihandle_n-1 ... ihandle n ) */ -"dup " /* ( ihandle_n-1 ... ihandle n n ) */ -"h# %p " /* ( ihandle_n-1 ... ihandle n n numfound ) */ -"l! " /* ( ihandle_n-1 ... ihandle n ) */ -"0 " /* ( ihandle_n-1 ... ihandle n 0 ) */ -"do " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i ) */ -" i " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i index ) */ -" h# %x " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i index max) */ -" < if " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i ) */ -" h# %p " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i buf ) */ -" i " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i buf index) */ -" 4 * + " /* ( ihandle_n-1 ... ihandle_i+1 ihandle_i buf' ) */ -" l! " /* ( ihandle_n-1 ... ihandle_i+1 ) */ -" else " /* */ -" drop " /* ( ihandle_n-1 ... ihandle_i+1 ) */ -" then " /* */ -"loop "; /* ( ihandle_n-1 ... ihandle_i+1 ) */ - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_fini() -{ - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -static int -ioctl_cmd(vnode_t *avp, int cmd, void *data, int datasize, int *bytecnt) -{ - struct strioctl ios; - int rval; - - ios.ic_timout = 0; - ios.ic_cmd = cmd; - ios.ic_dp = (char *)data; - ios.ic_len = datasize; - - rval = kstr_ioctl(avp, I_STR, (intptr_t)&ios); - if (bytecnt) - *bytecnt = ios.ic_len; - return (rval); -} - -/* - * How many consoles are actually linked underneath the Solaris console - * multiplexer. - */ -static int -usable_consoles(sm_mux_state_t *sp, uint_t *iconsoles, uint_t *oconsoles) -{ - uint_t j, cnt, icnt = 0u, ocnt = 0u; - - mutex_enter(&sp->sm_cons_mutex); - for (j = 0, cnt = 0; j < sp->sm_cons_cnt; j++) - if (sp->sm_cons_links[j].sm_muxid != 0) { - sm_console_t *cn = &sp->sm_cons_links[j]; - if (cn->sm_mode & FORINPUT) - icnt += 1; - if (cn->sm_mode & FOROUTPUT) - ocnt += 1; - if (cn->sm_mode == FORIO) - cnt += 1; - } - mutex_exit(&sp->sm_cons_mutex); - *iconsoles = icnt; - *oconsoles = ocnt; - return (cnt); -} - -/* - * Before linking a device underneath a serial multiplexer check that - * its minor node type is supported. - */ -static boolean_t -compatible_console(dev_t dev) -{ - int circ; - boolean_t compatible; - char *const *nodetype; - struct ddi_minor_data *dmdp; - dev_info_t *dip; - char devtype[32]; - int len; - - /* - * Find the node nodetype to verify that the current version of - * the code supports its use as a console - * Supported types are listed in the array supported_types - */ - if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) { - ttymux_dprintf(DPRINT_L2, "No dip for %d:%d\n", - getmajor(dev), getminor(dev)); - return (B_FALSE); - } - - compatible = B_FALSE; - len = sizeof (devtype); - - ndi_devi_enter(dip, &circ); - for (dmdp = DEVI(dip)->devi_minor; dmdp != NULL; dmdp = dmdp->next) { - struct ddi_minor_data *mdp = dmdp; - - if (mdp->ddm_dev == dev) { - - ttymux_dprintf(DPRINT_L0, "compat: matched dev\n"); - /* - * check the OBP device_type property first - * its a good bet that it will be compatible - * if it has the value serial. - */ - if (ddi_prop_op(DDI_DEV_T_ANY, dip, - PROP_LEN_AND_VAL_BUF, 0, "device_type", - (caddr_t)devtype, &len) == DDI_PROP_SUCCESS && - strcmp(devtype, "serial") == 0) { - compatible = B_TRUE; - } else { - for (nodetype = - (char *const *)&supported_types[0]; - *nodetype != (char *const)NULL; - nodetype++) { - if (strcmp(*nodetype, - mdp->ddm_node_type) == 0) { - compatible = B_TRUE; - break; - } - } - } - break; - } - } - ndi_devi_exit(dip, circ); - ddi_release_devi(dip); - - /* - * The current version of the implementation has only been tested - * with a serial multiplexer. - */ - - ttymux_dprintf(DPRINT_L0, "%d:%d is %s\n", getmajor(dev), - getminor(dev), (compatible) ? "compatible" : "incompatible"); - - return (compatible); -} - -/* - * get-device-list ( -- [ihandle n-1, ... ihandle], n ) - * Call the "get-device-list" method of an OBP device. - * ihdl - ihandle of the OBP device whose method is to be called - * ihdls - array of ihandles returned to the caller - * maxi - length of the ihdls array - */ -static int -get_device_list(ihandle_t ihdl, ihandle_t *ihdls, size_t maxi) -{ - int numfound = -1; - char fstr[FORTH_STRINGLEN]; - - if (snprintf(fstr, FORTH_STRINGLEN, fth_fmt, (caddr32_t)ihdl, - &numfound, maxi, ihdls) > FORTH_STRINGLEN) { - ttymux_dprintf(DPRINT_L3, - "WARNING: forth buffer size is too small.\n"); - return (0); - } - - prom_interpret(fstr, 0, 0, 0, 0, 0); - - ttymux_dprintf(DPRINT_L0, "ihdl 0x%p cnt %d\n", - (caddr32_t)ihdl, numfound); - - return (numfound); -} - -/* - * Read an OBP property and return the result in propval. - * The caller is responsible for freeing the memory. - */ -static int -read_prop(pnode_t node, char *propname, char **propval) -{ - int proplen = -1; - - if (node == OBP_BADNODE || - (proplen = prom_getproplen(node, propname)) <= 0) - return (proplen); - - *propval = kmem_zalloc(proplen + 1, KM_SLEEP); - (void) prom_getprop(node, propname, *propval); - - return (proplen); -} - -/* - * Parse a white space separated list of tokens and call - * the input action with each parsed token. - */ -static void -parse(sm_mux_state_t *ms, char *p, - void (*action)(sm_mux_state_t *, char *, void *), void *arg) -{ - char *e, *tok = NULL; - - if (p == 0 || *p == 0) - return; - - e = p + strlen(p); - - do { - switch (*p) { - case ' ': - case '\t': - if (tok != NULL) { - *p = 0; - action(ms, tok, arg); - tok = NULL; - *p = ' '; - } - break; - default: - if (tok == NULL) { - tok = p; - } - break; - } - } while (++p < e); - - if (tok != NULL) - action(ms, tok, arg); -} - -/* - * Search for a console structure matching a device path. - * Return a new initialized structure if one does not exist. - */ -sm_console_t * -get_aconsole(sm_mux_state_t *ms, char *path) -{ - sm_console_t *cn; - int j; - - for (cn = ms->sm_cons_links, j = 0; - j < ms->sm_cons_cnt; cn++, j++) { - if (cn->sm_path && strcmp(cn->sm_path, path) == 0) - break; - } - if (j == ms->sm_cons_cnt) { - if (j + 1 == TTYMUX_MAX_LINKS) { - cn = NULL; - } else { - bzero((caddr_t)cn, sizeof (*cn)); - ms->sm_cons_cnt += 1; - } - } - return (cn); -} - -/* - * Create a new console structure representing the device - * identified by path. The void * argument indicates which I/O - * mode the device will support. - */ -static void -add_aconsole(sm_mux_state_t *ms, char *path, void *arg) -{ - sm_console_t *cn; - char *cpath; - - if (*path == '/') { - cpath = kmem_alloc(strlen(path) + 1, KM_SLEEP); - (void) strcpy(cpath, path); - } else if (read_prop(prom_alias_node(), path, &cpath) <= 0) { - return; - } - - /* - * Device paths should have a minor name - if its missing assume - * it should be :a! - */ - if (strrchr(cpath, ':') == NULL) { - char *p; - size_t len = strlen(cpath) + 1; - - p = kmem_zalloc(len + 2, KM_SLEEP); - (void) strcpy(p, cpath); - (void) strcat(p, ":a"); /* assume :a ! */ - kmem_free(cpath, len); - cpath = p; - } - if ((cn = get_aconsole(ms, cpath)) != NULL) { - cn->sm_obp_con = ((uint_t)(uintptr_t)arg & OBPDEV) ? - B_TRUE : B_FALSE; - cn->sm_mode |= (io_mode_t)((uint_t)(uintptr_t)arg & FORIO); - if (cn->sm_path != NULL) - kmem_free(cn->sm_path, strlen(cn->sm_path) + 1); - cn->sm_path = cpath; - } else { - ttymux_dprintf(DPRINT_L3, "Too many " - " consoles - ignoring %s\n", cpath); - kmem_free(cpath, strlen(cpath) + 1); - } -} - -/* - * Discover which consoles OBP is using. - */ -static int -find_obp_consoles(sm_mux_state_t *ms, io_mode_t mode) -{ - sm_console_t *cn; - int i, cnt; - char *devpath; - ihandle_t ihdls[TTYMUX_MAX_LINKS]; - ihandle_t stdihdl; - - if (mode == FORINPUT) - stdihdl = ms->sm_cons_stdin.sm_i_ihdl; - else if (mode == FOROUTPUT) - stdihdl = ms->sm_cons_stdout.sm_o_ihdl; - else - return (EINVAL); - devpath = kmem_alloc(MAXPATHLEN+2, KM_SLEEP); - - cnt = get_device_list(stdihdl, ihdls, TTYMUX_MAX_LINKS); - - for (i = 0; i < cnt; i++) { - - if (prom_ihandle_to_path(ihdls[i], devpath, MAXPATHLEN) == 0) - continue; - /* - * If the minor name is not part of the path and there is - * more than one minor node then ddi_pathname_to_dev_t - * can fail to resolve the path correctly (it's an OBP - * problem)!!! If there's no minor name then assume the default - * minor name (:a). - */ - if (strrchr(devpath, ':') == NULL) - (void) strcat(devpath, ":a"); /* assume :a ! */ - - if ((cn = get_aconsole(ms, devpath)) == 0) { - ttymux_dprintf(DPRINT_L3, "Too many " - " consoles - ignoring %s\n", devpath); - continue; - } - - cn->sm_mode |= mode; - cn->sm_obp_con = B_TRUE; - if (mode == FORINPUT) - cn->sm_i_ihdl = ihdls[i]; - else - cn->sm_o_ihdl = ihdls[i]; - if (cn->sm_path == NULL) { - cn->sm_path = kmem_alloc(strlen(devpath) + 1, KM_SLEEP); - (void) strcpy(cn->sm_path, devpath); - } - - } - kmem_free(devpath, MAXPATHLEN + 2); - - return (0); -} - -/* - * Convert a file system path into a dev_t - */ -static dev_t -fs_devtype(char *fspath) -{ - vnode_t *vp = NULL; - dev_t dev; - - if (fspath == 0 || - vn_open(fspath, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0) != 0) { - return (NODEV); - } else { - dev = vp->v_rdev; - VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL); - VN_RELE(vp); - return (dev); - } -} - -/* - * Convert a device tree path into a dev_t - */ -static dev_t -di_devtype(char *path) -{ - dev_t dev; - - if (path == 0 || *path == 0) - return (NODEV); - - ttymux_dprintf(DPRINT_L0, "loading device %s\n", path); - dev = ddi_pathname_to_dev_t(path); - - return (dev); -} - - -static int -open_stream(vnode_t **vp, int *fd, dev_t dev) -{ - file_t *fp; - int rv; - - /* create a vnode for the device and open it */ - *vp = makespecvp(dev, VCHR); - if ((rv = VOP_OPEN(vp, FREAD+FWRITE+FNOCTTY, CRED(), NULL)) != 0) { - goto out2; - } - /* Associate a file pointer with the vnode */ - if ((rv = falloc(*vp, FREAD+FWRITE+FNOCTTY, &fp, NULL)) != 0) { - goto out1; - } - mutex_exit(&fp->f_tlock); /* must be called single threaded */ - /* Allocate a file descriptor (any non-negative integer will suffice) */ - if ((*fd = ufalloc(0)) == -1) { - rv = EMFILE; - goto out1; - } - /* associate the file pointer with the fd */ - setf(*fd, fp); - return (0); - -out1: - VOP_CLOSE(*vp, FREAD+FWRITE+FNOCTTY, 1, (offset_t)0, CRED(), NULL); -out2: - VN_RELE(*vp); - return (rv); -} - -/* - * Plumb a device specified by the sm_console_t argument underneath the - * serial multiplexer indicated by the vnode_t argument. - */ -static int -link_aconsole(vnode_t *mux_avp, sm_console_t *cn) -{ - vnode_t *lvp; - int lfd; - int rv, rval; - ttymux_assoc_t assoc; - struct termios tc; - - ASSERT(cn->sm_path); - - /* get an open vnode for the device */ - if ((rv = open_stream(&lvp, &lfd, cn->sm_dev)) != 0) - return (rv); - - /* - * Enable the receiver on the lower device since it will - * be used by OBP. - */ - if ((rv = ioctl_cmd(lvp, TCGETS, &tc, sizeof (tc), 0)) == 0) { - tc.c_cflag |= CREAD; - rv = ioctl_cmd(lvp, TCSETS, &tc, sizeof (tc), 0); - } - if (rv != 0) - ttymux_dprintf(DPRINT_L3, - "DACF: Failed to enable console receiver [error %d]\n", rv); - - /* - * Pop all the modules off the stream prior to linking it. - */ - do { - rv = strioctl(lvp, I_POP, 0, 0, K_TO_K, CRED(), &rval); - } while (rv == 0); - - if (rv != EINVAL) { - ttymux_dprintf(DPRINT_L3, - "Failed to pop all modules: error %d", rv); - goto out; - } - - if ((rv = strioctl(mux_avp, I_PLINK, (intptr_t)lfd, - FREAD+FWRITE+FNOCTTY, K_TO_K, CRED(), &(cn->sm_muxid))) != 0) { - - ttymux_dprintf(DPRINT_L3, - "Failed to link device: error %d", rv); - goto out; - } - /* close the linked device */ - (void) closeandsetf(lfd, NULL); - /* - * Now tell the mux to associate the new stream - */ - assoc.ttymux_udev = mux_avp->v_rdev; - assoc.ttymux_ldev = cn->sm_dev; - assoc.ttymux_linkid = cn->sm_muxid; - assoc.ttymux_tag = 0; - assoc.ttymux_ioflag = cn->sm_mode; - if ((rv = ioctl_cmd(mux_avp, TTYMUX_ASSOC, - (void *)&assoc, sizeof (assoc), 0)) != 0) { - ttymux_dprintf(DPRINT_L3, - "Failed to associate %d:%d with the console\n", - getmajor(cn->sm_dev), getminor(cn->sm_dev)); - - if (strioctl(mux_avp, I_PUNLINK, (intptr_t)cn->sm_muxid, 0, - K_TO_K, CRED(), &rval) != 0) - ttymux_dprintf(DPRINT_L3, - "Can't unlink %d:%d - Closing vnode\n", - getmajor(cn->sm_dev), getminor(cn->sm_dev)); - - } - return (rv); - -out: - VOP_CLOSE(lvp, FREAD+FWRITE+FNOCTTY, 1, (offset_t)0, CRED(), NULL); - VN_RELE(lvp); - return (rv); -} - -static int -enable_aconsole(sm_mux_state_t *ms, sm_console_t *cn, vnode_t *muxvp) -{ - ttymux_assoc_t assoc; - - ASSERT(cn && cn->sm_dev != NODEV); - - assoc.ttymux_ldev = cn->sm_dev; - - cn->sm_muxid = (ioctl_cmd(muxvp, TTYMUX_GETLINK, - (void *)&assoc, sizeof (assoc), 0) == 0) ? assoc.ttymux_linkid : 0; - - if (cn->sm_muxid != 0) - return (0); /* already linked */ - else - return (link_aconsole(muxvp, cn)); -} - -/* - * Enable all discovered consoles such that they can provide real I/O. - * The discovered list is stored in the sm_mux_state_t pointer. - */ -static int -enable_all_consoles(sm_mux_state_t *ms, vnode_t *muxvp) -{ - sm_console_t *cn; - uint_t j; - - ttymux_dprintf(DPRINT_L0, "Enable %d devices\n", ms->sm_cons_cnt); - for (cn = ms->sm_cons_links, j = 0; - j < ms->sm_cons_cnt; cn++, j++) { - - if (cn->sm_path == NULL) - continue; - - if ((strstr(cn->sm_path, "/dev") == cn->sm_path && - (cn->sm_dev = fs_devtype(cn->sm_path)) == NODEV) || - (cn->sm_dev = di_devtype(cn->sm_path)) == NODEV) { - - ttymux_dprintf(DPRINT_L0, - "Cannot find a driver for device: %s\n", - cn->sm_path ? cn->sm_path : ""); - continue; - } - ttymux_dprintf(DPRINT_L0, "Enabling %d:%d\n", - getmajor(cn->sm_dev), getminor(cn->sm_dev)); - - /* - * Refuse requests to use devices as consoles which have an - * unsupported minor node type. - */ - if (compatible_console(cn->sm_dev) == B_FALSE) - continue; - - /* - * Enable a console device by linking the target console - * underneath the ttymux minor node that has been specified - * in a DACF reservation (see /etc/dacf.conf). - */ - (void) enable_aconsole(ms, cn, muxvp); - } - return (0); -} - -static int -find_consoles(sm_mux_state_t *ms, dev_info_t *dip, dev_t dev) -{ - int len; - char *propval; - char devtype[32]; - pnode_t node; - uint_t flags; - - /* - * Look for target consoles based on options node properties - */ - node = prom_optionsnode(); - if ((len = read_prop(node, INPUT_ALIAS, &propval)) > 0) { - parse(ms, propval, add_aconsole, (void *)FORINPUT); - kmem_free(propval, len + 1); - } - if ((len = read_prop(node, OUTPUT_ALIAS, &propval)) > 0) { - parse(ms, propval, add_aconsole, (void *)FOROUTPUT); - kmem_free(propval, len + 1); - } - - /* - * Look for platform specific target consoles. - * Assume that they are OBP consoles and used for both input and output. - */ - flags = (uint_t)FORIO | OBPDEV; - if ((propval = platform_consoles(ms, dip, dev, flags)) != NULL) { - parse(ms, propval, add_aconsole, (void *)(uintptr_t)flags); - kmem_free(propval, strlen(propval) + 1); - } - - /* - * Discover which consoles OBP is actually using according to - * interfaces proposed by case number FWARC/262. - */ - len = sizeof (devtype); - if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 0, - "device_type", (caddr_t)devtype, &len) == DDI_PROP_SUCCESS && - strcmp(devtype, "serial") == 0 && - ddi_prop_exists(DDI_DEV_T_ANY, dip, 0, MUXDEVTYPE) == 1) { - - (void) find_obp_consoles(ms, FORINPUT); - (void) find_obp_consoles(ms, FOROUTPUT); - - } - ttymux_dprintf(DPRINT_L0, "%d consoles configured\n", - ms->sm_cons_cnt); - return (ms->sm_cons_cnt); -} - -static int -validate_reservation(dacf_infohdl_t di, dev_info_t **dip, dev_t *dev, - io_mode_t *mode) -{ - char *dname, *nname, *ipath, *opath; - - if ((dname = (char *)dacf_driver_name(di)) == NULL) - return (EINVAL); - - if ((*dip = dacf_devinfo_node(di)) == NULL) - return (EINVAL); - - *dev = makedevice(ddi_driver_major(*dip), dacf_minor_number(di)); - - if (*dev == NODEV || *dip == NULL || strcmp(dname, TTYMUX_DRVNAME) != 0) - return (EINVAL); - else if (getminor(*dev) != (minor_t)0) - return (EINVAL); /* minor 0 is special */ - else if (rconsvp != NULL || space_fetch(TTYMUXPTR) != NULL) - return (EAGAIN); /* already configured */ - - opath = prom_stdoutpath(); - ipath = prom_stdinpath(); - nname = ddi_node_name(*dip); - *mode = 0; - - if (ipath != NULL && strstr(ipath, nname) != 0) - *mode = FORINPUT; - if (opath != NULL && strstr(opath, nname) != 0) - *mode |= FOROUTPUT; - if ((*mode & FORIO) == 0) - return (EINVAL); - if ((*mode & FOROUTPUT) == 0) { - ttymux_dprintf(DPRINT_L3, - "Warning: multiplexer is not the output device\n"); - } - if ((*mode & FORINPUT) == 0) { - ttymux_dprintf(DPRINT_L3, - "Warning: multiplexer is not the input device\n"); - } - return (0); -} - -/* - * This operation set is for configuring the ttymux driver for use as - * the system console. - * It must run before consconfig configures the Solaris console. - */ -/*ARGSUSED*/ -static int -ttymux_config(dacf_infohdl_t info_hdl, dacf_arghdl_t arg_hdl, int flags) -{ - sm_mux_state_t *ms; - io_mode_t mode; - dev_t dev; - dev_info_t *dip; - uint_t i, icnt = 0, ocnt = 0; - int rv; - vnode_t *muxvp; - - ttymux_dprintf(DPRINT_L0, "\n"); - - if ((rv = validate_reservation(info_hdl, &dip, &dev, &mode)) != 0) { - ttymux_dprintf(DPRINT_L0, "reservation ignored (%d)\n", rv); - return (DACF_SUCCESS); - } - - ms = kmem_zalloc(sizeof (*ms), KM_SLEEP); - - mutex_init(&ms->sm_cons_mutex, NULL, MUTEX_DRIVER, NULL); - - for (i = 0; i < TTYMUX_MAX_LINKS; i++) - ms->sm_cons_links[i].sm_dev = NODEV; - - ms->sm_cons_stdin.sm_dev = ms->sm_cons_stdout.sm_dev = NODEV; - if (mode & FORINPUT) - ms->sm_cons_stdin.sm_dev = dev; - if (mode & FOROUTPUT) - ms->sm_cons_stdout.sm_dev = dev; - ms->sm_cons_stdin.sm_i_ihdl = prom_stdin_ihandle(); - ms->sm_cons_stdout.sm_o_ihdl = prom_stdout_ihandle(); - - if (prom_is_openprom()) { - pnode_t node = prom_optionsnode(); - - if (prom_getproplen(node, INPUT_ALIAS) > 0) { - ms->sm_ialias = kmem_alloc( - strlen(INPUT_ALIAS) + 1, KM_SLEEP); - (void) strcpy(ms->sm_ialias, INPUT_ALIAS); - } - if (prom_getproplen(node, OUTPUT_ALIAS) > 0) { - ms->sm_oalias = kmem_alloc( - strlen(OUTPUT_ALIAS) + 1, KM_SLEEP); - (void) strcpy(ms->sm_oalias, OUTPUT_ALIAS); - } - } - - (void) find_consoles(ms, dip, dev); - /* Store the console list for use by the ttymux driver */ - if (space_store(TTYMUXPTR, (uintptr_t)ms) != 0) { - ttymux_dprintf(DPRINT_L3, "Named pointer error\n"); - if (ms->sm_ialias) - kmem_free(ms->sm_ialias, strlen(ms->sm_ialias) + 1); - if (ms->sm_oalias) - kmem_free(ms->sm_oalias, strlen(ms->sm_oalias) + 1); - for (i = 0; i < ms->sm_cons_cnt; i++) { - sm_console_t *cn = &ms->sm_cons_links[i]; - if (cn->sm_path) - kmem_free(cn->sm_path, strlen(cn->sm_path) + 1); - } - kmem_free(ms, sizeof (*ms)); - return (DACF_FAILURE); - } - - muxvp = dacf_makevp(info_hdl); - - if ((rv = VOP_OPEN(&muxvp, OFLAGS, CRED(), NULL)) == 0) { - - (void) enable_all_consoles(ms, muxvp); - (void) usable_consoles(ms, &icnt, &ocnt); - - VOP_CLOSE(muxvp, OFLAGS, 1, (offset_t)0, CRED(), NULL); - VN_RELE(muxvp); - } else { - ttymux_dprintf(DPRINT_L3, - "Error %d opening the console device\n", rv); - VN_RELE(muxvp); - return (DACF_FAILURE); - } - - if (icnt == 0 && (mode & FORINPUT)) - ttymux_dprintf(DPRINT_L3, "No input consoles configured.\n"); - if (ocnt == 0 && (mode & FOROUTPUT)) - ttymux_dprintf(DPRINT_L3, "No output consoles configured.\n"); - - ttymux_dprintf(DPRINT_L0, "mux config complete\n"); - - return (DACF_SUCCESS); -} diff --git a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.h b/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.h deleted file mode 100644 index ba0941bded..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _SYS_MUXCONFIG_H -#define _SYS_MUXCONFIG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/ttymux.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Debug information - */ -/* - * Severity levels for printing - */ -#define DPRINT_L0 0 /* print every message */ -#define DPRINT_L1 1 /* debug */ -#define DPRINT_L2 2 /* minor errors */ -#define DPRINT_L3 3 /* major errors */ -#define DPRINT_L4 4 /* catastophic errors */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_MUXCONFIG_H */ diff --git a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf_util.c b/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf_util.c deleted file mode 100644 index 943897dc81..0000000000 --- a/usr/src/uts/sun4u/montecarlo/io/ttymux_dacf/ttymux_dacf_util.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/cmn_err.h> - -#include "ttymux_dacf.h" - -int ttymux_errlevel = DPRINT_L3; - -/* - * ttymux_dprintf - * Print string to the console. - */ -void -ttymux_dprintf(int l, const char *fmt, ...) -{ - va_list ap; - -#ifndef DEBUG - if (!l) { - return; - } -#endif - if ((l) < ttymux_errlevel) { - - return; - } - - va_start(ap, fmt); - (void) vprintf(fmt, ap); - va_end(ap); -} diff --git a/usr/src/uts/sun4u/montecarlo/pcf8574_nct/Makefile b/usr/src/uts/sun4u/montecarlo/pcf8574_nct/Makefile deleted file mode 100644 index 7d0d5667c8..0000000000 --- a/usr/src/uts/sun4u/montecarlo/pcf8574_nct/Makefile +++ /dev/null @@ -1,99 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the pcf8574 driver kernel module -# -# sun4u implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = pcf8574 -OBJECTS = $(PCF8574_NCT_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(PCF8574_NCT_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MONTECARLO_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.montecarlo - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -DNORDICA_CP1500 -CERRWARN += -_gcc=-Wno-uninitialized - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# -# Add our depedencies to LDFLAGS -# -LDFLAGS += -dy -Nmisc/i2c_svc -Ndrv/scsb - - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -LINT_LIB_DIR = $(MONTECARLO_LINT_LIB_DIR) -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/pcf8591_nct/Makefile b/usr/src/uts/sun4u/montecarlo/pcf8591_nct/Makefile deleted file mode 100644 index c962843f96..0000000000 --- a/usr/src/uts/sun4u/montecarlo/pcf8591_nct/Makefile +++ /dev/null @@ -1,97 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the pcf8591 driver kernel module -# -# sun4u implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = pcf8591 -OBJECTS = $(PCF8591_NCT_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(PCF8591_NCT_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MONTECARLO_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.montecarlo - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# -# Add our depedencies to LDFLAGS -# -LDFLAGS += -dy -Nmisc/i2c_svc -Ndrv/scsb - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -LINT_LIB_DIR = $(MONTECARLO_LINT_LIB_DIR) -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/scsb/Makefile b/usr/src/uts/sun4u/montecarlo/scsb/Makefile deleted file mode 100644 index e20ca311ff..0000000000 --- a/usr/src/uts/sun4u/montecarlo/scsb/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the scsb driver kernel module -# -# sun4u implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = scsb -OBJECTS = $(SCSB_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(SCSB_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MONTECARLO_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/sun4u/montecarlo/io - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.montecarlo - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -DNORDICA_CP1500 -CERRWARN += -_gcc=-Wno-switch -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-unused-function -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# Add our depedencies to LDFLAGS -# -LDFLAGS += -dy -Nmisc/hpcsvc -Nmisc/i2c_svc - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -LINT_LIB_DIR = $(MONTECARLO_LINT_LIB_DIR) -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/sys/Makefile b/usr/src/uts/sun4u/montecarlo/sys/Makefile deleted file mode 100644 index fbbb5168e7..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -UTSBASE = ../../.. - -# -# include global definitions -# -include ../Makefile.montecarlo - -# -# Override defaults. -# -FILEMODE = 644 - -HDRS= scsb_led.h - -ROOTHDRS= $(HDRS:%=$(USR_PSM_ISYS_DIR)/%) - -ROOTDIR= $(ROOT)/usr/share/src -ROOTDIRS= $(ROOTDIR)/uts $(ROOTDIR)/uts/$(PLATFORM) - -CHECKHDRS= $(HDRS:%.h=%.check) - -.KEEP_STATE: - -.PARALLEL: $(CHECKHDRS) $(ROOTHDRS) - -install_h: $(ROOTDIRS) .WAIT $(ROOTHDRS) $(ROOTLINK) - -check: $(CHECKHDRS) - -# -# install rules -# -$(USR_PSM_ISYS_DIR)/%: % $(USR_PSM_ISYS_DIR) - $(INS.file) - -$(ROOTDIRS): - $(INS.dir) - -FRC: - -include ../Makefile.targ diff --git a/usr/src/uts/sun4u/montecarlo/sys/acebus.h b/usr/src/uts/sun4u/montecarlo/sys/acebus.h deleted file mode 100644 index d5821afb4c..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/acebus.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_ACEBUS_H -#define _SYS_ACEBUS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * driver state type: - */ -typedef enum { NEW = 0, ATTACHED, RESUMED, DETACHED, - SUSPENDED, PM_SUSPENDED } driver_state_t; - -/* - * The i86pc specific code fragments are to support the debug of "honeynut" - * and "multigrain" prototypes on i86pc platform. Most of the fragments - * deal with differences in the interrupt dispatching between the prototypes - * and the cheerio ebus. On the prototype boards, all interrupt lines are - * tied together. For this case, the nexus driver uses a common interrupt - * handler to poll all of its children. - */ -#if defined(i86pc) -#define MAX_EBUS_DEVS 6 - -/* - * ebus device interrupt info; - */ -typedef struct { - char *name; - uint_t inuse; - uint_t (*handler)(); - caddr_t arg; -} ebus_intr_slot_t; -#endif - -struct ebus_intr_map { - uint32_t ebus_phys_hi; - uint32_t ebus_phys_low; - uint32_t ebus_intr; - uint32_t intr_ctlr_nodeid; - uint32_t ino; -}; - -struct ebus_intr_map_mask { - uint32_t ebus_phys_hi; - uint32_t ebus_phys_low; - uint32_t ebus_intr; -}; - -/* - * driver soft state structure: - */ -typedef struct { - dev_info_t *dip; - driver_state_t state; - pci_regspec_t *reg; - int nreg; - struct ebus_pci_rangespec *rangep; - int range_cnt; - -#if defined(i86pc) - ddi_iblock_cookie_t iblock; - ddi_idevice_cookie_t idevice; - ebus_intr_slot_t intr_slot[MAX_EBUS_DEVS]; -#endif -#if defined(__sparc) - /* Interrupt support */ - int intr_map_size; - struct ebus_intr_map *intr_map; - struct ebus_intr_map_mask *intr_map_mask; -#endif -} ebus_devstate_t; - -/* - * definition of ebus reg spec entry: - */ -typedef struct { - uint32_t addr_hi; - uint32_t addr_low; - uint32_t size; -} ebus_regspec_t; - -/* EBUS range entry */ -struct ebus_pci_rangespec { - uint32_t ebus_phys_hi; /* Child hi range address */ - uint32_t ebus_phys_low; /* Child low range address */ - uint32_t pci_phys_hi; /* Parent hi rng addr */ - uint32_t pci_phys_mid; /* Parent mid rng addr */ - uint32_t pci_phys_low; /* Parent low rng addr */ - uint32_t rng_size; /* Range size */ -}; - -/* - * use macros for soft state and driver properties: - */ -#define get_acebus_soft_state(i) \ - ((ebus_devstate_t *)ddi_get_soft_state(per_acebus_state, (i))) - -#define alloc_acebus_soft_state(i) \ - ddi_soft_state_zalloc(per_acebus_state, (i)) - -#define free_acebus_soft_state(i) \ - ddi_soft_state_free(per_acebus_state, (i)) - - -#define getprop(dip, name, addr, intp) \ - ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \ - (name), (caddr_t)(addr), (intp)) - -/* - * register offsets and lengths: - */ -#define TCR_OFFSET 0x710000 -#define TCR_LENGTH 12 - -#define CSR_IO_RINDEX 2 -#define CSR_SIZE 0x00800000 -#define TCR1_OFF 0x00710000 -#define TCR2_OFF 0x00710004 -#define TCR3_OFF 0x00710008 -#define PMD_AUX_OFF 0x00728000 -#define FREQ_AUX_OFF 0x0072a000 -#define DCSR1_OFF 0x00700000 -#define DACR1_OFF 0x00700004 -#define DBCR1_OFF 0x00700008 -#define DCSR2_OFF 0x00702000 -#define DACR2_OFF 0x00702004 -#define DBCR2_OFF 0x00702008 -#define DCSR3_OFF 0x00704000 -#define DACR3_OFF 0x00704004 -#define DBCR3_OFF 0x00704008 -#define DCSR4_OFF 0x00706000 -#define DACR4_OFF 0x00706004 -#define DBCR4_OFF 0x00706008 - -/* - * timing control register settings: - */ -#define TCR1 0x08101008 -#define TCR2 0x08100020 -#define TCR3 0x00000020 -#define TCR1_REGVAL 0xe3080808 -#define TCR2_REGVAL 0x0808ff20 -#define TCR3_REGVAL 0x91f3c420 - - - -#if defined(DEBUG) -#define D_IDENTIFY 0x00000001 -#define D_ATTACH 0x00000002 -#define D_DETACH 0x00000004 -#define D_MAP 0x00000008 -#define D_CTLOPS 0x00000010 -#define D_INTR 0x00000100 - -#define DBG(flag, psp, fmt) \ - acebus_debug(flag, psp, fmt, 0, 0, 0, 0, 0); -#define DBG1(flag, psp, fmt, a1) \ - acebus_debug(flag, psp, fmt, (uintptr_t)(a1), 0, 0, 0, 0); -#define DBG2(flag, psp, fmt, a1, a2) \ - acebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); -#define DBG3(flag, psp, fmt, a1, a2, a3) \ - acebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \ - (uintptr_t)(a3), 0, 0); -#define DBG4(flag, psp, fmt, a1, a2, a3, a4) \ - acebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \ - (uintptr_t)(a3), \ - (uintptr_t)(a4), 0); -#define DBG5(flag, psp, fmt, a1, a2, a3, a4, a5) \ - acebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \ - (uintptr_t)(a3), \ - (uintptr_t)(a4), (uintptr_t)(a5)); -static void -acebus_debug(uint_t, ebus_devstate_t *, char *, uintptr_t, uintptr_t, uintptr_t, - uintptr_t, uintptr_t); -#else -#define DBG(flag, psp, fmt) -#define DBG1(flag, psp, fmt, a1) -#define DBG2(flag, psp, fmt, a1, a2) -#define DBG3(flag, psp, fmt, a1, a2, a3) -#define DBG4(flag, psp, fmt, a1, a2, a3, a4) -#define DBG5(flag, psp, fmt, a1, a2, a3, a4, a5) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_ACEBUS_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/hsc.h b/usr/src/uts/sun4u/montecarlo/sys/hsc.h deleted file mode 100644 index 87e9f20f4d..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/hsc.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999-2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _MONTECARLO_SYS_HSC_H -#define _MONTECARLO_SYS_HSC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * These functions serve as the interface between the SCSB and the HSC - */ -int hsc_slot_occupancy(int, boolean_t, int, int); -int hsc_board_healthy(int slot_number, boolean_t healthy); -int hsc_init(); -int hsc_fini(); -void hsc_ac_op(); -int scsb_hsc_attach(dev_info_t *, void *, int); -int scsb_hsc_detach(dev_info_t *, void *, int); -int scsb_get_slot_state(); -int scsb_reset_slot(); -int scsb_connect_slot(); -int scsb_disconnect_slot(); -int scsb_hsc_ac_op(); -int scsb_hsc_freeze(dev_info_t *); -int scsb_hsc_restore(dev_info_t *); -int scsb_hsc_freeze_check(dev_info_t *); - - -#ifdef __cplusplus -} -#endif - -#endif /* _MONTECARLO_SYS_HSC_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/hscimpl.h b/usr/src/uts/sun4u/montecarlo/sys/hscimpl.h deleted file mode 100644 index c5599fa893..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/hscimpl.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999-2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _MONTECARLO_SYS_HSCIMPL_H -#define _MONTECARLO_SYS_HSCIMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include <sys/hotplug/hpctrl.h> - -/* - * Flag values - */ -#define HSC_ENABLED 0x1 /* if not enabled, slot unmanaged */ -#define HSC_AUTOCFG 0x2 /* if set, ENUM# events will be sent */ -#define HSC_REGISTERED HSC_ENABLED -#define HSC_ALARM_CARD_PRES 0x4 /* Alarm Card on this slot */ -#define HSC_BOARD_TYPE_HS 0x8 -#define HSC_BOARD_TYPE_UNKNOWN 0x10 -#define HSC_SLOT_ENABLED 0x20 -#define HSC_SLOT_BAD_STATE 0x40 /* Surprise Removal on this slot */ -#define HSC_ENUM_FAILED 0x80 /* Could not Enumerate this slot */ -#define HSC_SCB_HOTSWAPPED 0x100 /* slot status change due to SCB swap */ -#define HSC_HOTSWAP_MODE_BASIC 0 -#define HSC_HOTSWAP_MODE_FULL 1 - - -typedef struct hsc_slot_state { - int pslotnum; - int state; -} hsc_slot_state_t; - -typedef struct hsc_slot_table { - char nexus[128]; - int pci_devno; - int pslotnum; - int ga; -} hsc_slot_table_t; - -typedef struct hsc_prom_slot_table { - int phandle; - int pci_devno; - int pslotnum; - int ga; -} hsc_prom_slot_table_t; - -typedef struct hsc_state { - int instance; - int state; - dev_info_t *dip; - void *scsb_handle; - struct hsc_slot *hsp_last; /* last board plugged in. */ - hsc_slot_table_t *slot_table_prop; - int slot_table_size; - int hsc_intr_counter; - kmutex_t hsc_mutex; - ddi_iblock_cookie_t enum_iblock; - boolean_t regDone; - int n_registered_occupants; - int hotswap_mode; -} hsc_state_t; - -/* - * This struct describes a HS slot known to us. It maintains - * all the state associated with the slot. - * Slots are placed on a linked list. - */ -typedef struct hsc_slot { - struct hsc_slot *hs_next; - - void *hs_hpchandle; /* HPC (scsb) handle */ - - /* - * The hs_slot_number identifies the plysical slot. - * It should match with the documentation. - */ - int hs_slot_number; - - hpc_slot_info_t hs_info; - - hpc_board_type_t hs_board_type; - /* - * We only have 2 LEDs/slot on MonteCarlo, so we map them - * to the ACTIVE and FAULT ones. - * ACTIVE will be set when a board is in the slot, and has - * been configured. - */ - hpc_led_state_t hs_active_led_state; - hpc_led_state_t hs_fault_led_state; - - /* - * hs_slot_handle is useful for supporting ENUM# - * (when we need to inform the nexus of the event). - */ - hpc_slot_t hs_slot_handle; - - uint_t hs_flags; - - boolean_t hs_board_configured; - boolean_t hs_board_configuring; - boolean_t hs_board_unconfiguring; - boolean_t hs_board_healthy; - - /* - * The hs_slot_state is useful for HW-connection control - */ - hpc_slot_state_t hs_slot_state; - hsc_state_t *hsc; /* pointer to our controller device */ -} hsc_slot_t; - -/* state values in our control structure */ -#define HSC_ENUM_ENABLED 1 -#define HSC_ATTACHED 2 -#define HSC_SCB_CONNECTED 4 - -#ifdef __cplusplus -} -#endif - -#endif /* _MONTECARLO_SYS_HSCIMPL_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/mct_topology.h b/usr/src/uts/sun4u/montecarlo/sys/mct_topology.h deleted file mode 100644 index 205e2e608f..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/mct_topology.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999, 2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _MONTECARLO_SYS_MCT_TOPOLOGY_H -#define _MONTECARLO_SYS_MCT_TOPOLOGY_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * mct_topology.h - * MonteCarlo / Tonga topology structures and types for the scsb driver - * and its kstat structure "env_topology", to be available to applications - * like envmond and snmp agents. - */ -/* - * SCB information also defined in scsb.h, which file is not available to - * applications. - */ -#define SCB_P10_NOK_LED_REGS 4 -#define SCB_P10_OK_LED_REGS 4 -#define SCB_P10_BLINK_LED_REGS 2 -#define SCB_P10_LED_REGS 10 -#define SCB_P15_NOK_LED_REGS 3 -#define SCB_P15_OK_LED_REGS 3 -#define SCB_P15_BLINK_LED_REGS 3 -#define SCB_P15_LED_REGS 9 - -/* Save this existing definition, but use it as the MAX */ -#define SCSB_LEDDATA_REGISTERS SCB_P10_LED_REGS - -#define MC_MAX_SLOTS 8 /* CPU, ALRM, cPCI Slots */ -#define MC_MAX_FAN 2 -#define MC_MAX_PDU 2 -#define MC_MAX_PS 2 -#define MC_MAX_DISK 3 -#define MC_MAX_SCB 1 -#define MC_MAX_AC 1 -#define MC_MAX_CFTM 1 -#define MC_MAX_CRTM 1 -#define MC_MAX_PRTM 1 - -#define TG_MAX_SLOTS 5 /* CPU, ALRM, cPCI Slots */ -#define TG_MAX_FAN 2 -#define TG_MAX_PS 1 -#define TG_MAX_PDU 1 -#define TG_MAX_DISK 1 -#define TG_MAX_SCB 1 -#define TG_MAX_AC 1 -#define TG_MAX_CFTM 1 -#define TG_MAX_CRTM 1 -#define TG_MAX_PRTM 1 - -/* - * Maximum number of FRUs in MCT systems, - * used for sizeof fru_id_table[] and index check - */ -#define MCT_MAX_FRUS 32 - -/* - * The I2C addresses of System I2C devices - * from "MonteCarlo: Programming Interface Specifications" Version 0.9 - */ -#define MCT_I2C_CPUPWR 0x72 -#define MCT_I2C_FAN1 0x74 -#define MCT_I2C_FAN2 0x76 -#define MCT_I2C_FAN3 0x78 -#define MCT_I2C_PS1 0x7c -#define MCT_I2C_PS2 0x7e -#define MCT_I2C_SCB 0x80 -#define MCT_I2C_CPUTEMP 0x9e - -/* - * CFG1_MPID masks - */ -#define SCTRL_MPID_MASK 0xf -#define SCTRL_MPID_HALF 0x0 -#define SCTRL_MPID_QUARTER 0x1 -#define SCTRL_MPID_QUARTER_NODSK 0x3 - -/* - * Interrupt Event Codes - * Also used by "scsb" to locate fruid_table index, - * so the order is very important. - */ -#define SCTRL_EVENT_NONE 0x0000 -#define SCTRL_EVENT_SLOT1 0x00000001 -#define SCTRL_EVENT_SLOT2 0x00000002 -#define SCTRL_EVENT_SLOT3 0x00000004 -#define SCTRL_EVENT_SLOT4 0x00000008 -#define SCTRL_EVENT_SLOT5 0x00000010 -#define SCTRL_EVENT_SLOT6 0x00000020 -#define SCTRL_EVENT_SLOT7 0x00000040 -#define SCTRL_EVENT_SLOT8 0x00000080 -#define SCTRL_EVENT_SLOT9 0x00000100 -#define SCTRL_EVENT_SLOT10 0x00000200 -#define SCTRL_EVENT_PDU1 0x00000400 -#define SCTRL_EVENT_PDU2 0x00000800 -#define SCTRL_EVENT_PS1 0x00001000 -#define SCTRL_EVENT_PS2 0x00002000 -#define SCTRL_EVENT_DISK1 0x00004000 -#define SCTRL_EVENT_DISK2 0x00008000 -#define SCTRL_EVENT_DISK3 0x00010000 -#define SCTRL_EVENT_FAN1 0x00020000 -#define SCTRL_EVENT_FAN2 0x00040000 -#define SCTRL_EVENT_FAN3 0x00080000 -#define SCTRL_EVENT_ALARM 0x00100000 -#define SCTRL_EVENT_SCB 0x00200000 -#define SCTRL_EVENT_SSB 0x00400000 -#define SCTRL_EVENT_CRTM 0x00800000 -#define SCTRL_EVENT_CFTM 0x01000000 -#define SCTRL_EVENT_PRTM 0x02000000 -#define SCTRL_EVENT_PWRDWN 0x04000000 -#define SCTRL_EVENT_REPLACE 0x08000000 -#define SCTRL_EVENT_ALARM_INT 0x10000000 -#define SCTRL_EVENT_ALARM_INSERTION 0x20000000 -#define SCTRL_EVENT_ALARM_REMOVAL 0x40000000 -#define SCTRL_EVENT_OTHER 0x80000000 - - - -typedef uchar_t topo_id_t; -typedef uchar_t fru_id_t; -typedef uint16_t fru_version_t; -typedef uint16_t fru_max_t; -typedef uint16_t scsb_unum_t; - -typedef enum { - MCT_HEALTH_NA = 0, - MCT_HEALTH_OK = 1, - MCT_HEALTH_NOK = 2 -} fru_health_t; - -/* - * Known MC/Tg Slot occupants, and UNKN for unknown - * NOTE: the CTC occupant is the CFTM FRU type on MonteCarlo - */ -typedef enum { - OC_UNKN = 0, - OC_CPU = 1, - OC_AC = 2, - OC_BHS = 3, - OC_FHS = 4, - OC_HAHS = 5, - OC_QFE = 6, - OC_FRCH = 7, - OC_COMBO = 8, - OC_PMC = 9, - OC_ATM = 10, - OC_CTC = 11 -} mct_slot_occupant_t; - -typedef enum { - SLOT = 0, - PDU = 1, - PS = 2, - DISK = 3, - FAN = 4, - ALARM = 5, - SCB = 6, - SSB = 7, - CFTM = 8, - CRTM = 9, - PRTM = 10, - MIDPLANE = 11 -} scsb_utype_t; - -#define SCSB_UNIT_TYPES 11 /* w/o MIDPLANE */ - -typedef enum scsb_fru_status { - FRU_NOT_PRESENT, - FRU_PRESENT, - FRU_NOT_AVAILABLE -} scsb_fru_status_t; - -typedef enum { - SWAP_NOT, SWAP_BASIC, SWAP_FULL, SWAP_HA -} cpci_swap_type_t; - -typedef struct fru_options { - char *board_name; - cpci_swap_type_t swap_type; - struct fru_options *next; -} fru_options_t; - -typedef struct fru_i2c_info { - uchar_t syscfg_reg; - uchar_t syscfg_bit; - uchar_t ledata_reg; - uchar_t ledata_bit; - uchar_t blink_reg; - uchar_t blink_bit; -} fru_i2c_info_t; - -typedef struct fru_info { - scsb_fru_status_t fru_status; /* FRU present status */ - scsb_unum_t fru_unit; /* FRU external unit number */ - scsb_utype_t fru_type; /* also an index to FRU lists */ - fru_id_t fru_id; /* I2C address, SCSIID, Slot Num */ - fru_version_t fru_version; /* version number where possible */ - fru_options_t *type_list; /* list of possible boards for slots */ - fru_i2c_info_t *i2c_info; /* for I2C devices */ - struct fru_info *next; -} fru_info_t; - -struct system_info { - fru_info_t mid_plane; /* one always present */ - fru_max_t max_units[SCSB_UNIT_TYPES]; - fru_info_t *fru_info_list[SCSB_UNIT_TYPES]; -}; - -/* - * scsb kstat types - */ -#define SCSB_KS_LEDDATA "scsb_leddata" -#define SCSB_KS_STATE "scsb_state" -#define SCSB_KS_EVC_REGISTER "scsb_evc_register" -#define SCSB_KS_TOPOLOGY "env_topology" - -typedef struct ks_fru_info { - scsb_fru_status_t fru_status; /* FRU presence/availability status */ - scsb_unum_t fru_unit; /* FRU external unit number */ - scsb_utype_t fru_type; /* and occupant type for solts */ - fru_id_t fru_id; /* I2C address, SCSIID, Slot Num */ - fru_version_t fru_version; /* version number where possible */ - fru_health_t fru_health; /* From NOK LED, if available */ -} ks_fru_info_t; - -typedef union scsb_leddata { - uchar_t scb_led_regs[SCSB_LEDDATA_REGISTERS]; - union { - struct { - uchar_t nok_leds[SCB_P10_NOK_LED_REGS]; - uchar_t ok_leds[SCB_P10_OK_LED_REGS]; - uchar_t blink_leds[SCB_P10_BLINK_LED_REGS]; - } p10; - struct { - uchar_t nok_leds[SCB_P15_NOK_LED_REGS]; - uchar_t ok_leds[SCB_P15_OK_LED_REGS]; - uchar_t blink_leds[SCB_P15_BLINK_LED_REGS]; - } p15; - } leds; -} scsb_ks_leddata_t; - -typedef struct { - uint8_t scb_present; /* SCB is present */ - uint8_t ssb_present; /* SSB is present */ - uint8_t scsb_frozen; /* SCB swap state */ - uint8_t scsb_mode; /* driver access mode */ - uint8_t unused_1; - uint8_t unused_2; - uint8_t unused_3; - uint8_t unused_4; - uint32_t event_code; /* event code bit map */ -} scsb_ks_state_t; - -typedef struct { - ks_fru_info_t mid_plane; - fru_max_t max_units[SCSB_UNIT_TYPES]; - ks_fru_info_t mct_slots[MC_MAX_SLOTS]; - ks_fru_info_t mct_pdu[MC_MAX_PDU]; - ks_fru_info_t mct_ps[MC_MAX_PS]; - ks_fru_info_t mct_disk[MC_MAX_DISK]; - ks_fru_info_t mct_fan[MC_MAX_FAN]; - ks_fru_info_t mct_scb[MC_MAX_SCB]; - ks_fru_info_t mct_ssb[MC_MAX_SCB]; - ks_fru_info_t mct_alarm[MC_MAX_AC]; - ks_fru_info_t mct_cftm[MC_MAX_CFTM]; - ks_fru_info_t mct_crtm[MC_MAX_CRTM]; - ks_fru_info_t mct_prtm[MC_MAX_PRTM]; -} mct_topology_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _MONTECARLO_SYS_MCT_TOPOLOGY_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/netract_gen.h b/usr/src/uts/sun4u/montecarlo/sys/netract_gen.h deleted file mode 100644 index 501ed20fd7..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/netract_gen.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999, 2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -/* - * MonteCarlo's Common I2C Driver Definitions - * - * These definitions are derived from, or the same as, - * some of the definitions from sun4u/sys/envctrl_gen.h, - * which are common definitions for workgroup server platforms. - */ - -#ifndef _SYS_NETRACT_GEN_H -#define _SYS_NETRACT_GEN_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef _SYS_ENVCTRL_GEN_H -#define _SYS_ENVCTRL_GEN_H - -#define ENVCTRL_NORMAL_MODE 0x01 -#define ENVCTRL_DIAG_MODE 0x02 -#define ENVC_DEBUG_MODE 0x03 - -/* - * Max number of a particular - * device on one bus. - */ -#define ENVCTRL_MAX_DEVS 0x10 -#define ENVCTRL_I2C_NODEV 0xFF -#define ENVCTRL_INSTANCE_0 0x00 - -/* - * Kstat structure definitions (PSARC 1996/159) - */ -typedef struct envctrl_fan { - int instance; /* instance of this type */ - int type; /* CPU, PS or AMBIENT fan */ - boolean_t fans_ok; /* are the fans okay */ - int fanflt_num; /* if not okay, which fan faulted */ - uint_t fanspeed; /* chip to set speed of fans */ -} envctrl_fan_t; - -#endif /* _SYS_ENVCTRL_GEN_H */ - -#define ENVC_IOC_SETMODE (int)(_IOW('p', 77, uchar_t)) -#define ENVC_IOC_GETMODE (int)(_IOR('p', 87, uchar_t)) - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_NETRACT_GEN_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/pcf8574_nct.h b/usr/src/uts/sun4u/montecarlo/sys/pcf8574_nct.h deleted file mode 100644 index c915b47d57..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/pcf8574_nct.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999-2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _PCF8574_H -#define _PCF8574_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define PCF8574_NODE_TYPE "adc_i2c:gpio" -#define I2C_PCF8574_NAME "gpio" - -#define I2C_KSTAT_CPUVOLTAGE "gpio_cpuvoltage" -#define I2C_KSTAT_PWRSUPPLY "gpio_pwrsupply" -#define I2C_KSTAT_FANTRAY "gpio_fantray" - -/* - * PCF8574 ioctls for fantray and powersupplies. - */ - -#define ENVC_IOC_GETTEMP 0x10 -#define ENVC_IOC_SETFAN 0x11 -#define ENVC_IOC_GETFAN 0x12 -#define ENVC_IOC_GETSTATUS 0x15 -#define ENVC_IOC_GETTYPE 0x16 -#define ENVC_IOC_GETFAULT 0x17 -#define ENVC_IOC_PSTEMPOK 0x18 -#define ENVC_IOC_PSFANOK 0x1A -#define ENVC_IOC_PSONOFF 0x1B -#define ENVC_IOC_SETSTATUS 0x1C - -#define ENVC_IOC_INTRMASK 0x1D - -#define ENVCTRL_INTRMASK_SET 1 -#define ENVCTRL_INTRMASK_CLEAR 0 - -#define ENVCTRL_FANSPEED_LOW 0 -#define ENVCTRL_FANSPEED_HIGH 1 - -/* - * Could not find a definition for CPU voltage monitoring in Javelin - * Code. So writing a structure here. - */ - -typedef struct envctrl_cpuvoltage { - int value; -} envctrl_cpuvoltage_t; - -/* - * ps_present and fan_present fields modified for FRU callback and status - * See sys/scsb_cbi.h and definitions in scsb.c - */ -typedef struct envctrl_pwrsupply { - scsb_fru_status_t ps_present; /* Is powersupply present */ - boolean_t ps_ok; /* Is powersupply ok */ - boolean_t temp_ok; /* Is temperature ok */ - boolean_t psfan_ok; /* Is fan ok */ - boolean_t on_state; /* Powersupply on/off */ - int ps_ver; /* Pwr supply version and type */ -} envctrl_pwrsupp_t; - -typedef struct envctrl_fantray { - scsb_fru_status_t fan_present; /* fan1 present */ - boolean_t fan_ok; /* fan1 ok */ - boolean_t fanspeed; /* to set speed, input */ - int fan_ver; /* Fan version and type */ -} envctrl_fantray_t; - -#ifdef _KERNEL - -#ifndef I2CDEV_TRAN -#define I2CDEV_TRAN 1 -#endif - -#define PCF8574_MAX_DEVS 0x08 -#define PCF8574_MAX_CHANS 0x01 -#define PCF8574_BUSY 0x01 -#define PCF8574_NAMELEN 12 -#define PCF8574_INTR_ON 0x1 -#define PCF8574_INTR_ENABLED 0x2 - -#define PCF8574_MINOR_TO_DEVINST(x) (((x) & 0x700) >> 8) -#define PCF8574_MINOR_TO_CHANNEL(x) ((x) & 0x3) - -#define PCF8574_CHANNEL_TO_MINOR(x) ((x) & 0x3) -#define PCF8574_DEVINST_TO_MINOR(x) ((x) << 8) - - -#define PCF8574_TRAN_SIZE 1 -#ifndef PCF8574 -#define PCF8574 0 -#endif - -#ifndef PCF8574A -#define PCF8574A 1 -#endif - -#define PCF8574_SET ('A' << 8) -#define PCF8574_GET ('B' << 8) - -#define NUM_OF_PCF8574_DEVICES 8 -#define PCF8574_MAXPORTS 8 - -#define PCF8574_TYPE_CPUVOLTAGE 0 -#define PCF8574_TYPE_FANTRAY 1 -#define PCF8574_TYPE_PWRSUPP 2 - -#define PCF8574_ADR_CPUVOLTAGE 0x70 -#define PCF8574_ADR_PWRSUPPLY1 0x7C -#define PCF8574_ADR_PWRSUPPLY2 0x7E -#define PCF8574_ADR_FANTRAY1 0x74 -#define PCF8574_ADR_FANTRAY2 0x76 - -/* - * PCF8574 Fan Fail, Power Supply Fail Detector - * This device is driven by interrupts. Each time it interrupts - * you must look at the CSR to see which ports caused the interrupt - * they are indicated by a 1. - * - * Address map of this chip - * - * ------------------------------------------- - * | 0 | 1 | 1 | 1 | A2 | A1 | A0 | 0 | - * ------------------------------------------- - * - */ -#define I2C_PCF8574_PORT0 0x01 -#define I2C_PCF8574_PORT1 0x02 -#define I2C_PCF8574_PORT2 0x04 -#define I2C_PCF8574_PORT3 0x08 -#define I2C_PCF8574_PORT4 0x10 -#define I2C_PCF8574_PORT5 0x20 -#define I2C_PCF8574_PORT6 0x40 -#define I2C_PCF8574_PORT7 0x80 - -#define MAX_WLEN 64 -#define MAX_RLEN 64 - -/* - * Following property information taken from the - * "SPARCengine ASM Reference Manual" - * Property pointers are to DDI allocated space - * which must be freed in the detach() routine. - */ -/* - * for pcf8574_properties_t.channels_in_use->io_dir - */ -#define I2C_PROP_IODIR_IN 0 -#define I2C_PROP_IODIR_OUT 1 -#define I2C_PROP_IODIR_INOUT 2 - -/* - * for pcf8574_properties_t.channels_in_use->type - */ -#define I2C_PROP_TYPE_NOCARE 0 -#define I2C_PROP_TYPE_TEMP 1 -#define I2C_PROP_TYPE_VOLT 2 -#define I2C_PROP_TYPE_FANSTATS 3 -#define I2C_PROP_TYPE_FANSPEED 4 - -/* - * These are now defined in sys/netract_gen.h - * - * #define ENVC_IOC_GETMODE 0x1C - * #define ENVC_IOC_SETMODE 0x1D - */ - - -/* - * Bit positions for the pcf8574 registers. - */ - -#define PCF8574_PS_TYPE(X) ((X) & 0x3) -#define PCF8574_PS_INTMASK(X) (((X) >> 2) & 0x1) -#define PCF8574_PS_ONOFF(X) (((X) >> 3)& 0x1) -#define PCF8574_PS_FANOK(X) (((X) >> 4) & 0x1) -#define PCF8574_PS_TEMPOK(X) (((X) >> 6) & 0x1) -#define PCF8574_PS_FAULT(X) (((X) >> 7) & 0x1) - -#define PCF8574_FAN_TYPE(X) ((X) & 0x3) -#define PCF8574_FAN_INTMASK(X) (((X) >> 2) & 0x1) -#define PCF8574_FAN_FANSPD(X) (((X) >> 3) & 0x1) -#define PCF8574_FAN_FAULT(X) (((X) >> 7) & 0x1) - -/* Constructs the reg byte from bit value */ -#define PCF8574_FAN_SPEED(bit) ((bit) << 3) -#define PCF8574_INT_MASK(bit) ((bit) << 2) - -/* - * To tell the write_chip routine which bits to modify, a - * 1 in the corresponding position selects that bit for - * writing, a 0 ignores it. - */ -#define PCF8574_FANSPEED_BIT 0x08 -#define PCF8574_INTRMASK_BIT 0x04 - -/* - * Read and write masks for the fan and power supply. - * These masks indicate which ports attached to the - * PCF8574/A are input/output. We should construct the - * read and writemasks from the channels-in-use property - * for each pcf8574 device. In case the property is - * absent, we can assign them with these default values. - * While writing to the chip, we must or with the readmask, - * else that port will be disabled. - */ - -#define PCF8574_FAN_WRITEMASK 0x0c -#define PCF8574_FAN_READMASK 0xff -#define PCF8574_PS_WRITEMASK 0x04 -#define PCF8574_PS_READMASK 0xff -#define PCF8584_CPUVOLTAGE_WRITEMASK 0x88 -#define PCF8584_CPUVOLTAGE_READMASK 0x41 - -/* - * Default values of the Fan and PS registers. - * interrupt enabled. - */ -#define PCF8574_FAN_DEFAULT 0xfb -#define PCF8574_PS_DEFAULT 0xfb - -#define PCF8574_FAN_MASKINTR 0x04 - -#define PCF8574_PS_MASKINTR 0x04 - -#define PCF8574_FAN_SPEED60 0x00 -#define PCF8574_FAN_SPEED100 0x80 - -#define PCF8574_NUM_FANTRAY 2 -#define PCF8574_NUM_PWRSUPP 2 - -#define PCF8574_FAN_SPEED_LOW 0 -#define PCF8574_FAN_SPEED_HIGH 1 - -/* - * Stage of attachment. - */ -#define PCF8574_SOFT_STATE_ALLOC 0x0001 -#define PCF8574_PROPS_READ 0x0002 -#define PCF8574_MINORS_CREATED 0x0004 -#define PCF8574_ALLOC_TRANSFER 0x0008 -#define PCF8574_REGISTER_CLIENT 0x0010 -#define PCF8574_LOCK_INIT 0x0020 -#define PCF8574_INTR_MUTEX 0x0040 -#define PCF8574_INTR_ADDED 0x0080 -#define PCF8574_KSTAT_INIT 0x0100 - -/* - * PCF8574 ioctls for CPU Voltage (Nordica). - */ - - -typedef struct { - uint8_t port; - uint8_t io_dir; - uint8_t type; - uint8_t last_data; /* N/A */ -} pcf8574_channel_t; - -typedef struct { - char *name; - uint16_t i2c_bus; - uint16_t slave_address; - uint_t num_chans_used; - char **channels_description; - pcf8574_channel_t *channels_in_use; -} pcf8574_properties_t; - -struct pcf8574_unit { - kmutex_t umutex; - int instance; - dev_info_t *dip; - kcondvar_t pcf8574_cv; - i2c_transfer_t *i2c_tran; - i2c_client_hdl_t pcf8574_hdl; - char pcf8574_name[PCF8574_NAMELEN]; - pcf8574_properties_t props; - uint8_t pcf8574_flags; - int pcf8574_oflag; - uint8_t readmask; - uint8_t writemask; - ddi_iblock_cookie_t iblock; - kmutex_t intr_mutex; - uint8_t pcf8574_canintr; - void *envctrl_kstat; - uint8_t current_mode; - int sensor_type; - int pcf8574_type; - struct pollhead poll; - int poll_event; - uint_t attach_flag; - kstat_t *kstatp; - int i2c_status; -}; - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _PCF8574_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/pcf8591_nct.h b/usr/src/uts/sun4u/montecarlo/sys/pcf8591_nct.h deleted file mode 100644 index da67a5368d..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/pcf8591_nct.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999-2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _PCF8591_H -#define _PCF8591_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * PCF8591 Chip Used for temperature sensors - * - * Addressing Register definition. - * A0-A2 valid range is 0-7 - * - * ------------------------------------------------ - * | 1 | 0 | 0 | 1 | A2 | A1 | A0 | R/W | - * ------------------------------------------------ - */ - -#define PCF8591_MAX_DEVS 0x08 -#define PCF8591_MAX_CHANS 0x04 -#define PCF8591_BUSY 0x01 -#define PCF8591_NAMELEN 12 - -#define PCF8591_MINOR_TO_DEVINST(x) (((x) & 0x700) >> 8) -#define PCF8591_MINOR_TO_CHANNEL(x) ((x) & 0x3) - -#define PCF8591_CHANNEL_TO_MINOR(x) ((x) & 0x3) -#define PCF8591_DEVINST_TO_MINOR(x) ((x) << 8) -#define PCF8591_MINOR_NUM(i, c) (((i) << 8)|((c) & 0x3)) - -#define PCF8591_NODE_TYPE "ddi_i2c:adc" - -#define PCF8591_TRAN_SIZE 1 -#define I2C_PCF8591_NAME "adc-dac" -#define I2C_KSTAT_CPUTEMP "adc_temp" -#define I2C_TYPE_PCF8591 0 - -#define ENVC_NETRACT_CPU_SENSOR 0 - -#define I2C_DEV0 0x00 -#define I2C_DEV1 0x02 -#define I2C_DEV2 0x04 -#define I2C_DEV3 0x06 -#define I2C_DEV4 0x08 -#define I2C_DEV5 0x0A -#define I2C_DEV6 0x0C -#define I2C_DEV7 0x0E - -#define MAX_WLEN 64 -#define MAX_RLEN 64 - -#ifndef I2CDEV_TRAN -#define I2CDEV_TRAN 1 -#endif -#define I2CDEV_GETTEMP 82 -#define I2CDEV_GETTABLES 256 - -#define ENVC_IOC_GETTEMP 0x10 -/* - * These are now defined in sys/netract_gen.h - * - * #define ENVC_IOC_GETMODE 0x1C - * #define ENVC_IOC_SETMODE 0x1D - */ - -/* - * CONTROL OF CHIP - * PCF8591 Temp sensing control register definitions - * - * --------------------------------------------- - * | 0 | AOE | X | X | 0 | AIF | X | X | - * --------------------------------------------- - * AOE = Analog out enable.. not used on out implementation - * 5 & 4 = Analog Input Programming.. see data sheet for bits.. - * - * AIF = Auto increment flag - * bits 1 & 0 are for the Channel number. - */ - -/* - * We should be able to select the alalog input - * programming of our choice. By default, the - * alanog input programming is set to Single - * ended. The programmer can issue an ioctl to - * set the input programming mode. We will set - * the auto increment flag set to off, so the lower - * nibble in the control byte will be set to the - * channel number. - */ - -#define PCF8591_4SINGLE 0x00 /* 4 single ended inputs */ -#define PCF8591_3DIFF 0x10 /* 3 differential inputs */ -#define PCF8591_MIXED 0x20 /* single ended and diff mixed */ -#define PCF8591_2DIFF 0x30 /* 2 differential inputs */ - -#define PCF8591_WARNING_TEMP 0x0 -#define PCF8591_SHUTDOWN_TEMP 0x3 - -#define PCF8591_ANALOG_OUTPUT_EN 0x40 -#define PCF8591_ANALOG_INPUT_EN 0x00 -#define PCF8591_READ_BIT 0x01 - - -#define PCF8591_AUTO_INCR 0x04 -#define PCF8591_OSCILATOR 0x40 - -#define PCF8591_CH_0 0x00 -#define PCF8591_CH_1 0x01 -#define PCF8591_CH_2 0x02 -#define PCF8591_CH_3 0x03 - -/* - * Stage of attachment. - */ -#define PCF8591_SOFT_STATE_ALLOC 0x0001 -#define PCF8591_PROPS_READ 0x0002 -#define PCF8591_MINORS_CREATED 0x0004 -#define PCF8591_ALLOC_TRANSFER 0x0008 -#define PCF8591_REGISTER_CLIENT 0x0010 -#define PCF8591_LOCK_INIT 0x0020 -#define PCF8591_KSTAT_INIT 0x0040 - -#define MAX_REGS_8591 2 - -struct pcf8591 { - unsigned int reg_num; - unsigned int reg_value; -}; - -/* - * Following property information taken from the - * "SPARCengine ASM Reference Manual" - * Property pointers are to DDI allocated space - * which must be freed in the detach() routine. - */ - -/* - * for pcf8591_properties_t.channels_in_use->io_dir - */ -#define I2C_PROP_IODIR_IN 0 -#define I2C_PROP_IODIR_OUT 1 -#define I2C_PROP_IODIR_INOUT 2 - -/* - * for pcf8591_properties_t.channels_in_use->type - */ -#define I2C_PROP_TYPE_NOCARE 0 -#define I2C_PROP_TYPE_TEMP 1 -#define I2C_PROP_TYPE_VOLT 2 -#define I2C_PROP_TYPE_FANSTATS 3 -#define I2C_PROP_TYPE_FANSPEED 4 - -typedef struct { - uint8_t port; - uint8_t io_dir; - uint8_t type; - uint8_t last_data; -} pcf8591_channel_t; - -typedef struct { - char *name; - uint16_t i2c_bus; - uint16_t slave_address; - uint_t num_chans_used; - char **channels_description; - pcf8591_channel_t *channels_in_use; -} pcf8591_properties_t; - -struct pcf8591_unit { - int instance; - kmutex_t umutex; - dev_info_t *dip; - kcondvar_t pcf8591_cv; - uint8_t pcf8591_flags; - uint8_t pcf8591_inprog; - struct envctrl_temp temp_kstats; - kstat_t *tempksp; - uint_t attach_flag; - int pcf8591_oflag[PCF8591_MAX_CHANS]; - i2c_transfer_t *i2c_tran; - i2c_client_hdl_t pcf8591_hdl; - char pcf8591_name[PCF8591_NAMELEN]; - uint8_t current_mode; - uint8_t readmask; - pcf8591_properties_t props; /* device properties */ -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _PCF8591_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/scsb.h b/usr/src/uts/sun4u/montecarlo/sys/scsb.h deleted file mode 100644 index 0a5efaaa51..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/scsb.h +++ /dev/null @@ -1,711 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2001 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _MONTECARLO_SYS_SCSB_H -#define _MONTECARLO_SYS_SCSB_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _KERNEL -#include <sys/inttypes.h> -#include <sys/i2c/misc/i2c_svc.h> -#include <sys/ksynch.h> -#endif /* _KERNEL */ - -/* - * CPU and AlarmCard slots - * MonteCarlo: CPU = SLOT1, AC = SLOT8 - * Tonga: CPU = SLOT3, AC = SLOT1 - */ -#define SC_MC_CPU_SLOT 1 -#define SC_TG_CPU_SLOT 3 -#define SC_MC_AC_SLOT 8 -#define SC_TG_AC_SLOT 1 -#define SC_MC_CTC_SLOT 2 - -#define SCSB_MC_ALARM_SLOT SC_MC_AC_SLOT -#define SCSB_TONGA_ALARM_SLOT SC_TG_AC_SLOT - -#define SCTRL_PROM_P06 0x00 -#define SCTRL_PROM_P10 0x01 -#define SCTRL_PROM_P15 0x02 -#define SCTRL_PROM_P20 0x03 - -#define SCSB_RESET_SLOT 1 -#define SCSB_UNRESET_SLOT 2 -#define SCSB_GET_SLOT_RESET_STATUS 3 - -#define SCTRL_CFG_SLOT16 SCTRL_SYSCFG_5_READ-SCTRL_SYSCFG_BASE -#define SCTRL_CFG_SLOT710 SCTRL_SYSCFG_6_READ-SCTRL_SYSCFG_BASE -#define SCTRL_CFG_SLOTAC SCTRL_SYSCFG_4_READ-SCTRL_SYSCFG_BASE - -/* - * SCSB operations between scsb and the hotswap controller module - */ -#define SCSB_HSC_AC_BUSY 1 -#define SCSB_HSC_AC_CONFIGURED 2 -#define SCSB_HSC_AC_UNCONFIGURED 3 -#define SCSB_HSC_AC_UNCONFIGURE 4 -#define SCSB_HSC_AC_CONFIGURE 5 -#define SCSB_HSC_AC_SET_BUSY 6 -#define SCSB_HSC_AC_REMOVAL_ALERT 7 -/* - * SCSB_HSC_AC_GET_SLOT_INFO for hsc_ac_op() - * to return hsc_slot_t pointer (for debugging) - */ -#define SCSB_HSC_AC_GET_SLOT_INFO 11 - -/* - * The register set starting address, and macro for translating - * the index to 0 base. - */ -#define SCSB_REG_ADDR_START 0xC0 -#define SCSB_REG_INDEX(raddr) ((raddr) % SCSB_REG_ADDR_START) - -/* - * ---------------------- - * P1.0 - * ---------------------- - * The following three register offset groups are defined for P1.0 where - * FRUs might have three different bit offset values, - * Group 1: LEDs, Slot Reset, and BrdHlthy, - * Group 2: Config/Status registers - * Group 3: Interrupt Pointer/Mask registers - */ -#define REG_GROUP1 0 -#define REG_GROUP2 1 -#define REG_GROUP3 2 -#define REG_GROUPS_NUM 3 -#define IS_GROUP1(rx) (rx < SCTRL_SYSCFG_5) -#define IS_GROUP3(rx) (rx > SCTRL_SYSCFG_4) -#define IS_GROUP2(rx) (rx > (SCTRL_SYSCFG_5 - 1) && \ - (rx < (SCTRL_SYSCFG_4 + 1))) -#define IS_SCB_P10 (scsb->scsb_state & \ - (SCSB_P06_PROM | SCSB_P10_PROM)) -/* - * ---------------------- - * P1.5 - * ---------------------- - * The table access macros use BASE register plus register offset to get the - * correct register index or address. - * The SCB FRU type has two register offsets, LED reg and INT reg offsets. - * The one in fru_offsets[] is for the NOK, OK, and BLINK LED data. - * To get the register offset for the INTSRC and INTMASK registers, the - * following constant must be added to the table value returned by - * FRU_REG_INDEX(SCTRL_EVENT_SCB, SCTRL_INTMSK_BASE), NOT SCTRL_INTMASK_BASE. - * Given enough time, this too should be handled via macro access to tables. - */ -#define SCB_INT_OFFSET 2 - -/* - * ---------------------------------- - * P0.6, P1.0, P1.5, P2.0 DEFINITIONS - * ---------------------------------- - */ - -#define SCTRL_PROM_VERSION 0xCF /* same Addr for P06 thru P20 */ -#define IS_SCB_P15 (scsb->scsb_state & \ - (SCSB_P15_PROM | SCSB_P20_PROM)) - -/* - * SCB Register Indicies to scb_reg_index[] table - */ -#define SCTRL_SYS_CMD_BASE 0 -#define SCTRL_SYS_CMD1 SCTRL_SYS_CMD_BASE -#define SCTRL_SYS_CMD2 1 -#define SCTRL_LED_NOK_BASE 2 -#define SCTRL_LED_SLOT_16_NOK SCTRL_LED_NOK_BASE -#define SCTRL_LED_SLOT_712_NOK 3 -#define SCTRL_LED_DPP_NOK 4 -#define SCTRL_LED_FAN_NOK 5 -#define SCTRL_LED_OK_BASE 6 -#define SCTRL_LED_SLOT_16_OK SCTRL_LED_OK_BASE -#define SCTRL_LED_SLOT_712_OK 7 -#define SCTRL_LED_DPP_OK 8 -#define SCTRL_LED_FAN_OK 9 -#define SCTRL_RESET_BASE 10 -#define SCTRL_RESET_SLOT_16 SCTRL_RESET_BASE -#define SCTRL_RESET_SLOT_710A 11 -#define SCTRL_RESET_ALARM 11 -#define SCTRL_BLINK_OK_BASE 12 -#define SCTRL_BLINK_OK_1 SCTRL_BLINK_OK_BASE -#define SCTRL_BLINK_OK_2 13 -#define SCTRL_BLINK_GR_3 14 /* 0xCE */ -#define SCTRL_SCBID_BASE 15 -#define SCTRL_BHLTHY_BASE 16 -#define SCTRL_BHLTHY_SLOT_16 SCTRL_BHLTHY_BASE -#define SCTRL_BHLTHY_SLOT_710 17 -#define SCTRL_SYSCFG_BASE 18 -#define SCTRL_SYSCFG_5 SCTRL_SYSCFG_BASE -#define SCTRL_SYSCFG_6 19 -#define SCTRL_SYSCFG_1 20 -#define SCTRL_SYSCFG_2 21 -#define SCTRL_SYSCFG_3 22 -#define SCTRL_SYSCFG_4 23 -#define SCTRL_INTSRC_BASE 24 -#define SCTRL_INTSRC_HLTHY_BASE SCTRL_INTSRC_BASE -#define SCTRL_INTSRC_1 SCTRL_INTSRC_BASE -#define SCTRL_INTSRC_2 25 -#define SCTRL_INTSRC_3 26 -#define SCTRL_INTSRC_4 27 -#define SCTRL_INTSRC_5 28 -#define SCTRL_INTSRC_6 29 -#define SCTRL_INTSRC_SCB_P15 SCTRL_INTSRC_6 -#define SCTRL_INTMASK_BASE 30 -#define SCTRL_INTMASK_HLTHY_BASE SCTRL_INTMASK_BASE -#define SCTRL_INTMASK_1 SCTRL_INTMASK_BASE -#define SCTRL_INTMASK_2 31 -#define SCTRL_INTMASK_3 32 -#define SCTRL_INTMASK_4 33 -#define SCTRL_INTMASK_5 34 -#define SCTRL_INTMASK_6 35 - -#define SCTRL_INTPTR_BASE SCTRL_INTSRC_3 -#define SCTRL_INTMSK_BASE SCTRL_INTMASK_3 -/* - * The last two definitions are for register offset compatibility. - * These will be used with FRU_REG_INDEX macros, for P1.0 and P1.5, so 1.5 - * register offsets in upper nibble of fru_offset[] tables will be consistent. - * This happens because the HLTHY INTs and INT masks come before the slots and - * FRUs. That's what changes the register offsets. - * The only EXCEPTION is the ALARM RESET register, which for P1.5 is not - * BASE + 3 as in all other cases, but BASE + 1. FRU_REG_INDEX(code,base) does - * NOT work for ALARM RESET. Use ALARM_RESET_REG_INDEX() instead. - * FRU_REG_INDEX() works differently for P1.0, using offset groups to calculate - * the index to the fru_offset[] table. - */ - -/* - * REGISTER BIT OFFSETS - * For the bit definitions, the SCB register sets are divided into two tables, - * 1. scb_1x_fru_offset[] bit-offsets for all FRUs and - * Interrupt events - * 2. scb_1x_sys_offset[] for system command/control registers - * and any remaining bits, like MPID. - * - * This is a bit historic from P0.6,P1.0 days. - * The fru_offset table is indexed using the SCTRL_EVENT_ codes defined in - * mct_topology.h. Almost all of these describe interrupt generated events. - * Ths sys_offset table contains anything else, mostly the System Control - * registers and some bit definitions form the config/status registers. - */ - -/* - * scb_1x_sys_offset[] table indicies - * - * SCB System Command/Control Registers from 1.0 and 1.5 - */ -#define SCTRL_SYS_PS1_OFF 0 -#define SCTRL_SYS_PS2_OFF 1 -#define SCTRL_SYS_PS_OFF_BASE SCTRL_SYS_PS1_OFF -#define SCTRL_SYS_PS1_ON 2 -#define SCTRL_SYS_PS2_ON 3 -#define SCTRL_SYS_PS_ON_BASE SCTRL_SYS_PS1_ON -#define SCTRL_SYS_SCB_CTL0 4 -#define SCTRL_SYS_SCB_CTL1 5 -#define SCTRL_SYS_SCB_CTL2 6 -#define SCTRL_SYS_SCB_CTL3 7 -#define SCTRL_SYS_PSM_INT_ENABLE 8 -#define SCTRL_SYS_SCB_INIT 9 -#define SCTRL_SYS_TEST_MODE 10 -#define SCTRL_SYS_SCBLED 11 -#define SCTRL_SYS_SPA0 12 -#define SCTRL_SYS_SPA1 13 -#define SCTRL_SYS_SPA2 14 -#define SCTRL_SYS_RSVD 15 -/* - * SCB Config/Status register leftovers - */ -#define SCTRL_CFG_MPID0 16 -#define SCTRL_CFG_MPID1 17 -#define SCTRL_CFG_MPID2 18 -#define SCTRL_CFG_MPID3 19 -#define SCTRL_CFG_SCB_STAT0 20 -#define SCTRL_CFG_SCB_STAT2 21 -/* - * SCB Identity register offsets - */ -#define SCTRL_SCBID0 22 -#define SCTRL_SCBID_SIZE 4 -#define SCTRL_SCB_TEST 23 - -/* numregs table order and indicies */ -#define SCTRL_SYS_CMD_NUM 0 -#define SCTRL_LED_NOK_NUM 1 -#define SCTRL_LED_OK_NUM 2 -#define SCTRL_LED_NUM 3 -#define SCTRL_RESET_NUM 4 -#define SCTRL_BLINK_NUM 5 -#define SCTRL_SCBID_NUM 6 -#define SCTRL_BHLTHY_NUM 7 -#define SCTRL_SYSCFG_NUM 8 -#define SCTRL_INTSRC_NUM 9 -#define SCTRL_INTMSK_NUM 10 -#define SCTRL_TOTAL_NUM 11 - - -/* - * Macro Definitions for register and bit offset values - */ -/* macros names for scb_numregs[] access */ -#define SCTRL_SYSCMD_NUMREGS (scb_numregs[SCTRL_SYS_CMD_NUM]) -#define SCTRL_LED_NOK_NUMREGS (scb_numregs[SCTRL_LED_NOK_NUM]) -#define SCTRL_LED_OK_NUMREGS (scb_numregs[SCTRL_LED_OK_NUM]) -#define SCTRL_LED_NUMREGS (scb_numregs[SCTRL_LED_NUM]) -#define SCTRL_RESET_NUMREGS (scb_numregs[SCTRL_RESET_NUM]) -#define SCTRL_BLINK_NUMREGS (scb_numregs[SCTRL_BLINK_NUM]) -#define SCTRL_SCBID_NUMREGS (scb_numregs[SCTRL_SCBID_NUM]) -#define SCTRL_BHLTHY_NUMREGS (scb_numregs[SCTRL_BHLTHY_NUM]) -#define SCTRL_CFG_NUMREGS (scb_numregs[SCTRL_SYSCFG_NUM]) -#define SCTRL_INTR_NUMREGS (scb_numregs[SCTRL_INTSRC_NUM]) -#define SCTRL_MASK_NUMREGS (scb_numregs[SCTRL_INTMSK_NUM]) -#define SCTRL_TOTAL_NUMREGS (scb_numregs[SCTRL_TOTAL_NUM]) - -/* - * Maximum number of registers in a register group - * Needed for above register groups array sizing - */ -#define SCTRL_MAX_GROUP_NUMREGS 16 - -#define SCSB_REG_ADDR(rx) (scb_reg_index[rx]) -#define FRU_INDEX(code) (event_to_index(code)) -#define FRU_OFFSET_BASE(rx) (MCT_MAX_FRUS * (IS_SCB_P15 ? 0 : \ - (IS_GROUP1(rx) ? REG_GROUP1 : \ - (IS_GROUP3(rx) ? REG_GROUP3 : \ - REG_GROUP2)))) -#define FRU_OFFSET_VAL(code, rx) (scb_fru_offset[FRU_OFFSET_BASE(rx) + \ - FRU_INDEX(code)]) - -#define FRU_OFFSET(code, rx) (FRU_OFFSET_VAL(code, rx) & 0xf) -#define FRU_REG_INDEX(code, rx) (((FRU_OFFSET_VAL(code, rx) >> 4) \ - & 0xf) + rx) -#define FRU_REG_ADDR(code, rx) (SCSB_REG_ADDR(FRU_REG_INDEX(code, rx))) -#define SYS_OFFSET_VAL(idx) (scb_sys_offset[idx]) -#define SYS_OFFSET(idx) (SYS_OFFSET_VAL(idx) & 0xf) -#define SYS_REG_INDEX(idx, rx) (((SYS_OFFSET_VAL(idx) >> 4) \ - & 0xf) + rx) - -#define ALARM_RESET_REG_INDEX(code, rx) ((IS_SCB_P15 ? 1 : \ - ((FRU_OFFSET_VAL(code, rx) >> 4) \ - & 0xf)) + rx) -#define FRU_UNIT_TO_EVCODE(type, unit) (type_to_code1[type] << (unit - 1)) - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t *scb_reg_index; -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t *scb_numregs; -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t *scb_fru_offset; -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t *scb_sys_offset; - -/* - * -------------------- - * Common TABLES - * -------------------- - */ - -/* - * FRU type to unit 1 event_code, see FRU_UNIT_TO_EVCODE() macro above. - * Table order is dependent on scsb_utype_t definition in mct_topology.h - */ -/*LINTED table used in scsb.o and system utilities*/ -static uint32_t type_to_code1[] = { - SCTRL_EVENT_SLOT1, - SCTRL_EVENT_PDU1, - SCTRL_EVENT_PS1, - SCTRL_EVENT_DISK1, - SCTRL_EVENT_FAN1, - SCTRL_EVENT_ALARM, - SCTRL_EVENT_SCB, - SCTRL_EVENT_SSB, - SCTRL_EVENT_CFTM, - SCTRL_EVENT_CRTM, - SCTRL_EVENT_PRTM -}; - -/* - * -------------------- - * P0.6 and P1.0 TABLES - * -------------------- - */ - -/* - * MonteCarlo: Programming Inteface Specifications Version 0.9 - * 10/27/99 - * NOTE: P0.6 FANs and PDUs were different - */ -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_10_reg_index[] = { - 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 00 - 07 */ - 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, /* 08 - 15 */ - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, /* 16 - 23 */ - 0xD8, 0xD9, 0xDA, 0xDB, 0x00, 0x00, 0xDC, 0x00, /* 24 - 31 */ - 0xDC, 0xDD, 0xDE, 0xDF, 0xD8, 0xDC, 0x00, 0x00, /* 32 - 39 */ -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_10_numregs[] = { - 2, 4, 4, 8, 2, 2, 1, 2, 6, 4, 4, 32 -}; - - -/* - * MCT_MAX_FRUS * REG_GROUPS_NUM - * - * FRU order: - * 0 - 9: Slots 1 - 10 - * 10 - 11: PDU 1 - 2 - * 12 - 13: PS 1 - 2 - * 14 - 16: Disk 1 - 3 - * 17 - 19: Fan 1 - 3 - * 20: Alarm Card - * 21: SCB - * 22: SSB - * 23: CRTM - * 24: CFTM - * 25: PRTM - * 26: PWRDWN - * 27: REPLACE - * 28: ALARM_INT - * 29 - 31: Unused - * - * A register base group offset is added to the register base value to - * find the index into the reg_index table. - * Example: LED_NOK_BASE + '1' = register for slots 7-10 NOK LEDs - * This offset is encoded in the upper nibble in the following table - * of register offsets per FRU/EVENT. - * The register base group definitions are: - * base group offset group - * ---------------------- ------------ - * SCTRL_LED_NOK_BASE G1 - * SCTRL_LED_OK_BASE G1 - * SCTRL_RESET_BASE G1 - * SCTRL_BLINK_OK_BASE G1 - * SCTRL_BHLTHY_BASE G1 - * SCTRL_SYSCFG_BASE G2 - * SCTRL_INTSRC_BASE G3 - * SCTRL_INTMASK_BASE G3 - * SCTRL_SYS_CMD_BASE G4 - * - * See FRU_OFFSET() macro - */ -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_10_fru_offset[] = { - /* Register Group 1 */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* SLOT 1-6 */ - 0x10, 0x11, 0x12, 0x13, /* SLOT 7-10 */ - 0x35, 0x15, 0x21, 0x22, /* PDU/PS 1-2 */ - 0x23, 0x24, 0x25, /* Disks 1-3 */ - 0x33, 0x34, 0x35, /* Fans 1-3 */ - 0xFF, 0x20, 0xFF, /* Alarm Card, SCB, SSB */ - 0xFF, 0xFF, 0xFF, /* CRTM, CFTM, PRTM */ - 0xFF, 0xFF, 0xFF, /* PWRDWN, SCBRR, ACINT */ - 0xFF, 0xFF, 0xFF, /* Unused */ - /* Register Group 2 */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* SLOT 1-6 */ - 0x10, 0x11, 0x12, 0x13, /* SLOT 7-10 */ - 0x25, 0x27, 0x30, 0x31, /* PDU/PS 1-2 */ - 0x40, 0x41, 0x42, /* Disks 1-3 */ - 0x32, 0x33, 0x34, /* Fans 1-3 */ - 0x50, 0xFF, 0x35, /* Alarm Card, SCB, SSB */ - 0x43, 0x44, 0x45, /* CRTM, CFTM, PRTM */ - 0xFF, 0xFF, 0xFF, /* PWRDWN, SCBRR, ACINT */ - 0x24, 0x26, 0x20, /* STAT0, STAT1, MPID0 */ - /* Register Group 3 */ - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, /* SLOT 1-6 */ - 0x37, 0x26, 0x27, 0x16, /* SLOT 7-10 */ - 0xFF, 0xFF, 0x10, 0x11, /* PDU/PS 1-2 */ - 0x20, 0x21, 0x22, /* Disks 1-3 */ - 0x12, 0x13, 0x14, /* Fans 1-3 */ - 0x30, 0x04, 0x15, /* Alarm Card, SCB, SSB */ - 0x23, 0x24, 0x25, /* CRTM, CFTM, PRTM */ - 0x00, 0x02, 0x03, /* PWRDWN, SCBRR, ACINT */ - 0xFF, 0xFF, 0xFF, /* Unused */ -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_10_sys_offset[] = { - 0x00, 0x01, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, - 0x15, 0x16, 0xFF, 0x02, 0x03, 0x04, 0x05, 0x14, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x26, 0x00, 0x07, -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_10_int_masks[] = { - 0x11, 0x2F, 0x3F, 0xFF, 0x00, 0x00, -}; - - -/* - * -------------------- - * P1.5 and P2.0 TABLES - * -------------------- - */ - -/* - * MonteCarlo: Programming Inteface Specifications - * Chapter 12 from the MonteCarlo System Specification - * 02/08/00: Chapter update from Carl Meert - */ -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_15_reg_index[] = { - 0xE0, 0xE1, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, /* 00 - 07 */ - 0xC5, 0xC5, 0xE2, 0xE3, 0xC6, 0xC7, 0xC8, 0xCF, /* 08 - 15 */ - 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0x00, 0x00, /* 16 - 23 */ - 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, /* 24 - 31 */ - 0xD8, 0xD9, 0xDA, 0xDB, 0xD2, 0xD8, 0x00, 0x00, /* 32 - 39 */ -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_15_numregs[] = { - 2, 3, 3, 6, 2, 3, 1, 2, 4, 6, 6, 48 -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_15_fru_offset[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* SLOT 1-6 */ - 0x06, 0x07, 0x16, 0x17, /* SLOT 7-10 */ - 0x11, 0x13, 0x26, 0x27, /* PDU/PS 1-2 */ - 0x23, 0x24, 0x25, /* Disks 1-3 */ - 0x20, 0x21, 0xFF, /* Fans 1-3 */ - 0x30, 0x15, 0x33, /* Alarm Card, SCB, SSB */ - 0x31, 0x14, 0x32, /* CRTM, CFTM, PRTM */ - 0x34, 0xFF, 0x36, /* PWRDWN, SCBRR, ACINT */ - 0xFF, 0xFF, 0xFF, /* Unused */ -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_15_sys_offset[] = { - 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x34, 0x35, 0x36, 0x37, 0x10, 0x12, 0x00, 0x07 -}; - -/*LINTED table used in scsb.o and system utilities*/ -static uchar_t scb_15_int_masks[] = { - 0xFF, 0x00, 0xFF, 0x1A, 0xFB, 0x7F, -}; - -#define SCSB_NO_OF_BOARDS 1 - -/* - * scsb_state values - * outside _KERNEL for smctrl test utility - */ -#define SCSB_DOWN 0x0000 /* never really used */ -#define SCSB_UP 0x0001 -#define SCSB_OPEN 0x0002 -#define SCSB_EXCL 0x0004 -#define SCSB_APP_SLOTLED_CTRL 0x0008 -#define SCSB_KS_UPDATE 0x0010 -#define SCSB_FROZEN 0x0020 -#define SCSB_DEBUG_MODE 0x0040 -#define SCSB_DIAGS_MODE 0x0080 -#define SCSB_UNUSED_08 0x0100 -#define SCSB_PSM_INT_ENABLED 0x0200 -#define SCSB_UMUTEX 0x0400 -#define SCSB_CONDVAR 0x0800 -#define SCSB_SCB_PRESENT 0x1000 -#define SCSB_SSB_PRESENT 0x2000 -#define SCSB_UNUSED_14 0x4000 -#define SCSB_UNUSED_15 0x8000 -#define SCSB_MINOR_NODE 0x00010000 -#define SCSB_PROP_CREATE 0x00020000 -#define SCSB_IMUTEX 0x00040000 -#define SCSB_I2C_PHANDLE 0x00080000 -#define SCSB_I2C_TRANSFER 0x00100000 -#define SCSB_TOPOLOGY 0x00200000 -#define SCSB_KSTATS 0x00400000 -#define SCSB_IS_TONGA 0x00800000 -#define SCSB_P10_PROM 0x01000000 -#define SCSB_P15_PROM 0x02000000 -#define SCSB_P20_PROM 0x04000000 -#define SCSB_P2X_PROM 0x08000000 -#define SCSB_P06_PROM 0x10000000 -#define SCSB_P06_INTR_ON 0x20000000 -#define SCSB_P06_NOINT_KLUGE 0x40000000 -#define SCSB_IN_INTR 0x80000000 -#define SCSB_HSC_INIT 0x0001 -#define SCSB_ENUM_ENABLED 0x0002 -#define SCSB_ALARM_CARD_PRES 0x0004 -#define SCSB_ALARM_CARD_IN_USE 0x0008 -#define SCSB_AC_SLOT_INTR_DONE 0x0010 -#define SCSB_HSC_CTC_PRES 0x0020 -#define SCSB_HSC_UNUSED_06 0x0040 -#define SCSB_HSC_UNUSED_07 0x0080 -#define SCSB_HSC_UNUSED_08 0x0100 -#define SCSB_HSC_UNUSED_09 0x0200 -#define SCSB_HSC_UNUSED_10 0x0400 -#define SCSB_HSC_UNUSED_11 0x0800 -#define SCSB_HSC_UNUSED_12 0x1000 -#define SCSB_HSC_UNUSED_13 0x2000 -#define SCSB_HSC_UNUSED_14 0x4000 -#define SCSB_HSC_UNUSED_15 0x8000 - -#ifdef _KERNEL - -/* - * The System Controller Board uses the Xilinx to control the I2C bus. - * The address should really go to scsb.conf file. - * The I2C address of the System Controller Board - */ -#define SCSB_I2C_ADDR 0x80 -#define SCSB_I2C_ADDR_MASK 0xFF - -#define SCSB_DEVICE_NAME "scsb" -#define SCSB_INTR_PIL 4 - -/* - * definitions for Interrupt Event Code handling - */ -#define EVC_FIFO_SIZE 8 -#define EVC_PROCS_MAX 16 -/* - * return values for check_event_procs() - */ -#define EVC_NO_EVENT_CODE 1 -#define EVC_NO_CURR_PROC 2 -#define EVC_NEW_EVENT_CODE 3 -#define EVC_OR_EVENT_CODE 4 -#define EVC_FAILURE 5 -/* - * scsb_queue_ops() definitions - * Operations: - */ -#define QPROCSOFF 1 -#define QPUT_INT32 2 -#define QFIRST_AVAILABLE 3 -#define QFIRST_OPEN 4 -#define QFIND_QUEUE 5 -/* - * Return values: - * 0 - 15 are valid clone numbers used as index to clone_devs[] - * and returned for some operations instead of QOP_OK. - */ -#define QOP_OK 16 -#define QOP_FAILED -1 - -/* - * minor_t definitions - * bits 2-0 SCB instance 0-7 - * bit 3 Clone device for sm_open() - * bits 7-4 Cloned device numbers for a total of 15: 0x1# - 0xf# - * Must start with '1' to avoid conflict with: - * 0x00 non-clone device node for instance 0 - * 0x08 the clone device node for instance 0 - * the new minor_t for the clone is all of the above. - */ -#define SCSB_INSTANCE_MASK 0x07 -#define SCSB_CLONE 0x08 -#define SCSB_CLONES_MASK 0xf0 -#define SCSB_CLONES_SHIFT 4 -#define SCSB_CLONES_FIRST 1 -#define SCSB_CLONES_MAX 16 -#define SCSB_GET_CLONE(minor) ((minor&SCSB_CLONES_MASK)>>SCSB_CLONES_SHIFT) -#define SCSB_GET_INSTANCE(minor) \ - (minor&SCSB_INSTANCE_MASK) -#define SCSB_MAKE_MINOR(inst, clnum) \ - (inst|(clnum<<SCSB_CLONES_SHIFT)|SCSB_CLONE) - -typedef struct clone_dev { - queue_t *cl_rq; - minor_t cl_minor; - uint32_t cl_flags; -} clone_dev_t; - -typedef struct { - uint32_t scsb_instance; - uint32_t scsb_state; - uint32_t scsb_hsc_state; - int ac_slotnum; /* Alarm Card Slot Number */ - kmutex_t scsb_mutex; - kcondvar_t scsb_cv; - uint32_t scsb_opens; - dev_info_t *scsb_dev; - i2c_client_hdl_t scsb_phandle; /* i2c private handle from i2c nexus */ - mblk_t *scsb_mp; /* reserved for interrupt processing */ - i2c_transfer_t *scsb_i2ctp; /* pointer to read/write structure */ - uchar_t scsb_data_reg[SCSB_DATA_REGISTERS]; - int scsb_i2c_addr; /* i2c addr. */ - queue_t *scsb_rq; /* read q for scsb_instance */ - timeout_id_t scsb_btid; /* qbufcall, or qtimeout id */ - kmutex_t scsb_imutex; - ddi_iblock_cookie_t scsb_iblock; - kstat_t *ks_leddata; - kstat_t *ks_state; - kstat_t *ks_topology; - kstat_t *ks_evcreg; - uint32_t scsb_i2c_errcnt; - boolean_t scsb_err_flag; /* latch err until kstat read */ - boolean_t scsb_kstat_flag; /* do i2c trans for kstat */ - uint32_t scsb_clopens; - clone_dev_t clone_devs[SCSB_CLONES_MAX]; -} scsb_state_t; - -int scsb_led_get(scsb_state_t *, scsb_uinfo_t *, scsb_led_t led_type); -int scsb_led_set(scsb_state_t *, scsb_uinfo_t *, scsb_led_t led_type); -int scsb_reset_unit(scsb_state_t *, scsb_uinfo_t *); -int scsb_bhealthy_slot(scsb_state_t *, scsb_uinfo_t *); -int scsb_slot_occupancy(scsb_state_t *, scsb_uinfo_t *); - -#if defined(DEBUG) -extern void prom_printf(const char *, ...); -void scsb_debug_prnt(char *, uintptr_t, uintptr_t, - uintptr_t, uintptr_t, uintptr_t); - -#define DEBUG0(fmt)\ - scsb_debug_prnt(fmt, 0, 0, 0, 0, 0); -#define DEBUG1(fmt, a1)\ - scsb_debug_prnt(fmt, (uintptr_t)(a1), 0, 0, 0, 0); -#define DEBUG2(fmt, a1, a2)\ - scsb_debug_prnt(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); -#define DEBUG3(fmt, a1, a2, a3)\ - scsb_debug_prnt(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\ - (uintptr_t)(a3), 0, 0); -#define DEBUG4(fmt, a1, a2, a3, a4)\ - scsb_debug_prnt(fmt, (uintptr_t)(a1), (uintptr_t)(a2),\ - (uintptr_t)(a3), (uintptr_t)(a4), 0); -#else -#define DEBUG0(fmt) -#define DEBUG1(fmt, a1) -#define DEBUG2(fmt, a1, a2) -#define DEBUG3(fmt, a1, a2, a3) -#define DEBUG4(fmt, a1, a2, a3, a4) -#endif - - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _MONTECARLO_SYS_SCSB_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/scsb_cbi.h b/usr/src/uts/sun4u/montecarlo/sys/scsb_cbi.h deleted file mode 100644 index a9d4cb4727..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/scsb_cbi.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2000 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _MONTECARLO_SYS_SCSB_CBI_H -#define _MONTECARLO_SYS_SCSB_CBI_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef _KERNEL - -/* - * scsb_cbi.h - * scsb callback interface for some the MonteCarlo/Tonga I2C FRU drivers - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum scsb_fru_event { - FRU_INTR_EVENT, - FRU_CMD_EVENT -} scsb_fru_event_t; - -scsb_fru_status_t scsb_fru_register(void (*cb_func)(void *, - scsb_fru_event_t, - scsb_fru_status_t), - void *softstate_ptr, - fru_id_t fru_id); -void scsb_fru_unregister(void *soft_ptr, fru_id_t fru_id); -scsb_fru_status_t scsb_fru_status(fru_id_t fru_id); - -#ifdef __cplusplus -} -#endif -#endif /* _KERNEL */ - -#endif /* _MONTECARLO_SYS_SCSB_CBI_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/scsb_led.h b/usr/src/uts/sun4u/montecarlo/sys/scsb_led.h deleted file mode 100644 index ba55e77e5f..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/scsb_led.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2000 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Netra ct SCB/SSB driver (scsb) support for controlling the - * LEDs on the System Status Board that represent the cPCI Slots. - * Each slot has a pair of LEDs, one green (OK) and one amber (NOK). - * The OK (green) LED can also be made to blink. - */ - -#ifndef _SYS_SCSB_LED_H -#define _SYS_SCSB_LED_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define _SCSBIOC ('s' << 8) - -/* The ioctl command */ -#define ENVC_IOC_SETFSP (_SCSBIOC | 23) - -/* Netra ct 400 has 5 slots, Netra ct 800 has 8 slots. Including CPU */ -#define NCT800_MAX_SLOTS 8 -#define NCT400_MAX_SLOTS 5 - -typedef uint16_t scsb_unum_t; - -typedef enum { - SLOT = 0 -} scsb_utype_t; - -typedef enum { - NOK = 0, - OK = 1, -} scsb_led_t; - -typedef enum { - OFF = 0, - ON = 1, - BLINK = 2 -} scsb_ustate_t; - -typedef struct { - scsb_unum_t unit_number; - scsb_utype_t unit_type; - scsb_ustate_t unit_state; - scsb_led_t led_type; -} scsb_uinfo_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_SCSB_LED_H */ diff --git a/usr/src/uts/sun4u/montecarlo/sys/scsbioctl.h b/usr/src/uts/sun4u/montecarlo/sys/scsbioctl.h deleted file mode 100644 index f796aac40b..0000000000 --- a/usr/src/uts/sun4u/montecarlo/sys/scsbioctl.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2000 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _MONTERCARLO_SYS_SCSBIOCTL_H -#define _MONTERCARLO_SYS_SCSBIOCTL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SCB HW information, which is needed in scsb.h for scsb.c. - * there are 32 data registers on the system controller board - * most are used in P1.0, all are used in P1.5 - */ -#define SCSB_DATA_REGISTERS 48 - - -#define _SCSBIOC ('s' << 8) - -#define SCSBIOC_GET_STATUS (_SCSBIOC | 1) /* Internal */ -#define SCSBIOC_I2C_XFER (_SCSBIOC | 2) /* Internal */ - -#define SCSBIOC_ALL_LEDS_ON (_SCSBIOC | 3) /* Diagnostics */ -#define SCSBIOC_ALL_LEDS_OFF (_SCSBIOC | 4) /* Diagnostics */ - -#define SCSBIOC_FREEZE (_SCSBIOC | 5) /* Internal */ -#define SCSBIOC_RESTORE (_SCSBIOC | 6) /* Internal */ - -#define SCSBIOC_LED_NOK_SET (_SCSBIOC | 7) /* Diagnostics */ -#define SCSBIOC_LED_NOK_GET (_SCSBIOC | 8) /* Diagnostics */ -#define SCSBIOC_LED_OK_SET (_SCSBIOC | 9) /* Diagnostics */ -#define SCSBIOC_LED_OK_GET (_SCSBIOC | 10) /* Diagnostics */ -#define SCSBIOC_GET_FAN_STATUS (_SCSBIOC | 11) /* Internal */ -#define SCSBIOC_RESET_UNIT (_SCSBIOC | 12) /* Diagnostics */ -#define SCSBIOC_FAKE_INTR (_SCSBIOC | 13) /* Internal */ -#define SCSBIOC_BSELECT_SET (_SCSBIOC | 14) /* Internal */ -#define SCSBIOC_BSELECT_GET (_SCSBIOC | 15) /* Internal */ -#define SCSBIOC_BHEALTHY_SET (_SCSBIOC | 16) /* Internal */ -#define SCSBIOC_BHEALTHY_GET (_SCSBIOC | 17) /* Internal */ -#define SCSBIOC_GET_INTR_ARRAY (_SCSBIOC | 18) /* Internal */ - -#define ENVC_IOC_ACQUIRE_SLOT_LED_CTRL (_SCSBIOC | 21) /* EnvMon */ -#define ENVC_IOC_RELEASE_SLOT_LED_CTRL (_SCSBIOC | 22) /* EnvMon */ -#define ENVC_IOC_SETFSP (_SCSBIOC | 23) /* EnvMon */ -#define ENVC_IOC_GETDSKLED (_SCSBIOC | 24) /* EnvMon */ -#define ENVC_IOC_SETDSKLED (_SCSBIOC | 25) /* EnvMon */ -#define ENVC_IOC_REGISTER_PID (_SCSBIOC | 26) /* EnvMon */ -#define ENVC_IOC_UNREGISTER_PID (_SCSBIOC | 27) /* EnvMon */ -#define ENVC_IOC_ACCONF_RESTORED (_SCSBIOC | 28) /* EnvMon */ -#define ENVC_IOC_ACCONF_STORED (_SCSBIOC | 29) /* EnvMon */ - -#define SCSBIOC_REG_READ (_SCSBIOC | 31) /* Diagnostic */ -#define SCSBIOC_REG_WRITE (_SCSBIOC | 32) /* Diagnostic */ -#define SCSBIOC_GET_VERSIONS (_SCSBIOC | 33) /* Diagnostic */ - -/* these are for debug/testing and may be temporary */ -#define SCSBIOC_SHUTDOWN_POLL (_SCSBIOC | 41) /* Internal */ -#define SCSBIOC_SLOT_OCCUPANCY (_SCSBIOC | 42) /* Internal */ -#define SCSBIOC_INTEVENT_POLL (_SCSBIOC | 43) /* Internal */ -#define SCSBIOC_TOPOLOGY_DUMP (_SCSBIOC | 44) /* Internal */ -#define SCSBIOC_VALUE_MODE (_SCSBIOC | 45) /* Internal */ -#define SCSBIOC_GET_SLOT_INFO (_SCSBIOC | 46) /* Internal */ -#define SCSBIOC_DEBUG_MODE (_SCSBIOC | 52) /* Internal */ - -/* - * SCSBIOC_GET_VERSIONS structure - */ -#define SCSB_MODSTR_LEN 64 -#define SCSB_VERSTR_LEN 12 -typedef struct scsb_ids { - char modldrv_string[SCSB_MODSTR_LEN]; - char scsb_version[SCSB_VERSTR_LEN]; - uint8_t promid; - uint8_t pad[3]; -} scsb_ids_t; - - -typedef enum { - GET = 0, - SET = 1 -} scsb_op_t; - -typedef enum { - NOK = 0, - OK = 1, - NOUSE = 2 -} scsb_led_t; - -#define SCSB_LED_TYPES 2 - -typedef enum { - OFF = 0, - ON = 1, - BLINK = 2 -} scsb_ustate_t; - -typedef struct { - scsb_unum_t unit_number; - scsb_utype_t unit_type; - scsb_ustate_t unit_state; - scsb_led_t led_type; -} scsb_uinfo_t; - - -/* SCSBIOC_GET_STATUS data */ -typedef struct { - uchar_t scsb_reg[SCSB_DATA_REGISTERS]; -} scsb_status_t; - - -/* SCSBIOC_REG_READ / SCSBIOC_REG_WRITE data */ -typedef struct { - int16_t ioc_result; /* O: return value */ - uint16_t ioc_resio; /* O: bytes not transfered */ - uint16_t ioc_wlen; /* I: length of write buffer */ - uint16_t ioc_rlen; /* I: length of read buffer */ - uchar_t ioc_rbuf[64]; - uchar_t ioc_wbuf[64]; - uchar_t ioc_regindex; -} scsb_ioc_rdwr_t; - - -#ifdef __cplusplus -} -#endif - -#endif /* _MONTERCARLO_SYS_SCSBIOCTL_H */ diff --git a/usr/src/uts/sun4u/montecarlo/ttymux_dacf/Makefile b/usr/src/uts/sun4u/montecarlo/ttymux_dacf/Makefile deleted file mode 100644 index 5a584c25a9..0000000000 --- a/usr/src/uts/sun4u/montecarlo/ttymux_dacf/Makefile +++ /dev/null @@ -1,102 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the montecarlo ttymux_dacf -# kernel module. -# -# montecarlo implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = ttymux_dacf -OBJECTS = $(TTYMUX_DACF_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(TTYMUX_DACF_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MONTECARLO_DACF_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.montecarlo - -# -# Override defaults. -# -ALL_BUILDS = $(ALL_BUILDSONLY64) -DEF_BUILDS = $(DEF_BUILDSONLY64) -CLEANLINTFILES = $(LINT32_FILES) - -FILEMODE = 644 - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/montecarlo/Makefile.targ diff --git a/usr/src/uts/sun4u/snowbird/Makefile b/usr/src/uts/sun4u/snowbird/Makefile deleted file mode 100644 index ffc40d8267..0000000000 --- a/usr/src/uts/sun4u/snowbird/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright 2018 Gary mills -# -# This makefile drives the production of the sun4u snowbird platform -# module. -# -# sun4u snowbird implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -include $(UTSBASE)/sun4u/snowbird/Makefile.snowbird - -# -# -# - -def := TARGET= def -all := TARGET= all -install := TARGET= install -install_h := TARGET= install_h -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -lintlib := TARGET= lintlib -modlintlib := TARGET= modlintlib -modlist := TARGET= modlist -modlist := NO_STATE= -K $$MODSTATE$$$$ -clean.lint := TARGET= clean.lint -check := TARGET= check - -IMPLEMENTED_PLATFORM = SUNW,Netra-CP2300 - -# -# Default build targets. -# -.KEEP_STATE: - -.PARALLEL: $(SNOWBIRD_KMODS) - -def all clean clobber clean.lint modlist: $(SNOWBIRD_KMODS) - -install: $(ROOT_SNOWBIRD_DIR) $(USR_SNOWBIRD_DIR) \ - $(USR_SNOWBIRD_INC_DIR) \ - $(USR_SNOWBIRD_SBIN_DIR) \ - $(USR_SNOWBIRD_SBIN_PRTDIAG) \ - $(USR_SNOWBIRD_SBIN_FRUADM) \ - $(USR_SNOWBIRD_LIB_DIR) \ - .WAIT $(SNOWBIRD_KMODS) \ - ttymux_dacf ttymux.conf - -modlintlib: $(SNOWBIRD_KMODS) - -$(SNOWBIRD_KMODS): FRC - @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET) - -ttymux_dacf: $(ROOT_SNOWBIRD_DACF_DIR_64) - -@$(RM) $(ROOT_SNOWBIRD_DACF_DIR_64)/$@ - $(SYMLINK) $(ROOT_SNOWBIRD_DACF_LINK_64)/$@ \ - $(ROOT_SNOWBIRD_DACF_DIR_64)/$@ - - -ttymux.conf: $(ROOT_SNOWBIRD_DRV_DIR_32) - -@$(RM) $(ROOT_SNOWBIRD_DRV_DIR_32)/$@ - $(SYMLINK) $(ROOT_SNOWBIRD_DRV_LINK_32)/$@ \ - $(ROOT_SNOWBIRD_DRV_DIR_32)/$@ - -install_h check: FRC - @cd sys; pwd; $(MAKE) $(TARGET) - -lint: modlintlib - -LINT_LIBS = $(LINT_LIB) \ - -L$(SNOWBIRD_LINT_LIB_DIR) \ - -L$(LINT_LIB_DIR) $(LINT_KMODS:%=-l%) \ - $(CLOSED_LINT_KMODS:%=-l%) \ - -L$(SPARC_LIB_DIR) $(SPARC_LINTS:%=-l%) - -lint.platmod: modlintlib - @-$(ECHO) "\nSnowbird Platform-dependent module: global crosschecks:" - @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/snowbird/Makefile.targ diff --git a/usr/src/uts/sun4u/snowbird/Makefile.files b/usr/src/uts/sun4u/snowbird/Makefile.files deleted file mode 100644 index 1623055eda..0000000000 --- a/usr/src/uts/sun4u/snowbird/Makefile.files +++ /dev/null @@ -1,43 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/sun4u/snowbird/Makefile -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines all file modules for the directory -# uts/sun4u/snowbird and its children. These are the source files -# which are snowbird "implementation architecture" dependent. -# - -# -# Object lists -# - -TODDS1307_OBJS = todds1307.o - -# -# Miscellaneous -# -INC_PATH += -I$(UTSBASE)/sun4u/snowbird diff --git a/usr/src/uts/sun4u/snowbird/Makefile.rules b/usr/src/uts/sun4u/snowbird/Makefile.rules deleted file mode 100644 index 4b0475b3c8..0000000000 --- a/usr/src/uts/sun4u/snowbird/Makefile.rules +++ /dev/null @@ -1,62 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/sun4u/snowbird/Makefile -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines the build rules for the directory -# uts/sun4u/snowbird and its children. -# - -# -# C object build rules -# - -# -# snowbird specific drivers -# - - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/snowbird/io/todds1307/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/snowbird/os/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# -# Lint object build rules -# - -# -# snowbird specific drivers -# - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/snowbird/io/todds1307/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/snowbird/os/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/sun4u/snowbird/Makefile.snowbird b/usr/src/uts/sun4u/snowbird/Makefile.snowbird deleted file mode 100644 index 961962c57f..0000000000 --- a/usr/src/uts/sun4u/snowbird/Makefile.snowbird +++ /dev/null @@ -1,115 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. -# -# -# Global definitions for sun4u snowbird implementation specific modules. -# uts/sun4u/snowbird/Makefile.snowbird -# - -# -# Define directories. -# -MONTECARLO = SUNW,UltraSPARC-IIi-Netract -SNOWBIRD = SUNW,Netra-CP2300 -ROOT_MONTECARLO_DIR = $(ROOT_PLAT_DIR)/$(MONTECARLO) -ROOT_SNOWBIRD_DIR = $(ROOT_PLAT_DIR)/SUNW,Netra-CP2300 -ROOT_SNOWBIRD_MOD_DIR = $(ROOT_SNOWBIRD_DIR)/kernel -ROOT_SNOWBIRD_MISC_DIR_32 = $(ROOT_SNOWBIRD_DIR)/kernel/misc -ROOT_SNOWBIRD_MISC_DIR_64 = $(ROOT_SNOWBIRD_MISC_DIR_32)/$(SUBDIR64) -ROOT_SNOWBIRD_KERN_DIR_32 = $(ROOT_SNOWBIRD_MOD_DIR) -ROOT_SNOWBIRD_KERN_DIR_64 = $(ROOT_SNOWBIRD_MOD_DIR)/$(SUBDIR64) -ROOT_SNOWBIRD_DRV_DIR_32 = $(ROOT_SNOWBIRD_MOD_DIR)/drv -ROOT_SNOWBIRD_DRV_DIR_64 = $(ROOT_SNOWBIRD_MOD_DIR)/drv/$(SUBDIR64) -ROOT_SNOWBIRD_DRV_LINK_32 = $(ROOT_SNOWBIRD_DRV_DIR_32:$(ROOT_SNOWBIRD_DIR)%=../../../$(MONTECARLO)%) -ROOT_SNOWBIRD_TOD_DIR_32 = $(ROOT_SNOWBIRD_MOD_DIR)/tod -ROOT_SNOWBIRD_TOD_DIR_64 = $(ROOT_SNOWBIRD_MOD_DIR)/tod/$(SUBDIR64) -ROOT_SNOWBIRD_DACF_DIR_32 = $(ROOT_SNOWBIRD_MOD_DIR)/dacf -ROOT_SNOWBIRD_DACF_DIR_64 = $(ROOT_SNOWBIRD_MOD_DIR)/dacf/$(SUBDIR64) -ROOT_SNOWBIRD_DACF_LINK_64 = $(ROOT_SNOWBIRD_DACF_DIR_64:$(ROOT_SNOWBIRD_DIR)%=../../../../$(MONTECARLO)%) - -ROOT_SNOWBIRD_KERN_DIR = $(ROOT_SNOWBIRD_KERN_DIR_$(CLASS)) -ROOT_SNOWBIRD_DRV_DIR = $(ROOT_SNOWBIRD_DRV_DIR_$(CLASS)) -ROOT_SNOWBIRD_TOD_DIR = $(ROOT_SNOWBIRD_TOD_DIR_$(CLASS)) -ROOT_SNOWBIRD_MISC_DIR = $(ROOT_SNOWBIRD_MISC_DIR_$(CLASS)) -ROOT_SNOWBIRD_DACF_DIR = $(ROOT_SNOWBIRD_DACF_DIR_$(CLASS)) - -ROOT_PLAT_MOD_DIRS += $(ROOT_SNOWBIRD_MOD_DIR) -ROOT_PLAT_MISC_DIRS += $(ROOT_SNOWBIRD_MISC_DIR) -ROOT_PLAT_DRV_DIRS += $(ROOT_SNOWBIRD_DRV_DIR) -ROOT_PLAT_DACF_DIRS += $(ROOT_SNOWBIRD_DACF_DIR) - -ROOT_SNOWBIRD_DACF_LINK = $(ROOT_SNOWBIRD_DACF_LINK_$(CLASS)) -ROOT_SNOWBIRD_DRV_LINK = $(ROOT_SNOWBIRD_DRV_LINK_$(CLASS)) - -USR_SNOWBIRD_DIR = $(USR_PLAT_DIR)/SUNW,Netra-CP2300 -USR_SNOWBIRD_INC_DIR = $(USR_SNOWBIRD_DIR)/include -USR_SNOWBIRD_SBIN_DIR = $(USR_SNOWBIRD_DIR)/sbin -USR_SNOWBIRD_SBIN_PRTDIAG = $(USR_SNOWBIRD_SBIN_DIR)/prtdiag -USR_SNOWBIRD_SBIN_FRUADM = $(USR_SNOWBIRD_SBIN_DIR)/fruadm -USR_SNOWBIRD_LIB_DIR = $(USR_SNOWBIRD_DIR)/lib -USR_SNOWBIRD_ISYS_DIR = $(USR_SNOWBIRD_INC_DIR)/sys - - -SNOWBIRD_LINT_LIB_DIR= $(UTSBASE)/$(PLATFORM)/snowbird/lint-libs/$(OBJS_DIR) - - -# Define Objects -# -SNOWBIRD_OBJS = snowbird.o - -# -# Define modules. -# -SNOWBIRD_KMODS = todds1307 platmod - -# -# Include the makefiles which define build rule templates, the -# collection of files per module, and a few specific flags. Note -# that order is significant, just as with an include path. The -# first build rule template which matches the files name will be -# used. By including these in order from most machine dependent -# to most machine independent, we allow a machine dependent file -# to be used in preference over a machine independent version -# (Such as a machine specific optimization, which preserves the -# interfaces.) -# - -include $(UTSBASE)/sun4u/snowbird/Makefile.files -# -# Include common rules. -# -include $(UTSBASE)/sun4u/Makefile.sun4u - -# -# Define the actual specific platforms -# -MACHINE_DEFS += -D$(PLATFORM) -D_MACHDEP -DSFMMU -MACHINE_DEFS += -D_SNOWBIRD - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - diff --git a/usr/src/uts/sun4u/snowbird/Makefile.targ b/usr/src/uts/sun4u/snowbird/Makefile.targ deleted file mode 100644 index 3eff14b011..0000000000 --- a/usr/src/uts/sun4u/snowbird/Makefile.targ +++ /dev/null @@ -1,104 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. -# -# uts/sun4u/snowbird/Makefile.targ -# Common targets for sun4u snowbird implementation specific modules. -# -# - -.KEEP_STATE: - -# -# Rules for implementation subdirectories. -# -$(ROOT_SNOWBIRD_DIR): $(ROOT_PLAT_DIR) - -$(INS.dir) - -$(ROOT_SNOWBIRD_MOD_DIR): $(ROOT_SNOWBIRD_DIR) - -$(INS.dir) - -$(ROOT_SNOWBIRD_DRV_DIR_32): $(ROOT_SNOWBIRD_MOD_DIR) - -$(INS.dir) - -$(ROOT_SNOWBIRD_DRV_DIR_64): $(ROOT_SNOWBIRD_DRV_DIR_32) - -$(INS.dir) - -$(ROOT_SNOWBIRD_TOD_DIR_32): $(ROOT_SNOWBIRD_MOD_DIR) - -$(INS.dir) - -$(ROOT_SNOWBIRD_TOD_DIR_64): $(ROOT_SNOWBIRD_TOD_DIR_32) - -$(INS.dir) - -$(ROOT_SNOWBIRD_MISC_DIR_32): $(ROOT_SNOWBIRD_MOD_DIR) - -$(INS.dir) - -$(ROOT_SNOWBIRD_MISC_DIR_64): $(ROOT_SNOWBIRD_MISC_DIR_32) - -$(INS.dir) - -$(ROOT_SNOWBIRD_DACF_DIR_32): $(ROOT_SNOWBIRD_MOD_DIR) - -$(INS.dir) - -$(ROOT_SNOWBIRD_DACF_DIR_64): $(ROOT_SNOWBIRD_DACF_DIR_32) - -$(INS.dir) - -$(ROOT_SNOWBIRD_MOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_SNOWBIRD_MOD_DIR) FRC - $(INS.file) - -$(ROOT_SNOWBIRD_DACF_DIR)/%: $(OBJS_DIR)/% $(ROOT_SNOWBIRD_DACF_DIR) FRC - $(INS.file) - -$(ROOT_SNOWBIRD_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_SNOWBIRD_MISC_DIR) FRC - $(INS.file) - -$(ROOT_SNOWBIRD_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_SNOWBIRD_DRV_DIR) FRC - $(INS.file) - -$(ROOT_SNOWBIRD_TOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_SNOWBIRD_TOD_DIR) FRC - $(INS.file) - -$(USR_SNOWBIRD_DIR): $(USR_PLAT_DIR) - $(INS.dir) - -$(USR_SNOWBIRD_INC_DIR): $(USR_SNOWBIRD_DIR) - -$(INS.dir) - -$(USR_SNOWBIRD_SBIN_DIR): $(USR_SNOWBIRD_DIR) - -$(INS.dir) - -$(USR_SNOWBIRD_SBIN_PRTDIAG): $(USR_SNOWBIRD_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/prtdiag $@ - -$(USR_SNOWBIRD_SBIN_FRUADM): $(USR_SNOWBIRD_SBIN_DIR) - $(RM) -r $@; $(SYMLINK) ../../$(PLATFORM)/sbin/fruadm $@ - -$(USR_SNOWBIRD_LIB_DIR): $(USR_SNOWBIRD_DIR) - -$(INS.dir) - -$(USR_SNOWBIRD_ISYS_DIR): $(USR_SNOWBIRD_INC_DIR) - -$(INS.dir) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/snowbird/Makefile.rules -include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c b/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c deleted file mode 100644 index e0fd37ee04..0000000000 --- a/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c +++ /dev/null @@ -1,785 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#include <sys/types.h> -#include <sys/conf.h> -#include <sys/devops.h> -#include <sys/kmem.h> -#include <sys/open.h> -#include <sys/file.h> -#include <sys/note.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> - -#include <sys/modctl.h> -#include <sys/stat.h> -#include <sys/clock.h> -#include <sys/reboot.h> -#include <sys/machsystm.h> -#include <sys/poll.h> -#include <sys/pbio.h> -#include <sys/sysmacros.h> - -/* Added for prom interface */ -#include <sys/promif.h> -#include <sys/promimpl.h> - -#include <sys/i2c/misc/i2c_svc.h> -#include <sys/todds1307.h> - -#define I2C_DELAY 20000 -#define DS1307_DEVICE_TYPE "rtc" - -/* - * Driver enrty routines - */ -static int todds1307_attach(dev_info_t *, ddi_attach_cmd_t); -static int todds1307_detach(dev_info_t *, ddi_detach_cmd_t); -static int todds1307_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); - -/* - * tod_ops entry routines - */ -static timestruc_t todds1307_get(void); -static void todds1307_set(timestruc_t); -static uint_t todds1307_set_watchdog_timer(uint_t); -static uint_t todds1307_clear_watchdog_timer(void); -static void todds1307_set_power_alarm(timestruc_t); -static void todds1307_clear_power_alarm(void); -static int todds1307_setup_prom(); -static void todds1307_rele_prom(); -static int todds1307_prom_getdate(struct rtc_t *rtc); -static int todds1307_prom_setdate(struct rtc_t *rtc); - -/* - * Local functions - */ -static int todds1307_read_rtc(struct rtc_t *); -static int todds1307_write_rtc(struct rtc_t *); - -/* Anchor for soft state structure */ -static void *ds1307_statep; -static int instance = -1; -static int todds1307_attach_done = 0; -static kmutex_t todds1307_rd_lock; -static ihandle_t todds1307_ihandle = 0; - -/* one second time out */ -#define I2c_CYCLIC_TIMEOUT 1000000000 -uint_t i2c_cyclic_timeout = I2c_CYCLIC_TIMEOUT; -static int sync_clock_once = 1; -static struct rtc_t soft_rtc; - -/* - * For debugging only - */ -static unsigned char int2bcd(int num); -static int bcd2int(unsigned char num); - -/* - * cp_ops structure - */ -static struct cb_ops ds1307_cbops = { - nodev, /* open */ - nodev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - nodev, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - NULL, /* poll */ - ddi_prop_op, /* cb_prop_op */ - NULL, /* streamtab */ - D_NEW | D_MP, /* Driver compatibility flag */ - CB_REV, /* rev */ - nodev, /* int (*cb_aread)() */ - nodev /* int (*cb_awrite)() */ -}; - -/* - * dev_ops structure - */ -static struct dev_ops ds1307_ops = { - DEVO_REV, /* devo_rev */ - 0, /* refcnt - reference cnt always set to 0 */ - todds1307_getinfo, /* getinfo - Maybe requred */ - nulldev, /* identify */ - nulldev, /* probe */ - todds1307_attach, /* attach */ - todds1307_detach, /* detach */ - nodev, /* reset */ - &ds1307_cbops, /* cb_ops - ds1307 does not need this(?) */ - NULL, /* bus_ops */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -static struct modldrv todds1307_modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "tod driver for DS1307 v1.12", /* Name of the module */ - &ds1307_ops, /* Pointer to dev_ops */ -}; - -/* - * Module linkage structure - */ -static struct modlinkage todds1307_modlinkage = { - MODREV_1, - &todds1307_modldrv, - 0 -}; - -int -_init(void) -{ - int error; - - if (strcmp(tod_module_name, "todds1307") == 0) { - if ((error = ddi_soft_state_init(&ds1307_statep, - sizeof (ds1307_state_t), 0)) != DDI_SUCCESS) { - return (error); - } - - tod_ops.tod_get = todds1307_get; - tod_ops.tod_set = todds1307_set; - tod_ops.tod_set_watchdog_timer = todds1307_set_watchdog_timer; - tod_ops.tod_clear_watchdog_timer = - todds1307_clear_watchdog_timer; - tod_ops.tod_set_power_alarm = todds1307_set_power_alarm; - tod_ops.tod_clear_power_alarm = todds1307_clear_power_alarm; - } - - (void) todds1307_setup_prom(); - - /* - * Install the module - */ - if ((error = mod_install(&todds1307_modlinkage)) != 0) { - ddi_soft_state_fini(&ds1307_statep); - return (error); - } - mutex_init(&todds1307_rd_lock, NULL, MUTEX_DEFAULT, NULL); - - return (0); -} - -int -_fini(void) -{ - int error = 0; - - if (strcmp(tod_module_name, "todds1307") == 0) { - error = EBUSY; - } else { - if ((error = mod_remove(&todds1307_modlinkage)) == 0) { - ddi_soft_state_fini(&ds1307_statep); - mutex_destroy(&todds1307_rd_lock); - todds1307_rele_prom(); - } - } - - return (error); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&todds1307_modlinkage, modinfop)); -} - -/* - * cyclical call to get tod. - */ -static void -todds1307_cyclic(void *arg) -{ - - (void) todds1307_read_rtc((struct rtc_t *)arg); - -} - -/* - * register ds1307 client device with i2c services, and - * allocate & initialize soft state structure. - */ -static int -todds1307_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - static ds1307_state_t *statep = NULL; - i2c_transfer_t *i2c_tp = NULL; - uint8_t tempVal = (uint8_t)0; - switch (cmd) { - - case DDI_ATTACH: - break; - case DDI_RESUME: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } - - if (instance != -1) { - return (DDI_FAILURE); - } - - instance = ddi_get_instance(dip); - - /* - * Allocate soft state structure - */ - if (ddi_soft_state_zalloc(ds1307_statep, instance) != DDI_SUCCESS) { - return (DDI_FAILURE); - } - - statep = ddi_get_soft_state(ds1307_statep, instance); - if (statep == NULL) { - return (DDI_FAILURE); - } - - statep->dip = dip; - - if (i2c_client_register(dip, &statep->ds1307_i2c_hdl) != I2C_SUCCESS) { - ddi_soft_state_free(ds1307_statep, instance); - delay(drv_usectohz(I2C_DELAY)); - return (DDI_FAILURE); - } - - /* check and initialize the oscillator */ - - (void) i2c_transfer_alloc(statep->ds1307_i2c_hdl, - &i2c_tp, 1, 1, I2C_SLEEP); - i2c_tp->i2c_version = I2C_XFER_REV; - i2c_tp->i2c_flags = I2C_WR_RD; - i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; /* Read 00h */ - i2c_tp->i2c_wlen = 1; - i2c_tp->i2c_rlen = 1; - - if ((i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); - ddi_soft_state_free(ds1307_statep, instance); - delay(drv_usectohz(I2C_DELAY)); - return (DDI_FAILURE); - } - - tempVal = i2c_tp->i2c_rbuf[0]; - - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); - - if (tempVal & 0x80) { /* check Oscillator */ - (void) i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, - 2, 1, I2C_SLEEP); - i2c_tp->i2c_version = I2C_XFER_REV; - i2c_tp->i2c_flags = I2C_WR; - i2c_tp->i2c_wbuf[0] = 0x00; - i2c_tp->i2c_wbuf[1] = - (uchar_t)(i2c_tp->i2c_rbuf[0]& 0x7f); - i2c_tp->i2c_wlen = 2; - /* Enable oscillator */ - if ((i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) - != I2C_SUCCESS) { - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, - i2c_tp); - ddi_soft_state_free(ds1307_statep, instance); - return (DDI_FAILURE); - } - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); - } - - /* - * Create a periodical handler to read TOD. - */ - ASSERT(statep->cycid == NULL); - statep->cycid = ddi_periodic_add(todds1307_cyclic, &soft_rtc, - i2c_cyclic_timeout, DDI_IPL_1); - - statep->state = TOD_ATTACHED; - todds1307_attach_done = 1; - ddi_report_dev(dip); - - return (DDI_SUCCESS); -} - -/* - * Unregister ds1307 client device with i2c services and free - * soft state structure. - */ -/*ARGSUSED*/ -static int -todds1307_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - switch (cmd) { - - /* - * Once attached, do not allow detach because the system constantly - * calling todds1307_get() to get the time. If the driver is detached - * and the system try to get the time, the system will have memory - * problem. - * - * ds1307_state_t *statep = NULL; - * case DDI_DETACH: - * if ((statep = ddi_get_soft_state(ds1307_statep, - * instance)) == NULL) { - * return (ENOMEM); - * } - * i2c_client_unregister(statep->ds1307_i2c_hdl); - * ddi_soft_state_free(ds1307_statep, instance); - * return (DDI_SUCCESS); - */ - case DDI_SUSPEND: - return (DDI_SUCCESS); - - default: - return (DDI_FAILURE); - } -} - -/* *********************** tod_ops entry points ******************** */ - -/* - * Read the current time from the DS1307 chip and convert to UNIX form. - * Should be called with tod_clock held. - */ - -static timestruc_t -todds1307_get(void) -{ - timestruc_t ts; - todinfo_t tod; - struct rtc_t rtc; - - ASSERT(MUTEX_HELD(&tod_lock)); - - if (sync_clock_once) { - (void) todds1307_read_rtc(&soft_rtc); - sync_clock_once = 0; - } else { - tod_status_set(TOD_GET_FAILED); - return (hrestime); - } - - bcopy(&soft_rtc, &rtc, sizeof (rtc)); - - /* - * 00 - 68 = 2000 thru 2068 - * 69-99 = 1969 thru 1999 - */ - tod.tod_year = rtc.rtc_year; - if (rtc.rtc_year <= 68) - tod.tod_year += 100; - tod.tod_month = rtc.rtc_mon; - tod.tod_day = rtc.rtc_dom; - tod.tod_dow = rtc.rtc_dow; - tod.tod_hour = rtc.rtc_hrs; - tod.tod_min = rtc.rtc_min; - tod.tod_sec = rtc.rtc_sec; - - /* read was successful so ensure failure flag is clear */ - tod_status_clear(TOD_GET_FAILED); - - ts.tv_sec = tod_to_utc(tod); - ts.tv_nsec = 0; - return (ts); -} - -/* - * Program DS1307 with the specified time. - * Must be called with tod_lock held. The TOD - * chip supports date from 1969-2068 only. We must - * reject requests to set date below 2000. - */ -static void -todds1307_set(timestruc_t ts) -{ - struct rtc_t rtc; - todinfo_t tod = utc_to_tod(ts.tv_sec); - int year; - - - ASSERT(MUTEX_HELD(&tod_lock)); - - /* - * Year is base 1900, valid year range 1969-2068 - */ - if ((tod.tod_year < 69) || (tod.tod_year > 168)) - return; - - year = tod.tod_year; - if (year >= 100) - year -= 100; - - rtc.rtc_year = int2bcd(year); - rtc.rtc_mon = int2bcd(tod.tod_month); - rtc.rtc_dom = int2bcd(tod.tod_day); - rtc.rtc_dow = int2bcd(tod.tod_dow); - rtc.rtc_hrs = int2bcd(tod.tod_hour); - rtc.rtc_min = int2bcd(tod.tod_min); - rtc.rtc_sec = int2bcd(tod.tod_sec); - - (void) todds1307_write_rtc(&rtc); -} - -/* ARGSUSED */ -static void -todds1307_set_power_alarm(timestruc_t ts) -{ - ASSERT(MUTEX_HELD(&tod_lock)); -} - -/* ARGSUSED */ -static void -todds1307_clear_power_alarm(void) -{ - ASSERT(MUTEX_HELD(&tod_lock)); -} - -/* ARGSUSED */ -static uint_t -todds1307_set_watchdog_timer(uint_t timeoutval) -{ - ASSERT(MUTEX_HELD(&tod_lock)); - return (0); -} - -/* ARGSUSED */ -static uint_t -todds1307_clear_watchdog_timer(void) -{ - ASSERT(MUTEX_HELD(&tod_lock)); - return (0); -} - -/* ********************** Local functions ***************************** */ - -static char tod_read[7] = {-1, -1, -1, -1, -1, -1, -1}; -static int -todds1307_read_rtc(struct rtc_t *rtc) -{ - static ds1307_state_t *statep = NULL; - i2c_transfer_t *i2c_tp = NULL; - int i2c_cmd_status = I2C_FAILURE; - int counter = 4; - - if (!todds1307_attach_done) { - return (todds1307_prom_getdate(rtc)); - } - - statep = ddi_get_soft_state(ds1307_statep, instance); - if (statep == NULL) { - cmn_err(CE_WARN, "todds1307: ddi_get_soft_state failed"); - return (DDI_FAILURE); - } - - mutex_enter(&todds1307_rd_lock); - - /* - * Allocate 1 byte for write buffer and 7 bytes for read buffer to - * to accomodate sec, min, hrs, dayOfWeek, dayOfMonth, year - */ - if ((i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 1, - 7, I2C_SLEEP)) != I2C_SUCCESS) { - mutex_exit(&todds1307_rd_lock); - return (DDI_FAILURE); - } - - do { - i2c_tp->i2c_version = I2C_XFER_REV; - i2c_tp->i2c_flags = I2C_WR_RD; - i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; /* Start from reg 0x00 */ - i2c_tp->i2c_wlen = 1; /* Write one byte address */ - i2c_tp->i2c_rlen = 7; /* Read 7 regs */ - - if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, - i2c_tp)) != I2C_SUCCESS) { - drv_usecwait(I2C_DELAY); - goto done; - } - /* for first read, need to get valid data */ - while (tod_read[0] == -1 && counter > 0) { - /* move data to static buffer */ - bcopy(i2c_tp->i2c_rbuf, tod_read, 7); - - /* now read again */ - /* Start reading reg from 0x00 */ - i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; - i2c_tp->i2c_wlen = 1; /* Write one byte address */ - i2c_tp->i2c_rlen = 7; /* Read 7 regs */ - if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, - i2c_tp)) != I2C_SUCCESS) { - drv_usecwait(I2C_DELAY); - goto done; - } - /* if they are not the same, then read again */ - if (bcmp(tod_read, i2c_tp->i2c_rbuf, 7) != 0) { - tod_read[0] = -1; - counter--; - } - } - - } while (i2c_tp->i2c_rbuf[0] == 0x59 && - /* if seconds register is 0x59 (BCD), add data should match */ - bcmp(&tod_read[1], &i2c_tp->i2c_rbuf[1], 6) != 0 && - counter-- > 0); - - if (counter < 0) - cmn_err(CE_WARN, "i2ctod: TOD Chip failed ??"); - - /* move data to static buffer */ - bcopy(i2c_tp->i2c_rbuf, tod_read, 7); - - - rtc->rtc_year = bcd2int(i2c_tp->i2c_rbuf[6]); - rtc->rtc_mon = bcd2int(i2c_tp->i2c_rbuf[5]); - rtc->rtc_dom = bcd2int(i2c_tp->i2c_rbuf[4]); - rtc->rtc_dow = bcd2int(i2c_tp->i2c_rbuf[3]); - rtc->rtc_hrs = bcd2int(i2c_tp->i2c_rbuf[2]); - rtc->rtc_min = bcd2int(i2c_tp->i2c_rbuf[1]); - rtc->rtc_sec = bcd2int(i2c_tp->i2c_rbuf[0]); - -done: - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); - - mutex_exit(&todds1307_rd_lock); - return (i2c_cmd_status); -} - - -static int -todds1307_write_rtc(struct rtc_t *rtc) -{ - ds1307_state_t *statep = NULL; - i2c_transfer_t *i2c_tp = NULL; - int i2c_cmd_status = I2C_SUCCESS; - - - if (!todds1307_attach_done) { - return (todds1307_prom_setdate(rtc)); - } - - statep = ddi_get_soft_state(ds1307_statep, instance); - if (statep == NULL) { - return (DDI_FAILURE); - } - - if ((i2c_cmd_status = i2c_transfer_alloc(statep->ds1307_i2c_hdl, - &i2c_tp, 8, 0, I2C_SLEEP)) != I2C_SUCCESS) { - return (i2c_cmd_status); - } - - i2c_tp->i2c_version = I2C_XFER_REV; - i2c_tp->i2c_flags = I2C_WR; - i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; - i2c_tp->i2c_wbuf[1] = rtc->rtc_sec; - i2c_tp->i2c_wbuf[2] = rtc->rtc_min; - i2c_tp->i2c_wbuf[3] = rtc->rtc_hrs; - i2c_tp->i2c_wbuf[4] = rtc->rtc_dow; - i2c_tp->i2c_wbuf[5] = rtc->rtc_dom; - i2c_tp->i2c_wbuf[6] = rtc->rtc_mon; - i2c_tp->i2c_wbuf[7] = rtc->rtc_year; - i2c_tp->i2c_wlen = 8; - - if ((i2c_cmd_status = i2c_transfer(statep->ds1307_i2c_hdl, - i2c_tp)) != I2C_SUCCESS) { - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); - /* delay(drv_usectohz(I2C_DELAY)); */ - drv_usecwait(I2C_DELAY); - return (i2c_cmd_status); - } - - tod_read[0] = -1; /* invalidate saved data from read routine */ - - (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); - - return (i2c_cmd_status); -} - - -/*ARGSUSED*/ -static int -todds1307_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, - void **result) -{ - ds1307_state_t *softsp; - - if (instance == -1) { - return (DDI_FAILURE); - } - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if ((softsp = ddi_get_soft_state(ds1307_statep, instance)) - == NULL) - return (DDI_FAILURE); - *result = (void *)softsp->dip; - return (DDI_SUCCESS); - - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)(uintptr_t)instance; - return (DDI_SUCCESS); - - default: - return (DDI_FAILURE); - } -} - -/* - * Conversion functions - */ -static unsigned char -int2bcd(int num) { - return (((num / 10) << 4) /* tens BCD digit in high four bits */ - + (num % 10)); /* units digit goes in low four bits */ -} - -static int -bcd2int(unsigned char num) { - return (((num >> 4) * 10) /* 10 times high-order four bits */ - + (num & 0x0f)); /* plus low-order four bits */ -} - -/* - * Finds the device node with device_type "rtc" and opens it to - * execute the get-time method - */ -static int -todds1307_setup_prom() -{ - pnode_t todnode; - char tod1307_devpath[MAXNAMELEN]; - - if ((todnode = prom_findnode_bydevtype(prom_rootnode(), - DS1307_DEVICE_TYPE)) == OBP_NONODE) - return (DDI_FAILURE); - - /* - * We now have the phandle of the rtc node, we need to open the - * node and get the ihandle - */ - if (prom_phandle_to_path(todnode, tod1307_devpath, - sizeof (tod1307_devpath)) < 0) { - cmn_err(CE_WARN, "prom_phandle_to_path failed"); - return (DDI_FAILURE); - } - - /* - * Now open the node and store it's ihandle - */ - if ((todds1307_ihandle = prom_open(tod1307_devpath)) == NULL) { - cmn_err(CE_WARN, "prom_open failed"); - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -/* - * Closes the prom interface - */ -static void -todds1307_rele_prom() -{ - (void) prom_close(todds1307_ihandle); -} - -/* - * Read the date using "get-time" method in rtc node - * PROM returns 1969-1999 when reading 69-99 and - * 2000-2068 when reading 00-68 - */ -static int -todds1307_prom_getdate(struct rtc_t *rtc) -{ - int year; - cell_t ci[12]; - - ci[0] = p1275_ptr2cell("call-method"); /* Service name */ - ci[1] = 2; /* # of arguments */ - ci[2] = 7; /* # of result cells */ - ci[3] = p1275_ptr2cell("get-time"); - ci[4] = p1275_ihandle2cell(todds1307_ihandle); - - promif_preprom(); - (void) p1275_cif_handler(&ci); - promif_postprom(); - - year = p1275_cell2int(ci[6]); - rtc->rtc_mon = p1275_cell2int(ci[7]); - rtc->rtc_dom = p1275_cell2int(ci[8]); - rtc->rtc_dow = 0; - rtc->rtc_hrs = p1275_cell2int(ci[9]); - rtc->rtc_min = p1275_cell2int(ci[10]); - rtc->rtc_sec = p1275_cell2int(ci[11]); - if (year >= 2000) - year -= 2000; - else - year -= 1900; - rtc->rtc_year = year; - - return (DDI_SUCCESS); -} - -/* - * Read the date using "set-time" method in rtc node - * For values 00 - 68, write 2000-2068, and for 69-99, - * write 1969-1999 - */ -static int -todds1307_prom_setdate(struct rtc_t *rtc) -{ - int year; - cell_t ci[12]; - - year = rtc->rtc_year; - - if ((year < 0) || (year > 99)) - return (DDI_FAILURE); - - if (year <= 68) - year = rtc->rtc_year + 2000; - else - year = rtc->rtc_year + 1900; - - ci[0] = p1275_ptr2cell("call-method"); /* Service name */ - ci[1] = 8; /* # of arguments */ - ci[2] = 0; /* # of result cells */ - ci[3] = p1275_ptr2cell("set-time"); - ci[4] = p1275_ihandle2cell(todds1307_ihandle); - ci[5] = p1275_int2cell(year); - ci[6] = p1275_int2cell(rtc->rtc_mon); - ci[7] = p1275_int2cell(rtc->rtc_dom); - ci[8] = p1275_int2cell(rtc->rtc_hrs); - ci[9] = p1275_int2cell(rtc->rtc_min); - ci[10] = p1275_int2cell(rtc->rtc_sec); - - promif_preprom(); - (void) p1275_cif_handler(&ci); - promif_postprom(); - - return (DDI_SUCCESS); -} diff --git a/usr/src/uts/sun4u/snowbird/os/snowbird.c b/usr/src/uts/sun4u/snowbird/os/snowbird.c deleted file mode 100644 index 27af12bf4c..0000000000 --- a/usr/src/uts/sun4u/snowbird/os/snowbird.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sysmacros.h> -#include <sys/sunddi.h> -#include <sys/esunddi.h> -#include <sys/sunndi.h> - -#include <sys/platform_module.h> -#include <sys/errno.h> - -#define SHARED_SMBUS_PATH "/pci@1f,0/pci@1,1/pmu@3/i2c@0,0/i2c-nvram@0,8e" -static dev_info_t *shared_smbus_dip; -static kmutex_t snowbird_smbus_mutex; - -void -startup_platform(void) -{ - mutex_init(&snowbird_smbus_mutex, NULL, NULL, NULL); -} - -int -set_platform_tsb_spares() -{ - return (0); -} - -void -set_platform_defaults(void) -{ - extern char *tod_module_name; - tod_module_name = "todds1307"; -} - -/* - * Definitions for accessing the pci config space of the isa node - * of Southbridge. - */ -#define PLATFORM_ISA_PATHNAME "/pci@1f,0/isa@7" -#define PLATFORM_ISA_PATHNAME_WITH_SIMBA "/pci@1f,0/pci@1,1/isa@7" -ddi_acc_handle_t platform_isa_handle; /* handle for isa pci space */ - -void -load_platform_drivers(void) -{ - dev_info_t *dip; /* dip of the isa driver */ - - if (ddi_install_driver("power") != DDI_SUCCESS) - cmn_err(CE_WARN, "Failed to install \"power\" driver."); - - /* - * It is OK to return error because 'us' driver is not available - * in all clusters (e.g. missing in Core cluster). - */ - (void) ddi_install_driver("us"); - - /* - * Install Isa driver. This is required for the southbridge IDE - * workaround - to reset the IDE channel during IDE bus reset. - * Panic the system in case ISA driver could not be loaded or - * any problem in accessing its pci config space. Since the register - * to reset the channel for IDE is in ISA config space!. - */ - dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME_WITH_SIMBA, 0); - - if (dip == NULL) - dip = e_ddi_hold_devi_by_path(PLATFORM_ISA_PATHNAME, 0); - - if (dip == NULL) { - cmn_err(CE_PANIC, "Could not install the isa driver\n"); - return; - } - - if (pci_config_setup(dip, &platform_isa_handle) != DDI_SUCCESS) { - cmn_err(CE_PANIC, "Could not get the config space of isa\n"); - return; - } - - /* - * Figure out which smbus_dip is shared with OBP for the nvram - * device, so the lock can be acquired. - * - * This should really be done elsewhere, like startup_platform, but - * that runs before the devinfo tree is setup with configure(). - * So it is here until there is a better place. - */ - dip = e_ddi_hold_devi_by_path(SHARED_SMBUS_PATH, 0); - - if (dip != NULL) { - ASSERT(dip != NULL); - shared_smbus_dip = ddi_get_parent(dip); - - ndi_hold_devi(shared_smbus_dip); - ndi_rele_devi(dip); - } else { - shared_smbus_dip = NULL; - } - - /* - * Install the TOD driver - */ - if (ddi_install_driver("todds1307") != DDI_SUCCESS) - cmn_err(CE_WARN, "Failed to install \"todds1307\" driver."); -} - -/* - * This routine provides a workaround for a bug in the SB chip which - * can cause data corruption. Will be invoked from the IDE HBA driver for - * Acer SouthBridge at the time of IDE bus reset. - */ -/*ARGSUSED*/ -int -plat_ide_chipreset(dev_info_t *dip, int chno) -{ - uint8_t val; - int ret = DDI_SUCCESS; - - val = pci_config_get8(platform_isa_handle, 0x58); - /* - * The dip passed as the argument is not used for snowbird. - * This will be needed for platforms which have multiple on-board SB, - * The dip passed will be used to match the corresponding ISA node. - */ - switch (chno) { - case 0: - /* - * First disable the primary channel then re-enable it. - * As per ALI no wait should be required in between have - * given 1ms delay in between to be on safer side. - * bit 2 of register 0x58 when 0 disable the channel 0. - * bit 2 of register 0x58 when 1 enables the channel 0. - */ - pci_config_put8(platform_isa_handle, 0x58, val & 0xFB); - drv_usecwait(1000); - pci_config_put8(platform_isa_handle, 0x58, val); - break; - case 1: - /* - * bit 3 of register 0x58 when 0 disable the channel 1. - * bit 3 of register 0x58 when 1 enables the channel 1. - */ - pci_config_put8(platform_isa_handle, 0x58, val & 0xF7); - drv_usecwait(1000); - pci_config_put8(platform_isa_handle, 0x58, val); - break; - default: - /* - * Unknown channel number passed. Return failure. - */ - ret = DDI_FAILURE; - } - - return (ret); -} - - - -/*ARGSUSED*/ -int -plat_cpu_poweron(struct cpu *cp) -{ - return (ENOTSUP); /* not supported on this platform */ -} - -/*ARGSUSED*/ -int -plat_cpu_poweroff(struct cpu *cp) -{ - return (ENOTSUP); /* not supported on this platform */ -} - -/*ARGSUSED*/ -void -plat_freelist_process(int mnode) -{ -} - -char *platform_module_list[] = { - (char *)0 -}; - -/*ARGSUSED*/ -void -plat_tod_fault(enum tod_fault_type tod_bad) -{ -} - -/* - * Unfortunately, snowbird's smbus controller is used by both OBP - * and the OS's i2c drivers. The 'eeprom' command executes - * OBP code to handle property requests. If eeprom didn't do this, or if the - * controllers were partitioned so that all devices on a given controller were - * driven by either OBP or the OS, this wouldn't be necessary. - * - * Note that getprop doesn't have the same issue as it reads from cached - * memory in OBP. - */ - -/* - * Common locking enter code - */ -void -plat_setprop_enter(void) -{ - mutex_enter(&snowbird_smbus_mutex); -} - -/* - * Common locking exit code - */ -void -plat_setprop_exit(void) -{ - mutex_exit(&snowbird_smbus_mutex); -} - -/* - * Called by smbus driver - */ -void -plat_shared_i2c_enter(dev_info_t *dip) -{ - if (dip == shared_smbus_dip) { - plat_setprop_enter(); - } -} - -/* - * Called by smbus driver - */ -void -plat_shared_i2c_exit(dev_info_t *dip) -{ - if (dip == shared_smbus_dip) { - plat_setprop_exit(); - } -} diff --git a/usr/src/uts/sun4u/snowbird/platmod/Makefile b/usr/src/uts/sun4u/snowbird/platmod/Makefile deleted file mode 100644 index 60340b2180..0000000000 --- a/usr/src/uts/sun4u/snowbird/platmod/Makefile +++ /dev/null @@ -1,108 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the sun4u snowbird platform -# module. -# -# sun4u implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = platmod -OBJECTS = $(SNOWBIRD_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(SNOWBIRD_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_SNOWBIRD_MISC_DIR)/$(MODULE) - -PLAT_DIR = . -HERE = ../snowbird/platmod - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/snowbird/Makefile.snowbird - -# -# Override defaults -# -CLEANFILES += $(PLATLIB) $(SYM_MOD) - -# -# Define targets -# -ALL_TARGET = $(SYM_MOD) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -check: - -LINT_LIB_DIR = $(SNOWBIRD_LINT_LIB_DIR) - -$(PLATLIB): $(OBJECTS) - $(BUILD.SO) $(OBJECTS) - -$(SYM_MOD): $(UNIX_O) $(PLATLIB) - @echo "resolving symbols against unix.o" - @(cd $(UNIX_DIR); pwd; \ - PLAT_DIR=$(HERE) SYM_MOD=$(HERE)/$(SYM_MOD) $(MAKE) symcheck) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/snowbird/Makefile.targ diff --git a/usr/src/uts/sun4u/snowbird/sys/Makefile b/usr/src/uts/sun4u/snowbird/sys/Makefile deleted file mode 100644 index 76da598e4a..0000000000 --- a/usr/src/uts/sun4u/snowbird/sys/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/sun4u/snowbird/sys/Makefile -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -UTSBASE = ../../.. - -# -# include global definitions -# -include ../Makefile.snowbird - -# -# Override defaults. -# -FILEMODE = 644 - -HDRS= todds1307.h - -ROOTDIR= $(ROOT)/usr/include/sys - -ROOTHDRS= $(HDRS:%=$(ROOTDIR)/%) - -CHECKHDRS= $(HDRS:%.h=%.check) - -.KEEP_STATE: - -.PARALLEL: $(CHECKHDRS) $(ROOTHDRS) - -install_h: - -check: $(CHECKHDRS) - -# -# install rules -# -$(ROOTDIR)/%: % $(ROOTDIR) - $(INS.file) - -$(ROOTDIR): - $(INS.dir) - -FRC: - -include ../Makefile.targ diff --git a/usr/src/uts/sun4u/snowbird/sys/todds1307.h b/usr/src/uts/sun4u/snowbird/sys/todds1307.h deleted file mode 100644 index dd006c174b..0000000000 --- a/usr/src/uts/sun4u/snowbird/sys/todds1307.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _TODDS1307_H -#define _TODDS1307_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/i2c/clients/i2c_client.h> - -extern char *v_rtc_addr_reg; -extern volatile uint8_t *v_rtc_data_reg; - -#define DS1307_ADDR_REG *(volatile uint8_t *)v_rtc_addr_reg -#define DS1307_DATA_REG *(volatile uint8_t *)v_rtc_data_reg -#define DS1307_NODE_TYPE "ddi_i2c:tod" - -struct rtc_t { - uint8_t rtc_sec; /* Seconds[0-60] */ - uint8_t rtc_min; /* Minutes[0-60] */ - uint8_t rtc_hrs; /* Hours[(1-12)/(0-23)] */ - uint8_t rtc_dow; /* Day of week[1-7] */ - uint8_t rtc_dom; /* Day of month[(1-28/29/30/31)] */ - uint8_t rtc_mon; /* Month[1-12] */ - uint8_t rtc_year; /* Year[00-99] */ - uint8_t rtc_ctl; /* DS1307 Control register */ -}; - - -/* - * Register definitions for RTC driver (DS1307 chip) - */ - -#define RTC_SEC 0x00 /* 00h Second */ -#define RTC_MIN 0x01 /* 01h Minutes */ -#define RTC_HRS 0x02 /* 02h Hours */ -#define RTC_DOW 0x03 /* 03h Day-of-week */ -#define RTC_DOM 0x04 /* 04h Day-of-month */ -#define RTC_MON 0x05 /* 05h Month */ -#define RTC_YEAR 0x06 /* 06h Year */ -#define RTC_CTL 0x07 /* 07h Control reg. */ - -/* Oscillator */ - -#define OSCILLATOR_REG 0x00 /* Oscillator Reg Addr */ -#define OSCILLATOR_DISABLE 0x80 - -/* per instance based */ - -#define TOD_DETACHED 0x00 /* TOD detached */ -#define TOD_ATTACHED 0x01 /* TOD attached */ - -typedef struct ds1307_state { - i2c_client_hdl_t ds1307_i2c_hdl; - char i2ctod_name[MAXNAMELEN]; /* node name */ - kmutex_t i2ctod_mutex; /* protects soft state */ - int instance; - dev_info_t *dip; - uint32_t state; - ddi_periodic_t cycid; /* periodical callback */ - struct rtc_t rtc; - i2c_transfer_t *i2c_tp; - ddi_softintr_t soft_intr_id; - uint32_t progress; -}ds1307_state_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _TODDS1307_H */ diff --git a/usr/src/uts/sun4u/snowbird/todds1307/Makefile b/usr/src/uts/sun4u/snowbird/todds1307/Makefile deleted file mode 100644 index a5dc08e8fb..0000000000 --- a/usr/src/uts/sun4u/snowbird/todds1307/Makefile +++ /dev/null @@ -1,87 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/sun4u/snowbird/todds1307/Makefile -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -# This makefile drives the production of the snowbird_fans driver. -# -# Path to the base of the uts directory tree (usually /usr/src/uts). - -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = todds1307 -OBJECTS = $(TODDS1307_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(TODDS1307_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_SNOWBIRD_TOD_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/snowbird/Makefile.snowbird - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -I../../../sun4u - -LDFLAGS += -dy -N misc/i2c_svc - -CPPFLAGS += -I$(UTSBASE)/sun4u/snowbird - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -LINT_LIB_DIR = $(SNOWBIRD_LINT_LIB_DIR) - -# -# Include common targets -# -include $(UTSBASE)/sun4u/snowbird/Makefile.targ diff --git a/usr/src/uts/sun4u/sys/smc_commands.h b/usr/src/uts/sun4u/sys/smc_commands.h deleted file mode 100644 index 1b6aea9cf9..0000000000 --- a/usr/src/uts/sun4u/sys/smc_commands.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_SMC_COMMANDS_H -#define _SYS_SMC_COMMANDS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Address of BMC on IPMB */ -#define BMC_IPMB_ADDR 0x20 -#define SMC_CPCI_SLOT0_ADDR 0xB0 -#define SMC_CPCI_SLOT_ADDR(X) (SMC_CPCI_SLOT0_ADDR + \ - 2 * ((X) - 1)) - -typedef struct ctsmc_code_ent { - uint8_t code; - char *name; -} ctsmc_code_ent_t; - -/* - * Definition of Network Function Codes - */ -typedef enum { - SMC_NETFN_CHASSIS_REQ = 0x0, - SMC_NETFN_CHASSIS_RSP = 0x1, - SMC_NETFN_BRIDGE_REQ = 0x2, - SMC_NETFN_BRIDGE_RSP = 0x3, - SMC_NETFN_SENSOR_REQ = 0x4, - SMC_NETFN_SENSOR_RSP = 0x5, - SMC_NETFN_APP_REQ = 0x6, - SMC_NETFN_APP_RSP = 0x7, - SMC_NETFN_FIRMWARE_REQ = 0x8, - SMC_NETFN_FIRMWARE_RSP = 0x9, - SMC_NETFN_STORAGE_REQ = 0xA, - SMC_NETFN_STORAGE_RSP = 0xB -} smc_netfn_t; - -/* - * Definition of Completion codes - */ -typedef enum { - SMC_CC_SUCCESS = 0x00, - SMC_CC_NODE_BUSY = 0xC0, - SMC_CC_INVALID_COMMAND = 0xC1, - SMC_CC_INVALID_COMMAND_ON_LUN = 0xC2, - SMC_CC_TIMEOUT = 0xC3, - SMC_CC_RESOURCE_NOTAVAIL = 0xC4, - SMC_CC_RESERVATION = 0xC5, - SMC_CC_REQ_TRUNC = 0xC6, - SMC_CC_REQLEN_NOTVALID = 0xC7, - SMC_CC_REQLEN_EXCEED = 0xC8, - SMC_CC_PARAM_OUT_OF_RANGE = 0xC9, - SMC_CC_REQUEST_BYTES_FAILED = 0xCA, - SMC_CC_NOT_PRESENT = 0xCB, - SMC_CC_INVALID_FIELD = 0xCC, - SMC_CC_ILLEGAL_COMMAND = 0xCD, - SMC_CC_RESPONSE_FAILED = 0xCE, - SMC_CC_DUPLICATE_REQUEST = 0xCF, - SMC_CC_SDR_UPDATE_MODE = 0xD0, - SMC_CC_FIRMWARE_UPDATE_MODE = 0xD1, - SMC_CC_INIT_IN_PROGRESS = 0xD2, - SMC_CC_UNSPECIFIED_ERROR = 0xFF -} smc_cc_t; - -typedef enum { - SMC_BMC_LUN, - SMC_OEM1_LUN, - SMC_SMS_LUN, - SMC_OEM2_LUN -} smc_lun_t; - -/* - * App command codes for commands/event notifications etc. - */ -typedef enum { - SMC_GET_DEVICE_ID = 0x01, - SMC_COLD_RESET = 0x02, - SMC_WARM_RESET = 0x03, - SMC_GET_SELFTEST_RESULTS = 0x04, - SMC_MANUFACTURING_TEST_ON = 0x05, - SMC_SET_ACPI_POWER_STATE = 0x06, - SMC_GET_ACPI_POWER_STATE = 0x07, - SMC_GET_DEVICE_GUID = 0x08, - SMC_RESET_WATCHDOG_TIMER = 0x22, - SMC_EXPIRED_WATCHDOG_NOTIF = 0x23, /* Sent by driver */ - SMC_SET_WATCHDOG_TIMER = 0x24, - SMC_GET_WATCHDOG_TIMER = 0x25, - SMC_SET_GLOBAL_ENABLES = 0x2E, - SMC_GET_GLOBAL_ENABLES = 0x2F, - SMC_CLEAR_MESSAGE_FLAGS = 0x30, - SMC_GET_MESSAGE_FLAGS = 0x31, - SMC_ENABLE_MESSAGE_CHANNEL_RECEIVE = 0x32, - SMC_GET_MESSAGE = 0x33, - SMC_SEND_MESSAGE = 0x34, - SMC_READ_EVENT_MSG_BUFFER = 0x35, - SMC_SEND_TO_EVENT_MSG_BUFFER = 0x36, /* Changed from IPMI */ - SMC_MASTER_WR_RD_I2C = 0x52, - SMC_GET_GEOGRAPHICAL_ADDRESS = 0x55, - SMC_GET_BACKPLANE_TYPE = 0x57, - SMC_SELECT_MEMORY_DEVICE = 0x60, - SMC_READ_SELECTED_MEMORY_DEVICE = 0x61, - SMC_READ_MEMORY_DEVICE = 0x62, - SMC_WRITE_SELECTED_MEMORY_DEVICE = 0x63, - SMC_WRITE_MEMORY_DEVICE = 0x64, - SMC_ERASE_SELECTED_MEMORY_DEVICE = 0x65, - SMC_LOCK_UNLOCK_SELECTED_MEMORY = 0x66, - SMC_COMPUTE_CRC16_OF_SELECTED_MEMORY_DEVICE = 0x67, - SMC_COMPUTE_CRC16_OF_MEMORY_DEVICE = 0x68, - SMC_FILL_MEMORY_DEVICE = 0x6a, - SMC_QUERY_FIRMWARE_VERSION = 0x6f, - SMC_RESET_DEVICE = 0x70, - SMC_GET_ROLE_INFO = 0x71, - SMC_GET_FLASH_AND_BOOT_VERSION = 0x72, - SMC_GET_LOCAL_HA_SIGNAL_STATUS = 0x73, - SMC_SELECT_HA_HOTSWAP_MODE = 0x80, - SMC_GET_HA_HOTSWAP_SIGNAL_STATE = 0x81, - SMC_SET_HA_HOTSWAP_SIGNAL_STATE = 0x82, - SMC_NOTIFY_SMC_OF_HOST_HEALTH = 0x83, - SMC_TURN_ON_OFF_BLUE_LED = 0x84, - SMC_GET_EXECUTION_STATE = 0x85, - SMC_GET_SMC_UPTIME = 0x86, - SMC_ENUM_NOTIF = 0x87, - SMC_IPMI_RESPONSE_NOTIF = 0x88, - SMC_SET_INTERFACE_TIMEOUT = 0x89, - SMC_GET_INTERFACE_TIMEOUT = 0x8A, - SMC_SMC_LOCAL_EVENT_NOTIF = 0x8B, - SMC_GET_DEVICE_TABLE_DATA = 0x8C, - SMC_IPMI_MASTER_WR_RD_I2C = 0x90, - SMC_GET_SMC_SELF_TEST_RESULT = 0xA0, - SMC_READ_SMC_PLD_REGISTER = 0xA1, - SMC_WRITE_SMC_PLD_REGISTER = 0xA2, - SMC_SET_ROLE = 0xC0, - SMC_SET_CPCI_INTMASK = 0xC1, - SMC_GET_CPCI_INTMASK = 0xC2, - SMC_EEPROM_WRITE = 0xC3, - SMC_EEPROM_READ = 0xC4, - SMC_SET_STATE = 0xDE, - SMC_GET_STATE = 0xDF, - SMC_SET_DHCP_CLIENT_ID = 0xE1, - SMC_GET_DHCP_CLIENT_ID = 0xE2, - SMC_DEV_SDR_REPOSITORY_RESERVE = 0xE3, - SMC_FRU_INVENTORY_AREA_INFO_GET = 0xE4, - SMC_SET_BANNER = 0xE5, - SMC_GET_BANNER = 0xE6, - SMC_SEND_ASYNC_SEL_CMD_TO_HOST = 0xE7, - SMC_MASTER_WR_RD_I2C_2 = 0xE9, - SMC_GET_BUFFER_BLOCK_ALLOC_TABLE = 0xEA, - SMC_GET_BUFFER_ALLOC_TABLE = 0xEB, - SMC_GET_SFRS = 0xEC, - SMC_GET_PORT_VALUE = 0xED, - SMC_GET_BUFFER_DATA = 0xEE, - SMC_GET_PCB_DATA = 0xEF, - SMC_GET_PCB_BLOCK_ALLOC_TABLE = 0xF0, - SMC_GET_PCB_TABLE = 0xF1, - SMC_DEVICE_SDR_INFO_GET = 0xF2, - SMC_DEVICE_SDR_GET = 0xF3, - SMC_SENSOR_EVENT_ENABLE_GET = 0xF4, - SMC_SENSOR_EVENT_ENABLE_SET = 0xF5, - SMC_GET_CONFIG_BLOCK = 0xF8, - SMC_SET_CONFIG_BLOCK = 0xF9, - SMC_SET_VOLTAGE = 0xFB, - SMC_SENSOR_READING_GET = 0xFC, - SMC_SENSOR_THRESHOLD_GET = 0xFD, - SMC_SENSOR_THRESHOLD_SET = 0xFE, - SMC_CND_OF_CMD_MARKER = 0xFF -} smc_app_command_t; - -typedef enum { - SMC_GET_CHASSIS_STATUS = 0x01, - SMC_CHASSIS_CONTROL = 0x02, - SMC_GET_POH_COUNTER = 0x0F -} smc_chassis_command_t; - -typedef enum { - SMC_SET_EVENT_RECEIVER = 0x00, - SMC_GET_EVENT_RECEIVER = 0x01, - SMC_PLATFORM_EVENT_MESSAGE = 0x02 -} smc_event_command_t; - -typedef enum { - SMC_GET_SEL_INFO = 0x40, - SMC_GET_SEL_ALLOCATION_INFO = 0x41, - SMC_RESERVE_SEL = 0x42, - SMC_GET_SEL_ENTRY = 0x43, - SMC_ADD_SEL_ENTRY = 0x44, - SMC_PARTIAL_ADD_SEL_ENTRY = 0x45, - SMC_DELETE_SEL_ENTRY = 0x46, - SMC_CLEAR_SEL = 0x47, - SMC_GET_SEL_TIME = 0x48, - SMC_SET_SEL_TIME = 0x49 -} smc_sel_command_t; - -typedef enum { - SMC_GET_SDR_REPOSITORY_INFO = 0x20, - SMC_GET_SDR_REPOSITORY_ALLOCATION_INFO = 0x21, - SMC_RESERVE_SDR_REPOSITORY = 0x22, - SMC_GET_SDR = 0x23, - SMC_ADD_SDR = 0x24, - SMC_PARTIAL_ADD_SDR = 0x25, - SMC_DELETE_SDR = 0x26, - SMC_CLEAR_SDR_REPOSITORY = 0x27, - SMC_GET_SDR_REPOSITORY_TIME = 0x28, - SMC_SET_SDR_REPOSITORY_TIME = 0x29, - SMC_ENTER_SDR_REPOSITORY_UPDATE_MODE = 0x2A, - SMC_EXIT_SDR_REPOSITORY_UPDATE_MODE = 0x2B, - SMC_RUN_INITIALIZATION_AGENT = 0x2C -} smc_sdr_repository_command_t; - -typedef enum { - SMC_GET_FRU_INVENTORY_AREA_INFO = 0x10, - SMC_READ_FRU_INVENTORY_DATA = 0x11, - SMC_WRITE_FRU_INVENTORY_DATA = 0x12 -} smc_fru_inventory_device_command_t; - -typedef enum { - SMC_GET_DEVICE_SDR_INFO = 0x20, - SMC_GET_DEVICE_SDR = 0x21, - SMC_RESERVE_DEVICE_SDR_REPOSITORY = 0x22, - SMC_GET_SENSOR_READING_FACTORS = 0x23, - SMC_SET_SENSOR_HYSTERESIS = 0x24, - SMC_GET_SENSOR_HYSTERESIS = 0x25, - SMC_SET_SENSOR_THRESHOLD = 0x26, - SMC_GET_SENSOR_THRESHOLD = 0x27, - SMC_SET_SENSOR_EVENT_ENABLE = 0x28, - SMC_GET_SENSOR_EVENT_ENABLE = 0x29, - SMC_REARM_SENSOR_EVENTS = 0x2A, - SMC_GET_SENSOR_EVENT_STATUS = 0x2B, - /* RESERVED */ - SMC_GET_SENSOR_READING = 0x2D, - SMC_SET_SENSOR_TYPE = 0x2E, - SMC_GET_SENSOR_TYPE = 0x2F -} smc_sensor_device_command_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_SMC_COMMANDS_H */ diff --git a/usr/src/uts/sun4u/sys/smc_if.h b/usr/src/uts/sun4u/sys/smc_if.h deleted file mode 100644 index 8c35afe05a..0000000000 --- a/usr/src/uts/sun4u/sys/smc_if.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_SMC_IF_H -#define _SYS_SMC_IF_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define _SCIOC ('s' << 8) - -/* - * SMC Driver IOCTL - */ -#define SCIOC_MSG_SPEC (_SCIOC | 0x04) -#define SCIOC_RESERVE_SEQN (_SCIOC | 0x05) -#define SCIOC_FREE_SEQN (_SCIOC | 0x06) -#define SCIOC_SEND_SYNC_CMD (_SCIOC | 0x07) - -/* - * IOCTLs to facilitate debugging - */ -#define SCIOC_ECHO_ON_REQ (_SCIOC | 0x08) -#define SCIOC_ECHO_OFF_REQ (_SCIOC | 0x09) - -/* - * A response message can be sent from any application - * to simulate a condition of watchdog expiry or receiving - * async messages - */ -#define SCIOC_ASYNC_SIM (_SCIOC | 0x0A) - -#define SC_SUCCESS 0 -#define SC_FAILURE 1 - -/* - * structure definitions - */ -typedef struct { - uint8_t msg_id; - uint8_t cmd; - uint8_t len; -} sc_reqhdr_t; - -typedef struct { - uint8_t msg_id; - uint8_t cmd; /* Will be 0 is non-SMC response, e.g. wdog */ - uint8_t len; /* Length of message, including header */ - uint8_t cc; /* if non-SMC, contains MSG type */ -} sc_rsphdr_t; - -#define SC_SEND_HEADER (sizeof (sc_reqhdr_t)) -#define SC_RECV_HEADER (sizeof (sc_rsphdr_t)) - -#define SC_MSG_MAX_SIZE 0x3E -#define SC_SEND_DSIZE (SC_MSG_MAX_SIZE - SC_SEND_HEADER) -#define SC_RECV_DSIZE (SC_MSG_MAX_SIZE - SC_RECV_HEADER) - -#define SMC_CMD_FAILED -1 - -typedef enum { - SC_ATTR_SHARED, - SC_ATTR_EXCLUSIVE, - SC_ATTR_CLEAR, - SC_ATTR_CLEARALL -} sc_cmd_attr_t; - -#define MAX_CMDS 16 - -typedef struct { - uint8_t attribute; - uint8_t args[MAX_CMDS]; -} sc_cmdspec_t; - -#define SC_CMDSPEC_ATTR(CMDSPEC) ((CMDSPEC).attribute) -#define SC_CMDSPEC_ARGS(CMDSPEC) ((CMDSPEC).args) - -/* - * Entire SMC Request Message sent down-stream - */ -typedef struct { - sc_reqhdr_t hdr; - uchar_t data[SC_SEND_DSIZE]; -} sc_reqmsg_t; - -/* - * Entire SMC Response Message forwarded up-stream - */ -typedef struct { - sc_rsphdr_t hdr; - uchar_t data[SC_RECV_DSIZE]; -} sc_rspmsg_t; - -#define SC_MSG_HDR(msg) ((msg)->hdr) - -#define SC_SEND_DLENGTH(msg) (SC_MSG_HDR(msg).len) -#define SC_RECV_DLENGTH(msg) (SC_MSG_HDR(msg).len) - -#define SC_MSG_ID(msg) (SC_MSG_HDR(msg).msg_id) -#define SC_MSG_CMD(msg) (SC_MSG_HDR(msg).cmd) -#define SC_MSG_LEN(msg) (SC_MSG_HDR(msg).len) -#define SC_MSG_CC(msg) (SC_MSG_HDR(msg).cc) -#define SC_MSG_DATA(msg) ((msg)->data) - -/* - * IPMB sequence number request structure. Application can - * reserve a block of sequence numbers for communicating - * with each destination - */ -#define SC_SEQ_SZ 16 -typedef struct { - uint8_t d_addr; /* Destination micro-controller addr */ - int8_t n_seqn; /* Number of seq# requested, max 16, -1 => free all */ - uint8_t seq_numbers[SC_SEQ_SZ]; /* Placeholder for seq# */ -} sc_seqdesc_t; - -#define SC_SEQN_DADDR(SEQDESC) ((SEQDESC).d_addr) -#define SC_SEQN_COUNT(SEQDESC) ((SEQDESC).n_seqn) -#define SC_SEQN_NUMBERS(SEQDESC) ((SEQDESC).seq_numbers) - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_SMC_IF_H */ |