summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/io/consconfig_dacf.c28
-rw-r--r--usr/src/uts/i86pc/sys/sbd_ioctl.h31
-rw-r--r--usr/src/uts/sun4/os/intr.c4
-rw-r--r--usr/src/uts/sun4/sys/cpu_sgnblk_defs.h37
-rw-r--r--usr/src/uts/sun4u/Makefile.files2
-rw-r--r--usr/src/uts/sun4u/Makefile.sun4u4
-rw-r--r--usr/src/uts/sun4u/io/mach_rootnex.c11
-rw-r--r--usr/src/uts/sun4u/io/pci/pci_cb.c23
-rw-r--r--usr/src/uts/sun4u/io/pci/pci_ib.c34
-rw-r--r--usr/src/uts/sun4u/io/pci/pci_intr.c11
-rw-r--r--usr/src/uts/sun4u/io/pci/pcipsy.c38
-rw-r--r--usr/src/uts/sun4u/io/sbd_cpu.c8
-rw-r--r--usr/src/uts/sun4u/io/sysioerr.c42
-rw-r--r--usr/src/uts/sun4u/io/sysiosbus.c80
-rw-r--r--usr/src/uts/sun4u/io/todstarfire.c196
-rw-r--r--usr/src/uts/sun4u/ngdr/Makefile.files5
-rw-r--r--usr/src/uts/sun4u/ngdr/Makefile.rules5
-rw-r--r--usr/src/uts/sun4u/ngdr/io/dr_cpu.c22
-rw-r--r--usr/src/uts/sun4u/ngdr/io/dr_mem.c6
-rw-r--r--usr/src/uts/sun4u/os/mach_mp_startup.c7
-rw-r--r--usr/src/uts/sun4u/starfire/Makefile122
-rw-r--r--usr/src/uts/sun4u/starfire/Makefile.files67
-rw-r--r--usr/src/uts/sun4u/starfire/Makefile.rules106
-rw-r--r--usr/src/uts/sun4u/starfire/Makefile.starfire132
-rw-r--r--usr/src/uts/sun4u/starfire/Makefile.targ93
-rw-r--r--usr/src/uts/sun4u/starfire/cvc/Makefile88
-rw-r--r--usr/src/uts/sun4u/starfire/cvc/cvc.c1200
-rw-r--r--usr/src/uts/sun4u/starfire/cvc/cvc.conf28
-rw-r--r--usr/src/uts/sun4u/starfire/cvcredir/Makefile92
-rw-r--r--usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c278
-rw-r--r--usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf28
-rw-r--r--usr/src/uts/sun4u/starfire/genassym/Makefile94
-rw-r--r--usr/src/uts/sun4u/starfire/idn/Makefile103
-rw-r--r--usr/src/uts/sun4u/starfire/io/drmach.c3857
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn.c5787
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn.conf35
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn_dlpi.c2295
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn_proto.c12971
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn_smr.c2178
-rw-r--r--usr/src/uts/sun4u/starfire/io/idn_xf.c1694
-rw-r--r--usr/src/uts/sun4u/starfire/io/memctrl.c276
-rw-r--r--usr/src/uts/sun4u/starfire/io/ngdr.conf28
-rw-r--r--usr/src/uts/sun4u/starfire/io/portctrl.c271
-rw-r--r--usr/src/uts/sun4u/starfire/ml/drmach.il.cpp222
-rw-r--r--usr/src/uts/sun4u/starfire/ml/drmach_asm.s361
-rw-r--r--usr/src/uts/sun4u/starfire/ml/idn_asm.s385
-rw-r--r--usr/src/uts/sun4u/starfire/ml/idn_offsets.in60
-rw-r--r--usr/src/uts/sun4u/starfire/ngdr/Makefile95
-rw-r--r--usr/src/uts/sun4u/starfire/ngdrmach/Makefile92
-rw-r--r--usr/src/uts/sun4u/starfire/os/bbus_intr.c643
-rw-r--r--usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c181
-rw-r--r--usr/src/uts/sun4u/starfire/os/pda.c623
-rw-r--r--usr/src/uts/sun4u/starfire/os/starfire.c639
-rw-r--r--usr/src/uts/sun4u/starfire/pcipsy/Makefile95
-rw-r--r--usr/src/uts/sun4u/starfire/platmod/Makefile98
-rw-r--r--usr/src/uts/sun4u/starfire/rootnex/Makefile97
-rw-r--r--usr/src/uts/sun4u/starfire/sbus/Makefile98
-rw-r--r--usr/src/uts/sun4u/starfire/spitfire/Makefile109
-rw-r--r--usr/src/uts/sun4u/starfire/sys/Makefile68
-rw-r--r--usr/src/uts/sun4u/starfire/sys/cpu_sgn.h354
-rw-r--r--usr/src/uts/sun4u/starfire/sys/cvc.h116
-rw-r--r--usr/src/uts/sun4u/starfire/sys/drmach.h160
-rw-r--r--usr/src/uts/sun4u/starfire/sys/idn.h3886
-rw-r--r--usr/src/uts/sun4u/starfire/sys/idn_sigb.h401
-rw-r--r--usr/src/uts/sun4u/starfire/sys/idn_smr.h230
-rw-r--r--usr/src/uts/sun4u/starfire/sys/idn_xf.h133
-rw-r--r--usr/src/uts/sun4u/starfire/sys/pda.h226
-rw-r--r--usr/src/uts/sun4u/starfire/unix/Makefile189
-rw-r--r--usr/src/uts/sun4u/sys/Makefile2
-rw-r--r--usr/src/uts/sun4u/sys/machintreg.h16
-rw-r--r--usr/src/uts/sun4u/sys/machparam.h18
-rw-r--r--usr/src/uts/sun4u/sys/machthread.h35
-rw-r--r--usr/src/uts/sun4u/sys/pci/pci_cb.h9
-rw-r--r--usr/src/uts/sun4u/sys/pci/pci_ib.h14
-rw-r--r--usr/src/uts/sun4u/sys/pci/pci_regs.h7
-rw-r--r--usr/src/uts/sun4u/sys/prom_plat.h15
-rw-r--r--usr/src/uts/sun4u/sys/sbd_ioctl.h31
-rw-r--r--usr/src/uts/sun4u/sys/spitregs.h18
-rw-r--r--usr/src/uts/sun4u/sys/starfire.h248
-rw-r--r--usr/src/uts/sun4u/sys/sysiosbus.h8
-rw-r--r--usr/src/uts/sun4u/todstarfire/Makefile87
-rw-r--r--usr/src/uts/sun4v/os/mach_mp_startup.c9
82 files changed, 94 insertions, 42401 deletions
diff --git a/usr/src/uts/common/io/consconfig_dacf.c b/usr/src/uts/common/io/consconfig_dacf.c
index edeb0f93d2..444cb9ce33 100644
--- a/usr/src/uts/common/io/consconfig_dacf.c
+++ b/usr/src/uts/common/io/consconfig_dacf.c
@@ -25,6 +25,10 @@
*/
/*
+ * Copyright 2019 Peter Tribble.
+ */
+
+/*
* This module performs two functions. First, it kicks off the driver loading
* of the console devices during boot in dynamic_console_config().
* The loading of the drivers for the console devices triggers the
@@ -1533,29 +1537,6 @@ dynamic_console_config(void)
consconfig_load_drivers(consconfig_sp);
consconfig_sp->cons_input_type = cons_get_input_type(consconfig_sp);
- /*
- * This is legacy special case code for the "cool" virtual console
- * for the Starfire project. Starfire has a dummy "ssp-serial"
- * node in the OBP device tree and cvc is a pseudo driver.
- */
- if (consconfig_sp->cons_stdout_path != NULL && stdindev == NODEV &&
- strstr(consconfig_sp->cons_stdout_path, "ssp-serial")) {
- /*
- * Setup the virtual console driver for Starfire
- * Note that console I/O will still go through prom for now
- * (notice we don't open the driver here). The cvc driver
- * will be activated when /dev/console is opened by init.
- * During that time, a cvcd daemon will be started that
- * will open the cvcredirection driver to facilitate
- * the redirection of console I/O from cvc to cvcd.
- */
- rconsvp = i_consconfig_createvp(CVC_PATH);
- if (rconsvp == NULL)
- goto done;
- rconsdev = rconsvp->v_rdev;
- goto done;
- }
-
rwsconsvp = consconfig_sp->cons_wc_vp;
rwsconsdev = consconfig_sp->cons_wc_vp->v_rdev;
@@ -1574,7 +1555,6 @@ dynamic_console_config(void)
mousedev, kbddev, fbdev, rconsdev);
flush_deferred_console_buf();
-done:
consconfig_sp->cons_initialized = B_TRUE;
}
diff --git a/usr/src/uts/i86pc/sys/sbd_ioctl.h b/usr/src/uts/i86pc/sys/sbd_ioctl.h
index 1eab543aa3..1ca9473dc2 100644
--- a/usr/src/uts/i86pc/sys/sbd_ioctl.h
+++ b/usr/src/uts/i86pc/sys/sbd_ioctl.h
@@ -26,6 +26,9 @@
* Copyright (c) 2010, Intel Corporation.
* All rights reserved.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SBD_IOCTL_H
#define _SBD_IOCTL_H
@@ -508,34 +511,6 @@ typedef struct {
#define ESTC_NWSWITCH 1037
/* Cannot unconfigure I/O board: network switch failed */
-/* Starfire error codes */
-
-#define ESTF_NONE 2000 /* No error */
-#define ESTF_GETPROP 2001 /* Cannot read property value */
-#define ESTF_GETPROPLEN 2002 /* Cannot determine property length */
-#define ESTF_BNUM 2003 /* Invalid board number */
-#define ESTF_CONFIGBUSY 2004
- /* Cannot proceed; Board is configured or busy */
-#define ESTF_NOCPUID 2005 /* No CPU specified for connect */
-#define ESTF_PROBE 2006 /* Firmware probe failed */
-#define ESTF_DEPROBE 2007 /* Firmware deprobe failed */
-#define ESTF_MOVESIGB 2008 /* Firmware move-cpu0 failed */
-#define ESTF_JUGGLE 2009 /* Cannot move SIGB assignment */
-#define ESTF_HASSIGB 2010
- /* Cannot disconnect CPU; SIGB is currently assigned */
-#define ESTF_SUPPORT 2011 /* Operation not supported */
-#define ESTF_DRVFAIL 2012 /* Device driver failure */
-#define ESTF_SETCPUVAL 2013
- /* Must specify a CPU on the given board */
-#define ESTF_NODEV 2014 /* No such device */
-#define ESTF_INTERBOARD 2015
- /* Memory configured with inter-board interleaving */
-#define ESTF_UNKPTCMD 2016 /* Unrecognized platform command */
-#define ESTF_NOTID 2017 /* drmach parameter is not a valid ID */
-#define ESTF_INAPPROP 2018
- /* drmach parameter is inappropriate for operation */
-#define ESTF_INTERNAL 2019 /* Unexpected internal condition */
-
/* Daktari error codes */
#define EDAK_NONE 3000 /* no error */
diff --git a/usr/src/uts/sun4/os/intr.c b/usr/src/uts/sun4/os/intr.c
index 8036ca5bcb..3a7143115d 100644
--- a/usr/src/uts/sun4/os/intr.c
+++ b/usr/src/uts/sun4/os/intr.c
@@ -25,6 +25,9 @@
/*
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#include <sys/sysmacros.h>
#include <sys/stack.h>
@@ -115,7 +118,6 @@ intr_init(cpu_t *cp)
extern uint_t softlevel1();
init_ivintr();
- REGISTER_BBUS_INTR();
/*
* Register these software interrupts for ddi timer.
diff --git a/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h b/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h
index 0b18ca88f3..9e1a125308 100644
--- a/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h
+++ b/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h
@@ -23,12 +23,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _CPU_SGNBLK_DEFS_H
#define _CPU_SGNBLK_DEFS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -124,38 +125,6 @@ typedef union {
extern void (*cpu_sgn_func)(ushort_t, uchar_t, uchar_t, int);
-
-
-#ifdef _STARFIRE
-
-extern void register_bbus_intr();
-extern void cpu_sgn_mapin(int);
-extern void cpu_sgn_mapout(int);
-extern int cpu_sgn_exists(int);
-extern ushort_t get_cpu_sgn(int);
-extern uchar_t get_cpu_sgn_state(int);
-
-#define REGISTER_BBUS_INTR() register_bbus_intr()
-#define CPU_SGN_MAPIN(cpuid) cpu_sgn_mapin(cpuid)
-#define CPU_SGN_MAPOUT(cpuid) cpu_sgn_mapout(cpuid)
-#define CPU_SGN_EXISTS(cpuid) cpu_sgn_exists(cpuid)
-#define SGN_CPU_IS_OS(cpuid) (get_cpu_sgn(cpuid) == OS_SIG)
-#define SGN_CPU_IS_OBP(cpuid) (get_cpu_sgn(cpuid) == OBP_SIG)
-#define SGN_CPU_STATE_IS_DETACHED(cpuid) \
- (get_cpu_sgn_state(cpuid) == SIGST_DETACHED)
-
-#else
-
-#define REGISTER_BBUS_INTR()
-#define CPU_SGN_MAPIN(cpuid)
-#define CPU_SGN_MAPOUT(cpuid)
-#define CPU_SGN_EXISTS(cpuid) (0)
-#define SGN_CPU_IS_OS(cpuid) (0)
-#define SGN_CPU_IS_OBP(cpuid) (0)
-#define SGN_CPU_STATE_IS_DETACHED(cpuid) (0)
-
-#endif /* _STARFIRE */
-
#endif /* _KERNEL */
#ifdef __cplusplus
diff --git a/usr/src/uts/sun4u/Makefile.files b/usr/src/uts/sun4u/Makefile.files
index 5cfcd6025f..a2b45242cb 100644
--- a/usr/src/uts/sun4u/Makefile.files
+++ b/usr/src/uts/sun4u/Makefile.files
@@ -22,6 +22,7 @@
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright 2019 Peter Tribble.
#
# This Makefile defines all file modules for the directory uts/sun4u
# and it's children. These are the source files which are sun4u
@@ -160,7 +161,6 @@ SHA1_OBJS += sha1_asm.o
TODMOSTEK_OBJS += todmostek.o
TODDS1287_OBJS += todds1287.o
TODDS1337_OBJS += todds1337.o
-TODSTARFIRE_OBJS += todstarfire.o
TODSTARCAT_OBJS += todstarcat.o
TODBLADE_OBJS += todblade.o
TODM5819_OBJS += todm5819.o
diff --git a/usr/src/uts/sun4u/Makefile.sun4u b/usr/src/uts/sun4u/Makefile.sun4u
index d2b2b5cba7..f5e29d2a13 100644
--- a/usr/src/uts/sun4u/Makefile.sun4u
+++ b/usr/src/uts/sun4u/Makefile.sun4u
@@ -23,6 +23,7 @@
# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
# Copyright (c) 2013 Andrew Stormont. All rights reserved.
+# Copyright 2019 Peter Tribble.
#
# This makefile contains the common definitions for the sun4u unix
# and all sun4u implementation architecture dependent modules.
@@ -158,7 +159,6 @@ include $(UTSBASE)/Makefile.uts
# These come after Makefile.uts.
IMPLEMENTATIONS = tazmo
-IMPLEMENTATIONS += starfire
IMPLEMENTATIONS += javelin
IMPLEMENTATIONS += darwin
IMPLEMENTATIONS += quasar
@@ -459,7 +459,7 @@ CPU_KMODS += cheetah cheetahplus jalapeno serrano spitfire hummingbird
#
# sun4u 'TOD' Modules (/platform/.../kernel/tod):
#
-TOD_KMODS += todds1287 todds1337 todmostek todstarfire
+TOD_KMODS += todds1287 todds1337 todmostek
TOD_KMODS += todm5819 todblade todbq4802 todsg todopl
TOD_KMODS += todm5819p_rmc todstarcat
diff --git a/usr/src/uts/sun4u/io/mach_rootnex.c b/usr/src/uts/sun4u/io/mach_rootnex.c
index 8c0653d84a..b2a7ca8f1d 100644
--- a/usr/src/uts/sun4u/io/mach_rootnex.c
+++ b/usr/src/uts/sun4u/io/mach_rootnex.c
@@ -22,8 +22,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
/*
* sun4u root nexus driver
@@ -329,13 +330,7 @@ rootnex_name_child_impl(dev_info_t *child, char *name, int namelen)
if ((strcmp(node_name, "fhc") == 0) ||
(strcmp(node_name, "mem-unit") == 0) ||
(strcmp(node_name, "central") == 0)) {
-#ifdef _STARFIRE
- portid = ((((rp->regspec_bustype) & 0x6) >> 1) |
- (((rp->regspec_bustype) & 0xF0) >> 2) |
- (((rp->regspec_bustype) & 0x8) << 3));
-#else
portid = (rp->regspec_bustype >> 1) & 0x1f;
-#endif
/*
* The port-id must go on the hardware property list,
diff --git a/usr/src/uts/sun4u/io/pci/pci_cb.c b/usr/src/uts/sun4u/io/pci/pci_cb.c
index be0c9cf208..a22f1ca219 100644
--- a/usr/src/uts/sun4u/io/pci/pci_cb.c
+++ b/usr/src/uts/sun4u/io/pci/pci_cb.c
@@ -23,8 +23,9 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
/*
* PCI Control Block object
@@ -38,10 +39,6 @@
#include <sys/pci/pci_obj.h>
#include <sys/machsystm.h>
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-#endif /* _STARFIRE */
-
/*LINTLIBRARY*/
void
@@ -101,11 +98,6 @@ cb_enable_nintr(pci_t *pci_p, enum cb_nintr_index idx)
mutex_enter(&cb_p->cb_intr_lock);
cpu_id = intr_dist_cpuid();
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(cb_p->cb_ittrans_cookie, cpu_id,
- IB_GET_MAPREG_INO(ino));
-#endif /* _STARFIRE */
-
reg = ib_get_map_reg(mondo, cpu_id);
stdphysio(pa, reg);
@@ -167,10 +159,6 @@ cb_disable_nintr(cb_t *cb_p, enum cb_nintr_index idx, int wait)
cb_set_nintr_reg(cb_p, ino, COMMON_CLEAR_INTR_REG_PENDING);
cb_p->cb_inos[idx] = 0;
mutex_exit(&cb_p->cb_intr_lock);
-#ifdef _STARFIRE
- pc_ittrans_cleanup(cb_p->cb_ittrans_cookie,
- (volatile uint64_t *)(uintptr_t)ino);
-#endif /* _STARFIRE */
}
void
@@ -206,13 +194,8 @@ cb_intr_dist(void *arg)
mondo = CB_INO_TO_MONDO(cb_p, ino);
cpu_id = intr_dist_cpuid();
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(cb_p->cb_ittrans_cookie, cpu_id,
- IB_GET_MAPREG_INO(ino));
-#else
if (ib_map_reg_get_cpu(imr) == cpu_id)
continue; /* same cpu target, no re-program */
-#endif
cb_disable_nintr_reg(cb_p, ino, IB_INTR_WAIT);
stdphysio(mr_pa, ib_get_map_reg(mondo, cpu_id));
(void) lddphysio(mr_pa); /* flush previous write */
diff --git a/usr/src/uts/sun4u/io/pci/pci_ib.c b/usr/src/uts/sun4u/io/pci/pci_ib.c
index cedfc35e05..65d3a5c571 100644
--- a/usr/src/uts/sun4u/io/pci/pci_ib.c
+++ b/usr/src/uts/sun4u/io/pci/pci_ib.c
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
/*
* PCI Interrupt Block (RISCx) implementation
@@ -41,10 +44,6 @@
#include <sys/cpuvar.h>
#include <sys/pci/pci_obj.h>
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-#endif /* _STARFIRE */
-
/*LINTLIBRARY*/
static uint_t ib_intr_reset(void *arg);
@@ -156,10 +155,6 @@ ib_intr_enable(pci_t *pci_p, ib_ino_t ino)
*/
mutex_enter(&ib_p->ib_intr_lock);
cpu_id = intr_dist_cpuid();
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(IB2CB(ib_p)->cb_ittrans_cookie, cpu_id,
- IB_GET_MAPREG_INO(ino));
-#endif /* _STARFIRE */
DEBUG2(DBG_IB, pci_p->pci_dip,
"ib_intr_enable: ino=%x cpu_id=%x\n", ino, cpu_id);
@@ -202,10 +197,6 @@ ib_intr_disable(ib_t *ib_p, ib_ino_t ino, int wait)
}
wait_done:
IB_INO_INTR_PEND(ib_clear_intr_reg_addr(ib_p, ino));
-#ifdef _STARFIRE
- pc_ittrans_cleanup(IB2CB(ib_p)->cb_ittrans_cookie,
- (volatile uint64_t *)(uintptr_t)ino);
-#endif /* _STARFIRE */
}
/* can only used for psycho internal interrupts thermal, power, ue, ce, pbm */
@@ -231,15 +222,8 @@ ib_intr_dist_nintr(ib_t *ib_p, ib_ino_t ino, volatile uint64_t *imr_p)
cpu_id = intr_dist_cpuid();
-#ifdef _STARFIRE
- if (ino) {
- cpu_id = pc_translate_tgtid(IB2CB(ib_p)->cb_ittrans_cookie,
- cpu_id, IB_GET_MAPREG_INO(ino));
- }
-#else /* _STARFIRE */
if (ib_map_reg_get_cpu(*imr_p) == cpu_id)
return;
-#endif /* _STARFIRE */
*imr_p = ib_get_map_reg(IB_IMR2MONDO(imr), cpu_id);
imr = *imr_p; /* flush previous write */
@@ -286,20 +270,8 @@ ib_intr_dist(ib_t *ib_p, ib_ino_info_t *ino_p)
imr_p = ib_intr_map_reg_addr(ib_p, ino);
state_reg = IB_INO_INTR_STATE_REG(ib_p, ino);
-#ifdef _STARFIRE
- /*
- * For Starfire it is a pain to check the current target for
- * the mondo since we have to read the PC asics ITTR slot
- * assigned to this mondo. It will be much easier to assume
- * the current target is always different and do the target
- * reprogram all the time.
- */
- cpu_id = pc_translate_tgtid(IB2CB(ib_p)->cb_ittrans_cookie, cpu_id,
- IB_GET_MAPREG_INO(ino));
-#else
if (ib_map_reg_get_cpu(*imr_p) == cpu_id) /* same cpu, no reprog */
return;
-#endif /* _STARFIRE */
/* disable interrupt, this could disrupt devices sharing our slot */
IB_INO_INTR_OFF(imr_p);
diff --git a/usr/src/uts/sun4u/io/pci/pci_intr.c b/usr/src/uts/sun4u/io/pci/pci_intr.c
index 7d8760474b..493cc08f59 100644
--- a/usr/src/uts/sun4u/io/pci/pci_intr.c
+++ b/usr/src/uts/sun4u/io/pci/pci_intr.c
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
/*
* PCI nexus interrupt handling:
@@ -41,10 +44,6 @@
#include <sys/sdt.h>
#include <sys/clock.h>
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-#endif /* _STARFIRE */
-
/*
* interrupt jabber:
*
@@ -579,10 +578,6 @@ pci_add_intr(dev_info_t *dip, dev_info_t *rdip, ddi_intr_handle_impl_t *hdlp)
weight = pci_class_to_intr_weight(rdip);
intr_dist_cpuid_add_device_weight(cpu_id, rdip, weight);
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(cb_p->cb_ittrans_cookie, cpu_id,
- IB_GET_MAPREG_INO(ino));
-#endif /* _STARFIRE */
if (!ipil_list) {
*ino_p->ino_map_reg = ib_get_map_reg(mondo, cpu_id);
*ino_p->ino_map_reg;
diff --git a/usr/src/uts/sun4u/io/pci/pcipsy.c b/usr/src/uts/sun4u/io/pci/pcipsy.c
index 93e93d1008..06a4a71e06 100644
--- a/usr/src/uts/sun4u/io/pci/pcipsy.c
+++ b/usr/src/uts/sun4u/io/pci/pcipsy.c
@@ -22,8 +22,9 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
/*
* Psycho+ specifics implementation:
@@ -55,10 +56,6 @@
#include <sys/pci/pci_obj.h>
#include <sys/pci/pcipsy.h>
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-#endif /* _STARFIRE */
-
static uint32_t pci_identity_init(pci_t *pci_p);
static int pci_intr_setup(pci_t *pci_p);
static void pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p);
@@ -706,9 +703,6 @@ pci_cb_teardown(pci_t *pci_p)
cb_disable_nintr(cb_p, CBNINTR_THERMAL, IB_INTR_WAIT);
VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_THERMAL]) == 0);
}
-#ifdef _STARFIRE
- pc_ittrans_uninit(cb_p->cb_ittrans_cookie);
-#endif /* _STARFIRE */
}
int
@@ -961,27 +955,6 @@ pbm_configure(pbm_t *pbm_p)
*/
l &= ~PSYCHO_PCI_CTRL_WAKEUP_EN;
-#ifdef _STARFIRE
- /*
- * Hack to determine whether we do Starfire special handling
- * For starfire, we simply program a constant odd-value
- * (0x1D) in the MID field.
- *
- * Zero out the MID field before ORing. We leave the LSB of
- * the MID field intact since we cannot have a zero (even)
- * MID value.
- */
- l &= 0xFF0FFFFFFFFFFFFFULL;
- l |= 0x1DULL << 51;
-
- /*
- * Program in the Interrupt Group Number. Here we have to
- * convert the starfire 7bit upaid into a 5bit value.
- */
- l |= (uint64_t)STARFIRE_UPAID2HWIGN(pbm_p->pbm_pci_p->pci_id)
- << COMMON_CB_CONTROL_STATUS_IGN_SHIFT;
-#endif /* _STARFIRE */
-
/*
* Now finally write the control register with the appropriate value.
*/
@@ -1160,11 +1133,6 @@ pci_cb_setup(pci_t *pci_p)
csr &= ~COMMON_CB_CONTROL_STATUS_IAP;
stdphysio(csr_pa, csr);
-#ifdef _STARFIRE
- /* Setup Starfire interrupt target translation */
- pc_ittrans_init(pci_p->pci_id, &cb_p->cb_ittrans_cookie);
-#endif /* _STARFIRE */
-
}
void
diff --git a/usr/src/uts/sun4u/io/sbd_cpu.c b/usr/src/uts/sun4u/io/sbd_cpu.c
index efee104249..5db48f7572 100644
--- a/usr/src/uts/sun4u/io/sbd_cpu.c
+++ b/usr/src/uts/sun4u/io/sbd_cpu.c
@@ -23,8 +23,9 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
/*
* CPU support routines for DR
@@ -514,9 +515,6 @@ sbd_pre_attach_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum)
*/
PR_CPU("%s: unmapping sigblk for cpu %d\n",
f, cpuid);
-
- /* platform specific release of sigblk */
- CPU_SGN_MAPOUT(cpuid);
}
}
diff --git a/usr/src/uts/sun4u/io/sysioerr.c b/usr/src/uts/sun4u/io/sysioerr.c
index 75a5f3d59c..4242915e23 100644
--- a/usr/src/uts/sun4u/io/sysioerr.c
+++ b/usr/src/uts/sun4u/io/sysioerr.c
@@ -23,8 +23,9 @@
* Copyright 1990-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#include <sys/types.h>
#include <sys/conf.h>
@@ -53,16 +54,6 @@ int oven_test = 0;
*/
static int thermal_interrupt_enabled = 0;
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-
-int
-pc_translate_tgtid(caddr_t, int, volatile uint64_t *);
-
-void
-pc_ittrans_cleanup(caddr_t, volatile uint64_t *);
-#endif /* _STARFIRE */
-
/*
* adb debug_sysio_errs to 1 if you don't want your system to panic on
* sbus ue errors. adb sysio_err_flag to 0 if you don't want your system
@@ -235,29 +226,17 @@ sysio_init_err(struct sbus_soft_state *softsp)
*/
mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + UE_ECC_MAPREG);
cpu_id = acpu_id;
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
- mondo_vec_reg);
-#endif /* _STARFIRE */
tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
*mondo_vec_reg = tmp_mondo_vec;
mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + CE_ECC_MAPREG);
cpu_id = acpu_id;
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
- mondo_vec_reg);
-#endif /* _STARFIRE */
tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
*mondo_vec_reg = tmp_mondo_vec;
mondo_vec_reg =
(uint64_t *)(softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
cpu_id = acpu_id;
-#ifdef _STARFIRE
- cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id,
- mondo_vec_reg);
-#endif /* _STARFIRE */
tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
*mondo_vec_reg = tmp_mondo_vec;
@@ -312,11 +291,6 @@ sysio_dis_err(struct sbus_soft_state *softsp)
*mondo_vec_reg = 0;
-#ifdef _STARFIRE
- /* do cleanup for starfire interrupt target translation */
- pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
-#endif /* _STARFIRE */
-
*clear_vec_reg = 0;
mondo_vec_reg = (softsp->intr_mapping_reg + CE_ECC_MAPREG);
@@ -324,11 +298,6 @@ sysio_dis_err(struct sbus_soft_state *softsp)
*mondo_vec_reg = 0;
-#ifdef _STARFIRE
- /* Do cleanup for starfire interrupt target translation */
- pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
-#endif /* _STARFIRE */
-
*clear_vec_reg = 0;
mondo_vec_reg = (softsp->intr_mapping_reg + SBUS_ERR_MAPREG);
@@ -336,11 +305,6 @@ sysio_dis_err(struct sbus_soft_state *softsp)
*mondo_vec_reg = 0;
-#ifdef _STARFIRE
- /* Do cleanup for starfire interrupt target translation */
- pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
-#endif /* _STARFIRE */
-
*clear_vec_reg = 0;
/* Flush store buffers */
diff --git a/usr/src/uts/sun4u/io/sysiosbus.c b/usr/src/uts/sun4u/io/sysiosbus.c
index 71ec224b19..20b75c8a0b 100644
--- a/usr/src/uts/sun4u/io/sysiosbus.c
+++ b/usr/src/uts/sun4u/io/sysiosbus.c
@@ -27,6 +27,10 @@
* Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
+
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/ddi.h>
@@ -50,9 +54,6 @@
#include <sys/machsystm.h>
#include <sys/intreg.h>
#include <sys/ddi_subrdefs.h>
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-#endif /* _STARFIRE */
#include <sys/sdt.h>
/* Useful debugging Stuff */
@@ -287,20 +288,6 @@ static int
sbus_update_intr_state(dev_info_t *dip, dev_info_t *rdip,
ddi_intr_handle_impl_t *hdlp, uint_t new_intr_state);
-#ifdef _STARFIRE
-void
-pc_ittrans_init(int, caddr_t *);
-
-void
-pc_ittrans_uninit(caddr_t);
-
-int
-pc_translate_tgtid(caddr_t, int, volatile uint64_t *);
-
-void
-pc_ittrans_cleanup(caddr_t, volatile uint64_t *);
-#endif /* _STARFIRE */
-
/*
* Configuration data structures
*/
@@ -693,11 +680,6 @@ sbus_do_detach(dev_info_t *devi)
}
mutex_exit(&sbus_attachcnt_mutex);
-#ifdef _STARFIRE
- /* free starfire specific soft intr mapping structure */
- pc_ittrans_uninit(softsp->ittrans_cookie);
-#endif /* _STARFIRE */
-
/* free the soft state structure */
ddi_soft_state_free(sbusp, instance);
@@ -740,11 +722,6 @@ sbus_init(struct sbus_soft_state *softsp, caddr_t address)
"SBUS Control reg: 0x%p", (void *)softsp->sysio_ctrl_reg,
(void *)softsp->sbus_ctrl_reg));
-#ifdef _STARFIRE
- /* Setup interrupt target translation for starfire */
- pc_ittrans_init(softsp->upa_id, &softsp->ittrans_cookie);
-#endif /* _STARFIRE */
-
softsp->intr_mapping_ign =
UPAID_TO_IGN(softsp->upa_id) << IMR_IGN_SHIFT;
@@ -815,27 +792,6 @@ sbus_resume_init(struct sbus_soft_state *softsp, int resume)
* (RAZ) Get rid of this later!!!
*/
-#ifdef _STARFIRE
- /*
- * For Starfire, we need to program a
- * constant odd value.
- * Zero out the MID field before ORing
- * We leave the LSB of the MID field intact since
- * we cannot have a zero(even) MID value
- */
- uint64_t tmpconst = 0x1DULL;
- *softsp->sysio_ctrl_reg &= 0xFF0FFFFFFFFFFFFFULL;
- *softsp->sysio_ctrl_reg |= tmpconst << 51;
-
- /*
- * Program in the interrupt group number
- * Here we have to convert the starfire
- * 7 bit upaid into a 5bit value.
- */
- *softsp->sysio_ctrl_reg |=
- (uint64_t)STARFIRE_UPAID2HWIGN(softsp->upa_id)
- << SYSIO_IGN;
-#else
/* for the rest of sun4u's */
*softsp->sysio_ctrl_reg |=
(uint64_t)softsp->upa_id << 51;
@@ -843,7 +799,6 @@ sbus_resume_init(struct sbus_soft_state *softsp, int resume)
/* Program in the interrupt group number */
*softsp->sysio_ctrl_reg |=
(uint64_t)softsp->upa_id << SYSIO_IGN;
-#endif /* _STARFIRE */
/*
* Set appropriate fields of sbus control register.
@@ -1821,16 +1776,10 @@ sbus_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
(softsp->intr_hndlr_cnt[slot] == 0)) {
cpu_id = intr_dist_cpuid();
-#ifdef _STARFIRE
- tmp_mondo_vec = pc_translate_tgtid(
- softsp->ittrans_cookie, cpu_id,
- mondo_vec_reg) << IMR_TID_SHIFT;
-#else
tmp_mondo_vec =
cpu_id << IMR_TID_SHIFT;
DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: initial "
"mapping reg 0x%lx\n", tmp_mondo_vec));
-#endif /* _STARFIRE */
} else {
/*
* There is already a different
@@ -2004,10 +1953,6 @@ sbus_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
if ((softsp->intr_hndlr_cnt[slot] == 0) || (slot >= EXT_SBUS_SLOTS)) {
ASSERT(sbus_arg->handler_list == NULL);
-#ifdef _STARFIRE
- /* Do cleanup for interrupt target translation */
- pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg);
-#endif /* _STARFIRE */
}
@@ -2245,20 +2190,10 @@ sbus_intrdist(void *arg)
last_mondo_vec_reg = (uint64_t *)mondo_vec_reg;
cpu_id = intr_dist_cpuid();
-#ifdef _STARFIRE
- /*
- * For Starfire it is a pain to check the current target for
- * the mondo since we have to read the PC asics ITTR slot
- * assigned to this mondo. It will be much easier to assume
- * the current target is always different and do the target
- * reprogram all the time.
- */
-#else
if (((*mondo_vec_reg & IMR_TID) >> IMR_TID_SHIFT) == cpu_id) {
/* It is the same, don't reprogram */
return;
}
-#endif /* _STARFIRE */
/* So it's OK to reprogram the CPU target */
@@ -2315,14 +2250,7 @@ sbus_intrdist(void *arg)
}
/* re-target the mondo and turn it on */
-#ifdef _STARFIRE
- mondo_vec = (pc_translate_tgtid(softsp->ittrans_cookie,
- cpu_id, mondo_vec_reg) <<
- INTERRUPT_CPU_FIELD) |
- INTERRUPT_VALID;
-#else
mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID;
-#endif /* _STARFIRE */
/* write it back to the hardware. */
*mondo_vec_reg = mondo_vec;
diff --git a/usr/src/uts/sun4u/io/todstarfire.c b/usr/src/uts/sun4u/io/todstarfire.c
deleted file mode 100644
index b8571c49f8..0000000000
--- a/usr/src/uts/sun4u/io/todstarfire.c
+++ /dev/null
@@ -1,196 +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.
- */
-
-/*
- * tod driver module for Starfire
- * This module implements a soft tod since
- * starfire has no tod part.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/modctl.h>
-#include <sys/autoconf.h>
-#include <sys/debug.h>
-#include <sys/clock.h>
-#include <sys/cmn_err.h>
-#include <sys/promif.h>
-#include <sys/cpuvar.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <starfire/sys/cpu_sgn.h>
-
-static timestruc_t todsf_get(void);
-static void todsf_set(timestruc_t);
-static uint_t todsf_set_watchdog_timer(uint_t);
-static uint_t todsf_clear_watchdog_timer(void);
-static void todsf_set_power_alarm(timestruc_t);
-static void todsf_clear_power_alarm(void);
-static uint64_t todsf_get_cpufrequency(void);
-
-/*
- * Module linkage information for the kernel.
- */
-static struct modlmisc modlmisc = {
- &mod_miscops, "Soft tod module for Starfire"
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, (void *)&modlmisc, NULL
-};
-
-int
-_init(void)
-{
- if (strcmp(tod_module_name, "todstarfire") == 0) {
- int ssp_time32;
- char obp_string[40];
-
- /* Set the string to pass to OBP */
- (void) sprintf(obp_string, "h# %p unix-gettod",
- (void *)&ssp_time32);
-
- /* Get OBP to get TOD from ssp */
- prom_interpret(obp_string, 0, 0, 0, 0, 0);
-
- hrestime.tv_sec = (time_t)ssp_time32;
-
- tod_ops.tod_get = todsf_get;
- tod_ops.tod_set = todsf_set;
- tod_ops.tod_set_watchdog_timer = todsf_set_watchdog_timer;
- tod_ops.tod_clear_watchdog_timer = todsf_clear_watchdog_timer;
- tod_ops.tod_set_power_alarm = todsf_set_power_alarm;
- tod_ops.tod_clear_power_alarm = todsf_clear_power_alarm;
- tod_ops.tod_get_cpufrequency = todsf_get_cpufrequency;
-
- /*
- * Flag warning if user tried to use hardware watchdog
- */
- if (watchdog_enable) {
- cmn_err(CE_WARN, "Hardware watchdog unavailable");
- }
- }
-
- return (mod_install(&modlinkage));
-}
-
-int
-_fini(void)
-{
- if (strcmp(tod_module_name, "todstarfire") == 0)
- return (EBUSY);
- else
- return (mod_remove(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-
-/*
- * Simply return hrestime value
- * Must be called with tod_lock held.
- */
-static timestruc_t
-todsf_get(void)
-{
- timestruc_t ts;
- extern cpu_sgnblk_t *cpu_sgnblkp[];
-
- ASSERT(MUTEX_HELD(&tod_lock));
-
- ts = hrestime;
-
- /* Update the heartbeat */
- if (cpu_sgnblkp[CPU->cpu_id] != NULL)
- cpu_sgnblkp[CPU->cpu_id]->sigb_heartbeat++;
- return (ts);
-}
-
-/*
- * Null function for now.
- * Must be called with tod_lock held.
- */
-/* ARGSUSED */
-static void
-todsf_set(timestruc_t ts)
-{
- ASSERT(MUTEX_HELD(&tod_lock));
-}
-
-
-/*
- * No watchdog function.
- */
-/* ARGSUSED */
-static uint_t
-todsf_set_watchdog_timer(uint_t timeoutval)
-{
- ASSERT(MUTEX_HELD(&tod_lock));
- return (0);
-}
-
-/*
- * No watchdog function
- */
-static uint_t
-todsf_clear_watchdog_timer(void)
-{
- ASSERT(MUTEX_HELD(&tod_lock));
- return (0);
-}
-
-/*
- * Null function.
- */
-/* ARGSUSED */
-static void
-todsf_set_power_alarm(timestruc_t ts)
-{
- ASSERT(MUTEX_HELD(&tod_lock));
-}
-
-/*
- * Null function
- */
-static void
-todsf_clear_power_alarm()
-{
- ASSERT(MUTEX_HELD(&tod_lock));
-}
-
-/*
- * Get clock freq from the cpunode
- */
-uint64_t
-todsf_get_cpufrequency(void)
-{
- return (cpunodes[CPU->cpu_id].clock_freq);
-}
diff --git a/usr/src/uts/sun4u/ngdr/Makefile.files b/usr/src/uts/sun4u/ngdr/Makefile.files
index 32e9af4eed..f03fb7a323 100644
--- a/usr/src/uts/sun4u/ngdr/Makefile.files
+++ b/usr/src/uts/sun4u/ngdr/Makefile.files
@@ -20,15 +20,14 @@
# CDDL HEADER END
#
#
-#pragma ident "%Z%%M% %I% %E% SMI"
-#
# Copyright (c) 2001 by Sun Microsystems, Inc.
# All rights reserved.
+# Copyright 2019 Peter Tribble.
#
#
# This Makefile defines the shared dr module that is used by
-# directories uts/sun4u/starfire and uts/sun4u/starcat.
+# directory uts/sun4u/starcat.
#
#
diff --git a/usr/src/uts/sun4u/ngdr/Makefile.rules b/usr/src/uts/sun4u/ngdr/Makefile.rules
index f72c79102f..3cbdbbbeed 100644
--- a/usr/src/uts/sun4u/ngdr/Makefile.rules
+++ b/usr/src/uts/sun4u/ngdr/Makefile.rules
@@ -19,15 +19,14 @@
# CDDL HEADER END
#
#
-#pragma ident "%Z%%M% %I% %E% SMI"
-#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright 2019 Peter Tribble.
#
#
# This Makefile defines the build rules for the shared dr
-# module used by uts/sun4u/starfire and uts/sun4u/starcat.
+# module used by uts/sun4u/starcat.
#
#
diff --git a/usr/src/uts/sun4u/ngdr/io/dr_cpu.c b/usr/src/uts/sun4u/ngdr/io/dr_cpu.c
index 17a96f378c..87b5cc7fef 100644
--- a/usr/src/uts/sun4u/ngdr/io/dr_cpu.c
+++ b/usr/src/uts/sun4u/ngdr/io/dr_cpu.c
@@ -25,6 +25,10 @@
*/
/*
+ * Copyright 2019 Peter Tribble.
+ */
+
+/*
* CPU support routines for DR
*/
@@ -70,13 +74,8 @@
#include <sys/dr.h>
#include <sys/dr_util.h>
-#ifdef _STARFIRE
-#include <sys/starfire.h>
-extern struct cpu *SIGBCPU;
-#else
/* for the DR*INTERNAL_ERROR macros. see sys/dr.h. */
static char *dr_ie_fmt = "dr_cpu.c %d";
-#endif /* _STARFIRE */
int
dr_cpu_unit_is_sane(dr_board_t *bp, dr_cpu_unit_t *cp)
@@ -145,14 +144,7 @@ dr_cpu_set_prop(dr_cpu_unit_t *cp)
}
if (dip == NULL) {
-#ifndef _STARFIRE
- /*
- * Do not report an error on Starfire since
- * the dip will not be created until after
- * the CPU has been configured.
- */
DR_DEV_INTERNAL_ERROR(&cp->sbc_cm);
-#endif /* !_STARFIRE */
return;
}
@@ -309,8 +301,6 @@ dr_pre_attach_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
*/
PR_CPU("%s: unmapping sigblk for cpu %d\n", f,
up->sbc_cpu_id);
-
- CPU_SGN_MAPOUT(up->sbc_cpu_id);
}
}
@@ -671,10 +661,6 @@ dr_fill_cpu_stat(dr_cpu_unit_t *cp, drmach_status_t *pstat, sbd_cpu_stat_t *csp)
/* CPU specific status data */
csp->cs_cpuid = cp->sbc_cpu_id;
-#ifdef _STARFIRE
- csp->cs_isbootproc = (SIGBCPU->cpu_id == cp->sbc_cpu_id) ? 1 : 0;
-#endif /* _STARFIRE */
-
/*
* If the speed and ecache properties have not been
* cached yet, read them in from the device tree.
diff --git a/usr/src/uts/sun4u/ngdr/io/dr_mem.c b/usr/src/uts/sun4u/ngdr/io/dr_mem.c
index ccb70b83cb..436d899ef7 100644
--- a/usr/src/uts/sun4u/ngdr/io/dr_mem.c
+++ b/usr/src/uts/sun4u/ngdr/io/dr_mem.c
@@ -25,6 +25,10 @@
*/
/*
+ * Copyright 2019 Peter Tribble.
+ */
+
+/*
* DR memory support routines.
*/
@@ -628,7 +632,6 @@ dr_detach_mem(dr_handle_t *hp, dr_common_unit_t *cp)
}
}
-#ifndef _STARFIRE
/*
* XXX workaround for certain lab configurations (see also starcat drmach.c)
* Temporary code to get around observed incorrect results from
@@ -698,7 +701,6 @@ again:
}
#define kphysm_del_span_query dr_del_span_query
-#endif /* _STARFIRE */
/*
* NOTE: This routine is only partially smart about multiple
diff --git a/usr/src/uts/sun4u/os/mach_mp_startup.c b/usr/src/uts/sun4u/os/mach_mp_startup.c
index e513f902c4..279aafcd36 100644
--- a/usr/src/uts/sun4u/os/mach_mp_startup.c
+++ b/usr/src/uts/sun4u/os/mach_mp_startup.c
@@ -22,6 +22,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#include <sys/machsystm.h>
#include <sys/cpu_module.h>
@@ -64,10 +67,6 @@ init_cpu_info(struct cpu *cp)
(void) strcpy(pi->pi_processor_type, "sparcv9");
(void) strcpy(pi->pi_fputypes, "sparcv9");
- /*
- * StarFire requires the signature block stuff setup here
- */
- CPU_SGN_MAPIN(cpuid);
if (cpuid == cpu0.cpu_id) {
/*
* cpu0 starts out running. Other cpus are
diff --git a/usr/src/uts/sun4u/starfire/Makefile b/usr/src/uts/sun4u/starfire/Makefile
deleted file mode 100644
index 7a08af878a..0000000000
--- a/usr/src/uts/sun4u/starfire/Makefile
+++ /dev/null
@@ -1,122 +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 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# This makefile drives the production of the sun4u starfire platform
-# module.
-#
-# sun4u starfire implementation architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# The following are SPARC specific (rather than sun4u) specific modules
-# which are required for the sun4u kernel to completely lint. They are
-# not involved in the build in any other way. In order to minimize
-# build time, it is assumed that they are up to date. But since sun4u
-# is really a separate architecture we cannot use the v7 sparc modules.
-#
-SPARC_LIB_DIR = $(UTSBASE)/sparc/lint-libs/$(OBJS_DIR)
-
-SPARC_LINTS =
-
-SUN4U_LIB_DIR = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR)
-
-#
-#
-#
-LINT_LIBS = $(LINT_LIB) \
- $(SPARC_LINTS:%=$(SPARC_LIB_DIR)/llib-l%.ln) \
- $(LINT_KMODS:%=$(SUN4U_LIB_DIR)/llib-l%.ln) \
- $(CLOSED_LINT_KMODS:%=$(SUN4U_LIB_DIR)/llib-l%.ln)
-
-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,Ultra-Enterprise-10000
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-.PARALLEL: $(STARFIRE_KMODS)
-
-.NO_PARALLEL: $(STARFIRE_CPU_KMODS)
-
-def all clean clobber clean.lint: genassym unix .WAIT \
- $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS)
-
-modlist: unix $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS)
-
-install: $(ROOT_STARFIRE_DIR) $(USR_STARFIRE_DIR) \
- $(USR_STARFIRE_INC_DIR) \
- $(USR_STARFIRE_SBIN_DIR) \
- $(USR_STARFIRE_LIB_DIR) \
- genassym unix .WAIT $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS)
-
-lintlib: unix
-
-modlintlib: $(STARFIRE_KMODS) $(STARFIRE_CPU_KMODS)
-
-genassym unix $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS): FRC
- @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET)
-
-install_h check: FRC
- @cd sys; pwd; $(MAKE) $(TARGET)
-
-#
-# Full kernel lint target.
-#
-LINT_TARGET = globallint
-
-globallint:
- @-$(ECHO) "\nStarfire KERNEL: global crosschecks:"
- @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2)
-
-lint: lintlib .WAIT modlintlib .WAIT $(LINT_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/Makefile.files b/usr/src/uts/sun4u/starfire/Makefile.files
deleted file mode 100644
index 96c4d9a102..0000000000
--- a/usr/src/uts/sun4u/starfire/Makefile.files
+++ /dev/null
@@ -1,67 +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 1997-2001, 2003 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# This Makefile defines all file modules for the directory
-# uts/sun4u/starfire and its children. These are the source files which
-# are starfire "implementation architecture" dependent.
-#
-
-#
-# Object lists
-#
-# Starfire specific kernel modules
-
-CORE_OBJS += cpu_sgnblk.o bbus_intr.o portctrl.o
-
-#
-# Starfire specific driver related modules
-#
-CVC_OBJS += cvc.o
-
-CVCREDIR_OBJS += cvcredir.o
-
-NGDRMACH_OBJS += drmach.o drmach_asm.o pda.o memctrl.o \
- dr_util.o drmach_err.o
-
-IDN_OBJS += idn.o idn_proto.o idn_dlpi.o idn_xf.o idn_smr.o idn_asm.o \
- mi.o nd.o inet_common.o \
- memctrl.o pda.o
-IDN_DEPS += idn_asm.o
-
-#
-# Miscellaneous
-#
-INC_PATH += -I$(UTSBASE)/sun4u/starfire
-
-#
-# Since assym.h is a derived file, the dependency must be explicit for
-# all files including this file. (This is only actually required in the
-# instance when the .nse_depinfo file does not exist.) It may seem that
-# the lint targets should also have a similar dependency, but they don't
-# since only C headers are included when #defined(lint) is true.
-#
-ASSYM_DEPS += drmach_asm.o idn_asm.o
diff --git a/usr/src/uts/sun4u/starfire/Makefile.rules b/usr/src/uts/sun4u/starfire/Makefile.rules
deleted file mode 100644
index 5da6c4cce3..0000000000
--- a/usr/src/uts/sun4u/starfire/Makefile.rules
+++ /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 2006 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/starfire 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.
-
-#
-# inline support for DR.
-#
-
-IL_CPP=$(CPP) -P -DINLINE -D_ASM $(AS_INC_PATH) \
- $(CPP_DEFS) $(ALWAYS_DEFS) $(ALL_DEFS) $(CONFIG_DEFS)
-
-#
-# Section 1a: C object build rules
-#
-
-$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/cvc/%.c
- $(COMPILE.c) -o $@ $<
- $(CTFCONVERT_O)
-
-$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/cvcredir/%.c
- $(COMPILE.c) -o $@ $<
- $(CTFCONVERT_O)
-
-DRMACH_IL= $(OBJS_DIR)/drmach.il
-$(OBJS_DIR)/drmach.o := CC_XARCH_32 = -xarch=v8plusa
-$(OBJS_DIR)/drmach.o: $(UTSBASE)/sun4u/starfire/io/drmach.c $(DRMACH_IL)
- $(COMPILE.c) $(DRMACH_IL) -o $@ $(UTSBASE)/sun4u/starfire/io/drmach.c
- $(CTFCONVERT_O)
-
-$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/io/%.c
- $(COMPILE.c) -o $@ $<
- $(CTFCONVERT_O)
-
-$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/ml/%.s
- $(COMPILE.s) -o $@ $<
-
-$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/os/%.c
- $(COMPILE.c) -o $@ $<
- $(CTFCONVERT_O)
-
-STARFIRE_IO= $(UTSBASE)/sun4u/starfire/io
-
-CLEANFILES += $(STARFIRE_IO)/drmach_err.c
-
-$(STARFIRE_IO)/drmach_err.c: $(SBDGENERR) $(SBD_IOCTL)
- $(RM) $@
- $(SBDGENERRCMD) ESTF < $(SBD_IOCTL) > $@
-
-# inline stuff
-
-CLEANFILES += $(DRMACH_IL)
-
-$(DRMACH_IL): $(UTSBASE)/sun4u/starfire/ml/drmach.il.cpp
- $(IL_CPP) $(UTSBASE)/sun4u/starfire/ml/drmach.il.cpp > $@
-
-#
-# Section 1b: Lint object build rules
-#
-
-$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/cvc/%.c
- @($(LHEAD) $(LINT.c) $< $(LTAIL))
-
-$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/cvcredir/%.c
- @($(LHEAD) $(LINT.c) $< $(LTAIL))
-
-$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/io/%.c
- @($(LHEAD) $(LINT.c) $< $(LTAIL))
-
-$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/ml/%.s
- @($(LHEAD) $(LINT.s) $< $(LTAIL))
-
-$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/os/%.c
- @($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/sun4u/starfire/Makefile.starfire b/usr/src/uts/sun4u/starfire/Makefile.starfire
deleted file mode 100644
index ce706f8681..0000000000
--- a/usr/src/uts/sun4u/starfire/Makefile.starfire
+++ /dev/null
@@ -1,132 +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.
-#
-# Global definitions for sun4u starfire implementation specific modules.
-#
-
-#
-# Define directories.
-#
-ROOT_STARFIRE_DIR = $(ROOT_PLAT_DIR)/SUNW,Ultra-Enterprise-10000
-ROOT_STARFIRE_MOD_DIR = $(ROOT_STARFIRE_DIR)/kernel
-ROOT_STARFIRE_KERN_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)
-ROOT_STARFIRE_KERN_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/$(SUBDIR64)
-ROOT_STARFIRE_MISC_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)/misc
-ROOT_STARFIRE_MISC_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/misc/$(SUBDIR64)
-ROOT_STARFIRE_DRV_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)/drv
-ROOT_STARFIRE_DRV_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/drv/$(SUBDIR64)
-ROOT_STARFIRE_CPU_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)/cpu
-ROOT_STARFIRE_CPU_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/cpu/$(SUBDIR64)
-
-ROOT_STARFIRE_KERN_DIR = $(ROOT_STARFIRE_KERN_DIR_$(CLASS))
-ROOT_STARFIRE_MISC_DIR = $(ROOT_STARFIRE_MISC_DIR_$(CLASS))
-ROOT_STARFIRE_DRV_DIR = $(ROOT_STARFIRE_DRV_DIR_$(CLASS))
-ROOT_STARFIRE_CPU_DIR = $(ROOT_STARFIRE_CPU_DIR_$(CLASS))
-
-ROOT_PLAT_MOD_DIRS += $(ROOT_STARFIRE_MOD_DIR)
-ROOT_PLAT_MISC_DIRS_32 += $(ROOT_STARFIRE_MISC_DIR_32)
-
-USR_STARFIRE_DIR = $(USR_PLAT_DIR)/SUNW,Ultra-Enterprise-10000
-USR_STARFIRE_INC_DIR = $(USR_STARFIRE_DIR)/include
-USR_STARFIRE_ISYS_DIR = $(USR_STARFIRE_INC_DIR)/sys
-USR_STARFIRE_SBIN_DIR = $(USR_STARFIRE_DIR)/sbin
-USR_STARFIRE_LIB_DIR = $(USR_STARFIRE_DIR)/lib
-
-#
-# Define objects.
-#
-STARFIRE_OBJS = starfire.o
-
-#
-# Define modules.
-#
-STARFIRE_KMODS = platmod
-STARFIRE_KMODS += rootnex sbus pcipsy
-STARFIRE_KMODS += cvc cvcredir
-STARFIRE_KMODS += ngdr ngdrmach
-STARFIRE_KMODS += idn
-
-#
-# CPU modules.
-#
-STARFIRE_CPU_KMODS += spitfire
-
-#
-# 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/ngdr/Makefile.files
-include $(UTSBASE)/sun4u/starfire/Makefile.files
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/Makefile.sun4u
-
-#
-# Everybody needs to know how to build modstubs.o and to locate unix.o
-#
-UNIX_DIR = $(UTSBASE)/$(PLATFORM)/starfire/unix
-MODSTUBS_DIR = $(UNIX_DIR)
-DSF_DIR = $(UTSBASE)/$(PLATFORM)/starfire/genassym
-LINTS_DIR = $(OBJS_DIR)
-LINT_LIB_DIR = $(UTSBASE)/$(PLATFORM)/starfire/lint-libs/$(OBJS_DIR)
-
-UNIX_O = $(UNIX_DIR)/$(OBJS_DIR)/unix.o
-
-LINT_LIB = $(LINT_LIB_DIR)/llib-lunix.ln
-
-#
-# Define the actual specific platforms
-#
-MACHINE_DEFS = -D$(PLATFORM) -D_MACHDEP -DSFMMU
-MACHINE_DEFS += -D_STARFIRE -D_CPU_SIGNATURE
-
-#
-# Define for inline pre-processing since
-# cpp not smart about v9 yet.
-#
-CPP_DEFS_32 =
-CPP_DEFS_64 = -D__sparcv9
-CPP_DEFS = $(CPP_DEFS_$(CLASS))
-
-#
-# 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
-LINTTAGS += -erroff=E_BAD_FORMAT_STR2
diff --git a/usr/src/uts/sun4u/starfire/Makefile.targ b/usr/src/uts/sun4u/starfire/Makefile.targ
deleted file mode 100644
index e746704e81..0000000000
--- a/usr/src/uts/sun4u/starfire/Makefile.targ
+++ /dev/null
@@ -1,93 +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 starfire implementation specific modules.
-#
-
-.KEEP_STATE:
-
-#
-# Rules for implementation subdirectories.
-#
-$(ROOT_STARFIRE_DIR): $(ROOT_PLAT_DIR)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_MOD_DIR): $(ROOT_STARFIRE_DIR)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_KERN_DIR): $(ROOT_STARFIRE_MOD_DIR)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_DRV_DIR_32): $(ROOT_STARFIRE_MOD_DIR)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_DRV_DIR_64): $(ROOT_STARFIRE_DRV_DIR_32)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_CPU_DIR_32): $(ROOT_STARFIRE_MOD_DIR)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_CPU_DIR_64): $(ROOT_STARFIRE_CPU_DIR_32)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_MISC_DIR_32): $(ROOT_STARFIRE_MOD_DIR)
- -$(INS.dir)
-
-$(ROOT_STARFIRE_MISC_DIR_64): $(ROOT_STARFIRE_MISC_DIR_32)
- -$(INS.dir)
-
-$(USR_STARFIRE_DIR): $(USR_PLAT_DIR)
- -$(INS.dir)
-
-$(USR_STARFIRE_INC_DIR): $(USR_STARFIRE_DIR) $(USR_PSM_INCL_DIR)
- $(INS.slink4)
-
-$(USR_STARFIRE_SBIN_DIR): $(USR_STARFIRE_DIR) $(USR_PSM_SBIN_DIR)
- -$(INS.slink5)
-
-$(USR_STARFIRE_LIB_DIR): $(USR_STARFIRE_DIR) $(USR_PSM_LIB_DIR)
- -$(INS.dir)
-
-$(USR_STARFIRE_ISYS_DIR): $(USR_STARFIRE_INC_DIR)
- $(INS.dir)
-
-$(ROOT_STARFIRE_KERN_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_KERN_DIR) FRC
- $(INS.file)
-
-$(ROOT_STARFIRE_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_DRV_DIR) FRC
- $(INS.file)
-
-$(ROOT_STARFIRE_CPU_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_CPU_DIR) FRC
- $(INS.file)
-
-$(ROOT_STARFIRE_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_MISC_DIR) FRC
- $(INS.file)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/ngdr/Makefile.rules
-include $(UTSBASE)/sun4u/starfire/Makefile.rules
-include $(UTSBASE)/sun4u/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/cvc/Makefile b/usr/src/uts/sun4u/starfire/cvc/Makefile
deleted file mode 100644
index f450a72f3b..0000000000
--- a/usr/src/uts/sun4u/starfire/cvc/Makefile
+++ /dev/null
@@ -1,88 +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.
-#
-# This makefile drives the production of the cvc driver module.
-#
-# sun4u starfire 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 = cvc
-OBJECTS = $(CVC_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(CVC_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/cvc
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-unused-function
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/cvc/cvc.c b/usr/src/uts/sun4u/starfire/cvc/cvc.c
deleted file mode 100644
index 1538db559c..0000000000
--- a/usr/src/uts/sun4u/starfire/cvc/cvc.c
+++ /dev/null
@@ -1,1200 +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.
- */
-
-
-/*
- * MT STREAMS Virtual Console Device Driver
- */
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/processor.h>
-#include <sys/cpuvar.h>
-#include <sys/open.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/signal.h>
-#include <sys/cred.h>
-#include <sys/user.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/file.h>
-#include <sys/kmem.h>
-#include <sys/vmem.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/strsubr.h>
-#include <sys/strsun.h>
-#include <sys/tty.h>
-#include <sys/ptyvar.h>
-#include <sys/poll.h>
-#include <sys/debug.h>
-#include <sys/conf.h>
-
-#include <sys/starfire.h>
-#include <sys/mman.h>
-#include <vm/seg_kmem.h>
-
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/errno.h>
-#include <sys/modctl.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/cvc.h>
-#include <sys/cpu_sgn.h>
-
-extern void prom_printf(char *fmt, ...);
-
-static int cvc_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int cvc_attach(dev_info_t *, ddi_attach_cmd_t);
-static int cvc_detach(dev_info_t *, ddi_detach_cmd_t);
-static int cvc_open(register queue_t *, dev_t *, int, int, cred_t *);
-static int cvc_close(queue_t *, int, cred_t *);
-static int cvc_wput(queue_t *, mblk_t *);
-static int cvc_wsrv(queue_t *);
-static void cvc_ioctl(queue_t *, mblk_t *);
-static void cvc_ack(mblk_t *, mblk_t *, uint_t);
-static void cvc_reioctl(void *);
-static void cvc_input_daemon(void);
-static void cvc_putc(register int);
-static void cvc_flush_buf(void *);
-static void cvc_bbsram_ops(volatile uchar_t *);
-
-static caddr_t cvc_iobuf_mapin(processorid_t);
-static void cvc_iobuf_mapout(processorid_t);
- void cvc_assign_iocpu(processorid_t);
-
-/*
- * Private copy of devinfo pointer; cvc_info uses it.
- */
-static dev_info_t *cvcdip;
-
-/*
- * This buffer is used to manage mapping in the I/O buffer that CVC
- * uses when communicating with the SSP Client (netcon_server) via bbsram.
- */
-static caddr_t cvc_iobufp[NCPU];
-
-typedef struct cvc_s {
- bufcall_id_t cvc_wbufcid;
- tty_common_t cvc_tty;
-} cvc_t;
-
-cvc_t cvc_common_tty;
-
-static struct module_info cvcm_info = {
- 1313, /* mi_idnum Bad luck number ;-) */
- "cvc", /* mi_idname */
- 0, /* mi_minpsz */
- INFPSZ, /* mi_maxpsz */
- 2048, /* mi_hiwat */
- 2048 /* mi_lowat */
-};
-
-static struct qinit cvcrinit = {
- NULL, /* qi_putp */
- NULL, /* qi_srvp */
- cvc_open, /* qi_qopen */
- cvc_close, /* qi_qclose */
- NULL, /* qi_qadmin */
- &cvcm_info, /* qi_minfo */
- NULL /* qi_mstat */
-};
-
-static struct qinit cvcwinit = {
- cvc_wput, /* qi_putp */
- cvc_wsrv, /* qi_srvp */
- cvc_open, /* qi_qopen */
- cvc_close, /* qi_qclose */
- NULL, /* qi_qadmin */
- &cvcm_info, /* qi_minfo */
- NULL /* qi_mstat */
-};
-
-struct streamtab cvcinfo = {
- &cvcrinit, /* st_rdinit */
- &cvcwinit, /* st_wrinit */
- NULL, /* st_muxrinit */
- NULL /* st_muxwrinit */
-};
-
-#define TIMEOUT_DELAY 100000
-
-#define BBSRAM_INPUT_BUF ((volatile char *)(cvc_iobufp[cvc_iocpu] \
- + BBSRAM_INPUT_COUNT_OFF))
-
-#define BBSRAM_OUTPUT_BUF ((volatile char *)(cvc_iobufp[cvc_iocpu] \
- + BBSRAM_OUTPUT_COUNT_OFF))
-
-#define BBSRAM_INPUT_COUNT (*((volatile short *)BBSRAM_INPUT_BUF))
-
-#define BBSRAM_OUTPUT_COUNT (*((volatile short *)BBSRAM_OUTPUT_BUF))
-
-#define CVC_OUT_MAXSPIN 1024
-
-/* The bbsram control reg is located at the end of the I/O buffers */
-#define BBSRAM_CONTROL_REG ((volatile uchar_t *)(cvc_iobufp[cvc_iocpu] \
- + CVC_IN_SIZE + CVC_OUT_SIZE))
-
-static krwlock_t cvclock; /* lock protecting everything here */
-static queue_t *cvcinput_q; /* queue for console input */
-static queue_t *cvcoutput_q; /* queue for console output */
-static int cvc_instance = -1;
-static int cvc_stopped = 0;
-static int cvc_suspended = 0;
-static int cvc_hangup_ok = 0;
-
-static kthread_id_t cvc_input_daemon_thread;
-static kmutex_t cvcmutex; /* protects input */
-static kmutex_t cvc_buf_mutex; /* protects internal output buffer */
-static kmutex_t cvc_bbsram_input_mutex; /* protects BBSRAM inp buff */
-static int input_ok = 0; /* true when stream is valid */
-static int stop_bbsram = 1; /* true when BBSRAM is not usable */
-static int stop_timeout = 0;
-static uchar_t cvc_output_buffer[MAX_XFER_OUTPUT]; /* output buffer */
-static ushort_t cvc_output_count = 0;
-static int via_bbsram = 0; /* toggle switch */
-static timeout_id_t cvc_timeout_id = (timeout_id_t)-1;
-static processorid_t cvc_iocpu = -1; /* cpu id of cpu zero */
-
-/*
- * Module linkage information for the kernel.
- */
-
-DDI_DEFINE_STREAM_OPS(cvcops, nulldev, nulldev, cvc_attach, cvc_detach,
- nodev, cvc_info, (D_MTPERQ | D_MP), &cvcinfo,
- ddi_quiesce_not_supported);
-
-static struct modldrv modldrv = {
- &mod_driverops, /* Type of module. This one is a pseudo driver */
- "CVC driver 'cvc'",
- &cvcops, /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- &modldrv,
- NULL
-};
-
-int
-_init(void)
-{
- int status;
-
- status = mod_install(&modlinkage);
- if (status == 0) {
- mutex_init(&cvcmutex, NULL, MUTEX_DEFAULT, NULL);
- }
- return (status);
-}
-
-int
-_fini(void)
-{
- return (EBUSY);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-/*
- * DDI glue routines.
- */
-
-/* ARGSUSED */
-static int
-cvc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
- static char been_here = 0;
-
- if (cmd == DDI_RESUME) {
- cvc_suspended = 0;
- return (DDI_SUCCESS);
- }
-
- mutex_enter(&cvcmutex);
- if (!been_here) {
- been_here = 1;
- mutex_init(&cvc_buf_mutex, NULL, MUTEX_DEFAULT, NULL);
- mutex_init(&cvc_bbsram_input_mutex, NULL, MUTEX_DEFAULT, NULL);
- rw_init(&cvclock, NULL, RW_DRIVER, NULL);
- rw_enter(&cvclock, RW_WRITER);
- cvc_timeout_id = timeout(cvc_flush_buf, NULL,
- drv_usectohz(TIMEOUT_DELAY));
- rw_exit(&cvclock);
- cvc_instance = ddi_get_instance(devi);
- } else {
-#if defined(DEBUG)
- cmn_err(CE_NOTE,
- "cvc_attach: called multiple times!! (instance = %d)",
- ddi_get_instance(devi));
-#endif /* DEBUG */
- return (DDI_SUCCESS);
- }
- mutex_exit(&cvcmutex);
-
- if (ddi_create_minor_node(devi, "cvc", S_IFCHR,
- 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
- ddi_remove_minor_node(devi, NULL);
- return (-1);
- }
- cvcdip = devi;
- cvcinput_q = NULL;
- cvcoutput_q = NULL;
- return (DDI_SUCCESS);
-}
-
-static int
-cvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
- if (cmd == DDI_SUSPEND) {
- cvc_suspended = 1;
- } else {
- if (cmd != DDI_DETACH) {
- return (DDI_FAILURE);
- }
- /*
- * XXX this doesn't even begin to address the detach
- * issues - it doesn't terminate the outstanding thread,
- * it doesn't clean up mutexes, kill the timeout routine
- * etc.
- */
- if (cvc_instance == ddi_get_instance(dip)) {
- ddi_remove_minor_node(dip, NULL);
- }
- }
- return (DDI_SUCCESS);
-}
-
-/* ARGSUSED */
-static int
-cvc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
- register int error;
-
- switch (infocmd) {
- case DDI_INFO_DEVT2DEVINFO:
- if (cvcdip == NULL) {
- error = DDI_FAILURE;
- } else {
- *result = (void *)cvcdip;
- error = DDI_SUCCESS;
- }
- break;
- case DDI_INFO_DEVT2INSTANCE:
- *result = (void *)0;
- error = DDI_SUCCESS;
- break;
- default:
- error = DDI_FAILURE;
- }
- return (error);
-}
-
-/* ARGSUSED */
-static int
-cvc_open(register queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
-{
- register int unit = getminor(*devp);
- register int err = 0;
- tty_common_t *tty;
- cvc_t *cp;
- static int input_daemon_started;
-
- if (unit != 0)
- return (ENXIO);
-
- if (q->q_ptr)
- return (0);
-
- cp = (cvc_t *)&cvc_common_tty;
- bzero((caddr_t)cp, sizeof (cvc_t));
- cp->cvc_wbufcid = 0;
- tty = &cp->cvc_tty;
- tty->t_readq = q;
- tty->t_writeq = WR(q);
- WR(q)->q_ptr = q->q_ptr = (caddr_t)cp;
- cvcinput_q = RD(q); /* save for cvc_redir */
- qprocson(q);
- mutex_enter(&cvcmutex);
- input_ok = 1;
- if (!input_daemon_started) {
- extern struct cpu *SIGBCPU; /* bugid4141050 */
- extern cpu_sgnblk_t *cpu_sgnblkp[];
-
- input_daemon_started = 1;
- mutex_exit(&cvcmutex);
-
- ASSERT(cpu_sgnblkp[SIGBCPU->cpu_id] != NULL);
- cvc_assign_iocpu(SIGBCPU->cpu_id);
-
- cvc_input_daemon_thread = thread_create(NULL, 0,
- cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri);
- } else {
- mutex_exit(&cvcmutex);
- }
-#ifdef lint
- cvc_input_daemon_thread = cvc_input_daemon_thread;
-#endif
- return (err);
-}
-
-/* ARGSUSED */
-static int
-cvc_close(queue_t *q, int flag, cred_t *crp)
-{
- register int err = 0;
- register cvc_t *cp;
-
- mutex_enter(&cvcmutex);
- input_ok = 0;
- mutex_exit(&cvcmutex);
-
- cp = q->q_ptr;
- if (cp->cvc_wbufcid != 0) {
- unbufcall(cp->cvc_wbufcid);
- }
- ttycommon_close(&cp->cvc_tty);
- WR(q)->q_ptr = q->q_ptr = NULL;
- cvcinput_q = NULL;
- bzero((caddr_t)cp, sizeof (cvc_t));
- qprocsoff(q);
- return (err);
-}
-
-
-/*
- * cvc_wput()
- * cn driver does a strwrite of console output data to rconsvp which
- * has been set by consconfig. The data enters the cvc stream at the
- * streamhead and flows thru ttycompat and ldterm which have been
- * pushed on the stream. Console output data gets sent out either
- * by cvcredir (if there is a cvcd running) or bbsram (if there
- * isn't).
- * Data is sent to the cvcredir via it's read q which is cvcoutput_q
- * and was set in cvc_register().
- */
-static int
-cvc_wput(register queue_t *q, register mblk_t *mp)
-{
- int error = 0;
-
- rw_enter(&cvclock, RW_READER);
- switch (mp->b_datap->db_type) {
-
- case M_IOCTL:
- case M_CTL:
- cvc_ioctl(q, mp);
- break;
-
- case M_FLUSH:
- if (*mp->b_rptr & FLUSHW) {
- /*
- * Flush our write queue.
- */
- flushq(q, FLUSHDATA);
- *mp->b_rptr &= ~FLUSHW;
- }
- if (*mp->b_rptr & FLUSHR) {
- flushq(RD(q), FLUSHDATA);
- qreply(q, mp);
- } else
- freemsg(mp);
- break;
-
- case M_STOP:
- cvc_stopped = 1;
- freemsg(mp);
- break;
-
- case M_START:
- cvc_stopped = 0;
- freemsg(mp);
- qenable(q); /* Start up delayed messages */
- break;
-
- case M_READ:
- /*
- * ldterm handles this (VMIN/VTIME processing).
- */
- freemsg(mp);
- break;
- default:
- cmn_err(CE_WARN, "cvc_wput: illegal mblk = 0x%p",
- (void *)mp);
- cmn_err(CE_WARN, "cvc_wput: type = 0x%x",
- mp->b_datap->db_type);
- /* FALLTHROUGH */
-#ifdef lint
- break;
-#endif
-
- case M_DATA:
- if (cvc_stopped == 1 || cvc_suspended == 1) {
- (void) putq(q, mp);
- break;
- }
- if (cvcoutput_q != NULL && !via_bbsram) {
- /*
- * Send it up past cvcredir module.
- */
- putnext(cvcoutput_q, mp);
- } else {
- char *msgp, c;
- mblk_t *mp2 = mp;
- int count;
-
- while (mp2 != NULL) {
- count = mp2->b_wptr - mp2->b_rptr;
- msgp = (char *)mp2->b_rptr;
- while (count > 0) {
- count--;
- if ((c = *msgp++) != '\0') {
- /* don't print NULs */
- cvc_putc(c);
- }
- }
- mp2 = mp2->b_cont;
- }
- freemsg(mp);
- }
- break;
-
- }
- rw_exit(&cvclock);
- return (error);
-}
-
-static int cvc_wsrv_count = 0;
-
-static int
-cvc_wsrv(queue_t *q)
-{
- register mblk_t *mp;
-
- cvc_wsrv_count++;
-
- if (cvc_stopped == 1 || cvc_suspended == 1) {
- return (0);
- }
-
- rw_enter(&cvclock, RW_READER);
- while ((mp = getq(q)) != NULL) {
- if (cvcoutput_q != NULL && !via_bbsram) {
- /*
- * Send it up past cvcredir module.
- */
- putnext(cvcoutput_q, mp);
- } else {
- char *msgp, c;
- mblk_t *mp2 = mp;
- int count;
-
- while (mp2 != NULL) {
- count = mp2->b_wptr - mp2->b_rptr;
- msgp = (char *)mp2->b_rptr;
- while (count > 0) {
- count--;
- if ((c = *msgp++) != '\0') {
- /* don't print NULs */
- cvc_putc(c);
- }
- }
- mp2 = mp2->b_cont;
- }
- freemsg(mp);
- }
- }
- rw_exit(&cvclock);
- return (0);
-}
-
-
-/*
- * cvc_ioctl()
- * handle normal console ioctls.
- */
-static void
-cvc_ioctl(register queue_t *q, register mblk_t *mp)
-{
- register struct iocblk *iocp;
- register tty_common_t *tty;
- register cvc_t *cp;
- int datasize;
- int error = 0;
- mblk_t *tmp;
-
- cp = q->q_ptr;
- tty = &cp->cvc_tty;
- if (tty->t_iocpending != NULL) {
- freemsg(tty->t_iocpending);
- tty->t_iocpending = NULL;
- }
- datasize = ttycommon_ioctl(tty, q, mp, &error);
- if (datasize != 0) {
- if (cp->cvc_wbufcid)
- unbufcall(cp->cvc_wbufcid);
- cp->cvc_wbufcid = bufcall(datasize, BPRI_HI, cvc_reioctl, cp);
- return;
- }
- if (error < 0) {
- iocp = (struct iocblk *)mp->b_rptr;
- /*
- * "ttycommon_ioctl" didn't do anything; we process it here.
- */
- error = 0;
- switch (iocp->ioc_cmd) {
-
- /*
- * Set modem bit ioctls. These are NOPs for us, since we
- * dont control any hardware.
- */
- case TCSBRK:
- case TIOCSBRK:
- case TIOCCBRK:
- case TIOCMSET:
- case TIOCMBIS:
- case TIOCMBIC:
- if (iocp->ioc_count != TRANSPARENT) {
- mioc2ack(mp, NULL, 0, 0);
- } else {
- mcopyin(mp, NULL, sizeof (int), NULL);
- }
- /* qreply done below */
- break;
-
- /*
- * Get modem bits, we return 0 in mblk.
- */
- case TIOCMGET:
- tmp = allocb(sizeof (int), BPRI_MED);
- if (tmp == NULL) {
- miocnak(q, mp, 0, EAGAIN);
- return;
- }
- *(int *)tmp->b_rptr = 0;
-
- if (iocp->ioc_count != TRANSPARENT)
- mioc2ack(mp, tmp, sizeof (int), 0);
- else
- mcopyout(mp, NULL, sizeof (int), NULL, tmp);
- /* qreply done below */
- break;
-
- default:
- /*
- * If we don't understand it, it's an error. NAK it.
- */
- error = EINVAL;
- break;
- }
- }
- if (error != 0) {
- iocp->ioc_error = error;
- mp->b_datap->db_type = M_IOCNAK;
- }
- qreply(q, mp);
-
-}
-
-
-/*
- * cvc_redir()
- * called from cvcredir:cvcr_wput() to handle console input
- * data. This routine puts the cvcredir write (downstream) data
- * onto the cvc read (upstream) queues. Note that if `mp' is
- * an M_IOCTL, then it may be reused by the caller to send back
- * an M_IOCACK or M_IOCNAK.
- */
-int
-cvc_redir(mblk_t *mp)
-{
- register struct iocblk *iocp;
- register tty_common_t *tty;
- register cvc_t *cp;
- struct winsize *ws;
- int error;
-
- if (cvcinput_q == NULL) {
- cmn_err(CE_WARN, "cvc_redir: cvcinput_q NULL!");
- return (EINVAL);
- }
-
- if (DB_TYPE(mp) != M_IOCTL) {
- putnext(cvcinput_q, mp);
- return (0);
- }
-
- iocp = (struct iocblk *)mp->b_rptr;
- if (iocp->ioc_cmd == TIOCSWINSZ) {
- error = miocpullup(mp, sizeof (struct winsize));
- if (error != 0)
- return (error);
-
- ws = (struct winsize *)mp->b_cont->b_rptr;
- cp = cvcinput_q->q_ptr;
- tty = &cp->cvc_tty;
- mutex_enter(&tty->t_excl);
- if (bcmp(&tty->t_size, ws, sizeof (struct winsize)) != 0) {
- tty->t_size = *ws;
- mutex_exit(&tty->t_excl);
- (void) putnextctl1(cvcinput_q, M_PCSIG, SIGWINCH);
- } else
- mutex_exit(&tty->t_excl);
- } else {
- /*
- * It must be a CVC_DISCONNECT, send hangup.
- */
- ASSERT(iocp->ioc_cmd == CVC_DISCONNECT);
- if (cvc_hangup_ok)
- (void) putnextctl(cvcinput_q, M_HANGUP);
- }
-
- return (0);
-}
-
-
-/*
- * cvc_register()
- * called from cvcredir to register it's queues. cvc
- * receives data from cn via the streamhead and sends it to cvcredir
- * via pointers to cvcredir's queues.
- */
-int
-cvc_register(queue_t *q)
-{
- int error = -1;
-
- if (cvcinput_q == NULL)
- cmn_err(CE_WARN, "cvc_register: register w/ no console open!");
- rw_enter(&cvclock, RW_WRITER);
- if (cvcoutput_q == NULL) {
- cvcoutput_q = RD(q); /* Make sure its the upstream q */
- qprocson(cvcoutput_q); /* must be done within cvclock */
- error = 0;
- } else {
- /*
- * cmn_err will call us, so release lock.
- */
- rw_exit(&cvclock);
- if (cvcoutput_q == q)
- cmn_err(CE_WARN, "cvc_register: duplicate q!");
- else
- cmn_err(CE_WARN, "cvc_register: nondup q = 0x%p",
- (void *)q);
- return (error);
- }
-
- /*
- * Unless "via_bbsram" is set, i/o will be going through cvcd, so
- * stop flushing output to BBSRAM.
- */
- if ((cvc_timeout_id != (timeout_id_t)-1) && (!via_bbsram)) {
- stop_timeout = 1;
- (void) untimeout(cvc_timeout_id);
- cvc_timeout_id = (timeout_id_t)-1;
- cvc_hangup_ok = 1;
- }
- rw_exit(&cvclock);
- return (error);
-}
-
-
-/*
- * cvc_unregister()
- * called from cvcredir to clear pointers to its queues.
- * cvcredir no longer wants to send or receive data.
- */
-void
-cvc_unregister(queue_t *q)
-{
- rw_enter(&cvclock, RW_WRITER);
- if (q == cvcoutput_q) {
- qprocsoff(cvcoutput_q); /* must be done within cvclock */
- cvcoutput_q = NULL;
- } else {
- rw_exit(&cvclock);
- cmn_err(CE_WARN, "cvc_unregister: q = 0x%p not registered",
- (void *)q);
- return;
- }
-
- /*
- * i/o will not be going through cvcd, start flushing output to
- * BBSRAM
- */
- if (cvc_timeout_id == (timeout_id_t)-1) {
- stop_timeout = 0;
- cvc_timeout_id = timeout(cvc_flush_buf, NULL,
- drv_usectohz(TIMEOUT_DELAY));
- }
- rw_exit(&cvclock);
-}
-
-/*
- * cvc_reioctl()
- * Retry an "ioctl", now that "bufcall" claims we may be able
- * to allocate the buffer we need.
- */
-static void
-cvc_reioctl(void *unit)
-{
- register queue_t *q;
- register mblk_t *mp;
- register cvc_t *cp = (cvc_t *)unit;
-
- /*
- * The bufcall is no longer pending.
- */
- if (!cp->cvc_wbufcid) {
- return;
- }
- cp->cvc_wbufcid = 0;
- if ((q = cp->cvc_tty.t_writeq) == NULL) {
- return;
- }
- if ((mp = cp->cvc_tty.t_iocpending) != NULL) {
- /* not pending any more */
- cp->cvc_tty.t_iocpending = NULL;
- cvc_ioctl(q, mp);
- }
-}
-
-
-/*
- * cvc_bbsram_ops()
- * Process commands sent to cvc from netcon_server via BBSRAM
- */
-static void
-cvc_bbsram_ops(volatile unsigned char *op_reg)
-{
- uchar_t op;
-
- if ((op = *op_reg) == 0)
- return;
-
- ASSERT(MUTEX_HELD(&cvc_bbsram_input_mutex));
-
- switch (op) {
- case CVC_BBSRAM_BREAK: /* A console break (L1-A) */
- abort_sequence_enter((char *)NULL);
- break;
- case CVC_BBSRAM_DISCONNECT: /* Break connection, hang up */
- if (cvcinput_q && cvc_hangup_ok)
- (void) putnextctl(cvcinput_q, M_HANGUP);
- break;
- case CVC_BBSRAM_VIA_NET: /* console via network */
- via_bbsram = 0;
- /*
- * stop periodic flushing of output to BBSRAM
- * only if cvcredir/cvcd are present
- */
- rw_enter(&cvclock, RW_WRITER);
- if (cvcoutput_q != NULL) {
- stop_timeout = 1;
- if (cvc_timeout_id != (timeout_id_t)-1) {
- (void) untimeout(cvc_timeout_id);
- cvc_timeout_id = (timeout_id_t)-1;
- }
- }
- rw_exit(&cvclock);
- break;
- case CVC_BBSRAM_VIA_BBSRAM: /* console via bbsram */
- via_bbsram = 1;
- /* start periodic flushing of ouput to BBSRAM */
- rw_enter(&cvclock, RW_WRITER);
- if (cvc_timeout_id == (timeout_id_t)-1) {
- stop_timeout = 0;
- cvc_timeout_id = timeout(cvc_flush_buf,
- NULL, drv_usectohz(TIMEOUT_DELAY));
- }
- rw_exit(&cvclock);
- break;
- case CVC_BBSRAM_CLOSE_NET:
- /*
- * Send a hangup control message upstream to cvcd
- * thru cvcredir. This is an attempt to close
- * out any existing network connection(if any).
- * cvcoutput_q should point to the cvcredir's read
- * queue.
- */
- rw_enter(&cvclock, RW_READER);
- if (cvcoutput_q != NULL) {
- (void) putnextctl(cvcoutput_q, M_HANGUP);
- }
- rw_exit(&cvclock);
- break;
- default:
- cmn_err(CE_WARN, "cvc: unknown BBSRAM opcode %d\n",
- (unsigned int)op);
- break;
- }
- *op_reg = 0;
-}
-
-
-/*
- * cvc_putc()
- * Put a single character out to BBSRAM if space available.
- */
-static void
-cvc_putc(register int c)
-{
- static int output_lost = 0;
-
- if (c == '\n')
- cvc_putc('\r');
-
- mutex_enter(&cvc_buf_mutex);
- /*
- * Just exit if the buffer is already full.
- * It will be up to cvc_flush_buf() to flush the buffer.
- */
- if (cvc_output_count == MAX_XFER_OUTPUT) {
- output_lost = 1;
- mutex_exit(&cvc_buf_mutex);
- return;
- }
- if (output_lost)
- prom_printf("WARNING: overflow of cvc output buffer, "
- "output lost!");
- output_lost = 0;
- cvc_output_buffer[cvc_output_count] = (unsigned char)c;
- cvc_output_count++;
- if ((cvc_output_count == MAX_XFER_OUTPUT) || (c == '\n')) {
- /* flush cvc's internal output buffer to BBSRAM */
-
- /*
- * Wait for the BBSRAM output buffer to be emptied.
- * This may hang if netcon_server isn't running on the SSP
- */
- int maxspin = CVC_OUT_MAXSPIN;
- while ((BBSRAM_OUTPUT_COUNT != 0) && --maxspin) {
- if (stop_bbsram) {
- mutex_exit(&cvc_buf_mutex);
- return;
- }
- DELAY(1000);
- }
- bcopy((caddr_t)cvc_output_buffer,
- (caddr_t)(BBSRAM_OUTPUT_BUF - cvc_output_count),
- cvc_output_count);
-
- BBSRAM_OUTPUT_COUNT = cvc_output_count;
- cvc_output_count = 0;
- }
- mutex_exit(&cvc_buf_mutex);
-}
-
-
-/*
- * cvc_flush_buf()
- * Flush cvc's internal output buffer to BBSRAM at regular intervals.
- * This should only be done if cvcd is not running or the user (via the cvc
- * application on the SSP) has requested that i/o go through BBSRAM.
- */
-/* ARGSUSED */
-static void
-cvc_flush_buf(void *notused)
-{
- if (stop_timeout)
- return;
-
- mutex_enter(&cvc_buf_mutex);
- if (cvc_output_count != 0) {
- /*
- * Wait for the BBSRAM output buffer to be emptied.
- * This may hang if netcon_server isn't running on the SSP.
- */
- int maxspin = CVC_OUT_MAXSPIN;
- while ((BBSRAM_OUTPUT_COUNT != 0) && --maxspin) {
- if (stop_bbsram)
- goto exit;
- DELAY(1000);
- }
-
- bcopy((caddr_t)cvc_output_buffer,
- (caddr_t)BBSRAM_OUTPUT_BUF - cvc_output_count,
- cvc_output_count);
-
- BBSRAM_OUTPUT_COUNT = cvc_output_count;
- cvc_output_count = 0;
- }
-exit:
- mutex_exit(&cvc_buf_mutex);
- /* rw_enter(&cvclock, RW_WRITER); */
- cvc_timeout_id = timeout(cvc_flush_buf, NULL,
- drv_usectohz(TIMEOUT_DELAY));
- /* rw_exit(&cvclock); */
-}
-
-
-/*
- * cvc_getstr()
- * Poll BBSRAM for console input while available.
- */
-static void
-cvc_getstr(char *cp)
-{
- short count;
- volatile char *lp;
-
- mutex_enter(&cvc_bbsram_input_mutex);
- /* Poll BBSRAM for input */
- do {
- if (stop_bbsram) {
- *cp = '\0'; /* set string to zero-length */
- mutex_exit(&cvc_bbsram_input_mutex);
- return;
- }
- /*
- * Use a smaller delay between checks of BBSRAM for input
- * when cvcd/cvcredir are not running or "via_bbsram" has
- * been set.
- * We don't go away completely when i/o is going through the
- * network via cvcd since a command may be sent via BBSRAM
- * to switch if the network is down or hung.
- */
- if ((cvcoutput_q == NULL) || (via_bbsram))
- delay(drv_usectohz(100000));
- else
- delay(drv_usectohz(1000000));
- cvc_bbsram_ops(BBSRAM_CONTROL_REG);
- count = BBSRAM_INPUT_COUNT;
- } while (count == 0);
-
- lp = BBSRAM_INPUT_BUF - count;
-
- while (count--) {
- *cp++ = *lp++;
- }
- *cp = '\0';
-
- BBSRAM_INPUT_COUNT = 0;
- mutex_exit(&cvc_bbsram_input_mutex);
-}
-
-
-/*
- * cvc_input_daemon()
- * this function runs as a separate kernel thread and polls BBSRAM for
- * input, and possibly put it on read stream for the console.
- * There are two poll rates (implemented in cvc_getstr):
- * 100 000 uS (10 Hz) - no cvcd communications || via_bbsram
- * 1000 000 uS ( 1 Hz) - cvcd communications
- * This continues to run even if there are network console communications
- * in order to handle out-of-band signaling.
- */
-static void
-cvc_input_daemon(void)
-{
- char linebuf[MAX_XFER_INPUT];
- char *cp;
- mblk_t *mbp;
- int c;
- int dropped_read = 0;
-
- for (;;) {
- cvc_getstr(linebuf);
-
- mbp = allocb(strlen(linebuf), BPRI_MED);
- if (mbp == NULL) { /* drop it & go on if no buffer */
- if (!dropped_read) {
- cmn_err(CE_WARN,
- "cvc_input_daemon: "
- "dropping BBSRAM reads\n");
- }
- dropped_read++;
- continue;
- }
- if (dropped_read) {
- cmn_err(CE_WARN,
- "cvc_input_daemon: dropped %d BBSRAM reads\n",
- dropped_read);
- dropped_read = 0;
- }
-
- for (cp = linebuf; *cp != '\0'; cp++) {
- c = (int)*cp;
- if (c == '\r')
- c = '\n';
- c &= 0177;
- *mbp->b_wptr = (char)c;
- mbp->b_wptr++;
- }
- mutex_enter(&cvcmutex);
- if (input_ok) {
- if (cvcinput_q == NULL) {
- cmn_err(CE_WARN,
- "cvc_input_daemon: cvcinput_q is NULL!");
- } else {
- putnext(cvcinput_q, mbp);
- }
- } else {
- freemsg(mbp);
- }
- mutex_exit(&cvcmutex);
- }
-
- /* NOTREACHED */
-}
-
-
-/*
- * cvc_bbsram_stop()
- * Prevents accesses to BBSRAM. used by cvc_assign_iocpu() when
- * mapping in BBSRAM to a virtual address.
- */
-static void
-cvc_bbsram_stop(void)
-{
- stop_bbsram = 1;
- mutex_enter(&cvc_bbsram_input_mutex);
- mutex_enter(&cvc_buf_mutex);
-}
-
-
-/*
- * cvc_bbsram_start()
- * Allow accesses to BBSRAM, used by cvc_assign_iocpu() after
- * BBSRAM has been mapped to a virtual address.
- */
-static void
-cvc_bbsram_start(void)
-{
- stop_bbsram = 0;
- mutex_exit(&cvc_buf_mutex);
- mutex_exit(&cvc_bbsram_input_mutex);
-}
-
-
-/*
- * cvc_assign_iocpu()
- * Map in BBSRAM to a virtual address
- * This called by the kernel with the cpu id of cpu zero.
- */
-void
-cvc_assign_iocpu(processorid_t newcpu)
-{
- processorid_t oldcpu = cvc_iocpu;
-
- if (newcpu == oldcpu)
- return;
-
- cvc_iobufp[newcpu] = cvc_iobuf_mapin(newcpu);
-
- cvc_bbsram_stop();
-
- cvc_iocpu = newcpu;
-
- cvc_bbsram_start();
-
- if (oldcpu != -1)
- cvc_iobuf_mapout(oldcpu);
-}
-
-
-/*
- * cvc_iobuf_mapin()
- * Map in the cvc bbsram i/o buffer into kernel space.
- */
-static caddr_t
-cvc_iobuf_mapin(processorid_t cpu_id)
-{
- caddr_t cvaddr;
- uint64_t cvc_iobuf_physaddr;
- pfn_t pfn;
- uint_t num_pages;
- extern cpu_sgnblk_t *cpu_sgnblkp[];
-
- ASSERT(cpu_sgnblkp[cpu_id] != NULL);
-
- /*
- * First construct the physical base address of the bbsram
- * in Starfire PSI space associated with this cpu in question.
- */
- cvc_iobuf_physaddr = STARFIRE_UPAID2UPS(cpu_id) | STARFIRE_PSI_BASE;
-
- /*
- * Next add the cvc i/o buffer offset obtained from the
- * sigblock to get cvc iobuf physical address
- */
- cvc_iobuf_physaddr += cpu_sgnblkp[cpu_id]->sigb_cvc_off;
-
- /* Get the page frame number */
- pfn = (cvc_iobuf_physaddr >> MMU_PAGESHIFT);
-
- /* Calculate how many pages we need to map in */
- num_pages = mmu_btopr(((uint_t)(cvc_iobuf_physaddr
- & MMU_PAGEOFFSET) + sizeof (sigb_cvc_t)));
-
- /*
- * Map in the cvc iobuf
- */
- cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP);
-
- hat_devload(kas.a_hat, cvaddr, mmu_ptob(num_pages), pfn,
- PROT_READ | PROT_WRITE, HAT_LOAD_LOCK);
-
- return ((caddr_t)(cvaddr + (uint_t)(cvc_iobuf_physaddr
- & MMU_PAGEOFFSET)));
-}
-
-
-/*
- * cvc_iobuf_mapout()
- * Map out the cvc iobuf from kernel space
- */
-static void
-cvc_iobuf_mapout(processorid_t cpu_id)
-{
- caddr_t cvaddr;
- size_t num_pages;
-
- if ((cvaddr = cvc_iobufp[cpu_id]) == 0) {
- /* already unmapped - return */
- return;
- }
-
- /* Calculate how many pages we need to map out */
- num_pages = mmu_btopr(((size_t)((uint64_t)cvaddr & MMU_PAGEOFFSET) +
- sizeof (sigb_cvc_t)));
-
- /* Get cvaddr to the start of the page boundary */
- cvaddr = (caddr_t)(((uint64_t)cvaddr & MMU_PAGEMASK));
-
- hat_unload(kas.a_hat, cvaddr, mmu_ptob(num_pages), HAT_UNLOAD_UNLOCK);
- vmem_free(heap_arena, cvaddr, ptob(num_pages));
-
- cvc_iobufp[cpu_id] = NULL;
-}
diff --git a/usr/src/uts/sun4u/starfire/cvc/cvc.conf b/usr/src/uts/sun4u/starfire/cvc/cvc.conf
deleted file mode 100644
index 50abb823fe..0000000000
--- a/usr/src/uts/sun4u/starfire/cvc/cvc.conf
+++ /dev/null
@@ -1,28 +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 (c) 1996 by Sun Microsystems, Inc.
-# All rights reserved.
-#
-name="cvc" parent="pseudo" instance=0;
diff --git a/usr/src/uts/sun4u/starfire/cvcredir/Makefile b/usr/src/uts/sun4u/starfire/cvcredir/Makefile
deleted file mode 100644
index 6725d33bef..0000000000
--- a/usr/src/uts/sun4u/starfire/cvcredir/Makefile
+++ /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, 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) 2011 Bayard G. Bell. All rights reserved.
-#
-# This makefile drives the production of the cvcredir driver module.
-#
-# sun4u starfire 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 = cvcredir
-OBJECTS = $(CVCREDIR_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(CVCREDIR_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/cvcredir
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# Define dependency on cvc
-#
-LDFLAGS += -dy -N drv/cvc
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c b/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c
deleted file mode 100644
index 05e9784933..0000000000
--- a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c
+++ /dev/null
@@ -1,278 +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.
- */
-
-
-/*
- * MT STREAMS Virtual Console Redirection Device Driver
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/strsun.h>
-#include <sys/debug.h>
-#include <sys/thread.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/tty.h>
-#include <sys/cvc.h>
-#include <sys/conf.h>
-#include <sys/modctl.h>
-
-
-/*
- * Routine to to register/unregister our queue for console output and pass
- * redirected data to the console. The cvc driver will do a putnext using
- * our queue, so we will not see the redirected console data.
- */
-extern int cvc_redir(mblk_t *);
-extern int cvc_register(queue_t *);
-extern int cvc_unregister(queue_t *);
-
-static int cvcr_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int cvcr_attach(dev_info_t *, ddi_attach_cmd_t);
-static int cvcr_detach(dev_info_t *, ddi_detach_cmd_t);
-static int cvcr_wput(queue_t *, mblk_t *);
-static int cvcr_open(queue_t *, dev_t *, int, int, cred_t *);
-static int cvcr_close(queue_t *, int, cred_t *);
-static void cvcr_ioctl(queue_t *, mblk_t *);
-
-static dev_info_t *cvcr_dip;
-static int cvcr_suspend = 0;
-
-static struct module_info minfo = {
- 1314, /* mi_idnum Bad luck number +1 ;-) */
- "cvcredir", /* mi_idname */
- 0, /* mi_minpsz */
- INFPSZ, /* mi_maxpsz */
- 2048, /* mi_hiwat */
- 2048 /* mi_lowat */
-};
-
-static struct qinit cvcr_rinit = {
- NULL, /* qi_putp */
- NULL, /* qi_srvp */
- cvcr_open, /* qi_qopen */
- cvcr_close, /* qi_qclose */
- NULL, /* qi_qadmin */
- &minfo, /* qi_minfo */
- NULL /* qi_mstat */
-};
-
-static struct qinit cvcr_winit = {
- cvcr_wput, /* qi_putp */
- NULL, /* qi_srvp */
- cvcr_open, /* qi_qopen */
- cvcr_close, /* qi_qclose */
- NULL, /* qi_qadmin */
- &minfo, /* qi_minfo */
- NULL /* qi_mstat */
-};
-
-struct streamtab cvcrinfo = {
- &cvcr_rinit, /* st_rdinit */
- &cvcr_winit, /* st_wrinit */
- NULL, /* st_muxrinit */
- NULL /* st_muxwrinit */
-};
-
-DDI_DEFINE_STREAM_OPS(cvcrops, nulldev, nulldev, cvcr_attach,
- cvcr_detach, nodev, cvcr_info, (D_MTPERQ | D_MP), &cvcrinfo,
- ddi_quiesce_not_supported);
-
-static struct modldrv modldrv = {
- &mod_driverops, /* Type of module. This one is a pseudo driver */
- "CVC redirect driver 'cvcredir'",
- &cvcrops, /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- &modldrv,
- NULL
-};
-
-int
-_init(void)
-{
- return (mod_install(&modlinkage));
-}
-
-int
-_fini(void)
-{
- return (mod_remove(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-static int
-cvcr_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-#ifdef lint
- cvcr_suspend = cvcr_suspend;
-#endif
- if (cmd == DDI_RESUME) {
- cvcr_suspend = 0;
- } else {
- if (ddi_create_minor_node(devi, "cvcredir", S_IFCHR,
- 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
- ddi_remove_minor_node(devi, NULL);
- return (-1);
- }
- cvcr_dip = devi;
- }
- return (DDI_SUCCESS);
-}
-
-static int
-cvcr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
- if (cmd == DDI_SUSPEND) {
- cvcr_suspend = 1;
- } else {
- if (cmd != DDI_DETACH) {
- return (DDI_FAILURE);
- }
- ddi_remove_minor_node(dip, NULL);
- }
- return (DDI_SUCCESS);
-}
-
-/* ARGSUSED */
-static int
-cvcr_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
- register int error;
-
- switch (infocmd) {
- case DDI_INFO_DEVT2DEVINFO:
- if (cvcr_dip == NULL) {
- error = DDI_FAILURE;
- } else {
- *result = (void *)cvcr_dip;
- error = DDI_SUCCESS;
- }
- break;
- case DDI_INFO_DEVT2INSTANCE:
- *result = (void *)0;
- error = DDI_SUCCESS;
- break;
- default:
- error = DDI_FAILURE;
- }
- return (error);
-}
-
-/* ARGSUSED */
-static int
-cvcr_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
-{
- WR(q)->q_ptr = q->q_ptr = (char *)2;
- /*
- * call into the cvc driver to register our queue. cvc will use
- * our queue to send console output data upstream (our stream)to
- * cvcd which has us open and is reading console data.
- */
- if (cvc_register(RD(q)) == -1) {
- cmn_err(CE_WARN, "cvcr_open: cvc_register failed for q = 0x%p",
- (void *)q);
- }
- return (0);
-}
-
-/* ARGSUSED */
-static int
-cvcr_close(queue_t *q, int flag, cred_t *cred)
-{
- /*
- * call into the cvc driver to un-register our queue. cvc will
- * no longer use our queue to send console output data upstream.
- */
- (void) cvc_unregister(RD(q));
- WR(q)->q_ptr = q->q_ptr = NULL;
- return (0);
-}
-
-static int
-cvcr_wput(queue_t *q, mblk_t *mp)
-{
- /*
- * Handle BREAK key for debugger and TIOCSWINSZ.
- */
- if (mp->b_datap->db_type == M_IOCTL) {
- cvcr_ioctl(q, mp);
- return (0);
- }
- /*
- * Call into the cvc driver to put console input data on
- * its upstream queue to be picked up by the console driver.
- */
- if (cvc_redir(mp) != 0)
- freemsg(mp);
- return (0);
-}
-
-static void
-cvcr_ioctl(queue_t *q, mblk_t *mp)
-{
- struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
- int error;
-
- switch (iocp->ioc_cmd) {
- case CVC_BREAK:
- abort_sequence_enter(NULL);
- miocack(q, mp, 0, 0);
- break;
-
- case CVC_DISCONNECT:
- case TIOCSWINSZ:
- /*
- * Generate a SIGHUP or SIGWINCH to the console. Note in this
- * case cvc_redir does not free up mp, so we can reuse it for
- * the ACK/NAK.
- */
- error = cvc_redir(mp);
- if (error != 0)
- miocnak(q, mp, 0, error);
- else
- miocack(q, mp, 0, 0);
- break;
-
- default:
- miocnak(q, mp, 0, EINVAL);
- break;
- }
-}
diff --git a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf b/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf
deleted file mode 100644
index 64ed7ee2a3..0000000000
--- a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf
+++ /dev/null
@@ -1,28 +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 (c) 1996 by Sun Microsystems, Inc.
-# All rights reserved.
-#
-name="cvcredir" parent="pseudo" instance=0;
diff --git a/usr/src/uts/sun4u/starfire/genassym/Makefile b/usr/src/uts/sun4u/starfire/genassym/Makefile
deleted file mode 100644
index 1d2dd04248..0000000000
--- a/usr/src/uts/sun4u/starfire/genassym/Makefile
+++ /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
-#
-#
-# 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 assym.h through genconst/stabs.
-#
-# sun4u starfire implementation architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../../..
-
-ASSYM_H = $(DSF_DIR)/$(OBJS_DIR)/assym.h
-GENCONST = $(DSF_DIR)/$(OBJS_DIR)/genconst
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(ASSYM_H)
-
-#
-# This is DSF_DIR. Use a short path.
-#
-DSF_DIR = .
-
-#
-# Overrides
-#
-CLEANFILES = $(GENCONST) Nothing_to_remove
-CLOBBERFILES = $(ASSYM_H) $(CLEANFILES) Nothing_to_remove
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-clean.lint:
-
-install: def
-
-#
-# create assym.h
-#
-$(GENCONST): $(GENCONST_SRC)
- $(NATIVECC) -w $(ALWAYS_DEFS) $(GENCONST_DEFS) $(NATIVE_INC_PATH) \
- -o $(GENCONST) $(GENCONST_SRC)
-
-$(ASSYM_H): $(GENCONST) $(OFFSETS) $(PLATFORM_OFFSETS)
- $(OFFSETS_CREATE) <$(OFFSETS) >$@
- $(OFFSETS_CREATE) <$(PLATFORM_OFFSETS) >>$@
- $(GENCONST) >>$@
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/idn/Makefile b/usr/src/uts/sun4u/starfire/idn/Makefile
deleted file mode 100644
index 3d7de4962e..0000000000
--- a/usr/src/uts/sun4u/starfire/idn/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, 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.
-#
-
-#
-# This makefile drives the production of the idn driver module.
-#
-# sun4u starfire 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 = idn
-OBJECTS = $(IDN_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(IDN_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/io
-
-IDN_OFFSETS = $(UTSBASE)/sun4u/starfire/ml/idn_offsets.in
-IDN_OFFSETS_H = $(OBJS_DIR)/idn_offsets.h
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE) -DIPV6
-CERRWARN += -_gcc=-Wno-unused-function
-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)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-AS_INC_PATH += -I$(OBJS_DIR)
-
-$(IDN_DEPS:%=$(OBJS_DIR)/%): $(IDN_OFFSETS_H)
-
-$(IDN_OFFSETS_H): $(GENCONST) $(IDN_OFFSETS)
- $(OFFSETS_CREATE) <$(IDN_OFFSETS) >$@
- $(GENCONST) >>$@
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/io/drmach.c b/usr/src/uts/sun4u/starfire/io/drmach.c
deleted file mode 100644
index dc51df3d6f..0000000000
--- a/usr/src/uts/sun4u/starfire/io/drmach.c
+++ /dev/null
@@ -1,3857 +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.
- * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
- * Copyright (c) 2016 by Delphix. All rights reserved.
- */
-
-#include <sys/debug.h>
-#include <sys/types.h>
-#include <sys/varargs.h>
-#include <sys/errno.h>
-#include <sys/cred.h>
-#include <sys/dditypes.h>
-#include <sys/devops.h>
-#include <sys/modctl.h>
-#include <sys/poll.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ndi_impldefs.h>
-#include <sys/stat.h>
-#include <sys/kmem.h>
-#include <sys/vmem.h>
-#include <sys/processor.h>
-#include <sys/spitregs.h>
-#include <sys/cpuvar.h>
-#include <sys/cpupart.h>
-#include <sys/mem_config.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/systm.h>
-#include <sys/machsystm.h>
-#include <sys/autoconf.h>
-#include <sys/cmn_err.h>
-#include <sys/sysmacros.h>
-#include <sys/x_call.h>
-#include <sys/promif.h>
-#include <sys/prom_plat.h>
-#include <sys/membar.h>
-#include <vm/seg_kmem.h>
-#include <sys/mem_cage.h>
-#include <sys/stack.h>
-#include <sys/archsystm.h>
-#include <vm/hat_sfmmu.h>
-#include <sys/pte.h>
-#include <sys/mmu.h>
-#include <sys/cpu_module.h>
-#include <sys/obpdefs.h>
-#include <sys/note.h>
-
-#include <sys/starfire.h> /* plat_max_... decls */
-#include <sys/cvc.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/drmach.h>
-#include <sys/dr_util.h>
-#include <sys/pda.h>
-
-#include <sys/sysevent.h>
-#include <sys/sysevent/dr.h>
-#include <sys/sysevent/eventdefs.h>
-
-
-extern void bcopy32_il(uint64_t, uint64_t);
-extern void flush_ecache_il(
- uint64_t physaddr, int size, int linesz);
-extern uint_t ldphysio_il(uint64_t physaddr);
-extern void stphysio_il(uint64_t physaddr, uint_t value);
-
-extern uint64_t mc_get_mem_alignment(void);
-extern uint64_t mc_get_asr_addr(pnode_t);
-extern uint64_t mc_get_idle_addr(pnode_t);
-extern uint64_t mc_get_alignment_mask(pnode_t);
-extern int mc_read_asr(pnode_t, uint_t *);
-extern int mc_write_asr(pnode_t, uint_t);
-extern uint64_t mc_asr_to_pa(uint_t);
-extern uint_t mc_pa_to_asr(uint_t, uint64_t);
-
-extern int pc_madr_add(int, int, int, int);
-
-typedef struct {
- struct drmach_node *node;
- void *data;
-} drmach_node_walk_args_t;
-
-typedef struct drmach_node {
- void *here;
-
- pnode_t (*get_dnode)(struct drmach_node *node);
- int (*walk)(struct drmach_node *node, void *data,
- int (*cb)(drmach_node_walk_args_t *args));
-} drmach_node_t;
-
-typedef struct {
- int min_index;
- int max_index;
- int arr_sz;
- drmachid_t *arr;
-} drmach_array_t;
-
-typedef struct {
- void *isa;
-
- sbd_error_t *(*release)(drmachid_t);
- sbd_error_t *(*status)(drmachid_t, drmach_status_t *);
-
- char name[MAXNAMELEN];
-} drmach_common_t;
-
-typedef struct {
- drmach_common_t cm;
- int bnum;
- int assigned;
- int powered;
- int connect_cpuid;
- int cond;
- drmach_node_t *tree;
- drmach_array_t *devices;
-} drmach_board_t;
-
-typedef struct {
- drmach_common_t cm;
- drmach_board_t *bp;
- int unum;
- int busy;
- int powered;
- const char *type;
- drmach_node_t *node;
-} drmach_device_t;
-
-typedef struct {
- int flags;
- drmach_device_t *dp;
- sbd_error_t *err;
- dev_info_t *dip;
-} drmach_config_args_t;
-
-typedef struct {
- uint64_t idle_addr;
- drmach_device_t *mem;
-} drmach_mc_idle_script_t;
-
-typedef struct {
- uint64_t masr_addr;
- uint_t masr;
- uint_t _filler;
-} drmach_rename_script_t;
-
-typedef struct {
- void (*run)(void *arg);
- caddr_t data;
- pda_handle_t *ph;
- struct memlist *c_ml;
- uint64_t s_copybasepa;
- uint64_t t_copybasepa;
- drmach_device_t *restless_mc; /* diagnostic output */
-} drmach_copy_rename_program_t;
-
-typedef enum {
- DO_IDLE,
- DO_UNIDLE,
- DO_PAUSE,
- DO_UNPAUSE
-} drmach_iopc_op_t;
-
-typedef struct {
- drmach_board_t *obj;
- int ndevs;
- void *a;
- sbd_error_t *(*found)(void *a, const char *, int, drmachid_t);
- sbd_error_t *err;
-} drmach_board_cb_data_t;
-
-static caddr_t drmach_shutdown_va;
-
-static int drmach_initialized;
-static drmach_array_t *drmach_boards;
-
-static int drmach_cpu_delay = 100;
-static int drmach_cpu_ntries = 50000;
-
-volatile uchar_t *drmach_xt_mb;
-
-/*
- * Do not change the drmach_shutdown_mbox structure without
- * considering the drmach_shutdown_asm assembly language code.
- */
-struct drmach_shutdown_mbox {
- uint64_t estack;
- uint64_t flushaddr;
- int size;
- int linesize;
- uint64_t physaddr;
-};
-struct drmach_shutdown_mbox *drmach_shutdown_asm_mbox;
-
-static int drmach_fini(void);
-static sbd_error_t *drmach_device_new(drmach_node_t *,
- drmach_board_t *, drmach_device_t **);
-static sbd_error_t *drmach_cpu_new(drmach_device_t *);
-static sbd_error_t *drmach_mem_new(drmach_device_t *);
-static sbd_error_t *drmach_io_new(drmach_device_t *);
-static sbd_error_t *drmach_board_release(drmachid_t);
-static sbd_error_t *drmach_board_status(drmachid_t, drmach_status_t *);
-static sbd_error_t *drmach_cpu_release(drmachid_t);
-static sbd_error_t *drmach_cpu_status(drmachid_t, drmach_status_t *);
-static sbd_error_t *drmach_io_release(drmachid_t);
-static sbd_error_t *drmach_io_status(drmachid_t, drmach_status_t *);
-static sbd_error_t *drmach_mem_release(drmachid_t);
-static sbd_error_t *drmach_mem_status(drmachid_t, drmach_status_t *);
-
-extern struct cpu *SIGBCPU;
-
-#ifdef DEBUG
-
-#define DRMACH_PR if (drmach_debug) printf
-int drmach_debug = 0; /* set to non-zero to enable debug messages */
-#else
-
-#define DRMACH_PR _NOTE(CONSTANTCONDITION) if (0) printf
-#endif /* DEBUG */
-
-#define DRMACH_OBJ(id) ((drmach_common_t *)id)
-
-#define DRMACH_IS_BOARD_ID(id) \
- ((id != 0) && \
- (DRMACH_OBJ(id)->isa == (void *)drmach_board_new))
-
-#define DRMACH_IS_CPU_ID(id) \
- ((id != 0) && \
- (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new))
-
-#define DRMACH_IS_MEM_ID(id) \
- ((id != 0) && \
- (DRMACH_OBJ(id)->isa == (void *)drmach_mem_new))
-
-#define DRMACH_IS_IO_ID(id) \
- ((id != 0) && \
- (DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
-
-#define DRMACH_IS_DEVICE_ID(id) \
- ((id != 0) && \
- (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \
- DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \
- DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
-
-#define DRMACH_IS_ID(id) \
- ((id != 0) && \
- (DRMACH_OBJ(id)->isa == (void *)drmach_board_new || \
- DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \
- DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \
- DRMACH_OBJ(id)->isa == (void *)drmach_io_new))
-
-#define DRMACH_CPUID2BNUM(cpuid) \
- ((cpuid) / MAX_CPU_UNITS_PER_BOARD)
-
-#define DRMACH_INTERNAL_ERROR() \
- drerr_new(1, ESTF_INTERNAL, drmach_ie_fmt, __LINE__)
-static char *drmach_ie_fmt = "drmach.c %d";
-
-static struct {
- const char *name;
- const char *type;
- sbd_error_t *(*new)(drmach_device_t *);
-} name2type[] = {
- { "SUNW,UltraSPARC", DRMACH_DEVTYPE_CPU, drmach_cpu_new },
- { "mem-unit", DRMACH_DEVTYPE_MEM, drmach_mem_new },
- { "pci", DRMACH_DEVTYPE_PCI, drmach_io_new },
- { "sbus", DRMACH_DEVTYPE_SBUS, drmach_io_new },
-};
-
-/* node types to cleanup when a board is unconfigured */
-#define MISC_COUNTER_TIMER_DEVNAME "counter-timer"
-#define MISC_PERF_COUNTER_DEVNAME "perf-counter"
-
-/* utility */
-#define MBYTE (1048576ull)
-
-/*
- * drmach autoconfiguration data structures and interfaces
- */
-
-extern struct mod_ops mod_miscops;
-
-static struct modlmisc modlmisc = {
- &mod_miscops,
- "Sun Enterprise 10000 DR"
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- (void *)&modlmisc,
- NULL
-};
-
-static kmutex_t drmach_i_lock;
-
-int
-_init(void)
-{
- int err;
-
- /* check that we have the correct version of obp */
- if (prom_test("SUNW,UE10000,add-brd") != 0) {
-
- cmn_err(CE_WARN, "!OBP/SSP upgrade is required to enable "
- "DR Functionality");
-
- return (-1);
- }
-
- mutex_init(&drmach_i_lock, NULL, MUTEX_DRIVER, NULL);
-
- drmach_xt_mb = (uchar_t *)vmem_alloc(static_alloc_arena,
- NCPU * sizeof (uchar_t), VM_SLEEP);
- drmach_shutdown_asm_mbox = (struct drmach_shutdown_mbox *)
- vmem_alloc(static_alloc_arena, sizeof (struct drmach_shutdown_mbox),
- VM_SLEEP);
-
- if ((err = mod_install(&modlinkage)) != 0) {
- mutex_destroy(&drmach_i_lock);
- vmem_free(static_alloc_arena, (void *)drmach_xt_mb,
- NCPU * sizeof (uchar_t));
- vmem_free(static_alloc_arena, (void *)drmach_shutdown_asm_mbox,
- sizeof (struct drmach_shutdown_mbox));
- }
-
- return (err);
-}
-
-int
-_fini(void)
-{
- if (drmach_fini())
- return (DDI_FAILURE);
- else
- return (mod_remove(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-static pnode_t
-drmach_node_obp_get_dnode(drmach_node_t *np)
-{
- return ((pnode_t)(uintptr_t)np->here);
-}
-
-static int
-drmach_node_obp_walk(drmach_node_t *np, void *data,
- int (*cb)(drmach_node_walk_args_t *args))
-{
- pnode_t nodeid;
- int rv;
- drmach_node_walk_args_t args;
-
- /* initialized args structure for callback */
- args.node = np;
- args.data = data;
-
- nodeid = prom_childnode(prom_rootnode());
-
- /* save our new position with in the tree */
- np->here = (void *)(uintptr_t)nodeid;
-
- rv = 0;
- while (nodeid != OBP_NONODE) {
- rv = (*cb)(&args);
- if (rv)
- break;
-
- nodeid = prom_nextnode(nodeid);
-
- /* save our new position with in the tree */
- np->here = (void *)(uintptr_t)nodeid;
- }
-
- return (rv);
-}
-
-static drmach_node_t *
-drmach_node_new(void)
-{
- drmach_node_t *np;
-
- np = kmem_zalloc(sizeof (drmach_node_t), KM_SLEEP);
-
- np->get_dnode = drmach_node_obp_get_dnode;
- np->walk = drmach_node_obp_walk;
-
- return (np);
-}
-
-static void
-drmach_node_dispose(drmach_node_t *np)
-{
- kmem_free(np, sizeof (*np));
-}
-
-static dev_info_t *
-drmach_node_get_dip(drmach_node_t *np)
-{
- pnode_t nodeid;
-
- nodeid = np->get_dnode(np);
- if (nodeid == OBP_NONODE)
- return (NULL);
- else {
- dev_info_t *dip;
-
- /* The root node doesn't have to be held */
- dip = e_ddi_nodeid_to_dip(nodeid);
- if (dip) {
- /*
- * Branch rooted at dip is already held, so release
- * hold acquired in e_ddi_nodeid_to_dip()
- */
- ddi_release_devi(dip);
- ASSERT(e_ddi_branch_held(dip));
- }
-
- return (dip);
- }
- /*NOTREACHED*/
-}
-
-static pnode_t
-drmach_node_get_dnode(drmach_node_t *np)
-{
- return (np->get_dnode(np));
-}
-
-static int
-drmach_node_walk(drmach_node_t *np, void *param,
- int (*cb)(drmach_node_walk_args_t *args))
-{
- return (np->walk(np, param, cb));
-}
-
-static int
-drmach_node_get_prop(drmach_node_t *np, char *name, void *buf)
-{
- pnode_t nodeid;
- int rv;
-
- nodeid = np->get_dnode(np);
- if (nodeid == OBP_NONODE)
- rv = -1;
- else if (prom_getproplen(nodeid, (caddr_t)name) < 0)
- rv = -1;
- else {
- (void) prom_getprop(nodeid, (caddr_t)name, (caddr_t)buf);
- rv = 0;
- }
-
- return (rv);
-}
-
-static int
-drmach_node_get_proplen(drmach_node_t *np, char *name, int *len)
-{
- pnode_t nodeid;
- int rv;
-
- nodeid = np->get_dnode(np);
- if (nodeid == OBP_NONODE)
- rv = -1;
- else {
- *len = prom_getproplen(nodeid, (caddr_t)name);
- rv = (*len < 0 ? -1 : 0);
- }
-
- return (rv);
-}
-
-static drmachid_t
-drmach_node_dup(drmach_node_t *np)
-{
- drmach_node_t *dup;
-
- dup = drmach_node_new();
- dup->here = np->here;
-
- return (dup);
-}
-
-/*
- * drmach_array provides convenient array construction, access,
- * bounds checking and array destruction logic.
- */
-
-static drmach_array_t *
-drmach_array_new(int min_index, int max_index)
-{
- drmach_array_t *arr;
-
- arr = kmem_zalloc(sizeof (drmach_array_t), KM_SLEEP);
-
- arr->arr_sz = (max_index - min_index + 1) * sizeof (void *);
- if (arr->arr_sz > 0) {
- arr->min_index = min_index;
- arr->max_index = max_index;
-
- arr->arr = kmem_zalloc(arr->arr_sz, KM_SLEEP);
- return (arr);
- } else {
- kmem_free(arr, sizeof (*arr));
- return (0);
- }
-}
-
-static int
-drmach_array_set(drmach_array_t *arr, int idx, drmachid_t val)
-{
- if (idx < arr->min_index || idx > arr->max_index)
- return (-1);
- else {
- arr->arr[idx - arr->min_index] = val;
- return (0);
- }
- /*NOTREACHED*/
-}
-
-static int
-drmach_array_get(drmach_array_t *arr, int idx, drmachid_t *val)
-{
- if (idx < arr->min_index || idx > arr->max_index)
- return (-1);
- else {
- *val = arr->arr[idx - arr->min_index];
- return (0);
- }
- /*NOTREACHED*/
-}
-
-static int
-drmach_array_first(drmach_array_t *arr, int *idx, drmachid_t *val)
-{
- int rv;
-
- *idx = arr->min_index;
- while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL)
- *idx += 1;
-
- return (rv);
-}
-
-static int
-drmach_array_next(drmach_array_t *arr, int *idx, drmachid_t *val)
-{
- int rv;
-
- *idx += 1;
- while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL)
- *idx += 1;
-
- return (rv);
-}
-
-static void
-drmach_array_dispose(drmach_array_t *arr, void (*disposer)(drmachid_t))
-{
- drmachid_t val;
- int idx;
- int rv;
-
- rv = drmach_array_first(arr, &idx, &val);
- while (rv == 0) {
- (*disposer)(val);
- rv = drmach_array_next(arr, &idx, &val);
- }
-
- kmem_free(arr->arr, arr->arr_sz);
- kmem_free(arr, sizeof (*arr));
-}
-
-/*ARGSUSED*/
-static int
-drmach_prom_select(pnode_t nodeid, void *arg, uint_t flags)
-{
- int rprop[64];
- pnode_t saved;
- drmach_config_args_t *ap = (drmach_config_args_t *)arg;
- drmach_device_t *dp = ap->dp;
- sbd_error_t *err;
-
- saved = drmach_node_get_dnode(dp->node);
-
- if (nodeid != saved)
- return (DDI_FAILURE);
-
- if (saved == OBP_NONODE) {
- err = DRMACH_INTERNAL_ERROR();
- DRERR_SET_C(&ap->err, &err);
- return (DDI_FAILURE);
- }
-
- if (prom_getprop(nodeid, OBP_REG, (caddr_t)rprop) <= 0) {
- return (DDI_FAILURE);
- }
-
- return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static void
-drmach_branch_callback(dev_info_t *rdip, void *arg, uint_t flags)
-{
- drmach_config_args_t *ap = (drmach_config_args_t *)arg;
-
- ASSERT(ap->dip == NULL);
-
- ap->dip = rdip;
-}
-
-sbd_error_t *
-drmach_configure(drmachid_t id, int flags)
-{
- drmach_device_t *dp;
- sbd_error_t *err;
- drmach_config_args_t ca;
- devi_branch_t b = {0};
- dev_info_t *fdip = NULL;
-
- if (!DRMACH_IS_DEVICE_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- ca.dp = dp;
- ca.flags = flags;
- ca.err = NULL; /* will be set if error detected */
- ca.dip = NULL;
-
- b.arg = &ca;
- b.type = DEVI_BRANCH_PROM;
- b.create.prom_branch_select = drmach_prom_select;
- b.devi_branch_callback = drmach_branch_callback;
-
- if (e_ddi_branch_create(ddi_root_node(), &b, &fdip,
- DEVI_BRANCH_CHILD | DEVI_BRANCH_CONFIGURE) != 0) {
- char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-
- /*
- * If non-NULL, fdip is returned held and must be released.
- */
- if (fdip != NULL) {
- (void) ddi_pathname(fdip, path);
- ddi_release_devi(fdip);
- } else if (ca.dip != NULL) {
- /* safe to call ddi_pathname as dip already held */
- (void) ddi_pathname(ca.dip, path);
- } else {
- (void) strcpy(path, "<none>");
- }
-
- err = drerr_new(1, ESTF_DRVFAIL, path);
- DRERR_SET_C(&ca.err, &err);
- kmem_free(path, MAXPATHLEN);
- }
-
- return (ca.err);
-}
-
-static sbd_error_t *
-drmach_device_new(drmach_node_t *node,
- drmach_board_t *bp, drmach_device_t **dpp)
-{
- int i;
- int rv;
- drmach_device_t *dp;
- sbd_error_t *err;
- char name[OBP_MAXDRVNAME];
-
- rv = drmach_node_get_prop(node, OBP_NAME, name);
- if (rv) {
- /* every node is expected to have a name */
- err = drerr_new(1, ESTF_GETPROP,
- "PROM Node 0x%x: property %s",
- (uint_t)node->get_dnode(node), OBP_NAME);
-
- return (err);
- }
-
- /*
- * The node currently being examined is not listed in the name2type[]
- * array. In this case, the node is no interest to drmach. Both
- * dp and err are initialized here to yield nothing (no device or
- * error structure) for this case.
- */
- for (i = 0; i < sizeof (name2type) / sizeof (name2type[0]); i++)
- if (strcmp(name2type[i].name, name) == 0)
- break;
-
- if (i < sizeof (name2type) / sizeof (name2type[0])) {
- dp = kmem_zalloc(sizeof (drmach_device_t), KM_SLEEP);
-
- dp->bp = bp;
- dp->unum = -1;
- dp->node = drmach_node_dup(node);
- dp->type = name2type[i].type;
-
- err = (name2type[i].new)(dp);
- if (err) {
- drmach_node_dispose(node);
- kmem_free(dp, sizeof (*dp));
- dp = NULL;
- }
-
- *dpp = dp;
- return (err);
- }
-
- /*
- * The node currently being examined is not listed in the name2type[]
- * array. In this case, the node is no interest to drmach. Both
- * dp and err are initialized here to yield nothing (no device or
- * error structure) for this case.
- */
- *dpp = NULL;
- return (NULL);
-}
-
-static void
-drmach_device_dispose(drmachid_t id)
-{
- drmach_device_t *self = id;
-
- if (self->node)
- drmach_node_dispose(self->node);
-
- kmem_free(self, sizeof (*self));
-}
-
-static sbd_error_t *
-drmach_device_get_prop(drmach_device_t *dp, char *name, void *buf)
-{
- sbd_error_t *err = NULL;
- int rv;
-
- rv = drmach_node_get_prop(dp->node, name, buf);
- if (rv) {
- err = drerr_new(1, ESTF_GETPROP,
- "%s::%s: property %s",
- dp->bp->cm.name, dp->cm.name, name);
- }
-
- return (err);
-}
-
-static sbd_error_t *
-drmach_device_get_proplen(drmach_device_t *dp, char *name, int *len)
-{
- sbd_error_t *err = NULL;
- int rv;
-
- rv = drmach_node_get_proplen(dp->node, name, len);
- if (rv) {
- err = drerr_new(1, ESTF_GETPROPLEN,
- "%s::%s: property %s",
- dp->bp->cm.name, dp->cm.name, name);
- }
-
- return (err);
-}
-
-static drmach_board_t *
-drmach_board_new(int bnum)
-{
- drmach_board_t *bp;
-
- bp = kmem_zalloc(sizeof (drmach_board_t), KM_SLEEP);
-
- bp->cm.isa = (void *)drmach_board_new;
- bp->cm.release = drmach_board_release;
- bp->cm.status = drmach_board_status;
-
- (void) drmach_board_name(bnum, bp->cm.name, sizeof (bp->cm.name));
-
- bp->bnum = bnum;
- bp->devices = NULL;
- bp->connect_cpuid = -1;
- bp->tree = drmach_node_new();
- bp->assigned = !drmach_initialized;
- bp->powered = !drmach_initialized;
-
- (void) drmach_array_set(drmach_boards, bnum, bp);
- return (bp);
-}
-
-static void
-drmach_board_dispose(drmachid_t id)
-{
- drmach_board_t *bp;
-
- ASSERT(DRMACH_IS_BOARD_ID(id));
- bp = id;
-
- if (bp->tree)
- drmach_node_dispose(bp->tree);
-
- if (bp->devices)
- drmach_array_dispose(bp->devices, drmach_device_dispose);
-
- kmem_free(bp, sizeof (*bp));
-}
-
-static sbd_error_t *
-drmach_board_status(drmachid_t id, drmach_status_t *stat)
-{
- sbd_error_t *err = NULL;
- drmach_board_t *bp;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- bp = id;
-
- stat->assigned = bp->assigned;
- stat->powered = bp->powered;
- stat->busy = 0; /* assume not busy */
- stat->configured = 0; /* assume not configured */
- stat->empty = 0;
- stat->cond = bp->cond = SBD_COND_OK;
- (void) strncpy(stat->type, "System Brd", sizeof (stat->type));
- stat->info[0] = '\0';
-
- if (bp->devices) {
- int rv;
- int d_idx;
- drmachid_t d_id;
-
- rv = drmach_array_first(bp->devices, &d_idx, &d_id);
- while (rv == 0) {
- drmach_status_t d_stat;
-
- err = drmach_status(d_id, &d_stat);
- if (err)
- break;
-
- stat->busy |= d_stat.busy;
- stat->configured |= d_stat.configured;
-
- rv = drmach_array_next(bp->devices, &d_idx, &d_id);
- }
- }
-
- return (err);
-}
-
-/* a simple routine to reduce redundancy of this common logic */
-static pda_handle_t
-drmach_pda_open(void)
-{
- pda_handle_t ph;
-
- ph = pda_open();
- if (ph == NULL) {
- /* catch in debug kernels */
- ASSERT(0);
- cmn_err(CE_WARN, "pda_open failed");
- }
-
- return (ph);
-}
-
-#ifdef DEBUG
-int drmach_init_break = 0;
-#endif
-
-static int
-hold_rele_branch(dev_info_t *rdip, void *arg)
-{
- int i;
- int *holdp = (int *)arg;
- char *name = ddi_node_name(rdip);
-
- /*
- * For Starfire, we must be children of the root devinfo node
- */
- ASSERT(ddi_get_parent(rdip) == ddi_root_node());
-
- for (i = 0; i < sizeof (name2type) / sizeof (name2type[0]); i++)
- if (strcmp(name2type[i].name, name) == 0)
- break;
-
- if (i == sizeof (name2type) / sizeof (name2type[0])) {
- /* Not of interest to us */
- return (DDI_WALK_PRUNECHILD);
- }
-
- if (*holdp) {
- ASSERT(!e_ddi_branch_held(rdip));
- e_ddi_branch_hold(rdip);
- } else {
- ASSERT(e_ddi_branch_held(rdip));
- e_ddi_branch_rele(rdip);
- }
-
- return (DDI_WALK_PRUNECHILD);
-}
-
-static int
-drmach_init(void)
-{
- pnode_t nodeid;
- dev_info_t *rdip;
- int hold, circ;
-
-#ifdef DEBUG
- if (drmach_init_break)
- debug_enter("drmach_init: drmach_init_break set\n");
-#endif
- mutex_enter(&drmach_i_lock);
- if (drmach_initialized) {
- mutex_exit(&drmach_i_lock);
- return (0);
- }
-
- drmach_boards = drmach_array_new(0, MAX_BOARDS - 1);
-
- nodeid = prom_childnode(prom_rootnode());
- do {
- int bnum;
- drmachid_t id;
-
- bnum = -1;
- (void) prom_getprop(nodeid, OBP_BOARDNUM, (caddr_t)&bnum);
- if (bnum == -1)
- continue;
-
- if (drmach_array_get(drmach_boards, bnum, &id) == -1) {
- cmn_err(CE_WARN, "OBP node 0x%x has"
- " invalid property value, %s=%d",
- nodeid, OBP_BOARDNUM, bnum);
-
- /* clean up */
- drmach_array_dispose(
- drmach_boards, drmach_board_dispose);
-
- mutex_exit(&drmach_i_lock);
- return (-1);
- } else if (id == NULL)
- (void) drmach_board_new(bnum);
- } while ((nodeid = prom_nextnode(nodeid)) != OBP_NONODE);
-
- drmach_shutdown_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
-
- /*
- * Walk immediate children of devinfo root node and hold
- * all devinfo branches of interest.
- */
- hold = 1;
- rdip = ddi_root_node();
-
- ndi_devi_enter(rdip, &circ);
- ddi_walk_devs(ddi_get_child(rdip), hold_rele_branch, &hold);
- ndi_devi_exit(rdip, circ);
-
- drmach_initialized = 1;
-
- mutex_exit(&drmach_i_lock);
-
- return (0);
-}
-
-static int
-drmach_fini(void)
-{
- dev_info_t *rdip;
- int hold, circ;
-
- if (drmach_initialized) {
- int busy = 0;
- int rv;
- int idx;
- drmachid_t id;
-
- ASSERT(drmach_boards != NULL);
-
- rv = drmach_array_first(drmach_boards, &idx, &id);
- while (rv == 0) {
- sbd_error_t *err;
- drmach_status_t stat;
-
- err = drmach_board_status(id, &stat);
- if (err) {
- /* catch in debug kernels */
- ASSERT(0);
- sbd_err_clear(&err);
- busy = 1;
- } else
- busy |= stat.busy;
-
- rv = drmach_array_next(drmach_boards, &idx, &id);
- }
-
- if (busy)
- return (-1);
-
- drmach_array_dispose(drmach_boards, drmach_board_dispose);
- drmach_boards = NULL;
-
- vmem_free(heap_arena, drmach_shutdown_va, PAGESIZE);
-
- /*
- * Walk immediate children of the root devinfo node
- * releasing holds acquired on branches in drmach_init()
- */
- hold = 0;
- rdip = ddi_root_node();
-
- ndi_devi_enter(rdip, &circ);
- ddi_walk_devs(ddi_get_child(rdip), hold_rele_branch, &hold);
- ndi_devi_exit(rdip, circ);
-
- mutex_destroy(&drmach_i_lock);
-
- drmach_initialized = 0;
- }
- if (drmach_xt_mb != NULL) {
- vmem_free(static_alloc_arena, (void *)drmach_xt_mb,
- NCPU * sizeof (uchar_t));
- }
- if (drmach_shutdown_asm_mbox != NULL) {
- vmem_free(static_alloc_arena, (void *)drmach_shutdown_asm_mbox,
- sizeof (struct drmach_shutdown_mbox));
- }
- return (0);
-}
-
-static sbd_error_t *
-drmach_get_mc_asr_addr(drmachid_t id, uint64_t *pa)
-{
- drmach_device_t *dp;
- pnode_t nodeid;
- uint64_t addr;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- nodeid = drmach_node_get_dnode(dp->node);
- if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE)
- return (DRMACH_INTERNAL_ERROR());
-
- addr = mc_get_asr_addr(nodeid);
- if (addr == (uint64_t)-1)
- return (DRMACH_INTERNAL_ERROR());
-
- *pa = addr;
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_get_mc_idle_addr(drmachid_t id, uint64_t *pa)
-{
- drmach_device_t *dp;
- pnode_t nodeid;
- uint64_t addr;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- nodeid = drmach_node_get_dnode(dp->node);
- if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE)
- return (DRMACH_INTERNAL_ERROR());
-
- addr = mc_get_idle_addr(nodeid);
- if (addr == (uint64_t)-1)
- return (DRMACH_INTERNAL_ERROR());
-
- *pa = addr;
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_read_mc_asr(drmachid_t id, uint_t *mcregp)
-{
- drmach_device_t *dp;
- pnode_t nodeid;
- sbd_error_t *err;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- nodeid = drmach_node_get_dnode(dp->node);
- if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE)
- err = DRMACH_INTERNAL_ERROR();
- else if (mc_read_asr(nodeid, mcregp) == -1)
- err = DRMACH_INTERNAL_ERROR();
- else
- err = NULL;
-
- return (err);
-}
-
-static sbd_error_t *
-drmach_write_mc_asr(drmachid_t id, uint_t mcreg)
-{
- drmach_device_t *dp;
- pnode_t nodeid;
- sbd_error_t *err;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- nodeid = drmach_node_get_dnode(dp->node);
- if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE)
- err = DRMACH_INTERNAL_ERROR();
- else if (mc_write_asr(nodeid, mcreg) == -1)
- err = DRMACH_INTERNAL_ERROR();
- else
- err = NULL;
-
- return (err);
-}
-
-static sbd_error_t *
-drmach_prep_rename_script(drmach_device_t *s_mem, drmach_device_t *t_mem,
- uint64_t t_slice_offset, caddr_t buf, int buflen)
-{
- int i, b, m;
- drmach_mc_idle_script_t *isp;
- drmach_rename_script_t *rsp;
- int s_bd, t_bd;
- uint_t s_masr, t_masr;
- uint64_t s_new_basepa, t_new_basepa;
- int b_idx, rv;
- sbd_error_t *err;
- drmachid_t b_id;
- drmach_board_t *brd;
-
-#ifdef DEBUG
- /*
- * Starfire CPU/MEM/IO boards have only one MC per board.
- * This function has been coded with that fact in mind.
- */
- ASSERT(MAX_MEM_UNITS_PER_BOARD == 1);
-
- /*
- * calculate the maximum space that could be consumed,
- * then verify the available buffer space is adequate.
- */
- m = sizeof (drmach_mc_idle_script_t *) * 2; /* two MCs */
- b = sizeof (drmach_rename_script_t *) * 3 * MAX_CPU_UNITS_PER_BOARD;
- b += sizeof (drmach_rename_script_t *) * 3 * MAX_IO_UNITS_PER_BOARD;
- b *= MAX_BOARDS;
- b += sizeof (drmach_rename_script_t *) * 3;
- b += sizeof (drmach_rename_script_t *) * 1;
- ASSERT(m + b < buflen);
-#endif
-
- /*
- * construct an array of MC idle register addresses of
- * both MCs. The array is zero terminated -- as expected
- * by drmach_copy_rename_prog__relocatable().
- */
- isp = (drmach_mc_idle_script_t *)buf;
-
- /* source mc */
- err = drmach_get_mc_idle_addr(s_mem, &isp->idle_addr);
- if (err)
- return (err);
- isp->mem = s_mem;
- isp += 1;
-
- /* target mc */
- err = drmach_get_mc_idle_addr(t_mem, &isp->idle_addr);
- if (err)
- return (err);
- isp->mem = t_mem;
- isp += 1;
-
- /* terminator */
- isp->idle_addr = 0;
- isp->mem = NULL;
- isp += 1;
-
- /* fetch source mc asr register value */
- err = drmach_read_mc_asr(s_mem, &s_masr);
- if (err)
- return (err);
- else if (s_masr & STARFIRE_MC_INTERLEAVE_MASK) {
- return (drerr_new(1, ESTF_INTERBOARD, "%s::%s",
- s_mem->bp->cm.name, s_mem->cm.name));
- }
-
- /* fetch target mc asr register value */
- err = drmach_read_mc_asr(t_mem, &t_masr);
- if (err)
- return (err);
- else if (t_masr & STARFIRE_MC_INTERLEAVE_MASK) {
- return (drerr_new(1, ESTF_INTERBOARD, "%s::%s",
- t_mem->bp->cm.name, t_mem->cm.name));
- }
-
- /* get new source base pa from target's masr */
- s_new_basepa = mc_asr_to_pa(t_masr);
-
- /*
- * remove any existing slice offset to realign
- * memory with board's slice boundary
- */
- s_new_basepa &= ~ (mc_get_mem_alignment() - 1);
-
- /* get new target base pa from source's masr */
- t_new_basepa = mc_asr_to_pa(s_masr);
-
- /* remove any existing slice offset, then apply new offset */
- t_new_basepa &= ~ (mc_get_mem_alignment() - 1);
- t_new_basepa += t_slice_offset;
-
- /* encode new base pa into s_masr. turn off mem present bit */
- s_masr = mc_pa_to_asr(s_masr, s_new_basepa);
- s_masr &= ~STARFIRE_MC_MEM_PRESENT_MASK;
-
- /* encode new base pa into t_masr. turn on mem present bit */
- t_masr = mc_pa_to_asr(t_masr, t_new_basepa);
- t_masr |= STARFIRE_MC_MEM_PRESENT_MASK;
-
- /*
- * Step 0: Mark source memory as not present.
- */
- m = 0;
- rsp = (drmach_rename_script_t *)isp;
- err = drmach_get_mc_asr_addr(s_mem, &rsp[m].masr_addr);
- if (err)
- return (err);
- rsp[m].masr = s_masr;
- m++;
-
- /*
- * Step 1: Write source base address to target MC
- * with present bit off.
- */
- err = drmach_get_mc_asr_addr(t_mem, &rsp[m].masr_addr);
- if (err)
- return (err);
- rsp[m].masr = t_masr & ~STARFIRE_MC_MEM_PRESENT_MASK;
- m++;
-
- /*
- * Step 2: Now rewrite target reg with present bit on.
- */
- rsp[m].masr_addr = rsp[m-1].masr_addr;
- rsp[m].masr = t_masr;
- m++;
-
- s_bd = s_mem->bp->bnum;
- t_bd = t_mem->bp->bnum;
-
- DRMACH_PR("preparing script for CPU and IO units:\n");
-
- rv = drmach_array_first(drmach_boards, &b_idx, &b_id);
- if (rv) {
- /* catch this in debug kernels */
- ASSERT(0);
- return (DRMACH_INTERNAL_ERROR());
- }
-
- do {
- int d_idx;
- drmachid_t d_id;
- drmach_device_t *device;
-
- ASSERT(DRMACH_IS_BOARD_ID(b_id));
- brd = b_id;
- b = brd->bnum;
-
- /*
- * Step 3: Update PC MADR tables for CPUs.
- */
- if (brd->devices == NULL) {
- /* devices not initialized */
- continue;
- }
-
- rv = drmach_array_first(brd->devices, &d_idx, &d_id);
- if (rv) {
- /* must mean no devices on this board */
- break;
- }
-
- DRMACH_PR("\t%s\n", brd->cm.name);
-
- do {
- ASSERT(DRMACH_IS_DEVICE_ID(d_id));
-
- if (!DRMACH_IS_CPU_ID(d_id))
- continue;
-
- device = d_id;
- i = device->unum;
-
- DRMACH_PR("\t\t%s\n", device->cm.name);
-
- /*
- * Disabled detaching mem node.
- */
- rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, s_bd, i);
- rsp[m].masr = s_masr;
- m++;
- /*
- * Always write masr with present bit
- * off and then again with it on.
- */
- rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, t_bd, i);
- rsp[m].masr = t_masr & ~STARFIRE_MC_MEM_PRESENT_MASK;
- m++;
- rsp[m].masr_addr = rsp[m-1].masr_addr;
- rsp[m].masr = t_masr;
- m++;
-
- } while (drmach_array_next(brd->devices, &d_idx, &d_id) == 0);
-
- /*
- * Step 4: Update PC MADR tables for IOs.
- */
- rv = drmach_array_first(brd->devices, &d_idx, &d_id);
- /* this worked for previous loop, must work here too */
- ASSERT(rv == 0);
-
- do {
- ASSERT(DRMACH_IS_DEVICE_ID(d_id));
-
- if (!DRMACH_IS_IO_ID(d_id))
- continue;
-
- device = d_id;
- i = device->unum;
-
- DRMACH_PR("\t\t%s\n", device->cm.name);
-
- /*
- * Disabled detaching mem node.
- */
- rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, s_bd, i+4);
- rsp[m].masr = s_masr;
- m++;
- /*
- * Always write masr with present bit
- * off and then again with it on.
- */
- rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, t_bd, i+4);
- rsp[m].masr = t_masr & ~STARFIRE_MC_MEM_PRESENT_MASK;
- m++;
- rsp[m].masr_addr = rsp[m-1].masr_addr;
- rsp[m].masr = t_masr;
- m++;
-
- } while (drmach_array_next(brd->devices, &d_idx, &d_id) == 0);
- } while (drmach_array_next(drmach_boards, &b_idx, &b_id) == 0);
-
- /*
- * Zero masr_addr value indicates the END.
- */
- rsp[m].masr_addr = 0ull;
- rsp[m].masr = 0;
- DRMACH_PR("number of steps in rename script = %d\n", m);
- m++;
-
- /* paranoia */
- ASSERT((caddr_t)&rsp[m] <= buf + buflen);
-
-#ifdef DEBUG
- {
- int j;
-
- DRMACH_PR("mc idle register address list:");
- isp = (drmach_mc_idle_script_t *)buf;
- DRMACH_PR("source mc idle addr 0x%lx, mem id %p",
- isp[0].idle_addr, (void *)isp[0].mem);
- DRMACH_PR("target mc idle addr 0x%lx, mem id %p",
- isp[1].idle_addr, (void *)isp[1].mem);
- ASSERT(isp[2].idle_addr == 0);
-
- DRMACH_PR("copy-rename script:");
- for (j = 0; j < m; j++) {
- DRMACH_PR("0x%lx = 0x%08x",
- rsp[j].masr_addr, rsp[j].masr);
- }
-
- DELAY(1000000);
- }
-#endif
-
- /* return number of bytes consumed */
- b = (caddr_t)&rsp[m] - buf;
- DRMACH_PR("total number of bytes consumed is %d\n", b);
- ASSERT(b <= buflen);
-
-#ifdef lint
- buflen = buflen;
-#endif
-
- return (NULL);
-}
-
-/*
- * The routine performs the necessary memory COPY and MC adr SWITCH.
- * Both operations MUST be at the same "level" so that the stack is
- * maintained correctly between the copy and switch. The switch
- * portion implements a caching mechanism to guarantee the code text
- * is cached prior to execution. This is to guard against possible
- * memory access while the MC adr's are being modified.
- *
- * IMPORTANT: The _drmach_copy_rename_end() function must immediately
- * follow drmach_copy_rename_prog__relocatable() so that the correct
- * "length" of the drmach_copy_rename_prog__relocatable can be
- * calculated. This routine MUST be a LEAF function, i.e. it can
- * make NO function calls, primarily for two reasons:
- *
- * 1. We must keep the stack consistent across the "switch".
- * 2. Function calls are compiled to relative offsets, and
- * we execute this function we'll be executing it from
- * a copied version in a different area of memory, thus
- * the relative offsets will be bogus.
- *
- * Moreover, it must have the "__relocatable" suffix to inform DTrace
- * providers (and anything else, for that matter) that this
- * function's text is manually relocated elsewhere before it is
- * executed. That is, it cannot be safely instrumented with any
- * methodology that is PC-relative.
- */
-static void
-drmach_copy_rename_prog__relocatable(drmach_copy_rename_program_t *prog)
-{
- extern void drmach_exec_script_il(drmach_rename_script_t *rsp);
-
- drmach_mc_idle_script_t *isp;
- struct memlist *ml;
- int csize;
- int lnsize;
- uint64_t caddr;
-
- isp = (drmach_mc_idle_script_t *)prog->data;
-
- caddr = ecache_flushaddr;
- csize = (cpunodes[CPU->cpu_id].ecache_size << 1);
- lnsize = cpunodes[CPU->cpu_id].ecache_linesize;
-
- /*
- * DO COPY.
- */
- for (ml = prog->c_ml; ml; ml = ml->ml_next) {
- uint64_t s_pa, t_pa;
- uint64_t nbytes;
-
- s_pa = prog->s_copybasepa + ml->ml_address;
- t_pa = prog->t_copybasepa + ml->ml_address;
- nbytes = ml->ml_size;
-
- while (nbytes != 0ull) {
- /*
- * This copy does NOT use an ASI
- * that avoids the Ecache, therefore
- * the dst_pa addresses may remain
- * in our Ecache after the dst_pa
- * has been removed from the system.
- * A subsequent write-back to memory
- * will cause an ARB-stop because the
- * physical address no longer exists
- * in the system. Therefore we must
- * flush out local Ecache after we
- * finish the copy.
- */
-
- /* copy 32 bytes at src_pa to dst_pa */
- bcopy32_il(s_pa, t_pa);
-
- /* increment by 32 bytes */
- s_pa += (4 * sizeof (uint64_t));
- t_pa += (4 * sizeof (uint64_t));
-
- /* decrement by 32 bytes */
- nbytes -= (4 * sizeof (uint64_t));
- }
- }
-
- /*
- * Since bcopy32_il() does NOT use an ASI to bypass
- * the Ecache, we need to flush our Ecache after
- * the copy is complete.
- */
- flush_ecache_il(caddr, csize, lnsize); /* inline version */
-
- /*
- * Wait for MCs to go idle.
- */
- do {
- register int t = 10;
- register uint_t v;
-
- /* loop t cycles waiting for each mc to indicate it's idle */
- do {
- v = ldphysio_il(isp->idle_addr)
- & STARFIRE_MC_IDLE_MASK;
-
- } while (v != STARFIRE_MC_IDLE_MASK && t-- > 0);
-
- /* bailout if timedout */
- if (t <= 0) {
- prog->restless_mc = isp->mem;
- return;
- }
-
- isp += 1;
-
- /* stop if terminating zero has been reached */
- } while (isp->idle_addr != 0);
-
- /* advance passed terminating zero */
- isp += 1;
-
- /*
- * The following inline assembly routine caches
- * the rename script and then caches the code that
- * will do the rename. This is necessary
- * so that we don't have any memory references during
- * the reprogramming. We accomplish this by first
- * jumping through the code to guarantee it's cached
- * before we actually execute it.
- */
- drmach_exec_script_il((drmach_rename_script_t *)isp);
-}
-
-static void
-drmach_copy_rename_end(void)
-{
- /*
- * IMPORTANT: This function's location MUST be located immediately
- * following drmach_copy_rename_prog__relocatable to
- * accurately estimate its size. Note that this assumes
- * the compiler keeps these functions in the order in
- * which they appear :-o
- */
-}
-
-sbd_error_t *
-drmach_copy_rename_init(drmachid_t t_id, uint64_t t_slice_offset,
- drmachid_t s_id, struct memlist *c_ml, drmachid_t *pgm_id)
-{
- drmach_device_t *s_mem;
- drmach_device_t *t_mem;
- struct memlist *x_ml;
- uint64_t off_mask, s_copybasepa, t_copybasepa, t_basepa;
- int len;
- caddr_t bp, wp;
- pda_handle_t ph;
- sbd_error_t *err;
- drmach_copy_rename_program_t *prog;
-
- if (!DRMACH_IS_MEM_ID(s_id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- if (!DRMACH_IS_MEM_ID(t_id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- s_mem = s_id;
- t_mem = t_id;
-
- /* get starting physical address of target memory */
- err = drmach_mem_get_base_physaddr(t_id, &t_basepa);
- if (err)
- return (err);
-
- /* calculate slice offset mask from slice size */
- off_mask = mc_get_mem_alignment() - 1;
-
- /* calculate source and target base pa */
- s_copybasepa = c_ml->ml_address;
- t_copybasepa =
- t_basepa + ((c_ml->ml_address & off_mask) - t_slice_offset);
-
- /* paranoia */
- ASSERT((c_ml->ml_address & off_mask) >= t_slice_offset);
-
- /* adjust copy memlist addresses to be relative to copy base pa */
- x_ml = c_ml;
- while (x_ml != NULL) {
- x_ml->ml_address -= s_copybasepa;
- x_ml = x_ml->ml_next;
- }
-
-#ifdef DEBUG
- {
- uint64_t s_basepa, s_size, t_size;
-
- x_ml = c_ml;
- while (x_ml->ml_next != NULL)
- x_ml = x_ml->ml_next;
-
- DRMACH_PR("source copy span: base pa 0x%lx, end pa 0x%lx\n",
- s_copybasepa,
- s_copybasepa + x_ml->ml_address + x_ml->ml_size);
-
- DRMACH_PR("target copy span: base pa 0x%lx, end pa 0x%lx\n",
- t_copybasepa,
- t_copybasepa + x_ml->ml_address + x_ml->ml_size);
-
- DRMACH_PR("copy memlist (relative to copy base pa):\n");
- MEMLIST_DUMP(c_ml);
-
- err = drmach_mem_get_base_physaddr(s_id, &s_basepa);
- ASSERT(err == NULL);
-
- err = drmach_mem_get_size(s_id, &s_size);
- ASSERT(err == NULL);
-
- err = drmach_mem_get_size(t_id, &t_size);
- ASSERT(err == NULL);
-
- DRMACH_PR("current source base pa 0x%lx, size 0x%lx\n",
- s_basepa, s_size);
- DRMACH_PR("current target base pa 0x%lx, size 0x%lx\n",
- t_basepa, t_size);
-
- ASSERT(s_copybasepa + x_ml->ml_address + x_ml->ml_size <=
- s_basepa + s_size);
- ASSERT(t_copybasepa + x_ml->ml_address + x_ml->ml_size <=
- t_basepa + t_size);
- }
-#endif
-
- ph = drmach_pda_open();
- if (ph == NULL)
- return (DRMACH_INTERNAL_ERROR());
-
- /*
- * bp will be page aligned, since we're calling
- * kmem_zalloc() with an exact multiple of PAGESIZE.
- */
- wp = bp = kmem_zalloc(PAGESIZE, KM_SLEEP);
-
- /* allocate space for copy rename struct */
- len = sizeof (drmach_copy_rename_program_t);
- DRMACH_PR("prog = 0x%p, header len %d\n", (void *)wp, len);
- prog = (drmach_copy_rename_program_t *)wp;
- wp += (len + ecache_alignsize - 1) & ~ (ecache_alignsize - 1);
-
- /*
- * Copy the code for the copy-rename routine into
- * a page aligned piece of memory. We do this to guarantee
- * that we're executing within the same page and thus reduce
- * the possibility of cache collisions between different
- * pages.
- */
- len = (int)((ulong_t)drmach_copy_rename_end -
- (ulong_t)drmach_copy_rename_prog__relocatable);
- ASSERT(wp + len < bp + PAGESIZE);
- bcopy((caddr_t)drmach_copy_rename_prog__relocatable, wp, len);
-
- DRMACH_PR("copy-rename function 0x%p, len %d\n", (void *)wp, len);
- prog->run = (void (*)())wp;
- wp += (len + ecache_alignsize - 1) & ~ (ecache_alignsize - 1);
-
- /*
- * Prepare data page that will contain script of
- * operations to perform during copy-rename.
- * Allocate temporary buffer to hold script.
- */
- err = drmach_prep_rename_script(s_mem, t_mem, t_slice_offset,
- wp, PAGESIZE - (wp - bp));
- if (err) {
- (void) drmach_copy_rename_fini(prog);
- return (err);
- }
-
- DRMACH_PR("copy-rename script 0x%p, len %d\n", (void *)wp, len);
- prog->data = wp;
- wp += (len + ecache_alignsize - 1) & ~ (ecache_alignsize - 1);
-
- prog->ph = ph;
- prog->s_copybasepa = s_copybasepa;
- prog->t_copybasepa = t_copybasepa;
- prog->c_ml = c_ml;
- *pgm_id = prog;
-
- return (NULL);
-}
-
-sbd_error_t *
-drmach_copy_rename_fini(drmachid_t id)
-{
- drmach_copy_rename_program_t *prog = id;
- sbd_error_t *err = NULL;
-
- if (prog->c_ml != NULL)
- memlist_delete(prog->c_ml);
-
- if (prog->ph != NULL)
- pda_close(prog->ph);
-
- if (prog->restless_mc != 0) {
- cmn_err(CE_WARN, "MC did not idle; OBP Node 0x%x",
- (uint_t)drmach_node_get_dnode(prog->restless_mc->node));
-
- err = DRMACH_INTERNAL_ERROR();
- }
-
- kmem_free(prog, PAGESIZE);
-
- return (err);
-}
-
-static sbd_error_t *
-drmach_io_new(drmach_device_t *dp)
-{
- sbd_error_t *err;
- int portid;
-
- err = drmach_device_get_prop(dp, "upa-portid", &portid);
- if (err == NULL) {
- ASSERT(portid & 0x40);
- dp->unum = portid & 1;
- }
-
- dp->cm.isa = (void *)drmach_io_new;
- dp->cm.release = drmach_io_release;
- dp->cm.status = drmach_io_status;
-
- (void) snprintf(dp->cm.name, sizeof (dp->cm.name), "%s%d", dp->type,
- dp->unum);
-
- return (err);
-}
-
-static void
-drmach_iopc_op(pda_handle_t ph, drmach_iopc_op_t op)
-{
- register int b;
-
- for (b = 0; b < MAX_BOARDS; b++) {
- int p;
- ushort_t bda_ioc;
- board_desc_t *bdesc;
-
- if (pda_board_present(ph, b) == 0)
- continue;
-
- bdesc = (board_desc_t *)pda_get_board_info(ph, b);
- /*
- * Update PCs for IOCs.
- */
- bda_ioc = bdesc->bda_ioc;
- for (p = 0; p < MAX_IOCS; p++) {
- u_longlong_t idle_addr;
- uchar_t value;
-
- if (BDA_NBL(bda_ioc, p) != BDAN_GOOD)
- continue;
-
- idle_addr = STARFIRE_BB_PC_ADDR(b, p, 1);
-
- switch (op) {
- case DO_PAUSE:
- value = STARFIRE_BB_PC_PAUSE(p);
- break;
-
- case DO_IDLE:
- value = STARFIRE_BB_PC_IDLE(p);
- break;
-
- case DO_UNPAUSE:
- value = ldbphysio(idle_addr);
- value &= ~STARFIRE_BB_PC_PAUSE(p);
- break;
-
- case DO_UNIDLE:
- value = ldbphysio(idle_addr);
- value &= ~STARFIRE_BB_PC_IDLE(p);
- break;
-
- default:
- cmn_err(CE_PANIC,
- "drmach_iopc_op: unknown op (%d)",
- (int)op);
- /*NOTREACHED*/
- }
- stbphysio(idle_addr, value);
- }
- }
-}
-
-void
-drmach_copy_rename(drmachid_t id)
-{
- drmach_copy_rename_program_t *prog = id;
- uint64_t neer;
-
- /*
- * UPA IDLE
- * Protocol = PAUSE -> IDLE -> UNPAUSE
- * In reality since we only "idle" the IOPCs it's sufficient
- * to just issue the IDLE operation since (in theory) all IOPCs
- * in the field are PC6. However, we'll be robust and do the
- * proper workaround protocol so that we never have to worry!
- */
- drmach_iopc_op(prog->ph, DO_PAUSE);
- drmach_iopc_op(prog->ph, DO_IDLE);
- DELAY(100);
- drmach_iopc_op(prog->ph, DO_UNPAUSE);
- DELAY(100);
-
- /* disable CE reporting */
- neer = get_error_enable();
- set_error_enable(neer & ~EER_CEEN);
-
- /* run the copy/rename program */
- prog->run(prog);
-
- /* enable CE reporting */
- set_error_enable(neer);
-
- /*
- * UPA UNIDLE
- * Protocol = UNIDLE
- */
- drmach_iopc_op(prog->ph, DO_UNIDLE);
- DELAY(100);
-}
-
-/*
- * The counter-timer and perf-counter nodes are not being cleaned
- * up after a board that was present at start of day is detached.
- * If the board has become unconfigured with this operation, walk
- * the prom tree and find all counter-timer and perf-counter nodes
- * that have the same board number as the board that was just
- * unconfigured and remove them.
- */
-static sbd_error_t *
-drmach_remove_counter_nodes(drmachid_t id)
-{
- int num;
- char name[OBP_MAXDRVNAME];
- pnode_t child;
- dev_info_t *dip;
- sbd_error_t *err;
- drmach_status_t stat;
- drmach_board_t *bp;
-
- if (!DRMACH_IS_BOARD_ID(id)) {
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- }
-
- if ((err = drmach_board_status(id, &stat)) != NULL) {
- return (err);
- }
-
- /*
- * Only clean up the counter-timer and perf-counter
- * nodes when the entire board is unconfigured.
- */
- if (stat.configured) {
- return (NULL);
- }
-
- bp = (drmach_board_t *)id;
-
- err = NULL;
-
- for (child = prom_childnode(prom_rootnode()); child != OBP_NONODE;
- child = prom_nextnode(child)) {
-
- if (prom_getprop(child, OBP_BOARDNUM, (caddr_t)&num) == -1) {
- continue;
- }
-
- if (bp->bnum != num) {
- continue;
- }
-
- if (prom_getprop(child, OBP_NAME, (caddr_t)name) == -1) {
- continue;
- }
-
- if (strncmp(name, MISC_COUNTER_TIMER_DEVNAME, OBP_MAXDRVNAME) &&
- strncmp(name, MISC_PERF_COUNTER_DEVNAME, OBP_MAXDRVNAME)) {
- continue;
- }
-
- /* Root node doesn't have to be held */
- dip = e_ddi_nodeid_to_dip(child);
-
- /*
- * If the node is only in the OBP tree, then
- * we don't have to remove it.
- */
- if (dip) {
- dev_info_t *fdip = NULL;
-
- DRMACH_PR("removing %s devinfo node\n", name);
-
- e_ddi_branch_hold(dip);
- ddi_release_devi(dip); /* held in e_ddi_nodeid_to_dip */
-
- if (e_ddi_branch_destroy(dip, &fdip, 0)) {
- char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-
- /*
- * If non-NULL, fdip is held and must be
- * released.
- */
- if (fdip != NULL) {
- (void) ddi_pathname(fdip, path);
- ddi_release_devi(fdip);
- } else {
- (void) ddi_pathname(dip, path);
- }
-
- err = drerr_new(1, ESTF_DRVFAIL, path);
- kmem_free(path, MAXPATHLEN);
- e_ddi_branch_rele(dip);
- break;
- }
- }
- }
-
- return (err);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_pre_op(int cmd, drmachid_t id, drmach_opts_t *opts)
-{
- /* allow status and ncm operations to always succeed */
- if ((cmd == SBD_CMD_STATUS) || (cmd == SBD_CMD_GETNCM)) {
- return (NULL);
- }
-
- /* check all other commands for the required option string */
- if ((opts->size > 0) && (opts->copts != NULL)) {
-
- DRMACH_PR("platform options: %s\n", opts->copts);
-
- if (strstr(opts->copts, "xfdr") != NULL) {
- return (NULL);
- }
- }
-
- return (drerr_new(0, ESTF_SUPPORT, NULL));
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_post_op(int cmd, drmachid_t id, drmach_opts_t *opts)
-{
- sbd_error_t *err = NULL;
-
- switch (cmd) {
- case SBD_CMD_UNCONFIGURE:
-
- err = drmach_remove_counter_nodes(id);
- break;
-
- case SBD_CMD_CONFIGURE:
- case SBD_CMD_DISCONNECT:
- case SBD_CMD_CONNECT:
- case SBD_CMD_GETNCM:
- case SBD_CMD_STATUS:
- break;
-
- default:
- break;
- }
-
- return (err);
-}
-
-sbd_error_t *
-drmach_board_assign(int bnum, drmachid_t *id)
-{
- sbd_error_t *err;
-
- if (!drmach_initialized && drmach_init() == -1) {
- err = DRMACH_INTERNAL_ERROR();
- } else if (drmach_array_get(drmach_boards, bnum, id) == -1) {
- err = drerr_new(1, ESTF_BNUM, "%d", bnum);
- } else if (*id != NULL) {
- err = NULL;
- } else {
- drmach_board_t *bp;
-
- *id = (drmachid_t)drmach_board_new(bnum);
- bp = *id;
- bp->assigned = 1;
- err = NULL;
- }
-
- return (err);
-}
-
-static int
-drmach_attach_board(void *arg)
-{
- drmach_board_t *obj = (drmach_board_t *)arg;
- cpuset_t cset;
- int retval;
-
- /*
- * OBP disables traps during the board probe.
- * So, in order to prevent cross-call/cross-trap timeouts,
- * and thus panics, we effectively block anybody from
- * issuing xc's/xt's by doing a promsafe_xc_attention.
- * In the previous version of Starfire DR (2.6), a timeout
- * suspension mechanism was implemented in the send-mondo
- * assembly. That mechanism is unnecessary with the
- * existence of xc_attention/xc_dismissed.
- */
- cset = cpu_ready_set;
- promsafe_xc_attention(cset);
-
- retval = prom_starfire_add_brd(obj->connect_cpuid);
-
- xc_dismissed(cset);
-
- return (retval);
-}
-
-sbd_error_t *
-drmach_board_connect(drmachid_t id, drmach_opts_t *opts)
-{
- drmach_board_t *obj = (drmach_board_t *)id;
- int retval;
- sbd_error_t *err;
- char *cptr, *copts;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
-
- if (opts->size > 0)
- copts = opts->copts;
-
- if ((cptr = strstr(copts, "cpuid=")) != NULL) {
- int cpuid;
-
- cptr += strlen("cpuid=");
- cpuid = stoi(&cptr);
-
- if (DRMACH_CPUID2BNUM(cpuid) == obj->bnum) {
- obj->connect_cpuid = cpuid;
- obj->assigned = 1;
- } else
- return (drerr_new(1, ESTF_SETCPUVAL, "%d", cpuid));
- } else {
- /* cpuid was not specified */
- obj->connect_cpuid = -1;
- }
-
- if (obj->connect_cpuid == -1) {
- err = drerr_new(1, ESTF_NOCPUID, obj->cm.name);
- return (err);
- }
-
- cmn_err(CE_CONT, "DRMACH: PROM attach %s CPU %d\n",
- obj->cm.name, obj->connect_cpuid);
-
- retval = prom_tree_update(drmach_attach_board, obj);
-
- if (retval == 0)
- err = NULL;
- else {
- cmn_err(CE_WARN, "prom error: prom_starfire_add_brd(%d) "
- "returned %d", obj->connect_cpuid, retval);
-
- err = drerr_new(1, ESTF_PROBE, obj->cm.name);
- }
-
- obj->connect_cpuid = -1;
-
- return (err);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_board_disconnect(drmachid_t id, drmach_opts_t *opts)
-{
- drmach_board_t *bp;
- int rv;
- int d_idx; /* device index */
- drmachid_t d_id; /* device ID */
- sbd_error_t *err;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
-
- bp = id;
-
- /*
- * We need to make sure all of the board's device nodes
- * have been removed from the Solaris device tree before
- * continuing with the disconnect. Otherwise, we could
- * disconnect the board and remove the OBP device tree
- * nodes with Solaris device tree nodes remaining.
- *
- * On Starfire, Solaris device tree nodes are deleted
- * during unconfigure by drmach_unconfigure(). It's
- * necessary to do this here because drmach_unconfigure()
- * failures are not handled during unconfigure.
- */
- if (bp->devices) {
- rv = drmach_array_first(bp->devices, &d_idx, &d_id);
- while (rv == 0) {
- err = drmach_unconfigure(d_id, DRMACH_DEVI_REMOVE);
- if (err)
- return (err);
-
- rv = drmach_array_next(bp->devices, &d_idx, &d_id);
- }
- }
-
- /*
- * Starfire board Solaris device tree counter nodes,
- * which are only present on start-of-day boards, are
- * removed in the dr_post_op() code flow after the
- * board is unconfigured. We call the counter node
- * removal function here because unconfigure errors
- * can cause the dr_post_op() function to be skipped
- * after an unconfigure operation even though all of
- * the board's devices have been transitioned to the
- * unconfigured state.
- */
- err = drmach_remove_counter_nodes(id);
- if (err)
- return (err);
-
- return (NULL);
-}
-
-static int
-drmach_board_find_devices_cb(drmach_node_walk_args_t *args)
-{
- drmach_node_t *node = args->node;
- drmach_board_cb_data_t *data = args->data;
- drmach_board_t *obj = data->obj;
-
- int rv;
- int bnum;
- drmach_device_t *device;
-
- rv = drmach_node_get_prop(node, OBP_BOARDNUM, &bnum);
- if (rv) {
- /*
- * if the node does not have a board# property, then
- * by that information alone it is known that drmach
- * is not interested in it.
- */
- return (0);
- } else if (bnum != obj->bnum)
- return (0);
-
- /*
- * Create a device data structure from this node data.
- * The call may yield nothing if the node is not of interest
- * to drmach.
- */
- data->err = drmach_device_new(node, obj, &device);
- if (data->err)
- return (-1);
- else if (device == NULL) {
- /*
- * drmach_device_new examined the node we passed in
- * and determined that it was one not of interest to
- * drmach. So, it is skipped.
- */
- return (0);
- }
-
- rv = drmach_array_set(obj->devices, data->ndevs++, device);
- if (rv) {
- drmach_device_dispose(device);
- data->err = DRMACH_INTERNAL_ERROR();
- return (-1);
- }
-
- data->err = (*data->found)(data->a, device->type, device->unum, device);
- return (data->err == NULL ? 0 : -1);
-}
-
-sbd_error_t *
-drmach_board_find_devices(drmachid_t id, void *a,
- sbd_error_t *(*found)(void *a, const char *, int, drmachid_t))
-{
- extern int plat_max_cpu_units_per_board();
- extern int plat_max_mem_units_per_board();
- extern int plat_max_io_units_per_board();
-
- drmach_board_t *obj = (drmach_board_t *)id;
- sbd_error_t *err;
- int max_devices;
- int rv;
- drmach_board_cb_data_t data;
-
- max_devices = plat_max_cpu_units_per_board();
- max_devices += plat_max_mem_units_per_board();
- max_devices += plat_max_io_units_per_board();
-
- obj->devices = drmach_array_new(0, max_devices);
-
- data.obj = obj;
- data.ndevs = 0;
- data.found = found;
- data.a = a;
- data.err = NULL;
-
- rv = drmach_node_walk(obj->tree, &data, drmach_board_find_devices_cb);
- if (rv == 0)
- err = NULL;
- else {
- drmach_array_dispose(obj->devices, drmach_device_dispose);
- obj->devices = NULL;
-
- if (data.err)
- err = data.err;
- else
- err = DRMACH_INTERNAL_ERROR();
- }
-
- return (err);
-}
-
-int
-drmach_board_lookup(int bnum, drmachid_t *id)
-{
- int rv = 0;
-
- if (!drmach_initialized && drmach_init() == -1) {
- *id = 0;
- rv = -1;
- } else if (drmach_array_get(drmach_boards, bnum, id)) {
- *id = 0;
- rv = -1;
- }
- return (rv);
-}
-
-sbd_error_t *
-drmach_board_name(int bnum, char *buf, int buflen)
-{
- (void) snprintf(buf, buflen, "SB%d", bnum);
- return (NULL);
-}
-
-sbd_error_t *
-drmach_board_poweroff(drmachid_t id)
-{
- drmach_board_t *bp;
- sbd_error_t *err;
- drmach_status_t stat;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- bp = id;
-
- err = drmach_board_status(id, &stat);
- if (err)
- return (err);
- else if (stat.configured || stat.busy)
- return (drerr_new(0, ESTF_CONFIGBUSY, bp->cm.name));
- else {
- /* board power off is essentially a noop for Starfire */
- bp->powered = 0;
- return (NULL);
- }
- /*NOTREACHED*/
-}
-
-sbd_error_t *
-drmach_board_poweron(drmachid_t id)
-{
- drmach_board_t *bp;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- bp = id;
-
- /* board power on is essentially a noop for Starfire */
- bp->powered = 1;
-
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_board_release(drmachid_t id)
-{
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- return (NULL);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_board_test(drmachid_t id, drmach_opts_t *opts, int force)
-{
- return (NULL);
-}
-
-sbd_error_t *
-drmach_board_unassign(drmachid_t id)
-{
- drmach_board_t *bp;
- sbd_error_t *err;
- drmach_status_t stat;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- bp = id;
-
- err = drmach_board_status(id, &stat);
- if (err)
- return (err);
- else if (stat.configured || stat.busy)
- return (drerr_new(0, ESTF_CONFIGBUSY, bp->cm.name));
- else if (drmach_array_set(drmach_boards, bp->bnum, 0) != 0)
- return (DRMACH_INTERNAL_ERROR());
- else {
- drmach_board_dispose(bp);
- return (NULL);
- }
- /*NOTREACHED*/
-}
-
-static sbd_error_t *
-drmach_cpu_new(drmach_device_t *dp)
-{
- sbd_error_t *err;
- int portid;
-
- err = drmach_device_get_prop(dp, "upa-portid", &portid);
- if (err == NULL)
- dp->unum = portid & 3;
-
- dp->cm.isa = (void *)drmach_cpu_new;
- dp->cm.release = drmach_cpu_release;
- dp->cm.status = drmach_cpu_status;
-
- (void) snprintf(dp->cm.name, sizeof (dp->cm.name), "%s%d", dp->type,
- dp->unum);
-
- return (err);
-}
-
-/*
- * drmach_cpu_obp_detach()
- * This requires two steps, first, we must put the cpuid into the OBP
- * idle loop (Idle in Program) state. Then we call OBP to place the CPU
- * into the "Detached" state, which does any special processing to
- * actually detach the cpu, such as flushing ecache, and also ensures
- * that a subsequent breakpoint won't restart the cpu (if it was just in
- * Idle in Program state).
- */
-static void
-drmach_cpu_obp_detach(int cpuid)
-{
- /*
- * Cpu may not be under OBP's control. Eg, if cpu exited to download
- * helper on a prior attach.
- */
- if (CPU_SGN_EXISTS(cpuid) &&
- !SGN_CPU_IS_OS(cpuid) &&
- !SGN_CPU_IS_OBP(cpuid)) {
- cmn_err(CE_WARN,
- "unexpected signature (0x%x) for cpu %d",
- get_cpu_sgn(cpuid), cpuid);
- }
-
- /*
- * Now we place the CPU into the "Detached" idle loop in OBP.
- * This is so that the CPU won't be restarted if we break into
- * OBP with a breakpoint or BREAK key from the console, and also
- * if we need to do any special processing, such as flushing the
- * cpu's ecache, disabling interrupts (by turning of the ET bit in
- * the PSR) and/or spinning in BBSRAM rather than global memory.
- */
- DRMACH_PR("prom_starfire_rm_cpu(%d)\n", cpuid);
- prom_starfire_rm_cpu(cpuid);
-}
-
-/*
- * drmach_cpu_obp_is_detached() returns TRUE if the cpu sigblock signature state
- * is SIGBST_DETACHED; otherwise it returns FALSE. This routine should only
- * be called after we have asked OBP to detach the CPU. It should NOT be
- * called as a check during any other flow.
- */
-static int
-drmach_cpu_obp_is_detached(int cpuid)
-{
- if (!CPU_SGN_EXISTS(cpuid) ||
- (SGN_CPU_IS_OS(cpuid) && SGN_CPU_STATE_IS_DETACHED(cpuid)))
- return (1);
- else
- return (0);
-}
-
-static int
-drmach_cpu_start(struct cpu *cp)
-{
- int cpuid = cp->cpu_id;
- int ntries = drmach_cpu_ntries;
- extern void restart_other_cpu(int);
-
- ASSERT(MUTEX_HELD(&cpu_lock));
- ASSERT(cpunodes[cpuid].nodeid != (pnode_t)0);
-
- cp->cpu_flags &= ~CPU_POWEROFF;
-
- /*
- * NOTE: restart_other_cpu pauses cpus during the
- * slave cpu start. This helps to quiesce the
- * bus traffic a bit which makes the tick sync
- * routine in the prom more robust.
- */
- DRMACH_PR("COLD START for cpu (%d)\n", cpuid);
-
- prom_starfire_add_cpu(cpuid);
-
- restart_other_cpu(cpuid);
-
- /*
- * Wait for the cpu to reach its idle thread before
- * we zap it with a request to blow away the mappings
- * it (might) have for the drmach_shutdown_asm code
- * it may have executed on unconfigure.
- */
- while ((cp->cpu_thread != cp->cpu_idle_thread) && (ntries > 0)) {
- DELAY(drmach_cpu_delay);
- ntries--;
- }
-
- DRMACH_PR("waited %d out of %d loops for cpu %d\n",
- drmach_cpu_ntries - ntries, drmach_cpu_ntries, cpuid);
-
- xt_one(cpuid, vtag_flushpage_tl1,
- (uint64_t)drmach_shutdown_va, (uint64_t)ksfmmup);
-
- return (0);
-}
-
-/*
- * A detaching CPU is xcalled with an xtrap to drmach_cpu_stop_self() after
- * it has been offlined. The function of this routine is to get the cpu
- * spinning in a safe place. The requirement is that the system will not
- * reference anything on the detaching board (memory and i/o is detached
- * elsewhere) and that the CPU not reference anything on any other board
- * in the system. This isolation is required during and after the writes
- * to the domain masks to remove the board from the domain.
- *
- * To accomplish this isolation the following is done:
- * 1) Create a locked mapping to a location in BBSRAM where
- * the cpu will execute.
- * 2) Copy the target function (drmach_shutdown_asm) in which
- * the cpu will execute into BBSRAM.
- * 3) Jump into function with BBSRAM.
- * Function will:
- * 3.1) Flush its Ecache (displacement).
- * 3.2) Flush its Dcache with HW mechanism.
- * 3.3) Flush its Icache with HW mechanism.
- * 3.4) Flush all valid and _unlocked_ D-TLB entries.
- * 3.5) Flush all valid and _unlocked_ I-TLB entries.
- * 3.6) Clear xt_mb to signal completion. Note: cache line is
- * recovered by drmach_cpu_poweroff().
- * 4) Jump into a tight loop.
- */
-#define DRMACH_BBSRAM_OFFSET 0x1000
-
-static void
-drmach_cpu_stop_self(void)
-{
- int cpuid = (int)CPU->cpu_id;
- tte_t tte;
- volatile uint_t *src, *dst;
- size_t funclen;
- uint64_t bbsram_pa, bbsram_offset;
- uint_t bbsram_pfn;
- uint64_t bbsram_addr;
- void (*bbsram_func)(uint64_t);
- extern void drmach_shutdown_asm(uint64_t);
- extern void drmach_shutdown_asm_end(void);
-
- funclen = (uintptr_t)drmach_shutdown_asm_end -
- (uintptr_t)drmach_shutdown_asm;
- ASSERT(funclen <= MMU_PAGESIZE);
- /*
- * We'll start from the 0th's base.
- */
- bbsram_pa = STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE;
- bbsram_offset = bbsram_pa | 0xfe0ULL;
- bbsram_pa += ldphysio(bbsram_offset) + DRMACH_BBSRAM_OFFSET;
-
- bbsram_pfn = (uint_t)(bbsram_pa >> MMU_PAGESHIFT);
-
- bbsram_addr = (uint64_t)drmach_shutdown_va;
- drmach_shutdown_asm_mbox->estack = bbsram_addr + funclen;
-
- tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) |
- TTE_PFN_INTHI(bbsram_pfn);
- tte.tte_intlo = TTE_PFN_INTLO(bbsram_pfn) |
- TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT;
- sfmmu_dtlb_ld_kva(drmach_shutdown_va, &tte); /* load dtlb */
- sfmmu_itlb_ld_kva(drmach_shutdown_va, &tte); /* load itlb */
-
- for (src = (uint_t *)drmach_shutdown_asm, dst = (uint_t *)bbsram_addr;
- src < (uint_t *)drmach_shutdown_asm_end; src++, dst++)
- *dst = *src;
-
- bbsram_func = (void (*)())bbsram_addr;
- drmach_shutdown_asm_mbox->flushaddr = ecache_flushaddr;
- drmach_shutdown_asm_mbox->size = (cpunodes[cpuid].ecache_size << 1);
- drmach_shutdown_asm_mbox->linesize = cpunodes[cpuid].ecache_linesize;
- drmach_shutdown_asm_mbox->physaddr =
- va_to_pa((void *)&drmach_xt_mb[cpuid]);
-
- /*
- * Signal to drmach_cpu_poweroff() is via drmach_xt_mb cleared
- * by asm code
- */
-
- (*bbsram_func)(va_to_pa((void *)drmach_shutdown_asm_mbox));
-}
-
-static void
-drmach_cpu_shutdown_self(void)
-{
- cpu_t *cp = CPU;
- int cpuid = cp->cpu_id;
- extern void flush_windows(void);
-
- flush_windows();
-
- (void) spl8();
-
- ASSERT(cp->cpu_intr_actv == 0);
- ASSERT(cp->cpu_thread == cp->cpu_idle_thread ||
- cp->cpu_thread == cp->cpu_startup_thread);
-
- cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF;
-
- drmach_cpu_stop_self();
-
- cmn_err(CE_PANIC, "CPU %d FAILED TO SHUTDOWN", cpuid);
-}
-
-/* a helper routine to keep the math in one place */
-static processorid_t
-drmach_cpu_calc_id(drmach_device_t *dp)
-{
- return (dp->bp->bnum * MAX_CPU_UNITS_PER_BOARD + dp->unum);
-}
-
-/*
- * Move bootproc (SIGBCPU) to another cpu. If dst_cpu is NULL, a
- * destination cpu is chosen from the set of cpus not located on the
- * same board as the current bootproc cpu.
- */
-static sbd_error_t *
-drmach_cpu_juggle_bootproc(drmach_device_t *dst_cpu)
-{
- processorid_t cpuid;
- struct cpu *cp;
- sbd_error_t *err;
- int rv;
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- /* dst_cpu is NULL when target cpu is unspecified. So, pick one. */
- if (dst_cpu == NULL) {
- int avoid_board = DRMACH_CPUID2BNUM(SIGBCPU->cpu_id);
- int max_cpuid = MAX_BOARDS * MAX_CPU_UNITS_PER_BOARD;
-
- for (cpuid = 0; cpuid < max_cpuid; cpuid++)
- if (DRMACH_CPUID2BNUM(cpuid) != avoid_board) {
- cp = cpu_get(cpuid);
- if (cp != NULL && cpu_is_online(cp))
- break;
- }
-
- if (cpuid == max_cpuid) {
- err = drerr_new(1, ESTF_JUGGLE, NULL);
- return (err);
- }
-
- /* else, cp points to the selected target cpu */
- } else {
- cpuid = drmach_cpu_calc_id(dst_cpu);
-
- if ((cp = cpu_get(cpuid)) == NULL) {
- err = drerr_new(1, ESTF_NODEV, "%s::%s",
- dst_cpu->bp->cm.name, dst_cpu->cm.name);
- return (err);
- }
-
- if (cpuid == SIGBCPU->cpu_id) {
- cmn_err(CE_WARN,
- "SIGBCPU(%d) same as new selection(%d)",
- SIGBCPU->cpu_id, cpuid);
-
- /* technically not an error, but a no-op */
- return (NULL);
- }
- }
-
- cmn_err(CE_NOTE, "?relocating SIGBCPU from %d to %d",
- SIGBCPU->cpu_id, cpuid);
-
- DRMACH_PR("moving SIGBCPU to CPU %d\n", cpuid);
-
- /*
- * Tell OBP to initialize cvc-offset field of new CPU0
- * so that it's in sync with OBP and cvc_server
- */
- prom_starfire_init_console(cpuid);
-
- /*
- * Assign cvc to new cpu0's bbsram for I/O. This has to be
- * done BEFORE cpu0 is moved via obp, since this logic
- * will cause obp_helper to switch to a different bbsram for
- * cvc I/O. We don't want cvc writing to a buffer from which
- * nobody will pick up the data!
- */
- cvc_assign_iocpu(cpuid);
-
- rv = prom_starfire_move_cpu0(cpuid);
-
- if (rv == 0) {
- SIGBCPU = cp;
-
- DRMACH_PR("successfully juggled to CPU %d\n", cpuid);
- return (NULL);
- } else {
- DRMACH_PR("prom error: prom_starfire_move_cpu0(%d) "
- "returned %d\n", cpuid, rv);
-
- /*
- * The move failed, hopefully obp_helper is still back
- * at the old bootproc. Move cvc back there.
- */
- cvc_assign_iocpu(SIGBCPU->cpu_id);
-
-
- err = drerr_new(1, ESTF_MOVESIGB, "CPU %d", cpuid);
- return (err);
- }
- /*NOTREACHED*/
-}
-
-static sbd_error_t *
-drmach_cpu_release(drmachid_t id)
-{
- drmach_device_t *dp;
- processorid_t cpuid;
- struct cpu *cp;
- sbd_error_t *err;
-
- if (!DRMACH_IS_CPU_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
- cpuid = drmach_cpu_calc_id(dp);
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- cp = cpu_get(cpuid);
- if (cp == NULL)
- err = DRMACH_INTERNAL_ERROR();
- else if (SIGBCPU->cpu_id == cp->cpu_id)
- err = drmach_cpu_juggle_bootproc(NULL);
- else
- err = NULL;
-
- return (err);
-}
-
-static sbd_error_t *
-drmach_cpu_status(drmachid_t id, drmach_status_t *stat)
-{
- drmach_device_t *dp;
-
- ASSERT(DRMACH_IS_CPU_ID(id));
- dp = id;
-
- stat->assigned = dp->bp->assigned;
- stat->powered = dp->bp->powered;
- mutex_enter(&cpu_lock);
- stat->configured = (cpu_get(drmach_cpu_calc_id(dp)) != NULL);
- mutex_exit(&cpu_lock);
- stat->busy = dp->busy;
- (void) strncpy(stat->type, dp->type, sizeof (stat->type));
- stat->info[0] = '\0';
-
- return (NULL);
-}
-
-sbd_error_t *
-drmach_cpu_disconnect(drmachid_t id)
-{
- drmach_device_t *cpu;
- int cpuid;
- int ntries;
- int p;
- u_longlong_t pc_addr;
- uchar_t rvalue;
-
- if (!DRMACH_IS_CPU_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- cpu = id;
-
- cpuid = drmach_cpu_calc_id(cpu);
- if (SIGBCPU->cpu_id == cpuid) {
- /* this cpu is SIGBCPU, can't disconnect */
- return (drerr_new(1, ESTF_HASSIGB, "%s::%s",
- cpu->bp->cm.name, cpu->cm.name));
- }
-
- /*
- * Make sure SIGBST_DETACHED is set before
- * mapping out the sig block.
- */
- ntries = drmach_cpu_ntries;
- while (!drmach_cpu_obp_is_detached(cpuid) && ntries) {
- DELAY(drmach_cpu_delay);
- ntries--;
- }
- if (!drmach_cpu_obp_is_detached(cpuid)) {
- cmn_err(CE_WARN, "failed to mark cpu %d detached in sigblock",
- cpuid);
- }
-
- /* map out signature block */
- if (CPU_SGN_EXISTS(cpuid)) {
- CPU_SGN_MAPOUT(cpuid);
- }
-
- /*
- * We now PC IDLE the processor to guarantee we
- * stop any transactions from coming from it.
- */
- p = cpu->unum & 1;
- pc_addr = STARFIRE_BB_PC_ADDR(cpu->bp->bnum, cpu->unum, 0);
-
- DRMACH_PR("PC idle cpu %d (addr = 0x%llx, port = %d, p = %d)",
- drmach_cpu_calc_id(cpu), pc_addr, cpu->unum, p);
-
- rvalue = ldbphysio(pc_addr);
- rvalue |= STARFIRE_BB_PC_IDLE(p);
- stbphysio(pc_addr, rvalue);
- DELAY(50000);
-
- return (NULL);
-}
-
-sbd_error_t *
-drmach_cpu_get_id(drmachid_t id, processorid_t *cpuid)
-{
- drmach_device_t *cpu;
-
- if (!DRMACH_IS_CPU_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- cpu = id;
-
- *cpuid = drmach_cpu_calc_id(cpu);
- return (NULL);
-}
-
-sbd_error_t *
-drmach_cpu_get_impl(drmachid_t id, int *ip)
-{
- drmach_device_t *cpu;
- int impl;
-
- if (!DRMACH_IS_CPU_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
-
- cpu = id;
-
- if (drmach_node_get_prop(cpu->node, "implementation#", &impl) == -1) {
- return (DRMACH_INTERNAL_ERROR());
- }
-
- *ip = impl;
-
- return (NULL);
-}
-
-void
-drmach_cpu_flush_ecache_sync(void)
-{
- ASSERT(curthread->t_bound_cpu == CPU);
-
- /*
- * Now let's flush our ecache thereby removing all references
- * to the target (detaching) memory from all ecache's in
- * system.
- */
- cpu_flush_ecache();
-
- /*
- * Delay 100 usec out of paranoia to insure everything
- * (hardware queues) has drained before we start reprogramming
- * the hardware.
- */
- DELAY(100);
-}
-
-sbd_error_t *
-drmach_get_dip(drmachid_t id, dev_info_t **dip)
-{
- drmach_device_t *dp;
-
- if (!DRMACH_IS_DEVICE_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- *dip = drmach_node_get_dip(dp->node);
- return (NULL);
-}
-
-sbd_error_t *
-drmach_io_is_attached(drmachid_t id, int *yes)
-{
- drmach_device_t *dp;
- dev_info_t *dip;
- int state;
-
- if (!DRMACH_IS_IO_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- dip = drmach_node_get_dip(dp->node);
- if (dip == NULL) {
- *yes = 0;
- return (NULL);
- }
-
- state = ddi_get_devstate(dip);
- *yes = (i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP));
-
- return (NULL);
-}
-
-sbd_error_t *
-drmach_io_pre_release(drmachid_t id)
-{
- if (!DRMACH_IS_IO_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_io_release(drmachid_t id)
-{
- if (!DRMACH_IS_IO_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- return (NULL);
-}
-
-sbd_error_t *
-drmach_io_unrelease(drmachid_t id)
-{
- if (!DRMACH_IS_IO_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- return (NULL);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_io_post_release(drmachid_t id)
-{
- return (NULL);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_io_post_attach(drmachid_t id)
-{
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_io_status(drmachid_t id, drmach_status_t *stat)
-{
- drmach_device_t *dp;
- sbd_error_t *err;
- int configured;
-
- ASSERT(DRMACH_IS_IO_ID(id));
- dp = id;
-
- err = drmach_io_is_attached(id, &configured);
- if (err)
- return (err);
-
- stat->assigned = dp->bp->assigned;
- stat->powered = dp->bp->powered;
- stat->configured = (configured != 0);
- stat->busy = dp->busy;
- (void) strncpy(stat->type, dp->type, sizeof (stat->type));
- stat->info[0] = '\0';
-
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_mem_new(drmach_device_t *dp)
-{
- dp->unum = 0;
- dp->cm.isa = (void *)drmach_mem_new;
- dp->cm.release = drmach_mem_release;
- dp->cm.status = drmach_mem_status;
-
- (void) snprintf(dp->cm.name, sizeof (dp->cm.name), "%s", dp->type);
-
- return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_add_span(drmachid_t id, uint64_t basepa, uint64_t size)
-{
- pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT);
- pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
- pda_handle_t ph;
- int rv;
-
- ASSERT(size != 0);
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
-
- rv = kcage_range_add(basepfn, npages, KCAGE_DOWN);
- if (rv == ENOMEM) {
- cmn_err(CE_WARN, "%lu megabytes not available to kernel cage",
- (ulong_t)(size == 0 ? 0 : size / MBYTE));
- } else if (rv != 0) {
- /* catch this in debug kernels */
- ASSERT(0);
-
- cmn_err(CE_WARN, "unexpected kcage_range_add"
- " return value %d", rv);
- }
-
- /*
- * Update the PDA (post2obp) structure with the
- * range of the newly added memory.
- */
- ph = drmach_pda_open();
- if (ph != NULL) {
- pda_mem_add_span(ph, basepa, size);
- pda_close(ph);
- }
-
- return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_del_span(drmachid_t id, uint64_t basepa, uint64_t size)
-{
- drmach_device_t *mem = id;
- pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT);
- pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT);
- uint_t mcreg;
- sbd_error_t *err;
- pda_handle_t ph;
- int rv;
-
- err = drmach_read_mc_asr(id, &mcreg);
- if (err)
- return (err);
- else if (mcreg & STARFIRE_MC_INTERLEAVE_MASK) {
- return (drerr_new(1, ESTF_INTERBOARD, "%s::%s",
- mem->bp->cm.name, mem->cm.name));
- }
-
- if (size > 0) {
- rv = kcage_range_delete_post_mem_del(basepfn, npages);
- if (rv != 0) {
- cmn_err(CE_WARN,
- "unexpected kcage_range_delete_post_mem_del"
- " return value %d", rv);
- return (DRMACH_INTERNAL_ERROR());
- }
- }
-
- /*
- * Update the PDA (post2obp) structure with the
- * range of removed memory.
- */
- ph = drmach_pda_open();
- if (ph != NULL) {
- if (size > 0)
- pda_mem_del_span(ph, basepa, size);
-
- /* update PDA to board's new mc register settings */
- pda_mem_sync(ph, mem->bp->bnum, 0);
-
- pda_close(ph);
- }
-
- return (NULL);
-}
-
-/* support routine for enable and disable */
-static sbd_error_t *
-drmach_mem_update_interconnect(drmachid_t id, uint_t mcreg)
-{
- drmach_device_t *dp;
- pda_handle_t ph;
- int b;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- dp = id;
-
- ph = drmach_pda_open();
- if (ph == NULL)
- return (DRMACH_INTERNAL_ERROR());
-
- for (b = 0; b < MAX_BOARDS; b++) {
- int p;
- int rv;
- ushort_t bda_proc, bda_ioc;
- board_desc_t *bdesc;
-
- if (pda_board_present(ph, b) == 0)
- continue;
-
- bdesc = (board_desc_t *)pda_get_board_info(ph, b);
-
- /*
- * Update PCs for CPUs.
- */
-
- /* make sure definition in platmod is in sync with pda */
- ASSERT(MAX_PROCMODS == MAX_CPU_UNITS_PER_BOARD);
-
- bda_proc = bdesc->bda_proc;
- for (p = 0; p < MAX_PROCMODS; p++) {
- if (BDA_NBL(bda_proc, p) != BDAN_GOOD)
- continue;
-
- rv = pc_madr_add(b, dp->bp->bnum, p, mcreg);
- if (rv) {
- pda_close(ph);
- return (DRMACH_INTERNAL_ERROR());
- }
- }
-
- /*
- * Update PCs for IOCs.
- */
-
- /* make sure definition in platmod is in sync with pda */
- ASSERT(MAX_IOCS == MAX_IO_UNITS_PER_BOARD);
-
- bda_ioc = bdesc->bda_ioc;
- for (p = 0; p < MAX_IOCS; p++) {
- if (BDA_NBL(bda_ioc, p) != BDAN_GOOD)
- continue;
-
- rv = pc_madr_add(b, dp->bp->bnum, p + 4, mcreg);
- if (rv) {
- pda_close(ph);
- return (DRMACH_INTERNAL_ERROR());
- }
- }
- }
-
- pda_close(ph);
- return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_disable(drmachid_t id)
-{
- sbd_error_t *err;
- uint_t mcreg;
-
- err = drmach_read_mc_asr(id, &mcreg);
- if (err == NULL) {
- ASSERT(mcreg & STARFIRE_MC_MEM_PRESENT_MASK);
-
- /* Turn off presence bit. */
- mcreg &= ~STARFIRE_MC_MEM_PRESENT_MASK;
-
- err = drmach_mem_update_interconnect(id, mcreg);
- if (err == NULL)
- err = drmach_write_mc_asr(id, mcreg);
- }
-
- return (err);
-}
-
-sbd_error_t *
-drmach_mem_enable(drmachid_t id)
-{
- sbd_error_t *err;
- uint_t mcreg;
-
- err = drmach_read_mc_asr(id, &mcreg);
- if (err == NULL) {
- mcreg |= STARFIRE_MC_MEM_PRESENT_MASK;
-
- err = drmach_write_mc_asr(id, mcreg);
- if (err == NULL)
- err = drmach_mem_update_interconnect(id, mcreg);
- }
-
- return (err);
-}
-
-sbd_error_t *
-drmach_mem_get_alignment(drmachid_t id, uint64_t *mask)
-{
- drmach_device_t *mem;
- sbd_error_t *err;
- pnode_t nodeid;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- mem = id;
-
- nodeid = drmach_node_get_dnode(mem->node);
- if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE)
- err = DRMACH_INTERNAL_ERROR();
- else {
- uint64_t size;
-
- size = mc_get_alignment_mask(nodeid);
- if (size == (uint64_t)-1)
- err = DRMACH_INTERNAL_ERROR();
- else {
- *mask = size - 1;
- err = NULL;
- }
- }
-
- return (err);
-}
-
-sbd_error_t *
-drmach_mem_get_base_physaddr(drmachid_t id, uint64_t *pa)
-{
- sbd_error_t *err;
- uint_t mcreg;
-
- err = drmach_read_mc_asr(id, &mcreg);
- if (err == NULL)
- *pa = mc_asr_to_pa(mcreg);
-
- return (err);
-}
-
-/*
- * Use of this routine after copy/rename will yield incorrect results,
- * because the OBP MEMAVAIL property will not correctly reflect the
- * programming of the MCs.
- */
-sbd_error_t *
-drmach_mem_get_memlist(drmachid_t id, struct memlist **ml)
-{
- drmach_device_t *mem;
- int rv, i, rlen, rblks;
- sbd_error_t *err;
- struct memlist *mlist;
- struct sf_memunit_regspec *rlist;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- mem = id;
-
- err = drmach_device_get_proplen(mem, "dr-available", &rlen);
- if (err)
- return (err);
-
- rlist = kmem_zalloc(rlen, KM_SLEEP);
-
- err = drmach_device_get_prop(mem, "dr-available", rlist);
- if (err) {
- kmem_free(rlist, rlen);
- return (err);
- }
-
- mlist = NULL;
- rblks = rlen / sizeof (struct sf_memunit_regspec);
- for (i = 0; i < rblks; i++) {
- uint64_t addr, size;
-
- addr = (uint64_t)rlist[i].regspec_addr_hi << 32;
- addr |= (uint64_t)rlist[i].regspec_addr_lo;
- size = (uint64_t)rlist[i].regspec_size_hi << 32;
- size |= (uint64_t)rlist[i].regspec_size_lo;
-
- mlist = memlist_add_span(mlist, addr, size);
- }
-
- kmem_free(rlist, rlen);
-
- /*
- * Make sure the incoming memlist doesn't already
- * intersect with what's present in the system (phys_install).
- */
- memlist_read_lock();
- rv = memlist_intersect(phys_install, mlist);
- memlist_read_unlock();
- if (rv) {
-#ifdef DEBUG
- DRMACH_PR("OBP derived memlist intersects"
- " with phys_install\n");
- memlist_dump(mlist);
-
- DRMACH_PR("phys_install memlist:\n");
- memlist_dump(phys_install);
-#endif
-
- memlist_delete(mlist);
- return (DRMACH_INTERNAL_ERROR());
- }
-
-#ifdef DEBUG
- DRMACH_PR("OBP derived memlist:");
- memlist_dump(mlist);
-#endif
-
- *ml = mlist;
- return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_get_size(drmachid_t id, uint64_t *bytes)
-{
- drmach_device_t *mem;
- pda_handle_t ph;
- pgcnt_t npages;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- mem = id;
-
- ph = drmach_pda_open();
- if (ph == NULL)
- return (DRMACH_INTERNAL_ERROR());
-
- npages = pda_get_mem_size(ph, mem->bp->bnum);
- *bytes = (uint64_t)npages << PAGESHIFT;
-
- pda_close(ph);
- return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_get_slice_size(drmachid_t id, uint64_t *bytes)
-{
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
-
- *bytes = mc_get_mem_alignment();
- return (NULL);
-}
-
-/* field debugging tool */
-processorid_t drmach_mem_cpu_affinity_nail = 0;
-
-processorid_t
-drmach_mem_cpu_affinity(drmachid_t id)
-{
- drmach_device_t *mp;
- drmach_board_t *bp;
- processorid_t cpuid;
-
- if (!DRMACH_IS_MEM_ID(id))
- return (CPU_CURRENT);
-
- if (drmach_mem_cpu_affinity_nail) {
- cpuid = drmach_mem_cpu_affinity_nail;
-
- if (cpuid < 0 || cpuid > NCPU)
- return (CPU_CURRENT);
-
- mutex_enter(&cpu_lock);
- if (cpu[cpuid] == NULL || !CPU_ACTIVE(cpu[cpuid]))
- cpuid = CPU_CURRENT;
- mutex_exit(&cpu_lock);
-
- return (cpuid);
- }
-
- /* try to choose a proc on the target board */
- mp = id;
- bp = mp->bp;
- if (bp->devices) {
- int rv;
- int d_idx;
- drmachid_t d_id;
-
- rv = drmach_array_first(bp->devices, &d_idx, &d_id);
- while (rv == 0) {
- if (DRMACH_IS_CPU_ID(d_id)) {
- cpuid = drmach_cpu_calc_id(d_id);
-
- mutex_enter(&cpu_lock);
- if (cpu[cpuid] && CPU_ACTIVE(cpu[cpuid])) {
- mutex_exit(&cpu_lock);
- DRMACH_PR("drmach_mem_cpu_affinity: "
- "selected cpuid=%d\n", cpuid);
- return (cpuid);
- } else {
- mutex_exit(&cpu_lock);
- }
- }
-
- rv = drmach_array_next(bp->devices, &d_idx, &d_id);
- }
- }
-
- /* otherwise, this proc, wherever it is */
- DRMACH_PR("drmach_mem_cpu_affinity: using default CPU_CURRENT\n");
-
- return (CPU_CURRENT);
-}
-
-static sbd_error_t *
-drmach_mem_release(drmachid_t id)
-{
- if (!DRMACH_IS_MEM_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- return (NULL);
-}
-
-static sbd_error_t *
-drmach_mem_status(drmachid_t id, drmach_status_t *stat)
-{
- drmach_device_t *dp;
- sbd_error_t *err;
- uint64_t pa, slice_size;
- struct memlist *ml;
-
- ASSERT(DRMACH_IS_MEM_ID(id));
- dp = id;
-
- /* get starting physical address of target memory */
- err = drmach_mem_get_base_physaddr(id, &pa);
- if (err)
- return (err);
-
- /* round down to slice boundary */
- slice_size = mc_get_mem_alignment();
- pa &= ~ (slice_size - 1);
-
- /* stop at first span that is in slice */
- memlist_read_lock();
- for (ml = phys_install; ml; ml = ml->ml_next)
- if (ml->ml_address >= pa && ml->ml_address < pa + slice_size)
- break;
- memlist_read_unlock();
-
- stat->assigned = dp->bp->assigned;
- stat->powered = dp->bp->powered;
- stat->configured = (ml != NULL);
- stat->busy = dp->busy;
- (void) strncpy(stat->type, dp->type, sizeof (stat->type));
- stat->info[0] = '\0';
-
- return (NULL);
-}
-
-static int
-drmach_detach_board(void *arg)
-{
- cpuset_t cset;
- int retval;
- drmach_board_t *bp = (drmach_board_t *)arg;
-
- cset = cpu_ready_set;
- promsafe_xc_attention(cset);
-
- retval = prom_starfire_rm_brd(bp->bnum);
-
- xc_dismissed(cset);
-
- return (retval);
-}
-
-sbd_error_t *
-drmach_board_deprobe(drmachid_t id)
-{
- drmach_board_t *bp;
- int retval;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- bp = id;
-
- cmn_err(CE_CONT, "DR: PROM detach board %d\n", bp->bnum);
-
- retval = prom_tree_update(drmach_detach_board, bp);
-
- if (retval == 0)
- return (NULL);
- else {
- cmn_err(CE_WARN, "prom error: prom_starfire_rm_brd(%d) "
- "returned %d", bp->bnum, retval);
- return (drerr_new(1, ESTF_DEPROBE, "%s", bp->cm.name));
- }
-}
-
-/*ARGSUSED*/
-static sbd_error_t *
-drmach_pt_juggle_bootproc(drmachid_t id, drmach_opts_t *opts)
-{
- drmach_device_t *cpu;
- sbd_error_t *err;
-
- if (!DRMACH_IS_CPU_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- cpu = id;
-
- mutex_enter(&cpu_lock);
-
- err = drmach_cpu_juggle_bootproc(cpu);
-
- mutex_exit(&cpu_lock);
-
- return (err);
-}
-
-/*ARGSUSED*/
-static sbd_error_t *
-drmach_pt_dump_pdainfo(drmachid_t id, drmach_opts_t *opts)
-{
- drmach_board_t *bp;
- int board;
- int i;
- pda_handle_t ph;
- board_desc_t *bdesc;
-
- if (!DRMACH_IS_BOARD_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- bp = id;
- board = bp->bnum;
-
- ph = drmach_pda_open();
- if (ph == NULL)
- return (DRMACH_INTERNAL_ERROR());
-
- if (pda_board_present(ph, board) == 0) {
- cmn_err(CE_CONT, "board %d is MISSING\n", board);
- pda_close(ph);
- return (DRMACH_INTERNAL_ERROR());
- }
-
- cmn_err(CE_CONT, "board %d is PRESENT\n", board);
-
- bdesc = (board_desc_t *)pda_get_board_info(ph, board);
- if (bdesc == NULL) {
- cmn_err(CE_CONT,
- "no board descriptor found for board %d\n",
- board);
- pda_close(ph);
- return (DRMACH_INTERNAL_ERROR());
- }
-
- /* make sure definition in platmod is in sync with pda */
- ASSERT(MAX_PROCMODS == MAX_CPU_UNITS_PER_BOARD);
-
- for (i = 0; i < MAX_PROCMODS; i++) {
- if (BDA_NBL(bdesc->bda_proc, i) == BDAN_GOOD)
- cmn_err(CE_CONT,
- "proc %d.%d PRESENT\n", board, i);
- else
- cmn_err(CE_CONT,
- "proc %d.%d MISSING\n", board, i);
- }
-
- for (i = 0; i < MAX_MGROUPS; i++) {
- if (BDA_NBL(bdesc->bda_mgroup, i) == BDAN_GOOD)
- cmn_err(CE_CONT,
- "mgroup %d.%d PRESENT\n", board, i);
- else
- cmn_err(CE_CONT,
- "mgroup %d.%d MISSING\n", board, i);
- }
-
- /* make sure definition in platmod is in sync with pda */
- ASSERT(MAX_IOCS == MAX_IO_UNITS_PER_BOARD);
-
- for (i = 0; i < MAX_IOCS; i++) {
- int s;
-
- if (BDA_NBL(bdesc->bda_ioc, i) == BDAN_GOOD) {
- cmn_err(CE_CONT,
- "ioc %d.%d PRESENT\n", board, i);
- for (s = 0; s < MAX_SLOTS_PER_IOC; s++) {
- if (BDA_NBL(bdesc->bda_ios[i], s) != BDAN_GOOD)
- continue;
- cmn_err(CE_CONT,
- "..scard %d.%d.%d PRESENT\n",
- board, i, s);
- }
- } else {
- cmn_err(CE_CONT,
- "ioc %d.%d MISSING\n",
- board, i);
- }
- }
-
- cmn_err(CE_CONT,
- "board %d memsize = %d pages\n",
- board, pda_get_mem_size(ph, board));
-
- pda_close(ph);
-
- return (NULL);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_pt_readmem(drmachid_t id, drmach_opts_t *opts)
-{
- struct memlist *ml;
- uint64_t src_pa;
- uint64_t dst_pa;
- uint64_t dst;
-
- dst_pa = va_to_pa(&dst);
-
- memlist_read_lock();
- for (ml = phys_install; ml; ml = ml->ml_next) {
- uint64_t nbytes;
-
- src_pa = ml->ml_address;
- nbytes = ml->ml_size;
-
- while (nbytes != 0ull) {
-
- /* copy 32 bytes at arc_pa to dst_pa */
- bcopy32_il(src_pa, dst_pa);
-
- /* increment by 32 bytes */
- src_pa += (4 * sizeof (uint64_t));
-
- /* decrement by 32 bytes */
- nbytes -= (4 * sizeof (uint64_t));
- }
- }
- memlist_read_unlock();
-
- return (NULL);
-}
-
-static struct {
- const char *name;
- sbd_error_t *(*handler)(drmachid_t id, drmach_opts_t *opts);
-} drmach_pt_arr[] = {
- { "juggle", drmach_pt_juggle_bootproc },
- { "pda", drmach_pt_dump_pdainfo },
- { "readmem", drmach_pt_readmem },
-
- /* the following line must always be last */
- { NULL, NULL }
-};
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_passthru(drmachid_t id, drmach_opts_t *opts)
-{
- int i;
- sbd_error_t *err;
-
- i = 0;
- while (drmach_pt_arr[i].name != NULL) {
- int len = strlen(drmach_pt_arr[i].name);
-
- if (strncmp(drmach_pt_arr[i].name, opts->copts, len) == 0)
- break;
-
- i += 1;
- }
-
- if (drmach_pt_arr[i].name == NULL)
- err = drerr_new(0, ESTF_UNKPTCMD, opts->copts);
- else
- err = (*drmach_pt_arr[i].handler)(id, opts);
-
- return (err);
-}
-
-sbd_error_t *
-drmach_release(drmachid_t id)
-{
- drmach_common_t *cp;
- if (!DRMACH_IS_DEVICE_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
- cp = id;
-
- return (cp->release(id));
-}
-
-sbd_error_t *
-drmach_status(drmachid_t id, drmach_status_t *stat)
-{
- drmach_common_t *cp;
-
- if (!DRMACH_IS_ID(id))
- return (drerr_new(0, ESTF_NOTID, NULL));
- cp = id;
-
- return (cp->status(id, stat));
-}
-
-sbd_error_t *
-drmach_unconfigure(drmachid_t id, int flags)
-{
- drmach_device_t *dp;
- pnode_t nodeid;
- dev_info_t *dip, *fdip = NULL;
-
- if (!DRMACH_IS_DEVICE_ID(id))
- return (drerr_new(0, ESTF_INAPPROP, NULL));
-
- dp = id;
-
- nodeid = drmach_node_get_dnode(dp->node);
- if (nodeid == OBP_NONODE)
- return (DRMACH_INTERNAL_ERROR());
-
- dip = e_ddi_nodeid_to_dip(nodeid);
- if (dip == NULL)
- return (NULL);
-
- /*
- * Branch already held, so hold acquired in
- * e_ddi_nodeid_to_dip() can be released
- */
- ddi_release_devi(dip);
-
- if (flags & DEVI_BRANCH_DESTROY)
- flags |= DEVI_BRANCH_EVENT;
-
- /*
- * Force flag is no longer necessary. See starcat/io/drmach.c
- * for details.
- */
- ASSERT(e_ddi_branch_held(dip));
- if (e_ddi_branch_unconfigure(dip, &fdip, flags)) {
- sbd_error_t *err;
- char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-
- /*
- * If non-NULL, fdip is returned held and must be released.
- */
- if (fdip != NULL) {
- (void) ddi_pathname(fdip, path);
- ndi_rele_devi(fdip);
- } else {
- (void) ddi_pathname(dip, path);
- }
-
- err = drerr_new(1, ESTF_DRVFAIL, path);
-
- kmem_free(path, MAXPATHLEN);
-
- return (err);
- }
-
- return (NULL);
-}
-
-/*
- * drmach interfaces to legacy Starfire platmod logic
- * linkage via runtime symbol look up, called from plat_cpu_power*
- */
-
-/*
- * Start up a cpu. It is possible that we're attempting to restart
- * the cpu after an UNCONFIGURE in which case the cpu will be
- * spinning in its cache. So, all we have to do is wake it up.
- * Under normal circumstances the cpu will be coming from a previous
- * CONNECT and thus will be spinning in OBP. In both cases, the
- * startup sequence is the same.
- */
-int
-drmach_cpu_poweron(struct cpu *cp)
-{
- DRMACH_PR("drmach_cpu_poweron: starting cpuid %d\n", cp->cpu_id);
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- if (drmach_cpu_start(cp) != 0)
- return (EBUSY);
- else
- return (0);
-}
-
-int
-drmach_cpu_poweroff(struct cpu *cp)
-{
- int ntries, cnt;
- processorid_t cpuid = cp->cpu_id;
- void drmach_cpu_shutdown_self(void);
-
- DRMACH_PR("drmach_cpu_poweroff: stopping cpuid %d\n", cp->cpu_id);
-
- ASSERT(MUTEX_HELD(&cpu_lock));
-
- /*
- * Capture all CPUs (except for detaching proc) to prevent
- * crosscalls to the detaching proc until it has cleared its
- * bit in cpu_ready_set.
- *
- * The CPU's remain paused and the prom_mutex is known to be free.
- * This prevents the x-trap victim from blocking when doing prom
- * IEEE-1275 calls at a high PIL level.
- */
- promsafe_pause_cpus();
-
- /*
- * Quiesce interrupts on the target CPU. We do this by setting
- * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to
- * prevent it from receiving cross calls and cross traps.
- * This prevents the processor from receiving any new soft interrupts.
- */
- mp_cpu_quiesce(cp);
-
- /* setup xt_mb, will be cleared by drmach_shutdown_asm when ready */
- drmach_xt_mb[cpuid] = 0x80;
-
- xt_one_unchecked(cpuid, (xcfunc_t *)idle_stop_xcall,
- (uint64_t)drmach_cpu_shutdown_self, NULL);
-
- ntries = drmach_cpu_ntries;
- cnt = 0;
- while (drmach_xt_mb[cpuid] && ntries) {
- DELAY(drmach_cpu_delay);
- ntries--;
- cnt++;
- }
-
- drmach_xt_mb[cpuid] = 0; /* steal the cache line back */
-
- start_cpus();
-
- DRMACH_PR("waited %d out of %d tries for "
- "drmach_cpu_shutdown_self on cpu%d",
- drmach_cpu_ntries - ntries, drmach_cpu_ntries, cp->cpu_id);
-
- drmach_cpu_obp_detach(cpuid);
-
- CPU_SIGNATURE(OS_SIG, SIGST_DETACHED, SIGSUBST_NULL, cpuid);
-
- return (0);
-}
-
-/*ARGSUSED*/
-int
-drmach_verify_sr(dev_info_t *dip, int sflag)
-{
- return (0);
-}
-
-void
-drmach_suspend_last(void)
-{
-}
-
-void
-drmach_resume_first(void)
-{
-}
-
-/*
- * Log a DR sysevent.
- * Return value: 0 success, non-zero failure.
- */
-int
-drmach_log_sysevent(int board, char *hint, int flag, int verbose)
-{
- sysevent_t *ev;
- sysevent_id_t eid;
- int rv, km_flag;
- sysevent_value_t evnt_val;
- sysevent_attr_list_t *evnt_attr_list = NULL;
- char attach_pnt[MAXNAMELEN];
-
- km_flag = (flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
- attach_pnt[0] = '\0';
- if (drmach_board_name(board, attach_pnt, MAXNAMELEN)) {
- rv = -1;
- goto logexit;
- }
- if (verbose)
- DRMACH_PR("drmach_log_sysevent: %s %s, flag: %d, verbose: %d\n",
- attach_pnt, hint, flag, verbose);
-
- if ((ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE,
- SUNW_KERN_PUB"dr", km_flag)) == NULL) {
- rv = -2;
- goto logexit;
- }
- evnt_val.value_type = SE_DATA_TYPE_STRING;
- evnt_val.value.sv_string = attach_pnt;
- if ((rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID,
- &evnt_val, km_flag)) != 0)
- goto logexit;
-
- evnt_val.value_type = SE_DATA_TYPE_STRING;
- evnt_val.value.sv_string = hint;
- if ((rv = sysevent_add_attr(&evnt_attr_list, DR_HINT,
- &evnt_val, km_flag)) != 0) {
- sysevent_free_attr(evnt_attr_list);
- goto logexit;
- }
-
- (void) sysevent_attach_attributes(ev, evnt_attr_list);
-
- /*
- * Log the event but do not sleep waiting for its
- * delivery. This provides insulation from syseventd.
- */
- rv = log_sysevent(ev, SE_NOSLEEP, &eid);
-
-logexit:
- if (ev)
- sysevent_free(ev);
- if ((rv != 0) && verbose)
- cmn_err(CE_WARN,
- "drmach_log_sysevent failed (rv %d) for %s %s\n",
- rv, attach_pnt, hint);
-
- return (rv);
-}
-
-/*ARGSUSED*/
-int
-drmach_allow_memrange_modify(drmachid_t id)
-{
- return (1); /* TRUE */
-}
diff --git a/usr/src/uts/sun4u/starfire/io/idn.c b/usr/src/uts/sun4u/starfire/io/idn.c
deleted file mode 100644
index 79eb65f819..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn.c
+++ /dev/null
@@ -1,5787 +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) 2016 by Delphix. All rights reserved.
- */
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/open.h>
-#include <sys/param.h>
-#include <sys/machparam.h>
-#include <sys/systm.h>
-#include <sys/signal.h>
-#include <sys/cred.h>
-#include <sys/user.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/file.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/strsubr.h>
-#include <sys/strsun.h>
-#include <inet/common.h>
-#include <inet/mi.h>
-#include <inet/nd.h>
-#include <sys/poll.h>
-#include <sys/utsname.h>
-#include <sys/debug.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/errno.h>
-#include <sys/modctl.h>
-#include <sys/machsystm.h>
-#include <sys/promif.h>
-#include <sys/prom_plat.h>
-#include <sys/obpdefs.h>
-#include <vm/seg_kmem.h>
-#include <vm/seg_kp.h>
-#include <sys/kstat.h>
-#include <sys/membar.h>
-#include <sys/ivintr.h>
-#include <sys/vm_machparam.h>
-#include <sys/x_call.h>
-#include <sys/cpuvar.h>
-#include <sys/archsystm.h>
-#include <sys/dmv.h>
-
-#include <sys/idn.h>
-#include <sys/idn_xf.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/cpu_sgn.h>
-
-struct idn_gkstat sg_kstat;
-
-#define MBXTBL_PART_REPORT ((caddr_t)1)
-#define MBXTBL_FULL_REPORT ((caddr_t)2)
-
-idn_domain_t idn_domain[MAX_DOMAINS];
-idn_global_t idn;
-int idn_debug;
-int idn_snoop;
-int idn_history;
-
-typedef enum {
- IDN_GPROPS_OKAY,
- IDN_GPROPS_UNCHECKED,
- IDN_GPROPS_ERROR
-} idn_gprops_t;
-
-struct idn_history idnhlog;
-
-/*
- * IDN "tunables".
- */
-int idn_smr_size;
-int idn_nwr_size;
-int idn_lowat;
-int idn_hiwat;
-int idn_protocol_nservers;
-int idn_awolmsg_interval;
-int idn_smr_bufsize;
-int idn_slab_bufcount;
-int idn_slab_prealloc;
-int idn_slab_maxperdomain;
-int idn_slab_mintotal;
-int idn_window_max;
-int idn_window_incr;
-int idn_window_emax;
-int idn_reclaim_min;
-int idn_reclaim_max;
-int idn_mbox_per_net;
-int idn_max_nets;
-
-int idn_netsvr_spin_count;
-int idn_netsvr_wait_min;
-int idn_netsvr_wait_max;
-int idn_netsvr_wait_shift;
-
-int idn_checksum;
-
-int idn_msgwait_nego;
-int idn_msgwait_cfg;
-int idn_msgwait_con;
-int idn_msgwait_fin;
-int idn_msgwait_cmd;
-int idn_msgwait_data;
-
-int idn_retryfreq_nego;
-int idn_retryfreq_con;
-int idn_retryfreq_fin;
-
-int idn_window_emax; /* calculated */
-int idn_slab_maxperdomain; /* calculated */
-
-/*
- * DMV interrupt support.
- */
-int idn_pil;
-int idn_dmv_pending_max;
-idn_dmv_msg_t *idn_iv_queue[NCPU];
-int idn_intr_index[NCPU]; /* idn_handler ONLY */
-static idn_dmv_data_t *idn_dmv_data;
-
-int idn_sigbpil;
-
-idnparam_t idn_param_arr[] = {
-{ 0, 1, 0, /* 0 */ "idn_modunloadable" },
-};
-
-/*
- * Parameters that are only accessible in a DEBUG driver.
- */
-static char *idn_param_debug_only[] = {
-#if 0
- "idn_checksum",
-#endif /* 0 */
- 0
-};
-
-/*
- * Parameters that are READ-ONLY.
- */
-static char *idn_param_read_only[] = {
-#if 0
- "idn_window_emax",
- "idn_slab_maxperdomain",
-#endif /* 0 */
- 0
-};
-
-static struct idn_global_props {
- int p_min, p_max, p_def;
- char *p_string;
- int *p_var;
-} idn_global_props[] = {
-{ 0, 0, 0, "idn_debug", &idn_debug },
-{ 0, 1, 0, "idn_history", &idn_history },
-{ 0, IDN_SMR_MAXSIZE,
- 0, "idn_smr_size", &idn_smr_size },
-{ 0, IDN_SMR_MAXSIZE,
- 0, "idn_nwr_size", &idn_nwr_size },
-{ 1, 512*1024,
- 1, "idn_lowat", &idn_lowat },
-{ 1*1024,
- 1*1024*1024,
- 256*1024,
- "idn_hiwat", &idn_hiwat },
-{ IDN_SMR_BUFSIZE_MIN,
- IDN_SMR_BUFSIZE_MAX,
- IDN_SMR_BUFSIZE_DEF,
- "idn_smr_bufsize", &idn_smr_bufsize },
-{ 4, 1024, 32, "idn_slab_bufcount", &idn_slab_bufcount },
-{ 0, 10, 0, "idn_slab_prealloc", &idn_slab_prealloc },
-{ 2, MAX_DOMAINS,
- 8, "idn_slab_mintotal", &idn_slab_mintotal },
-{ 8, 256, 64, "idn_window_max", &idn_window_max },
-{ 0, 32, 8, "idn_window_incr", &idn_window_incr },
-{ 1, 128, 5, "idn_reclaim_min", &idn_reclaim_min },
-{ 0, 128, 0, "idn_reclaim_max", &idn_reclaim_max },
-{ 1, IDN_MAXMAX_NETS,
- 8, "idn_max_nets", &idn_max_nets },
-{ 31, 511, 127, "idn_mbox_per_net", &idn_mbox_per_net },
-{ 0, 1, 1, "idn_checksum", &idn_checksum },
-{ 0, 10000, 500, "idn_netsvr_spin_count",
- &idn_netsvr_spin_count },
-{ 0, 30*100, 40, "idn_netsvr_wait_min", &idn_netsvr_wait_min },
-{ 0, 60*100, 16*100, "idn_netsvr_wait_max", &idn_netsvr_wait_max },
-{ 1, 5, 1, "idn_netsvr_wait_shift",
- &idn_netsvr_wait_shift },
-{ 1, MAX_DOMAINS,
- IDN_PROTOCOL_NSERVERS,
- "idn_protocol_nservers",
- &idn_protocol_nservers },
-{ 0, 3600, IDN_AWOLMSG_INTERVAL,
- "idn_awolmsg_interval", &idn_awolmsg_interval },
-{ 10, 300, IDN_MSGWAIT_NEGO,
- "idn_msgwait_nego", &idn_msgwait_nego },
-{ 10, 300, IDN_MSGWAIT_CFG,
- "idn_msgwait_cfg", &idn_msgwait_cfg },
-{ 10, 300, IDN_MSGWAIT_CON,
- "idn_msgwait_con", &idn_msgwait_con },
-{ 10, 300, IDN_MSGWAIT_FIN,
- "idn_msgwait_fin", &idn_msgwait_fin },
-{ 10, 300, IDN_MSGWAIT_CMD,
- "idn_msgwait_cmd", &idn_msgwait_cmd },
-{ 10, 300, IDN_MSGWAIT_DATA,
- "idn_msgwait_data", &idn_msgwait_data },
-{ 1, 60, IDN_RETRYFREQ_NEGO,
- "idn_retryfreq_nego", &idn_retryfreq_nego },
-{ 1, 60, IDN_RETRYFREQ_CON,
- "idn_retryfreq_con", &idn_retryfreq_con },
-{ 1, 60, IDN_RETRYFREQ_FIN,
- "idn_retryfreq_fin", &idn_retryfreq_fin },
-{ 1, 9, IDN_PIL,
- "idn_pil", &idn_pil },
-{ 1, 9, IDN_SIGBPIL,
- "idn_sigbpil", &idn_sigbpil },
-{ 8, 512, IDN_DMV_PENDING_MAX,
- "idn_dmv_pending_max", &idn_dmv_pending_max },
-{ 0, 0, 0, NULL, NULL }
-};
-
-struct idn *idn_i2s_table[IDN_MAXMAX_NETS << 1];
-clock_t idn_msg_waittime[IDN_NUM_MSGTYPES];
-clock_t idn_msg_retrytime[(int)IDN_NUM_RETRYTYPES];
-
-static caddr_t idn_ndlist; /* head of 'named dispatch' var list */
-
-static int idnattach(dev_info_t *, ddi_attach_cmd_t);
-static int idndetach(dev_info_t *, ddi_detach_cmd_t);
-static int idnopen(register queue_t *, dev_t *, int, int, cred_t *);
-static int idnclose(queue_t *, int, cred_t *);
-static int idnwput(queue_t *, mblk_t *);
-static int idnwsrv(queue_t *);
-static int idnrput(queue_t *, mblk_t *);
-static void idnioctl(queue_t *, mblk_t *);
-static idn_gprops_t idn_check_conf(dev_info_t *dip, processorid_t *cpuid);
-static int idn_size_check();
-static void idn_xmit_monitor_init();
-static void idn_xmit_monitor_deinit();
-static void idn_init_msg_waittime();
-static void idn_init_msg_retrytime();
-static void idn_sigb_setup(cpu_sgnblk_t *sigbp, void *arg);
-static int idn_init(dev_info_t *dip);
-static int idn_deinit();
-static void idn_sigbhandler_create();
-static void idn_sigbhandler_kill();
-static uint_t idn_sigbhandler_wakeup(caddr_t arg1, caddr_t arg2);
-static void idn_sigbhandler_thread(struct sigbintr **sbpp);
-static void idn_sigbhandler(processorid_t cpuid, cpu_sgnblk_t *sgnblkp);
-static int idn_info(idnsb_info_t *sfp);
-static int idn_init_smr();
-static void idn_deinit_smr();
-static int idn_prom_getsmr(uint_t *smrsz, uint64_t *paddrp,
- uint64_t *sizep);
-static int idn_init_handler();
-static void idn_deinit_handler();
-static uint_t idn_handler(caddr_t unused, caddr_t unused2);
-/*
- * ioctl services
- */
-static int idnioc_link(idnop_t *idnop);
-static int idnioc_unlink(idnop_t *idnop);
-static int idn_rw_mem(idnop_t *idnop);
-static int idn_send_ping(idnop_t *idnop);
-
-static void idn_domains_init(struct hwconfig *local_hw);
-static void idn_domains_deinit();
-static void idn_retrytask_init();
-static void idn_retrytask_deinit();
-static void idn_gkstat_init();
-static void idn_gkstat_deinit();
-static int idn_gkstat_update();
-static void idn_timercache_init();
-static void idn_timercache_deinit();
-static void idn_dopers_init();
-static void idn_dopers_deinit();
-
-static void idn_param_cleanup();
-static int idn_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
-static int idn_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
- cred_t *cr);
-static int idn_param_register(register idnparam_t *idnpa, int count);
-static int idn_slabpool_report(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static int idn_buffer_report(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static int idn_mboxtbl_report(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static int idn_mainmbox_report(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static void idn_mainmbox_domain_report(queue_t *wq, mblk_t *mp, int domid,
- idn_mainmbox_t *mmp, char *mbxtype);
-static int idn_global_report(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static int idn_domain_report(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static int idn_get_net_binding(queue_t *wq, mblk_t *mp, caddr_t cp,
- cred_t *cr);
-static int idn_set_net_binding(queue_t *wq, mblk_t *mp, char *value,
- caddr_t cp, cred_t *cr);
-
-/*
- * String definitions used for DEBUG and non-DEBUG.
- */
-const char *idnm_str[] = {
-/* 0 */ "null",
-/* 1 */ "nego",
-/* 2 */ "con",
-/* 3 */ "cfg",
-/* 4 */ "fin",
-/* 5 */ "cmd",
-/* 6 */ "data",
-};
-
-const char *idnds_str[] = {
-/* 0 */ "CLOSED",
-/* 1 */ "NEGO_PEND",
-/* 2 */ "NEGO_SENT",
-/* 3 */ "NEGO_RCVD",
-/* 4 */ "CONFIG",
-/* 5 */ "CON_PEND",
-/* 6 */ "CON_SENT",
-/* 7 */ "CON_RCVD",
-/* 8 */ "CON_READY",
-/* 9 */ "CONNECTED",
-/* 10 */ "FIN_PEND",
-/* 11 */ "FIN_SENT",
-/* 12 */ "FIN_RCVD",
-/* 13 */ "DMAP"
-};
-
-const char *idnxs_str[] = {
-/* 0 */ "PEND",
-/* 1 */ "SENT",
-/* 2 */ "RCVD",
-/* 3 */ "FINAL",
-/* 4 */ "NIL"
-};
-
-const char *idngs_str[] = {
-/* 0 */ "OFFLINE",
-/* 1 */ "CONNECT",
-/* 2 */ "ONLINE",
-/* 3 */ "DISCONNECT",
-/* 4 */ "RECONFIG",
-/* 5 */ "unknown",
-/* 6 */ "unknown",
-/* 7 */ "unknown",
-/* 8 */ "unknown",
-/* 9 */ "unknown",
-/* 10 */ "IGNORE"
-};
-
-const char *idncmd_str[] = {
-/* 0 */ "unknown",
-/* 1 */ "SLABALLOC",
-/* 2 */ "SLABFREE",
-/* 3 */ "SLABREAP",
-/* 4 */ "NODENAME"
-};
-
-const char *idncon_str[] = {
-/* 0 */ "OFF",
-/* 1 */ "NORMAL",
-/* 2 */ "QUERY"
-};
-
-const char *idnfin_str[] = {
-/* 0 */ "OFF",
-/* 1 */ "NORMAL",
-/* 2 */ "FORCE_SOFT",
-/* 3 */ "FORCE_HARD",
-/* 4 */ "QUERY"
-};
-
-const char *idnfinopt_str[] = {
-/* 0 */ "NONE",
-/* 1 */ "UNLINK",
-/* 2 */ "RELINK"
-};
-
-const char *idnfinarg_str[] = {
-/* 0 */ "NONE",
-/* 1 */ "SMRBAD",
-/* 2 */ "CPUCFG",
-/* 3 */ "HWERR",
-/* 4 */ "CFGERR_FATAL",
-/* 5 */ "CFGERR_MTU",
-/* 6 */ "CFGERR_BUF",
-/* 7 */ "CFGERR_SLAB",
-/* 8 */ "CFGERR_NWR",
-/* 9 */ "CFGERR_NETS",
-/* 10 */ "CFGERR_MBOX",
-/* 11 */ "CFGERR_NMCADR",
-/* 12 */ "CFGERR_MCADR",
-/* 13 */ "CFGERR_CKSUM",
-/* 14 */ "CFGERR_SMR",
-};
-
-const char *idnsync_str[] = {
-/* 0 */ "NIL",
-/* 1 */ "CONNECT",
-/* 2 */ "DISCONNECT"
-};
-
-const char *idnreg_str[] = {
-/* 0 */ "REG",
-/* 1 */ "NEW",
-/* 2 */ "QUERY"
-};
-
-const char *idnnack_str[] = {
-/* 0 */ "unknown",
-/* 1 */ "NOCONN",
-/* 2 */ "BADCHAN",
-/* 3 */ "BADCFG",
-/* 4 */ "BADCMD",
-/* 5 */ "RETRY",
-/* 6 */ "DUP",
-/* 7 */ "EXIT",
-/* 8 */ "--reserved1",
-/* 9 */ "--reserved2",
-/* 10 */ "--reserved3"
-};
-
-const char *idnop_str[] = {
-/* 0 */ "DISCONNECTED",
-/* 1 */ "CONNECTED",
-/* 2 */ "ERROR"
-};
-
-const char *chanop_str[] = {
-/* 0 */ "OPEN",
-/* 1 */ "SOFT_CLOSE",
-/* 2 */ "HARD_CLOSE",
-/* 3 */ "OFFLINE",
-/* 4 */ "ONLINE"
-};
-
-const char *chanaction_str[] = {
-/* 0 */ "DETACH",
-/* 1 */ "STOP",
-/* 2 */ "SUSPEND",
-/* 3 */ "RESUME",
-/* 4 */ "RESTART",
-/* 5 */ "ATTACH"
-};
-
-const char *timer_str[] = {
-/* 0 */ "NIL",
-/* 1 */ "MSG"
-};
-
-static struct module_info idnrinfo = {
- IDNIDNUM, /* mi_idnum */
- IDNNAME, /* mi_idname */
- IDNMINPSZ, /* mi_minpsz */
- IDNMAXPSZ, /* mi_maxpsz */
- 0, /* mi_hiwat - see IDN_HIWAT */
- 0 /* mi_lowat - see IDN_LOWAT */
-};
-
-static struct module_info idnwinfo = {
- IDNIDNUM, /* mi_idnum */
- IDNNAME, /* mi_idname */
- IDNMINPSZ, /* mi_minpsz */
- IDNMAXPSZ, /* mi_maxpsz */
- 0, /* mi_hiwat - see IDN_HIWAT */
- 0 /* mi_lowat - see IDN_LOWAT */
-};
-
-static struct qinit idnrinit = {
- idnrput, /* qi_putp */
- NULL, /* qi_srvp */
- idnopen, /* qi_qopen */
- idnclose, /* qi_qclose */
- NULL, /* qi_qadmin */
- &idnrinfo, /* qi_minfo */
- NULL, /* qi_mstat */
- NULL, /* qi_rwp */
- NULL, /* qi_infop */
- STRUIOT_DONTCARE /* qi_struiot */
-};
-
-static struct qinit idnwinit = {
- idnwput, /* qi_putp */
- idnwsrv, /* qi_srvp */
- NULL, /* qi_qopen */
- NULL, /* qi_qclose */
- NULL, /* qi_qadmin */
- &idnwinfo, /* qi_minfo */
- NULL, /* qi_mstat */
- NULL, /* qi_rwp */
- NULL, /* qi_infop */
- STRUIOT_DONTCARE /* qi_struiot */
-};
-
-struct streamtab idninfo = {
- &idnrinit, /* st_rdinit */
- &idnwinit, /* st_wrinit */
- NULL, /* st_muxrinit */
- NULL, /* st_muxwinit */
-};
-
-/*
- * Module linkage information (cb_ops & dev_ops) for the kernel.
- */
-
-static struct cb_ops cb_idnops = {
- nulldev, /* cb_open */
- nulldev, /* cb_close */
- nodev, /* cb_strategy */
- nodev, /* cb_print */
- nodev, /* cb_dump */
- nodev, /* cb_read */
- nodev, /* cb_write */
- nodev, /* cb_ioctl */
- nodev, /* cb_devmap */
- nodev, /* cb_mmap */
- nodev, /* cb_segmap */
- nochpoll, /* cb_chpoll */
- ddi_prop_op, /* cb_prop_op */
- &idninfo, /* cb_stream */
- D_MP, /* cb_flag */
- CB_REV, /* cb_rev */
- nodev, /* cb_aread */
- nodev, /* cb_awrite */
-};
-
-static struct dev_ops idnops = {
- DEVO_REV, /* devo_rev */
- 0, /* devo_refcnt */
- ddi_no_info, /* devo_getinfo */
- nulldev, /* devo_identify */
- nulldev, /* devo_probe */
- idnattach, /* devo_attach */
- idndetach, /* devo_detach */
- nodev, /* devo_reset */
- &cb_idnops, /* devo_cb_ops */
- (struct bus_ops *)NULL, /* devo_bus_ops */
- NULL, /* devo_power */
- ddi_quiesce_not_needed, /* quiesce */
-};
-
-extern cpuset_t cpu_ready_set;
-
-static struct modldrv modldrv = {
- &mod_driverops, /* This module is a pseudo driver */
- IDNDESC " 1.58",
- &idnops
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- &modldrv,
- NULL
-};
-
-/*
- * --------------------------------------------------
- */
-int
-_init(void)
-{
- idn.version = IDN_VERSION;
-
- return (mod_install(&modlinkage));
-}
-
-int
-_fini(void)
-{
- return (mod_remove(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-/*
- * ----------------------------------------------
- */
-static int
-idnattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
- int instance;
- int doinit = 0;
- processorid_t bcpuid;
- struct idn *sip;
- struct idnstr *stp;
- procname_t proc = "idnattach";
-
-
-#ifndef lint
- ASSERT(sizeof (idnsb_t) == IDNSB_SIZE);
- ASSERT(offsetof(struct idnsb, id_hwchkpt[0]) == 0x40);
-#endif /* lint */
-
- switch (cmd) {
- case DDI_RESUME:
- sip = ddi_get_driver_private(dip);
- /*
- * sip may have not yet been set if the
- * OBP environment variable (idn-smr-size)
- * was not set.
- */
- if (sip == NULL)
- return (DDI_FAILURE);
- /*
- * RESUME IDN services.
- */
- IDN_GLOCK_SHARED();
- if (idn.state != IDNGS_OFFLINE) {
- cmn_err(CE_WARN,
- "IDN: 101: not in expected OFFLINE state "
- "for DDI_RESUME");
- ASSERT(0);
- }
- IDN_GUNLOCK();
-
- /*
- * RESUME DLPI services.
- */
- sip->si_flags &= ~IDNSUSPENDED;
-
- rw_enter(&idn.struprwlock, RW_READER);
- for (stp = idn.strup; stp; stp = stp->ss_nextp)
- if (stp->ss_sip == sip) {
- doinit = 1;
- break;
- }
- rw_exit(&idn.struprwlock);
- if (doinit)
- (void) idndl_init(sip);
-
- return (DDI_SUCCESS);
-
- case DDI_ATTACH:
- break;
-
- default:
- return (DDI_FAILURE);
- }
-
- instance = ddi_get_instance(dip);
-
- PR_DRV("%s: instance = %d\n", proc, instance);
-
- if (idn_check_conf(dip, &bcpuid) == IDN_GPROPS_ERROR)
- return (DDI_FAILURE);
-
- mutex_enter(&idn.siplock);
-
- if (ddi_create_minor_node(dip, IDNNAME, S_IFCHR, instance,
- DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) {
- mutex_exit(&idn.siplock);
- return (DDI_FAILURE);
- }
-
- if (idn.smr.ready == 0) {
- if (idn_init_smr() == 0) {
- idn.enabled = 1;
-#ifdef DEBUG
- cmn_err(CE_NOTE, "!IDN: Driver enabled");
-#endif /* DEBUG */
- } else {
- cmn_err(CE_NOTE,
- "!IDN: 102: driver disabled "
- "- check OBP environment "
- "(idn-smr-size)");
- mutex_exit(&idn.siplock);
- return (DDI_SUCCESS);
- }
- }
-
- ASSERT(idn.smr.ready || idn.enabled);
-
- if (idn.dip == NULL) {
- doinit = 1;
-
- if (idn_size_check()) {
- idn_deinit_smr();
- ddi_remove_minor_node(dip, NULL);
- mutex_exit(&idn.siplock);
- return (DDI_FAILURE);
- }
-
- if (idn_init(dip)) {
- idn_deinit_smr();
- ddi_remove_minor_node(dip, NULL);
- mutex_exit(&idn.siplock);
- return (DDI_FAILURE);
- }
- }
-
- ASSERT(idn.dip);
-
- /*
- * This must occur _after_ idn_init() since
- * it assumes idn_chanservers_init() has been
- * called.
- */
- idn_chanserver_bind(ddi_get_instance(dip), bcpuid);
-
- /*
- * DLPI supporting stuff.
- */
- sip = GETSTRUCT(struct idn, 1);
- sip->si_dip = dip;
- ddi_set_driver_private(dip, sip);
- sip->si_nextp = idn.sip;
- idn.sip = sip;
- IDN_SET_INST2SIP(instance, sip);
- mutex_exit(&idn.siplock);
-
- if (doinit)
- idndl_dlpi_init(); /* initializes idninfoack */
- /*
- * Get our local IDN ethernet address.
- */
- idndl_localetheraddr(sip, &sip->si_ouraddr);
- idndl_statinit(sip);
-
- if (doinit) {
- idn_gkstat_init();
- /*
- * Add our sigblock SSP interrupt handler.
- */
- mutex_enter(&idn.sigbintr.sb_mutex);
- idn_sigbhandler_create();
- mutex_exit(&idn.sigbintr.sb_mutex);
-
- if (sgnblk_poll_register(idn_sigbhandler) == 0) {
- mutex_enter(&idn.sigbintr.sb_mutex);
- idn_sigbhandler_kill();
- idn.sigbintr.sb_cpuid = (uchar_t)-1;
- idn.sigbintr.sb_busy = IDNSIGB_INACTIVE;
- mutex_exit(&idn.sigbintr.sb_mutex);
-
- idn_gkstat_deinit();
-
- mutex_enter(&idn.siplock);
- (void) idn_deinit();
- IDN_SET_INST2SIP(instance, NULL);
- idn.sip = sip->si_nextp;
- mutex_exit(&idn.siplock);
-
- ddi_remove_minor_node(dip, NULL);
-
- return (DDI_FAILURE);
- }
- /*
- * We require sigblkp[cpu0] to be mapped for hardware
- * configuration determination and also auto-linking
- * on bootup.
- */
- if (sgnblk_poll_reference(idn_sigb_setup, NULL) != 0) {
- (void) sgnblk_poll_unregister(idn_sigbhandler);
- mutex_enter(&idn.sigbintr.sb_mutex);
- idn_sigbhandler_kill();
- idn.sigbintr.sb_cpuid = (uchar_t)-1;
- idn.sigbintr.sb_busy = IDNSIGB_INACTIVE;
- mutex_exit(&idn.sigbintr.sb_mutex);
-
- idn_gkstat_deinit();
-
- mutex_enter(&idn.siplock);
- (void) idn_deinit();
- IDN_SET_INST2SIP(instance, NULL);
- idn.sip = sip->si_nextp;
- mutex_exit(&idn.siplock);
-
- ddi_remove_minor_node(dip, NULL);
-
- cmn_err(CE_WARN,
- "IDN: 103: unable to reference sigblock area");
-
- return (DDI_FAILURE);
- }
-
- idn_init_autolink();
- }
-
- ddi_report_dev(dip);
-
- return (DDI_SUCCESS);
-}
-
-/*
- * ----------------------------------------------
- */
-static int
-idndetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
- int err = 0;
- int instance;
- struct idn *sip, *hsip, *tsip;
- procname_t proc = "idndetach";
-
- sip = ddi_get_driver_private(dip);
- instance = ddi_get_instance(dip);
-
- switch (cmd) {
- case DDI_SUSPEND:
- if (sip == NULL)
- return (DDI_FAILURE);
- /*
- * SUSPEND IDN services.
- * - Actually don't suspend anything, we just
- * make sure we're not connected per DR protocol.
- * If we really wanted to suspend it should
- * be done _after_ DLPI is suspended so that
- * we're not competing with that traffic.
- */
- IDN_GLOCK_SHARED();
-
- if (idn.state != IDNGS_OFFLINE) {
- int d;
-
- cmn_err(CE_WARN,
- "IDN: 104: cannot suspend while active "
- "(state = %s)",
- idngs_str[idn.state]);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- idn_domain_t *dp;
-
- dp = &idn_domain[d];
- if (dp->dcpu < 0)
- continue;
-
- cmn_err(CE_CONT,
- "IDN: 121: domain %d (CPU %d, name "
- "\"%s\", state %s)\n",
- d, dp->dcpu, dp->dname,
- idnds_str[dp->dstate]);
- }
- err = 1;
- }
-
- IDN_GUNLOCK();
-
- if (err)
- return (DDI_FAILURE);
- /*
- * SUSPEND DLPI services.
- */
- sip->si_flags |= IDNSUSPENDED;
-
- idndl_uninit(sip);
-
- return (DDI_FAILURE);
-
- case DDI_DETACH:
- if (idn.enabled == 0) {
- ddi_remove_minor_node(dip, NULL);
- ASSERT(idn.dip == NULL);
- return (DDI_SUCCESS);
- }
- if (!IDN_MODUNLOADABLE)
- return (DDI_FAILURE);
- break;
-
- default:
- return (DDI_FAILURE);
- }
-
- PR_DRV("%s: instance = %d\n", proc, instance);
-
- if (sip == NULL) {
- /*
- * No resources allocated.
- */
- return (DDI_SUCCESS);
- }
-
- mutex_enter(&idn.siplock);
- if (idn.sip && (idn.sip->si_nextp == NULL)) {
- /*
- * This is our last stream connection
- * going away. Time to deinit and flag
- * the SSP we're (IDN) DOWN.
- */
- if (idn_deinit()) {
- /*
- * Must still be active.
- */
- mutex_exit(&idn.siplock);
- return (DDI_FAILURE);
- }
- idn_deinit_autolink();
- /*
- * Remove our sigblock SSP interrupt handler.
- */
- (void) sgnblk_poll_unregister(idn_sigbhandler);
- mutex_enter(&idn.sigbintr.sb_mutex);
- idn_sigbhandler_kill();
- idn.sigbintr.sb_cpuid = (uchar_t)-1;
- idn.sigbintr.sb_busy = IDNSIGB_NOTREADY;
- mutex_exit(&idn.sigbintr.sb_mutex);
- /*
- * Remove our reference to the sigblock area.
- */
- sgnblk_poll_unreference(idn_sigb_setup);
- idn_gkstat_deinit();
- }
-
- ddi_remove_minor_node(dip, NULL);
-
- /*
- * Remove this instance from our linked list.
- */
- IDN_SET_INST2SIP(instance, NULL);
- if ((hsip = tsip = idn.sip) == sip) {
- idn.sip = sip->si_nextp;
- } else {
- for (; hsip && (sip != hsip); tsip = hsip,
- hsip = hsip->si_nextp)
- ;
- if (hsip)
- tsip->si_nextp = hsip->si_nextp;
- }
- mutex_exit(&idn.siplock);
- if (sip->si_ksp)
- kstat_delete(sip->si_ksp);
-
- ddi_set_driver_private(dip, NULL);
-
- FREESTRUCT(sip, struct idn, 1);
-
- return (DDI_SUCCESS);
-}
-
-/*
- * ----------------------------------------------
- */
-static idn_gprops_t
-idn_check_conf(dev_info_t *dip, processorid_t *cpuid)
-{
- static idn_gprops_t global_props = IDN_GPROPS_UNCHECKED;
-
- if (global_props == IDN_GPROPS_UNCHECKED) {
- int p;
-
- global_props = IDN_GPROPS_OKAY;
-
- for (p = 0; idn_global_props[p].p_string; p++) {
- char *str;
- int *var;
- int val, v_min, v_max, v_def;
-
- str = idn_global_props[p].p_string;
- var = (int *)idn_global_props[p].p_var;
- v_min = idn_global_props[p].p_min;
- v_max = idn_global_props[p].p_max;
- v_def = idn_global_props[p].p_def;
- ASSERT(str && var);
-
- val = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
- DDI_PROP_DONTPASS |
- DDI_PROP_NOTPROM,
- str, v_def);
- if ((v_min != v_max) &&
- ((val < v_min) || (val > v_max))) {
- cmn_err(CE_WARN,
- "IDN: 105: driver parameter "
- "(%s) specified (%d) out of "
- "range [%d - %d]",
- str, val, v_min, v_max);
- global_props = IDN_GPROPS_ERROR;
- } else {
- *var = val;
- }
- }
- }
-
- *cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
- DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
- "bind_cpu", -1);
-
- return (global_props);
-}
-
-static int
-idn_size_check()
-{
- int i, cnt;
- int rv = 0;
- ulong_t mboxareasize;
- int max_num_slabs;
- procname_t proc = "idn_size_check";
-
- if (IDN_NWR_SIZE == 0)
- IDN_NWR_SIZE = IDN_SMR_SIZE;
-
- if (IDN_NWR_SIZE > IDN_SMR_SIZE) {
- cmn_err(CE_WARN,
- "IDN: 106: idn_nwr_size(%d) > idn_smr_size(%d)"
- " - Limiting to %d MB",
- IDN_NWR_SIZE, IDN_SMR_SIZE, IDN_SMR_SIZE);
- IDN_NWR_SIZE = IDN_SMR_SIZE;
- }
-
- if (MB2B(IDN_NWR_SIZE) < IDN_SLAB_SIZE) {
- cmn_err(CE_WARN,
- "IDN: 107: memory region(%lu) < slab size(%u)",
- MB2B(IDN_NWR_SIZE), IDN_SLAB_SIZE);
- rv = -1;
- }
-
- if (IDN_LOWAT >= IDN_HIWAT) {
- cmn_err(CE_WARN,
- "IDN: 108: idn_lowat(%d) >= idn_hiwat(%d)",
- IDN_LOWAT, IDN_HIWAT);
- rv = -1;
- }
-
- mboxareasize = (ulong_t)(IDN_MBOXAREA_SIZE + (IDN_SMR_BUFSIZE - 1));
- mboxareasize &= ~((ulong_t)IDN_SMR_BUFSIZE - 1);
-#ifdef DEBUG
- if ((ulong_t)IDN_SLAB_SIZE < mboxareasize) {
- PR_DRV("%s: slab size(%d) < mailbox area(%ld)",
- proc, IDN_SLAB_SIZE, mboxareasize);
- /* not fatal */
- }
-#endif /* DEBUG */
-
- if ((mboxareasize + (ulong_t)IDN_SLAB_SIZE) > MB2B(IDN_NWR_SIZE)) {
- cmn_err(CE_WARN,
- "IDN: 109: mailbox area(%lu) + slab size(%u) "
- "> nwr region(%lu)",
- mboxareasize, IDN_SLAB_SIZE,
- MB2B(IDN_NWR_SIZE));
- rv = -1;
- }
-
- max_num_slabs = (int)((MB2B(IDN_NWR_SIZE) - mboxareasize) /
- (ulong_t)IDN_SLAB_SIZE);
- if (max_num_slabs < IDN_SLAB_MINTOTAL) {
- cmn_err(CE_WARN,
- "IDN: 110: maximum number of slabs(%d) < "
- "minimum required(%d)",
- max_num_slabs, IDN_SLAB_MINTOTAL);
- rv = -1;
- } else {
- IDN_SLAB_MAXPERDOMAIN = max_num_slabs / IDN_SLAB_MINTOTAL;
- }
-
-#if 0
- if ((IDN_MTU + sizeof (struct ether_header)) > IDN_DATA_SIZE) {
- cmn_err(CE_WARN,
- "IDN: (IDN_MTU(%d) + ether_header(%d)) "
- "> IDN_DATA_SIZE(%lu)",
- IDN_MTU, sizeof (struct ether_header),
- IDN_DATA_SIZE);
- rv = -1;
- }
-#endif /* 0 */
-
- if (IDN_SMR_BUFSIZE & (IDN_ALIGNSIZE - 1)) {
- cmn_err(CE_WARN,
- "IDN: 111: idn_smr_bufsize(%d) not on a "
- "64 byte boundary", IDN_SMR_BUFSIZE);
- rv = -1;
- }
-
- for (i = cnt = 0;
- (cnt <= 1) && (((ulong_t)1 << i) < MB2B(IDN_NWR_SIZE));
- i++)
- if ((1 << i) & IDN_SMR_BUFSIZE)
- cnt++;
- if ((i > 0) && (!cnt || (cnt > 1))) {
- cmn_err(CE_WARN,
- "IDN: 112: idn_smr_bufsize(%d) not a power of 2",
- IDN_SMR_BUFSIZE);
- rv = -1;
- }
-
- if ((IDN_MBOX_PER_NET & 1) == 0) {
- cmn_err(CE_WARN,
- "IDN: 113: idn_mbox_per_net(%d) must be an "
- "odd number", IDN_MBOX_PER_NET);
- rv = -1;
- }
-
- if (idn.nchannels > 0)
- IDN_WINDOW_EMAX = IDN_WINDOW_MAX +
- ((idn.nchannels - 1) * IDN_WINDOW_INCR);
-
- if (IDN_NETSVR_WAIT_MIN > IDN_NETSVR_WAIT_MAX) {
- cmn_err(CE_WARN,
- "IDN: 115: idn_netsvr_wait_min(%d) cannot be "
- "greater than idn_netsvr_wait_max(%d)",
- IDN_NETSVR_WAIT_MIN,
- IDN_NETSVR_WAIT_MAX);
- rv = -1;
- }
-
- return (rv);
-}
-
-static int
-idn_init_smr()
-{
- uint64_t obp_paddr;
- uint64_t obp_size; /* in Bytes */
- uint_t smr_size; /* in MBytes */
- pgcnt_t npages;
- procname_t proc = "idn_init_smr";
-
- if (idn.smr.ready)
- return (0);
-
- if (idn_prom_getsmr(&smr_size, &obp_paddr, &obp_size) < 0)
- return (-1);
-
- PR_PROTO("%s: smr_size = %d, obp_paddr = 0x%lx, obp_size = 0x%lx\n",
- proc, smr_size, obp_paddr, obp_size);
-
- if (IDN_SMR_SIZE)
- smr_size = MIN(smr_size, IDN_SMR_SIZE);
-
- npages = btopr(MB2B(smr_size));
-
- idn.smr.prom_paddr = obp_paddr;
- idn.smr.prom_size = obp_size;
- idn.smr.vaddr = vmem_alloc(heap_arena, ptob(npages), VM_SLEEP);
- ASSERT(((ulong_t)idn.smr.vaddr & MMU_PAGEOFFSET) == 0);
- idn.smr.locpfn = (pfn_t)(obp_paddr >> MMU_PAGESHIFT);
- idn.smr.rempfn = idn.smr.rempfnlim = PFN_INVALID;
- IDN_SMR_SIZE = smr_size;
-
- PR_PROTO("%s: smr vaddr = %p\n", proc, (void *)idn.smr.vaddr);
-
- smr_remap(&kas, idn.smr.vaddr, idn.smr.locpfn, IDN_SMR_SIZE);
-
- idn.localid = PADDR_TO_DOMAINID(obp_paddr);
-
- idn.smr.ready = 1;
-
- return (0);
-}
-
-static void
-idn_deinit_smr()
-{
- pgcnt_t npages;
-
- if (idn.smr.ready == 0)
- return;
-
- smr_remap(&kas, idn.smr.vaddr, PFN_INVALID, IDN_SMR_SIZE);
-
- npages = btopr(MB2B(IDN_SMR_SIZE));
-
- vmem_free(heap_arena, idn.smr.vaddr, ptob(npages));
-
- idn.localid = IDN_NIL_DOMID;
-
- IDN_SMR_SIZE = 0;
-
- idn.smr.ready = 0;
-}
-
-/*ARGSUSED1*/
-static void
-idn_sigb_setup(cpu_sgnblk_t *sigbp, void *arg)
-{
- procname_t proc = "idn_sigb_setup";
-
- PR_PROTO("%s: Setting sigb to %p\n", proc, (void *)sigbp);
-
- mutex_enter(&idn.idnsb_mutex);
- if (sigbp == NULL) {
- idn.idnsb = NULL;
- idn.idnsb_eventp = NULL;
- mutex_exit(&idn.idnsb_mutex);
- return;
- }
- idn.idnsb_eventp = (idnsb_event_t *)sigbp->sigb_idn;
- idn.idnsb = (idnsb_t *)&idn.idnsb_eventp->idn_reserved1;
- mutex_exit(&idn.idnsb_mutex);
-}
-
-static int
-idn_init(dev_info_t *dip)
-{
- struct hwconfig local_hw;
- procname_t proc = "idn_init";
-
-
- ASSERT(MUTEX_HELD(&idn.siplock));
-
- if (!idn.enabled) {
- cmn_err(CE_WARN,
- "IDN: 117: IDN not enabled");
- return (-1);
- }
-
- if (idn.dip != NULL) {
- PR_DRV("%s: already initialized (dip = 0x%p)\n",
- proc, (void *)idn.dip);
- return (0);
- }
-
- /*
- * Determine our local domain's hardware configuration.
- */
- if (get_hw_config(&local_hw)) {
- cmn_err(CE_WARN,
- "IDN: 118: hardware config not appropriate");
- return (-1);
- }
-
- PR_DRV("%s: locpfn = 0x%lx\n", proc, idn.smr.locpfn);
- PR_DRV("%s: rempfn = 0x%lx\n", proc, idn.smr.rempfn);
- PR_DRV("%s: smrsize = %d MB\n", proc, IDN_SMR_SIZE);
-
- rw_init(&idn.grwlock, NULL, RW_DEFAULT, NULL);
- rw_init(&idn.struprwlock, NULL, RW_DEFAULT, NULL);
- mutex_init(&idn.sync.sz_mutex, NULL, MUTEX_DEFAULT, NULL);
- mutex_init(&idn.sipwenlock, NULL, MUTEX_DEFAULT, NULL);
-
- /*
- * Calculate proper value for idn.bframe_shift.
- * Kind of hokey as it assume knowledge of the format
- * of the idnparam_t structure.
- */
- {
- int s;
-
- for (s = 0; (1 << s) < IDN_SMR_BUFSIZE_MIN; s++)
- ;
- idn.bframe_shift = s;
- PR_DRV("%s: idn.bframe_shift = %d, minbuf = %d\n",
- proc, idn.bframe_shift, IDN_SMR_BUFSIZE_MIN);
-
- ASSERT((uint_t)IDN_OFFSET2BFRAME(MB2B(idn_smr_size)) <
- (1 << 24));
- }
-
- idn_xmit_monitor_init();
-
- /*
- * Initialize the domain op (dopers) stuff.
- */
- idn_dopers_init();
-
- /*
- * Initialize the timer (kmem) cache used for timeout
- * structures.
- */
- idn_timercache_init();
-
- /*
- * Initialize the slab waiting areas.
- */
- (void) smr_slabwaiter_init();
-
- /*
- * Initialize retryjob kmem cache.
- */
- idn_retrytask_init();
-
- idn_init_msg_waittime();
- idn_init_msg_retrytime();
-
- /*
- * Initialize idn_domains[] and local domains information
- * include idn_global information.
- */
- idn_domains_init(&local_hw);
-
- /*
- * Start up IDN protocol servers.
- */
- if (idn_protocol_init(idn_protocol_nservers) <= 0) {
- cmn_err(CE_WARN,
- "IDN: 119: failed to initialize %d protocol servers",
- idn_protocol_nservers);
- idn_domains_deinit();
- idn_retrytask_deinit();
- smr_slabwaiter_deinit();
- idn_timercache_deinit();
- idn_dopers_deinit();
- idn_xmit_monitor_deinit();
- mutex_destroy(&idn.sipwenlock);
- mutex_destroy(&idn.sync.sz_mutex);
- rw_destroy(&idn.grwlock);
- rw_destroy(&idn.struprwlock);
- return (-1);
- }
-
- /*
- * Initialize chan_servers array.
- */
- (void) idn_chanservers_init();
-
- /*
- * Need to register the IDN handler with the DMV subsystem.
- *
- * Need to prevent the IDN driver from being unloaded
- * once loaded since DMV's may come in at any time.
- * If the driver is not loaded and the idn_dmv_handler
- * has been registered with the DMV, system will crash.
- */
- (void) idn_init_handler();
-
- idn.dip = dip;
- IDN_GLOCK_EXCL();
- IDN_GSTATE_TRANSITION(IDNGS_OFFLINE);
- IDN_GUNLOCK();
-
- return (0);
-}
-
-static int
-idn_deinit()
-{
- procname_t proc = "idn_deinit";
-
- ASSERT(MUTEX_HELD(&idn.siplock));
-
- IDN_GLOCK_EXCL();
-
- if (idn.state != IDNGS_OFFLINE) {
- int d;
-
- cmn_err(CE_WARN,
- "IDN: 120: cannot deinit while active "
- "(state = %s)", idngs_str[idn.state]);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- idn_domain_t *dp;
-
- dp = &idn_domain[d];
- if (dp->dcpu < 0)
- continue;
-
- cmn_err(CE_CONT,
- "IDN: 121: domain %d (CPU %d, "
- "name \"%s\", state %s)\n",
- d, dp->dcpu, dp->dname,
- idnds_str[dp->dstate]);
- }
- IDN_GUNLOCK();
- return (-1);
- }
-
- if (idn.dip == NULL) {
- PR_DRV("%s: already deinitialized\n", proc);
- IDN_GUNLOCK();
- return (0);
- }
-
- IDN_GSTATE_TRANSITION(IDNGS_IGNORE);
-
- IDN_GUNLOCK();
-
- idn_xmit_monitor_deinit();
-
- idn_deinit_handler();
-
- idn_chanservers_deinit();
-
- idn.nchannels = 0;
- ASSERT(idn.chan_servers == NULL);
-
- smr_slabpool_deinit();
-
- idn_protocol_deinit();
-
- idn_domains_deinit();
-
- smr_slabwaiter_deinit();
-
- idn_retrytask_deinit();
-
- idn_timercache_deinit();
-
- idn_dopers_deinit();
-
- ASSERT(idn.localid == IDN_NIL_DOMID);
-
- IDN_SET_MASTERID(IDN_NIL_DOMID);
-
- idn_deinit_smr();
-
- mutex_destroy(&idn.sipwenlock);
- mutex_destroy(&idn.sync.sz_mutex);
- rw_destroy(&idn.grwlock);
- rw_destroy(&idn.struprwlock);
-
- idn.dip = NULL;
-
- return (0);
-}
-
-static void
-idn_xmit_monitor_init()
-{
- mutex_init(&idn.xmit_lock, NULL, MUTEX_DEFAULT, NULL);
- idn.xmit_tid = (timeout_id_t)NULL;
- CHANSET_ZERO(idn.xmit_chanset_wanted);
-}
-
-static void
-idn_xmit_monitor_deinit()
-{
- timeout_id_t tid;
-
- mutex_enter(&idn.xmit_lock);
- CHANSET_ZERO(idn.xmit_chanset_wanted);
- if ((tid = idn.xmit_tid) != (timeout_id_t)NULL) {
- idn.xmit_tid = (timeout_id_t)NULL;
- mutex_exit(&idn.xmit_lock);
- (void) untimeout(tid);
- } else {
- mutex_exit(&idn.xmit_lock);
- }
- mutex_destroy(&idn.xmit_lock);
-}
-
-static void
-idn_init_msg_waittime()
-{
- idn_msg_waittime[IDNP_NULL] = -1;
- idn_msg_waittime[IDNP_NEGO] = idn_msgwait_nego * hz;
- idn_msg_waittime[IDNP_CFG] = idn_msgwait_cfg * hz;
- idn_msg_waittime[IDNP_CON] = idn_msgwait_con * hz;
- idn_msg_waittime[IDNP_FIN] = idn_msgwait_fin * hz;
- idn_msg_waittime[IDNP_CMD] = idn_msgwait_cmd * hz;
- idn_msg_waittime[IDNP_DATA] = idn_msgwait_data * hz;
-}
-
-static void
-idn_init_msg_retrytime()
-{
- idn_msg_retrytime[(int)IDNRETRY_NIL] = -1;
- idn_msg_retrytime[(int)IDNRETRY_NEGO] = idn_retryfreq_nego * hz;
- idn_msg_retrytime[(int)IDNRETRY_CON] = idn_retryfreq_con * hz;
- idn_msg_retrytime[(int)IDNRETRY_CONQ] = idn_retryfreq_con * hz;
- idn_msg_retrytime[(int)IDNRETRY_FIN] = idn_retryfreq_fin * hz;
- idn_msg_retrytime[(int)IDNRETRY_FINQ] = idn_retryfreq_fin * hz;
-}
-
-/*
- * ----------------------------------------------
- */
-/*ARGSUSED*/
-static int
-idnopen(register queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *crp)
-{
- register int err = 0;
- int minordev;
- struct idnstr *stp, **pstp;
- procname_t proc = "idnopen";
-
- ASSERT(sflag != MODOPEN);
-
- IDN_GLOCK_EXCL();
-
- rw_enter(&idn.struprwlock, RW_WRITER);
- mutex_enter(&idn.sipwenlock);
- pstp = &idn.strup;
-
- if (idn.enabled == 0) {
- PR_DRV("%s: Driver disabled (check OBP:idn-smr-size)\n",
- proc);
- mutex_exit(&idn.sipwenlock);
- rw_exit(&idn.struprwlock);
- IDN_GUNLOCK();
- return (EACCES);
- }
-
- if (!idn_ndlist &&
- idn_param_register(idn_param_arr, A_CNT(idn_param_arr))) {
- PR_DRV("%s: failed to register ndd parameters\n", proc);
- mutex_exit(&idn.sipwenlock);
- rw_exit(&idn.struprwlock);
- IDN_GUNLOCK();
- return (ENOMEM);
- }
- IDN_GUNLOCK();
-
- if (sflag == CLONEOPEN) {
- minordev = 0;
- for (stp = *pstp; stp; pstp = &stp->ss_nextp, stp = *pstp) {
- if (minordev < stp->ss_minor)
- break;
- minordev++;
- }
- *devp = makedevice(getmajor(*devp), minordev);
- } else {
- minordev = getminor(*devp);
- }
- if (rq->q_ptr)
- goto done;
-
- stp = GETSTRUCT(struct idnstr, 1);
- stp->ss_rq = rq;
- stp->ss_minor = minordev;
- rw_init(&stp->ss_rwlock, NULL, RW_DEFAULT, NULL);
- /*
- * DLPI stuff
- */
- stp->ss_sip = NULL;
- stp->ss_state = DL_UNATTACHED;
- stp->ss_sap = 0;
- stp->ss_flags = 0;
- stp->ss_mccount = 0;
- stp->ss_mctab = NULL;
-
- /*
- * Link new entry into list of actives.
- */
- stp->ss_nextp = *pstp;
- *pstp = stp;
-
- WR(rq)->q_ptr = rq->q_ptr = (void *)stp;
- /*
- * Disable automatic enabling of our write service
- * procedure. We control this explicitly.
- */
- noenable(WR(rq));
-
- /*
- * Set our STREAMs queue maximum packet size that
- * we'll accept and our high/low water marks.
- */
- (void) strqset(WR(rq), QMAXPSZ, 0, IDN_DATA_SIZE);
- (void) strqset(WR(rq), QLOWAT, 0, IDN_LOWAT);
- (void) strqset(WR(rq), QHIWAT, 0, IDN_HIWAT);
- (void) strqset(rq, QMAXPSZ, 0, IDN_DATA_SIZE);
- (void) strqset(rq, QLOWAT, 0, IDN_LOWAT);
- (void) strqset(rq, QHIWAT, 0, IDN_HIWAT);
-
-done:
- mutex_exit(&idn.sipwenlock);
- rw_exit(&idn.struprwlock);
-
- (void) qassociate(rq, -1);
- qprocson(rq);
-
- return (err);
-}
-
-/*
- * ----------------------------------------------
- */
-/*ARGSUSED1*/
-static int
-idnclose(queue_t *rq, int flag, cred_t *crp)
-{
- struct idnstr *stp, **pstp;
-
- ASSERT(rq->q_ptr);
-
- qprocsoff(rq);
- /*
- * Guaranteed to be single threaded with respect
- * to this stream at this point.
- */
-
- stp = (struct idnstr *)rq->q_ptr;
-
- if (stp->ss_sip)
- idndl_dodetach(stp);
-
- rw_enter(&idn.struprwlock, RW_WRITER);
- mutex_enter(&idn.sipwenlock);
- pstp = &idn.strup;
- for (stp = *pstp; stp; pstp = &stp->ss_nextp, stp = *pstp)
- if (stp == (struct idnstr *)rq->q_ptr)
- break;
- ASSERT(stp);
- ASSERT(stp->ss_rq == rq);
- *pstp = stp->ss_nextp;
-
- rw_destroy(&stp->ss_rwlock);
- FREESTRUCT(stp, struct idnstr, 1);
-
- WR(rq)->q_ptr = rq->q_ptr = NULL;
- mutex_exit(&idn.sipwenlock);
- rw_exit(&idn.struprwlock);
-
- idn_param_cleanup();
- (void) qassociate(rq, -1);
-
- return (0);
-}
-
-/*
- * ----------------------------------------------
- */
-static int
-idnwput(register queue_t *wq, register mblk_t *mp)
-{
- register struct idnstr *stp;
- struct idn *sip;
- procname_t proc = "idnwput";
-
- stp = (struct idnstr *)wq->q_ptr;
- sip = stp->ss_sip;
-
- switch (DB_TYPE(mp)) {
- case M_IOCTL:
- idnioctl(wq, mp);
- break;
-
- case M_DATA:
- if (((stp->ss_flags & (IDNSFAST|IDNSRAW)) == 0) ||
- (stp->ss_state != DL_IDLE) ||
- (sip == NULL)) {
- PR_DLPI("%s: fl=0x%x, st=0x%x, ret(EPROTO)\n",
- proc, stp->ss_flags, stp->ss_state);
- merror(wq, mp, EPROTO);
-
- } else if (wq->q_first) {
- if (putq(wq, mp) == 0)
- freemsg(mp);
- /*
- * We're only holding the reader lock,
- * but that's okay since this field
- * is just a soft-flag.
- */
- sip->si_wantw = 1;
- qenable(wq);
-
- } else if (sip->si_flags & IDNPROMISC) {
- if (putq(wq, mp) == 0) {
- PR_DLPI("%s: putq failed\n", proc);
- freemsg(mp);
- } else {
- PR_DLPI("%s: putq succeeded\n", proc);
- }
- qenable(wq);
-
- } else {
- PR_DLPI("%s: idndl_start(sip=0x%p)\n",
- proc, (void *)sip);
- rw_enter(&stp->ss_rwlock, RW_READER);
- (void) idndl_start(wq, mp, sip);
- rw_exit(&stp->ss_rwlock);
- }
- break;
-
- case M_PROTO:
- case M_PCPROTO:
- /*
- * Break the association between the current thread
- * and the thread that calls idndl_proto() to resolve
- * the problem of idn_chan_server() threads which
- * loop back around to call idndl_proto and try to
- * recursively acquire internal locks.
- */
- if (putq(wq, mp) == 0)
- freemsg(mp);
- qenable(wq);
- break;
-
- case M_FLUSH:
- PR_STR("%s: M_FLUSH request (flush = %d)\n",
- proc, (int)*mp->b_rptr);
- if (*mp->b_rptr & FLUSHW) {
- flushq(wq, FLUSHALL);
- *mp->b_rptr &= ~FLUSHW;
- }
- if (*mp->b_rptr & FLUSHR)
- qreply(wq, mp);
- else
- freemsg(mp);
- break;
-
- default:
- PR_STR("%s: unexpected DB_TYPE 0x%x\n",
- proc, DB_TYPE(mp));
- freemsg(mp);
- break;
- }
-
- return (0);
-}
-
-/*
- * ----------------------------------------------
- */
-static int
-idnwsrv(queue_t *wq)
-{
- mblk_t *mp;
- int err = 0;
- struct idnstr *stp;
- struct idn *sip;
- procname_t proc = "idnwsrv";
-
- stp = (struct idnstr *)wq->q_ptr;
- sip = stp->ss_sip;
-
- while (mp = getq(wq)) {
- switch (DB_TYPE(mp)) {
- case M_DATA:
- if (sip) {
- PR_DLPI("%s: idndl_start(sip=0x%p)\n",
- proc, (void *)sip);
- rw_enter(&stp->ss_rwlock, RW_READER);
- err = idndl_start(wq, mp, sip);
- rw_exit(&stp->ss_rwlock);
- if (err)
- goto done;
- } else {
- PR_DLPI("%s: NO sip to start msg\n", proc);
- freemsg(mp);
- }
- break;
-
- case M_PROTO:
- case M_PCPROTO:
- idndl_proto(wq, mp);
- break;
-
- default:
- ASSERT(0);
- PR_STR("%s: unexpected db_type (%d)\n",
- proc, DB_TYPE(mp));
- freemsg(mp);
- break;
- }
- }
-done:
- return (0);
-}
-
-/*
- * ----------------------------------------------
- */
-static int
-idnrput(register queue_t *rq, register mblk_t *mp)
-{
- register int err = 0;
- procname_t proc = "idnrput";
-
- switch (DB_TYPE(mp)) {
- case M_DATA:
- /*
- * Should not reach here with data packets
- * if running DLPI.
- */
- cmn_err(CE_WARN,
- "IDN: 123: unexpected M_DATA packets for "
- "q_stream 0x%p", (void *)rq->q_stream);
- freemsg(mp);
- err = ENXIO;
- break;
-
- case M_FLUSH:
- PR_STR("%s: M_FLUSH request (flush = %d)\n",
- proc, (int)*mp->b_rptr);
- if (*mp->b_rptr & FLUSHR)
- flushq(rq, FLUSHALL);
- (void) putnext(rq, mp);
- break;
-
- case M_ERROR:
- PR_STR("%s: M_ERROR (error = %d) coming through\n",
- proc, (int)*mp->b_rptr);
- (void) putnext(rq, mp);
- break;
- default:
- PR_STR("%s: unexpected DB_TYPE 0x%x\n",
- proc, DB_TYPE(mp));
- freemsg(mp);
- err = ENXIO;
- break;
- }
-
- return (err);
-}
-
-/*
- * ----------------------------------------------
- * Not allowed to enqueue messages! Only M_DATA messages
- * can be enqueued on the write stream.
- * ----------------------------------------------
- */
-static void
-idnioctl(register queue_t *wq, register mblk_t *mp)
-{
- register struct iocblk *iocp;
- register int cmd;
- idnop_t *idnop = NULL;
- int error = 0;
- int argsize;
- procname_t proc = "idnioctl";
-
- iocp = (struct iocblk *)mp->b_rptr;
- cmd = iocp->ioc_cmd;
-
- /*
- * Intercept DLPI ioctl's.
- */
- if (VALID_DLPIOP(cmd)) {
- PR_STR("%s: DLPI ioctl(%d)\n", proc, cmd);
- error = idnioc_dlpi(wq, mp, &argsize);
- goto done;
- }
-
- /*
- * Validate expected arguments.
- */
- if (!VALID_IDNIOCTL(cmd)) {
- PR_STR("%s: invalid cmd (0x%x)\n", proc, cmd);
- error = EINVAL;
- goto done;
-
- } else if (!VALID_NDOP(cmd)) {
- error = miocpullup(mp, sizeof (idnop_t));
- if (error != 0) {
- PR_STR("%s: idnioc(cmd = 0x%x) miocpullup "
- "failed (%d)\n", proc, cmd, error);
- goto done;
- }
- }
-
- argsize = mp->b_cont->b_wptr - mp->b_cont->b_rptr;
- idnop = (idnop_t *)mp->b_cont->b_rptr;
-
- switch (cmd) {
- case IDNIOC_LINK:
- error = idnioc_link(idnop);
- break;
-
- case IDNIOC_UNLINK:
- error = idnioc_unlink(idnop);
- break;
-
- case IDNIOC_MEM_RW:
- error = idn_rw_mem(idnop);
- break;
-
- case IDNIOC_PING:
- error = idn_send_ping(idnop);
- break;
-
- case ND_SET:
- IDN_GLOCK_EXCL();
- if (!nd_getset(wq, idn_ndlist, mp)) {
- IDN_GUNLOCK();
- error = ENOENT;
- break;
- }
- IDN_GUNLOCK();
- qreply(wq, mp);
- return;
-
- case ND_GET:
- IDN_GLOCK_SHARED();
- if (!nd_getset(wq, idn_ndlist, mp)) {
- IDN_GUNLOCK();
- error = ENOENT;
- break;
- }
- IDN_GUNLOCK();
- qreply(wq, mp);
- return;
-
- default:
- PR_STR("%s: invalid cmd 0x%x\n", proc, cmd);
- error = EINVAL;
- break;
- }
-
-done:
- if (error == 0)
- miocack(wq, mp, argsize, 0);
- else
- miocnak(wq, mp, 0, error);
-}
-
-/*
- * This thread actually services the SSI_LINK/UNLINK calls
- * asynchronously that come via BBSRAM. This is necessary
- * since we can't process them from within the context of
- * the interrupt handler in which idn_sigbhandler() is
- * called.
- */
-static void
-idn_sigbhandler_thread(struct sigbintr **sbpp)
-{
- int d, pri, rv;
- struct sigbintr *sbp;
- sigbmbox_t *mbp;
- idn_fin_t fintype;
- idnsb_data_t *sdp;
- idnsb_info_t *sfp;
- idnsb_error_t *sep;
- idn_domain_t *dp;
- procname_t proc = "idn_sigbhandler_thread";
-
-
- sbp = *sbpp;
-
- PR_PROTO("%s: KICKED OFF (sigbintr pointer = 0x%p)\n",
- proc, (void *)sbp);
-
- ASSERT(sbp == &idn.sigbintr);
-
- mutex_enter(&idn.sigbintr.sb_mutex);
-
- while (sbp->sb_busy != IDNSIGB_DIE) {
- cpu_sgnblk_t *sigbp;
-
- while ((sbp->sb_busy != IDNSIGB_ACTIVE) &&
- (sbp->sb_busy != IDNSIGB_DIE)) {
- cv_wait(&sbp->sb_cv, &idn.sigbintr.sb_mutex);
- PR_PROTO("%s: AWAKENED (busy = %d)\n",
- proc, (int)sbp->sb_busy);
- }
- if (sbp->sb_busy == IDNSIGB_DIE) {
- PR_PROTO("%s: DIE REQUESTED\n", proc);
- break;
- }
-
- if ((sigbp = cpu_sgnblkp[sbp->sb_cpuid]) == NULL) {
- cmn_err(CE_WARN,
- "IDN: 124: sigblk for CPU ID %d "
- "is NULL", sbp->sb_cpuid);
- sbp->sb_busy = IDNSIGB_INACTIVE;
- continue;
- }
-
- mbp = &sigbp->sigb_host_mbox;
-
- if (mbp->flag != SIGB_MBOX_BUSY) {
- PR_PROTO("%s: sigblk mbox flag (%d) != BUSY (%d)\n",
- proc, mbp->flag, SIGB_MBOX_BUSY);
- sbp->sb_busy = IDNSIGB_INACTIVE;
- continue;
- }
- /*
- * The sb_busy bit is set and the mailbox flag
- * indicates BUSY also, so we effectively have things locked.
- * So, we can drop the critical sb_mutex which we want to
- * do since it pushes us to PIL 14 while we hold it and we
- * don't want to run at PIL 14 across IDN code.
- */
- mutex_exit(&idn.sigbintr.sb_mutex);
-
- sdp = (idnsb_data_t *)mbp->data;
- sep = (idnsb_error_t *)&sdp->ssb_error;
- INIT_IDNKERR(sep);
-
- if (mbp->len != sizeof (idnsb_data_t)) {
- PR_PROTO("%s: sigblk mbox length (%d) != "
- "expected (%lu)\n", proc, mbp->len,
- sizeof (idnsb_data_t));
- SET_IDNKERR_ERRNO(sep, EINVAL);
- SET_IDNKERR_IDNERR(sep, IDNKERR_DATA_LEN);
- SET_IDNKERR_PARAM0(sep, sizeof (idnsb_data_t));
-
- goto sberr;
-
- }
- if (idn.enabled == 0) {
-#ifdef DEBUG
- cmn_err(CE_NOTE,
- "IDN: 102: driver disabled "
- "- check OBP environment "
- "(idn-smr-size)");
-#else /* DEBUG */
- cmn_err(CE_NOTE,
- "!IDN: 102: driver disabled "
- "- check OBP environment "
- "(idn-smr-size)");
-#endif /* DEBUG */
- SET_IDNKERR_ERRNO(sep, EACCES);
- SET_IDNKERR_IDNERR(sep, IDNKERR_DRV_DISABLED);
-
- goto sberr;
-
- }
-
- switch (mbp->cmd) {
-
- case SSI_LINK:
- {
- idnsb_link_t slp;
-
- bcopy(&sdp->ssb_link, &slp, sizeof (slp));
-
- if (slp.master_pri < 0) {
- pri = IDNVOTE_MINPRI;
- } else if (slp.master_pri > 0) {
- /*
- * If I'm already in a IDN network,
- * then my vote priority is set to
- * the max, otherwise it's one-less.
- */
- pri = IDNVOTE_MAXPRI;
- IDN_GLOCK_SHARED();
- if (idn.ndomains <= 1)
- pri--;
- IDN_GUNLOCK();
- } else {
- pri = IDNVOTE_DEFPRI;
- }
-
- PR_PROTO("%s: SSI_LINK(cpuid = %d, domid = %d, "
- "pri = %d (req = %d), t/o = %d)\n",
- proc, slp.cpuid, slp.domid, pri,
- slp.master_pri, slp.timeout);
-
- rv = idn_link(slp.domid, slp.cpuid, pri,
- slp.timeout, sep);
- SET_IDNKERR_ERRNO(sep, rv);
- (void) idn_info(&sdp->ssb_info);
- break;
- }
-
- case SSI_UNLINK:
- {
- idnsb_unlink_t sup;
- idn_domain_t *xdp;
- domainset_t domset;
-
- bcopy(&sdp->ssb_unlink, &sup, sizeof (sup));
-
- PR_PROTO("%s: SSI_UNLINK(c = %d, d = %d, bs = 0x%x, "
- "f = %d, is = 0x%x, t/o = %d)\n",
- proc, sup.cpuid, sup.domid, sup.boardset,
- sup.force, sup.idnset, sup.timeout);
-
- domset = idn.domset.ds_trans_on |
- idn.domset.ds_connected |
- idn.domset.ds_trans_off |
- idn.domset.ds_awol |
- idn.domset.ds_relink;
-
- if (VALID_DOMAINID(sup.domid)) {
- dp = &idn_domain[sup.domid];
- } else if (VALID_CPUID(sup.cpuid)) {
- for (d = 0; d < MAX_DOMAINS; d++) {
- xdp = &idn_domain[d];
-
- if ((xdp->dcpu == IDN_NIL_DCPU) &&
- !DOMAIN_IN_SET(domset, d))
- continue;
-
- if (CPU_IN_SET(xdp->dcpuset,
- sup.cpuid))
- break;
- }
- dp = (d == MAX_DOMAINS) ? NULL : xdp;
- }
- if ((dp == NULL) && sup.boardset) {
- for (d = 0; d < MAX_DOMAINS; d++) {
- xdp = &idn_domain[d];
-
- if ((xdp->dcpu == IDN_NIL_DCPU) &&
- !DOMAIN_IN_SET(domset, d))
- continue;
-
- if (xdp->dhw.dh_boardset &
- sup.boardset)
- break;
- }
- dp = (d == MAX_DOMAINS) ? NULL : xdp;
- }
- if (dp == NULL) {
- SET_IDNKERR_ERRNO(sep, EINVAL);
- SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_DOMAIN);
- SET_IDNKERR_PARAM0(sep, sup.domid);
- SET_IDNKERR_PARAM1(sep, sup.cpuid);
- (void) idn_info(&sdp->ssb_info);
- goto sberr;
- } else {
- sup.domid = dp->domid;
- }
-
- switch (sup.force) {
- case SSIFORCE_OFF:
- fintype = IDNFIN_NORMAL;
- break;
-
- case SSIFORCE_SOFT:
- fintype = IDNFIN_FORCE_SOFT;
- break;
-
- case SSIFORCE_HARD:
- fintype = IDNFIN_FORCE_HARD;
- break;
- default:
- SET_IDNKERR_ERRNO(sep, EINVAL);
- SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_FORCE);
- SET_IDNKERR_PARAM0(sep, sup.force);
- (void) idn_info(&sdp->ssb_info);
- goto sberr;
- }
-
- rv = idn_unlink(sup.domid, sup.idnset, fintype,
- IDNFIN_OPT_UNLINK, sup.timeout, sep);
- SET_IDNKERR_ERRNO(sep, rv);
- (void) idn_info(&sdp->ssb_info);
- break;
- }
-
- case SSI_INFO:
- sfp = &sdp->ssb_info;
-
- PR_PROTO("%s: SSI_INFO\n", proc);
-
- rv = idn_info(sfp);
- SET_IDNKERR_ERRNO(sep, rv);
- if (rv != 0) {
- SET_IDNKERR_IDNERR(sep, IDNKERR_INFO_FAILED);
- }
- break;
-
- default:
- ASSERT(0);
- SET_IDNKERR_ERRNO(sep, EINVAL);
- SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_CMD);
- SET_IDNKERR_PARAM0(sep, mbp->cmd);
- break;
- }
-
-sberr:
-
- if (GET_IDNKERR_ERRNO(sep) != 0) {
- cmn_err(CE_WARN,
-#ifdef DEBUG
- "IDN: 125: op (%s) failed, returning "
- "(%d/0x%x [%d, %d, %d])",
-#else /* DEBUG */
- "!IDN: 125: op (%s) failed, returning "
- "(%d/0x%x [%d, %d, %d])",
-#endif /* DEBUG */
- (mbp->cmd == SSI_LINK) ? "LINK" :
- (mbp->cmd == SSI_UNLINK) ? "UNLINK" :
- (mbp->cmd == SSI_INFO) ?
- "INFO" : "UNKNOWN",
- GET_IDNKERR_ERRNO(sep),
- GET_IDNKERR_IDNERR(sep),
- GET_IDNKERR_PARAM0(sep),
- GET_IDNKERR_PARAM1(sep),
- GET_IDNKERR_PARAM2(sep));
- }
-
- PR_PROTO("%s: returning errno = %d, idnerr = %d, "
- "params = [%d, %d, %d]\n",
- proc, GET_IDNKERR_ERRNO(sep), GET_IDNKERR_IDNERR(sep),
- GET_IDNKERR_PARAM0(sep), GET_IDNKERR_PARAM1(sep),
- GET_IDNKERR_PARAM2(sep));
-
- mutex_enter(&idn.sigbintr.sb_mutex);
- ASSERT((sbp->sb_busy == IDNSIGB_ACTIVE) ||
- (sbp->sb_busy == IDNSIGB_DIE));
- mbp->cmd |= SSI_ACK;
- if (sbp->sb_busy == IDNSIGB_ACTIVE)
- sbp->sb_busy = IDNSIGB_INACTIVE;
- /*
- * Set flag which kicks off response to SSP.
- */
- membar_stst_ldst();
- mbp->flag = HOST_TO_CBS;
- }
-
- /*
- * Wake up the dude that killed us!
- */
- idn.sigb_threadp = NULL;
- cv_signal(&sbp->sb_cv);
- mutex_exit(&idn.sigbintr.sb_mutex);
- thread_exit();
-}
-
-/*
- * Create the thread that will service sigb interrupts.
- */
-static void
-idn_sigbhandler_create()
-{
- struct sigbintr *sbp;
-
- if (idn.sigb_threadp) {
- cmn_err(CE_WARN,
- "IDN: 126: sigbhandler thread already "
- "exists (0x%p)", (void *)idn.sigb_threadp);
- return;
- }
- cv_init(&idn.sigbintr.sb_cv, NULL, CV_DEFAULT, NULL);
- sbp = &idn.sigbintr;
- sbp->sb_busy = IDNSIGB_INACTIVE;
- idn.sigb_threadp = thread_create(NULL, 0,
- idn_sigbhandler_thread, &sbp, sizeof (sbp), &p0,
- TS_RUN, minclsyspri);
- sbp->sb_inum = add_softintr((uint_t)idn_sigbpil,
- idn_sigbhandler_wakeup, 0, SOFTINT_ST);
-}
-
-static void
-idn_sigbhandler_kill()
-{
- if (idn.sigb_threadp) {
- struct sigbintr *sbp;
-
- sbp = &idn.sigbintr;
- if (sbp->sb_inum != 0)
- (void) rem_softintr(sbp->sb_inum);
- sbp->sb_inum = 0;
- sbp->sb_busy = IDNSIGB_DIE;
- cv_signal(&sbp->sb_cv);
- while (idn.sigb_threadp != NULL)
- cv_wait(&sbp->sb_cv, &idn.sigbintr.sb_mutex);
- sbp->sb_busy = IDNSIGB_INACTIVE;
- cv_destroy(&sbp->sb_cv);
- }
-}
-
-/*ARGSUSED0*/
-static uint_t
-idn_sigbhandler_wakeup(caddr_t arg1, caddr_t arg2)
-{
- mutex_enter(&idn.sigbintr.sb_mutex);
- if (idn.sigbintr.sb_busy == IDNSIGB_STARTED) {
- idn.sigbintr.sb_busy = IDNSIGB_ACTIVE;
- cv_signal(&idn.sigbintr.sb_cv);
- }
- mutex_exit(&idn.sigbintr.sb_mutex);
-
- return (DDI_INTR_CLAIMED);
-}
-
-static void
-idn_sigbhandler(processorid_t cpuid, cpu_sgnblk_t *sgnblkp)
-{
- struct sigbintr *sbp = &idn.sigbintr;
- sigbmbox_t *mbp;
- idnsb_data_t *sdp;
- idnsb_error_t *sep;
- uint32_t cmd;
- int sigb_lock = 0;
-
- ASSERT(sgnblkp);
-
- mbp = &sgnblkp->sigb_host_mbox;
- sdp = (idnsb_data_t *)mbp->data;
- sep = &sdp->ssb_error;
- cmd = mbp->cmd;
-
- if ((mbp->flag != CBS_TO_HOST) || !VALID_IDNSIGBCMD(cmd)) {
- /*
- * Not a valid IDN command. Just bail out.
- */
- return;
- }
-
- mbp->flag = SIGB_MBOX_BUSY;
- SET_IDNKERR_ERRNO(sep, 0);
-
- if (cmd & SSI_ACK) {
- /*
- * Hmmm...weird, the ACK bit is set.
- */
- SET_IDNKERR_ERRNO(sep, EPROTO);
- SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_CMD);
- SET_IDNKERR_PARAM0(sep, cmd);
- goto sigb_done;
- }
-
- if (!mutex_tryenter(&idn.sigbintr.sb_mutex)) {
- /*
- * Couldn't get the lock. Driver is either
- * not quite all the way up or is shutting down
- * for some reason. Caller should spin again.
- */
- cmd |= SSI_ACK;
- SET_IDNKERR_ERRNO(sep, EBUSY);
- SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_LOCKED);
- goto sigb_done;
- }
- sigb_lock = 1;
-
- if ((idn.sigb_threadp == NULL) ||
- (sbp->sb_busy == IDNSIGB_NOTREADY)) {
- cmd |= SSI_ACK;
- SET_IDNKERR_ERRNO(sep, EAGAIN);
- SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_NOTRDY);
- goto sigb_done;
- }
-
- if (sbp->sb_busy != IDNSIGB_INACTIVE) {
- cmd |= SSI_ACK;
- SET_IDNKERR_ERRNO(sep, EBUSY);
- SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_BUSY);
- goto sigb_done;
- }
-
- sbp->sb_cpuid = (uchar_t)cpuid & 0xff;
- membar_stst_ldst();
- sbp->sb_busy = IDNSIGB_STARTED;
- /*
- * The sb_busy bit is set and the mailbox flag
- * indicates BUSY also, so we effectively have things locked.
- * So, we can drop the critical sb_mutex which we want to
- * do since it pushes us to PIL 14 while we hold it and we
- * don't want to run at PIL 14 across IDN code.
- *
- * Send interrupt to cause idn_sigbhandler_thread to wakeup.
- * We cannot do wakeup (cv_signal) directly from here since
- * we're executing from a high-level (14) interrupt.
- */
- setsoftint(sbp->sb_inum);
-
-sigb_done:
-
- if (GET_IDNKERR_ERRNO(sep) != 0) {
- mbp->len = sizeof (idnsb_data_t);
- mbp->cmd = cmd;
- membar_stst_ldst();
- mbp->flag = HOST_TO_CBS;
- }
-
- if (sigb_lock)
- mutex_exit(&idn.sigbintr.sb_mutex);
-}
-
-static int
-idn_info(idnsb_info_t *sfp)
-{
- int count, d;
- idn_domain_t *dp;
- idnsb_info_t sinfo;
- int local_id, master_id;
- procname_t proc = "idn_info";
-
- bzero(&sinfo, sizeof (sinfo));
- sinfo.master_index = (uchar_t)-1;
- sinfo.master_cpuid = (uchar_t)-1;
- sinfo.local_index = (uchar_t)-1;
- sinfo.local_cpuid = (uchar_t)-1;
-
- IDN_GLOCK_SHARED();
-
- sinfo.idn_state = (uchar_t)idn.state;
-
- switch (idn.state) {
- case IDNGS_OFFLINE:
- sinfo.idn_active = SSISTATE_INACTIVE;
- PR_PROTO("%s: idn_state (%s) = INACTIVE\n",
- proc, idngs_str[idn.state]);
- break;
-
- case IDNGS_IGNORE:
- PR_PROTO("%s: IGNORING IDN_INFO call...\n", proc);
- IDN_GUNLOCK();
- return (EIO);
-
- default:
- sinfo.idn_active = SSISTATE_ACTIVE;
- PR_PROTO("%s: idn_state (%s) = ACTIVE\n",
- proc, idngs_str[idn.state]);
- break;
- }
- master_id = IDN_GET_MASTERID();
- local_id = idn.localid;
-
- /*
- * Need to drop idn.grwlock before acquiring domain locks.
- */
- IDN_GUNLOCK();
-
- IDN_SYNC_LOCK();
-
- sinfo.awol_domset = (ushort_t)idn.domset.ds_awol;
- sinfo.conn_domset = (ushort_t)(idn.domset.ds_connected &
- ~idn.domset.ds_trans_on);
- DOMAINSET_ADD(sinfo.conn_domset, idn.localid);
-
- count = 0;
- for (d = 0; d < MAX_DOMAINS; d++) {
- dp = &idn_domain[d];
-
- if (dp->dcpu == IDN_NIL_DCPU)
- continue;
-
- IDN_DLOCK_SHARED(d);
- if ((dp->dcpu == IDN_NIL_DCPU) ||
- (dp->dstate == IDNDS_CLOSED)) {
- IDN_DUNLOCK(d);
- continue;
- }
-
- count++;
- if (d == local_id) {
- sinfo.local_index = (uchar_t)d;
- sinfo.local_cpuid = (uchar_t)dp->dcpu;
- PR_PROTO("%s: domid %d is LOCAL (cpuid = %d)\n",
- proc, d, dp->dcpu);
- }
- if (d == master_id) {
- sinfo.master_index = (uchar_t)d;
- sinfo.master_cpuid = (uchar_t)dp->dcpu;
- PR_PROTO("%s: domid %d is MASTER (cpuid = %d)\n",
- proc, d, dp->dcpu);
- }
-
- sinfo.domain_boardset[d] = (ushort_t)dp->dhw.dh_boardset;
-
- IDN_DUNLOCK(d);
- }
-
- IDN_SYNC_UNLOCK();
-
- bcopy(&sinfo, sfp, sizeof (*sfp));
-
- PR_PROTO("%s: Found %d domains within IDNnet\n", proc, count);
-
- return (0);
-}
-
-/*
- * ----------------------------------------------
- * ndd param support routines.
- * - Borrowed from tcp.
- * ----------------------------------------------
- */
-static void
-idn_param_cleanup()
-{
- IDN_GLOCK_EXCL();
- if (!idn.strup && idn_ndlist)
- nd_free(&idn_ndlist);
- IDN_GUNLOCK();
-}
-
-/*ARGSUSED*/
-static int
-idn_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- idnparam_t *idnpa = (idnparam_t *)cp;
-
- /*
- * lock grabbed before calling nd_getset.
- */
- ASSERT(IDN_GLOCK_IS_HELD());
-
- (void) mi_mpprintf(mp, "%ld", idnpa->sp_val);
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-idn_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
-{
- char *end;
- ulong_t new_value;
- idnparam_t *idnpa = (idnparam_t *)cp;
-
- /*
- * lock grabbed before calling nd_getset.
- */
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- new_value = (ulong_t)mi_strtol(value, &end, 10);
-
- if ((end == value) ||
- (new_value < idnpa->sp_min) ||
- (new_value > idnpa->sp_max))
- return (EINVAL);
-
- if (idn.enabled == 0) {
-#ifdef DEBUG
- cmn_err(CE_NOTE,
- "IDN: 102: driver disabled "
- "- check OBP environment "
- "(idn-smr-size)");
-#else /* DEBUG */
- cmn_err(CE_NOTE,
- "!IDN: 102: driver disabled "
- "- check OBP environment "
- "(idn-smr-size)");
-#endif /* DEBUG */
- return (EACCES);
- }
-
- idnpa->sp_val = new_value;
-
- return (0);
-}
-
-static int
-idn_param_register(register idnparam_t *idnpa, int count)
-{
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- for (; count > 0; count--, idnpa++) {
- if (idnpa->sp_name && idnpa->sp_name[0]) {
- register int i;
- ndsetf_t set_func;
- char *p;
- /*
- * Don't advertise in non-DEBUG parameters.
- */
- for (i = 0; idn_param_debug_only[i]; i++) {
- p = idn_param_debug_only[i];
- if (strcmp(idnpa->sp_name, p) == 0)
- break;
- }
- if (idn_param_debug_only[i])
- continue;
-
- /*
- * Do not register a "set" function for
- * read-only parameters.
- */
- for (i = 0; idn_param_read_only[i]; i++) {
- p = idn_param_read_only[i];
- if (strcmp(idnpa->sp_name, p) == 0)
- break;
- }
- if (idn_param_read_only[i])
- set_func = NULL;
- else
- set_func = idn_param_set;
-
- if (!nd_load(&idn_ndlist, idnpa->sp_name,
- idn_param_get, set_func,
- (caddr_t)idnpa)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- }
- }
- if (!nd_load(&idn_ndlist, "idn_slabpool", idn_slabpool_report,
- NULL, NULL)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_buffers", idn_buffer_report,
- NULL, NULL)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_mboxtbl", idn_mboxtbl_report,
- NULL, MBXTBL_PART_REPORT)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_mboxtbl_all", idn_mboxtbl_report,
- NULL, MBXTBL_FULL_REPORT)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_mainmbox", idn_mainmbox_report,
- NULL, NULL)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_global", idn_global_report,
- NULL, NULL)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_domain", idn_domain_report,
- NULL, (caddr_t)0)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_domain_all", idn_domain_report,
- NULL, (caddr_t)1)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
- if (!nd_load(&idn_ndlist, "idn_bind_net", idn_get_net_binding,
- idn_set_net_binding, NULL)) {
- nd_free(&idn_ndlist);
- return (-1);
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-idn_set_net_binding(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
-{
- char *end, *cpup;
- long net;
- processorid_t cpuid;
-
- /*
- * lock grabbed before calling nd_getset.
- */
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- if ((cpup = strchr(value, '=')) == NULL)
- return (EINVAL);
-
- *cpup++ = '\0';
-
- net = mi_strtol(value, &end, 10);
- if ((end == value) || (net < 0) || (net >= IDN_MAX_NETS) ||
- !CHAN_IN_SET(idn.chanset, net))
- return (EINVAL);
-
- cpuid = (processorid_t)mi_strtol(cpup, &end, 10);
- if ((end == cpup) || ((cpuid != -1) &&
- (!VALID_CPUID(cpuid) ||
- !CPU_IN_SET(cpu_ready_set, cpuid))))
- return (EINVAL);
-
- idn_chanserver_bind(net, cpuid);
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-idn_get_net_binding(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- int c;
-
- /*
- * lock grabbed before calling nd_getset.
- */
- ASSERT(IDN_GLOCK_IS_HELD());
-
- (void) mi_mpprintf(mp,
- "IDN network interfaces/channels active = %d",
- idn.nchannels);
-
- if (idn.nchannels == 0)
- return (0);
-
- (void) mi_mpprintf(mp, "Net Cpu");
-
- for (c = 0; c < IDN_MAX_NETS; c++) {
- int bc;
- idn_chansvr_t *csp;
-
- if (!CHAN_IN_SET(idn.chanset, c))
- continue;
-
- csp = &idn.chan_servers[c];
-
- if ((bc = csp->ch_bound_cpuid) == -1)
- bc = csp->ch_bound_cpuid_pending;
-
- if (c < 10)
- (void) mi_mpprintf(mp, " %d %d", c, bc);
- else
- (void) mi_mpprintf(mp, " %d %d", c, bc);
- }
-
- return (0);
-}
-
-static int
-idnioc_link(idnop_t *idnop)
-{
- int rv;
- int pri;
- idnsb_error_t err;
- procname_t proc = "idnioc_link";
-
- if (idnop->link.master < 0)
- pri = IDNVOTE_MINPRI;
- else if (idnop->link.master > 0)
- pri = IDNVOTE_MAXPRI;
- else
- pri = IDNVOTE_DEFPRI;
-
- PR_DRV("%s: domid = %d, cpuid = %d, pri = %d\n",
- proc, idnop->link.domid, idnop->link.cpuid, pri);
-
- rv = idn_link(idnop->link.domid, idnop->link.cpuid,
- pri, idnop->link.wait, &err);
-
- return (rv);
-}
-
-static int
-idnioc_unlink(idnop_t *idnop)
-{
- int d, cpuid, domid, rv;
- boardset_t idnset;
- idn_fin_t fintype;
- idn_domain_t *dp, *xdp;
- idnsb_error_t err;
- procname_t proc = "idnioc_unlink";
-
- PR_DRV("%s: domid = %d, cpuid = %d, force = %d\n",
- proc, idnop->unlink.domid, idnop->unlink.cpuid,
- idnop->unlink.force);
-
- idnset = BOARDSET_ALL;
- domid = idnop->unlink.domid;
- cpuid = idnop->unlink.cpuid;
- dp = NULL;
-
- if (domid == IDN_NIL_DOMID)
- domid = idn.localid;
-
- if (VALID_DOMAINID(domid)) {
- dp = &idn_domain[domid];
- if (VALID_CPUID(cpuid) && (dp->dcpu != IDN_NIL_DCPU) &&
- !CPU_IN_SET(dp->dcpuset, cpuid)) {
- dp = NULL;
- PR_PROTO("%s: ERROR: invalid cpuid "
- "(%d) for domain (%d) [cset = 0x%x.x%x]\n",
- proc, cpuid, domid,
- UPPER32_CPUMASK(dp->dcpuset),
- LOWER32_CPUMASK(dp->dcpuset));
- }
- } else if (VALID_CPUID(cpuid)) {
- for (d = 0; d < MAX_DOMAINS; d++) {
- xdp = &idn_domain[d];
-
- if (xdp->dcpu == IDN_NIL_DCPU)
- continue;
-
- if (CPU_IN_SET(xdp->dcpuset, cpuid))
- break;
- }
- dp = (d == MAX_DOMAINS) ? NULL : xdp;
- }
-
- if ((dp == NULL) || (dp->dcpu == IDN_NIL_DCPU))
- return (0);
-
- domid = dp->domid;
-
- switch (idnop->unlink.force) {
- case SSIFORCE_OFF:
- fintype = IDNFIN_NORMAL;
- break;
-
- case SSIFORCE_SOFT:
- fintype = IDNFIN_FORCE_SOFT;
- break;
-
- case SSIFORCE_HARD:
- fintype = IDNFIN_FORCE_HARD;
- break;
- default:
- PR_PROTO("%s: invalid force parameter \"%d\"",
- proc, idnop->unlink.force);
- return (EINVAL);
- }
-
- rv = idn_unlink(domid, idnset, fintype, IDNFIN_OPT_UNLINK,
- idnop->unlink.wait, &err);
-
- return (rv);
-}
-
-static int
-idn_send_ping(idnop_t *idnop)
-{
- int domid = idnop->ping.domid;
- int cpuid = idnop->ping.cpuid;
- int ocpuid;
- idn_domain_t *dp;
- idn_msgtype_t mt;
- procname_t proc = "idn_send_ping";
-
- if ((domid == IDN_NIL_DOMID) && (cpuid == IDN_NIL_DCPU)) {
- cmn_err(CE_WARN,
- "IDN: %s: no valid domain ID or CPU ID given",
- proc);
- return (EINVAL);
- }
- if (domid == IDN_NIL_DOMID)
- domid = MAX_DOMAINS - 1;
-
- dp = &idn_domain[domid];
- IDN_DLOCK_EXCL(domid);
- if ((dp->dcpu == IDN_NIL_DCPU) && (cpuid == IDN_NIL_DCPU)) {
- cmn_err(CE_WARN,
- "IDN: %s: no valid target CPU specified",
- proc);
- IDN_DUNLOCK(domid);
- return (EINVAL);
- }
- if (cpuid == IDN_NIL_DCPU)
- cpuid = dp->dcpu;
-
- ocpuid = dp->dcpu;
- dp->dcpu = cpuid;
-
- /*
- * XXX - Need a special PING IDN command.
- */
- mt.mt_mtype = IDNP_DATA | IDNP_ACK;
- mt.mt_atype = 0;
-
- (void) IDNXDC(domid, &mt, 0x100, 0x200, 0x300, 0x400);
-
- dp->dcpu = ocpuid;
- IDN_DUNLOCK(domid);
-
- return (0);
-}
-
-/*
- * ----------------------------------------------
- */
-static void
-idn_dopers_init()
-{
- int i;
- dop_waitlist_t *dwl;
-
- if (idn.dopers)
- return;
-
- idn.dopers = GETSTRUCT(struct dopers, 1);
-
- bzero(idn.dopers, sizeof (struct dopers));
-
- dwl = &idn.dopers->_dop_wcache[0];
- for (i = 0; i < (IDNOP_CACHE_SIZE-1); i++)
- dwl[i].dw_next = &dwl[i+1];
- dwl[i].dw_next = NULL;
-
- idn.dopers->dop_freelist = &idn.dopers->_dop_wcache[0];
- idn.dopers->dop_waitcount = 0;
- idn.dopers->dop_domset = 0;
- idn.dopers->dop_waitlist = NULL;
-
- cv_init(&idn.dopers->dop_cv, NULL, CV_DEFAULT, NULL);
- mutex_init(&idn.dopers->dop_mutex, NULL, MUTEX_DEFAULT, NULL);
-}
-
-static void
-idn_dopers_deinit()
-{
- dop_waitlist_t *dwl, *next_dwl;
-
-
- if (idn.dopers == NULL)
- return;
-
- for (dwl = idn.dopers->dop_waitlist; dwl; dwl = next_dwl) {
- next_dwl = dwl->dw_next;
- if (!IDNOP_IN_CACHE(dwl))
- FREESTRUCT(dwl, dop_waitlist_t, 1);
- }
-
- cv_destroy(&idn.dopers->dop_cv);
- mutex_destroy(&idn.dopers->dop_mutex);
-
- FREESTRUCT(idn.dopers, struct dopers, 1);
- idn.dopers = NULL;
-}
-
-/*
- * Reset the dop_errset field in preparation for an
- * IDN operation attempt. This is only called from
- * idn_link() and idn_unlink().
- */
-void *
-idn_init_op(idn_opflag_t opflag, domainset_t domset, idnsb_error_t *sep)
-{
- dop_waitlist_t *dwl;
- /*
- * Clear any outstanding error ops in preparation
- * for an IDN (link/unlink) operation.
- */
- mutex_enter(&idn.dopers->dop_mutex);
- if ((dwl = idn.dopers->dop_freelist) == NULL) {
- dwl = GETSTRUCT(dop_waitlist_t, 1);
- } else {
- idn.dopers->dop_freelist = dwl->dw_next;
- bzero(dwl, sizeof (*dwl));
- }
- dwl->dw_op = opflag;
- dwl->dw_reqset = domset;
- dwl->dw_idnerr = sep;
- dwl->dw_next = idn.dopers->dop_waitlist;
-
- idn.dopers->dop_waitlist = dwl;
- idn.dopers->dop_waitcount++;
- idn.dopers->dop_domset |= domset;
- mutex_exit(&idn.dopers->dop_mutex);
-
- return (dwl);
-}
-
-/*
- * Anybody waiting on a opflag operation for any one
- * of the domains in domset, needs to be updated to
- * additionally wait for new domains in domset.
- * This is used, for example, when needing to connect
- * to more domains than known at the time of the
- * original request.
- */
-void
-idn_add_op(idn_opflag_t opflag, domainset_t domset)
-{
- dop_waitlist_t *dwl;
-
- mutex_enter(&idn.dopers->dop_mutex);
- if ((idn.dopers->dop_waitcount == 0) ||
- ((idn.dopers->dop_domset & domset) == 0)) {
- mutex_exit(&idn.dopers->dop_mutex);
- return;
- }
- for (dwl = idn.dopers->dop_waitlist; dwl; dwl = dwl->dw_next)
- if ((dwl->dw_op == opflag) && (dwl->dw_reqset & domset))
- dwl->dw_reqset |= domset;
- mutex_exit(&idn.dopers->dop_mutex);
-}
-
-/*
- * Mechanism to wakeup any potential users which may be waiting
- * for a link/unlink operation to complete. If an error occurred
- * don't update dop_errset unless there was no previous error.
- */
-void
-idn_update_op(idn_opflag_t opflag, domainset_t domset, idnsb_error_t *sep)
-{
- int do_wakeup = 0;
- dop_waitlist_t *dw;
- procname_t proc = "idn_update_op";
-
- mutex_enter(&idn.dopers->dop_mutex);
- /*
- * If there are no waiters, or nobody is waiting for
- * the particular domainset in question, then
- * just bail.
- */
- if ((idn.dopers->dop_waitcount == 0) ||
- ((idn.dopers->dop_domset & domset) == 0)) {
- mutex_exit(&idn.dopers->dop_mutex);
- PR_PROTO("%s: NO waiters exist (domset=0x%x)\n",
- proc, domset);
- return;
- }
-
- for (dw = idn.dopers->dop_waitlist; dw; dw = dw->dw_next) {
- int d;
- domainset_t dset, rset;
-
- if ((dset = dw->dw_reqset & domset) == 0)
- continue;
-
- if (opflag == IDNOP_ERROR) {
- dw->dw_errset |= dset;
- if (sep) {
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(dset, d))
- continue;
-
- dw->dw_errors[d] =
- (short)GET_IDNKERR_ERRNO(sep);
- }
- bcopy(sep, dw->dw_idnerr, sizeof (*sep));
- }
- } else if (opflag == dw->dw_op) {
- dw->dw_domset |= dset;
- }
-
- /*
- * Check if all the domains are spoken for that
- * a particular waiter may have been waiting for.
- * If there's at least one, we'll need to broadcast.
- */
- rset = (dw->dw_errset | dw->dw_domset) & dw->dw_reqset;
- if (rset == dw->dw_reqset)
- do_wakeup++;
- }
-
- PR_PROTO("%s: found %d waiters ready for wakeup\n", proc, do_wakeup);
-
- if (do_wakeup > 0)
- cv_broadcast(&idn.dopers->dop_cv);
-
- mutex_exit(&idn.dopers->dop_mutex);
-}
-
-void
-idn_deinit_op(void *cookie)
-{
- domainset_t domset;
- dop_waitlist_t *hw, *tw;
- dop_waitlist_t *dwl = (dop_waitlist_t *)cookie;
-
- mutex_enter(&idn.dopers->dop_mutex);
-
- ASSERT(idn.dopers->dop_waitlist);
-
- if (dwl == idn.dopers->dop_waitlist) {
- idn.dopers->dop_waitlist = dwl->dw_next;
- if (IDNOP_IN_CACHE(dwl)) {
- dwl->dw_next = idn.dopers->dop_freelist;
- idn.dopers->dop_freelist = dwl;
- } else {
- FREESTRUCT(dwl, dop_waitlist_t, 1);
- }
- } else {
- for (tw = idn.dopers->dop_waitlist, hw = tw->dw_next;
- hw;
- tw = hw, hw = hw->dw_next) {
- if (dwl == hw)
- break;
- }
- ASSERT(hw);
-
- tw->dw_next = hw->dw_next;
- }
-
- /*
- * Recompute domainset for which waiters might be waiting.
- * It's possible there may be other waiters waiting for
- * the same domainset that the current waiter that's leaving
- * may have been waiting for, so we can't simply delete
- * the leaving waiter's domainset from dop_domset.
- */
- for (hw = idn.dopers->dop_waitlist, domset = 0; hw; hw = hw->dw_next)
- domset |= hw->dw_reqset;
-
- idn.dopers->dop_waitcount--;
- idn.dopers->dop_domset = domset;
-
- mutex_exit(&idn.dopers->dop_mutex);
-}
-
-/*
- * Wait until the specified operation succeeds or fails with
- * respect to the given domains. Note the function terminates
- * if at least one error occurs.
- * This process is necessary since link/unlink operations occur
- * asynchronously and we need some way of waiting to find out
- * if it indeed completed.
- * Timeout value is received indirectly from the SSP and
- * represents seconds.
- */
-int
-idn_wait_op(void *cookie, domainset_t *domsetp, int wait_timeout)
-{
- int d, rv, err = 0;
- dop_waitlist_t *dwl;
-
-
- dwl = (dop_waitlist_t *)cookie;
-
- ASSERT(wait_timeout > 0);
- ASSERT((dwl->dw_op == IDNOP_CONNECTED) ||
- (dwl->dw_op == IDNOP_DISCONNECTED));
-
- mutex_enter(&idn.dopers->dop_mutex);
-
- while (((dwl->dw_domset | dwl->dw_errset) != dwl->dw_reqset) && !err) {
- rv = cv_reltimedwait_sig(&idn.dopers->dop_cv,
- &idn.dopers->dop_mutex, (wait_timeout * hz), TR_CLOCK_TICK);
-
- if ((dwl->dw_domset | dwl->dw_errset) == dwl->dw_reqset)
- break;
-
- switch (rv) {
- case -1:
- /*
- * timed out
- */
- cmn_err(CE_WARN,
- "!IDN: 129: %s operation timed out",
- (dwl->dw_op == IDNOP_CONNECTED) ? "LINK" :
- (dwl->dw_op == IDNOP_DISCONNECTED) ? "UNLINK" :
- "UNKNOWN");
- /*FALLTHROUGH*/
- case 0:
- /*
- * signal, e.g. kill(2)
- */
- err = 1;
- break;
-
- default:
- break;
- }
- }
-
- if (dwl->dw_domset == dwl->dw_reqset) {
- rv = 0;
- } else {
- /*
- * Op failed for some domains or we were awakened.
- */
- for (d = rv = 0; (d < MAX_DOMAINS) && !rv; d++)
- rv = dwl->dw_errors[d];
- }
- *domsetp = dwl->dw_domset;
-
- mutex_exit(&idn.dopers->dop_mutex);
-
- idn_deinit_op(cookie);
-
- return (rv);
-}
-
-/*
- * --------------------------------------------------
- * Return any valid (& ready) cpuid for the given board based on
- * the given cpuset.
- * --------------------------------------------------
- */
-int
-board_to_ready_cpu(int board, cpuset_t cpuset)
-{
- int base_cpuid;
- int ncpu_board = MAX_CPU_PER_BRD;
-
- board *= ncpu_board;
- for (base_cpuid = board;
- base_cpuid < (board + ncpu_board);
- base_cpuid++)
- if (CPU_IN_SET(cpuset, base_cpuid))
- return (base_cpuid);
-
- return (-1);
-}
-
-void
-idn_domain_resetentry(idn_domain_t *dp)
-{
- register int i;
- procname_t proc = "idn_domain_resetentry";
-
- ASSERT(dp);
- ASSERT(dp->dstate == IDNDS_CLOSED);
- ASSERT(IDN_DLOCK_IS_EXCL(dp->domid));
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- ASSERT(dp->domid == (dp - &idn_domain[0]));
-
- IDN_FSTATE_TRANSITION(dp, IDNFIN_OFF);
- dp->dname[0] = '\0';
- dp->dnetid = (ushort_t)-1;
- dp->dmtu = 0;
- dp->dbufsize = 0;
- dp->dslabsize = 0;
- dp->dnwrsize = 0;
- dp->dncpus = 0;
- dp->dcpuindex = 0;
- CPUSET_ZERO(dp->dcpuset);
- dp->dcpu = dp->dcpu_last = dp->dcpu_save = IDN_NIL_DCPU;
- dp->dvote.ticket = 0;
- dp->dslab = NULL;
- dp->dslab_state = DSLAB_STATE_UNKNOWN;
- dp->dnslabs = 0;
- dp->dio = 0;
- dp->dioerr = 0;
- lock_clear(&dp->diowanted);
- bzero(&dp->dhw, sizeof (dp->dhw));
- dp->dxp = NULL;
- IDN_XSTATE_TRANSITION(dp, IDNXS_NIL);
- dp->dsync.s_cmd = IDNSYNC_NIL;
- dp->dfin_sync = IDNFIN_SYNC_OFF;
- IDN_RESET_COOKIES(dp->domid);
- dp->dcookie_err = 0;
- bzero(&dp->dawol, sizeof (dp->dawol));
- dp->dtmp = -1;
-
- if (dp->dtimerq.tq_queue != NULL) {
- PR_PROTO("%s: WARNING: MSG timerq not empty (count = %d)\n",
- proc, dp->dtimerq.tq_count);
- IDN_MSGTIMER_STOP(dp->domid, 0, 0);
- }
-
- for (i = 0; i < NCPU; i++)
- dp->dcpumap[i] = (uchar_t)-1;
-}
-
-int
-idn_open_domain(int domid, int cpuid, uint_t ticket)
-{
- int c, new_cpuid;
- idn_domain_t *dp, *ldp;
- procname_t proc = "idn_open_domain";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (!VALID_DOMAINID(domid)) {
- PR_PROTO("%s: INVALID domainid (%d) "
- "[cpuid = %d, ticket = 0x%x]\n",
- proc, domid, cpuid, ticket);
- return (-1);
- }
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- if (dp->dcpu >= 0) {
- PR_PROTO("%s:%d: domain already OPEN (state = %s)\n",
- proc, domid, idnds_str[dp->dstate]);
- return (1);
- }
-
- if (DOMAIN_IN_SET(idn.domset.ds_relink, domid)) {
- if (dp->dcpu_save == IDN_NIL_DCPU)
- new_cpuid = cpuid;
- else
- new_cpuid = dp->dcpu_save;
- } else {
- new_cpuid = cpuid;
- }
-
- if (new_cpuid == IDN_NIL_DCPU) {
- PR_PROTO("%s:%d: WARNING: invalid cpuid (%d) specified\n",
- proc, domid, new_cpuid);
- return (-1);
- }
-
- IDN_GLOCK_EXCL();
-
- idn_domain_resetentry(dp);
-
- PR_STATE("%s:%d: requested cpuid %d, assigning cpuid %d\n",
- proc, domid, cpuid, new_cpuid);
-
- idn_assign_cookie(domid);
-
- dp->dcpu = dp->dcpu_save = new_cpuid;
- dp->dvote.ticket = ticket;
- CPUSET_ADD(dp->dcpuset, new_cpuid);
- dp->dncpus = 1;
- for (c = 0; c < NCPU; c++)
- dp->dcpumap[c] = (uchar_t)new_cpuid;
- dp->dhw.dh_nboards = 1;
- dp->dhw.dh_boardset = BOARDSET(CPUID_TO_BOARDID(new_cpuid));
-
- if (domid != idn.localid)
- IDN_DLOCK_EXCL(idn.localid);
-
- if (idn.ndomains == 1) {
- struct hwconfig local_hw;
-
- /*
- * We're attempting to connect to our first domain.
- * Recheck our local hardware configuration before
- * we go any further in case it changed due to a DR,
- * and update any structs dependent on this.
- * ASSUMPTION:
- * IDN is unlinked before performing any DRs.
- */
- PR_PROTO("%s: RECHECKING local HW config.\n", proc);
- if (get_hw_config(&local_hw)) {
- dp->dcpu = IDN_NIL_DCPU;
- cmn_err(CE_WARN,
- "IDN: 118: hardware config not appropriate");
- if (domid != idn.localid)
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
- return (-1);
- }
- (void) update_local_hw_config(ldp, &local_hw);
- }
-
- idn.ndomains++;
-
- if (domid != idn.localid)
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
-
- IDN_MBOX_LOCK(domid);
- dp->dmbox.m_tbl = NULL;
-
- if (domid != idn.localid) {
- dp->dmbox.m_send = idn_mainmbox_init(domid,
- IDNMMBOX_TYPE_SEND);
- dp->dmbox.m_recv = idn_mainmbox_init(domid,
- IDNMMBOX_TYPE_RECV);
- } else {
- /*
- * The local domain does not need send/recv
- * mailboxes in its idn_domain[] entry.
- */
- dp->dmbox.m_send = NULL;
- dp->dmbox.m_recv = NULL;
- }
- IDN_MBOX_UNLOCK(domid);
-
- PR_PROTO("%s:%d: new domain (cpu = %d, vote = 0x%x)\n",
- proc, domid, dp->dcpu, dp->dvote.ticket);
-
- return (0);
-}
-
-/*
- * The local domain never "closes" itself unless the driver
- * is doing a idndetach. It will be reopened during idnattach
- * when idn_domains_init is called.
- */
-void
-idn_close_domain(int domid)
-{
- uint_t token;
- idn_domain_t *dp;
- procname_t proc = "idn_close_domain";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
-
- ASSERT(dp->dstate == IDNDS_CLOSED);
-
- if (dp->dcpu == IDN_NIL_DCPU) {
- PR_PROTO("%s:%d: DOMAIN ALREADY CLOSED!\n",
- proc, domid);
- return;
- }
-
- token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL);
-
- (void) idn_retry_terminate(token);
-
- DOMAINSET_DEL(idn.domset.ds_trans_on, domid);
- DOMAINSET_DEL(idn.domset.ds_ready_on, domid);
- DOMAINSET_DEL(idn.domset.ds_connected, domid);
- DOMAINSET_DEL(idn.domset.ds_trans_off, domid);
- DOMAINSET_DEL(idn.domset.ds_ready_off, domid);
- DOMAINSET_DEL(idn.domset.ds_hwlinked, domid);
- DOMAINSET_DEL(idn.domset.ds_flush, domid);
-
- idn_sync_exit(domid, IDNSYNC_CONNECT);
- idn_sync_exit(domid, IDNSYNC_DISCONNECT);
-
- IDN_GLOCK_EXCL();
-
- if (DOMAIN_IN_SET(idn.domset.ds_awol, domid))
- idn_clear_awol(domid);
-
- idn.ndomains--;
-
- IDN_GUNLOCK();
-
- IDN_MBOX_LOCK(domid);
- dp->dmbox.m_tbl = NULL;
-
- if (dp->dmbox.m_send) {
- idn_mainmbox_deinit(domid, dp->dmbox.m_send);
- dp->dmbox.m_send = NULL;
- }
-
- if (dp->dmbox.m_recv) {
- idn_mainmbox_deinit(domid, dp->dmbox.m_recv);
- dp->dmbox.m_recv = NULL;
- }
-
- IDN_MBOX_UNLOCK(domid);
-
- cmn_err(CE_NOTE,
- "!IDN: 142: link (domain %d, CPU %d) disconnected",
- dp->domid, dp->dcpu);
-
- dp->dcpu = IDN_NIL_DCPU; /* ultimate demise */
-
- IDN_RESET_COOKIES(domid);
-
- ASSERT(dp->dio <= 0);
- ASSERT(dp->dioerr == 0);
- ASSERT(dp->dslab == NULL);
- ASSERT(dp->dnslabs == 0);
-
- IDN_GKSTAT_GLOBAL_EVENT(gk_unlinks, gk_unlink_last);
-}
-
-
-/*
- * -----------------------------------------------------------------------
- */
-static void
-idn_domains_init(struct hwconfig *local_hw)
-{
- register int i, d;
- idn_domain_t *ldp;
- uchar_t *cpumap;
-
- ASSERT(local_hw != NULL);
-
- cpumap = GETSTRUCT(uchar_t, NCPU * MAX_DOMAINS);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- register idn_domain_t *dp;
-
- dp = &idn_domain[d];
-
- dp->domid = d;
-
- rw_init(&dp->drwlock, NULL, RW_DEFAULT, NULL);
-
- IDN_TIMERQ_INIT(&dp->dtimerq);
-
- dp->dstate = IDNDS_CLOSED;
-
- mutex_init(&dp->dmbox.m_mutex, NULL, MUTEX_DEFAULT, NULL);
-
- dp->dcpumap = cpumap;
-
- rw_init(&dp->dslab_rwlock, NULL, RW_DEFAULT, NULL);
-
- IDN_DLOCK_EXCL(d);
- IDN_GLOCK_EXCL();
-
- idn_domain_resetentry(dp);
-
- IDN_GUNLOCK();
-
- IDNSB_DOMAIN_UPDATE(dp);
-
- IDN_DUNLOCK(d);
-
- cpumap += NCPU;
- }
-
- IDN_SYNC_LOCK();
-
- /*
- * Update local domain information.
- */
- ASSERT(idn.smr.locpfn);
- ASSERT(local_hw->dh_nboards && local_hw->dh_boardset);
-
- idn.ndomains = 0; /* note that open_domain will get us to 1 */
-
- IDN_DLOCK_EXCL(idn.localid);
- d = idn_open_domain(idn.localid, (int)CPU->cpu_id, 0);
- ASSERT(d == 0);
- IDN_GLOCK_EXCL();
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
-
- ldp = &idn_domain[idn.localid];
-
- (void) strncpy(ldp->dname, utsname.nodename, MAXDNAME - 1);
- ldp->dname[MAXDNAME-1] = '\0';
- bcopy(local_hw, &ldp->dhw, sizeof (ldp->dhw));
- ASSERT(idn.ndomains == 1);
- ASSERT((ldp->dhw.dh_nboards > 0) &&
- (ldp->dhw.dh_nboards <= MAX_BOARDS));
- ldp->dnetid = IDN_DOMID2NETID(ldp->domid);
- ldp->dmtu = IDN_MTU;
- ldp->dbufsize = IDN_SMR_BUFSIZE;
- ldp->dslabsize = (short)IDN_SLAB_BUFCOUNT;
- ldp->dnwrsize = (short)IDN_NWR_SIZE;
- ldp->dcpuset = cpu_ready_set;
- ldp->dncpus = (short)ncpus;
- ldp->dvote.ticket = IDNVOTE_INITIAL_TICKET;
- ldp->dvote.v.master = 0;
- ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1;
- ldp->dvote.v.ncpus = (int)ldp->dncpus - 1;
- ldp->dvote.v.board = CPUID_TO_BOARDID(ldp->dcpu);
- i = -1;
- for (d = 0; d < NCPU; d++) {
- BUMP_INDEX(ldp->dcpuset, i);
- ldp->dcpumap[d] = (uchar_t)i;
- }
-
- CPUSET_ZERO(idn.dc_cpuset);
- CPUSET_OR(idn.dc_cpuset, ldp->dcpuset);
- idn.dc_boardset = ldp->dhw.dh_boardset;
-
- /*
- * Setting the state for ourselves is only relevant
- * for loopback performance testing. Anyway, it
- * makes sense that we always have an established
- * connection with ourself regardless of IDN :-o
- */
- IDN_DSTATE_TRANSITION(ldp, IDNDS_CONNECTED);
-
- IDN_GUNLOCK();
- IDN_DUNLOCK(idn.localid);
- IDN_SYNC_UNLOCK();
-}
-
-static void
-idn_domains_deinit()
-{
- register int d;
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(idn.localid);
- IDN_DSTATE_TRANSITION(&idn_domain[idn.localid], IDNDS_CLOSED);
- idn_close_domain(idn.localid);
- IDN_DUNLOCK(idn.localid);
- IDN_SYNC_UNLOCK();
- idn.localid = IDN_NIL_DOMID;
-
- FREESTRUCT(idn_domain[0].dcpumap, uchar_t, NCPU * MAX_DOMAINS);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- idn_domain_t *dp;
-
- dp = &idn_domain[d];
-
- rw_destroy(&dp->dslab_rwlock);
- mutex_destroy(&dp->dmbox.m_mutex);
- rw_destroy(&dp->drwlock);
- IDN_TIMERQ_DEINIT(&dp->dtimerq);
- dp->dcpumap = NULL;
- }
-}
-
-/*
- * -----------------------------------------------------------------------
- */
-static void
-idn_retrytask_init()
-{
- ASSERT(idn.retryqueue.rq_cache == NULL);
-
- mutex_init(&idn.retryqueue.rq_mutex, NULL, MUTEX_DEFAULT, NULL);
- idn.retryqueue.rq_cache = kmem_cache_create("idn_retryjob_cache",
- sizeof (idn_retry_job_t),
- 0, NULL, NULL, NULL,
- NULL, NULL, 0);
-}
-
-static void
-idn_retrytask_deinit()
-{
- if (idn.retryqueue.rq_cache == NULL)
- return;
-
- kmem_cache_destroy(idn.retryqueue.rq_cache);
- mutex_destroy(&idn.retryqueue.rq_mutex);
-
- bzero(&idn.retryqueue, sizeof (idn.retryqueue));
-}
-
-/*
- * -----------------------------------------------------------------------
- */
-static void
-idn_timercache_init()
-{
- ASSERT(idn.timer_cache == NULL);
-
- idn.timer_cache = kmem_cache_create("idn_timer_cache",
- sizeof (idn_timer_t),
- 0, NULL, NULL, NULL,
- NULL, NULL, 0);
-}
-
-static void
-idn_timercache_deinit()
-{
- if (idn.timer_cache == NULL)
- return;
-
- kmem_cache_destroy(idn.timer_cache);
- idn.timer_cache = NULL;
-}
-
-idn_timer_t *
-idn_timer_alloc()
-{
- idn_timer_t *tp;
-
- tp = kmem_cache_alloc(idn.timer_cache, KM_SLEEP);
- bzero(tp, sizeof (*tp));
- tp->t_forw = tp->t_back = tp;
-
- return (tp);
-}
-
-void
-idn_timer_free(idn_timer_t *tp)
-{
- if (tp == NULL)
- return;
- kmem_cache_free(idn.timer_cache, tp);
-}
-
-void
-idn_timerq_init(idn_timerq_t *tq)
-{
- mutex_init(&tq->tq_mutex, NULL, MUTEX_DEFAULT, NULL);
- tq->tq_count = 0;
- tq->tq_queue = NULL;
-}
-
-void
-idn_timerq_deinit(idn_timerq_t *tq)
-{
- ASSERT(tq->tq_queue == NULL);
- mutex_destroy(&tq->tq_mutex);
-}
-
-/*
- * Dequeue all the timers of the given subtype from the
- * given timerQ. If subtype is 0, then dequeue all the
- * timers.
- */
-idn_timer_t *
-idn_timer_get(idn_timerq_t *tq, int type, ushort_t tcookie)
-{
- register idn_timer_t *tp, *tphead;
-
- ASSERT(IDN_TIMERQ_IS_LOCKED(tq));
-
- if ((tp = tq->tq_queue) == NULL)
- return (NULL);
-
- if (!type) {
- tq->tq_queue = NULL;
- tq->tq_count = 0;
- tphead = tp;
- } else {
- int count;
- idn_timer_t *tpnext;
-
- tphead = NULL;
- count = tq->tq_count;
- do {
- tpnext = tp->t_forw;
- if ((tp->t_type == type) &&
- (!tcookie || (tp->t_cookie == tcookie))) {
- tp->t_forw->t_back = tp->t_back;
- tp->t_back->t_forw = tp->t_forw;
- if (tphead == NULL) {
- tp->t_forw = tp->t_back = tp;
- } else {
- tp->t_forw = tphead;
- tp->t_back = tphead->t_back;
- tp->t_back->t_forw = tp;
- tphead->t_back = tp;
- }
- tphead = tp;
- if (--(tq->tq_count) == 0)
- tq->tq_queue = NULL;
- else if (tq->tq_queue == tp)
- tq->tq_queue = tpnext;
- }
- tp = tpnext;
- } while (--count > 0);
- }
-
- if (tphead) {
- tphead->t_back->t_forw = NULL;
-
- for (tp = tphead; tp; tp = tp->t_forw)
- tp->t_onq = 0;
- }
-
- return (tphead);
-}
-
-ushort_t
-idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp, clock_t tval)
-{
- idn_timer_t *otp;
- ushort_t tcookie;
- procname_t proc = "idn_timer_start";
- STRING(str);
-
- ASSERT(tq && tp && (tval > 0));
- ASSERT((tp->t_forw == tp) && (tp->t_back == tp));
- ASSERT(tp->t_type != 0);
-
- IDN_TIMERQ_LOCK(tq);
- /*
- * Assign a unique non-zero 8-bit cookie to this timer
- * if the caller hasn't already preassigned one.
- */
- while ((tcookie = tp->t_cookie) == 0) {
- tp->t_cookie = (tp->t_type & 0xf) |
- ((++tq->tq_cookie & 0xf) << 4);
- /*
- * Calculated cookie must never conflict
- * with the public timer cookie.
- */
- ASSERT(tp->t_cookie != IDN_TIMER_PUBLIC_COOKIE);
- }
-
- /*
- * First have to remove old timers of the
- * same type and cookie, and get rid of them.
- */
- otp = idn_timer_get(tq, tp->t_type, tcookie);
-
- tq->tq_count++;
-
- if (tq->tq_queue == NULL) {
- tq->tq_queue = tp;
- ASSERT((tp->t_forw == tp) && (tp->t_back == tp));
- } else {
- /*
- * Put me at the end of the list.
- */
- tp->t_forw = tq->tq_queue;
- tp->t_back = tq->tq_queue->t_back;
- tp->t_back->t_forw = tp;
- tp->t_forw->t_back = tp;
- }
-
- tp->t_onq = 1;
- tp->t_q = tq;
- tp->t_id = timeout(idn_timer_expired, (caddr_t)tp, tval);
-
-
- INUM2STR(tp->t_type, str);
- PR_TIMER("%s: started %s timer (domain = %d, cookie = 0x%x)\n",
- proc, str, tp->t_domid, tcookie);
-
- IDN_TIMERQ_UNLOCK(tq);
-
- if (otp)
- (void) idn_timer_stopall(otp);
-
- return (tcookie);
-}
-
-/*
- * Stop all timers of the given subtype.
- * If subtype is 0, then stop all timers
- * in this timerQ.
- */
-void
-idn_timer_stop(idn_timerq_t *tq, int type, ushort_t tcookie)
-{
- idn_timer_t *tphead;
- procname_t proc = "idn_timer_stop";
- STRING(str);
-
- ASSERT(tq);
-
- INUM2STR(type, str);
-
- IDN_TIMERQ_LOCK(tq);
-
- if (tq->tq_count == 0) {
- PR_TIMER("%s: found no %s timers (count=0)\n", proc, str);
- IDN_TIMERQ_UNLOCK(tq);
- return;
- }
- tphead = idn_timer_get(tq, type, tcookie);
-#ifdef DEBUG
- if (tphead == NULL)
- PR_TIMER("%s: found no %s (cookie = 0x%x) "
- "timers (count=%d)!!\n",
- proc, str, tcookie, tq->tq_count);
-#endif /* DEBUG */
- IDN_TIMERQ_UNLOCK(tq);
-
- if (tphead)
- (void) idn_timer_stopall(tphead);
-}
-
-int
-idn_timer_stopall(idn_timer_t *tp)
-{
- int count = 0;
- int nonactive;
- uint_t type;
- idn_timer_t *ntp;
- procname_t proc = "idn_timer_stopall";
- STRING(str);
-
- nonactive = 0;
-
- if (tp) {
- /*
- * Circle should have been broken.
- */
- ASSERT(tp->t_back->t_forw == NULL);
- type = tp->t_type;
- INUM2STR(type, str);
- }
-
- for (; tp; tp = ntp) {
- ntp = tp->t_forw;
- count++;
- ASSERT(tp->t_id != (timeout_id_t)0);
- if (untimeout(tp->t_id) < 0) {
- nonactive++;
- PR_TIMER("%s: bad %s untimeout (domain=%d)\n",
- proc, str, tp->t_domid);
- } else {
- PR_TIMER("%s: good %s untimeout (domain=%d)\n",
- proc, str, tp->t_domid);
- }
- /*
- * There are two possible outcomes from
- * the untimeout(). Each ultimately result
- * in us having to free the timeout structure.
- *
- * 1. We successfully aborted a timeout call.
- *
- * 2. We failed to find the given timer. It
- * probably just fired off.
- */
- idn_timer_free(tp);
- }
- PR_TIMER("%s: stopped %d of %d %s timers\n",
- proc, count - nonactive, count, str);
-
- return (count);
-}
-
-void
-idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp)
-{
- ASSERT(tq && tp);
- ASSERT(IDN_TIMERQ_IS_LOCKED(tq));
-
- ASSERT(tp->t_q == tq);
-
- if (tp->t_onq == 0) {
- /*
- * We've already been dequeued.
- */
- ASSERT(tp == tp->t_forw);
- ASSERT(tp == tp->t_back);
- } else {
- /*
- * We're still in the queue, get out.
- */
- if (tq->tq_queue == tp)
- tq->tq_queue = tp->t_forw;
- tp->t_forw->t_back = tp->t_back;
- tp->t_back->t_forw = tp->t_forw;
- tp->t_onq = 0;
- if (--(tq->tq_count) == 0) {
- ASSERT(tq->tq_queue == tp);
- tq->tq_queue = NULL;
- }
- tp->t_forw = tp->t_back = tp;
- }
-}
-
-/*
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-idn_slabpool_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- register int p, nfree;
- char dsetstr[128];
-
- ASSERT(IDN_GLOCK_IS_HELD());
-
- if (idn.slabpool == NULL) {
- (void) mi_mpprintf(mp,
- "IDN slabpool not initialized (masterid = %d)",
- IDN_GET_MASTERID());
- return (0);
- }
-
- for (p = nfree = 0; p < idn.slabpool->npools; p++)
- nfree += idn.slabpool->pool[p].nfree;
-
- (void) mi_mpprintf(mp,
- "IDN slabpool (ntotal_slabs = %d, nalloc = %d, "
- "npools = %d)",
- idn.slabpool->ntotslabs,
- idn.slabpool->ntotslabs - nfree,
- idn.slabpool->npools);
-
- (void) mi_mpprintf(mp, "pool nslabs nfree domains");
-
- for (p = 0; p < idn.slabpool->npools; p++) {
- register int d, s;
- uint_t domset;
-
- domset = 0;
- for (s = 0; s < idn.slabpool->pool[p].nslabs; s++) {
- short dd;
-
- dd = idn.slabpool->pool[p].sarray[s].sl_domid;
- if (dd != (short)IDN_NIL_DOMID)
- DOMAINSET_ADD(domset, dd);
- }
- dsetstr[0] = '\0';
- if (domset) {
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(domset, d))
- continue;
-
- if (dsetstr[0] == '\0')
- (void) sprintf(dsetstr, "%d", d);
- else
- (void) sprintf(dsetstr, "%s %d",
- dsetstr, d);
- }
- }
-
- if (p < 10)
- (void) mi_mpprintf(mp, " %d %d %d %s",
- p, idn.slabpool->pool[p].nslabs,
- idn.slabpool->pool[p].nfree,
- dsetstr);
- else
- (void) mi_mpprintf(mp, " %d %d %d %s",
- p, idn.slabpool->pool[p].nslabs,
- idn.slabpool->pool[p].nfree,
- dsetstr);
- }
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-idn_buffer_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- smr_slab_t *sp;
- register int d, cnt;
- int bufcount[MAX_DOMAINS];
- int spl;
-
- ASSERT(IDN_GLOCK_IS_HELD());
-
- if (idn.localid == IDN_NIL_DOMID) {
- (void) mi_mpprintf(mp, "IDN not initialized (localid = %d)",
- idn.localid);
- return (0);
- }
-
- (void) mi_mpprintf(mp, "Local domain has %d slabs allocated.",
- idn_domain[idn.localid].dnslabs);
-
- DSLAB_LOCK_SHARED(idn.localid);
- if ((sp = idn_domain[idn.localid].dslab) == NULL) {
- DSLAB_UNLOCK(idn.localid);
- return (0);
- }
-
- bzero(bufcount, sizeof (bufcount));
- cnt = 0;
-
- spl = splhi();
- for (; sp; sp = sp->sl_next) {
- smr_slabbuf_t *bp;
-
- while (!lock_try(&sp->sl_lock))
- ;
- for (bp = sp->sl_inuse; bp; bp = bp->sb_next) {
- bufcount[bp->sb_domid]++;
- cnt++;
- }
- lock_clear(&sp->sl_lock);
- }
- splx(spl);
-
- DSLAB_UNLOCK(idn.localid);
-
- (void) mi_mpprintf(mp, "Local domain has %d buffers outstanding.", cnt);
- if (cnt == 0)
- return (0);
-
- (void) mi_mpprintf(mp, "Domain nbufs");
- for (d = 0; d < MAX_DOMAINS; d++)
- if (bufcount[d]) {
- if (d < 10)
- (void) mi_mpprintf(mp, " %d %d",
- d, bufcount[d]);
- else
- (void) mi_mpprintf(mp, " %d %d",
- d, bufcount[d]);
- }
-
- return (0);
-}
-
-static const char *
-_get_spaces(int w, int s, int W)
-{
- static const char *const _spaces[] = {
- "", /* 0 */
- " ", /* 1 */
- " ", /* 2 */
- " ", /* 3 */
- " ", /* 4 */
- " ", /* 5 */
- " ", /* 6 */
- " ", /* 7 */
- " ", /* 8 */
- " ", /* 9 */
- " ", /* 10 */
- " ", /* 11 */
- " ", /* 12 */
- " ", /* 13 */
- " ", /* 14 */
- " ", /* 15 */
- " ", /* 16 */
- " ", /* 17 */
- " ", /* 18 */
- " ", /* 19 */
- };
- return (_spaces[w+s-W]);
-}
-
-#define _SSS(X, W, w, s) \
- (((w) >= (W)) && (X)) ? _get_spaces((w), (s), (W))
-
-static const char *
-_hexspace(uint64_t v, int sz, int width, int padding)
-{
- int maxnbl = 16;
- int diff;
- uchar_t *np;
-
- diff = sizeof (uint64_t) - sz;
- np = (uchar_t *)&v + diff;
- maxnbl -= diff << 1;
- while (sz-- > 0) {
- if ((*np & 0xf0) && (width >= maxnbl))
- return (_get_spaces(width, padding, maxnbl));
- maxnbl--;
- if ((*np & 0x0f) && (width >= maxnbl))
- return (_get_spaces(width, padding, maxnbl));
- maxnbl--;
- np++;
- }
- return (_get_spaces(width, padding, 1));
-}
-
-#define HEXSPACE(v, t, w, s) _hexspace((uint64_t)(v), sizeof (t), (w), (s))
-
-#define DECSPACE(n, w, s) \
- (_SSS((uint_t)(n) >= 10000000, 8, (w), (s)) : \
- _SSS((uint_t)(n) >= 1000000, 7, (w), (s)) : \
- _SSS((uint_t)(n) >= 100000, 6, (w), (s)) : \
- _SSS((uint_t)(n) >= 10000, 5, (w), (s)) : \
- _SSS((uint_t)(n) >= 1000, 4, (w), (s)) : \
- _SSS((uint_t)(n) >= 100, 3, (w), (s)) : \
- _SSS((uint_t)(n) >= 10, 2, (w), (s)) : \
- _get_spaces((w), (s), 1))
-
-#define DECSPACE16(n, w, s) \
- (_SSS((n) >= 10000, 5, (w), (s)) : \
- _SSS((n) >= 1000, 4, (w), (s)) : \
- _SSS((n) >= 100, 3, (w), (s)) : \
- _SSS((n) >= 10, 2, (w), (s)) : \
- _get_spaces((w), (s), 1))
-
-#define MBXINFO(mtp) \
- (void *)&mtp->mt_header, \
- HEXSPACE(&mtp->mt_header, &mtp->mt_header, 16, 2), \
- mtp->mt_header.mh_svr_ready_ptr, \
- HEXSPACE(mtp->mt_header.mh_svr_ready_ptr, \
- mtp->mt_header.mh_svr_ready_ptr, 8, 1), \
- mtp->mt_header.mh_svr_active_ptr, \
- HEXSPACE(mtp->mt_header.mh_svr_active_ptr, \
- mtp->mt_header.mh_svr_active_ptr, 8, 2), \
- *(ushort_t *)(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_ready_ptr)), \
- DECSPACE16(*(ushort_t *) \
- (IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_ready_ptr)), \
- 1, 1), \
- *(ushort_t *)(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_active_ptr)), \
- DECSPACE16(*(ushort_t *) \
- (IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_active_ptr)), \
- 1, 5), \
- mtp->mt_header.mh_cookie, \
- HEXSPACE(mtp->mt_header.mh_cookie, \
- mtp->mt_header.mh_cookie, 8, 2), \
- (void *)&mtp->mt_queue[0], \
- HEXSPACE(&mtp->mt_queue[0], &mtp->mt_queue[0], 16, 2)
-
-/*ARGSUSED*/
-static int
-idn_mboxtbl_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- register int c, n, domid, subdomid;
- register idn_mboxtbl_t *mtp;
- register idn_mboxmsg_t *msp;
- idn_mboxtbl_t *map, *mtbasep;
-
-
- ASSERT((cp == MBXTBL_PART_REPORT) || (cp == MBXTBL_FULL_REPORT));
-
- if (IDN_GLOCK_TRY_SHARED() == 0) {
- (void) mi_mpprintf(mp, "Local domain busy, try again.");
- return (0);
- }
-
- if ((map = idn.mboxarea) == NULL) {
- (void) mi_mpprintf(mp,
- "WARNING: Local domain is not master, "
- "ASSUMING idn.smr.vaddr.");
- map = (idn_mboxtbl_t *)idn.smr.vaddr;
- }
-
- if (map) {
- (void) mi_mpprintf(mp, "Mailbox Area starts @ 0x%p",
- (void *)map);
- } else {
- (void) mi_mpprintf(mp, "Mailbox Area not found.");
- goto repdone;
- }
-
- if (!idn.nchannels) {
- (void) mi_mpprintf(mp, "No OPEN channels found");
- goto repdone;
- }
-
- for (c = 0; c < IDN_MAX_NETS; c++) {
-
- IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]);
- if (!IDN_CHANNEL_IS_ATTACHED(&idn.chan_servers[c])) {
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
- continue;
- }
-
- (void) mi_mpprintf(mp,
- "Channel %d ---------------------------"
- "--------------------------"
- "-----------------------------", c);
- (void) mi_mpprintf(mp,
- " Domain Header "
- "Ready/Active Ptrs "
- "rdy/actv cookie Queue "
- "busy");
-
- for (domid = 0; domid < MAX_DOMAINS; domid++) {
- register int busy_count;
-
- if ((cp == MBXTBL_PART_REPORT) &&
- (idn_domain[domid].dcpu == IDN_NIL_DCPU))
- continue;
-
- mtbasep = IDN_MBOXAREA_BASE(map, domid);
-
- for (subdomid = 0; subdomid < MAX_DOMAINS;
- subdomid++) {
- mtp = IDN_MBOXTBL_PTR(mtbasep, subdomid);
- mtp = IDN_MBOXTBL_PTR_CHAN(mtp, c);
-
- if (subdomid == domid) {
- if (subdomid == 0)
- (void) mi_mpprintf(mp,
- " %x.%x-%d%s%s",
- domid, subdomid, c,
- /*CONSTCOND*/
- DECSPACE(c, 2, 2),
- "-- unused --");
- else
- (void) mi_mpprintf(mp,
- " .%x-%d%s%s",
- subdomid, c,
- /*CONSTCOND*/
- DECSPACE(c, 2, 2),
- "-- unused --");
- continue;
- }
- busy_count = 0;
- msp = &mtp->mt_queue[0];
- for (n = 0; n < IDN_MMBOX_NUMENTRIES; n++) {
- if (msp[n].ms_owner)
- busy_count++;
- }
- if (subdomid == 0) {
- (void) mi_mpprintf(mp,
- " %x.%x-%d%s%p%s%x%s/ %x%s"
- "%d%s/ %d%s%x%s%p%s%d%s",
- domid, subdomid, c,
- /*CONSTCOND*/
- DECSPACE(c, 2, 2),
- MBXINFO(mtp), busy_count,
- busy_count ? " <<<<<":"");
- } else {
- (void) mi_mpprintf(mp,
- " .%x-%d%s%p%s%x%s/ %x%s"
- "%d%s/ %d%s%x%s%p%s%d%s",
- subdomid, c,
- /*CONSTCOND*/
- DECSPACE(c, 2, 2),
- MBXINFO(mtp), busy_count,
- busy_count ? " <<<<<":"");
- }
- }
- }
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
- }
-
-repdone:
- IDN_GUNLOCK();
-
- return (0);
-}
-
-/*ARGSUSED*/
-static void
-idn_mainmbox_domain_report(queue_t *wq, mblk_t *mp, int domid,
- idn_mainmbox_t *mmp, char *mbxtype)
-{
- register int c;
-
- if (mmp == NULL) {
- (void) mi_mpprintf(mp, " %x.%s -- none --", domid, mbxtype);
- return;
- }
-
- for (c = 0; c < IDN_MAX_NETS; mmp++, c++) {
- int mm_count;
-
- IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]);
- if (IDN_CHANNEL_IS_DETACHED(&idn.chan_servers[c])) {
- (void) mi_mpprintf(mp, " %x.%s %u -- not open --",
- domid, mbxtype, (int)mmp->mm_channel);
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
- continue;
- }
-
- mm_count = ((mmp->mm_count < 0) ? 0 : mmp->mm_count) / 1000;
-
- (void) mi_mpprintf(mp, " %x.%s %d%s%d%s%d%s%p%s%p%s%p%s%d/%d",
- domid, mbxtype,
- (int)mmp->mm_channel,
- /*CONSTCOND*/
- DECSPACE((int)mmp->mm_channel, 5, 2),
- mm_count, DECSPACE(mm_count, 8, 2),
- mmp->mm_dropped,
- DECSPACE(mmp->mm_dropped, 8, 2),
- (void *)mmp->mm_smr_mboxp,
- HEXSPACE(mmp->mm_smr_mboxp,
- mmp->mm_smr_mboxp, 16, 2),
- (void *)mmp->mm_smr_readyp,
- HEXSPACE(mmp->mm_smr_readyp,
- mmp->mm_smr_readyp, 16, 2),
- (void *)mmp->mm_smr_activep,
- HEXSPACE(mmp->mm_smr_activep,
- mmp->mm_smr_activep, 16, 2),
- mmp->mm_qiget, mmp->mm_qiput);
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
- }
-}
-
-/*ARGSUSED2*/
-static int
-idn_mainmbox_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- int domid;
- int header = 0;
-
- /*
- * Domain 0 never has a send/recv mainmbox so
- * don't bother printing it.
- */
- for (domid = 1; domid < MAX_DOMAINS; domid++) {
- idn_domain_t *dp;
-
- dp = &idn_domain[domid];
-
- if (dp->dcpu == IDN_NIL_DCPU)
- continue;
- IDN_DLOCK_SHARED(domid);
- if (dp->dcpu == IDN_NIL_DCPU) {
- IDN_DUNLOCK(domid);
- continue;
- }
- if (!header) {
- (void) mi_mpprintf(mp,
- "Domain Chan PktCntK "
- "PktDrop SMRMbox "
- "ReadyPtr "
- "ActvPtr Miget/Miput");
- header = 1;
- }
-
- mutex_enter(&dp->dmbox.m_mutex);
- idn_mainmbox_domain_report(wq, mp, domid,
- idn_domain[domid].dmbox.m_send,
- "snd");
- idn_mainmbox_domain_report(wq, mp, domid,
- idn_domain[domid].dmbox.m_recv,
- "rcv");
- mutex_exit(&dp->dmbox.m_mutex);
-
- IDN_DUNLOCK(domid);
-
- (void) mi_mpprintf(mp,
- " ---------------------------------------"
- "------------------------"
- "----------------------------");
- }
-
- if (!header)
- (void) mi_mpprintf(mp, "No ACTIVE domain connections exist");
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-idn_global_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- int i, nactive, masterid, nretry;
- uint_t locpfn_upper, locpfn_lower,
- rempfn_upper, rempfn_lower;
- uint_t marea_upper, marea_lower,
- iarea_upper, iarea_lower;
- char alt_dbuffer[64];
- idn_retry_job_t *rp;
- domainset_t retryset;
- domainset_t connected;
- idn_synczone_t *zp;
- idn_syncop_t *sp;
- idn_domain_t *dp;
- char *dbp, *dbuffer;
-
- if (IDN_SYNC_TRYLOCK() == 0) {
- (void) mi_mpprintf(mp, "Sync lock busy, try again.");
- return (0);
- }
-
- if (IDN_GLOCK_TRY_SHARED() == 0) {
- (void) mi_mpprintf(mp, "Local domain busy, try again.");
- IDN_SYNC_UNLOCK();
- return (0);
- }
- if ((dbp = dbuffer = ALLOC_DISPSTRING()) == NULL)
- dbp = alt_dbuffer;
-
- (void) mi_mpprintf(mp, "IDN\n Global State = %s (%d)",
- idngs_str[idn.state], idn.state);
-
- (void) mi_mpprintf(mp, "SMR");
- (void) mi_mpprintf(mp, " vaddr ");
- (void) mi_mpprintf(mp, " 0x%p", (void *)idn.smr.vaddr);
-
- (void) mi_mpprintf(mp, " paddr-local paddr-remote");
- masterid = IDN_GET_MASTERID();
- locpfn_upper = (uint_t)(idn.smr.locpfn >> (32 - PAGESHIFT));
- locpfn_lower = (uint_t)(idn.smr.locpfn << PAGESHIFT);
- if (idn.smr.rempfn == PFN_INVALID) {
- rempfn_upper = rempfn_lower = 0;
- } else {
- rempfn_upper = (uint_t)(idn.smr.rempfn >> (32 - PAGESHIFT));
- rempfn_lower = (uint_t)(idn.smr.rempfn << PAGESHIFT);
- }
- (void) mi_mpprintf(mp, " 0x%x.%x%s0x%x.%x",
- locpfn_upper, locpfn_lower,
- HEXSPACE(locpfn_lower, locpfn_lower, 8,
- (locpfn_upper < 0x10) ? 4 : 3),
- rempfn_upper, rempfn_lower);
-
- (void) mi_mpprintf(mp, " SMR length = %d MBytes", IDN_SMR_SIZE);
- (void) mi_mpprintf(mp, " SMR bufsize = %d Bytes", IDN_SMR_BUFSIZE);
- (void) mi_mpprintf(mp, " NWR length = %d MBytes", IDN_NWR_SIZE);
- marea_upper = (uint_t)((uint64_t)IDN_MBOXAREA_SIZE >> 32);
- marea_lower = (uint_t)((uint64_t)IDN_MBOXAREA_SIZE & 0xffffffff);
- iarea_upper = (uint_t)((uint64_t)(MB2B(IDN_NWR_SIZE) -
- (size_t)IDN_MBOXAREA_SIZE) >> 32);
- iarea_lower = (uint_t)((MB2B(IDN_NWR_SIZE) -
- (size_t)IDN_MBOXAREA_SIZE) & 0xffffffff);
- (void) mi_mpprintf(mp,
- " [ mbox area = 0x%x.%x Bytes, "
- "iobuf area = 0x%x.%x Bytes ]",
- marea_upper, marea_lower, iarea_upper, iarea_lower);
-
- (void) mi_mpprintf(mp,
- "\nIDNnet (local domain [id:%d] [name:%s] is %s)",
- idn.localid,
- idn_domain[idn.localid].dname,
- (masterid == IDN_NIL_DOMID) ? "IDLE" :
- (idn.localid == masterid) ? "MASTER" :
- "SLAVE");
- nactive = 0;
- for (i = 0; i < IDN_MAX_NETS; i++) {
- IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[i]);
- if (IDN_CHANNEL_IS_ACTIVE(&idn.chan_servers[i]))
- nactive++;
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[i]);
- }
- (void) mi_mpprintf(mp, " I/O Networks: (Open = %d, "
- "Active = %d, Max = %d)",
- idn.nchannels, nactive, IDN_MAX_NETS);
- (void) mi_mpprintf(mp, " Number of Domains = %d", idn.ndomains);
- (void) mi_mpprintf(mp, " Number of AWOLs = %d", idn.nawols);
- /*
- * During connect domains can possibly be in ds_connected
- * while still in ds_trans_on. Only once they leave ds_trans_on
- * are they really connected.
- */
- connected = idn.domset.ds_connected & ~idn.domset.ds_trans_on;
- DOMAINSET_ADD(connected, idn.localid);
- boardset2str(connected, dbp);
- (void) mi_mpprintf(mp, " Connected Domains = %s", dbp);
- domainset2str(idn.domset.ds_trans_on, dbp);
- (void) mi_mpprintf(mp, " Pending Domain Links = %s",
- idn.domset.ds_trans_on ? dbp : "<>");
- domainset2str(idn.domset.ds_trans_off, dbp);
- (void) mi_mpprintf(mp, " Pending Domain Unlinks = %s",
- idn.domset.ds_trans_off ? dbp : "<>");
- mutex_enter(&idn.retryqueue.rq_mutex);
- nretry = idn.retryqueue.rq_count;
- retryset = 0;
- for (i = 0, rp = idn.retryqueue.rq_jobs; i < nretry; i++,
- rp = rp->rj_next) {
- int domid;
-
- domid = IDN_RETRY_TOKEN2DOMID(rp->rj_token);
- if (VALID_DOMAINID(domid)) {
- DOMAINSET_ADD(retryset, domid);
- }
- }
- mutex_exit(&idn.retryqueue.rq_mutex);
- domainset2str(retryset, dbp);
- (void) mi_mpprintf(mp, " Retry Jobs:Domains = %d:%s",
- nretry, retryset ? dbp : "<>");
- domainset2str(idn.domset.ds_hitlist, dbp);
- (void) mi_mpprintf(mp, " Hitlist Domains = %s",
- idn.domset.ds_hitlist ? dbp : "<>");
- domainset2str(idn.domset.ds_relink, dbp);
- (void) mi_mpprintf(mp, " Reconfig Domains = %s",
- idn.domset.ds_relink ? dbp : "<>");
- if (idn.domset.ds_relink)
- (void) mi_mpprintf(mp, " new master id = %d",
- IDN_GET_NEW_MASTERID());
- if (masterid == IDN_NIL_DOMID) {
- (void) mi_mpprintf(mp, " Master Domain: no master");
- } else {
- idn_domain_t *mdp;
-
- mdp = &idn_domain[masterid];
-
- (void) mi_mpprintf(mp,
- " Master Domain (id:name/brds - state):");
-
- if (strlen(mdp->dname) > 0)
- (void) strcpy(dbp, mdp->dname);
- else
- boardset2str(mdp->dhw.dh_boardset, dbp);
- if (masterid < 10)
- (void) mi_mpprintf(mp, " %d: %s - %s",
- masterid, dbp,
- idnds_str[mdp->dstate]);
- else
- (void) mi_mpprintf(mp, " %d: %s - %s",
- masterid, dbp,
- idnds_str[mdp->dstate]);
- }
- if (idn.ndomains <= 1) {
- (void) mi_mpprintf(mp, " Slave Domains: none");
- } else {
- int d;
-
- (void) mi_mpprintf(mp,
- " Slave Domains (id:name/brds - state):");
- for (d = 0; d < MAX_DOMAINS; d++) {
- dp = &idn_domain[d];
-
- if ((dp->dcpu == IDN_NIL_DCPU) || (d == masterid))
- continue;
-
- if (strlen(dp->dname) > 0)
- (void) strcpy(dbp, dp->dname);
- else
- boardset2str(dp->dhw.dh_boardset, dbp);
- if (d < 10)
- (void) mi_mpprintf(mp, " %d: %s - %s",
- d, dbp,
- idnds_str[dp->dstate]);
- else
- (void) mi_mpprintf(mp, " %d: %s - %s",
- d, dbp,
- idnds_str[dp->dstate]);
- }
- }
-
- if (idn.nawols == 0) {
- (void) mi_mpprintf(mp, " AWOL Domains: none");
- } else {
- int d;
-
- (void) mi_mpprintf(mp, " AWOL Domains (id:name/brds):");
- for (d = 0; d < MAX_DOMAINS; d++) {
- dp = &idn_domain[d];
-
- if (!DOMAIN_IN_SET(idn.domset.ds_awol, d) ||
- (dp->dcpu == IDN_NIL_DCPU))
- continue;
-
- if (strlen(dp->dname) > 0)
- (void) strcpy(dbp, dp->dname);
- else
- boardset2str(dp->dhw.dh_boardset, dbp);
- if (d < 10)
- (void) mi_mpprintf(mp, " %d: %s",
- d, dbp);
- else
- (void) mi_mpprintf(mp, " %d: %s",
- d, dbp);
- }
- }
-
- /*CONSTCOND*/
- i = IDN_SYNC_GETZONE(IDNSYNC_CONNECT);
- zp = &idn.sync.sz_zone[i];
- if (zp->sc_cnt == 0) {
- (void) mi_mpprintf(mp, " Sync Zone (con): [empty]");
- } else {
- (void) mi_mpprintf(mp, " Sync Zone (con): [%d domains]",
- zp->sc_cnt);
- sp = zp->sc_op;
- for (i = 0; (i < zp->sc_cnt) && sp; i++) {
- (void) mi_mpprintf(mp,
- " "
- "%x: x_set =%s0x%x, r_set =%s0x%x",
- sp->s_domid,
- HEXSPACE(sp->s_set_exp,
- sp->s_set_exp, 4, 1),
- sp->s_set_exp,
- HEXSPACE(sp->s_set_rdy,
- sp->s_set_rdy, 4, 1),
- sp->s_set_rdy);
- sp = sp->s_next;
- }
- }
- /*CONSTCOND*/
- i = IDN_SYNC_GETZONE(IDNSYNC_DISCONNECT);
- zp = &idn.sync.sz_zone[i];
- if (zp->sc_cnt == 0) {
- (void) mi_mpprintf(mp, " Sync Zone (dis): [empty]");
- } else {
- (void) mi_mpprintf(mp, " Sync Zone (dis): [%d domains]",
- zp->sc_cnt);
- sp = zp->sc_op;
- for (i = 0; (i < zp->sc_cnt) && sp; i++) {
- (void) mi_mpprintf(mp,
- " "
- "%x: x_set =%s0x%x, r_set =%s0x%x",
- sp->s_domid,
- HEXSPACE(sp->s_set_exp,
- sp->s_set_exp, 4, 1),
- sp->s_set_exp,
- HEXSPACE(sp->s_set_rdy,
- sp->s_set_rdy, 4, 1),
- sp->s_set_rdy);
- sp = sp->s_next;
- }
- }
-
- IDN_GUNLOCK();
- IDN_SYNC_UNLOCK();
-
- if (dbuffer) {
- FREE_DISPSTRING(dbuffer);
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-idn_domain_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
- int d, nchan;
- uint_t domset;
- idn_chanset_t chanset;
- idn_domain_t *dp;
- uint_t pset_upper, pset_lower;
- char *dbuffer, *dbp;
- char alt_dbuffer[64];
-
-
- if (IDN_SYNC_TRYLOCK() == 0) {
- (void) mi_mpprintf(mp, "Sync lock busy, try again.");
- return (0);
- }
-
- if (IDN_GLOCK_TRY_SHARED() == 0) {
- (void) mi_mpprintf(mp, "Local domain busy, try again.");
- IDN_SYNC_UNLOCK();
- return (0);
- }
-
- if ((dbp = dbuffer = ALLOC_DISPSTRING()) == NULL)
- dbp = alt_dbuffer;
-
- if (cp == NULL)
- domset = DOMAINSET(idn.localid);
- else
- domset = DOMAINSET_ALL;
-
- for (d = 0; d < MAX_DOMAINS; d++) {
-
- if (DOMAIN_IN_SET(domset, d) == 0)
- continue;
-
- dp = &idn_domain[d];
-
- if (dp->dcpu == IDN_NIL_DCPU)
- continue;
-
- if (IDN_DLOCK_TRY_SHARED(d) == 0) {
- if (d < 10)
- (void) mi_mpprintf(mp,
- "Domain %d (0x%p) busy...",
- d, (void *)dp);
- else
- (void) mi_mpprintf(mp,
- "Domain %d (0x%p) busy...",
- d, (void *)dp);
- continue;
- }
- if (dp->dcpu == IDN_NIL_DCPU) {
- IDN_DUNLOCK(d);
- continue;
- }
- if (d < 10)
- (void) mi_mpprintf(mp, "%sDomain %d (0x%p)",
- (d && (idn.ndomains > 1)) ? "\n" : "",
- d, (void *)dp);
- else
- (void) mi_mpprintf(mp, "%sDomain %d (0x%p)",
- (d && (idn.ndomains > 1)) ? "\n" : "",
- d, (void *)dp);
-
- if (d == idn.localid)
- (void) mi_mpprintf(mp, " (local) State = %s (%d)",
- idnds_str[dp->dstate], dp->dstate);
- else
- (void) mi_mpprintf(mp, " State = %s (%d)",
- idnds_str[dp->dstate], dp->dstate);
- (void) mi_mpprintf(mp, " Name = %s, Netid = %d",
- (strlen(dp->dname) > 0) ? dp->dname : "<>",
- (int)dp->dnetid);
-
- CHANSET_ZERO(chanset);
- nchan = idn_domain_is_registered(d, -1, &chanset);
- if (dbuffer)
- mask2str(chanset, dbp, 32);
- else
- (void) sprintf(dbp, "0x%x", chanset);
- (void) mi_mpprintf(mp, " Nchans = %d, Chanset = %s",
- nchan, nchan ? dbp : "<>");
- pset_upper = UPPER32_CPUMASK(dp->dcpuset);
- pset_lower = LOWER32_CPUMASK(dp->dcpuset);
- if (dbuffer)
- boardset2str(dp->dhw.dh_boardset, dbp);
- else
- (void) sprintf(dbp, "0x%x", dp->dhw.dh_boardset);
-
- (void) mi_mpprintf(mp, " Nboards = %d, Brdset = %s",
- dp->dhw.dh_nboards,
- dp->dhw.dh_nboards ? dbp : "<>");
- (void) sprintf(dbp, "0x%x.%x", pset_upper, pset_lower);
- (void) mi_mpprintf(mp, " Ncpus = %d, Cpuset = %s",
- dp->dncpus, dp->dncpus ? dbp : "<>");
- (void) mi_mpprintf(mp, " Nmcadr = %d",
- dp->dhw.dh_nmcadr);
- (void) mi_mpprintf(mp,
- " MsgTimer = %s (cnt = %d)",
- (dp->dtimerq.tq_count > 0)
- ? "active" : "idle",
- dp->dtimerq.tq_count);
- (void) mi_mpprintf(mp, " Dcpu = %d "
- "(lastcpu = %d, cpuindex = %d)",
- dp->dcpu, dp->dcpu_last, dp->dcpuindex);
- (void) mi_mpprintf(mp, " Dio = %d "
- "(ioerr = %d, iochk = %d, iowanted = %d)",
- dp->dio, dp->dioerr, dp->diocheck ? 1 : 0,
- dp->diowanted ? 1 : 0);
- if (dp->dsync.s_cmd == IDNSYNC_NIL) {
- (void) mi_mpprintf(mp, " Dsync = %s",
- idnsync_str[IDNSYNC_NIL]);
- } else {
- (void) mi_mpprintf(mp,
- " Dsync = %s "
- "(x_set = 0x%x, r_set = 0x%x)",
- idnsync_str[dp->dsync.s_cmd],
- (uint_t)dp->dsync.s_set_exp,
- (uint_t)dp->dsync.s_set_rdy);
- }
- (void) mi_mpprintf(mp, " Dvote = 0x%x",
- dp->dvote.ticket);
- (void) mi_mpprintf(mp, " Dfin = %s (Sync = %s)",
- idnfin_str[dp->dfin],
- (dp->dfin_sync == IDNFIN_SYNC_OFF) ? "OFF" :
- (dp->dfin_sync == IDNFIN_SYNC_YES) ? "YES" :
- "NO");
- (void) mi_mpprintf(mp, " Dcookie_err = %s (cnt = %d)",
- dp->dcookie_err ? "YES" : "NO",
- dp->dcookie_errcnt);
- IDN_DUNLOCK(d);
- }
-
- IDN_GUNLOCK();
-
- if (dbuffer) {
- FREE_DISPSTRING(dbuffer);
- }
-
- IDN_SYNC_UNLOCK();
-
- return (0);
-}
-
-#define SNOOP_ENTRIES 2048 /* power of 2 */
-
-struct snoop_buffer {
-/* 0 */ char io;
-/* 1 */ char board;
-/* 2 */ char trans[14];
-
-/* 10 */ uint_t xargs[4];
-} *snoop_data, snoop_buffer[SNOOP_ENTRIES+1];
-
-
-int snoop_index;
-kmutex_t snoop_mutex;
-static char _bd2hexascii[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-#define SNOOP_IDN(in, tr, bd, arg1, arg2, arg3, arg4) \
-{ \
- if (idn_snoop) { \
- mutex_enter(&snoop_mutex); \
- if (snoop_data == NULL) { \
- snoop_data = (struct snoop_buffer *) \
- (((uint_t)(uintptr_t)snoop_buffer + 0xf) & \
- ~0xf); \
- } \
- snoop_data[snoop_index].io = ((in) == 0) ? 'o' : 'i'; \
- snoop_data[snoop_index].board = \
- ((bd) == -1) ? 'X' : _bd2hexascii[bd]; \
- (void) strncpy(snoop_data[snoop_index].trans, (tr), 14); \
- snoop_data[snoop_index].xargs[0] = (arg1); \
- snoop_data[snoop_index].xargs[1] = (arg2); \
- snoop_data[snoop_index].xargs[2] = (arg3); \
- snoop_data[snoop_index].xargs[3] = (arg4); \
- snoop_index++; \
- snoop_index &= SNOOP_ENTRIES - 1; \
- mutex_exit(&snoop_mutex); \
- } \
-}
-
-/*
- * Allocate the circular buffers to be used for
- * DMV interrupt processing.
- */
-static int
-idn_init_handler()
-{
- int i, c;
- size_t len;
- idn_dmv_msg_t *basep, *ivp;
- uint32_t ivp_offset;
- procname_t proc = "idn_init_handler";
-
- if (idn.intr.dmv_data != NULL) {
- cmn_err(CE_WARN,
- "IDN: 130: IDN DMV handler already initialized");
- return (-1);
- }
-
- /*
- * This memory will be touched by the low-level
- * DMV trap handler for IDN.
- */
- len = sizeof (idn_dmv_data_t);
- len = roundup(len, sizeof (uint64_t));
- len += NCPU * idn_dmv_pending_max * sizeof (idn_dmv_msg_t);
- len = roundup(len, PAGESIZE);
-
- PR_PROTO("%s: sizeof (idn_dmv_data_t) = %lu\n",
- proc, sizeof (idn_dmv_data_t));
- PR_PROTO("%s: allocating %lu bytes for dmv data area\n", proc, len);
-
- idn.intr.dmv_data_len = len;
- idn.intr.dmv_data = kmem_zalloc(len, KM_SLEEP);
-
- PR_PROTO("%s: DMV data area = %p\n", proc, (void *)idn.intr.dmv_data);
-
- idn_dmv_data = (idn_dmv_data_t *)idn.intr.dmv_data;
- basep = (idn_dmv_msg_t *)roundup((size_t)idn.intr.dmv_data +
- sizeof (idn_dmv_data_t),
- sizeof (uint64_t));
- idn_dmv_data->idn_dmv_qbase = (uint64_t)basep;
-
- ivp = basep;
- ivp_offset = 0;
- /*
- * The buffer queues are allocated per-cpu.
- */
- for (c = 0, ivp = basep; c < NCPU; ivp++, c++) {
- idn_dmv_data->idn_dmv_cpu[c].idn_dmv_current = ivp_offset;
- idn_iv_queue[c] = ivp;
- ivp_offset += sizeof (idn_dmv_msg_t);
- for (i = 1; i < idn_dmv_pending_max; ivp++, i++) {
- ivp->iv_next = ivp_offset;
- ivp->iv_ready = 0;
- lock_set(&ivp->iv_ready);
- ivp_offset += sizeof (idn_dmv_msg_t);
- }
- ivp->iv_next = idn_dmv_data->idn_dmv_cpu[c].idn_dmv_current;
- ivp->iv_ready = 0;
- lock_set(&ivp->iv_ready);
- }
-
- idn.intr.dmv_inum = STARFIRE_DMV_IDN_BASE;
- idn.intr.soft_inum = add_softintr((uint_t)idn_pil, idn_handler, 0,
- SOFTINT_ST);
- idn_dmv_data->idn_soft_inum = idn.intr.soft_inum;
- /*
- * Make sure everything is out there before
- * we effectively set it free for use.
- */
- membar_stld_stst();
-
- if (dmv_add_intr(idn.intr.dmv_inum, idn_dmv_handler,
- (caddr_t)idn_dmv_data)) {
- idn_deinit_handler();
- cmn_err(CE_WARN, "IDN: 132: failed to add IDN DMV handler");
- return (-1);
- }
-
- return (0);
-}
-
-static void
-idn_deinit_handler()
-{
- if (idn.intr.dmv_data == NULL)
- return;
-
- (void) dmv_rem_intr(idn.intr.dmv_inum);
- (void) rem_softintr(idn.intr.soft_inum);
- kmem_free(idn.intr.dmv_data, idn.intr.dmv_data_len);
- idn.intr.dmv_data = NULL;
-}
-
-/*
- * High-level (soft interrupt) handler for DMV interrupts
- */
-/*ARGSUSED0*/
-static uint_t
-idn_handler(caddr_t unused, caddr_t unused2)
-{
-#ifdef DEBUG
- int count = 0;
-#endif /* DEBUG */
- int cpuid = (int)CPU->cpu_id;
- ushort_t mtype, atype;
- idn_dmv_msg_t *xp, *xplimit;
- procname_t proc = "idn_handler";
-
- ASSERT(getpil() >= idn_pil);
- flush_windows();
-
- /*
- * Clear the synchronization flag to indicate that
- * processing has started. As long as idn_dmv_active
- * is non-zero, idn_dmv_handler will queue work without
- * initiating a soft interrupt. Since we clear it
- * first thing at most one pil-interrupt for IDN will
- * queue up behind the currently active one. We don't
- * want to clear this flag at the end because it leaves
- * a window where an interrupt could get lost (unless it's
- * pushed by a subsequent interrupt). The objective in
- * doing this is to prevent exhausting a cpu's intr_vec
- * structures with interrupts of the same pil level.
- */
- lock_clear(&idn_dmv_data->idn_dmv_cpu[cpuid].idn_dmv_active);
-
- xp = idn_iv_queue[cpuid];
- xplimit = xp + idn_dmv_pending_max;
- xp += idn_intr_index[cpuid];
- /*
- * As long as there's stuff that's READY in the
- * queue, keep processing.
- */
- while (lock_try(&xp->iv_ready)) {
-
- ASSERT(lock_try(&xp->iv_inuse) == 0);
-
- mtype = (ushort_t)xp->iv_mtype;
- mtype &= IDNP_MSGTYPE_MASK | IDNP_ACKNACK_MASK;
- atype = (ushort_t)xp->iv_atype;
-
- if (((int)xp->iv_ver == idn.version) && mtype) {
- idn_protojob_t *jp;
-#ifdef DEBUG
- STRING(mstr);
- STRING(astr);
-
- INUM2STR(mtype, mstr);
- if ((mtype & IDNP_MSGTYPE_MASK) == 0) {
- INUM2STR(atype, astr);
- (void) strcat(mstr, "/");
- (void) strcat(mstr, astr);
- }
-
- count++;
-
- PR_XDC("%s:%d:%d RECV: scpu = %d, msg = 0x%x(%s)\n",
- proc, (int)xp->iv_domid, count,
- (int)xp->iv_cpuid, mtype, mstr);
- PR_XDC("%s:%d:%d R-DATA: a0 = 0x%x, a1 = 0x%x\n",
- proc, (int)xp->iv_domid, count,
- xp->iv_xargs0, xp->iv_xargs1);
- PR_XDC("%s:%d:%d R-DATA: a2 = 0x%x, a3 = 0x%x\n",
- proc, (int)xp->iv_domid, count,
- xp->iv_xargs2, xp->iv_xargs3);
-#endif /* DEBUG */
-
- if (mtype == IDNP_DATA) {
- jp = NULL;
- /*
- * The only time we receive pure
- * data messages at this level is
- * to wake up the channel server.
- * Since this is often an urgent
- * request we'll do it from here
- * instead of waiting for a proto
- * server to do it.
- */
- idn_signal_data_server((int)xp->iv_domid,
- (ushort_t)xp->iv_xargs0);
- } else {
- jp = idn_protojob_alloc(KM_NOSLEEP);
- /*
- * If the allocation fails, just drop
- * the message and get on with life.
- * If memory pressure is this great then
- * dropping this message is probably
- * the least of our worries!
- */
- if (jp) {
- jp->j_msg.m_domid = (int)xp->iv_domid;
- jp->j_msg.m_cpuid = (int)xp->iv_cpuid;
- jp->j_msg.m_msgtype = mtype;
- jp->j_msg.m_acktype = atype;
- jp->j_msg.m_cookie = xp->iv_cookie;
- SET_XARGS(jp->j_msg.m_xargs,
- xp->iv_xargs0, xp->iv_xargs1,
- xp->iv_xargs2, xp->iv_xargs3);
- }
-
- }
- membar_ldst_stst();
-
- lock_clear(&xp->iv_inuse);
-
- if (jp)
- idn_protojob_submit(jp->j_msg.m_domid, jp);
- } else {
- membar_ldst_stst();
- IDN_GKSTAT_INC(gk_dropped_intrs);
- lock_clear(&xp->iv_inuse);
- }
-
- if (++xp == xplimit)
- xp = idn_iv_queue[cpuid];
- }
-
- idn_intr_index[cpuid] = xp - idn_iv_queue[cpuid];
-
- return (DDI_INTR_CLAIMED);
-}
-
-void
-idn_awol_event_set(boardset_t boardset)
-{
- idnsb_event_t *sbp;
- procname_t proc = "idn_awol_event_set";
-
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- mutex_enter(&idn.idnsb_mutex);
- sbp = idn.idnsb_eventp;
- if (sbp == NULL) {
- cmn_err(CE_WARN, "IDN: 133: sigblock event area missing");
- cmn_err(CE_CONT,
- "IDN: 134: unable to mark boardset (0x%x) AWOL\n",
- boardset);
- mutex_exit(&idn.idnsb_mutex);
- return;
- }
-
- if (boardset == 0) {
- PR_PROTO("%s: AWOL BOARDSET is 0, NO EVENT <<<<<<<<<<<<<<<\n",
- proc);
- mutex_exit(&idn.idnsb_mutex);
- return;
- } else {
- PR_PROTO("%s: MARKING BOARDSET (0x%x) AWOL\n", proc, boardset);
- }
- SSIEVENT_ADD(sbp, SSIEVENT_AWOL, boardset);
- mutex_exit(&idn.idnsb_mutex);
-}
-
-void
-idn_awol_event_clear(boardset_t boardset)
-{
- idnsb_event_t *sbp;
- procname_t proc = "idn_awol_event_clear";
-
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- mutex_enter(&idn.idnsb_mutex);
- sbp = idn.idnsb_eventp;
- if (sbp == NULL) {
- cmn_err(CE_WARN, "IDN: 133: sigblock event area missing");
- cmn_err(CE_CONT,
- "IDN: 134: unable to mark boardset (0x%x) AWOL\n",
- boardset);
- mutex_exit(&idn.idnsb_mutex);
- return;
- }
-
- if (boardset == 0) {
- PR_PROTO("%s: AWOL BOARDSET is 0, NO EVENT <<<<<<<<<<<<<<<\n",
- proc);
- mutex_exit(&idn.idnsb_mutex);
- return;
- } else {
- PR_PROTO("%s: CLEARING BOARDSET (0x%x) AWOL\n", proc, boardset);
- }
- SSIEVENT_DEL(sbp, SSIEVENT_AWOL, boardset);
- mutex_exit(&idn.idnsb_mutex);
-}
-
-static void
-idn_gkstat_init()
-{
- struct kstat *ksp;
- struct idn_gkstat_named *sgkp;
-
-#ifdef kstat
- if ((ksp = kstat_create(IDNNAME, ddi_get_instance(idn.dip),
- IDNNAME, "net", KSTAT_TYPE_NAMED,
- sizeof (struct idn_gkstat_named) / sizeof (kstat_named_t),
- KSTAT_FLAG_PERSISTENT)) == NULL) {
-#else
- if ((ksp = kstat_create(IDNNAME, ddi_get_instance(idn.dip),
- IDNNAME, "net", KSTAT_TYPE_NAMED,
- sizeof (struct idn_gkstat_named) /
- sizeof (kstat_named_t), 0)) == NULL) {
-#endif /* kstat */
- cmn_err(CE_CONT, "IDN: 135: %s: %s\n",
- IDNNAME, "kstat_create failed");
- return;
- }
-
- idn.ksp = ksp;
- sgkp = (struct idn_gkstat_named *)(ksp->ks_data);
- kstat_named_init(&sgkp->sk_curtime, "curtime",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_reconfigs, "reconfigs",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_reconfig_last, "reconfig_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_reaps, "reaps",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_reap_last, "reap_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_links, "links",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_link_last, "link_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_unlinks, "unlinks",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_unlink_last, "unlink_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_buffail, "buf_fail",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_buffail_last, "buf_fail_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_slabfail, "slab_fail",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_slabfail_last, "slab_fail_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_slabfail_last, "slab_fail_last",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_reap_count, "reap_count",
- KSTAT_DATA_ULONG);
- kstat_named_init(&sgkp->sk_dropped_intrs, "dropped_intrs",
- KSTAT_DATA_ULONG);
- ksp->ks_update = idn_gkstat_update;
- ksp->ks_private = (void *)NULL;
- kstat_install(ksp);
-}
-
-static void
-idn_gkstat_deinit()
-{
- if (idn.ksp)
- kstat_delete(idn.ksp);
- idn.ksp = NULL;
-}
-
-static int
-idn_gkstat_update(kstat_t *ksp, int rw)
-{
- struct idn_gkstat_named *sgkp;
-
- sgkp = (struct idn_gkstat_named *)ksp->ks_data;
-
- if (rw == KSTAT_WRITE) {
- sg_kstat.gk_reconfigs = sgkp->sk_reconfigs.value.ul;
- sg_kstat.gk_reconfig_last = sgkp->sk_reconfig_last.value.ul;
- sg_kstat.gk_reaps = sgkp->sk_reaps.value.ul;
- sg_kstat.gk_reap_last = sgkp->sk_reap_last.value.ul;
- sg_kstat.gk_links = sgkp->sk_links.value.ul;
- sg_kstat.gk_link_last = sgkp->sk_link_last.value.ul;
- sg_kstat.gk_unlinks = sgkp->sk_unlinks.value.ul;
- sg_kstat.gk_unlink_last = sgkp->sk_unlink_last.value.ul;
- sg_kstat.gk_buffail = sgkp->sk_buffail.value.ul;
- sg_kstat.gk_buffail_last = sgkp->sk_buffail_last.value.ul;
- sg_kstat.gk_slabfail = sgkp->sk_slabfail.value.ul;
- sg_kstat.gk_slabfail_last = sgkp->sk_slabfail_last.value.ul;
- sg_kstat.gk_reap_count = sgkp->sk_reap_count.value.ul;
- sg_kstat.gk_dropped_intrs = sgkp->sk_dropped_intrs.value.ul;
- } else {
- sgkp->sk_curtime.value.ul = ddi_get_lbolt();
- sgkp->sk_reconfigs.value.ul = sg_kstat.gk_reconfigs;
- sgkp->sk_reconfig_last.value.ul = sg_kstat.gk_reconfig_last;
- sgkp->sk_reaps.value.ul = sg_kstat.gk_reaps;
- sgkp->sk_reap_last.value.ul = sg_kstat.gk_reap_last;
- sgkp->sk_links.value.ul = sg_kstat.gk_links;
- sgkp->sk_link_last.value.ul = sg_kstat.gk_link_last;
- sgkp->sk_unlinks.value.ul = sg_kstat.gk_unlinks;
- sgkp->sk_unlink_last.value.ul = sg_kstat.gk_unlink_last;
- sgkp->sk_buffail.value.ul = sg_kstat.gk_buffail;
- sgkp->sk_buffail_last.value.ul = sg_kstat.gk_buffail_last;
- sgkp->sk_slabfail.value.ul = sg_kstat.gk_slabfail;
- sgkp->sk_slabfail_last.value.ul = sg_kstat.gk_slabfail_last;
- sgkp->sk_reap_count.value.ul = sg_kstat.gk_reap_count;
- sgkp->sk_dropped_intrs.value.ul = sg_kstat.gk_dropped_intrs;
- }
-
- return (0);
-}
-
-#ifdef DEBUG
-#define RW_HISTORY 100
-static uint_t rw_history[NCPU][RW_HISTORY];
-static int rw_index[NCPU];
-#endif /* DEBUG */
-
-static int
-idn_rw_mem(idnop_t *idnop)
-{
- uint_t lo_off, hi_off;
- int rw, blksize, num;
- int cpuid;
- register int n, idx;
- char *ibuf, *obuf;
- char *smraddr;
- struct seg *segp;
- ulong_t randx;
- kmutex_t slock;
- kcondvar_t scv;
- static int orig_gstate = IDNGS_IGNORE;
- extern struct seg ktextseg;
-
-#define RANDOM_INIT() (randx = ddi_get_lbolt())
-#define RANDOM(a, b) \
- (((a) >= (b)) ? \
- (a) : (((randx = randx * 1103515245L + 12345) % ((b)-(a))) + (a)))
-
- RANDOM_INIT();
-
- lo_off = idnop->rwmem.lo_off;
- hi_off = idnop->rwmem.hi_off;
- blksize = idnop->rwmem.blksize;
- num = idnop->rwmem.num;
- rw = idnop->rwmem.rw; /* 0 = rd, 1 = wr, 2 = rd/wr */
-
- if (((hi_off > (uint_t)MB2B(IDN_SMR_SIZE)) || (lo_off >= hi_off) ||
- (blksize <= 0) || (blksize > (hi_off - lo_off)) || (num <= 0)) &&
- (idnop->rwmem.goawol == -1)) {
- return (EINVAL);
- }
-
- if (idnop->rwmem.goawol && (orig_gstate == IDNGS_IGNORE)) {
- IDN_GLOCK_EXCL();
- cmn_err(CE_WARN, "IDN: Local domain going into IGNORE MODE!!");
- orig_gstate = idn.state;
- IDN_GSTATE_TRANSITION(IDNGS_IGNORE);
- IDN_GUNLOCK();
-
- } else if (!idnop->rwmem.goawol && (orig_gstate != IDNGS_IGNORE)) {
- IDN_GLOCK_EXCL();
- cmn_err(CE_WARN,
- "IDN: Local domain restoring original state %s(%d)",
- idngs_str[orig_gstate], (int)orig_gstate);
- IDN_GSTATE_TRANSITION(orig_gstate);
- orig_gstate = IDNGS_IGNORE;
- IDN_GUNLOCK();
- }
- /*
- * Just requested AWOL.
- */
- if (num == 0)
- return (0);
- /*
- * Default READ only.
- */
- ibuf = (char *)kmem_alloc(blksize, KM_SLEEP);
- if (rw == 1) {
- /*
- * WRITE only.
- */
- obuf = ibuf;
- ibuf = NULL;
- } else if (rw == 2) {
- /*
- * READ/WRITE.
- */
- obuf = (char *)kmem_alloc(blksize, KM_SLEEP);
- for (segp = &ktextseg; segp; segp = AS_SEGNEXT(&kas, segp)) {
- if (segp->s_size >= blksize)
- break;
- }
- if (segp == NULL) {
- cmn_err(CE_WARN,
- "IDN: blksize (%d) too large", blksize);
- return (EINVAL);
- }
- bcopy(segp->s_base, obuf, blksize);
- }
-
- mutex_init(&slock, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&scv, NULL, CV_DEFAULT, NULL);
-
- cmn_err(CE_NOTE,
- "IDN: starting %s of %d blocks of %d bytes each...",
- (rw == 1) ? "W-ONLY" : (rw == 2) ? "RW" : "R-ONLY",
- num, blksize);
-
- for (n = 0; n < num; n++) {
- uint_t rpos;
-
- if ((hi_off - lo_off) > blksize)
- rpos = RANDOM(lo_off, (hi_off - blksize));
- else
- rpos = lo_off;
- smraddr = IDN_OFFSET2ADDR(rpos);
-
- cpuid = (int)CPU->cpu_id;
-#ifdef DEBUG
- idx = rw_index[cpuid]++ % RW_HISTORY;
- rw_history[cpuid][idx] = rpos;
-#endif /* DEBUG */
-
- switch (rw) {
- case 0:
- bcopy(smraddr, ibuf, blksize);
- break;
- case 1:
- bcopy(obuf, smraddr, blksize);
- break;
- case 2:
- if (n & 1)
- bcopy(obuf, smraddr, blksize);
- else
- bcopy(smraddr, ibuf, blksize);
- break;
- default:
- break;
- }
- if (!(n % 1000)) {
- int rv;
-
- mutex_enter(&slock);
- rv = cv_reltimedwait_sig(&scv, &slock, hz,
- TR_CLOCK_TICK);
- mutex_exit(&slock);
- if (rv == 0)
- break;
- }
- }
-
- cv_destroy(&scv);
- mutex_destroy(&slock);
-
- if (ibuf)
- kmem_free(ibuf, blksize);
- if (obuf)
- kmem_free(obuf, blksize);
-
- return (0);
-}
-
-void
-inum2str(uint_t inum, char str[])
-{
- uint_t acknack;
-
- str[0] = '\0';
-
- acknack = (inum & IDNP_ACKNACK_MASK);
- inum &= ~IDNP_ACKNACK_MASK;
-
- if (!inum && !acknack) {
- (void) strcpy(str, idnm_str[0]);
- return;
- }
-
- if (inum == 0) {
- (void) strcpy(str, (acknack & IDNP_ACK) ? "ack" : "nack");
- } else {
- if (inum < IDN_NUM_MSGTYPES)
- (void) strcpy(str, idnm_str[inum]);
- else
- (void) sprintf(str, "0x%x?", inum);
- if (acknack) {
- if (acknack & IDNP_ACK)
- (void) strcat(str, "+ack");
- else
- (void) strcat(str, "+nack");
- }
- }
-}
-
-boardset_t
-cpuset2boardset(cpuset_t portset)
-{
- register int c;
- register boardset_t bset;
-
- bset = 0;
- for (c = 0; c < NCPU; )
- if (CPU_IN_SET(portset, c)) {
- BOARDSET_ADD(bset, CPUID_TO_BOARDID(c));
- c = (c + 4) & ~3;
- } else {
- c++;
- }
-
- return (bset);
-}
-
-void
-cpuset2str(cpuset_t cset, char buffer[])
-{
- register int c, n;
-
- buffer[0] = '\0';
- for (c = n = 0; c < NCPU; c++) {
- if (!CPU_IN_SET(cset, c))
- continue;
-#ifdef DEBUG
- if (strlen(buffer) >= _DSTRLEN) {
- PR_PROTO("************* WARNING WARNING WARNING\n");
- PR_PROTO("cpuset2str(cpu = %d) buffer "
- "OVERFLOW <<<<<<\n", c);
- PR_PROTO("*******************************\n");
- (void) sprintf(&buffer[_DSTRLEN-6], "*OVER");
- return;
- }
-#endif /* DEBUG */
- if (n == 0)
- (void) sprintf(buffer, "%d", c);
- else
- (void) sprintf(buffer, "%s, %d", buffer, c);
- n++;
- }
-}
-
-void
-domainset2str(domainset_t dset, char buffer[])
-{
- /*
- * Since domainset_t and boardset_t are the
- * same (max = MAX_DOMAINS = MAX_BOARDS) we
- * can just overload boardset2str().
- */
- mask2str((uint_t)dset, buffer, MAX_DOMAINS);
-}
-
-void
-boardset2str(boardset_t bset, char buffer[])
-{
- mask2str((uint_t)bset, buffer, MAX_BOARDS);
-}
-
-void
-mask2str(uint_t mask, char buffer[], int maxnum)
-{
- int n, i;
-
- buffer[0] = '\0';
- for (i = n = 0; i < maxnum; i++) {
- if ((mask & (1 << i)) == 0)
- continue;
- if (n == 0)
- (void) sprintf(buffer, "%d", i);
- else
- (void) sprintf(buffer, "%s, %d", buffer, i);
- n++;
- }
-}
-
-int
-idnxdc(int domid, idn_msgtype_t *mtp,
- uint_t arg1, uint_t arg2,
- uint_t arg3, uint_t arg4)
-{
- int rv, cpuid, tcpuid;
- uint_t cookie;
- uint64_t pdata;
- uint64_t dmv_word0, dmv_word1, dmv_word2;
- idn_domain_t *dp = &idn_domain[domid];
- extern kmutex_t xc_sys_mutex;
- extern int xc_spl_enter[];
- procname_t proc = "idnxdc";
-
-
- if (idn_snoop) {
- int bd;
- STRING(str);
- STRING(mstr);
- STRING(astr);
-
- INUM2STR(mtp->mt_mtype, mstr);
- if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == 0) {
- INUM2STR(arg1, astr);
- (void) sprintf(str, "%s/%s", mstr, astr);
- } else {
- (void) strcpy(str, mstr);
- }
- if (dp->dcpu == IDN_NIL_DCPU)
- bd = -1;
- else
- bd = CPUID_TO_BOARDID(dp->dcpu);
- SNOOP_IDN(0, str, bd, arg1, arg2, arg3, arg4);
- }
-
- /*
- * For NEGO messages we send the remote domain the cookie we
- * expect it to use in subsequent messages that it sends
- * to us (dcookie_recv).
- * For other messages, we must use the cookie that the
- * remote domain assigned to us for sending (dcookie_send).
- */
- if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == IDNP_NEGO)
- cookie = IDN_MAKE_COOKIE(dp->dcookie_recv, mtp->mt_cookie);
- else
- cookie = IDN_MAKE_COOKIE(dp->dcookie_send, mtp->mt_cookie);
-
- pdata = IDN_MAKE_PDATA(mtp->mt_mtype, mtp->mt_atype, cookie);
-
- dmv_word0 = DMV_MAKE_DMV(idn.intr.dmv_inum, pdata);
- dmv_word1 = ((uint64_t)arg1 << 32) | (uint64_t)arg2;
- dmv_word2 = ((uint64_t)arg3 << 32) | (uint64_t)arg4;
-
- ASSERT((dp->dcpu != IDN_NIL_DCPU) ||
- (dp->dcpu_last != IDN_NIL_DCPU));
-
- tcpuid = (dp->dcpu == IDN_NIL_DCPU) ?
- dp->dcpu_last : dp->dcpu;
-
- if (tcpuid == IDN_NIL_DCPU) {
- PR_PROTO("%s:%d: cpu/cpu_last == NIL_DCPU\n",
- proc, domid);
- return (-1);
- }
-
- mutex_enter(&xc_sys_mutex);
- cpuid = (int)CPU->cpu_id;
- xc_spl_enter[cpuid] = 1;
-
- idnxf_init_mondo(dmv_word0, dmv_word1, dmv_word2);
-
- rv = idnxf_send_mondo(STARFIRE_UPAID2HWMID(tcpuid));
-
- xc_spl_enter[cpuid] = 0;
- mutex_exit(&xc_sys_mutex);
-
- return (rv);
-}
-
-void
-idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp,
- uint_t arg1, uint_t arg2,
- uint_t arg3, uint_t arg4)
-{
- int d;
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- idn_domain_t *dp;
-
- if (!DOMAIN_IN_SET(domset, d))
- continue;
-
- dp = &idn_domain[d];
- if (dp->dcpu == IDN_NIL_DCPU)
- continue;
-
- (void) IDNXDC(d, mtp, arg1, arg2, arg3, arg4);
- }
-}
-
-#define PROM_SMRSIZE 0x1
-#define PROM_SMRADDR 0x2
-#define PROM_SMRPROPS (PROM_SMRSIZE | PROM_SMRADDR)
-/*
- * Locate the idn-smr-size property to determine the size of the SMR
- * region for the SSI. Value inherently enables/disables SSI capability.
- */
-static int
-idn_prom_getsmr(uint_t *smrsz, uint64_t *paddrp, uint64_t *sizep)
-{
- pnode_t nodeid;
- int found = 0;
- int len;
- uint_t smrsize = 0;
- uint64_t obpaddr, obpsize;
- struct smraddr {
- uint32_t hi_addr;
- uint32_t lo_addr;
- uint32_t hi_size;
- uint32_t lo_size;
- } smraddr;
- procname_t proc = "idn_prom_getsmr";
-
- bzero(&smraddr, sizeof (smraddr));
- /*
- * idn-smr-size is a property of the "memory" node and
- * is defined in megabytes.
- */
- nodeid = prom_finddevice("/memory");
-
- if (nodeid != OBP_NONODE) {
- len = prom_getproplen(nodeid, IDN_PROP_SMRSIZE);
- if (len == sizeof (smrsize)) {
- (void) prom_getprop(nodeid, IDN_PROP_SMRSIZE,
- (caddr_t)&smrsize);
- found |= PROM_SMRSIZE;
- }
- len = prom_getproplen(nodeid, IDN_PROP_SMRADDR);
- if (len == sizeof (smraddr)) {
- (void) prom_getprop(nodeid, IDN_PROP_SMRADDR,
- (caddr_t)&smraddr);
- found |= PROM_SMRADDR;
- }
- }
-
- if (found != PROM_SMRPROPS) {
- if ((found & PROM_SMRSIZE) == 0)
- cmn_err(CE_WARN,
- "IDN: 136: \"%s\" property not found, "
- "disabling IDN",
- IDN_PROP_SMRSIZE);
- if (smrsize && ((found & PROM_SMRADDR) == 0))
- cmn_err(CE_WARN,
- "IDN: 136: \"%s\" property not found, "
- "disabling IDN",
- IDN_PROP_SMRADDR);
- return (-1);
- }
-
- if (smrsize == 0) {
- PR_SMR("%s: IDN DISABLED (idn_smr_size = 0)\n", proc);
- cmn_err(CE_NOTE, "!IDN: 137: SMR size is 0, disabling IDN");
-
- } else if (smrsize > IDN_SMR_MAXSIZE) {
- PR_SMR("%s: IDN DISABLED (idn_smr_size too big %d > %d MB)\n",
- proc, smrsize, IDN_SMR_MAXSIZE);
- cmn_err(CE_WARN,
- "!IDN: 138: SMR size (%dMB) is too big (max = %dMB), "
- "disabling IDN",
- smrsize, IDN_SMR_MAXSIZE);
- smrsize = 0;
- } else {
- *smrsz = smrsize;
- found &= ~PROM_SMRSIZE;
- }
-
- obpaddr = ((uint64_t)smraddr.hi_addr << 32) |
- (uint64_t)smraddr.lo_addr;
- obpsize = ((uint64_t)smraddr.hi_size << 32) |
- (uint64_t)smraddr.lo_size;
-
- if (obpsize == 0) {
- if (smrsize > 0) {
- cmn_err(CE_WARN, "!IDN: 139: OBP region for "
- "SMR is 0 length");
- }
- } else if (obpsize < (uint64_t)MB2B(smrsize)) {
- cmn_err(CE_WARN,
- "!IDN: 140: OBP region (%ld B) smaller "
- "than requested size (%ld B)",
- obpsize, MB2B(smrsize));
- } else if ((obpaddr & ((uint64_t)IDN_SMR_ALIGN - 1)) != 0) {
- cmn_err(CE_WARN,
- "!IDN: 141: OBP region (0x%lx) not on (0x%x) "
- "boundary", obpaddr, IDN_SMR_ALIGN);
- } else {
- *sizep = obpsize;
- *paddrp = obpaddr;
- found &= ~PROM_SMRADDR;
- }
-
- return (found ? -1 : 0);
-}
-
-void
-idn_init_autolink()
-{
- idnsb_event_t *sbp;
- procname_t proc = "idn_init_autolink";
-
- mutex_enter(&idn.idnsb_mutex);
- if ((sbp = idn.idnsb_eventp) == NULL) {
- PR_PROTO("%s: IDN private sigb (event) area is NULL\n", proc);
- mutex_exit(&idn.idnsb_mutex);
- return;
- }
-
- PR_PROTO("%s: marking domain IDN ready.\n", proc);
-
- bzero(sbp, sizeof (*sbp));
-
- sbp->idn_version = (uchar_t)idn.version;
- SSIEVENT_SET(sbp, SSIEVENT_BOOT, 0);
- (void) strncpy(sbp->idn_cookie_str, SSIEVENT_COOKIE,
- SSIEVENT_COOKIE_LEN);
- mutex_exit(&idn.idnsb_mutex);
-}
-
-void
-idn_deinit_autolink()
-{
- idnsb_event_t *sbp;
- procname_t proc = "idn_deinit_autolink";
-
- mutex_enter(&idn.idnsb_mutex);
- if ((sbp = idn.idnsb_eventp) == NULL) {
- PR_PROTO("%s: IDN private sigb (event) area is NULL\n", proc);
- mutex_exit(&idn.idnsb_mutex);
- return;
- }
-
- PR_PROTO("%s: marking domain IDN unavailable.\n", proc);
-
- sbp->idn_version = (uchar_t)idn.version;
- SSIEVENT_CLEAR(sbp, SSIEVENT_BOOT, 0);
- (void) strncpy(sbp->idn_cookie_str, SSIEVENT_COOKIE,
- SSIEVENT_COOKIE_LEN);
- mutex_exit(&idn.idnsb_mutex);
-}
-
-void
-_make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower)
-{
- int c;
-
- CPUSET_ZERO(*csetp);
-
- for (c = 0; c < 32; c++) {
- if (lower & (1 << c)) {
- CPUSET_ADD(*csetp, c);
- }
- if (upper & (1 << (c + 32))) {
- CPUSET_ADD(*csetp, c + 32);
- }
- }
-}
-
-uint_t
-_lower32cpumask(cpuset_t cset)
-{
- int c;
- uint_t set = 0;
-
- for (c = 0; c < 32; c++)
- if (CPU_IN_SET(cset, c))
- set |= 1 << c;
-
- return (set);
-}
-
-uint_t
-_upper32cpumask(cpuset_t cset)
-{
- int c;
- uint_t set = 0;
-
- for (c = 32; c < NCPU; c++)
- if (CPU_IN_SET(cset, c))
- set |= 1 << (c - 32);
-
- return (set);
-}
-
-#ifdef DEBUG
-int
-debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp,
- uint_t a1, uint_t a2, uint_t a3, uint_t a4)
-{
- idn_domain_t *dp = &idn_domain[domid];
- int rv, cpuid, bd;
- static int xx = 0;
- STRING(str);
- STRING(mstr);
- STRING(astr);
-
- xx++;
- INUM2STR(mtp->mt_mtype, mstr);
- if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == 0) {
- INUM2STR(a1, astr);
- (void) sprintf(str, "%s/%s", mstr, astr);
- } else {
- (void) strcpy(str, mstr);
- }
-
- if ((cpuid = dp->dcpu) == IDN_NIL_DCPU)
- bd = -1;
- else
- bd = CPUID_TO_BOARDID(cpuid);
-
- SNOOP_IDN(0, str, bd, a1, a2, a3, a4);
-
- PR_XDC("%s:%d:%d SENT: scpu = %d, msg = 0x%x(%s)\n",
- f, domid, xx, cpuid, mtp->mt_mtype, str);
- PR_XDC("%s:%d:%d S-DATA: a1 = 0x%x, a2 = 0x%x\n",
- f, domid, xx, a1, a2);
- PR_XDC("%s:%d:%d S-DATA: a3 = 0x%x, a4 = 0x%x\n",
- f, domid, xx, a3, a4);
-
- rv = idnxdc(domid, mtp, a1, a2, a3, a4);
- if (rv != 0) {
- PR_XDC("%s:%d:%d: WARNING: idnxdc(cpu %d) FAILED\n",
- f, domid, xx, cpuid);
- }
-
- return (rv);
-}
-
-caddr_t
-_idn_getstruct(char *structname, int size)
-{
- caddr_t ptr;
- procname_t proc = "GETSTRUCT";
-
- ptr = kmem_zalloc(size, KM_SLEEP);
-
- PR_ALLOC("%s: ptr 0x%p, struct(%s), size = %d\n",
- proc, (void *)ptr, structname, size);
-
- return (ptr);
-}
-
-void
-_idn_freestruct(caddr_t ptr, char *structname, int size)
-{
- procname_t proc = "FREESTRUCT";
-
- PR_ALLOC("%s: ptr 0x%p, struct(%s), size = %d\n",
- proc, (void *)ptr, structname, size);
-
- ASSERT(ptr != NULL);
- kmem_free(ptr, size);
-}
-#endif /* DEBUG */
diff --git a/usr/src/uts/sun4u/starfire/io/idn.conf b/usr/src/uts/sun4u/starfire/io/idn.conf
deleted file mode 100644
index 7bd23982b1..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn.conf
+++ /dev/null
@@ -1,35 +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) 1998 by Sun Microsystems, Inc.
-# All rights reserved.
-#
-#ident "%Z%%M% %I% %E% SMI"
-
-name="idn" parent="pseudo" instance=0;
-name="idn" parent="pseudo" instance=1;
-name="idn" parent="pseudo" instance=2;
-name="idn" parent="pseudo" instance=3;
-name="idn" parent="pseudo" instance=4;
-name="idn" parent="pseudo" instance=5;
-name="idn" parent="pseudo" instance=6;
-name="idn" parent="pseudo" instance=7;
diff --git a/usr/src/uts/sun4u/starfire/io/idn_dlpi.c b/usr/src/uts/sun4u/starfire/io/idn_dlpi.c
deleted file mode 100644
index 693499c041..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn_dlpi.c
+++ /dev/null
@@ -1,2295 +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.
- */
-
-/*
- * IDN DLPI support (based on QE implementation).
- */
-#include <sys/types.h>
-#include <sys/debug.h>
-#include <sys/stropts.h>
-#include <sys/stream.h>
-#include <sys/systm.h>
-#include <sys/cmn_err.h>
-#include <sys/errno.h>
-#ifdef xxx_trace
-#include <sys/vtrace.h>
-#endif /* xxx_trace */
-#include <sys/kmem.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/strsun.h>
-#include <sys/stat.h>
-#include <sys/kstat.h>
-#include <sys/dlpi.h>
-#include <sys/time.h>
-#include <sys/cpuvar.h>
-
-#include <sys/idn.h>
-
-#ifdef IPV6
-#define IS_ETHERTYPE_IPV4(x) ((x) == ETHERTYPE_IP)
-#define IS_ETHERTYPE_IPV6(x) ((x) == ETHERTYPE_IPV6)
-#define IS_ETHERTYPE_IP(x) (IS_ETHERTYPE_IPV4(x) || IS_ETHERTYPE_IPV6(x))
-#else
-#define IS_ETHERTYPE_IPV4(x) ((x) == ETHERTYPE_IP)
-#define IS_ETHERTYPE_IPV6(x) (0)
-#define IS_ETHERTYPE_IP IS_ETHERTYPE_IPV4
-#endif /* IPV6 */
-
-#ifdef IDN_TRACE
-/*
- * This stuff should go into <sys/vtrace.h>
- */
-#define TR_FAC_IDN 100
-/*
- * TR_FAC_IDN tags
- */
-#define TR_IDN_OPEN 0
-#define TR_IDN_CLOSE 1
-#define TR_IDN_WPUT_START 2
-#define TR_IDN_WPUT_END 3
-#define TR_IDN_WSRV_START 4
-#define TR_IDN_WSRV_END 5
-#define TR_IDN_START_START 6
-#define TR_IDN_START_END 7
-#define TR_IDN_INTR_START 8
-#define TR_IDN_INTR_END 9
-#define TR_IDN_READ_START 10
-#define TR_IDN_READ_END 11
-#define TR_IDN_SENDUP_START 12
-#define TR_IDN_SENDUP_END 13
-#define TR_IDN_ADDUDIND_START 14
-#define TR_IDN_ADDUDIND_END 15
-#define TR_IDN_GETBUF_START 16
-#define TR_IDN_GETBUF_END 17
-#define TR_IDN_FREEBUF_START 18
-#define TR_IDN_FREEBUF_END 19
-#define TR_IDN_PROTO_START 20
-#define TR_IDN_PROTO_END 21
-#define TR_IDN_INIT_START 22
-#define TR_IDN_INIT_END 23
-#define TR_IDN_PROTO_IN 24
-#define TR_IDN_PROTO_OUT 25
-
-#define IDNTRACE(fac, tag) (printf("idn.TRACE: "))
-
-#define TRACE_0(fac, tag, name) \
- IDNTRACE((fac), (tag)); \
- printf(name); printf("\n");
-
-#define TRACE_1(fac, tag, name, d1) \
- IDNTRACE((fac), (tag)); \
- printf(name, (d1)); printf("\n");
-
-#define TRACE_2(fac, tag, name, d1, d2) \
- IDNTRACE((fac), (tag)); \
- printf(name, (d1), (d2)); printf("\n");
-
-#define TRACE_3(fac, tag, name, d1, d2, d3) \
- IDNTRACE((fac), (tag)); \
- printf(name, (d1), (d2), (d3)); printf("\n");
-
-#define TRACE_4(fac, tag, name, d1, d2, d3, d4) \
- IDNTRACE((fac), (tag)); \
- printf(name, (d1), (d2), (d3), (d4)); printf("\n");
-
-#define TRACE_5(fac, tag, name, d1, d2, d3, d4, d5) \
- IDNTRACE((fac), (tag)); \
- printf(name, (d1), (d2), (d3), (d4), (d5)); printf("\n");
-
-#else /* IDN_TRACE */
-
-#define TRACE_0(fac, tag, name) {}
-#define TRACE_1(fac, tag, name, d1) {}
-#define TRACE_2(fac, tag, name, d1, d2) {}
-#define TRACE_3(fac, tag, name, d1, d2, d3) {}
-#define TRACE_4(fac, tag, name, d1, d2, d3, d4) {}
-#define TRACE_5(fac, tag, name, d1, d2, d3, d4, d5) {}
-
-#endif /* IDN_TRACE */
-
-#ifdef DEBUG
-#define DLERRORACK(qq, mm, cc, ee, xx) \
-{ \
- PR_DLPI("dlpi: ERRORACK: 0x%x(%s), err = 0x%x(%s)\n", \
- (uint_t)(cc), dlprim2str(cc), \
- (uint_t)(ee), dlerr2str((int)(ee))); \
- dlerrorack((qq), (mm), (cc), (ee), (xx)); \
-}
-#define DLOKACK(qq, mm, cc) \
-{ \
- PR_DLPI("dlpi: OKACK: 0x%x(%s)\n", (cc), dlprim2str(cc)); \
- dlokack((qq), (mm), (cc)); \
-}
-#define DLBINDACK(qq, mm, ss, aa, ll, xx, yy) \
-{ \
- PR_DLPI("dlpi: BINDACK: eth=%x:%x:%x:%x:%x:%x, sap=0x%x, l=%d\n", \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[0], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[1], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[2], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[3], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[4], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[5], \
- (uint_t)(ss), (int)(ll)); \
- dlbindack((qq), (mm), (ss), (aa), (ll), (xx), (yy)); \
-}
-#define DLPHYSADDRACK(qq, mm, aa, ll) \
-{ \
- PR_DLPI("dlpi: PHYSACK: eth=%x:%x:%x:%x:%x:%x, l=%d\n", \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[0], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[1], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[2], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[3], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[4], \
- ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[5], \
- (ll)); \
- dlphysaddrack((qq), (mm), (aa), (ll)); \
-}
-
-static char *dlerrstr[] = {
- "DL_BADSAP",
- "DL_BADADDR",
- "DL_ACCESS",
- "DL_OUTSTATE",
- "DL_SYSERR",
- "DL_BADCORR",
- "DL_BADDATA",
- "DL_UNSUPPORTED",
- "DL_BADPPA",
- "DL_BADPRIM",
- "DL_BADQOSPARAM",
- "DL_BADQOSTYPE",
- "DL_BADTOKEN",
- "DL_BOUND",
- "DL_INITFAILED",
- "DL_NOADDR",
- "DL_NOTINIT",
- "DL_UNDELIVERABLE",
- "DL_NOTSUPPORTED",
- "DL_TOOMANY",
- "DL_NOTENAB",
- "DL_BUSY",
- "DL_NOAUTO",
- "DL_NOXIDAUTO",
- "DL_NOTESTAUTO",
- "DL_XIDAUTO",
- "DL_TESTAUTO",
- "DL_PENDING"
-};
-static int dlerrnum = (sizeof (dlerrstr) / sizeof (char *));
-
-static char *
-dlerr2str(int err)
-{
- if ((err < 0) || (err >= dlerrnum))
- return ("unknown");
- else
- return (dlerrstr[err]);
-}
-
-static char *
-dlprim2str(int prim)
-{
- char *pstr;
-
- switch (prim) {
- case DL_UNITDATA_REQ: pstr = "UNITDATA_REQ"; break;
- case DL_ATTACH_REQ: pstr = "ATTACH_REQ"; break;
- case DL_DETACH_REQ: pstr = "DETACH_REQ"; break;
- case DL_BIND_REQ: pstr = "BIND_REQ"; break;
- case DL_UNBIND_REQ: pstr = "UNBIND_REQ"; break;
- case DL_INFO_REQ: pstr = "INFO_REQ"; break;
- case DL_PROMISCON_REQ: pstr = "PROMISCON_REQ"; break;
- case DL_PROMISCOFF_REQ: pstr = "PROMISCOFF_REQ"; break;
- case DL_ENABMULTI_REQ: pstr = "ENABMULTI_REQ"; break;
- case DL_DISABMULTI_REQ: pstr = "DISABMULTI_REQ"; break;
- case DL_PHYS_ADDR_REQ: pstr = "PHYS_ADDR_REQ"; break;
- case DL_SET_PHYS_ADDR_REQ:
- pstr = "SET_PHYS_ADDR_REQ"; break;
- default: pstr = "unsupported"; break;
- }
- return (pstr);
-}
-#else /* DEBUG */
-#define DLERRORACK(qq, mm, cc, ee, xx) \
- (dlerrorack((qq), (mm), (cc), (ee), (xx)))
-#define DLOKACK(qq, mm, cc) \
- (dlokack((qq), (mm), (cc)))
-#define DLBINDACK(qq, mm, ss, aa, ll, xx, yy) \
- (dlbindack((qq), (mm), (ss), (aa), (ll), (xx), (yy)))
-#define DLPHYSADDRACK(qq, mm, aa, ll) \
- (dlphysaddrack((qq), (mm), (aa), (ll)))
-#endif /* DEBUG */
-
-#define IDNDL_ADDR_IS_MULTICAST(ap) (((ap)->ether_addr_octet[0] & 01) == 1)
-/*
- * MIB II broadcast/multicast packets
- */
-#define IS_BROADCAST(ehp) \
- (ether_cmp(&(ehp)->ether_dhost, &etherbroadcastaddr) == 0)
-#define IS_MULTICAST(ehp) \
- IDNDL_ADDR_IS_MULTICAST(&(ehp)->ether_dhost)
-#define BUMP_InNUcast(sip, ehp) \
- if (IS_BROADCAST(ehp)) { \
- (sip)->si_kstat.si_brdcstrcv++; \
- } else if (IS_MULTICAST(ehp)) { \
- (sip)->si_kstat.si_multircv++; \
- }
-#define BUMP_OutNUcast(sip, ehp) \
- if (IS_BROADCAST(ehp)) { \
- (sip)->si_kstat.si_brdcstxmt++; \
- } else if (IS_MULTICAST(ehp)) { \
- (sip)->si_kstat.si_multixmt++; \
- }
-
-/*
- * Function prototypes.
- */
-static int idndl_ioc_hdr_info(queue_t *, mblk_t *, int *);
-static void idndl_areq(queue_t *, mblk_t *);
-static void idndl_dreq(queue_t *, mblk_t *);
-static void idndl_breq(queue_t *, mblk_t *);
-static void idndl_ubreq(queue_t *, mblk_t *);
-static void idndl_ireq(queue_t *, mblk_t *);
-static void idndl_ponreq(queue_t *, mblk_t *);
-static void idndl_poffreq(queue_t *, mblk_t *);
-static void idndl_emreq(queue_t *, mblk_t *);
-static void idndl_dmreq(queue_t *, mblk_t *);
-static void idndl_pareq(queue_t *, mblk_t *);
-#ifdef notdef
-static void idndl_spareq(queue_t *, mblk_t *);
-#endif /* notdef */
-static void idndl_udreq(queue_t *, mblk_t *);
-static void serror(dev_info_t *dip, int idnerr, char *fmt, ...);
-static mblk_t *idndl_addudind(struct idn *, mblk_t *, struct ether_addr *,
- struct ether_addr *, int, ulong_t);
-static void idndl_setipq(struct idn *);
-static int idndl_mcmatch(struct idnstr *, struct ether_addr *);
-static int idndl_stat_kstat_update(kstat_t *ksp, int rw);
-
-static int _idndl_ether2domain(struct ether_addr *eap);
-static struct idn *_idndl_ether2sip(struct ether_addr *eap);
-
-
-#define IDNSAPMATCH(sap, type, flags) ((sap == type)? 1 : \
- ((flags & IDNSALLSAP)? 1 : \
- ((sap <= ETHERMTU) && sap && (type <= ETHERMTU))? 1 : 0))
-
-/*
- * Our DL_INFO_ACK template.
- */
-static dl_info_ack_t idninfoack = {
- DL_INFO_ACK, /* dl_primitive */
- 0, /* dl_max_sdu (see idndl_dlpi_init()) */
- 0, /* dl_min_sdu */
- IDNADDRL, /* dl_addr_length */
- DL_ETHER, /* DL_OTHER, */ /* dl_mac_type */
- 0, /* dl_reserved */
- 0, /* dl_current_state */
- -2, /* dl_sap_length */
- DL_CLDLS, /* DL_CODLS? */ /* dl_service_mode */
- 0, /* dl_qos_length */
- 0, /* dl_qos_offset */
- 0, /* dl_range_length */
- 0, /* dl_range_offset */
- DL_STYLE2, /* dl_provider_style */
- sizeof (dl_info_ack_t), /* dl_addr_offset */
- DL_VERSION_2, /* dl_version */
- ETHERADDRL, /* dl_brdcst_addr_length */
- sizeof (dl_info_ack_t) + IDNADDRL, /* dl_brdcst_addr_offset */
- 0 /* dl_growth */
-};
-
-/*
- * Ethernet broadcast address definition.
- */
-static struct ether_addr etherbroadcastaddr = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-/*
- * --------------------------------------------------
- */
-void
-idndl_localetheraddr(struct idn *sip, struct ether_addr *eap)
-{
- int rv;
- int instance;
- procname_t proc = "idndl_localetheraddr";
-
- ASSERT(sip && sip->si_dip && eap);
-
- instance = ddi_get_instance(sip->si_dip);
-
- PR_DLPI("%s: getting local etheraddr...\n", proc);
-
- rv = idndl_domain_etheraddr(idn.localid, instance, eap);
- ASSERT(rv == 0);
-}
-
-int
-idndl_domain_etheraddr(int domid, int channel, struct ether_addr *eap)
-{
- uchar_t netid;
- procname_t proc = "idndl_domain_etheraddr";
-
- if (idn_domain[domid].dcpu == IDN_NIL_DCPU)
- return (-1);
-
- netid = (uchar_t)idn_domain[domid].dnetid;
-
- PR_DLPI("%s: dnetid = 0x%x, channel = 0x%x\n",
- proc, (uint_t)netid, channel);
-
-#ifdef notdef
- localetheraddr(NULL, eap);
-
- PR_DLPI("%s: localetheraddr = %x:%x:%x:%x:%x:%x\n",
- proc, eap->ether_addr_octet[0], eap->ether_addr_octet[1],
- eap->ether_addr_octet[2], eap->ether_addr_octet[3],
- eap->ether_addr_octet[4], eap->ether_addr_octet[5]):
-#endif /* notdef */
-
- eap->ether_addr_octet[IDNETHER_ZERO] = 0;
- eap->ether_addr_octet[IDNETHER_COOKIE1] = IDNETHER_COOKIE1_VAL;
- eap->ether_addr_octet[IDNETHER_COOKIE2] = IDNETHER_COOKIE2_VAL;
- eap->ether_addr_octet[IDNETHER_NETID] = netid;
- eap->ether_addr_octet[IDNETHER_CHANNEL] = (uchar_t)channel;
- eap->ether_addr_octet[IDNETHER_RESERVED] = IDNETHER_RESERVED_VAL;
-
- PR_DLPI("%s: domain %d: etheraddr = %x:%x:%x:%x:%x:%x\n",
- proc, domid,
- eap->ether_addr_octet[0], eap->ether_addr_octet[1],
- eap->ether_addr_octet[2], eap->ether_addr_octet[3],
- eap->ether_addr_octet[4], eap->ether_addr_octet[5]);
-
- return (0);
-}
-
-#ifdef DEBUG
-/*
- */
-static int
-_idndl_ether2domain(struct ether_addr *eap)
-{
- uchar_t *eaop;
-
- eaop = eap->ether_addr_octet;
-
- ASSERT(IDNDL_ADDR_IS_MULTICAST(eap) ||
- ((eaop[IDNETHER_COOKIE1] == IDNETHER_COOKIE1_VAL) &&
- (eaop[IDNETHER_COOKIE2] == IDNETHER_COOKIE2_VAL)) ||
- ((eaop[IDNETHER_COOKIE1] == 0xff) &&
- (eaop[IDNETHER_COOKIE2] == 0xff)));
- /*
- * Note that (IDN_NIL_DOMID) will be returned if ether address is
- * a broadcast 0xff.
- */
- return (IDN_NETID2DOMID(eaop[IDNETHER_NETID]));
-}
-
-/*
- */
-static struct idn *
-_idndl_ether2sip(struct ether_addr *eap)
-{
- int instance;
- struct idn *sip;
- uchar_t *eaop;
- procname_t proc = "_idndl_ether2sip";
-
- eaop = eap->ether_addr_octet;
-
- if (!IDNDL_ADDR_IS_MULTICAST(eap) &&
- (((eaop[IDNETHER_COOKIE1] != IDNETHER_COOKIE1_VAL) ||
- (eaop[IDNETHER_COOKIE2] != IDNETHER_COOKIE2_VAL)) &&
- ((eaop[IDNETHER_COOKIE1] != 0xff) ||
- (eaop[IDNETHER_COOKIE2] != 0xff)))) {
-
- cmn_err(CE_WARN,
- "IDN: 400: corrupted MAC header "
- "(exp %x or 0xffff, act 0x%x)",
- (IDNETHER_COOKIE1_VAL << 8) |
- IDNETHER_COOKIE2_VAL,
- (eaop[IDNETHER_COOKIE1] << 8) |
- eaop[IDNETHER_COOKIE2]);
-
- return (NULL);
- }
-
- if (IDNDL_ADDR_IS_MULTICAST(eap)) {
- PR_DLPI("%s: MULTICAST ADDR *** ERROR ***\n", proc);
- sip = NULL;
- } else if (eaop[IDNETHER_CHANNEL] == 0xff) {
- /*
- * Received a broadcast. Need to manually
- * find anybody the first running sip and use it.
- * XXX - kind of kludgy - single threads broadcasts.
- */
- PR_DLPI("%s: BROADCAST CHANNEL *** ERROR ***\n", proc);
- sip = NULL;
- } else {
- instance = (int)eaop[IDNETHER_CHANNEL];
-
- sip = IDN_INST2SIP(instance);
- }
-
- return (sip);
-}
-#endif /* DEBUG */
-
-void
-idndl_dlpi_init()
-{
- procname_t proc = "idndl_dlpi_init";
-
- PR_DLPI("%s: setting dl_max_sdu to %ld (0x%lx) bytes\n",
- proc, IDN_MTU, IDN_MTU);
- /*
- * This field is dynamic because the user may
- * want to dynamically set it _before_ an IDNnet
- * has been established via ndd(1M).
- */
- idninfoack.dl_max_sdu = IDN_MTU;
-}
-
-static int
-idndl_stat_kstat_update(kstat_t *ksp, int rw)
-{
- struct idn *sip;
- struct idn_kstat_named *skp;
-
- sip = (struct idn *)ksp->ks_private;
- skp = (struct idn_kstat_named *)ksp->ks_data;
-
- if (rw == KSTAT_WRITE) {
-#if 0
- bzero(&sg_kstat.gk_kstat, sizeof (sg_kstat.gk_kstat));
-#endif /* 0 */
- bzero(&sip->si_kstat, sizeof (sip->si_kstat));
-
- sip->si_kstat.si_ipackets = skp->sk_ipackets.value.ul;
- sip->si_kstat.si_ierrors = skp->sk_ierrors.value.ul;
- sip->si_kstat.si_opackets = skp->sk_opackets.value.ul;
- sip->si_kstat.si_oerrors = skp->sk_oerrors.value.ul;
- sip->si_kstat.si_txcoll = skp->sk_txcoll.value.ul;
- sip->si_kstat.si_rxcoll = skp->sk_rxcoll.value.ul;
- sip->si_kstat.si_crc = skp->sk_crc.value.ul;
- sip->si_kstat.si_buff = skp->sk_buff.value.ul;
- sip->si_kstat.si_nolink = skp->sk_nolink.value.ul;
- sip->si_kstat.si_linkdown = skp->sk_linkdown.value.ul;
- sip->si_kstat.si_inits = skp->sk_inits.value.ul;
- sip->si_kstat.si_nocanput = skp->sk_nocanput.value.ul;
- sip->si_kstat.si_allocbfail = skp->sk_allocbfail.value.ul;
- sip->si_kstat.si_notbufs = skp->sk_notbufs.value.ul;
- sip->si_kstat.si_reclaim = skp->sk_reclaim.value.ul;
- sip->si_kstat.si_smraddr = skp->sk_smraddr.value.ul;
- sip->si_kstat.si_txmax = skp->sk_txmax.value.ul;
- sip->si_kstat.si_txfull = skp->sk_txfull.value.ul;
- sip->si_kstat.si_xdcall = skp->sk_xdcall.value.ul;
- sip->si_kstat.si_sigsvr = skp->sk_sigsvr.value.ul;
- sip->si_kstat.si_mboxcrc = skp->sk_mboxcrc.value.ul;
- /*
- * MIB II kstat variables
- */
- sip->si_kstat.si_rcvbytes = skp->sk_rcvbytes.value.ul;
- sip->si_kstat.si_xmtbytes = skp->sk_xmtbytes.value.ul;
- sip->si_kstat.si_multircv = skp->sk_multircv.value.ul;
- sip->si_kstat.si_multixmt = skp->sk_multixmt.value.ul;
- sip->si_kstat.si_brdcstrcv = skp->sk_brdcstrcv.value.ul;
- sip->si_kstat.si_brdcstxmt = skp->sk_brdcstxmt.value.ul;
- sip->si_kstat.si_norcvbuf = skp->sk_norcvbuf.value.ul;
- sip->si_kstat.si_noxmtbuf = skp->sk_noxmtbuf.value.ul;
- /*
- * PSARC 1997/198 : 64bit kstats
- */
- sip->si_kstat.si_ipackets64 = skp->sk_ipackets64.value.ull;
- sip->si_kstat.si_opackets64 = skp->sk_opackets64.value.ull;
- sip->si_kstat.si_rbytes64 = skp->sk_rbytes64.value.ull;
- sip->si_kstat.si_obytes64 = skp->sk_obytes64.value.ull;
- /*
- * PSARC 1997/247 : RFC 1643
- */
- sip->si_kstat.si_fcs_errors = skp->sk_fcs_errors.value.ul;
- sip->si_kstat.si_macxmt_errors =
- skp->sk_macxmt_errors.value.ul;
- sip->si_kstat.si_toolong_errors =
- skp->sk_toolong_errors.value.ul;
- sip->si_kstat.si_macrcv_errors =
- skp->sk_macrcv_errors.value.ul;
-
- return (0);
- }
-
- skp->sk_ipackets.value.ul = sip->si_kstat.si_ipackets;
- skp->sk_ierrors.value.ul = sip->si_kstat.si_ierrors;
- skp->sk_opackets.value.ul = sip->si_kstat.si_opackets;
- skp->sk_oerrors.value.ul = sip->si_kstat.si_oerrors;
- skp->sk_txcoll.value.ul = sip->si_kstat.si_txcoll;
- skp->sk_rxcoll.value.ul = sip->si_kstat.si_rxcoll;
- skp->sk_crc.value.ul = sip->si_kstat.si_crc;
- skp->sk_buff.value.ul = sip->si_kstat.si_buff;
- skp->sk_nolink.value.ul = sip->si_kstat.si_nolink;
- skp->sk_linkdown.value.ul = sip->si_kstat.si_linkdown;
- skp->sk_inits.value.ul = sip->si_kstat.si_inits;
- skp->sk_nocanput.value.ul = sip->si_kstat.si_nocanput;
- skp->sk_allocbfail.value.ul = sip->si_kstat.si_allocbfail;
- skp->sk_notbufs.value.ul = sip->si_kstat.si_notbufs;
- skp->sk_reclaim.value.ul = sip->si_kstat.si_reclaim;
- skp->sk_smraddr.value.ul = sip->si_kstat.si_smraddr;
- skp->sk_txfull.value.ul = sip->si_kstat.si_txfull;
- skp->sk_txmax.value.ul = sip->si_kstat.si_txmax;
- skp->sk_xdcall.value.ul = sip->si_kstat.si_xdcall;
- skp->sk_sigsvr.value.ul = sip->si_kstat.si_sigsvr;
- skp->sk_mboxcrc.value.ul = sip->si_kstat.si_mboxcrc;
- /*
- * MIB II kstat variables
- */
- skp->sk_rcvbytes.value.ul = sip->si_kstat.si_rcvbytes;
- skp->sk_xmtbytes.value.ul = sip->si_kstat.si_xmtbytes;
- skp->sk_multircv.value.ul = sip->si_kstat.si_multircv;
- skp->sk_multixmt.value.ul = sip->si_kstat.si_multixmt;
- skp->sk_brdcstrcv.value.ul = sip->si_kstat.si_brdcstrcv;
- skp->sk_brdcstxmt.value.ul = sip->si_kstat.si_brdcstxmt;
- skp->sk_norcvbuf.value.ul = sip->si_kstat.si_norcvbuf;
- skp->sk_noxmtbuf.value.ul = sip->si_kstat.si_noxmtbuf;
- /*
- * PSARC 1997/198 : 64bit kstats
- */
- skp->sk_ipackets64.value.ull = sip->si_kstat.si_ipackets64;
- skp->sk_opackets64.value.ull = sip->si_kstat.si_opackets64;
- skp->sk_rbytes64.value.ull = sip->si_kstat.si_rbytes64;
- skp->sk_obytes64.value.ull = sip->si_kstat.si_obytes64;
- /*
- * PSARC 1997/247 : RFC 1643
- */
- skp->sk_fcs_errors.value.ul = sip->si_kstat.si_fcs_errors;
- skp->sk_macxmt_errors.value.ul = sip->si_kstat.si_macxmt_errors;
- skp->sk_toolong_errors.value.ul = sip->si_kstat.si_toolong_errors;
- skp->sk_macrcv_errors.value.ul = sip->si_kstat.si_macrcv_errors;
-
- return (0);
-}
-
-void
-idndl_statinit(struct idn *sip)
-{
- struct kstat *ksp;
- struct idn_kstat_named *skp;
-
-#ifdef kstat
- if ((ksp = kstat_create(IDNNAME, ddi_get_instance(sip->si_dip),
- NULL, "net", KSTAT_TYPE_NAMED,
- sizeof (struct idn_kstat_named) / sizeof (kstat_named_t),
- KSTAT_FLAG_PERSISTENT)) == NULL) {
-#else
- if ((ksp = kstat_create(IDNNAME, ddi_get_instance(sip->si_dip),
- NULL, "net", KSTAT_TYPE_NAMED,
- sizeof (struct idn_kstat_named) /
- sizeof (kstat_named_t), 0)) == NULL) {
-#endif /* kstat */
- serror(sip->si_dip, 450, "kstat_create failed");
- return;
- }
-
- sip->si_ksp = ksp;
- skp = (struct idn_kstat_named *)(ksp->ks_data);
- kstat_named_init(&skp->sk_ipackets, "ipackets",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_ierrors, "ierrors",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_opackets, "opackets",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_oerrors, "oerrors",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_txcoll, "collisions",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_rxcoll, "rx_collisions",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_crc, "crc",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_buff, "buff",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_nolink, "nolink",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_linkdown, "linkdown",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_inits, "inits",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_nocanput, "nocanput",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_allocbfail, "allocbfail",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_notbufs, "notbufs",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_reclaim, "reclaim",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_smraddr, "smraddr",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_txmax, "txmax",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_txfull, "txfull",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_xdcall, "xdcall",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_sigsvr, "sigsvr",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_mboxcrc, "mboxcrc",
- KSTAT_DATA_ULONG);
- /*
- * MIB II kstat variables
- */
- kstat_named_init(&skp->sk_rcvbytes, "rbytes",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_xmtbytes, "obytes",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_multircv, "multircv",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_multixmt, "multixmt",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_brdcstrcv, "brdcstrcv",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_brdcstxmt, "brdcstxmt",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_norcvbuf, "norcvbuf",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_noxmtbuf, "noxmtbuf",
- KSTAT_DATA_ULONG);
- /*
- * PSARC 1997/198 : 64bit kstats
- */
- kstat_named_init(&skp->sk_ipackets64, "ipackets64",
- KSTAT_DATA_ULONGLONG);
- kstat_named_init(&skp->sk_opackets64, "opackets64",
- KSTAT_DATA_ULONGLONG);
- kstat_named_init(&skp->sk_rbytes64, "rbytes64",
- KSTAT_DATA_ULONGLONG);
- kstat_named_init(&skp->sk_obytes64, "obytes64",
- KSTAT_DATA_ULONGLONG);
- /*
- * PSARC 1997/247 : RFC 1643
- */
- kstat_named_init(&skp->sk_fcs_errors, "fcs_errors",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_macxmt_errors, "macxmt_errors",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_toolong_errors, "toolong_errors",
- KSTAT_DATA_ULONG);
- kstat_named_init(&skp->sk_macrcv_errors, "macrcv_errors",
- KSTAT_DATA_ULONG);
-
- ksp->ks_update = idndl_stat_kstat_update;
- ksp->ks_private = (void *)sip;
- kstat_install(ksp);
-}
-
-void
-idndl_proto(queue_t *wq, mblk_t *mp)
-{
- union DL_primitives *dlp;
- struct idnstr *stp;
- t_uscalar_t prim;
- procname_t proc = "idndl_proto";
-
- stp = (struct idnstr *)wq->q_ptr;
- if (MBLKL(mp) < sizeof (t_uscalar_t)) {
- /*
- * Gotta at least have enough room to hold
- * the primitive!
- */
- DLERRORACK(wq, mp, -1, DL_BADPRIM, 0);
- return;
- }
- dlp = (union DL_primitives *)mp->b_rptr;
- prim = dlp->dl_primitive;
-
- TRACE_2(TR_FAC_IDN, TR_IDN_PROTO_START,
- "idndl_proto start: wq %p dlprim %X", wq, prim);
-
-#ifdef DEBUG
- PR_DLPI("%s: stp = 0x%p, wq = 0x%p, dlprim = 0x%x(%s)\n",
- proc, (void *)stp, (void *)wq, prim, dlprim2str(prim));
-#endif /* DEBUG */
-
- rw_enter(&stp->ss_rwlock, RW_WRITER);
-
- switch (prim) {
- case DL_UNITDATA_REQ:
- idndl_udreq(wq, mp);
- break;
-
- case DL_ATTACH_REQ:
- idndl_areq(wq, mp);
- break;
-
- case DL_DETACH_REQ:
- idndl_dreq(wq, mp);
- break;
-
- case DL_BIND_REQ:
- idndl_breq(wq, mp);
- break;
-
- case DL_UNBIND_REQ:
- idndl_ubreq(wq, mp);
- break;
-
- case DL_INFO_REQ:
- idndl_ireq(wq, mp);
- break;
-
- case DL_PROMISCON_REQ:
- idndl_ponreq(wq, mp);
- break;
-
- case DL_PROMISCOFF_REQ:
- idndl_poffreq(wq, mp);
- break;
-
- case DL_ENABMULTI_REQ:
- idndl_emreq(wq, mp);
- break;
-
- case DL_DISABMULTI_REQ:
- idndl_dmreq(wq, mp);
- break;
-
- case DL_PHYS_ADDR_REQ:
- idndl_pareq(wq, mp);
- break;
-
-#ifdef notdef
- /*
- * We cannot allow this in IDN-land because we
- * rely on the ethernet (physical) address to determine
- * where to target the message. Recall that unlike
- * ethernet we simply cannot dump junk on the wire and
- * expect it to automatically find its destination.
- * In the IDN we need to target the destination.
- * Note that if we used POINT-TO-POINT then we wouldn't
- * have to worry about the physical address since each
- * domain connection would have a separate queue.
- * However, ptp then requires multiple interfaces at
- * the appl level as opposed to a single one for all
- * of idn. We opt for the simpler single interface (idn0).
- */
- case DL_SET_PHYS_ADDR_REQ:
- idndl_spareq(wq, mp);
- break;
-#endif /* notdef */
-
- default:
- DLERRORACK(wq, mp, prim, DL_UNSUPPORTED, 0);
- break;
- }
-
- TRACE_2(TR_FAC_IDN, TR_IDN_PROTO_END,
- "idnproto end: wq %p dlprim %X", wq, prim);
-
- rw_exit(&stp->ss_rwlock);
-}
-
-int
-idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsizep)
-{
- int rv = 0;
- struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
- struct idnstr *stp = (struct idnstr *)wq->q_ptr;
- procname_t proc = "idnioc_dlpi";
-
- *argsizep = 0;
-
- switch (iocp->ioc_cmd) {
- case DLIOCRAW: /* raw M_DATA mode */
- PR_DLPI("%s: cmd = DLIOCRAW\n", proc);
- stp->ss_flags |= IDNSRAW;
- break;
-
- case DL_IOC_HDR_INFO: /* M_DATA "fastpath" info request */
- PR_DLPI("%s: cmd = DL_IOC_HDR_INFO\n", proc);
- rv = idndl_ioc_hdr_info(wq, mp, argsizep);
- break;
-
- default:
- PR_DLPI("%s: invalid cmd 0x%x\n", proc, iocp->ioc_cmd);
- rv = EINVAL;
- break;
- }
- return (rv);
-}
-
-/*
- * M_DATA "fastpath" info request.
- * Following the M_IOCTL mblk should come a DL_UNITDATA_REQ mblk.
- * We ack with an M_IOCACK pointing to the original DL_UNITDATA_REQ mblk
- * followed by an mblk containing the raw ethernet header corresponding
- * to the destination address. Subsequently, we may receive M_DATA
- * msgs which start with this header and may send up
- * up M_DATA msgs with b_rptr pointing to a (ulong) group address
- * indicator followed by the network-layer data (IP packet header).
- * This is all selectable on a per-Stream basis.
- */
-static int
-idndl_ioc_hdr_info(queue_t *wq, mblk_t *mp, int *argsizep)
-{
- mblk_t *nmp;
- struct idnstr *stp;
- struct idndladdr *dlap;
- dl_unitdata_req_t *dludp;
- struct ether_header *headerp;
- struct idn *sip;
- int off, len;
- int padding = 0;
- int error;
- procname_t proc = "idndl_ioc_hdr_info";
-
- stp = (struct idnstr *)wq->q_ptr;
- sip = stp->ss_sip;
- if (sip == NULL) {
- PR_DLPI("%s: NULL sip (ret EINVAL)\n", proc);
- return (EINVAL);
- }
-
- error = miocpullup(mp, sizeof (dl_unitdata_req_t) + IDNADDRL);
- if (error != 0) {
- PR_DLPI("%s: sanity error (ret %d)\n", proc, error);
- return (error);
- }
-
- /*
- * Sanity check the DL_UNITDATA_REQ destination address
- * offset and length values.
- */
- dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
- off = dludp->dl_dest_addr_offset;
- len = dludp->dl_dest_addr_length;
- if (dludp->dl_primitive != DL_UNITDATA_REQ ||
- !MBLKIN(mp->b_cont, off, len) || len != IDNADDRL) {
- PR_DLPI("%s: off(0x%x)/len(%d) error (ret EINVAL)\n",
- proc, off, len);
- return (EINVAL);
- }
-
- dlap = (struct idndladdr *)(mp->b_cont->b_rptr + off);
-
- /*
- * Allocate a new mblk to hold the ether header.
- */
- nmp = allocb(sizeof (struct ether_header) + padding, BPRI_MED);
- if (nmp == NULL) {
- IDN_KSTAT_INC(sip, si_allocbfail);
- return (ENOMEM);
- }
- nmp->b_rptr += padding;
- nmp->b_wptr = nmp->b_rptr + sizeof (struct ether_header);
-
- /*
- * Fill in the ether header.
- */
- headerp = (struct ether_header *)nmp->b_rptr;
- ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
- ether_copy(&sip->si_ouraddr, &headerp->ether_shost);
- headerp->ether_type = dlap->dl_sap;
-
- /*
- * Link new mblk in after the "request" mblks.
- */
- linkb(mp, nmp);
-
- stp->ss_flags |= IDNSFAST;
-
- /*
- * XXX Don't bother calling idndl_setipq() here.
- */
-
- if (argsizep)
- *argsizep = msgsize(mp->b_cont);
-
- return (0);
-}
-
-static void
-idndl_areq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- union DL_primitives *dlp;
- struct idn *sip;
- int ppa;
- procname_t proc = "idndl_areq";
-
- stp = (struct idnstr *)wq->q_ptr;
- dlp = (union DL_primitives *)mp->b_rptr;
-
- if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0);
- return;
- }
-
- if (stp->ss_state != DL_UNATTACHED) {
- DLERRORACK(wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- ppa = dlp->attach_req.dl_ppa;
-
- /*
- * Valid ppa?
- */
- if (ppa == -1 || qassociate(wq, ppa) != 0) {
- PR_DLPI("%s: bad ppa %d\n", proc, ppa);
- DLERRORACK(wq, mp, dlp->dl_primitive, DL_BADPPA, 0);
- return;
- }
- mutex_enter(&idn.siplock);
- for (sip = idn.sip; sip; sip = sip->si_nextp) {
- if (ppa == ddi_get_instance(sip->si_dip))
- break;
- }
- mutex_exit(&idn.siplock);
- ASSERT(sip != NULL); /* qassociate() succeeded */
-
- /*
- * Has device been initialized? Do so if necessary.
- */
- if ((sip->si_flags & IDNRUNNING) == 0) {
- if (idndl_init(sip)) {
- DLERRORACK(wq, mp, dlp->dl_primitive,
- DL_INITFAILED, 0);
- (void) qassociate(wq, -1);
- return;
- }
- }
-
- /*
- * Set link to device and update our state.
- */
- stp->ss_sip = sip;
- stp->ss_state = DL_UNBOUND;
-
- DLOKACK(wq, mp, DL_ATTACH_REQ);
-}
-
-static void
-idndl_dreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
- return;
- }
-
- if (stp->ss_state != DL_UNBOUND) {
- DLERRORACK(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- idndl_dodetach(stp);
- (void) qassociate(wq, -1);
- DLOKACK(wq, mp, DL_DETACH_REQ);
-}
-
-/*
- * Detach a Stream from an interface.
- */
-void
-idndl_dodetach(struct idnstr *stp)
-{
- struct idnstr *tstp;
- struct idn *sip;
- int reinit = 0;
-
- ASSERT(stp->ss_sip);
-
- sip = stp->ss_sip;
- stp->ss_sip = NULL;
-
- /*
- * Disable promiscuous mode if on.
- */
- if (stp->ss_flags & IDNSALLPHYS) {
- stp->ss_flags &= ~IDNSALLPHYS;
- reinit = 1;
- }
-
- /*
- * Disable ALLMULTI mode if on.
- */
- if (stp->ss_flags & IDNSALLMULTI) {
- stp->ss_flags &= ~IDNSALLMULTI;
- reinit = 1;
- }
-
- /*
- * Disable any Multicast Addresses.
- */
- stp->ss_mccount = 0;
- if (stp->ss_mctab) {
- kmem_free(stp->ss_mctab, IDNMCALLOC);
- stp->ss_mctab = NULL;
- reinit = 1;
- }
-
- /*
- * Detach from device structure.
- * Uninit the device when no other streams are attached to it.
- */
- rw_enter(&idn.struprwlock, RW_READER);
- for (tstp = idn.strup; tstp; tstp = tstp->ss_nextp)
- if (tstp->ss_sip == sip)
- break;
- rw_exit(&idn.struprwlock);
-
- if (tstp == NULL)
- idndl_uninit(sip);
- else if (reinit)
- (void) idndl_init(sip);
-
- stp->ss_state = DL_UNATTACHED;
-
- idndl_setipq(sip);
-}
-
-static void
-idndl_breq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- union DL_primitives *dlp;
- struct idn *sip;
- struct idndladdr idnaddr;
- t_uscalar_t sap;
- int xidtest;
- procname_t proc = "idndl_breq";
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
- return;
- }
-
- if (stp->ss_state != DL_UNBOUND) {
- DLERRORACK(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- dlp = (union DL_primitives *)mp->b_rptr;
-
- if (dlp->bind_req.dl_service_mode != idninfoack.dl_service_mode) {
- DLERRORACK(wq, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0);
- return;
- }
-
- sip = stp->ss_sip;
- sap = dlp->bind_req.dl_sap;
- xidtest = dlp->bind_req.dl_xidtest_flg;
-
- ASSERT(sip);
-
- if (xidtest) {
- DLERRORACK(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
- return;
- }
-
- if (sap > ETHERTYPE_MAX) {
- DLERRORACK(wq, mp, dlp->dl_primitive, DL_BADSAP, 0);
- return;
- }
-
- /*
- * Save SAP value for this Stream and change state.
- */
- stp->ss_sap = sap;
- stp->ss_state = DL_IDLE;
-
- idnaddr.dl_sap = sap;
- ether_copy(&sip->si_ouraddr, &idnaddr.dl_phys);
-
- if (IS_ETHERTYPE_IP(sap)) {
- int channel;
-
- channel =
- (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
- PR_DLPI("%s: IP SAP, opening channel %d\n", proc, channel);
- if (idn_open_channel(channel)) {
- PR_DLPI("%s: FAILED TO OPEN CHANNEL %d\n",
- proc, channel);
- DLERRORACK(wq, mp, dlp->dl_primitive, DL_NOADDR, 0);
- return;
- }
- }
- DLBINDACK(wq, mp, sap, &idnaddr, IDNADDRL, 0, 0);
-
- idndl_setipq(sip);
-}
-
-static void
-idndl_ubreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- procname_t proc = "idndl_ubreq";
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
- return;
- }
-
- if (stp->ss_state != DL_IDLE) {
- DLERRORACK(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- stp->ss_state = DL_UNBOUND;
-
- if (IS_ETHERTYPE_IP(stp->ss_sap)) {
- struct idn *sip;
- int channel;
-
- sip = stp->ss_sip;
- channel =
- (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
- PR_DLPI("%s: IP SAP, unbinding channel %d\n", proc, channel);
- /*
- * We need to do an "soft" close since there's a
- * potential that we've been called by one of the
- * IDN data server/dispatcher threads! We'll deadlock
- * if we attempt a "hard" close of the channel from here.
- */
- idn_close_channel(channel, IDNCHAN_SOFT_CLOSE);
- }
-
- stp->ss_sap = 0;
-
- DLOKACK(wq, mp, DL_UNBIND_REQ);
-
- idndl_setipq(stp->ss_sip);
-}
-
-static void
-idndl_ireq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- dl_info_ack_t *dlip;
- struct idndladdr *dlap;
- struct ether_addr *ep;
- int size;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0);
- return;
- }
-
- /*
- * Exchange current msg for a DL_INFO_ACK.
- */
- size = sizeof (dl_info_ack_t) + IDNADDRL + ETHERADDRL;
- if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL)
- return;
-
- /*
- * Fill in the DL_INFO_ACK fields and reply.
- */
- dlip = (dl_info_ack_t *)mp->b_rptr;
- ASSERT(idninfoack.dl_max_sdu);
- *dlip = idninfoack;
- dlip->dl_current_state = stp->ss_state;
- dlap = (struct idndladdr *)(mp->b_rptr + dlip->dl_addr_offset);
- dlap->dl_sap = stp->ss_sap;
- if (stp->ss_sip) {
- ether_copy(&stp->ss_sip->si_ouraddr, &dlap->dl_phys);
- } else {
- bzero(&dlap->dl_phys, ETHERADDRL);
- }
- ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
- ether_copy(&etherbroadcastaddr, ep);
-
- qreply(wq, mp);
-}
-
-static void
-idndl_ponreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
- return;
- }
-
- switch (((dl_promiscon_req_t *)mp->b_rptr)->dl_level) {
- case DL_PROMISC_PHYS:
- stp->ss_flags |= IDNSALLPHYS;
- break;
-
- case DL_PROMISC_SAP:
- stp->ss_flags |= IDNSALLSAP;
- break;
-
- case DL_PROMISC_MULTI:
- stp->ss_flags |= IDNSALLMULTI;
- break;
-
- default:
- DLERRORACK(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
- return;
- }
-
- if (stp->ss_sip)
- (void) idndl_init(stp->ss_sip);
-
- if (stp->ss_sip)
- idndl_setipq(stp->ss_sip);
-
- DLOKACK(wq, mp, DL_PROMISCON_REQ);
-}
-
-static void
-idndl_poffreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- int flag;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
- return;
- }
-
- switch (((dl_promiscoff_req_t *)mp->b_rptr)->dl_level) {
- case DL_PROMISC_PHYS:
- flag = IDNSALLPHYS;
- break;
-
- case DL_PROMISC_SAP:
- flag = IDNSALLSAP;
- break;
-
- case DL_PROMISC_MULTI:
- flag = IDNSALLMULTI;
- break;
-
- default:
- DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
- return;
- }
-
- if ((stp->ss_flags & flag) == 0) {
- DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
- return;
- }
-
- stp->ss_flags &= ~flag;
-
- if (stp->ss_sip)
- (void) idndl_init(stp->ss_sip);
-
- if (stp->ss_sip)
- idndl_setipq(stp->ss_sip);
-
- DLOKACK(wq, mp, DL_PROMISCOFF_REQ);
-}
-
-static void
-idndl_emreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- union DL_primitives *dlp;
- struct ether_addr *addrp;
- int off;
- int len;
- int i;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_ENABMULTI_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0);
- return;
- }
-
- if (stp->ss_state == DL_UNATTACHED) {
- DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- dlp = (union DL_primitives *)mp->b_rptr;
- len = dlp->enabmulti_req.dl_addr_length;
- off = dlp->enabmulti_req.dl_addr_offset;
- addrp = (struct ether_addr *)(mp->b_rptr + off);
-
- if ((len != ETHERADDRL) ||
- !MBLKIN(mp, off, len) ||
- !IDNDL_ADDR_IS_MULTICAST(addrp)) {
- DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
- return;
- }
-
- if ((stp->ss_mccount + 1) >= IDNMAXMC) {
- DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_TOOMANY, 0);
- return;
- }
-
- /*
- * Allocate table on first request.
- */
- if (stp->ss_mctab == NULL)
- stp->ss_mctab = kmem_alloc(IDNMCALLOC, KM_SLEEP);
-
- /*
- * Check to see if the address is already in the table.
- * Bug 1209733:
- * If present in the table, add the entry to the end of the table
- * and return without initializing the hardware.
- */
- for (i = 0; i < stp->ss_mccount; i++) {
- if (ether_cmp(&stp->ss_mctab[i], addrp) == 0) {
- stp->ss_mctab[stp->ss_mccount++] = *addrp;
- DLOKACK(wq, mp, DL_ENABMULTI_REQ);
- return;
- }
- }
-
- stp->ss_mctab[stp->ss_mccount++] = *addrp;
-
- (void) idndl_init(stp->ss_sip);
-
- DLOKACK(wq, mp, DL_ENABMULTI_REQ);
-}
-
-static void
-idndl_dmreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- union DL_primitives *dlp;
- struct ether_addr *addrp;
- int off;
- int len;
- int i;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_DISABMULTI_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
- return;
- }
-
- if (stp->ss_state == DL_UNATTACHED) {
- DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- dlp = (union DL_primitives *)mp->b_rptr;
- len = dlp->disabmulti_req.dl_addr_length;
- off = dlp->disabmulti_req.dl_addr_offset;
- addrp = (struct ether_addr *)(mp->b_rptr + off);
-
- if ((len != ETHERADDRL) || !MBLKIN(mp, off, len)) {
- DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0);
- return;
- }
-
- /*
- * Find the address in the multicast table for this Stream
- * and delete it by shifting all subsequent multicast
- * table entries over one.
- */
- for (i = 0; i < stp->ss_mccount; i++)
- if (ether_cmp(addrp, &stp->ss_mctab[i]) == 0) {
- bcopy(&stp->ss_mctab[i+1],
- &stp->ss_mctab[i],
- ((stp->ss_mccount - i) *
- sizeof (struct ether_addr)));
- stp->ss_mccount--;
- (void) idndl_init(stp->ss_sip);
- DLOKACK(wq, mp, DL_DISABMULTI_REQ);
- return;
- }
- DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_NOTENAB, 0);
-}
-
-static void
-idndl_pareq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- union DL_primitives *dlp;
- int type;
- struct idn *sip;
- struct ether_addr addr;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
- return;
- }
-
- dlp = (union DL_primitives *)mp->b_rptr;
- type = dlp->physaddr_req.dl_addr_type;
- sip = stp->ss_sip;
-
- if (sip == NULL) {
- DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- switch (type) {
- case DL_FACT_PHYS_ADDR:
- idndl_localetheraddr(sip, &addr);
- break;
-
- case DL_CURR_PHYS_ADDR:
- ether_copy(&sip->si_ouraddr, &addr);
- break;
-
- default:
- DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
- return;
- }
-
- DLPHYSADDRACK(wq, mp, &addr, ETHERADDRL);
-}
-
-#ifdef notdef
-static void
-idndl_spareq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- union DL_primitives *dlp;
- int off;
- int len;
- struct ether_addr *addrp;
- struct idn *sip;
-
- stp = (struct idnstr *)wq->q_ptr;
-
- if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) {
- DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
- return;
- }
-
- dlp = (union DL_primitives *)mp->b_rptr;
- len = dlp->set_physaddr_req.dl_addr_length;
- off = dlp->set_physaddr_req.dl_addr_offset;
-
- if (!MBLKIN(mp, off, len)) {
- DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
- return;
- }
-
- addrp = (struct ether_addr *)(mp->b_rptr + off);
-
- /*
- * Error if length of address isn't right or the address
- * specified is a multicast or broadcast address.
- */
- if ((len != ETHERADDRL) ||
- IDNDL_ADDR_IS_MULTICAST(addrp) ||
- (ether_cmp(addrp, &etherbroadcastaddr) == 0)) {
- DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
- return;
- }
-
- /*
- * Error if this stream is not attached to a device.
- */
- if ((sip = stp->ss_sip) == NULL) {
- DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- /*
- * Set new interface local address and re-init device.
- * This is destructive to any other streams attached
- * to this device.
- */
- ether_copy(addrp, &sip->si_ouraddr);
- (void) idndl_init(stp->ss_sip);
-
- DLOKACK(wq, mp, DL_SET_PHYS_ADDR_REQ);
-}
-#endif /* notdef */
-
-static void
-idndl_udreq(queue_t *wq, mblk_t *mp)
-{
- struct idnstr *stp;
- register struct idn *sip;
- register dl_unitdata_req_t *dludp;
- mblk_t *nmp;
- struct idndladdr *dlap;
- struct ether_header *headerp;
- t_uscalar_t off, len;
- t_uscalar_t sap;
-
- stp = (struct idnstr *)wq->q_ptr;
- sip = stp->ss_sip;
-
- if (stp->ss_state != DL_IDLE) {
- DLERRORACK(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
- return;
- }
-
- dludp = (dl_unitdata_req_t *)mp->b_rptr;
-
- off = dludp->dl_dest_addr_offset;
- len = dludp->dl_dest_addr_length;
-
- /*
- * Validate destination address format.
- */
- if (!MBLKIN(mp, off, len) || (len != IDNADDRL)) {
- dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0);
- return;
- }
-
- /*
- * Error if no M_DATA follows.
- */
- nmp = mp->b_cont;
- if (nmp == NULL) {
- dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADDATA, 0);
- return;
- }
-
- dlap = (struct idndladdr *)(mp->b_rptr + off);
-
- /*
- * Create ethernet header by either prepending it onto the
- * next mblk if potential, or reusing the M_PROTO block if not.
- */
- if ((DB_REF(nmp) == 1) &&
- (MBLKHEAD(nmp) >= sizeof (struct ether_header)) &&
- (((ulong_t)nmp->b_rptr & 0x1) == 0)) {
- nmp->b_rptr -= sizeof (struct ether_header);
- headerp = (struct ether_header *)nmp->b_rptr;
- ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
- ether_copy(&sip->si_ouraddr, &headerp->ether_shost);
- sap = dlap->dl_sap;
- freeb(mp);
- mp = nmp;
- } else {
- DB_TYPE(mp) = M_DATA;
- headerp = (struct ether_header *)mp->b_rptr;
- mp->b_wptr = mp->b_rptr + sizeof (struct ether_header);
- ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
- ether_copy(&sip->si_ouraddr, &headerp->ether_shost);
- sap = dlap->dl_sap;
- }
-
- /*
- * For transmitting, the driver looks at the
- * sap field of the DL_BIND_REQ being 0 in addition to the type
- * field in the range [0-1500]. If either is true, then the driver
- * computes the length of the message, not including initial M_PROTO
- * mblk (message block), of all subsequent DL_UNITDATA_REQ messages and
- * transmits 802.3 frames that have this value in the MAC frame header
- * length field.
- */
- if ((sap <= ETHERMTU) || (stp->ss_sap == 0))
- headerp->ether_type = (msgsize(mp) -
- sizeof (struct ether_header));
- else
- headerp->ether_type = sap;
-
- /*
- * The data transfer code requires only READ access (idn_wput_data).
- */
- rw_downgrade(&stp->ss_rwlock);
- (void) idndl_start(wq, mp, sip);
-}
-
-int
-idndl_start(queue_t *wq, register mblk_t *mp, register struct idn *sip)
-{
- int rv = 0;
- int flags;
- int broadcast = 0;
- int goagain = 0;
- int goqueue = 0;
- int msgcount;
- char channel;
- mblk_t *nmp = NULL;
- int domid;
- domainset_t domset;
- idn_netaddr_t netaddr;
- struct idnstr *stp;
- struct ether_header *ehp;
- procname_t proc = "idndl_start";
-
- ASSERT(DB_TYPE(mp) == M_DATA);
-
- stp = (struct idnstr *)wq->q_ptr;
- ASSERT(sip == stp->ss_sip);
- flags = sip->si_flags;
- channel = (char)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
-
- ASSERT(RW_READ_HELD(&stp->ss_rwlock));
-
- if ((flags & (IDNRUNNING|IDNPROMISC)) != IDNRUNNING) {
- if (!(flags & IDNRUNNING))
- goto requeue;
- }
-
- /*
- * Translate an IDN ethernet address into a domainid
- * and idnaddr.
- */
- ehp = (struct ether_header *)mp->b_rptr;
- domid = IDNDL_ETHER2DOMAIN(&ehp->ether_dhost);
-
- /*
- * update MIB II statistics
- */
- BUMP_OutNUcast(sip, ehp);
-
- PR_DLPI("%s: ether %x:%x:%x:%x:%x:%x (domid = %d)\n",
- proc, ehp->ether_dhost.ether_addr_octet[0],
- ehp->ether_dhost.ether_addr_octet[1],
- ehp->ether_dhost.ether_addr_octet[2],
- ehp->ether_dhost.ether_addr_octet[3],
- ehp->ether_dhost.ether_addr_octet[4],
- ehp->ether_dhost.ether_addr_octet[5],
- domid);
-
- netaddr.net.chan = channel;
- PR_DLPI("%s: source channel = %d\n", proc, (int)channel);
-
- if ((ether_cmp(&ehp->ether_dhost, &etherbroadcastaddr) == 0) ||
- IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost)) {
- /*
- * Caller wants to broadcast!
- * XXX - Send to everybody but ourself???
- */
- PR_DLPI("%s: broadcast/multicast requested!!!\n", proc);
- domset = ~DOMAINSET(idn.localid);
- broadcast = 1;
- netaddr.net.netid = IDN_BROADCAST_ALLNETID;
- if ((flags & IDNPROMISC) &&
- ((nmp = copymsg(mp)) == NULL)) {
- IDN_KSTAT_INC(sip, si_allocbfail);
- }
-
- } else if (domid != IDN_NIL_DOMID) {
- domset = DOMAINSET(domid);
- netaddr.net.netid = idn_domain[domid].dnetid;
- if ((flags & IDNPROMISC) &&
- ((nmp = copymsg(mp)) == NULL)) {
- IDN_KSTAT_INC(sip, si_allocbfail);
- }
- } else {
-#ifdef DEBUG
- int netid;
-
- netid = (int)
- ehp->ether_dhost.ether_addr_octet[IDNETHER_NETID];
- PR_DLPI("%s: no domain found for netid 0x%x\n",
- proc, netid);
-#endif /* DEBUG */
- goto bad;
- }
-
- PR_DLPI("%s: target domainset = 0x%x\n", proc, domset);
-
- if ((domset == 0) && (domid == IDN_NIL_DOMID)) {
- PR_DLPI("%s: not connected to any domains!! Bailing\n",
- proc);
- goto bad;
- }
- /*
- * XXX - Need to find a better way to handle broadcasting.
- * Should be able to take advantage of the fact that
- * we can broadcast XDC's (xdc_some). Need to use
- * atomic counter (semaphore) instead of binary
- * "owner" flag, or perhaps domain specific owner bytes.
- *
- * Transfer the data.
- */
- msgcount = 0;
- if (!broadcast)
- goto noloop;
-
- for (domid = 0; domid < MAX_DOMAINS; domid++) {
- if (!DOMAIN_IN_SET(domset, domid))
- continue;
-
-noloop:
-
- if (idn_domain[domid].dcpu == IDN_NIL_DCPU) {
- if (broadcast)
- continue;
- else
- break;
- }
-
- rv = idn_send_data(domid, netaddr, wq, mp);
-
- switch (rv) {
- case IDNXMIT_LOOP: /* handled in loopback */
- msgcount++;
- break;
-
- case IDNXMIT_OKAY: /* handled, okay to free */
- msgcount++;
- break;
-
- case IDNXMIT_RETRY:
- if (!broadcast)
- goto tryagain;
- goagain++;
- break;
-
- case IDNXMIT_REQUEUE:
- if (!broadcast)
- goto requeue;
- goqueue++;
- break;
-
- default:
- if (!broadcast)
- goto bad;
- break;
- }
- if (!broadcast)
- break;
- }
-
- if (msgcount == 0)
- if (goqueue)
- goto requeue;
- else if (goagain)
- goto tryagain;
- else
- goto bad;
-
- if ((flags & IDNPROMISC) && nmp)
- idndl_sendup(sip, nmp, idndl_paccept);
-
- freemsg(mp);
-
- PR_DLPI("%s: successful transmit to domainset 0x%x.\n",
- proc, domset);
-
- return (0);
-
-bad:
- PR_DLPI("%s: bad transmission to domainset 0x%x, dropping msg.\n",
- proc, domset);
- if (nmp)
- freemsg(nmp);
- freemsg(mp);
- qenable(wq);
- return (1);
-
-requeue:
- PR_DLPI("%s: requeue for domainset 0x%x, no qenable\n",
- proc, domset);
- if (nmp)
- freemsg(nmp);
- if (putbq(wq, mp) == 0)
- freemsg(mp);
- return (1);
-
-tryagain:
- PR_DLPI("%s: try again to domainset 0x%x, putbq.\n",
- proc, domset);
- if (nmp)
- freemsg(nmp);
- if (putbq(wq, mp) == 0)
- freemsg(mp);
- qenable(wq);
- return (1);
-}
-
-/*
- * Called by: idnh_recv_data, idn_recv_mboxdata.
- */
-void
-idndl_read(struct idn *sip, mblk_t *mp)
-{
- struct ether_header *ehp;
- queue_t *ip4q;
- queue_t *ip6q;
- int pktlen;
- procname_t proc = "idndl_read";
-
- PR_DLPI("%s: incoming msgsize = %lu, msgdsize = %lu\n",
- proc, msgsize(mp), msgdsize(mp));
-
- ehp = (struct ether_header *)mp->b_rptr;
- if (sip == NULL)
- sip = IDNDL_ETHER2SIP(&ehp->ether_dhost);
- if (sip == NULL) {
- /*
- * If the sip is NULL, then I don't have a connection
- * for this network. No point in sending the message
- * up.
- */
- PR_DLPI("%s: no plumbing to send message through.\n",
- proc);
- freemsg(mp);
- return;
- }
- IDN_KSTAT_INC(sip, si_ipackets);
- IDN_KSTAT_INC(sip, si_ipackets64);
- /*
- * update MIB II statistics
- */
- pktlen = mp->b_wptr - mp->b_rptr;
- BUMP_InNUcast(sip, ehp);
- IDN_KSTAT_ADD(sip, si_rcvbytes, pktlen);
- IDN_KSTAT_ADD(sip, si_rbytes64, (uint64_t)pktlen);
-
- ip4q = sip->si_ip4q;
- ip6q = sip->si_ip6q;
-
- if (IS_ETHERTYPE_IPV4(ehp->ether_type) &&
- !IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost) &&
- ip4q &&
- canputnext(ip4q)) {
- mp->b_rptr += sizeof (struct ether_header);
- (void) putnext(ip4q, mp);
- /*LINTED*/
- } else if (IS_ETHERTYPE_IPV6(ehp->ether_type) &&
- !IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost) &&
- ip6q &&
- canputnext(ip6q)) {
- mp->b_rptr += sizeof (struct ether_header);
- (void) putnext(ip6q, mp);
- } else {
- /*
- * Strip the PADs for 802.3
- */
- pktlen = ehp->ether_type + sizeof (struct ether_header);
- PR_DLPI("%s: stripping PADs for 802.3 (pktlen=%d)\n",
- proc, pktlen);
- if (pktlen < ETHERMIN)
- mp->b_wptr = mp->b_rptr + pktlen;
- idndl_sendup(sip, mp, idndl_accept);
- }
-}
-
-int
-idndl_init(struct idn *sip)
-{
- struct idnstr *stp;
-
- if (sip->si_flags & IDNSUSPENDED)
- (void) ddi_dev_is_needed(sip->si_dip, 0, 1);
-
- sip->si_flags = 0;
- sip->si_wantw = 0;
-
- IDN_KSTAT_INC(sip, si_inits);
-
- rw_enter(&idn.struprwlock, RW_WRITER);
-
- for (stp = idn.strup; stp; stp = stp->ss_nextp) {
- if ((stp->ss_sip == sip) && (stp->ss_flags & IDNSALLPHYS)) {
- sip->si_flags |= IDNPROMISC;
- break;
- }
- }
-
- sip->si_flags |= IDNRUNNING;
-
- mutex_enter(&idn.sipwenlock);
- idndl_wenable(sip);
- mutex_exit(&idn.sipwenlock);
-
- rw_exit(&idn.struprwlock);
-
- return (!(sip->si_flags & IDNRUNNING));
-}
-
-void
-idndl_uninit(struct idn *sip)
-{
- int channel;
- procname_t proc = "idndl_uninit";
-
- sip->si_flags &= ~IDNRUNNING;
-
- channel = (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL];
- PR_DLPI("%s: IP SAP, uninit channel %d\n", proc, channel);
- /*
- * A uninit is a hard close of an interface.
- */
- idn_close_channel(channel, IDNCHAN_HARD_CLOSE);
-}
-
-/*
- * Send packet upstream.
- * Assume mp->b_rptr points to ether_header.
- */
-void
-idndl_sendup(struct idn *sip, mblk_t *mp, struct idnstr *(*acceptfunc)())
-{
- int type;
- struct ether_addr *dhostp, *shostp;
- struct idnstr *stp, *nstp;
- mblk_t *nmp;
- ulong_t isgroupaddr;
-
- TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_START, "idnsendup start");
-
- dhostp = &((struct ether_header *)mp->b_rptr)->ether_dhost;
- shostp = &((struct ether_header *)mp->b_rptr)->ether_shost;
- type = ((struct ether_header *)mp->b_rptr)->ether_type;
-
- isgroupaddr = IDNDL_ADDR_IS_MULTICAST(dhostp);
-
- /*
- * While holding a reader lock on the linked list of streams structures,
- * attempt to match the address criteria for each stream
- * and pass up the raw M_DATA ("fastpath") or a DL_UNITDATA_IND.
- */
-
- rw_enter(&idn.struprwlock, RW_READER);
-
- if ((stp = (*acceptfunc)(idn.strup, sip, type, dhostp)) == NULL) {
- rw_exit(&idn.struprwlock);
- freemsg(mp);
- TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_END, "idnsendup end");
- return;
- }
-
- /*
- * Loop on matching open streams until (*acceptfunc)() returns NULL.
- */
- for (; nstp = (*acceptfunc)(stp->ss_nextp, sip, type, dhostp);
- stp = nstp) {
-
- if (canputnext(stp->ss_rq) == 0) {
- IDN_KSTAT_INC(sip, si_nocanput);
- continue;
- }
- if ((nmp = dupmsg(mp)) == NULL)
- nmp = copymsg(mp);
- if (nmp) {
- if ((stp->ss_flags & IDNSFAST) && !isgroupaddr) {
- nmp->b_rptr += sizeof (struct ether_header);
- (void) putnext(stp->ss_rq, nmp);
- } else if (stp->ss_flags & IDNSRAW) {
- (void) putnext(stp->ss_rq, nmp);
- } else if ((nmp = idndl_addudind(sip, nmp, shostp,
- dhostp, type, isgroupaddr))) {
- (void) putnext(stp->ss_rq, nmp);
- }
- } else {
- IDN_KSTAT_INC(sip, si_allocbfail);
- }
- }
-
-
- /*
- * Do the last one.
- */
- if (canputnext(stp->ss_rq)) {
- if ((stp->ss_flags & IDNSFAST) && !isgroupaddr) {
- mp->b_rptr += sizeof (struct ether_header);
- (void) putnext(stp->ss_rq, mp);
- } else if (stp->ss_flags & IDNSRAW) {
- (void) putnext(stp->ss_rq, mp);
- } else if ((mp = idndl_addudind(sip, mp, shostp, dhostp,
- type, isgroupaddr))) {
- (void) putnext(stp->ss_rq, mp);
- }
- } else {
- freemsg(mp);
- IDN_KSTAT_INC(sip, si_nocanput);
- IDN_KSTAT_INC(sip, si_norcvbuf); /* MIB II */
- }
-
- rw_exit(&idn.struprwlock);
- TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_END, "idnsendup end");
-}
-
-/*
- * Test upstream destination sap and address match.
- */
-struct idnstr *
-idndl_accept(register struct idnstr *stp, register struct idn *sip,
- int type, struct ether_addr *addrp)
-{
- t_uscalar_t sap;
- uint_t flags;
-
- for (; stp; stp = stp->ss_nextp) {
- sap = stp->ss_sap;
- flags = stp->ss_flags;
-
- if ((stp->ss_sip == sip) && IDNSAPMATCH(sap, type, flags))
- if ((ether_cmp(addrp, &sip->si_ouraddr) == 0) ||
- (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
- (flags & IDNSALLPHYS) ||
- idndl_mcmatch(stp, addrp))
- return (stp);
- }
-
- return (NULL);
-}
-
-/*
- * Test upstream destination sap and address match for IDNSALLPHYS only.
- */
-/* ARGSUSED3 */
-struct idnstr *
-idndl_paccept(register struct idnstr *stp, register struct idn *sip,
- int type, struct ether_addr *addrp)
-{
- t_uscalar_t sap;
- uint_t flags;
-
- for (; stp; stp = stp->ss_nextp) {
- sap = stp->ss_sap;
- flags = stp->ss_flags;
-
- if ((stp->ss_sip == sip) &&
- IDNSAPMATCH(sap, type, flags) &&
- (flags & IDNSALLPHYS))
- return (stp);
- }
-
- return (NULL);
-}
-
-/*
- * Set or clear the device ipq pointer.
- * Assumes IPv4 and IPv6 are IDNSFAST.
- */
-static void
-idndl_setipq(struct idn *sip)
-{
- struct idnstr *stp;
- int ok4 = 1;
- int ok6 = 1;
- queue_t *ip4q = NULL;
- queue_t *ip6q = NULL;
-
- rw_enter(&idn.struprwlock, RW_READER);
-
- for (stp = idn.strup; stp; stp = stp->ss_nextp) {
- if (stp->ss_sip == sip) {
- if (stp->ss_flags & (IDNSALLPHYS|IDNSALLSAP)) {
- ok4 = 0;
- ok6 = 0;
- break;
- }
- if (IS_ETHERTYPE_IPV4(stp->ss_sap)) {
- if (ip4q == NULL)
- ip4q = stp->ss_rq;
- else
- ok4 = 0;
- /*LINTED*/
- } else if (IS_ETHERTYPE_IPV6(stp->ss_sap)) {
- if (ip6q == NULL)
- ip6q = stp->ss_rq;
- else
- ok6 = 0;
- }
- }
- }
-
- rw_exit(&idn.struprwlock);
-
- if (ok4)
- sip->si_ip4q = ip4q;
- else
- sip->si_ip4q = NULL;
- if (ok6)
- sip->si_ip6q = ip6q;
- else
- sip->si_ip6q = NULL;
-}
-
-/*
- * Prefix msg with a DL_UNITDATA_IND mblk and return the new msg.
- */
-static mblk_t *
-idndl_addudind(struct idn *sip, mblk_t *mp,
- struct ether_addr *shostp, struct ether_addr *dhostp,
- int type, ulong_t isgroupaddr)
-{
- dl_unitdata_ind_t *dludindp;
- struct idndladdr *dlap;
- mblk_t *nmp;
- int size;
-
- TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_START, "idndl_addudind start");
-
- mp->b_rptr += sizeof (struct ether_header);
-
- /*
- * Allocate an M_PROTO mblk for the DL_UNITDATA_IND.
- */
- size = sizeof (dl_unitdata_ind_t) + IDNADDRL + IDNADDRL;
- nmp = allocb(IDNROUNDUP(IDNHEADROOM + size, sizeof (double)), BPRI_LO);
- if (nmp == NULL) {
- IDN_KSTAT_INC(sip, si_allocbfail);
- IDN_KSTAT_INC(sip, si_ierrors);
- if (idn_debug)
- serror(sip->si_dip, 451, "allocb failed");
- freemsg(mp);
- TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_END, "idndl_addudind end");
- return (NULL);
- }
- DB_TYPE(nmp) = M_PROTO;
- nmp->b_wptr = nmp->b_datap->db_lim;
- nmp->b_rptr = nmp->b_wptr - size;
-
- /*
- * Construct a DL_UNITDATA_IND primitive.
- */
- dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
- dludindp->dl_primitive = DL_UNITDATA_IND;
- dludindp->dl_dest_addr_length = IDNADDRL;
- dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
- dludindp->dl_src_addr_length = IDNADDRL;
- dludindp->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + IDNADDRL;
- dludindp->dl_group_address = isgroupaddr;
-
- dlap = (struct idndladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t));
- ether_copy(dhostp, &dlap->dl_phys);
- dlap->dl_sap = (ushort_t)type;
-
- dlap = (struct idndladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t)
- + IDNADDRL);
- ether_copy(shostp, &dlap->dl_phys);
- dlap->dl_sap = (ushort_t)type;
-
- /*
- * Link the M_PROTO and M_DATA together.
- */
- nmp->b_cont = mp;
- TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_END, "idndl_addudind end");
- return (nmp);
-}
-
-/*
- * Return TRUE if the given multicast address is one
- * of those that this particular Stream is interested in.
- */
-static int
-idndl_mcmatch(register struct idnstr *stp, register struct ether_addr *addrp)
-{
- register struct ether_addr *mctab;
- register int mccount;
- register int i;
-
- /*
- * Return FALSE if not a multicast address.
- */
- if (!IDNDL_ADDR_IS_MULTICAST(addrp))
- return (0);
-
- /*
- * Check if all multicasts have been enabled for this Stream
- */
- if (stp->ss_flags & IDNSALLMULTI)
- return (1);
-
- /*
- * Return FALSE if no multicast addresses enabled for this Stream.
- */
- if (stp->ss_mccount == 0)
- return (0);
-
- /*
- * Otherwise, find it in the table.
- */
-
- mccount = stp->ss_mccount;
- mctab = stp->ss_mctab;
-
- for (i = 0; i < mccount; i++)
- if (!ether_cmp(addrp, &mctab[i]))
- return (1);
-
- return (0);
-}
-
-/*
- * Start xmit on any msgs previously enqueued on any write queues.
- * If the caller passes NULL, then we need to check all
- * our interfaces.
- */
-void
-idndl_wenable(struct idn *sip)
-{
- struct idnstr *stp;
- queue_t *wq;
-
- /*
- * Order of wantw accesses is important.
- */
- ASSERT((sip == NULL) ? RW_LOCK_HELD(&idn.struprwlock) : 1);
- ASSERT(MUTEX_HELD(&idn.sipwenlock));
-
- do {
- if (sip)
- sip->si_wantw = 0;
- for (stp = idn.strup; stp; stp = stp->ss_nextp) {
- if ((!sip || (stp->ss_sip == sip)) &&
- stp->ss_rq && ((wq = WR(stp->ss_rq))->q_first))
- qenable(wq);
- }
- } while (sip && sip->si_wantw);
-}
-
-/*VARARGS*/
-static void
-serror(dev_info_t *dip, int idnerr, char *fmt, ...)
-{
- static long last;
- static char *lastfmt;
- char msg_buffer[255];
- va_list ap;
- time_t now;
-
- /*
- * Don't print same error message too often.
- */
- now = gethrestime_sec();
- if ((last == (now & ~1)) && (lastfmt == fmt))
- return;
-
- last = now & ~1;
- lastfmt = fmt;
-
- va_start(ap, fmt);
- (void) vsprintf(msg_buffer, fmt, ap);
- cmn_err(CE_CONT, "IDN: %d: %s%d: %s\n",
- idnerr, ddi_get_name(dip),
- ddi_get_instance(dip), msg_buffer);
- va_end(ap);
-}
diff --git a/usr/src/uts/sun4u/starfire/io/idn_proto.c b/usr/src/uts/sun4u/starfire/io/idn_proto.c
deleted file mode 100644
index cebcdb89f7..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn_proto.c
+++ /dev/null
@@ -1,12971 +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) 2016 by Delphix. All rights reserved.
- */
-
-/*
- * Inter-Domain Network
- *
- * IDN Protocol functions to support domain link/unlink/reconfig.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/machparam.h>
-#include <sys/debug.h>
-#include <sys/cpuvar.h>
-#include <sys/kmem.h>
-#include <sys/mutex.h>
-#include <sys/rwlock.h>
-#include <sys/systm.h>
-#include <sys/stream.h>
-#include <sys/strsun.h>
-#include <sys/stropts.h>
-#include <sys/sema_impl.h>
-#include <sys/membar.h>
-#include <sys/utsname.h>
-#include <inet/common.h>
-#include <inet/mi.h>
-#include <netinet/ip6.h>
-#include <inet/ip.h>
-#include <netinet/in.h>
-#include <sys/vm_machparam.h>
-#include <sys/x_call.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/atomic.h>
-#include <vm/as.h> /* kas decl */
-
-#include <sys/idn.h>
-#include <sys/idn_xf.h>
-
-#define IDNBUG_CPUPERBOARD
-
-extern pri_t maxclsyspri;
-extern u_longlong_t gettick();
-
-clock_t idn_xmit_monitor_freq = 50;
-
-static int idn_connect(int domid);
-static int idn_disconnect(int domid, idn_fin_t fintype,
- idn_finarg_t finarg, idn_finsync_t finsync);
-static void idn_deconfig(int domid);
-static void idn_unlink_domainset(domainset_t domset, idn_fin_t fintype,
- idn_finarg_t finarg, idn_finopt_t finopt,
- boardset_t idnset);
-static void idn_retry_execute(void *arg);
-static void idn_retry_submit(void (*func)(uint_t token, void *arg),
- void *arg, uint_t token, clock_t ticks);
-static void idn_shutdown_datapath(domainset_t domset, int force);
-static mblk_t *idn_fill_buffer(caddr_t bufp, int size, mblk_t *mp,
- uchar_t **data_rptrp);
-static ushort_t idn_cksum(register ushort_t *hdrp, register int count);
-static int idn_mark_awol(int domid, clock_t *atime);
-
-static void idn_recv_proto(idn_protomsg_t *hp);
-static void idn_send_config(int domid, int phase);
-static void idn_recv_config(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static int idn_send_master_config(int domid, int phase);
-static int idn_send_slave_config(int domid, int phase);
-static uint_t idn_check_master_config(int domid, uint_t *exp, uint_t *act);
-static uint_t idn_check_slave_config(int domid, uint_t *exp, uint_t *act);
-static int idn_recv_config_done(int domid);
-static void idn_nego_cleanup_check(int domid, int new_masterid,
- int new_cpuid);
-static void idn_recv_cmd(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static int idn_recv_data(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static int idn_send_data_loopback(idn_netaddr_t dst_netaddr,
- queue_t *wq, mblk_t *mp);
-static void idn_send_dataresp(int domid, idn_nack_t nacktype);
-static int idn_send_mboxdata(int domid, struct idn *sip, int channel,
- caddr_t bufp);
-static int idn_recv_mboxdata(int channel, caddr_t bufp);
-static int idn_program_hardware(int domid);
-static int idn_deprogram_hardware(int domid);
-
-static void idn_send_cmd_nackresp(int domid, idn_msgtype_t *mtp,
- idn_cmd_t cmdtype, idn_nack_t nacktype);
-static void idn_local_cmd(idn_cmd_t cmdtype, uint_t arg1,
- uint_t arg2, uint_t arg3);
-static void idn_terminate_cmd(int domid, int serrno);
-static void idn_mboxarea_init(idn_mboxtbl_t *mtp, register int ntbls);
-static void idn_mainmbox_activate(int domid);
-static void idn_mainmbox_deactivate(ushort_t domset);
-static void idn_mainmbox_chan_register(int domid,
- idn_mainmbox_t *send_mmp,
- idn_mainmbox_t *recv_mmp, int channel);
-static int idn_mainmbox_chan_unregister(ushort_t domset, int channel);
-static int idn_mainmbox_flush(int domid, idn_mainmbox_t *mmp);
-static void idn_mainmbox_reset(int domid, idn_mainmbox_t *cmp);
-static int idn_activate_channel(idn_chanset_t chanset,
- idn_chanop_t chanop);
-static void idn_deactivate_channel(idn_chanset_t chanset,
- idn_chanop_t chanop);
-static int idn_deactivate_channel_services(int channel,
- idn_chanop_t chanop);
-static int idn_activate_channel_services(int channel);
-static void idn_chan_server(idn_chansvr_t **cspp);
-#if 0
-static void idn_chan_flush(idn_chansvr_t *csp);
-#endif /* 0 */
-static void idn_chan_action(int channel, idn_chanaction_t chanaction,
- int wait);
-static void idn_chan_addmbox(int channel, ushort_t domset);
-static void idn_chan_delmbox(int channel, ushort_t domset);
-static void idn_submit_chanactivate_job(int channel);
-static void idn_exec_chanactivate(void *chn);
-
-static void idn_link_established(void *arg);
-static void idn_prealloc_slab(int nslabs);
-static void idn_recv_slaballoc_req(int domid, idn_msgtype_t *mtp,
- uint_t slab_size);
-static void idn_send_slaballoc_resp(int domid, idn_msgtype_t *mtp,
- uint_t slab_offset, uint_t slab_size,
- int serrno);
-static void idn_recv_slaballoc_resp(int domid, smr_offset_t slab_offset,
- uint_t slab_size, int serrno);
-static void idn_recv_slabreap_req(int domid, idn_msgtype_t *mtp,
- int nslabs);
-static void idn_recv_slabreap_resp(int domid, int nslabs, int serrno);
-static void idn_send_slabreap_resp(int domid, idn_msgtype_t *mtp,
- int nslabs, int serrno);
-static void idn_recv_slabfree_req(int domid, idn_msgtype_t *mtp,
- smr_offset_t slab_offset, uint_t slab_size);
-static void idn_recv_slabfree_resp(int domid, uint_t slab_offset,
- uint_t slab_size, int serrno);
-static void idn_send_slabfree_resp(int domid, idn_msgtype_t *mtp,
- uint_t slab_offset, uint_t slab_size,
- int serrno);
-static void idn_retry_nodename_req(void *arg);
-static void idn_send_nodename_req(int domid);
-static void idn_send_nodename_resp(int domid, idn_msgtype_t *mtp,
- uint_t bufoffset, int serrno);
-static void idn_recv_nodename_req(int domid, idn_msgtype_t *mtp,
- uint_t bufoffset);
-static void idn_recv_nodename_resp(int domid, uint_t bufoffset,
- int serrno);
-
-static void idn_protocol_server(int *id);
-static void idn_protocol_server_killall();
-static void idn_protojob_free(idn_protojob_t *jp);
-
-static int idn_xstate_transfunc(int domid, void *transarg);
-static int idn_xphase_transition(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_sync_enter(int domid, idn_synccmd_t cmd,
- domainset_t xset, domainset_t rset,
- int (*transfunc)(), void *transarg);
-static domainset_t
- idn_sync_register(int domid, idn_synccmd_t cmd,
- domainset_t ready_set, idn_syncreg_t regtype);
-static void idn_sync_register_awol(int domid);
-static int idn_verify_config_mbox(int domid);
-static int idn_select_master(int domid, int rmasterid, int rcpuid);
-
-static int valid_mtu(uint_t mtu);
-static int valid_bufsize(uint_t bufsize);
-static int valid_slabsize(int slabsize);
-static int valid_nwrsize(int nwrsize);
-
-static int idn_master_init();
-static void idn_master_deinit();
-
-static void idn_send_acknack(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-
-static int idn_send_nego(int domid, idn_msgtype_t *mtp,
- domainset_t conset);
-static void idn_retry_nego(uint_t token, void *arg);
-static int idn_check_nego(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_nego_pend(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_error_nego(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_nego_sent(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_nego_rcvd(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_final_nego(int domid);
-static void idn_exit_nego(int domid, uint_t msgtype);
-
-static int idn_send_con(int domid, idn_msgtype_t *mtp,
- idn_con_t contype, domainset_t conset);
-static void idn_retry_con(uint_t token, void *arg);
-static int idn_check_con(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_con_pend(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_error_con(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_con_sent(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_con_rcvd(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_final_con(int domid);
-static void idn_exit_con(int domid, uint_t msgtype);
-
-static int idn_send_fin(int domid, idn_msgtype_t *mtp, idn_fin_t fintype,
- idn_finarg_t finarg, idn_finopt_t finopt,
- domainset_t finset, uint_t finmaster);
-static void idn_retry_fin(uint_t token, void *arg);
-static int idn_check_fin_pend(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_fin_pend(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_error_fin_pend(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static int idn_check_fin_sent(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_fin_sent(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_error_fin_sent(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_action_fin_rcvd(int domid, idn_msgtype_t *mtp,
- idn_xdcargs_t xargs);
-static void idn_final_fin(int domid);
-static void idn_exit_fin(int domid, uint_t msgtype);
-
-/*
- * We keep a small cache of protojob structures just
- * in case allocation within idn_handler comes back
- * with nothing from the land of kmem.
- */
-idn_protojob_t idn_protojob_cache[IDN_DMV_PENDING_MAX];
-idn_protojob_t *idn_protojob_cache_list;
-kmutex_t idn_protojob_cache_lock;
-
-/*
- * - receive message.
- * - call check-function for current state.
- * - if (check-function == ok) then
- * call action-function for current state.
- * else
- * call error-function for current state.
- * - transition state based on check results.
- * - if (next state == final state) then
- * call final-function.
- */
-static idn_xphase_t xphase_nego = {
- IDNP_NEGO,
- {
- { IDNDS_NEGO_PEND,
- idn_check_nego,
- idn_action_nego_pend,
- idn_error_nego},
- { IDNDS_NEGO_SENT,
- idn_check_nego,
- idn_action_nego_sent,
- idn_error_nego},
- { IDNDS_NEGO_RCVD,
- NULL,
- idn_action_nego_rcvd,
- NULL },
- { IDNDS_CONFIG, NULL, NULL, NULL },
- },
- idn_final_nego,
- idn_exit_nego
-};
-
-static idn_xphase_t xphase_con = {
- IDNP_CON,
- {
- { IDNDS_CON_PEND,
- idn_check_con,
- idn_action_con_pend,
- idn_error_con},
- { IDNDS_CON_SENT,
- idn_check_con,
- idn_action_con_sent,
- idn_error_con},
- { IDNDS_CON_RCVD,
- NULL,
- idn_action_con_rcvd,
- NULL },
- { IDNDS_CON_READY, NULL, NULL, NULL },
- },
- idn_final_con,
- idn_exit_con
-};
-
-static idn_xphase_t xphase_fin = {
- IDNP_FIN,
- {
- { IDNDS_FIN_PEND,
- idn_check_fin_pend,
- idn_action_fin_pend,
- idn_error_fin_pend },
- { IDNDS_FIN_SENT,
- idn_check_fin_sent,
- idn_action_fin_sent,
- idn_error_fin_sent },
- { IDNDS_FIN_RCVD,
- NULL,
- idn_action_fin_rcvd,
- NULL },
- { IDNDS_DMAP, NULL, NULL, NULL },
- },
- idn_final_fin,
- idn_exit_fin
-};
-
-static int idnxs_state_table[4][5][2] = {
- { /* IDNXS_PEND */
- { IDNXS_SENT, IDNXS_PEND }, /* 0 */
- { IDNXS_RCVD, IDNXS_PEND }, /* msg */
- { IDNXS_NIL, IDNXS_PEND }, /* msg+ack */
- { IDNXS_PEND, IDNXS_NIL }, /* ack */
- { IDNXS_PEND, IDNXS_NIL }, /* nack */
- },
- { /* IDNXS_SENT */
- { IDNXS_NIL, IDNXS_NIL }, /* 0 */
- { IDNXS_RCVD, IDNXS_PEND }, /* msg */
- { IDNXS_FINAL, IDNXS_PEND }, /* msg+ack */
- { IDNXS_NIL, IDNXS_NIL }, /* ack */
- { IDNXS_PEND, IDNXS_NIL }, /* nack */
- },
- { /* IDNXS_RCVD */
- { IDNXS_NIL, IDNXS_NIL }, /* 0 */
- { IDNXS_NIL, IDNXS_NIL }, /* msg */
- { IDNXS_FINAL, IDNXS_NIL }, /* msg+ack */
- { IDNXS_FINAL, IDNXS_NIL }, /* ack */
- { IDNXS_PEND, IDNXS_NIL }, /* nack */
- },
- { /* IDNXS_FINAL */
- { IDNXS_NIL, IDNXS_NIL }, /* 0 */
- { IDNXS_NIL, IDNXS_NIL }, /* msg */
- { IDNXS_NIL, IDNXS_NIL }, /* msg+ack */
- { IDNXS_NIL, IDNXS_NIL }, /* ack */
- { IDNXS_NIL, IDNXS_NIL }, /* nack */
- }
-};
-
-/*
- * NONE Respective domain does not have a master.
- * OTHER Respective domain has a master different
- * than either local or remote.
- * LOCAL Respective domain has chosen local as master.
- * REMOTE Respective domain has chosen remote as master.
- *
- * Actions:
- * VOTE Compare votes and select one.
- * VOTE_RCFG Compare votes and Reconfigure
- * if necessary, i.e. remote won.
- * CONNECT Connect to remote's OTHER if different
- * than our local master.
- * LOCAL Local domain is winner.
- * REMOTE Remote domain is winner.
- * WAIT Wait for remote to connect to our
- * master if theirs is different.
- * ERROR An impossible condition.
- *
- * Index:
- * 0 = Local
- * 1 = Remote
- */
-static idn_master_select_t master_select_table[4][4] = {
- { /* local remote */
- MASTER_SELECT_VOTE, /* NONE NONE */
- MASTER_SELECT_CONNECT, /* NONE OTHER */
- MASTER_SELECT_LOCAL, /* NONE LOCAL */
- MASTER_SELECT_REMOTE /* NONE REMOTE */
- },
- {
- MASTER_SELECT_WAIT, /* OTHER NONE */
- MASTER_SELECT_CONNECT, /* OTHER OTHER */
- MASTER_SELECT_WAIT, /* OTHER LOCAL */
- MASTER_SELECT_WAIT /* OTHER REMOTE */
- },
- {
- MASTER_SELECT_LOCAL, /* LOCAL NONE */
- MASTER_SELECT_CONNECT, /* LOCAL OTHER */
- MASTER_SELECT_LOCAL, /* LOCAL LOCAL */
- MASTER_SELECT_VOTE_RCFG /* LOCAL REMOTE */
- },
- {
- MASTER_SELECT_REMOTE, /* REMOTE NONE */
- MASTER_SELECT_CONNECT, /* REMOTE OTHER */
- MASTER_SELECT_ERROR, /* REMOTE LOCAL */
- MASTER_SELECT_REMOTE /* REMOTE REMOTE */
- }
-};
-
-void
-idn_assign_cookie(int domid)
-{
- static ushort_t num = 0;
- ushort_t cookie;
- procname_t proc = "idn_assign_cookie";
-
- if ((cookie = idn_domain[domid].dcookie_recv) != 0)
- return;
-
- cookie = (ushort_t)(((uint64_t)&idn_domain[domid] >> 8) & 0xff);
- while ((cookie ^= num++ & 0xff) == 0)
- ;
-
- PR_PROTO("%s:%d: assigned RECV cookie 0x%x\n", proc, domid, cookie);
-
- idn_domain[domid].dcookie_recv = cookie;
-}
-
-void
-idn_update_priority(int domid, int pri)
-{
- idn_domain_t *dp;
- procname_t proc = "idn_update_priority";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
-
- if (pri >= IDNVOTE_MINPRI) {
- dp->dvote.v.priority = pri & IDNVOTE_PRI_MASK;
-
- PR_PROTO("%s:%d: SETTING PRIORITY to req(%d) "
- "(localpri = 0x%x)\n",
- proc, domid, pri, IDNVOTE_PRIVALUE(dp->dvote));
- } else {
- PR_PROTO("%s:%d: PRIORITIES UNCHANGED (pri = 0x%x)\n",
- proc, domid, IDNVOTE_PRIVALUE(dp->dvote));
- }
-}
-
-/*
- * Initiate a link between the local domain and the remote domain
- * containing the given cpuid.
- */
-int
-idn_link(int domid, int cpuid, int pri, int waittime, idnsb_error_t *sep)
-{
- int rv;
- idn_domain_t *dp;
- void *opcookie;
- procname_t proc = "idn_link";
-
- if ((cpuid < 0) || (cpuid >= NCPU)) {
- cmn_err(CE_WARN,
- "IDN: 201: (LINK) invalid CPU ID (%d)", cpuid);
- return (EINVAL);
- }
- if (waittime < 0) {
- cmn_err(CE_WARN,
- "IDN: 202: (LINK) invalid time-out value (%d)",
- waittime);
- return (EINVAL);
- }
- if (!VALID_DOMAINID(domid)) {
- cmn_err(CE_WARN,
- "IDN: 203: (LINK) invalid domain ID (%d)",
- domid);
- return (EINVAL);
- }
- if (domid == idn.localid)
- return (0);
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
-
- dp = &idn_domain[domid];
-
- switch (dp->dstate) {
- case IDNDS_CLOSED:
- break;
-
- case IDNDS_CONNECTED:
-#ifdef DEBUG
- cmn_err(CE_NOTE,
- "!IDN: domain %d (CPU ID %d) already connected",
- domid, cpuid);
-#endif /* DEBUG */
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return (0);
-
- default:
- cmn_err(CE_WARN,
- "IDN: 204: domain %d state (%s) inappropriate",
- domid, idnds_str[dp->dstate]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return (EINVAL);
- }
-
- rv = idn_open_domain(domid, cpuid, 0);
- if (rv != 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s) failed to open-domain(%d,%d)",
- proc, domid, cpuid);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return (EIO);
- }
-
-
- IDN_DLOCK_EXCL(idn.localid);
- idn_update_priority(idn.localid, pri);
- IDN_DUNLOCK(idn.localid);
-
- if (waittime > 0)
- opcookie = idn_init_op(IDNOP_CONNECTED, DOMAINSET(domid), sep);
-
- (void) idn_connect(domid);
-
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
-
- PR_PROTO("%s:%d: ALLOCATED idn_link(%d)\n", proc, domid, cpuid);
-
- if (waittime > 0) {
- boardset_t domset = 0;
- /*
- * Well we've successfully allocated a domain id,
- * but the link may not be fully established yet.
- * Need to wait since it happens asynchronously.
- */
- PR_PROTO("%s:%d: WAITING for op(%s) for (domset 0%x)...\n",
- proc, domid, idnop_str[IDNOP_CONNECTED],
- DOMAINSET(domid));
-
- rv = idn_wait_op(opcookie, &domset, waittime);
- }
-
-#ifdef DEBUG
- if (rv == 0) {
- if (waittime > 0) {
- PR_PROTO("%s:%d: connect SUCCEEDED (cpu %d)\n",
- proc, domid, cpuid);
- } else {
- PR_PROTO("%s:%d: connect KICKED OFF (cpu %d)\n",
- proc, domid, cpuid);
- }
- } else {
- PR_PROTO("%s:%d: connect FAILED (cpu %d)\n",
- proc, domid, cpuid);
- }
-#endif /* DEBUG */
-
- return (rv);
-}
-
-/*
- * Unlink the given domain from any domain cluster of
- * which it might be a member. Force indicates that domain
- * should not go AWOL and if it's currently AWOL to close
- * and remove it.
- * IMPORTANT: If the (hard) force flag is set, the caller is
- * assumed to GUARANTEE that the given domain will
- * not attempt to communicate with the local domain
- * in any manner.
- */
-int
-idn_unlink(int domid, boardset_t idnset, idn_fin_t fintype,
- idn_finopt_t finopt, int waittime, idnsb_error_t *sep)
-{
- int rv = 0;
- domainset_t domset;
- void *opcookie;
- procname_t proc = "idn_unlink";
-
-
- if (waittime < 0) {
- cmn_err(CE_WARN,
- "IDN: 202: (UNLINK) invalid time-out value (%d)",
- waittime);
- SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_WTIME);
- SET_IDNKERR_PARAM0(sep, waittime);
- return (EINVAL);
- }
- if (!VALID_DOMAINID(domid)) {
- cmn_err(CE_WARN,
- "IDN: 203: (UNLINK) invalid domain ID (%d)",
- domid);
- SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_DOMAIN);
- SET_IDNKERR_PARAM0(sep, domid);
- SET_IDNKERR_PARAM1(sep, -1);
- return (EINVAL);
- }
- if (idn.localid == IDN_NIL_DOMID) {
-#ifdef DEBUG
- cmn_err(CE_NOTE,
- "!IDN: %s: local domain not connected to an IDNnet",
- proc);
-#endif /* DEBUG */
- return (0);
- }
-
- /*
- * Lock ordering protocols requires that we grab the
- * global lock _before_ the local domain's lock.
- * However, non-local domains must have their lock
- * grabbed _before_ the global lock.
- */
- IDN_SYNC_LOCK();
- IDN_GLOCK_EXCL();
- domset = idn.domset.ds_trans_on | idn.domset.ds_trans_off;
- if ((idn.state == IDNGS_OFFLINE) && !domset) {
-#ifdef DEBUG
- cmn_err(CE_WARN,
- "!IDN: %s: local domain not connected to an IDNnet",
- proc);
-#endif /* DEBUG */
- IDN_GUNLOCK();
- IDN_SYNC_UNLOCK();
- return (0);
- }
-
- if ((domid == IDN_NIL_DOMID) || (domid == idn.localid)) {
- domid = idn.localid;
- IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- domset = DOMAINSET_ALL;
- DOMAINSET_DEL(domset, idn.localid);
- } else {
- domset = DOMAINSET(domid);
- }
- IDN_GUNLOCK();
-
- if (waittime > 0)
- opcookie = idn_init_op(IDNOP_DISCONNECTED, domset, sep);
-
- idn_unlink_domainset(domset, fintype, IDNFIN_ARG_NONE, finopt, idnset);
-
- IDN_SYNC_UNLOCK();
-
- if (waittime > 0) {
- /*
- * Well the unlink has successfully kicked off.
- * Since process is asynchronous we need to wait
- * for it to complete.
- */
- PR_PROTO("%s:%d: WAITING for op(%s) for (domset 0%x)...\n",
- proc, domid, idnop_str[IDNOP_DISCONNECTED],
- domset);
-
- rv = idn_wait_op(opcookie, &domset, waittime);
- }
-
- if (rv == 0) {
- if (waittime > 0) {
- PR_PROTO("%s:%d: disconnect SUCCEEDED\n",
- proc, domid);
- } else {
- PR_PROTO("%s:%d: disconnect KICKED OFF\n",
- proc, domid);
- }
- } else {
- PR_PROTO("%s:%d: disconnect FAILED\n", proc, domid);
- }
-
- return (rv);
-}
-
-static void
-idn_unlink_domainset(domainset_t domset, idn_fin_t fintype,
- idn_finarg_t finarg, idn_finopt_t finopt,
- boardset_t idnset)
-{
- int d;
- domainset_t offset;
- procname_t proc = "idn_unlink_domainset";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
-
- /*
- * Determine subset for which we have
- * no active connections.
- */
- offset = domset & ~(idn.domset.ds_trans_on |
- idn.domset.ds_connected |
- idn.domset.ds_trans_off |
- idn.domset.ds_relink);
- /*
- * Determine subset that are really candidates.
- * Note that we include those already down the path
- * since it's possible a request came in to upgrade
- * their fintype (e.g. NORMAL->FORCE_SOFT).
- */
- domset &= ~offset;
-
- if (offset)
- idn_update_op(IDNOP_DISCONNECTED, offset, NULL);
-
- IDN_GLOCK_EXCL();
- if ((finopt == IDNFIN_OPT_RELINK) && (idn.state != IDNGS_DISCONNECT)) {
- /*
- * Don't add domains already transitioning off.
- * If they caught on an earlier Reconfig wave then
- * they'll already be in ds_relink anyway. Otherwise,
- * once a domain is transition off we can't upgrade
- * him to a RELINK.
- */
-#ifdef DEBUG
- if (idn.domset.ds_hitlist & domset) {
- PR_HITLIST("%s: domset=%x, hitlist=%x, trans_off=%x "
- "-> relink = %x -> %x\n",
- proc, domset, idn.domset.ds_hitlist,
- idn.domset.ds_relink, idn.domset.ds_trans_off,
- idn.domset.ds_relink |
- (domset & ~idn.domset.ds_trans_off));
- }
-#endif /* DEBUG */
-
- domset &= ~idn.domset.ds_trans_off;
- idn.domset.ds_relink |= domset;
- } else {
- idn.domset.ds_relink &= ~domset;
- }
- /*
- * Update the ds_trans_on/off so we don't waste
- * time talking to these folks.
- */
- idn.domset.ds_trans_on &= ~domset;
- idn.domset.ds_trans_off |= domset;
-
- if (domset == 0) {
- if ((idn.domset.ds_trans_on |
- idn.domset.ds_connected |
- idn.domset.ds_trans_off |
- idn.domset.ds_relink) == 0) {
- PR_HITLIST("%s:%x: HITLIST %x -> 0\n",
- proc, domset, idn.domset.ds_hitlist);
- idn.domset.ds_hitlist = 0;
- IDN_GSTATE_TRANSITION(IDNGS_OFFLINE);
- }
- IDN_GUNLOCK();
- return;
- }
- IDN_GUNLOCK();
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- idn_domain_t *dp;
- idn_fin_t ftype;
-
- if (!DOMAIN_IN_SET(domset, d))
- continue;
-
- dp = &idn_domain[d];
- IDN_DLOCK_EXCL(d);
- IDN_HISTORY_LOG(IDNH_RELINK, d, dp->dstate,
- idn.domset.ds_relink);
- ftype = fintype;
- if ((dp->dcpu != IDN_NIL_DCPU) && dp->dhw.dh_boardset) {
- /*
- * If domain is not in the IDNSET passed
- * down then we need to upgrade this to
- * hard-force in order to prevent possible
- * system failures (arbstop). This is simply
- * extra protection beyond that checked by
- * the SSP. IDNSET contains the set of boards
- * that have a "link" to the local domain,
- * including the SMD regs.
- */
- if ((idnset & dp->dhw.dh_boardset) == 0) {
- PR_PROTO("%s:%d: boardset 0x%x "
- "NOT in IDNSET 0x%x\n",
- proc, d, dp->dhw.dh_boardset,
- idnset);
- if (ftype != IDNFIN_FORCE_HARD)
- cmn_err(CE_NOTE,
- "!IDN: 222: no IDN linkage "
- "found (b=0x%x, i=0x%x) "
- "upgrading unlink %s to %s",
- dp->dhw.dh_boardset,
- idnset, idnfin_str[ftype],
- idnfin_str[IDNFIN_FORCE_HARD]);
-
- ftype = IDNFIN_FORCE_HARD;
- } else {
- PR_PROTO("%s:%d: boardset 0x%x "
- "FOUND in IDNSET 0x%x\n",
- proc, d, dp->dhw.dh_boardset,
- idnset);
- }
- }
- (void) idn_disconnect(d, ftype, finarg, IDNDS_SYNC_TYPE(dp));
- IDN_DUNLOCK(d);
- }
-}
-
-/*
- * Return w/locks held.
- */
-static int
-idn_connect(int domid)
-{
- idn_xdcargs_t xargs;
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_connect";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- ASSERT(dp->dcpu != IDN_NIL_DCPU);
-
- if (dp->dstate != IDNDS_CLOSED) {
- if (DOMAIN_IN_SET(idn.domset.ds_trans_on |
- idn.domset.ds_connected, domid)) {
- PR_PROTO("%s:%d: already connected or "
- "in-progress\n", proc, domid);
- } else {
- PR_PROTO("%s:%d: current state (%s) != "
- "CLOSED\n", proc, domid,
- idnds_str[dp->dstate]);
- }
- return (-1);
- }
-
- ASSERT(!DOMAIN_IN_SET(idn.domset.ds_connected, domid));
- ASSERT(!DOMAIN_IN_SET(idn.domset.ds_trans_off, domid));
-
- dp->dxp = &xphase_nego;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
-
- (void) idn_xphase_transition(domid, NULL, xargs);
-
- return (0);
-}
-
-/*
- * Return w/locks held.
- */
-static int
-idn_disconnect(int domid, idn_fin_t fintype, idn_finarg_t finarg,
- idn_finsync_t finsync)
-{
- int new_masterid, new_cpuid = IDN_NIL_DCPU;
- uint_t token;
- uint_t finmaster;
- idn_xdcargs_t xargs;
- idn_finopt_t finopt;
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_disconnect";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (dp->dstate == IDNDS_CLOSED) {
- PR_PROTO("%s:%d: already CLOSED\n", proc, domid);
- idn_update_op(IDNOP_DISCONNECTED, DOMAINSET(domid), NULL);
- return (-1);
- }
-
- /*
- * Terminate any outstanding commands that were
- * targeted towards this domain.
- */
- idn_terminate_cmd(domid, ECANCELED);
-
- /*
- * Terminate any and all retries that may have
- * outstanding for this domain.
- */
- token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL);
- (void) idn_retry_terminate(token);
-
- /*
- * Stop all outstanding message timers for
- * this guy.
- */
- IDN_MSGTIMER_STOP(domid, 0, 0);
-
- dp->dxp = &xphase_fin;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- if ((int)dp->dfin < (int)fintype) {
- /*
- * You can only upgrade a fin type.
- * We don't allow it to be downgraded
- * as it's too dangerous since some
- * state may have been blown away while
- * we were fin'ing at a higher level.
- */
- IDN_FSTATE_TRANSITION(dp, fintype);
- }
-
- dp->dfin_sync = finsync;
- PR_PROTO("%s:%d: disconnect synchronously = %s\n",
- proc, domid, (finsync == IDNFIN_SYNC_OFF) ? "OFF" :
- (finsync == IDNFIN_SYNC_NO) ? "NO" : "YES");
-
- IDN_GLOCK_SHARED();
- if (DOMAIN_IN_SET(idn.domset.ds_relink, domid) &&
- (idn.state != IDNGS_DISCONNECT)) {
- finopt = IDNFIN_OPT_RELINK;
- } else {
- finopt = IDNFIN_OPT_UNLINK;
- PR_HITLIST("%s:%d: HITLIST %x -> %x\n",
- proc, domid, idn.domset.ds_hitlist,
- idn.domset.ds_hitlist | DOMAINSET(domid));
- DOMAINSET_ADD(idn.domset.ds_hitlist, domid);
- }
-
- CLR_XARGS(xargs);
- SET_XARGS_FIN_TYPE(xargs, dp->dfin);
- SET_XARGS_FIN_ARG(xargs, finarg);
- SET_XARGS_FIN_OPT(xargs, finopt);
- SET_XARGS_FIN_DOMSET(xargs, 0); /* unused when msg = 0 */
- new_masterid = IDN_GET_NEW_MASTERID();
- IDN_GUNLOCK();
- if (new_masterid != IDN_NIL_DOMID)
- new_cpuid = idn_domain[new_masterid].dcpu;
- finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid);
- SET_XARGS_FIN_MASTER(xargs, finmaster);
-
- (void) idn_xphase_transition(domid, NULL, xargs);
-
- return (0);
-}
-
-static int
-idn_next_xstate(idn_xstate_t o_xstate, int err, uint_t msg)
-{
- int index;
- procname_t proc = "idn_next_xstate";
-
- ASSERT(((int)o_xstate >= 0) && ((int)o_xstate <= 4));
-
- if (!msg)
- index = 0;
- else if ((msg & IDNP_MSGTYPE_MASK) == 0)
- index = (msg & IDNP_ACK) ? 3 : (msg & IDNP_NACK) ? 4 : -1;
- else
- index = (msg & IDNP_ACK) ? 2 :
- !(msg & IDNP_ACKNACK_MASK) ? 1 : -1;
-
- if (index == -1) {
- STRING(str);
-
- INUM2STR(msg, str);
- PR_PROTO("%s: (msg = 0x%x(%s))\n", proc, msg, str);
- return (IDNXS_NIL);
- }
-
- if (err == -1) {
- int n_xstate;
- /*
- * Caller is just interested in querying is this
- * is a valid message to receive in the current
- * xstate. A return value of IDNXS_NIL indicates
- * that it's not. A return value of non-IDNXS_NIL
- * indicates it's cool. An invalid message is
- * determined by both err & !err states being IDNXS_NIL.
- */
- n_xstate = idnxs_state_table[(int)o_xstate][index][0];
- if (n_xstate != IDNXS_NIL)
- return (n_xstate);
- else
- return (idnxs_state_table[(int)o_xstate][index][1]);
- } else {
- return (idnxs_state_table[(int)o_xstate][index][err ? 1 : 0]);
- }
-}
-
-static int
-idn_select_candidate(domainset_t master_set)
-{
- int d, best_id = IDN_NIL_DOMID;
- uint_t best_vote = 0;
- idn_domain_t *dp;
- procname_t proc = "idn_select_candidate";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
-
- if (master_set == 0) {
- PR_PROTO("%s: %x -> %d\n", proc, master_set, IDN_NIL_DOMID);
- return (IDN_NIL_DOMID);
- }
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- uint_t vote;
- idn_vote_t v;
-
- if (!DOMAIN_IN_SET(master_set, d))
- continue;
-
- dp = &idn_domain[d];
-
- if ((dp->domid == IDN_NIL_DOMID) ||
- (dp->dcpu == IDN_NIL_DCPU) ||
- ((v.ticket = dp->dvote.ticket) == 0))
- continue;
-
- vote = IDNVOTE_ELECT(v);
-
- if (vote > best_vote) {
- best_vote = vote;
- best_id = d;
- }
- }
-
- PR_PROTO("%s: %x -> %d\n", proc, master_set, best_id);
-
- return (best_id);
-}
-
-/*
- * If a non-zero value is returned then GLOCK will have been dropped.
- * Otherwise, routine returns with all incoming locks still held.
- */
-static int
-idn_select_master(int domid, int rmasterid, int rcpuid)
-{
- char *sel;
- int lmasterid, masterid;
- int do_reconfig = 0;
- int lindex, rindex;
- idn_domain_t *ldp, *rdp;
- uint_t rvote, lvote;
- idn_master_select_t select;
- procname_t proc = "idn_select_master";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_GLOCK_IS_EXCL());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- PR_PROTO("%s:%d: lmasterid = %d, rmasterid = %d, rcpuid = %d\n",
- proc, domid, IDN_GET_MASTERID(), rmasterid, rcpuid);
-
- IDN_DLOCK_EXCL(idn.localid);
-
- ldp = &idn_domain[idn.localid];
- rdp = &idn_domain[domid];
-
- /*
- * Clear master bits since mastership is derived from
- * other information (local/remote idn.masterid/idn.new_masterid)
- * and we don't want the vote master bit to confuse matters.
- */
- lvote = IDNVOTE_ELECT(ldp->dvote);
- rvote = IDNVOTE_ELECT(rdp->dvote);
-
- lmasterid = IDN_GET_MASTERID();
-
- lindex = (lmasterid == IDN_NIL_DOMID) ? MASTER_IS_NONE :
- (lmasterid == idn.localid) ? MASTER_IS_LOCAL :
- (lmasterid == domid) ? MASTER_IS_REMOTE :
- MASTER_IS_OTHER;
-
- rindex = (rmasterid == IDN_NIL_DOMID) ? MASTER_IS_NONE :
- (rmasterid == domid) ? MASTER_IS_REMOTE :
- (rmasterid == idn.localid) ? MASTER_IS_LOCAL :
- MASTER_IS_OTHER;
-
- select = master_select_table[lindex][rindex];
-
- masterid = IDN_NIL_DOMID;
-
- /*
- * Each case is responsible for dropping DLOCK(localid)
- * and GLOCK if it doesn't select a master, unless a
- * reconfig is necessary.
- */
- switch (select) {
- case MASTER_SELECT_VOTE_RCFG:
- sel = "VOTE_RECONFIG";
- if (lvote > rvote) {
- /*
- * If the local domain is the winner then remote
- * domain will have to Reconfig. We'll continue
- * through the connection process anyway. The
- * remote domains will tell us to back-off while
- * Reconfigs, but that's okay as we'll keep retrying.
- */
- masterid = idn.localid;
- } else if (lvote < rvote) {
- do_reconfig = 1;
- /*
- * GLOCK will get dropped once reconfig
- * is kicked off.
- */
- } else {
- cmn_err(CE_WARN,
- "IDN: 206: cannot link domains "
- "with equal votes (L(%d),R(%d),0x%x)",
- idn.localid, domid, rvote);
- IDN_GUNLOCK();
- }
- IDN_DUNLOCK(idn.localid);
- break;
-
- case MASTER_SELECT_VOTE:
- sel = "VOTE";
- if (lvote > rvote) {
- masterid = idn.localid;
- ldp->dvote.v.master = 1;
- rdp->dvote.v.master = 0;
- } else if (lvote < rvote) {
- masterid = domid;
- ldp->dvote.v.master = 0;
- rdp->dvote.v.master = 1;
- } else {
- cmn_err(CE_WARN,
- "IDN: 206: cannot link domains "
- "with equal votes (L(%d),R(%d),0x%x)",
- idn.localid, domid, rvote);
- }
- ASSERT(IDN_GET_MASTERID() == IDN_NIL_DOMID);
- if (masterid != IDN_NIL_DOMID) {
- IDN_SET_MASTERID(masterid);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- } else {
- IDN_GUNLOCK();
- }
- IDN_DUNLOCK(idn.localid);
- break;
-
- case MASTER_SELECT_REMOTE:
- sel = "REMOTE";
- masterid = domid;
- if (IDN_GET_MASTERID() == IDN_NIL_DOMID) {
- IDN_SET_MASTERID(masterid);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- ldp->dvote.v.master = 0;
- rdp->dvote.v.master = 1;
- }
- ASSERT(IDN_GET_MASTERID() == domid);
- IDN_DUNLOCK(idn.localid);
- break;
-
- case MASTER_SELECT_LOCAL:
- sel = "LOCAL";
- masterid = idn.localid;
- if (IDN_GET_MASTERID() == IDN_NIL_DOMID) {
- IDN_SET_MASTERID(masterid);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- ldp->dvote.v.master = 1;
- rdp->dvote.v.master = 0;
- }
- ASSERT(IDN_GET_MASTERID() == idn.localid);
- IDN_DUNLOCK(idn.localid);
- break;
-
- case MASTER_SELECT_CONNECT:
- sel = "CONNECT";
- if (rmasterid == lmasterid) {
- /*
- * Local and remote have same master,
- * let him come onboard.
- */
- masterid = lmasterid;
- IDN_DUNLOCK(idn.localid);
-
- } else {
- int rv;
-
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
- IDN_DLOCK_EXCL(rmasterid);
- PR_PROTO("%s:%d: attempting connect w/remote "
- "master %d\n",
- proc, domid, rmasterid);
- rv = idn_open_domain(rmasterid, rcpuid, 0);
- if (rv == 0) {
- (void) idn_connect(rmasterid);
- } else if (rv < 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s) failed to "
- "open-domain(%d,%d)",
- proc, rmasterid, rcpuid);
- } else {
- /*
- * Must already have a connection going.
- */
- PR_PROTO("%s:%d: failed "
- "idn_open_domain(%d,%d,0) "
- "(rv = %d)\n",
- proc, domid, rmasterid,
- rcpuid, rv);
- }
- IDN_DUNLOCK(rmasterid);
- }
- break;
-
- case MASTER_SELECT_WAIT:
- sel = "WAIT";
- /*
- * If the remote domain has the same master as the local
- * domain then there's no need to wait.
- */
- if (rmasterid == lmasterid) {
- masterid = lmasterid;
- } else {
- IDN_GUNLOCK();
- }
- IDN_DUNLOCK(idn.localid);
- break;
-
- case MASTER_SELECT_ERROR:
- sel = "ERROR";
- /*
- * Hit impossible condition.
- */
- cmn_err(CE_WARN,
- "IDN: 207: local/remote master-id conflict "
- "(%d.lmasterid = %d, %d.rmasterid = %d)",
- idn.localid, lmasterid, domid, rmasterid);
- IDN_GUNLOCK();
- IDN_DUNLOCK(idn.localid);
- break;
-
- default:
- cmn_err(CE_WARN,
- "IDN: 208: %s: unknown case (%d)",
- proc, (int)select);
- IDN_GUNLOCK();
- IDN_DUNLOCK(idn.localid);
- ASSERT(0);
- break;
- }
-
- if (masterid == IDN_NIL_DOMID) {
- PR_PROTO("%s:%d: NO MASTER SELECTED (rmstr=%d) sel=%s\n",
- proc, domid, rmasterid, sel);
- } else {
- PR_PROTO("%s:%d: MASTER SELECTED = %d (%s)\n",
- proc, domid, masterid,
- (masterid == idn.localid) ? "LOCAL" :
- (masterid == domid) ? "REMOTE" : "OTHER");
- }
-
- if (do_reconfig) {
- domainset_t dis_set;
-
- /*
- * Local domain already has a master.
- * Need to dismantle all connections
- * and reestablish one with new master.
- */
- IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs, gk_reconfig_last);
-
- PR_PROTO("%s:%d: RECONFIG new masterid = %d\n",
- proc, domid, domid);
-
- IDN_GSTATE_TRANSITION(IDNGS_RECONFIG);
- IDN_SET_NEW_MASTERID(domid);
- IDN_GUNLOCK();
-
- dis_set = idn.domset.ds_trans_on | idn.domset.ds_connected;
- DOMAINSET_DEL(dis_set, domid);
-
- idn_unlink_domainset(dis_set, IDNFIN_NORMAL, IDNFIN_ARG_NONE,
- IDNFIN_OPT_RELINK, BOARDSET_ALL);
- }
-
- return ((masterid == IDN_NIL_DOMID) ? -1 : 0);
-}
-
-/*ARGSUSED1*/
-static void
-idn_retry_query(uint_t token, void *arg)
-{
- idn_retry_t rtype = IDN_RETRY_TOKEN2TYPE(token);
- int d, domid = IDN_RETRY_TOKEN2DOMID(token);
- idn_domain_t *dp = &idn_domain[domid];
- idn_synccmd_t sync_cmd;
- domainset_t query_set, my_ready_set;
- procname_t proc = "idn_retry_query";
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
-
- switch (rtype) {
- case IDNRETRY_CONQ:
- sync_cmd = IDNSYNC_CONNECT;
- my_ready_set = idn.domset.ds_ready_on | idn.domset.ds_connected;
- my_ready_set &= ~idn.domset.ds_trans_off;
- DOMAINSET_ADD(my_ready_set, idn.localid);
- break;
-
- case IDNRETRY_FINQ:
- sync_cmd = IDNSYNC_DISCONNECT;
- my_ready_set = idn.domset.ds_ready_off |
- ~idn.domset.ds_connected;
- break;
-
- default:
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- if (dp->dsync.s_cmd == sync_cmd)
- my_ready_set |= dp->dsync.s_set_rdy;
-
- query_set = idn_sync_register(domid, sync_cmd, 0, IDNSYNC_REG_QUERY);
-
- PR_PROTO("%s:%d: query_set = 0x%x\n", proc, domid, query_set);
-
- if (query_set == 0) {
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(query_set, d))
- continue;
-
- dp = &idn_domain[d];
- if (d != domid)
- IDN_DLOCK_EXCL(d);
-
- if ((dp->dsync.s_cmd == sync_cmd) ||
- (!dp->dcookie_send &&
- (rtype == IDNRETRY_CONQ))) {
- if (d != domid)
- IDN_DUNLOCK(d);
- continue;
- }
-
- IDN_SYNC_QUERY_UPDATE(domid, d);
-
- if (rtype == IDNRETRY_CONQ)
- (void) idn_send_con(d, NULL, IDNCON_QUERY,
- my_ready_set);
- else
- (void) idn_send_fin(d, NULL, IDNFIN_QUERY,
- IDNFIN_ARG_NONE, IDNFIN_OPT_NONE, my_ready_set,
- NIL_FIN_MASTER);
- if (d != domid)
- IDN_DUNLOCK(d);
- }
-
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
-}
-
-static int
-idn_send_nego(int domid, idn_msgtype_t *mtp, domainset_t conset)
-{
- idn_domain_t *ldp, *dp;
- int d, masterid;
- uint_t dmask;
- uint_t acknack;
- uint_t ticket;
- idnneg_dset_t dset;
- idn_msgtype_t mt;
- procname_t proc = "idn_send_nego";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (mtp) {
- acknack = mtp->mt_mtype & IDNP_ACKNACK_MASK;
- mt.mt_mtype = mtp->mt_mtype;
- mt.mt_atype = mtp->mt_atype;
- mt.mt_cookie = mtp->mt_cookie;
- } else {
- acknack = 0;
- mt.mt_mtype = IDNP_NEGO;
- mt.mt_atype = 0;
- mt.mt_cookie = IDN_TIMER_PUBLIC_COOKIE;
- }
-
- IDN_GLOCK_SHARED();
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- if ((idn.state == IDNGS_RECONFIG) ||
- ((masterid = IDN_GET_MASTERID()) == IDN_NIL_DOMID)) {
- masterid = IDN_GET_NEW_MASTERID();
- if ((masterid == idn.localid) || (masterid == domid)) {
- /*
- * We only send the new-master "hint" to
- * "other" domains. If the new-master is
- * ourself or we're talking to the new-master
- * then we need to be accurate about our
- * real master so that the correct master
- * is selected.
- */
- masterid = IDN_NIL_DOMID;
- }
- }
-
- DOMAINSET_DEL(conset, idn.localid);
- DOMAINSET_DEL(conset, domid);
- /*
- * Exclude domains from conset that are on
- * remote domain's hitlist. He's not interested
- * in hearing about them. SSP is probably requesting
- * such domains be unlinked - will eventually get to
- * local domain.
- */
- conset &= ~idn.domset.ds_hitlist;
- if ((masterid != IDN_NIL_DOMID) &&
- DOMAIN_IN_SET(idn.domset.ds_hitlist, masterid)) {
- PR_PROTO("%s:%d: masterid(%d) on hitlist(0x%x) -> -1\n",
- proc, domid, masterid, idn.domset.ds_hitlist);
- /*
- * Yikes, our chosen master is on the hitlist!
- */
- masterid = IDN_NIL_DOMID;
- }
-
- dmask = IDNNEG_DSET_MYMASK();
- IDNNEG_DSET_INIT(dset, dmask);
- for (d = 0; d < MAX_DOMAINS; d++) {
- int cpuid;
-
- if (!DOMAIN_IN_SET(conset, d))
- continue;
-
- if ((cpuid = idn_domain[d].dcpu) == IDN_NIL_DCPU) {
- ASSERT(d != masterid);
- continue;
- }
-
- IDNNEG_DSET_SET(dset, d, cpuid, dmask);
- }
- IDNNEG_DSET_SET_MASTER(dset, domid, masterid);
- ASSERT((masterid != IDN_NIL_DOMID) ?
- (idn_domain[masterid].dcpu != IDN_NIL_DCPU) : 1);
- IDN_GUNLOCK();
-
- IDN_DLOCK_SHARED(idn.localid);
- ticket = IDNVOTE_BASICS(ldp->dvote);
- /*
- * We just want to send basic vote components without an
- * indication of mastership (master bit) since that's primarily
- * for local domain's usage. There is more correct master
- * indications in the DSET. Recall that if we were in a
- * Reconfig we would have transmitted the "new_masterid"
- * which might conflict with the local domain's vote.v.master
- * bit if he was originally the master prior to the Reconfig.
- */
-
- PR_PROTO("%s:%d: sending nego%sto (cpu %d) "
- "[v=0x%x, cs=0x%x, mstr=%d]\n",
- proc, domid,
- (acknack & IDNP_ACK) ? "+ack " :
- (acknack & IDNP_NACK) ? "+nack " : " ",
- dp->dcpu, ticket, conset, masterid);
-
- IDN_MSGTIMER_START(domid, IDNP_NEGO, 0,
- idn_msg_waittime[IDNP_NEGO], &mt.mt_cookie);
-
- IDNXDC(domid, &mt, ticket, dset[0], dset[1], dset[2]);
-
- IDN_DUNLOCK(idn.localid);
-
- return (0);
-}
-
-static int
-idn_recv_nego(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs,
- ushort_t dcookie)
-{
- uint_t msg = mtp->mt_mtype;
- idn_msgtype_t mt;
- idn_domain_t *dp = &idn_domain[domid];
- idn_xdcargs_t nargs;
- procname_t proc = "idn_recv_nego";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- mt.mt_cookie = mtp->mt_cookie;
-
-#ifdef DEBUG
- if (DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) {
- PR_HITLIST("%s:%d: dcpu=%d, dstate=%s, msg=%x, "
- "hitlist=%x\n",
- proc, domid, dp->dcpu, idnds_str[dp->dstate],
- msg, idn.domset.ds_hitlist);
- }
-#endif /* DEBUG */
-
- if (dp->dcpu == IDN_NIL_DCPU) {
- int cpuid;
- uint_t ticket;
- /*
- * Brandnew link. Need to open a new domain entry.
- */
- ticket = GET_XARGS_NEGO_TICKET(xargs);
- cpuid = dp->dcpu_last;
- ASSERT(VALID_CPUID(cpuid));
-
- if (idn_open_domain(domid, cpuid, ticket) != 0) {
- PR_PROTO("%s:%d: FAILED to open doamin "
- "(ticket = 0x%x)\n",
- proc, domid, ticket);
- return (-1);
- }
- }
-
- if ((msg & IDNP_MSGTYPE_MASK) == IDNP_NEGO) {
- PR_PROTO("%s:%d: assigned SEND cookie 0x%x\n",
- proc, domid, dcookie);
- dp->dcookie_send = dcookie;
- }
-
- if ((dp->dxp == NULL) && IDNDS_IS_CLOSED(dp)) {
- dp->dxp = &xphase_nego;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- } else if (dp->dxp != &xphase_nego) {
- if (msg & IDNP_MSGTYPE_MASK) {
- /*
- * If we already have a connection to somebody
- * trying to initiate a connection to us, then
- * possibly we've awaken from a coma or he did.
- * In any case, dismantle current connection
- * and attempt to establish a new one.
- */
- if (dp->dstate == IDNDS_CONNECTED) {
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid,
- dp->dstate, idn.domset.ds_relink);
- (void) idn_disconnect(domid, IDNFIN_NORMAL,
- IDNFIN_ARG_NONE, IDNFIN_SYNC_YES);
- } else {
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
-
- CLR_XARGS(nargs);
-
- if (DOMAIN_IN_SET(idn.domset.ds_hitlist,
- domid)) {
- SET_XARGS_NACK_TYPE(nargs,
- IDNNACK_EXIT);
- } else {
- int new_masterid;
- int new_cpuid = IDN_NIL_DCPU;
-
- SET_XARGS_NACK_TYPE(nargs,
- IDNNACK_RETRY);
- IDN_GLOCK_SHARED();
- new_masterid = IDN_GET_NEW_MASTERID();
- if (new_masterid == IDN_NIL_DOMID)
- new_masterid =
- IDN_GET_MASTERID();
- if (new_masterid != IDN_NIL_DOMID) {
- idn_domain_t *mdp;
-
- mdp = &idn_domain[new_masterid];
- new_cpuid = mdp->dcpu;
- }
- SET_XARGS_NACK_ARG1(nargs,
- new_masterid);
- SET_XARGS_NACK_ARG2(nargs, new_cpuid);
- IDN_GUNLOCK();
- }
- idn_send_acknack(domid, &mt, nargs);
- }
- }
- return (0);
- }
-
- (void) idn_xphase_transition(domid, mtp, xargs);
-
- return (0);
-}
-
-/*ARGSUSED1*/
-static void
-idn_retry_nego(uint_t token, void *arg)
-{
- int domid = IDN_RETRY_TOKEN2DOMID(token);
- int new_masterid;
- idn_domain_t *dp = &idn_domain[domid];
- idn_xdcargs_t xargs;
- procname_t proc = "idn_retry_nego";
-
- ASSERT(IDN_RETRY_TOKEN2TYPE(token) == IDNRETRY_NEGO);
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
-
- if (dp->dxp != &xphase_nego) {
- STRING(str);
-
-#ifdef DEBUG
- if (dp->dxp) {
- INUM2STR(dp->dxp->xt_msgtype, str);
- }
-#endif /* DEBUG */
-
- PR_PROTO("%s:%d: dxp(%s) != NEGO...bailing...\n",
- proc, domid, dp->dxp ? str : "NULL");
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- if (dp->dxstate != IDNXS_PEND) {
- PR_PROTO("%s:%d: xstate(%s) != %s...bailing\n",
- proc, domid, idnxs_str[dp->dxstate],
- idnxs_str[IDNXS_PEND]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- IDN_GLOCK_SHARED();
- if (idn.state == IDNGS_RECONFIG) {
- /*
- * Have to try again later after
- * reconfig has completed.
- */
- PR_PROTO("%s:%d: reconfig in-progress...try later\n",
- proc, domid);
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[IDNP_NEGO]);
- IDN_GUNLOCK();
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
- new_masterid = IDN_GET_NEW_MASTERID();
- if ((idn.state == IDNGS_CONNECT) &&
- (new_masterid != IDN_NIL_DOMID) &&
- (domid != new_masterid) &&
- (idn.localid != new_masterid)) {
- /*
- * We have a new master pending and this
- * guy isn't it. Wait until the local domain
- * has a chance to connect with the new
- * master before going forward with this
- * guy.
- */
- PR_PROTO("%s:%d: waiting for connect to new master %d\n",
- proc, domid, IDN_GET_NEW_MASTERID());
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[IDNP_NEGO]);
- IDN_GUNLOCK();
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
- IDN_GUNLOCK();
-
- (void) idn_xphase_transition(domid, NULL, xargs);
-
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
-}
-
-static int
-idn_check_nego(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- int d, new_masterid, masterid;
- int cpuid, m_cpuid = -1;
- uint_t dmask;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_domain_t *dp, *ldp;
- domainset_t con_set, pending_set;
- idnneg_dset_t dset;
- procname_t proc = "idn_check_nego";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- if (msg & IDNP_NACK) {
- if (GET_XARGS_NACK_TYPE(xargs) == IDNNACK_EXIT) {
- PR_HITLIST("%s:%d(%s): (msg=%x) EXIT received, "
- "adding to hitlist %x -> %x\n",
- proc, domid, idnds_str[dp->dstate], msg,
- idn.domset.ds_hitlist,
- idn.domset.ds_hitlist | DOMAINSET(domid));
-
- DOMAINSET_ADD(idn.domset.ds_hitlist, domid);
- return (-1);
- } else {
- return (0);
- }
- }
-
- if (DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) {
- PR_HITLIST("%s:%d(%s): (msg=%x) domain in hitlist (%x) - "
- "exiting phase\n",
- proc, domid, idnds_str[dp->dstate], msg,
- idn.domset.ds_hitlist);
- return (-1);
- }
-
- if ((dp->dstate == IDNDS_NEGO_PEND) && (msg & IDNP_MSGTYPE_MASK) &&
- (msg & IDNP_ACK)) /* nego+ack */
- return (1);
-
- dmask = (uint_t)-1;
-
- IDN_GLOCK_EXCL();
- if (idn.state == IDNGS_DISCONNECT) {
- PR_PROTO("%s:%d: DISCONNECT in-progress >>> EXIT\n",
- proc, domid);
- IDN_GUNLOCK();
- return (-1);
- } else if (idn.state == IDNGS_OFFLINE) {
- IDN_GSTATE_TRANSITION(IDNGS_CONNECT);
- IDN_PREP_HWINIT();
- IDN_DLOCK_EXCL(idn.localid);
- ldp->dvote.v.connected = 0;
- IDN_DUNLOCK(idn.localid);
- }
-
- if (!DOMAIN_IN_SET(idn.domset.ds_trans_on, domid)) {
- DOMAINSET_ADD(idn.domset.ds_trans_on, domid);
- IDN_HISTORY_LOG(IDNH_NEGO, domid,
- idn.domset.ds_trans_on,
- idn.domset.ds_connected);
- }
-
- switch (idn.state) {
- case IDNGS_RECONFIG:
- PR_PROTO("%s:%d: RECONFIG in-progress >>> RETRY\n",
- proc, domid);
- IDN_GUNLOCK();
- return (1);
-
- case IDNGS_CONNECT:
- new_masterid = IDN_GET_NEW_MASTERID();
- if ((new_masterid != IDN_NIL_DOMID) &&
- (domid != new_masterid) &&
- (idn.localid != new_masterid)) {
- PR_PROTO("%s:%d: waiting for connect to "
- "new master %d\n",
- proc, domid, IDN_GET_NEW_MASTERID());
- IDN_GUNLOCK();
- return (1);
- }
- break;
-
- default:
- break;
- }
-
- ASSERT((idn.state == IDNGS_CONNECT) || (idn.state == IDNGS_ONLINE));
-
- con_set = 0;
-
- if (msg) {
- idn_domain_t *mdp;
- idn_vote_t vote;
-
- vote.ticket = GET_XARGS_NEGO_TICKET(xargs);
- /*
- * Sender should note have set master bit,
- * but just in case clear it so local domain
- * doesn't get confused.
- */
- vote.v.master = 0;
- dp->dvote.ticket = vote.ticket;
- GET_XARGS_NEGO_DSET(xargs, dset);
- /*LINTED*/
- IDNNEG_DSET_GET_MASK(dset, domid, dmask);
- IDNNEG_DSET_GET_MASTER(dset, new_masterid);
- if (new_masterid == IDNNEG_NO_MASTER) {
- new_masterid = IDN_NIL_DOMID;
- } else {
- /*
- * Remote domain has a master. Find
- * his cpuid in the dset. We may need
- * it to initiate a connection.
- */
- if (new_masterid == domid) {
- m_cpuid = dp->dcpu;
- } else {
- IDNNEG_DSET_GET(dset, new_masterid, m_cpuid,
- dmask);
- if (m_cpuid == -1) {
- /*
- * Something is bogus if remote domain
- * is reporting a valid masterid, but
- * doesn't have the cpuid for it.
- */
- cmn_err(CE_WARN,
- "IDN: 209: remote domain (ID "
- "%d, CPU %d) reporting master "
- "(ID %d) without CPU ID",
- domid, dp->dcpu, new_masterid);
- DOMAINSET_ADD(idn.domset.ds_hitlist,
- domid);
- IDN_GUNLOCK();
- return (-1);
- }
- }
- }
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- if ((d == idn.localid) || (d == domid))
- continue;
- IDNNEG_DSET_GET(dset, d, cpuid, dmask);
- if (cpuid != -1) {
- DOMAINSET_ADD(con_set, d);
- }
- }
-
-#ifdef DEBUG
- if (idn.domset.ds_hitlist) {
- PR_HITLIST("%s:%d: con_set %x -> %x (hitlist = %x)\n",
- proc, domid, con_set,
- con_set & ~idn.domset.ds_hitlist,
- idn.domset.ds_hitlist);
- }
-#endif /* DEBUG */
-
- con_set &= ~idn.domset.ds_hitlist;
-
- ASSERT(!DOMAIN_IN_SET(con_set, idn.localid));
- ASSERT(!DOMAIN_IN_SET(con_set, domid));
-
- if ((new_masterid != IDN_NIL_DOMID) &&
- DOMAIN_IN_SET(idn.domset.ds_hitlist, new_masterid)) {
- PR_HITLIST("%s:%d: new_mstr %d -> -1 (hitlist = %x)\n",
- proc, domid, new_masterid,
- idn.domset.ds_hitlist);
- IDN_GUNLOCK();
- return (1);
- }
-
- if (idn_select_master(domid, new_masterid, m_cpuid) < 0) {
- /*
- * Returns w/GLOCK dropped if error.
- */
- return (1);
- }
-
- masterid = IDN_GET_MASTERID();
- ASSERT(masterid != IDN_NIL_DOMID);
-
- if (idn.state == IDNGS_CONNECT) {
- /*
- * This is the initial connection for
- * the local domain.
- */
- IDN_DLOCK_EXCL(idn.localid);
-
- if (masterid == idn.localid) {
- if (idn_master_init() < 0) {
- cmn_err(CE_WARN,
- "IDN: 210: failed to init "
- "MASTER context");
- ldp->dvote.v.master = 0;
- IDN_DUNLOCK(idn.localid);
- IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT);
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- IDN_GUNLOCK();
- return (-1);
- }
- DSLAB_LOCK_EXCL(idn.localid);
- ldp->dslab_state = DSLAB_STATE_LOCAL;
- DSLAB_UNLOCK(idn.localid);
- ldp->dvote.v.connected = 1;
- } else {
- /*
- * Either the remote domain is the
- * master or its a new slave trying
- * to connect to us. We can't allow
- * further progress until we've
- * sync'd up with the master.
- */
- if (masterid != domid) {
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
- return (1);
- }
- DSLAB_LOCK_EXCL(idn.localid);
- ldp->dslab_state = DSLAB_STATE_REMOTE;
- DSLAB_UNLOCK(idn.localid);
- }
- IDN_DUNLOCK(idn.localid);
- /*
- * We've sync'd up with the new master.
- */
- IDN_GSTATE_TRANSITION(IDNGS_ONLINE);
- }
-
- mdp = &idn_domain[masterid];
-
- if ((masterid != domid) && !IDNDS_CONFIG_DONE(mdp)) {
- /*
- * We can't progress any further with
- * other domains until we've exchanged all
- * the necessary CFG info with the master,
- * i.e. until we have a mailbox area from
- * which we can allocate mailboxes to
- * other domains.
- */
- PR_PROTO("%s:%d: still exchanging CFG "
- "w/master(%d)\n", proc, domid, masterid);
- IDN_GUNLOCK();
- return (1);
- }
-
- DSLAB_LOCK_EXCL(domid);
- dp->dslab_state = ldp->dslab_state;
- DSLAB_UNLOCK(domid);
- if (idn.state != IDNGS_ONLINE) {
- IDN_GSTATE_TRANSITION(IDNGS_ONLINE);
- }
- }
-
- IDN_GUNLOCK();
-
- pending_set = con_set;
- pending_set &= ~(idn.domset.ds_trans_on | idn.domset.ds_connected);
- idn.domset.ds_trans_on |= pending_set;
-
- con_set |= idn.domset.ds_trans_on | idn.domset.ds_connected;
- con_set &= ~idn.domset.ds_trans_off;
- DOMAINSET_ADD(con_set, idn.localid);
-
- if (dp->dsync.s_cmd != IDNSYNC_CONNECT) {
- idn_sync_exit(domid, IDNSYNC_DISCONNECT);
- idn_sync_enter(domid, IDNSYNC_CONNECT,
- con_set, DOMAINSET(idn.localid), idn_xstate_transfunc,
- (void *)IDNP_CON);
- }
-
- /*
- * Get this domain registered as an expected domain on
- * the remaining domains in the CONNECT synchronization.
- */
- (void) idn_sync_register(domid, IDNSYNC_CONNECT, 0, IDNSYNC_REG_NEW);
-
- /*
- * Note that if (msg == 0), i.e. then there will be
- * no dset and also pending_set will be 0.
- * So, the following loop will never attempt to
- * look at the dset unless (msg != 0), implying
- * that we've been through the initial code above
- * and have initialized dmask.
- */
- ASSERT(pending_set ? (dmask != (uint_t)-1) : 1);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- int rv;
-
- if (!DOMAIN_IN_SET(pending_set, d))
- continue;
-
- ASSERT((d != idn.localid) && (d != domid));
-
- dp = &idn_domain[d];
-
- IDNNEG_DSET_GET(dset, d, cpuid, dmask);
- if (cpuid == -1) {
- PR_PROTO("%s:%d: failed to get cpuid from dset "
- "for domain %d (pset = 0x%x)\n",
- proc, domid, d, pending_set);
- DOMAINSET_DEL(idn.domset.ds_trans_on, d);
- continue;
- }
-
- IDN_DLOCK_EXCL(d);
- if ((rv = idn_open_domain(d, cpuid, 0)) != 0) {
- PR_PROTO("%s:%d: failed "
- "idn_open_domain(%d,%d,0) (rv = %d)\n",
- proc, domid, d, cpuid, rv);
- if (rv < 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s) failed to "
- "open-domain(%d,%d)",
- proc, d, cpuid);
- DOMAINSET_DEL(idn.domset.ds_trans_on, d);
- } else if (DOMAIN_IN_SET(idn.domset.ds_trans_off, d)) {
- /*
- * We've requested to connect to a domain
- * from which we're disconnecting. We
- * better mark this guy for relinking.
- */
- DOMAINSET_ADD(idn.domset.ds_relink, d);
- IDN_HISTORY_LOG(IDNH_RELINK, d, dp->dstate,
- idn.domset.ds_relink);
- }
- IDN_DUNLOCK(d);
- continue;
- }
-
- (void) idn_connect(d);
-
- IDN_DUNLOCK(d);
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static void
-idn_action_nego_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_msgtype_t mt;
- domainset_t con_set;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- con_set = idn.domset.ds_trans_on | idn.domset.ds_connected;
- con_set &= ~idn.domset.ds_trans_off;
-
- if (!msg) {
- (void) idn_send_nego(domid, NULL, con_set);
- } else {
- mt.mt_mtype = IDNP_NEGO | IDNP_ACK;
- mt.mt_atype = 0;
- mt.mt_cookie = mtp->mt_cookie;
- (void) idn_send_nego(domid, &mt, con_set);
- }
-}
-
-/*ARGSUSED*/
-static void
-idn_error_nego(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- int new_masterid, new_cpuid;
- int retry = 1;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- uint_t token;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK) {
- idn_nack_t nack;
-
- nack = GET_XARGS_NACK_TYPE(xargs);
- switch (nack) {
- case IDNNACK_RETRY:
- new_masterid = (int)GET_XARGS_NACK_ARG1(xargs);
- new_cpuid = (int)GET_XARGS_NACK_ARG2(xargs);
- break;
-
- case IDNNACK_EXIT:
- retry = 0;
- /*FALLTHROUGH*/
-
- default:
- new_masterid = IDN_NIL_DOMID;
- new_cpuid = IDN_NIL_DCPU;
- break;
- }
- idn_nego_cleanup_check(domid, new_masterid, new_cpuid);
- }
-
- if (msg & IDNP_MSGTYPE_MASK) {
- idn_msgtype_t mt;
- idn_xdcargs_t nargs;
-
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
- mt.mt_cookie = mtp->mt_cookie;
- CLR_XARGS(nargs);
- SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY);
- IDN_GLOCK_SHARED();
- new_masterid = IDN_GET_NEW_MASTERID();
- if (new_masterid == IDN_NIL_DOMID)
- new_masterid = IDN_GET_MASTERID();
- if (new_masterid != IDN_NIL_DOMID)
- new_cpuid = idn_domain[new_masterid].dcpu;
- else
- new_cpuid = IDN_NIL_DCPU;
- SET_XARGS_NACK_ARG1(nargs, new_masterid);
- SET_XARGS_NACK_ARG2(nargs, new_cpuid);
- IDN_GUNLOCK();
- idn_send_acknack(domid, &mt, nargs);
- }
-
- if (retry) {
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO);
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_NEGO]);
- } else {
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- IDN_RESET_COOKIES(domid);
- (void) idn_disconnect(domid, IDNFIN_NORMAL, IDNFIN_ARG_NONE,
- IDNDS_SYNC_TYPE(&idn_domain[domid]));
- }
-}
-
-/*ARGSUSED*/
-static void
-idn_action_nego_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- domainset_t conset;
- idn_msgtype_t mt;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- mt.mt_cookie = mtp ? mtp->mt_cookie : 0;
-
- conset = idn.domset.ds_trans_on | idn.domset.ds_connected;
- conset &= ~idn.domset.ds_trans_off;
-
- if ((msg & IDNP_ACKNACK_MASK) == 0) {
- /*
- * nego
- */
- mt.mt_mtype = IDNP_NEGO | IDNP_ACK;
- mt.mt_atype = 0;
- (void) idn_send_nego(domid, &mt, conset);
- } else if (msg & IDNP_MSGTYPE_MASK) {
- int d;
- idn_xdcargs_t nargs;
- idnneg_dset_t dset;
- uint_t dmask;
- idn_vote_t vote;
-
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = msg;
- DOMAINSET_DEL(conset, idn.localid);
- DOMAINSET_DEL(conset, domid);
-
- dmask = IDNNEG_DSET_MYMASK();
- IDNNEG_DSET_INIT(dset, dmask);
- for (d = 0; d < MAX_DOMAINS; d++) {
- int cpuid;
-
- if (!DOMAIN_IN_SET(conset, d))
- continue;
-
- if ((cpuid = idn_domain[d].dcpu) == IDN_NIL_DCPU)
- continue;
-
- IDNNEG_DSET_SET(dset, d, cpuid, dmask);
- }
- IDNNEG_DSET_SET_MASTER(dset, domid, IDN_GET_MASTERID());
- ASSERT((IDN_GET_MASTERID() != IDN_NIL_DOMID) ?
- (idn_domain[IDN_GET_MASTERID()].dcpu != IDN_NIL_DCPU) : 1);
- vote.ticket = idn_domain[idn.localid].dvote.ticket;
- vote.v.master = 0;
- CLR_XARGS(nargs);
- SET_XARGS_NEGO_TICKET(nargs, vote.ticket);
- SET_XARGS_NEGO_DSET(nargs, dset);
- /*
- * nego+ack
- */
- idn_send_acknack(domid, &mt, nargs);
- } else {
- uint_t token;
- int new_masterid, new_cpuid;
- int retry = 1;
- idn_nack_t nack;
- /*
- * nack - retry
- *
- * It's possible if we've made it this far that
- * we may have already chosen a master and this
- * dude might be it! If it is we need to clean up.
- */
- nack = GET_XARGS_NACK_TYPE(xargs);
- switch (nack) {
- case IDNNACK_RETRY:
- new_masterid = (int)GET_XARGS_NACK_ARG1(xargs);
- new_cpuid = (int)GET_XARGS_NACK_ARG2(xargs);
- break;
-
- case IDNNACK_EXIT:
- retry = 0;
- /*FALLTHROUGH*/
-
- default:
- new_masterid = IDN_NIL_DOMID;
- new_cpuid = IDN_NIL_DCPU;
- break;
- }
-
- idn_nego_cleanup_check(domid, new_masterid, new_cpuid);
-
- if (retry) {
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO);
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_NEGO]);
- } else {
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- IDN_RESET_COOKIES(domid);
- (void) idn_disconnect(domid, IDNFIN_NORMAL,
- IDNFIN_ARG_NONE,
- IDNDS_SYNC_TYPE(&idn_domain[domid]));
- }
- }
-}
-
-/*ARGSUSED*/
-static void
-idn_action_nego_rcvd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK) {
- uint_t token;
- int new_masterid, new_cpuid;
- int retry = 1;
- idn_nack_t nack;
- /*
- * nack - retry.
- *
- * At this stage of receiving a nack we need to
- * check whether we need to start over again with
- * selecting a new master.
- */
- nack = GET_XARGS_NACK_TYPE(xargs);
- switch (nack) {
- case IDNNACK_RETRY:
- new_masterid = (int)GET_XARGS_NACK_ARG1(xargs);
- new_cpuid = (int)GET_XARGS_NACK_ARG2(xargs);
- break;
-
- case IDNNACK_EXIT:
- retry = 0;
- /*FALLTHROUGH*/
-
- default:
- new_masterid = IDN_NIL_DOMID;
- new_cpuid = IDN_NIL_DCPU;
- break;
- }
-
- idn_nego_cleanup_check(domid, new_masterid, new_cpuid);
-
- if (retry) {
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO);
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_NEGO]);
- } else {
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- IDN_RESET_COOKIES(domid);
- (void) idn_disconnect(domid, IDNFIN_NORMAL,
- IDNFIN_ARG_NONE,
- IDNDS_SYNC_TYPE(&idn_domain[domid]));
- }
- }
-}
-
-static void
-idn_final_nego(int domid)
-{
- idn_domain_t *dp = &idn_domain[domid];
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- (void) idn_retry_terminate(IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO));
-
- ASSERT(dp->dstate == IDNDS_CONFIG);
-
- dp->dxp = NULL;
- IDN_XSTATE_TRANSITION(dp, IDNXS_NIL);
-
- idn_send_config(domid, 1);
-}
-
-/*
- */
-/*ARGSUSED1*/
-static void
-idn_exit_nego(int domid, uint_t msgtype)
-{
- idn_domain_t *dp;
- idn_fin_t fintype;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
-
- fintype = msgtype ? IDNFIN_NORMAL : IDNFIN_FORCE_HARD;
-
- (void) idn_retry_terminate(IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO));
-
- ASSERT(!DOMAIN_IN_SET(idn.domset.ds_connected, domid));
- ASSERT(!DOMAIN_IN_SET(idn.domset.ds_ready_on, domid));
- ASSERT(dp->dxp == &xphase_nego);
-
- idn_nego_cleanup_check(domid, IDN_NIL_DOMID, IDN_NIL_DCPU);
-
- IDN_GLOCK_SHARED();
- if ((idn.state != IDNGS_DISCONNECT) &&
- !DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) {
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate,
- idn.domset.ds_relink);
- } else {
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), NULL);
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- }
- IDN_GUNLOCK();
- /*
- * Reset send cookie to 0 so that receiver does not validate
- * cookie. This is necessary since at this early stage it's
- * possible we may not have exchanged appropriate cookies.
- */
- IDN_RESET_COOKIES(domid);
- (void) idn_disconnect(domid, fintype, IDNFIN_ARG_NONE,
- IDNDS_SYNC_TYPE(dp));
-}
-
-static void
-idn_nego_cleanup_check(int domid, int new_masterid, int new_cpuid)
-{
- idn_domain_t *ldp, *dp;
- procname_t proc = "idn_nego_cleanup_check";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- IDN_GLOCK_EXCL();
-
- if (((idn.state == IDNGS_ONLINE) && !idn.domset.ds_connected) ||
- (idn.state == IDNGS_CONNECT)) {
- domainset_t trans_on;
- int masterid;
- int retry_domid = IDN_NIL_DOMID;
- int rv;
-
- IDN_DLOCK_EXCL(idn.localid);
- masterid = (idn.state == IDNGS_ONLINE) ?
- IDN_GET_MASTERID() : IDN_GET_NEW_MASTERID();
- trans_on = idn.domset.ds_trans_on;
- DOMAINSET_DEL(trans_on, domid);
- if (trans_on == 0) {
- int d;
- domainset_t relink = idn.domset.ds_relink;
- /*
- * This was the only guy we were trying
- * to connect with.
- */
- ASSERT((idn.state == IDNGS_ONLINE) ?
- ((idn.localid == masterid) ||
- (domid == masterid)) : 1);
- if (idn.localid == masterid)
- idn_master_deinit();
- ldp->dvote.v.connected = 0;
- ldp->dvote.v.master = 0;
- dp->dvote.v.master = 0;
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- IDN_SET_NEW_MASTERID(new_masterid);
- IDN_GSTATE_TRANSITION(IDNGS_CONNECT);
- IDN_PREP_HWINIT();
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
- /*
- * If there's a new master available then
- * just try and relink with him unless
- * it's ourself.
- */
- if ((new_masterid != IDN_NIL_DOMID) &&
- (new_masterid != idn.localid) &&
- (new_masterid != domid)) {
- IDN_DLOCK_EXCL(new_masterid);
- rv = idn_open_domain(new_masterid,
- new_cpuid, 0);
- if (rv < 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s) failed to "
- "open-domain(%d,%d)",
- proc, new_masterid, new_cpuid);
- IDN_GLOCK_EXCL();
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- IDN_GUNLOCK();
- } else {
- relink = DOMAINSET(new_masterid);
- }
- IDN_DUNLOCK(new_masterid);
- }
- DOMAINSET_DEL(relink, domid);
- if (relink)
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(relink, d))
- continue;
- retry_domid = d;
- break;
- }
- } else if (domid == masterid) {
- /*
- * There are other domains we were trying
- * to connect to. As long as the chosen
- * master was somebody other then this
- * domain that nack'd us, life is cool, but
- * if it was this remote domain we'll need
- * to start over.
- */
- IDN_DUNLOCK(idn.localid);
- dp->dvote.v.master = 0;
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- IDN_SET_NEW_MASTERID(new_masterid);
-
- if (idn.state == IDNGS_ONLINE) {
- IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs,
- gk_reconfig_last);
- IDN_GSTATE_TRANSITION(IDNGS_RECONFIG);
- IDN_GUNLOCK();
- idn_unlink_domainset(trans_on, IDNFIN_NORMAL,
- IDNFIN_ARG_NONE,
- IDNFIN_OPT_RELINK,
- BOARDSET_ALL);
- } else if ((new_masterid != IDN_NIL_DOMID) &&
- (new_masterid != idn.localid) &&
- (new_masterid != domid) &&
- !DOMAIN_IN_SET(trans_on, new_masterid)) {
- IDN_GUNLOCK();
- IDN_DLOCK_EXCL(new_masterid);
- rv = idn_open_domain(new_masterid,
- new_cpuid, 0);
- IDN_GLOCK_EXCL();
- IDN_DUNLOCK(new_masterid);
- if (rv < 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s) failed to "
- "open-domain(%d,%d)",
- proc, new_masterid,
- new_cpuid);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- new_masterid = IDN_NIL_DOMID;
- } else {
- retry_domid = new_masterid;
- }
- IDN_GUNLOCK();
- } else {
- IDN_GUNLOCK();
- }
- } else {
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
- }
- if (retry_domid != IDN_NIL_DOMID) {
- uint_t token;
- idn_domain_t *rdp = &idn_domain[retry_domid];
-
- IDN_DLOCK_EXCL(retry_domid);
- rdp->dxp = &xphase_nego;
- IDN_XSTATE_TRANSITION(rdp, IDNXS_PEND);
- IDN_DUNLOCK(retry_domid);
- token = IDN_RETRY_TOKEN(retry_domid, IDNRETRY_NEGO);
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_NEGO]);
- }
- } else {
- IDN_GUNLOCK();
- }
-}
-
-static int
-idn_send_con(int domid, idn_msgtype_t *mtp, idn_con_t contype, domainset_t
- conset)
-{
- idn_msgtype_t mt;
- uint_t acknack;
- procname_t proc = "idn_send_con";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (mtp) {
- acknack = mtp->mt_mtype & IDNP_ACKNACK_MASK;
- mt.mt_mtype = mtp->mt_mtype;
- mt.mt_atype = mtp->mt_atype;
- mt.mt_cookie = mtp->mt_cookie;
- } else {
- acknack = 0;
- mt.mt_mtype = IDNP_CON;
- mt.mt_atype = 0;
- /*
- * For simple CON queries we want a unique
- * timer assigned. For others, they
- * effectively share one.
- */
- if (contype == IDNCON_QUERY)
- mt.mt_cookie = 0;
- else
- mt.mt_cookie = IDN_TIMER_PUBLIC_COOKIE;
- }
-
- ASSERT((contype == IDNCON_QUERY) ? idn_domain[domid].dcookie_send : 1);
-
- PR_PROTO("%s:%d: sending con%sto (cpu %d) [ct=%s, cs=0x%x]\n",
- proc, domid,
- (acknack & IDNP_ACK) ? "+ack " :
- (acknack & IDNP_NACK) ? "+nack " : " ",
- idn_domain[domid].dcpu,
- idncon_str[contype], conset);
-
- IDN_MSGTIMER_START(domid, IDNP_CON, (ushort_t)contype,
- idn_msg_waittime[IDNP_CON], &mt.mt_cookie);
-
- IDNXDC(domid, &mt, (uint_t)contype, (uint_t)conset, 0, 0);
-
- return (0);
-}
-
-/*
- * Must leave w/DLOCK dropped and SYNC_LOCK held.
- */
-static int
-idn_recv_con(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- uint_t msgarg = mtp ? mtp->mt_atype : 0;
- idn_con_t contype;
- domainset_t my_ready_set, ready_set;
- idn_msgtype_t mt;
- idn_domain_t *dp = &idn_domain[domid];
- idn_xdcargs_t aargs;
- procname_t proc = "idn_recv_con";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- mt.mt_cookie = mtp ? mtp->mt_cookie : 0;
-
- contype = GET_XARGS_CON_TYPE(xargs);
- ready_set = GET_XARGS_CON_DOMSET(xargs);
-
- CLR_XARGS(aargs);
-
- if (!(msg & IDNP_NACK) && (contype == IDNCON_QUERY)) {
- domainset_t query_set;
-
- query_set = idn_sync_register(domid, IDNSYNC_CONNECT,
- ready_set, IDNSYNC_REG_REG);
-
- my_ready_set = idn.domset.ds_connected | idn.domset.ds_ready_on;
- my_ready_set &= ~idn.domset.ds_trans_off;
- DOMAINSET_ADD(my_ready_set, idn.localid);
-
- if (msg & IDNP_MSGTYPE_MASK) {
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = IDNP_CON;
- SET_XARGS_CON_TYPE(aargs, contype);
- SET_XARGS_CON_DOMSET(aargs, my_ready_set);
- idn_send_acknack(domid, &mt, aargs);
- }
-
- if (query_set) {
- uint_t token;
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_CONQ);
- idn_retry_submit(idn_retry_query, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_CONQ]);
- }
-
- return (0);
- }
-
- if (dp->dxp == NULL) {
- STRING(mstr);
- STRING(lstr);
- /*
- * Must have received an inappropriate error
- * message as we should already be registered
- * by the time we reach here.
- */
- INUM2STR(msg, mstr);
- INUM2STR(msgarg, lstr);
-
- PR_PROTO("%s:%d: ERROR: NOT YET REGISTERED (%s/%s)\n",
- proc, domid, mstr, lstr);
-
- if (msg & IDNP_MSGTYPE_MASK) {
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
- SET_XARGS_NACK_TYPE(aargs, IDNNACK_RETRY);
- idn_send_acknack(domid, &mt, aargs);
- }
-
- return (-1);
- }
-
- (void) idn_xphase_transition(domid, mtp, xargs);
-
- return (0);
-}
-
-/*ARGSUSED1*/
-static void
-idn_retry_con(uint_t token, void *arg)
-{
- int domid = IDN_RETRY_TOKEN2DOMID(token);
- idn_domain_t *dp = &idn_domain[domid];
- idn_xdcargs_t xargs;
- procname_t proc = "idn_retry_con";
-
- ASSERT(IDN_RETRY_TOKEN2TYPE(token) == IDNRETRY_CON);
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
-
- if (dp->dxp != &xphase_con) {
- STRING(str);
-
-#ifdef DEBUG
- if (dp->dxp) {
- INUM2STR(dp->dxp->xt_msgtype, str);
- }
-#endif /* DEBUG */
-
- PR_PROTO("%s:%d: dxp(%s) != CON...bailing...\n",
- proc, domid, dp->dxp ? str : "NULL");
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- if ((dp->dsync.s_cmd != IDNSYNC_CONNECT) ||
- (dp->dxstate != IDNXS_PEND)) {
- PR_PROTO("%s:%d: cmd (%s) and/or xstate (%s) not "
- "expected (%s/%s)\n",
- proc, domid, idnsync_str[dp->dsync.s_cmd],
- idnxs_str[dp->dxstate], idnsync_str[IDNSYNC_CONNECT],
- idnxs_str[IDNXS_PEND]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- (void) idn_xphase_transition(domid, NULL, xargs);
-
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
-}
-
-static int
-idn_check_con(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- int ready;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_domain_t *dp = &idn_domain[domid];
- domainset_t ready_set, my_ready_set, query_set;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK)
- return (0);
-
- if ((dp->dstate == IDNDS_CON_PEND) &&
- (msg & IDNP_MSGTYPE_MASK) && (msg & IDNP_ACK)) /* con+ack */
- return (1);
-
- if (msg == 0) {
- ready_set = idn.domset.ds_connected &
- ~idn.domset.ds_trans_off;
- } else {
- ready_set = GET_XARGS_CON_DOMSET(xargs);
- DOMAINSET_ADD(idn.domset.ds_ready_on, domid);
- }
-
- DOMAINSET_ADD(ready_set, idn.localid);
-
- query_set = idn_sync_register(domid, IDNSYNC_CONNECT,
- ready_set, IDNSYNC_REG_REG);
- /*
- * No need to query this domain as he's already
- * in the CON sequence.
- */
- DOMAINSET_DEL(query_set, domid);
-
- ready = (dp->dsync.s_set_exp == dp->dsync.s_set_rdy) ? 1 : 0;
- if (ready) {
- DOMAINSET_DEL(idn.domset.ds_ready_on, domid);
- DOMAINSET_ADD(idn.domset.ds_connected, domid);
- }
-
- if (query_set) {
- int d;
-
- my_ready_set = idn.domset.ds_ready_on |
- idn.domset.ds_connected;
- my_ready_set &= ~idn.domset.ds_trans_off;
- DOMAINSET_ADD(my_ready_set, idn.localid);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(query_set, d))
- continue;
-
- dp = &idn_domain[d];
-
- IDN_DLOCK_EXCL(d);
- if ((dp->dsync.s_cmd == IDNSYNC_CONNECT) ||
- !dp->dcookie_send) {
- IDN_DUNLOCK(d);
- continue;
- }
-
- IDN_SYNC_QUERY_UPDATE(domid, d);
-
- (void) idn_send_con(d, NULL, IDNCON_QUERY,
- my_ready_set);
- IDN_DUNLOCK(d);
- }
- }
-
- return (!msg ? 0 : (ready ? 0 : 1));
-}
-
-/*ARGSUSED2*/
-static void
-idn_error_con(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t token;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_MSGTYPE_MASK) {
- idn_msgtype_t mt;
- idn_xdcargs_t nargs;
-
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
- mt.mt_cookie = mtp->mt_cookie;
- CLR_XARGS(nargs);
- SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY);
- idn_send_acknack(domid, &mt, nargs);
- }
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON);
- idn_retry_submit(idn_retry_con, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_CON]);
-}
-
-/*ARGSUSED*/
-static void
-idn_action_con_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_domain_t *dp = &idn_domain[domid];
- idn_msgtype_t mt;
- domainset_t my_ready_set;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_on |
- idn.domset.ds_connected;
- my_ready_set &= ~idn.domset.ds_trans_off;
- DOMAINSET_ADD(my_ready_set, idn.localid);
-
- if (!msg) {
- (void) idn_send_con(domid, NULL, IDNCON_NORMAL, my_ready_set);
- } else {
- mt.mt_mtype = IDNP_CON | IDNP_ACK;
- mt.mt_atype = 0;
- mt.mt_cookie = mtp->mt_cookie;
- (void) idn_send_con(domid, &mt, IDNCON_NORMAL, my_ready_set);
- }
-}
-
-static void
-idn_action_con_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_domain_t *dp = &idn_domain[domid];
- idn_con_t contype;
- domainset_t my_ready_set;
- idn_msgtype_t mt;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- mt.mt_cookie = mtp ? mtp->mt_cookie : 0;
-
- my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_on |
- idn.domset.ds_connected;
- my_ready_set &= ~idn.domset.ds_trans_off;
- DOMAINSET_ADD(my_ready_set, idn.localid);
-
- contype = GET_XARGS_CON_TYPE(xargs);
-
- if ((msg & IDNP_ACKNACK_MASK) == 0) {
- /*
- * con
- */
- mt.mt_mtype = IDNP_CON | IDNP_ACK;
- mt.mt_atype = 0;
- (void) idn_send_con(domid, &mt, contype, my_ready_set);
- } else if (msg & IDNP_MSGTYPE_MASK) {
- idn_xdcargs_t cargs;
-
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = msg;
- CLR_XARGS(cargs);
- SET_XARGS_CON_TYPE(cargs, contype);
- SET_XARGS_CON_DOMSET(cargs, my_ready_set);
- /*
- * con+ack
- */
- idn_send_acknack(domid, &mt, cargs);
- } else {
- uint_t token;
- /*
- * nack - retry
- */
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON);
- idn_retry_submit(idn_retry_con, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_CON]);
- }
-}
-
-/*ARGSUSED*/
-static void
-idn_action_con_rcvd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK) {
- uint_t token;
- /*
- * nack - retry
- */
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON);
- idn_retry_submit(idn_retry_con, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_CON]);
- }
-}
-
-static void
-idn_final_con(int domid)
-{
- uint_t targ;
- uint_t token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON);
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_final_con";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- (void) idn_retry_terminate(token);
-
- dp->dxp = NULL;
- IDN_XSTATE_TRANSITION(dp, IDNXS_NIL);
-
- idn_sync_exit(domid, IDNSYNC_CONNECT);
-
- CHECKPOINT_OPENED(IDNSB_CHKPT_LINK, dp->dhw.dh_boardset, 1);
-
- DOMAINSET_DEL(idn.domset.ds_trans_on, domid);
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- IDN_FSTATE_TRANSITION(dp, IDNFIN_OFF);
-
- PR_PROTO("%s:%d: CONNECTED\n", proc, domid);
-
- if (idn.domset.ds_trans_on == 0) {
- if ((idn.domset.ds_trans_off | idn.domset.ds_relink) == 0) {
- PR_HITLIST("%s:%d: HITLIST %x -> 0\n",
- proc, domid, idn.domset.ds_hitlist);
- idn.domset.ds_hitlist = 0;
- }
- PR_PROTO("%s:%d: ALL CONNECTED ************ "
- "(0x%x + 0x%x) = 0x%x\n", proc, domid,
- DOMAINSET(idn.localid), idn.domset.ds_connected,
- DOMAINSET(idn.localid) | idn.domset.ds_connected);
- } else {
- PR_PROTO("%s:%d: >>> ds_trans_on = 0x%x, ds_ready_on = 0x%x\n",
- proc, domid,
- idn.domset.ds_trans_on, idn.domset.ds_ready_on);
- }
-
- if (idn_verify_config_mbox(domid)) {
- idnsb_error_t idnerr;
- /*
- * Mailbox is not cool. Need to disconnect.
- */
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EPROTO);
- SET_IDNKERR_IDNERR(&idnerr, IDNKERR_SMR_CORRUPTED);
- SET_IDNKERR_PARAM0(&idnerr, domid);
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr);
- /*
- * We cannot disconnect from an individual domain
- * unless all domains are attempting to disconnect
- * from him also, especially now since we touched
- * the SMR and now we have a potential cache conflicts
- * with the other domains with respect to this
- * domain. Disconnect attempt will effectively
- * shutdown connection with respective domain
- * which is the effect we really want anyway.
- */
- (void) idn_disconnect(domid, IDNFIN_NORMAL, IDNFIN_ARG_SMRBAD,
- IDNFIN_SYNC_YES);
-
- return;
- }
-
- if (lock_try(&idn.first_swlink)) {
- /*
- * This is our first connection. Need to
- * kick some stuff into gear.
- */
- idndl_dlpi_init();
- (void) idn_activate_channel(CHANSET_ALL, IDNCHAN_ONLINE);
-
- targ = 0xf0;
- } else {
- targ = 0;
- }
-
- idn_mainmbox_activate(domid);
-
- idn_update_op(IDNOP_CONNECTED, DOMAINSET(domid), NULL);
-
- IDN_GKSTAT_GLOBAL_EVENT(gk_links, gk_link_last);
-
- membar_stst_ldst();
-
- IDN_DSTATE_TRANSITION(dp, IDNDS_CONNECTED);
- /*
- * Need to kick off initial commands in background.
- * We do not want to do them within the context of
- * a protocol server because they may sleep and thus
- * cause the protocol server to incur a soft-deadlock,
- * i.e. he's sleeping waiting in the slab-waiting area
- * for a response that will arrive on his protojob
- * queue, but which he obviously can't process since
- * he's not waiting on his protojob queue.
- */
- targ |= domid & 0x0f;
- (void) timeout(idn_link_established, (void *)(uintptr_t)targ, 50);
-
- cmn_err(CE_NOTE,
- "!IDN: 200: link (domain %d, CPU %d) connected",
- dp->domid, dp->dcpu);
-}
-
-static void
-idn_exit_con(int domid, uint_t msgtype)
-{
- idn_domain_t *dp = &idn_domain[domid];
- idn_fin_t fintype;
- procname_t proc = "idn_exit_con";
- STRING(str);
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- INUM2STR(msgtype, str);
- PR_PROTO("%s:%d: msgtype = 0x%x(%s)\n", proc, domid, msgtype, str);
-
- fintype = msgtype ? IDNFIN_NORMAL : IDNFIN_FORCE_HARD;
-
- IDN_GLOCK_SHARED();
- if (idn.state != IDNGS_DISCONNECT) {
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate,
- idn.domset.ds_relink);
- } else {
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- }
- IDN_GUNLOCK();
-
- (void) idn_disconnect(domid, fintype, IDNFIN_ARG_NONE,
- IDNDS_SYNC_TYPE(dp));
-}
-
-static int
-idn_send_fin(int domid, idn_msgtype_t *mtp, idn_fin_t fintype, idn_finarg_t
- finarg, idn_finopt_t finopt, domainset_t finset, uint_t finmaster)
-{
- int need_timer = 1;
- uint_t acknack;
- uint_t fintypearg = 0;
- idn_msgtype_t mt;
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_send_fin";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- ASSERT((fintype != IDNFIN_QUERY) ? (finopt != IDNFIN_OPT_NONE) : 1);
-
- if (mtp) {
- acknack = mtp->mt_mtype & IDNP_ACKNACK_MASK;
- mt.mt_mtype = mtp->mt_mtype;
- mt.mt_atype = mtp->mt_atype;
- mt.mt_cookie = mtp->mt_cookie;
- } else {
- acknack = 0;
- mt.mt_mtype = IDNP_FIN;
- mt.mt_atype = 0;
- /*
- * For simple FIN queries we want a unique
- * timer assigned. For others, they
- * effectively share one.
- */
- if (fintype == IDNFIN_QUERY)
- mt.mt_cookie = 0;
- else
- mt.mt_cookie = IDN_TIMER_PUBLIC_COOKIE;
- }
-
- PR_PROTO("%s:%d: sending fin%sto (cpu %d) "
- "[ft=%s, fa=%s, fs=0x%x, fo=%s, fm=(%d,%d)]\n",
- proc, domid,
- (acknack & IDNP_ACK) ? "+ack " :
- (acknack & IDNP_NACK) ? "+nack " : " ",
- dp->dcpu, idnfin_str[fintype], idnfinarg_str[finarg],
- (int)finset, idnfinopt_str[finopt],
- FIN_MASTER_DOMID(finmaster), FIN_MASTER_CPUID(finmaster));
-
- if (need_timer) {
- IDN_MSGTIMER_START(domid, IDNP_FIN, (ushort_t)fintype,
- idn_msg_waittime[IDNP_FIN], &mt.mt_cookie);
- }
-
- SET_FIN_TYPE(fintypearg, fintype);
- SET_FIN_ARG(fintypearg, finarg);
-
- IDNXDC(domid, &mt, fintypearg, (uint_t)finset, (uint_t)finopt,
- finmaster);
-
- return (0);
-}
-
-/*
- * Must leave w/DLOCK dropped and SYNC_LOCK held.
- */
-static int
-idn_recv_fin(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_fin_t fintype;
- idn_finarg_t finarg;
- idn_finopt_t finopt;
- domainset_t my_ready_set, ready_set;
- idn_msgtype_t mt;
- idn_domain_t *dp = &idn_domain[domid];
- idn_xdcargs_t aargs;
- procname_t proc = "idn_recv_fin";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- mt.mt_cookie = mtp ? mtp->mt_cookie : 0;
-
- fintype = GET_XARGS_FIN_TYPE(xargs);
- finarg = GET_XARGS_FIN_ARG(xargs);
- ready_set = GET_XARGS_FIN_DOMSET(xargs);
- finopt = GET_XARGS_FIN_OPT(xargs);
-
- CLR_XARGS(aargs);
-
- if (msg & IDNP_NACK) {
- PR_PROTO("%s:%d: received NACK (type = %s)\n",
- proc, domid, idnnack_str[xargs[0]]);
- } else {
- PR_PROTO("%s:%d: fintype = %s, finopt = %s, "
- "finarg = %s, ready_set = 0x%x\n",
- proc, domid, idnfin_str[fintype],
- idnfinopt_str[finopt],
- idnfinarg_str[finarg], ready_set);
- }
-
- if (!(msg & IDNP_NACK) && (fintype == IDNFIN_QUERY)) {
- domainset_t query_set;
-
- query_set = idn_sync_register(domid, IDNSYNC_DISCONNECT,
- ready_set, IDNSYNC_REG_REG);
-
- my_ready_set = ~idn.domset.ds_connected |
- idn.domset.ds_ready_off;
-
- if (msg & IDNP_MSGTYPE_MASK) {
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = IDNP_FIN;
- SET_XARGS_FIN_TYPE(aargs, fintype);
- SET_XARGS_FIN_ARG(aargs, finarg);
- SET_XARGS_FIN_DOMSET(aargs, my_ready_set);
- SET_XARGS_FIN_OPT(aargs, IDNFIN_OPT_NONE);
- SET_XARGS_FIN_MASTER(aargs, NIL_FIN_MASTER);
- idn_send_acknack(domid, &mt, aargs);
- }
-
- if (query_set) {
- uint_t token;
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FINQ);
- idn_retry_submit(idn_retry_query, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FINQ]);
- }
-
- return (0);
- }
-
- if (dp->dxp != &xphase_fin) {
- uint_t token;
-
- if (IDNDS_IS_CLOSED(dp)) {
- PR_PROTO("%s:%d: domain already closed (%s)\n",
- proc, domid, idnds_str[dp->dstate]);
- if (msg & IDNP_MSGTYPE_MASK) {
- /*
- * fin or fin+ack.
- */
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
- SET_XARGS_NACK_TYPE(aargs, IDNNACK_NOCONN);
- idn_send_acknack(domid, &mt, aargs);
- }
- return (0);
- }
- dp->dfin_sync = IDNDS_SYNC_TYPE(dp);
-
- /*
- * Need to do some clean-up ala idn_disconnect().
- *
- * Terminate any outstanding commands that were
- * targeted towards this domain.
- */
- idn_terminate_cmd(domid, ECANCELED);
-
- /*
- * Terminate any and all retries that may have
- * outstanding for this domain.
- */
- token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL);
- (void) idn_retry_terminate(token);
-
- /*
- * Stop all outstanding message timers for
- * this guy.
- */
- IDN_MSGTIMER_STOP(domid, 0, 0);
-
- dp->dxp = &xphase_fin;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- }
-
- if (msg & IDNP_NACK) {
- idn_nack_t nack;
-
- nack = GET_XARGS_NACK_TYPE(xargs);
- if (nack == IDNNACK_NOCONN) {
- /*
- * We're trying to FIN with somebody we're
- * already disconnected from. Need to
- * speed this guy through.
- */
- DOMAINSET_ADD(idn.domset.ds_ready_off, domid);
- (void) idn_sync_register(domid, IDNSYNC_DISCONNECT,
- DOMAINSET_ALL, IDNSYNC_REG_REG);
- ready_set = (uint_t)DOMAINSET_ALL;
- /*
- * Need to transform message to allow us to
- * pass this guy right through and not waste time
- * talking to him.
- */
- IDN_FSTATE_TRANSITION(dp, IDNFIN_FORCE_HARD);
-
- switch (dp->dstate) {
- case IDNDS_FIN_PEND:
- mtp->mt_mtype = 0;
- mtp->mt_atype = 0;
- break;
-
- case IDNDS_FIN_SENT:
- mtp->mt_mtype = IDNP_FIN | IDNP_ACK;
- mtp->mt_atype = 0;
- break;
-
- case IDNDS_FIN_RCVD:
- mtp->mt_mtype = IDNP_ACK;
- mtp->mt_atype = IDNP_FIN | IDNP_ACK;
- break;
-
- default:
-#ifdef DEBUG
- cmn_err(CE_PANIC,
- "%s:%d: UNEXPECTED state = %s",
- proc, domid,
- idnds_str[dp->dstate]);
-#endif /* DEBUG */
- break;
- }
- }
- fintype = (uint_t)dp->dfin;
- finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ?
- IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK;
-
- CLR_XARGS(xargs);
- SET_XARGS_FIN_TYPE(xargs, fintype);
- SET_XARGS_FIN_ARG(xargs, finarg);
- SET_XARGS_FIN_DOMSET(xargs, ready_set);
- SET_XARGS_FIN_OPT(xargs, finopt);
- SET_XARGS_FIN_MASTER(xargs, NIL_FIN_MASTER);
- }
-
- (void) idn_xphase_transition(domid, mtp, xargs);
-
- return (0);
-}
-
-/*ARGSUSED1*/
-static void
-idn_retry_fin(uint_t token, void *arg)
-{
- int domid = IDN_RETRY_TOKEN2DOMID(token);
- int new_masterid, new_cpuid = IDN_NIL_DCPU;
- uint_t finmaster;
- idn_domain_t *dp = &idn_domain[domid];
- idn_xdcargs_t xargs;
- idn_finopt_t finopt;
- procname_t proc = "idn_retry_fin";
-
- ASSERT(IDN_RETRY_TOKEN2TYPE(token) == IDNRETRY_FIN);
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
-
- if (dp->dxp != &xphase_fin) {
- PR_PROTO("%s:%d: dxp(0x%p) != xstate_fin(0x%p)...bailing\n",
- proc, domid, (void *)dp->dxp, (void *)&xphase_fin);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- if (dp->dxstate != IDNXS_PEND) {
- PR_PROTO("%s:%d: xstate(%s) != %s...bailing\n",
- proc, domid, idnxs_str[dp->dxstate],
- idnxs_str[IDNXS_PEND]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
-
- finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ?
- IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK;
-
- CLR_XARGS(xargs);
- SET_XARGS_FIN_TYPE(xargs, dp->dfin);
- /*LINTED*/
- SET_XARGS_FIN_ARG(xargs, IDNFIN_ARG_NONE);
- SET_XARGS_FIN_OPT(xargs, finopt);
- SET_XARGS_FIN_DOMSET(xargs, 0); /* unused when msg == 0 */
- IDN_GLOCK_SHARED();
- new_masterid = IDN_GET_NEW_MASTERID();
- IDN_GUNLOCK();
- if (new_masterid != IDN_NIL_DOMID)
- new_cpuid = idn_domain[new_masterid].dcpu;
- finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid);
- SET_XARGS_FIN_MASTER(xargs, finmaster);
-
- (void) idn_xphase_transition(domid, NULL, xargs);
-
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
-}
-
-static int
-idn_check_fin_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- idn_domain_t *dp = &idn_domain[domid];
- idn_fin_t fintype;
- idn_finopt_t finopt;
- idn_finarg_t finarg;
- int ready;
- int finmasterid;
- int fincpuid;
- uint_t finmaster;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- domainset_t query_set, ready_set, conn_set;
- domainset_t my_ready_set, shutdown_set;
- procname_t proc = "idn_check_fin_pend";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK)
- return (0);
-
- if ((dp->dstate == IDNDS_FIN_PEND) && (msg & IDNP_MSGTYPE_MASK) &&
- (msg & IDNP_ACK)) /* fin+ack */
- return (1);
-
- query_set = 0;
-
- if (!DOMAIN_IN_SET(idn.domset.ds_trans_off, domid)) {
- /*
- * Can't remove domain from ds_connected yet,
- * since he's still officially connected until
- * we get an ACK from him.
- */
- DOMAINSET_DEL(idn.domset.ds_trans_on, domid);
- DOMAINSET_ADD(idn.domset.ds_trans_off, domid);
- }
-
- IDN_GLOCK_SHARED();
- conn_set = (idn.domset.ds_connected | idn.domset.ds_trans_on) &
- ~idn.domset.ds_trans_off;
- if ((idn.state == IDNGS_DISCONNECT) ||
- (idn.state == IDNGS_RECONFIG) ||
- (domid == IDN_GET_MASTERID()) || !conn_set) {
- /*
- * If we're disconnecting, reconfiguring,
- * unlinking from the master, or unlinking
- * the last of our connections, then we need
- * to shutdown all the channels.
- */
- shutdown_set = DOMAINSET_ALL;
- } else {
- shutdown_set = DOMAINSET(domid);
- }
- IDN_GUNLOCK();
-
- idn_shutdown_datapath(shutdown_set, (dp->dfin == IDNFIN_FORCE_HARD));
-
- IDN_GLOCK_EXCL();
- /*
- * Remap the SMR back to our local space if the remote
- * domain going down is the master. We do this now before
- * flushing caches. This will help guarantee that any
- * accidental accesses to the SMR after the cache flush
- * will only go to local memory.
- */
- if ((domid == IDN_GET_MASTERID()) && (idn.smr.rempfn != PFN_INVALID)) {
- PR_PROTO("%s:%d: deconfiging CURRENT MASTER - SMR remap\n",
- proc, domid);
- IDN_DLOCK_EXCL(idn.localid);
- /*
- * We're going to remap the SMR,
- * so gotta blow away our local
- * pointer to the mbox table.
- */
- idn_domain[idn.localid].dmbox.m_tbl = NULL;
- IDN_DUNLOCK(idn.localid);
-
- idn.smr.rempfn = PFN_INVALID;
- idn.smr.rempfnlim = PFN_INVALID;
-
- smr_remap(&kas, idn.smr.vaddr, idn.smr.locpfn, IDN_SMR_SIZE);
- }
- IDN_GUNLOCK();
-
- if (DOMAIN_IN_SET(idn.domset.ds_flush, domid)) {
- idnxf_flushall_ecache();
- CHECKPOINT_CLOSED(IDNSB_CHKPT_CACHE, dp->dhw.dh_boardset, 2);
- DOMAINSET_DEL(idn.domset.ds_flush, domid);
- }
-
- fintype = GET_XARGS_FIN_TYPE(xargs);
- finarg = GET_XARGS_FIN_ARG(xargs);
- ready_set = GET_XARGS_FIN_DOMSET(xargs);
- finopt = GET_XARGS_FIN_OPT(xargs);
-
- ASSERT(fintype != IDNFIN_QUERY);
- if (!VALID_FIN(fintype)) {
- /*
- * If for some reason remote domain
- * sent us an invalid FIN type,
- * override it to a NORMAL fin.
- */
- PR_PROTO("%s:%d: WARNING invalid fintype (%d) -> %s(%d)\n",
- proc, domid, (int)fintype,
- idnfin_str[IDNFIN_NORMAL], (int)IDNFIN_NORMAL);
- fintype = IDNFIN_NORMAL;
- }
-
- if (!VALID_FINOPT(finopt)) {
- PR_PROTO("%s:%d: WARNING invalid finopt (%d) -> %s(%d)\n",
- proc, domid, (int)finopt,
- idnfinopt_str[IDNFIN_OPT_UNLINK],
- (int)IDNFIN_OPT_UNLINK);
- finopt = IDNFIN_OPT_UNLINK;
- }
-
- finmaster = GET_XARGS_FIN_MASTER(xargs);
- finmasterid = FIN_MASTER_DOMID(finmaster);
- fincpuid = FIN_MASTER_CPUID(finmaster);
-
- if ((finarg != IDNFIN_ARG_NONE) &&
- !DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) {
- idnsb_error_t idnerr;
-
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EPROTO);
- SET_IDNKERR_IDNERR(&idnerr, FINARG2IDNKERR(finarg));
- SET_IDNKERR_PARAM0(&idnerr, domid);
-
- if (IDNFIN_ARG_IS_FATAL(finarg)) {
- finopt = IDNFIN_OPT_UNLINK;
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- DOMAINSET_ADD(idn.domset.ds_hitlist, domid);
-
- if (idn.domset.ds_connected == 0) {
- domainset_t domset;
-
- IDN_GLOCK_EXCL();
- domset = ~idn.domset.ds_relink;
- if (idn.domset.ds_relink == 0) {
- IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT);
- }
- domset &= ~idn.domset.ds_hitlist;
- /*
- * The primary domain we were trying to
- * connect to fin'd us with a fatal argument.
- * Something isn't cool in our IDN environment,
- * e.g. corrupted SMR or non-compatible CONFIG
- * parameters. In any case we need to dismantle
- * ourselves completely.
- */
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- IDN_GUNLOCK();
- IDN_DUNLOCK(domid);
-
- DOMAINSET_DEL(domset, idn.localid);
- DOMAINSET_DEL(domset, domid);
-
- idn_update_op(IDNOP_ERROR, DOMAINSET_ALL,
- &idnerr);
-
- PR_HITLIST("%s:%d: unlink_domainset(%x) "
- "due to CFG error (relink=%x, "
- "hitlist=%x)\n", proc, domid, domset,
- idn.domset.ds_relink,
- idn.domset.ds_hitlist);
-
- idn_unlink_domainset(domset, IDNFIN_NORMAL,
- finarg, IDNFIN_OPT_UNLINK, BOARDSET_ALL);
- IDN_DLOCK_EXCL(domid);
- }
- PR_HITLIST("%s:%d: CFG error, (conn=%x, relink=%x, "
- "hitlist=%x)\n",
- proc, domid, idn.domset.ds_connected,
- idn.domset.ds_relink, idn.domset.ds_hitlist);
- }
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr);
- }
-
- if ((finmasterid != IDN_NIL_DOMID) && (!VALID_DOMAINID(finmasterid) ||
- DOMAIN_IN_SET(idn.domset.ds_hitlist, domid))) {
- PR_HITLIST("%s:%d: finmasterid = %d -> -1, relink=%x, "
- "hitlist=%x\n",
- proc, domid, finmasterid, idn.domset.ds_relink,
- idn.domset.ds_hitlist);
- PR_PROTO("%s:%d: WARNING invalid finmasterid (%d) -> -1\n",
- proc, domid, finmasterid);
- finmasterid = IDN_NIL_DOMID;
- }
-
- IDN_GLOCK_EXCL();
-
- if ((finopt == IDNFIN_OPT_RELINK) && (idn.state != IDNGS_DISCONNECT)) {
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate,
- idn.domset.ds_relink);
- } else {
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- DOMAINSET_ADD(idn.domset.ds_hitlist, domid);
- }
-
- if ((domid == IDN_GET_NEW_MASTERID()) &&
- !DOMAIN_IN_SET(idn.domset.ds_relink, domid)) {
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- }
-
- if ((idn.state != IDNGS_DISCONNECT) && (idn.state != IDNGS_RECONFIG) &&
- (domid == IDN_GET_MASTERID())) {
- domainset_t dis_set, master_candidates;
-
- IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs, gk_reconfig_last);
-
- IDN_GSTATE_TRANSITION(IDNGS_RECONFIG);
- IDN_GUNLOCK();
-
- if ((finmasterid != IDN_NIL_DOMID) &&
- (finmasterid != idn.localid)) {
- if (finmasterid != domid)
- IDN_DLOCK_EXCL(finmasterid);
- if (idn_open_domain(finmasterid, fincpuid, 0) < 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s) failed to "
- "open-domain(%d,%d)",
- proc, finmasterid, fincpuid);
- if (finmasterid != domid)
- IDN_DUNLOCK(finmasterid);
- finmasterid = IDN_NIL_DOMID;
- }
- if (finmasterid != domid)
- IDN_DUNLOCK(finmasterid);
- }
-
- IDN_GLOCK_EXCL();
- if (finmasterid == IDN_NIL_DOMID) {
- int m;
-
- master_candidates = idn.domset.ds_trans_on |
- idn.domset.ds_connected |
- idn.domset.ds_relink;
- master_candidates &= ~(idn.domset.ds_trans_off &
- ~idn.domset.ds_relink);
- DOMAINSET_DEL(master_candidates, domid);
- /*
- * Local domain gets to participate also.
- */
- DOMAINSET_ADD(master_candidates, idn.localid);
-
- m = idn_select_candidate(master_candidates);
- IDN_SET_NEW_MASTERID(m);
- } else {
- IDN_SET_NEW_MASTERID(finmasterid);
- }
- IDN_GUNLOCK();
-
- dis_set = idn.domset.ds_trans_on | idn.domset.ds_connected;
- DOMAINSET_DEL(dis_set, domid);
-
- idn_unlink_domainset(dis_set, IDNFIN_NORMAL, IDNFIN_ARG_NONE,
- IDNFIN_OPT_RELINK, BOARDSET_ALL);
- } else {
- IDN_GUNLOCK();
- }
-
- /*
- * My local ready-set are those domains from which I
- * have confirmed no datapaths exist.
- */
- my_ready_set = ~idn.domset.ds_connected;
-
- switch (dp->dfin) {
- case IDNFIN_NORMAL:
- case IDNFIN_FORCE_SOFT:
- case IDNFIN_FORCE_HARD:
- if (fintype < dp->dfin) {
- /*
- * Remote domain has requested a
- * FIN of lower priority than what
- * we're currently running. Just
- * leave the priority where it is.
- */
- break;
- }
- /*FALLTHROUGH*/
-
- default:
- IDN_FSTATE_TRANSITION(dp, fintype);
- break;
- }
-
- ASSERT(dp->dfin_sync != IDNFIN_SYNC_OFF);
-
- if (msg == 0) {
- /*
- * Local domain is initiating a FIN sequence
- * to remote domid. Note that remote domain
- * remains in ds_connected even though he's
- * in thet ready-set from the local domain's
- * perspective. We can't remove him from
- * ds_connected until we get a confirmed message
- * from him indicating he has ceased communication.
- */
- ready_set = my_ready_set;
- } else {
- /*
- * Remote domain initiated a FIN sequence
- * to local domain. This implies that he
- * has shutdown his datapath to us. Since
- * we shutdown our datapath to him, we're
- * effectively now in his ready-set.
- */
- DOMAINSET_ADD(ready_set, idn.localid);
- /*
- * Since we know both sides of the connection
- * have ceased, this remote domain is effectively
- * considered disconnected.
- */
- DOMAINSET_ADD(idn.domset.ds_ready_off, domid);
- }
-
- if (dp->dfin == IDNFIN_FORCE_HARD) {
- /*
- * If we're doing a hard disconnect
- * of this domain then we want to
- * blow straight through and not
- * waste time trying to talk to the
- * remote domain nor to domains we
- * believe are AWOL. Although we will
- * try and do it cleanly with
- * everybody else.
- */
- DOMAINSET_ADD(my_ready_set, domid);
- my_ready_set |= idn.domset.ds_awol;
- ready_set = DOMAINSET_ALL;
-
- } else if (dp->dfin_sync == IDNFIN_SYNC_NO) {
- /*
- * If we're not fin'ing this domain
- * synchronously then the only
- * expected domain set is himself.
- */
- ready_set |= ~DOMAINSET(domid);
- my_ready_set |= ~DOMAINSET(domid);
- }
-
- if (dp->dsync.s_cmd != IDNSYNC_DISCONNECT) {
- idn_sync_exit(domid, IDNSYNC_CONNECT);
- idn_sync_enter(domid, IDNSYNC_DISCONNECT, DOMAINSET_ALL,
- my_ready_set, idn_xstate_transfunc, (void *)IDNP_FIN);
- }
-
- query_set = idn_sync_register(domid, IDNSYNC_DISCONNECT, ready_set,
- IDNSYNC_REG_REG);
-
- /*
- * No need to query this domain as he's already
- * in the FIN sequence.
- */
- DOMAINSET_DEL(query_set, domid);
-
- ready = (dp->dsync.s_set_exp == dp->dsync.s_set_rdy) ? 1 : 0;
- if (ready) {
- DOMAINSET_DEL(idn.domset.ds_ready_off, domid);
- DOMAINSET_DEL(idn.domset.ds_connected, domid);
- }
-
- if (query_set) {
- int d;
-
- my_ready_set = idn.domset.ds_ready_off |
- ~idn.domset.ds_connected;
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(query_set, d))
- continue;
-
- dp = &idn_domain[d];
-
- IDN_DLOCK_EXCL(d);
-
- if (dp->dsync.s_cmd == IDNSYNC_DISCONNECT) {
- IDN_DUNLOCK(d);
- continue;
- }
-
- IDN_SYNC_QUERY_UPDATE(domid, d);
-
- (void) idn_send_fin(d, NULL, IDNFIN_QUERY,
- IDNFIN_ARG_NONE, IDNFIN_OPT_NONE, my_ready_set,
- NIL_FIN_MASTER);
- IDN_DUNLOCK(d);
- }
- }
-
- return (!msg ? 0 : (ready ? 0 : 1));
-}
-
-/*ARGSUSED*/
-static void
-idn_error_fin_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- uint_t token;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- /*
- * Don't communicate with domains that
- * we're forcing a hard disconnect.
- */
- if ((idn_domain[domid].dfin != IDNFIN_FORCE_HARD) &&
- (msg & IDNP_MSGTYPE_MASK)) {
- idn_msgtype_t mt;
- idn_xdcargs_t nargs;
-
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
- mt.mt_cookie = mtp->mt_cookie;
- CLR_XARGS(nargs);
- SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY);
- idn_send_acknack(domid, &mt, nargs);
- }
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
-}
-
-static void
-idn_action_fin_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- idn_domain_t *dp = &idn_domain[domid];
- domainset_t my_ready_set;
- idn_finopt_t finopt;
- idn_finarg_t finarg;
- uint_t finmaster;
- int new_masterid, new_cpuid = IDN_NIL_DCPU;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_msgtype_t mt;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_off |
- ~idn.domset.ds_connected;
-
- ASSERT(xargs[0] != (uint_t)IDNFIN_QUERY);
-
- finarg = GET_XARGS_FIN_ARG(xargs);
- finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ?
- IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK;
-
- mt.mt_cookie = mtp ? mtp->mt_cookie : 0;
-
- IDN_GLOCK_SHARED();
- new_masterid = IDN_GET_NEW_MASTERID();
- IDN_GUNLOCK();
- if (new_masterid != IDN_NIL_DOMID)
- new_cpuid = idn_domain[new_masterid].dcpu;
- finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid);
-
- if (dp->dfin == IDNFIN_FORCE_HARD) {
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (!msg) {
- mt.mt_mtype = IDNP_FIN | IDNP_ACK;
- mt.mt_atype = 0;
- } else {
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = IDNP_FIN | IDNP_ACK;
- }
- (void) idn_xphase_transition(domid, &mt, xargs);
- } else if (!msg) {
- (void) idn_send_fin(domid, NULL, dp->dfin, finarg,
- finopt, my_ready_set, finmaster);
- } else if ((msg & IDNP_ACKNACK_MASK) == 0) {
- /*
- * fin
- */
- mt.mt_mtype = IDNP_FIN | IDNP_ACK;
- mt.mt_atype = 0;
- (void) idn_send_fin(domid, &mt, dp->dfin, finarg,
- finopt, my_ready_set, finmaster);
- } else {
- uint_t token;
- /*
- * nack - retry
- */
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
- }
-}
-
-static int
-idn_check_fin_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- int ready;
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- idn_fin_t fintype;
- idn_finopt_t finopt;
- idn_domain_t *dp = &idn_domain[domid];
- domainset_t query_set, ready_set;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK)
- return (0);
-
- fintype = GET_XARGS_FIN_TYPE(xargs);
- ready_set = GET_XARGS_FIN_DOMSET(xargs);
- finopt = GET_XARGS_FIN_OPT(xargs);
-
- ASSERT(fintype != IDNFIN_QUERY);
- if (!VALID_FIN(fintype)) {
- /*
- * If for some reason remote domain
- * sent us an invalid FIN type,
- * override it to a NORMAL fin.
- */
- fintype = IDNFIN_NORMAL;
- }
-
- if (!VALID_FINOPT(finopt)) {
- finopt = IDNFIN_OPT_UNLINK;
- }
- IDN_GLOCK_SHARED();
- if ((finopt == IDNFIN_OPT_RELINK) && (idn.state != IDNGS_DISCONNECT)) {
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate,
- idn.domset.ds_relink);
- } else {
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- }
- IDN_GUNLOCK();
-
- switch (dp->dfin) {
- case IDNFIN_NORMAL:
- case IDNFIN_FORCE_SOFT:
- case IDNFIN_FORCE_HARD:
- if (fintype < dp->dfin) {
- /*
- * Remote domain has requested a
- * FIN of lower priority than what
- * we're current running. Just
- * leave the priority where it is.
- */
- break;
- }
- /*FALLTHROUGH*/
-
- default:
- IDN_FSTATE_TRANSITION(dp, fintype);
- break;
- }
-
- if (dp->dfin == IDNFIN_FORCE_HARD) {
- /*
- * If we're doing a hard disconnect
- * of this domain then we want to
- * blow straight through and not
- * waste time trying to talk to the
- * remote domain. By registering him
- * as ready with respect to all
- * possible domains he'll transition
- * immediately. Note that we'll still
- * try and do it coherently with
- * other domains to which we're connected.
- */
- ready_set = DOMAINSET_ALL;
- } else {
- DOMAINSET_ADD(ready_set, idn.localid);
- }
-
- DOMAINSET_ADD(idn.domset.ds_ready_off, domid);
-
- query_set = idn_sync_register(domid, IDNSYNC_DISCONNECT,
- ready_set, IDNSYNC_REG_REG);
- /*
- * No need to query this domain as he's already
- * in the FIN sequence.
- */
- DOMAINSET_DEL(query_set, domid);
-
- ready = (dp->dsync.s_set_exp == dp->dsync.s_set_rdy) ? 1 : 0;
- if (ready) {
- DOMAINSET_DEL(idn.domset.ds_ready_off, domid);
- DOMAINSET_DEL(idn.domset.ds_connected, domid);
- }
-
- if (query_set) {
- int d;
- domainset_t my_ready_set;
-
- my_ready_set = idn.domset.ds_ready_off |
- ~idn.domset.ds_connected;
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(query_set, d))
- continue;
-
- dp = &idn_domain[d];
-
- IDN_DLOCK_EXCL(d);
-
- if (dp->dsync.s_cmd == IDNSYNC_DISCONNECT) {
- IDN_DUNLOCK(d);
- continue;
- }
-
- IDN_SYNC_QUERY_UPDATE(domid, d);
-
- (void) idn_send_fin(d, NULL, IDNFIN_QUERY,
- IDNFIN_ARG_NONE, IDNFIN_OPT_NONE, my_ready_set,
- NIL_FIN_MASTER);
- IDN_DUNLOCK(d);
- }
- }
-
- return ((ready > 0) ? 0 : 1);
-}
-
-/*ARGSUSED*/
-static void
-idn_error_fin_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- uint_t token;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- /*
- * Don't communicate with domains that
- * we're forcing a hard disconnect.
- */
- if ((idn_domain[domid].dfin != IDNFIN_FORCE_HARD) &&
- (msg & IDNP_MSGTYPE_MASK)) {
- idn_msgtype_t mt;
- idn_xdcargs_t nargs;
-
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = msg;
- mt.mt_cookie = mtp->mt_cookie;
- CLR_XARGS(nargs);
- SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY);
- idn_send_acknack(domid, &mt, nargs);
- }
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
-}
-
-static void
-idn_action_fin_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- int new_masterid, new_cpuid = IDN_NIL_DCPU;
- uint_t finmaster;
- idn_msgtype_t mt;
- idn_finopt_t finopt;
- idn_finarg_t finarg;
- domainset_t my_ready_set;
- idn_domain_t *dp = &idn_domain[domid];
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- mt.mt_cookie = mtp ? mtp->mt_cookie : 0;
-
- finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ?
- IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK;
-
- finarg = GET_XARGS_FIN_ARG(xargs);
-
- my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_off |
- ~idn.domset.ds_connected;
-
- IDN_GLOCK_SHARED();
- new_masterid = IDN_GET_NEW_MASTERID();
- IDN_GUNLOCK();
- if (new_masterid != IDN_NIL_DOMID)
- new_cpuid = idn_domain[new_masterid].dcpu;
- finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid);
-
- if ((msg & IDNP_ACKNACK_MASK) == 0) {
- /*
- * fin
- */
- if (dp->dfin == IDNFIN_FORCE_HARD) {
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = IDNP_FIN | IDNP_ACK;
- (void) idn_xphase_transition(domid, &mt, xargs);
- } else {
- mt.mt_mtype = IDNP_FIN | IDNP_ACK;
- mt.mt_atype = 0;
- (void) idn_send_fin(domid, &mt, dp->dfin, finarg,
- finopt, my_ready_set, finmaster);
- }
- } else if (msg & IDNP_MSGTYPE_MASK) {
- /*
- * fin+ack
- */
- if (dp->dfin != IDNFIN_FORCE_HARD) {
- idn_xdcargs_t fargs;
-
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = msg;
- CLR_XARGS(fargs);
- SET_XARGS_FIN_TYPE(fargs, dp->dfin);
- SET_XARGS_FIN_ARG(fargs, finarg);
- SET_XARGS_FIN_DOMSET(fargs, my_ready_set);
- SET_XARGS_FIN_OPT(fargs, finopt);
- SET_XARGS_FIN_MASTER(fargs, finmaster);
- idn_send_acknack(domid, &mt, fargs);
- }
- } else {
- uint_t token;
- /*
- * nack - retry
- */
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
- }
-}
-
-/*ARGSUSED*/
-static void
-idn_action_fin_rcvd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (msg & IDNP_NACK) {
- uint_t token;
- /*
- * nack - retry.
- */
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
- }
-}
-
-static void
-idn_final_fin(int domid)
-{
- int do_relink;
- int rv, d, new_masterid = IDN_NIL_DOMID;
- idn_gstate_t next_gstate;
- domainset_t relinkset;
- uint_t token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_domain_t *ldp, *dp = &idn_domain[domid];
- procname_t proc = "idn_final_fin";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(dp->dstate == IDNDS_DMAP);
-
- (void) idn_retry_terminate(token);
-
- dp->dxp = NULL;
- IDN_XSTATE_TRANSITION(dp, IDNXS_NIL);
-
- idn_sync_exit(domid, IDNSYNC_DISCONNECT);
-
- DOMAINSET_DEL(idn.domset.ds_trans_off, domid);
-
- do_relink = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ? 1 : 0;
-
- /*
- * idn_deconfig will idn_close_domain.
- */
- idn_deconfig(domid);
-
- PR_PROTO("%s:%d: DISCONNECTED\n", proc, domid);
-
- IDN_GLOCK_EXCL();
- /*
- * It's important that this update-op occur within
- * the context of holding the glock(EXCL). There is
- * still some additional state stuff to cleanup which
- * will be completed once the glock is dropped in
- * this flow. Which means anybody that's doing a
- * SSI_INFO and waiting on glock will not actually
- * run until the clean-up is completed, which is what
- * we want. Recall that a separate thread processes
- * the SSI_LINK/UNLINK calls and when they complete
- * (i.e. are awakened) they will immediately SSI_INFO
- * and we don't want them to prematurely pick up stale
- * information.
- */
- idn_update_op(IDNOP_DISCONNECTED, DOMAINSET(domid), NULL);
-
- ASSERT(idn.state != IDNGS_OFFLINE);
- ASSERT(!DOMAIN_IN_SET(idn.domset.ds_trans_on, domid));
-
- if (domid == IDN_GET_MASTERID()) {
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- dp->dvote.v.master = 0;
- }
-
- if ((domid == IDN_GET_NEW_MASTERID()) && !do_relink) {
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- }
-
- if (idn.state == IDNGS_RECONFIG)
- new_masterid = IDN_GET_NEW_MASTERID();
-
- if ((idn.domset.ds_trans_on | idn.domset.ds_trans_off |
- idn.domset.ds_relink) == 0) {
- PR_HITLIST("%s:%d: HITLIST %x -> 0\n",
- proc, domid, idn.domset.ds_hitlist);
- idn.domset.ds_hitlist = 0;
- }
-
- if (idn.domset.ds_connected || idn.domset.ds_trans_off) {
- PR_PROTO("%s:%d: ds_connected = 0x%x, ds_trans_off = 0x%x\n",
- proc, domid, idn.domset.ds_connected,
- idn.domset.ds_trans_off);
- IDN_GUNLOCK();
- goto fin_done;
- }
-
- IDN_DLOCK_EXCL(idn.localid);
- ldp = &idn_domain[idn.localid];
-
- if (idn.domset.ds_trans_on != 0) {
- ASSERT((idn.state != IDNGS_DISCONNECT) &&
- (idn.state != IDNGS_OFFLINE));
-
- switch (idn.state) {
- case IDNGS_CONNECT:
- if (idn.localid == IDN_GET_MASTERID()) {
- idn_master_deinit();
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- ldp->dvote.v.master = 0;
- }
- /*FALLTHROUGH*/
- case IDNGS_ONLINE:
- next_gstate = idn.state;
- break;
-
- case IDNGS_RECONFIG:
- if (idn.localid == IDN_GET_MASTERID()) {
- idn_master_deinit();
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- ldp->dvote.v.master = 0;
- }
- ASSERT(IDN_GET_MASTERID() == IDN_NIL_DOMID);
- next_gstate = IDNGS_CONNECT;
- ldp->dvote.v.connected = 0;
- /*
- * Need to do HWINIT since we won't
- * be transitioning through OFFLINE
- * which would normally be caught in
- * idn_check_nego() when we
- * initially go to CONNECT.
- */
- IDN_PREP_HWINIT();
- break;
-
- case IDNGS_DISCONNECT:
- case IDNGS_OFFLINE:
- cmn_err(CE_WARN,
- "IDN: 211: disconnect domain %d, "
- "unexpected Gstate (%s)",
- domid, idngs_str[idn.state]);
- IDN_DUNLOCK(idn.localid);
- IDN_GUNLOCK();
- goto fin_done;
-
- default:
- /*
- * XXX
- * Go into FATAL state?
- */
- cmn_err(CE_PANIC,
- "IDN: 212: disconnect domain %d, "
- "bad Gstate (%d)",
- domid, idn.state);
- /* not reached */
- break;
- }
- } else {
- if (idn.localid == IDN_GET_MASTERID()) {
- idn_master_deinit();
- IDN_SET_MASTERID(IDN_NIL_DOMID);
- ldp->dvote.v.master = 0;
- }
- next_gstate = IDNGS_OFFLINE;
- if (idn.domset.ds_relink == 0) {
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- }
- }
- IDN_DUNLOCK(idn.localid);
-
- /*
- * If we reach here we've effectively disconnected all
- * existing links, however new ones may be pending.
- */
- PR_PROTO("%s:%d: ALL DISCONNECTED *****************\n", proc, domid);
-
- IDN_GSTATE_TRANSITION(next_gstate);
-
- ASSERT((idn.state == IDNGS_OFFLINE) ?
- (IDN_GET_MASTERID() == IDN_NIL_DOMID) : 1);
-
- IDN_GUNLOCK();
-
- /*
- * If we have no new masterid and yet there are relinkers
- * out there, then force us to attempt to link with one
- * of them.
- */
- if ((new_masterid == IDN_NIL_DOMID) && idn.domset.ds_relink)
- new_masterid = idn.localid;
-
- if (new_masterid != IDN_NIL_DOMID) {
- /*
- * If the local domain is the selected
- * master then we'll want to initiate
- * a link with one of the other candidates.
- * If not, then we want to initiate a link
- * with the master only.
- */
- relinkset = (new_masterid == idn.localid) ?
- idn.domset.ds_relink : DOMAINSET(new_masterid);
-
- DOMAINSET_DEL(relinkset, idn.localid);
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- int lock_held;
-
- if (!DOMAIN_IN_SET(relinkset, d))
- continue;
-
- if (d == domid) {
- do_relink = 0;
- lock_held = 0;
- } else {
- IDN_DLOCK_EXCL(d);
- lock_held = 1;
- }
-
- rv = idn_open_domain(d, -1, 0);
- if (rv == 0) {
- rv = idn_connect(d);
- if (lock_held)
- IDN_DUNLOCK(d);
- /*
- * If we're able to kick off at
- * least one connect then that's
- * good enough for now. The others
- * will fall into place normally.
- */
- if (rv == 0)
- break;
- } else if (rv < 0) {
- if (lock_held)
- IDN_DUNLOCK(d);
- cmn_err(CE_WARN,
- "IDN: 205: (%s.1) failed to "
- "open-domain(%d,%d)",
- proc, domid, -1);
- DOMAINSET_DEL(idn.domset.ds_relink, d);
- } else {
- if (lock_held)
- IDN_DUNLOCK(d);
- PR_PROTO("%s:%d: failed to "
- "re-open domain %d "
- "(cpu %d) [rv = %d]\n",
- proc, domid, d, idn_domain[d].dcpu,
- rv);
- }
- }
- }
-
-fin_done:
- if (do_relink) {
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- rv = idn_open_domain(domid, -1, 0);
- if (rv == 0) {
- (void) idn_connect(domid);
- } else if (rv < 0) {
- cmn_err(CE_WARN,
- "IDN: 205: (%s.2) failed to "
- "open-domain(%d,%d)",
- proc, domid, -1);
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- }
- }
-}
-
-static void
-idn_exit_fin(int domid, uint_t msgtype)
-{
- idn_domain_t *dp = &idn_domain[domid];
- uint_t token;
- procname_t proc = "idn_exit_fin";
- STRING(str);
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- INUM2STR(msgtype, str);
- PR_PROTO("%s:%d: msgtype = 0x%x(%s)\n", proc, domid, msgtype, str);
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- (void) idn_retry_terminate(token);
-
- DOMAINSET_DEL(idn.domset.ds_ready_off, domid);
-
- dp->dxp = &xphase_fin;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
-
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
-}
-
-/*
- * Must return w/locks held.
- */
-static int
-idn_xphase_transition(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- uint_t msgarg = mtp ? mtp->mt_atype : 0;
- idn_xphase_t *xp;
- idn_domain_t *dp;
- int (*cfunc)(int, idn_msgtype_t *, idn_xdcargs_t);
- void (*ffunc)(int);
- void (*afunc)(int, idn_msgtype_t *, idn_xdcargs_t);
- void (*efunc)(int, idn_msgtype_t *, idn_xdcargs_t);
- void (*xfunc)(int, uint_t);
- int err = 0;
- uint_t msgtype;
- idn_xstate_t o_xstate, n_xstate;
- procname_t proc = "idn_xphase_transition";
- STRING(mstr);
- STRING(astr);
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- INUM2STR(msg, mstr);
- INUM2STR(msgarg, astr);
-
- dp = &idn_domain[domid];
- if ((xp = dp->dxp) == NULL) {
- PR_PROTO("%s:%d: WARNING: domain xsp is NULL (msg = %s, "
- "msgarg = %s) <<<<<<<<<<<<\n",
- proc, domid, mstr, astr);
- return (-1);
- }
- o_xstate = dp->dxstate;
-
- xfunc = xp->xt_exit;
-
- if ((msgtype = (msg & IDNP_MSGTYPE_MASK)) == 0)
- msgtype = msgarg & IDNP_MSGTYPE_MASK;
-
- if ((o_xstate == IDNXS_PEND) && msg &&
- ((msg & IDNP_ACKNACK_MASK) == msg)) {
- PR_PROTO("%s:%d: unwanted acknack received (o_xstate = %s, "
- "msg = %s/%s - dropping message\n",
- proc, domid, idnxs_str[(int)o_xstate], mstr, astr);
- return (0);
- }
-
- /*
- * Validate that message received is following
- * the expected protocol for the current state.
- */
- if (idn_next_xstate(o_xstate, -1, msg) == IDNXS_NIL) {
- PR_PROTO("%s:%d: WARNING: o_xstate = %s, msg = %s -> NIL "
- "<<<<<<<<<\n",
- proc, domid, idnxs_str[(int)o_xstate], mstr);
- if (xfunc)
- (*xfunc)(domid, msgtype);
- return (-1);
- }
-
- if (msg || msgarg) {
- /*
- * Verify that message type is correct for
- * the given xstate.
- */
- if (msgtype != xp->xt_msgtype) {
- STRING(xstr);
- STRING(tstr);
-
- INUM2STR(xp->xt_msgtype, xstr);
- INUM2STR(msgtype, tstr);
- PR_PROTO("%s:%d: WARNING: msg expected %s(0x%x), "
- "actual %s(0x%x) [msg=%s(0x%x), "
- "msgarg=%s(0x%x)]\n",
- proc, domid, xstr, xp->xt_msgtype,
- tstr, msgtype, mstr, msg, astr, msgarg);
- if (xfunc)
- (*xfunc)(domid, msgtype);
- return (-1);
- }
- }
-
- cfunc = xp->xt_trans[(int)o_xstate].t_check;
-
- if (cfunc && ((err = (*cfunc)(domid, mtp, xargs)) < 0)) {
- if (o_xstate != IDNXS_PEND) {
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- }
- if (xfunc)
- (*xfunc)(domid, msgtype);
- return (-1);
- }
-
- n_xstate = idn_next_xstate(o_xstate, err, msg);
-
- if (n_xstate == IDNXS_NIL) {
- PR_PROTO("%s:%d: WARNING: n_xstate = %s, msg = %s -> NIL "
- "<<<<<<<<<\n",
- proc, domid, idnxs_str[(int)n_xstate], mstr);
- if (xfunc)
- (*xfunc)(domid, msgtype);
- return (-1);
- }
-
- if (n_xstate != o_xstate) {
- IDN_XSTATE_TRANSITION(dp, n_xstate);
- }
-
- if (err) {
- if ((efunc = xp->xt_trans[(int)o_xstate].t_error) != NULL)
- (*efunc)(domid, mtp, xargs);
- } else if ((afunc = xp->xt_trans[(int)o_xstate].t_action) != NULL) {
- (*afunc)(domid, mtp, xargs);
- }
-
- if ((n_xstate == IDNXS_FINAL) && ((ffunc = xp->xt_final) != NULL))
- (*ffunc)(domid);
-
- return (0);
-}
-
-/*
- * Entered and returns w/DLOCK & SYNC_LOCK held.
- */
-static int
-idn_xstate_transfunc(int domid, void *transarg)
-{
- uint_t msg = (uint_t)(uintptr_t)transarg;
- uint_t token;
- procname_t proc = "idn_xstate_transfunc";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
-
- switch (msg) {
- case IDNP_CON:
- DOMAINSET_ADD(idn.domset.ds_connected, domid);
- break;
-
- case IDNP_FIN:
- DOMAINSET_DEL(idn.domset.ds_connected, domid);
- break;
-
- default:
- PR_PROTO("%s:%d: ERROR: unknown msg (0x%x) <<<<<<<<\n",
- proc, domid, msg);
- return (0);
- }
-
- token = IDN_RETRY_TOKEN(domid, (msg == IDNP_CON) ?
- IDNRETRY_CON : IDNRETRY_FIN);
- if (msg == IDNP_CON)
- idn_retry_submit(idn_retry_con, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_CON]);
- else
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
-
- return (1);
-}
-
-/*
- * Entered and returns w/DLOCK & SYNC_LOCK held.
- */
-static void
-idn_sync_enter(int domid, idn_synccmd_t cmd, domainset_t xset,
- domainset_t rset, int (*transfunc)(), void *transarg)
-{
- int z;
- idn_syncop_t *sp;
- idn_synczone_t *zp;
- procname_t proc = "idn_sync_enter";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- z = IDN_SYNC_GETZONE(cmd);
- ASSERT(z >= 0);
- zp = &idn.sync.sz_zone[z];
-
- PR_SYNC("%s:%d: cmd=%s(%d), z=%d, xs=0x%x, rx=0x%x, cnt=%d\n",
- proc, domid, idnsync_str[cmd], cmd, z, xset, rset, zp->sc_cnt);
-
- sp = &idn_domain[domid].dsync;
-
- sp->s_domid = domid;
- sp->s_cmd = cmd;
- sp->s_msg = 0;
- sp->s_set_exp = xset;
- sp->s_set_rdy = rset;
- sp->s_transfunc = transfunc;
- sp->s_transarg = transarg;
- IDN_SYNC_QUERY_INIT(domid);
-
- sp->s_next = zp->sc_op;
- zp->sc_op = sp;
- zp->sc_cnt++;
-}
-
-/*
- * Entered and returns w/DLOCK & SYNC_LOCK held.
- */
-void
-idn_sync_exit(int domid, idn_synccmd_t cmd)
-{
- int d, z, zone, tot_queries, tot_domains;
- idn_syncop_t *sp;
- idn_synczone_t *zp = NULL;
- procname_t proc = "idn_sync_exit";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- sp = &idn_domain[domid].dsync;
-
- z = IDN_SYNC_GETZONE(sp->s_cmd);
-
- zone = IDN_SYNC_GETZONE(cmd);
-
- PR_SYNC("%s:%d: cmd=%s(%d) (z=%d, zone=%d)\n",
- proc, domid, idnsync_str[cmd], cmd, z, zone);
-
-#ifdef DEBUG
- if (z != -1) {
- tot_queries = tot_domains = 0;
-
- for (d = 0; d < MAX_DOMAINS; d++) {
- int qv;
-
- if ((qv = sp->s_query[d]) > 0) {
- tot_queries += qv;
- tot_domains++;
- PR_SYNC("%s:%d: query_count = %d\n",
- proc, domid, qv);
- }
- }
- PR_SYNC("%s:%d: tot_queries = %d, tot_domaines = %d\n",
- proc, domid, tot_queries, tot_domains);
- }
-#endif /* DEBUG */
-
- zp = (z != -1) ? &idn.sync.sz_zone[z] : NULL;
-
- if (zp) {
- idn_syncop_t **spp;
-
- for (spp = &zp->sc_op; *spp; spp = &((*spp)->s_next)) {
- if (*spp == sp) {
- *spp = sp->s_next;
- sp->s_next = NULL;
- zp->sc_cnt--;
- break;
- }
- }
- }
-
- sp->s_cmd = IDNSYNC_NIL;
-
- for (z = 0; z < IDN_SYNC_NUMZONE; z++) {
- idn_syncop_t **spp, **nspp;
-
- if ((zone != -1) && (z != zone))
- continue;
-
- zp = &idn.sync.sz_zone[z];
-
- for (spp = &zp->sc_op; *spp; spp = nspp) {
- sp = *spp;
- nspp = &sp->s_next;
-
- if (!DOMAIN_IN_SET(sp->s_set_exp, domid))
- continue;
-
- DOMAINSET_DEL(sp->s_set_exp, domid);
- DOMAINSET_DEL(sp->s_set_rdy, domid);
-
- if ((sp->s_set_exp == sp->s_set_rdy) &&
- sp->s_transfunc) {
- int delok;
-
- ASSERT(sp->s_domid != domid);
-
- PR_SYNC("%s:%d invoking transfunc "
- "for domain %d\n",
- proc, domid, sp->s_domid);
- delok = (*sp->s_transfunc)(sp->s_domid,
- sp->s_transarg);
- if (delok) {
- *spp = sp->s_next;
- sp->s_next = NULL;
- zp->sc_cnt--;
- nspp = spp;
- }
- }
- }
- }
-}
-
-/*
- * Entered and returns w/DLOCK & SYNC_LOCK held.
- */
-static domainset_t
-idn_sync_register(int domid, idn_synccmd_t cmd, domainset_t ready_set,
- idn_syncreg_t regtype)
-{
- int z;
- idn_synczone_t *zp;
- idn_syncop_t *sp, **spp, **nspp;
- domainset_t query_set = 0, trans_set;
- procname_t proc = "idn_sync_register";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if ((z = IDN_SYNC_GETZONE(cmd)) == -1) {
- PR_SYNC("%s:%d: ERROR: unexpected sync cmd(%d)\n",
- proc, domid, cmd);
- return (0);
- }
-
- /*
- * Find out what domains are in transition with respect
- * to given command. There will be no need to query
- * these folks.
- */
- trans_set = IDN_SYNC_GETTRANS(cmd);
-
- zp = &idn.sync.sz_zone[z];
-
- PR_SYNC("%s:%d: cmd=%s(%d), z=%d, rset=0x%x, "
- "regtype=%s(%d), sc_op=%s\n",
- proc, domid, idnsync_str[cmd], cmd, z, ready_set,
- idnreg_str[regtype], regtype,
- zp->sc_op ? idnsync_str[zp->sc_op->s_cmd] : "NULL");
-
- for (spp = &zp->sc_op; *spp; spp = nspp) {
- sp = *spp;
- nspp = &sp->s_next;
-
- if (regtype == IDNSYNC_REG_NEW) {
- DOMAINSET_ADD(sp->s_set_exp, domid);
- PR_SYNC("%s:%d: adding new to %d (exp=0x%x)\n",
- proc, domid, sp->s_domid, sp->s_set_exp);
- } else if (regtype == IDNSYNC_REG_QUERY) {
- query_set |= ~sp->s_set_rdy & sp->s_set_exp;
- continue;
- }
-
- if (!DOMAIN_IN_SET(sp->s_set_exp, domid))
- continue;
-
- if (!DOMAIN_IN_SET(ready_set, sp->s_domid)) {
- /*
- * Given domid doesn't have a desired
- * domain in his ready-set. We'll need
- * to query him again.
- */
- DOMAINSET_ADD(query_set, domid);
- continue;
- }
-
- /*
- * If we reach here, then an expected domain
- * has marked its respective datapath to
- * sp->s_domid as down (i.e. in his ready_set).
- */
- DOMAINSET_ADD(sp->s_set_rdy, domid);
-
- PR_SYNC("%s:%d: mark READY for domain %d "
- "(r=0x%x, x=0x%x)\n",
- proc, domid, sp->s_domid,
- sp->s_set_rdy, sp->s_set_exp);
-
- query_set |= ~sp->s_set_rdy & sp->s_set_exp;
-
- if (sp->s_set_exp == sp->s_set_rdy) {
-#ifdef DEBUG
- if (sp->s_msg == 0) {
- sp->s_msg = 1;
- PR_SYNC("%s:%d: >>>>>>>>>>> DOMAIN %d "
- "ALL CHECKED IN (0x%x)\n",
- proc, domid, sp->s_domid,
- sp->s_set_exp);
- }
-#endif /* DEBUG */
-
- if ((sp->s_domid != domid) && sp->s_transfunc) {
- int delok;
-
- PR_SYNC("%s:%d invoking transfunc "
- "for domain %d\n",
- proc, domid, sp->s_domid);
- delok = (*sp->s_transfunc)(sp->s_domid,
- sp->s_transarg);
- if (delok) {
- *spp = sp->s_next;
- sp->s_next = NULL;
- zp->sc_cnt--;
- nspp = spp;
- }
- }
- }
- }
-
- PR_SYNC("%s:%d: trans_set = 0x%x, query_set = 0x%x -> 0x%x\n",
- proc, domid, trans_set, query_set, query_set & ~trans_set);
-
- query_set &= ~trans_set;
-
- return (query_set);
-}
-
-static void
-idn_sync_register_awol(int domid)
-{
- int z;
- idn_synccmd_t cmd = IDNSYNC_DISCONNECT;
- idn_synczone_t *zp;
- idn_syncop_t *sp;
- procname_t proc = "idn_sync_register_awol";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
-
- if ((z = IDN_SYNC_GETZONE(cmd)) == -1) {
- PR_SYNC("%s:%d: ERROR: unexpected sync cmd(%d)\n",
- proc, domid, cmd);
- return;
- }
-
- zp = &idn.sync.sz_zone[z];
-
- PR_SYNC("%s:%d: cmd=%s(%d), z=%d (domain %d = AWOL)\n",
- proc, domid, idnsync_str[cmd], cmd, z, domid);
-
- for (sp = zp->sc_op; sp; sp = sp->s_next) {
- idn_domain_t *dp;
-
- dp = &idn_domain[sp->s_domid];
- if (dp->dfin == IDNFIN_FORCE_HARD) {
- DOMAINSET_ADD(sp->s_set_rdy, domid);
- PR_SYNC("%s:%d: adding new to %d (rdy=0x%x)\n",
- proc, domid, sp->s_domid, sp->s_set_rdy);
- }
- }
-}
-
-static void
-idn_link_established(void *arg)
-{
- int first_link;
- int domid, masterid;
- uint_t info = (uint_t)(uintptr_t)arg;
-
- first_link = (int)(info & 0xf0);
- domid = (int)(info & 0x0f);
-
- IDN_GLOCK_SHARED();
- masterid = IDN_GET_MASTERID();
- if ((masterid == IDN_NIL_DOMID) ||
- (idn_domain[masterid].dstate != IDNDS_CONNECTED)) {
- /*
- * No point in doing this unless we're connected
- * to the master.
- */
- if ((masterid != IDN_NIL_DOMID) &&
- (idn.state == IDNGS_ONLINE)) {
- /*
- * As long as we're still online keep
- * trying.
- */
- (void) timeout(idn_link_established, arg, 50);
- }
- IDN_GUNLOCK();
- return;
- }
- IDN_GUNLOCK();
-
- if (first_link && IDN_SLAB_PREALLOC)
- idn_prealloc_slab(IDN_SLAB_PREALLOC);
-
- /*
- * No guarantee, but it might save a little
- * time.
- */
- if (idn_domain[domid].dstate == IDNDS_CONNECTED) {
- /*
- * Get the remote domain's dname.
- */
- idn_send_nodename_req(domid);
- }
-
- /*
- * May have had some streams backed up waiting for
- * this connection. Prod them.
- */
- rw_enter(&idn.struprwlock, RW_READER);
- mutex_enter(&idn.sipwenlock);
- idndl_wenable(NULL);
- mutex_exit(&idn.sipwenlock);
- rw_exit(&idn.struprwlock);
-}
-
-/*
- * Send the following chunk of data received from above onto
- * the IDN wire. This is raw data as far as the IDN driver
- * is concerned.
- * Returns:
- * IDNXMIT_LOOP - Msg handled in loopback and thus
- * still active (i.e. don't free).
- * IDNXMIT_OKAY - Data handled (freemsg).
- * IDNXMIT_DROP - Packet should be dropped.
- * IDNXMIT_RETRY - Packet should be requeued and retried.
- * IDNXMIT_REQUEUE - Packet should be requeued, but not
- * immediatetly retried.
- */
-int
-idn_send_data(int dst_domid, idn_netaddr_t dst_netaddr, queue_t *wq, mblk_t *mp)
-{
- int pktcnt = 0;
- int msglen;
- int rv = IDNXMIT_OKAY;
- int xfersize = 0;
- caddr_t iobufp, iodatap;
- uchar_t *data_rptr;
- int cpuindex;
- int serrno;
- int channel;
- int retry_reclaim;
- idn_chansvr_t *csp = NULL;
- uint_t netports = 0;
- struct idnstr *stp;
- struct idn *sip;
- idn_domain_t *dp;
- struct ether_header *ehp;
- smr_pkthdr_t *hdrp;
- idn_msgtype_t mt;
- procname_t proc = "idn_send_data";
-#ifdef DEBUG
- size_t orig_msglen = msgsize(mp);
-#endif /* DEBUG */
-
- ASSERT(DB_TYPE(mp) == M_DATA);
-
- mt.mt_mtype = IDNP_DATA;
- mt.mt_atype = 0;
- mt.mt_cookie = 0;
-
- channel = (int)dst_netaddr.net.chan;
-
- msglen = msgdsize(mp);
- PR_DATA("%s:%d: (netaddr 0x%x) msgsize=%ld, msgdsize=%d\n",
- proc, dst_domid, dst_netaddr.netaddr, msgsize(mp), msglen);
-
- ASSERT(wq->q_ptr);
-
- stp = (struct idnstr *)wq->q_ptr;
- sip = stp->ss_sip;
- ASSERT(sip);
-
- if (msglen < 0) {
- /*
- * No data to send. That was easy!
- */
- PR_DATA("%s:%d: BAD msg length (%d) (netaddr 0x%x)\n",
- proc, dst_domid, msglen, dst_netaddr.netaddr);
- return (IDNXMIT_DROP);
- }
-
- ASSERT(RW_READ_HELD(&stp->ss_rwlock));
-
- if (dst_domid == IDN_NIL_DOMID) {
- cmn_err(CE_WARN,
- "IDN: 213: no destination specified "
- "(d=%d, c=%d, n=0x%x)",
- dst_domid, dst_netaddr.net.chan,
- dst_netaddr.net.netid);
- IDN_KSTAT_INC(sip, si_nolink);
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- rv = IDNXMIT_DROP;
- goto nocando;
- }
-
- ehp = (struct ether_header *)mp->b_rptr;
- PR_DATA("%s:%d: destination channel = %d\n", proc, dst_domid, channel);
-
-#ifdef DEBUG
- {
- uchar_t echn;
-
- echn = (uchar_t)
- ehp->ether_shost.ether_addr_octet[IDNETHER_CHANNEL];
- ASSERT((uchar_t)channel == echn);
- }
-#endif /* DEBUG */
- ASSERT(msglen <= IDN_DATA_SIZE);
-
- dp = &idn_domain[dst_domid];
- /*
- * Get reader lock. We hold for the duration
- * of the transfer so that our state doesn't
- * change during this activity. Note that since
- * we grab the reader lock, we can still permit
- * simultaneous tranfers from different threads
- * to the same domain.
- * Before we waste a bunch of time gathering locks, etc.
- * do a an unprotected check to make sure things are
- * semi-copesetic. If these values are in flux,
- * that's okay.
- */
- if ((dp->dstate != IDNDS_CONNECTED) || (idn.state != IDNGS_ONLINE)) {
- IDN_KSTAT_INC(sip, si_linkdown);
- if (idn.state != IDNGS_ONLINE) {
- rv = IDNXMIT_REQUEUE;
- } else {
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- rv = IDNXMIT_DROP;
- }
- goto nocando;
- }
-
- if (idn.chan_servers[channel].ch_send.c_checkin) {
- /*
- * Gotta bail, somethin' s'up.
- */
- rv = IDNXMIT_REQUEUE;
- goto nocando;
- }
-
- csp = &idn.chan_servers[channel];
- IDN_CHAN_LOCK_SEND(csp);
-
- if (dst_netaddr.net.netid == IDN_BROADCAST_ALLNETID) {
- /*
- * We're doing a broadcast. Need to set
- * up IDN netaddr's one at a time.
- * We set the ethernet destination to the same
- * instance as the sending address. The instance
- * numbers effectively represent subnets.
- */
- dst_netaddr.net.netid = dp->dnetid;
-
- (void) idndl_domain_etheraddr(dst_domid, channel,
- &ehp->ether_dhost);
-
- if (dst_domid == idn.localid) {
- mblk_t *nmp;
- /*
- * If this is a broadcast and going to
- * the local domain, then we need to make
- * a private copy of the message since
- * the current one will be reused when
- * transmitting to other domains.
- */
- PR_DATA("%s:%d: dup broadcast msg for local domain\n",
- proc, dst_domid);
- if ((nmp = copymsg(mp)) == NULL) {
- /*
- * Couldn't get a duplicate copy.
- */
- IDN_CHAN_UNLOCK_SEND(csp);
- csp = NULL;
- IDN_KSTAT_INC(sip, si_allocbfail);
- IDN_KSTAT_INC(sip, si_noxmtbuf);
- rv = IDNXMIT_DROP;
- goto nocando;
- }
- mp = nmp;
- }
- }
-
- if (dp->dnetid != dst_netaddr.net.netid) {
- PR_DATA("%s:%d: dest netid (0x%x) != expected (0x%x)\n",
- proc, dst_domid, (uint_t)dst_netaddr.net.netid,
- (uint_t)dp->dnetid);
- IDN_CHAN_UNLOCK_SEND(csp);
- csp = NULL;
- IDN_KSTAT_INC(sip, si_nolink);
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- rv = IDNXMIT_DROP;
- goto nocando;
- }
-
- if (dst_domid == idn.localid) {
- int lbrv;
- /*
- * Sending to our local domain! Loopback.
- * Note that idn_send_data_loop returning 0
- * does not mean the message can now be freed.
- * We need to return (-1) so that caller doesn't
- * try to free mblk.
- */
- IDN_CHAN_UNLOCK_SEND(csp);
- rw_exit(&stp->ss_rwlock);
- lbrv = idn_send_data_loopback(dst_netaddr, wq, mp);
- rw_enter(&stp->ss_rwlock, RW_READER);
- if (lbrv == 0) {
- return (IDNXMIT_LOOP);
- } else {
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- return (IDNXMIT_DROP);
- }
- }
-
- if (dp->dstate != IDNDS_CONNECTED) {
- /*
- * Can't send data unless a link has already been
- * established with the target domain. Normally,
- * a user cannot set the remote netaddr unless a
- * link has already been established, however it
- * is possible the connection may have become
- * disconnected since that time.
- */
- IDN_CHAN_UNLOCK_SEND(csp);
- csp = NULL;
- IDN_KSTAT_INC(sip, si_linkdown);
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- rv = IDNXMIT_DROP;
- goto nocando;
- }
-
- /*
- * Need to make sure the channel is active and that the
- * domain to which we're sending is allowed to receive stuff.
- */
- if (!IDN_CHANNEL_IS_SEND_ACTIVE(csp)) {
- int not_active;
- /*
- * See if we can activate channel.
- */
- IDN_CHAN_UNLOCK_SEND(csp);
- not_active = idn_activate_channel(CHANSET(channel),
- IDNCHAN_OPEN);
- if (!not_active) {
- /*
- * Only grab the lock for a recheck if we were
- * able to activate the channel.
- */
- IDN_CHAN_LOCK_SEND(csp);
- }
- /*
- * Verify channel still active now that we have the lock.
- */
- if (not_active || !IDN_CHANNEL_IS_SEND_ACTIVE(csp)) {
- if (!not_active) {
- /*
- * Only need to drop the lock if it was
- * acquired while we thought we had
- * activated the channel.
- */
- IDN_CHAN_UNLOCK_SEND(csp);
- }
- ASSERT(!IDN_CHAN_SEND_IS_LOCKED(csp));
- /*
- * Damn! Must have went inactive during the window
- * before we regrabbed the send lock. Oh well, can't
- * spend all day doing this, bail out. Set csp to
- * NULL to prevent inprogress update at bottom.
- */
- csp = NULL;
- /*
- * Channel is not active, should not be used.
- */
- PR_DATA("%s:%d: dest channel %d NOT ACTIVE\n",
- proc, dst_domid, channel);
- IDN_KSTAT_INC(sip, si_linkdown);
- rv = IDNXMIT_REQUEUE;
- goto nocando;
- }
- ASSERT(IDN_CHAN_SEND_IS_LOCKED(csp));
- }
- /*
- * If we made it here then the channel is active
- * Make sure the target domain is registered to receive stuff,
- * i.e. we're still linked.
- */
- if (!IDN_CHAN_DOMAIN_IS_REGISTERED(csp, dst_domid)) {
- /*
- * If domain is not even registered with this channel
- * then we have no business being here. Doesn't matter
- * whether it's active or not.
- */
- PR_DATA("%s:%d: domain not registered with channel %d\n",
- proc, dst_domid, channel);
- /*
- * Set csp to NULL to prevent in-progress update below.
- */
- IDN_CHAN_UNLOCK_SEND(csp);
- csp = NULL;
- IDN_KSTAT_INC(sip, si_linkdown);
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- rv = IDNXMIT_DROP;
- goto nocando;
- }
-
- IDN_CHAN_SEND_INPROGRESS(csp);
- IDN_CHAN_UNLOCK_SEND(csp);
-
- /*
- * Find a target cpu to send interrupt to if
- * it becomes necessary (i.e. remote channel
- * server is idle).
- */
- cpuindex = dp->dcpuindex;
-
- /*
- * dcpuindex is atomically incremented, but other than
- * that is not well protected and that's okay. The
- * intention is to simply spread around the interrupts
- * at the destination domain, however we don't have to
- * anal about it. If we hit the same cpu multiple times
- * in a row that's okay, it will only be for a very short
- * period anyway before the cpuindex is incremented
- * to the next cpu.
- */
- if (cpuindex < NCPU) {
- ATOMIC_INC(dp->dcpuindex);
- }
- if (dp->dcpuindex >= NCPU)
- dp->dcpuindex = 0;
-
- IDN_ASSIGN_DCPU(dp, cpuindex);
-
-#ifdef XXX_DLPI_UNFRIENDLY
- {
- ushort_t dstport = (ushort_t)dp->dcpu;
-
- /*
- * XXX
- * This is not DLPI friendly, but we need some way
- * of distributing our XDC interrupts to the cpus
- * on the remote domain in a relatively random fashion
- * while trying to remain constant for an individual
- * network connection. Don't want the target network
- * appl pinging around cpus thrashing the caches.
- * So, we'll pick target cpus based on the destination
- * TCP/IP port (socket). The (simple) alternative to
- * this is to simply send all messages destined for
- * particular domain to the same cpu (dcpu), but
- * will lower our bandwidth and introduce a lot of
- * contention on that target cpu.
- */
- if (ehp->ether_type == ETHERTYPE_IP) {
- ipha_t *ipha;
- uchar_t *dstporta;
- int hdr_length;
- mblk_t *nmp = mp;
- uchar_t *rptr = mp->b_rptr +
- sizeof (struct ether_header);
- if (nmp->b_wptr <= rptr) {
- /*
- * Only the ethernet header was contained
- * in the first block. Check for the
- * next packet.
- */
- if ((nmp = mp->b_cont) != NULL)
- rptr = nmp->b_rptr;
- }
- /*
- * If we still haven't found the IP header packet
- * then don't bother. Can't search forever.
- */
- if (nmp &&
- ((nmp->b_wptr - rptr) >= IP_SIMPLE_HDR_LENGTH)) {
- ipha = (ipha_t *)ALIGN32(rptr);
-
- ASSERT(DB_TYPE(mp) == M_DATA);
- hdr_length = IPH_HDR_LENGTH(ipha);
-
- switch (ipha->ipha_protocol) {
- case IPPROTO_UDP:
- case IPPROTO_TCP:
- /*
- * TCP/UDP Protocol Header (1st word)
- * 0 15,16 31
- * -----------------------
- * | src port | dst port |
- * -----------------------
- */
- dstporta = (uchar_t *)ipha + hdr_length;
- netports = *(uint_t *)dstporta;
- dstporta += 2;
- dstport = *(ushort_t *)dstporta;
- break;
- default:
- break;
- }
- }
-
- }
- IDN_ASSIGN_DCPU(dp, dstport);
-
- PR_DATA("%s:%d: (dstport %d) assigned %d\n",
- proc, dst_domid, (int)dstport, dp->dcpu);
- }
-#endif /* XXX_DLPI_UNFRIENDLY */
-
- data_rptr = mp->b_rptr;
-
- ASSERT(dp->dcpu != IDN_NIL_DCPU);
-
- ASSERT(idn_domain[dst_domid].dmbox.m_send);
-
- retry_reclaim = 1;
-retry:
- if ((dp->dio >= IDN_RECLAIM_MIN) || dp->diowanted) {
- int reclaim_req;
- /*
- * Reclaim however many outstanding buffers
- * there are up to IDN_RECLAIM_MAX if it's set.
- */
- reclaim_req = dp->diowanted ? -1 : IDN_RECLAIM_MAX ?
- MIN(dp->dio, IDN_RECLAIM_MAX) : dp->dio;
- (void) idn_reclaim_mboxdata(dst_domid, channel,
- reclaim_req);
- }
-
- if (dp->dio >= IDN_WINDOW_EMAX) {
-
- if (lock_try(&dp->diocheck)) {
- IDN_MSGTIMER_START(dst_domid, IDNP_DATA, 0,
- idn_msg_waittime[IDNP_DATA],
- &mt.mt_cookie);
- /*
- * We have exceeded the minimum window for
- * outstanding I/O buffers to this domain.
- * Need to start the MSG timer to check for
- * possible response from remote domain.
- * The remote domain may be hung. Send a
- * wakeup! Specify all channels for given
- * domain since we don't know precisely which
- * is backed up (dio is global).
- */
- IDNXDC(dst_domid, &mt,
- (uint_t)dst_netaddr.net.chan, 0, 0, 0);
- }
-
- /*
- * Yikes! We have exceeded the maximum window
- * which means no more packets going to remote
- * domain until he frees some up.
- */
- IDN_KSTAT_INC(sip, si_txmax);
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- rv = IDNXMIT_DROP;
- goto nocando;
- }
-
- /*
- * Allocate a SMR I/O buffer and send it.
- */
- if (msglen == 0) {
- /*
- * A zero length messages is effectively a signal
- * to just send an interrupt to the remote domain.
- */
- IDN_MSGTIMER_START(dst_domid, IDNP_DATA, 0,
- idn_msg_waittime[IDNP_DATA],
- &mt.mt_cookie);
- IDNXDC(dst_domid, &mt,
- (uint_t)dst_netaddr.net.chan, 0, 0, 0);
- }
- for (; (msglen > 0) && mp; msglen -= xfersize) {
- int xrv;
- smr_offset_t bufoffset;
-#ifdef DEBUG
- int n_xfersize;
-#endif /* DEBUG */
-
- ASSERT(msglen <= IDN_DATA_SIZE);
- xfersize = msglen;
-
- serrno = smr_buf_alloc(dst_domid, xfersize, &iobufp);
- if (serrno) {
- PR_DATA("%s:%d: failed to alloc SMR I/O buffer "
- "(serrno = %d)\n",
- proc, dst_domid, serrno);
- /*
- * Failure is either due to a timeout waiting
- * for the master to give us a slab, OR the
- * local domain exhausted its slab quota!
- * In either case we'll have to bail from
- * here and let higher layers decide what
- * to do.
- * We also could have had locking problems.
- * A negative serrno indicates we lost the lock
- * on dst_domid, so no need in dropping lock.
- */
-
- if (lock_try(&dp->diowanted) && retry_reclaim) {
- /*
- * We were the first to acquire the
- * lock indicating that it wasn't
- * set on entry to idn_send_data.
- * So, let's go back and see if we
- * can't reclaim some buffers and
- * try again.
- * It's very likely diowanted will be
- * enough to prevent us from looping
- * on retrying here, however to protect
- * against the small window where a
- * race condition might exist, we use
- * the retry_reclaim flag so that we
- * don't retry more than once.
- */
- retry_reclaim = 0;
- goto retry;
- }
-
- rv = (serrno > 0) ? serrno : -serrno;
- IDN_KSTAT_INC(sip, si_notbufs);
- IDN_KSTAT_INC(sip, si_noxmtbuf); /* MIB II */
- switch (rv) {
- case ENOMEM:
- case EBUSY:
- case ENOLCK:
- case ETIMEDOUT:
- case EDQUOT:
- /*
- * These are all transient conditions
- * which should be recoverable over
- * time.
- */
- rv = IDNXMIT_REQUEUE;
- break;
-
- default:
- rv = IDNXMIT_DROP;
- break;
- }
- goto nocando;
- }
-
- lock_clear(&dp->diowanted);
-
- hdrp = IDN_BUF2HDR(iobufp);
- bufoffset = (smr_offset_t)IDN_ALIGNPTR(sizeof (smr_pkthdr_t),
- data_rptr);
- /*
- * If the alignment of bufoffset took us pass the
- * length of a smr_pkthdr_t then we need to possibly
- * lower xfersize since it was calulated based on
- * a perfect alignment. However, if we're in DLPI
- * mode then shouldn't be necessary since the length
- * of the incoming packet (mblk) should have already
- * taken into consideration this possible adjustment.
- */
-#ifdef DEBUG
- if (bufoffset != sizeof (smr_pkthdr_t))
- PR_DATA("%s:%d: offset ALIGNMENT (%lu -> %u) "
- "(data_rptr = %p)\n",
- proc, dst_domid, sizeof (smr_pkthdr_t),
- bufoffset, (void *)data_rptr);
-
- n_xfersize = MIN(xfersize, (IDN_SMR_BUFSIZE - bufoffset));
- if (xfersize != n_xfersize) {
- PR_DATA("%s:%d: xfersize ADJUST (%d -> %d)\n",
- proc, dst_domid, xfersize, n_xfersize);
- cmn_err(CE_WARN, "%s: ERROR (xfersize = %d, > "
- "bufsize(%d)-bufoffset(%d) = %d)",
- proc, xfersize, IDN_SMR_BUFSIZE,
- bufoffset,
- IDN_SMR_BUFSIZE - bufoffset);
- }
-#endif /* DEBUG */
- xfersize = MIN(xfersize, (int)(IDN_SMR_BUFSIZE - bufoffset));
-
- iodatap = IDN_BUF2DATA(iobufp, bufoffset);
- mp = idn_fill_buffer(iodatap, xfersize, mp, &data_rptr);
-
- hdrp->b_netaddr = dst_netaddr.netaddr;
- hdrp->b_netports = netports;
- hdrp->b_offset = bufoffset;
- hdrp->b_length = xfersize;
- hdrp->b_next = IDN_NIL_SMROFFSET;
- hdrp->b_rawio = 0;
- hdrp->b_cksum = IDN_CKSUM_PKT(hdrp);
-
- xrv = idn_send_mboxdata(dst_domid, sip, channel, iobufp);
- if (xrv) {
- /*
- * Reclaim packet.
- * Return error on this packet so it can be retried
- * (putbq). Note that it should be safe to assume
- * that this for-loop is only executed once when in
- * DLPI mode and so no need to worry about fractured
- * mblk packet.
- */
- PR_DATA("%s:%d: DATA XFER to chan %d FAILED "
- "(ret=%d)\n",
- proc, dst_domid, channel, xrv);
- (void) smr_buf_free(dst_domid, iobufp, xfersize);
-
- PR_DATA("%s:%d: (line %d) dec(dio) -> %d\n",
- proc, dst_domid, __LINE__, dp->dio);
-
- rv = IDNXMIT_DROP;
- IDN_KSTAT_INC(sip, si_macxmt_errors);
- goto nocando;
- } else {
- pktcnt++;
- /*
- * Packet will get freed on a subsequent send
- * when we reclaim buffers that the receivers
- * has finished consuming.
- */
- }
- }
-
-#ifdef DEBUG
- if (pktcnt > 1)
- cmn_err(CE_WARN,
- "%s: ERROR: sent multi-pkts (%d), len = %ld",
- proc, pktcnt, orig_msglen);
-#endif /* DEBUG */
-
- PR_DATA("%s:%d: SENT %d packets (%d @ 0x%x)\n",
- proc, dst_domid, pktcnt, dst_netaddr.net.chan,
- dst_netaddr.net.netid);
-
- IDN_CHAN_LOCK_SEND(csp);
- IDN_CHAN_SEND_DONE(csp);
- IDN_CHAN_UNLOCK_SEND(csp);
-
- return (IDNXMIT_OKAY);
-
-nocando:
-
- if (csp) {
- IDN_CHAN_LOCK_SEND(csp);
- IDN_CHAN_SEND_DONE(csp);
- IDN_CHAN_UNLOCK_SEND(csp);
- }
-
- if (rv == IDNXMIT_REQUEUE) {
- /*
- * Better kick off monitor to check when
- * it's ready to reenable the queues for
- * this channel.
- */
- idn_xmit_monitor_kickoff(channel);
- }
-
- return (rv);
-}
-
-/*
- * Function to support local loopback testing of IDN driver.
- * Primarily geared towards measuring stream-head and IDN driver
- * overhead with respect to data messages. Setting idn_strhead_only
- * allows routine to focus on stream-head overhead by simply putting
- * the message straight to the 'next' queue of the destination
- * read-queue. Current implementation puts the message directly to
- * the read-queue thus sending the message right back to the IDN driver
- * as though the data came in off the wire. No need to worry about
- * any IDN layers attempting to ack data as that's normally handled
- * by idnh_recv_data.
- *
- * dst_netaddr = destination port-n-addr on local domain.
- * wq = write queue from whence message came.
- * mp = the (data-only) message.
- *
- * Returns 0 Indicates data handled.
- * errno EAGAIN indicates data can be retried.
- * Other errno's indicate failure to handle.
- */
-static int
-idn_send_data_loopback(idn_netaddr_t dst_netaddr, queue_t *wq, mblk_t *mp)
-{
- register struct idnstr *stp;
- struct idn *sip;
- int rv = 0;
- procname_t proc = "idn_send_data_loopback";
-
- if (dst_netaddr.net.netid != idn_domain[idn.localid].dnetid) {
- PR_DATA("%s: dst_netaddr.net.netid 0x%x != local 0x%x\n",
- proc, dst_netaddr.net.netid,
- idn_domain[idn.localid].dnetid);
- rv = EADDRNOTAVAIL;
- goto done;
- }
- stp = (struct idnstr *)wq->q_ptr;
- if (!stp || !stp->ss_rq) {
- rv = EDESTADDRREQ;
- goto done;
- }
- sip = stp->ss_sip;
-
- idndl_read(sip, mp);
- rv = 0;
-
-done:
- return (rv);
-}
-
-/*
- * Fill bufp with as much data as possible from the message pointed
- * to by mp up to size bytes.
- * Save our current read pointer in the variable parameter (data_rptrp)
- * so we know where to start on the next go around. Don't want to
- * bump the actual b_rptr in the mblk because the mblk may need to
- * be reused, e.g. broadcast.
- * Return the mblk pointer to the position we had to stop.
- */
-static mblk_t *
-idn_fill_buffer(caddr_t bufp, int size, mblk_t *mp, uchar_t **data_rptrp)
-{
- int copysize;
-
- ASSERT(bufp && size);
-
- if (mp == NULL)
- return (NULL);
-
- while ((size > 0) && mp) {
-
- copysize = MIN(mp->b_wptr - (*data_rptrp), size);
-
- if (copysize > 0) {
- /*
- * If there's data to copy, do it.
- */
- bcopy((*data_rptrp), bufp, copysize);
- (*data_rptrp) += copysize;
- bufp += copysize;
- size -= copysize;
- }
- if (mp->b_wptr <= (*data_rptrp)) {
- /*
- * If we emptied the mblk, then
- * move on to the next one.
- */
- for (mp = mp->b_cont;
- mp && (mp->b_datap->db_type != M_DATA);
- mp = mp->b_cont)
- ;
- if (mp)
- *data_rptrp = mp->b_rptr;
- }
- }
- return (mp);
-}
-
-/*
- * Messages received here do NOT arrive on a stream, but are
- * instead handled via the idn_protocol_servers. This routine
- * is effectively the job processor for the protocol servers.
- */
-static void
-idn_recv_proto(idn_protomsg_t *hp)
-{
- int domid, cpuid;
- int sync_lock = 0;
- idn_domain_t *dp;
- register uint_t mtype;
- register uint_t msgtype, acktype;
- idn_msgtype_t mt;
- ushort_t dcookie, tcookie;
- procname_t proc = "idn_recv_proto";
-
-
- if (idn.state == IDNGS_IGNORE) {
- /*
- * Fault injection to simulate non-responsive domain.
- */
- return;
- }
-
- domid = hp->m_domid;
- cpuid = hp->m_cpuid;
- msgtype = hp->m_msgtype;
- acktype = hp->m_acktype;
- dcookie = IDN_DCOOKIE(hp->m_cookie);
- tcookie = IDN_TCOOKIE(hp->m_cookie);
- /*
- * msgtype = Is the type of message we received,
- * e.g. nego, ack, nego+ack, etc.
- *
- * acktype = If we received a pure ack or nack
- * then this variable is set to the
- * type of message that was ack/nack'd.
- */
- if ((mtype = msgtype & IDNP_MSGTYPE_MASK) == 0) {
- /*
- * Received a pure ack/nack.
- */
- mtype = acktype & IDNP_MSGTYPE_MASK;
- }
-
- if (!VALID_MSGTYPE(mtype)) {
- PR_PROTO("%s:%d: ERROR: invalid message type (0x%x)\n",
- proc, domid, mtype);
- return;
- }
- if (!VALID_CPUID(cpuid)) {
- PR_PROTO("%s:%d: ERROR: invalid cpuid (%d)\n",
- proc, domid, cpuid);
- return;
- }
-
- /*
- * No pure data packets should reach this level.
- * Data+ack messages will reach here, but only
- * for the purpose of stopping the timer which
- * happens by default when this routine is called.
- */
- ASSERT(msgtype != IDNP_DATA);
-
- /*
- * We should never receive a request from ourself,
- * except for commands in the case of broadcasts!
- */
- if ((domid == idn.localid) && (mtype != IDNP_CMD)) {
- char str[15];
-
- inum2str(hp->m_msgtype, str);
-
- cmn_err(CE_WARN,
- "IDN: 214: received message (%s[0x%x]) from self "
- "(domid %d)",
- str, hp->m_msgtype, domid);
- return;
- }
-
- IDN_SYNC_LOCK();
- /*
- * Set a flag indicating whether we really need
- * SYNC-LOCK. We'll drop it in a little bit if
- * we really don't need it.
- */
- switch (mtype) {
- case IDNP_CON:
- case IDNP_FIN:
- case IDNP_NEGO:
- sync_lock = 1;
- break;
-
- default:
- break;
- }
-
- dp = &idn_domain[domid];
- IDN_DLOCK_EXCL(domid);
-
- /*
- * The only messages we do _not_ check the cookie are:
- * nego
- * nego+ack
- * fin - if received cookie is 0.
- * fin+ack - if received cookie is 0.
- * ack/fin - if received cookie is 0.
- * nack/fin - if received cookie is 0.
- */
- if (((msgtype & IDNP_MSGTYPE_MASK) != IDNP_NEGO) &&
- ((mtype != IDNP_FIN) || (dcookie && dp->dcookie_recv))) {
- if (dp->dcookie_recv != dcookie) {
- dp->dcookie_errcnt++;
- if (dp->dcookie_err == 0) {
- /*
- * Set cookie error to prevent a
- * possible flood of bogus cookies
- * and thus error messages.
- */
- dp->dcookie_err = 1;
- cmn_err(CE_WARN,
- "IDN: 215: invalid cookie (0x%x) "
- "for message (0x%x) from domain %d",
- dcookie, hp->m_msgtype, domid);
-
- PR_PROTO("%s:%d: received cookie (0x%x), "
- "expected (0x%x) [errcnt = %d]\n",
- proc, domid, dcookie,
- dp->dcookie_recv, dp->dcookie_errcnt);
- }
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- return;
- }
- }
- dp->dcookie_err = 0;
- IDN_GLOCK_EXCL();
-
- idn_clear_awol(domid);
-
- IDN_GUNLOCK();
- if (!sync_lock) /* really don't need SYNC-LOCK past here */
- IDN_SYNC_UNLOCK();
-
- /*
- * Stop any timers that may have been outstanding for
- * this domain, for this particular message type.
- * Note that CFG timers are directly managed by
- * config recv/send code.
- */
- if ((mtype != IDNP_CFG) && (msgtype & IDNP_ACKNACK_MASK) && tcookie) {
- IDN_MSGTIMER_STOP(domid, mtype, tcookie);
- }
-
- /*
- * Keep track of the last cpu to send us a message.
- * If the domain has not yet been assigned, we'll need
- * this cpuid in order to send back a respond.
- */
- dp->dcpu_last = cpuid;
-
- mt.mt_mtype = (ushort_t)msgtype;
- mt.mt_atype = (ushort_t)acktype;
- mt.mt_cookie = tcookie;
-
- switch (mtype) {
- case IDNP_NEGO:
- (void) idn_recv_nego(domid, &mt, hp->m_xargs, dcookie);
- break;
-
- case IDNP_CFG:
- idn_recv_config(domid, &mt, hp->m_xargs);
- break;
-
- case IDNP_CON:
- (void) idn_recv_con(domid, &mt, hp->m_xargs);
- break;
-
- case IDNP_FIN:
- (void) idn_recv_fin(domid, &mt, hp->m_xargs);
- break;
-
- case IDNP_CMD:
- idn_recv_cmd(domid, &mt, hp->m_xargs);
- break;
-
- case IDNP_DATA:
- ASSERT(msgtype & IDNP_ACKNACK_MASK);
- /*
- * When doing the fast track we simply process
- * possible nack error conditions. The actual
- * processing of the SMR data buffer is taken
- * care of in idnh_recv_dataack. When NOT doing
- * the fast track, we do all the processing here
- * in the protocol server.
- */
- (void) idn_recv_data(domid, &mt, hp->m_xargs);
- break;
-
- default:
- /*
- * Should be receiving 0 inum and 0 acknack.
- */
-#ifdef DEBUG
- cmn_err(CE_PANIC,
-#else /* DEBUG */
- cmn_err(CE_WARN,
-#endif /* DEBUG */
- /* CSTYLED */
- "IDN: 216: (0x%x)msgtype/(0x%x)acktype rcvd from "
- /* CSTYLED */
- "domain %d", msgtype, acktype, domid);
- break;
- }
-
- IDN_DUNLOCK(domid);
- /*
- * All receiving routines are responsible for dropping drwlock.
- */
-
- if (sync_lock)
- IDN_SYNC_UNLOCK();
-}
-
-/*
- * Once the CONFIG state is hit we immediately blast out all
- * of our config info. This guarantees that the CONFIG state
- * effectively signifies that the sender has sent _all_ of
- * their config info.
- */
-static void
-idn_send_config(int domid, int phase)
-{
- idn_domain_t *dp;
- int rv;
- clock_t cfg_waittime = idn_msg_waittime[IDNP_CFG];
- procname_t proc = "idn_send_config";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
-
- ASSERT(dp->dstate == IDNDS_CONFIG);
-
- if (phase == 1) {
- /*
- * Reset stuff in dtmp to 0:
- * dcfgphase
- * dcksum
- * dncfgitems
- * dmaxnets
- * dmboxpernet
- */
- dp->dtmp = 0;
- }
-
- if (dp->dcfgsnddone) {
- if (!dp->dcfgrcvdone) {
- IDN_MSGTIMER_START(domid, IDNP_CFG, 0,
- cfg_waittime, NULL);
- }
- return;
- }
-
- IDN_DLOCK_SHARED(idn.localid);
-
- PR_PROTO("%s:%d: sending %s config (phase %d)\n",
- proc, domid,
- idn_domain[idn.localid].dvote.v.master ? "MASTER" : "SLAVE",
- phase);
-
- if (idn_domain[idn.localid].dvote.v.master)
- rv = idn_send_master_config(domid, phase);
- else
- rv = idn_send_slave_config(domid, phase);
-
- IDN_DUNLOCK(idn.localid);
-
- if (rv >= 0) {
-
- if (rv == 1) {
- dp->dcfgsnddone = 1;
- PR_PROTO("%s:%d: SEND config DONE\n", proc, domid);
- if (!dp->dcfgrcvdone) {
- IDN_MSGTIMER_START(domid, IDNP_CFG, 0,
- cfg_waittime, NULL);
- }
- } else {
- IDN_MSGTIMER_START(domid, IDNP_CFG, 0,
- cfg_waittime, NULL);
- }
- }
-}
-
-/*
- * Clear out the mailbox table.
- * NOTE: This routine touches the SMR.
- */
-static void
-idn_reset_mboxtbl(idn_mboxtbl_t *mtp)
-{
- int qi;
- idn_mboxmsg_t *mp = &mtp->mt_queue[0];
-
- qi = 0;
- do {
- mp[qi].ms_bframe = 0;
- mp[qi].ms_owner = 0;
- mp[qi].ms_flag = 0;
- IDN_MMBOXINDEX_INC(qi);
- } while (qi);
-}
-
-static int
-idn_get_mbox_config(int domid, int *mindex, smr_offset_t *mtable,
- smr_offset_t *mdomain)
-{
- idn_domain_t *dp, *ldp;
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(IDN_DLOCK_IS_SHARED(idn.localid));
- ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID);
-
- /*
- * Get SMR offset of receive mailbox assigned
- * to respective domain. If I'm a slave then
- * my dmbox.m_tbl will not have been assigned yet.
- * Instead of sending the actual offset I send
- * the master his assigned index. Since the
- * master knows what offset it will assign to
- * me he can determine his assigned (recv) mailbox
- * based on the offset and given index. The local
- * domain can also use this information once the
- * dmbox.m_tbl is received to properly assign the
- * correct mbox offset to the master.
- */
- if (ldp->dmbox.m_tbl == NULL) {
- /*
- * Local domain has not yet been assigned a
- * (recv) mailbox table. This must be the
- * initial connection of this domain.
- */
- ASSERT(dp->dvote.v.master && !ldp->dvote.v.master);
- ASSERT(mindex);
- *mindex = domid;
- } else {
- idn_mboxtbl_t *mtp;
-
- mtp = IDN_MBOXTBL_PTR(ldp->dmbox.m_tbl, domid);
-
- ASSERT(mdomain);
- *mdomain = IDN_ADDR2OFFSET(mtp);
-
- if (ldp->dvote.v.master) {
- /*
- * Need to calculate mailbox table to
- * assign to the given domain. Since
- * I'm the master his mailbox is in
- * the (all-domains) mailbox table.
- */
- mtp = IDN_MBOXAREA_BASE(idn.mboxarea, domid);
- ASSERT(mtable);
- *mtable = IDN_ADDR2OFFSET(mtp);
-
- dp->dmbox.m_tbl = mtp;
- }
- }
-
- return (0);
-}
-
-/*
- * RETURNS:
- * 1 Unexpected/unnecessary phase.
- * 0 Successfully handled, timer needed.
- */
-static int
-idn_send_master_config(int domid, int phase)
-{
- idn_cfgsubtype_t cfg_subtype;
- int rv = 0;
- idn_domain_t *dp, *ldp;
- idn_msgtype_t mt;
- int nmcadr;
- uint_t barpfn, larpfn;
- uint_t cpus_u32, cpus_l32;
- uint_t mcadr[3];
- smr_offset_t mbox_table, mbox_domain;
- register int b, p, m;
- procname_t proc = "idn_send_master_config";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(IDN_DLOCK_IS_SHARED(idn.localid));
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- ASSERT(dp->dstate == IDNDS_CONFIG);
- ASSERT(dp->dvote.v.master == 0);
- ASSERT(ldp->dvote.v.master == 1);
-
- mt.mt_mtype = IDNP_CFG;
- mt.mt_atype = 0;
- mt.mt_cookie = 0;
- m = 0;
- mcadr[0] = mcadr[1] = mcadr[2] = 0;
- cfg_subtype.val = 0;
-
- switch (phase) {
-
- case 1:
- mbox_table = mbox_domain = IDN_NIL_SMROFFSET;
- (void) idn_get_mbox_config(domid, NULL, &mbox_table,
- &mbox_domain);
- /*
- * ----------------------------------------------------
- * Send: SLABSIZE, DATAMBOX.DOMAIN, DATAMBOX.TABLE
- * ----------------------------------------------------
- */
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_SLAB);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_DATAMBOX,
- IDNCFGARG_DATAMBOX_DOMAIN);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_DATAMBOX,
- IDNCFGARG_DATAMBOX_TABLE);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- ASSERT(mbox_domain != IDN_NIL_SMROFFSET);
- ASSERT(mbox_table != IDN_NIL_SMROFFSET);
-
- PR_PROTO("%s:%d:%d: sending SLABSIZE (%d), "
- "DATAMBOX.DOMAIN (0x%x), DATAMBOX.TABLE (0x%x)\n",
- proc, domid, phase, IDN_SLAB_BUFCOUNT, mbox_domain,
- mbox_table);
-
- IDNXDC(domid, &mt, cfg_subtype.val, IDN_SLAB_BUFCOUNT,
- mbox_domain, mbox_table);
- break;
-
- case 2:
- barpfn = idn.smr.locpfn;
- larpfn = barpfn + (uint_t)btop(MB2B(IDN_SMR_SIZE));
- /*
- * ----------------------------------------------------
- * Send: NETID, BARLAR
- * ----------------------------------------------------
- */
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_NETID, 0);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_BARLAR,
- IDNCFGARG_BARLAR_BAR);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_BARLAR,
- IDNCFGARG_BARLAR_LAR);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending NETID (%d), "
- "BARPFN/LARPFN (0x%x/0x%x)\n",
- proc, domid, phase, ldp->dnetid, barpfn, larpfn);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- (uint_t)ldp->dnetid, barpfn, larpfn);
- break;
-
- case 3:
- nmcadr = ldp->dhw.dh_nmcadr;
- cpus_u32 = UPPER32_CPUMASK(ldp->dcpuset);
- cpus_l32 = LOWER32_CPUMASK(ldp->dcpuset);
- /*
- * ----------------------------------------------------
- * Send: CPUSET, NMCADR
- * ----------------------------------------------------
- */
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_CPUSET,
- IDNCFGARG_CPUSET_UPPER);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_CPUSET,
- IDNCFGARG_CPUSET_LOWER);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_NMCADR, 0);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending CPUSET (0x%x.%x), NMCADR (%d)\n",
- proc, domid, phase, cpus_u32, cpus_l32, nmcadr);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- cpus_u32, cpus_l32, nmcadr);
- break;
-
- case 4:
- /*
- * ----------------------------------------------------
- * Send: BOARDSET, MTU, BUFSIZE
- * ----------------------------------------------------
- */
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_BOARDSET, 0);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_MTU);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_BUF);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending BOARDSET (0x%x), MTU (0x%lx), "
- "BUFSIZE (0x%x)\n", proc, domid, phase,
- ldp->dhw.dh_boardset, IDN_MTU, IDN_SMR_BUFSIZE);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- ldp->dhw.dh_boardset, IDN_MTU, IDN_SMR_BUFSIZE);
- break;
-
- case 5:
- /*
- * ----------------------------------------------------
- * Send: MAXNETS, MBOXPERNET, CKSUM
- * ----------------------------------------------------
- */
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_DATASVR,
- IDNCFGARG_DATASVR_MAXNETS);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_DATASVR,
- IDNCFGARG_DATASVR_MBXPERNET);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_OPTIONS,
- IDNCFGARG_CHECKSUM);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending MAXNETS (%d), "
- "MBOXPERNET (%d), CKSUM (%d)\n",
- proc, domid, phase,
- IDN_MAX_NETS, IDN_MBOX_PER_NET,
- IDN_CHECKSUM);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- IDN_MAX_NETS, IDN_MBOX_PER_NET, IDN_CHECKSUM);
- break;
-
- case 6:
- /*
- * ----------------------------------------------------
- * Send: NWRSIZE (piggyback on MCADRs)
- * ----------------------------------------------------
- */
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_NWR);
- mcadr[0] = IDN_NWR_SIZE;
- m = 1;
-
- /*FALLTHROUGH*/
-
- default: /* case 7 and above */
- /*
- * ----------------------------------------------------
- * Send: MCADR's
- * ----------------------------------------------------
- * First need to figure how many we've already sent
- * based on what phase of CONFIG we're in.
- * ----------------------------------------------------
- */
- if (phase > 6) {
- p = ((phase - 7) * 3) + 2;
- for (b = 0; (b < MAX_BOARDS) && (p > 0); b++)
- if (ldp->dhw.dh_mcadr[b])
- p--;
- } else {
- b = 0;
- }
-
- for (; (b < MAX_BOARDS) && (m < 3); b++) {
- if (ldp->dhw.dh_mcadr[b] == 0)
- continue;
- mcadr[m] = ldp->dhw.dh_mcadr[b];
- cfg_subtype.param.p[m] = IDN_CFGPARAM(IDNCFG_MCADR, b);
- m++;
- }
- if (m > 0) {
- if (phase == 6) {
- PR_PROTO("%s:%d:%d: sending NWRSIZE (%d), "
- "MCADRs (0x%x, 0x%x)\n",
- proc, domid, phase,
- mcadr[0], mcadr[1], mcadr[2]);
- } else {
- PR_PROTO("%s:%d:%d: sending MCADRs "
- "(0x%x, 0x%x, 0x%x)\n",
- proc, domid, phase,
- mcadr[0], mcadr[1], mcadr[2]);
- }
- cfg_subtype.info.num = m;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- mcadr[0], mcadr[1], mcadr[2]);
- } else {
- rv = 1;
- }
- break;
- }
-
- return (rv);
-}
-
-/*
- * RETURNS:
- * 1 Unexpected/unnecessary phase.
- * 0 Successfully handled.
- */
-static int
-idn_send_slave_config(int domid, int phase)
-{
- idn_cfgsubtype_t cfg_subtype;
- int rv = 0;
- idn_domain_t *dp, *ldp;
- smr_offset_t mbox_domain;
- idn_msgtype_t mt;
- int mbox_index;
- uint_t cpus_u32, cpus_l32;
- procname_t proc = "idn_send_slave_config";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(IDN_DLOCK_IS_SHARED(idn.localid));
-
- mt.mt_mtype = IDNP_CFG;
- mt.mt_atype = 0;
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- ASSERT(dp->dstate == IDNDS_CONFIG);
- ASSERT(ldp->dvote.v.master == 0);
-
- switch (phase) {
-
- case 1:
- mbox_index = IDN_NIL_DOMID;
- mbox_domain = IDN_NIL_SMROFFSET;
- (void) idn_get_mbox_config(domid, &mbox_index, NULL,
- &mbox_domain);
- /*
- * ----------------------------------------------------
- * Send: DATAMBOX.DOMAIN or DATAMBOX.INDEX,
- * DATASVR.MAXNETS, DATASVR.MBXPERNET
- * ----------------------------------------------------
- */
- cfg_subtype.val = 0;
- if (mbox_index == IDN_NIL_DOMID) {
- ASSERT(mbox_domain != IDN_NIL_SMROFFSET);
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_DATAMBOX,
- IDNCFGARG_DATAMBOX_DOMAIN);
- } else {
- /*
- * Should only be sending Index to
- * the master and not another slave.
- */
- ASSERT(dp->dvote.v.master);
- ASSERT(mbox_domain == IDN_NIL_SMROFFSET);
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_DATAMBOX,
- IDNCFGARG_DATAMBOX_INDEX);
- }
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_DATASVR,
- IDNCFGARG_DATASVR_MAXNETS);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_DATASVR,
- IDNCFGARG_DATASVR_MBXPERNET);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending DATAMBOX.%s (0x%x), "
- "MAXNETS (%d), MBXPERNET (%d)\n",
- proc, domid, phase,
- (IDN_CFGPARAM_ARG(cfg_subtype.param.p[0])
- == IDNCFGARG_DATAMBOX_INDEX) ? "INDEX" : "DOMAIN",
- (mbox_index == IDN_NIL_DOMID) ? mbox_domain : mbox_index,
- IDN_MAX_NETS, IDN_MBOX_PER_NET);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- ((mbox_index == IDN_NIL_DOMID) ? mbox_domain : mbox_index),
- IDN_MAX_NETS, IDN_MBOX_PER_NET);
- break;
-
- case 2:
- cpus_u32 = UPPER32_CPUMASK(ldp->dcpuset);
- cpus_l32 = LOWER32_CPUMASK(ldp->dcpuset);
- /*
- * ----------------------------------------------------
- * Send: NETID, CPUSET
- * ----------------------------------------------------
- */
- cfg_subtype.val = 0;
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_NETID, 0);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_CPUSET,
- IDNCFGARG_CPUSET_UPPER);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_CPUSET,
- IDNCFGARG_CPUSET_LOWER);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending NETID (%d), "
- "CPUSET (0x%x.%x)\n", proc, domid, phase,
- ldp->dnetid, cpus_u32, cpus_l32);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- (uint_t)ldp->dnetid, cpus_u32, cpus_l32);
- break;
-
- case 3:
- /*
- * ----------------------------------------------------
- * Send: BOARDSET, MTU, BUFSIZE
- * ----------------------------------------------------
- */
- cfg_subtype.val = 0;
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_BOARDSET, 0);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_MTU);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_BUF);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending BOARDSET (0x%x), MTU (0x%lx), "
- "BUFSIZE (0x%x)\n",
- proc, domid, phase, ldp->dhw.dh_boardset, IDN_MTU,
- IDN_SMR_BUFSIZE);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- ldp->dhw.dh_boardset, IDN_MTU, IDN_SMR_BUFSIZE);
- break;
-
- case 4:
- /*
- * ----------------------------------------------------
- * Send: SLABSIZE, OPTIONS.CHECKSUM, NWR_SIZE
- * ----------------------------------------------------
- */
- cfg_subtype.val = 0;
- cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_SLAB);
- cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_OPTIONS,
- IDNCFGARG_CHECKSUM);
- cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_SIZE,
- IDNCFGARG_SIZE_NWR);
- cfg_subtype.info.num = 3;
- cfg_subtype.info.phase = phase;
- dp->dcfgphase = phase;
-
- PR_PROTO("%s:%d:%d: sending SLABSIZE (%d), CKSUM (%d), "
- "NWRSIZE (%d)\n",
- proc, domid, phase, IDN_SLAB_BUFCOUNT,
- IDN_CHECKSUM, IDN_NWR_SIZE);
-
- IDNXDC(domid, &mt, cfg_subtype.val,
- IDN_SLAB_BUFCOUNT, IDN_CHECKSUM, IDN_NWR_SIZE);
- break;
-
- default:
- rv = 1;
- break;
- }
-
- return (rv);
-}
-
-#define CFG_FATAL ((uint_t)-1) /* reset link */
-#define CFG_CONTINUE 0x0000 /* looking for more */
-#define CFG_DONE 0x0001 /* got everything expected */
-#define CFG_ERR_MTU 0x0002
-#define CFG_ERR_BUF 0x0004
-#define CFG_ERR_SLAB 0x0008
-#define CFG_ERR_NWR 0x0010
-#define CFG_ERR_NETS 0x0020
-#define CFG_ERR_MBOX 0x0040
-#define CFG_ERR_NMCADR 0x0080
-#define CFG_ERR_MCADR 0x0100
-#define CFG_ERR_CKSUM 0x0200
-#define CFG_ERR_SMR 0x0400
-#define CFG_MAX_ERRORS 16
-
-#define CFGERR2IDNKERR(ce) \
- (((ce) & CFG_ERR_MTU) ? IDNKERR_CONFIG_MTU : \
- ((ce) & CFG_ERR_BUF) ? IDNKERR_CONFIG_BUF : \
- ((ce) & CFG_ERR_SLAB) ? IDNKERR_CONFIG_SLAB : \
- ((ce) & CFG_ERR_NWR) ? IDNKERR_CONFIG_NWR : \
- ((ce) & CFG_ERR_NETS) ? IDNKERR_CONFIG_NETS : \
- ((ce) & CFG_ERR_MBOX) ? IDNKERR_CONFIG_MBOX : \
- ((ce) & CFG_ERR_NMCADR) ? IDNKERR_CONFIG_NMCADR : \
- ((ce) & CFG_ERR_MCADR) ? IDNKERR_CONFIG_MCADR : \
- ((ce) & CFG_ERR_CKSUM) ? IDNKERR_CONFIG_CKSUM : \
- ((ce) & CFG_ERR_SMR) ? IDNKERR_CONFIG_SMR : 0)
-
-#define CFGERR2FINARG(ce) \
- (((ce) & CFG_ERR_MTU) ? IDNFIN_ARG_CFGERR_MTU : \
- ((ce) & CFG_ERR_BUF) ? IDNFIN_ARG_CFGERR_BUF : \
- ((ce) & CFG_ERR_SLAB) ? IDNFIN_ARG_CFGERR_SLAB : \
- ((ce) & CFG_ERR_NWR) ? IDNFIN_ARG_CFGERR_NWR : \
- ((ce) & CFG_ERR_NETS) ? IDNFIN_ARG_CFGERR_NETS : \
- ((ce) & CFG_ERR_MBOX) ? IDNFIN_ARG_CFGERR_MBOX : \
- ((ce) & CFG_ERR_NMCADR) ? IDNFIN_ARG_CFGERR_NMCADR : \
- ((ce) & CFG_ERR_MCADR) ? IDNFIN_ARG_CFGERR_MCADR : \
- ((ce) & CFG_ERR_CKSUM) ? IDNFIN_ARG_CFGERR_CKSUM : \
- ((ce) & CFG_ERR_SMR) ? IDNFIN_ARG_CFGERR_SMR : IDNFIN_ARG_NONE)
-
-/*
- * Called when some CFG messages arrive. We use dncfgitems to count the
- * total number of items received so far since we'll receive multiple CFG
- * messages during the CONFIG phase. Note that dncfgitems is initialized
- * in idn_send_config.
- */
-static void
-idn_recv_config(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp->mt_mtype;
- uint_t rv, rv_expected, rv_actual;
- int pnum;
- int phase;
- register int p;
- register int c;
- idn_mainmbox_t *mmp;
- register uint_t subtype, subtype_arg;
- idn_domain_t *dp;
- int index;
- idn_domain_t *ldp = &idn_domain[idn.localid];
- idn_mboxtbl_t *mbtp;
- idn_cfgsubtype_t cfg_subtype;
- idn_xdcargs_t cfg_arg;
- idn_msgtype_t mt;
- idnsb_error_t idnerr;
- procname_t proc = "idn_recv_config";
-
- ASSERT(domid != idn.localid);
-
- GET_XARGS(xargs, &cfg_subtype.val, &cfg_arg[0], &cfg_arg[1],
- &cfg_arg[2]);
- cfg_arg[3] = 0;
-
- dp = &idn_domain[domid];
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (dp->dstate != IDNDS_CONFIG) {
- /*
- * Not ready to receive config info.
- * Drop whatever he sent us. Let the
- * timer continue and timeout if needed.
- */
- PR_PROTO("%s:%d: WARNING state(%s) != CONFIG\n",
- proc, domid, idnds_str[dp->dstate]);
- return;
- }
-
- if ((msg & IDNP_ACKNACK_MASK) || dp->dcfgsnddone) {
- IDN_MSGTIMER_STOP(domid, IDNP_CFG, 0);
- }
-
- if (msg & IDNP_ACKNACK_MASK) {
- /*
- * ack/cfg
- */
- phase = GET_XARGS_CFG_PHASE(xargs);
-
- PR_PROTO("%s:%d: received ACK for CFG phase %d\n",
- proc, domid, phase);
- if (phase != (int)dp->dcfgphase) {
- /*
- * Phase is not what we were
- * expecting. Something got lost
- * in the shuffle. Restart the
- * timer and let it timeout if necessary
- * and reestablish the connection.
- */
- IDN_MSGTIMER_START(domid, IDNP_CFG, dp->dcfgphase,
- idn_msg_waittime[IDNP_CFG], NULL);
- } else {
- idn_send_config(domid, phase + 1);
-
- if (dp->dcfgsnddone && dp->dcfgrcvdone) {
- IDN_DUNLOCK(domid);
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
- if (dp->dstate == IDNDS_CONFIG) {
- dp->dxp = &xphase_con;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- bzero(xargs, sizeof (xargs));
-
- (void) idn_xphase_transition(domid,
- NULL, xargs);
- }
- IDN_SYNC_UNLOCK();
- }
- }
- return;
- }
-
- pnum = (int)cfg_subtype.info.num;
- phase = (int)cfg_subtype.info.phase;
-
- for (p = 0; p < pnum; p++) {
- int board;
-#ifdef DEBUG
- uint_t val;
- char *str;
-
- val = 0;
- str = NULL;
-#define RCVCFG(s, v) { str = (s); val = (v); }
-#else
-#define RCVCFG(s, v) {}
-#endif /* DEBUG */
-
- subtype = IDN_CFGPARAM_TYPE(cfg_subtype.param.p[p]);
- subtype_arg = IDN_CFGPARAM_ARG(cfg_subtype.param.p[p]);
-
- switch (subtype) {
-
- case IDNCFG_BARLAR:
- IDN_GLOCK_EXCL();
- switch (subtype_arg) {
-
- case IDNCFGARG_BARLAR_BAR:
- if (idn.smr.rempfn == PFN_INVALID) {
- idn.smr.rempfn = (pfn_t)cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("BARLAR_BAR", cfg_arg[p]);
- }
- break;
-
- case IDNCFGARG_BARLAR_LAR:
- if (idn.smr.rempfnlim == PFN_INVALID) {
- idn.smr.rempfnlim = (pfn_t)cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("BARLAR_LAR", cfg_arg[p]);
- }
- break;
-
- default:
- cmn_err(CE_WARN,
- "IDN 217: unknown CFGARG type (%d) "
- "from domain %d",
- subtype_arg, domid);
- break;
- }
- IDN_GUNLOCK();
- break;
-
- case IDNCFG_MCADR:
- board = subtype_arg;
- if ((board >= 0) && (board < MAX_BOARDS) &&
- (dp->dhw.dh_mcadr[board] == 0)) {
- dp->dhw.dh_mcadr[board] = cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("MCADR", cfg_arg[p]);
- }
- break;
-
- case IDNCFG_NMCADR:
- if (dp->dhw.dh_nmcadr == 0) {
- dp->dhw.dh_nmcadr = cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("NMCADR", cfg_arg[p]);
- }
- break;
-
- case IDNCFG_CPUSET:
- switch (subtype_arg) {
-
- case IDNCFGARG_CPUSET_UPPER:
- {
- cpuset_t tmpset;
-
- MAKE64_CPUMASK(tmpset, cfg_arg[p], 0);
- CPUSET_OR(dp->dcpuset, tmpset);
- dp->dncfgitems++;
- RCVCFG("CPUSET_UPPER", cfg_arg[p]);
- break;
- }
- case IDNCFGARG_CPUSET_LOWER:
- {
- cpuset_t tmpset;
-
- MAKE64_CPUMASK(tmpset, 0, cfg_arg[p]);
- CPUSET_OR(dp->dcpuset, tmpset);
- dp->dncfgitems++;
- RCVCFG("CPUSET_LOWER", cfg_arg[p]);
- break;
- }
- default:
- ASSERT(0);
- break;
- }
- break;
-
- case IDNCFG_NETID:
- if (dp->dnetid == (ushort_t)-1) {
- dp->dnetid = (ushort_t)cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("NETID", cfg_arg[p]);
- }
- break;
-
- case IDNCFG_BOARDSET:
- if ((dp->dhw.dh_boardset & cfg_arg[p])
- == dp->dhw.dh_boardset) {
- /*
- * Boardset better include what we
- * already know about.
- */
- dp->dhw.dh_boardset = cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("BOARDSET", cfg_arg[p]);
- }
- break;
-
- case IDNCFG_SIZE:
- switch (subtype_arg) {
-
- case IDNCFGARG_SIZE_MTU:
- if (dp->dmtu == 0) {
- dp->dmtu = cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("MTU", cfg_arg[p]);
- }
- break;
-
- case IDNCFGARG_SIZE_BUF:
- if (dp->dbufsize == 0) {
- dp->dbufsize = cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("BUFSIZE", cfg_arg[p]);
- }
- break;
-
- case IDNCFGARG_SIZE_SLAB:
- if (dp->dslabsize == 0) {
- dp->dslabsize = (short)cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("SLABSIZE", cfg_arg[p]);
- }
- break;
-
- case IDNCFGARG_SIZE_NWR:
- if (dp->dnwrsize == 0) {
- dp->dnwrsize = (short)cfg_arg[p];
- dp->dncfgitems++;
- RCVCFG("NWRSIZE", cfg_arg[p]);
- }
- break;
-
- default:
- ASSERT(0);
- break;
- }
- break;
-
- case IDNCFG_DATAMBOX:
- switch (subtype_arg) {
-
- case IDNCFGARG_DATAMBOX_TABLE:
- if (ldp->dmbox.m_tbl ||
- !dp->dvote.v.master ||
- !VALID_NWROFFSET(cfg_arg[p], 4)) {
- /*
- * Only a master should be
- * sending us a datambox table.
- */
- break;
- }
- IDN_DLOCK_EXCL(idn.localid);
- ldp->dmbox.m_tbl = (idn_mboxtbl_t *)
- IDN_OFFSET2ADDR(cfg_arg[p]);
- IDN_DUNLOCK(idn.localid);
- dp->dncfgitems++;
- RCVCFG("DATAMBOX.TABLE", cfg_arg[p]);
- break;
-
- case IDNCFGARG_DATAMBOX_DOMAIN:
- if (dp->dmbox.m_send->mm_smr_mboxp ||
- !VALID_NWROFFSET(cfg_arg[p], 4))
- break;
- mbtp = (idn_mboxtbl_t *)
- IDN_OFFSET2ADDR(cfg_arg[p]);
- mmp = dp->dmbox.m_send;
- for (c = 0; c < IDN_MAX_NETS; c++) {
-
- mutex_enter(&mmp[c].mm_mutex);
- mmp[c].mm_smr_mboxp = mbtp;
- mutex_exit(&mmp[c].mm_mutex);
-
- IDN_MBOXTBL_PTR_INC(mbtp);
- }
- if (c <= 0)
- break;
- dp->dncfgitems++;
- RCVCFG("DATAMBOX.DOMAIN", cfg_arg[p]);
- break;
-
- case IDNCFGARG_DATAMBOX_INDEX:
- if (!ldp->dvote.v.master ||
- dp->dmbox.m_send->mm_smr_mboxp) {
- /*
- * If I'm not the master then
- * I can't handle processing a
- * mailbox index.
- * OR, if I already have the send
- * mailbox, I'm done with this
- * config item.
- */
- break;
- }
- ASSERT(dp->dmbox.m_tbl);
- index = (int)cfg_arg[p];
- /*
- * The given index is the local domain's
- * index into the remote domain's mailbox
- * table that contains the mailbox that
- * remote domain wants the local domain to
- * use as the send mailbox for messages
- * destined for the remote domain.
- * I.e. from the remote domain's
- * perspective, this is his receive
- * mailbox.
- */
- mbtp = IDN_MBOXTBL_PTR(dp->dmbox.m_tbl, index);
- mmp = dp->dmbox.m_send;
- for (c = 0; c < IDN_MAX_NETS; c++) {
-
- mutex_enter(&mmp[c].mm_mutex);
- mmp[c].mm_smr_mboxp = mbtp;
- mutex_exit(&mmp[c].mm_mutex);
-
- IDN_MBOXTBL_PTR_INC(mbtp);
- }
- if (c <= 0)
- break;
- dp->dncfgitems++;
- RCVCFG("DATAMBOX.INDEX", cfg_arg[p]);
- break;
-
- default:
- ASSERT(0);
- break;
- }
- break;
-
- case IDNCFG_DATASVR:
- switch (subtype_arg) {
-
- case IDNCFGARG_DATASVR_MAXNETS:
- if (dp->dmaxnets)
- break;
- dp->dmaxnets = (uint_t)(cfg_arg[p] & 0x3f);
- dp->dncfgitems++;
- RCVCFG("DATASVR.MAXNETS", cfg_arg[p]);
- break;
-
- case IDNCFGARG_DATASVR_MBXPERNET:
- if (dp->dmboxpernet)
- break;
- dp->dmboxpernet = (uint_t)(cfg_arg[p] & 0x1ff);
- dp->dncfgitems++;
- RCVCFG("DATASVR.MBXPERNET", cfg_arg[p]);
- break;
-
- default:
- ASSERT(0);
- break;
- }
- break;
-
- case IDNCFG_OPTIONS:
- switch (subtype_arg) {
-
- case IDNCFGARG_CHECKSUM:
- if (dp->dcksum)
- break;
- if ((cfg_arg[p] & 0xff) == 0)
- dp->dcksum = 1; /* off */
- else
- dp->dcksum = 2; /* on */
- dp->dncfgitems++;
- RCVCFG("OPTIONS.CHECKSUM", cfg_arg[p]);
- break;
-
- default:
- ASSERT(0);
- break;
- }
-
- default:
- break;
- }
-#ifdef DEBUG
- PR_PROTO("%s:%d: received %s (0x%x)\n",
- proc, domid, str ? str : "<empty>", val);
-#endif /* DEBUG */
- }
-
- mt.mt_mtype = IDNP_ACK;
- mt.mt_atype = IDNP_CFG;
- mt.mt_cookie = mtp->mt_cookie;
- CLR_XARGS(cfg_arg);
- SET_XARGS_CFG_PHASE(cfg_arg, phase);
- idn_send_acknack(domid, &mt, cfg_arg);
-
- rv_expected = rv_actual = 0;
-
- if (dp->dvote.v.master == 0) {
- /*
- * Remote domain is a slave, check if we've received
- * all that we were expecting, and if so transition to
- * the next state.
- */
- rv = idn_check_slave_config(domid, &rv_expected, &rv_actual);
- } else {
- /*
- * Remote domain is a master, check if this slave has
- * received all that it was expecting, and if so
- * transition to the next state.
- */
- rv = idn_check_master_config(domid, &rv_expected, &rv_actual);
- }
-
- switch (rv) {
- case CFG_DONE:
- /*
- * All config info received that was expected, wrap up.
- */
- if (!idn_recv_config_done(domid) && dp->dvote.v.master) {
- IDN_DLOCK_EXCL(idn.localid);
- ldp->dvote.v.connected = 1;
- IDN_DUNLOCK(idn.localid);
- }
- break;
-
- case CFG_CONTINUE:
- /*
- * If we're not done sending our own config, then
- * there's no need to set a timer since one will
- * automatically be set when we send a config
- * message waiting for an acknowledgement.
- */
- if (dp->dcfgsnddone) {
- /*
- * We haven't yet received all the config
- * information we were expecting. Need to
- * restart CFG timer if we've sent everything..
- */
- IDN_MSGTIMER_START(domid, IDNP_CFG, 0,
- idn_msg_waittime[IDNP_CFG], NULL);
- }
- break;
-
- case CFG_FATAL:
- /*
- * Fatal error occurred during config exchange.
- * We need to shutdown connection in this
- * case, so initiate a (non-relink) FIN.
- * so let's get the show on the road.
- */
- IDN_DUNLOCK(domid);
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
- /*
- * If the state has changed from CONFIG
- * then somebody else has taken over
- * control of this domain so we can just
- * bail out.
- */
- if (dp->dstate == IDNDS_CONFIG) {
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EPROTO);
- SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CONFIG_FATAL);
- SET_IDNKERR_PARAM0(&idnerr, domid);
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr);
- /*
- * Keep this guy around so we can try again.
- */
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate,
- idn.domset.ds_relink);
- (void) idn_disconnect(domid, IDNFIN_NORMAL,
- IDNFIN_ARG_CFGERR_FATAL,
- IDNFIN_SYNC_NO);
- }
- IDN_SYNC_UNLOCK();
- break;
-
- default: /* parameter conflict */
- IDN_DUNLOCK(domid);
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
- if (dp->dstate != IDNDS_CONFIG) {
- /*
- * Hmmm...changed in the short period
- * we had dropped the lock, oh well.
- */
- IDN_SYNC_UNLOCK();
- break;
- }
- c = 0;
- for (p = 0; p < CFG_MAX_ERRORS; p++)
- if (rv & (1 << p))
- c++;
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EINVAL);
- SET_IDNKERR_PARAM0(&idnerr, domid);
- if (c > 1) {
- SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CONFIG_MULTIPLE);
- SET_IDNKERR_PARAM1(&idnerr, c);
- } else {
- SET_IDNKERR_IDNERR(&idnerr, CFGERR2IDNKERR(rv));
- SET_IDNKERR_PARAM1(&idnerr, rv_expected);
- SET_IDNKERR_PARAM2(&idnerr, rv_actual);
- }
- /*
- * Any parameter conflicts are grounds for dismissal.
- */
- if (idn.domset.ds_connected == 0) {
- domainset_t domset;
- /*
- * We have no other connections yet.
- * We must blow out of here completely
- * unless we have relinkers left from
- * a RECONFIG.
- */
- IDN_GLOCK_EXCL();
- domset = ~idn.domset.ds_relink;
- if (idn.domset.ds_relink == 0) {
- IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT);
- }
- domset &= ~idn.domset.ds_hitlist;
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- IDN_GUNLOCK();
- IDN_DUNLOCK(domid);
-
- DOMAINSET_DEL(domset, idn.localid);
-
- idn_update_op(IDNOP_ERROR, DOMAINSET_ALL, &idnerr);
-
- PR_HITLIST("%s:%d: unlink_domainset(%x) due to "
- "CFG error (relink=%x, hitlist=%x)\n",
- proc, domid, domset, idn.domset.ds_relink,
- idn.domset.ds_hitlist);
-
- idn_unlink_domainset(domset, IDNFIN_NORMAL,
- CFGERR2FINARG(rv),
- IDNFIN_OPT_UNLINK,
- BOARDSET_ALL);
- IDN_SYNC_UNLOCK();
- IDN_DLOCK_EXCL(domid);
- } else {
- PR_HITLIST("%s:%d: idn_disconnect(%d) due to CFG "
- "error (conn=%x, relink=%x, hitlist=%x)\n",
- proc, domid, domid, idn.domset.ds_connected,
- idn.domset.ds_relink, idn.domset.ds_hitlist);
- /*
- * If we have other connections then
- * we're only going to blow away this
- * single connection.
- */
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr);
-
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- (void) idn_disconnect(domid, IDNFIN_NORMAL,
- CFGERR2FINARG(rv), IDNFIN_SYNC_NO);
- IDN_SYNC_UNLOCK();
- }
- break;
- }
-}
-
-/*
- * Called by master or slave which expects exactly the following
- * with respect to config info received from a SLAVE:
- * IDNCFG_CPUSET
- * IDNCFG_NETID
- * IDNCFG_BOARDSET
- * IDNCFG_SIZE (MTU, BUF, SLAB, NWR)
- * IDNCFG_DATAMBOX (DOMAIN or INDEX if caller is master)
- * IDNCFG_DATASVR (MAXNETS, MBXPERNET)
- * IDNCFG_OPTIONS (CHECKSUM)
- */
-static uint_t
-idn_check_slave_config(int domid, uint_t *exp, uint_t *act)
-{
- uint_t rv = 0;
- idn_domain_t *ldp, *dp;
- procname_t proc = "idn_check_slave_config";
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- ASSERT(domid != idn.localid);
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(dp->dstate == IDNDS_CONFIG);
-
- PR_PROTO("%s:%d: number received %d, number expected %d\n",
- proc, domid, (int)dp->dncfgitems, IDN_SLAVE_NCFGITEMS);
-
- if ((int)dp->dncfgitems < IDN_SLAVE_NCFGITEMS)
- return (CFG_CONTINUE);
-
- if ((dp->dnetid == (ushort_t)-1) ||
- CPUSET_ISNULL(dp->dcpuset) ||
- (dp->dhw.dh_boardset == 0) ||
- (dp->dmbox.m_send->mm_smr_mboxp == NULL) ||
- (dp->dmaxnets == 0) ||
- (dp->dmboxpernet == 0) ||
- (dp->dcksum == 0) ||
- (dp->dmtu == 0) ||
- (dp->dbufsize == 0) ||
- (dp->dslabsize == 0) ||
- (dp->dnwrsize == 0)) {
- /*
- * We received our IDN_SLAVE_NCFGITEMS config items,
- * but not all what we were expecting! Gotta nack and
- * close connection.
- */
- cmn_err(CE_WARN,
- "IDN: 218: missing some required config items from "
- "domain %d", domid);
-
- rv = CFG_FATAL;
- goto done;
- }
-
- if (!valid_mtu(dp->dmtu)) {
- cmn_err(CE_WARN,
- "IDN: 219: remote domain %d MTU (%d) invalid "
- "(local.mtu = %d)", dp->domid, dp->dmtu, ldp->dmtu);
-
- *exp = (uint_t)ldp->dmtu;
- *act = (uint_t)dp->dmtu;
- rv |= CFG_ERR_MTU;
- }
- if (!valid_bufsize(dp->dbufsize)) {
- cmn_err(CE_WARN,
- "IDN: 220: remote domain %d BUFSIZE (%d) invalid "
- "(local.bufsize = %d)", dp->domid, dp->dbufsize,
- ldp->dbufsize);
-
- *exp = (uint_t)ldp->dbufsize;
- *act = (uint_t)dp->dbufsize;
- rv |= CFG_ERR_BUF;
- }
- if (!valid_slabsize((int)dp->dslabsize)) {
- cmn_err(CE_WARN,
- "IDN: 221: remote domain %d SLABSIZE (%d) invalid "
- "(local.slabsize = %d)",
- dp->domid, dp->dslabsize, ldp->dslabsize);
-
- *exp = (uint_t)ldp->dslabsize;
- *act = (uint_t)dp->dslabsize;
- rv |= CFG_ERR_SLAB;
- }
- if (!valid_nwrsize((int)dp->dnwrsize)) {
- cmn_err(CE_WARN,
- "IDN: 223: remote domain %d NWRSIZE (%d) invalid "
- "(local.nwrsize = %d)",
- dp->domid, dp->dnwrsize, ldp->dnwrsize);
-
- *exp = (uint_t)ldp->dnwrsize;
- *act = (uint_t)dp->dnwrsize;
- rv |= CFG_ERR_NWR;
- }
- if ((int)dp->dmaxnets != IDN_MAX_NETS) {
- cmn_err(CE_WARN,
- "IDN: 224: remote domain %d MAX_NETS (%d) invalid "
- "(local.maxnets = %d)",
- dp->domid, (int)dp->dmaxnets, IDN_MAX_NETS);
-
- *exp = (uint_t)IDN_MAX_NETS;
- *act = (uint_t)dp->dmaxnets;
- rv |= CFG_ERR_NETS;
- }
- if ((int)dp->dmboxpernet != IDN_MBOX_PER_NET) {
- cmn_err(CE_WARN,
- "IDN: 225: remote domain %d MBOX_PER_NET (%d) "
- "invalid (local.mboxpernet = %d)",
- dp->domid, (int)dp->dmboxpernet, IDN_MBOX_PER_NET);
-
- *exp = (uint_t)IDN_MBOX_PER_NET;
- *act = (uint_t)dp->dmboxpernet;
- rv |= CFG_ERR_MBOX;
- }
- if ((dp->dcksum - 1) != (uchar_t)IDN_CHECKSUM) {
- cmn_err(CE_WARN,
- "IDN: 226: remote domain %d CHECKSUM flag (%d) "
- "mismatches local domain's (%d)",
- dp->domid, (int)dp->dcksum - 1, IDN_CHECKSUM);
-
- *exp = (uint_t)IDN_CHECKSUM;
- *act = (uint_t)(dp->dcksum - 1);
- rv |= CFG_ERR_CKSUM;
- }
-
-done:
-
- return (rv ? rv : CFG_DONE);
-}
-
-/*
- * Called by slave ONLY which expects exactly the following
- * config info from the MASTER:
- * IDNCFG_BARLAR
- * IDNCFG_MCADR
- * IDNCFG_NMCADR
- * IDNCFG_CPUSET
- * IDNCFG_NETID
- * IDNCFG_BOARDSET
- * IDNCFG_SIZE (MTU, BUF, SLAB, NWR)
- * IDNCFG_DATAMBOX (TABLE, DOMAIN)
- * IDNCFG_DATASVR (MAXNETS, MBXPERNET)
- * IDNCFG_OPTIONS (CHECKSUM)
- */
-static uint_t
-idn_check_master_config(int domid, uint_t *exp, uint_t *act)
-{
- uint_t rv = 0;
- int nmcadr;
- int total_expitems;
- int p, m, err;
- idn_domain_t *dp;
- idn_domain_t *ldp = &idn_domain[idn.localid];
- procname_t proc = "idn_check_master_config";
-
- dp = &idn_domain[domid];
-
- ASSERT(IDN_GET_MASTERID() != idn.localid);
- ASSERT(domid != idn.localid);
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(dp->dstate == IDNDS_CONFIG);
-
- PR_PROTO("%s:%d: number received %d, minimum number expected %d\n",
- proc, domid, (int)dp->dncfgitems, IDN_MASTER_NCFGITEMS);
-
- if ((int)dp->dncfgitems < IDN_MASTER_NCFGITEMS)
- return (CFG_CONTINUE);
-
- /*
- * We have at least IDN_MASTER_NCFGITEMS items which
- * means we have at least one MCADR. Need to make sure
- * we have all that we're expecting, NMCADR.
- */
- total_expitems = IDN_MASTER_NCFGITEMS + dp->dhw.dh_nmcadr - 1;
- if ((dp->dhw.dh_nmcadr == 0) ||
- ((int)dp->dncfgitems < total_expitems)) {
- /*
- * We have not yet received all the MCADRs
- * we're expecting.
- */
- PR_PROTO("%s:%d: haven't received all MCADRs yet.\n",
- proc, domid);
- return (CFG_CONTINUE);
- }
-
- nmcadr = 0;
- for (p = 0; p < MAX_BOARDS; p++)
- if (dp->dhw.dh_mcadr[p] != 0)
- nmcadr++;
-
- IDN_GLOCK_SHARED();
- if ((idn.smr.rempfn == PFN_INVALID) ||
- (idn.smr.rempfnlim == PFN_INVALID) ||
- (dp->dnetid == (ushort_t)-1) ||
- CPUSET_ISNULL(dp->dcpuset) ||
- (dp->dhw.dh_boardset == 0) ||
- (nmcadr != dp->dhw.dh_nmcadr) ||
- (dp->dmbox.m_send->mm_smr_mboxp == NULL) ||
- (ldp->dmbox.m_tbl == NULL) ||
- (dp->dmaxnets == 0) ||
- (dp->dmboxpernet == 0) ||
- (dp->dcksum == 0) ||
- (dp->dmtu == 0) ||
- (dp->dbufsize == 0) ||
- (dp->dnwrsize == 0)) {
-
- IDN_GUNLOCK();
- /*
- * We received all of our config items, but not
- * all what we were expecting! Gotta reset and
- * close connection.
- */
- cmn_err(CE_WARN,
- "IDN: 227: missing some required config items from "
- "domain %d", domid);
-
- rv = CFG_FATAL;
- goto done;
- }
- if ((idn.smr.rempfnlim - idn.smr.rempfn) > btop(MB2B(IDN_SMR_SIZE))) {
- /*
- * The master's SMR region is larger than
- * mine! This means that this domain may
- * receive I/O buffers which are out of the
- * range of this local domain's SMR virtual
- * address space. The master SMR has to be
- * no larger than the local SMR in order to
- * guarantee enough local virtual addresses
- * to see all of the SMR space.
- * XXX - Possibly add negotiating SMR size.
- * Try to create a new virtual mapping.
- * Could let domains negotiate SMR size.
- * Winning size would have to be smallest
- * in DC. If so, how to handle incoming
- * domains with even smaller SMRs?
- * - Could either disallow connection
- * - Could reconfigure to use smaller SMR.
- */
- cmn_err(CE_WARN,
- "IDN: 228: master's SMR (%ld) larger than "
- "local's SMR (%ld)",
- idn.smr.rempfnlim - idn.smr.rempfn,
- btop(MB2B(IDN_SMR_SIZE)));
-
- *exp = (uint_t)IDN_SMR_SIZE;
- *act = (uint_t)B2MB(ptob(idn.smr.rempfnlim - idn.smr.rempfn));
- rv |= CFG_ERR_SMR;
- }
- IDN_GUNLOCK();
-
- if (!valid_mtu(dp->dmtu)) {
- cmn_err(CE_WARN,
- "IDN: 219: remote domain %d MTU (%d) invalid "
- "(local.mtu = %d)", dp->domid, dp->dmtu, ldp->dmtu);
-
- *exp = (uint_t)ldp->dmtu;
- *act = (uint_t)dp->dmtu;
- rv |= CFG_ERR_MTU;
- }
- if (!valid_bufsize(dp->dbufsize)) {
- cmn_err(CE_WARN,
- "IDN: 220: remote domain %d BUFSIZE (%d) invalid "
- "(local.bufsize = %d)", dp->domid, dp->dbufsize,
- ldp->dbufsize);
-
- *exp = (uint_t)ldp->dbufsize;
- *act = (uint_t)dp->dbufsize;
- rv |= CFG_ERR_BUF;
- }
- if (!valid_nwrsize((int)dp->dnwrsize)) {
- cmn_err(CE_WARN,
- "IDN: 223: remote domain %d NWRSIZE (%d) invalid "
- "(local.nwrsize = %d)",
- dp->domid, dp->dnwrsize, ldp->dnwrsize);
-
- *exp = (uint_t)ldp->dnwrsize;
- *act = (uint_t)dp->dnwrsize;
- rv |= CFG_ERR_NWR;
- }
- if ((int)dp->dmaxnets != IDN_MAX_NETS) {
- cmn_err(CE_WARN,
- "IDN: 224: remote domain %d MAX_NETS (%d) invalid "
- "(local.maxnets = %d)",
- dp->domid, (int)dp->dmaxnets, IDN_MAX_NETS);
-
- *exp = (uint_t)IDN_MAX_NETS;
- *act = (uint_t)dp->dmaxnets;
- rv |= CFG_ERR_NETS;
- }
- if ((int)dp->dmboxpernet != IDN_MBOX_PER_NET) {
- cmn_err(CE_WARN,
- "IDN: 225: remote domain %d MBOX_PER_NET (%d) "
- "invalid (local.mboxpernet = %d)",
- dp->domid, (int)dp->dmboxpernet, IDN_MBOX_PER_NET);
-
- *exp = (uint_t)IDN_MBOX_PER_NET;
- *act = (uint_t)dp->dmboxpernet;
- rv |= CFG_ERR_MBOX;
- }
- if ((dp->dcksum - 1) != (uchar_t)IDN_CHECKSUM) {
- cmn_err(CE_WARN,
- "IDN: 226: remote domain %d CHECKSUM flag (%d) "
- "mismatches local domain's (%d)",
- dp->domid, (int)dp->dcksum - 1, IDN_CHECKSUM);
-
- *exp = (uint_t)IDN_CHECKSUM;
- *act = (uint_t)(dp->dcksum - 1);
- rv |= CFG_ERR_CKSUM;
- }
- nmcadr = 0;
- err = 0;
- for (m = 0; m < MAX_BOARDS; m++) {
- if (!BOARD_IN_SET(dp->dhw.dh_boardset, m) &&
- dp->dhw.dh_mcadr[m]) {
- cmn_err(CE_WARN,
- "IDN: 229: remote domain %d boardset (0x%x) "
- "conflicts with MCADR(board %d) [0x%x]",
- dp->domid, (uint_t)dp->dhw.dh_boardset, m,
- dp->dhw.dh_mcadr[m]);
- err++;
- }
- if (dp->dhw.dh_mcadr[m])
- nmcadr++;
- }
- if (err) {
- *exp = 0;
- *act = err;
- rv |= CFG_ERR_MCADR;
- } else if (nmcadr != dp->dhw.dh_nmcadr) {
- cmn_err(CE_WARN,
- "IDN: 230: remote domain %d reported number of "
- "MCADRs (%d) mismatches received (%d)",
- dp->domid, dp->dhw.dh_nmcadr, nmcadr);
- *exp = (uint_t)dp->dhw.dh_nmcadr;
- *act = (uint_t)nmcadr;
- rv |= CFG_ERR_NMCADR;
- }
-
-done:
-
- return (rv ? rv : CFG_DONE);
-}
-
-static int
-idn_recv_config_done(int domid)
-{
- boardset_t b_conflicts;
- cpuset_t p_conflicts;
- register int p, i;
- register idn_domain_t *dp;
- idnsb_error_t idnerr;
- procname_t proc = "idn_recv_config_done";
-
- ASSERT(domid != IDN_NIL_DOMID);
- dp = &idn_domain[domid];
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- /*
- * Well, we received all that we were expecting
- * so stop any CFG timers we had going.
- */
- IDN_MSGTIMER_STOP(domid, IDNP_CFG, 0);
-
- dp->dncpus = 0;
- for (p = 0; p < NCPU; p++)
- if (CPU_IN_SET(dp->dcpuset, p))
- dp->dncpus++;
- dp->dhw.dh_nboards = 0;
- for (p = 0; p < MAX_BOARDS; p++)
- if (BOARD_IN_SET(dp->dhw.dh_boardset, p))
- dp->dhw.dh_nboards++;
-
- IDN_GLOCK_EXCL();
- /*
- * Verify dcpuset and dhw.dh_boardset don't
- * conflict with any existing DC member.
- */
- b_conflicts = idn.dc_boardset & dp->dhw.dh_boardset;
- CPUSET_ZERO(p_conflicts);
- CPUSET_OR(p_conflicts, idn.dc_cpuset);
- CPUSET_AND(p_conflicts, dp->dcpuset);
-
- if (b_conflicts || !CPUSET_ISNULL(p_conflicts)) {
- if (b_conflicts) {
- cmn_err(CE_WARN,
- "IDN: 231: domain %d boardset "
- "(0x%x) conflicts with existing "
- "IDN boardset (0x%x)",
- domid, dp->dhw.dh_boardset,
- b_conflicts);
- }
- if (!CPUSET_ISNULL(p_conflicts)) {
- cmn_err(CE_WARN,
- "IDN: 232: domain %d cpuset "
- "(0x%x.%0x) conflicts with existing "
- "IDN cpuset (0x%x.%0x)", domid,
- UPPER32_CPUMASK(dp->dcpuset),
- LOWER32_CPUMASK(dp->dcpuset),
- UPPER32_CPUMASK(p_conflicts),
- LOWER32_CPUMASK(p_conflicts));
- }
- IDN_GUNLOCK();
- /*
- * Need to disconnect and not retry with this guy.
- */
- IDN_DUNLOCK(domid);
- IDN_SYNC_LOCK();
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- IDN_DLOCK_EXCL(domid);
-
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EPROTO);
- SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CONFIG_FATAL);
- SET_IDNKERR_PARAM0(&idnerr, domid);
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr);
-
- (void) idn_disconnect(domid, IDNFIN_FORCE_HARD,
- IDNFIN_ARG_CFGERR_FATAL, IDNFIN_SYNC_NO);
- IDN_SYNC_UNLOCK();
-
- return (-1);
- }
-
- idn_mainmbox_reset(domid, dp->dmbox.m_send);
- idn_mainmbox_reset(domid, dp->dmbox.m_recv);
-
-#ifdef IDNBUG_CPUPERBOARD
- /*
- * We only allow connections to domains whose (mem) boards
- * all have at least one cpu. This is necessary so that
- * we can program the CICs of that respective board. This
- * is primarily only a requirement if the remote domain
- * is the master _and_ has the SMR in that particular board.
- * To simplify the checking we simply restrict connections to
- * domains that have at least one cpu on all boards that
- * contain memory.
- */
- if (!idn_cpu_per_board((void *)NULL, dp->dcpuset, &dp->dhw)) {
- cmn_err(CE_WARN,
- "IDN: 233: domain %d missing CPU per "
- "memory boardset (0x%x), CPU boardset (0x%x)",
- domid, dp->dhw.dh_boardset,
- cpuset2boardset(dp->dcpuset));
-
- IDN_GUNLOCK();
- /*
- * Need to disconnect and not retry with this guy.
- */
- IDN_DUNLOCK(domid);
- IDN_SYNC_LOCK();
- DOMAINSET_DEL(idn.domset.ds_relink, domid);
- IDN_DLOCK_EXCL(domid);
-
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EINVAL);
- SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CPU_CONFIG);
- SET_IDNKERR_PARAM0(&idnerr, domid);
- idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr);
-
- (void) idn_disconnect(domid, IDNFIN_FORCE_HARD,
- IDNFIN_ARG_CPUCFG, IDNFIN_SYNC_NO);
- IDN_SYNC_UNLOCK();
-
- return (-1);
- }
-#endif /* IDNBUG_CPUPERBOARD */
-
- CPUSET_OR(idn.dc_cpuset, dp->dcpuset);
- idn.dc_boardset |= dp->dhw.dh_boardset;
-
- IDN_GUNLOCK();
-
- /*
- * Set up the portmap for this domain.
- */
- i = -1;
- for (p = 0; p < NCPU; p++) {
- BUMP_INDEX(dp->dcpuset, i);
- dp->dcpumap[p] = (uchar_t)i;
- }
-
- /*
- * Got everything we need from the remote
- * domain, now we can program hardware as needed.
- */
- if (idn_program_hardware(domid) != 0) {
- domainset_t domset;
- /*
- * Yikes! Failed to program hardware.
- * Gotta bail.
- */
- cmn_err(CE_WARN,
- "IDN: 234: failed to program hardware for domain %d "
- "(boardset = 0x%x)",
- domid, dp->dhw.dh_boardset);
-
- IDN_DUNLOCK(domid);
- /*
- * If we're having problems programming our
- * hardware we better unlink completely from
- * the IDN before things get really bad.
- */
- IDN_SYNC_LOCK();
- IDN_GLOCK_EXCL();
- IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT);
- domset = DOMAINSET_ALL;
- DOMAINSET_DEL(domset, idn.localid);
- IDN_SET_NEW_MASTERID(IDN_NIL_DOMID);
- IDN_GUNLOCK();
-
- INIT_IDNKERR(&idnerr);
- SET_IDNKERR_ERRNO(&idnerr, EINVAL);
- SET_IDNKERR_IDNERR(&idnerr, IDNKERR_HW_ERROR);
- SET_IDNKERR_PARAM0(&idnerr, domid);
- idn_update_op(IDNOP_ERROR, DOMAINSET_ALL, &idnerr);
-
- idn_unlink_domainset(domset, IDNFIN_NORMAL, IDNFIN_ARG_HWERR,
- IDNFIN_OPT_UNLINK, BOARDSET_ALL);
-
- IDN_SYNC_UNLOCK();
- IDN_DLOCK_EXCL(domid);
-
- return (-1);
- }
-
- /*
- * Now that hardware has been programmed we can
- * remap the SMR into our local space, if necessary.
- */
- IDN_GLOCK_EXCL();
- if (domid == IDN_GET_MASTERID()) {
- /*
- * No need to worry about disabling the data
- * server since at this stage there is only
- * one and he doesn't go active until his
- * mailbox (dmbox.m_recv->mm_smr_mboxp) is set up.
- */
- smr_remap(&kas, idn.smr.vaddr, idn.smr.rempfn, IDN_SMR_SIZE);
- }
- IDN_GUNLOCK();
-
- /*
- * There is no need to ACK the CFG messages since remote
- * domain would not progress to the next state (CON_SENT)
- * unless he has received everything.
- */
-
- dp->dcfgrcvdone = 1;
- PR_PROTO("%s:%d: RECV config DONE\n", proc, domid);
-
- if (dp->dcfgsnddone) {
- idn_xdcargs_t xargs;
- /*
- * Well, we've received all that we were expecting,
- * but we don't know if the remote domain has
- * received all that it was expecting from us,
- * although we know we transferred everything
- * so let's get the show on the road.
- */
- IDN_DUNLOCK(domid);
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(domid);
- /*
- * If the state has changed from CONFIG
- * then somebody else has taken over
- * control of this domain so we can just
- * bail out.
- */
- if (dp->dstate == IDNDS_CONFIG) {
- dp->dxp = &xphase_con;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- bzero(xargs, sizeof (xargs));
-
- (void) idn_xphase_transition(domid, NULL, xargs);
- }
- IDN_SYNC_UNLOCK();
- }
-
- return (0);
-}
-
-static int
-idn_verify_config_mbox(int domid)
-{
- idn_domain_t *ldp, *dp;
- idn_mainmbox_t *mmp;
- idn_mboxtbl_t *mtp;
- int c, rv = 0;
- uint_t activeptr, readyptr;
- ushort_t mbox_csum;
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- dp = &idn_domain[domid];
- ldp = &idn_domain[idn.localid];
-
- /*
- * The master will have assigned us the dmbox.m_tbl
- * from which we assign our receive mailboxes.
- * The first (0) entry contains the cookie used
- * for verification.
- */
- IDN_DLOCK_SHARED(idn.localid);
- /*
- * Now that we have an assigned mboxtbl from the
- * master, we can determine which receive mailbox
- * we indirectly assigned to him at the time we
- * sent him his MBOX_INDEX. Prep it, however note
- * that the master will have not been able to
- * validate it because of the chicken 'n egg
- * problem between a master and slave. Thus we
- * need to reset the cookie after the prep.
- */
- mmp = dp->dmbox.m_recv;
- mtp = IDN_MBOXTBL_PTR(ldp->dmbox.m_tbl, domid);
- for (c = 0; c < IDN_MAX_NETS; c++) {
- mutex_enter(&mmp[c].mm_mutex);
- ASSERT(!mmp[c].mm_smr_mboxp);
-
- mmp[c].mm_smr_mboxp = mtp;
- mbox_csum = IDN_CKSUM_MBOX(&mtp->mt_header);
- if (!VALID_MBOXHDR(&mtp->mt_header, c, mbox_csum)) {
- cmn_err(CE_WARN,
- "IDN: 235: [recv] mailbox (domain %d, "
- "channel %d) SMR CORRUPTED - RELINK",
- domid, c);
- cmn_err(CE_CONT,
- "IDN: 235: [recv] expected (cookie 0x%x, "
- "cksum 0x%x) actual (cookie 0x%x, "
- "cksum 0x%x)\n",
- IDN_GET_MBOXHDR_COOKIE(&mtp->mt_header),
- (int)mtp->mt_header.mh_cksum,
- IDN_MAKE_MBOXHDR_COOKIE(0, 0, c),
- (int)mbox_csum);
- mutex_exit(&mmp[c].mm_mutex);
- rv = -1;
- break;
- }
- activeptr = mtp->mt_header.mh_svr_active_ptr;
- readyptr = mtp->mt_header.mh_svr_ready_ptr;
- /*
- * Verify pointers are valid.
- */
- if (!activeptr || !VALID_NWROFFSET(activeptr, 2) ||
- !readyptr || !VALID_NWROFFSET(readyptr, 2)) {
- cmn_err(CE_WARN,
- "IDN: 235: [recv] mailbox (domain %d, "
- "channel %d) SMR CORRUPTED - RELINK",
- domid, c);
- cmn_err(CE_CONT,
- "IDN: 235: [recv] activeptr (0x%x), "
- "readyptr (0x%x)\n",
- activeptr, readyptr);
- mutex_exit(&mmp[c].mm_mutex);
- rv = -1;
- break;
- }
- mmp[c].mm_smr_activep = (ushort_t *)IDN_OFFSET2ADDR(activeptr);
- mmp[c].mm_smr_readyp = (ushort_t *)IDN_OFFSET2ADDR(readyptr);
- mutex_exit(&mmp[c].mm_mutex);
- IDN_MBOXTBL_PTR_INC(mtp);
- }
-
- IDN_DUNLOCK(idn.localid);
-
- if (rv)
- return (rv);
-
- /*
- * Now we need to translate SMR offsets for send mailboxes
- * to actual virtual addresses.
- */
- mmp = dp->dmbox.m_send;
- for (c = 0; c < IDN_MAX_NETS; mmp++, c++) {
- mutex_enter(&mmp->mm_mutex);
- if ((mtp = mmp->mm_smr_mboxp) == NULL) {
- mutex_exit(&mmp->mm_mutex);
- rv = -1;
- break;
- }
-
- mbox_csum = IDN_CKSUM_MBOX(&mtp->mt_header);
-
- if (!VALID_MBOXHDR(&mtp->mt_header, c, mbox_csum)) {
- cmn_err(CE_WARN,
- "IDN: 235: [send] mailbox (domain %d, "
- "channel %d) SMR CORRUPTED - RELINK",
- domid, c);
- cmn_err(CE_CONT,
- "IDN: 235: [send] expected (cookie 0x%x, "
- "cksum 0x%x) actual (cookie 0x%x, "
- "cksum 0x%x)\n",
- IDN_GET_MBOXHDR_COOKIE(&mtp->mt_header),
- (int)mtp->mt_header.mh_cksum,
- IDN_MAKE_MBOXHDR_COOKIE(0, 0, c),
- (int)mbox_csum);
- mutex_exit(&mmp->mm_mutex);
- rv = -1;
- break;
- }
- activeptr = mtp->mt_header.mh_svr_active_ptr;
- readyptr = mtp->mt_header.mh_svr_ready_ptr;
- /*
- * Paranoid check.
- */
- if (!activeptr || !VALID_NWROFFSET(activeptr, 2) ||
- !readyptr || !VALID_NWROFFSET(readyptr, 2)) {
- cmn_err(CE_WARN,
- "IDN: 235: [send] mailbox (domain %d, "
- "channel %d) SMR CORRUPTED - RELINK",
- domid, c);
- cmn_err(CE_CONT,
- "IDN: 235: [send] activeptr (0x%x), "
- "readyptr (0x%x)\n",
- activeptr, readyptr);
- mutex_exit(&mmp->mm_mutex);
- rv = -1;
- break;
- }
- mmp->mm_smr_activep = (ushort_t *)IDN_OFFSET2ADDR(activeptr);
- mmp->mm_smr_readyp = (ushort_t *)IDN_OFFSET2ADDR(readyptr);
- idn_reset_mboxtbl(mtp);
- mutex_exit(&mmp->mm_mutex);
- IDN_MBOXTBL_PTR_INC(mtp);
- }
-
- return (rv);
-}
-
-/*
- * The BUFSIZEs between domains have to be equal so that slave buffers
- * and the master's slabpool are consistent.
- * The MTUs between domains have to be equal so they can transfer
- * packets consistently without possible data truncation.
- *
- * ZZZ - Perhaps these could be negotiated?
- */
-static int
-valid_mtu(uint_t mtu)
-{
- return ((mtu == idn_domain[idn.localid].dmtu) && mtu);
-}
-
-static int
-valid_bufsize(uint_t bufsize)
-{
- return ((bufsize == idn_domain[idn.localid].dbufsize) && bufsize);
-}
-
-static int
-valid_slabsize(int slabsize)
-{
- return ((slabsize == idn_domain[idn.localid].dslabsize) && slabsize);
-}
-
-static int
-valid_nwrsize(int nwrsize)
-{
- return ((nwrsize == idn_domain[idn.localid].dnwrsize) && nwrsize);
-}
-
-static int
-idn_program_hardware(int domid)
-{
- int rv, is_master;
- idn_domain_t *dp;
- uint_t *mcadrp;
- pfn_t rem_pfn, rem_pfnlimit;
- procname_t proc = "idn_program_hardware";
-
- PR_PROTO("%s:%d: program hw in domain %d w.r.t remote domain %d\n",
- proc, domid, idn.localid, domid);
-
- dp = &idn_domain[domid];
-
- ASSERT(domid != idn.localid);
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(dp->dstate == IDNDS_CONFIG);
-
- IDN_GLOCK_EXCL();
-
- if (DOMAIN_IN_SET(idn.domset.ds_hwlinked, domid)) {
- IDN_GUNLOCK();
- return (0);
- }
-
- DOMAINSET_ADD(idn.domset.ds_flush, domid);
- CHECKPOINT_OPENED(IDNSB_CHKPT_CACHE, dp->dhw.dh_boardset, 1);
-
- if (domid != IDN_GET_MASTERID()) {
- /*
- * If the remote domain is a slave, then
- * all we have to program is the CIC sm_mask.
- */
- is_master = 0;
- if ((idn.localid == IDN_GET_MASTERID()) &&
- lock_try(&idn.first_hwlink)) {
- /*
- * This is our first HW link and I'm the
- * master, which means we need to program
- * our local bar/lar.
- */
- ASSERT(idn.first_hwmasterid == (short)IDN_NIL_DOMID);
- idn.first_hwmasterid = (short)idn.localid;
- rem_pfn = idn.smr.locpfn;
- rem_pfnlimit = idn.smr.locpfn +
- btop(MB2B(IDN_SMR_SIZE));
- } else {
- /*
- * Otherwise, just a slave linking to
- * another slave. No bar/lar updating
- * necessary.
- */
- rem_pfn = rem_pfnlimit = PFN_INVALID;
- }
- mcadrp = NULL;
- } else {
- /*
- * If the remote domain is a master, then
- * we need to program the CIC sm_mask/sm_bar/sm_lar,
- * and PC's.
- */
- is_master = 1;
- rem_pfn = idn.smr.rempfn;
- rem_pfnlimit = idn.smr.rempfnlim;
- mcadrp = dp->dhw.dh_mcadr;
- ASSERT(idn.first_hwmasterid == (short)IDN_NIL_DOMID);
- idn.first_hwmasterid = (short)domid;
- }
-
- PR_PROTO("%s:%d: ADD bset (0x%x)\n", proc, domid, dp->dhw.dh_boardset);
-
- rv = idnxf_shmem_add(is_master, dp->dhw.dh_boardset,
- rem_pfn, rem_pfnlimit, mcadrp);
-
- if (rv == 0) {
- DOMAINSET_ADD(idn.domset.ds_hwlinked, domid);
- } else {
- if (rem_pfn == idn.smr.locpfn)
- lock_clear(&idn.first_hwlink);
-
- if (idn.first_hwmasterid == (short)domid)
- idn.first_hwmasterid = (short)IDN_NIL_DOMID;
-
- (void) idnxf_shmem_sub(is_master, dp->dhw.dh_boardset);
- }
-
- IDN_GUNLOCK();
-
- return (rv);
-}
-
-static int
-idn_deprogram_hardware(int domid)
-{
- int rv, is_master;
- idn_domain_t *dp;
- procname_t proc = "idn_deprogram_hardware";
-
-
- dp = &idn_domain[domid];
-
- ASSERT(domid != idn.localid);
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- /*
- * Need to take into consideration what boards remote
- * domain was connected to. If we don't have a connection to
- * them ourself, then we better remove them now , otherwise
- * they'll never be removed (unless we link to them at some point).
- */
-#if 0
- DEBUG_USECDELAY(500000);
-#endif /* 0 */
-
- IDN_GLOCK_EXCL();
-
- if (!DOMAIN_IN_SET(idn.domset.ds_hwlinked, domid)) {
- IDN_GUNLOCK();
- return (0);
- }
-
- PR_PROTO("%s:%d: DEprogram hw in domain %d w.r.t remote domain %d\n",
- proc, domid, idn.localid, domid);
-
- /*
- * It's possible to come through this flow for domains that
- * have not been programmed, i.e. not in idn.hwlinked_domset,
- * so don't bother asserting that they might be in there.
- * This can occur if we lose a domain during the config/syn
- * sequence. If this occurs we won't know whether the remote
- * domain has programmed its hardware or not. If it has then
- * it will have to go through the DMAP sequence and thus we
- * have to go through it also. So, if we reach at least the
- * CONFIG state, we need to go through the DMAP handshake.
- */
-
- PR_PROTO("%s:%d: SUB bset (0x%x)\n", proc, domid, dp->dhw.dh_boardset);
-
- if (idn.first_hwmasterid == (short)domid) {
- is_master = 1;
- idn.first_hwmasterid = (short)IDN_NIL_DOMID;
- } else {
- is_master = 0;
- }
- rv = idnxf_shmem_sub(is_master, dp->dhw.dh_boardset);
-
- if (rv == 0)
- DOMAINSET_DEL(idn.domset.ds_hwlinked, domid);
-
- IDN_GUNLOCK();
-
- return (rv);
-}
-
-/*
- * Remember can't send slabs back to master at this point.
- * Entered with write-drwlock held.
- * Returns with drwlock dropped.
- */
-static void
-idn_deconfig(int domid)
-{
- idn_domain_t *dp, *ldp;
- smr_slab_t *sp;
- int c, masterid;
- procname_t proc = "idn_deconfig";
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
- ASSERT(domid != idn.localid);
-
- ldp = &idn_domain[idn.localid];
- dp = &idn_domain[domid];
-
- ASSERT(dp->dstate == IDNDS_DMAP);
-
- PR_PROTO("%s:%d: (dio=%d, dioerr=%d, dnslabs=%d)\n",
- proc, domid, dp->dio, dp->dioerr, dp->dnslabs);
-
- IDN_GLOCK_EXCL();
- masterid = IDN_GET_MASTERID();
-
- idn.dc_boardset &= ~dp->dhw.dh_boardset;
- for (c = 0; c < NCPU; c++) {
- if (CPU_IN_SET(dp->dcpuset, c)) {
- CPUSET_DEL(idn.dc_cpuset, c);
- }
- }
-
- IDN_GUNLOCK();
-
- (void) smr_buf_free_all(domid);
-
- if (idn.localid == masterid) {
- /*
- * Since I'm the master there may
- * have been slabs in this domain's
- * idn_domain[] entry.
- */
- DSLAB_LOCK_EXCL(domid);
- if ((sp = dp->dslab) != NULL) {
- PR_PROTO("%s:%d: freeing up %d dead slabs\n",
- proc, domid, dp->dnslabs);
- smr_slab_free(domid, sp);
- dp->dslab = NULL;
- dp->dnslabs = 0;
- dp->dslab_state = DSLAB_STATE_UNKNOWN;
- }
- DSLAB_UNLOCK(domid);
- } else if (domid == masterid) {
- /*
- * We're shutting down the master!
- * We need to blow away our local slab
- * data structures.
- * Since I'm not the master, there should
- * be no slab structures in the given
- * domain's idn_domain[] entry. They should
- * only exist in the local domain's entry.
- */
- DSLAB_LOCK_EXCL(idn.localid);
- ASSERT(dp->dslab == NULL);
-#ifdef DEBUG
- {
- int nbusy = 0;
- uint_t dommask = 0;
- for (sp = ldp->dslab; sp; sp = sp->sl_next) {
- smr_slabbuf_t *bp;
-
- if (!smr_slab_busy(sp))
- continue;
- nbusy++;
- for (bp = sp->sl_inuse; bp; bp = bp->sb_next)
- if (bp->sb_domid != IDN_NIL_DOMID)
- DOMAINSET_ADD(dommask,
- bp->sb_domid);
- }
- if (nbusy)
- PR_PROTO("%s:%d: found %d busy slabs "
- "(dommask = 0x%x)\n",
- proc, domid, nbusy, dommask);
- }
-#endif /* DEBUG */
- if ((sp = ldp->dslab) != NULL) {
- PR_PROTO("%s:%d: freeing up %d local slab "
- "structs\n", proc, domid, ldp->dnslabs);
- smr_slab_garbage_collection(sp);
- ldp->dslab = NULL;
- ldp->dnslabs = 0;
- ldp->dslab_state = DSLAB_STATE_UNKNOWN;
- }
- DSLAB_UNLOCK(idn.localid);
- }
- if (dp->dio) {
- PR_PROTO("%s:%d: reset dio (%d) to 0\n", proc, domid, dp->dio);
- dp->dio = 0;
- }
- dp->dioerr = 0;
-
- PR_PROTO("%s:%d: reset diocheck (%x) to 0\n",
- proc, domid, dp->diocheck);
- lock_clear(&dp->diocheck);
-
- CHECKPOINT_CLOSED(IDNSB_CHKPT_LINK, dp->dhw.dh_boardset, 2);
-
- /*
- * Should have already flush our memory before
- * reaching this stage. The issue is that by the
- * time we reach here the remote domains may have
- * already reprogrammed their hardware and so flushing
- * out caches now could result in a arbstop/hang
- * if we have data that needs to go back to one
- * of the remote domains that has already reprogrammed
- * its hardware.
- */
- ASSERT(!DOMAIN_IN_SET(idn.domset.ds_flush, domid));
-
- (void) idn_deprogram_hardware(domid);
- /*
- * XXX - what to do if we
- * fail to program hardware
- * probably should panic since
- * demise of system may be near?
- * Sufficient to just shutdown network?
- */
-
- IDN_DSTATE_TRANSITION(dp, IDNDS_CLOSED);
-
- idn_close_domain(domid);
-}
-
-/*
- * If we're sending a Reset we better make sure we don't have any
- * references or traffic headed in the direction of this guy, since
- * when he receives the reset, he'll start shutting down which means
- * we effectively have to shutdown _before_ sending the reset.
- * DO NOT HOLD ANY DOMAIN RWLOCKS ON ENTRY. Could result in deadlock
- * due to channel server looping back through STREAMs and attempting
- * to acquire domain lock, i.e. channel server will never "stop".
- */
-static void
-idn_shutdown_datapath(domainset_t domset, int force)
-{
- int do_allchan;
- idn_domain_t *dp;
- register int d;
- procname_t proc = "idn_shutdown_datapath";
-
-
- PR_CHAN("%s: domset = 0x%x\n", proc, (uint_t)domset);
-
- do_allchan = (domset == DOMAINSET_ALL) ? 1 : 0;
-
- DOMAINSET_DEL(domset, idn.localid);
-
- if (do_allchan) {
- /*
- * Need to stop all outgoing and
- * incoming SMR references.
- */
- idn_deactivate_channel(CHANSET_ALL, IDNCHAN_OFFLINE);
- }
-
- /*
- * If force is set then we don't want to reference
- * the SMR at all, so deactivate the domains from
- * channels first. This will result in the mainmbox-flush
- * routines to just clean up without referencing the
- * SMR space.
- */
- if (force)
- idn_mainmbox_deactivate(domset);
-
- /*
- * Flush out mailboxes (clear smr reference).
- */
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(domset, d))
- continue;
-
- dp = &idn_domain[d];
- if ((dp->dmbox.m_send == NULL) && (dp->dmbox.m_recv == NULL))
- continue;
-
- IDN_MBOX_LOCK(d);
- if (dp->dmbox.m_send)
- (void) idn_mainmbox_flush(d, dp->dmbox.m_send);
- if (dp->dmbox.m_recv)
- (void) idn_mainmbox_flush(d, dp->dmbox.m_recv);
- IDN_MBOX_UNLOCK(d);
- }
- /*
- * Deactivate all domain references also.
- * Only necessary if it wasn't already done above.
- */
- if (!force)
- idn_mainmbox_deactivate(domset);
-}
-
-void
-idn_send_cmd(int domid, idn_cmd_t cmdtype, uint_t arg1, uint_t arg2, uint_t
- arg3)
-{
- idn_msgtype_t mt;
- procname_t proc = "idn_send_cmd";
-
- mt.mt_mtype = IDNP_CMD;
- mt.mt_atype = 0;
- mt.mt_cookie = 0;
-
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- PR_PROTO("%s:%d: sending command %s\n", proc, domid,
- VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown");
-
- IDN_MSGTIMER_START(domid, IDNP_CMD, (ushort_t)cmdtype,
- idn_msg_waittime[IDNP_CMD], &mt.mt_cookie);
-
- IDNXDC(domid, &mt, (uint_t)cmdtype, arg1, arg2, arg3);
-}
-
-void
-idn_send_cmdresp(int domid, idn_msgtype_t *mtp, idn_cmd_t cmdtype, uint_t arg1,
- uint_t arg2, uint_t cerrno)
-{
- idn_msgtype_t mt;
-
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- if (domid == idn.localid) {
- /*
- * It's possible local domain received a command
- * from itself. However, we cannot send a normal
- * "ack" response (XDC) to ourself.
- */
- return;
- }
-
- mt.mt_mtype = IDNP_CMD | IDNP_ACK;
- mt.mt_atype = 0;
- mt.mt_cookie = mtp->mt_cookie;
-
- IDNXDC(domid, &mt, (uint_t)cmdtype, arg1, arg2, cerrno);
-}
-
-static void
-idn_send_cmd_nackresp(int domid, idn_msgtype_t *mtp, idn_cmd_t cmdtype,
- idn_nack_t nacktype)
-{
- idn_msgtype_t mt;
-
- if (domid == idn.localid)
- return;
-
- mt.mt_mtype = IDNP_CMD | IDNP_NACK;
- mt.mt_atype = 0;
- mt.mt_cookie = mtp->mt_cookie;
-
- (void) IDNXDC(domid, &mt, (uint_t)cmdtype, (uint_t)nacktype, 0, 0);
-}
-
-void
-idn_broadcast_cmd(idn_cmd_t cmdtype, uint_t arg1, uint_t arg2, uint_t arg3)
-{
- idn_msgtype_t mt;
- domainset_t domset;
- procname_t proc = "idn_broadcast_cmd";
-
- IDN_GLOCK_SHARED();
-
- domset = idn.domset.ds_connected;
- DOMAINSET_DEL(domset, idn.localid);
-
- PR_PROTO("%s: broadcasting command (%s) to domainset 0x%x\n",
- proc, VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown",
- domset);
-
- mt.mt_mtype = IDNP_CMD;
- mt.mt_atype = 0;
- mt.mt_cookie = 0;
-
- IDNXDC_BROADCAST(domset, &mt, (uint_t)cmdtype, arg1, arg2, arg3);
-
- IDN_GUNLOCK();
- /*
- * This is a broadcast which means local domain needs
- * to process it also. Since we can't XDC to ourselves
- * we simply call a local function.
- */
- idn_local_cmd(cmdtype, arg1, arg2, arg3);
-}
-
-/*
- * Since xargs[0] contains the cmdtype, only xargs[1], xargs[2], xargs[3]
- * are valid possible response arguments.
- */
-static void
-idn_recv_cmd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- uint_t msg = mtp->mt_mtype;
- register idn_domain_t *dp;
- idn_cmd_t cmdtype;
- uint_t acknack;
- uint_t cmdarg1, cmdarg2, cmdarg3;
- int islocal;
- int unsup_cmd_sent, unsup_cmd_recvd;
- procname_t proc = "idn_recv_cmd";
-
- acknack = msg & IDNP_ACKNACK_MASK;
- GET_XARGS(xargs, &cmdtype, &cmdarg1, &cmdarg2, &cmdarg3);
-
- dp = &idn_domain[domid];
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- IDN_GLOCK_SHARED();
-
- islocal = (domid == idn.localid);
-
- ASSERT(!acknack || (acknack & IDNP_ACKNACK_MASK));
-
- PR_PROTO("%s:%d: (local=%d) acknack=0x%x, cmdtype=%s(%d), "
- "a1=0x%x, a2=0x%x, a3=0x%x\n",
- proc, domid, islocal, acknack,
- VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown",
- cmdtype, cmdarg1, cmdarg2, cmdarg3);
-
- unsup_cmd_sent = unsup_cmd_recvd = 0;
-
- if ((IDN_GET_MASTERID() == IDN_NIL_DOMID) ||
- (dp->dstate != IDNDS_CONNECTED)) {
- /*
- * Commands cannot be handled without a valid
- * master. If this is a request then nack him.
- */
- PR_PROTO("%s:%d: cannot process CMD w/o master (%d, %s)\n",
- proc, domid, IDN_GET_MASTERID(),
- idnds_str[dp->dstate]);
-
- if (!islocal && !(acknack & IDNP_ACKNACK_MASK))
- idn_send_cmd_nackresp(domid, mtp, cmdtype,
- IDNNACK_NOCONN);
- IDN_GUNLOCK();
- return;
- }
- IDN_GUNLOCK();
-
- if (acknack & IDNP_ACKNACK_MASK) {
- idn_nack_t nack;
- /*
- * Receiving a cmd+ack or cmd+nack in response to some
- * earlier command we must have issued.
- * If the response is a nack, there are two possibilites:
- *
- * 1. Remote domain failed to allocate due
- * to limited resources.
- *
- * 2. Remote domain does not support this
- * particular command.
- *
- * In the case of #2, the argument immediately after
- * the cmdtype (xargs[1]) will be (-1).
- */
- nack = (idn_nack_t)cmdarg1;
- if ((acknack & IDNP_NACK) && (nack == IDNNACK_BADCMD))
- unsup_cmd_sent++;
-
- if (islocal) {
- /*
- * Shouldn't be receiving local commands w/acks.
- */
- cmdtype = (idn_cmd_t)0;
- }
-
- switch (cmdtype) {
- case IDNCMD_SLABALLOC:
- idn_recv_slaballoc_resp(domid, cmdarg1, cmdarg2,
- cmdarg3);
- break;
-
- case IDNCMD_SLABFREE:
- idn_recv_slabfree_resp(domid, cmdarg1, cmdarg2,
- cmdarg3);
- break;
-
- case IDNCMD_SLABREAP:
- /*
- * We only care if successful.
- */
- if (acknack & IDNP_ACK)
- idn_recv_slabreap_resp(domid, cmdarg1, cmdarg3);
- break;
-
- case IDNCMD_NODENAME:
- if ((acknack & IDNP_NACK) == 0) {
- idn_recv_nodename_resp(domid, cmdarg1, cmdarg3);
- break;
- }
- switch (nack) {
- case IDNNACK_NOCONN:
- case IDNNACK_RETRY:
- /*
- * Remote domain was not quite
- * ready, try again.
- */
- PR_PROTO("%s:%d: remote not ready "
- "for %s - retrying "
- "[dstate=%s]\n",
- proc, domid,
- idncmd_str[IDNCMD_NODENAME],
- idnds_str[dp->dstate]);
-
- if (dp->dstate == IDNDS_CONNECTED)
- (void) timeout(idn_retry_nodename_req,
- (void *)(uintptr_t)domid, hz);
- default:
- break;
- }
- break;
-
- default:
- /*
- * Unsupported command.
- */
- unsup_cmd_recvd++;
- break;
- }
- if (unsup_cmd_sent) {
- PR_PROTO("%s:%d: unsupported command "
- "requested (0x%x)\n",
- proc, domid, cmdtype);
- }
- if (unsup_cmd_recvd) {
- PR_PROTO("%s:%d: unsupported command "
- "response (0x%x)\n",
- proc, domid, cmdtype);
- }
- } else {
- /*
- * Receiving a regular cmd from a remote domain.
- */
- switch (cmdtype) {
- case IDNCMD_SLABALLOC:
- idn_recv_slaballoc_req(domid, mtp, cmdarg1);
- break;
-
- case IDNCMD_SLABFREE:
- idn_recv_slabfree_req(domid, mtp, cmdarg1, cmdarg2);
- break;
-
- case IDNCMD_SLABREAP:
- idn_recv_slabreap_req(domid, mtp, cmdarg1);
- break;
-
- case IDNCMD_NODENAME:
- idn_recv_nodename_req(domid, mtp, cmdarg1);
- break;
-
- default:
- /*
- * Unsupported command.
- */
- unsup_cmd_recvd++;
- break;
- }
- if (!islocal && unsup_cmd_recvd) {
- /*
- * Received an unsupported IDN command.
- */
- idn_send_cmd_nackresp(domid, mtp, cmdtype,
- IDNNACK_BADCMD);
- }
- }
-}
-
-/*
- * This is a supporting routine for idn_broadcast_cmd() to
- * handle processing of the requested command for the local
- * domain. Currently the only support broadcast command
- * supported is reaping.
- */
-/*ARGSUSED2*/
-static void
-idn_local_cmd(idn_cmd_t cmdtype, uint_t arg1, uint_t arg2, uint_t arg3)
-{
- idn_protojob_t *jp;
- idn_domain_t *ldp = &idn_domain[idn.localid];
- procname_t proc = "idn_local_cmd";
-
- PR_PROTO("%s: submitting local command %s on domain %d\n",
- proc, VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown",
- idn.localid);
-
-
- jp = idn_protojob_alloc(KM_SLEEP);
-
- jp->j_msg.m_domid = ldp->domid;
- jp->j_msg.m_msgtype = IDNP_CMD;
- jp->j_msg.m_cookie = ldp->dcookie_recv;
- SET_XARGS(jp->j_msg.m_xargs, cmdtype, arg1, arg2, arg3);
-
- idn_protojob_submit(ldp->domid, jp);
-}
-
-/*
- * Terminate any outstanding commands that may have
- * been targeted for the given domain. A command is
- * designated as outstanding if it has an active timer.
- *
- * serrno = ECANCELED.
- */
-static void
-idn_terminate_cmd(int domid, int serrno)
-{
- idn_domain_t *dp;
- idn_timer_t *tplist = NULL, *tp;
- procname_t proc = "idn_terminate_cmd";
-
- dp = &idn_domain[domid];
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- IDN_MSGTIMER_GET(dp, IDNP_CMD, tplist, 0);
- /*
- * At this point the timers are effectively terminated
- * since when they're t_onq indication is set false.
- */
- if (tplist == NULL) {
- PR_PROTO("%s:%d: no outstanding cmds found\n",
- proc, domid);
- /*
- * There is a window where we may have caught a
- * request just prior to issuing the actual
- * command (SLABALLOC). We're guaranteed if there
- * was, then he will have at least registered.
- * So, if we abort the command now, he'll catch
- * it before going to sleep.
- * Drop through.
- */
- }
- ASSERT(tplist ? (tplist->t_back->t_forw == NULL) : 1);
-
- for (tp = tplist; tp; tp = tp->t_forw) {
- ASSERT(tp->t_type == IDNP_CMD);
-
- PR_PROTO("%s:%d: found outstanding cmd: %s\n",
- proc, domid, idncmd_str[tp->t_subtype]);
-
- switch (tp->t_subtype) {
- case IDNCMD_SLABALLOC:
- /*
- * Outstanding slaballoc request may have
- * slab waiters hanging around. Need to
- * tell them to bail out. The given domain
- * must be the master if we have an outstanding
- * command to him. This also presumes that
- * if there are any waiters they're only in
- * the local domain's waiting area (i.e. we're
- * a slave).
- */
-#ifdef DEBUG
- IDN_GLOCK_SHARED();
- ASSERT(domid == IDN_GET_MASTERID());
- ASSERT(idn.localid != IDN_GET_MASTERID());
- IDN_GUNLOCK();
-#endif /* DEBUG */
- (void) smr_slabwaiter_abort(idn.localid, serrno);
- break;
-
- case IDNCMD_SLABFREE:
- case IDNCMD_SLABREAP:
- case IDNCMD_NODENAME:
- /*
- * Nothing really waiting for these operations
- * so no biggy if we just drop.
- * Note that NODENAME may have an outstanding
- * buffer, however that will be reclaimed
- * when we actually unlink from domain.
- */
- break;
-
- default:
- ASSERT(0);
- break;
- }
- }
- /*
- * As mentioned before the timers are effectively no-op'd
- * once they're dequeued, however let's cleanup house and
- * get rid of the useless entries in the timeout queue.
- */
- if (tplist) {
- IDN_TIMER_STOPALL(tplist);
- }
-
- if (idn_domain[idn.localid].dvote.v.master) {
- /*
- * I'm the master so it's possible I had
- * outstanding commands (SLABALLOC) waiting
- * to be satisfied for the given domain.
- * Since we're forcing an error it's okay
- * to continue holding onto the drwlock.
- */
- PR_PROTO("%s:%d: abort slaballoc waiters\n", proc, domid);
- (void) smr_slabwaiter_abort(domid, serrno);
-
- } else if (dp->dvote.v.master) {
- PR_PROTO("%s:%d: abort (local domain) slaballoc waiters\n",
- proc, domid);
- (void) smr_slabwaiter_abort(idn.localid, serrno);
- }
-}
-
-static void
-idn_send_acknack(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_send_acknack";
-
- ASSERT(mtp ? (mtp->mt_mtype & IDNP_ACKNACK_MASK) : 1);
- ASSERT(domid != IDN_NIL_DOMID);
-
-#ifdef DEBUG
- {
- STRING(mstr);
- STRING(astr);
-
- INUM2STR(mtp->mt_mtype, mstr);
- INUM2STR(mtp->mt_atype, astr);
-
- if (mtp->mt_mtype & IDNP_ACK) {
- PR_PROTO("%s:%d: dstate=%s, msg=(%s/%s), "
- "a1=0x%x, a2=0x%x, a3=0x%x, a4 = 0x%x\n",
- proc, domid, idnds_str[dp->dstate],
- astr, mstr, xargs[0], xargs[1],
- xargs[2], xargs[3]);
- } else {
- idn_nack_t nack;
-
- nack = GET_XARGS_NACK_TYPE(xargs);
- PR_PROTO("%s:%d: dstate=%s, msg=(%s/%s), "
- "nack=%s(0x%x)\n",
- proc, domid, idnds_str[dp->dstate],
- astr, mstr, idnnack_str[nack],
- (uint_t)nack);
- }
- }
-#endif /* DEBUG */
-
- (void) IDNXDC(domid, mtp, xargs[0], xargs[1], xargs[2], xargs[3]);
-}
-
-/*ARGSUSED0*/
-static void
-idn_prealloc_slab(int nslabs)
-{
- register int s, serrno;
- smr_slab_t *sp;
- idn_domain_t *ldp = &idn_domain[idn.localid];
- procname_t proc = "idn_prealloc_slab";
-
- IDN_GLOCK_SHARED();
- DSLAB_LOCK_SHARED(idn.localid);
- if ((idn.state != IDNGS_ONLINE) || (ldp->dnslabs > 0)) {
- /*
- * Not in the proper state or slab already allocated.
- */
- DSLAB_UNLOCK(idn.localid);
- IDN_GUNLOCK();
- return;
- }
- IDN_GUNLOCK();
- ASSERT(!ldp->dslab);
-
- serrno = 0;
- for (s = 0; (s < nslabs) && ((int)ldp->dnslabs < nslabs); s++) {
- /*
- * Returns with ldp->drwlock dropped.
- */
- serrno = smr_slab_alloc(idn.localid, &sp);
- if (serrno != 0) {
- PR_PROTO("%s: FAILED to pre-alloc'd "
- "slab (serrno = %d)\n", proc, serrno);
- break;
- }
- /*
- * State may have changed since smr_slab_alloc
- * temporarily drops drwlock. Make sure we're
- * still connected.
- */
- PR_PROTO("%s: SUCCESSFULLY pre-alloc'd slab\n", proc);
-
- if (idn.state != IDNGS_ONLINE) {
- PR_PROTO("%s: Lost connection..leaving\n", proc);
- break;
- }
- }
-
- DSLAB_UNLOCK(idn.localid);
-}
-
-/*
- * Received a request from a remote domain to
- * allocate a slab from the master SMR for him.
- * Allocate slab and return the response.
- */
-static void
-idn_recv_slaballoc_req(int domid, idn_msgtype_t *mtp, uint_t slab_size)
-{
- register idn_domain_t *dp;
- procname_t proc = "idn_recv_slaballoc_req";
-
- PR_PROTO("%s: slaballoc req from domain %d (size=0x%x)\n",
- proc, domid, slab_size);
-
- dp = &idn_domain[domid];
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- IDN_GLOCK_SHARED();
-
- if (idn.localid != IDN_GET_MASTERID()) {
- IDN_GUNLOCK();
- /*
- * It's a fatal error if the remote domain thinks
- * we're the master.
- */
- idn_send_slaballoc_resp(domid, mtp, 0, 0, EACCES);
-
- } else if (dp->dstate != IDNDS_CONNECTED) {
-
- IDN_GUNLOCK();
- /*
- * It's a fatal error if we don't yet have a
- * connection established with the requestor.
- */
- idn_send_slaballoc_resp(domid, mtp, 0, 0, ENOLINK);
- } else {
- int serrno;
- smr_slab_t *sp;
- smr_offset_t slab_offset;
-
- IDN_GUNLOCK();
- DSLAB_LOCK_SHARED(domid);
- IDN_DUNLOCK(domid);
- /*
- * We're connected and we're the master.
- * smr_slab_alloc() returns with dp->drwlock dropped.
- */
- if ((serrno = smr_slab_alloc(domid, &sp)) == 0) {
- /*
- * Successfully allocated slab for remote slave.
- */
- slab_offset = IDN_ADDR2OFFSET(sp->sl_start);
- slab_size = sp->sl_end - sp->sl_start;
- ASSERT((slab_offset != 0) && (slab_size != 0));
- } else {
- slab_offset = slab_size = 0;
- }
- DSLAB_UNLOCK(domid);
- /*
- * The drwlock is dropped during smr_slab_alloc.
- * During that time our connection with the given
- * domain may have changed. Better check again.
- */
- IDN_DLOCK_SHARED(domid);
- if ((dp->dstate != IDNDS_CONNECTED) && !serrno) {
- /*
- * Connection broke. Keep the slab here.
- */
- DSLAB_LOCK_EXCL(domid);
- IDN_DUNLOCK(domid);
- smr_slab_free(domid, sp);
- DSLAB_UNLOCK(domid);
- slab_offset = slab_size = 0;
- serrno = ECANCELED;
- IDN_DLOCK_SHARED(domid);
- }
- /*
- * Send response.
- * Note that smr_slab_alloc automatically installs
- * slab into domains respective idn_domain entry
- * to be associated with that domain.
- */
- idn_send_slaballoc_resp(domid, mtp, slab_offset, slab_size,
- serrno);
- }
-}
-
-static void
-idn_send_slaballoc_resp(int domid, idn_msgtype_t *mtp, smr_offset_t slab_offset,
- uint_t slab_size, int serrno)
-{
- procname_t proc = "idn_send_slaballoc_resp";
-
- PR_PROTO("%s: slaballoc resp to domain %d (off=0x%x, size=0x%x) "
- "[serrno = %d]\n",
- proc, domid, slab_offset, slab_size, serrno);
-
- idn_send_cmdresp(domid, mtp, IDNCMD_SLABALLOC, slab_offset, slab_size,
- serrno);
-}
-
-/*
- * Received the ack or nack to a previous allocation request
- * made by the local domain to the master for a slab. Need
- * to "put" the response into the waiting area for any
- * waiters.
- */
-static void
-idn_recv_slaballoc_resp(int domid, smr_offset_t slab_offset, uint_t slab_size,
- int serrno)
-{
- smr_slab_t *sp = NULL;
- int rv;
- procname_t proc = "idn_recv_slaballoc_resp";
-
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- PR_PROTO("%s: slaballoc resp from domain %d (off=0x%x, size=0x%x) "
- "[serrno = %d]\n",
- proc, domid, slab_offset, slab_size, serrno);
-
- if (!serrno) {
- IDN_GLOCK_SHARED();
- if (domid != IDN_GET_MASTERID()) {
- /*
- * We should only be receiving responses from
- * our master. This is either a bogus message
- * or an old response. In either case dump it.
- */
- PR_PROTO("%s: BOGUS slaballoc resp from domid %d "
- "(master = %d)\n",
- proc, domid, IDN_GET_MASTERID());
- serrno = EPROTO;
- }
- IDN_GUNLOCK();
-
- if (!serrno &&
- !VALID_NWROFFSET(slab_offset, IDN_SMR_BUFSIZE)) {
- PR_PROTO("%s: slab offset (0x%x) out of range "
- "(0-0x%lx)\n",
- proc, slab_offset, MB2B(IDN_NWR_SIZE));
- serrno = EPROTO;
- } else if (!serrno) {
- sp = GETSTRUCT(smr_slab_t, 1);
- sp->sl_start = IDN_OFFSET2ADDR(slab_offset);
- sp->sl_end = sp->sl_start + slab_size;
- smr_alloc_buflist(sp);
- }
- }
-
- /*
- * Always "put" slabs back to yourself since you're a slave.
- * Note that we set the forceflag so that even if there are
- * no waiters we still install the slab for the domain.
- */
- if (!serrno) {
- DSLAB_LOCK_EXCL(idn.localid);
- }
- rv = smr_slaballoc_put(idn.localid, sp, 1, serrno);
- if (!serrno) {
- DSLAB_UNLOCK(idn.localid);
- }
-
- if (rv < 0) {
- /*
- * Some kind of error trying to install response.
- * If there was a valid slab sent to us, we'll
- * just have to send it back.
- */
- PR_PROTO("%s: failed to install response in waiting area\n",
- proc);
- if (slab_size != 0) {
- PR_PROTO("%s: sending slab back to domain %d "
- "(master = %d)\n",
- proc, domid, IDN_GET_MASTERID());
- idn_send_cmd(domid, IDNCMD_SLABFREE, slab_offset,
- slab_size, 0);
- }
- if (sp) {
- smr_free_buflist(sp);
- FREESTRUCT(sp, smr_slab_t, 1);
- }
- }
-}
-
-/*
- * Note that slab reaping is effectively performed asynchronously
- * since the request will be received a protocol server.
- */
-static void
-idn_recv_slabreap_req(int domid, idn_msgtype_t *mtp, int nslabs)
-{
- procname_t proc = "idn_recv_slabreap_req";
-
- PR_PROTO("%s: slab reap request (nslabs = %d)\n", proc, nslabs);
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- IDN_GLOCK_SHARED();
- if (domid != IDN_GET_MASTERID()) {
- /*
- * Only the master can request that slabs be reaped.
- */
- IDN_GUNLOCK();
- PR_PROTO("%s: only master can request slab reaping\n", proc);
-
- idn_send_cmdresp(domid, mtp, IDNCMD_SLABREAP, 0, 0, EACCES);
-
- return;
- }
- IDN_GUNLOCK();
-
- if (nslabs != 0) {
- IDN_DUNLOCK(domid);
- smr_slab_reap(idn.localid, &nslabs);
- IDN_DLOCK_SHARED(domid);
- }
-
- PR_PROTO("%s: slab reap result (nslabs = %d)\n", proc, nslabs);
-
- /*
- * Go ahead and send the reap response back before we start
- * free'ing off the individual slabs.
- */
- idn_send_slabreap_resp(domid, mtp, nslabs, 0);
-}
-
-static void
-idn_recv_slabreap_resp(int domid, int nslabs, int serrno)
-{
- procname_t proc = "idn_recv_slabreap_resp";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if ((idn.localid != IDN_GET_MASTERID()) || (idn.localid == domid)) {
- PR_PROTO("%s: unexpected slabreap resp received "
- "(domid = %d)\n", proc, domid);
- ASSERT(0);
- return;
- }
- PR_PROTO("%s: recvd reap response from domain %d for %d slabs "
- "[serrno = %d]\n", proc, domid, nslabs, serrno);
-}
-
-/*
- * Not really necessary to send slabreap response.
- * XXX - perhaps useful to master for accounting or
- * throttling of further reaping?
- */
-static void
-idn_send_slabreap_resp(int domid, idn_msgtype_t *mtp, int nslabs, int serrno)
-{
- idn_send_cmdresp(domid, mtp, IDNCMD_SLABREAP, nslabs, 0, serrno);
-}
-
-/*
- * Slave -> Master ONLY
- * Master never sends slabfree request to itself.
- */
-static void
-idn_recv_slabfree_req(int domid, idn_msgtype_t *mtp, smr_offset_t slab_offset,
- uint_t slab_size)
-{
- smr_slab_t *sp;
- int serrno;
- caddr_t s_start, s_end;
- procname_t proc = "idn_recv_slabfree_req";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (domid == IDN_GET_MASTERID()) {
- PR_PROTO("%s: unexpected slabfree req received (domid = %d)\n",
- proc, domid);
- idn_send_slabfree_resp(domid, mtp, slab_offset, slab_size,
- EACCES);
- return;
- }
- if (slab_size > IDN_SLAB_SIZE) {
- PR_PROTO("%s: unexpected slab size. exp %d, recvd %d\n",
- proc, IDN_SLAB_SIZE, slab_size);
- idn_send_slabfree_resp(domid, mtp, slab_offset, slab_size,
- EINVAL);
- return;
- }
- s_start = IDN_OFFSET2ADDR(slab_offset);
- s_end = s_start + slab_size;
- /*
- * Master has received a SLABFREE request (effectively a response
- * to some earlier SLABREAP request.
- * Find the slab associated with this slab and free it up.
- */
- DSLAB_LOCK_EXCL(domid);
- if ((sp = smr_slaballoc_get(domid, s_start, s_end)) != NULL) {
- smr_slab_free(domid, sp);
- serrno = 0;
- } else {
- serrno = EINVAL;
- }
- DSLAB_UNLOCK(domid);
-
- idn_send_slabfree_resp(domid, mtp, slab_offset, slab_size, serrno);
-}
-
-/*
- * Master -> Slave ONLY
- */
-static void
-idn_recv_slabfree_resp(int domid, uint_t slab_offset, uint_t slab_size, int
- serrno)
-{
- procname_t proc = "idn_recv_slabfree_resp";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (domid != IDN_GET_MASTERID()) {
- PR_PROTO("%s: unexpected slabfree resp received (domid = %d)\n",
- proc, domid);
- ASSERT(0);
- return;
- }
- if (slab_size > IDN_SLAB_SIZE) {
- PR_PROTO("%s: unexpected slab size. exp %d, recvd %d\n",
- proc, IDN_SLAB_SIZE, slab_size);
- ASSERT(0);
- return;
- }
- PR_PROTO("%s: recvd free resp from dom %d "
- "- slab (off/size) 0x%x/0x%x [serrno = %d]\n",
- proc, domid, slab_offset, slab_size, serrno);
-}
-
-static void
-idn_send_slabfree_resp(int domid, idn_msgtype_t *mtp, uint_t slab_offset,
- uint_t slab_size, int serrno)
-{
- idn_send_cmdresp(domid, mtp, IDNCMD_SLABFREE, slab_offset, slab_size,
- serrno);
-}
-
-static void
-idn_retry_nodename_req(void *arg)
-{
- int domid = (int)(uintptr_t)arg;
-
- idn_send_nodename_req(domid);
-}
-
-static void
-idn_send_nodename_req(int domid)
-{
- caddr_t b_bufp;
- smr_offset_t bufoffset;
- int serrno;
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_send_nodename_req";
-
- /*
- * Need to drop domain lock across
- * SMR allocation.
- */
- serrno = smr_buf_alloc(domid, MAXDNAME+1, &b_bufp);
-
- IDN_DLOCK_SHARED(domid);
- if (dp->dstate != IDNDS_CONNECTED) {
- /*
- * Lost connection.
- */
- PR_PROTO("%s:%d: connection lost [dstate = %s]\n",
- proc, domid, idnds_str[dp->dstate]);
- IDN_DUNLOCK(domid);
- if (!serrno)
- (void) smr_buf_free(domid, b_bufp, MAXDNAME+1);
- return;
- }
- if (serrno) {
- /*
- * Failed to allocate buffer, but still have
- * connection so keep trying. We may have queried
- * the master a little too earlier.
- */
- PR_PROTO("%s:%d: buffer alloc failed [dstate = %s]\n",
- proc, domid, idnds_str[dp->dstate]);
- (void) timeout(idn_retry_nodename_req, (void *)(uintptr_t)domid,
- hz);
- IDN_DUNLOCK(domid);
- return;
- }
-
- *b_bufp = (char)MAXDNAME;
- bufoffset = IDN_ADDR2OFFSET(b_bufp);
-
- idn_send_cmd(domid, IDNCMD_NODENAME, bufoffset, 0, 0);
- IDN_DUNLOCK(domid);
-}
-
-static void
-idn_send_nodename_resp(int domid, idn_msgtype_t *mtp, smr_offset_t bufoffset,
- int serrno)
-{
- idn_send_cmdresp(domid, mtp, IDNCMD_NODENAME, (uint_t)bufoffset, 0,
- serrno);
-}
-
-static void
-idn_recv_nodename_req(int domid, idn_msgtype_t *mtp, smr_offset_t bufoffset)
-{
- caddr_t b_bufp;
- int length;
- idn_domain_t *ldp = &idn_domain[idn.localid];
- procname_t proc = "idn_recv_nodename_req";
-
- IDN_DLOCK_EXCL(idn.localid);
- if (!strlen(ldp->dname)) {
- if (!strlen(utsname.nodename)) {
- /*
- * Local domain's nodename hasn't been
- * set yet.
- */
- IDN_DUNLOCK(idn.localid);
- idn_send_cmd_nackresp(domid, mtp, IDNCMD_NODENAME,
- IDNNACK_RETRY);
- return;
- }
- (void) strncpy(ldp->dname, utsname.nodename, MAXDNAME - 1);
- }
- IDN_DLOCK_DOWNGRADE(idn.localid);
-
- if (!VALID_NWROFFSET(bufoffset, IDN_SMR_BUFSIZE)) {
- PR_PROTO("%s:%d: invalid SMR offset received (0x%x)\n",
- proc, domid, bufoffset);
- IDN_DUNLOCK(idn.localid);
- idn_send_nodename_resp(domid, mtp, bufoffset, EINVAL);
- return;
- }
-
- b_bufp = IDN_OFFSET2ADDR(bufoffset);
- length = (int)(*b_bufp++ & 0xff);
-
- if (length < strlen(ldp->dname)) {
- PR_PROTO("%s:%d: buffer not big enough (req %lu, got %d)\n",
- proc, domid, strlen(ldp->dname), length);
- IDN_DUNLOCK(idn.localid);
- idn_send_nodename_resp(domid, mtp, bufoffset, EINVAL);
- return;
- }
-
- (void) strncpy(b_bufp, ldp->dname, MAXDNAME);
- b_bufp[MAXDNAME-1] = 0;
- IDN_DUNLOCK(idn.localid);
-
- idn_send_nodename_resp(domid, mtp, bufoffset, 0);
-}
-
-static void
-idn_recv_nodename_resp(int domid, smr_offset_t bufoffset, int serrno)
-{
- caddr_t b_bufp;
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_recv_nodename_resp";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- if (!VALID_NWROFFSET(bufoffset, IDN_SMR_BUFSIZE)) {
- PR_PROTO("%s:%d: invalid SMR offset received (0x%x)\n",
- proc, domid, bufoffset);
- return;
- }
-
- if (serrno == 0) {
- b_bufp = IDN_OFFSET2ADDR(bufoffset) + 1;
- b_bufp[MAXDNAME-1] = 0;
-
- if (strlen(b_bufp) > 0) {
- (void) strncpy(dp->dname, b_bufp, MAXDNAME);
- PR_PROTO("%s:%d: received nodename(%s)\n",
- proc, domid, dp->dname);
- }
- }
-
- (void) smr_buf_free(domid, b_bufp - 1, MAXDNAME + 1);
-}
-
-/*
- * The master allocations the SMR management structures.
- */
-static int
-idn_master_init()
-{
- idn_domain_t *ldp = &idn_domain[idn.localid];
- size_t reserved_size = 0;
- caddr_t reserved_area = NULL;
- procname_t proc = "idn_master_init";
-
- ASSERT(IDN_GLOCK_IS_EXCL());
- ASSERT(IDN_DLOCK_IS_EXCL(idn.localid));
-
- if (idn.mboxarea != NULL) {
- PR_PROTO("%s: master data already initialized\n", proc);
- return (0);
- }
-
- PR_PROTO("%s: initializing master data (domid = %d)\n",
- proc, idn.localid);
-
- /*
- * Reserve an area of the SMR for mailbox usage.
- * This area is allocated to other domains via
- * the master. Round it up to IDN_SMR_BUFSIZE multiple.
- */
- reserved_size = IDNROUNDUP(IDN_MBOXAREA_SIZE, IDN_SMR_BUFSIZE);
-
- PR_PROTO("%s: reserving %lu bytes for mailbox area\n",
- proc, reserved_size);
-
-#ifdef DEBUG
- if (reserved_size > (size_t)IDN_SLAB_SIZE) {
- PR_PROTO("%s: WARNING mbox area (%ld) > slab size (%d)\n",
- proc, reserved_size, IDN_SLAB_SIZE);
- }
-#endif /* DEBUG */
- /*
- * Initialize the pool of slabs and SMR I/O buffers.
- */
- if (smr_slabpool_init(reserved_size, &reserved_area) != 0) {
- idn_master_deinit();
- return (-1);
- }
-
- ASSERT(idn.mboxarea == NULL);
- ASSERT(reserved_area);
-
- bzero(reserved_area, reserved_size);
-
- idn.mboxarea = (idn_mboxtbl_t *)reserved_area;
- ldp->dmbox.m_tbl = IDN_MBOXAREA_BASE(idn.mboxarea, idn.localid);
- /*
- * Initialize the SMR pointers in the entire
- * mailbox table.
- */
- idn_mboxarea_init(idn.mboxarea, IDN_MBOXAREA_SIZE / IDN_MBOXTBL_SIZE);
-
- return (0);
-}
-
-static void
-idn_master_deinit()
-{
- idn_domain_t *ldp;
- smr_slab_t *sp;
- procname_t proc = "idn_master_deinit";
-
- ASSERT(IDN_GLOCK_IS_EXCL());
- ASSERT(IDN_DLOCK_IS_EXCL(idn.localid));
-
- if (idn.mboxarea == NULL) {
- PR_PROTO("%s: master data already deinitialized\n", proc);
- return;
- }
-
- ldp = &idn_domain[idn.localid];
-
- PR_PROTO("%s: deinitializing master data (domid = %d)\n",
- proc, idn.localid);
-
- ldp->dmbox.m_tbl = NULL;
- idn.mboxarea = NULL;
- /*
- * Master may still be holding onto slabs of his own.
- */
- DSLAB_LOCK_EXCL(idn.localid);
- sp = ldp->dslab;
- ldp->dslab = NULL;
- ldp->dnslabs = 0;
- if (sp)
- smr_slab_free(idn.localid, sp);
- ldp->dslab_state = DSLAB_STATE_UNKNOWN;
- DSLAB_UNLOCK(idn.localid);
-
- smr_slabpool_deinit();
-}
-
-static int
-idn_mark_awol(int domid, clock_t *atime)
-{
- clock_t awol;
- idn_domain_t *dp = &idn_domain[domid];
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_GLOCK_IS_EXCL());
-
- if (!DOMAIN_IN_SET(idn.domset.ds_awol, domid)) {
- DOMAINSET_ADD(idn.domset.ds_awol, domid);
- idn.nawols++;
- }
- awol = ddi_get_lbolt();
- if (dp->dawol.a_count++ == 0)
- dp->dawol.a_time = awol;
- dp->dawol.a_last = awol;
- if ((awol - dp->dawol.a_msg) >= (clock_t)(idn_awolmsg_interval * hz))
- dp->dawol.a_msg = awol;
- else
- awol = 0;
-
- *atime = awol;
-
- idn_awol_event_set(dp->dhw.dh_boardset);
-
- return (dp->dawol.a_count);
-}
-
-void
-idn_clear_awol(int domid)
-{
- idn_domain_t *dp = &idn_domain[domid];
-
- ASSERT(IDN_SYNC_IS_LOCKED());
- ASSERT(IDN_GLOCK_IS_EXCL());
- if (DOMAIN_IN_SET(idn.domset.ds_awol, domid)) {
- DOMAINSET_DEL(idn.domset.ds_awol, domid);
- idn.nawols--;
- }
- if (dp->dawol.a_count > 0) {
- dp->dawol.a_count = 0;
- dp->dawol.a_last = dp->dawol.a_time;
- dp->dawol.a_time = 0;
- dp->dawol.a_msg = 0;
-
- idn_awol_event_clear(dp->dhw.dh_boardset);
- }
-}
-
-/*
- * A timer expired.
- */
-void
-idn_timer_expired(void *arg)
-{
- idn_domain_t *dp;
- char *op = "UNKNOWN";
- clock_t awol = 0;
- int awolcount, dcpu, domid;
- idn_timer_t *tp = (idn_timer_t *)arg;
- idn_timerq_t *tq = NULL;
- uint_t token;
- char dname[MAXDNAME];
- procname_t proc = "idn_timer_expired";
- STRING(str);
-
- tq = tp->t_q;
-
- ASSERT(tp->t_domid != IDN_NIL_DOMID);
-
- IDN_TIMERQ_LOCK(tq);
-
- INUM2STR(tp->t_type, str);
-
- if (tp->t_onq == 0) {
- PR_TIMER("%s: timer CAUGHT TERMINATION (type = %s)\n",
- proc, str);
- /*
- * Timer was dequeued. Somebody is trying
- * to shut it down.
- */
- IDN_TIMERQ_UNLOCK(tq);
- return;
- }
-
- IDN_TIMER_DEQUEUE(tq, tp);
-
- IDN_TIMERQ_UNLOCK(tq);
-
- IDN_SYNC_LOCK();
- IDN_DLOCK_EXCL(tp->t_domid);
-
- domid = tp->t_domid;
-
- dp = &idn_domain[domid];
- (void) strcpy(dname, dp->dname);
- dcpu = dp->dcpu;
-
- IDN_TIMER_EXEC(tp);
-
-#ifdef DEBUG
- PR_TIMER("%s:%d: [%s] timer EXPIRED (C=0x%x, P=0x%llx, X=0x%llx)\n",
- proc, tp->t_domid, str, tp->t_cookie,
- tp->t_posttime, tp->t_exectime);
-#endif /* DEBUG */
-
- /*
- * IMPORTANT:
- * Each case is responsible for dropping SYNC_LOCK & DLOCK.
- */
- switch (tp->t_type) {
- case IDNP_DATA:
- IDN_SYNC_UNLOCK();
- /*
- * Timed out waiting for a data packet response.
- * We can't close domain since he may just be
- * temporarily AWOL.
- * Note that dio and diocheck do not get cleared.
- * This is taken care of when the domain restarts
- * or is fatally closed.
- * We only need a reader lock for this.
- */
- IDN_DLOCK_DOWNGRADE(domid);
- if (dp->diocheck && dp->dmbox.m_send) {
- (void) idn_reclaim_mboxdata(domid, 0, -1);
- if (dp->dio >= IDN_WINDOW_EMAX) {
- idn_msgtype_t mt;
- /*
- * Restart timer for another
- * go around.
- */
- IDN_MSGTIMER_START(domid, IDNP_DATA, 0,
- idn_msg_waittime[IDNP_DATA],
- &mt.mt_cookie);
- } else {
- lock_clear(&dp->diocheck);
- }
- }
- IDN_DUNLOCK(domid);
- break;
-
- case IDNP_NEGO:
- /*
- * If we're not in a NEGO transition, then
- * just ignore this timeout.
- */
- if (dp->dxp == &xphase_nego) {
- uint_t token;
-
- IDN_GLOCK_EXCL();
- op = "CONNECT";
- awolcount = idn_mark_awol(domid, &awol);
- IDN_GUNLOCK();
-
- idn_nego_cleanup_check(domid, IDN_NIL_DOMID,
- IDN_NIL_DCPU);
-
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO);
- idn_retry_submit(idn_retry_nego, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_NEGO]);
- }
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
-
- case IDNP_CMD:
- /*
- * Timeouts on commands typically mean that the
- * the master is not responding. Furthermore, we
- * can't FORCE a FIN disconnect since at this stage
- * we are CONNECTED and thus other domains may
- * have cache entries that we're sharing with them.
- * Only choice is to completely disconnect from
- * IDN and try to reestablish connection.
- *
- * However, timeouts attempting to get nodename
- * are not fatal. Although we don't want to retry
- * either since each timeout is a lost buffer to
- * the remote domain.
- */
- if (tp->t_subtype == (ushort_t)IDNCMD_NODENAME) {
- PR_PROTO("%s:%d: timedout waiting for nodename\n",
- proc, domid);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
- }
-
- IDN_GLOCK_EXCL();
- if (idn.state == IDNGS_ONLINE) {
- domainset_t domset;
- int masterid = IDN_GET_MASTERID();
-
- IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs,
- gk_reconfig_last);
-
- PR_PROTO("%s:%d: RECONFIG trying old masterid = %d\n",
- proc, domid, masterid);
-
- IDN_GSTATE_TRANSITION(IDNGS_RECONFIG);
- IDN_SET_NEW_MASTERID(masterid);
- IDN_GUNLOCK();
- IDN_DUNLOCK(domid);
-
- domset = idn.domset.ds_trans_on |
- idn.domset.ds_connected;
-
- idn_unlink_domainset(domset, IDNFIN_NORMAL,
- IDNFIN_ARG_NONE, IDNFIN_OPT_RELINK, BOARDSET_ALL);
- } else {
- IDN_GUNLOCK();
- IDN_DUNLOCK(domid);
- }
- IDN_SYNC_UNLOCK();
- break;
-
- case IDNP_CON:
- if (tp->t_subtype == (ushort_t)IDNCON_QUERY) {
- /*
- * Timed out sending a CON-query. This is
- * non-fatal. We simply need to retry.
- */
- IDN_GLOCK_EXCL();
- op = "CONNECT";
- awolcount = idn_mark_awol(domid, &awol);
- IDN_GUNLOCK();
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_CONQ);
- idn_retry_submit(idn_retry_query, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_CONQ]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
- }
- /*FALLTHROUGH*/
- case IDNP_CFG:
- /*
- * Any timeouts here we simply try to disconnect
- * and reestablish the link. Since we haven't
- * reached the connected state w.r.t. this domain
- * we put his fin state to FORCE-HARD in order
- * to shoot right through without involving other
- * domains. Recall that other domains may have
- * established connections with the given domain
- * which means any FIN queries to them will always
- * return connected to the given domain. Since
- * neither the given domain nor the local domain
- * plan on disconnecting from the IDN the connection
- * to the other domains will remain thereby preventing
- * the local FIN from ever completing. Recall that
- * a FIN depends on all member domains FIN'ing also.
- */
- IDN_GLOCK_EXCL();
- op = "CONNECT";
- awolcount = idn_mark_awol(domid, &awol);
- IDN_GUNLOCK();
- DOMAINSET_ADD(idn.domset.ds_relink, domid);
- IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate,
- idn.domset.ds_relink);
- (void) idn_disconnect(domid, IDNFIN_FORCE_SOFT,
- IDNFIN_ARG_NONE, IDNFIN_SYNC_NO);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
-
- case IDNP_FIN:
- /*
- * Timeouts here simply try to retry.
- */
- IDN_GLOCK_EXCL();
- op = "DISCONNECT";
- awolcount = idn_mark_awol(domid, &awol);
- IDN_GUNLOCK();
- if (tp->t_subtype == (ushort_t)IDNFIN_QUERY) {
- int d;
- domainset_t rdyset;
- /*
- * Timed out sending a FIN-query. This is
- * non-fatal. We simply need to retry.
- * If we were doing a forced unlink of any
- * domains, we don't want this awol guy
- * to hold us up. Looks for any forced
- * unlinks and make them "ready" with
- * respect to this awol domain.
- */
- rdyset = 0;
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (FIN_IS_FORCE(idn_domain[d].dfin)) {
- DOMAINSET_ADD(rdyset, d);
- }
- }
- if (rdyset)
- (void) idn_sync_register(domid,
- IDNSYNC_DISCONNECT,
- rdyset, IDNSYNC_REG_REG);
-
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FINQ);
- idn_retry_submit(idn_retry_query, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FINQ]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
- }
-
- if (dp->dfin == IDNFIN_FORCE_SOFT) {
- IDN_FSTATE_TRANSITION(dp, IDNFIN_FORCE_HARD);
- }
- /*
- * Anybody that was waiting on this domain and
- * had a hard-force in action gets this guy for
- * free in their base ready-set.
- */
- idn_sync_register_awol(domid);
-
- dp->dxp = &xphase_fin;
- IDN_XSTATE_TRANSITION(dp, IDNXS_PEND);
- token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN);
- idn_retry_submit(idn_retry_fin, NULL, token,
- idn_msg_retrytime[(int)IDNRETRY_FIN]);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
-
- default:
-
- ASSERT(0);
- IDN_DUNLOCK(domid);
- IDN_SYNC_UNLOCK();
- break;
- }
-
- IDN_TIMER_FREE(tp);
-
- if (awol) {
- if (strlen(dname) > 0) {
- cmn_err(CE_WARN,
- "IDN: 236: domain (%s) [ID %d] not "
- "responding to %s [#%d]",
- dname, domid, op, awolcount);
- } else {
- cmn_err(CE_WARN,
- "IDN: 236: domain [ID %d, CPU %d] not "
- "responding to %s [#%d]",
- domid, dcpu, op, awolcount);
- }
- }
-}
-
-#if 0
-static int
-idn_retry_check(uint_t token)
-{
- int i, count = 0;
- int domid = IDN_RETRY_TOKEN2DOMID(token);
- int key = IDN_RETRY_TOKEN2TYPE(token);
- idn_retry_job_t *rp;
- idn_retry_queue_t *qp;
-
- qp = &idn.retryqueue;
-
- mutex_enter(&qp->rq_mutex);
-
- for (i = 0, rp = qp->rq_jobs; i < qp->rq_count; i++, rp = rp->rj_next)
- if ((domid == IDN_RETRY_TOKEN2DOMID(rp->rj_token)) &&
- ((key == IDN_RETRY_TYPEALL) || (rp->rj_token == token)))
- count++;
-
- mutex_exit(&qp->rq_mutex);
-
- return (count);
-}
-#endif /* 0 */
-
-static void
-idn_retry_execute(void *arg)
-{
- idn_retry_job_t *rp = (idn_retry_job_t *)arg;
- idn_retry_queue_t *qp;
-
- qp = &idn.retryqueue;
-
- mutex_enter(&qp->rq_mutex);
- if (rp->rj_onq == 0) {
- /*
- * Job has already been claimed by
- * retry termination routine.
- * Bail out.
- */
- mutex_exit(&qp->rq_mutex);
- return;
- }
- rp->rj_next->rj_prev = rp->rj_prev;
- rp->rj_prev->rj_next = rp->rj_next;
- if (--(qp->rq_count) == 0)
- qp->rq_jobs = NULL;
- else if (qp->rq_jobs == rp)
- qp->rq_jobs = rp->rj_next;
- mutex_exit(&qp->rq_mutex);
-
- (*rp->rj_func)(rp->rj_token, rp->rj_arg);
-
- IDNRETRY_FREEJOB(rp);
-}
-
-/*
- *
- */
-static void
-idn_retry_submit(void (*func)(uint_t token, void *arg), void *arg, uint_t token,
- clock_t ticks)
-{
- idn_retry_job_t *rp, *cp;
- idn_retry_queue_t *qp;
- int c;
- procname_t proc = "idn_retry_submit";
-
- if (ticks < 0) {
- PR_PROTO("%s: (token = 0x%x) WARNING ticks = %ld\n",
- proc, token, ticks);
- return;
- }
- if (ticks == 0) /* At least one tick to get into background */
- ticks++;
-
- PR_PROTO("%s: token = 0x%x\n", proc, token);
-
- qp = &idn.retryqueue;
-
- mutex_enter(&qp->rq_mutex);
- for (c = 0, cp = qp->rq_jobs; c < qp->rq_count; cp = cp->rj_next, c++) {
- if (cp->rj_token == token) {
- PR_PROTO("%s: token = (%d,0x%x) already present\n",
- proc, IDN_RETRY_TOKEN2DOMID(token),
- IDN_RETRY_TOKEN2TYPE(token));
- break;
- }
- }
-
- if (c < qp->rq_count) {
- mutex_exit(&qp->rq_mutex);
- return;
- }
-
- rp = IDNRETRY_ALLOCJOB();
- rp->rj_func = func;
- rp->rj_arg = arg;
- rp->rj_token = token;
- rp->rj_prev = rp->rj_next = rp;
-
- if (qp->rq_jobs == NULL) {
- qp->rq_jobs = rp;
- } else {
- rp->rj_next = qp->rq_jobs;
- rp->rj_prev = qp->rq_jobs->rj_prev;
- rp->rj_next->rj_prev = rp;
- rp->rj_prev->rj_next = rp;
- }
- rp->rj_onq = 1;
- qp->rq_count++;
- rp->rj_id = timeout(idn_retry_execute, (caddr_t)rp, ticks);
- mutex_exit(&qp->rq_mutex);
-}
-
-int
-idn_retry_terminate(uint_t token)
-{
- int i, domid;
- uint_t key, count;
- idn_retry_job_t *rp, *nrp, *fp;
- idn_retry_queue_t *qp;
- procname_t proc = "idn_retry_terminate";
-
- key = IDN_RETRY_TOKEN2TYPE(token);
- domid = IDN_RETRY_TOKEN2DOMID(token);
- fp = NULL;
- qp = &idn.retryqueue;
-
- mutex_enter(&qp->rq_mutex);
- for (i = count = 0, rp = qp->rq_jobs; i < qp->rq_count; i++) {
- nrp = rp->rj_next;
- if ((domid == IDN_RETRY_TOKEN2DOMID(rp->rj_token)) &&
- ((key == IDN_RETRY_TYPEALL) ||
- (rp->rj_token == token))) {
- /*
- * Turn off onq field as a signal to
- * the execution routine that this
- * retry has been terminated. This
- * is necessary since we can't untimeout
- * while holding the rq_mutex otherwise
- * we'll deadlock with the execution
- * routine. We'll untimeout these guys
- * _after_ we drop rq_mutex.
- */
- rp->rj_onq = 0;
- rp->rj_next->rj_prev = rp->rj_prev;
- rp->rj_prev->rj_next = rp->rj_next;
- if (qp->rq_jobs == rp)
- qp->rq_jobs = rp->rj_next;
- rp->rj_next = fp;
- fp = rp;
- count++;
- }
- rp = nrp;
- }
-
- if ((qp->rq_count -= count) == 0)
- qp->rq_jobs = NULL;
-
- mutex_exit(&qp->rq_mutex);
-
- PR_PROTO("%s: token = (%d,0x%x), dequeued = %d\n",
- proc, domid, key, count);
-
- for (; fp; fp = nrp) {
- (void) untimeout(fp->rj_id);
-
- nrp = fp->rj_next;
- IDNRETRY_FREEJOB(fp);
- }
-
- return (count);
-}
-
-/*
- * -----------------------------------------------------------------------
- * The sole purpose of the idn_protocol_server is to manage the IDN
- * protocols between the various domains. These messages do _not_ go
- * through the regular streams queues since they are not dependent on
- * any user process or module necessarily having the IDN driver open.
- * There may be multiple instances of these servers to enhance performance
- * of domain management. Each server is assigned a idn_protoqueue_t
- * from which to obtain the work they need to do.
- * -----------------------------------------------------------------------
- */
-int
-idn_protocol_init(int nservers)
-{
- int i;
- idn_protojob_t *jp;
- register idn_protoqueue_t *protoq;
-
- if (nservers <= 0) {
- cmn_err(CE_WARN,
- "IDN: 237: invalid number (%d) of protocol servers",
- nservers);
- return (-1);
- }
-
- idn.protocol.p_jobpool = kmem_cache_create("idn_protocol_jobcache",
- sizeof (idn_protojob_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
- if (idn.protocol.p_jobpool == NULL) {
- cmn_err(CE_WARN,
- "IDN: 238: kmem_cache_create(jobcache) failed");
- return (-1);
- }
-
- /*
- * Initialize static cache for protojob.
- */
- mutex_init(&idn_protojob_cache_lock, NULL, MUTEX_DRIVER, NULL);
- jp = &idn_protojob_cache[0];
- for (i = 1; i < IDN_DMV_PENDING_MAX; jp = jp->j_next, i++) {
- jp->j_cache = 1;
- jp->j_next = &idn_protojob_cache[i];
- }
- jp->j_cache = 1;
- jp->j_next = NULL;
- idn_protojob_cache_list = &idn_protojob_cache[0];
-
- /*
- * Init morgue semaphore.
- */
- sema_init(&idn.protocol.p_morgue, 0, NULL, SEMA_DEFAULT, NULL);
- /*
- * Alloc server queues.
- */
- idn.protocol.p_serverq = GETSTRUCT(idn_protoqueue_t, nservers);
-
- /*
- * Init server queues.
- */
- protoq = idn.protocol.p_serverq;
- for (i = 0; i < nservers; protoq++, i++) {
- mutex_init(&protoq->q_mutex, NULL, MUTEX_DRIVER, NULL);
- cv_init(&protoq->q_cv, NULL, CV_DEFAULT, NULL);
- protoq->q_id = i;
- protoq->q_joblist = NULL;
- protoq->q_joblist_tail = NULL;
- protoq->q_die = 0;
- protoq->q_morgue = &idn.protocol.p_morgue;
- /*
- * Create protocol server thread.
- */
- protoq->q_threadp = thread_create(NULL, 0,
- idn_protocol_server, (caddr_t)&i, sizeof (i), &p0,
- TS_RUN, maxclsyspri);
- }
- /*
- * The servers are kept in the p_server[] array, however
- * we'll build a linked list of them to facilitate debugging.
- */
- protoq = idn.protocol.p_serverq;
- for (i = 0; i < (nservers - 1); protoq++, i++)
- protoq->q_next = (protoq + 1);
- protoq->q_next = NULL;
-
- idn.nservers = nservers;
-
- return (idn.nservers);
-}
-
-void
-idn_protocol_deinit()
-{
- register int i;
- int nservers;
- register idn_protoqueue_t *protoq;
-
- nservers = idn.nservers;
-
- if (nservers <= 0)
- return;
-
- /*
- * Make sure the servers are dead.
- */
- idn_protocol_server_killall();
- ASSERT(idn.nservers == 0);
- /*
- * Destroy the mutexes.
- */
- protoq = idn.protocol.p_serverq;
- for (i = 0; i < nservers; protoq++, i++) {
- mutex_destroy(&protoq->q_mutex);
- cv_destroy(&protoq->q_cv);
- }
- /*
- * Free up the protoqueue memory.
- */
- FREESTRUCT(idn.protocol.p_serverq, idn_protoqueue_t, nservers);
- idn.protocol.p_serverq = NULL;
- /*
- * Destroy the morgue semaphore.
- */
- sema_destroy(&idn.protocol.p_morgue);
-
- if (idn.protocol.p_jobpool) {
- kmem_cache_destroy(idn.protocol.p_jobpool);
- idn.protocol.p_jobpool = NULL;
- }
-}
-
-static void
-idn_protocol_server(int *id)
-{
- idn_protoqueue_t *pq;
- idn_protojob_t *jl;
- register idn_protojob_t *jp;
- procname_t proc = "idn_protocol_server";
-
- if (id == NULL) {
- PR_PROTO("%s: id == NULL, thread exiting\n", proc);
- return;
- }
- ASSERT((*id >= 0) && (*id < idn_protocol_nservers));
-
- pq = &idn.protocol.p_serverq[*id];
-
- ASSERT(pq->q_id == *id);
-
- PR_PROTO("%s: id %d starting up (pq = 0x%p)\n",
- proc, pq->q_id, (void *)pq);
-
- /*CONSTCOND*/
- while (1) {
- mutex_enter(&pq->q_mutex);
-
- while (((jl = pq->q_joblist) == NULL) && !pq->q_die)
- cv_wait(&pq->q_cv, &pq->q_mutex);
-
- pq->q_joblist = pq->q_joblist_tail = NULL;
-
- if (pq->q_die) {
- /*
- * We've been killed. Need to check-in
- * at the morgue.
- */
- pq->q_threadp = NULL;
- mutex_exit(&pq->q_mutex);
- PR_PROTO("%s: thread (%d) killed...bye bye\n",
- proc, pq->q_id);
- for (jp = jl; jp; jp = jl) {
- jl = jp->j_next;
- idn_protojob_free(jp);
- }
- sema_v(pq->q_morgue);
- thread_exit();
- /*NOTREACHED*/
- }
- mutex_exit(&pq->q_mutex);
-
- /*
- * We can process the jobs asynchronously while more are
- * put on.
- */
- for (jp = jl; jp; jp = jl) {
- jl = jp->j_next;
- idn_recv_proto(&(jp->j_msg));
- idn_protojob_free(jp);
- }
- }
-}
-
-/*
- * Kill off all the protocol servers.
- */
-static void
-idn_protocol_server_killall()
-{
- register idn_protoqueue_t *pq;
- int i;
- procname_t proc = "idn_protocol_server_killall";
-
- PR_PROTO("%s: killing off %d protocol servers\n",
- proc, idn.nservers);
-
- pq = idn.protocol.p_serverq;
- for (i = 0; i < idn.nservers; pq++, i++) {
- mutex_enter(&pq->q_mutex);
- pq->q_die = 1;
- cv_signal(&pq->q_cv);
- mutex_exit(&pq->q_mutex);
- }
-
- while (idn.nservers > 0) {
- sema_p(&idn.protocol.p_morgue);
- idn.nservers--;
- }
-}
-
-idn_protojob_t *
-idn_protojob_alloc(int kmflag)
-{
- idn_protojob_t *jp;
-
- jp = kmem_cache_alloc(idn.protocol.p_jobpool, kmflag);
- if (jp == NULL) {
- mutex_enter(&idn_protojob_cache_lock);
- if ((jp = idn_protojob_cache_list) != NULL)
- idn_protojob_cache_list = jp->j_next;
- mutex_exit(&idn_protojob_cache_lock);
- } else {
- jp->j_cache = 0;
- }
-
- return (jp);
-}
-
-static void
-idn_protojob_free(idn_protojob_t *jp)
-{
- ASSERT(jp);
-
- if (jp->j_cache) {
- mutex_enter(&idn_protojob_cache_lock);
- jp->j_next = idn_protojob_cache_list;
- idn_protojob_cache_list = jp;
- mutex_exit(&idn_protojob_cache_lock);
- } else {
- kmem_cache_free(idn.protocol.p_jobpool, (void *)jp);
- }
-}
-
-void
-idn_protojob_submit(int cookie, idn_protojob_t *jp)
-{
- idn_protoqueue_t *pq;
- int serverid;
- procname_t proc = "idn_protojob_submit";
- STRING(str);
-
- if (jp == NULL)
- return;
-
- serverid = IDN_PROTOCOL_SERVER_HASH(cookie);
-
- pq = &idn.protocol.p_serverq[serverid];
-
- INUM2STR(jp->j_msg.m_msgtype, str);
- PR_PROTO("%s: job (d=%d, m=0x%x, %s) submitted to "
- "protocol server %d\n", proc, jp->j_msg.m_domid,
- jp->j_msg.m_msgtype, str, serverid);
-
- mutex_enter(&pq->q_mutex);
- /*
- * Can't submit jobs to dying servers.
- */
- if (!pq->q_die) {
- if (pq->q_joblist_tail) {
- pq->q_joblist_tail->j_next = jp;
- pq->q_joblist_tail = jp;
- } else {
- pq->q_joblist = pq->q_joblist_tail = jp;
- }
- jp->j_next = NULL;
- cv_signal(&pq->q_cv);
- } else {
- PR_PROTO("%s: protocol server dead. freeing protojob\n",
- proc);
- idn_protojob_free(jp);
- }
- mutex_exit(&pq->q_mutex);
-}
-
-static void
-idn_mboxarea_init(idn_mboxtbl_t *mtp, register int ntbls)
-{
- register int d;
- caddr_t state_ptr = NULL, mtbasep = (caddr_t)mtp;
- idn_mboxtbl_t *amtp;
- procname_t proc = "idn_mboxarea_init";
-
- ASSERT(mtp && (ntbls > 0));
-
- PR_PROTO("%s: init mboxtbl (0x%p) ntbls = %d\n",
- proc, (void *)mtp, ntbls);
-
- for (d = 0; d < ntbls; d++) {
- register int pd, sd;
- register int ch;
-
- mtp->mt_header.mh_svr_active = 0;
- mtp->mt_header.mh_svr_ready = 0;
- /*
- * Initialize the header of each mbox table
- * with a cookie for identity.
- */
- /*
- * Format: 0xc0c0DSCC
- * D = primary domain
- * S = sub-domain of primary
- * CC = channel of sub-domain.
- */
- pd = (d / MAX_DOMAINS) / IDN_MAX_NETS;
- sd = (d / IDN_MAX_NETS) % MAX_DOMAINS;
- ch = d % IDN_MAX_NETS;
-
- /*
- * We point all sub-domains in the same channel
- * to the same active sync flag since a single server
- * services all domains in the same channel.
- */
- amtp = IDN_MBOXTBL_ABS_PTR(mtbasep, pd, 0, ch);
-
- state_ptr = (caddr_t)&amtp->mt_header.mh_svr_active;
- mtp->mt_header.mh_svr_active_ptr = IDN_ADDR2OFFSET(state_ptr);
-
- state_ptr = (caddr_t)&amtp->mt_header.mh_svr_ready;
- mtp->mt_header.mh_svr_ready_ptr = IDN_ADDR2OFFSET(state_ptr);
-
- mtp->mt_header.mh_cookie = IDN_MAKE_MBOXHDR_COOKIE(pd, sd, ch);
-
- mtp->mt_header.mh_cksum = IDN_CKSUM_MBOX(&mtp->mt_header);
-
- IDN_MBOXTBL_PTR_INC(mtp);
- }
- /*
- * Now that the master has initialized the entire mailbox
- * region the referenced memory may not necessarily be up-to-date
- * with respect to the actual SMR memory due to caching.
- * In order to make sure future connecting domains get a
- * consistent picture of the mailbox region, it's necessary
- * for the master to flush its caches.
- */
- PR_PROTO("%s: flushing ecache's of local (master) domain\n", proc);
-
- idnxf_flushall_ecache();
-}
-
-idn_mainmbox_t *
-idn_mainmbox_init(int domid, int mbx)
-{
- idn_mainmbox_t *mmp;
- int c;
- idn_mainmbox_t *cmp;
- procname_t proc = "idn_mainmbox_init";
-
- ASSERT(idn_domain[domid].dcpu != IDN_NIL_DCPU);
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- PR_PROTO("%s: initializing main %s mailbox for domain %d\n",
- proc, IDNMBOX_IS_RECV(mbx) ? "RECV" : "SEND", domid);
-
- cmp = GETSTRUCT(idn_mainmbox_t, IDN_MAX_NETS);
- for (c = 0; c < IDN_MAX_NETS; c++) {
- mmp = &cmp[c];
- mmp->mm_channel = (short)c;
- mutex_init(&mmp->mm_mutex, NULL, MUTEX_DRIVER, NULL);
- mmp->mm_domid = (short)domid;
- mmp->mm_type = mbx;
- }
- mmp = cmp;
- /*
- * The actual SMR mailbox (mmp->mm_smr_mboxp) gets setup
- * when the SMR is setup.
- */
-
- return (mmp);
-}
-
-static void
-idn_mainmbox_reset(int domid, idn_mainmbox_t *cmp)
-{
- idn_mainmbox_t *mmp;
- int c;
- procname_t proc = "idn_mainmbox_reset";
-
- ASSERT(IDN_DLOCK_IS_EXCL(domid));
-
- PR_PROTO("%s: reseting main %s mailbox for domain %d\n",
- proc, IDNMBOX_IS_RECV(cmp->mm_type) ? "RECV" : "SEND", domid);
-
- for (c = 0; c < IDN_MAX_NETS; c++) {
- mmp = &cmp[c];
-
- mmp->mm_channel = (short)c;
- mmp->mm_domid = (short)domid;
- mmp->mm_count = 0;
- mmp->mm_flags = 0;
- mmp->mm_qiget = mmp->mm_qiput = 0;
- mmp->mm_csp = NULL;
- ASSERT(mmp->mm_type == cmp->mm_type);
- }
-}
-
-void
-idn_mainmbox_deinit(int domid, idn_mainmbox_t *mmp)
-{
- procname_t proc = "idn_mainmbox_deinit";
-
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- PR_PROTO("%s: deinitializing main %s mailbox for domain %d\n",
- proc, IDNMBOX_IS_RECV(mmp->mm_type) ? "RECV" : "SEND", domid);
-
- ASSERT(idn_domain_is_registered(domid, -1, NULL) == 0);
-
- FREESTRUCT(mmp, idn_mainmbox_t, IDN_MAX_NETS);
-}
-
-static void
-idn_mainmbox_activate(int domid)
-{
- register int c;
- idn_domain_t *dp = &idn_domain[domid];
- procname_t proc = "idn_mainmbox_activate";
-
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- PR_PROTO("%s:%d: activating main mailbox\n", proc, domid);
-
- for (c = 0; c < IDN_MAX_NETS; c++)
- idn_mainmbox_chan_register(domid, &dp->dmbox.m_send[c],
- &dp->dmbox.m_recv[c], c);
-}
-
-/*
- * Called upon disabling the SMR to deactivate all the mailboxes
- * so that they no longer reference the SMR that's going away.
- *
- * stopall - Indicates to stop all channel services, across the board.
- */
-static void
-idn_mainmbox_deactivate(ushort_t domset)
-{
- int svr_count;
- procname_t proc = "idn_mainmbox_deactivate";
-
-
- if (domset == 0)
- return;
-
- PR_PROTO("%s: %s deactivating main mailboxes for domset 0x%x\n",
- proc, (domset == (ushort_t)-1) ? "STOP-ALL" : "NORMAL", domset);
-
- svr_count = idn_mainmbox_chan_unregister(domset, -1);
-
- PR_PROTO("%s: deactivated %d chansvrs (domset 0x%x)\n",
- proc, svr_count, domset);
-}
-
-static void
-idn_mainmbox_chan_register(int domid, idn_mainmbox_t *send_mmp,
- idn_mainmbox_t *recv_mmp, int channel)
-{
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- /*
- * Obtain receive mailbox lock first.
- */
- mutex_enter(&recv_mmp->mm_mutex);
- mutex_enter(&send_mmp->mm_mutex);
-
- ASSERT(recv_mmp->mm_channel == (short)channel);
- ASSERT(send_mmp->mm_channel == (short)channel);
-
- recv_mmp->mm_csp = &idn.chan_servers[channel];
- recv_mmp->mm_count = 0;
- recv_mmp->mm_dropped = 0;
- recv_mmp->mm_flags = 0;
-
- send_mmp->mm_csp = &idn.chan_servers[channel];
- send_mmp->mm_count = 0;
- send_mmp->mm_dropped = 0;
- send_mmp->mm_flags = 0;
-
- mutex_exit(&send_mmp->mm_mutex);
- mutex_exit(&recv_mmp->mm_mutex);
-
- /*
- * We have to add ourselves to the respective
- * channel server's service table.
- * Note that the channel may not necessarily be
- * active at this time.
- */
- ASSERT(idn.chan_servers);
- /*
- * Have to get the channel server under
- * control so we can add ourselves.
- * Returns w/c_mutex.
- */
- IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[channel]);
- /*
- * Add the following domain (mailbox) for monitoring
- * by the respective channel server.
- */
- idn_chan_addmbox(channel, DOMAINSET(domid));
-
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[channel]);
-}
-
-/*
- * Unregister the given domain from the specified channel(s) for monitoring.
- */
-static int
-idn_mainmbox_chan_unregister(ushort_t domset, int channel)
-{
- int c, dd_count;
- int min_chan, max_chan;
- procname_t proc = "idn_mainmbox_chan_unregister";
-
- PR_CHAN("%s: deactivating main mailboxes (channel %d) "
- "for domset 0x%x\n", proc, channel, domset);
-
- if (channel == -1) {
- min_chan = 0;
- max_chan = IDN_MAX_NETS - 1;
- } else {
- min_chan = max_chan = channel;
- }
- /*
- * Point all the data dispatchers to the same morgue
- * so we can kill them all at once.
- */
- dd_count = 0;
- for (c = min_chan; c <= max_chan; c++) {
-
- /*
- * Have to get the channel server under
- * control so we can remove ourselves.
- * Returns w/c_mutex held.
- */
- IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]);
- /*
- * Delete the following domain (mailbox) from
- * monitoring by the respective channel server.
- */
- idn_chan_delmbox(c, (ushort_t)domset);
-
- IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]);
- dd_count++;
- }
- PR_CHAN("%s: deactivated %d channel mboxes for domset 0x%x, chan %d\n",
- proc, dd_count, domset, channel);
- return (dd_count);
-}
-
-/*
- * Check if the given domain is registered with the given channel(s).
- */
-int
-idn_domain_is_registered(int domid, int channel, idn_chanset_t *chansetp)
-{
- int regcount;
- int c, min_chan, max_chan;
- idn_chanset_t chanset;
- procname_t proc = "idn_domain_is_registered";
-
- CHANSET_ZERO(chanset);
-
- if (idn.chan_servers == NULL) {
- PR_CHAN("%s: idn.chan_servers == NULL!!\n", proc);
- return (0);
- }
-
- if (channel == -1) {
- min_chan = 0;
- max_chan = IDN_MAX_NETS - 1;
- } else {
- min_chan = max_chan = channel;
- }
-
- regcount = 0;
-
- for (c = min_chan; c <= max_chan; c++) {
- idn_chansvr_t *csp;
-
- csp = &idn.chan_servers[c];
- IDN_CHAN_LOCK_SEND(csp);
- /*
- * Don't really need recv side lock since registeration
- * can't change while we're holding send side.
- * No need to wait for send side to actually suspend
- * since all we want to do is prevent the registered
- * information from changing.
- */
- if (IDN_CHAN_DOMAIN_IS_REGISTERED(csp, domid)) {
- regcount++;
- CHANSET_ADD(chanset, c);
- }
-
- IDN_CHAN_UNLOCK_SEND(csp);
- }
-
- PR_CHAN("%s: domid %d mbox reg'd with %d channels [0x%x] (req=%d)\n",
- proc, domid, regcount, chanset, channel);
-
- if (chansetp)
- *chansetp = chanset;
-
- return (regcount);
-}
-
-static int
-idn_mainmbox_flush(int domid, idn_mainmbox_t *mmp)
-{
- register int qi;
- register idn_mboxmsg_t *mqp;
- int total_count = 0;
- int c, count;
- int mbox_type;
- char *mbox_str;
- int lost_io, total_lost_io = 0;
- idn_chanset_t chanset;
- procname_t proc = "idn_mainmbox_flush";
-
-
- if (mmp == NULL)
- return (0);
-
- CHANSET_ZERO(chanset);
-
- mbox_type = mmp->mm_type;
- ASSERT((mbox_type == IDNMMBOX_TYPE_SEND) ||
- (mbox_type == IDNMMBOX_TYPE_RECV));
-
- mbox_str = (mbox_type == IDNMMBOX_TYPE_SEND) ? "SEND" : "RECV";
-
- /*
- * Determine which channels this domain is registered
- * with. If he's not registered with any, then we
- * can't touch the SMR.
- */
- (void) idn_domain_is_registered(domid, -1, &chanset);
-
- for (c = 0; c < IDN_MAX_NETS; c++) {
- ushort_t mbox_csum;
-
- if (mmp[c].mm_smr_mboxp == NULL)
- continue;
- mutex_enter(&mmp[c].mm_mutex);
- ASSERT(mmp[c].mm_type == mbox_type);
- if (CHAN_IN_SET(chanset, c) == 0) {
- /*
- * Domain is no longer registered.
- * DON'T TOUCH THE SMR - IT'S POISON!
- */
- if (mmp[c].mm_smr_mboxp) {
- PR_CHAN("%s:%d:%s: domain unregistered "
- "w/chan %d - DUMPING SMR reference\n",
- proc, domid, mbox_str, c);
- lost_io = IDN_MMBOXINDEX_DIFF(mmp[c].mm_qiput,
- mmp[c].mm_qiget);
-#ifdef DEBUG
- if (mbox_type == IDNMMBOX_TYPE_RECV) {
- PR_CHAN("%s:%d:%s: blowing away %d "
- "incoming pkts\n",
- proc, domid, mbox_str, lost_io);
- } else {
- PR_CHAN("%s:%d:%s: blowing away %d/%d "
- "outstanding pkts\n",
- proc, domid, mbox_str, lost_io,
- idn_domain[domid].dio);
- }
-#endif /* DEBUG */
- }
- mmp[c].mm_qiput = mmp[c].mm_qiget = 0;
- mmp[c].mm_smr_mboxp = NULL;
- total_lost_io += lost_io;
- }
- if (mmp[c].mm_smr_mboxp) {
- mbox_csum =
- IDN_CKSUM_MBOX(&mmp[c].mm_smr_mboxp->mt_header);
- if (!VALID_NWRADDR(mmp[c].mm_smr_mboxp, 4) ||
- !VALID_MBOXHDR(&mmp[c].mm_smr_mboxp->mt_header,
- c, mbox_csum)) {
- lost_io = IDN_MMBOXINDEX_DIFF(mmp[c].mm_qiput,
- mmp[c].mm_qiget);
-#ifdef DEBUG
- if (mbox_type == IDNMMBOX_TYPE_RECV) {
- PR_CHAN("%s:%d:%s: bad mbox. blowing "
- "away %d incoming pkts\n",
- proc, domid, mbox_str, lost_io);
- } else {
- PR_CHAN("%s:%d:%s: bad mbox. blowing "
- "away %d/%d outstanding pkts\n",
- proc, domid, mbox_str, lost_io,
- idn_domain[domid].dio);
- }
-#endif /* DEBUG */
- mmp[c].mm_smr_mboxp = NULL;
- mmp[c].mm_qiput = mmp[c].mm_qiget = 0;
- total_lost_io += lost_io;
- }
- }
- if (mmp[c].mm_smr_mboxp == NULL) {
- mutex_exit(&mmp[c].mm_mutex);
- continue;
- }
- mqp = &mmp[c].mm_smr_mboxp->mt_queue[0];
- qi = 0;
- count = 0;
- /*
- * It's quite possible the remote domain may be accessing
- * these mailbox entries at the exact same time we're
- * clearing the owner bit. That's okay. All we're trying
- * to do at this point is to minimize the number of packets
- * the remote domain might try to process unnecessarily.
- */
- do {
- if (mqp[qi].ms_owner)
- count++;
- mqp[qi].ms_owner = 0;
- IDN_MMBOXINDEX_INC(qi);
- } while (qi);
-
- lost_io = IDN_MMBOXINDEX_DIFF(mmp[c].mm_qiput, mmp[c].mm_qiget);
- total_lost_io += lost_io;
-
- mmp[c].mm_qiput = mmp[c].mm_qiget = 0;
- mmp[c].mm_smr_mboxp = NULL;
- mutex_exit(&mmp[c].mm_mutex);
-
- total_count += count;
-
- PR_CHAN("%s:%d:%s: flushed out %d mbox entries for chan %d\n",
- proc, domid, mbox_str, count, c);
- }
-
- if (total_lost_io && (mbox_type == IDNMMBOX_TYPE_SEND)) {
- int lost_bufs;
- /*
- * If we lost all our outstanding I/O. We could
- * possible could have slabs now with mistakenly
- * outstanding I/O buffers. Need to clean them up.
- * Clean up of leftovers our self.
- */
- lost_bufs = smr_buf_free_all(domid);
-
- PR_CHAN("%s:%d:%s: flushed %d/%d buffers from slabs\n",
- proc, domid, mbox_str, lost_bufs, total_lost_io);
- }
-
- PR_CHAN("%s:%d:%s: flushed total of %d mailbox entries (lost %d)\n",
- proc, domid, mbox_str, total_count, total_lost_io);
-
- return (total_count);
-}
-
-void
-idn_chanserver_bind(int net, int cpuid)
-{
- int ocpuid;
- cpu_t *cp;
- idn_chansvr_t *csp;
- kthread_id_t tp;
- procname_t proc = "idn_chanserver_bind";
-
- csp = &idn.chan_servers[net];
- IDN_CHAN_LOCK_GLOBAL(csp);
-
- mutex_enter(&cpu_lock); /* protect checking cpu_ready_set */
- ocpuid = csp->ch_bound_cpuid;
- cp = cpu_get(cpuid);
- if ((cpuid != -1) && ((cp == NULL) || !cpu_is_online(cp))) {
- mutex_exit(&cpu_lock);
- cmn_err(CE_WARN,
- "IDN: 239: invalid CPU ID (%d) specified for "
- "IDN net %d",
- cpuid, net);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- return;
- }
- if ((tp = csp->ch_recv_threadp) == NULL) {
- /*
- * Thread is not yet active. Set ch_bound_cpuid
- * so when thread activates it will automatically
- * bind itself.
- */
- csp->ch_bound_cpuid = -1;
- csp->ch_bound_cpuid_pending = cpuid;
- } else {
- if (ocpuid != -1) {
- thread_affinity_clear(tp);
- csp->ch_bound_cpuid = -1;
- }
- if (cpuid >= 0) {
- thread_affinity_set(tp, cpuid);
- csp->ch_bound_cpuid = cpuid;
- }
- csp->ch_bound_cpuid_pending = -1;
- }
- mutex_exit(&cpu_lock);
-
- PR_CHAN("%s: bound net/channel (%d) from cpuid %d to%scpuid %d\n",
- proc, net, ocpuid, tp ? " " : " (pending) ", cpuid);
-
- IDN_CHAN_UNLOCK_GLOBAL(csp);
-}
-
-#ifdef DEBUG
-static idn_mboxhdr_t *prev_mhp[IDN_MAXMAX_NETS];
-#endif /* DEBUG */
-/*
- * Get access to the respective channel server's synchronization
- * header which resides in SMR space.
- */
-static idn_mboxhdr_t *
-idn_chan_server_syncheader(int channel)
-{
- idn_domain_t *ldp = &idn_domain[idn.localid];
- idn_mboxtbl_t *mtp;
- idn_mboxhdr_t *mhp;
- ushort_t mbox_csum;
- procname_t proc = "idn_chan_server_syncheader";
-
- ASSERT(IDN_CHAN_RECV_IS_LOCKED(&idn.chan_servers[channel]));
-
- IDN_DLOCK_SHARED(idn.localid);
-
- if (ldp->dmbox.m_tbl == NULL) {
- PR_CHAN("%s: local dmbox.m_tbl == NULL\n", proc);
- IDN_DUNLOCK(idn.localid);
- return (NULL);
- }
-
- mtp = IDN_MBOXTBL_PTR_CHAN(ldp->dmbox.m_tbl, channel);
- mhp = &mtp->mt_header;
- mbox_csum = IDN_CKSUM_MBOX(&mtp->mt_header);
-
-#ifdef DEBUG
- if (mhp != prev_mhp[channel]) {
- prev_mhp[channel] = mhp;
- PR_CHAN("%s: chan_server (%d) cookie = 0x%x (exp 0x%x)\n",
- proc, channel, IDN_GET_MBOXHDR_COOKIE(mhp),
- IDN_MAKE_MBOXHDR_COOKIE(0, 0, channel));
- PR_CHAN("%s: chan_server (%d) actv_ptr = 0x%x (exp 0x%x)\n",
- proc, channel, mhp->mh_svr_active_ptr,
- IDN_ADDR2OFFSET(&mhp->mh_svr_active));
- PR_CHAN("%s: chan_server (%d) ready_ptr = 0x%x (exp 0x%x)\n",
- proc, channel, mhp->mh_svr_ready_ptr,
- IDN_ADDR2OFFSET(&mhp->mh_svr_ready));
- PR_CHAN("%s: chan_server (%d) mbox_cksum = 0x%x (exp 0x%x)\n",
- proc, channel, (int)mhp->mh_cksum, (int)mbox_csum);
- }
-#endif /* DEBUG */
-
- if ((IDN_ADDR2OFFSET(&mhp->mh_svr_active) !=
- mhp->mh_svr_active_ptr) ||
- (IDN_ADDR2OFFSET(&mhp->mh_svr_ready) != mhp->mh_svr_ready_ptr) ||
- !VALID_MBOXHDR(mhp, channel, mbox_csum)) {
- idn_chansvr_t *csp;
-
- csp = &idn.chan_servers[channel];
- if (IDN_CHANNEL_IS_RECV_CORRUPTED(csp) == 0) {
- IDN_CHANSVC_MARK_RECV_CORRUPTED(csp);
-
- cmn_err(CE_WARN,
- "IDN: 240: (channel %d) SMR CORRUPTED "
- "- RELINK", channel);
- cmn_err(CE_CONT,
- "IDN: 240: (channel %d) cookie "
- "(expected 0x%x, actual 0x%x)\n",
- channel,
- IDN_MAKE_MBOXHDR_COOKIE(0, 0, channel),
- mhp->mh_cookie);
- cmn_err(CE_CONT,
- "IDN: 240: (channel %d) actv_flg "
- "(expected 0x%x, actual 0x%x)\n",
- channel, mhp->mh_svr_active_ptr,
- IDN_ADDR2OFFSET(&mhp->mh_svr_active));
- cmn_err(CE_CONT,
- "IDN: 240: (channel %d) ready_flg "
- "(expected 0x%x, actual 0x%x)\n",
- channel, mhp->mh_svr_ready_ptr,
- IDN_ADDR2OFFSET(&mhp->mh_svr_ready));
- }
-
- mhp = NULL;
- }
- IDN_DUNLOCK(idn.localid);
-
- PR_CHAN("%s: channel(%d) mainhp = 0x%p\n", proc, channel, (void *)mhp);
-
- return (mhp);
-}
-
-#define CHANSVR_SYNC_CACHE(csp, mmp, chan) \
-{ \
- ASSERT(IDN_CHAN_RECV_IS_LOCKED(csp)); \
- if ((csp)->ch_recv_changed) { \
- register int _d; \
- (csp)->ch_recv_scanset = (csp)->ch_recv_scanset_pending; \
- (csp)->ch_recv_domset = (csp)->ch_recv_domset_pending; \
- for (_d = 0; _d < MAX_DOMAINS; _d++) { \
- if (DOMAIN_IN_SET((csp)->ch_recv_domset, _d)) { \
- (mmp)[_d] = \
- &idn_domain[_d].dmbox.m_recv[chan]; \
- } else { \
- (mmp)[_d] = NULL; \
- } \
- } \
- (csp)->ch_recv_changed = 0; \
- } \
-}
-#define CHANSVR_NEXT_DOMID(csp, i, d) \
-{ \
- (i) = ((i) + 1) & (MAX_DOMAINS - 1); \
- (d) = (int)(((csp)->ch_recv_scanset >> ((i) << 2)) & 0xf); \
-}
-#define CHANSVR_RESET_INDEX(i) ((i) = -1)
-
-#ifdef DEBUG
-static idn_mainmbox_t *Mmp[IDN_MAXMAX_NETS][MAX_DOMAINS];
-#endif /* DEBUG */
-
-static void
-idn_chan_server(idn_chansvr_t **cspp)
-{
- idn_mboxhdr_t *mainhp;
- register idn_chansvr_t *csp;
- register idn_mboxmsg_t *mqp;
-#ifdef DEBUG
- idn_mainmbox_t **mmp;
-#else
- idn_mainmbox_t *mmp[MAX_DOMAINS];
-#endif /* DEBUG */
- register int qi;
- struct idn *sip;
- int channel;
- int cpuid;
- int empty;
- int tot_pktcount, tot_dropcount;
- register int index;
- register int domid;
- register int idleloops;
- procname_t proc = "idn_chan_server";
-
-
-#ifdef DEBUG
- mmp = &Mmp[(*cspp)->ch_id][0];
- bzero(mmp, MAX_DOMAINS * sizeof (idn_mainmbox_t *));
-#else /* DEBUG */
- bzero(mmp, sizeof (mmp));
-#endif /* DEBUG */
-
- tot_pktcount = tot_dropcount = 0;
-
- ASSERT(cspp && *cspp);
-
- csp = *cspp;
- channel = csp->ch_id;
- sip = IDN_INST2SIP(channel);
- ASSERT(sip);
-
- PR_CHAN("%s: CHANNEL SERVER (channel %d) GOING ACTIVE...\n",
- proc, channel);
-
- IDN_CHAN_LOCK_RECV(csp);
- IDN_CHAN_RECV_INPROGRESS(csp);
- ASSERT(csp->ch_recv_threadp == curthread);
- mutex_enter(&cpu_lock);
- if ((cpuid = csp->ch_bound_cpuid_pending) != -1) {
- cpu_t *cp = cpu_get(cpuid);
- /*
- * We've been requested to bind to
- * a particular cpu.
- */
- if ((cp == NULL) || !cpu_is_online(cp)) {
- /*
- * Cpu seems to have gone away or gone offline
- * since originally requested.
- */
- mutex_exit(&cpu_lock);
- cmn_err(CE_WARN,
- "IDN: 239: invalid CPU ID (%d) specified for "
- "IDN net %d",
- cpuid, channel);
- } else {
- csp->ch_bound_cpuid = cpuid;
- affinity_set(csp->ch_bound_cpuid);
- mutex_exit(&cpu_lock);
- }
- csp->ch_bound_cpuid_pending = -1;
- } else {
- mutex_exit(&cpu_lock);
- }
- if (csp->ch_bound_cpuid != -1) {
- PR_CHAN("%s: thread bound to cpuid %d\n",
- proc, csp->ch_bound_cpuid);
- }
- /*
- * Only the first (main) mbox header is used for
- * synchronization with data delivery since there is
- * only data server for all mailboxes for this
- * given channel.
- */
- CHANSVR_SYNC_CACHE(csp, mmp, channel);
-
- mainhp = ((csp->ch_recv_domcount > 0) &&
- IDN_CHANNEL_IS_RECV_ACTIVE(csp))
- ? idn_chan_server_syncheader(channel) : NULL;
-
- if (mainhp && IDN_CHANNEL_IS_RECV_ACTIVE(csp))
- mainhp->mh_svr_active = 1;
-
- ASSERT(csp->ch_recv_domcount ?
- (csp->ch_recv_scanset && csp->ch_recv_domset) : 1);
-
- IDN_CHAN_UNLOCK_RECV(csp);
-
- empty = 0;
- idleloops = 0;
- CHANSVR_RESET_INDEX(index);
-
- /*
- * ---------------------------------------------
- */
- /*CONSTCOND*/
- while (1) {
- register int pktcount;
- register int dropcount;
- ushort_t mbox_csum;
- idn_mboxtbl_t *smr_mboxp; /* points to SMR space */
- register smr_offset_t bufoffset;
-#ifdef DEBUG
- register smr_pkthdr_t *hdrp;
- idn_netaddr_t netaddr;
-#endif /* DEBUG */
-
- /*
- * Speed through and find the next available domid.
- */
- CHANSVR_NEXT_DOMID(csp, index, domid);
-
- if (!index) {
- /*
- * We only check state changes when
- * we wrap around. Done for performance.
- */
- if (!IDN_CHANNEL_IS_RECV_ACTIVE(csp) ||
- csp->ch_recv.c_checkin ||
- (idn.state != IDNGS_ONLINE)) {
-
- PR_DATA("%s: (channel %d) %s\n",
- proc, channel,
- IDN_CHANNEL_IS_DETACHED(csp)
- ? "DEAD" :
- IDN_CHANNEL_IS_PENDING(csp)
- ? "IDLED" :
- IDN_CHANNEL_IS_ACTIVE(csp)
- ? "ACTIVE" : "DISABLED");
- goto cc_sleep;
- }
- }
- if (csp->ch_recv.c_checkin)
- goto cc_sleep;
-
- if (empty == csp->ch_recv_domcount) {
- empty = 0;
- goto cc_slowdown;
- }
-
- ASSERT(mmp[domid] != NULL);
-
- mutex_enter(&mmp[domid]->mm_mutex);
- if ((smr_mboxp = mmp[domid]->mm_smr_mboxp) == NULL) {
- /*
- * Somebody is trying to shut things down.
- */
- empty++;
- mutex_exit(&mmp[domid]->mm_mutex);
- continue;
- }
- ASSERT(mmp[domid]->mm_channel == (short)channel);
- /*
- * We don't care if the mm_smr_mboxp is nullified
- * after this point. The thread attempting to shut
- * us down has to formally pause this channel before
- * anything is official anyway. So, we can continue
- * with our local SMR reference until the thread
- * shutting us down really stops us.
- *
- * Need to get the qiget index _before_ we drop the
- * lock since it might get flushed (idn_mainmbox_flush)
- * once we drop the mm_mutex.
- *
- * We prefer not to hold the mm_mutex across the
- * idn_recv_mboxdata() call since that may be time-
- * consuming.
- */
- qi = mmp[domid]->mm_qiget;
-
- /*
- * Check the mailbox header if checksum is turned on.
- */
- mbox_csum = IDN_CKSUM_MBOX(&smr_mboxp->mt_header);
- if (!VALID_MBOXHDR(&smr_mboxp->mt_header, channel, mbox_csum)) {
- IDN_KSTAT_INC(sip, si_mboxcrc);
- IDN_KSTAT_INC(sip, si_ierrors);
- if (!(mmp[domid]->mm_flags & IDNMMBOX_FLAG_CORRUPTED)) {
- cmn_err(CE_WARN,
- "IDN: 241: [recv] (domain %d, "
- "channel %d) SMR CORRUPTED - RELINK",
- domid, channel);
- mmp[domid]->mm_flags |= IDNMMBOX_FLAG_CORRUPTED;
- }
- empty = 0;
- mutex_exit(&mmp[domid]->mm_mutex);
- goto cc_sleep;
- }
- mutex_exit(&mmp[domid]->mm_mutex);
- mqp = &smr_mboxp->mt_queue[0];
-
- pktcount = dropcount = 0;
-
- if (mqp[qi].ms_owner == 0)
- goto cc_next;
-
- bufoffset = IDN_BFRAME2OFFSET(mqp[qi].ms_bframe);
-
- if (!VALID_NWROFFSET(bufoffset, IDN_SMR_BUFSIZE)) {
- /* ASSERT(0); */
- mqp[qi].ms_flag |= IDN_MBOXMSG_FLAG_ERR_BADOFFSET;
- mqp[qi].ms_owner = 0;
- IDN_MMBOXINDEX_INC(qi);
- dropcount++;
-
- IDN_KSTAT_INC(sip, si_smraddr);
- IDN_KSTAT_INC(sip, si_ierrors);
-
- } else {
- PR_DATA("%s: (channel %d) pkt (off 0x%x, "
- "qiget %d) from domain %d\n",
- proc, channel, bufoffset, qi, domid);
-#ifdef DEBUG
-
- hdrp = IDN_BUF2HDR(IDN_OFFSET2ADDR(bufoffset));
- netaddr.netaddr = hdrp->b_netaddr;
- ASSERT(netaddr.net.chan == (ushort_t)channel);
-#endif /* DEBUG */
-
- if (idn_recv_mboxdata(channel,
- IDN_OFFSET2ADDR(bufoffset)) < 0) {
- mutex_enter(&mmp[domid]->mm_mutex);
- if (!(mmp[domid]->mm_flags &
- IDNMMBOX_FLAG_CORRUPTED)) {
- cmn_err(CE_WARN,
- "IDN: 241: [recv] (domain "
- "%d, channel %d) SMR "
- "CORRUPTED - RELINK",
- domid, channel);
- mmp[domid]->mm_flags |=
- IDNMMBOX_FLAG_CORRUPTED;
- }
- mutex_exit(&mmp[domid]->mm_mutex);
- }
-
- mqp[qi].ms_owner = 0;
- IDN_MMBOXINDEX_INC(qi);
- pktcount++;
- }
-
-cc_next:
-
- mutex_enter(&mmp[domid]->mm_mutex);
- if (mmp[domid]->mm_smr_mboxp) {
- if (dropcount)
- mmp[domid]->mm_dropped += dropcount;
- mmp[domid]->mm_qiget = qi;
- mmp[domid]->mm_count += pktcount;
- }
- mutex_exit(&mmp[domid]->mm_mutex);
-
- if (pktcount == 0) {
- empty++;
- } else {
- csp->ch_recv_waittime = IDN_NETSVR_WAIT_MIN;
- empty = 0;
- idleloops = 0;
-
- PR_DATA("%s: (channel %d) dom=%d, pktcnt=%d\n",
- proc, channel, domid, pktcount);
- }
-
- continue;
-
-cc_slowdown:
-
-#ifdef DEBUG
- if (idleloops == 0) {
- PR_DATA("%s: (channel %d) going SOFT IDLE...\n",
- proc, channel);
- }
-#endif /* DEBUG */
- if (idleloops++ < IDN_NETSVR_SPIN_COUNT) {
- /*
- * At this level we only busy-wait.
- * Get back into action.
- */
- continue;
- }
- idleloops = 0;
-
-cc_sleep:
-
- if (mainhp)
- mainhp->mh_svr_active = 0;
-
- IDN_CHAN_LOCK_RECV(csp);
-
-cc_die:
-
- ASSERT(IDN_CHAN_RECV_IS_LOCKED(csp));
-
- if (!IDN_CHANNEL_IS_RECV_ACTIVE(csp) &&
- IDN_CHANNEL_IS_DETACHED(csp)) {
- /*
- * Time to die...
- */
- PR_CHAN("%s: (channel %d) serviced %d "
- "packets, drop = %d\n", proc, channel,
- tot_pktcount, tot_dropcount);
- PR_CHAN("%s: (channel %d) TERMINATING\n",
- proc, channel);
- PR_CHAN("%s: (channel %d) ch_morguep = %p\n",
- proc, channel, (void *)csp->ch_recv_morguep);
-
- csp->ch_recv_threadp = NULL;
-#ifdef DEBUG
- for (index = 0; index < csp->ch_recv_domcount;
- index++) {
- if ((int)((csp->ch_recv_scanset >>
- (index*4)) & 0xf) == domid) {
- PR_DATA("%s: WARNING (channel %d) "
- "DROPPING domid %d...\n",
- proc, channel, domid);
- }
- }
-#endif /* DEBUG */
- IDN_CHAN_RECV_DONE(csp);
-
- sema_v(csp->ch_recv_morguep);
-
- IDN_CHAN_UNLOCK_RECV(csp);
-
- thread_exit();
- /* not reached */
- }
-
- do {
- if (IDN_CHANNEL_IS_DETACHED(csp)) {
- PR_CHAN("%s: (channel %d) going to DIE...\n",
- proc, channel);
- goto cc_die;
- }
-#ifdef DEBUG
- if (IDN_CHANNEL_IS_RECV_ACTIVE(csp) &&
- (csp->ch_recv_waittime <= IDN_NETSVR_WAIT_MAX)) {
- PR_CHAN("%s: (channel %d) going SOFT IDLE "
- "(waittime = %d ticks)...\n",
- proc, channel,
- csp->ch_recv_waittime);
- } else {
- PR_CHAN("%s: (channel %d) going "
- "HARD IDLE...\n", proc, channel);
- }
-#endif /* DEBUG */
- IDN_CHAN_RECV_DONE(csp);
-
- /*
- * If we're being asked to check-in then
- * go into a hard sleep. Want to give the
- * thread requesting us to checkin a chance.
- */
- while (csp->ch_recv.c_checkin)
- cv_wait(&csp->ch_recv_cv,
- &csp->ch_recv.c_mutex);
-
- if (csp->ch_recv_waittime > IDN_NETSVR_WAIT_MAX)
- cv_wait(&csp->ch_recv_cv,
- &csp->ch_recv.c_mutex);
- else
- (void) cv_reltimedwait(&csp->ch_recv_cv,
- &csp->ch_recv.c_mutex,
- csp->ch_recv_waittime, TR_CLOCK_TICK);
-
- IDN_CHAN_RECV_INPROGRESS(csp);
-
- IDN_KSTAT_INC(sip, si_sigsvr);
-
- if (csp->ch_recv_waittime <= IDN_NETSVR_WAIT_MAX)
- csp->ch_recv_waittime <<=
- IDN_NETSVR_WAIT_SHIFT;
-
- } while (!IDN_CHANNEL_IS_RECV_ACTIVE(csp));
-
- /*
- * Before we see the world (and touch SMR space),
- * see if we've been told to die.
- */
- mainhp = NULL;
- /*
- * The world may have changed since we were
- * asleep. Need to resync cache and check for a
- * new syncheader.
- *
- * Reset chansvr cache against any changes in
- * mbox fields we need (mm_qiget).
- */
- CHANSVR_SYNC_CACHE(csp, mmp, channel);
- if (csp->ch_recv_domcount <= 0) {
- /*
- * Everybody disappeared on us.
- * Go back to sleep.
- */
- goto cc_die;
- }
- ASSERT(csp->ch_recv_scanset && csp->ch_recv_domset);
-
- mainhp = idn_chan_server_syncheader(channel);
- if (mainhp == NULL) {
- /*
- * Bummer...we're idling...
- */
- goto cc_die;
- }
-
- mainhp->mh_svr_active = 1;
-
- IDN_CHAN_UNLOCK_RECV(csp);
- /*
- * Reset the domid index after sleeping.
- */
- CHANSVR_RESET_INDEX(index);
-
- empty = 0;
- idleloops = 0;
- }
-}
-
-#if 0
-/*
- * We maintain a separate function for flushing the STREAMs
- * queue of a channel because it must be done outside the
- * context of the idn_chan_action routine. The streams flush
- * cannot occur inline with the idn_chan_action because
- * the act of flushing may cause IDN send functions to be called
- * directly and thus locks to be obtained which could result
- * in deadlocks.
- */
-static void
-idn_chan_flush(idn_chansvr_t *csp)
-{
- queue_t *rq;
- struct idn *sip;
- int flush_type = 0;
- idn_chaninfo_t *csend, *crecv;
- procname_t proc = "idn_chan_flush";
-
- csend = &csp->ch_send;
- crecv = &csp->ch_recv;
-
- mutex_enter(&crecv->c_mutex);
- mutex_enter(&csend->c_mutex);
-
- if (crecv->c_state & IDN_CHANSVC_STATE_FLUSH)
- flush_type |= FLUSHR;
-
- if (csend->c_state & IDN_CHANSVC_STATE_FLUSH)
- flush_type |= FLUSHW;
-
- if (flush_type) {
- rq = NULL;
- rw_enter(&idn.struprwlock, RW_READER);
- if ((sip = IDN_INST2SIP(csp->ch_id)) != NULL)
- rq = sip->si_ipq;
- rw_exit(&idn.struprwlock);
- if (rq) {
- /*
- * Flush the STREAM if possible
- * to get the channel server coherent
- * enough to respond to us.
- */
- PR_CHAN("%s: sending FLUSH (%x) to channel %d\n",
- proc, flush_type, csp->ch_id);
-
- (void) putnextctl1(rq, M_FLUSH, flush_type);
- }
- crecv->c_state &= ~IDN_CHANSVC_STATE_FLUSH;
- csend->c_state &= ~IDN_CHANSVC_STATE_FLUSH;
-
- if (crecv->c_waiters)
- cv_broadcast(&crecv->c_cv);
- }
-
- mutex_exit(&csend->c_mutex);
- mutex_exit(&crecv->c_mutex);
-}
-#endif /* 0 */
-
-/*
- * Locks are with respect to SEND/RECV locks (c_mutex).
- *
- * STOP/SUSPEND/DETACH
- * - Entered with locks dropped, leave with locks held.
- * DETACH - lock dropped manually.
- * RESTART/RESUME
- * - Entered with locks held, leave with locks dropped.
- * ATTACH
- * - both enter and leave with locks dropped.
- */
-static void
-idn_chan_action(int channel, idn_chanaction_t chanaction, int wait)
-{
- uchar_t clr_state, set_state;
- uint_t is_running;
- domainset_t closed_slabwaiters = 0;
- struct idn *sip;
- idn_chansvr_t *csp;
- idn_chaninfo_t *csend, *crecv;
- procname_t proc = "idn_chan_action";
-
- ASSERT((channel >= 0) && (channel < IDN_MAX_NETS));
- ASSERT(idn.chan_servers);
-
- csp = &idn.chan_servers[channel];
-
- PR_CHAN("%s: requesting %s for channel %d\n",
- proc, chanaction_str[(int)chanaction], channel);
-
- csend = &csp->ch_send;
- crecv = &csp->ch_recv;
-
- ASSERT(IDN_CHAN_GLOBAL_IS_LOCKED(csp));
-
- clr_state = set_state = 0;
-
- switch (chanaction) {
- case IDNCHAN_ACTION_DETACH:
- clr_state = IDN_CHANSVC_STATE_MASK;
- /*FALLTHROUGH*/
-
- case IDNCHAN_ACTION_STOP:
- clr_state |= IDN_CHANSVC_STATE_ENABLED;
- /*FALLTHROUGH*/
-
- case IDNCHAN_ACTION_SUSPEND:
- clr_state |= IDN_CHANSVC_STATE_ACTIVE;
-
- /*
- * Must maintain this locking order.
- * Set asynchronous check-in flags.
- */
- crecv->c_checkin = 1;
- csend->c_checkin = 1;
-
- is_running = 0;
- if ((csend->c_inprogress || crecv->c_inprogress) &&
- wait && (csp->ch_recv_threadp != curthread)) {
-
- rw_enter(&idn.struprwlock, RW_READER);
- if ((sip = IDN_INST2SIP(channel)) != NULL) {
- /*
- * Temporarily turn off the STREAM
- * to give a chance to breath.
- */
- is_running = sip->si_flags & IDNRUNNING;
- if (is_running)
- sip->si_flags &= ~IDNRUNNING;
- }
- rw_exit(&idn.struprwlock);
- }
-
- mutex_enter(&crecv->c_mutex);
- crecv->c_state &= ~clr_state;
-
- mutex_enter(&csend->c_mutex);
- csend->c_state &= ~clr_state;
-
- /*
- * It's possible the channel server could come
- * through this flow itself due to putting data upstream
- * that ultimately turned around and came back down for
- * sending. If this is the case we certainly don't
- * want to cv_wait, otherwise we'll obviously deadlock
- * waiting for ourself. So, only block if somebody
- * other than the channel server we're attempting to
- * suspend/stop.
- */
- if (wait && (csp->ch_recv_threadp != curthread)) {
- int do_flush = 0;
-
- if (csend->c_inprogress || crecv->c_inprogress)
- do_flush++;
-
- if (do_flush) {
- rw_enter(&idn.struprwlock, RW_READER);
- if ((sip = IDN_INST2SIP(channel)) != NULL) {
- /*
- * Temporarily turn off the STREAM
- * to give a chance to breath.
- */
- if (sip->si_flags & IDNRUNNING) {
- is_running = 1;
- sip->si_flags &= ~IDNRUNNING;
- }
- }
- rw_exit(&idn.struprwlock);
- }
-
- /*
- * If we have any senders in-progress
- * it's possible they're stuck waiting
- * down in smr_buf_alloc which may never
- * arrive if we're in an unlink process.
- * Rather than wait for it to timeout
- * let's be proactive so we can disconnect
- * asap.
- */
- closed_slabwaiters = csp->ch_reg_domset;
- DOMAINSET_ADD(closed_slabwaiters, idn.localid);
- if (closed_slabwaiters)
- smr_slabwaiter_close(closed_slabwaiters);
-
- do {
- /*
- * It's possible due to a STREAMs
- * loopback from read queue to write queue
- * that receiver and sender may be same
- * thread, i.e. receiver's inprogress
- * flag will never clear until sender's
- * inprogress flag clears. So, we wait
- * for sender's inprogress first.
- */
- while (csend->c_inprogress) {
- mutex_exit(&crecv->c_mutex);
- while (csend->c_inprogress) {
- csend->c_waiters++;
- cv_wait(&csend->c_cv,
- &csend->c_mutex);
- csend->c_waiters--;
- }
- /*
- * Maintain lock ordering.
- * Eventually we will catch
- * him due to the flag settings.
- */
- mutex_exit(&csend->c_mutex);
- mutex_enter(&crecv->c_mutex);
- mutex_enter(&csend->c_mutex);
- }
- if (crecv->c_inprogress) {
- mutex_exit(&csend->c_mutex);
- while (crecv->c_inprogress) {
- crecv->c_waiters++;
- cv_wait(&crecv->c_cv,
- &crecv->c_mutex);
- crecv->c_waiters--;
- }
- mutex_enter(&csend->c_mutex);
- }
- } while (csend->c_inprogress);
- }
-
- if (is_running) {
- /*
- * Restore the IDNRUNNING bit in
- * the flags to let them know the
- * channel is still alive.
- */
- rw_enter(&idn.struprwlock, RW_READER);
- if ((sip = IDN_INST2SIP(channel)) != NULL)
- sip->si_flags |= IDNRUNNING;
- rw_exit(&idn.struprwlock);
- }
-
- if (closed_slabwaiters) {
- /*
- * We can reopen now since at this point no new
- * slabwaiters will attempt to come in and wait.
- */
- smr_slabwaiter_open(csp->ch_reg_domset);
- }
-
- crecv->c_checkin = 0;
- csend->c_checkin = 0;
-
- /*
- * ALL leave with locks held.
- */
- PR_CHAN("%s: action (%s) for channel %d - COMPLETED\n",
- proc, chanaction_str[(int)chanaction], channel);
- break;
-
- case IDNCHAN_ACTION_ATTACH:
- mutex_enter(&crecv->c_mutex);
- mutex_enter(&csend->c_mutex);
- set_state |= csp->ch_state & IDN_CHANSVC_STATE_ATTACHED;
- /*FALLTHROUGH*/
-
- case IDNCHAN_ACTION_RESTART:
- set_state |= csp->ch_state & IDN_CHANSVC_STATE_ENABLED;
- /*FALLTHROUGH*/
-
- case IDNCHAN_ACTION_RESUME:
- ASSERT(IDN_CHAN_LOCAL_IS_LOCKED(csp));
- set_state |= csp->ch_state & IDN_CHANSVC_STATE_ACTIVE;
-
- crecv->c_state |= set_state;
- csend->c_state |= set_state;
-
- /*
- * The channel server itself could come through this
- * flow, so obviously no point in attempting to wake
- * ourself up!.
- */
- if (csp->ch_recv_threadp && (csp->ch_recv_threadp != curthread))
- cv_signal(&csp->ch_recv_cv);
-
- PR_CHAN("%s: action (%s) for channel %d - COMPLETED\n",
- proc, chanaction_str[(int)chanaction], channel);
-
- /*
- * Leaves with lock released.
- */
- mutex_exit(&csend->c_mutex);
- mutex_exit(&crecv->c_mutex);
- break;
-
- default:
- ASSERT(0);
- break;
- }
-}
-
-static void
-idn_chan_addmbox(int channel, ushort_t domset)
-{
- idn_chansvr_t *csp;
- register int d;
- procname_t proc = "idn_chan_addmbox";
-
- PR_CHAN("%s: adding domset 0x%x main mailboxes to channel %d\n",
- proc, domset, channel);
-
- ASSERT(idn.chan_servers);
-
- csp = &idn.chan_servers[channel];
-
- /*
- * Adding domains to a channel can be
- * asynchonous, so we don't bother waiting.
- */
- IDN_CHANNEL_SUSPEND(channel, 0);
-
- /*
- * Now we have the sending and receiving sides blocked
- * for this channel.
- */
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(domset, d))
- continue;
- if (IDN_CHAN_DOMAIN_IS_REGISTERED(csp, d)) {
- DOMAINSET_DEL(domset, d);
- continue;
- }
- IDN_CHANSVR_SCANSET_ADD_PENDING(csp, d);
- DOMAINSET_ADD(csp->ch_recv_domset_pending, d);
- IDN_CHAN_DOMAIN_REGISTER(csp, d);
-
- PR_CHAN("%s: domain %d (channel %d) RECV (pending) "
- "scanset = 0x%lx\n", proc, d, channel,
- csp->ch_recv_scanset_pending);
- PR_CHAN("%s: domain %d (channel %d) domset = 0x%x\n",
- proc, d, channel, (uint_t)csp->ch_reg_domset);
-
- CHECKPOINT_OPENED(IDNSB_CHKPT_CHAN,
- idn_domain[d].dhw.dh_boardset, 1);
- }
- if (domset)
- csp->ch_recv_changed = 1;
-
- IDN_CHANNEL_RESUME(channel);
-}
-
-static void
-idn_chan_delmbox(int channel, ushort_t domset)
-{
- idn_chansvr_t *csp;
- register int d;
- procname_t proc = "idn_chan_delmbox";
-
- PR_CHAN("%s: deleting domset 0x%x main mailboxes from channel %d\n",
- proc, domset, channel);
-
- ASSERT(idn.chan_servers);
-
- csp = &idn.chan_servers[channel];
-
- /*
- * Here we have to wait for the channel server
- * as it's vital that we don't return without guaranteeing
- * that the given domset is no longer registered.
- */
- IDN_CHANNEL_SUSPEND(channel, 1);
-
- /*
- * Now we have the sending and receiving sides blocked
- * for this channel.
- */
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(domset, d))
- continue;
- if (!IDN_CHAN_DOMAIN_IS_REGISTERED(csp, d)) {
- DOMAINSET_DEL(domset, d);
- continue;
- }
- /*
- * This domain has a mailbox hanging on this channel.
- * Get him out.
- *
- * First remove him from the receive side.
- */
- ASSERT(csp->ch_recv_domcount > 0);
- IDN_CHANSVR_SCANSET_DEL_PENDING(csp, d);
- DOMAINSET_DEL(csp->ch_recv_domset_pending, d);
- IDN_CHAN_DOMAIN_UNREGISTER(csp, d);
-
- PR_CHAN("%s: domain %d (channel %d) RECV (pending) "
- "scanset = 0x%lx\n", proc, d, channel,
- csp->ch_recv_scanset_pending);
- PR_CHAN("%s: domain %d (channel %d) domset = 0x%x\n",
- proc, d, channel, (uint_t)csp->ch_reg_domset);
-
- CHECKPOINT_CLOSED(IDNSB_CHKPT_CHAN,
- idn_domain[d].dhw.dh_boardset, 2);
-
- }
- if (domset)
- csp->ch_recv_changed = 1;
-
- IDN_CHANNEL_RESUME(channel);
-}
-
-static int
-idn_valid_etherheader(struct ether_header *ehp)
-{
- uchar_t *eap;
-
- eap = &ehp->ether_dhost.ether_addr_octet[0];
-
- if ((eap[IDNETHER_ZERO] != 0) && (eap[IDNETHER_ZERO] != 0xff))
- return (0);
-
- if ((eap[IDNETHER_COOKIE1] != IDNETHER_COOKIE1_VAL) &&
- (eap[IDNETHER_COOKIE1] != 0xff))
- return (0);
-
- if ((eap[IDNETHER_COOKIE2] != IDNETHER_COOKIE2_VAL) &&
- (eap[IDNETHER_COOKIE2] != 0xff))
- return (0);
-
- if ((eap[IDNETHER_RESERVED] != IDNETHER_RESERVED_VAL) &&
- (eap[IDNETHER_RESERVED] != 0xff))
- return (0);
-
- if (!VALID_UCHANNEL(eap[IDNETHER_CHANNEL]) &&
- (eap[IDNETHER_CHANNEL] != 0xff))
- return (0);
-
- if (!VALID_UDOMAINID(IDN_NETID2DOMID(eap[IDNETHER_NETID])) &&
- (eap[IDNETHER_NETID] != 0xff))
- return (0);
-
- return (1);
-}
-
-/*
- * Packet header has already been filled in.
- * RETURNS: 0
- * ENOLINK
- * EPROTO
- * ENOSPC
- */
-/*ARGSUSED*/
-static int
-idn_send_mboxdata(int domid, struct idn *sip, int channel, caddr_t bufp)
-{
- idn_mainmbox_t *mmp;
- idn_mboxmsg_t *mqp;
- smr_pkthdr_t *hdrp;
- smr_offset_t bufoffset;
- idn_netaddr_t dst;
- ushort_t mbox_csum;
- int rv = 0;
- int pktlen, qi;
- procname_t proc = "idn_send_mboxdata";
-
- mmp = idn_domain[domid].dmbox.m_send;
- if (mmp == NULL) {
- PR_DATA("%s: dmbox.m_send == NULL\n", proc);
- IDN_KSTAT_INC(sip, si_linkdown);
- return (ENOLINK);
- }
-
- mmp += channel;
- mutex_enter(&mmp->mm_mutex);
-
- if (mmp->mm_smr_mboxp == NULL) {
- PR_DATA("%s: (d %d, chn %d) mm_smr_mboxp == NULL\n",
- proc, domid, channel);
- IDN_KSTAT_INC(sip, si_linkdown);
- rv = ENOLINK;
- goto send_err;
- }
- mbox_csum = IDN_CKSUM_MBOX(&mmp->mm_smr_mboxp->mt_header);
- if (mbox_csum != mmp->mm_smr_mboxp->mt_header.mh_cksum) {
- PR_DATA("%s: (d %d, chn %d) mbox hdr cksum (%d) "
- "!= actual (%d)\n",
- proc, domid, channel, mbox_csum,
- mmp->mm_smr_mboxp->mt_header.mh_cksum);
- if ((mmp->mm_flags & IDNMMBOX_FLAG_CORRUPTED) == 0) {
- cmn_err(CE_WARN,
- "IDN: 241: [send] (domain %d, "
- "channel %d) SMR CORRUPTED - RELINK",
- domid, channel);
- mmp->mm_flags |= IDNMMBOX_FLAG_CORRUPTED;
- }
- IDN_KSTAT_INC(sip, si_mboxcrc);
- IDN_KSTAT_INC(sip, si_oerrors);
- rv = EPROTO;
- goto send_err;
- }
-
- bufoffset = IDN_ADDR2OFFSET(bufp);
- hdrp = IDN_BUF2HDR(bufp);
- pktlen = hdrp->b_length;
- dst.netaddr = hdrp->b_netaddr;
- ASSERT(dst.net.chan == (ushort_t)channel);
-
- mqp = &mmp->mm_smr_mboxp->mt_queue[0];
- qi = mmp->mm_qiput;
-
- if (mqp[qi].ms_owner) {
- PR_DATA("%s: mailbox FULL (qiput=%d, qiget=%d)\n",
- proc, mmp->mm_qiput, mmp->mm_qiget);
- IDN_KSTAT_INC(sip, si_txfull);
- rv = ENOSPC;
- goto send_err;
- }
- if (mqp[qi].ms_flag & IDN_MBOXMSG_FLAG_RECLAIM) {
- smr_offset_t recl_bufoffset;
- /*
- * Remote domain finished with mailbox entry,
- * however it has not been reclaimed yet. A reclaim
- * was done before coming into this routine, however
- * timing may have been such that the entry became
- * free just after the reclamation, but before
- * entry into here. Go ahead and reclaim this entry.
- */
- recl_bufoffset = IDN_BFRAME2OFFSET(mqp[qi].ms_bframe);
-
- PR_DATA("%s: attempting reclaim (domain %d) "
- "(qiput=%d, b_off=0x%x)\n",
- proc, domid, qi, recl_bufoffset);
-
- if (VALID_NWROFFSET(recl_bufoffset, IDN_SMR_BUFSIZE)) {
- int recl;
- caddr_t b_bufp;
- smr_pkthdr_t *b_hdrp;
-
- b_bufp = IDN_OFFSET2ADDR(recl_bufoffset);
- b_hdrp = IDN_BUF2HDR(b_bufp);
-
- if (IDN_CKSUM_PKT(b_hdrp) != b_hdrp->b_cksum) {
- IDN_KSTAT_INC(sip, si_crc);
- IDN_KSTAT_INC(sip, si_fcs_errors);
- IDN_KSTAT_INC(sip, si_reclaim);
- IDN_KSTAT_INC(sip, si_oerrors);
- }
-
- recl = smr_buf_free(domid, b_bufp, b_hdrp->b_length);
-#ifdef DEBUG
- if (recl == 0) {
- PR_DATA("%s: SUCCESSFULLY reclaimed buf "
- "(domain %d)\n", proc, domid);
- } else {
- PR_DATA("%s: WARNING: reclaim failed (FREE) "
- "(domain %d)\n", proc, domid);
- }
-#endif /* DEBUG */
- } else {
- IDN_KSTAT_INC(sip, si_smraddr);
- IDN_KSTAT_INC(sip, si_reclaim);
- PR_DATA("%s: WARNING: reclaim failed (BAD OFFSET) "
- "(domain %d)\n", proc, domid);
- }
- }
-
- if (*mmp->mm_smr_readyp == 0) {
- mmp->mm_qiput = qi;
- IDN_KSTAT_INC(sip, si_linkdown);
- rv = ENOLINK;
- goto send_err;
- }
-
- mqp[qi].ms_flag = IDN_MBOXMSG_FLAG_RECLAIM;
- mqp[qi].ms_bframe = IDN_OFFSET2BFRAME(bufoffset);
- /* membar_stst(); */
- mqp[qi].ms_owner = 1;
-
- IDN_MMBOXINDEX_INC(qi);
-
- mmp->mm_qiput = qi;
-
- mmp->mm_count++;
-
- if ((*mmp->mm_smr_readyp) && !(*mmp->mm_smr_activep)) {
- idn_msgtype_t mt;
-
- mt.mt_mtype = IDNP_DATA;
- mt.mt_atype = 0;
- IDN_KSTAT_INC(sip, si_xdcall);
- (void) IDNXDC(domid, &mt, (uint_t)dst.net.chan, 0, 0, 0);
- }
- mutex_exit(&mmp->mm_mutex);
- IDN_KSTAT_INC(sip, si_opackets);
- IDN_KSTAT_INC(sip, si_opackets64);
- IDN_KSTAT_ADD(sip, si_xmtbytes, pktlen);
- IDN_KSTAT_ADD(sip, si_obytes64, (uint64_t)pktlen);
-
- return (0);
-
-send_err:
- mmp->mm_dropped++;
-
- mutex_exit(&mmp->mm_mutex);
-
- return (rv);
-}
-
-static int
-idn_recv_mboxdata(int channel, caddr_t bufp)
-{
- smr_pkthdr_t *hdrp;
- struct idn *sip;
- mblk_t *mp = nilp(mblk_t);
- int pktlen;
- int apktlen;
- int rv = 0;
- smr_offset_t bufoffset;
- ushort_t csum;
- idn_netaddr_t dst, daddr;
- procname_t proc = "idn_recv_mboxdata";
-
- hdrp = IDN_BUF2HDR(bufp);
-
- csum = IDN_CKSUM_PKT(hdrp);
-
- sip = IDN_INST2SIP(channel);
- if (sip == NULL) {
- /*LINTED*/
- sip = IDN_INST2SIP(0);
- }
- ASSERT(sip);
-
- if (csum != hdrp->b_cksum) {
- PR_DATA("%s: bad checksum(%x) != expected(%x)\n",
- proc, (uint_t)csum, (uint_t)hdrp->b_cksum);
- IDN_KSTAT_INC(sip, si_crc);
- IDN_KSTAT_INC(sip, si_fcs_errors);
- rv = -1;
- goto recv_err;
- }
-
- daddr.net.chan = (ushort_t)channel;
- daddr.net.netid = (ushort_t)idn.localid;
-
- dst.netaddr = hdrp->b_netaddr;
- bufoffset = hdrp->b_offset;
-
- if (dst.netaddr != daddr.netaddr) {
- PR_DATA("%s: wrong dest netaddr (0x%x), expected (0x%x)\n",
- proc, dst.netaddr, daddr.netaddr);
- IDN_KSTAT_INC(sip, si_nolink);
- IDN_KSTAT_INC(sip, si_macrcv_errors);
- goto recv_err;
- }
- pktlen = hdrp->b_length;
- apktlen = pktlen;
-
- if ((pktlen <= 0) || (pktlen > IDN_DATA_SIZE)) {
- PR_DATA("%s: invalid packet length (%d) <= 0 || > %lu\n",
- proc, pktlen, IDN_DATA_SIZE);
- IDN_KSTAT_INC(sip, si_buff);
- IDN_KSTAT_INC(sip, si_toolong_errors);
- goto recv_err;
- }
-
- mp = allocb(apktlen + IDN_ALIGNSIZE, BPRI_LO);
- if (mp == nilp(mblk_t)) {
- PR_DATA("%s: allocb(pkt) failed\n", proc);
- IDN_KSTAT_INC(sip, si_allocbfail);
- IDN_KSTAT_INC(sip, si_norcvbuf); /* MIB II */
- goto recv_err;
- }
- ASSERT(DB_TYPE(mp) == M_DATA);
- /*
- * Copy data packet into its streams buffer.
- * Align pointers for maximum bcopy performance.
- */
- mp->b_rptr = (uchar_t *)IDN_ALIGNPTR(mp->b_rptr, bufoffset);
- bcopy(IDN_BUF2DATA(bufp, bufoffset), mp->b_rptr, apktlen);
- mp->b_wptr = mp->b_rptr + pktlen;
-
- if (IDN_CHECKSUM &&
- !idn_valid_etherheader((struct ether_header *)mp->b_rptr)) {
- freeb(mp);
- mp = nilp(mblk_t);
- PR_DATA("%s: etherheader CORRUPTED\n", proc);
- IDN_KSTAT_INC(sip, si_crc);
- IDN_KSTAT_INC(sip, si_fcs_errors);
- rv = -1;
- goto recv_err;
- }
-
- idndl_read(NULL, mp);
-
-recv_err:
-
- if (mp == nilp(mblk_t)) {
- IDN_KSTAT_INC(sip, si_ierrors);
- }
-
- return (rv);
-}
-
-/*
- * When on shutdown path (idn_active_resources) must call
- * idn_mainmbox_flush() _BEFORE_ calling idn_reclaim_mboxdata()
- * for any final data. This is necessary incase the mailboxes
- * have been unregistered. If they have then idn_mainmbox_flush()
- * will set mm_smr_mboxp to NULL which prevents us from touching
- * poison SMR space.
- */
-int
-idn_reclaim_mboxdata(int domid, int channel, int nbufs)
-{
- idn_mainmbox_t *mmp;
- idn_mboxmsg_t *mqp;
- smr_pkthdr_t *hdrp;
- idn_domain_t *dp;
- int qi;
- int mi;
- int reclaim_cnt = 0;
- int free_cnt;
- ushort_t csum;
- struct idn *sip;
- smr_offset_t reclaim_list, curr, prev;
- procname_t proc = "idn_reclaim_mboxdata";
-
-
- sip = IDN_INST2SIP(channel);
- if (sip == NULL) {
- /*LINTED*/
- sip = IDN_INST2SIP(0);
- }
- ASSERT(sip);
-
- dp = &idn_domain[domid];
-
- PR_DATA("%s: requested %d buffers from domain %d\n",
- proc, nbufs, domid);
-
- if (lock_try(&dp->dreclaim_inprogress) == 0) {
- /*
- * Reclaim is already in progress, don't
- * bother.
- */
- PR_DATA("%s: reclaim already in progress\n", proc);
- return (0);
- }
-
- if (dp->dmbox.m_send == NULL)
- return (0);
-
- reclaim_list = curr = prev = IDN_NIL_SMROFFSET;
-
- mi = (int)dp->dreclaim_index;
- do {
- ushort_t mbox_csum;
-
- mmp = &dp->dmbox.m_send[mi];
- /* do-while continues down */
- ASSERT(mmp);
- if (mutex_tryenter(&mmp->mm_mutex) == 0) {
- /*
- * This channel is busy, move on.
- */
- IDN_MBOXCHAN_INC(mi);
- continue;
- }
-
- if (mmp->mm_smr_mboxp == NULL) {
- PR_DATA("%s: no smr pointer for domid %d, chan %d\n",
- proc, domid, (int)mmp->mm_channel);
- ASSERT(mmp->mm_qiget == mmp->mm_qiput);
- mutex_exit(&mmp->mm_mutex);
- IDN_MBOXCHAN_INC(mi);
- continue;
- }
- mbox_csum = IDN_CKSUM_MBOX(&mmp->mm_smr_mboxp->mt_header);
- if (mbox_csum != mmp->mm_smr_mboxp->mt_header.mh_cksum) {
- PR_DATA("%s: (d %d, chn %d) mbox hdr "
- "cksum (%d) != actual (%d)\n",
- proc, domid, (int)mmp->mm_channel, mbox_csum,
- mmp->mm_smr_mboxp->mt_header.mh_cksum);
- IDN_KSTAT_INC(sip, si_mboxcrc);
- IDN_KSTAT_INC(sip, si_oerrors);
- mutex_exit(&mmp->mm_mutex);
- IDN_MBOXCHAN_INC(mi);
- continue;
- }
- mqp = &mmp->mm_smr_mboxp->mt_queue[0];
- qi = mmp->mm_qiget;
-
- while (!mqp[qi].ms_owner &&
- (mqp[qi].ms_flag & IDN_MBOXMSG_FLAG_RECLAIM) &&
- nbufs) {
- idn_mboxmsg_t *msp;
- int badbuf;
-
- badbuf = 0;
- msp = &mqp[qi];
-
- if (msp->ms_flag & IDN_MBOXMSG_FLAG_ERRMASK) {
- PR_DATA("%s: msg.flag ERROR(0x%x) (off=0x%x, "
- "domid=%d, qiget=%d)\n", proc,
- (uint_t)(msp->ms_flag &
- IDN_MBOXMSG_FLAG_ERRMASK),
- IDN_BFRAME2OFFSET(msp->ms_bframe),
- domid, qi);
- }
- prev = curr;
- curr = IDN_BFRAME2OFFSET(mqp[qi].ms_bframe);
-
- if (!VALID_NWROFFSET(curr, IDN_SMR_BUFSIZE)) {
- badbuf = 1;
- IDN_KSTAT_INC(sip, si_reclaim);
- } else {
- /*
- * Put the buffers onto a list that will be
- * formally reclaimed down below. This allows
- * us to free up mboxq entries as fast as
- * possible.
- */
- hdrp = IDN_BUF2HDR(IDN_OFFSET2ADDR(curr));
- csum = IDN_CKSUM_PKT(hdrp);
-
- if (csum != hdrp->b_cksum) {
- badbuf = 1;
- IDN_KSTAT_INC(sip, si_crc);
- IDN_KSTAT_INC(sip, si_fcs_errors);
- IDN_KSTAT_INC(sip, si_reclaim);
- if (!(mmp->mm_flags &
- IDNMMBOX_FLAG_CORRUPTED)) {
- cmn_err(CE_WARN,
- "IDN: 241: [send] "
- "(domain %d, channel "
- "%d) SMR CORRUPTED - "
- "RELINK",
- domid, channel);
- mmp->mm_flags |=
- IDNMMBOX_FLAG_CORRUPTED;
- }
-
- } else if (reclaim_list == IDN_NIL_SMROFFSET) {
- reclaim_list = curr;
- } else {
- caddr_t bufp;
-
- bufp = IDN_OFFSET2ADDR(prev);
- hdrp = IDN_BUF2HDR(bufp);
- hdrp->b_next = curr;
- }
- }
-
- mqp[qi].ms_flag = 0;
-
- IDN_MMBOXINDEX_INC(qi);
-
- if (!badbuf) {
- nbufs--;
- reclaim_cnt++;
- }
-
- if (qi == mmp->mm_qiget)
- break;
- }
- mmp->mm_qiget = qi;
-
- mutex_exit(&mmp->mm_mutex);
-
- IDN_MBOXCHAN_INC(mi);
-
- } while ((mi != (int)dp->dreclaim_index) && nbufs);
-
- dp->dreclaim_index = (uchar_t)mi;
-
- if (reclaim_list != IDN_NIL_SMROFFSET) {
- hdrp = IDN_BUF2HDR(IDN_OFFSET2ADDR(curr));
- hdrp->b_next = IDN_NIL_SMROFFSET;
- }
-
- PR_DATA("%s: reclaimed %d buffers from domain %d\n",
- proc, reclaim_cnt, domid);
-
- if (reclaim_cnt == 0) {
- lock_clear(&dp->dreclaim_inprogress);
- return (0);
- }
-
- /*
- * Now actually go and reclaim (free) the buffers.
- */
- free_cnt = 0;
-
- for (curr = reclaim_list; curr != IDN_NIL_SMROFFSET; ) {
- caddr_t bufp;
-
- bufp = IDN_OFFSET2ADDR(curr);
- hdrp = IDN_BUF2HDR(bufp);
- csum = IDN_CKSUM_PKT(hdrp);
- if (csum != hdrp->b_cksum) {
- /*
- * Once corruption is detected we
- * can't trust our list any further.
- * These buffers are effectively lost.
- */
- cmn_err(CE_WARN,
- "IDN: 241: [send] (domain %d, channel %d) SMR "
- "CORRUPTED - RELINK", domid, channel);
- break;
- }
-
- curr = hdrp->b_next;
-
- if (!smr_buf_free(domid, bufp, hdrp->b_length))
- free_cnt++;
- }
-
- if ((dp->dio < IDN_WINDOW_EMAX) && dp->diocheck) {
- lock_clear(&dp->diocheck);
- IDN_MSGTIMER_STOP(domid, IDNP_DATA, 0);
- }
-
-#ifdef DEBUG
- if (free_cnt != reclaim_cnt) {
- PR_DATA("%s: *** WARNING *** freecnt(%d) != reclaim_cnt (%d)\n",
- proc, free_cnt, reclaim_cnt);
- }
-#endif /* DEBUG */
-
- lock_clear(&dp->dreclaim_inprogress);
-
- return (reclaim_cnt);
-}
-
-void
-idn_signal_data_server(int domid, ushort_t channel)
-{
- idn_nack_t nacktype = 0;
- idn_domain_t *dp;
- idn_chansvr_t *csp;
- int c, min_chan, max_chan;
- idn_mainmbox_t *mmp;
- procname_t proc = "idn_signal_data_server";
-
-
- if (domid == IDN_NIL_DOMID)
- return;
-
- dp = &idn_domain[domid];
-
- if (dp->dawol.a_count > 0) {
- /*
- * Domain was previously AWOL, but no longer.
- */
- IDN_SYNC_LOCK();
- IDN_GLOCK_EXCL();
- idn_clear_awol(domid);
- IDN_GUNLOCK();
- IDN_SYNC_UNLOCK();
- }
- /*
- * Do a precheck before wasting time trying to acquire the lock.
- */
- if ((dp->dstate != IDNDS_CONNECTED) || !IDN_DLOCK_TRY_SHARED(domid)) {
- /*
- * Either we're not connected or somebody is busy working
- * on the domain. Bail on the signal for now, we'll catch
- * it on the next go around.
- */
- return;
- }
- /*
- * We didn't have the drwlock on the first check of dstate,
- * but now that we do, make sure the world hasn't changed!
- */
- if (dp->dstate != IDNDS_CONNECTED) {
- /*
- * If we reach here, then no connection.
- * Send no response if this is the case.
- */
- nacktype = IDNNACK_NOCONN;
- goto send_dresp;
- }
-
- /*
- * No need to worry about locking mainmbox
- * because we're already holding reader
- * lock on domain, plus we're just reading
- * fields in the mainmbox which only change
- * (or go away) when the writer lock is
- * held on the domain.
- */
- if ((mmp = dp->dmbox.m_recv) == NULL) {
- /*
- * No local mailbox.
- */
- nacktype = IDNNACK_BADCFG;
- goto send_dresp;
- }
- if ((channel != IDN_BROADCAST_ALLCHAN) && (channel >= IDN_MAX_NETS)) {
- nacktype = IDNNACK_BADCHAN;
- goto send_dresp;
- }
- if (channel == IDN_BROADCAST_ALLCHAN) {
- PR_DATA("%s: requested signal to ALL channels on domain %d\n",
- proc, domid);
- min_chan = 0;
- max_chan = IDN_MAX_NETS - 1;
- } else {
- PR_DATA("%s: requested signal to channel %d on domain %d\n",
- proc, channel, domid);
- min_chan = max_chan = (int)channel;
- }
- mmp += min_chan;
- for (c = min_chan; c <= max_chan; mmp++, c++) {
-
- /*
- * We do a quick check for a pending channel.
- * If pending it will need activation and we rather
- * do that through a separate (proto) thread.
- */
- csp = &idn.chan_servers[c];
-
- if (csp->ch_recv.c_checkin) {
- PR_DATA("%s: chansvr (%d) for domid %d CHECK-IN\n",
- proc, c, domid);
- continue;
- }
-
- if (IDN_CHAN_TRYLOCK_RECV(csp) == 0) {
- /*
- * Failed to grab lock, server must be active.
- */
- PR_DATA("%s: chansvr (%d) for domid %d already actv\n",
- proc, c, domid);
- continue;
- }
-
- if (IDN_CHANNEL_IS_PENDING(csp)) {
- /*
- * Lock is pending. Submit asynchronous
- * job to activate and move-on.
- */
- IDN_CHAN_UNLOCK_RECV(csp);
- idn_submit_chanactivate_job(c);
- continue;
- }
-
- /*
- * If he ain't active, we ain't talkin'.
- */
- if (IDN_CHANNEL_IS_RECV_ACTIVE(csp) == 0) {
- IDN_CHAN_UNLOCK_RECV(csp);
- PR_DATA("%s: chansvr (%d) for domid %d inactive\n",
- proc, c, domid);
- continue;
- }
-
- if (mutex_tryenter(&mmp->mm_mutex) == 0) {
- IDN_CHAN_UNLOCK_RECV(csp);
- continue;
- }
-
- if (mmp->mm_csp != csp) {
- /*
- * Not registered.
- */
- mutex_exit(&mmp->mm_mutex);
- IDN_CHAN_UNLOCK_RECV(csp);
- continue;
-
- }
- if (mmp->mm_smr_mboxp == NULL) {
- /*
- * No SMR mailbox.
- */
- mutex_exit(&mmp->mm_mutex);
- IDN_CHAN_UNLOCK_RECV(csp);
- continue;
- }
- mutex_exit(&mmp->mm_mutex);
-
- if (csp->ch_recv.c_inprogress) {
- /*
- * Data server is already active.
- */
- IDN_CHAN_UNLOCK_RECV(csp);
- PR_DATA("%s: chansvr (%d) for domid %d already actv\n",
- proc, c, domid);
- continue;
- }
- ASSERT(csp == &idn.chan_servers[c]);
-
-
- PR_DATA("%s: signaling data dispatcher for chan %d dom %d\n",
- proc, c, domid);
- ASSERT(csp);
- cv_signal(&csp->ch_recv_cv);
- IDN_CHAN_UNLOCK_RECV(csp);
- }
-
- if (!nacktype || (channel == IDN_BROADCAST_ALLCHAN)) {
- /*
- * If there were no real errors or we were
- * handling multiple channels, then just
- * return.
- */
- IDN_DUNLOCK(domid);
- return;
- }
-
-send_dresp:
-
- PR_DATA("%s: sending NACK (%s) back to domain %d (cpu %d)\n",
- proc, idnnack_str[nacktype], domid, idn_domain[domid].dcpu);
-
- idn_send_dataresp(domid, nacktype);
-
- IDN_DUNLOCK(domid);
-}
-
-/*ARGSUSED*/
-static int
-idn_recv_data(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs)
-{
-#ifdef DEBUG
- uint_t msg = mtp ? mtp->mt_mtype : 0;
- uint_t msgarg = mtp ? mtp->mt_atype : 0;
- procname_t proc = "idn_recv_data";
-
- PR_PROTO("%s:%d: DATA message received (msg = 0x%x, msgarg = 0x%x)\n",
- proc, domid, msg, msgarg);
- PR_PROTO("%s:%d: xargs = (0x%x, 0x%x, 0x%x, 0x%x)\n",
- proc, domid, xargs[0], xargs[1], xargs[2], xargs[3]);
-#endif /* DEBUG */
-
- return (0);
-}
-
-/*
- * Only used when sending a negative response.
- */
-static void
-idn_send_dataresp(int domid, idn_nack_t nacktype)
-{
- idn_msgtype_t mt;
-
- ASSERT(IDN_DLOCK_IS_HELD(domid));
-
- if (idn_domain[domid].dcpu == IDN_NIL_DCPU)
- return;
-
- mt.mt_mtype = IDNP_NACK;
- mt.mt_atype = IDNP_DATA;
-
- (void) IDNXDC(domid, &mt, (uint_t)nacktype, 0, 0, 0);
-}
-
-/*
- * Checksum routine used in checksum smr_pkthdr_t and idn_mboxhdr_t.
- */
-static ushort_t
-idn_cksum(register ushort_t *hdrp, register int count)
-{
- register int i;
- register ushort_t sum = 0;
-
- for (i = 0; i < count; i++)
- sum += hdrp[i];
-
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
-
- return (~sum);
-}
-
-/*
- * ------------------------------------------------
- */
-
-int
-idn_open_channel(int channel)
-{
- int masterid;
- idn_chansvr_t *csp;
- struct idn *sip;
- procname_t proc = "idn_open_channel";
-
- if (channel >= IDN_MAX_NETS) {
- cmn_err(CE_WARN,
- "IDN: 242: maximum channels (%d) already open",
- IDN_MAX_NETS);
- return (-1);
- }
- IDN_GLOCK_EXCL();
-
- ASSERT(idn.chan_servers != NULL);
-
- csp = &idn.chan_servers[channel];
-
- IDN_CHAN_LOCK_GLOBAL(csp);
-
- if (IDN_CHANNEL_IS_ATTACHED(csp)) {
- PR_CHAN("%s: channel %d already open\n", proc, channel);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- IDN_GUNLOCK();
- return (0);
- }
-
- /*
- * Need to zero out the kstats now that we're activating
- * this channel.
- */
- for (sip = idn.sip; sip; sip = sip->si_nextp) {
- if (sip->si_dip && (ddi_get_instance(sip->si_dip) == channel)) {
- bzero(&sip->si_kstat, sizeof (sip->si_kstat));
- break;
- }
- }
-
- IDN_CHANSVC_MARK_ATTACHED(csp);
- idn.nchannels++;
- CHANSET_ADD(idn.chanset, channel);
- IDN_CHANNEL_ATTACH(channel);
-
- IDN_CHAN_UNLOCK_GLOBAL(csp);
-
- /*
- * We increase our window threshold each time a channel
- * is opened.
- */
- ASSERT(idn.nchannels > 0);
- IDN_WINDOW_EMAX = IDN_WINDOW_MAX +
- ((idn.nchannels - 1) * IDN_WINDOW_INCR);
-
- PR_CHAN("%s: channel %d is OPEN (nchannels = %d)\n",
- proc, channel, idn.nchannels);
-
- masterid = IDN_GET_MASTERID();
- IDN_GUNLOCK();
-
- /*
- * Check if there is an active master to which
- * we're connected. If so, then activate channel.
- */
- if (masterid != IDN_NIL_DOMID) {
- idn_domain_t *dp;
-
- dp = &idn_domain[masterid];
- IDN_DLOCK_SHARED(masterid);
- if (dp->dvote.v.master && (dp->dstate == IDNDS_CONNECTED))
- (void) idn_activate_channel(CHANSET(channel),
- IDNCHAN_ONLINE);
- IDN_DUNLOCK(masterid);
- }
-
- return (0);
-}
-
-void
-idn_close_channel(int channel, idn_chanop_t chanop)
-{
- idn_chansvr_t *csp;
- procname_t proc = "idn_close_channel";
-
-
- ASSERT(idn.chan_servers != NULL);
-
- csp = &idn.chan_servers[channel];
-
- IDN_GLOCK_EXCL();
-
- IDN_CHAN_LOCK_GLOBAL(csp);
- if (IDN_CHANNEL_IS_DETACHED(csp)) {
- PR_CHAN("%s: channel %d already closed\n", proc, channel);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- IDN_GUNLOCK();
- return;
- }
- IDN_CHAN_UNLOCK_GLOBAL(csp);
-
- idn_deactivate_channel(CHANSET(channel), chanop);
-
- IDN_CHAN_LOCK_GLOBAL(csp);
-
- if (chanop == IDNCHAN_HARD_CLOSE) {
- idn.nchannels--;
- CHANSET_DEL(idn.chanset, channel);
- /*
- * We increase our window threshold each time a channel
- * is opened.
- */
- if (idn.nchannels <= 0)
- IDN_WINDOW_EMAX = 0;
- else
- IDN_WINDOW_EMAX = IDN_WINDOW_MAX +
- ((idn.nchannels - 1) * IDN_WINDOW_INCR);
- }
-
- PR_CHAN("%s: channel %d is (%s) CLOSED (nchannels = %d)\n",
- proc, channel,
- (chanop == IDNCHAN_SOFT_CLOSE) ? "SOFT"
- : (chanop == IDNCHAN_HARD_CLOSE) ? "HARD" : "OFFLINE",
- idn.nchannels);
-
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- IDN_GUNLOCK();
-}
-
-static int
-idn_activate_channel(idn_chanset_t chanset, idn_chanop_t chanop)
-{
- int c, rv = 0;
- procname_t proc = "idn_activate_channel";
-
- PR_CHAN("%s: chanset = 0x%x, chanop = %s\n",
- proc, chanset, chanop_str[chanop]);
-
- if (idn.state != IDNGS_ONLINE) {
- /*
- * Can't activate any channels unless local
- * domain is connected and thus has a master.
- */
- PR_CHAN("%s: local domain not connected. no data servers\n",
- proc);
- return (-1);
- }
-
- for (c = 0; c < IDN_MAX_NETS; c++) {
- idn_chansvr_t *csp;
- idn_mboxhdr_t *mainhp;
- struct idn *sip;
-
- if (!CHAN_IN_SET(chanset, c))
- continue;
- csp = &idn.chan_servers[c];
-
- if (chanop == IDNCHAN_ONLINE) {
- IDN_CHAN_LOCK_GLOBAL(csp);
- } else {
- /*
- * We don't wait to grab the global lock
- * if IDNCHAN_OPEN since these occur along
- * critical data paths and will be retried
- * anyway if needed.
- */
- if (IDN_CHAN_TRYLOCK_GLOBAL(csp) == 0) {
- PR_CHAN("%s: failed to acquire global "
- "lock for channel %d\n",
- proc, c);
- continue;
- }
- }
-
- if (!IDN_CHANNEL_IS_ATTACHED(csp)) {
- PR_CHAN("%s: channel %d NOT open\n", proc, c);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- continue;
-
- }
-
- if (IDN_CHANNEL_IS_ACTIVE(csp)) {
-
- PR_CHAN("%s: channel %d already active\n", proc, c);
- rv++;
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- continue;
-
- }
- /*
- * Channel activation can happen asynchronously.
- */
- IDN_CHANNEL_SUSPEND(c, 0);
-
- if (IDN_CHANNEL_IS_PENDING(csp) && (chanop == IDNCHAN_OPEN)) {
-
- PR_CHAN("%s: ACTIVATING channel %d\n", proc, c);
-
- if (idn_activate_channel_services(c) >= 0) {
- PR_CHAN("%s: Setting channel %d ACTIVE\n",
- proc, c);
- IDN_CHANSVC_MARK_ACTIVE(csp);
- rv++;
- }
- } else if (!IDN_CHANNEL_IS_PENDING(csp) &&
- (chanop == IDNCHAN_ONLINE)) {
- PR_CHAN("%s: Setting channel %d PENDING\n", proc, c);
-
- IDN_CHANSVC_MARK_PENDING(csp);
- }
- /*
- * Don't syncheader (i.e. touch SMR) unless
- * channel is at least ENABLED. For a DISABLED
- * channel, the SMR may be invalid so do NOT
- * touch it.
- */
- if (IDN_CHANNEL_IS_ENABLED(csp) &&
- ((mainhp = idn_chan_server_syncheader(c)) != NULL)) {
- PR_CHAN("%s: marking chansvr (mhp=0x%p) %d READY\n",
- proc, (void *)mainhp, c);
- mainhp->mh_svr_ready = 1;
- }
-
- IDN_CHANNEL_RESUME(c);
- sip = IDN_INST2SIP(c);
- ASSERT(sip);
- if (sip->si_wantw) {
- mutex_enter(&idn.sipwenlock);
- idndl_wenable(sip);
- mutex_exit(&idn.sipwenlock);
- }
- IDN_CHAN_UNLOCK_GLOBAL(csp);
-
- }
- /*
- * Returns "not active", i.e. value of 0 indicates
- * no channels are activated.
- */
- return (rv == 0);
-}
-
-static void
-idn_deactivate_channel(idn_chanset_t chanset, idn_chanop_t chanop)
-{
- int c;
- procname_t proc = "idn_deactivate_channel";
-
- PR_CHAN("%s: chanset = 0x%x, chanop = %s\n",
- proc, chanset, chanop_str[chanop]);
-
- for (c = 0; c < IDN_MAX_NETS; c++) {
- idn_chansvr_t *csp;
- idn_mboxhdr_t *mainhp;
-
- if (!CHAN_IN_SET(chanset, c))
- continue;
-
- csp = &idn.chan_servers[c];
-
- IDN_CHAN_LOCK_GLOBAL(csp);
-
- if (((chanop == IDNCHAN_SOFT_CLOSE) &&
- !IDN_CHANNEL_IS_ACTIVE(csp)) ||
- ((chanop == IDNCHAN_HARD_CLOSE) &&
- IDN_CHANNEL_IS_DETACHED(csp)) ||
- ((chanop == IDNCHAN_OFFLINE) &&
- !IDN_CHANNEL_IS_ENABLED(csp))) {
-
- ASSERT(!IDN_CHANNEL_IS_RECV_ACTIVE(csp));
- ASSERT(!IDN_CHANNEL_IS_SEND_ACTIVE(csp));
-
- PR_CHAN("%s: channel %d already deactivated\n",
- proc, c);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- continue;
- }
-
- switch (chanop) {
- case IDNCHAN_OFFLINE:
- IDN_CHANSVC_MARK_IDLE(csp);
- IDN_CHANSVC_MARK_DISABLED(csp);
- IDN_CHANNEL_STOP(c, 1);
- mainhp = idn_chan_server_syncheader(c);
- if (mainhp != NULL)
- mainhp->mh_svr_ready = 0;
- break;
-
- case IDNCHAN_HARD_CLOSE:
- IDN_CHANSVC_MARK_DETACHED(csp);
- IDN_CHANNEL_DETACH(c, 1);
- mainhp = idn_chan_server_syncheader(c);
- if (mainhp != NULL)
- mainhp->mh_svr_ready = 0;
- break;
-
- default:
- IDN_CHANSVC_MARK_IDLE(csp);
- IDN_CHANNEL_SUSPEND(c, 1);
- ASSERT(IDN_CHANNEL_IS_ATTACHED(csp));
- break;
- }
-
- lock_clear(&csp->ch_actvlck);
- lock_clear(&csp->ch_initlck);
-
- PR_CHAN("%s: DEACTIVATING channel %d (%s)\n", proc, c,
- chanop_str[chanop]);
- PR_CHAN("%s: removing chanset 0x%x data svrs for "
- "each domain link\n", proc, chanset);
-
- (void) idn_deactivate_channel_services(c, chanop);
- }
- /*
- * Returns with channels unlocked.
- */
-}
-
-/*
- * The priority of the channel server must be less than that
- * of the protocol server since the protocol server tasks
- * are (can be) of more importance.
- *
- * Possible range: 60-99.
- */
-static pri_t idn_chansvr_pri = (7 * MAXCLSYSPRI) / 8;
-
-static int
-idn_activate_channel_services(int channel)
-{
- idn_chansvr_t *csp;
- procname_t proc = "idn_activate_channel_services";
-
-
- ASSERT((channel >= 0) && (channel < IDN_MAX_NETS));
-
- csp = &idn.chan_servers[channel];
-
- ASSERT(IDN_CHAN_GLOBAL_IS_LOCKED(csp));
- ASSERT(IDN_CHAN_LOCAL_IS_LOCKED(csp));
-
- if (csp->ch_recv_threadp) {
- /*
- * There's an existing dispatcher!
- * Must have been idle'd during an earlier
- * stint.
- */
- ASSERT(csp->ch_id == (uchar_t)channel);
- PR_CHAN("%s: existing chansvr FOUND for (c=%d)\n",
- proc, channel);
-
- if (IDN_CHANNEL_IS_PENDING(csp) == 0)
- return (-1);
-
- PR_CHAN("%s: chansvr (c=%d) Rstate = 0x%x, Sstate = 0x%x\n",
- proc, channel, csp->ch_recv.c_state,
- csp->ch_send.c_state);
-
- cv_signal(&csp->ch_recv_cv);
-
- return (0);
- }
-
- if (IDN_CHANNEL_IS_PENDING(csp) == 0)
- return (-1);
-
- csp->ch_id = (uchar_t)channel;
-
- PR_CHAN("%s: init channel %d server\n", proc, channel);
-
- csp->ch_recv_morguep = GETSTRUCT(ksema_t, 1);
- sema_init(csp->ch_recv_morguep, 0, NULL, SEMA_DRIVER, NULL);
-
- csp->ch_recv.c_inprogress = 0;
- csp->ch_recv.c_waiters = 0;
- csp->ch_recv.c_checkin = 0;
- csp->ch_recv_changed = 1;
-
- csp->ch_recv_domset = csp->ch_reg_domset;
-
- csp->ch_recv_waittime = IDN_NETSVR_WAIT_MIN;
-
- csp->ch_recv_threadp = thread_create(NULL, 0,
- idn_chan_server, &csp, sizeof (csp), &p0, TS_RUN, idn_chansvr_pri);
-
- csp->ch_send.c_inprogress = 0;
- csp->ch_send.c_waiters = 0;
- csp->ch_send.c_checkin = 0;
-
- return (0);
-}
-
-/*
- * This routine can handle terminating a set of channel
- * servers all at once, however currently only used
- * for serial killing, i.e. one-at-a-time.
- *
- * Entered with RECV locks held on chanset.
- * Acquires SEND locks if needed.
- * Leaves with all RECV and SEND locks dropped.
- */
-static int
-idn_deactivate_channel_services(int channel, idn_chanop_t chanop)
-{
- idn_chansvr_t *csp;
- int cs_count;
- int c;
- idn_chanset_t chanset;
- ksema_t *central_morguep = NULL;
- procname_t proc = "idn_deactivate_channel_services";
-
-
- ASSERT(idn.chan_servers);
-
- PR_CHAN("%s: deactivating channel %d services\n", proc, channel);
-
- /*
- * XXX
- * Old code allowed us to deactivate multiple channel
- * servers at once. Keep for now just in case.
- */
- chanset = CHANSET(channel);
-
- /*
- * Point all the data dispatchers to the same morgue
- * so we can kill them all at once.
- */
- cs_count = 0;
- for (c = 0; c < IDN_MAX_NETS; c++) {
- if (!CHAN_IN_SET(chanset, c))
- continue;
-
- csp = &idn.chan_servers[c];
- ASSERT(IDN_CHAN_GLOBAL_IS_LOCKED(csp));
- ASSERT(IDN_CHAN_LOCAL_IS_LOCKED(csp));
-
- if (csp->ch_recv_threadp == NULL) {
- /*
- * No channel server home.
- * But we're still holding the c_mutex.
- * At mark him idle incase we start him up.
- */
- PR_CHAN("%s: no channel server found for chan %d\n",
- proc, c);
- IDN_CHAN_UNLOCK_LOCAL(csp);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- continue;
- }
- ASSERT(csp->ch_id == (uchar_t)c);
-
- /*
- * Okay, now we've blocked the send and receive sides.
- */
-
- if ((chanop == IDNCHAN_SOFT_CLOSE) ||
- (chanop == IDNCHAN_OFFLINE)) {
- /*
- * We set turned off the ACTIVE flag, but there's
- * no guarantee he stopped because of it. He may
- * have already been sleeping. We need to be
- * sure he recognizes the IDLE, so we need to
- * signal him and give him a chance to see it.
- */
- cv_signal(&csp->ch_recv_cv);
- IDN_CHAN_UNLOCK_LOCAL(csp);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- cs_count++;
- continue;
- }
-
- PR_CHAN("%s: pointing chansvr %d to morgue (0x%p)\n",
- proc, c, central_morguep ? (void *)central_morguep
- : (void *)(csp->ch_recv_morguep));
-
- if (central_morguep == NULL) {
- central_morguep = csp->ch_recv_morguep;
- } else {
- sema_destroy(csp->ch_recv_morguep);
- FREESTRUCT(csp->ch_recv_morguep, ksema_t, 1);
-
- csp->ch_recv_morguep = central_morguep;
- }
- cv_signal(&csp->ch_recv_cv);
- if (csp->ch_recv.c_waiters > 0)
- cv_broadcast(&csp->ch_recv.c_cv);
- /*
- * Save any existing binding for next reincarnation.
- * Note that we're holding the local and global
- * locks so we're protected against others touchers
- * of the ch_bound_cpuid fields.
- */
- csp->ch_bound_cpuid_pending = csp->ch_bound_cpuid;
- csp->ch_bound_cpuid = -1;
- IDN_CHAN_UNLOCK_LOCAL(csp);
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- cs_count++;
- }
- PR_CHAN("%s: signaled %d chansvrs for chanset 0x%x\n",
- proc, cs_count, chanset);
-
- if ((chanop == IDNCHAN_SOFT_CLOSE) || (chanop == IDNCHAN_OFFLINE))
- return (cs_count);
-
- PR_CHAN("%s: waiting for %d (chnset=0x%x) chan svrs to term\n",
- proc, cs_count, chanset);
- PR_CHAN("%s: morguep = 0x%p\n", proc, (void *)central_morguep);
-
- ASSERT((cs_count > 0) ? (central_morguep != NULL) : 1);
- while (cs_count-- > 0)
- sema_p(central_morguep);
-
- if (central_morguep) {
- sema_destroy(central_morguep);
- FREESTRUCT(central_morguep, ksema_t, 1);
- }
-
- return (cs_count);
-}
-
-int
-idn_chanservers_init()
-{
- int c;
- idn_chansvr_t *csp;
-
-
- if (idn.chan_servers)
- return (0);
-
- idn.chan_servers = GETSTRUCT(idn_chansvr_t, IDN_MAXMAX_NETS);
-
- for (c = 0; c < IDN_MAXMAX_NETS; c++) {
- csp = &idn.chan_servers[c];
- mutex_init(&csp->ch_send.c_mutex, NULL, MUTEX_DEFAULT, NULL);
- mutex_init(&csp->ch_recv.c_mutex, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&csp->ch_send.c_cv, NULL, CV_DRIVER, NULL);
- cv_init(&csp->ch_recv.c_cv, NULL, CV_DRIVER, NULL);
- cv_init(&csp->ch_recv_cv, NULL, CV_DRIVER, NULL);
- csp->ch_bound_cpuid = -1;
- csp->ch_bound_cpuid_pending = -1;
- }
-
- return (c);
-}
-
-void
-idn_chanservers_deinit()
-{
- int c;
- idn_chansvr_t *csp;
-
-
- if (idn.chan_servers == NULL)
- return;
-
- for (c = 0; c < IDN_MAXMAX_NETS; c++) {
- csp = &idn.chan_servers[c];
-
- mutex_destroy(&csp->ch_send.c_mutex);
- mutex_destroy(&csp->ch_recv.c_mutex);
- cv_destroy(&csp->ch_send.c_cv);
- cv_destroy(&csp->ch_recv.c_cv);
- cv_destroy(&csp->ch_recv_cv);
- }
-
- FREESTRUCT(idn.chan_servers, idn_chansvr_t, IDN_MAXMAX_NETS);
- idn.chan_servers = NULL;
-}
-
-static void
-idn_exec_chanactivate(void *chn)
-{
- int not_active, channel;
- idn_chansvr_t *csp;
-
- channel = (int)(uintptr_t)chn;
-
- IDN_GLOCK_SHARED();
- if (idn.chan_servers == NULL) {
- IDN_GUNLOCK();
- return;
- }
- csp = &idn.chan_servers[channel];
-
- if (IDN_CHAN_TRYLOCK_GLOBAL(csp) == 0) {
- /*
- * If we can't grab the global lock, then
- * something is up, skip out.
- */
- IDN_GUNLOCK();
- return;
- }
- IDN_GUNLOCK();
-
- if (IDN_CHANNEL_IS_PENDING(csp) && lock_try(&csp->ch_actvlck)) {
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- not_active = idn_activate_channel(CHANSET(channel),
- IDNCHAN_OPEN);
- if (not_active)
- lock_clear(&csp->ch_actvlck);
- } else {
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- }
-}
-
-/*
- * Delayed activation of channel. We don't want to do this within
- * idn_signal_data_server() since that's called within the context
- * of an XDC handler so we submit it as a timeout() call to be short
- * as soon as possible.
- * The ch_initlck & ch_actvlck are used to synchronize activation
- * of the channel so that we don't have multiple idn_activate_channel's
- * attempting to activate the same channel.
- */
-static void
-idn_submit_chanactivate_job(int channel)
-{
- idn_chansvr_t *csp;
-
- if (idn.chan_servers == NULL)
- return;
- csp = &idn.chan_servers[channel];
-
- if (lock_try(&csp->ch_initlck) == 0)
- return;
-
- (void) timeout(idn_exec_chanactivate, (caddr_t)(uintptr_t)channel, 1);
-}
-
-/*ARGSUSED0*/
-static void
-idn_xmit_monitor(void *unused)
-{
- int c, d;
- idn_chansvr_t *csp;
- idn_chanset_t wake_set;
- domainset_t conset;
- smr_slab_t *sp;
- procname_t proc = "idn_xmit_monitor";
-
- CHANSET_ZERO(wake_set);
-
- mutex_enter(&idn.xmit_lock);
- if ((idn.xmit_tid == NULL) || !idn.xmit_chanset_wanted) {
- idn.xmit_tid = NULL;
- mutex_exit(&idn.xmit_lock);
- PR_XMON("%s: bailing out\n", proc);
- return;
- }
-
- /*
- * No point in transmitting unless state
- * is ONLINE.
- */
- if (idn.state != IDNGS_ONLINE)
- goto retry;
-
- conset = idn.domset.ds_connected;
-
- /*
- * Try and reclaim some buffers if possible.
- */
- for (d = 0; d < MAX_DOMAINS; d++) {
- if (!DOMAIN_IN_SET(conset, d))
- continue;
-
- if (!IDN_DLOCK_TRY_SHARED(d))
- continue;
-
- if (idn_domain[d].dcpu != IDN_NIL_DCPU)
- (void) idn_reclaim_mboxdata(d, 0, -1);
-
- IDN_DUNLOCK(d);
- }
-
- /*
- * Now check if we were successful in getting
- * any buffers.
- */
- DSLAB_LOCK_SHARED(idn.localid);
- sp = idn_domain[idn.localid].dslab;
- for (; sp; sp = sp->sl_next)
- if (sp->sl_free)
- break;
- DSLAB_UNLOCK(idn.localid);
-
- /*
- * If there are no buffers available,
- * no point in reenabling the queues.
- */
- if (sp == NULL)
- goto retry;
-
- CHANSET_ZERO(wake_set);
- for (c = 0; c < IDN_MAX_NETS; c++) {
- int pending_bits;
- struct idn *sip;
-
- if (!CHAN_IN_SET(idn.xmit_chanset_wanted, c))
- continue;
-
- csp = &idn.chan_servers[c];
- if (!IDN_CHAN_TRYLOCK_GLOBAL(csp))
- continue;
-
- pending_bits = csp->ch_state & IDN_CHANSVC_PENDING_BITS;
-
- sip = IDN_INST2SIP(c);
-
- if (!csp->ch_send.c_checkin &&
- (pending_bits == IDN_CHANSVC_PENDING_BITS) &&
- sip && (sip->si_flags & IDNRUNNING)) {
-
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- CHANSET_ADD(wake_set, c);
-
- PR_XMON("%s: QENABLE for channel %d\n", proc, c);
-
- rw_enter(&idn.struprwlock, RW_READER);
- mutex_enter(&idn.sipwenlock);
- idndl_wenable(sip);
- mutex_exit(&idn.sipwenlock);
- rw_exit(&idn.struprwlock);
- } else {
- IDN_CHAN_UNLOCK_GLOBAL(csp);
- }
- }
-
- /*
- * Clear the channels we enabled.
- */
- idn.xmit_chanset_wanted &= ~wake_set;
-
-retry:
-
- if (idn.xmit_chanset_wanted == 0)
- idn.xmit_tid = NULL;
- else
- idn.xmit_tid = timeout(idn_xmit_monitor, NULL,
- idn_xmit_monitor_freq);
-
- mutex_exit(&idn.xmit_lock);
-}
-
-void
-idn_xmit_monitor_kickoff(int chan_wanted)
-{
- procname_t proc = "idn_xmit_monitor_kickoff";
-
- mutex_enter(&idn.xmit_lock);
-
- if (chan_wanted < 0) {
- /*
- * Wants all channels.
- */
- idn.xmit_chanset_wanted = CHANSET_ALL;
- } else {
- CHANSET_ADD(idn.xmit_chanset_wanted, chan_wanted);
- }
-
- if (idn.xmit_tid != (timeout_id_t)NULL) {
- /*
- * A monitor is already running, so
- * he will catch the new "wants" when
- * he comes around.
- */
- mutex_exit(&idn.xmit_lock);
- return;
- }
-
- PR_XMON("%s: xmit_mon kicked OFF (chanset = 0x%x)\n",
- proc, idn.xmit_chanset_wanted);
-
- idn.xmit_tid = timeout(idn_xmit_monitor, NULL, idn_xmit_monitor_freq);
-
- mutex_exit(&idn.xmit_lock);
-}
diff --git a/usr/src/uts/sun4u/starfire/io/idn_smr.c b/usr/src/uts/sun4u/starfire/io/idn_smr.c
deleted file mode 100644
index be520d731c..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn_smr.c
+++ /dev/null
@@ -1,2178 +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) 2016 by Delphix. All rights reserved.
- *
- * Inter-Domain Network
- *
- * Shared Memory Region (SMR) supporting code.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/machparam.h>
-#include <sys/debug.h>
-#include <sys/cpuvar.h>
-#include <sys/kmem.h>
-#include <sys/mutex.h>
-#include <sys/rwlock.h>
-#include <sys/systm.h>
-#include <sys/machlock.h>
-#include <sys/membar.h>
-#include <sys/mman.h>
-#include <vm/hat.h>
-#include <vm/as.h>
-#include <vm/hat_sfmmu.h>
-#include <sys/vm_machparam.h>
-#include <sys/x_call.h>
-
-#include <sys/idn.h>
-
-#ifdef DEBUG
-#define DIOCHECK(domid) \
-{ \
- int _dio; \
- if ((_dio = idn_domain[domid].dio) < 0) { \
- cmn_err(CE_WARN, \
- ">>>>> file %s, line %d: domain %d, dio = %d", \
- __FILE__, __LINE__, (domid), _dio); \
- } \
-}
-#else
-#define DIOCHECK(domid)
-#endif /* DEBUG */
-
-static int smr_slab_alloc_local(int domid, smr_slab_t **spp);
-static int smr_slab_alloc_remote(int domid, smr_slab_t **spp);
-static void smr_slab_free_local(int domid, smr_slab_t *sp);
-static void smr_slab_free_remote(int domid, smr_slab_t *sp);
-static int smr_slabwaiter_register(int domid);
-static int smr_slabwaiter_unregister(int domid, smr_slab_t **spp);
-static int smr_slaballoc_wait(int domid, smr_slab_t **spp);
-static smr_slab_t *smr_slab_reserve(int domid);
-static void smr_slab_unreserve(int domid, smr_slab_t *sp);
-static void smr_slab_reap_global();
-
-/*
- * Can only be called by the master. Allocate a slab from the
- * local pool representing the SMR, on behalf of the given
- * domain. Slab is either being requested for use by the
- * local domain (i.e. domid == idn.localid), or it's being
- * allocated to give to a remote domain which requested one.
- * In the base of allocating on behalf of a remote domain,
- * smr_slab_t structure is used simply to manage ownership.
- *
- * Returns: smr_slaballoc_wait
- * (EINVAL, ETIMEDOUT)
- * smr_slabwatier_unregister
- * (0, EINVAL, EBUSY, ENOMEM)
- * ENOLCK
- */
-static int
-smr_slab_alloc_local(int domid, smr_slab_t **spp)
-{
- int serrno = 0;
- int nwait;
- smr_slab_t *sp;
- idn_domain_t *dp;
-
-
- /*
- * Only the master can make local allocations.
- */
- ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID);
- ASSERT(idn.localid == IDN_GET_MASTERID());
-
- *spp = NULL;
-
- dp = &idn_domain[domid];
- ASSERT(DSLAB_READ_HELD(domid));
- ASSERT(dp->dslab_state == DSLAB_STATE_LOCAL);
-
- /*
- * Register myself with the waiting list.
- */
- nwait = smr_slabwaiter_register(domid);
-
- if (nwait > 1) {
- /*
- * XXX - old comment?
- * Need to drop the read lock _after_ registering
- * ourselves with the potential wait list for this allocation.
- * Although this allocation is not a remote one, we could
- * still have multiple threads on the master trying to
- * satisfy (allocate) request on behalf of a remote domain.
- */
- /*
- * Somebody is already in the process of satisfying
- * the allocation request for this respective
- * domain. All we need to do is wait and let
- * it happen.
- */
- serrno = smr_slaballoc_wait(domid, spp);
- return (serrno);
- }
- /*
- * I'm the original slab requester for this domain. It's local
- * so go ahead and do the job.
- */
-
- if ((sp = smr_slab_reserve(domid)) == NULL)
- serrno = ENOMEM;
-
- /*
- * Allocation may have failed. In either case we've
- * got to do the put to at least wake potential waiters up.
- */
- if (!serrno) {
- if (DSLAB_LOCK_TRYUPGRADE(domid) == 0) {
- DSLAB_UNLOCK(domid);
- DSLAB_LOCK_EXCL(domid);
- }
- }
-
- (void) smr_slaballoc_put(domid, sp, 0, serrno);
-
- /*
- * If serrno is ENOLCK here, then we must have failed
- * on the upgrade above, so lock already dropped.
- */
- if (serrno != ENOLCK) {
- /*
- * Need to drop since reaping may be recursive?
- */
- DSLAB_UNLOCK(domid);
- }
-
- /*
- * Since we were the original requester but never went
- * to sleep, we need to directly unregister ourselves
- * from the waiting list.
- */
- serrno = smr_slabwaiter_unregister(domid, spp);
-
- /*
- * Now that we've satisfied the request, let's check if any
- * reaping is necessary. Only the master does this and only
- * when allocating slabs, an infrequent event :-o
- */
- smr_slab_reap_global();
-
- ASSERT((serrno == 0) ? (*spp != NULL) : (*spp == NULL));
-
- DSLAB_LOCK_SHARED(domid);
-
- return (serrno);
-}
-
-/*
- * Can only be called by a slave on behalf of himself. Need to
- * make a request to the master to allocate a slab of SMR buffers
- * for the local domain.
- *
- * Returns: smr_slaballoc_wait
- * (0, EINVAL, EBUSY, ENOMEM)
- * ENOLCK
- * ECANCELED
- */
-static int
-smr_slab_alloc_remote(int domid, smr_slab_t **spp)
-{
- int nwait;
- int serrno = 0;
- int bailout = 0;
- int masterid;
- idn_domain_t *dp, *mdp = NULL;
- procname_t proc = "smr_slab_alloc_remote";
-
- /*
- * Only slaves make remote allocations.
- */
- ASSERT(idn.localid != IDN_GET_MASTERID());
- ASSERT(domid == idn.localid);
- ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID);
-
- *spp = NULL;
-
- dp = &idn_domain[domid];
- ASSERT(DSLAB_READ_HELD(domid));
- ASSERT(dp->dslab_state == DSLAB_STATE_REMOTE);
-
- /*
- * Register myself with the slaballoc waiting list.
- * Note that only allow one outstanding allocation
- * request for the given domain. Other callers which
- * detect a slab is needed simply get stuck on the
- * waiting list waiting for the original caller to
- * get the job done.
- * The waiter_register routine will allocate the necessary
- * slab structure which will ultimately be inserted in
- * the domain's slab list via smr_slaballoc_put().
- */
- nwait = smr_slabwaiter_register(domid);
-
- /*
- * Make sure we have a connection with the master
- * before we wait around for nothing and send a
- * command off to nowhere.
- * First do a quick (no lock) check for global okayness.
- */
- if ((idn.state != IDNGS_ONLINE) ||
- ((masterid = IDN_GET_MASTERID()) == IDN_NIL_DOMID)) {
- bailout = 1;
- serrno = ECANCELED;
- }
- /*
- * We need to drop our read lock _before_ acquiring the
- * slaballoc waiter lock. This is necessary because the
- * thread that receives the slab alloc response and fills
- * in the slab structure will need to grab the domain write
- * lock while holding onto the slaballoc waiter lock.
- * Potentially could deadlock if we didn't drop our domain
- * lock before. Plus, we've registered.
- *
- * 4093209 - Note also that we do this _after_ the check for
- * idn.masterid where we grab the READER global
- * lock. This is to prevent somebody from
- * changing our state after we drop the drwlock.
- * A deadlock can occur when shutting down a
- * domain we're holding the
- */
-
- if (!bailout) {
- mdp = &idn_domain[masterid];
- /*
- * Global state is okay. Let's double check the
- * state of our actual target domain.
- */
- if (mdp->dstate != IDNDS_CONNECTED) {
- bailout = 1;
- serrno = ECANCELED;
- } else if (IDN_DLOCK_TRY_SHARED(masterid)) {
- if (mdp->dstate != IDNDS_CONNECTED) {
- bailout = 1;
- serrno = ECANCELED;
- IDN_DUNLOCK(masterid);
- } else if (nwait != 1) {
- IDN_DUNLOCK(masterid);
- }
- /*
- * Note that keep the drwlock(read) for
- * the target (master) domain if it appears
- * we're the lucky one to send the command.
- * We hold onto the lock until we've actually
- * sent the command out.
- * We don't reach this place unless it
- * appears everything is kosher with
- * the target (master) domain.
- */
- } else {
- bailout = 1;
- serrno = ENOLCK;
- }
- }
-
- if (bailout) {
- ASSERT(serrno);
- /*
- * Gotta bail. Abort operation. Error result
- * will be picked up when we attempt to wait.
- */
- PR_SMR("%s: BAILING OUT on behalf domain %d "
- "(err=%d, gs=%s, ms=%s)\n",
- proc, domid, serrno, idngs_str[idn.state],
- (masterid == IDN_NIL_DOMID)
- ? "unknown" : idnds_str[idn_domain[masterid].dstate]);
- (void) smr_slabwaiter_abort(domid, serrno);
-
- } else if (nwait == 1) {
- /*
- * We are the original requester. Initiate the
- * actual request to the master.
- */
- idn_send_cmd(masterid, IDNCMD_SLABALLOC, IDN_SLAB_SIZE, 0, 0);
- ASSERT(mdp);
- IDN_DUNLOCK(masterid);
- }
-
- /*
- * Wait here for response. Once awakened func returns
- * with slab structure possibly filled with gifts!
- */
- serrno = smr_slaballoc_wait(domid, spp);
-
- return (serrno);
-}
-
-/*
- * Allocate a slab from the Master on behalf
- * of the given domain. Note that master uses
- * this function to allocate slabs on behalf of
- * remote domains also.
- * Entered with drwlock held.
- * Leaves with drwlock dropped.
- * Returns: EDQUOT
- * EINVAL
- * ENOLCK
- * smr_slab_alloc_local
- * smr_slab_alloc_remote
- * (0, EINVAL, EBUSY, ENOMEM)
- */
-int
-smr_slab_alloc(int domid, smr_slab_t **spp)
-{
- int serrno = 0;
- idn_domain_t *dp;
- procname_t proc = "smr_slab_alloc";
-
-
- dp = &idn_domain[domid];
-
- ASSERT(DSLAB_READ_HELD(domid));
- ASSERT(dp->dslab_state != DSLAB_STATE_UNKNOWN);
-
- *spp = NULL;
-
- switch (dp->dslab_state) {
- case DSLAB_STATE_UNKNOWN:
- cmn_err(CE_WARN,
- "IDN: 300: no slab allocations without a master");
- serrno = EINVAL;
- break;
-
- case DSLAB_STATE_LOCAL:
- /*
- * If I'm the master, then get a slab
- * from the local SMR pool, but only
- * if the number of allocated slabs has
- * not been exceeded.
- */
- if (((int)dp->dnslabs < IDN_SLAB_MAXPERDOMAIN) ||
- !IDN_SLAB_MAXPERDOMAIN)
- serrno = smr_slab_alloc_local(domid, spp);
- else
- serrno = EDQUOT;
- break;
-
- case DSLAB_STATE_REMOTE:
- /*
- * Have to make a remote request.
- * In order to prevent overwhelming the master
- * with a bunch of requests that it won't be able
- * to handle we do a check to see if we're still
- * under quota. Note that the limit is known
- * apriori based on the SMR/NWR size and
- * IDN_SLAB_MINTOTAL. Domains must have the same
- * size SMR/NWR, however they can have different
- * IDN_SLAB_MINTOTAL. Thus a domain could throttle
- * itself however it wishes.
- */
- if (((int)dp->dnslabs < IDN_SLAB_MAXPERDOMAIN) ||
- !IDN_SLAB_MAXPERDOMAIN)
- serrno = smr_slab_alloc_remote(domid, spp);
- else
- serrno = EDQUOT;
- break;
-
- default:
- cmn_err(CE_WARN,
- "IDN: 301: (ALLOC) unknown slab state (%d) "
- "for domain %d", dp->dslab_state, domid);
- serrno = EINVAL;
- break;
- }
-
- if (*spp == NULL) {
- PR_SMR("%s: failed to allocate %s slab [serrno = %d]\n",
- proc, (idn.localid == IDN_GET_MASTERID()) ?
- "local" : "remote", serrno);
- }
-
- if (serrno) {
- IDN_GKSTAT_GLOBAL_EVENT(gk_slabfail, gk_slabfail_last);
- }
-
- return (serrno);
-}
-
-static void
-smr_slab_free_local(int domid, smr_slab_t *sp)
-{
- int rv;
-
- /*
- * Do a slaballoc_put just in case there may have
- * been waiters for slabs for this respective domain
- * before we unreserve this slab.
- */
- rv = smr_slaballoc_put(domid, sp, 0, 0);
-
- if (rv == -1) {
- /*
- * Put failed. Must not have been any waiters.
- * Go ahead and unreserve the space.
- */
- smr_slab_unreserve(domid, sp);
- }
-}
-
-static void
-smr_slab_free_remote(int domid, smr_slab_t *sp)
-{
- smr_offset_t slab_offset;
- int slab_size;
- int rv;
- int masterid;
-
- ASSERT(domid == idn.localid);
- ASSERT(idn.localid != IDN_GET_MASTERID());
- ASSERT(DSLAB_WRITE_HELD(domid));
- ASSERT(idn_domain[domid].dslab_state == DSLAB_STATE_REMOTE);
-
- masterid = IDN_GET_MASTERID();
-
- ASSERT(masterid != IDN_NIL_DOMID);
-
- slab_offset = IDN_ADDR2OFFSET(sp->sl_start);
- slab_size = (int)(sp->sl_end - sp->sl_start);
-
- /*
- * Do a slaballoc_put just in case there may have
- * been waiters for slabs for this domain before
- * returning back to the master.
- */
- rv = smr_slaballoc_put(domid, sp, 0, 0);
-
- if ((rv == -1) && (masterid != IDN_NIL_DOMID)) {
- /*
- * Put failed. No waiters so free the local data
- * structure ship the SMR range off to the master.
- */
- smr_free_buflist(sp);
- FREESTRUCT(sp, smr_slab_t, 1);
-
- IDN_DLOCK_SHARED(masterid);
- idn_send_cmd(masterid, IDNCMD_SLABFREE, slab_offset, slab_size,
- 0);
- IDN_DUNLOCK(masterid);
- }
-}
-
-/*
- * Free up the list of slabs passed
- */
-void
-smr_slab_free(int domid, smr_slab_t *sp)
-{
- smr_slab_t *nsp = NULL;
-
- ASSERT(DSLAB_WRITE_HELD(domid));
-
- if (sp == NULL)
- return;
-
- ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID);
-
- switch (idn_domain[domid].dslab_state) {
- case DSLAB_STATE_UNKNOWN:
- cmn_err(CE_WARN, "IDN: 302: no slab free without a master");
- break;
-
- case DSLAB_STATE_LOCAL:
- /*
- * If I'm the master then put the slabs
- * back to the local SMR pool.
- */
- for (; sp; sp = nsp) {
- nsp = sp->sl_next;
- smr_slab_free_local(domid, sp);
- }
- break;
-
- case DSLAB_STATE_REMOTE:
- /*
- * If the domid is my own then I'm freeing
- * a slab back to the Master.
- */
- for (; sp; sp = nsp) {
- nsp = sp->sl_next;
- smr_slab_free_remote(domid, sp);
- }
- break;
-
- default:
- cmn_err(CE_WARN,
- "IDN: 301: (FREE) unknown slab state (%d) for domain %d",
- idn_domain[domid].dslab_state, domid);
- break;
- }
-}
-
-/*
- * Free up the list of slab data structures ONLY.
- * This is called during a fatal shutdown of the master
- * where we need to garbage collect the locally allocated
- * data structures used to manage slabs allocated to the
- * local domain. Should never be called by a master since
- * the master can do a regular smr_slab_free.
- */
-void
-smr_slab_garbage_collection(smr_slab_t *sp)
-{
- smr_slab_t *nsp;
-
- ASSERT(idn_domain[idn.localid].dvote.v.master == 0);
-
- if (sp == NULL)
- return;
- /*
- * Since this is only ever called by a slave,
- * the slab structure size always contains a buflist.
- */
- for (; sp; sp = nsp) {
- nsp = sp->sl_next;
- smr_free_buflist(sp);
- FREESTRUCT(sp, smr_slab_t, 1);
- }
-}
-
-/*
- * Allocate a SMR buffer on behalf of the local domain
- * which is ultimately targeted for the given domain.
- *
- * IMPORTANT: This routine is going to drop the domain rwlock (drwlock)
- * for the domain on whose behalf the request is being
- * made. This routine canNOT block on trying to
- * reacquire the drwlock. If it does block then somebody
- * must have the write lock on the domain which most likely
- * means the domain is going south anyway, so just bail on
- * this buffer. Higher levels will retry if needed.
- *
- * XXX - Support larger than IDN_SMR_BUFSIZE allocations?
- *
- * Returns: A negative return value indicates lock lost on domid.
- * EINVAL, ENOLINK, ENOLCK(internal)
- * smr_slaballoc_wait
- * (EINVAL, ETIMEDOUT)
- * smr_slabwatier_unregister
- * (0, EINVAL, EBUSY, ENOMEM)
- */
-int
-smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp)
-{
- register idn_domain_t *dp, *ldp;
- smr_slab_t *sp;
- caddr_t bufp = NULL;
- int serrno;
- procname_t proc = "smr_buf_alloc";
-
- dp = &idn_domain[domid];
- /*
- * Local domain can only allocate on behalf of
- * itself if this is a priviledged call and the
- * caller is the master.
- */
- ASSERT((domid != idn.localid) && (domid != IDN_NIL_DOMID));
-
- *bufpp = NULL;
-
- if (len > IDN_DATA_SIZE) {
- cmn_err(CE_WARN,
- "IDN: 303: buffer len %d > IDN_DATA_SIZE (%lu)",
- len, IDN_DATA_SIZE);
- IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, gk_buffail_last);
- return (EINVAL);
- }
-
- /*
- * Need to go to my local slab list to find
- * a buffer.
- */
- ldp = &idn_domain[idn.localid];
- /*
- * Now we loop trying to locate a buffer out of our
- * slabs. We continue this until either we find a
- * buffer or we're unable to allocate a slab. Note
- * that new slabs are allocated to the front.
- */
- DSLAB_LOCK_SHARED(idn.localid);
- sp = ldp->dslab;
- do {
- int spl, all_empty;
-
- if (sp == NULL) {
- if ((serrno = smr_slab_alloc(idn.localid, &sp)) != 0) {
- PR_SMR("%s:%d: failed to allocate "
- "slab [serrno = %d]",
- proc, domid, serrno);
- DSLAB_UNLOCK(idn.localid);
- IDN_GKSTAT_GLOBAL_EVENT(gk_buffail,
- gk_buffail_last);
- return (serrno);
- }
- /*
- * Of course, the world may have changed while
- * we dropped the lock. Better make sure we're
- * still established.
- */
- if (dp->dstate != IDNDS_CONNECTED) {
- PR_SMR("%s:%d: state changed during slab "
- "alloc (dstate = %s)\n",
- proc, domid, idnds_str[dp->dstate]);
- DSLAB_UNLOCK(idn.localid);
- IDN_GKSTAT_GLOBAL_EVENT(gk_buffail,
- gk_buffail_last);
- return (ENOLINK);
- }
- /*
- * We were able to allocate a slab. Should
- * be at the front of the list, spin again.
- */
- sp = ldp->dslab;
- }
- /*
- * If we have reached here then we have a slab!
- * Hopefully there are free bufs there :-o
- */
- spl = splhi();
- all_empty = 1;
- for (; sp && !bufp; sp = sp->sl_next) {
- smr_slabbuf_t *bp;
-
- if (sp->sl_free == NULL)
- continue;
-
- if (!lock_try(&sp->sl_lock)) {
- all_empty = 0;
- continue;
- }
-
- if ((bp = sp->sl_free) == NULL) {
- lock_clear(&sp->sl_lock);
- continue;
- }
-
- sp->sl_free = bp->sb_next;
- bp->sb_next = sp->sl_inuse;
- sp->sl_inuse = bp;
- /*
- * Found a free buffer.
- */
- bp->sb_domid = domid;
- bufp = bp->sb_bufp;
- lock_clear(&sp->sl_lock);
- }
- splx(spl);
-
- if (!all_empty && !bufp) {
- /*
- * If we still haven't found a buffer, but
- * there's still possibly a buffer available,
- * then try again. Only if we're absolutely
- * sure all slabs are empty do we attempt
- * to allocate a new one.
- */
- sp = ldp->dslab;
- }
- } while (bufp == NULL);
-
- *bufpp = bufp;
-
- ATOMIC_INC(dp->dio);
-
- DSLAB_UNLOCK(idn.localid);
-
- return (0);
-}
-
-/*
- * Free a buffer allocated to the local domain back to
- * its respective slab. Slabs are freed via the slab-reap command.
- * XXX - Support larger than IDN_SMR_BUFSIZE allocations?
- */
-int
-smr_buf_free(int domid, caddr_t bufp, uint_t len)
-{
- register smr_slab_t *sp;
- smr_slabbuf_t *bp, **bpp;
- idn_domain_t *ldp;
- int buffreed;
- int lockheld = (len == (uint_t)-1);
-
- /*
- * We should never be free'ing a buffer on
- * behalf of ourselves as we are never the
- * target for allocated SMR buffers.
- */
- ASSERT(domid != idn.localid);
-
- sp = NULL;
- buffreed = 0;
- ldp = &idn_domain[idn.localid];
-
- DSLAB_LOCK_SHARED(idn.localid);
-
- if (((uintptr_t)bufp & (IDN_SMR_BUFSIZE-1)) &&
- (IDN_ADDR2OFFSET(bufp) % IDN_SMR_BUFSIZE)) {
- cmn_err(CE_WARN,
- "IDN: 304: buffer (0x%p) from domain %d not on a "
- "%d boundary", (void *)bufp, domid, IDN_SMR_BUFSIZE);
- goto bfdone;
- }
- if (!lockheld && (len > IDN_DATA_SIZE)) {
- cmn_err(CE_WARN,
- "IDN: 305: buffer length (%d) from domain %d greater "
- "than IDN_DATA_SIZE (%lu)",
- len, domid, IDN_DATA_SIZE);
- goto bfdone;
- }
-
- for (sp = ldp->dslab; sp; sp = sp->sl_next)
- if ((bufp >= sp->sl_start) && (bufp < sp->sl_end))
- break;
-
- if (sp) {
- int spl;
-
- spl = splhi();
- while (!lock_try(&sp->sl_lock))
- ;
- bpp = &sp->sl_inuse;
- for (bp = *bpp; bp; bp = *bpp) {
- if (bp->sb_bufp == bufp)
- break;
- bpp = &bp->sb_next;
- }
- if (bp) {
- ASSERT(bp->sb_domid == domid);
- buffreed++;
- bp->sb_domid = IDN_NIL_DOMID;
- *bpp = bp->sb_next;
- bp->sb_next = sp->sl_free;
- sp->sl_free = bp;
- }
- lock_clear(&sp->sl_lock);
- splx(spl);
- }
-bfdone:
- if (buffreed) {
- ATOMIC_DEC(idn_domain[domid].dio);
- DIOCHECK(domid);
- } else {
- cmn_err(CE_WARN,
- "IDN: 306: unknown buffer (0x%p) from domain %d",
- (void *)bufp, domid);
- ATOMIC_INC(idn_domain[domid].dioerr);
- }
-
- DSLAB_UNLOCK(idn.localid);
-
- return (sp ? 0 : -1);
-}
-
-/*
- * Alternative interface to smr_buf_free, but with local drwlock
- * held.
- */
-/* ARGSUSED2 */
-int
-smr_buf_free_locked(int domid, caddr_t bufp, uint_t len)
-{
- return (smr_buf_free(domid, bufp, (uint_t)-1));
-}
-
-/*
- * Free any and all buffers associated with the given domain.
- * Assumption is that domain is dead and buffers are not in use.
- * Returns: Number of buffers freed.
- * -1 if error.
- */
-int
-smr_buf_free_all(int domid)
-{
- register smr_slab_t *sp;
- register smr_slabbuf_t *bp, **bpp;
- idn_domain_t *ldp;
- int nbufsfreed = 0;
- procname_t proc = "smr_buf_free_all";
-
- /*
- * We should never be free'ing buffers on
- * behalf of ourself
- */
- ASSERT(domid != idn.localid);
-
- if (!VALID_DOMAINID(domid)) {
- cmn_err(CE_WARN, "IDN: 307: domain ID (%d) invalid", domid);
- return (-1);
- }
-
- ldp = &idn_domain[idn.localid];
-
- /*
- * We grab the writer lock so that we don't have any
- * competition during a "free-all" call.
- * No need to grab individual slab locks when holding
- * dslab(writer).
- */
- DSLAB_LOCK_EXCL(idn.localid);
-
- for (sp = ldp->dslab; sp; sp = sp->sl_next) {
- bpp = &sp->sl_inuse;
- for (bp = *bpp; bp; bp = *bpp) {
- if (bp->sb_domid == domid) {
- bp->sb_domid = IDN_NIL_DOMID;
- *bpp = bp->sb_next;
- bp->sb_next = sp->sl_free;
- sp->sl_free = bp;
- nbufsfreed++;
- } else {
- bpp = &bp->sb_next;
- }
- }
- }
-
- if (nbufsfreed > 0) {
- ATOMIC_SUB(idn_domain[domid].dio, nbufsfreed);
- idn_domain[domid].dioerr = 0;
- DIOCHECK(domid);
- }
-
- DSLAB_UNLOCK(idn.localid);
-
- PR_SMR("%s: freed %d buffers for domain %d\n", proc, nbufsfreed, domid);
-
- return (nbufsfreed);
-}
-
-int
-smr_buf_reclaim(int domid, int nbufs)
-{
- int num_reclaimed = 0;
- idn_domain_t *ldp, *dp;
- procname_t proc = "smr_buf_reclaim";
-
- ldp = &idn_domain[idn.localid];
- dp = &idn_domain[domid];
-
- ASSERT(domid != idn.localid);
-
- if (ATOMIC_CAS(&dp->dreclaim_inprogress, 0, 1)) {
- /*
- * Reclaim is already in progress, don't
- * bother.
- */
- PR_DATA("%s: reclaim already in progress\n", proc);
- return (0);
- }
-
- PR_SMR("%s: requested %d buffers from domain %d\n", proc, nbufs, domid);
-
- if (dp->dio && nbufs) {
- register smr_slab_t *sp;
- int spl;
-
- DSLAB_LOCK_SHARED(idn.localid);
- spl = splhi();
- for (sp = ldp->dslab; sp && nbufs; sp = sp->sl_next) {
- register smr_slabbuf_t *bp, **bpp;
-
- if (sp->sl_inuse == NULL)
- continue;
-
- if (!lock_try(&sp->sl_lock))
- continue;
-
- if (sp->sl_inuse == NULL) {
- lock_clear(&sp->sl_lock);
- continue;
- }
-
- bpp = &sp->sl_inuse;
- for (bp = *bpp; bp && nbufs; bp = *bpp) {
- if (bp->sb_domid == domid) {
- /*
- * Buffer no longer in use,
- * reclaim it.
- */
- bp->sb_domid = IDN_NIL_DOMID;
- *bpp = bp->sb_next;
- bp->sb_next = sp->sl_free;
- sp->sl_free = bp;
- num_reclaimed++;
- nbufs--;
- } else {
- bpp = &bp->sb_next;
- }
- }
- lock_clear(&sp->sl_lock);
- }
- splx(spl);
-
- if (num_reclaimed > 0) {
- ATOMIC_SUB(dp->dio, num_reclaimed);
- DIOCHECK(domid);
- }
- DSLAB_UNLOCK(idn.localid);
- }
-
- PR_SMR("%s: reclaimed %d buffers from domain %d\n",
- proc, num_reclaimed, domid);
-
- return (num_reclaimed);
-}
-
-/*
- * Returns 1 If any buffers are locked for the given slab.
- * 0 If all buffers are free for the given slab.
- *
- * The caller is assumed to have the slab protected so that no
- * new allocations are attempted from it. Also, this is only
- * valid to be called with respect to slabs that were allocated
- * on behalf of the local domain, i.e. the master is not expected
- * to call this function with (slave) slab "representatives".
- */
-int
-smr_slab_busy(smr_slab_t *sp)
-{
- return ((sp && sp->sl_inuse) ? 1 : 0);
-}
-
-int
-smr_slabwaiter_init()
-{
- register int i;
- struct slabwaiter *wp;
-
- if (idn.slabwaiter != NULL)
- return (0);
-
- /*
- * Initialize the slab waiting area for MAX_DOMAINS.
- */
- idn.slabwaiter = GETSTRUCT(struct slabwaiter, MAX_DOMAINS);
- wp = idn.slabwaiter;
- for (i = 0; i < MAX_DOMAINS; wp++, i++) {
- wp->w_closed = 0;
- mutex_init(&wp->w_mutex, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&wp->w_cv, NULL, CV_DEFAULT, NULL);
- }
-
- return (0);
-}
-
-void
-smr_slabwaiter_deinit()
-{
- register int i;
- struct slabwaiter *wp;
-
- if ((wp = idn.slabwaiter) == NULL)
- return;
-
- for (i = 0; i < MAX_DOMAINS; wp++, i++) {
- ASSERT(wp->w_nwaiters == 0);
- ASSERT(wp->w_sp == NULL);
- cv_destroy(&wp->w_cv);
- mutex_destroy(&wp->w_mutex);
- }
-
- FREESTRUCT(idn.slabwaiter, struct slabwaiter, MAX_DOMAINS);
- idn.slabwaiter = NULL;
-}
-
-void
-smr_slabwaiter_open(domainset_t domset)
-{
- int d;
- struct slabwaiter *wp;
-
- if ((domset == 0) || !idn.slabwaiter)
- return;
-
- wp = idn.slabwaiter;
-
- for (d = 0; d < MAX_DOMAINS; wp++, d++) {
- if (!DOMAIN_IN_SET(domset, d))
- continue;
- mutex_enter(&wp->w_mutex);
- wp->w_closed = 0;
- mutex_exit(&wp->w_mutex);
- }
-}
-
-void
-smr_slabwaiter_close(domainset_t domset)
-{
- int d;
- struct slabwaiter *wp;
-
- if ((domset == 0) || !idn.slabwaiter)
- return;
-
- wp = idn.slabwaiter;
-
- for (d = 0; d < MAX_DOMAINS; wp++, d++) {
- if (!DOMAIN_IN_SET(domset, d))
- continue;
- mutex_enter(&wp->w_mutex);
- wp->w_closed = 1;
- cv_broadcast(&wp->w_cv);
- mutex_exit(&wp->w_mutex);
- }
-}
-
-/*
- * Register the caller with the waiting list for the
- * given domain.
- *
- * Protocol:
- * 1st Local requester: register -> alloc ->
- * put(wakeup|xdc) -> unregister
- * Nth Local requester: register -> wait
- * 1st Remote requester: register -> xdc -> wait
- * Nth Remote requester: register -> wait
- *
- * Remote Responder: local alloc -> put(xdc)
- * Local Handler: xdc -> put(wakeup)
- *
- * E.g. A standard slave allocation request:
- * slave master
- * ----- ------
- * idn_slab_alloc(remote)
- * - register
- * - xdc -> idn_handler
- * - wait ...
- * idn_slab_alloc(local)
- * - register
- * - alloc
- * - put
- * . wakeup [local]
- * - unregister
- * idn_handler <- - xdc
- * - put DONE
- * . wakeup [local]
- * |
- * V
- * - wait
- * . unregister
- * DONE
- */
-static int
-smr_slabwaiter_register(int domid)
-{
- struct slabwaiter *wp;
- int nwait;
- procname_t proc = "smr_slabwaiter_register";
-
-
- ASSERT(domid != IDN_NIL_DOMID);
-
- ASSERT(DSLAB_READ_HELD(domid));
-
- wp = &idn.slabwaiter[domid];
-
- ASSERT(MUTEX_NOT_HELD(&wp->w_mutex));
-
- mutex_enter(&wp->w_mutex);
-
- nwait = ++(wp->w_nwaiters);
- ASSERT(nwait > 0);
-
- PR_SMR("%s: domain = %d, (new)nwaiters = %d\n", proc, domid, nwait);
-
- if (nwait > 1) {
- /*
- * There are already waiters for slab allocations
- * with respect to this domain.
- */
- PR_SMR("%s: existing waiters for slabs for domain %d\n",
- proc, domid);
- mutex_exit(&wp->w_mutex);
-
- return (nwait);
- }
- PR_SMR("%s: initial waiter for slabs for domain %d\n", proc, domid);
- /*
- * We are the first requester of a slab allocation for this
- * respective domain. Need to prep waiting area for
- * subsequent arrival of a slab.
- */
- wp->w_sp = NULL;
- wp->w_done = 0;
- wp->w_serrno = 0;
-
- mutex_exit(&wp->w_mutex);
-
- return (nwait);
-}
-
-/*
- * It is assumed that the caller had previously registered,
- * but wakeup did not occur due to caller never waiting.
- * Thus, slaballoc mutex is still held by caller.
- *
- * Returns: 0
- * EINVAL
- * EBUSY
- * w_serrno (smr_slaballoc_put)
- * (0, ENOLCK, ENOMEM, EDQUOT, EBUSY, ECANCELED)
- */
-static int
-smr_slabwaiter_unregister(int domid, smr_slab_t **spp)
-{
- struct slabwaiter *wp;
- int serrno = 0;
- procname_t proc = "smr_slabwaiter_unregister";
-
-
- ASSERT(domid != IDN_NIL_DOMID);
-
- wp = &idn.slabwaiter[domid];
-
- mutex_enter(&wp->w_mutex);
-
- PR_SMR("%s: domain = %d, nwaiters = %d\n", proc, domid, wp->w_nwaiters);
-
- if (wp->w_nwaiters <= 0) {
- /*
- * Hmmm...nobody is registered!
- */
- PR_SMR("%s: NO WAITERS (domid = %d)\n", proc, domid);
- mutex_exit(&wp->w_mutex);
- return (EINVAL);
- }
- (wp->w_nwaiters)--;
- /*
- * Is our present under the tree?
- */
- if (!wp->w_done) {
- /*
- * Bummer...no presents. Let the caller know
- * via a null slab pointer.
- * Note that we don't clean up immediately since
- * message might still come in for other waiters.
- * Thus, late sleepers may still get a chance.
- */
- PR_SMR("%s: bummer no slab allocated for domain %d\n",
- proc, domid);
- ASSERT(wp->w_sp == NULL);
- (*spp) = NULL;
- serrno = wp->w_closed ? ECANCELED : EBUSY;
-
- } else {
- (*spp) = wp->w_sp;
- serrno = wp->w_serrno;
-
-#ifdef DEBUG
- if (serrno == 0) {
- register smr_slab_t *sp;
-
- ASSERT(wp->w_sp);
- PR_SMR("%s: allocation succeeded (domain %d)\n",
- proc, domid);
-
- DSLAB_LOCK_SHARED(domid);
- for (sp = idn_domain[domid].dslab; sp; sp = sp->sl_next)
- if (sp == wp->w_sp)
- break;
- if (sp == NULL)
- cmn_err(CE_WARN,
- "%s:%d: slab ptr = NULL",
- proc, domid);
- DSLAB_UNLOCK(domid);
- } else {
- PR_SMR("%s: allocation failed (domain %d) "
- "[serrno = %d]\n", proc, domid, serrno);
- }
-#endif /* DEBUG */
- }
- if (wp->w_nwaiters == 0) {
- /*
- * Last one turns out the lights.
- */
- PR_SMR("%s: domain %d last waiter, turning out lights\n",
- proc, domid);
- wp->w_sp = NULL;
- wp->w_done = 0;
- wp->w_serrno = 0;
- }
- mutex_exit(&wp->w_mutex);
-
- return (serrno);
-}
-
-/*
- * Called to abort any slaballoc requests on behalf of the
- * given domain.
- */
-int
-smr_slabwaiter_abort(int domid, int serrno)
-{
- ASSERT(serrno != 0);
-
- return (smr_slaballoc_put(domid, NULL, 0, serrno));
-}
-
-/*
- * Put ourselves into a timedwait waiting for slab to be
- * allocated.
- * Returns with slaballoc mutex dropped.
- *
- * Returns: EINVAL
- * ETIMEDOUT
- * smr_slabwatier_unregister
- * (0, EINVAL, EBUSY, ENOMEM)
- */
-static int
-smr_slaballoc_wait(int domid, smr_slab_t **spp)
-{
- struct slabwaiter *wp;
- int serrno = 0, serrno_unreg;
- procname_t proc = "smr_slaballoc_wait";
-
-
- wp = &idn.slabwaiter[domid];
-
- ASSERT(MUTEX_NOT_HELD(&wp->w_mutex));
-
- mutex_enter(&wp->w_mutex);
-
- PR_SMR("%s: domain = %d, nwaiters = %d, wsp = 0x%p\n",
- proc, domid, wp->w_nwaiters, (void *)wp->w_sp);
-
- if (wp->w_nwaiters <= 0) {
- /*
- * Hmmm...no waiters registered.
- */
- PR_SMR("%s: domain %d, no waiters!\n", proc, domid);
- mutex_exit(&wp->w_mutex);
- return (EINVAL);
- }
- ASSERT(DSLAB_READ_HELD(domid));
- DSLAB_UNLOCK(domid);
-
- if (!wp->w_done && !wp->w_closed) {
- int rv;
-
- /*
- * Only wait if data hasn't arrived yet.
- */
- PR_SMR("%s: domain %d, going to sleep...\n", proc, domid);
-
- rv = cv_reltimedwait_sig(&wp->w_cv, &wp->w_mutex,
- IDN_SLABALLOC_WAITTIME, TR_CLOCK_TICK);
- if (rv == -1)
- serrno = ETIMEDOUT;
-
- PR_SMR("%s: domain %d, awakened (reason = %s)\n",
- proc, domid, (rv == -1) ? "TIMEOUT" : "SIGNALED");
- }
- /*
- * We've awakened or request already filled!
- * Unregister ourselves.
- */
- mutex_exit(&wp->w_mutex);
-
- /*
- * Any gifts will be entered into spp.
- */
- serrno_unreg = smr_slabwaiter_unregister(domid, spp);
-
- /*
- * Leave with reader lock on dslab_lock.
- */
- DSLAB_LOCK_SHARED(domid);
-
- if ((serrno_unreg == EBUSY) && (serrno == ETIMEDOUT))
- return (serrno);
- else
- return (serrno_unreg);
-}
-
-/*
- * A SMR slab was allocated on behalf of the given domain.
- * Wakeup anybody that may have been waiting for the allocation.
- * Note that if the domain is a remote one, i.e. master is allocating
- * on behalf of a slave, it's up to the caller to transmit the
- * allocation response to that domain.
- * The force flag indicates that we want to install the slab for
- * the given user regardless of whether there are waiters or not.
- * This is used primarily in situations where a slave may have timed
- * out before the response actually arrived. In this situation we
- * don't want to send slab back to the master after we went through
- * the trouble of allocating one. Master is _not_ allowed to do this
- * for remote domains.
- *
- * Returns: -1 Non-registered waiter or waiting area garbaged.
- * 0 Successfully performed operation.
- */
-int
-smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag, int serrno)
-{
- idn_domain_t *dp;
- struct slabwaiter *wp;
- procname_t proc = "smr_slaballoc_put";
-
-
- dp = &idn_domain[domid];
-
- ASSERT(!serrno ? DSLAB_WRITE_HELD(domid) : 1);
-
- if (domid == IDN_NIL_DOMID)
- return (-1);
-
- ASSERT(serrno ? (sp == NULL) : (sp != NULL));
-
- wp = &idn.slabwaiter[domid];
-
- mutex_enter(&wp->w_mutex);
-
- PR_SMR("%s: domain = %d, bufp = 0x%p, ebufp = 0x%p, "
- "(f = %d, se = %d)\n", proc, domid,
- (sp ? (void *)sp->sl_start : 0),
- (sp ? (void *)sp->sl_end : 0), forceflag, serrno);
-
- if (wp->w_nwaiters <= 0) {
- /*
- * There are no waiters!! Must have timed out
- * and left. Oh well...
- */
- PR_SMR("%s: no slaballoc waiters found for domain %d\n",
- proc, domid);
- if (!forceflag || serrno || !sp) {
- /*
- * No waiters and caller doesn't want to force it.
- */
- mutex_exit(&wp->w_mutex);
- return (-1);
- }
- PR_SMR("%s: forcing slab onto domain %d\n", proc, domid);
- ASSERT(domid == idn.localid);
- ASSERT(wp->w_sp == NULL);
- wp->w_done = 0;
- /*
- * Now we fall through and let it be added in the
- * regular manor.
- */
- }
- if (wp->w_done) {
- /*
- * There's at least one waiter so there has
- * to be a slab structure waiting for us.
- * If everything is going smoothly, there should only
- * be one guy coming through the path of inserting
- * an error or good slab. However, if a disconnect was
- * detected, you may get several guys coming through
- * trying to let everybody know.
- */
- ASSERT(wp->w_serrno ?
- (wp->w_sp == NULL) : (wp->w_sp != NULL));
-
- cv_broadcast(&wp->w_cv);
- mutex_exit(&wp->w_mutex);
-
- return (-1);
- }
- if (serrno != 0) {
- /*
- * Bummer...allocation failed. This call is simply
- * to wake up the sleepers and let them know.
- */
- PR_SMR("%s: slaballoc failed for domain %d\n", proc, domid);
- wp->w_serrno = serrno;
- wp->w_done = 1;
- cv_broadcast(&wp->w_cv);
- mutex_exit(&wp->w_mutex);
-
- return (0);
- }
- PR_SMR("%s: putting slab into struct (domid=%d, localid=%d)\n",
- proc, domid, idn.localid);
- /*
- * Prep the slab structure.
- */
-
- if (domid == idn.localid) {
- /*
- * Allocation was indeed for me.
- * Slab may or may not be locked when
- * we reach. Normally they will be locked
- * if we're being called on behalf of a
- * free, and not locked if on behalf of
- * a new allocation request.
- */
- lock_clear(&sp->sl_lock);
- smr_alloc_buflist(sp);
-#ifdef DEBUG
- } else {
- uint_t rv;
- /*
- * Slab was not allocated on my behalf. Must be
- * a master request on behalf of some other domain.
- * Prep appropriately. Slab should have been locked
- * by smr_slab_reserve.
- */
- rv = lock_try(&sp->sl_lock);
- ASSERT(!rv);
- ASSERT(sp->sl_domid == (short)domid);
-#endif /* DEBUG */
- }
-
- /*
- * Slab is ready to go. Insert it into the domain's
- * slab list so once we wake everybody up they'll find it.
- * You better have write lock if you're putting treasures
- * there.
- */
- ASSERT(DSLAB_WRITE_HELD(domid));
-
- sp->sl_next = dp->dslab;
- dp->dslab = sp;
- dp->dnslabs++;
-
- /*
- * It's possible to fall through here without waiters.
- * This is a case where forceflag was set.
- */
- if (wp->w_nwaiters > 0) {
- wp->w_sp = sp;
- wp->w_serrno = serrno;
- wp->w_done = 1;
- cv_broadcast(&wp->w_cv);
- } else {
- ASSERT(forceflag);
- wp->w_sp = NULL;
- wp->w_serrno = 0;
- wp->w_done = 0;
- }
- mutex_exit(&wp->w_mutex);
-
- return (0);
-}
-
-/*
- * Get the slab representing [bufp,ebufp] from the respective
- * domain's pool if all the buffers are free. Remove them from
- * the domain's list and return it.
- * If bufp == NULL, then return however many free ones you
- * can find.
- * List of slabs are returned locked (sl_lock).
- * XXX - Need minimum limit to make sure we don't free up _all_
- * of our slabs! However, during a shutdown we will need
- * method to free them all up regardless of locking.
- */
-smr_slab_t *
-smr_slaballoc_get(int domid, caddr_t bufp, caddr_t ebufp)
-{
- idn_domain_t *dp;
- smr_slab_t *retsp, *sp, **psp;
- int foundit, islocal = 0;
- int nslabs;
- procname_t proc = "smr_slaballoc_get";
-
- PR_SMR("%s: getting slab for domain %d [bufp=0x%p, ebufp=0x%p]\n",
- proc, domid, (void *)bufp, (void *)ebufp);
-
- dp = &idn_domain[domid];
-
- ASSERT(DSLAB_WRITE_HELD(domid));
-
- if ((sp = dp->dslab) == NULL) {
- PR_SMR("%s: oops, no slabs for domain %d\n", proc, domid);
- return (NULL);
- }
- /*
- * If domid is myself then I'm trying to get a slab out
- * of my local pool. Otherwise, I'm the master and
- * I'm trying to get the slab representative from the
- * global pool.
- */
- if (domid == idn.localid)
- islocal = 1;
-
- if (bufp != NULL) {
- nslabs = -1;
- } else {
- nslabs = *(int *)ebufp;
- if (nslabs == 0) {
- PR_SMR("%s: requested nslabs (%d) <= 0\n",
- proc, nslabs);
- return (NULL);
- } else if (nslabs < 0) {
- /*
- * Caller wants them all!
- */
- nslabs = (int)dp->dnslabs;
- }
- }
-
- retsp = NULL;
- foundit = 0;
- for (psp = &dp->dslab; sp; sp = *psp) {
- int isbusy;
-
- if (bufp && (sp->sl_start != bufp)) {
- psp = &sp->sl_next;
- continue;
- }
-
- if (bufp && (ebufp > sp->sl_end)) {
- PR_SMR("%s: bufp/ebufp (0x%p/0x%p) "
- "expected (0x%p/0x%p)\n", proc, (void *)bufp,
- (void *)ebufp, (void *)sp->sl_start,
- (void *)sp->sl_end);
- ASSERT(0);
- }
- /*
- * We found the desired slab. Make sure
- * it's free.
- */
- foundit++;
- isbusy = 0;
- if (islocal) {
- int spl;
-
- /*
- * Some of the buffers in the slab
- * are still in use. Unlock the
- * buffers we locked and bail out.
- */
- spl = splhi();
- if (!lock_try(&sp->sl_lock)) {
- isbusy = 1;
- foundit--;
- } else if (sp->sl_inuse) {
- lock_clear(&sp->sl_lock);
- isbusy = 1;
- foundit--;
- }
- splx(spl);
- } else {
- /*
- * If not local, then I'm the master getting
- * a slab from one of the slaves. In this case,
- * their slab structs will always be locked.
- */
- ASSERT(!lock_try(&sp->sl_lock));
- }
- if (!isbusy) {
- /*
- * Delete the entry from the list and slap
- * it onto our return list.
- */
- *psp = sp->sl_next;
- sp->sl_next = retsp;
- retsp = sp;
- } else {
- psp = &sp->sl_next;
- }
- /*
- * If bufp == NULL (alternate interface) and we haven't
- * found the desired number of slabs yet, keep looking.
- */
- if (bufp || (foundit == nslabs))
- break;
- }
- dp->dnslabs -= (short)foundit;
-
- if (foundit) {
- PR_SMR("%s: found %d free slabs (domid = %d)\n", proc, foundit,
- domid);
- } else {
- PR_SMR("%s: no free slabs found (domid = %d)\n", proc, domid);
- }
-
- /*
- * If this is the alternate interface, need to return
- * the number of slabs found in the ebufp parameter.
- */
- if (bufp == NULL)
- *(int *)ebufp = foundit;
-
- return (retsp);
-}
-
-/*
- * Wrapper to hide alternate interface to smr_slaballoc_get()
- */
-smr_slab_t *
-smr_slaballoc_get_n(int domid, int *nslabs)
-{
- smr_slab_t *sp;
-
- ASSERT(DSLAB_WRITE_HELD(domid));
-
- sp = smr_slaballoc_get(domid, NULL, (caddr_t)nslabs);
-
- return (sp);
-}
-
-/*
- * Only called by master. Initialize slab pool based on local SMR.
- * Returns number of slabs initialized.
- * reserved_size = Length of area at the front of the NWR portion
- * of the SMR to reserve and not make available for
- * slab allocations. Must be a IDN_SMR_BUFSIZE multiple.
- * reserved_area = Pointer to reserved area, if any.
- */
-int
-smr_slabpool_init(size_t reserved_size, caddr_t *reserved_area)
-{
- size_t nwr_available;
- int minperpool, ntotslabs, nxslabs, nslabs;
- register int p, pp;
- register caddr_t bufp;
- register smr_slab_t *sp;
-
- ASSERT(IDN_GLOCK_IS_EXCL());
- ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID);
-
- *reserved_area = NULL;
-
- nwr_available = MB2B(IDN_NWR_SIZE) - reserved_size;
-
- if ((idn.localid != IDN_GET_MASTERID()) ||
- (nwr_available < IDN_SLAB_SIZE) ||
- (idn.slabpool != NULL) ||
- ((reserved_size != 0) && (reserved_size & (IDN_SMR_BUFSIZE-1)))) {
- return (-1);
- }
-
- idn.slabpool = GETSTRUCT(struct slabpool, 1);
- idn.slabpool->ntotslabs = ntotslabs = nwr_available / IDN_SLAB_SIZE;
- ASSERT(ntotslabs > 0);
- minperpool = (ntotslabs < IDN_SLAB_MINPERPOOL) ?
- 1 : IDN_SLAB_MINPERPOOL;
- idn.slabpool->npools = (ntotslabs + (minperpool - 1)) / minperpool;
-
- if ((idn.slabpool->npools & 1) == 0) {
- /*
- * npools needs to be odd for hashing algorithm.
- */
- idn.slabpool->npools++;
- }
- ASSERT(idn.slabpool->npools > 0);
- minperpool = (ntotslabs < idn.slabpool->npools) ?
- 1 : (ntotslabs / idn.slabpool->npools);
-
- /*
- * Calculate the number of extra slabs that will need to
- * be alloted to the pools. This number will be less than
- * npools. Only one extra slab is allocated to each pool
- * until we have assigned all the extra slabs.
- */
- if (ntotslabs > (idn.slabpool->npools * minperpool))
- nxslabs = ntotslabs - (idn.slabpool->npools * minperpool);
- else
- nxslabs = 0;
- ASSERT((nxslabs >= 0) && (nxslabs < idn.slabpool->npools));
-
- idn.slabpool->pool = GETSTRUCT(struct smr_slabtbl,
- idn.slabpool->npools);
- sp = GETSTRUCT(smr_slab_t, idn.slabpool->ntotslabs);
-
- idn.slabpool->savep = sp;
- bufp = idn.smr.vaddr + reserved_size;
-
- for (p = nslabs = 0;
- (p < idn.slabpool->npools) && (ntotslabs > 0);
- p++, ntotslabs -= nslabs) {
-
- nslabs = (ntotslabs < minperpool) ? ntotslabs : minperpool;
- if (nxslabs > 0) {
- nslabs++;
- nxslabs--;
- }
- idn.slabpool->pool[p].sarray = sp;
- for (pp = 0; pp < nslabs; pp++) {
-
- sp->sl_next = NULL;
- sp->sl_start = bufp;
- sp->sl_end = bufp = sp->sl_start + IDN_SLAB_SIZE;
- sp->sl_lock = 0;
- sp->sl_domid = (short)IDN_NIL_DOMID;
-
- sp++;
- }
- idn.slabpool->pool[p].nfree = nslabs;
- idn.slabpool->pool[p].nslabs = nslabs;
- }
- ASSERT((ntotslabs == 0) && (nxslabs == 0));
- /*
- * We should be at the end of the SMR at this point.
- */
- ASSERT(bufp == (idn.smr.vaddr + reserved_size
- + (idn.slabpool->ntotslabs * IDN_SLAB_SIZE)));
-
- if (reserved_size != 0)
- *reserved_area = idn.smr.vaddr;
-
- return (0);
-}
-
-void
-smr_slabpool_deinit()
-{
- if (idn.slabpool == NULL)
- return;
-
- FREESTRUCT(idn.slabpool->savep, smr_slab_t, idn.slabpool->ntotslabs);
- FREESTRUCT(idn.slabpool->pool, struct smr_slabtbl,
- idn.slabpool->npools);
- FREESTRUCT(idn.slabpool, struct slabpool, 1);
-
- idn.slabpool = NULL;
-}
-
-void
-smr_alloc_buflist(smr_slab_t *sp)
-{
- int n, nbufs;
- caddr_t sbufp;
- smr_slabbuf_t *hp, *bp;
-
- if (sp->sl_head)
- return;
-
- nbufs = (sp->sl_end - sp->sl_start) / IDN_SMR_BUFSIZE;
- ASSERT(nbufs > 0);
- if (nbufs <= 0) {
- sp->sl_head = sp->sl_free = sp->sl_inuse = NULL;
- return;
- }
-
- hp = GETSTRUCT(smr_slabbuf_t, nbufs);
-
- sbufp = sp->sl_start;
- for (n = 0, bp = hp; n < nbufs; bp++, n++) {
- bp->sb_bufp = sbufp;
- bp->sb_domid = IDN_NIL_DOMID;
- bp->sb_next = bp + 1;
- sbufp += IDN_SMR_BUFSIZE;
- }
- (--bp)->sb_next = NULL;
-
- sp->sl_head = sp->sl_free = hp;
- sp->sl_inuse = NULL;
-}
-
-void
-smr_free_buflist(smr_slab_t *sp)
-{
- int nbufs;
-
- if (sp->sl_head == NULL)
- return;
-
- nbufs = (sp->sl_end - sp->sl_start) / IDN_SMR_BUFSIZE;
-
- FREESTRUCT(sp->sl_head, smr_slabbuf_t, nbufs);
-
- sp->sl_head = sp->sl_free = sp->sl_inuse = NULL;
-}
-
-/*
- * Returns: 0 Successfully located a slab.
- * -1 Failure.
- */
-static smr_slab_t *
-smr_slab_reserve(int domid)
-{
- register int p, nextp, s, nexts;
- register smr_slab_t *spa;
- int startp, starts;
- int foundone = 0;
- int spl;
- procname_t proc = "smr_slab_reserve";
-
- p = startp = SMR_SLABPOOL_HASH(domid);
- nextp = -1;
-
- spl = splhi();
- while ((nextp != startp) && !foundone) {
-
- s = starts = SMR_SLAB_HASH(p, domid);
- nexts = -1;
- spa = &(idn.slabpool->pool[p].sarray[0]);
-
- while ((nexts != starts) && !foundone) {
- if (lock_try(&spa[s].sl_lock)) {
- foundone = 1;
- break;
- }
- nexts = SMR_SLAB_HASHSTEP(p, s);
- s = nexts;
- }
- if (foundone)
- break;
- nextp = SMR_SLABPOOL_HASHSTEP(p);
- p = nextp;
- }
- splx(spl);
-
- if (foundone) {
- ASSERT((&spa[s] >= idn.slabpool->savep) &&
- (&spa[s] < (idn.slabpool->savep +
- idn.slabpool->ntotslabs)));
-
- spa[s].sl_domid = (short)domid;
-
- ATOMIC_DEC(idn.slabpool->pool[p].nfree);
-
- if (domid == idn.localid) {
- smr_slab_t *nsp;
- /*
- * Caller is actually reserving a slab for
- * themself which means they'll need the full
- * slab structure to represent all of the I/O
- * buffers. The "spa" is just a representative
- * and doesn't contain the space to manage the
- * individual buffers. Need to alloc a full-size
- * struct.
- * Note that this results in the returning
- * smr_slab_t structure being unlocked.
- */
- ASSERT(idn.localid == IDN_GET_MASTERID());
- nsp = GETSTRUCT(smr_slab_t, 1);
- nsp->sl_start = spa[s].sl_start;
- nsp->sl_end = spa[s].sl_end;
- smr_alloc_buflist(nsp);
- spa = nsp;
- PR_SMR("%s: allocated full slab struct for domain %d\n",
- proc, domid);
- } else {
- /*
- * Slab structure gets returned locked.
- */
- spa += s;
- }
-
- PR_SMR("%s: allocated slab 0x%p (start=0x%p, size=%lu) for "
- "domain %d\n", proc, (void *)spa, (void *)spa->sl_start,
- spa->sl_end - spa->sl_start, domid);
- } else {
- PR_SMR("%s: FAILED to allocate for domain %d\n",
- proc, domid);
- spa = NULL;
- }
-
- return (spa);
-}
-
-static void
-smr_slab_unreserve(int domid, smr_slab_t *sp)
-{
- register int p, nextp, s, nexts;
- register smr_slab_t *spa;
- int foundit = 0;
- int startp, starts;
- caddr_t bufp;
- procname_t proc = "smr_slab_unreserve";
-
- bufp = sp->sl_start;
- p = startp = SMR_SLABPOOL_HASH(domid);
- nextp = -1;
-
- while ((nextp != startp) && !foundit) {
-
- s = starts = SMR_SLAB_HASH(p, domid);
- nexts = -1;
- spa = &(idn.slabpool->pool[p].sarray[0]);
-
- while ((nexts != starts) && !foundit) {
- if (spa[s].sl_start == bufp) {
- foundit = 1;
- break;
- }
- nexts = SMR_SLAB_HASHSTEP(p, s);
- s = nexts;
- }
- if (foundit)
- break;
- nextp = SMR_SLABPOOL_HASHSTEP(p);
- p = nextp;
- }
- if (foundit) {
- ASSERT((&spa[s] >= idn.slabpool->savep) &&
- (&spa[s] < (idn.slabpool->savep +
- idn.slabpool->ntotslabs)));
- ASSERT(!lock_try(&spa[s].sl_lock));
- ASSERT(spa[s].sl_domid == (short)domid);
-
- spa[s].sl_next = NULL;
- spa[s].sl_domid = (short)IDN_NIL_DOMID;
- lock_clear(&spa[s].sl_lock);
-
- ATOMIC_INC(idn.slabpool->pool[p].nfree);
-
- PR_SMR("%s: freed (bufp=0x%p) for domain %d\n",
- proc, (void *)bufp, domid);
-
- if (domid == idn.localid) {
- /*
- * Caller is actually unreserving a slab of their
- * own. Note that only the master calls this
- * routine. Since the master's local slab
- * structures do not get entered into the global
- * "representative" pool, we need to free up the
- * data structure that was passed in.
- */
- ASSERT(idn.localid == IDN_GET_MASTERID());
- ASSERT(sp != &spa[s]);
-
- smr_free_buflist(sp);
- FREESTRUCT(sp, smr_slab_t, 1);
- } else {
- ASSERT(sp == &spa[s]);
- }
- } else {
- /*
- * Couldn't find slab entry for given buf!
- */
- PR_SMR("%s: FAILED to free (bufp=0x%p) for domain %d\n",
- proc, (void *)bufp, domid);
- }
-}
-
-/*
- * The Reap Protocol:
- * master slave
- * ------ -----
- * smr_slab_reap_global
- * - idn_broadcast_cmd(SLABREAP) -> idn_recv_cmd(SLABREAP)
- * . idn_local_cmd(SLABREAP) - idn_recv_slabreap_req
- * - smr_slab_reap . smr_slab_reap
- * . smr_slaballoc_get_n - smr_slaballoc_get_n
- * . smr_slab_free - smr_slab_free
- * - smr_slab_free_local . smr_slab_free_remote
- * . smr_slab_unreserve
- * <- - idn_send_cmd(SLABFREE)
- * idn_recv_cmd(SLABFREE)
- * - idn_recv_slabfree_req
- * . smr_slaballoc_get
- * . smr_slab_free
- * - smr_slab_free_local
- * . smr_slab_unreserve
- * . idn_send_slabfree_resp -> idn_recv_cmd(SLABFREE | ack)
- * - idn_recv_slabfree_resp
- *
- * idn_recv_cmd(SLABREAP | ack) <- . idn_send_slabreap_resp
- * - idn_recv_slabreap_resp DONE
- * DONE
- *
- * Check available slabs and if we're below the threshold, kick
- * off reaping to all remote domains. There is no guarantee remote
- * domains will be able to free up any.
- */
-static void
-smr_slab_reap_global()
-{
- register int p, npools;
- register int total_free = 0;
- register struct smr_slabtbl *tblp;
- static clock_t reap_last = 0;
- procname_t proc = "smr_slab_reap_global";
- clock_t now;
-
- ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID);
-
- DSLAB_LOCK_SHARED(idn.localid);
- if (idn_domain[idn.localid].dslab_state != DSLAB_STATE_LOCAL) {
- PR_SMR("%s: only allowed by master (%d)\n",
- proc, IDN_GET_MASTERID());
- DSLAB_UNLOCK(idn.localid);
- return;
- }
- DSLAB_UNLOCK(idn.localid);
-
- now = ddi_get_lbolt();
- if ((now > 0) && (now > reap_last) &&
- ((now - reap_last) < IDN_REAP_INTERVAL))
- return;
-
- reap_last = now;
-
- ASSERT(idn.slabpool);
-
- npools = idn.slabpool->npools;
- tblp = idn.slabpool->pool;
-
- for (p = 0; p < npools; tblp++, p++)
- total_free += tblp->nfree;
-
- if (total_free <= IDN_SLAB_THRESHOLD) {
- int diff, reap_per_domain;
-
- PR_SMR("%s: kicking off reaping "
- "(total_free = %d, min = %d)\n",
- proc, total_free, IDN_SLAB_THRESHOLD);
-
- diff = IDN_SLAB_THRESHOLD - total_free;
- reap_per_domain = (diff < idn.ndomains) ?
- 1 : (diff / idn.ndomains);
-
- idn_broadcast_cmd(IDNCMD_SLABREAP, reap_per_domain, 0, 0);
- }
-}
-
-void
-smr_slab_reap(int domid, int *nslabs)
-{
- register int d;
- int nreclaimed;
- smr_slab_t *sp;
- domainset_t reapset;
- procname_t proc = "smr_slab_reap";
-
- /*
- * Should only be called on behalf of local
- * domain.
- */
- if (domid != idn.localid) {
- PR_SMR("%s: called by domain %d, should only be local (%d)\n",
- proc, domid, idn.localid);
- ASSERT(0);
- return;
- }
- /*
- * Try and reclaim some buffers so we can possibly
- * free up some slabs.
- */
- reapset = idn.domset.ds_connected;
-
- IDN_GKSTAT_GLOBAL_EVENT(gk_reaps, gk_reap_last);
-
- nreclaimed = 0;
- for (d = 0; d < MAX_DOMAINS; d++) {
- int nr;
- idn_domain_t *dp;
-
- if (!DOMAIN_IN_SET(reapset, d))
- continue;
-
- IDN_DLOCK_SHARED(d);
-
- dp = &idn_domain[d];
- if ((d == idn.localid) || (dp->dcpu < 0)) {
- IDN_DUNLOCK(d);
- continue;
- }
- /*
- * Clean up any dead I/O errors if possible.
- */
- if (dp->dioerr > 0) {
- idn_domain_t *ldp;
- register int cnt;
- register smr_slabbuf_t *bp;
- /*
- * We need to grab the writer lock to prevent
- * anybody from allocating buffers while we
- * traverse the slabs outstanding.
- */
- cnt = 0;
- ldp = &idn_domain[idn.localid];
- IDN_DLOCK_EXCL(idn.localid);
- DSLAB_LOCK_EXCL(idn.localid);
- for (sp = ldp->dslab; sp; sp = sp->sl_next)
- for (bp = sp->sl_inuse; bp; bp = bp->sb_next)
- if (bp->sb_domid == d)
- cnt++;
- DSLAB_UNLOCK(idn.localid);
- ASSERT((dp->dio + dp->dioerr) >= cnt);
- dp->dio = cnt;
- dp->dioerr = 0;
- IDN_DUNLOCK(idn.localid);
- }
- if ((dp->dstate == IDNDS_CONNECTED) &&
- ((nr = idn_reclaim_mboxdata(d, 0, -1)) > 0))
- nreclaimed += nr;
-
- IDN_DUNLOCK(d);
- }
-
- DSLAB_LOCK_EXCL(domid);
- sp = smr_slaballoc_get_n(domid, nslabs);
- if (sp) {
- IDN_GKSTAT_ADD(gk_reap_count, (ulong_t)(*nslabs));
- smr_slab_free(domid, sp);
- }
- DSLAB_UNLOCK(domid);
-}
-
-/*
- * ---------------------------------------------------------------------
- * Remap the (IDN) shared memory region to a new physical address.
- * Caller is expected to have performed a ecache flush if needed.
- * ---------------------------------------------------------------------
- */
-void
-smr_remap(struct as *as, register caddr_t vaddr,
- register pfn_t new_pfn, uint_t mblen)
-{
- tte_t tte;
- size_t blen;
- pgcnt_t p, npgs;
- procname_t proc = "smr_remap";
-
- if (va_to_pfn(vaddr) == new_pfn) {
- PR_REMAP("%s: vaddr (0x%p) already mapped to pfn (0x%lx)\n",
- proc, (void *)vaddr, new_pfn);
- return;
- }
-
- blen = MB2B(mblen);
- npgs = btopr(blen);
- ASSERT(npgs != 0);
-
- PR_REMAP("%s: va = 0x%p, pfn = 0x%lx, npgs = %ld, mb = %d MB (%ld)\n",
- proc, (void *)vaddr, new_pfn, npgs, mblen, blen);
-
- /*
- * Unmap the SMR virtual address from it's current
- * mapping.
- */
- hat_unload(as->a_hat, vaddr, blen, HAT_UNLOAD_UNLOCK);
-
- if (new_pfn == PFN_INVALID)
- return;
-
- /*
- * Map the SMR to the new physical address space,
- * presumably a remote pfn. Cannot use hat_devload
- * because it will think pfn represents non-memory,
- * since it may extend beyond its physmax.
- */
- for (p = 0; p < npgs; p++) {
- sfmmu_memtte(&tte, new_pfn, PROT_READ | PROT_WRITE | HAT_NOSYNC,
- TTE8K);
- sfmmu_tteload(as->a_hat, &tte, vaddr, NULL, HAT_LOAD_LOCK);
-
- vaddr += MMU_PAGESIZE;
- new_pfn++;
- }
-
- PR_REMAP("%s: remapped %ld pages (expected %ld)\n",
- proc, npgs, btopr(MB2B(mblen)));
-}
diff --git a/usr/src/uts/sun4u/starfire/io/idn_xf.c b/usr/src/uts/sun4u/starfire/io/idn_xf.c
deleted file mode 100644
index 797f2479a8..0000000000
--- a/usr/src/uts/sun4u/starfire/io/idn_xf.c
+++ /dev/null
@@ -1,1694 +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) 2016 by Delphix. All rights reserved.
- */
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/open.h>
-#include <sys/param.h>
-#include <sys/vm_machparam.h>
-#include <sys/machparam.h>
-#include <sys/systm.h>
-#include <sys/signal.h>
-#include <sys/cred.h>
-#include <sys/user.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/uio.h>
-#include <sys/buf.h>
-#include <sys/file.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/strsubr.h>
-#include <sys/poll.h>
-#include <sys/debug.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/errno.h>
-#include <sys/modctl.h>
-#include <sys/x_call.h>
-#include <sys/cpuvar.h>
-#include <sys/machcpuvar.h>
-#include <sys/machsystm.h>
-
-#include <sys/pda.h>
-#include <sys/starfire.h>
-#include <sys/idn.h>
-#include <sys/idn_xf.h>
-
-kmutex_t idn_xf_mutex; /* to serialize hardware access */
-/*
- * This data structure is referenced during the cross-call
- * update of the CICs. The semaphore is used for synchronization
- * when waiting for completion of the respective operation.
- * We want IDNCIC_TIMEOUT ticks for all the cpus to check-in
- * before we bail out and fail the operation.
- */
-#define IDNCIC_TIMEOUT (30*hz)
-#define IDNCIC_TIMECHK (hz/3)
-#define IDNCIC_UNKNOWN 0
-#define IDNCIC_OK 1 /* values for xf_errcic */
-#define IDNCIC_ERR 2
-#define IDNCIC_BUSY 3
-
-#ifdef DEBUG
-#define NCICREGS 3 /* smmask, smbar, smlar */
-#define CICREG_SMMASK 0
-#define CICREG_SMBAR 1
-#define CICREG_SMLAR 2
-
-#define RESET_CIC_HISTORY() \
- (xf_cicboards = xf_cicbuses = 0, \
- bzero(xf_cicregs, sizeof (xf_cicregs)))
-
-#define UPDATE_CIC_HISTORY(reg, brd, bus, val) \
- (BOARDSET_ADD(xf_cicboards, (brd)), \
- BOARDSET_ADD(xf_cicbuses, (bus)), \
- xf_cicregs[brd][bus][reg] = (val))
-
-#define DUMP_CIC_HISTORY() \
-{ \
- if (idn_debug & IDNDBG_XF) { \
- int _bd, _bs; \
- procname_t _proc = "dump_cic_history"; \
- for (_bd = 0; _bd < MAX_BOARDS; _bd++) { \
- if (!BOARD_IN_SET(xf_cicboards, _bd)) \
- continue; \
- for (_bs = 0; _bs < MAX_ABUSES; _bs++) { \
- if (!BOARD_IN_SET(xf_cicbuses, _bs)) \
- continue; \
- printf("%s: (bd.bs = %d.%d) m/b/l = " \
- "%x/%x/%x\n", _proc, _bd, _bs, \
- xf_cicregs[_bd][_bs][CICREG_SMMASK], \
- xf_cicregs[_bd][_bs][CICREG_SMBAR], \
- xf_cicregs[_bd][_bs][CICREG_SMLAR]); \
- } \
- } \
- DEBUG_DELAY(); \
- } \
-}
-
-/*
- * Globally updated during CIC reg updates. Everybody has
- * a unique location, so no concern about updates stepping
- * on each other.
- */
-static ushort_t xf_cicboards, xf_cicbuses;
-static uint_t xf_cicregs[MAX_BOARDS][MAX_ABUSES][NCICREGS];
-#else /* DEBUG */
-#define RESET_CIC_HISTORY()
-#define UPDATE_CIC_HISTORY(reg, brd, bus, val)
-#define DUMP_CIC_HISTORY()
-#endif /* DEBUG */
-
-struct idnxf_cic_info { /* protected by idn_xf_mutex */
-/* 0 */ short xf_abus_mask;
-/* 2 */ boardset_t xf_boardset;
-/* 4 */ uint_t xf_smbase;
-/* 8 */ uint_t xf_smlimit;
-/* c */ int xf_doadd;
-
-/* 10 */ int xf_count; /* atomically updated */
-/* 14 */ time_t xf_start_time;
-/* 18 */ kcondvar_t xf_cv;
-/* 1a */ short xf_errtimer;
-/* 1c */ int xf_errcnt; /* atomically updated */
-
-/* 20 */ uchar_t xf_errcic[MAX_BOARDS][MAX_ABUSES];
-
-/* 60 */ kmutex_t xf_mutex;
-}; /* sizeof = 0x68 = 104 (26X) */
-
-static struct idnxf_cic_info idnxf_cic_info;
-#ifdef DEBUG
-static uint_t o_idn_debug;
-#endif /* DEBUG */
-
-int idn_check_cpu_per_board = 1;
-
-static int pc_prep_cic_buffer(int cpuid, uint_t cicdata);
-static int cic_write_sm_mask(int board, int bus, boardset_t sm_mask);
-static int cic_write_sm_bar(int board, int bus, uint_t sm_bar);
-static int cic_write_sm_lar(int board, int bus, uint_t sm_lar);
-static int cic_get_smmask_bit(void);
-static int pc_write_madr(pda_handle_t ph,
- int lboard, int rboard, uint_t madr);
-static boardset_t get_boardset(pda_handle_t ph, int *nboards);
-static int verify_smregs(int brd, int bus, boardset_t smmask,
- uint_t smbase, uint_t smlimit);
-static void idnxf_shmem_wakeup(void *arg);
-static void idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2);
-static int idnxf_shmem_update_all(pda_handle_t ph,
- boardset_t boardset, uint_t smbase,
- uint_t smlimit, int doadd);
-
-#define PHYSIO_ST(paddr, val) (stphysio((paddr), (val)))
-#define PHYSIO_LD(paddr) (ldphysio(paddr))
-#define PHYSIO_STH(paddr, val) (sthphysio((paddr), (val)))
-#define PHYSIO_LDH(paddr) (ldhphysio(paddr))
-
-#ifdef DEBUG
-#define DEBUG_DELAY() (drv_usecwait(5000)) /* 5 ms */
-#else /* DEBUG */
-#define DEBUG_DELAY()
-#endif /* DEBUG */
-
-
-/*
- * ---------------------------------------------------------------------
- */
-boardset_t
-cic_read_domain_mask(int board, int bus)
-{
- u_longlong_t csr_addr;
- boardset_t domain_mask;
- procname_t proc = "cic_read_domain_mask";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_DOMAIN_MASK_ADDR,
- bus);
- PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- domain_mask = (boardset_t)PHYSIO_LDH(csr_addr);
-
- return (domain_mask);
-}
-
-boardset_t
-cic_read_sm_mask(int board, int bus)
-{
- u_longlong_t csr_addr;
- boardset_t sm_mask;
- procname_t proc = "cic_read_sm_mask";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR,
- bus);
- PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_mask = (boardset_t)PHYSIO_LDH(csr_addr);
-
- return (sm_mask);
-}
-
-static int
-cic_write_sm_mask(int board, int bus, boardset_t sm_mask)
-{
- u_longlong_t csr_addr;
- int cnt;
- procname_t proc = "cic_write_sm_mask";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- sm_mask &= 0xffff;
- /*
- * Before we can write to the CIC, we need to set
- * up the CIC write data buffer in the PC.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, (uint_t)sm_mask) < 0)
- return (-1);
-
- /*
- * Now we can write to the CIC.
- */
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR,
- bus);
- PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s: writing sm_mask = 0x%x\n",
- proc, (ushort_t)sm_mask);
-
- UPDATE_CIC_HISTORY(CICREG_SMMASK, board, bus, sm_mask);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_mask);
- /*
- * Read back for verification.
- */
- for (cnt = 0; (PHYSIO_LDH(csr_addr) != sm_mask) && (cnt < 10); cnt++)
- ;
-
- return ((cnt == 10) ? -1 : 0);
-}
-
-uint_t
-cic_read_sm_bar(int board, int bus)
-{
- u_longlong_t csr_addr;
- uint_t sm_bar;
- procname_t proc = "cic_read_sm_bar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_bar = (uint_t)PHYSIO_LDH(csr_addr);
- sm_bar <<= 16;
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_bar |= (uint_t)PHYSIO_LDH(csr_addr);
-
- return (sm_bar);
-}
-
-static int
-cic_write_sm_bar(int board, int bus, uint_t sm_bar)
-{
- int cnt;
- u_longlong_t csr_addr;
- uint_t sm_bar_lsb, sm_bar_msb;
- procname_t proc = "cic_write_sm_bar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- sm_bar_lsb = sm_bar & 0xffff;
- sm_bar_msb = (sm_bar >> 16) & 0xffff;
-
- /*
- * Before we can write to the CIC, we need to set
- * up the CIC write data buffer in the PC.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_msb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:MSB: sm_bar[31:16] = 0x%x\n",
- proc, (ushort_t)sm_bar_msb);
-
- UPDATE_CIC_HISTORY(CICREG_SMBAR, board, bus, sm_bar);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_bar_msb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_msb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 500: failed to write sm_bar (msb) (0x%x)",
- (uint_t)sm_bar_msb);
- return (-1);
- }
-
- /*
- * Now to LSB portion.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_lsb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:LSB: sm_bar[15:0] = 0x%x\n",
- proc, (ushort_t)sm_bar_lsb);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_bar_lsb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_lsb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 500: failed to write sm_bar (lsb) (0x%x)",
- (uint_t)sm_bar_lsb);
- return (-1);
- }
-
- return (0);
-}
-
-uint_t
-cic_read_sm_lar(int board, int bus)
-{
- u_longlong_t csr_addr;
- uint_t sm_lar;
- procname_t proc = "cic_read_sm_lar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_lar = (uint_t)PHYSIO_LDH(csr_addr);
- sm_lar <<= 16;
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
-
- sm_lar |= (uint_t)PHYSIO_LDH(csr_addr);
-
- return (sm_lar);
-}
-
-static int
-cic_write_sm_lar(int board, int bus, uint_t sm_lar)
-{
- int cnt;
- u_longlong_t csr_addr;
- uint_t sm_lar_lsb, sm_lar_msb;
- procname_t proc = "cic_write_sm_lar";
-
- ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
-
- sm_lar_lsb = sm_lar & 0xffff;
- sm_lar_msb = (sm_lar >> 16) & 0xffff;
-
- /*
- * Before we can write to the CIC, we need to set
- * up the CIC write data buffer in the PC.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_msb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR,
- bus);
- PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:MSB: sm_lar[31:16] = 0x%x\n",
- proc, (ushort_t)sm_lar_msb);
-
- UPDATE_CIC_HISTORY(CICREG_SMLAR, board, bus, sm_lar);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_lar_msb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_msb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 501: failed to write sm_lar (msb) (0x%x)",
- (uint_t)sm_lar_msb);
- return (-1);
- }
-
- /*
- * Now to LSB portion.
- */
- if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_lsb) < 0)
- return (-1);
-
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR,
- bus);
- PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
- proc, board, bus, csr_addr);
- PR_XF("%s:LSB: sm_lar[15:0] = 0x%x\n",
- proc, (ushort_t)sm_lar_lsb);
-
- PHYSIO_STH(csr_addr, (ushort_t)sm_lar_lsb);
- for (cnt = 0;
- ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_lsb) && (cnt < 10);
- cnt++)
- ;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 501: failed to write sm_lar (lsb) (0x%x)",
- (uint_t)sm_lar_lsb);
- return (-1);
- }
-
- return (0);
-}
-
-static int
-cic_get_smmask_bit(void)
-{
- u_longlong_t csr_addr;
- int board;
- uint_t config1;
- procname_t proc = "cic_get_smmask_bit";
-
- affinity_set(CPU_CURRENT);
-
- board = CPUID_TO_BOARDID(CPU->cpu_id);
- /*
- * Now that I'm stuck on this cpu I can go look at this
- * board's CIC registers.
- */
- csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_CONFIG1_ADDR, 0);
- PR_XF("%s: (bd=%d) csr_addr = 0x%llx (via cpu %d)\n",
- proc, board, csr_addr, (int)CPU->cpu_id);
-
- config1 = (uint_t)PHYSIO_LDH(csr_addr);
-
- config1 = CIC_CONFIG1_SMMASK_BIT(config1);
-
- affinity_clear();
-
- return (config1);
-}
-
-static int
-pc_prep_cic_buffer(int cpuid, uint_t cicdata)
-{
- int rv;
- int brd, port;
- u_longlong_t csr_addr;
- register int cnt;
- procname_t proc = "pc_prep_cic_buffer";
-
-
- ASSERT(CPU->cpu_id == cpuid);
-
- port = cpuid % plat_max_cpu_units_per_board();
- brd = CPUID_TO_BOARDID(cpuid);
-
- csr_addr = STARFIRE_PC_CICBUF_ADDR(brd, port);
-
- /*
- * csr_addr now points to CIC write buffer which resides
- * in PC register space.
- */
- PR_XF("%s: (cpu=%d) csr_addr = 0x%llx\n", proc, cpuid, csr_addr);
-
- PHYSIO_ST(csr_addr, cicdata);
-
- /*
- * Now we need to read back the data to guarantee
- * it got there. Part of the PC protocol.
- */
- for (cnt = 0; (PHYSIO_LD(csr_addr) != cicdata) && (cnt < 10);
- cnt++)
- ;
-
- rv = 0;
- if (cnt == 10) {
- cmn_err(CE_WARN,
- "IDN: 502: unable to store data (0x%x) to "
- "CIC buffer (0x%llx)",
- cicdata, csr_addr);
- rv = -1;
- } else if (cnt >= 1) {
- PR_XF("%s: MULTIPLE READS (cpu=%d) cnt = %d\n",
- proc, cpuid, cnt);
- }
-
- return (rv);
-}
-
-/*
- * --------------------------------------------------
- * Write the given MC address decoding register contents (madr) of
- * the respective remote board (rboard) into all the PCs located on
- * the local board (lboard).
- * --------------------------------------------------
- */
-static int
-pc_write_madr(pda_handle_t ph, int lboard, int rboard, uint_t madr)
-{
- u_longlong_t pc_madr_addr;
- register int p, ioc;
- register ushort_t procset, iocset;
- int rv = 0;
- uint_t rd_madr;
- board_desc_t *lbp;
- procname_t proc = "pc_write_madr";
-
- lbp = pda_get_board_info(ph, lboard);
-
- ASSERT(lbp);
- ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
-
- procset = lbp->bda_proc;
- iocset = lbp->bda_ioc;
-
- /*
- * Update the PCs for the cpus.
- */
- for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) {
- int i;
-
- if (!((procset & BDAN_MASK) == BDAN_GOOD))
- continue;
-
- pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
- rboard, p);
-
- /*
- * On this first iteration of updating the PC
- * we need to turn off the MADR VALID bit so that
- * there's no accidental usage of the entry before
- * all four bytes have been updated in the PC.
- */
- if (madr != 0) {
- /*
- * Need to clear valid bit on first
- * go around.
- */
- madr &= ~STARFIRE_PC_MADR_VALIDBIT;
- }
- PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
- "[lb=%d, rb=%d, cpu=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, p);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (1) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 503: (invalidate) failed to update "
- "PC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- continue;
- }
- if (madr == 0) {
- continue;
- } else {
- /*
- * Turn the valid bit back on.
- */
- madr |= STARFIRE_PC_MADR_VALIDBIT;
- }
- PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
- "[lb=%d, rb=%d, cpu=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, p);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (2) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 503: (validate) failed to update "
- "PC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- }
- }
- /*
- * Update the PCs for the iocs.
- */
- for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) {
- int i;
-
- if (!((iocset & BDAN_MASK) == BDAN_GOOD))
- continue;
-
- pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
- rboard, ioc + 4);
-
- if (madr != 0) {
- /*
- * Need to clear valid bit on first
- * go around.
- */
- madr &= ~STARFIRE_PC_MADR_VALIDBIT;
- }
- PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
- "[lb=%d, rb=%d, ioc=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, ioc);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (3) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 504: (invalidate) failed to update "
- "IOPC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- continue;
- }
-
- if (madr == 0) {
- continue;
- } else {
- /*
- * Turn the valid bit back on.
- */
- madr |= STARFIRE_PC_MADR_VALIDBIT;
- }
-
- PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
- "[lb=%d, rb=%d, ioc=%d]\n",
- proc, madr, pc_madr_addr, lboard, rboard, ioc);
- DEBUG_DELAY();
-
- for (i = 0; i < 20; i++) {
- PHYSIO_ST(pc_madr_addr, madr);
- /*
- * Read back for sanity check.
- */
- rd_madr = PHYSIO_LD(pc_madr_addr);
- if (madr == rd_madr)
- break;
- }
- if (i > 0) {
- PR_XF("%s: WARNING: (4) lb=%d, rb=%d, "
- "madr=0x%x (i=%d)\n",
- proc, lboard, rboard, madr, i);
- }
- if (rd_madr != madr) {
- cmn_err(CE_WARN,
- "IDN: 504: (validate) failed to update "
- "IOPC madr (expected 0x%x, actual 0x%x)",
- madr, rd_madr);
- rv++;
- }
- }
-
- return (rv ? -1 : 0);
-}
-
-/*
- * --------------------------------------------------
- * Read the array of MC address decoding registers from one of the
- * PCs on the local board (lboard) into the given in array (mc_adr).
- * --------------------------------------------------
- */
-void
-pc_read_madr(pda_handle_t ph, int lboard, uint_t mc_adr[], int local_only)
-{
- u_longlong_t pc_madr_addr;
- register int p, ioc;
- register ushort_t procset, iocset;
- int brd;
- board_desc_t *lbp;
-
- lbp = pda_get_board_info(ph, lboard);
-
- ASSERT(lbp);
- ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
-
- procset = lbp->bda_proc;
- iocset = lbp->bda_ioc;
-
- for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++)
- if ((procset & BDAN_MASK) == BDAN_GOOD)
- break;
-
- if (p == MAX_PROCMODS) {
- /*
- * Couldn't find a PC off a cpu, let's check the
- * IOCs.
- */
- for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++)
- if ((iocset & BDAN_MASK) == BDAN_GOOD)
- break;
- if (ioc == MAX_IOCS) {
- cmn_err(CE_WARN,
- "IDN: 505: board %d missing any valid PCs",
- lboard);
- return;
- }
- p = ioc + 4;
- }
-
- pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 0, p);
- /*
- * pc_madr_addr = Starts at entry for board 0.
- */
- for (brd = 0; brd < MAX_BOARDS; brd++) {
- /*
- * It's possible our local PC may have old entries to
- * AWOL domains. Only want to pay attention to PC
- * entries corresponding to our boards.
- */
- lbp = pda_get_board_info(ph, brd);
- if (!local_only || ((lbp->bda_board & BDAN_MASK) == BDAN_GOOD))
- mc_adr[brd] = PHYSIO_LD(pc_madr_addr);
- else
- mc_adr[brd] = 0;
-
- pc_madr_addr += ((u_longlong_t)1 <<
- STARFIRE_PC_MADR_BOARD_SHIFT);
- }
-}
-
-/*
- * --------------------------------------------------
- * Read the MC address decoding register contents for all
- * possible boards and store the results in their respective
- * slot in mc_adr. Keep a count of non-zero MC ADRs and
- * return that.
- * --------------------------------------------------
- */
-void
-mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], int *nmcadr)
-{
- int brd;
- uint_t madr[MAX_BOARDS];
-
- /*
- * Note that each PC has a complete copy of all MC contents
- * and so all we have to do is read one PC rather than
- * each of the MCs in the system.
- */
- brd = CPUID_TO_BOARDID(CPU->cpu_id);
- pc_read_madr(ph, brd, madr, 1);
-
- *nmcadr = 0;
- for (brd = 0; brd < MAX_BOARDS; brd++)
- if ((mc_adr[brd] = madr[brd]) != 0)
- (*nmcadr)++;
-}
-
-static boardset_t
-get_boardset(pda_handle_t ph, int *nboards)
-{
- int brd;
- int nbrds = 0;
- boardset_t bmask;
-
- if (nboards != NULL)
- *nboards = 0;
-
- bmask = 0;
- for (brd = 0; brd < MAX_BOARDS; brd++) {
- if (pda_board_present(ph, brd)) {
- bmask |= 1 << brd;
- nbrds++;
- }
- }
- if (nboards != NULL)
- *nboards = (short)nbrds;
-
- return (bmask);
-}
-
-int
-update_local_hw_config(idn_domain_t *ldp, struct hwconfig *loc_hw)
-{
- procname_t proc = "update_local_hw_config";
-
- ASSERT(IDN_DLOCK_IS_EXCL(ldp->domid));
- ASSERT(IDN_GLOCK_IS_EXCL());
- ASSERT(ldp == &idn_domain[idn.localid]);
-
- if (ldp->dhw.dh_boardset != loc_hw->dh_boardset) {
- int c;
-
- PR_PROTO("%s: NEW HW CONFIG (old_bset = 0x%x, "
- "new_bset = 0x%x)\n",
- proc, ldp->dhw.dh_boardset, loc_hw->dh_boardset);
-
- PR_PROTO("%s: clearing boardset 0x%x\n", proc,
- ldp->dhw.dh_boardset & ~loc_hw->dh_boardset);
- PR_PROTO("%s: setting boardset 0x%x\n", proc,
- loc_hw->dh_boardset & ~ldp->dhw.dh_boardset);
-
- idn.dc_boardset &= ~ldp->dhw.dh_boardset;
- idn.dc_boardset |= loc_hw->dh_boardset;
- for (c = 0; c < NCPU; c++) {
- if (CPU_IN_SET(ldp->dcpuset, c)) {
- CPUSET_DEL(idn.dc_cpuset, c);
- }
- }
- CPUSET_OR(idn.dc_cpuset, cpu_ready_set);
-
- bcopy(loc_hw, &ldp->dhw, sizeof (ldp->dhw));
- ldp->dcpuset = cpu_ready_set;
- ldp->dcpu = cpu0.cpu_id;
- ldp->dncpus = (int)ncpus;
- ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1;
- ldp->dvote.v.ncpus = (int)ldp->dncpus - 1;
- ldp->dvote.v.board = CPUID_TO_BOARDID(CPU->cpu_id);
-
- return (1);
- } else {
- PR_PROTO("%s: NO change detected\n", proc);
- return (0);
- }
-}
-
-int
-get_hw_config(struct hwconfig *loc_hw)
-{
- pda_handle_t ph;
- boardset_t domainset;
- int bd;
- int nmcadr;
- int nboards;
- procname_t proc = "get_hw_config";
-
- ASSERT(loc_hw != NULL);
-
- bzero(loc_hw, sizeof (*loc_hw));
- /*
- * See if sm_mask is writable.
- * XXX - Should be the same for all CIC's. Do we
- * we need to verify?
- */
- if (cic_get_smmask_bit() == 0) {
- /*
- * If smmask is not writable, we can not allow
- * IDN operations.
- */
- cmn_err(CE_WARN,
- "IDN: 506: cic sm_mask is not writeable");
- return (-1);
- }
- /*
- * Map in the post2obp structure so we can find
- * valid boards and hardware asics.
- */
- ph = pda_open();
- if (ph == (pda_handle_t)NULL) {
- cmn_err(CE_WARN,
- "IDN: 507: failed to map-in post2obp structure");
- return (-1);
- } else if (!pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- pda_close(ph);
- return (-1);
- }
- /*
- * Need to read the MC address decoding registers
- * so that they can be given to other domains.
- */
- loc_hw->dh_boardset = get_boardset(ph, &nboards);
- loc_hw->dh_nboards = (short)nboards;
- ASSERT(loc_hw->dh_boardset & (1 << CPUID_TO_BOARDID(CPU->cpu_id)));
-
- mc_get_adr_all(ph, loc_hw->dh_mcadr, &nmcadr);
- loc_hw->dh_nmcadr = (short)nmcadr;
-
- affinity_set(CPU_CURRENT);
- /*
- * There will always be a bus 0 (logical).
- */
- bd = CPUID_TO_BOARDID(CPU->cpu_id);
- domainset = (boardset_t)cic_read_domain_mask(bd, 0);
- affinity_clear();
-
- if (!idn_cpu_per_board(ph, cpu_ready_set, loc_hw)) {
- pda_close(ph);
- return (-1);
- }
-
- pda_close(ph);
-
-
-#ifdef DEBUG
- {
- int brd;
-
- for (brd = 0; brd < MAX_BOARDS; brd++)
- if (loc_hw->dh_mcadr[brd] != 0) {
- PR_XF("%s: brd %d, mc = 0x%x\n",
- proc, brd, loc_hw->dh_mcadr[brd]);
- }
- }
-#endif /* DEBUG */
-
- if ((loc_hw->dh_boardset != domainset) || (loc_hw->dh_nmcadr < 1))
- return (-1);
- else
- return (0);
-}
-
-/*
- * Function called via timeout() to wakeup a possibly stuck
- * idnxf_shmem_update_all() should not all cpus check-in after a
- * x-call to update their respective CICs.
- */
-/*ARGSUSED0*/
-static void
-idnxf_shmem_wakeup(void *arg)
-{
- struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg;
- int count;
- int expired;
- procname_t proc = "idnxf_shmem_wakeup";
-
- expired = ((ddi_get_lbolt() - idnxfp->xf_start_time) >=
- IDNCIC_TIMEOUT) ? 1 : 0;
-
- if ((count = idnxfp->xf_count) == 0) {
- /*
- * Everybody has finished. Wakeup the requester.
- */
- mutex_enter(&idnxfp->xf_mutex);
- cv_signal(&idnxfp->xf_cv);
- mutex_exit(&idnxfp->xf_mutex);
-
- } else if ((count > 0) && expired) {
- /*
- * There are still active cic updaters and time
- * has expired. Bail on them.
- */
- idnxfp->xf_errtimer = 1;
-#ifdef DEBUG
- /*
- * Special debug case since idn_debug
- * may have been temporarily cleared
- * during xc_some.
- */
- if ((idn_debug | o_idn_debug) & IDNDBG_REGS)
- printf("%s: TIMEOUT...bailing on %d lost CIC "
- "updates...\n", proc, count);
-#endif /* DEBUG */
-
- ATOMIC_SUB(idnxfp->xf_count, count);
-
- mutex_enter(&idnxfp->xf_mutex);
- cv_signal(&idnxfp->xf_cv);
- mutex_exit(&idnxfp->xf_mutex);
-
- } else {
- (void) timeout(idnxf_shmem_wakeup, (caddr_t)idnxfp,
- (clock_t)IDNCIC_TIMECHK);
- }
-}
-
-/*
- * Called indirectly from idnxf_shmem_update_all() via a xcall
- * for the recepient cpu to update the CICs on its respective
- * board.
- * IMPORTANT: NO console output from this routine!!
- */
-static void
-idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2)
-{
- struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg1;
- time_t start_time = (time_t)arg2;
- int rv, cpuid, brd, bus;
- boardset_t smmask;
-
-
- cpuid = CPU->cpu_id;
- brd = CPUID_TO_BOARDID(cpuid);
-
- if (idnxfp->xf_start_time != start_time) {
- /*
- * Ooops! Not my place to intrude.
- */
- idnxf_cic_info.xf_errcic[brd][0] = IDNCIC_BUSY;
- ATOMIC_INC(idnxf_cic_info.xf_errcnt);
-
- goto done;
- }
-
- /*
- * We're executing out of the context of a cross-call
- * so we're effectively bound! :)
- */
- for (bus = 0; bus < MAX_ABUSES; bus++) {
- /*
- * XXX - need to worry about shuffle??
- */
- if (!(idnxfp->xf_abus_mask & (1 << bus)))
- continue;
- smmask = cic_read_sm_mask(brd, bus);
-
- if (idnxfp->xf_doadd) {
- smmask |= idnxfp->xf_boardset;
- (void) cic_write_sm_mask(brd, bus, smmask);
-
- if (idnxfp->xf_smbase != (uint_t)-1) {
- (void) cic_write_sm_bar(brd, bus,
- idnxfp->xf_smbase);
- (void) cic_write_sm_lar(brd, bus,
- idnxfp->xf_smlimit);
- }
- /*
- * Verify data got there!
- */
- rv = verify_smregs(brd, bus, smmask, idnxfp->xf_smbase,
- idnxfp->xf_smlimit);
- } else {
- smmask &= ~idnxfp->xf_boardset;
- (void) cic_write_sm_mask(brd, bus, smmask);
-
- if (!smmask) {
- /*
- * Update the LAR first so that we effectively
- * disable the register without possibly
- * opening the window to transaction we
- * don't care about. Updating the LAR first
- * will guarantee we effectively turn it
- * off immediately.
- */
- (void) cic_write_sm_lar(brd, bus, 0);
- (void) cic_write_sm_bar(brd, bus, 1);
-
- rv = verify_smregs(brd, bus, smmask, 1, 0);
- } else {
- rv = verify_smregs(brd, bus, smmask,
- (uint_t)-1, (uint_t)-1);
- }
- }
- if (rv) {
- idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_ERR;
- ATOMIC_INC(idnxf_cic_info.xf_errcnt);
- } else {
- idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_OK;
- }
- }
-
-done:
- ATOMIC_DEC(idnxf_cic_info.xf_count);
-}
-
-static int
-idnxf_shmem_update_all(pda_handle_t ph, boardset_t boardset,
- uint_t smbase, uint_t smlimit, int doadd)
-{
- cpuset_t target_cpuset;
- int target_count;
- int rv = 0;
- int c, brd, bus;
- short abus_mask;
- time_t start_time;
- procname_t proc = "idnxf_shmem_update_all";
-
-
- ASSERT(MUTEX_HELD(&idn_xf_mutex));
-
- pda_get_busmask(ph, &abus_mask, NULL);
-
- CPUSET_ZERO(target_cpuset);
- target_count = 0;
- /*
- * Build a cpuset of target cpus (one per board) to
- * be used to send the CIC update xcall.
- */
- for (brd = 0; brd < MAX_BOARDS; brd++) {
- /*
- * Need to target an available cpu on the target board
- * so that we can look at the CICs on that board.
- */
- c = board_to_ready_cpu(brd, cpu_ready_set);
-
- if (c == -1) {
- /*
- * If there's no cpu on this board, no
- * need to update the CICs.
- */
- continue;
- }
- CPUSET_ADD(target_cpuset, c);
- target_count++;
- }
-
- if (CPUSET_ISNULL(target_cpuset)) {
- PR_REGS("%s: NO target cpus to update!!\n", proc);
- return (0);
- }
-
- RESET_CIC_HISTORY();
-
- /*
- * Broadcast out the CIC update request and then
- * sit back and wait for dinner to arrive!
- * Let's set up the global structure all the xcall
- * recepients will read.
- */
- start_time = ddi_get_lbolt();
- /*
- * Set the start time. Make sure it's different
- * then the previous run.
- */
- if (start_time <= idnxf_cic_info.xf_start_time)
- start_time++;
- idnxf_cic_info.xf_start_time = start_time;
-
- idnxf_cic_info.xf_abus_mask = abus_mask;
- idnxf_cic_info.xf_boardset = boardset;
- idnxf_cic_info.xf_smbase = smbase;
- idnxf_cic_info.xf_smlimit = smlimit;
- idnxf_cic_info.xf_doadd = doadd;
- idnxf_cic_info.xf_count = target_count;
- idnxf_cic_info.xf_errcnt = 0;
- idnxf_cic_info.xf_errtimer = 0;
- bzero(&idnxf_cic_info.xf_errcic, sizeof (idnxf_cic_info.xf_errcic));
-
- /*
- * Broadcast out the xcall to do the task.
- */
-#ifdef DEBUG
- {
- uint_t tu32, tl32;
-
- tu32 = UPPER32_CPUMASK(target_cpuset);
- tl32 = LOWER32_CPUMASK(target_cpuset);
- PR_REGS("%s: (start %ld) broadcasting CIC - "
- "%s to cpus 0x%x.%0x\n",
- proc, start_time, doadd ? "LINK" : "UNLINK",
- tu32, tl32);
- }
-
- /*
- * Can't dump debug during cross-calls.
- */
- o_idn_debug = idn_debug;
- idn_debug = 0;
-#endif /* DEBUG */
-
- xc_attention(target_cpuset);
-
- xc_some(target_cpuset, idnxf_shmem_update_one,
- (uint64_t)&idnxf_cic_info, (uint64_t)start_time);
-
- xc_dismissed(target_cpuset);
-
- ASSERT(idnxf_cic_info.xf_count == 0);
-
-#ifdef DEBUG
- idn_debug = o_idn_debug;
- o_idn_debug = 0;
-#endif /* DEBUG */
-
- PR_REGS("%s: waiting for completion of %d CIC - %s...\n",
- proc, idnxf_cic_info.xf_count, doadd ? "LINKS" : "UNLINKS");
- PR_REGS("%s: CIC - %s have checked IN.\n",
- proc, doadd ? "LINKS" : "UNLINKS");
-
- /*
- * Modifying xf_start_time effectively disables any
- * possible outstanding xcall's since they don't touch
- * idnxf_cic_info unless their given start_time matches
- * that in the idnxf_cic_info structure.
- */
- idnxf_cic_info.xf_start_time++;
-
- PR_REGS("%s: xf_errcnt = %d, xf_errtimer = %d\n",
- proc, idnxf_cic_info.xf_errcnt, idnxf_cic_info.xf_errtimer);
- DUMP_CIC_HISTORY();
- /*
- * Should errors be fatal? (panic).
- */
- rv = 0;
- for (c = 0; c < NCPU; c++) {
- if (!CPU_IN_SET(target_cpuset, c))
- continue;
- brd = CPUID_TO_BOARDID(c);
-
- for (bus = 0; bus < MAX_ABUSES; bus++) {
-
- if (!(abus_mask & (1 << bus)))
- continue;
-
- switch (idnxf_cic_info.xf_errcic[brd][bus]) {
- case IDNCIC_UNKNOWN:
- /*
- * Unknown is only an error if the
- * timer expired.
- */
- if (!idnxf_cic_info.xf_errtimer)
- break;
- cmn_err(CE_WARN,
- "IDN: 509: CPU %d never responded "
- "to CIC update", c);
- /*FALLTHROUGH*/
-
- case IDNCIC_ERR:
- cmn_err(CE_WARN,
- "IDN: 510: failed write-smregs "
- "(bd=%d, bs=%d, sm(bar=0x%x, "
- "lar=0x%x))",
- brd, bus, smbase, smlimit);
- rv++;
- break;
-
- case IDNCIC_BUSY:
- cmn_err(CE_WARN, "IDN: 511: update-one "
- "(cpu=%d, bd=%d) time conflict",
- c, brd);
- /*
- * Should never occur. Not fatal,
- * just continue.
- */
- break;
-
- default:
- PR_REGS("%s: board %d, bus %d "
- "(bar=0x%x,lar=0x%x) - update OK\n",
- proc, brd, bus, smbase, smlimit);
- break;
- }
- }
- }
-
- return (rv ? -1 : 0);
-}
-
-/*
- * Add the respective boardset/base/limit/mcadr's to the local
- * domain's hardware configuration with respect to the SMR.
- *
- * is_master Indicates remote domain is a master.
- */
-int
-idnxf_shmem_add(int is_master, boardset_t boardset, pfn_t pfnbase,
- pfn_t pfnlimit, uint_t *mcadr)
-{
- int rv = 0;
- register int brd, rbrd;
- register boardset_t localboardset;
- uint_t madr;
- uint_t smbase, smlimit;
- pda_handle_t ph;
- procname_t proc = "idnxf_shmem_add";
-
-
- localboardset = idn_domain[idn.localid].dhw.dh_boardset;
-
- ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
- ASSERT(is_master ? (pfnbase && pfnlimit && mcadr) : 1);
-
- if (pfnbase != PFN_INVALID) {
- smbase = (uint_t)PFN_TO_SMADDR(pfnbase);
- smlimit = (uint_t)PFN_TO_SMADDR(pfnlimit);
- } else {
- smbase = smlimit = (uint_t)-1;
- }
- PR_REGS("%s: is_master=%d, boardset=0x%x, smbase=0x%x, smlimit=%x\n",
- proc, is_master, boardset, smbase, smlimit);
-
- /*
- * Need to serialize hardware access so we don't have multiple
- * threads attempting to access hardware regs simulataneously.
- * This should not be a significant performance penalty since
- * the hardware is only touched when domains are linking or
- * unlinking.
- */
- mutex_enter(&idn_xf_mutex);
-
- /*
- * Map in the post2obp structure so we can find
- * bus config information.
- */
- ph = pda_open();
- if (ph == (pda_handle_t)NULL) {
- cmn_err(CE_WARN,
- "IDN: 507: failed to map-in post2obp structure");
- rv = -1;
- goto done;
-
- } else if (!pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- rv = -1;
- goto done;
- }
- /*
- * Take a checkpoint in bbsram for diagnostic purposes.
- */
- CHECKPOINT_OPENED(IDNSB_CHKPT_SMR, boardset, 1);
-
- rv = idnxf_shmem_update_all(ph, boardset, smbase, smlimit, 1);
-
- if (rv || (is_master == 0))
- goto done;
-
- /*
- * If this is a slave (i.e. remote domain is_master),
- * then we need to deprogram our PCs.
- */
- PR_REGS("%s: updating PC regs (lboardset=0x%x, rboardset=0x%x)\n",
- proc, localboardset, boardset);
-
- for (brd = 0; brd < MAX_BOARDS; brd++) {
-
- if (!BOARD_IN_SET(localboardset, brd))
- continue;
- /*
- * If this is a slave (i.e. remote domain is_master),
- * then we need to program our PCs.
- */
- for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
-
- if ((madr = mcadr[rbrd]) == 0)
- continue;
-
- ASSERT(BOARD_IN_SET(boardset, rbrd));
- /*
- * Write the MC adr for the respective
- * remote board (rbrd) into the PCs of
- * the given local board (brd).
- */
- if (pc_write_madr(ph, brd, rbrd, madr) < 0) {
- cmn_err(CE_WARN,
- "IDN: 512: failed [add] write-madr "
- "(bd=%d, rbd=%d, madr=0x%x)",
- brd, rbrd, madr);
- rv = -1;
- goto done;
- }
- }
- }
-
-done:
- if (ph)
- pda_close(ph);
-
- mutex_exit(&idn_xf_mutex);
- /*
- * XXX
- *
- * Failure here is fatal. Disable IDN?
- * NOn-zero return value will at least prevent
- * linkage with domain - probably sufficient.
- */
- return (rv);
-}
-
-/*
- * Remove the respective boardset from the local domain's
- * hardware configuration with respect to the SMR.
- *
- * is_master Indicates remote domain is a master.
- */
-int
-idnxf_shmem_sub(int is_master, boardset_t boardset)
-{
- int rv = 0;
- register int brd, rbrd;
- register boardset_t localboardset;
- pda_handle_t ph;
- procname_t proc = "idnxf_shmem_sub";
-
- localboardset = idn_domain[idn.localid].dhw.dh_boardset;
-
- ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
-
- PR_REGS("%s: is_master=%d, boardset=0x%x\n",
- proc, is_master, boardset);
-
- /*
- * Need to serialize hardware access so we don't have multiple
- * threads attempting to access hardware regs simulataneously.
- * This should not be a significant performance penalty since
- * the hardware is only touched when domains are linking or
- * unlinking.
- */
- mutex_enter(&idn_xf_mutex);
-
- /*
- * Map in the post2obp structure so we can find
- * bus config information.
- */
- ph = pda_open();
- if (ph == (pda_handle_t)NULL) {
- cmn_err(CE_WARN,
- "IDN: 507: failed to map-in post2obp structure");
- rv = -1;
- goto done;
-
- } else if (!pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- rv = -1;
- goto done;
- }
- /*
- * Take a checkpoint in bbsram for diagnostic purposes.
- */
- CHECKPOINT_CLOSED(IDNSB_CHKPT_SMR, boardset, 2);
-
- rv = idnxf_shmem_update_all(ph, boardset, (uint_t)-1, (uint_t)-1, 0);
-
- if (rv || (is_master == 0))
- goto done;
-
- /*
- * If this is a slave (i.e. remote domain is_master),
- * then we need to deprogram our PCs.
- */
- PR_REGS("%s: reseting PC regs (lboardset=0x%x, rboardset=0x%x)\n",
- proc, localboardset, boardset);
-
- for (brd = 0; brd < MAX_BOARDS; brd++) {
-
- if (!BOARD_IN_SET(localboardset, brd))
- continue;
-
- for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
-
- if (!BOARD_IN_SET(boardset, rbrd))
- continue;
- /*
- * Clear the MC adr for the respective
- * remote board (rbrd) into the PCs of
- * the given local board (brd).
- */
- if (pc_write_madr(ph, brd, rbrd, 0) < 0) {
- cmn_err(CE_WARN,
- "IDN: 512: failed [del] write-madr "
- "(bd=%d, rbd=%d, madr=0x%x)",
- brd, rbrd, 0);
- rv = -1;
- goto done;
- }
- }
- }
-
-done:
- if (ph)
- pda_close(ph);
- mutex_exit(&idn_xf_mutex);
-
- return (rv);
-}
-
-/*
- * We cannot cross-trap cpu_flush_ecache since it references
- * %g7 via CPU. It's possible that %g7 may not be set up
- * when the trap comes in, and could thus cause a crash.
- * Well...at least that's what has been happening when I
- * tried x-calls within an xc_attention (KMISS) panic.
- * Instead we use cross-calls. However, since we can't
- * xc_attention around a cross-call, we have not guaranteed
- * way of knowing the operation succeeded. To synchronize
- * this flush operation across cpus, we use a semaphore
- * which is V'd by the receiving cpus and P'd by the caller
- * initiating the all-cpus flush.
- */
-/*ARGSUSED0*/
-void
-idn_flush_ecache(uint64_t arg1, uint64_t arg2)
-{
- extern void cpu_flush_ecache(void);
-
- cpu_flush_ecache();
- /*
- * Paranoia...Give things a chance to drain.
- */
- drv_usecwait(500000); /* 500 msec */
-}
-/*
- * Flush the ecache's of all the cpus within this domain of
- * any possible SMR references.
- * This logic is borrowed from ecc.c:cpu_flush_ecache().
- */
-void
-idnxf_flushall_ecache()
-{
- cpuset_t local_cpuset;
- procname_t proc = "idnxf_flushall_ecache";
-
-
- PR_XF("%s: flushing ecache (cpu_ready_set = 0x%x.%x)\n", proc,
- UPPER32_CPUMASK(cpu_ready_set), LOWER32_CPUMASK(cpu_ready_set));
-
- CHECKPOINT_CACHE_CLEAR_DEBUG(1);
- CHECKPOINT_CACHE_STEP_DEBUG(0x1, 2);
-
- local_cpuset = cpu_ready_set;
-
- xc_attention(local_cpuset);
-
- /*
- * We tell each cpu to do a flush and then we hit
- * a semaphore to synchronize with all of them
- * to guarantee they have completed the flush before
- * we continue on. We have to do this type of
- * sychronization since we can't xc_attention around
- * a cross-call.
- */
- CHECKPOINT_CACHE_STEP_DEBUG(0x2, 3);
-
- xc_all(idn_flush_ecache, 0, 0);
-
- CHECKPOINT_CACHE_STEP_DEBUG(0x4, 4);
-
- xc_dismissed(local_cpuset);
-
- CHECKPOINT_CACHE_STEP_DEBUG(0x8, 5);
-}
-
-/*
- * --------------------------------------------------
- */
-static int
-verify_smregs(int brd, int bus, boardset_t smmask, uint_t smbase, uint_t
- smlimit)
-{
- int rv = 0;
- uint_t smreg;
-
- if (smmask != (boardset_t)-1) {
- smreg = (uint_t)cic_read_sm_mask(brd, bus);
- if (smreg != (uint_t)smmask) {
- cmn_err(CE_WARN,
- "IDN: 513: sm-mask error "
- "(expected = 0x%x, actual = 0x%x)",
- (uint_t)smmask, smreg);
- rv++;
- }
- }
-
- if (smbase != (uint_t)-1) {
- smreg = cic_read_sm_bar(brd, bus);
- if (smreg != smbase) {
- cmn_err(CE_WARN,
- "IDN: 514: sm-base error "
- "(expected = 0x%x, actual = 0x%x)",
- smbase, smreg);
- rv++;
- }
- }
-
- if (smlimit != (uint_t)-1) {
- smreg = cic_read_sm_lar(brd, bus);
- if (smreg != smlimit) {
- cmn_err(CE_WARN,
- "IDN: 515: sm-limit error "
- "(expected = 0x%x, actual = 0x%x)",
- smlimit, smreg);
- rv++;
- }
- }
-
- return (rv ? -1 : 0);
-}
-
-/*
- * -------------------------------------------------------------
- */
-int
-idn_cpu_per_board(pda_handle_t ph, cpuset_t cset, struct hwconfig *hwp)
-{
- int b, err = 0;
- boardset_t bset, cpu_bset;
- board_desc_t *lbp;
-
- if (!idn_check_cpu_per_board)
- return (1);
-
- bset = hwp->dh_boardset;
- CPUSET_TO_BOARDSET(cset, cpu_bset);
-
- /*
- * Every board has at least one cpu, we're happy.
- */
- if (cpu_bset == bset)
- return (1);
-
- /*
- * Well, not all boards had cpus. That's okay so
- * long as they don't have memory also.
- * Get rid of the boards that have a cpu.
- */
- bset &= ~cpu_bset;
- /*
- * None of the remaining boards in the set shold have mem.
- */
- err = 0;
-
- /*
- * A NULL post2obp pointer indicates we're checking
- * the config of a remote domain. Since we can't
- * look at the post2obp of the remote domain, we'll
- * have to trust what it passed us in its config.
- */
- if (ph && !pda_is_valid(ph)) {
- cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
- return (0);
- }
-
- for (b = 0; b < MAX_BOARDS; b++) {
- if (!BOARD_IN_SET(bset, b))
- continue;
-
- lbp = ph ? pda_get_board_info(ph, b) : NULL;
-
- if ((lbp &&
- (BDA_NBL(lbp->bda_board, BDA_MC_NBL) == BDAN_GOOD)) ||
- (!lbp && hwp->dh_mcadr[b])) {
- err++;
- cmn_err(CE_WARN,
- "IDN: 516: (%s) board %d has memory, "
- "but no CPUs - CPU per memory board REQUIRED",
- ph ? "local" : "remote", b);
- }
- }
-
- return (err ? 0 : 1);
-}
diff --git a/usr/src/uts/sun4u/starfire/io/memctrl.c b/usr/src/uts/sun4u/starfire/io/memctrl.c
deleted file mode 100644
index 953542f3cb..0000000000
--- a/usr/src/uts/sun4u/starfire/io/memctrl.c
+++ /dev/null
@@ -1,276 +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"
-
-/*
- * Starfire Memory Controller specific routines.
- */
-
-#include <sys/debug.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/dditypes.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/promif.h>
-#include <sys/machsystm.h>
-
-#include <sys/starfire.h>
-
-struct mc_dimm_table {
- int mc_type;
- int mc_module_size; /* module size in MB */
-};
-
-static struct mc_dimm_table dimmsize_table[] = {
- { 4, 8 },
- { 6, 8 },
- { 11, 32 },
- { 15, 128 },
- { 0, 0 }
-};
-
-#define MC_MB(mb) ((mb) * 1048576ull)
-
-struct mc_seg_size {
- uint_t seg_mask;
- uint64_t seg_size;
-};
-
-struct mc_seg_size mc_seg_table[] = {
- { 0x7f, MC_MB(64) },
- { 0x7e, MC_MB(128) },
- { 0x7c, MC_MB(256) },
- { 0x78, MC_MB(512) },
- { 0x70, MC_MB(1024) },
- { 0x60, MC_MB(2048) },
- { 0x40, MC_MB(4096) },
- { 0, 0 }
-};
-
-/*
- * Alignment of memory between MC's.
- */
-uint64_t
-mc_get_mem_alignment()
-{
- return (STARFIRE_MC_MEMBOARD_ALIGNMENT);
-}
-
-uint64_t
-mc_get_asr_addr(pnode_t nodeid)
-{
- int rlen;
- uint64_t psi_addr;
- struct sf_memunit_regspec reg;
-
- rlen = prom_getproplen(nodeid, "reg");
- if (rlen != sizeof (struct sf_memunit_regspec))
- return ((uint64_t)-1);
-
- if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
- return ((uint64_t)-1);
-
- psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32;
- psi_addr |= (uint64_t)reg.regspec_addr_lo;
-
- return (STARFIRE_MC_ASR_ADDR(psi_addr));
-}
-
-uint64_t
-mc_get_idle_addr(pnode_t nodeid)
-{
- int rlen;
- uint64_t psi_addr;
- struct sf_memunit_regspec reg;
-
- rlen = prom_getproplen(nodeid, "reg");
- if (rlen != sizeof (struct sf_memunit_regspec))
- return ((uint64_t)-1);
-
- if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
- return ((uint64_t)-1);
-
- psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32;
- psi_addr |= (uint64_t)reg.regspec_addr_lo;
-
- return (STARFIRE_MC_IDLE_ADDR(psi_addr));
-}
-
-int
-mc_get_dimm_size(pnode_t nodeid)
-{
- uint64_t psi_addr;
- uint_t dimmtype;
- int i, rlen;
- struct sf_memunit_regspec reg;
-
- rlen = prom_getproplen(nodeid, "reg");
- if (rlen != sizeof (struct sf_memunit_regspec))
- return (-1);
-
- if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
- return (-1);
-
- psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32;
- psi_addr |= (uint64_t)reg.regspec_addr_lo;
- psi_addr = STARFIRE_MC_DIMMTYPE_ADDR(psi_addr);
-
- if (psi_addr == (uint64_t)-1)
- return (-1);
-
- dimmtype = ldphysio(psi_addr);
- dimmtype &= STARFIRE_MC_DIMMSIZE_MASK;
-
- for (i = 0; dimmsize_table[i].mc_type != 0; i++)
- if (dimmsize_table[i].mc_type == dimmtype)
- break;
-
- return (dimmsize_table[i].mc_module_size);
-}
-
-uint64_t
-mc_get_alignment_mask(pnode_t nodeid)
-{
- uint64_t psi_addr, seg_sz;
- uint_t mcreg, seg_sz_mask;
- int i, rlen;
- struct sf_memunit_regspec reg;
-
- rlen = prom_getproplen(nodeid, "reg");
- if (rlen != sizeof (struct sf_memunit_regspec))
- return (-1);
-
- if (prom_getprop(nodeid, "reg", (caddr_t)&reg) < 0)
- return (-1);
-
- psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32;
- psi_addr |= (uint64_t)reg.regspec_addr_lo;
- psi_addr = STARFIRE_MC_ASR_ADDR(psi_addr);
-
- if (psi_addr == (uint64_t)-1)
- return (-1);
-
- mcreg = ldphysio(psi_addr);
- seg_sz_mask = (mcreg & STARFIRE_MC_MASK_MASK) >> 8;
-
- for (i = 0; mc_seg_table[i].seg_size != 0; i++)
- if (mc_seg_table[i].seg_mask == seg_sz_mask)
- break;
-
- if (mc_seg_table[i].seg_size == 0)
- seg_sz = mc_get_mem_alignment();
- else
- seg_sz = mc_seg_table[i].seg_size;
-
-#ifdef DEBUG
- printf("nodeid %x, mc asr addr %lx, val %x, seg_sz_mask %x, "
- "seg_sz %lx\n", nodeid, psi_addr, mcreg, seg_sz_mask, seg_sz);
-#endif /* DEBUG */
-
- return (seg_sz - 1);
-}
-
-int
-mc_read_asr(pnode_t nodeid, uint_t *mcregp)
-{
- uint64_t psi_addr;
-
- *mcregp = 0;
-
- psi_addr = mc_get_asr_addr(nodeid);
- if (psi_addr == (uint64_t)-1)
- return (-1);
-
- *mcregp = ldphysio(psi_addr);
-
- return (0);
-}
-
-int
-mc_write_asr(pnode_t nodeid, uint_t mcreg)
-{
- uint_t mcreg_rd;
- uint64_t psi_addr;
-
- psi_addr = mc_get_asr_addr(nodeid);
- if (psi_addr == (uint64_t)-1)
- return (-1);
-
- stphysio(psi_addr, mcreg);
-
- mcreg_rd = ldphysio(psi_addr);
- ASSERT(mcreg_rd == mcreg);
-
- return ((mcreg_rd != mcreg) ? -1 : 0);
-}
-
-uint64_t
-mc_asr_to_pa(uint_t mcreg)
-{
- uint64_t pa, masr, addrmask, lowbitmask;
-
- /*
- * Remove memory present bit.
- */
- masr = (uint64_t)(mcreg & ~STARFIRE_MC_MEM_PRESENT_MASK);
- /*
- * Get mask for bits 32-26.
- */
- lowbitmask = masr & (uint64_t)STARFIRE_MC_MASK_MASK;
- lowbitmask <<= STARFIRE_MC_MASK_SHIFT;
- addrmask = STARFIRE_MC_ADDR_HIBITS | lowbitmask;
-
- pa = (masr << STARFIRE_MC_BASE_SHIFT) & addrmask;
-
- return (pa);
-}
-
-uint_t
-mc_pa_to_asr(uint_t masr, uint64_t pa)
-{
- uint64_t addrmask, lowbitmask;
- uint_t base;
-
- /*
- * Get mask for bits 32-26.
- */
- lowbitmask = masr & (uint64_t)STARFIRE_MC_MASK_MASK;
- lowbitmask <<= STARFIRE_MC_MASK_SHIFT;
- addrmask = STARFIRE_MC_ADDR_HIBITS | lowbitmask;
-
- base = (pa & addrmask) >> STARFIRE_MC_BASE_SHIFT;
- masr &= ~ STARFIRE_MC_MEM_BASEADDR_MASK;
- masr |= base & STARFIRE_MC_MEM_BASEADDR_MASK;
-
- ASSERT(mc_asr_to_pa(masr) == pa);
-
- return (masr);
-}
diff --git a/usr/src/uts/sun4u/starfire/io/ngdr.conf b/usr/src/uts/sun4u/starfire/io/ngdr.conf
deleted file mode 100644
index 85b7a4e81f..0000000000
--- a/usr/src/uts/sun4u/starfire/io/ngdr.conf
+++ /dev/null
@@ -1,28 +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.
-#
-#ident "%Z%%M% %I% %E% SMI"
-
-name="ngdr" parent="pseudo" instance=0;
diff --git a/usr/src/uts/sun4u/starfire/io/portctrl.c b/usr/src/uts/sun4u/starfire/io/portctrl.c
deleted file mode 100644
index adfe173833..0000000000
--- a/usr/src/uts/sun4u/starfire/io/portctrl.c
+++ /dev/null
@@ -1,271 +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 1990-2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-#include <sys/cmn_err.h>
-#include <sys/kmem.h>
-#include <sys/debug.h>
-#include <sys/machsystm.h>
-#include <sys/starfire.h>
-
-/*
- * Interrupt target translation data for
- * Starfire's Port controller asics
- */
-struct pc_ittrans_data {
- kmutex_t ittrans_lock; /* lock for ITTR array */
- volatile uint64_t *ittrans_mondovec[32]; /* mondovecreg addr array */
- uint64_t ittransreg_physaddr[32]; /* ITTREG physaddr array */
-};
-
-/*
- * Setup and initialize the soft table that
- * represent the Starfire interrupt target translation
- * registers in the Port controller asics. There is one
- * for each sysio/pci instance.
- */
-void
-pc_ittrans_init(int upa_id, caddr_t *ittptr_cookie)
-{
- int i;
- uint64_t physaddr;
- struct pc_ittrans_data *tmpptr;
-
- ASSERT(ittptr_cookie != NULL);
-
- /*
- * Allocate the data structure to support starfire's
- * interrupt target translations
- */
- tmpptr = (struct pc_ittrans_data *)
- kmem_zalloc(sizeof (struct pc_ittrans_data),
- KM_SLEEP);
-
- /* Initialize the ittrans lock */
- mutex_init(&tmpptr->ittrans_lock, NULL, MUTEX_DEFAULT, NULL);
-
- /*
- * Construct the base physical address of the
- * ITTR registers associated with this PC asics
- */
- physaddr = STARFIRE_UPAID2UPS(upa_id);
- physaddr |= (STARFIRE_PSI_BASE | STARFIRE_PSI_PCREG_OFF |
- STARFIRE_PC_INT_MAP);
-
- /*
- * Initialize the ITTR table
- * This soft table is used to represent the interrupt
- * target translation hardware registers in the Starfire's
- * PC asics. There are 32 slots and each slot consists of
- * a mondovec regaddr entry and the physical address of
- * the that ITT register. A empty slot is one whose
- * mondovec entry is null. To reserve/use a slot for a
- * particular intr mapping reg, we simply find
- * a empty slot and write in the mondovec mapping
- * regaddr into the mondovec field.
- */
- for (i = 0; i < 32; i++) {
- tmpptr->ittrans_mondovec[i] = NULL;
- tmpptr->ittransreg_physaddr[i] = physaddr + i*16;
- }
-
- *ittptr_cookie = (caddr_t)tmpptr;
-}
-
-void
-pc_ittrans_uninit(caddr_t ittr_cookie)
-{
- struct pc_ittrans_data *tmpptr;
-
- ASSERT(ittr_cookie != NULL);
-
- tmpptr = (struct pc_ittrans_data *)ittr_cookie;
-
- mutex_destroy(&tmpptr->ittrans_lock);
- kmem_free((int *)ittr_cookie, sizeof (struct pc_ittrans_data));
-}
-
-/*
- * This routine searches for a slot in the soft ITTR table
- * that was reserved earlier by matching the mondovec
- * mapping regaddr argument with the corresponding field in
- * the table. Note that the soft ITTR table mirrors the
- * corresponding hw table in the starfire port controller(PC)
- * asics. A new slot will be obtained if the slot cannot
- * be found. (not reserved previously). The routine then programs
- * in the target cpu id into the PC ITTR hardware, updates the
- * soft table and return the index to this slot as the target
- * id cookie.
- */
-int
-pc_translate_tgtid(caddr_t ittr_cookie, int cpu_id,
- volatile uint64_t *mondovec_addr)
-{
- struct pc_ittrans_data *ittptr;
- int i;
- int foundslot = -1;
-
- ASSERT(ittr_cookie != NULL);
-
- ittptr = (struct pc_ittrans_data *)ittr_cookie;
-
- mutex_enter(&ittptr->ittrans_lock);
-
- /*
- * Search the mondovec addrlist to see if we
- * already reserved/used a slot for this particular
- * mondovec mapping regaddr.
- */
- for (i = 0; i < 32; i++) {
- if (mondovec_addr == ittptr->ittrans_mondovec[i]) {
- /*
- * found the slot that matches the
- * mondo vec in question
- */
- foundslot = i;
- break;
- }
- if (foundslot == -1 && ittptr->ittrans_mondovec[i] == NULL)
- /* keep track of a empty slot */
- foundslot = i;
- }
-
- if (foundslot != -1) {
- /* We found a slot for this mondo vec, let's use it */
- stphysio(ittptr->ittransreg_physaddr[foundslot],
- STARFIRE_UPAID2HWMID(cpu_id));
- ittptr->ittrans_mondovec[foundslot] = mondovec_addr;
- } else {
- cmn_err(CE_PANIC, "No more ITTR slots!!");
- }
-
- mutex_exit(&ittptr->ittrans_lock);
- return (foundslot);
-}
-
-/*
- * This routine searches the interrupt target translation table
- * (if exists) for a slot that was reserved/used earlier by
- * matching the mondovec_addr input argument with the mondovec
- * field in the table. The routine then free the found slot by
- * resetting it to zero.
- */
-void
-pc_ittrans_cleanup(caddr_t ittr_cookie,
- volatile uint64_t *mondovec_addr)
-{
-
- struct pc_ittrans_data *ittptr;
- int i;
- int foundslot = -1;
-
- ASSERT(ittr_cookie != NULL);
-
- ittptr = (struct pc_ittrans_data *)ittr_cookie;
-
- mutex_enter(&ittptr->ittrans_lock);
-
- /*
- * Search the mondovec addrlist for the reserved/used
- * slot associated with this particular mondo vector.
- */
- for (i = 0; i < 32; i++) {
- if (mondovec_addr == ittptr->ittrans_mondovec[i]) {
- /*
- * found the slot that matches the
- * mondo vec in question
- */
- foundslot = i;
- break;
- }
- }
-
- if (foundslot != -1) {
- /* We found a slot for this mondo vec, clear it */
- ittptr->ittrans_mondovec[foundslot] = 0;
- }
-
- mutex_exit(&ittptr->ittrans_lock);
-}
-
-int
-pc_madr_add(int lboard, int rboard, int proc, uint_t madr)
-{
- register int i;
- uint_t madr_rd, madr_off;
- uint64_t pc_madr_addr;
-
- pc_madr_addr = STARFIRE_PC_MADR_ADDR(lboard, rboard, proc);
-
- /*
- * First write with Presence bit disabled
- * and then with it enabled.
- */
- madr_off = madr & ~STARFIRE_MC_MEM_PRESENT_MASK;
- stphysio(pc_madr_addr, madr_off);
-
- for (i = 0; i < 20; i++) {
- madr_rd = ldphysio(pc_madr_addr);
- if (madr_off == madr_rd)
- break;
- }
- if (madr_off != madr_rd) {
- cmn_err(CE_WARN,
- "pc_madr_add: (1) failed to update "
- "PC MADR (%d, %d, %d, 0x%x)\n",
- lboard, rboard, proc, madr);
- return (-1);
- }
- if (madr == madr_off) {
- /*
- * Caller wanted to write value out there
- * with presence bit turned off, which is
- * what we just completed. So, we're finished.
- */
- return (0);
- }
- /*
- * Now write with Presence bit enabled.
- */
- stphysio(pc_madr_addr, madr);
-
- for (i = 0; i < 20; i++) {
- madr_rd = ldphysio(pc_madr_addr);
- if (madr == madr_rd)
- break;
- }
- if (madr != madr_rd) {
- cmn_err(CE_WARN,
- "pc_madr_add: (2) failed to update "
- "PC MADR (%d, %d, %d, 0x%x)\n",
- lboard, rboard, proc, madr);
- return (-1);
- }
-
- return (0);
-}
diff --git a/usr/src/uts/sun4u/starfire/ml/drmach.il.cpp b/usr/src/uts/sun4u/starfire/ml/drmach.il.cpp
deleted file mode 100644
index f948876aa4..0000000000
--- a/usr/src/uts/sun4u/starfire/ml/drmach.il.cpp
+++ /dev/null
@@ -1,222 +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 2001,2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file is through cpp before being used as
- * an inline. It contains support routines used
- * only by DR for the copy-rename sequence.
- */
-
-#if defined(lint)
-#include <sys/types.h>
-#endif /* lint */
-
-#ifndef INLINE
-
-#include <sys/asm_linkage.h>
-
-#else /* INLINE */
-
-#define ENTRY_NP(x) .inline x,0
-#define retl /* nop */
-#define SET_SIZE(x) .end
-
-#endif /* INLINE */
-
-#include <sys/privregs.h>
-#include <sys/sun4asi.h>
-#include <sys/machparam.h>
-
-/*
- * Bcopy routine used by DR to copy
- * between physical addresses.
- * Borrowed from Starfire DR 2.6.
- */
-#if defined(lint)
-
-/*ARGSUSED*/
-void
-bcopy32_il(uint64_t paddr1, uint64_t paddr2)
-{}
-
-#else /* lint */
-
- ENTRY_NP(bcopy32_il)
- .register %g2, #scratch
- .register %g3, #scratch
- rdpr %pstate, %o4
- andn %o4, PSTATE_IE | PSTATE_AM, %g3 ! clear IE, AM bits
- wrpr %g0, %g3, %pstate
-
- ldxa [%o0]ASI_MEM, %o2
- add %o0, 8, %o0
- ldxa [%o0]ASI_MEM, %o3
- add %o0, 8, %o0
- ldxa [%o0]ASI_MEM, %g1
- add %o0, 8, %o0
- ldxa [%o0]ASI_MEM, %g2
-
- stxa %o2, [%o1]ASI_MEM
- add %o1, 8, %o1
- stxa %o3, [%o1]ASI_MEM
- add %o1, 8, %o1
- stxa %g1, [%o1]ASI_MEM
- add %o1, 8, %o1
- stxa %g2, [%o1]ASI_MEM
-
- retl
- wrpr %g0, %o4, %pstate ! restore earlier pstate register value
- SET_SIZE(bcopy32_il)
-
-#endif /* lint */
-
-#if defined(lint)
-
-/*ARGSUSED*/
-void
-flush_ecache_il(uint64_t physaddr, uint_t size, uint_t linesize)
-{}
-
-#else /* lint */
-
- ENTRY_NP(flush_ecache_il)
- srl %o1, 0, %o1 ! clear upper 32 bits
- srl %o2, 0, %o2 ! clear upper 32 bits
- rdpr %pstate, %o3
- andn %o3, PSTATE_IE | PSTATE_AM, %o4
- wrpr %g0, %o4, %pstate ! clear AM to access 64 bit physaddr
- b 2f
- nop
-1:
- ldxa [%o0 + %o1]ASI_MEM, %g0 ! start reading from physaddr + size
-2:
- subcc %o1, %o2, %o1
- bgeu,a 1b
- nop
-
- ! retl
- wrpr %g0, %o3, %pstate ! restore earlier pstate
- SET_SIZE(flush_ecache_il)
-
-#endif /* lint */
-
-#if defined(lint)
-
-/*ARGUSED*/
-void
-stphysio_il(uint64_t physaddr, u_int value)
-{}
-
-/*ARGSUSED*/
-u_int
-ldphysio_il(uint64_t physaddr)
-{ return(0); }
-
-#else /* lint */
-
- ENTRY_NP(stphysio_il)
- rdpr %pstate, %o2 /* read PSTATE reg */
- andn %o2, PSTATE_IE | PSTATE_AM, %o3
- wrpr %g0, %o3, %pstate
- stwa %o1, [%o0]ASI_IO /* store value via bypass ASI */
- retl
- wrpr %g0, %o2, %pstate /* restore the PSTATE */
- SET_SIZE(stphysio_il)
-
- !
- ! load value at physical address in I/O space
- !
- ! u_int ldphysio_il(uint64_t physaddr)
- !
- ENTRY_NP(ldphysio_il)
- rdpr %pstate, %o2 /* read PSTATE reg */
- andn %o2, PSTATE_IE | PSTATE_AM, %o3
- wrpr %g0, %o3, %pstate
- lduwa [%o0]ASI_IO, %o0 /* load value via bypass ASI */
- retl
- wrpr %g0, %o2, %pstate /* restore pstate */
- SET_SIZE(ldphysio_il)
-
-#endif /* lint */
-
-#if defined(lint)
-
-/*
- * Argument to drmach_exec_script_il is a pointer to:
- *
- * typedef struct {
- * uint64_t masr_addr;
- * uint_t masr;
- * uint_t _filler;
- * } drmach_rename_script_t;
- */
-
-/*ARGUSED*/
-void
-drmach_exec_script_il(void *sp)
-{}
-
-#else /* lint */
-
- ENTRY_NP(drmach_exec_script_il)
- mov %o0, %o2
-0: /* cache script */
- ldx [%o2], %o1
- cmp %g0, %o1
- bnz,pt %xcc, 0b
- add %o2, 16, %o2
-
- rdpr %pstate, %o4 /* read PSTATE reg */
- andn %o4, PSTATE_IE | PSTATE_AM, %o1
- wrpr %g0, %o1, %pstate
-
- b 2f /* cache it */
- nop
-1:
- ldx [%o0], %o1
- cmp %g0, %o1
- bz,pn %xcc, 5f
- ld [%o0 + 8], %o2
- b 3f
- stwa %o2, [%o1]ASI_IO
-2:
- b 4f /* cache it */
- nop
-3:
- add %o0, 16, %o0
- b 1b
- lduwa [%o1]ASI_IO, %g0 /* read back to insure written */
-4:
- b 1b /* caching done */
- nop
-5:
- retl
- wrpr %g0, %o4, %pstate /* restore the PSTATE */
- SET_SIZE(drmach_exec_script_il)
-
-#endif /* lint */
diff --git a/usr/src/uts/sun4u/starfire/ml/drmach_asm.s b/usr/src/uts/sun4u/starfire/ml/drmach_asm.s
deleted file mode 100644
index 3c825df992..0000000000
--- a/usr/src/uts/sun4u/starfire/ml/drmach_asm.s
+++ /dev/null
@@ -1,361 +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"
-
-/*
- * This file is through cpp before being used as
- * an inline. It contains support routines used
- * only by DR for the copy-rename sequence.
- */
-
-#if defined(lint)
-#include <sys/types.h>
-#else
-#include "assym.h"
-#endif /* lint */
-
-#include <sys/asm_linkage.h>
-#include <sys/param.h>
-#include <sys/privregs.h>
-#include <sys/machasi.h>
-#include <sys/spitregs.h>
-#include <sys/mmu.h>
-#include <sys/machthread.h>
-#include <sys/pte.h>
-#include <sys/stack.h>
-#include <sys/vis.h>
-
-#ifndef lint
-
-/*
- * arg1 = icache_size
- * arg2 = icache_linesize
- */
-#define ICACHE_FLUSHALL(lbl, arg1, arg2, tmp1) \
- ldxa [%g0]ASI_LSU, tmp1 ;\
- btst LSU_IC, tmp1 ;\
- bz,pn %icc, lbl/**/1 ;\
- sub arg1, arg2, tmp1 ;\
-lbl/**/0: ;\
- stxa %g0, [tmp1]ASI_IC_TAG ;\
- membar #Sync ;\
- cmp %g0, tmp1 ;\
- bne,pt %icc, lbl/**/0 ;\
- sub tmp1, arg2, tmp1 ;\
-lbl/**/1:
-
-/*
- * arg1 = dcache_size
- * arg2 = dcache_linesize
- */
-#define DCACHE_FLUSHALL(lbl, arg1, arg2, tmp1) \
- ldxa [%g0]ASI_LSU, tmp1 ;\
- btst LSU_DC, tmp1 ;\
- bz,pn %icc, lbl/**/1 ;\
- sub arg1, arg2, tmp1 ;\
-lbl/**/0: ;\
- stxa %g0, [tmp1]ASI_DC_TAG ;\
- membar #Sync ;\
- cmp %g0, tmp1 ;\
- bne,pt %icc, lbl/**/0 ;\
- sub tmp1, arg2, tmp1 ;\
-lbl/**/1:
-
-/*
- * arg1 = ecache flush physaddr
- * arg2 = size
- * arg3 = ecache_linesize
- */
-#define ECACHE_FLUSHALL(lbl, arg1, arg2, arg3, tmp1, tmp2) \
- rdpr %pstate, tmp1 ;\
- andn tmp1, PSTATE_IE | PSTATE_AM, tmp2 ;\
- wrpr %g0, tmp2, %pstate ;\
- b lbl/**/1 ;\
-lbl/**/0: ;\
- sub arg2, arg3, arg2 ;\
-lbl/**/1: ;\
- brgez,a arg2, lbl/**/0 ;\
- ldxa [arg1 + arg2]ASI_MEM, %g0 ;\
- wrpr %g0, tmp1, %pstate
-
-#ifdef SF_ERRATA_32
-#define SF_WORKAROUND(tmp1, tmp2) \
- sethi %hi(FLUSH_ADDR), tmp2 ;\
- set MMU_PCONTEXT, tmp1 ;\
- stxa %g0, [tmp1]ASI_DMMU ;\
- flush tmp2 ;
-#else
-#define SF_WORKAROUND(tmp1, tmp2)
-#endif /* SF_ERRATA_32 */
-
-/*
- * arg1 = vaddr
- * arg2 = ctxnum
- * - disable interrupts and clear address mask
- * to access 64 bit physaddr
- * - Blow out the TLB.
- * . If it's kernel context, then use primary context.
- * . Otherwise, use secondary.
- */
-#define VTAG_FLUSHPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4) \
- rdpr %pstate, tmp1 ;\
- andn tmp1, PSTATE_IE | PSTATE_AM, tmp2 ;\
- wrpr tmp2, 0, %pstate ;\
- brnz,pt arg2, lbl/**/1 ;\
- sethi %hi(FLUSH_ADDR), tmp2 ;\
- stxa %g0, [arg1]ASI_DTLB_DEMAP ;\
- stxa %g0, [arg1]ASI_ITLB_DEMAP ;\
- b lbl/**/5 ;\
- flush tmp2 ;\
-lbl/**/1: ;\
- set MMU_SCONTEXT, tmp3 ;\
- ldxa [tmp3]ASI_DMMU, tmp4 ;\
- or DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1 ;\
- cmp tmp4, arg2 ;\
- be,a,pt %icc, lbl/**/4 ;\
- nop ;\
- stxa arg2, [tmp3]ASI_DMMU ;\
-lbl/**/4: ;\
- stxa %g0, [arg1]ASI_DTLB_DEMAP ;\
- stxa %g0, [arg1]ASI_ITLB_DEMAP ;\
- flush tmp2 ;\
- be,a,pt %icc, lbl/**/5 ;\
- nop ;\
- stxa tmp4, [tmp3]ASI_DMMU ;\
- flush tmp2 ;\
-lbl/**/5: ;\
- wrpr %g0, tmp1, %pstate
-
-/*
- * arg1 = dtlb entry
- * - Before first compare:
- * tmp4 = tte
- * tmp5 = vaddr
- * tmp6 = cntxnum
- */
-#define DTLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \
- tmp4, tmp5, tmp6) \
-lbl/**/0: ;\
- sllx arg1, 3, tmp3 ;\
- SF_WORKAROUND(tmp1, tmp2) ;\
- ldxa [tmp3]ASI_DTLB_ACCESS, tmp4 ;\
- srlx tmp4, 6, tmp4 ;\
- andcc tmp4, 1, %g0 ;\
- bnz,pn %xcc, lbl/**/1 ;\
- srlx tmp4, 57, tmp4 ;\
- andcc tmp4, 1, %g0 ;\
- beq,pn %xcc, lbl/**/1 ;\
- nop ;\
- set TAGREAD_CTX_MASK, tmp1 ;\
- ldxa [tmp3]ASI_DTLB_TAGREAD, tmp2 ;\
- and tmp2, tmp1, tmp6 ;\
- andn tmp2, tmp1, tmp5 ;\
- VTAG_FLUSHPAGE(VD, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\
-lbl/**/1: ;\
- brgz,pt arg1, lbl/**/0 ;\
- sub arg1, 1, arg1
-
-/*
- * arg1 = itlb entry
- * - Before first compare:
- * tmp4 = tte
- * tmp5 = vaddr
- * tmp6 = cntxnum
- */
-#define ITLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \
- tmp4, tmp5, tmp6) \
-lbl/**/0: ;\
- sllx arg1, 3, tmp3 ;\
- SF_WORKAROUND(tmp1, tmp2) ;\
- ldxa [tmp3]ASI_ITLB_ACCESS, tmp4 ;\
- srlx tmp4, 6, tmp4 ;\
- andcc tmp4, 1, %g0 ;\
- bnz,pn %xcc, lbl/**/1 ;\
- srlx tmp4, 57, tmp4 ;\
- andcc tmp4, 1, %g0 ;\
- beq,pn %xcc, lbl/**/1 ;\
- nop ;\
- set TAGREAD_CTX_MASK, tmp1 ;\
- ldxa [tmp3]ASI_ITLB_TAGREAD, tmp2 ;\
- and tmp2, tmp1, tmp6 ;\
- andn tmp2, tmp1, tmp5 ;\
- VTAG_FLUSHPAGE(VI, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\
-lbl/**/1: ;\
- brgz,pt arg1, lbl/**/0 ;\
- sub arg1, 1, arg1
-
-#define CLEARTL(lvl) \
- wrpr %g0, lvl, %tl ;\
- wrpr %g0, %g0, %tpc ;\
- wrpr %g0, %g0, %tnpc ;\
- wrpr %g0, %g0, %tt
-
-#define SWITCH_STACK(estk) \
- flushw ;\
- sub estk, SA(KFPUSIZE+GSR_SIZE), estk ;\
- andn estk, 0x3f, estk ;\
- sub estk, SA(MINFRAME) + STACK_BIAS, %sp ;\
- mov estk, %fp
-
-#endif /* !lint */
-
-#if defined(lint)
-
-/*ARGSUSED*/
-void
-drmach_shutdown_asm(uint64_t mbox_addr)
-{}
-
-#else /* lint */
-
- ENTRY_NP(drmach_shutdown_asm)
- mov %o0, %o5
-
- ldxa [%o5]ASI_MEM, %o0 ! get 8-byte estack in o0
- add %o5, 8, %o5
- ldxa [%o5]ASI_MEM, %o1 ! get 8-byte flushaddr in o1
- add %o5, 8, %o5
- lda [%o5]ASI_MEM, %o2 ! get 4-byte size in o2
- srl %o2, 0, %o2
- add %o5, 4, %o5
- lda [%o5]ASI_MEM, %o3 ! get 4-byte linesize in o3
- srl %o3, 0, %o3
- add %o5, 4, %o5
- ldxa [%o5]ASI_MEM, %o4 ! get 8-byte physaddr in o4
-
-
- ! %o0 = base (va mapping this code in bbsram)
- ! %o1 = flushaddr for ecache
- ! %o2 = size to use for ecache flush
- ! %o3 = ecache linesize
- ! %o4 = phys addr of byte to clear when finished
- !
- ! output: Stores a zero at [%o4]ASI_MEM
-
- membar #LoadStore
-
- !
- ! Switch stack pointer to bbsram
- !
- SWITCH_STACK(%o0)
-
- !
- ! Get some globals
- !
- mov %o3, %g1 ! ecache_linesize
- mov %o4, %o0 ! physaddr byte to clear
-
- sethi %hi(dcache_linesize), %g2
- ld [%g2 + %lo(dcache_linesize)], %g2
-
- sethi %hi(dcache_size), %g3
- ld [%g3 + %lo(dcache_size)], %g3
-
- sethi %hi(icache_linesize), %g4
- ld [%g4 + %lo(icache_linesize)], %g4
-
- sethi %hi(icache_size), %g5
- ld [%g5 + %lo(icache_size)], %g5
-
- sethi %hi(dtlb_entries), %o5
- ld [%o5 + %lo(dtlb_entries)], %o5
- sllx %o5, 32, %o5
- srlx %o5, 32, %o5
-
- sethi %hi(itlb_entries), %o3
- ld [%o3 + %lo(itlb_entries)], %o3
- !
- ! cram Xtlb_entries into a single register (%o5)
- ! %o5 upper 32 = itlb_entries
- ! lower 32 = dtlb_entries
- !
- sllx %o3, 32, %o3
- or %o5, %o3, %o5
-
- !
- ! Flush E$
- !
- ECACHE_FLUSHALL(EC, %o1, %o2, %g1, %o3, %o4)
- !
- ! %o1 & %o2 now available
- !
-
- membar #Sync
-
- !
- ! Flush D$
- !
- DCACHE_FLUSHALL(DC, %g3, %g2, %o3)
-
- !
- ! Flush I$
- !
- ICACHE_FLUSHALL(IC, %g5, %g4, %o3)
-
- membar #Sync
-
- !
- ! Flush dtlb's
- !
- srlx %o5, 32, %g5 ! %g5 = itlb_entries
- sllx %o5, 32, %o5
- srlx %o5, 32, %g1
- sub %g1, 1, %g1 ! %g1 = dtlb_entries - 1
-
- DTLB_FLUSH_UNLOCKED(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5)
-
- !
- ! Flush itlb's
- !
- sub %g5, 1, %g1 ! %g1 = itlb_entries - 1
-
- ITLB_FLUSH_UNLOCKED(I, %g1, %g3, %g4, %o2, %o3, %o4, %o5)
-
- membar #Sync
-
- !
- ! Clear byte to signal finished.
- !
- stba %g0, [%o0]ASI_MEM
- membar #Sync
-
- !
- ! read ensures that last write completed (has left queue in the PC chip)
- !
- lduba [%o0]ASI_MEM, %g0
-5:
- ba 5b
- nop
- SET_SIZE(drmach_shutdown_asm)
-
- .global drmach_shutdown_asm_end
-
- .skip 2048
-
-drmach_shutdown_asm_end:
-
-#endif /* lint */
diff --git a/usr/src/uts/sun4u/starfire/ml/idn_asm.s b/usr/src/uts/sun4u/starfire/ml/idn_asm.s
deleted file mode 100644
index 563fe67286..0000000000
--- a/usr/src/uts/sun4u/starfire/ml/idn_asm.s
+++ /dev/null
@@ -1,385 +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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file contains the low-level DMV interrupt
- * handler for IDN cross-domain interrupts.
- */
-
-#if defined(lint)
-#include <sys/types.h>
-#endif /* lint */
-
-#include <sys/asm_linkage.h>
-#include <sys/machasi.h>
-#include <sys/privregs.h>
-#include <sys/intreg.h>
-#include <sys/machthread.h>
-
-#include <sys/idn.h>
-
-#if !defined(lint)
-#include "idn_offsets.h"
-#endif /* !lint */
-
-#define IDN_MONDO
-
-/*
- * The IDN_DMV_CPU_SHIFT is based on the sizeof (idn_dmv_cpu_t)
- * which must be a power of 2 to optimize calculating our
- * entry into idn_dmv_cpu[].
- */
-#define IDN_DMV_CPU_SHIFT 4
-
-/*
- *--------------------------------------------------------
- */
-#if defined(lint)
-
-/*
- * Would be nice to use init_mondo, but unforunately
- * it assumes the first arg is 32-bits.
- */
-/*ARGSUSED*/
-void
-idnxf_init_mondo(uint64_t arg0, uint64_t arg1, uint64_t arg2)
-{}
-
-#else /* lint */
-
- .global _idn_dispatch_status_busy
-_idn_dispatch_status_busy:
- .asciz "ASI_INTR_DISPATCH_STATUS error: busy"
- .align 4
-
- ENTRY_NP(idnxf_init_mondo)
-#ifdef DEBUG
- !
- ! IDSR should not be busy at the moment - borrowed from init_mondo
- !
- ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1
- btst IDSR_BUSY, %g1
- bz,pt %xcc, 1f
- mov ASI_INTR_DISPATCH, %asi
- sethi %hi(_idn_dispatch_status_busy), %o0
- call panic
- or %o0, %lo(_idn_dispatch_status_busy), %o0
-#endif /* DEBUG */
-
- mov ASI_INTR_DISPATCH, %asi
-1:
- stxa %o0, [IDDR_0]%asi ! dmv_word0
- stxa %o1, [IDDR_1]%asi ! dmv_word1
- stxa %o2, [IDDR_2]%asi ! dmv_word2
-
- retl
- membar #Sync
-
- SET_SIZE(idnxf_init_mondo)
-
-#endif /* lint */
-/*
- *--------------------------------------------------------
- */
-#if defined(lint)
-
-/*
- * Unfortunately, send_mondo is rather picky about getting
- * a result from the cpu it sends an interrupt to. If it
- * doesn't get a result within a specific timeframe it
- * will panic! For IDN that's not cool since a cpu hungup
- * in one could ultimately result in the demise of a cpu
- * in another domain. Instead of getting our panties in
- * a bind, we simply bail out.
- */
-/*ARGSUSED*/
-int
-idnxf_send_mondo(int upaid)
-{ return (0); }
-
-#else /* lint */
-
- .seg ".data"
-
- .global _idn_send_mondo_failure
-_idn_send_mondo_failure:
- .word 0
-
- .seg ".text"
- ENTRY(idnxf_send_mondo)
- !
- ! NOTE:
- ! This is stolen from send_mondo. The changes
- ! are those ifdef'd with IDN_MONDO
- !
- ! construct the interrupt dispatch command register in %g1
- ! also, get the dispatch out as SOON as possible
- ! (initial analysis puts the minimum dispatch time at around
- ! 30-60 cycles. hence, we try to get the dispatch out quickly
- ! and then start the rapid check loop).
- !
- rd %tick, %o4 ! baseline tick
- sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<18:14> = upa port id
- or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70
- stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch
-#if defined(SF_ERRATA_54)
- membar #Sync ! store must occur before load
- mov 0x20, %g3 ! UDBH Control Register Read
- ldxa [%g3]ASI_SDB_INTR_R, %g0
-#endif
- membar #Sync
- clr %o2 ! clear NACK counter
- clr %o3 ! clear BUSY counter
-
- !
- ! how long, in ticks, are we willing to wait completely
- !
- sethi %hi(xc_tick_limit), %g2
- ldx [%g2 + %lo(xc_tick_limit)], %g2
- add %g2, %o4, %o5 ! compute the limit value
-
- !
- ! check the dispatch status
- !
-.check_dispatch:
- ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %o1
- brz,pn %o1, .dispatch_complete
- rd %tick, %g5
-
- !
- ! see if we've gone beyond the limit
- ! (can tick ever overflow?)
- !
-.timeout_primed:
- sub %o5, %g5, %g2 ! limit - tick < 0 if timeout
- brgez,pt %g2, .check_busy
- inc %o3 ! bump the BUSY counter
-
-#ifdef IDN_MONDO
- !
- ! Within the context of IDN we don't want
- ! to panic just because we can't send_mondo.
- ! Clear the dispatch register and increment
- ! our count of failures.
- !
- stxa %g0, [%g1]ASI_INTR_DISPATCH
- sethi %hi(_idn_send_mondo_failure), %o0
- ld [%o0 + %lo(_idn_send_mondo_failure)], %o1
- inc %o1
- st %o1, [%o0 + %lo(_idn_send_mondo_failure)]
- retl
- mov -1, %o0 ! return (-1)
-#else /* IDN_MONDO */
- !
- ! time to die, see if we are already panicing
- !
- mov %o0, %o1 ! save target
- sethi %hi(_send_mondo_nack), %o0
- or %o0, %lo(_send_mondo_nack), %o0
- sethi %hi(panicstr), %g2
- ldn [%g2 + %lo(panicstr)], %g2
- brnz %g2, .dispatch_complete ! skip if already in panic
- nop
- call panic
- nop
-#endif /* IDN_MONDO */
-
-.check_busy:
- btst IDSR_BUSY, %o1 ! was it BUSY?
- bnz,pt %xcc, .check_dispatch
- nop
-
- !
- ! we weren't busy, we must have been NACK'd
- ! wait a while and send again
- ! (this might need jitter)
- !
- sethi %hi(sys_clock_mhz), %g2
- lduw [%g2 + %lo(sys_clock_mhz)], %g2
- rd %tick, %g4
- add %g2, %g4, %g2
-.delay:
- cmp %g2, %g4
- bgu,pt %xcc, .delay
- rd %tick, %g4
-
- stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch
-#if defined(SF_ERRATA_54)
- membar #Sync ! store must occur before load
- ldxa [%g3]ASI_SDB_INTR_R, %g0
-#endif
- membar #Sync
- clr %o3 ! reset BUSY counter
- ba .check_dispatch
- inc %o2 ! bump the NACK counter
-
-.dispatch_complete:
-#ifndef IDN_MONDO
-#ifdef SEND_MONDO_STATS
- !
- ! Increment the appropriate entry in a send_mondo timeout array
- ! x_entry[CPU][MSB]++;
- sub %g5, %o4, %g5 ! how long did we wait?
- clr %o1 ! o1 is now bit counter
-1: orcc %g5, %g0, %g0 ! any bits left?
- srlx %g5, 1, %g5 ! bits to the right
- bne,a,pt %xcc, 1b
- add %o1, 4, %o1 ! pointer increment
-
- !
- ! now compute the base of the x_early entry for our cpu
- !
- CPU_INDEX(%o0, %g5)
- sll %o0, 8, %o0 ! 64 * 4
- add %o0, %o1, %o1 ! %o0 = &[CPU][delay]
-
- !
- ! and increment the appropriate value
- !
- sethi %hi(x_early), %o0
- or %o0, %lo(x_early), %o0
- ld [%o0 + %o1], %g5
- inc %g5
- st %g5, [%o0 + %o1]
-#endif /* SEND_MONDO_STATS */
-#endif /* !IDN_MONDO */
- retl
-#ifdef IDN_MONDO
- mov %g0, %o0 ! return (0)
-#else /* IDN_MONDO */
- nop
-#endif /* IDN_MONDO */
- SET_SIZE(idnxf_send_mondo)
-
-#endif /* lint */
-/*
- *--------------------------------------------------------
- */
-#if defined(lint)
-
-/*ARGSUSED*/
-void
-idn_dmv_handler(void *arg)
-{}
-
-#else /* lint */
-
- ENTRY_NP(idn_dmv_handler)
- !
- ! On entry:
- ! g1 = idn_dmv_data
- ! g2 = word 0
- !
- ldx [%g1 + IDN_DMV_QBASE], %g4 ! g4 = idn_dmv_qbase
- add %g1, IDN_DMV_CPU, %g3 ! g3 = &idn_dmv_cpu[0]
-
- CPU_INDEX(%g6, %g5) ! g6 = cpuid
-
- !
- ! g5 = cur = idn_dmv_cpu[cpuid]
- !
- sll %g6, IDN_DMV_CPU_SHIFT, %g6 ! g6 = cpuid * 8
- add %g3, IDN_DMV_CURRENT, %g3
- ld [%g6 + %g3], %g5
- !
- ! g5 = idn_dmv_cpu[cpuid].idn_dmv_current
- ! offset from idn_dmv_qbase
- !
- or %g5, %g0, %g5 ! get to 64-bits
- add %g5, %g4, %g5 ! g5 = idn_dmv_current
- ! actual address
- ldstub [%g5 + IV_INUSE], %g7 ! cur->iv_inuse = 0xff
- brz,pt %g7, 1f ! did we get it?
- sub %g3, IDN_DMV_CURRENT, %g4
-
- !
- ! Queue is FULL. Drop interrupt.
- !
- add %g4, IDN_DMV_LOSTINTR, %g3
- ld [%g6 + %g3], %g2
- !
- ! g2 = idn_dmv_cpu[cpuid].idn_iv_lostintr++
- !
- inc %g2
- set dmv_finish_intr, %g4
- st %g2, [%g3 + %g6]
- jmp %g4
- mov -1, %g1
- !
- ! not reached
- !
-
-1:
- add %g4, IDN_DMV_ACTIVE, %g7
- !
- ! Move current pointer to next one.
- ! idn_dmv_current[cpuid] = cur->iv_next
- !
- ld [%g5 + IV_NEXT], %g4
- st %g4, [%g3 + %g6]
-
- !
- ! Start filling in structure with data.
- !
- stx %g2, [%g5 + IV_HEAD]
-
- mov IRDR_1, %g2
- mov IRDR_2, %g4
- ldxa [%g2]ASI_INTR_RECEIVE, %g2 ! g2 = xargs[0,1]
- ldxa [%g4]ASI_INTR_RECEIVE, %g4 ! g4 = xargs[2,3]
-
- stx %g2, [%g5 + IV_XARGS0]
- stx %g4, [%g5 + IV_XARGS2]
-
- membar #StoreLoad|#StoreStore
-
- clrb [%g5 + IV_READY] ! cur->iv_ready = 0 (unlocked)
-
- !
- ! See if we're already active, i.e. have things
- ! queued. If so, don't bother generating a soft
- ! interrupt. IDN interrupts could exhaust the
- ! intr_vec structs for the given cpu and that code
- ! doesn't know how to survive with intr_vec structs!
- !
- ldstub [%g6 + %g7], %g7 ! idn_dmv_active = 0xff
- brz,a,pt %g7, 2f
- ldx [%g1 + IDN_SOFT_INUM], %g7 ! g7 = idn_soft_inum
- mov -1, %g7
-2:
-
- !
- ! Setup to cause an IDN soft interrupt to occur,
- ! (if necessary).
- !
- set dmv_finish_intr, %g3
- jmp %g3
- mov %g7, %g1
-
- SET_SIZE(idn_dmv_handler)
-
-#endif /* lint */
diff --git a/usr/src/uts/sun4u/starfire/ml/idn_offsets.in b/usr/src/uts/sun4u/starfire/ml/idn_offsets.in
deleted file mode 100644
index 2a5da76e4b..0000000000
--- a/usr/src/uts/sun4u/starfire/ml/idn_offsets.in
+++ /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 by Sun Microsystems, Inc.
-\ All rights reserved.
-\
-\ Based on sun4u/ml/offsets.in.
-\
-\ Definitions needed by IDN send-mondo support.
-\
-\ Offset definitions for low-level idn_dmv_handler() (assembly code)
-\
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/param.h>
-#include <sys/machparam.h>
-#include <sys/systm.h>
-#include <sys/machsystm.h>
-#include <sys/cpuvar.h>
-
-#include <sys/idn.h>
-
-idn_dmv_cpu_t IDN_DMV_CPU_SIZE
- idn_dmv_current
- idn_dmv_active
- idn_dmv_lostintr
-
-idn_dmv_data_t IDN_DMV_DATA_SIZE
- idn_soft_inum
- idn_dmv_qbase
- idn_dmv_cpu
-
-idn_dmv_msg_t IDN_DMV_MSG_SIZE
- iv_next
- iv_inuse
- iv_ready
- iv_head
- iv_xargs0
- iv_xargs2
diff --git a/usr/src/uts/sun4u/starfire/ngdr/Makefile b/usr/src/uts/sun4u/starfire/ngdr/Makefile
deleted file mode 100644
index 7d68bff634..0000000000
--- a/usr/src/uts/sun4u/starfire/ngdr/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, 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.
-#
-
-#
-# This makefile drives the production of the ngdr driver module.
-#
-# sun4u starfire 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 = ngdr
-OBJECTS = $(DR_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(DR_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/io
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/ngdrmach
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/ngdrmach/Makefile b/usr/src/uts/sun4u/starfire/ngdrmach/Makefile
deleted file mode 100644
index 181e6cf8a6..0000000000
--- a/usr/src/uts/sun4u/starfire/ngdrmach/Makefile
+++ /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, 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) 2011 Bayard G. Bell. All rights reserved.
-#
-# This makefile drives the production of the ngdrmach loadable module.
-#
-# sun4u starfire 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 = ngdrmach
-OBJECTS = $(NGDRMACH_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(NGDRMACH_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_MISC_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# Define dependency on cvc
-#
-LDFLAGS += -dy -N drv/cvc
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/os/bbus_intr.c b/usr/src/uts/sun4u/starfire/os/bbus_intr.c
deleted file mode 100644
index f82d8afc50..0000000000
--- a/usr/src/uts/sun4u/starfire/os/bbus_intr.c
+++ /dev/null
@@ -1,643 +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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/kmem.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <vm/seg.h>
-#include <sys/iommu.h>
-#include <sys/vtrace.h>
-#include <sys/intreg.h>
-#include <sys/ivintr.h>
-#include <sys/cpuvar.h>
-#include <sys/systm.h>
-#include <sys/machsystm.h>
-#include <sys/cyclic.h>
-#include <sys/cpu_sgn.h>
-
-extern cpu_sgnblk_t *cpu_sgnblkp[NCPU];
-extern struct cpu *SIGBCPU;
-extern void power_down(const char *);
-
-uint_t bbus_intr_inum;
-uint64_t bbus_poll_inum;
-
-/*
- * Support for sgnblk polling.
- */
-
-/* Internal function prototypes */
-static void sgnblk_poll_init();
-static uint_t bbus_poll(caddr_t arg1, caddr_t arg2);
-static void sgnblk_poll_handler(void *unused);
-#ifdef THROTTLE
-static void sgnblk_poll_throttle(uint64_t interval);
-#endif /* THROTTLE */
-
-/* Default sgnblk polling interval is every 5 seconds. */
-#define ONE_SECOND (1000000) /* in usecs */
-#ifdef THROTTLE
-#define SGNBLK_POLL_INTERVAL (5 * ONE_SECOND)
-#define SGNBLK_POLL_FAST (ONE_SECOND >> 1)
-#define SGNBLK_POLL_FAST_WIN ((60 * ONE_SECOND) / \
- SGNBLK_POLL_FAST)
-#else /* THROTTLE */
-/*
- * Until we can find a way to throttle back to 0.5 second intervals
- * we're stuck fixed on 2.5 second intervals.
- */
-#define SGNBLK_POLL_INTERVAL ((2 * ONE_SECOND) + (ONE_SECOND >> 1))
-#endif /* THROTTLE */
-
-#define MAX_SGNBLK_POLL_CLNT 5
-
-void (*pollclntfunc[MAX_SGNBLK_POLL_CLNT])();
-/*
- * sgnblk_mutex Protects juggling & sgnblk_poll_refs[].
- * sgnblk_poll_mutex Protects pollclntfunc[].
- */
-kmutex_t sgnblk_mutex;
-kmutex_t sgnblk_poll_mutex;
-static uint64_t sgnblk_poll_interval = SGNBLK_POLL_INTERVAL;
-#ifdef THROTTLE
-static uint64_t sgnblk_poll_fast = SGNBLK_POLL_FAST;
-static int64_t sgnblk_poll_fast_win = SGNBLK_POLL_FAST_WIN;
-#endif /* THROTTLE */
-static processorid_t sgnblk_pollcpu = -1;
-/*
- * Note that the sigblock polling depends on CY_HIGH_LEVEL
- * being higher than PIL_13 since we ultimately need to
- * dispatch a PIL_13 soft handler.
- * Also, we assume one sgnblk handler for the entire system.
- * Once upon a time we had them per-cpu. With the Cyclic stuff
- * we would have to bind our cyclic handler to a cpu and doing
- * this prevents that cpu from being offlined. Since the Cyclic
- * subsystem could indirectly juggle us without us knowing we
- * have to assume we're running from any possible cpu and not
- * always SIGBCPU.
- */
-#ifdef THROTTLE
-static cyclic_id_t sgnblk_poll_cycid = CYCLIC_NONE;
-#endif /* THROTTLE */
-static cyc_handler_t sgnblk_poll_cychandler = {
- sgnblk_poll_handler,
- NULL,
- CY_HIGH_LEVEL
-};
-static cyc_time_t sgnblk_poll_time;
-
-/*
- * Anybody that references the polling (SIGBCPU) can
- * register a callback function that will be called if
- * the polling cpu is juggled, e.g. during a DR operation.
- */
-#define MAX_SGNBLK_POLL_REFS 10
-
-struct sgnblk_poll_refs {
- void (*callback)(cpu_sgnblk_t *sigbp, void *arg);
- void *arg;
-} sgnblk_poll_refs[MAX_SGNBLK_POLL_REFS];
-
-/*
- * Bootbus intr handler: Generic handler for all SSP/CBS
- * interrupt requests initiated via the hw bootbus intr
- * mechanism. This is similar to the level15
- * interrupt handling for sigb commands in the CS6400.
- * Most of these code were stolen from the sigb stuff in
- * in CS6400.
- */
-
-extern struct cpu cpu0;
-
-/*ARGSUSED*/
-static uint_t
-bbus_intr(caddr_t arg)
-{
- int cmd = 0;
- processorid_t cpu_id = CPU->cpu_id;
- int retflag;
- int resp = 0;
- proc_t *initpp;
-
- ASSERT(cpu_sgnblkp[cpu_id] != NULL);
-
- /*
- * Check for unsolicited messages in the host's mailbox.
- */
- retflag = cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag;
-
- switch (retflag) {
- case CBS_TO_HOST:
- retflag = HOST_TO_CBS;
- break;
- default:
- retflag = SIGB_MBOX_EMPTY;
- break;
- }
- if (retflag == SIGB_MBOX_EMPTY)
- return (0); /* interrupt not claimed */
-
- /*
- * We only look for UNSOLICITED messages, i.e. commands.
- * Responses to these commands are returned into the same
- * mailbox from which the command was received, i.e. host's.
- *
- * If the host should solicit a message from the SSP, that
- * message/command goes into the SSP's mailbox (sigb_ssp_mbox).
- * The responses (from the SSP) to these messages will be
- * read from the ssp mailbox by whomever solicited it, but
- * will NOT be handled through this level 15 interrupt
- * mechanism.
- *
- * Note that use of the flag field of the signature block mailbox
- * structure and the mailbox protocol itself, serializes access
- * to these mailboxes.
- */
-
- resp = 0;
-
- /*
- * The first sizeof (uint_t) bytes of the data field
- * is the command.
- */
- cmd = cpu_sgnblkp[cpu_id]->sigb_host_mbox.cmd;
-
- switch (cmd) {
- case SSP_GOTO_OBP:
- /*
- * Let's set the mailbox flag to BUSY while we are in OBP
- */
- cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = SIGB_MBOX_BUSY;
-
- debug_enter("SSP requested (SSP_GOTO_OBP)");
- /*
- * This command does NOT require a response.
- */
- resp = 0;
- break;
-
- case SSP_GOTO_PANIC:
- /*
- * Let's reset the mailbox flag before we bail.
- */
- cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = SIGB_MBOX_EMPTY;
-
- cmn_err(CE_PANIC, "SSP requested (SSP_GOTO_PANIC)\n");
- /* should never reach this point */
-
- resp = 0;
- break;
- case SSP_ENVIRON:
- /*
- * Environmental Interrupt.
- */
-
- /*
- * Send SIGPWR to init(1) it will run rc0, which will uadmin to
- * powerdown.
- */
-
- mutex_enter(&pidlock);
- initpp = prfind(P_INITPID);
- mutex_exit(&pidlock);
-
- /*
- * If we're still booting and init(1) isn't set up yet,
- * simply halt.
- */
- if (initpp == NULL) {
- extern void halt(char *);
- cmn_err(CE_WARN, "?Environmental Interrupt");
- power_down((char *)NULL);
- halt("Power off the System!\n"); /* just in case */
- }
-
- /*
- * else, graceful shutdown with inittab and all getting involved
- *
- * XXX: Do we Need to modify the init process for the Cray 6400!
- */
- psignal(initpp, SIGPWR);
-
- /*
- * XXX: kick off a sanity timeout panic in case the /etc/inittab
- * or /etc/rc0 files are hosed. The 6400 needs to hang here
- * when we return from psignal.
- *
- * cmn_err(CE_PANIC, "SSP requested (SSP_ENVIRON)\n");
- * should never reach this point
- */
-
- resp = 0;
- break;
- /*
- * Could handle more mailbox commands right here.
- */
-
- default:
- resp = SIGB_BAD_MBOX_CMD;
- break;
- }
-
- /*
- * If resp is non-zero then we'll automatically reset
- * the handler_sigb lock once we've sent the response,
- * however if no response is needed, then resetlck must
- * be set so that the handler_sigb lock is reset.
- */
- if (resp != 0) {
- /*
- * Had some kind of trouble handling the mailbox
- * command. Need to send back an error response
- * and back out of the cpu_sgnblk handling.
- */
- cpu_sgnblkp[cpu_id]->sigb_host_mbox.cmd = resp;
- bcopy((caddr_t)&cmd,
- (caddr_t)&cpu_sgnblkp[cpu_id]->sigb_host_mbox.data[0],
- sizeof (cmd));
- cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = retflag;
- } else {
- /*
- * No response expected, but we still have to
- * reset the flag to empty for the next person.
- */
- cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = SIGB_MBOX_EMPTY;
- }
- return (1); /* interrupt claimed */
-}
-
-void
-register_bbus_intr()
-{
- /*
- * Starfire's ASIC have the capability to generate a mondo
- * vector. The SSP uses this capability via the Boot Bus to
- * send an interrupt to a domain.
- *
- * The SSP generates a mondo with:
- * ign = UPAID_TO_IGN(bootcpu_upaid)
- * ino = 0
- *
- * An interrupt handler is added for this inum.
- */
- bbus_intr_inum = UPAID_TO_IGN(cpu0.cpu_id) * MAX_INO;
- VERIFY(add_ivintr(bbus_intr_inum, PIL_13, (intrfunc)bbus_intr,
- NULL, NULL, NULL) == 0);
-
-
- /*
- * Due to a HW flaw in starfire, liberal use
- * of bootbus intrs under heavy system load
- * may cause the machine to arbstop. The workaround
- * is to provide a polling mechanism thru the signature
- * block interface to allow another way for the SSP to
- * interrupt the host. Applications like IDN which generate
- * a high degree of SSP to host interruptions for
- * synchronization will need to use the polling facility
- * instead of the hw bootbus interrupt mechanism.
- * The HW bootbus intr support is left intact as it
- * will still be used by existing SSP applications for system
- * recovery in the event of system hangs etc.. In such situations,
- * HW bootbus intr is a better mechanism as it is HW generated
- * level 15 interrupt that has a better chance of kicking
- * a otherwise hung OS into recovery.
- *
- * Polling is done by scheduling a constant tick timer
- * interrupt at a certain predefined interval.
- * The handler will do a poll and if there is a
- * "intr" request, scheduled a soft level 13 intr
- * to handle it. Allocate the inum for the level
- * 13 intr here.
- */
- bbus_poll_inum = add_softintr(PIL_13, bbus_poll, 0, SOFTINT_ST);
-}
-
-static void
-sgnblk_poll_init()
-{
- ASSERT(MUTEX_HELD(&sgnblk_mutex));
-
- mutex_init(&sgnblk_poll_mutex, NULL,
- MUTEX_SPIN, (void *)ipltospl(PIL_14));
- sgnblk_pollcpu = SIGBCPU->cpu_id;
- mutex_enter(&cpu_lock);
- sgnblk_poll_time.cyt_when = 0ull;
- sgnblk_poll_time.cyt_interval = sgnblk_poll_interval * 1000ull;
-#ifdef THROTTLE
- sgnblk_poll_cycid = cyclic_add(&sgnblk_poll_cychandler,
- &sgnblk_poll_time);
-#else /* THROTTLE */
- (void) cyclic_add(&sgnblk_poll_cychandler, &sgnblk_poll_time);
-#endif /* THROTTLE */
- mutex_exit(&cpu_lock);
- ASSERT(sgnblk_pollcpu == SIGBCPU->cpu_id);
-}
-
-int
-sgnblk_poll_register(void(*func)(processorid_t cpu_id,
- cpu_sgnblk_t *cpu_sgnblkp))
-{
- int i;
-
- /*
- * See if we need to initialize
- * sgnblk polling
- */
- mutex_enter(&sgnblk_mutex);
- if (sgnblk_pollcpu == -1)
- sgnblk_poll_init();
- mutex_exit(&sgnblk_mutex);
-
- mutex_enter(&sgnblk_poll_mutex);
-
- /*
- * Look for a empty slot
- */
- for (i = 0; i < MAX_SGNBLK_POLL_CLNT; i++) {
- if (pollclntfunc[i] == NULL) {
- pollclntfunc[i] = func;
- mutex_exit(&sgnblk_poll_mutex);
- return (1);
- }
- }
- mutex_exit(&sgnblk_poll_mutex);
- return (0); /* failed */
-}
-
-int
-sgnblk_poll_unregister(void(*func)(processorid_t cpu_id,
- cpu_sgnblk_t *cpu_sgnblkp))
-{
- int i;
-
- mutex_enter(&sgnblk_poll_mutex);
-
- /*
- * Look for the slot matching the function passed in.
- */
- for (i = 0; i < MAX_SGNBLK_POLL_CLNT; i++) {
- if (pollclntfunc[i] == func) {
- pollclntfunc[i] = NULL;
- mutex_exit(&sgnblk_poll_mutex);
- return (1);
- }
- }
- mutex_exit(&sgnblk_poll_mutex);
- return (0); /* failed */
-}
-
-
-/*
- * For DR support.
- * Juggle poll tick client to another cpu
- * Assumed to be called single threaded.
- */
-void
-juggle_sgnblk_poll(struct cpu *cp)
-{
- int i;
-
- mutex_enter(&sgnblk_mutex);
-
- if (sgnblk_pollcpu == -1 ||
- (cp != NULL && sgnblk_pollcpu == cp->cpu_id)) {
- mutex_exit(&sgnblk_mutex);
- return;
- }
-
- /*
- * Disable by simply returning here
- * Passing a null cp is assumed to be
- * sgnpoll disable request.
- */
- if (cp == NULL) {
- for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) {
- void (*func)(), *arg;
-
- if ((func = sgnblk_poll_refs[i].callback) != NULL) {
- arg = sgnblk_poll_refs[i].arg;
- (*func)(NULL, arg);
- }
- }
- mutex_exit(&sgnblk_mutex);
- return;
- }
-
- sgnblk_pollcpu = cp->cpu_id;
-
- for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) {
- void (*func)(), *arg;
-
- if ((func = sgnblk_poll_refs[i].callback) != NULL) {
- arg = sgnblk_poll_refs[i].arg;
- (*func)(cpu_sgnblkp[sgnblk_pollcpu], arg);
- }
- }
-
- mutex_exit(&sgnblk_mutex);
-}
-
-#ifdef THROTTLE
-/*ARGSUSED0*/
-static void
-_sgnblk_poll_throttle(void *unused)
-{
- mutex_enter(&cpu_lock);
- if (sgnblk_poll_cycid != CYCLIC_NONE) {
- cyclic_remove(sgnblk_poll_cycid);
- sgnblk_poll_cycid = CYCLIC_NONE;
- }
-
- if (sgnblk_poll_time.cyt_interval > 0ull)
- sgnblk_poll_cycid = cyclic_add(&sgnblk_poll_cychandler,
- &sgnblk_poll_time);
- mutex_exit(&cpu_lock);
-}
-
-/*
- * We don't want to remove the cyclic within the context of
- * the handler so we kick off the throttle in background
- * via a timeout call.
- */
-static void
-sgnblk_poll_throttle(uint64_t new_interval)
-{
- mutex_enter(&cpu_lock);
- sgnblk_poll_time.cyt_when = 0ull;
- sgnblk_poll_time.cyt_interval = new_interval * 1000ull;
- mutex_exit(&cpu_lock);
-
- (void) timeout(_sgnblk_poll_throttle, NULL, (clock_t)0);
-}
-#endif /* THROTTLE */
-
-/*
- * High priority interrupt handler (PIL_14)
- * for signature block mbox polling.
- */
-/*ARGSUSED0*/
-static void
-sgnblk_poll_handler(void *unused)
-{
- processorid_t cpuid = SIGBCPU->cpu_id;
-#ifdef THROTTLE
- static int64_t sb_window = -1;
- static uint64_t sb_interval = 0;
-#endif /* THROTTLE */
-
- if (cpu_sgnblkp[cpuid] == NULL)
- return;
-
- /*
- * Poll for SSP requests
- */
- if (cpu_sgnblkp[cpuid]->sigb_host_mbox.intr == SIGB_INTR_SEND) {
- /* reset the flag - sure hope this is atomic */
- cpu_sgnblkp[cpuid]->sigb_host_mbox.intr = SIGB_INTR_OFF;
-
-#ifdef THROTTLE
- /*
- * Go into fast poll mode for a short duration
- * (SGNBLK_POLL_FAST_WIN) in SGNBLK_POLL_FAST interval.
- * The assumption here is that we just got activity
- * on the mbox poll, the probability of more coming down
- * the pipe is high - so let's look more often.
- */
- if ((sb_window < 0) && (sb_interval > sgnblk_poll_fast)) {
- sb_interval = sgnblk_poll_fast;
- sgnblk_poll_throttle(sb_interval);
- }
- sb_window = sgnblk_poll_fast_win;
-#endif /* THROTTLE */
-
- /* schedule poll processing */
- setsoftint(bbus_poll_inum);
-
-#ifdef THROTTLE
- } else if (sb_window >= 0) {
- /* Revert to slow polling once fast window ends */
- if ((--sb_window < 0) &&
- (sb_interval < sgnblk_poll_interval)) {
- sb_interval = sgnblk_poll_interval;
- sgnblk_poll_throttle(sb_interval);
- }
-#endif /* THROTTLE */
- }
-}
-
-/*ARGSUSED*/
-static uint_t
-bbus_poll(caddr_t arg1, caddr_t arg2)
-{
- int i;
- processorid_t cpu_id = SIGBCPU->cpu_id;
- cpu_sgnblk_t *sgnblkp = cpu_sgnblkp[cpu_id];
-
- /*
- * Go thru the poll client array and call the
- * poll client functions one by one
- */
- mutex_enter(&sgnblk_poll_mutex);
-
- for (i = 0; i < MAX_SGNBLK_POLL_CLNT; i++) {
- void (*func)(processorid_t cpuid, cpu_sgnblk_t *sgnblkp);
-
- if ((func = pollclntfunc[i]) != NULL) {
- mutex_exit(&sgnblk_poll_mutex);
- (*func)(cpu_id, sgnblkp);
- mutex_enter(&sgnblk_poll_mutex);
- }
- }
- mutex_exit(&sgnblk_poll_mutex);
-
- return (1);
-}
-
-int
-sgnblk_poll_reference(void (*callback)(cpu_sgnblk_t *sigb, void *arg),
- void *arg)
-{
- int i, slot;
- cpu_sgnblk_t *sigbp;
-
- if (callback == NULL)
- return (-1);
-
- mutex_enter(&sgnblk_mutex);
- /*
- * First verify caller is not already registered.
- */
- slot = -1;
- for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) {
- if ((slot == -1) && (sgnblk_poll_refs[i].callback == NULL)) {
- slot = i;
- continue;
- }
- if (sgnblk_poll_refs[i].callback == callback) {
- mutex_exit(&sgnblk_mutex);
- return (-1);
- }
- }
- /*
- * Now find an empty entry.
- */
- if (slot == -1) {
- mutex_exit(&sgnblk_mutex);
- return (-1);
- }
- sgnblk_poll_refs[slot].callback = callback;
- sgnblk_poll_refs[slot].arg = arg;
-
- sigbp = (sgnblk_pollcpu != -1) ? cpu_sgnblkp[sgnblk_pollcpu] : NULL;
-
- (*callback)(sigbp, arg);
-
- mutex_exit(&sgnblk_mutex);
-
- return (0);
-}
-
-void
-sgnblk_poll_unreference(void (*callback)(cpu_sgnblk_t *sigb, void *arg))
-{
- int i;
-
- mutex_enter(&sgnblk_mutex);
- for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) {
- if (sgnblk_poll_refs[i].callback == callback) {
- void *arg;
-
- arg = sgnblk_poll_refs[i].arg;
- (*callback)(NULL, arg);
- sgnblk_poll_refs[i].callback = NULL;
- sgnblk_poll_refs[i].arg = NULL;
- break;
- }
- }
- mutex_exit(&sgnblk_mutex);
-}
diff --git a/usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c b/usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c
deleted file mode 100644
index be505da37b..0000000000
--- a/usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c
+++ /dev/null
@@ -1,181 +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"
-
-/*
- * Following is STARFIRE specific code
- */
-
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/archsystm.h>
-#include <sys/machsystm.h>
-#include <sys/vmem.h>
-#include <sys/mman.h>
-#include <sys/vm.h>
-
-#include <sys/cmn_err.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/starfire.h>
-
-#include <vm/seg.h>
-#include <vm/seg_kmem.h>
-#include <vm/seg_kp.h>
-#include <sys/vtrace.h>
-#include <sys/cpu_sgn.h>
-
-/*
- * SIGBCPU represents the cpu maintaining the primary
- * sigblock (bbsram). This bbsram is used for CVC
- * and maintains the post2obp structure. It starts
- * out as the bootproc (cpu0).
- */
-struct cpu *SIGBCPU = &cpu0;
-
-cpu_sgnblk_t *cpu_sgnblkp[NCPU];
-
-/*
- * Mapin the the cpu's signature block.
- */
-void
-cpu_sgn_mapin(int cpuid)
-{
- uint64_t bbsram_physaddr;
- uint64_t cpu_sgnblk_physaddr;
- uint32_t cpu_sgnblk_offset;
- caddr_t cvaddr;
- pgcnt_t num_pages;
- pfn_t pfn;
-
- ASSERT(cpu_sgnblkp[cpuid] == NULL);
-
- /*
- * Construct the physical base address of the bbsram
- * in PSI space associated with this cpu in question.
- */
- cpu_sgnblk_physaddr = bbsram_physaddr =
- STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE;
-
- /*
- * The cpu_sgnblk pointer offsets are stored in the
- * undefined hardware trap slot 0x7f which is located
- * at offset 0xfe0. There are 2 of them since the
- * bbsram is shared among the 2 cpus residing on the
- * a PC. We need to determine the CPU in question whether
- * it is in port 0 or 1. CPU on port 0 has its
- * signature blkptr stored in 0xfe0 while the cpu_sgnblk
- * ptr of local port 1's CPU is in offset 0xfe8.
- */
- if (cpuid & 0x1) {
- /* CPU is in local port 1 */
- bbsram_physaddr |= 0xfe8ULL;
- } else {
- /* CPU is in local port 0 */
- bbsram_physaddr |= 0xfe0ULL;
- }
-
- /*
- * Read in the cpu_sgnblk pointer offset. Add it to the bbsram
- * base address to get the base address of the cpu_sgnblk.
- */
- cpu_sgnblk_offset = ldphysio(bbsram_physaddr);
- cpu_sgnblk_physaddr += cpu_sgnblk_offset;
-
- pfn = (pfn_t)(cpu_sgnblk_physaddr >> MMU_PAGESHIFT);
-
- num_pages = mmu_btopr(((cpu_sgnblk_physaddr &
- MMU_PAGEOFFSET) + sizeof (cpu_sgnblk_t)));
-
- /*
- * Map in the cpu_sgnblk
- */
- cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP);
-
- hat_devload(kas.a_hat, cvaddr, ptob(num_pages),
- pfn, PROT_READ | PROT_WRITE, HAT_LOAD_LOCK);
-
- cpu_sgnblkp[cpuid] = ((cpu_sgnblk_t *)(cvaddr +
- (uint32_t)(cpu_sgnblk_offset & MMU_PAGEOFFSET)));
-}
-
-void
-cpu_sgn_mapout(int cpuid)
-{
- ulong_t cvaddr, num_pages;
- uint32_t cpu_sgnblk_offset;
- uint64_t cpu_sgnblk_physaddr;
- uint64_t bbsram_physaddr;
-
- if ((cvaddr = (ulong_t)cpu_sgnblkp[cpuid]) == NULL) {
- cmn_err(CE_WARN, "cpu_sgn_mapout: ERROR: "
- "cpu_sgnblkp[%d] = NULL\n", cpuid);
- } else {
- cvaddr &= ~MMU_PAGEOFFSET;
-
- /*
- * Construct the physical base address of the bbsram
- * in PSI space associated with this cpu in question.
- */
- bbsram_physaddr = STARFIRE_UPAID2UPS(cpuid) |
- STARFIRE_PSI_BASE;
- cpu_sgnblk_physaddr = bbsram_physaddr;
-
- /*
- * The cpu_sgnblk pointer offsets are stored in the
- * undefined hardware trap slot 0x7f which is located
- * at offset 0xfe0. There are 2 of them since the
- * bbsram is shared among the 2 cpus residing on the
- * a PC. We need to determine the CPU in question whether
- * it is in port 0 or 1. CPU on port 0 has its
- * signature blkptr stored in 0xfe0 while the cpu_sgnblk
- * ptr of local port 1's CPU is in offset 0xfe8.
- */
- if (cpuid & 0x1) {
- /* CPU is in local port 1 */
- bbsram_physaddr |= 0xfe8ULL;
- } else {
- /* CPU is in local port 0 */
- bbsram_physaddr |= 0xfe0ULL;
- }
-
- /*
- * Read in the cpu_sgnblk pointer offset. Add it to the bbsram
- * base address to get the base address of the cpu_sgnblk.
- */
- cpu_sgnblk_offset = ldphysio(bbsram_physaddr);
- cpu_sgnblk_physaddr += cpu_sgnblk_offset;
-
- num_pages = mmu_btopr(((uint_t)(cpu_sgnblk_physaddr &
- MMU_PAGEOFFSET) + sizeof (cpu_sgnblk_t)));
-
- hat_unload(kas.a_hat, (caddr_t)cvaddr, ptob(num_pages),
- HAT_UNLOAD_UNLOCK);
- vmem_free(heap_arena, (caddr_t)cvaddr, ptob(num_pages));
-
- cpu_sgnblkp[cpuid] = NULL;
- }
-}
diff --git a/usr/src/uts/sun4u/starfire/os/pda.c b/usr/src/uts/sun4u/starfire/os/pda.c
deleted file mode 100644
index 5aee0cd542..0000000000
--- a/usr/src/uts/sun4u/starfire/os/pda.c
+++ /dev/null
@@ -1,623 +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"
-
-/*
- * Starfire Post Descriptor Array (post2obp) management.
- */
-
-#include <sys/debug.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/cpuvar.h>
-#include <sys/dditypes.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/kmem.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/vm.h>
-#include <vm/seg.h>
-#include <vm/seg_kmem.h>
-#include <vm/seg_kp.h>
-#include <sys/machsystm.h>
-#include <sys/starfire.h>
-
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/pda.h>
-#include <sys/cpu_sgn.h>
-
-extern struct cpu *SIGBCPU;
-extern cpu_sgnblk_t *cpu_sgnblkp[];
-
-extern uint64_t mc_get_mem_alignment();
-extern uint64_t mc_asr_to_pa(uint_t mcreg);
-
-static post2obp_info_t *cpu_p2o_mapin(int cpuid);
-static void cpu_p2o_mapout(int cpuid, post2obp_info_t *p2o);
-static void p2o_update_checksum(post2obp_info_t *p2o);
-static uint_t p2o_calc_checksum(post2obp_info_t *p2o);
-static void p2o_mem_sort(post2obp_info_t *p2o);
-static void p2o_mem_coalesce(post2obp_info_t *p2o);
-
-typedef struct {
- post2obp_info_t *p2o_ptr;
- int p2o_cpuid;
-} p2o_info_t;
-
-/*
- * PDA management routines. Should ultimately be made
- * accessible to other Starfire subsystems, but for
- * now we'll leave it here.
- */
-pda_handle_t
-pda_open()
-{
- p2o_info_t *pip;
-
- if (SIGBCPU == NULL) {
- cmn_err(CE_WARN, "pda_open: SIGBCPU is NULL");
- return (NULL);
- }
-
- pip = (p2o_info_t *)kmem_alloc(sizeof (p2o_info_t), KM_SLEEP);
-
- pip->p2o_cpuid = (int)SIGBCPU->cpu_id;
- pip->p2o_ptr = cpu_p2o_mapin(pip->p2o_cpuid);
-
- if (pip->p2o_ptr == NULL) {
- kmem_free((caddr_t)pip, sizeof (p2o_info_t));
- return ((pda_handle_t)NULL);
- } else {
- return ((pda_handle_t)pip);
- }
-}
-
-void
-pda_close(pda_handle_t ph)
-{
- p2o_info_t *pip;
-
- if ((pip = (p2o_info_t *)ph) == NULL)
- return;
-
- cpu_p2o_mapout(pip->p2o_cpuid, pip->p2o_ptr);
-
- kmem_free((caddr_t)pip, sizeof (p2o_info_t));
-}
-
-int
-pda_board_present(pda_handle_t ph, int boardnum)
-{
- ushort_t bda_board;
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
-
- bda_board = p2o->p2o_bdinfo[boardnum].bda_board;
-
- if ((bda_board & BDAN_MASK) != BDAN_GOOD)
- return (0);
- else
- return (1);
-}
-
-void *
-pda_get_board_info(pda_handle_t ph, int boardnum)
-{
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
-
- return ((void *)&(p2o->p2o_bdinfo[boardnum]));
-}
-
-uint_t
-pda_get_mem_size(pda_handle_t ph, int boardnum)
-{
- int c;
- pgcnt_t npages;
- uint_t asr;
- pfn_t basepfn, endpfn;
- uint64_t basepa, endpa;
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
-
- if (boardnum == -1)
- return (p2o->p2o_memtotal.Memt_NumPages);
-
- asr = p2o->p2o_bdminfo[boardnum].bmda_adr;
-
- basepa = mc_asr_to_pa(asr);
- /*
- * Put on MC alignment.
- */
- endpa = mc_get_mem_alignment();
- basepa &= ~(endpa - 1);
- endpa += basepa;
- basepfn = (pfn_t)(basepa >> PAGESHIFT);
- endpfn = (pfn_t)(endpa >> PAGESHIFT);
-
- npages = 0;
-
- for (c = 0; c < p2o->p2o_memtotal.Memt_NumChunks; c++) {
- pfn_t c_basepfn, c_endpfn;
-
- c_basepfn = (pfn_t)p2o->p2o_mchunks[c].Memc_StartAddress
- >> (PAGESHIFT - BDA_PAGESHIFT);
- c_endpfn = (pfn_t)p2o->p2o_mchunks[c].Memc_Size
- >> (PAGESHIFT - BDA_PAGESHIFT);
- c_endpfn += c_basepfn;
-
- if ((endpfn <= c_basepfn) || (basepfn >= c_endpfn))
- continue;
-
- c_basepfn = MAX(c_basepfn, basepfn);
- c_endpfn = MIN(c_endpfn, endpfn);
- ASSERT(c_basepfn <= c_endpfn);
-
- npages += c_endpfn - c_basepfn;
- }
-
- return (npages);
-}
-
-void
-pda_mem_add_span(pda_handle_t ph, uint64_t basepa, uint64_t nbytes)
-{
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
- int c, nchunks;
- pfn_t a_pfn, a_npgs;
-
- ASSERT(p2o);
-
- nchunks = p2o->p2o_memtotal.Memt_NumChunks;
- a_pfn = (pfn_t)(basepa >> BDA_PAGESHIFT);
- a_npgs = (pfn_t)(nbytes >> BDA_PAGESHIFT);
-
- for (c = 0; c < nchunks; c++) {
- int cend;
-
- if (a_pfn <= p2o->p2o_mchunks[c].Memc_StartAddress) {
- for (cend = nchunks; cend > c; cend--)
- p2o->p2o_mchunks[cend] =
- p2o->p2o_mchunks[cend - 1];
- break;
- }
- }
- p2o->p2o_mchunks[c].Memc_StartAddress = a_pfn;
- p2o->p2o_mchunks[c].Memc_Size = a_npgs;
- nchunks++;
-
- p2o->p2o_memtotal.Memt_NumChunks = nchunks;
- p2o->p2o_memtotal.Memt_NumPages += a_npgs;
-
- p2o_mem_sort(p2o);
- p2o_mem_coalesce(p2o);
- p2o_update_checksum(p2o);
-}
-
-void
-pda_mem_del_span(pda_handle_t ph, uint64_t basepa, uint64_t nbytes)
-{
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
- int c, o_nchunks, n_nchunks;
- pfn_t d_pfn;
- pgcnt_t d_npgs, npages;
- MemChunk_t *mp, *endp;
-
- ASSERT(p2o);
-
- d_pfn = (pfn_t)(basepa >> BDA_PAGESHIFT);
- d_npgs = (pgcnt_t)(nbytes >> BDA_PAGESHIFT);
- n_nchunks = o_nchunks = p2o->p2o_memtotal.Memt_NumChunks;
- endp = &(p2o->p2o_mchunks[o_nchunks]);
- npages = 0;
-
- for (c = 0; c < o_nchunks; c++) {
- uint_t p_pfn, p_npgs;
-
- p_pfn = p2o->p2o_mchunks[c].Memc_StartAddress;
- p_npgs = p2o->p2o_mchunks[c].Memc_Size;
- if (p_npgs == 0)
- continue;
-
- if (((d_pfn + d_npgs) <= p_pfn) ||
- (d_pfn >= (p_pfn + p_npgs))) {
- npages += p_npgs;
- continue;
- }
-
- if (d_pfn < p_pfn) {
- if ((d_pfn + d_npgs) >= (p_pfn + p_npgs)) {
- /*
- * Entire chunk goes away.
- */
- p_pfn = p_npgs = 0;
- } else {
- p_npgs -= d_pfn + d_npgs - p_pfn;
- p_pfn = d_pfn + d_npgs;
- }
- } else if (d_pfn == p_pfn) {
- if ((d_pfn + d_npgs) >= (p_pfn + p_npgs)) {
- p_pfn = p_npgs = 0;
- } else {
- p_npgs -= d_npgs;
- p_pfn += d_npgs;
- }
- } else {
- if ((d_pfn + d_npgs) >= (p_pfn + p_npgs)) {
- p_npgs = d_pfn - p_pfn;
- npages += p_npgs;
- } else {
- /*
- * Ugh, got to split a
- * memchunk, we're going to
- * need an extra one. It's
- * gotten from the end.
- */
- endp->Memc_StartAddress = d_pfn + d_npgs;
- endp->Memc_Size = (p_pfn + p_npgs)
- - (d_pfn + d_npgs);
- npages += endp->Memc_Size;
- endp++;
- n_nchunks++;
- p_npgs = d_pfn - p_pfn;
- }
- }
-
- p2o->p2o_mchunks[c].Memc_StartAddress = p_pfn;
- p2o->p2o_mchunks[c].Memc_Size = p_npgs;
- if (p_npgs == 0)
- n_nchunks--;
- npages += p_npgs;
- }
- p2o->p2o_memtotal.Memt_NumChunks = n_nchunks;
- p2o->p2o_memtotal.Memt_NumPages = npages;
-
- /*
- * There is a possibility we created holes in the memchunk list
- * due to memchunks that went away. Before we can sort and
- * coalesce we need to "pull up" the end of the memchunk list
- * and get rid of any holes.
- * endp = points to the last empty memchunk entry.
- */
- for (mp = &(p2o->p2o_mchunks[0]); mp < endp; mp++) {
- register MemChunk_t *mmp;
-
- if (mp->Memc_Size)
- continue;
-
- for (mmp = mp; mmp < endp; mmp++)
- *mmp = *(mmp + 1);
- mp--;
- endp--;
- }
- ASSERT(endp == &(p2o->p2o_mchunks[n_nchunks]));
-
- p2o_mem_sort(p2o);
- p2o_mem_coalesce(p2o);
- p2o_update_checksum(p2o);
-}
-
-/*
- * Synchonize all memory attributes (currently just MC ADRs [aka ASR])
- * with PDA representative values for the given board. A board value
- * of (-1) indicates all boards.
- */
-/*ARGSUSED*/
-void
-pda_mem_sync(pda_handle_t ph, int board, int unit)
-{
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
- register int b;
-
- for (b = 0; b < MAX_SYSBDS; b++) {
- if ((board != -1) && (board != b))
- continue;
-
- if (pda_board_present(ph, b)) {
- uint64_t masr;
- uint_t masr_value;
-
- masr = STARFIRE_MC_ASR_ADDR_BOARD(b);
- masr_value = ldphysio(masr);
-
- p2o->p2o_bdminfo[b].bmda_adr = masr_value;
- }
-
- if (board == b)
- break;
- }
-
- p2o_update_checksum(p2o);
-}
-
-void
-pda_get_busmask(pda_handle_t ph, short *amask, short *dmask)
-{
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
-
- if (amask)
- *amask = p2o ? p2o->p2o_abus_mask : 0;
-
- if (dmask)
- *dmask = p2o ? p2o->p2o_dbus_mask : 0;
-}
-
-int
-pda_is_valid(pda_handle_t ph)
-{
- post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr;
- uint_t csum;
-
- if (p2o == NULL)
- return (0);
-
- csum = p2o_calc_checksum(p2o);
-
- return (csum == p2o->p2o_csum);
-}
-
-/*
- * Post2obp support functions below here. Internal to PDA module.
- *
- * p2o_update_checksum
- *
- * Calculate checksum for post2obp structure and insert it so
- * when POST reads it it'll be happy.
- */
-static void
-p2o_update_checksum(post2obp_info_t *p2o)
-{
- uint_t new_csum;
-
- ASSERT(p2o);
-
- new_csum = p2o_calc_checksum(p2o);
- p2o->p2o_csum = new_csum;
-}
-
-static uint_t
-p2o_calc_checksum(post2obp_info_t *p2o)
-{
- int i, nchunks;
- uint_t *csumptr;
- uint_t p2o_size;
- uint_t csum, o_csum;
-
- ASSERT(p2o != NULL);
-
- nchunks = p2o->p2o_memtotal.Memt_NumChunks;
- p2o_size = sizeof (post2obp_info_t)
- + ((nchunks - VAR_ARRAY_LEN) * sizeof (MemChunk_t));
- p2o_size /= sizeof (uint_t);
-
- o_csum = p2o->p2o_csum;
- p2o->p2o_csum = 0;
- csum = 0;
- for (i = 0, csumptr = (uint_t *)p2o; i < p2o_size; i++)
- csum += *csumptr++;
- p2o->p2o_csum = o_csum;
-
- return (-csum);
-}
-
-/*
- * Sort the mchunk list in ascending order based on the
- * Memc_StartAddress field.
- *
- * disclosure: This is based on the qsort() library routine.
- */
-static void
-p2o_mem_sort(post2obp_info_t *p2o)
-{
- MemChunk_t *base;
- int nchunks;
- uint_t c1, c2;
- char *min, *max;
- register char c, *i, *j, *lo, *hi;
-
- ASSERT(p2o != NULL);
-
- nchunks = p2o->p2o_memtotal.Memt_NumChunks;
- base = &p2o->p2o_mchunks[0];
-
- /* ala qsort() */
- max = (char *)base + nchunks * sizeof (MemChunk_t);
- hi = max;
- for (j = lo = (char *)base; (lo += sizeof (MemChunk_t)) < hi; ) {
- c1 = ((MemChunk_t *)j)->Memc_StartAddress;
- c2 = ((MemChunk_t *)lo)->Memc_StartAddress;
- if (c1 > c2)
- j = lo;
- }
- if (j != (char *)base) {
- for (i = (char *)base,
- hi = (char *)base + sizeof (MemChunk_t);
- /* CSTYLED */
- i < hi;) {
- c = *j;
- *j++ = *i;
- *i++ = c;
- }
- }
- for (min = (char *)base;
- /* CSTYLED */
- (hi = min += sizeof (MemChunk_t)) < max;) {
- do {
- hi -= sizeof (MemChunk_t);
- c1 = ((MemChunk_t *)hi)->Memc_StartAddress;
- c2 = ((MemChunk_t *)min)->Memc_StartAddress;
- } while (c1 > c2);
- if ((hi += sizeof (MemChunk_t)) != min) {
- for (lo = min + sizeof (MemChunk_t);
- /* CSTYLED */
- --lo >= min;) {
- c = *lo;
- for (i = j = lo;
- (j -= sizeof (MemChunk_t)) >= hi;
- i = j) {
- *i = *j;
- }
- *i = c;
- }
- }
- }
-}
-
-static void
-p2o_mem_coalesce(post2obp_info_t *p2o)
-{
- MemChunk_t *mc;
- int nchunks, new_nchunks;
- uint_t addr, size, naddr, nsize;
- uint_t npages;
- register int i, cp, ncp;
-
- ASSERT(p2o != NULL);
-
- nchunks = new_nchunks = p2o->p2o_memtotal.Memt_NumChunks;
- mc = &p2o->p2o_mchunks[0];
-
- for (cp = i = 0; i < (nchunks-1); i++, cp = ncp) {
- ncp = cp + 1;
- addr = mc[cp].Memc_StartAddress;
- size = mc[cp].Memc_Size;
- naddr = mc[ncp].Memc_StartAddress;
- nsize = mc[ncp].Memc_Size;
-
- if ((addr + size) >= naddr) {
- uint_t overlap;
-
- overlap = addr + size - naddr;
- /*
- * if (nsize < overlap) then
- * next entry fits within the current
- * entry so no need to update size.
- */
- if (nsize >= overlap) {
- size += nsize - overlap;
- mc[cp].Memc_Size = size;
- }
- bcopy((char *)&mc[ncp+1],
- (char *)&mc[ncp],
- (nchunks - ncp - 1) * sizeof (MemChunk_t));
- ncp = cp;
- new_nchunks--;
- }
- }
-
- npages = 0;
- for (i = 0; i < new_nchunks; i++)
- npages += p2o->p2o_mchunks[i].Memc_Size;
-
- p2o->p2o_memtotal.Memt_NumChunks = new_nchunks;
- p2o->p2o_memtotal.Memt_NumPages = npages;
-}
-
-/*
- * Mapin the the cpu's post2obp structure.
- */
-static post2obp_info_t *
-cpu_p2o_mapin(int cpuid)
-{
- uint64_t cpu_p2o_physaddr;
- uint32_t cpu_p2o_offset;
- caddr_t cvaddr;
- uint_t num_pages;
- pfn_t pfn;
-
- ASSERT(cpu_sgnblkp[cpuid] != NULL);
- /*
- * Construct the physical base address of the bbsram
- * in PSI space associated with this cpu in question.
- */
- cpu_p2o_offset = (uint32_t)cpu_sgnblkp[cpuid]->sigb_postconfig;
- if (cpu_p2o_offset == 0) {
- cmn_err(CE_WARN,
- "cpu_p2o_mapin:%d: sigb_postconfig == NULL\n",
- cpuid);
- return (NULL);
- }
- cpu_p2o_physaddr = (STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE) +
- (uint64_t)cpu_p2o_offset;
- cpu_p2o_offset = (uint32_t)(cpu_p2o_physaddr & MMU_PAGEOFFSET);
- cpu_p2o_physaddr -= (uint64_t)cpu_p2o_offset;
-
- /*
- * cpu_p2o_physaddr = Beginning of page containing p2o.
- * cpu_p2o_offset = Offset within page where p2o starts.
- */
-
- pfn = (pfn_t)(cpu_p2o_physaddr >> MMU_PAGESHIFT);
-
- num_pages = mmu_btopr(cpu_p2o_offset + sizeof (post2obp_info_t));
-
- /*
- * Map in the post2obp structure.
- */
- cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP);
-
- hat_devload(kas.a_hat, cvaddr, ptob(num_pages),
- pfn, PROT_READ | PROT_WRITE, HAT_LOAD_LOCK);
-
- return ((post2obp_info_t *)(cvaddr + (ulong_t)cpu_p2o_offset));
-}
-
-static void
-cpu_p2o_mapout(int cpuid, post2obp_info_t *p2o)
-{
- ulong_t cvaddr, num_pages;
- uint32_t cpu_p2o_offset;
-
- ASSERT(cpu_sgnblkp[cpuid] != NULL);
-
- cpu_p2o_offset = (uint32_t)cpu_sgnblkp[cpuid]->sigb_postconfig;
- if (cpu_p2o_offset == 0) {
- cmn_err(CE_WARN,
- "cpu_p2o_mapout:%d: sigb_postconfig == NULL\n",
- cpuid);
- return;
- }
-
- cpu_p2o_offset = (uint32_t)(((STARFIRE_UPAID2UPS(cpuid) |
- STARFIRE_PSI_BASE) +
- (uint64_t)cpu_p2o_offset) &
- MMU_PAGEOFFSET);
-
- num_pages = mmu_btopr(cpu_p2o_offset + sizeof (post2obp_info_t));
-
- cvaddr = (ulong_t)p2o - cpu_p2o_offset;
- if (cvaddr & MMU_PAGEOFFSET) {
- cmn_err(CE_WARN,
- "cpu_p2o_mapout:%d: cvaddr (0x%x) not on page "
- "boundary\n",
- cpuid, (uint_t)cvaddr);
- return;
- }
-
- hat_unload(kas.a_hat, (caddr_t)cvaddr, ptob(num_pages),
- HAT_UNLOAD_UNLOCK);
- vmem_free(heap_arena, (caddr_t)cvaddr, ptob(num_pages));
-}
diff --git a/usr/src/uts/sun4u/starfire/os/starfire.c b/usr/src/uts/sun4u/starfire/os/starfire.c
deleted file mode 100644
index 2dd0688f4a..0000000000
--- a/usr/src/uts/sun4u/starfire/os/starfire.c
+++ /dev/null
@@ -1,639 +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 <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysmacros.h>
-#include <sys/sunddi.h>
-#include <sys/modctl.h>
-#include <sys/promif.h>
-#include <sys/machparam.h>
-#include <sys/kobj.h>
-#include <sys/mem_cage.h>
-#include <sys/starfire.h>
-
-#include <sys/platform_module.h>
-#include <sys/errno.h>
-#include <vm/page.h>
-#include <vm/hat_sfmmu.h>
-#include <sys/memnode.h>
-#include <vm/vm_dep.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/cpu_sgn.h>
-#include <sys/kdi_impl.h>
-#include <sys/clock_impl.h>
-
-extern cpu_sgnblk_t *cpu_sgnblkp[];
-
-/* Preallocation of spare tsb's for DR - none for now */
-int starfire_tsb_spares = STARFIRE_MAX_BOARDS << 1;
-
-/* Set the maximum number of boards... for DR */
-int starfire_boards = STARFIRE_MAX_BOARDS;
-
-/* Maximum number of cpus per board... for DR */
-int starfire_cpu_per_board = 4;
-
-/* Maximum number of mem-units per board... for DR */
-int starfire_mem_per_board = 1;
-
-/* Maximum number of io-units (buses) per board... for DR */
-int starfire_io_per_board = 2;
-
-/* Preferred minimum cage size (expressed in pages)... for DR */
-pgcnt_t starfire_startup_cage_size = 0;
-
-void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t);
-
-int
-set_platform_max_ncpus(void)
-{
- starfire_boards = MIN(starfire_boards, STARFIRE_MAX_BOARDS);
-
- if (starfire_boards < 1)
- starfire_boards = 1;
-
- return (starfire_boards * starfire_cpu_per_board);
-}
-
-void
-startup_platform(void)
-{
-}
-
-int
-set_platform_tsb_spares()
-{
- return (MIN(starfire_tsb_spares, MAX_UPA));
-}
-
-void
-set_platform_defaults(void)
-{
- extern char *tod_module_name;
- extern int ts_dispatch_extended;
- extern void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int);
-
- uint32_t revlevel;
- char buf[20];
-
-#ifdef DEBUG
- ce_verbose_memory = 2;
- ce_verbose_other = 2;
-#endif
-
- /*
- * Check to see if we have the right firmware
- * We simply do a prom_test to see if
- * "SUNW,UE10000-prom-version" interface exist.
- */
- if (prom_test("SUNW,UE10000-prom-version") != 0) {
- halt("Firmware upgrade is required to boot this OS!");
- } else {
- /*
- * Versions 5 to 50 and 150 or above can support this OS
- */
- (void) sprintf(buf, "cpu-prom-version swap l!");
- prom_interpret(buf, (uintptr_t)&revlevel, 0, 0, 0, 0);
- if ((revlevel < 5) || ((revlevel > 50) && (revlevel < 150)))
- halt("Firmware upgrade is required to boot this OS!");
- }
-
- /* Set the CPU signature function pointer */
- cpu_sgn_func = cpu_sgn_update;
-
- /* Set appropriate tod module for starfire */
- ASSERT(tod_module_name == NULL);
- tod_module_name = "todstarfire";
-
- /*
- * Use the alternate TS dispatch table, which is better
- * tuned for large servers.
- */
- if (ts_dispatch_extended == -1) /* use platform default */
- ts_dispatch_extended = 1;
-}
-
-#ifdef DEBUG
-pgcnt_t starfire_cage_size_limit;
-#endif
-
-void
-set_platform_cage_params(void)
-{
- extern pgcnt_t total_pages;
- extern struct memlist *phys_avail;
-
- if (kernel_cage_enable) {
- pgcnt_t preferred_cage_size;
-
- preferred_cage_size =
- MAX(starfire_startup_cage_size, total_pages / 256);
-
-#ifdef DEBUG
- if (starfire_cage_size_limit)
- preferred_cage_size = starfire_cage_size_limit;
-#endif
- /*
- * Note: we are assuming that post has load the
- * whole show in to the high end of memory. Having
- * taken this leap, we copy the whole of phys_avail
- * the glist and arrange for the cage to grow
- * downward (descending pfns).
- */
- kcage_range_init(phys_avail, KCAGE_DOWN, preferred_cage_size);
- }
-
- if (kcage_on)
- cmn_err(CE_NOTE, "!DR Kernel Cage is ENABLED");
- else
- cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED");
-}
-
-void
-load_platform_drivers(void)
-{
- /* load the NGDR driver */
- if (i_ddi_attach_pseudo_node("ngdr") == NULL) {
- cmn_err(CE_WARN, "ngdr failed to load");
- }
-}
-
-/*
- * Starfire does not support power control of CPUs from the OS.
- */
-/*ARGSUSED*/
-int
-plat_cpu_poweron(struct cpu *cp)
-{
- int (*starfire_cpu_poweron)(struct cpu *) = NULL;
-
- starfire_cpu_poweron =
- (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0);
-
- if (starfire_cpu_poweron == NULL)
- return (ENOTSUP);
- else
- return ((starfire_cpu_poweron)(cp));
-}
-
-/*ARGSUSED*/
-int
-plat_cpu_poweroff(struct cpu *cp)
-{
- int (*starfire_cpu_poweroff)(struct cpu *) = NULL;
-
- starfire_cpu_poweroff =
- (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0);
-
- if (starfire_cpu_poweroff == NULL)
- return (ENOTSUP);
- else
- return ((starfire_cpu_poweroff)(cp));
-}
-
-void
-plat_dmv_params(uint_t *hwint, uint_t *swint)
-{
- *hwint = STARFIRE_DMV_HWINT;
- *swint = 0;
-}
-
-/*
- * The following our currently private to Starfire DR
- */
-int
-plat_max_boards()
-{
- return (starfire_boards);
-}
-
-int
-plat_max_cpu_units_per_board()
-{
- return (starfire_cpu_per_board);
-}
-
-int
-plat_max_mem_units_per_board()
-{
- return (starfire_mem_per_board);
-}
-
-int
-plat_max_io_units_per_board()
-{
- return (starfire_io_per_board);
-}
-
-
-/*
- * This index is used to associate a given pfn to a place on the freelist.
- * This results in dispersing pfn assignment over all the boards in the
- * system.
- * Choose the index randomly to prevent clustering pages of different
- * colors on the same board.
- */
-static uint_t random_idx(int ubound);
-
-#define PFN_2_LBN(pfn) (((pfn) >> (STARFIRE_MC_MEMBOARD_SHIFT - PAGESHIFT)) % \
- STARFIRE_MAX_BOARDS)
-
-void
-plat_freelist_process(int mnode)
-{
- page_t *page, **freelist;
- page_t *bdlist[STARFIRE_MAX_BOARDS];
- page_t **sortlist[STARFIRE_MAX_BOARDS];
- uint32_t idx, idy, size, color, max_color, lbn;
- uint32_t bd_flags, bd_cnt, result, bds;
- kmutex_t *pcm;
- int mtype;
-
- /* for each page size */
- for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) {
- for (size = 0; size < mmu_page_sizes; size++) {
-
- /*
- * Compute the maximum # of phys colors based on
- * page size.
- */
- max_color = page_get_pagecolors(size);
-
- /* for each color */
- for (color = 0; color < max_color; color++) {
-
- bd_cnt = 0;
- bd_flags = 0;
- for (idx = 0; idx < STARFIRE_MAX_BOARDS;
- idx++) {
- bdlist[idx] = NULL;
- sortlist[idx] = NULL;
- }
-
- /* find freelist */
- freelist = &PAGE_FREELISTS(mnode, size,
- color, mtype);
-
- if (*freelist == NULL)
- continue;
-
- /* acquire locks */
- pcm = PC_BIN_MUTEX(mnode, color, PG_FREE_LIST);
- mutex_enter(pcm);
-
- /*
- * read freelist & sort pages by logical
- * board number
- */
- /* grab pages till last one. */
- while (*freelist) {
- page = *freelist;
- result = page_trylock(page, SE_EXCL);
-
- ASSERT(result);
-
- /* Delete from freelist */
- if (size != 0) {
- page_vpsub(freelist, page);
- } else {
- mach_page_sub(freelist, page);
- }
-
- /* detect the lbn */
- lbn = PFN_2_LBN(page->p_pagenum);
-
- /* add to bdlist[lbn] */
- if (size != 0) {
- page_vpadd(&bdlist[lbn], page);
- } else {
- mach_page_add(&bdlist[lbn],
- page);
- }
-
- /* if lbn new */
- if ((bd_flags & (1 << lbn)) == 0) {
- bd_flags |= (1 << lbn);
- bd_cnt++;
- }
- page_unlock(page);
- }
-
- /*
- * Make the sortlist so
- * bd_cnt choices show up
- */
- bds = 0;
- for (idx = 0; idx < STARFIRE_MAX_BOARDS;
- idx++) {
- if (bdlist[idx])
- sortlist[bds++] = &bdlist[idx];
- }
-
- /*
- * Set random start.
- */
- (void) random_idx(-color);
-
- /*
- * now rebuild the freelist by shuffling
- * pages from bd lists
- */
- while (bd_cnt) {
-
- /*
- * get "random" index between 0 &
- * bd_cnt
- */
-
- ASSERT(bd_cnt &&
- (bd_cnt < STARFIRE_MAX_BOARDS+1));
-
- idx = random_idx(bd_cnt);
-
- page = *sortlist[idx];
- result = page_trylock(page, SE_EXCL);
-
- ASSERT(result);
-
- /* Delete from sort_list */
- /* & Append to freelist */
- /* Big pages use vp_add - 8k don't */
- if (size != 0) {
- page_vpsub(sortlist[idx], page);
- page_vpadd(freelist, page);
- } else {
- mach_page_sub(sortlist[idx],
- page);
- mach_page_add(freelist, page);
- }
-
- /* needed for indexing tmp lists */
- lbn = PFN_2_LBN(page->p_pagenum);
-
- /*
- * if this was the last page on this
- * list?
- */
- if (*sortlist[idx] == NULL) {
-
- /* have to find brd list */
-
- /* idx is lbn? -- No! */
- /* sortlist, brdlist */
- /* have diff indexs */
- bd_flags &= ~(1 << lbn);
- --bd_cnt;
-
- /*
- * redo the sortlist so only
- * bd_cnt choices show up
- */
- bds = 0;
- for (idy = 0;
- idy < STARFIRE_MAX_BOARDS;
- idy++) {
- if (bdlist[idy]) {
- sortlist[bds++]
- /* CSTYLED */
- = &bdlist[idy];
- }
- }
- }
- page_unlock(page);
- }
- mutex_exit(pcm);
- }
- }
- }
-}
-
-/*
- * If ubound > 0, will return an int between 0 & ubound
- * If ubound < 0, will set "random seed"
- */
-static uint_t
-random_idx(int ubound)
-{
- static int idx = 0;
-
- if (ubound > 0) {
- idx = (idx + 1) % ubound;
- return (idx);
- }
- idx = -ubound;
- return (0);
-}
-
-/*
- * No platform drivers on this platform
- */
-char *platform_module_list[] = {
- (char *)0
-};
-
-/*ARGSUSED*/
-void
-plat_tod_fault(enum tod_fault_type tod_bad)
-{
-}
-
-/*
- * Update signature block and the signature ring buffer of a given cpu_id.
- */
-void
-cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid)
-{
- uchar_t idx;
- cpu_sgnblk_t *cpu_sgnblkptr;
-
- /*
- * cpuid == -1 indicates that the operation applies to all cpus.
- */
- if (cpuid < 0) {
- sgn_update_all_cpus(sgn, state, sub_state);
- return;
- }
-
- if (cpu_sgnblkp[cpuid] == NULL)
- return;
-
- cpu_sgnblkptr = cpu_sgnblkp[cpuid];
-
- /*
- * Map new generic cpu states to older Starfire states.
- */
- switch (state) {
- case SIGST_OFFLINE:
- state = SIGBST_OFFLINE;
- break;
- case SIGST_RESUME_INPROGRESS:
- state = SIGBST_RESUME_INPROGRESS;
- break;
- case SIGST_QUIESCE_INPROGRESS:
- state = SIGBST_QUIESCE_INPROGRESS;
- break;
- case SIGST_QUIESCED:
- state = SIGBST_QUIESCED;
- break;
- case SIGST_EXIT:
- switch (sub_state) {
- case SIGSUBST_DEBUG:
- state = SIGBST_RUN;
- sub_state = EXIT_NULL;
- break;
- case SIGSUBST_PANIC_CONT:
- state = SIGBST_RUN;
- sub_state = EXIT_PANIC2;
- break;
- case SIGSUBST_DUMP:
- state = SIGBST_EXIT;
- sub_state = EXIT_PANIC2;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- cpu_sgnblkptr->sigb_signature.state_t.sig = sgn;
- cpu_sgnblkptr->sigb_signature.state_t.state = state;
- cpu_sgnblkptr->sigb_signature.state_t.sub_state = sub_state;
-
- /* Update the ring buffer */
- idx = cpu_sgnblkptr->sigb_ringbuf.wr_ptr;
- cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sig = sgn;
- cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.state = state;
- cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sub_state = sub_state;
- cpu_sgnblkptr->sigb_ringbuf.wr_ptr += 1;
- cpu_sgnblkptr->sigb_ringbuf.wr_ptr &= RB_IDX_MASK;
-}
-
-/*
- * Update signature block and the signature ring buffer of all CPUs.
- */
-void
-sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state)
-{
- int i = 0;
- uchar_t cpu_state;
- uchar_t cpu_sub_state;
-
- for (i = 0; i < NCPU; i++) {
- cpu_sgnblk_t *sblkp;
-
- sblkp = cpu_sgnblkp[i];
- cpu_sub_state = sub_state;
-
- if ((sblkp != NULL) && (cpu[i] != NULL && (cpu[i]->cpu_flags &
- (CPU_EXISTS|CPU_QUIESCED)))) {
-
- if (sub_state == EXIT_REBOOT) {
- cpu_sub_state =
- sblkp->sigb_signature.state_t.sub_state;
-
- if ((cpu_sub_state == EXIT_PANIC1) ||
- (cpu_sub_state == EXIT_PANIC2))
- cpu_sub_state = EXIT_PANIC_REBOOT;
- else
- cpu_sub_state = EXIT_REBOOT;
- }
-
- /*
- * If we get here from an OBP sync after watchdog,
- * we need to retain the watchdog sync state so that
- * hostmon knows what's going on. So if we're in
- * watchdog we don't update the state.
- */
-
- cpu_state = sblkp->sigb_signature.state_t.state;
- if (cpu_state == SIGBST_WATCHDOG_SYNC)
- cpu_sgn_update(sgn, SIGBST_WATCHDOG_SYNC,
- cpu_sub_state, i);
- else if (cpu_state == SIGBST_REDMODE_SYNC)
- cpu_sgn_update(sgn, SIGBST_REDMODE_SYNC,
- cpu_sub_state, i);
- else
- cpu_sgn_update(sgn, state, cpu_sub_state, i);
- }
- }
-}
-
-int
-cpu_sgn_exists(int cpuid)
-{
- return (cpu_sgnblkp[cpuid] != NULL);
-}
-
-ushort_t
-get_cpu_sgn(int cpuid)
-{
- if (cpu_sgnblkp[cpuid] == NULL)
- return ((ushort_t)-1);
-
- return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.sig);
-}
-
-uchar_t
-get_cpu_sgn_state(int cpuid)
-{
- if (cpu_sgnblkp[cpuid] == NULL)
- return ((uchar_t)-1);
-
- return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.state);
-}
-
-/*
- * KDI functions - used by the in-situ kernel debugger (kmdb) to perform
- * platform-specific operations. These functions execute when the world is
- * stopped, and as such cannot make any blocking calls, hold locks, etc.
- * promif functions are a special case, and may be used.
- */
-
-static void
-starfire_system_claim(void)
-{
- lbolt_debug_entry();
-
- prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
-}
-
-static void
-starfire_system_release(void)
-{
- prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0);
-
- lbolt_debug_return();
-}
-
-void
-plat_kdi_init(kdi_t *kdi)
-{
- kdi->pkdi_system_claim = starfire_system_claim;
- kdi->pkdi_system_release = starfire_system_release;
-}
diff --git a/usr/src/uts/sun4u/starfire/pcipsy/Makefile b/usr/src/uts/sun4u/starfire/pcipsy/Makefile
deleted file mode 100644
index 97bb94d9a6..0000000000
--- a/usr/src/uts/sun4u/starfire/pcipsy/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, 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.
-#
-# uts/sun4u/starfire/pcipsy/Makefile
-#
-# This makefile drives the production of the PCI 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 = pcipsy
-OBJECTS = $(PSYCHO_PCI_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(PSYCHO_PCI_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-uninitialized
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-unused-function
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/platmod/Makefile b/usr/src/uts/sun4u/starfire/platmod/Makefile
deleted file mode 100644
index 026493c4fb..0000000000
--- a/usr/src/uts/sun4u/starfire/platmod/Makefile
+++ /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 2005 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 sun4u starfire platform
-# module.
-#
-# sun4u starfire 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 = $(STARFIRE_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(STARFIRE_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_MISC_DIR)/$(MODULE)
-PLAT_DIR = .
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Override defaults
-#
-CLEANFILES += $(PLATLIB)
-
-#
-# Define targets
-#
-ALL_TARGET = $(PLATLIB)
-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)
-
-$(PLATLIB): $(BINARY)
- $(BUILD.SO) $(BINARY)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/rootnex/Makefile b/usr/src/uts/sun4u/starfire/rootnex/Makefile
deleted file mode 100644
index 191a61016c..0000000000
--- a/usr/src/uts/sun4u/starfire/rootnex/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, 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.
-#
-# This makefile drives the production of the rootnex driver
-#
-# sun4u starfire 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 = rootnex
-OBJECTS = $(ROOTNEX_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(ROOTNEX_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Override defaults to build a unique, local modstubs.o.
-#
-MODSTUBS_DIR = .
-$(MODSTUBS_O) := AS_CPPFLAGS += -DROOTNEX_MODULE
-
-CLEANFILES += $(MODSTUBS_O)
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-unused-variable
-CERRWARN += -_gcc=-Wno-uninitialized
-CERRWARN += -_gcc=-Wno-switch
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/sbus/Makefile b/usr/src/uts/sun4u/starfire/sbus/Makefile
deleted file mode 100644
index 03c6d28bf4..0000000000
--- a/usr/src/uts/sun4u/starfire/sbus/Makefile
+++ /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, 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.
-#
-# uts/sun4u/starfire/sbus/Makefile
-#
-# This makefile drives the production of the SBus driver kernel module,
-# the iommu nexus, and the obio nexus (which really is sbus on sun5).
-#
-# starfire 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 = sbus
-OBJECTS = $(SYSIO_SBUS_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(SYSIO_SBUS_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-# Turn this on once compiler understands v9 in it's backend
-#INLINES += $(UTSBASE)/sun4u/io/iommu.il
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-type-limits
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# 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/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/spitfire/Makefile b/usr/src/uts/sun4u/starfire/spitfire/Makefile
deleted file mode 100644
index 9db750b1cd..0000000000
--- a/usr/src/uts/sun4u/starfire/spitfire/Makefile
+++ /dev/null
@@ -1,109 +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 the sun4u UltraSPARC driver module.
-#
-# sun4u/starfire 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 = SUNW,UltraSPARC-II
-OBJECTS = $(SPITFIRE_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(SPITFIRE_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_STARFIRE_CPU_DIR)/$(MODULE)
-
-CPU_DIR = .
-HERE = ../spitfire
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Override defaults
-#
-CLEANFILES += $(CPULIB) $(SYM_MOD)
-
-#
-# Define targets
-#
-ALL_TARGET = $(SYM_MOD)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = def $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-uninitialized
-
-CPPFLAGS += -DCPU_MODULE -DSPITFIRE
-AS_CPPFLAGS += -DCPU_MODULE -DSPITFIRE
-
-#
-# 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)
-
-$(CPULIB): $(BINARY)
- $(BUILD.SO) $(BINARY)
-
-$(SYM_MOD): $(UNIX_O) $(CPULIB)
- @echo "resolving symbols against unix.o"
- @(cd $(UNIX_DIR); pwd; \
- CPU_DIR=$(HERE) SYM_MOD=$(HERE)/$(SYM_MOD) $(MAKE) symcheck)
-
-$(ROOTSOFTLINKS): $(ROOTMODULE)
- $(RM) $@; $(SYMLINK) $(MODULE) $@
-
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/sys/Makefile b/usr/src/uts/sun4u/starfire/sys/Makefile
deleted file mode 100644
index 00f306b5c3..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/Makefile
+++ /dev/null
@@ -1,68 +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.starfire
-
-#
-# Override defaults.
-#
-FILEMODE = 644
-
-HDRS= cvc.h
-
-STARHDRS= $(UTSBASE)/sun4u/ngdr/sys/dr.h \
- $(UTSBASE)/sun4u/ngdr/sys/dr_util.h
-
-ROOTHDRS= $(HDRS:%=$(USR_STARFIRE_ISYS_DIR)/%)
-
-ROOTDIR= $(ROOT)/usr/share/src
-ROOTDIRS= $(ROOTDIR)/uts $(ROOTDIR)/uts/$(PLATFORM)
-
-CHECKHDRS= $(HDRS:%.h=%.check) \
- $(STARHDRS:%.h=%.check)
-
-.KEEP_STATE:
-
-.PARALLEL: $(CHECKHDRS) $(ROOTHDRS)
-
-install_h: $(ROOTDIRS) .WAIT $(ROOTHDRS) $(ROOTLINK)
-
-check: $(CHECKHDRS)
-
-#
-# install rules
-#
-$(USR_STARFIRE_ISYS_DIR)/%: % $(USR_STARFIRE_ISYS_DIR)
- $(INS.file)
-
-$(ROOTDIRS):
- $(INS.dir)
-
-FRC:
-
-include ../Makefile.targ
diff --git a/usr/src/uts/sun4u/starfire/sys/cpu_sgn.h b/usr/src/uts/sun4u/starfire/sys/cpu_sgn.h
deleted file mode 100644
index 8c14d34f3b..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/cpu_sgn.h
+++ /dev/null
@@ -1,354 +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) 2000 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef _CPU_SGN_H
-#define _CPU_SGN_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _ASM
-#include <sys/types.h>
-#include <sys/cpuvar.h>
-#endif /* _ASM */
-
-/*
- * BBSRAM virtual address - 64 bits max.
- */
-typedef uint64_t vaddr_t;
-
-/*
- * Special type for BBSRAM offsets (rather than pointers).
- * This must be a 32 bit value
- */
-typedef uint32_t bboff_t;
-
-/*
- * As long as each component of the revision is less than
- * 256, this trick will work. So we check for that and generate a
- * syntax error if the SID is out of range.
- */
-#define SIGB_MBOX_SIZE 64
-/* reserved space - rounds size of sigblock_t to 512 */
-#define SIGB_RESV 16
-
-#define BASE_ADDR_T_OFFSET 0xFE0 /* BBSRAM base_addr_t offset */
-
-#define CVC_OUT_SIZ 1024 /* cvc output buffer size */
-#define CVC_IN_SIZ 256 /* cvc input buffer size */
-
-/* make sure the assembler doesn't see the C code */
-#ifndef _ASM
-
-/*
- * The reserved hardware interrupt 7F is used as a pointer structure
- * to the two processors' signature blocks in bbsram. Each trap entry
- * is 32 bytes, so this structure is always present at bbsram offset
- * 0xFE0.
- * Over time, we may discover other items that need pointers, that don't
- * logically fit in the sigblocks themselves. This structure declares
- * the global use of these 8 words.
- * The spare_x words are reserved in case a design change calls for
- * using 64-bit virtual addresses instead of offsets. This is
- * considered unlikely.
- *
- * The offsets and this structure are normally created by POST when it
- * initially creates the sigblocks. Subsequent programs may move the
- * sigblocks in bbsram as they see fit, as long as this structure is changed
- * to reflect the new location.
- */
-
-typedef struct {
- bboff_t sigblk_offset_0; /* BBSRAM sig block 0 offset */
- uint32_t spare_0; /* spare word just in case */
- bboff_t sigblk_offset_1; /* BBSRAM sig block 1 offset */
- uint32_t spare_1; /* another just in case */
- uint32_t pad[4]; /* trap is 8 32-bit words long */
-} base_addr_t;
-
-
-/*
- * The following are used in the flag field of the mailbox structure.
- * They are used to synchronize access with the mailbox between the
- * SSP and Host, and indicate direction of the given message.
- */
-#define SIGB_MBOX_EMPTY 0
-#define SIGB_MBOX_BUSY 1
-#define HOST_TO_CBS 2
-#define CBS_TO_HOST 3
-
-/* for sigblk polling */
-#define SIGB_INTR_OFF 0x00
-#define SIGB_INTR_SEND 0xFF
-
-typedef short mboxflag_t;
-
-/*
- * BE CAREFUL with modifications. To optimize transfers on the
- * bootbus between the kernel and mailbox, try to make sure the data
- * field falls on a 16 byte boundary.
- */
-typedef struct {
-/* 0 */ short intr;
-/* 2 */ mboxflag_t flag;
-/* 4 */ int32_t len;
-/* 8 */ uint32_t cmd;
-/* c */ char data[SIGB_MBOX_SIZE];
-} sigbmbox_t; /* sizeof = 76 (0x4c) = 19X */
-
-typedef struct {
- uchar_t cvc_output_buf[CVC_OUT_SIZ];
- uchar_t cvc_input_buf[CVC_IN_SIZ];
- uchar_t cvc_obp_input_flag; /* !=0 -> OBP wants CVC input */
-} sigb_cvc_t;
-
-/*
- * Every CPU signature, state, or substate transition is captured
- * in the ring buffer. OS or OBP will be the writer of the ring buffer
- * and control board executive (via JTAG) will be the sole reader. Because of
- * space limitation in the BBSRAM, the ring buffer can only be 64 entries big.
- * A ring buffer is necessary because of the speed difference between the
- * reader and writer, and to prevent race condition.
- *
- * The ring buffer structure contains two pointers, one for reading and
- * one for writing, and the buffer itself. The last 6 bits in each of the
- * pointer identify an entry in the buffer. The read pointer represents
- * the next entry the reader should read. The write pointer represents the
- * next entry the writer is going to write. For the reader, the ring buffer
- * contains un-read entries if the read and write pointers are different.
- *
- * In most situations, the reader should be able to keep up with the
- * writer. However, in the case where the writer is transitioning
- * rapidly, the reader may not be able to keep up and causes an overflow.
- * When an overflow happens, instead of suspending the writer, the
- * writer continues to write.
- *
- * The first transition that causes an overflow has 2 consequences
- * because of this continuous write action:
- * 1. The ring buffer is flushed, all previous transitions history are lost.
- *
- * Flushing the ring buffer is acceptable since the reader is not
- * able to keep up with rapid transitions, it is better off to start
- * from the current transition than trying to catch up.
- *
- * 2. The new transition is recorded in the ring buffer. However, bcecause of
- * the way the write pointer is updated, both the read and write pointers
- * will be identical which makes the reader thinks there is no transition to
- * read.
- *
- * Even though the reader does not see the most current signature/state in the
- * ring buffer, it can be found in the signature block data structure.
- * The reader can do a read in the signature block to obtain the current
- * signature/block if the read/write pointers indicate the buffer is empty.
- * The problem will go away once the writer starts writing again.
- *
- * Initial condition:
- * rd_ptr = 0
- * wr_ptr = 0
- *
- * To write a signature into the ring buffer, the steps are:
- * 1. write signature into ringbuf[wr_ptr]
- * 2. increment wr_ptr by 1 modulo SIGB_RB_SIZ using RB_IDX_MASK
- *
- * Note: the writer always writes to the ring buffer and the signature
- * field in the signature block data structure.
- *
- * To read a signature from the ring buffer, the steps are:
- * 1. compare rd_ptr and wr_ptr
- * 2. if they are not equal then
- * read signature ringbuf[rd_ptr]
- * increment rd_ptr by 1 modulo SIGB_RB_SIZ using RB_IDX_MASK
- * save a copy of the signature locally
- * return the signature
- * 3. else
- * read signature from the signature block data structure
- * if signature is not the same as the last signature then
- * return the signature
- *
- */
-
-#define SIGB_RB_SIZ 64 /* ring buffer size */
-#define RB_IDX_MASK 0x3f /* mask to determine read/write index */
-
-typedef struct {
-/* 0 */ uchar_t rd_ptr; /* entry to read */
-/* 1 */ uchar_t wr_ptr; /* next entry to write */
-/* 4 */ sig_state_t ringbuf[SIGB_RB_SIZ];
-} sigb_ringbuf_t; /* sizeof = 260 (0x104) = 65X */
-
-typedef struct cpu_sgnblk {
-/* 0 */ uint32_t sigb_magic; /* SIGBLOCK_MAGIC */
-/* 4 */ uint32_t sigb_version; /* changes with each SID */
-/* 8 */ uint32_t sigb_flags; /* struct sigblock status */
-/* c */ uint32_t sigb_heartbeat; /* prog's heartbeat */
-
-/* 10 */ uint32_t sigb_leds; /* Software LED */
-/* 14 */ sig_state_t sigb_signature; /* Current signature & state */
-
- /*
- * sigb_ringbuf captures the last SIGB_RB_SIZ signature/state
- * transitions.
- */
-/* 18 */ sigb_ringbuf_t sigb_ringbuf;
-
- /*
- * sigb_host_mbox is intended for msgs targeted for the Host and
- * follows the protocol:
- * SSP -> [cmd] -> Host -> [resp] -> SSP.
- */
-/* 11c */ sigbmbox_t sigb_host_mbox;
-
-/* 168 */ char sigb_idn[sizeof (sigbmbox_t)];
-
-/* 1b4 */ bboff_t sigb_obp_mbox; /* OBP/DHLP mailbox. */
-
-/* 1b8 */ bboff_t sigb_postconfig; /* config info from POST */
-
-/* 1bc */ uint32_t sigb_post; /* POST opaque */
-
-/* 1c0 */ bboff_t sigb_slavep; /* Slave startup block offset */
-
-/* 1c4 */ bboff_t sigb_resetinfo_off; /* Resetinfo offset */
-
-/* 1c8 */ bboff_t sigb_cvc_off; /* CVC offset */
-
-/* 1cc */ bboff_t sigb_eeprom_off; /* EEPROM offset */
-
-/* 1d0 */ vaddr_t sigb_wdog_reset_vec; /* Watchdog Reset Vector */
-
-/* 1d8 */ vaddr_t sigb_xir_reset_vec; /* XIR Reset vector */
-
-/* 1e0 */ vaddr_t sigb_sir_reset_vec; /* SIR Reset Vector */
-
-/* 1e8 */ vaddr_t sigb_red_state_reset_vec; /* RED State Reset Vector */
-
-/* 1f0 */ uchar_t sigb_resv_array[SIGB_RESV]; /* reserved space */
-} cpu_sgnblk_t; /* sizeof = 512 (0x200) = 128X */
-
-#endif /* _ASM */
-
-/*
- * Mailbox commands.
- *
- * The commands are listed here so that they are in a central place
- * for all users of the signature block mailbox. Want to be careful
- * that some subsystems don't accidently use the same value for a
- * command. For this reason we introduce a cookie for each subsystem.
- */
-
-#define SIGB_HANDLER_BUSY (-2)
-#define SIGB_BAD_MBOX_CMD (-1)
-#define SSP_CMD ('S' << 8) /* generic SSP */
-#define SSP_CMD_SUCCESS (SSP_CMD | 0x1)
-#define SSP_GOTO_OBP (SSP_CMD | 0x2)
-#define SSP_GOTO_PANIC (SSP_CMD | 0x3)
-#define SSP_ENVIRON (SSP_CMD | 0x4) /* environmental intr */
-
-#ifdef _KERNEL
-
-#ifdef _STARFIRE
-
-extern void juggle_sgnblk_poll(struct cpu *);
-extern int sgnblk_poll_register(void (*)(processorid_t, cpu_sgnblk_t *));
-extern int sgnblk_poll_unregister(void (*)(processorid_t, cpu_sgnblk_t *));
-extern int sgnblk_poll_reference(void (*)(cpu_sgnblk_t *, void *), void *);
-extern void sgnblk_poll_unreference(void (*)(cpu_sgnblk_t *, void *));
-
-extern cpu_sgnblk_t *cpu_sgnblkp[NCPU];
-
-/*
- * Starfire specific signatures
- */
-#define POST_SIG SIG_BLD('P', 'O')
-#define DHLP_SIG SIG_BLD('D', 'H')
-
-/*
- * Starfire specific Sigblock states.
- */
-#define SIGBST_NONE 0 /* no state */
-#define SIGBST_RUN 1 /* running */
-#define SIGBST_EXIT 2 /* finished */
-#define SIGBST_PRERUN 3 /* pre-exec */
-#define SIGBST_ARBSTOP 4 /* transient arbstop state */
-#define SIGBST_RESET 5 /* reset */
-#define SIGBST_POWEROFF 6 /* no power */
-#define SIGBST_DETACHED 7 /* spinning in OBP after DR DETACH */
-#define SIGBST_CALLBACK 8 /* kernel calling back into OBP */
-#define SIGBST_WATCHDOG 9 /* OBP running after watchdog */
-#define SIGBST_WATCHDOG_SYNC 10 /* OBP "sync" after watchdog reset */
-#define SIGBST_OFFLINE 11 /* cpu offline */
-#define SIGBST_BOOTING 12 /* booting */
-#define SIGBST_UNKNOWN 13 /* unknown */
-#define SIGBST_XIR 14 /* OBP running after XIR */
-#define SIGBST_XIR_SYNC 15 /* OBP trying "sync" in XIR */
-#define SIGBST_SIR 16 /* OBP running after SIR */
-#define SIGBST_SIR_SYNC 17 /* OBP trying "sync" in SIR */
-#define SIGBST_REDMODE 18 /* OBP running after REDMODE */
-#define SIGBST_REDMODE_SYNC 19 /* OBP trying "sync" in REDMODE */
-#define SIGBST_QUIESCED 20 /* system quiesced */
-#define SIGBST_QUIESCE_INPROGRESS 21 /* system quiesce in-progress */
-#define SIGBST_RESUME_INPROGRESS 22 /* system resume in-progress */
-
-/*
- * Starfire specific Sigblock sub-states
- */
-#define EXIT_NULL 0
-#define EXIT_HALT 1
-#define EXIT_ENVIRON 2
-#define EXIT_REBOOT 3
-#define EXIT_PANIC1 4
-#define EXIT_PANIC2 5
-#define EXIT_HUNG 6
-#define EXIT_WATCH 7
-#define EXIT_PANIC_REBOOT 8
-#define EXIT_WATCHDOG_REBOOT 9
-#define EXIT_SOFT_INIT_RESET 10 /* SIR */
-#define EXIT_EXTERN_INIT_RESET 11 /* XIR */
-#define EXIT_REDMODE_REBOOT 12 /* REDMODE */
-#define EXIT_OBP_RESET 13 /* OBP RESET */
-
-#else
-
-#define REGISTER_BBUS_INTR()
-#define CPU_SGN_MAPIN(cpuid)
-#define CPU_SGN_MAPOUT(cpuid)
-#define CPU_SGN_EXISTS(cpuid) (0)
-#define SGN_CPU_IS_OS(cpuid) (0)
-#define SGN_CPU_IS_OBP(cpuid) (0)
-#define SGN_CPU_STATE_IS_DETACHED(cpuid) (0)
-
-#endif /* _STARFIRE */
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CPU_SGN_H */
diff --git a/usr/src/uts/sun4u/starfire/sys/cvc.h b/usr/src/uts/sun4u/starfire/sys/cvc.h
deleted file mode 100644
index 4f36155022..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/cvc.h
+++ /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.
- */
-
-#ifndef _CVC_H
-#define _CVC_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define cvc_username "ssp"
-#define CVCD_SERVICE "cvc_hostd"
-#define CVC_CONN_SERVICE "cvc"
-#define MAX_CVC_CONN 100
-#define MAXPKTSZ 4096
-
-#define TRUE 1
-#define FALSE 0
-
-/*
- * Network Redirection driver ioctl to jump into debugger.
- */
-#define CVC 'N'
-#define CVC_BREAK (CVC<<8)
-#define CVC_DISCONNECT ((CVC<<8)|0x1)
-
-#define CVC_CONN_BREAK 0x1 /* Break to OBP or kmdb */
-#define CVC_CONN_DIS 0x2 /* disconnect */
-#define CVC_CONN_STAT 0x4 /* status of CVC connects */
-#define CVC_CONN_WRITE 0x8 /* ask write permission */
-#define CVC_CONN_RELW 0x10 /* release write permission */
-#define CVC_CONN_WRLK 0x20 /* Lock the Write */
-#define CVC_CONN_PRIVATE 0x40 /* Only one session is allowed */
-#define CVC_CONN_SWITCH 0x41 /* Switch communication path */
-
-
-#define TCP_DEV "/dev/tcp"
-#define CVCREDIR_DEV "/devices/pseudo/cvcredir@0:cvcredir"
-
-/*
- * Layout of BBSRAM input and output buffers:
- *
- *
- * |---------------|
- * 0x1f400 | control msg | Receive buffer is reduced by two bytes to
- * | 1 byte | accomodate a control msg area in which
- * |---------------| information is sent from obp_helper to the
- * | send buffer | cvc driver (e.g. break to obp) when
- * | | communication is over BBSRAM.
- * | 1020 bytes |
- * |---------------|
- * | send count |
- * 0x1f7fe | 2 bytes |
- * |---------------|
- * | receive buffer|
- * | |
- * | 1022 bytes |
- * |---------------|
- * | output count |
- * 0x1fbfe | 2 bytes |
- * |---------------|
- *
- */
-
-#define BBSRAM_COUNT_SIZE sizeof (short)
-#define CVC_IN_SIZE 256
-#define CVC_OUT_SIZE 1024
-#define MAX_XFER_INPUT (CVC_IN_SIZE - BBSRAM_COUNT_SIZE)
-#define MAX_XFER_OUTPUT (CVC_OUT_SIZE - BBSRAM_COUNT_SIZE)
-
-#define BBSRAM_OUTPUT_COUNT_OFF (CVC_OUT_SIZE - BBSRAM_COUNT_SIZE)
-#define BBSRAM_INPUT_COUNT_OFF (CVC_OUT_SIZE + CVC_IN_SIZE - BBSRAM_COUNT_SIZE)
-
-/*
- * Control msgs sent across BBSRAM from obp_helper to cvc driver
- */
-#define CVC_BBSRAM_BREAK 1
-#define CVC_BBSRAM_DISCONNECT 2
-#define CVC_BBSRAM_VIA_NET 3
-#define CVC_BBSRAM_VIA_BBSRAM 4
-#define CVC_BBSRAM_CLOSE_NET 5
-
-#ifdef _KERNEL
-extern void cvc_assign_iocpu(int cpu_id);
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CVC_H */
diff --git a/usr/src/uts/sun4u/starfire/sys/drmach.h b/usr/src/uts/sun4u/starfire/sys/drmach.h
deleted file mode 100644
index 68b8fcc87e..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/drmach.h
+++ /dev/null
@@ -1,160 +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.
- */
-
-#ifndef _SYS_DRMACH_H_
-#define _SYS_DRMACH_H_
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-#include <sys/memlist.h>
-#include <sys/processor.h>
-#include <sys/starfire.h>
-#include <sys/sbd_ioctl.h>
-#include <sys/sysevent.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MAX_BOARDS plat_max_boards()
-#define MAX_CPU_UNITS_PER_BOARD plat_max_cpu_units_per_board()
-#define MAX_MEM_UNITS_PER_BOARD plat_max_mem_units_per_board()
-#define MAX_IO_UNITS_PER_BOARD plat_max_io_units_per_board()
-#define MAX_CMP_UNITS_PER_BOARD MAX_CPU_UNITS_PER_BOARD
-#define MAX_CORES_PER_CMP 1
-
-/* flags for drmach_configure() and drmach_unconfigure() */
-#define DRMACH_DEVI_FORCE 1
-#define DRMACH_DEVI_REMOVE 2
-
-/* returned with drmach_board_find_devices callback */
-#define DRMACH_DEVTYPE_CPU "cpu"
-#define DRMACH_DEVTYPE_MEM "memory"
-#define DRMACH_DEVTYPE_PCI "pci"
-#define DRMACH_DEVTYPE_SBUS "sbus"
-
-/* number of bytes in smallest coherency unit of this machine */
-#define DRMACH_COHERENCY_UNIT 64
-
-typedef void *drmachid_t;
-
-typedef struct {
- boolean_t assigned;
- boolean_t powered;
- boolean_t configured;
- boolean_t busy;
- boolean_t empty;
- sbd_cond_t cond;
- char type[MAXNAMELEN];
- char info[MAXPATHLEN]; /* TODO: what size? */
-} drmach_status_t;
-
-typedef struct {
- int size;
- char *copts;
-} drmach_opts_t;
-
-extern sbd_error_t *drmach_copy_rename_init(
- drmachid_t dst_id, uint64_t dst_slice_offset,
- drmachid_t src_id, struct memlist *src_copy_ml,
- drmachid_t *pgm_id);
-extern sbd_error_t *drmach_copy_rename_fini(drmachid_t id);
-extern void drmach_copy_rename(drmachid_t id);
-
-extern sbd_error_t *drmach_pre_op(int cmd, drmachid_t id,
- drmach_opts_t *opts);
-extern sbd_error_t *drmach_post_op(int cmd, drmachid_t id,
- drmach_opts_t *opts);
-
-extern sbd_error_t *drmach_board_assign(int bnum, drmachid_t *id);
-extern sbd_error_t *drmach_board_connect(drmachid_t id,
- drmach_opts_t *opts);
-extern sbd_error_t *drmach_board_deprobe(drmachid_t id);
-extern sbd_error_t *drmach_board_disconnect(drmachid_t id,
- drmach_opts_t *opts);
-extern sbd_error_t *drmach_board_find_devices(drmachid_t id, void *a,
- sbd_error_t *(*found)(void *a, const char *, int, drmachid_t));
-extern int drmach_board_lookup(int bnum, drmachid_t *id);
-extern sbd_error_t *drmach_passthru(drmachid_t id,
- drmach_opts_t *opts);
-
-extern sbd_error_t *drmach_board_name(int bnum, char *buf, int buflen);
-
-extern sbd_error_t *drmach_board_poweroff(drmachid_t id);
-extern sbd_error_t *drmach_board_poweron(drmachid_t id);
-extern sbd_error_t *drmach_board_test(drmachid_t id, drmach_opts_t *opts,
- int force);
-
-extern sbd_error_t *drmach_board_unassign(drmachid_t id);
-
-extern sbd_error_t *drmach_configure(drmachid_t id, int flags);
-
-extern sbd_error_t *drmach_cpu_disconnect(drmachid_t id);
-extern sbd_error_t *drmach_cpu_get_id(drmachid_t id, processorid_t *cpuid);
-extern sbd_error_t *drmach_cpu_get_impl(drmachid_t id, int *ip);
-extern void drmach_cpu_flush_ecache_sync(void);
-
-extern sbd_error_t *drmach_get_dip(drmachid_t id, dev_info_t **dip);
-
-extern sbd_error_t *drmach_io_is_attached(drmachid_t id, int *yes);
-extern sbd_error_t *drmach_io_post_attach(drmachid_t id);
-extern sbd_error_t *drmach_io_post_release(drmachid_t id);
-extern sbd_error_t *drmach_io_pre_release(drmachid_t id);
-extern sbd_error_t *drmach_io_unrelease(drmachid_t id);
-
-extern sbd_error_t *drmach_mem_add_span(drmachid_t id,
- uint64_t basepa, uint64_t size);
-extern sbd_error_t *drmach_mem_del_span(drmachid_t id,
- uint64_t basepa, uint64_t size);
-extern sbd_error_t *drmach_mem_disable(drmachid_t id);
-extern sbd_error_t *drmach_mem_enable(drmachid_t id);
-extern sbd_error_t *drmach_mem_get_alignment(drmachid_t id, uint64_t *pa);
-extern sbd_error_t *drmach_mem_get_base_physaddr(drmachid_t id,
- uint64_t *pa);
-extern sbd_error_t *drmach_mem_get_memlist(drmachid_t id,
- struct memlist **ml);
-extern sbd_error_t *drmach_mem_get_size(drmachid_t id, uint64_t *bytes);
-extern sbd_error_t *drmach_mem_get_slice_size(drmachid_t id,
- uint64_t *bytes);
-extern processorid_t drmach_mem_cpu_affinity(drmachid_t id);
-extern int drmach_allow_memrange_modify(drmachid_t id);
-
-extern sbd_error_t *drmach_release(drmachid_t id);
-extern sbd_error_t *drmach_status(drmachid_t id, drmach_status_t *stat);
-extern sbd_error_t *drmach_unconfigure(drmachid_t id, int flags);
-extern int drmach_log_sysevent(int board, char *hint, int flag,
- int verbose);
-
-extern int drmach_verify_sr(dev_info_t *dip, int sflag);
-extern void drmach_suspend_last();
-extern void drmach_resume_first();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_DRMACH_H_ */
diff --git a/usr/src/uts/sun4u/starfire/sys/idn.h b/usr/src/uts/sun4u/starfire/sys/idn.h
deleted file mode 100644
index a8ee2ce9b8..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/idn.h
+++ /dev/null
@@ -1,3886 +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) 2016 by Delphix. All rights reserved.
- *
- * Inter-Domain Network
- */
-
-#ifndef _SYS_IDN_H
-#define _SYS_IDN_H
-
-#ifndef _ASM
-
-#ifdef _KERNEL
-
-#include <sys/note.h>
-
-#include <sys/cmn_err.h>
-#include <sys/dditypes.h>
-#include <sys/stream.h>
-#include <sys/machsystm.h>
-#include <sys/ethernet.h>
-#include <sys/dlpi.h>
-#include <sys/time.h>
-#include <sys/kmem.h>
-#include <sys/atomic.h>
-#include <sys/cpuvar.h>
-
-#include <sys/idn_sigb.h>
-#include <sys/idn_smr.h>
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef const char * const procname_t;
-
-#define MB2B(m) ((size_t)(m) << 20) /* MBytes to Bytes */
-#define B2MB(b) ((uint_t)((b) >> 20)) /* Bytes to MBytes */
-
-#ifdef _KERNEL
-
-/*
- * IDN_PROP_SMRSIZE - User specified size in MBytes.
- * IDN_PROP_SMRADDR - OBP's internal physical address of the region.
- *
- * OBP properties of "memory" node that define the SMR space.
- */
-#define IDN_PROP_SMRSIZE "idn-smr-size"
-#define IDN_PROP_SMRADDR "idn-smr-addr"
-
-/*
- * IDN_AWOLMSG_INTERVAL (driver.conf)
- *
- * Number of seconds between AWOL messages on a per-domain basis.
- * The purpose is to throttle the frequency at which these
- * messages appear.
- *
- * IDN_MSGWAIT_NEGO (driver.conf)
- * IDN_MSGWAIT_CFG
- * IDN_MSGWAIT_CON
- * IDN_MSGWAIT_FIN
- * IDN_MSGWAIT_CMD
- * IDN_MSGWAIT_DATA
- *
- * Number of seconds to wait for response to respective
- * message type.
- *
- * IDN_RETRYFREQ_NEGO (driver.conf)
- * IDN_RETRYFREQ_CON
- * IDN_RETRYFREQ_FIN
- *
- * Number of seconds to wait between retries of the respective
- * message type.
- *
- * IDN_SMR_ALIGN (not tunable)
- *
- * The hardware registers that describe the SMR are based on a 64K
- * aligned physical address.
- *
- * IDN_SMR_SIZE (OBP [only])
- *
- * Total size of the SMR (Shared Memory Region) in bytes.
- *
- * IDN_NWR_SIZE (driver.conf)
- *
- * Total size of the NWR (NetWork Region) portion of the SMR which
- * is actually used to support network activity. The NWR is managed
- * as simply a pool of I/O buffers which are distributed by the
- * Master domain to the Slaves for the purpose of communicating
- * between each other. If not set then the entire SMR is used
- * as the NWR.
- * Req: IDN_NWR_SIZE <= IDN_SMR_SIZE
- *
- * IDN_SMR_BUFSIZE (driver.conf)
- *
- * Size of individual SMR buffers. The SMR is divided into chunks
- * of IDN_SMR_BUFSIZE bytes. The IDN_MTU is based on this size
- * and thus the IDN_SMR_BUFSIZE should be chosen based on performance.
- *
- * IDN_DATA_SIZE (NOT tunable)
- *
- * Portion of IDN_SMR_BUFSIZE that can contain raw non-IDN dependent
- * data. We subtract IDN_ALIGNSIZE bytes to allow for fast bcopy
- * alignment.
- * Req: IDN_DATA_SIZE <=
- * (IDN_SMR_BUFSIZE - sizeof (smr_pkthdr_t) - IDN_ALIGNSIZE)
- *
- * IDN_MTU (indirectly tunable via IDN_SMR_BUFSIZE)
- *
- * This size represents the portion of an SMR I/O buffers that can
- * contain (ethernet headerless) data.
- * Req: IDN_MTU <= IDN_DATA_SIZE - sizeof (ether_header)
- *
- * IDN_WINDOW_MAX (driver.conf)
- *
- * Maximum number of outstanding packets that are allowed per
- * domain. If this value is exceeded for a particular domain
- * no further I/Os will be transmitted to that domain until it
- * has acknowledged enough of the previous transmission to bring
- * down its outstanding I/O count (idn_domain.dio) below this
- * value. In addition, if this value is exceeded then a Timer
- * is scheduled to check for any response from the remote domain.
- *
- * IDN_WINDOW_INCR (driver.conf)
- *
- * As more channels/nets are activated on a particular domain
- * the greater the number of possible outstanding data packets
- * that can be outstanding to a given domain. Since this natural
- * occurence can result in the outstanding-I/O count to a given
- * domain to increase we run the risk of dropping into the
- * IDN_WINDOW_MAX region even though the receiving domain
- * may be fine with handling the load. In order to compensate
- * for this increased activity and to not incur unjustified
- * slips into the IDN_WINDOW_MAX region, the IDN_WINDOW_MAX
- * value is adjusted by IDN_WINDOW_INCR for each channel/net
- * that is activated for a given domain.
- *
- * IDN_WINDOW_EMAX (not tunable)
- *
- * The effective value of IDN_WINDOW_MAX once it has
- * been adjusted by IDN_WINDOW_INCR.
- *
- * IDN_RECLAIM_MIN (driver.conf)
- *
- * Minimum number of outstanding packets that our allowed
- * before subsequent sends will attempt to reclaim some number
- * of outstanding data packets.
- *
- * IDN_RECLAIM_MAX (driver.conf)
- * This value represents the maximum number of outstanding
- * packets we will try to reclaim during a send once we've
- * passed the IDN_RECLAIM_MIN boundary.
- *
- * IDN_MODUNLOADABLE (ndd)
- *
- * By default the IDN driver is unloadable. Setting this
- * variable will allow the IDN driver to be unloaded provided
- * it's not in use.
- *
- * IDN_LOWAT/IDN_HIWAT (driver.conf)
- *
- * Low/High water marks for the STREAM interface to IDN.
- *
- * IDN_MBOX_PER_NET (driver.conf)
- *
- * Number of mailbox entries that are allocated per channel/net.
- * This value effectively represents the amount of outstanding
- * activity that can reside at a domain. Increasing this value
- * allows more packets to be in transit to a domain, however
- * at some point there are diminishing returns since the receiver
- * can only consume packets so fast.
- *
- * IDN_MAX_NETS (driver.conf)
- *
- * Maximum number of network interfaces (channels) that IDN
- * is currently configured to allow. The absolute max is
- * IDN_MAXMAX_NETS. We don't automatically default IDN_MAX_NETS
- * to IDN_MAXMAX_NETS because it would mean wasted space in
- * the mailbox region having to reserve mailboxes that will
- * very likely go unused. The smaller this value the fewer
- * the number of mailboxes in the SMR and thus the greater the
- * number of possible I/O buffers available.
- * Req: IDN_MAX_NETS <= IDN_MAXMAX_NETS
- *
- * IDN_CHECKSUM (driver.conf)
- *
- * If enabled, IDN validates the smr_pkthdr_t of incoming packets
- * via a checksum, and calculates the checksum for outgoing packets.
- * Only the first 3 fields of smr_pkthdr_t are checksummed and
- * must be set to their expected values prior to calculating the
- * checksum. Turned OFF by default when compiled DEBUG.
- *
- * IDN_SMR_MAXSIZE (not tunable)
- *
- * The absolute maximum size of the SMR region that we'll allow.
- * Note that the virtual address space comes out kernelmap.
- */
-#define IDN_AWOLMSG_INTERVAL 60 /* seconds */
-#define IDN_MSGWAIT_NEGO 20 /* seconds */
-#define IDN_MSGWAIT_CFG 40
-#define IDN_MSGWAIT_CON 20
-#define IDN_MSGWAIT_FIN 40
-#define IDN_MSGWAIT_CMD 40
-#define IDN_MSGWAIT_DATA 30
-#define IDN_RETRYFREQ_NEGO 2
-#define IDN_RETRYFREQ_CON 2
-#define IDN_RETRYFREQ_FIN 3
-
-#define IDN_SMR_BUFSIZE_MIN 512
-#define IDN_SMR_BUFSIZE_MAX (512*1024)
-#define IDN_SMR_BUFSIZE_DEF (16*1024)
-
-#define IDN_SMR_SHIFT (16)
-#define IDN_SMR_ALIGN (1 << IDN_SMR_SHIFT) /* 64K */
-#define IDN_SMR_SIZE idn_smr_size
-#define IDN_NWR_SIZE idn_nwr_size
-#define IDN_SMR_BUFSIZE idn_smr_bufsize
-#define IDN_DATA_SIZE (IDN_SMR_BUFSIZE \
- - sizeof (smr_pkthdr_t) \
- - IDN_ALIGNSIZE)
-#define IDN_MTU (IDN_DATA_SIZE - sizeof (struct ether_header))
-#define IDN_WINDOW_MAX idn_window_max
-#define IDN_WINDOW_INCR idn_window_incr
-#define IDN_WINDOW_EMAX idn_window_emax
-#define IDN_RECLAIM_MIN idn_reclaim_min
-#define IDN_RECLAIM_MAX idn_reclaim_max
-#define IDN_MODUNLOADABLE idn_modunloadable
-#define IDN_LOWAT idn_lowat
-#define IDN_HIWAT idn_hiwat
-#define IDN_MBOX_PER_NET idn_mbox_per_net
-#define IDN_MAX_NETS idn_max_nets
-#define IDN_CHECKSUM idn_checksum
-#define IDN_SMR_MAXSIZE 96
-#define _IDN_SMR_SIZE 32 /* 32M */
-#define _IDN_NWR_SIZE _IDN_SMR_SIZE /* 32M */
-#define _IDN_SMR_BUFSIZE (16 * 1024) /* 16K */
-
-
-#define IDN_TUNEVAR_NAME(v) (*(char **)((ulong_t)&(v)+(sizeof (ulong_t))))
-#define IDN_TUNEVAR_VALUE(v) (v)
-
-/*
- * History structure to support problem analysis.
- */
-#define IDN_HISTORY_NUM 1024
-#define IDN_HISTORY_LOG(op, d0, d1, d2) \
- if (idn_history) { \
- mutex_enter(&idnhlog.h_mutex); \
- idnhlog.h_log[idnhlog.h_index].e_time = TIMESTAMP(); \
- idnhlog.h_log[idnhlog.h_index].e_op = (ushort_t)(op); \
- idnhlog.h_log[idnhlog.h_index].e_data[0] = (ushort_t)(d0); \
- idnhlog.h_log[idnhlog.h_index].e_data[1] = (ushort_t)(d1); \
- idnhlog.h_log[idnhlog.h_index].e_data[2] = (ushort_t)(d2); \
- idnhlog.h_index++; \
- idnhlog.h_index &= (IDN_HISTORY_NUM - 1); \
- mutex_exit(&idnhlog.h_mutex); \
- }
-
-#define IDNH_GSTATE 0x0001 /* d0=gstate, d1=, d2= */
-#define IDNH_DSTATE 0x0002 /* d0=domid, d1=dstate, d2=cpuid */
-#define IDNH_AWOL 0x0003 /* d0=domid, d1=dstate, d2=cpuid */
-#define IDNH_MASTERID 0x0004 /* d0=masterid, d1=oldid, d2= */
-#define IDNH_NEGO 0x0005 /* d0=domid, d1=ds_trans_on, d2=ds_connected */
-#define IDNH_FIN 0x0006 /* d0=domid, d1=finstate, d2= */
-#define IDNH_RELINK 0x0007 /* d0=domid, d1=dstate, d2=ds_relink */
-
-struct idn_h_entry {
- hrtime_t e_time;
- ushort_t e_op;
- ushort_t e_data[3];
-};
-
-struct idn_history {
- kmutex_t h_mutex;
- int h_index;
- struct idn_h_entry h_log[IDN_HISTORY_NUM];
-};
-#endif /* _KERNEL */
-
-/*
- * IDN_SIGBPIL - Interrupt level at which IDN driver
- * wakes up idn_sigbhandler_thread
- */
-#define IDN_SIGBPIL PIL_3
-
-/*
- * Definition of sigbintr.sb_busy values which
- * represents state of idn_sigbhandler.
- */
-#define IDNSIGB_NOTREADY ((uchar_t)0)
-#define IDNSIGB_INACTIVE ((uchar_t)1)
-#define IDNSIGB_STARTED ((uchar_t)2)
-#define IDNSIGB_ACTIVE ((uchar_t)3)
-#define IDNSIGB_DIE ((uchar_t)4)
-
-/*
- * Some Xfire based macros that assume 4 cpus per board.
- */
-#define CPUID_TO_BOARDID(c) ((c) >> 2)
-#define MAX_CPU_PER_BRD 4
-#define CPUSET_TO_BOARDSET(cset, bset) \
- { \
- register int c, b; \
- (bset) = 0; \
- for (b = 0; b < MAX_BOARDS; b++) \
- for (c = 0; c < MAX_CPU_PER_BRD; c++) \
- if (CPU_IN_SET((cset), \
- (b * MAX_CPU_PER_BRD) + c)) \
- (bset) |= 1 << b; \
- }
-
-/*
- * Macros to manipulate boardset and domainset masks.
- */
-typedef ushort_t boardset_t; /* assumes max of 16 boards */
-typedef ushort_t domainset_t; /* assumes max of 16 domains */
-
-#define BOARDSET(brd) ((boardset_t)(1 << (brd)))
-#define BOARDSET_ALL ((boardset_t)~0)
-#define BOARD_IN_SET(set, brd) ((set) & BOARDSET(brd))
-#define BOARDSET_ADD(set, brd) ((set) |= BOARDSET(brd))
-#define BOARDSET_DEL(set, brd) ((set) &= ~BOARDSET(brd))
-#define DOMAINSET(d) ((domainset_t)1 << (d))
-#define DOMAINSET_ALL ((domainset_t)~0)
-#define DOMAIN_IN_SET(s, d) ((s) & DOMAINSET(d))
-#define DOMAINSET_ADD(s, d) ((s) |= DOMAINSET(d))
-#define DOMAINSET_DEL(s, d) ((s) &= ~DOMAINSET(d))
-
-/*
- * PFN_TO_SMADDR macro converts a PFN to a IDN_SMR_ALIGN'ed
- * address suitable for the CIC bar/lar registers.
- */
-#if (IDN_SMR_SHIFT <= MMU_PAGESHIFT)
-#define PFN_TO_SMADDR(pfn) ((pfn) << (MMU_PAGESHIFT - IDN_SMR_SHIFT))
-#else
-#define PFN_TO_SMADDR(pfn) ((pfn) >> (IDN_SMR_SHIFT - MMU_PAGESHIFT))
-#endif
-
-/*
- * Translate a physical address to a unique domain identifier.
- * IMPORTANT - Assumes each board's memory is configured on a 8GB
- * boundary. PA(8G) = PFN(1M).
- */
-#define MEM8G_SHIFT 33 /* (1 << 33) == 8G */
-#define PADDR_TO_DOMAINID(paddr) ((int)((paddr) >> MEM8G_SHIFT) & 0xf)
-
-#define VALID_NWROFFSET(off, align) \
- (((uint_t)(off) >= 0) && \
- ((size_t)(off) < MB2B(IDN_NWR_SIZE)) && \
- !((uint_t)(off) & ((align) - 1)))
-#define VALID_NWRADDR(addr, align) \
- (((caddr_t)(addr) >= idn.smr.vaddr) && \
- VALID_NWROFFSET(((caddr_t)(addr) - idn.smr.vaddr), (align)))
-#define VALID_DOMAINID(d) (((d) >= 0) && ((d) < MAX_DOMAINS))
-#define VALID_UDOMAINID(d) ((d) < MAX_DOMAINS)
-#define VALID_CPUID(c) (((c) >= 0) && ((c) < NCPU))
-#define VALID_CHANNEL(c) (((c) >= 0) && ((c) < IDN_MAX_NETS))
-#define VALID_UCHANNEL(c) ((c) < IDN_MAX_NETS)
-
-/*
- * The following are bit values of idn_debug, currently
- * only useful if compiled with DEBUG.
- */
-#ifdef DEBUG
-#define STRING(sss) char sss[20]
-#define INUM2STR(mm, ss) inum2str((mm), (ss))
-
-#define IDNDBG_XDC 0x00000001
-#define IDNDBG_XF 0x00000002
-#define IDNDBG_REGS 0x00000004
-#define IDNDBG_SMR 0x00000008
-#define IDNDBG_PROTO 0x00000010
-#define IDNDBG_STR 0x00000020
-#define IDNDBG_DRV 0x00000040
-#define IDNDBG_DATA 0x00000080
-#define IDNDBG_STATE 0x00000100
-#define IDNDBG_DLPI 0x00000200
-#define IDNDBG_KERN 0x00000400
-#define IDNDBG_ALLOC 0x00000800
-#define IDNDBG_REMAP 0x00001000
-#define IDNDBG_TIMER 0x00002000
-#define IDNDBG_CHAN 0x00004000
-#define IDNDBG_AWOL 0x00008000
-#define IDNDBG_SYNC 0x00010000
-#define _IDNDBG_UNUSED0 0x00020000
-#define IDNDBG_HITLIST 0x00040000
-#define IDNDBG_XMON 0x00080000
-#define IDNDBG_TEST 0x80000000
-#define IDNDBG_ALL ((uint_t)-1)
-
-#define PR_ALL if (idn_debug) printf
-#define PR_XDC if (idn_debug & IDNDBG_XDC) printf
-#define PR_XF if (idn_debug & IDNDBG_XF) printf
-#define PR_REGS if (idn_debug & IDNDBG_REGS) printf
-#define PR_SMR if (idn_debug & IDNDBG_SMR) printf
-#define PR_PROTO if (idn_debug & IDNDBG_PROTO) printf
-#define PR_STR if (idn_debug & IDNDBG_STR) printf
-#define PR_DRV if (idn_debug & IDNDBG_DRV) printf
-#define PR_DATA if (idn_debug & IDNDBG_DATA) printf
-#define PR_STATE if (idn_debug & IDNDBG_STATE) printf
-#define PR_DLPI if (idn_debug & IDNDBG_DLPI) printf
-#define PR_KERN if (idn_debug & IDNDBG_KERN) printf
-#define PR_ALLOC if (idn_debug & IDNDBG_ALLOC) printf
-#define PR_REMAP if (idn_debug & (IDNDBG_SMR|IDNDBG_REMAP)) printf
-#define PR_TIMER if (idn_debug & IDNDBG_TIMER) printf
-#define PR_CHAN if (idn_debug & IDNDBG_CHAN) printf
-#define PR_AWOL if (idn_debug & (IDNDBG_PROTO|IDNDBG_AWOL)) printf
-#define PR_SYNC if (idn_debug & IDNDBG_SYNC) printf
-#define _PR_UNUSED0 if (idn_debug & _IDNDBG_UNUSED0) printf
-#define PR_HITLIST if (idn_debug & IDNDBG_HITLIST) printf
-#define PR_XMON if (idn_debug & IDNDBG_XMON) printf
-#define PR_TEST if (idn_debug & IDNDBG_TEST) printf
-#else
-#define STRING(sss) char *sss = ""
-#define INUM2STR(mm, ss)
-
-#define PR_ALL if (0) printf
-#define PR_XDC PR_ALL
-#define PR_XF PR_ALL
-#define PR_REGS PR_ALL
-#define PR_SMR PR_ALL
-#define PR_PROTO PR_ALL
-#define PR_STR PR_ALL
-#define PR_DRV PR_ALL
-#define PR_DATA PR_ALL
-#define PR_STATE PR_ALL
-#define PR_DLPI PR_ALL
-#define PR_KERN PR_ALL
-#define PR_ALLOC PR_ALL
-#define PR_REMAP PR_ALL
-#define PR_TIMER PR_ALL
-#define PR_CHAN PR_ALL
-#define PR_AWOL PR_ALL
-#define PR_SYNC PR_ALL
-#define PR_SNOOP PR_ALL
-#define PR_HITLIST PR_ALL
-#define PR_XMON PR_ALL
-#define PR_TEST PR_ALL
-#endif /* DEBUG */
-
-#ifdef _KERNEL
-/*
- * IDN drivers fields.
- *
- * IDNMINPSZ Minimum packet size the IDN supports.
- *
- * IDNMAXPSZ Maximum packet size that IDN supports from upper
- * layers. Is equal to IDN_MTU + ether_header. Note
- * that the IDN driver could support larger packets
- * however the infrastructure to support fragmentation
- * does not (and should not) exist with respect to
- * ethernet packet types.
- */
-#ifdef DEBUG
-#define IDNDESC "Inter-Domain Network (DEBUG)"
-#else
-#define IDNDESC "Inter-Domain Network"
-#endif /* DEBUG */
-
-#define IDNIDNUM 8264
-#define IDNNAME "idn"
-#define IDNMINPSZ 0 /* set at idnopen() */
-#define IDNMAXPSZ 0 /* set at idnopen() */
-
-#endif /* _KERNEL */
-
-/*
- * IDN Global States.
- */
-typedef enum {
-/* 0 */ IDNGS_OFFLINE = 0, /* idle */
-/* 1 */ IDNGS_CONNECT, /* connecting initial domain */
-/* 2 */ IDNGS_ONLINE, /* master selected */
-/* 3 */ IDNGS_DISCONNECT, /* local is unlinking */
-/* 4 */ IDNGS_RECONFIG, /* selecting new master */
-/* 5 */ _IDNGS_UNUNSED5,
-/* 6 */ _IDNGS_UNUNSED6,
-/* 7 */ _IDNGS_UNUNSED7,
-/* 8 */ _IDNGS_UNUNSED8,
-/* 9 */ _IDNGS_UNUNSED9,
-/* 10 */ IDNGS_IGNORE /* ignore requests (fault injection) */
-} idn_gstate_t;
-
-#ifdef _KERNEL
-
-#define TIMESTAMP() (gethrtime() / 1000000ull)
-
-/*
- * Spaced defined in:
- * sigblkp[cpu0.cpu_id]->sigb_idn.reserved1.
- */
-#define IDNSB_GSTATE_NEW 0
-#define IDNSB_GSTATE_OLD 1
-#define IDNSB_MASTERCPU 2
-#define IDNSB_RESERVED 3
-
-#define IDNSB_HWCHKPT_MAX 4
-
-#define IDNSB_SIZE 72
-/*
- * This structure gets overlay onto:
- * sigblkp[cpu0.cpu_id]->sigb_idn.reserved1.
- *
- * This structure must be exactly IDNSB_SIZE bytes.
- */
-typedef struct idnsb {
- uchar_t id_gstate;
- uchar_t id_pgstate;
- uchar_t id_master_board;
- uchar_t id_pmaster_board;
-
- uchar_t reserved_DO_NOT_USE[24]; /* idnevent_t field */
-
- struct {
- uchar_t d_board;
- uchar_t d_state;
- } id_status[MAX_DOMAINS];
- uint_t id_hwstate;
- ushort_t id_hwchkpt[IDNSB_HWCHKPT_MAX];
-} idnsb_t; /* sizeof = 72 (0x48) 18X bytes */
-
-
-#define IDNSB_DOMAIN_UPDATE(dp) \
- { \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- int domid = (dp)->domid; \
- if ((dp)->dcpu == IDN_NIL_DCPU) \
- idn.idnsb->id_status[domid].d_board = \
- (uchar_t)0xff; \
- else if ((dp)->dvote.v.board == 0) \
- idn.idnsb->id_status[domid].d_board = \
- (uchar_t)CPUID_TO_BOARDID((dp)->dcpu); \
- else \
- idn.idnsb->id_status[domid].d_board = \
- (uchar_t)(dp)->dvote.v.board; \
- idn.idnsb->id_status[domid].d_state = \
- (uchar_t)(dp)->dstate; \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- }
-/*
- * The following definitions and macros pertain to the
- * id_hwstate and id_hwchkpt[] fields.
- *
- * id_hwstate (m = mark: 1=open, 2=close)
- * 0 1 2 3 4 5 6 7
- * ---------------------------------
- * | m | m | m | m | XX unused XXX |
- * ---------------------------------
- * | | | |
- * | | | +- CACHE
- * | | +- CHAN
- * | +- LINK
- * +- SMR
- *
- * Note that nibble 4 is used in DEBUG for noting cache
- * flush progress through idnxf_flushall_ecache(). This
- * will override id_hwchkpt[] since it only has room for
- * 4 items, however the BBSRAM space is there and
- * unofficially available :-o
- *
- * id_hwchkpt[0] = SMR boardset
- * id_hwchkpt[1] = LINK boardset
- * id_hwchkpt[2] = CHAN boardset
- * id_hwchkpt[3] = CACHE boardset.
- */
-#define IDNSB_CHKPT_SMR 0
-#define IDNSB_CHKPT_LINK 1
-#define IDNSB_CHKPT_CHAN 2
-#define IDNSB_CHKPT_CACHE 3
-#define IDNSB_CHKPT_UNUSED 4 /* This is the max you can have */
-
-#define _CHKPT_MARKIT(item, mark) \
- { \
- uint_t mk = (((uint_t)((mark) & 0xf)) << \
- (((sizeof (uint_t) << 1) - 1 - (item)) << 2)); \
- uint_t *sp = &idn.idnsb->id_hwstate; \
- ASSERT(idn.idnsb); \
- *sp &= ~(((uint_t)0xf) << (((sizeof (uint_t) << 1) \
- - 1 - (item)) << 2)); \
- *sp |= mk; \
- }
-
-#define CHECKPOINT_OPENED(item, bset, mark) \
- { \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \
- _CHKPT_MARKIT((item), (mark)); \
- sp[item] |= ((ushort_t)(bset)); \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- }
-
-#define CHECKPOINT_CLOSED(item, bset, mark) \
- { \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \
- _CHKPT_MARKIT((item), (mark)); \
- sp[item] &= (ushort_t)~(bset); \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- }
-
-#define CHECKPOINT_CLEAR(item, mark) \
- { \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \
- _CHKPT_MARKIT((item), (mark)); \
- sp[item] = 0; \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- }
-#ifdef DEBUG
-#define CHECKPOINT_CACHE_CLEAR_DEBUG(mark) \
- CHECKPOINT_CLEAR(IDNSB_CHKPT_UNUSED, (mark))
-#define CHECKPOINT_CACHE_STEP_DEBUG(bset, mark) \
- CHECKPOINT_OPENED(IDNSB_CHKPT_UNUSED, (bset), (mark))
-#else
-#define CHECKPOINT_CACHE_CLEAR_DEBUG(mark)
-#define CHECKPOINT_CACHE_STEP_DEBUG(bset, mark)
-#endif /* DEBUG */
-
-
-#ifdef DEBUG
-#define IDN_GSTATE_TRANSITION(ns) \
- { \
- hrtime_t tstamp; \
- /*LINTED*/ \
- IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \
- tstamp = TIMESTAMP(); \
- ASSERT(IDN_GLOCK_IS_EXCL()); \
- PR_STATE("GSTATE:%ld: (l=%d) %s(%d) -> %s(%d)\n", \
- (uint64_t)tstamp, __LINE__, \
- idngs_str[idn.state], idn.state, \
- idngs_str[ns], (ns)); \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- idn.idnsb->id_pgstate = (uchar_t)idn.state; \
- idn.idnsb->id_gstate = (uchar_t)(ns); \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- idn.state = (ns); \
- }
-#else
-#define IDN_GSTATE_TRANSITION(ns) \
- { \
- IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- idn.idnsb->id_pgstate = (uchar_t)idn.state; \
- idn.idnsb->id_gstate = (uchar_t)(ns); \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- idn.state = (ns); \
- }
-#endif /* DEBUG */
-
-/*
- * IDN link/unlink operations occur asynchronously with respect to the
- * caller. The following definitions are to support the return of
- * success/failure back to the original requesting thread. It's
- * unlikely to have multiple outstanding link/unlink requests so we
- * just provide a very small cache of waiting list entries. If the
- * cache becomes exhausted then additional ones are kmem_alloc'd.
- */
-#define IDNOP_CACHE_SIZE 3
-#define IDNOP_IN_CACHE(dwl) \
- (((dwl) >= &idn.dopers->_dop_wcache[0]) && \
- ((dwl) < &idn.dopers->_dop_wcache[IDNOP_CACHE_SIZE]))
-
-typedef struct dop_waitlist {
- struct dop_waitlist *dw_next;
- domainset_t dw_reqset;
- domainset_t dw_domset;
- short dw_op;
- domainset_t dw_errset;
- idnsb_error_t *dw_idnerr;
- short dw_errors[MAX_DOMAINS];
-} dop_waitlist_t;
-
-typedef uint_t idn_xdcargs_t[4];
-typedef uint_t idn_chanset_t;
-
-/*
- * Types of synchronization zones which a connection
- * could be in.
- */
-typedef enum {
- IDNSYNC_NIL,
- IDNSYNC_CONNECT,
- IDNSYNC_DISCONNECT
-} idn_synccmd_t;
-
-/*
- * Type of sync-registration that is being requested.
- */
-typedef enum {
- IDNSYNC_REG_REG,
- IDNSYNC_REG_NEW,
- IDNSYNC_REG_QUERY
-} idn_syncreg_t;
-
-#define IDN_SYNC_NUMZONE 3
-#define IDN_SYNC_GETZONE(s) ((((s) != IDNSYNC_CONNECT) && \
- ((s) != IDNSYNC_DISCONNECT)) ? \
- -1 : (int)(s) - 1)
-#define IDN_SYNC_GETTRANS(s) (((s) == IDNSYNC_CONNECT) ? \
- idn.domset.ds_trans_on : \
- ((s) == IDNSYNC_DISCONNECT) ? \
- idn.domset.ds_trans_off : 0)
-
-/*
- * Generic states when in a state transition region.
- * These ultimately map to domain states via
- * a idn_xphase_t definition. General model:
- *
- * PEND
- * /\
- * / \
- * | |
- * V V
- * SENT--->RCVD
- * \ /
- * \ /
- * VV
- * FINAL
- *
- * Start these types with PEND = 0 so that they're
- * compatible with idnxs_state_table[] and idn_xphase_t
- * phases that use the value as an index.
- */
-typedef enum {
-/* 0 */ IDNXS_PEND = 0,
-/* 1 */ IDNXS_SENT,
-/* 2 */ IDNXS_RCVD,
-/* 3 */ IDNXS_FINAL,
-/* 4 */ IDNXS_NIL
-} idn_xstate_t;
-
-/*
- * Locking protocol:
- *
- * Each routine is called with SYNC_LOCK and
- * the respective domain's DLOCK(EXCL) held.
- * The routines must return with these locks
- * still held.
- */
-struct idn_msgtype;
-
-typedef struct {
- int t_state;
- int (*t_check)(int domid, struct idn_msgtype *mtp,
- idn_xdcargs_t xargs);
- void (*t_action)(int domid, struct idn_msgtype *mtp,
- idn_xdcargs_t xargs);
- void (*t_error)(int domid, struct idn_msgtype *mtp,
- idn_xdcargs_t xargs);
-} idn_trans_t;
-
-/*
- * The callback routines (xt_final & xt_exit) are called with
- * DLOCK and SYNC_LOCK held and they are required to return
- * with these locks still held.
- */
-typedef struct {
- uint_t xt_msgtype;
- idn_trans_t xt_trans[4];
- void (*xt_final)(int domid);
- void (*xt_exit)(int domid, uint_t msgtype);
-} idn_xphase_t;
-
-/*
- * Synchronization entry representing the synchronization
- * state with respect to a given domain for a given zone.
- */
-typedef struct idn_syncop {
- struct idn_syncop *s_next;
- int s_domid;
- idn_synccmd_t s_cmd;
- int s_msg;
-
- domainset_t s_set_exp;
- domainset_t s_set_rdy;
- int (*s_transfunc)(int domid, void *arg);
- void *s_transarg;
-#ifdef DEBUG
- int s_query[MAX_DOMAINS];
-#endif /* DEBUG */
-} idn_syncop_t;
-
-#ifdef DEBUG
-#define IDN_SYNC_QUERY_INIT(d) \
- (bzero((caddr_t)idn_domain[d].dsync.s_query, \
- sizeof (idn_domain[d].dsync.s_query)))
-#define IDN_SYNC_QUERY_UPDATE(md, sd) (idn_domain[md].dsync.s_query[sd]++)
-#else /* DEBUG */
-#define IDN_SYNC_QUERY_INIT(d)
-#define IDN_SYNC_QUERY_UPDATE(md, sd)
-#endif /* DEBUG */
-
-typedef struct {
- idn_syncop_t *sc_op;
- int sc_cnt;
-} idn_synczone_t;
-
-#endif /* _KERNEL */
-
-/*
- * Vote Ticket used during negotiations and elections.
- *
- * 31 0
- * -----------------------------------------
- * |m...|....|pppp|....|Cbbb|bccc|cccB|BBB1|
- * -----------------------------------------
- * m [31] = master/slave
- * . [30:24] = unused
- * p [23:20] = priority
- * . [19:16] = unused
- * C [15] = connected (has master)
- * b [14:11] = nmembrds-1
- * c [10:5] = ncpus-1
- * B [4:1] = board_id
- * 1 [0] = one
- */
-typedef union {
- struct {
- uint_t master :1;
- uint_t unused0 :7;
- uint_t priority :4;
- uint_t unused1 :4;
- uint_t connected :1;
- uint_t nmembrds :4;
- uint_t ncpus :6;
- uint_t board :4;
- uint_t one :1;
- } v;
- uint_t ticket;
-} idn_vote_t;
-
-#define IDNVOTE_PRI_MASK 0xf
-#define IDNVOTE_MAXPRI 0xf
-#define IDNVOTE_MINPRI 0
-#define IDNVOTE_DEFPRI 1 /* must be larger than MINPRI */
-/*
- * Initially:
- * vote.v.priority = IDNVOTE_DEFPRI
- * vote.v.one = 1
- */
-#define IDNVOTE_INITIAL_TICKET ((IDNVOTE_DEFPRI << 20) | 1)
-#define IDNVOTE_PRIVALUE(vvv) \
- ((int)vvv.v.priority + ((int)vvv.v.master ? IDNVOTE_MAXPRI : 0))
-
-/*
- * During elections we only use the "elect" attributes of the
- * election ticket, i.e. those physical attributes pertaining
- * to the individual domain (priority, nboards, ncpus, board).
- */
-#define IDNVOTE_ELECT_MASK 0x00f07fff
-#define IDNVOTE_ELECT(tkt) ((tkt).ticket & IDNVOTE_ELECT_MASK)
-#define IDNVOTE_BASICS_MASK 0x00f0ffff
-#define IDNVOTE_BASICS(tkt) ((tkt).ticket & IDNVOTE_BASICS_MASK)
-
-/*
- * Values used in idn_select_master().
- */
-#define MASTER_IS_NONE 0 /* index into master_select_table */
-#define MASTER_IS_OTHER 1
-#define MASTER_IS_LOCAL 2
-#define MASTER_IS_REMOTE 3
-
-typedef enum {
- MASTER_SELECT_VOTE,
- MASTER_SELECT_VOTE_RCFG,
- MASTER_SELECT_CONNECT,
- MASTER_SELECT_REMOTE,
- MASTER_SELECT_LOCAL,
- MASTER_SELECT_WAIT,
- MASTER_SELECT_ERROR
-} idn_master_select_t;
-
-/*
- * Used to synchronize completion of link/unlink with respect to
- * the original requester (user). Necessary since link establishment
- * occurs asynchronously.
- */
-typedef enum {
-/* 0 */ IDNOP_DISCONNECTED, /* successfully disconnected */
-/* 1 */ IDNOP_CONNECTED, /* successfully established */
-/* 2 */ IDNOP_ERROR /* error trying to link/unlink */
-} idn_opflag_t;
-
-/*
- * IDN Protocol Messages.
- * These are IDN version (IDN_VERSION) dependent.
- *
- * ----- 7, --- 6,5.................0
- * | ack | nack | IDN message type |
- * ----------------------------------
- */
-#define IDN_VERSION 1
-
-/*
- * Must be no more than 6-bits. See DMV private data.
- */
-#define IDNP_ACK 0x20
-#define IDNP_NACK 0x10
-#define IDNP_NULL 0x00
-#define IDNP_NEGO 0x01
-#define IDNP_CON 0x02
-#define IDNP_CFG 0x03
-#define IDNP_FIN 0x04
-#define IDNP_CMD 0x05
-#define IDNP_DATA 0x06
-
-#define IDN_NUM_MSGTYPES 7
-#define IDNP_ACKNACK_MASK (IDNP_ACK | IDNP_NACK)
-#define IDNP_MSGTYPE_MASK 0x0f
-#define VALID_MSGTYPE(m) (((m) >= IDNP_NEGO) && ((m) < IDN_NUM_MSGTYPES))
-
-typedef struct idn_msgtype {
- ushort_t mt_mtype;
- ushort_t mt_atype;
- ushort_t mt_cookie;
-} idn_msgtype_t;
-
-/*
- * IDN private data section of DMV layout (48 bits).
- *
- * 47......40,39.....34,33.....28,27..24,23......16,15..............0
- * | version | msgtype | acktype | did | cpuid | cookie |
- * ------------------------------------------------------------------
- *
- * version Local domain's version of IDN software.
- * msgtype Type of IDN message, e.g. nego, syn, etc.
- * acktype If msgtype is a ACK or NACK, then acktype is the
- * type of ack that we're receiving, e.g. ack/nego|ack.
- * did Local domain's ID (netid) - system-wide unique.
- * cpuid Local domain's CPU->cpu_id that sending message.
- * cookie Cookie assigned by remote domain for authentication.
- * For NEGO & NEGO+ACK messages, it's the cookie that
- * the sender expects the receiver to use in subsequent
- * messages. The upper-eight bits represent a timer
- * cookie to associate timers with expected messages.
- */
-#endif /* !_ASM */
-
-#ifdef _KERNEL
-
-#define _IDNPD_COOKIE_MASK 0xffff
-#define _IDNPD_COOKIE_SHIFT 32
-#define _IDNPD_VER_MASK 0xff
-#define _IDNPD_VER_SHIFT 24
-#define _IDNPD_MTYPE_MASK 0x3f
-#define _IDNPD_MTYPE_SHIFT 18
-#define _IDNPD_ATYPE_MASK 0x3f
-#define _IDNPD_ATYPE_SHIFT 12
-#define _IDNPD_DOMID_MASK 0xf
-#define _IDNPD_DOMID_SHIFT 8
-#define _IDNPD_CPUID_MASK 0xff
-#define _IDNPD_CPUID_SHIFT 0
-
-#define _IDNPD_COOKIE_LEN 16
-
-#ifndef _ASM
-
-#define IDN_PD2COOKIE(pdata) \
- (((uint_t)((pdata) >> _IDNPD_COOKIE_SHIFT)) & _IDNPD_COOKIE_MASK)
-#define IDN_PD2VER(pdata) \
- (((uint_t)((pdata) >> _IDNPD_VER_SHIFT)) & _IDNPD_VER_MASK)
-#define IDN_PD2MTYPE(pdata) \
- (((uint_t)((pdata) >> _IDNPD_MTYPE_SHIFT)) & _IDNPD_MTYPE_MASK)
-#define IDN_PD2ATYPE(pdata) \
- (((uint_t)((pdata) >> _IDNPD_ATYPE_SHIFT)) & _IDNPD_ATYPE_MASK)
-#define IDN_PD2DOMID(pdata) \
- (((uint_t)((pdata) >> _IDNPD_DOMID_SHIFT)) & _IDNPD_DOMID_MASK)
-#define IDN_PD2CPUID(pdata) \
- (((uint_t)((pdata) >> _IDNPD_CPUID_SHIFT)) & _IDNPD_CPUID_MASK)
-
-#define IDN_MAKE_PDATA(mtype, atype, cookie) \
- ((((uint64_t)(cookie) & UINT64_C(_IDNPD_COOKIE_MASK)) << \
- _IDNPD_COOKIE_SHIFT) | \
- (((uint64_t)idn.version & UINT64_C(_IDNPD_VER_MASK)) << \
- _IDNPD_VER_SHIFT) | \
- (((uint64_t)(mtype) & UINT64_C(_IDNPD_MTYPE_MASK)) << \
- _IDNPD_MTYPE_SHIFT) | \
- (((uint64_t)(atype) & UINT64_C(_IDNPD_ATYPE_MASK)) << \
- _IDNPD_ATYPE_SHIFT) | \
- (((uint64_t)idn.localid & UINT64_C(_IDNPD_DOMID_MASK)) << \
- _IDNPD_DOMID_SHIFT) | \
- (((uint64_t)CPU->cpu_id & UINT64_C(_IDNPD_CPUID_MASK)) << \
- _IDNPD_CPUID_SHIFT))
-
-#define IDN_TCOOKIE(ck) (((ck) >> 8) & 0xff)
-#define IDN_DCOOKIE(ck) ((ck) & 0xff)
-#define IDN_MAKE_COOKIE(d, t) ((((t) & 0xff) << 8) | ((d) & 0xff))
-
-/*
- * IDNP_NEGO
- *
- * 127........96,95........64,63........32,31.........0
- * | vote | domainset |
- * ----------------------------------------------------
- * vote Local/Remote domain's vote ticket.
- * domainset Mask of cpuids of domains to which
- * sender is connected. Position in domainset
- * designates respective domainid.
- * E.g. domainset[6] = 20 -> domainid 6 is
- * accessible via cpuid 20.
- * The slot for the receiving domain
- * contains the masterid of the sending
- * domain. If the sending domain does
- * not have a master then the entry will
- * contain IDNNEG_NO_MASTER.
- *
- * These macros insert a domainid-cpuid pair into the
- * domainset to be subsequently passed in a NEGO message,
- * also retrieve the cpuid from the domainset for a
- * given domainid.
- *
- * Usage:
- * Sending:
- * mask = IDNNEG_DSET_MYMASK();
- * IDNNEG_DSET_INIT(dset, mask)
- * for (all domains except self)
- * IDNNEG_DSET_SET(dset, domain, cpuid, mask);
- *
- * Receiving:
- * IDNNEG_DSET_GET_MASK(dset, recv_domid, recv_mask);
- * for (all domains except recv_domid)
- * IDNNEG_DSET_GET(dset, domid, cpuid, recv_mask);
- */
-typedef uint_t idnneg_dset_t[3];
-
-#define IDNNEG_NO_MASTER 0x3f
-#define __IDNNEG_DSET_CLEAR(dset) (bzero((caddr_t)(dset), \
- sizeof (idnneg_dset_t)))
-#define IDNNEG_DSET_MYMASK() (idn_domain[idn.localid].dcpu)
-
-#define IDNNEG_DSET_INIT(dset, mask) \
- { \
- __IDNNEG_DSET_CLEAR(dset); \
- IDNNEG_DSET_SET((dset), idn.localid, (mask), idn.localid); \
- }
-
-#define IDNNEG_DSET_SET(dset, domid, cpuid, mask) \
- { \
- uint_t _s = ((domid) & 0xf) * 6; \
- int _i = _s >> 5; \
- uint_t _s0 = _s & 0x1f; \
- uint_t _t = ((cpuid) ^ (mask)) & 0x3f; \
- /*LINTED*/ \
- ASSERT(((domid) == idn.localid) ? \
- ((mask) == idn.localid) : ((cpuid) != (mask))); \
- (dset)[_i] |= _t << _s0; \
- if ((_s0 + 6) > 32) \
- (dset)[_i + 1] |= _t >> (32 - _s0); \
- }
-
-#define __IDNNEG_DSET_GET(dset, domid, cpuid, mask, uncond) \
- { \
- uint_t _s = ((domid) & 0xf) * 6; \
- int _i = _s >> 5; \
- uint_t _s0 = _s & 0x1f; \
- uint_t _s1 = (_s + 6) & 0x1f; \
- (cpuid) = ((dset)[_i] >> _s0) & 0x3f; \
- if ((_s0 + 6) > 32) \
- (cpuid) |= ((dset)[_i + 1] << (6 - _s1)) & 0x3f; \
- if ((cpuid) || (uncond)) \
- (cpuid) ^= (mask) & 0x3f; \
- else \
- (cpuid) = -1; \
- }
-
-#define IDNNEG_DSET_GET_MASK(dset, domid, mask) \
- __IDNNEG_DSET_GET((dset), (domid), (mask), (domid), 1)
-
-#define IDNNEG_DSET_GET_MASTER(dset, master) \
- __IDNNEG_DSET_GET((dset), idn.localid, (master), \
- idn.localid+MAX_DOMAINS, 0)
-
-#define IDNNEG_DSET_SET_MASTER(dset, domid, master) \
- IDNNEG_DSET_SET((dset), (domid), (master), \
- (domid)+MAX_DOMAINS)
-
-#define IDNNEG_DSET_GET(dset, domid, cpuid, mask) \
- __IDNNEG_DSET_GET((dset), (domid), (cpuid), (mask), 0)
-
-/*
- * IDNP_CFG sub-types.
- *
- * Format of first 32 bit word in XDC:
- * stX = sub-type.
- * staX = sub-type arg.
- * X = position in idn_cfgsubtype_t.param.p[] array.
- * num = number of parameters in this XDC (0-3)
- *
- * 31...28,27...24,23...20,19...16,15...12,11....8,7.....3,2....0
- * | st0 . sta0 | st1 . sta1 | st2 . sta2 | phase | num |
- * --------------------------------------------------------------
- *
- * Note that since the first 32-bit word in a (IDNP_CFG) XDC is used
- * for a sub-type, subsequent three 32-bits words are used for data that
- * pertains to respective sub-type, i.e. first sub-type corresponds
- * to first of the 3x32-bit words (pos=0), second sub-type corresponds
- * to second of the 3x32-bit words (pos=1), etc. Obviously, a max of
- * only three sub-types can be sent per xdc.
- */
-#define IDNCFG_BARLAR 0x1 /* SMR base/limit pfn */
-#define IDNCFGARG_BARLAR_BAR 0 /* BAR */
-#define IDNCFGARG_BARLAR_LAR 1 /* LAR */
-#define IDNCFG_MCADR 0x2 /* MC ADR, arg = board number */
-#define IDNCFG_NMCADR 0x3 /* Number of MC ADRs to expect */
-#define IDNCFG_CPUSET 0x4 /* dcpuset of remote domain */
-#define IDNCFGARG_CPUSET_UPPER 0 /* 1st word */
-#define IDNCFGARG_CPUSET_LOWER 1 /* 2nd word */
-#define IDNCFG_NETID 0x5 /* dnetid, arg = 0 */
-#define IDNCFG_BOARDSET 0x6 /* board set, arg = 0 */
-#define IDNCFG_SIZE 0x7 /* SMR size parameters */
-#define IDNCFGARG_SIZE_MTU 0 /* IDN_MTU */
-#define IDNCFGARG_SIZE_BUF 1 /* IDN_SMR_BUFSIZE */
-#define IDNCFGARG_SIZE_SLAB 2 /* IDN_SLAB_BUFCOUNT */
-#define IDNCFGARG_SIZE_NWR 3 /* IDN_NWR_SIZE */
-#define IDNCFG_DATAMBOX 0x8 /* SMR data mailbox info */
-#define IDNCFGARG_DATAMBOX_TABLE 0 /* recvmbox table */
-#define IDNCFGARG_DATAMBOX_DOMAIN 1 /* domain's recvmbox */
-#define IDNCFGARG_DATAMBOX_INDEX 2 /* domain's index into table */
-#define IDNCFG_DATASVR 0x9 /* Data server info */
-#define IDNCFGARG_DATASVR_MAXNETS 0 /* max # of nets/channels */
-#define IDNCFGARG_DATASVR_MBXPERNET 1 /* # mbox per net/channel */
-#define IDNCFG_OPTIONS 0xa /* various options */
-#define IDNCFGARG_CHECKSUM 0 /* IDN_CHECKSUM */
-
-#define IDN_CFGPARAM(st, sta) ((uchar_t)((((st) & 0xf) << 4) | ((sta) & 0xf)))
-#define IDN_CFGPARAM_TYPE(p) (((p) >> 4) & 0xf)
-#define IDN_CFGPARAM_ARG(p) ((p) & 0xf)
-
-typedef union {
- struct {
- uchar_t p[3];
- uchar_t _num_phase; /* info.num, info.phase used instead */
- } param;
- struct {
- uint_t _p : 24; /* param.p[] used instead */
- uint_t num : 2;
- uint_t phase : 6;
- } info;
- uint_t val;
-} idn_cfgsubtype_t;
-
-/*
- * IDN_MASTER_NCFGITEMS
- * Minimum number of config items expected from master.
- *
- * IDN_SLAVE_NCFGITEMS
- * Number of config items expected from slave.
- */
-#define IDN_MASTER_NCFGITEMS 17 /* max = +14 (mcadrs) */
-#define IDN_SLAVE_NCFGITEMS 12
-
-/*
- * IDNP_CMD sub-types.
- */
-typedef enum {
-/* 1 */ IDNCMD_SLABALLOC = 1, /* Request to allocate a slab */
-/* 2 */ IDNCMD_SLABFREE, /* Request to free a slab */
-/* 3 */ IDNCMD_SLABREAP, /* Reap any free slabs */
-/* 4 */ IDNCMD_NODENAME /* Query nodename of domain */
-} idn_cmd_t;
-
-#define VALID_IDNCMD(c) (((int)(c) >= (int)IDNCMD_SLABALLOC) && \
- ((int)(c) <= (int)IDNCMD_NODENAME))
-/*
- * IDNP_NACK
- */
-typedef enum {
-/* 1 */ IDNNACK_NOCONN = 1,
-/* 2 */ IDNNACK_BADCHAN,
-/* 3 */ IDNNACK_BADCFG,
-/* 4 */ IDNNACK_BADCMD,
-/* 5 */ IDNNACK_RETRY,
-/* 6 */ IDNNACK_DUP,
-/* 7 */ IDNNACK_EXIT,
-/* 8 */ IDNNACK_RESERVED1,
-/* 9 */ IDNNACK_RESERVED2,
-/* 10 */ IDNNACK_RESERVED3
-} idn_nack_t;
-
-/*
- * IDNP_CON sub-types.
- */
-typedef enum {
-/* 0 */ IDNCON_OFF = 0,
-/* 1 */ IDNCON_NORMAL, /* regular connect sequence */
-/* 2 */ IDNCON_QUERY /* query for connect info */
-} idn_con_t;
-
-/*
- * IDNP_FIN sub-types.
- */
-typedef enum {
-/* 0 */ IDNFIN_OFF = 0, /* active, no fin */
-/* 1 */ IDNFIN_NORMAL, /* normal disconnect req */
-/* 2 */ IDNFIN_FORCE_SOFT, /* normal dis, force if goes AWOL */
-/* 3 */ IDNFIN_FORCE_HARD, /* force disconnect of AWOL domain */
-/* 4 */ IDNFIN_QUERY /* query for fin info */
-} idn_fin_t;
-
-#define VALID_FIN(f) (((int)(f) > 0) && \
- ((int)(f) < (int)IDNFIN_QUERY))
-#define FIN_IS_FORCE(f) (((f) == IDNFIN_FORCE_SOFT) || \
- ((f) == IDNFIN_FORCE_HARD))
-
-/*
- * FIN ARG types - reasons a FIN was sent.
- */
-typedef enum {
-/* 0 */ IDNFIN_ARG_NONE = 0, /* no argument */
-/* 1 */ IDNFIN_ARG_SMRBAD, /* SMR is corrupted */
-/* 2 */ IDNFIN_ARG_CPUCFG, /* missing cpu per board */
-/* 3 */ IDNFIN_ARG_HWERR, /* error programming hardware */
-/* 4 */ IDNFIN_ARG_CFGERR_FATAL, /* Fatal error during CONFIG */
-/* 5 */ IDNFIN_ARG_CFGERR_MTU, /* MTU sizes conflict */
-/* 6 */ IDNFIN_ARG_CFGERR_BUF, /* SMR_BUF_SIZE conflicts */
-/* 7 */ IDNFIN_ARG_CFGERR_SLAB, /* SLAB sizes conflict */
-/* 8 */ IDNFIN_ARG_CFGERR_NWR, /* NWR sizes conflict */
-/* 9 */ IDNFIN_ARG_CFGERR_NETS, /* MAX_NETS conflict */
-/* 10 */ IDNFIN_ARG_CFGERR_MBOX, /* MBOX_PER_NET conflict */
-/* 11 */ IDNFIN_ARG_CFGERR_NMCADR, /* NMCADR mismatches actual */
-/* 12 */ IDNFIN_ARG_CFGERR_MCADR, /* missing some MCADRs */
-/* 13 */ IDNFIN_ARG_CFGERR_CKSUM, /* checksum settings conflict */
-/* 14 */ IDNFIN_ARG_CFGERR_SMR /* SMR sizes conflict */
-} idn_finarg_t;
-
-#define IDNFIN_ARG_IS_FATAL(fa) ((fa) > IDNFIN_ARG_NONE)
-
-#define SET_FIN_TYPE(x, t) \
- ((x) &= 0xffff, (x) |= (((uint_t)(t) & 0xffff) << 16))
-#define SET_FIN_ARG(x, a) \
- ((x) &= ~0xffff, (x) |= ((uint_t)(a) & 0xffff))
-#define GET_FIN_TYPE(x) ((idn_fin_t)(((x) >> 16) & 0xffff))
-#define GET_FIN_ARG(x) ((idn_finarg_t)((x) & 0xffff))
-
-#define FINARG2IDNKERR(fa) \
- (((fa) == IDNFIN_ARG_SMRBAD) ? IDNKERR_SMR_CORRUPTED : \
- ((fa) == IDNFIN_ARG_CPUCFG) ? IDNKERR_CPU_CONFIG : \
- ((fa) == IDNFIN_ARG_HWERR) ? IDNKERR_HW_ERROR : \
- ((fa) == IDNFIN_ARG_CFGERR_FATAL) ? IDNKERR_HW_ERROR : \
- ((fa) == IDNFIN_ARG_CFGERR_MTU) ? IDNKERR_CONFIG_MTU : \
- ((fa) == IDNFIN_ARG_CFGERR_BUF) ? IDNKERR_CONFIG_BUF : \
- ((fa) == IDNFIN_ARG_CFGERR_SLAB) ? IDNKERR_CONFIG_SLAB : \
- ((fa) == IDNFIN_ARG_CFGERR_NWR) ? IDNKERR_CONFIG_NWR : \
- ((fa) == IDNFIN_ARG_CFGERR_NETS) ? IDNKERR_CONFIG_NETS : \
- ((fa) == IDNFIN_ARG_CFGERR_MBOX) ? IDNKERR_CONFIG_MBOX : \
- ((fa) == IDNFIN_ARG_CFGERR_NMCADR) ? IDNKERR_CONFIG_NMCADR : \
- ((fa) == IDNFIN_ARG_CFGERR_MCADR) ? IDNKERR_CONFIG_MCADR : \
- ((fa) == IDNFIN_ARG_CFGERR_CKSUM) ? IDNKERR_CONFIG_CKSUM : \
- ((fa) == IDNFIN_ARG_CFGERR_SMR) ? IDNKERR_CONFIG_SMR : 0)
-
-/*
- * FIN SYNC types.
- */
-#define IDNFIN_SYNC_OFF 0 /* not set */
-#define IDNFIN_SYNC_NO 1 /* no-sync necessary */
-#define IDNFIN_SYNC_YES 2 /* do fin synchronously */
-
-typedef short idn_finsync_t;
-
-/*
- * IDNP_FIN options.
- */
-typedef enum {
-/* 0 */ IDNFIN_OPT_NONE = 0, /* none (used w/query) */
-/* 1 */ IDNFIN_OPT_UNLINK, /* normal unlink request */
-/* 2 */ IDNFIN_OPT_RELINK /* disconnect and retry link */
-} idn_finopt_t;
-
-#define VALID_FINOPT(f) (((f) == IDNFIN_OPT_UNLINK) || \
- ((f) == IDNFIN_OPT_RELINK))
-
-#define FIN_MASTER_DOMID(x) (((((x) >> 16) & 0xffff) == 0xffff) ? \
- IDN_NIL_DOMID : (((x) >> 16) & 0xffff))
-#define FIN_MASTER_CPUID(x) ((((x) & 0xffff) == 0xffff) ? \
- IDN_NIL_DCPU : ((x) & 0xfff))
-#define MAKE_FIN_MASTER(d, c) ((((uint_t)(d) & 0xffff) << 16) | \
- ((uint_t)(c) & 0xffff))
-#define NIL_FIN_MASTER MAKE_FIN_MASTER(IDN_NIL_DOMID, IDN_NIL_DCPU)
-
-#ifdef DEBUG
-#define IDN_FSTATE_TRANSITION(dp, ns) \
- { \
- int _id; \
- _id = (dp)->domid; \
- if ((dp)->dfin != (ns)) { \
- hrtime_t tstamp; \
- tstamp = TIMESTAMP(); \
- IDN_HISTORY_LOG(IDNH_FIN, _id, (ns), 0); \
- PR_STATE("FSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \
- "%s(%d) -> %s(%d)\n", \
- (uint64_t)tstamp, _id, \
- __LINE__, \
- ((dp)->dcpu == IDN_NIL_DCPU) ? -1 : \
- CPUID_TO_BOARDID((dp)->dcpu), \
- (dp)->dcpu, \
- idnfin_str[(dp)->dfin], (dp)->dfin, \
- idnfin_str[ns], (ns)); \
- (dp)->dfin = (ns); \
- } \
- }
-#else
-#define IDN_FSTATE_TRANSITION(dp, ns) \
- { \
- IDN_HISTORY_LOG(IDNH_FIN, (dp)->domid, (ns), 0); \
- (dp)->dfin = (ns); \
- }
-#endif /* DEBUG */
-
-#endif /* !_ASM */
-#endif /* _KERNEL */
-
-#ifndef _ASM
-/*
- * IDN Per-Domain States.
- */
-typedef enum {
-/* 0 */ IDNDS_CLOSED, /* idle */
-/* 1 */ IDNDS_NEGO_PEND, /* link initiating */
-/* 2 */ IDNDS_NEGO_SENT, /* link initiated, nego sent */
-/* 3 */ IDNDS_NEGO_RCVD, /* link wanted, nego+ack sent */
-/* 4 */ IDNDS_CONFIG, /* passing config info, prgm hw */
-/* 5 */ IDNDS_CON_PEND, /* connection pending */
-/* 6 */ IDNDS_CON_SENT, /* con sent */
-/* 7 */ IDNDS_CON_RCVD, /* con sent & received */
-/* 8 */ IDNDS_CON_READY, /* ready to establish link */
-/* 9 */ IDNDS_CONNECTED, /* established - linked */
-/* 10 */ IDNDS_FIN_PEND, /* unlink initiating */
-/* 11 */ IDNDS_FIN_SENT, /* unlink initiated, fin sent */
-/* 12 */ IDNDS_FIN_RCVD, /* unlink wanted by remote */
-/* 13 */ IDNDS_DMAP /* deprogramming hw */
-} idn_dstate_t;
-
-#define IDNDS_IS_CLOSED(dp) (((dp)->dstate == IDNDS_CLOSED) || \
- ((dp)->dstate == IDNDS_DMAP))
-#define IDNDS_IS_CONNECTING(dp) (((dp)->dstate > IDNDS_CLOSED) && \
- ((dp)->dstate < IDNDS_CONNECTED))
-#define IDNDS_IS_DISCONNECTING(dp) ((dp)->dstate > IDNDS_CONNECTED)
-#define IDNDS_CONFIG_DONE(dp) (((dp)->dstate == IDNDS_CLOSED) || \
- ((dp)->dstate > IDNDS_CONFIG))
-#define IDNDS_SYNC_TYPE(dp) (((dp)->dfin_sync != IDNFIN_SYNC_OFF) ? \
- (dp)->dfin_sync : \
- ((dp)->dstate < IDNDS_CON_READY) ? \
- IDNFIN_SYNC_NO : IDNFIN_SYNC_YES)
-
-#endif /* !_ASM */
-
-#ifdef _KERNEL
-#ifndef _ASM
-/*
- * ---------------------------------------------------------------------
- */
-typedef struct idn_timer {
- struct idn_timer *t_forw,
- *t_back;
- struct idn_timerq *t_q;
-
- timeout_id_t t_id;
- short t_domid;
- short t_onq;
- ushort_t t_type;
- ushort_t t_subtype;
- uint_t t_cookie;
-#ifdef DEBUG
- hrtime_t t_posttime;
- hrtime_t t_exectime;
-#endif /* DEBUG */
-} idn_timer_t;
-
-#define IDN_TIMER_PUBLIC_COOKIE 0xf
-
-#define IDN_TIMERQ_IS_LOCKED(tq) (MUTEX_HELD(&(tq)->tq_mutex))
-#define IDN_TIMERQ_LOCK(tq) (mutex_enter(&(tq)->tq_mutex))
-#define IDN_TIMERQ_UNLOCK(tq) (mutex_exit(&(tq)->tq_mutex))
-
-#define IDN_TIMERQ_INIT(tq) (idn_timerq_init(tq))
-#define IDN_TIMERQ_DEINIT(tq) (idn_timerq_deinit(tq))
-#define IDN_TIMER_ALLOC() (idn_timer_alloc())
-#define IDN_TIMER_FREE(tp) (idn_timer_free(tp))
-
-#define IDN_TIMER_START(tq, tp, tim) \
- (idn_timer_start((tq), (tp), (tim)))
-#define IDN_TIMER_STOP(tq, typ, ck) \
- ((void) idn_timer_stop((tq), (typ), (ck)))
-#define IDN_TIMER_STOPALL(tp) \
- ((void) idn_timer_stopall(tp))
-#define IDN_TIMER_GET(tq, typ, tp, ck) \
- { \
- mutex_enter(&((tq)->tq_mutex)); \
- (tp) = idn_timer_get((tq), (typ), (ck)); \
- mutex_exit(&((tq)->tq_mutex)); \
- }
-#define IDN_TIMER_DEQUEUE(tq, tp) \
- (idn_timer_dequeue((tq), (tp)))
-#ifdef DEBUG
-#define IDN_TIMER_POST(tp) \
- ((tp)->t_posttime = gethrtime(), (tp)->t_exectime = 0)
-#define IDN_TIMER_EXEC(tp) ((tp)->t_exectime = gethrtime())
-#else /* DEBUG */
-#define IDN_TIMER_POST(tp)
-#define IDN_TIMER_EXEC(tp)
-#endif /* DEBUG */
-
-#define IDN_MSGTIMER_START(domid, typ, subtyp, tim, ckp) \
- { \
- idn_timer_t *_tp; \
- char _str[15]; \
- ushort_t *_ckp = (ckp); \
- inum2str((typ), _str); \
- PR_TIMER("msgtimer:%d: START: type = %s (0x%x)\n", \
- (domid), _str, (typ)); \
- _tp = IDN_TIMER_ALLOC(); \
- _tp->t_type = (ushort_t)(typ); \
- _tp->t_subtype = (ushort_t)(subtyp); \
- _tp->t_domid = (short)(domid); \
- _tp->t_cookie = (_ckp) ? *(_ckp) : 0; \
- IDN_TIMER_POST(_tp); \
- if (_ckp) { \
- *(_ckp) = IDN_TIMER_START(&idn_domain[domid].dtimerq, \
- _tp, (tim)); \
- } else { \
- (void) IDN_TIMER_START(&idn_domain[domid].dtimerq, \
- _tp, (tim)); \
- } \
- }
-#define IDN_MSGTIMER_STOP(domid, typ, ck) \
- { \
- char _str[15]; \
- inum2str((typ), _str); \
- PR_TIMER("msgtimer:%d: STOP: type = %s (0x%x), " \
- "cookie = 0x%x\n", \
- (domid), _str, (typ), (ck)); \
- IDN_TIMER_STOP(&idn_domain[domid].dtimerq, (typ), (ck)); \
- }
-#define IDN_MSGTIMER_GET(dp, typ, tp, ck) \
- IDN_TIMER_GET(&(dp)->dtimerq, (typ), (tp), (ck))
-
-/*
- * IDN_SLABALLOC_WAITTIME
- * Max wait time in ticks that local domains waits for
- * master to respond to a slab allocation request. Has
- * to be at least as long as wait time for a response to
- * the command.
- */
-#define IDN_SLABALLOC_WAITTIME ((3 * idn_msg_waittime[IDNP_CMD]) / 2)
-
-/*
- * Domain state transition macros.
- */
-#ifdef DEBUG
-#define IDN_DSTATE_TRANSITION(dp, ns) \
- { \
- int id; \
- hrtime_t tstamp; \
- tstamp = TIMESTAMP(); \
- ASSERT(RW_WRITE_HELD(&(dp)->drwlock)); \
- id = (dp)->domid; \
- IDN_HISTORY_LOG(IDNH_DSTATE, id, (ns), \
- (uint_t)(dp)->dcpu); \
- PR_STATE("DSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \
- "%s(%d) -> %s(%d)\n", \
- (uint64_t)tstamp, id, \
- __LINE__, \
- ((dp)->dcpu == IDN_NIL_DCPU) ? \
- -1 : CPUID_TO_BOARDID((dp)->dcpu), \
- (dp)->dcpu, \
- idnds_str[(dp)->dstate], (dp)->dstate, \
- idnds_str[ns], (ns)); \
- (dp)->dstate = (ns); \
- IDNSB_DOMAIN_UPDATE(dp); \
- }
-#else
-#define IDN_DSTATE_TRANSITION(dp, ns) \
- { \
- IDN_HISTORY_LOG(IDNH_DSTATE, (dp)->domid, \
- (ns), (uint_t)(dp)->dcpu); \
- (dp)->dstate = (ns); \
- IDNSB_DOMAIN_UPDATE(dp); \
- }
-#endif /* DEBUG */
-
-#define IDN_XSTATE_TRANSITION(dp, xs) \
- { \
- int _xs = (xs); \
- (dp)->dxstate = _xs; \
- if (_xs != IDNXS_NIL) { \
- ASSERT((dp)->dxp); \
- IDN_DSTATE_TRANSITION((dp), \
- (dp)->dxp->xt_trans[_xs].t_state); \
- } \
- }
-
-/*
- * ---------------------------------------------------------------------
- * IDN Per-Domain Data
- *
- * The comment to the right of the respective field represents
- * what lock protects that field. If there is no comment then
- * no lock is required to access the field.
- * ---------------------------------------------------------------------
- */
-
-#define MAXDNAME 32
-
-typedef struct idn_domain {
- krwlock_t drwlock;
- /*
- * Assigned domid for domain. Never
- * changes once idn_domain[] is
- * initialized. We are guaranteed that
- * all domains in IDN will have a
- * uniqueue domid in the range (0-15).
- */
- int domid;
- idn_dstate_t dstate; /* drwlock */
- idn_xstate_t dxstate; /* drwlock */
- /*
- * Gotten from uname -n for local
- * domain. Remote domains pass
- * theirs during Config phase.
- */
- char dname[MAXDNAME]; /* drwlock */
- /*
- * IDN-wide unique identifier for the
- * given domain. This value will be
- * the same as the domid.
- */
- ushort_t dnetid; /* drwlock */
- idn_vote_t dvote; /* drwlock */
- /*
- * Used during FIN sequenece to
- * determine what type of shutdown
- * (unlink) we're executing with
- * respect to the given domain.
- */
- idn_fin_t dfin; /* drwlock */
- /*
- * A non-zero value for dfin_sync
- * indicates that unlink of respective
- * domain does not need to be performed
- * synchronously among all the IDN
- * member domains.
- */
- short dfin_sync; /* grwlock */
- /*
- * Cookie used to determine the
- * proper context in which we're
- * receiving messages from the given
- * domain. Assigned cookies are exchanged
- * during initial NEGO messages.
- */
- ushort_t dcookie_send; /* drwlock */
- ushort_t dcookie_recv; /* drwlock */
- short dcookie_err; /* drwlock */
- int dcookie_errcnt; /* drwlock */
- /*
- * Primary target cpu for sending
- * messages. Can change to help
- * distribute interrupts on receiving
- * side.
- */
- int dcpu; /* drwlock */
- /*
- * Used to store dcpu from a previous
- * life. Only used when requesting
- * a RELINK with a domain we were just
- * previously linked with. Thus, it
- * does represent a valid cpu in the
- * remote domain.
- */
- int dcpu_save; /* drwlock */
- /*
- * Used to store from which cpu the
- * last message was received.
- */
- int dcpu_last;
- /*
- * Transition phase area. This field
- * points to the proper phase structure
- * depending on what stage the given
- * domain is in.
- */
- idn_xphase_t *dxp; /* drwlock */
- /*
- * Actual synchronization object for
- * the given domain.
- */
- idn_syncop_t dsync; /* drwlock & idn.sync.sz_mutex */
- /*
- * Slab information for given domain.
- * If the local domain is a master,
- * then this field in each domain is used
- * to store which slabs have been assigned
- * to given domain. If the local domain
- * is a slave, then this information is
- * NULL for all remote idn_domain[]
- * entries, but for local domain holds
- * those slabs assigned to local domain.
- */
- smr_slab_t *dslab; /* dslab_rwlock */
- short dnslabs; /* dslab_rwlock */
- short dslab_state; /* dslab_rwlock */
- krwlock_t dslab_rwlock;
- /*
- * Set of cpus belonging to domain.
- */
- cpuset_t dcpuset; /* drwlock */
-
- int dncpus; /* drwlock */
- /*
- * Index into dcpumap to determine
- * which cpu to target next for
- * interrupt. Intended to allow fair
- * distribution of interrupts on
- * remote domain.
- */
- uint_t dcpuindex; /* drwlock */
- /*
- * Quick look-up map of cpus belonging
- * to domain. Used to select next target.
- */
- uchar_t *dcpumap; /* drwlock */
- /*
- * Non-zero indicates outstanding
- * I/O's to given domain.
- */
- int dio; /* drwlock */
- int dioerr; /* drwlock */
- /*
- * Set when we fail to allocate a buffer
- * for a domain. Dictates whether to
- * reclaim max buffers or not.
- */
- lock_t diowanted;
- /*
- * Set when remote domain does not
- * seem to be picking up messages sent
- * to it. Non-zero indicates we have
- * an outstanding "ping" to domain.
- */
- lock_t diocheck; /* drwlock */
- short dslabsize; /* drwlock */
- uint_t dmtu; /* drwlock */
-
- uint_t dbufsize; /* drwlock */
- short dnwrsize; /* drwlock */
- lock_t dreclaim_inprogress; /* drwlock */
- uchar_t dreclaim_index; /* drwlock */
- /*
- * The following field is primarily
- * used during CFG exchange to keep
- * track of certain per-domain information.
- */
- union { /* all - drwlock */
- struct {
- uint_t _dcfgphase : 6;
- uint_t _dcfgsnddone : 1;
- uint_t _dcfgrcvdone : 1;
- uint_t _dcksum : 2;
- uint_t _dmaxnets : 6;
- uint_t _dmboxpernet : 9;
- uint_t _dncfgitems : 6;
- uint_t _drecfg : 1;
- } _s;
- int _dtmp;
- } _u;
- /*
- * Each domain entry maintains a
- * timer queue holding timers for
- * messages outstanding to that domain.
- */
- struct idn_timerq {
- int tq_cookie; /* tq_mutex */
- kmutex_t tq_mutex;
- int tq_count; /* tq_mutex */
- idn_timer_t *tq_queue; /* tq_mutex */
- } dtimerq;
- /*
- * dawol is used to keep
- * track of AWOL details for
- * given domain when it is
- * non-responsive.
- */
- struct {
- int a_count; /* drwlock */
- clock_t a_time; /* drwlock */
- clock_t a_last; /* drwlock */
- clock_t a_msg; /* drwlock */
- } dawol;
-
- struct hwconfig {
- short dh_nboards; /* drwlock */
- short dh_nmcadr; /* drwlock */
- boardset_t dh_boardset; /* drwlock */
- uint_t dh_mcadr[MAX_BOARDS]; /* drwlock */
- } dhw;
- /*
- * Mailbox information used to
- * send/recv messages to given domain.
- */
- struct {
- kmutex_t m_mutex;
- struct idn_mboxtbl *m_tbl; /* m_mutex */
- struct idn_mainmbox *m_send; /* m_mutex */
- struct idn_mainmbox *m_recv; /* m_mutex */
- } dmbox;
-} idn_domain_t;
-
-typedef struct idn_timerq idn_timerq_t;
-
-#define dcfgphase _u._s._dcfgphase
-#define dcfgsnddone _u._s._dcfgsnddone
-#define dcfgrcvdone _u._s._dcfgrcvdone
-#define dcksum _u._s._dcksum
-#define dmaxnets _u._s._dmaxnets
-#define dmboxpernet _u._s._dmboxpernet
-#define dncfgitems _u._s._dncfgitems
-#define drecfg _u._s._drecfg
-#define dbindport _u._dbindport
-#define dconnected _u._dconnected
-#define dtmp _u._dtmp
-
-#define IDN_DLOCK_EXCL(dd) (rw_enter(&idn_domain[dd].drwlock, RW_WRITER))
-#define IDN_DLOCK_SHARED(dd) (rw_enter(&idn_domain[dd].drwlock, RW_READER))
-#define IDN_DLOCK_TRY_SHARED(dd) \
- (rw_tryenter(&idn_domain[dd].drwlock, \
- RW_READER))
-#define IDN_DLOCK_DOWNGRADE(dd) (rw_downgrade(&idn_domain[dd].drwlock))
-#define IDN_DUNLOCK(dd) (rw_exit(&idn_domain[dd].drwlock))
-#define IDN_DLOCK_IS_EXCL(dd) (RW_WRITE_HELD(&idn_domain[dd].drwlock))
-#define IDN_DLOCK_IS_SHARED(dd) (RW_READ_HELD(&idn_domain[dd].drwlock))
-#define IDN_DLOCK_IS_HELD(dd) (RW_LOCK_HELD(&idn_domain[dd].drwlock))
-
-#define IDN_MBOX_LOCK(dd) (mutex_enter(&idn_domain[dd].dmbox.m_mutex))
-#define IDN_MBOX_UNLOCK(dd) (mutex_exit(&idn_domain[dd].dmbox.m_mutex))
-
-#define IDN_RESET_COOKIES(dd) \
- (idn_domain[dd].dcookie_send = idn_domain[dd].dcookie_recv = 0)
-
-#define DSLAB_STATE_UNKNOWN 0
-#define DSLAB_STATE_LOCAL 1
-#define DSLAB_STATE_REMOTE 2
-
-#define DSLAB_READ_HELD(d) RW_READ_HELD(&idn_domain[d].dslab_rwlock)
-#define DSLAB_WRITE_HELD(d) RW_WRITE_HELD(&idn_domain[d].dslab_rwlock)
-
-#define DSLAB_LOCK_EXCL(d) \
- rw_enter(&idn_domain[d].dslab_rwlock, RW_WRITER)
-#define DSLAB_LOCK_SHARED(d) \
- rw_enter(&idn_domain[d].dslab_rwlock, RW_READER)
-#define DSLAB_LOCK_TRYUPGRADE(d) \
- rw_tryupgrade(&idn_domain[d].dslab_rwlock)
-#define DSLAB_UNLOCK(d) rw_exit(&idn_domain[d].dslab_rwlock)
-
-/*
- * ---------------------------------------------------------------------
- * Macro to pick another target for the given domain. This hopefully
- * improves performance by better distributing the SSI responsibilities
- * at the target domain.
- * ---------------------------------------------------------------------
- */
-#define BUMP_INDEX(set, index) \
- { \
- register int p; \
- for (p = (index)+1; p < NCPU; p++) \
- if (CPU_IN_SET((set), p)) \
- break; \
- if (p >= NCPU) \
- for (p = 0; p <= (index); p++) \
- if (CPU_IN_SET((set), p)) \
- break; \
- if (!CPU_IN_SET((set), p)) { \
- uint_t _u32, _l32; \
- _u32 = UPPER32_CPUMASK(set); \
- _l32 = LOWER32_CPUMASK(set); \
- cmn_err(CE_PANIC, \
- "IDN: cpu %d not in cpuset 0x%x.%0x\n", \
- p, _u32, _l32); \
- } \
- (index) = p; \
- }
-
-#define IDN_ASSIGN_DCPU(dp, cookie) \
- ((dp)->dcpu = (int)((dp)->dcpumap[(cookie) & (NCPU-1)]))
-
-/*
- * ---------------------------------------------------------------------
- * Atomic increment/decrement, swap, compare-swap functions.
- * ---------------------------------------------------------------------
- */
-#define ATOMIC_INC(v) atomic_inc_32((uint_t *)&(v))
-#define ATOMIC_DEC(v) atomic_dec_32((uint_t *)&(v))
-#define ATOMIC_SUB(v, n) atomic_add_32((uint_t *)&(v), -(n))
-#define ATOMIC_CAS(a, c, n) atomic_cas_32((uint32_t *)(a), (uint32_t)(c), \
- (uint32_t)(n))
-#define ATOMIC_SWAPL(a, v) atomic_swap_32((uint32_t *)(a), (uint32_t)(v))
-
-/*
- * DMV vector interrupt support.
- *
- * A fixed-size circular buffer is maintained as a queue of
- * incoming interrupts. The low-level idn_dmv_handler() waits
- * for an entry to become FREE and will atomically mark it INUSE.
- * Once it has filled in the appropriate fields it will be marked
- * as READY. The high-level idn_handler() will be invoked and will
- * process all messages in the queue that are READY. Each message
- * is marked PROCESS, a protojob job created and filled in, and
- * then the interrupt message is marked FREE for use in the next
- * interrupt. The iv_state field is used to hold the relevant
- * state and is updated atomically.
- */
-#define IDN_PIL PIL_8
-#define IDN_DMV_PENDING_MAX 128 /* per cpu */
-
-#endif /* !_ASM */
-
-#ifndef _ASM
-
-/*
- * The size of this structure must be a power of 2
- * so that we can do a simple shift to calculate
- * our offset into based on cpuid.
- */
-typedef struct idn_dmv_cpu {
- uint32_t idn_dmv_current;
- int32_t idn_dmv_lostintr;
- lock_t idn_dmv_active;
- char _padding[(2 * sizeof (uint64_t)) - \
- sizeof (uint32_t) - \
- sizeof (lock_t) - \
- sizeof (int32_t)];
-} idn_dmv_cpu_t;
-
-typedef struct idn_dmv_data {
- uint64_t idn_soft_inum;
- uint64_t idn_dmv_qbase;
- idn_dmv_cpu_t idn_dmv_cpu[NCPU];
-} idn_dmv_data_t;
-
-/*
- * Requirements of the following data structure:
- * - MUST be double-word (8 bytes) aligned.
- * - _iv_head field MUST start on double-word boundary.
- * - iv_xargs0 MUST start on double-word boundary
- * with iv_xargs1 immediately following.
- * - iv_xargs2 MUST start on double-word boundary
- * with iv_xargs3 immediately following.
- */
-typedef struct idn_dmv_msg {
- uint32_t iv_next; /* offset */
- uchar_t iv_inuse;
- uchar_t iv_ready;
- ushort_t _padding;
- uint32_t iv_head : 16;
- uint32_t iv_cookie : 16;
- uint32_t iv_ver : 8;
- uint32_t iv_mtype : 6;
- uint32_t iv_atype : 6;
- uint32_t iv_domid : 4;
- uint32_t iv_cpuid : 8;
- uint32_t iv_xargs0;
- uint32_t iv_xargs1;
- uint32_t iv_xargs2;
- uint32_t iv_xargs3;
-} idn_dmv_msg_t;
-
-extern uint_t idn_dmv_inum;
-extern uint_t idn_soft_inum;
-
-/*
- * An IDN-network address has the following format:
- *
- * 31......16,15........0
- * | channel | dnetid |
- * ----------------------
- * channel - network interface.
- * netid - idn_domain[].dnetid
- */
-#define IDN_MAXMAX_NETS 32
-#define IDN_BROADCAST_ALLCHAN ((ushort_t)-1)
-#define IDN_BROADCAST_ALLNETID ((ushort_t)-1)
-
-typedef union {
- struct {
- ushort_t chan;
- ushort_t netid;
- } net;
- uint_t netaddr;
-} idn_netaddr_t;
-
-#define CHANSET_ALL (~((idn_chanset_t)0))
-#define CHANSET(c) \
- ((idn_chanset_t)1 << ((c) & 31))
-#define CHAN_IN_SET(m, c) \
- (((m) & ((idn_chanset_t)1 << ((c) & 31))) != 0)
-#define CHANSET_ADD(m, c) \
- ((m) |= ((idn_chanset_t)1 << ((c) & 31)))
-#define CHANSET_DEL(m, c) \
- ((m) &= ~((idn_chanset_t)1 << ((c) & 31)))
-#define CHANSET_ZERO(m) ((m) = 0)
-
-typedef enum {
-/* 0 */ IDNCHAN_OPEN,
-/* 1 */ IDNCHAN_SOFT_CLOSE,
-/* 2 */ IDNCHAN_HARD_CLOSE,
-/* 3 */ IDNCHAN_OFFLINE,
-/* 4 */ IDNCHAN_ONLINE
-} idn_chanop_t;
-
-/*
- * Retry support.
- */
-#define IDN_RETRY_TOKEN(d, x) ((((d) & 0xf) << 16) | \
- (0xffff & (uint_t)(x)))
-#define IDN_RETRY_TOKEN2DOMID(t) ((int)(((t) >> 16) & 0xf))
-#define IDN_RETRY_TOKEN2TYPE(t) ((idn_retry_t)((t) & 0xffff))
-#define IDN_RETRY_TYPEALL ((idn_retry_t)0xffff)
-#define IDN_RETRY_INTERVAL hz /* 1 sec */
-#define IDN_RETRY_RECFG_MULTIPLE 10
-
-#define IDN_RETRYINTERVAL_NEGO (2 * hz)
-#define IDN_RETRYINTERVAL_CON (2 * hz)
-#define IDN_RETRYINTERVAL_FIN (2 * hz)
-
-typedef struct idn_retry_job {
- struct idn_retry_job *rj_prev;
- struct idn_retry_job *rj_next;
- void (*rj_func)(uint_t token, void *arg);
- void *rj_arg;
- uint_t rj_token;
- short rj_onq;
- timeout_id_t rj_id;
-} idn_retry_job_t;
-
-#define IDNRETRY_ALLOCJOB() \
- ((idn_retry_job_t *)kmem_cache_alloc(idn.retryqueue.rq_cache, KM_SLEEP))
-#define IDNRETRY_FREEJOB(j) \
- (kmem_cache_free(idn.retryqueue.rq_cache, (void *)(j)))
-
-typedef enum {
-/* 0 */ IDNRETRY_NIL = 0,
-/* 1 */ IDNRETRY_NEGO,
-/* 2 */ IDNRETRY_CON,
-/* 3 */ IDNRETRY_CONQ, /* for CON queries */
-/* 4 */ IDNRETRY_FIN,
-/* 5 */ IDNRETRY_FINQ, /* for FIN queries */
-/* 6 */ IDN_NUM_RETRYTYPES
-} idn_retry_t;
-
-/*
- * ---------------------------------------------------------------------
- */
-typedef struct {
- int m_domid;
- int m_cpuid;
- ushort_t m_msgtype;
- ushort_t m_acktype;
- ushort_t m_cookie;
- idn_xdcargs_t m_xargs;
-} idn_protomsg_t;
-
-typedef struct idn_protojob {
- struct idn_protojob *j_next;
- int j_cache;
- idn_protomsg_t j_msg;
-} idn_protojob_t;
-
-typedef struct idn_protoqueue {
- struct idn_protoqueue *q_next;
- idn_protojob_t *q_joblist;
- idn_protojob_t *q_joblist_tail;
- int q_die;
- int q_id;
- ksema_t *q_morgue;
- kthread_id_t q_threadp;
- kcondvar_t q_cv;
- kmutex_t q_mutex;
-} idn_protoqueue_t;
-
-#define IDN_PROTOCOL_NSERVERS 4
-#define IDN_PROTOCOL_SERVER_HASH(d) ((d) % idn.nservers)
-#define IDN_PROTOJOB_CHUNKS (idn.nservers)
-
-/*
- * ---------------------------------------------------------------------
- * Data Server definitions.
- *
- * idn_datasvr_t - Describes data server thread.
- * . ds_id - Per-domain identifier for data server.
- * . ds_domid - Domain which data server is handling.
- * . ds_state - Flag to enable/disable/terminate
- * data server.
- * . ds_mboxp - Pointer to data server's (local)
- * mailbox to be serviced.
- * . ds_waittime - cv_timedwait sleep time before
- * checking respective mailbox.
- * . ds_threadp - Pointer to data server thread.
- * . ds_cv - Condvar for sleeping.
- * . ds_morguep - Semaphore for terminating thread.
- *
- * idn_mboxhdr_t - Resides in SMR space (MUST be cache_linesize).
- * . mh_svr_active - Non-zero indicates data server is
- * actively reading mailbox for messages.
- * . mh_svr_ready - Non-zero indicates data server has
- * allocated and is ready to accept data.
- * . mh_cookie - Identifier primarily for debug purposes.
- *
- * idn_mboxmsg_t - Entry in the SMR space circular queue use to
- * represent a data packet.
- * . mm_owner - Non-zero indicates entry is available
- * to be processed by receiver's data server.
- * . mm_flag - Indicates whether entry needs to be
- * reclaimed by the sender. Also holds error
- * indications (e.g. bad offset).
- * . mm_offset - SMR offset of respective data packet.
- *
- * idn_mboxtbl_t - Encapsulation of a per-domain mailbox (SMR space).
- * . mt_header - Header information for synchronization.
- * . mt_queue - Circular queue of idn_mboxmsg_t entries.
- *
- * idn_mainmbox_t - Encapsulation of main SMR recv/send mailboxes.
- * . mm_mutex - Protects mm_* entries, enqueuing, and
- * dequeuing of messages. Also protects
- * updates to the route table pointed to
- * by mm_routetbl.
- * . mm_count - send: Current number of messages
- * enqueued.
- * - recv: Cumulative number of messages
- * processed.
- * . mm_max_count - send: Maximum number of messages
- * enqueued per iteration.
- * recv: Maximum number of messages
- * dequeued per iteration.
- * . mm_smr_mboxp - Pointer to SMR (vaddr) space where
- * respective mailbox resides.
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXHDR_COOKIE_TOP ((uint_t)0xc0c0)
-#define IDN_MAKE_MBOXHDR_COOKIE(pd, sd, ch) \
- ((IDN_MBOXHDR_COOKIE_TOP << 16) \
- | (((uint_t)(pd) & 0xf) << 12) \
- | (((uint_t)(sd) & 0xf) << 8) \
- | ((uint_t)(ch) & 0xf))
-#define IDN_GET_MBOXHDR_COOKIE(mhp) \
- ((mhp)->mh_cookie & ~0xff00)
-#define VALID_MBOXHDR(mhp, ch, cksum) \
- ((IDN_GET_MBOXHDR_COOKIE(mhp) == \
- IDN_MAKE_MBOXHDR_COOKIE(0, 0, (ch))) && \
- ((cksum) == (*(mhp)).mh_cksum))
-/*
- * The number of entries in a mailbox queue must be chosen so
- * that (IDN_MMBOX_NUMENTRIES * sizeof (idn_mboxmsg_t)) is a multiple
- * of a cacheline size (64).
- */
-#define IDN_MMBOX_NUMENTRIES IDN_MBOX_PER_NET
-/*
- * We step through the mailboxes in effectively cacheline size
- * incremenents so that the source and receiving cpus are not competing
- * for the same cacheline when transmitting/receiving messages into/from
- * the mailboxes. The hard requirement is that the step value be even
- * since the mailbox size will be chosen odd. This allows us to wraparound
- * the mailbox uniquely touching each entry until we've exhausted them
- * all at which point we'll end up where we initially started and repeat
- * again.
- */
-#define IDN_MMBOXINDEX_STEP (((64 / sizeof (idn_mboxmsg_t)) + 1) & 0xfffe)
-#define IDN_MMBOXINDEX_INC(i) \
- { \
- if (((i) += IDN_MMBOXINDEX_STEP) >= IDN_MMBOX_NUMENTRIES) \
- (i) -= IDN_MMBOX_NUMENTRIES; \
- }
-
-#define IDN_MMBOXINDEX_DIFF(i, j) \
- (((i) >= (j)) ? (((i) - (j)) / IDN_MMBOXINDEX_STEP) \
- : ((((i) + IDN_MMBOX_NUMENTRIES) - (j)) / IDN_MMBOXINDEX_STEP))
-
-/*
- * Require IDN_MBOXAREA_SIZE <= IDN_SLAB_SIZE so we don't waste
- * slab space.
- *
- * Each domain maintains a MAX_DOMAIN(16) entry mbox_table. Each
- * entry represents a receive mailbox for a possible domain to which
- * the given domain may have a connection. The send mailbox for each
- * respective domain is given to the local domain at the time of
- * connection establishment.
- */
-
-/*
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXTBL_SIZE \
- (IDNROUNDUP(((IDN_MBOX_PER_NET * sizeof (idn_mboxmsg_t)) \
- + sizeof (idn_mboxhdr_t)), IDN_ALIGNSIZE))
-
-/*
- * ---------------------------------------------------------------------
- * Each domain has idn_max_nets worth of possible mailbox tables
- * for each domain to which it might possibly be connected.
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXAREA_SIZE \
- (IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS * MAX_DOMAINS)
-#define IDN_MBOXAREA_OFFSET(d) \
- ((d) * IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS)
-
-/*
- * ---------------------------------------------------------------------
- * Return the base of the mailbox area (set of tables) assigned
- * to the given domain id.
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXAREA_BASE(m, d) \
- ((idn_mboxtbl_t *)(((ulong_t)(m)) + IDN_MBOXAREA_OFFSET(d)))
-
-/*
- * ---------------------------------------------------------------------
- * Return the pointer to the respective receive mailbox (table set)
- * for the given domain id relative to the given base mailbox table.
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXTBL_PTR(t, d) \
- ((idn_mboxtbl_t *)(((ulong_t)(t)) + ((d) * IDN_MBOXTBL_SIZE \
- * IDN_MAX_NETS)))
-/*
- * ---------------------------------------------------------------------
- * Return the pointer to the actual target mailbox based on the
- * given channel in the given mailbox table.
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXTBL_PTR_CHAN(t, c) \
- ((idn_mboxtbl_t *)(((ulong_t)(t)) + ((c) * IDN_MBOXTBL_SIZE)))
-
-#define IDN_MBOXTBL_PTR_INC(t) \
- ((t) = (idn_mboxtbl_t *)(((ulong_t)(t)) + IDN_MBOXTBL_SIZE))
-
-#define IDN_MBOXCHAN_INC(i) \
- { \
- if (++(i) == IDN_MAX_NETS) \
- (i) = 0; \
- }
-
-/*
- * ---------------------------------------------------------------------
- * Return the absolute location within the entire mailbox area
- * of the mboxtbl for the given primary and secondary domain and
- * channel. Only relevant when done by the master.
- * ---------------------------------------------------------------------
- */
-#define IDN_MBOXTBL_ABS_PTR(mt, pd, sd, ch) \
- (IDN_MBOXTBL_PTR_CHAN( \
- IDN_MBOXTBL_PTR( \
- IDN_MBOXAREA_BASE((mt), (pd)), \
- (sd)), \
- (ch)))
-
-#define IDN_BFRAME_SHIFT idn.bframe_shift
-#define IDN_BFRAME2OFFSET(bf) ((bf) << IDN_BFRAME_SHIFT)
-#define IDN_BFRAME2ADDR(bf) IDN_OFFSET2ADDR(IDN_BFRAME2OFFSET(bf))
-#define IDN_OFFSET2BFRAME(off) (((off) >> IDN_BFRAME_SHIFT) & 0xffffff)
-#define IDN_ADDR2BFRAME(addr) IDN_OFFSET2BFRAME(IDN_ADDR2OFFSET(addr))
-
-typedef struct idn_mboxmsg {
- uint_t ms_owner : 1,
- ms_flag : 7,
- ms_bframe : 24;
-} idn_mboxmsg_t;
-
-typedef idn_mboxmsg_t idn_mboxq_t[1];
-
-#define IDN_CKSUM_MBOX_COUNT (offsetof(idn_mboxhdr_t, mh_svr_ready) / 2)
-
-#define IDN_CKSUM_MBOX(h) \
- (IDN_CHECKSUM ? \
- idn_cksum((ushort_t *)(h), IDN_CKSUM_MBOX_COUNT) : 0)
-
-typedef struct idn_mboxhdr {
- uint_t mh_cookie;
- uint_t mh_svr_ready_ptr;
- uint_t mh_svr_active_ptr;
- ushort_t mh_svr_ready;
- ushort_t mh_svr_active;
-
- uint_t _padding[(64 -
- (4*sizeof (uint_t)) -
- (2*sizeof (ushort_t))) / sizeof (uint_t)];
-
- uint_t mh_cksum;
-} idn_mboxhdr_t;
-
-typedef struct idn_mboxtbl {
- idn_mboxhdr_t mt_header;
- idn_mboxq_t mt_queue;
-} idn_mboxtbl_t;
-
-#define IDN_CHAN_DOMAIN_REGISTER(csp, dom) \
- (DOMAINSET_ADD((csp)->ch_reg_domset, (dom)))
-
-#define IDN_CHAN_DOMAIN_UNREGISTER(csp, dom) \
- (DOMAINSET_DEL((csp)->ch_reg_domset, (dom)))
-
-#define IDN_CHAN_DOMAIN_IS_REGISTERED(csp, dom) \
- (DOMAIN_IN_SET((csp)->ch_reg_domset, (dom)))
-
-#define IDN_CHANSVR_SCANSET_ADD_PENDING(csp, dom) \
- { \
- register int _d; \
- register uint64_t _domset; \
- (dom) &= MAX_DOMAINS - 1; /* Assumes power of 2 */ \
- _domset = 0ull; \
- for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \
- if ((int)(((csp)->ch_recv_scanset_pending >> \
- (_d * 4)) & 0xf) == (dom)) \
- break; \
- else \
- _domset = (_domset << 4) | 0xfull; \
- } \
- if (_d == (csp)->ch_recv_domcount) { \
- _domset &= (csp)->ch_recv_scanset_pending; \
- _domset |= (uint64_t)(dom) << \
- ((csp)->ch_recv_domcount * 4); \
- (csp)->ch_recv_domcount++; \
- (csp)->ch_recv_scanset_pending = 0ull; \
- for (_d = 0; _d < 16; \
- _d += (csp)->ch_recv_domcount) { \
- (csp)->ch_recv_scanset_pending |= _domset; \
- _domset <<= (csp)->ch_recv_domcount * 4; \
- } \
- } \
- }
-#define IDN_CHANSVR_SCANSET_DEL_PENDING(csp, dom) \
- { \
- register int _d; \
- register uint64_t _domset; \
- (dom) &= MAX_DOMAINS - 1; /* Assumes power of 2 */ \
- _domset = 0ull; \
- for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \
- if ((int)(((csp)->ch_recv_scanset_pending >> \
- (_d * 4)) & 0xf) == (dom)) \
- break; \
- else \
- _domset = (_domset << 4) | 0xfull; \
- } \
- if (_d < (csp)->ch_recv_domcount) { \
- _domset &= (csp)->ch_recv_scanset_pending; \
- (csp)->ch_recv_scanset_pending >>= 4; \
- (csp)->ch_recv_domcount--; \
- for (; _d < (csp)->ch_recv_domcount; _d++) \
- _domset |= (csp)->ch_recv_scanset_pending &\
- (0xfull << (_d * 4)); \
- (csp)->ch_recv_scanset_pending = 0ull; \
- if ((csp)->ch_recv_domcount) { \
- for (_d = 0; _d < 16; \
- _d += (csp)->ch_recv_domcount) { \
- (csp)->ch_recv_scanset_pending |= \
- _domset; \
- _domset <<= \
- (csp)->ch_recv_domcount * 4; \
- } \
- } \
- } \
- }
-
-#define IDN_CHAN_TRYLOCK_GLOBAL(csp) \
- mutex_tryenter(&(csp)->ch_mutex)
-#define IDN_CHAN_LOCK_GLOBAL(csp) \
- mutex_enter(&(csp)->ch_mutex)
-#define IDN_CHAN_UNLOCK_GLOBAL(csp) \
- mutex_exit(&(csp)->ch_mutex)
-#define IDN_CHAN_GLOBAL_IS_LOCKED(csp) \
- (MUTEX_HELD(&(csp)->ch_mutex))
-
-#define IDN_CHAN_LOCAL_IS_LOCKED(csp) \
- (MUTEX_HELD(&(csp)->ch_send.c_mutex) && \
- MUTEX_HELD(&(csp)->ch_recv.c_mutex))
-#define IDN_CHAN_LOCK_LOCAL(csp) \
- (mutex_enter(&(csp)->ch_recv.c_mutex, \
- mutex_enter(&(csp)->ch_send.c_mutex))
-#define IDN_CHAN_UNLOCK_LOCAL(csp) \
- (mutex_exit(&(csp)->ch_send.c_mutex), \
- mutex_exit(&(csp)->ch_recv.c_mutex))
-
-#define IDN_CHAN_RECV_IS_LOCKED(csp) \
- (MUTEX_HELD(&(csp)->ch_recv.c_mutex))
-#define IDN_CHAN_TRYLOCK_RECV(csp) \
- (mutex_tryenter(&(csp)->ch_recv.c_mutex))
-#define IDN_CHAN_LOCK_RECV(csp) \
- (mutex_enter(&(csp)->ch_recv.c_mutex))
-#define IDN_CHAN_UNLOCK_RECV(csp) \
- (mutex_exit(&(csp)->ch_recv.c_mutex))
-
-#define IDN_CHAN_SEND_IS_LOCKED(csp) \
- (MUTEX_HELD(&(csp)->ch_send.c_mutex))
-#define IDN_CHAN_TRYLOCK_SEND(csp) \
- (mutex_tryenter(&(csp)->ch_send.c_mutex))
-#define IDN_CHAN_LOCK_SEND(csp) \
- (mutex_enter(&(csp)->ch_send.c_mutex))
-#define IDN_CHAN_UNLOCK_SEND(csp) \
- (mutex_exit(&(csp)->ch_send.c_mutex))
-
-/*
- * A channel table is an array of pointers to mailboxes
- * for the respective domains for the given channel.
- * Used a cache for the frequently used items. Respective
- * fields in mainmbox are updated just prior to sleeping.
- */
-
-/*
- * Reading c_state requires either c_mutex or ch_mutex.
- * Writing c_state requires both c_mutex and ch_mutex in the order:
- * ch_mutex
- * c_mutex
- */
-typedef struct idn_chaninfo {
- kmutex_t c_mutex;
- uchar_t c_state; /* protected by c_mutex */
- uchar_t c_checkin; /* asynchronous flag */
- kcondvar_t c_cv;
- ushort_t c_waiters; /* protected by c_mutex */
- ushort_t c_inprogress; /* protected by c_mutex */
-} idn_chaninfo_t;
-
-/*
- * Reading/Writing ch_state requires ch_mutex.
- * When updating both recv and send c_state's for the locks
- * must be grabbed in the following order:
- * ch_mutex
- * ch_recv.c_mutex
- * ch_send.c_mutex
- * This order is necessary to prevent deadlocks.
- * In general ch_state is intended to represent c_state of
- * individual send/recv sides. During state transitions the
- * ch_state and c_state values may be slightly different,
- * but eventually should end up identical.
- */
-typedef struct idn_chansvr {
- uchar_t ch_id;
- uchar_t ch_state; /* protected by ch_mutex */
- lock_t ch_initlck;
- lock_t ch_actvlck;
- domainset_t ch_reg_domset;
- kmutex_t ch_mutex;
-
- idn_chaninfo_t ch_send;
- int _padding2[(64 -
- (2*sizeof (uchar_t)) - (2*sizeof (lock_t)) -
- sizeof (uint_t) - sizeof (kmutex_t) -
- sizeof (idn_chaninfo_t)) / sizeof (int)];
-
- idn_chaninfo_t ch_recv;
-
- uint64_t ch_recv_scanset;
- uint64_t ch_recv_scanset_pending;
-
- domainset_t ch_recv_domset;
- domainset_t ch_recv_domset_pending;
- short ch_recv_domcount;
- kcondvar_t ch_recv_cv;
- int ch_recv_waittime;
- int ch_recv_changed;
-
- kthread_id_t ch_recv_threadp;
- ksema_t *ch_recv_morguep;
- int ch_bound_cpuid;
- int ch_bound_cpuid_pending;
-} idn_chansvr_t;
-
-typedef struct idn_mainmbox {
- kmutex_t mm_mutex;
- short mm_channel;
- short mm_domid;
- ushort_t mm_flags;
- short mm_type;
-
- idn_chansvr_t *mm_csp; /* non-NULL indicates reg'd */
- int mm_count;
- int mm_dropped;
- idn_mboxtbl_t *mm_smr_mboxp; /* SMR vaddr */
-
- ushort_t *mm_smr_activep; /* SMR pointer */
- ushort_t *mm_smr_readyp; /* SMR pointer */
- int mm_qiget; /* next msg to get */
- int mm_qiput; /* next slot to put msg */
-} idn_mainmbox_t;
-
-/*
- * mm_flags
- */
-#define IDNMMBOX_FLAG_CORRUPTED 0x01
-/*
- * mm_type
- */
-#define IDNMMBOX_TYPE_RECV 0x1
-#define IDNMMBOX_TYPE_SEND 0x2
-
-#define IDNMBOX_IS_RECV(m) ((m) == IDNMMBOX_TYPE_RECV)
-#define IDNMBOX_IS_SEND(m) ((m) == IDNMMBOX_TYPE_SEND)
-
-/*
- * Period between sending wakeup xdc's to remote domain.
- */
-#define IDN_CHANNEL_WAKEUP_PERIOD (hz >> 1)
-/*
- * ms_flag bit values.
- */
-#define IDN_MBOXMSG_FLAG_RECLAIM 0x1 /* needs to be reclaimed */
-#define IDN_MBOXMSG_FLAG_INPROCESS 0x2
-#define IDN_MBOXMSG_FLAG_ERR_BADOFFSET 0x4
-#define IDN_MBOXMSG_FLAG_ERR_NOMBOX 0x8
-#define IDN_MBOXMSG_FLAG_ERRMASK 0xc
-/*
- * ch_state/c_state bit values.
- */
-#define IDN_CHANSVC_STATE_ATTACHED 0x01
-#define IDN_CHANSVC_STATE_ENABLED 0x02
-#define IDN_CHANSVC_STATE_ACTIVE 0x04
-#define IDN_CHANSVC_STATE_FLUSH 0x10
-#define IDN_CHANSVC_STATE_CORRUPTED 0x20
-#define IDN_CHANSVC_STATE_MASK 0x07 /* ATTACHED/ENABLED/ACTIVE */
-
-#define IDN_CHANSVC_PENDING_BITS (IDN_CHANSVC_STATE_ATTACHED | \
- IDN_CHANSVC_STATE_ENABLED)
-
-/*
- * GLOBAL
- */
-#define IDN_CHANNEL_IS_ATTACHED(csp) \
- ((csp)->ch_state & IDN_CHANSVC_STATE_ATTACHED)
-#define IDN_CHANNEL_IS_DETACHED(csp) \
- (!IDN_CHANNEL_IS_ATTACHED(csp))
-#define IDN_CHANNEL_IS_PENDING(csp) \
- (((csp)->ch_state & IDN_CHANSVC_STATE_MASK) == \
- IDN_CHANSVC_PENDING_BITS)
-#define IDN_CHANNEL_IS_ACTIVE(csp) \
- ((csp)->ch_state & IDN_CHANSVC_STATE_ACTIVE)
-#define IDN_CHANNEL_IS_ENABLED(csp) \
- ((csp)->ch_state & IDN_CHANSVC_STATE_ENABLED)
-/*
- * SEND
- */
-#define IDN_CHANNEL_IS_SEND_ACTIVE(csp) \
- ((csp)->ch_send.c_state & IDN_CHANSVC_STATE_ACTIVE)
-/*
- * RECV
- */
-#define IDN_CHANNEL_IS_RECV_ACTIVE(csp) \
- ((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_ACTIVE)
-#define IDN_CHANNEL_IS_RECV_CORRUPTED(csp) \
- ((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_CORRUPTED)
-
-
-#define IDN_CHAN_SEND_INPROGRESS(csp) ((csp)->ch_send.c_inprogress++)
-#define IDN_CHAN_SEND_DONE(csp) \
- { \
- ASSERT((csp)->ch_send.c_inprogress > 0); \
- if ((--((csp)->ch_send.c_inprogress) == 0) && \
- ((csp)->ch_send.c_waiters != 0)) \
- cv_broadcast(&(csp)->ch_send.c_cv); \
- }
-#define IDN_CHAN_RECV_INPROGRESS(csp) ((csp)->ch_recv.c_inprogress++)
-#define IDN_CHAN_RECV_DONE(csp) \
- { \
- ASSERT((csp)->ch_recv.c_inprogress > 0); \
- if ((--((csp)->ch_recv.c_inprogress) == 0) && \
- ((csp)->ch_recv.c_waiters != 0)) \
- cv_broadcast(&(csp)->ch_recv.c_cv); \
- }
-
-#define IDN_CHANSVC_MARK_ATTACHED(csp) \
- ((csp)->ch_state = IDN_CHANSVC_STATE_ATTACHED)
-#define IDN_CHANSVC_MARK_DETACHED(csp) \
- ((csp)->ch_state = 0)
-#define IDN_CHANSVC_MARK_PENDING(csp) \
- ((csp)->ch_state |= IDN_CHANSVC_STATE_ENABLED)
-#define IDN_CHANSVC_MARK_DISABLED(csp) \
- ((csp)->ch_state &= ~IDN_CHANSVC_STATE_ENABLED)
-#define IDN_CHANSVC_MARK_ACTIVE(csp) \
- ((csp)->ch_state |= IDN_CHANSVC_STATE_ACTIVE)
-#define IDN_CHANSVC_MARK_IDLE(csp) \
- ((csp)->ch_state &= ~IDN_CHANSVC_STATE_ACTIVE)
-
-#define IDN_CHANSVC_MARK_RECV_ACTIVE(csp) \
- ((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_ACTIVE)
-#define IDN_CHANSVC_MARK_RECV_CORRUPTED(csp) \
- ((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_CORRUPTED)
-#define IDN_CHANSVC_MARK_SEND_ACTIVE(csp) \
- ((csp)->ch_send.c_state |= IDN_CHANSVC_STATE_ACTIVE)
-
-typedef enum {
- IDNCHAN_ACTION_DETACH, /* DETACH (ATTACHED = 0) */
- IDNCHAN_ACTION_STOP, /* DISABLE (ENABLED = 0) */
- IDNCHAN_ACTION_SUSPEND, /* IDLE (ACTIVE = 0) */
- IDNCHAN_ACTION_RESUME,
- IDNCHAN_ACTION_RESTART,
- IDNCHAN_ACTION_ATTACH
-} idn_chanaction_t;
-
-#define IDN_CHANNEL_SUSPEND(c, w) \
- (idn_chan_action((c), IDNCHAN_ACTION_SUSPEND, (w)))
-#define IDN_CHANNEL_RESUME(c) \
- (idn_chan_action((c), IDNCHAN_ACTION_RESUME, 0))
-#define IDN_CHANNEL_STOP(c, w) \
- (idn_chan_action((c), IDNCHAN_ACTION_STOP, (w)))
-#define IDN_CHANNEL_RESTART(c) \
- (idn_chan_action((c), IDNCHAN_ACTION_RESTART, 0))
-#define IDN_CHANNEL_DETACH(c, w) \
- (idn_chan_action((c), IDNCHAN_ACTION_DETACH, (w)))
-#define IDN_CHANNEL_ATTACH(c) \
- (idn_chan_action((c), IDNCHAN_ACTION_ATTACH, 0))
-
-/*
- * ds_waittime range values.
- * When a packet arrives the waittime starts at MIN and gradually
- * shifts up to MAX until another packet arrives. If still no
- * packet arrives then we go to a hard sleep
- */
-#define IDN_NETSVR_SPIN_COUNT idn_netsvr_spin_count
-#define IDN_NETSVR_WAIT_MIN idn_netsvr_wait_min
-#define IDN_NETSVR_WAIT_MAX idn_netsvr_wait_max
-#define IDN_NETSVR_WAIT_SHIFT idn_netsvr_wait_shift
-
-/*
- * ---------------------------------------------------------------------
- * IDN Global Data
- *
- * The comment to the right of the respective field represents
- * what lock protects that field. If there is no comment then
- * no lock is required to access the field.
- * ---------------------------------------------------------------------
- */
-typedef struct idn_global { /* protected by... */
- krwlock_t grwlock;
- /*
- * Global state of IDN w.r.t.
- * the local domain.
- */
- idn_gstate_t state; /* grwlock */
- /*
- * Version of the IDN driver.
- * Is passed in DMV header so that
- * other domains can validate they
- * support protocol used by local
- * domain.
- */
- int version;
- /*
- * Set to 1 if SMR region properly
- * allocated and available.
- */
- int enabled;
- /*
- * Local domains "domain id".
- */
- int localid;
- /*
- * Domain id of the Master domain.
- * Set to IDN_NIL_DOMID if none
- * currently exists.
- */
- int masterid; /* grwlock */
- /*
- * Primarily used during Reconfiguration
- * to track the expected new Master.
- * Once the current IDN is dismantled
- * the local domain will attempt to
- * connect to this new domain.
- */
- int new_masterid; /* grwlock */
- /*
- * Number of protocol servers configured.
- */
- int nservers;
-
- dev_info_t *dip;
-
- struct {
- /*
- * dmv_inum
- * Interrupt number assigned by
- * DMV subsystem to IDN's DMV
- * handler.
- * soft_inum
- * Soft interrupt number assigned
- * by OS (add_softintr) for Soft
- * interrupt dispatched by DMV
- * handler.
- */
- uint_t dmv_inum;
- uint64_t soft_inum;
- caddr_t dmv_data;
- size_t dmv_data_len;
- } intr;
- /*
- * first_swlink
- * Used as synchronization to
- * know whether channels need
- * to be activated or not.
- * first_hwlink
- * Used as mechanism to determine
- * whether local domain needs
- * to publicize its SMR, assuming
- * it is the Master.
- * first_hwmaster
- * Domainid of the domain that
- * was the master at the time
- * the hardware was programmed.
- * We need to keep this so that
- * we deprogram with respect to
- * the correct domain that the
- * hardware was originally
- * programmed to.
- */
- lock_t first_swlink;
- lock_t first_hwlink;
- short first_hwmasterid;
- /*
- * The xmit* fields are used to set-up a background
- * thread to monitor when a channel is ready to be
- * enabled again. This is necessary since IDN
- * can't rely on hardware to interrupt it when
- * things are ready to go. We need this ability
- * to wakeup our STREAMS queues.
- * Criteria for reenabling queues.
- * gstate == IDNGS_ONLINE
- * channel = !check-in
- * buffers are available
- *
- * xmit_chanset_wanted
- * Indicates which channels wish to have
- * their queues reenabled when ready.
- * xmit_tid
- * Timeout-id of monitor.
- */
- kmutex_t xmit_lock;
- idn_chanset_t xmit_chanset_wanted; /* xmit_lock */
- timeout_id_t xmit_tid; /* xmit_lock */
-
- struct {
- /*
- * ready
- * Indicates SMR region allocated
- * and available from OBP.
- * vaddr
- * Virtual address assigned to SMR.
- * locpfn
- * Page Frame Number associated
- * with local domain's SMR.
- * rempfn
- * Page Frame Number associated
- * with remote (Master) domain's SMR.
- * rempfnlim
- * PFN past end of remote domain's
- * SMR.
- * prom_paddr/prom_size
- * Physical address and size of
- * SMR that were assigned by OBP.
- */
- int ready;
- caddr_t vaddr;
- pfn_t locpfn;
- pfn_t rempfn; /* grwlock */
-
- pfn_t rempfnlim; /* grwlock */
- uint64_t prom_paddr;
-
- uint64_t prom_size;
- } smr;
-
- /*
- * idnsb_mutex
- * Protects access to IDN's
- * sigblock area.
- * idnsb_eventp
- * IDN's private area in sigblock
- * used for signaling events
- * regarding IDN state to SSP.
- * idnsb
- * Area within IDN's private
- * sigblock area used for tracking
- * certain IDN state which might
- * be useful during arbstop
- * conditions (if caused by IDN!).
- */
- kmutex_t idnsb_mutex;
- idnsb_event_t *idnsb_eventp;
- idnsb_t *idnsb;
-
- struct sigbintr {
- /*
- * sb_mutex
- * Protects sigbintr elements
- * to synchronize execution of
- * sigblock (IDN) mailbox handling.
- * sb_cpuid
- * Cpu whose sigblock mailbox
- * originally received IDN request
- * from SSP. Necessary to know
- * where to put response.
- * sb_busy
- * Flag indicating state of
- * sigblock handler thread.
- * Synchronize activity between
- * SSP and current IDN requests that
- * are in progress.
- * sb_cv
- * Condition variable for sigblock
- * handler thread to wait on.
- * sb_inum
- * Soft interrupt number assigned
- * by OS to handle soft interrupt
- * request make by low-level (IDN)
- * sigblock handler to dispatch actual
- * processing of sigblock (mailbox)
- * request.
- */
- kmutex_t sb_mutex;
- uchar_t sb_cpuid; /* sigbintr.sb_mutex */
- uchar_t sb_busy; /* sigbintr.sb_mutex */
- kcondvar_t sb_cv; /* sigbintr.sb_mutex */
- uint64_t sb_inum; /* sigbintr.sb_mutex */
- } sigbintr;
-
- /*
- * struprwlock, strup, sip, siplock
- * Standard network streams
- * handling structures to manage
- * instances of IDN driver.
- */
- krwlock_t struprwlock;
- struct idnstr *strup; /* struprwlock */
-
- struct idn *sip; /* siplock */
- kmutex_t sipwenlock;
- kmutex_t siplock;
-
- /*
- * Area where IDN maintains its kstats.
- */
- kstat_t *ksp;
- /*
- * Number of domains that local domain
- * has "open".
- */
- int ndomains; /* grwlock */
- /*
- * Number of domains that local domain
- * has registered as non-responsive.
- */
- int nawols; /* grwlock */
- /*
- * Number of network channels (interfaces)
- * which are currently active.
- */
- int nchannels; /* grwlock */
- /*
- * Bitmask representing channels
- * that are currently active.
- */
- idn_chanset_t chanset; /* grwlock */
- /*
- * Array of channel (network/data) servers
- * that have been created. Not necessarily
- * all active.
- */
- idn_chansvr_t *chan_servers; /* elmts = ch_mutex */
- /*
- * Pointer to sigblock handler thread
- * which ultimately processes SSP
- * IDN requests.
- */
- kthread_id_t sigb_threadp;
- /*
- * Pointer to area used by Master
- * to hold mailbox structures.
- * Actual memory is in SMR.
- */
- idn_mboxtbl_t *mboxarea; /* grwlock */
-
- struct {
- /*
- * IDN_SYNC_LOCK - Provides serialization
- * mechanism when performing synchronous
- * operations across domains.
- */
- kmutex_t sz_mutex;
- /*
- * Actual synchronization zones for
- * CONNECT/DISCONNECT phases.
- */
- idn_synczone_t sz_zone[IDN_SYNC_NUMZONE];
- } sync; /* sz_mutex */
-
- struct {
- /*
- * ds_trans_on
- * Set of domains which are trying
- * to establish a link w/local.
- * ds_ready_on
- * Set of domains which local knows
- * are ready for linking, but has
- * not yet confirmed w/peers.
- * ds_connected
- * Set of domains that local has
- * confirmed as being ready.
- * ds_trans_off
- * Set of domains which are trying
- * to unlink from local.
- * ds_ready_off
- * Set of domains which local knows
- * are ready for unlink, but has
- * not yet confirmed w/peers.
- * ds_relink
- * Set of domains we're expecting
- * to relink with subsequent to
- * a RECONFIG (new master selection).
- * ds_hwlinked
- * Set of domains for which local
- * has programmed its hardware.
- * ds_flush
- * Set of domains requiring that
- * local flush its ecache prior
- * to unlinking.
- * ds_awol
- * Set of domains believed to be
- * AWOL - haven't responded to
- * any queries.
- * ds_hitlist
- * Set of domains which local domain
- * is unlinking from and wishes to ignore
- * any extraneous indirect link requests
- * from other domains, e.g. during a
- * Reconfig.
- */
- domainset_t ds_trans_on; /* sz_mutex */
- domainset_t ds_ready_on; /* sz_mutex */
-
- domainset_t ds_connected; /* sz_mutex */
- domainset_t ds_trans_off; /* sz_mutex */
-
- domainset_t ds_ready_off; /* sz_mutex */
- domainset_t ds_relink; /* sz_mutex */
-
- domainset_t ds_hwlinked; /* sz_mutex */
- domainset_t ds_flush; /* sz_mutex */
-
- domainset_t ds_awol; /* sz_mutex */
- domainset_t ds_hitlist; /* sz_mutex */
- } domset;
- /*
- * Bitmask identifying all cpus in
- * the local IDN.
- */
- cpuset_t dc_cpuset;
- /*
- * Bitmask identifying all boards in
- * the local IDN.
- */
- boardset_t dc_boardset;
-
- struct dopers {
- /*
- * Waiting area for IDN requests,
- * i.e. link & unlinks. IDN requests
- * are performed asynchronously so
- * we need a place to wait until the
- * operation has completed.
- *
- * dop_domset
- * Identifies which domains the
- * current waiter is interested in.
- * dop_waitcount
- * Number of waiters in the room.
- * dop_waitlist
- * Actual waiting area.
- * dop_freelist
- * Freelist (small cache) of
- * structs for waiting area.
- */
- kmutex_t dop_mutex;
- kcondvar_t dop_cv; /* dop_mutex */
- domainset_t dop_domset; /* dop_mutex */
- int dop_waitcount; /* dop_mutex */
- dop_waitlist_t *dop_waitlist; /* dop_mutex */
- dop_waitlist_t *dop_freelist; /* dop_mutex */
- /* dop_mutex */
- dop_waitlist_t _dop_wcache[IDNOP_CACHE_SIZE];
- } *dopers;
-
- struct {
- /*
- * Protocol Server:
- *
- * p_server
- * Linked list of queues
- * describing protocol
- * servers in use.
- * p_jobpool
- * Kmem cache of structs
- * used to enqueue protocol
- * jobs for protocol servers.
- * p_morgue
- * Synchronization (check-in)
- * area used when terminating
- * protocol servers (threads).
- */
- struct idn_protoqueue *p_serverq;
- kmem_cache_t *p_jobpool;
- ksema_t p_morgue;
- } protocol;
-
- struct idn_retry_queue {
- /*
- * rq_jobs
- * Queue of Retry jobs
- * that are outstanding.
- * rq_count
- * Number of jobs on retry
- * queue.
- * rq_cache
- * Kmem cache for structs
- * used to describe retry
- * jobs.
- */
- idn_retry_job_t *rq_jobs; /* rq_mutex */
- int rq_count; /* rq_mutex */
- kmutex_t rq_mutex; /* rq_mutex */
-
- kcondvar_t rq_cv; /* rq_mutex */
- kmem_cache_t *rq_cache;
- } retryqueue;
-
- struct slabpool {
- /*
- * Slabpool:
- *
- * ntotslabs
- * Total number of slabs
- * in SMR (free & in-use).
- * npools
- * Number of pools available
- * in list. One smr_slabtbl
- * exists for each pool.
- */
- int ntotslabs;
- int npools;
- struct smr_slabtbl {
- /*
- * sarray
- * Array of slab structs
- * representing slabs in SMR.
- * nfree
- * Number of slabs actually
- * available in sarray.
- * nslabs
- * Number of slabs represented
- * in sarray (free & in-use).
- */
- smr_slab_t *sarray;
- int nfree;
- int nslabs;
- } *pool;
- /*
- * Holds array of smr_slab_t structs kmem_alloc'd
- * for slabpool.
- */
- smr_slab_t *savep;
- } *slabpool;
-
- struct slabwaiter {
- /*
- * Waiting area for threads
- * requesting slab allocations.
- * Used by Slaves for all requests,
- * but used by Master only for
- * redundant requests, i.e. multiple
- * requests on behalf of the same
- * domain. One slabwaiter area
- * exist for each possible domain.
- *
- * w_nwaiters
- * Number of threads waiting
- * in waiting area.
- * w_done
- * Flag to indicate that
- * allocation request has
- * completed.
- * w_serrno
- * Non-zero indicates an
- * errno value to represent
- * error that occurred during
- * attempt to allocate slab.
- * w_closed
- * Indicates that waiting area is
- * closed and won't allow any new
- * waiters. This occurs during
- * the small window where we're
- * trying to suspend a channel.
- * w_cv
- * Condvar for waiting on.
- * w_sp
- * Holds slab structure of
- * successfully allocated slab.
- */
- kmutex_t w_mutex;
- short w_nwaiters; /* w_mutex */
- short w_done; /* w_mutex */
- short w_serrno; /* w_mutex */
- short w_closed; /* w_mutex */
- kcondvar_t w_cv; /* w_mutex */
- smr_slab_t *w_sp; /* w_mutex */
- } *slabwaiter;
- /*
- * Kmem cache used for allocating
- * timer structures for outstanding
- * IDN requests.
- */
- kmem_cache_t *timer_cache;
- /*
- * Effectively constant used in
- * translating buffer frames in
- * mailbox message frames to
- * offsets within SMR.
- */
- int bframe_shift;
-} idn_global_t;
-
-typedef struct idn_retry_queue idn_retry_queue_t;
-
-#define IDN_GET_MASTERID() (idn.masterid)
-#define IDN_SET_MASTERID(mid) \
- { \
- int _mid = (mid); \
- mutex_enter(&idn.idnsb_mutex); \
- if (idn.idnsb) { \
- idn.idnsb->id_pmaster_board = \
- idn.idnsb->id_master_board; \
- if (_mid == IDN_NIL_DOMID) \
- idn.idnsb->id_master_board = (uchar_t)0xff; \
- else \
- idn.idnsb->id_master_board = \
- (uchar_t)idn_domain[_mid].dvote.v.board; \
- } \
- mutex_exit(&idn.idnsb_mutex); \
- IDN_HISTORY_LOG(IDNH_MASTERID, _mid, idn.masterid, 0); \
- PR_STATE("%d: MASTERID %d -> %d\n", __LINE__, \
- idn.masterid, _mid); \
- idn.masterid = _mid; \
- }
-#define IDN_GET_NEW_MASTERID() (idn.new_masterid)
-#define IDN_SET_NEW_MASTERID(mid) \
- { \
- PR_STATE("%d: NEW MASTERID %d -> %d\n", __LINE__, \
- idn.new_masterid, (mid)); \
- idn.new_masterid = (mid); \
- }
-
-#define IDN_GLOCK_EXCL() (rw_enter(&idn.grwlock, RW_WRITER))
-#define IDN_GLOCK_SHARED() (rw_enter(&idn.grwlock, RW_READER))
-#define IDN_GLOCK_TRY_SHARED() (rw_tryenter(&idn.grwlock, RW_READER))
-#define IDN_GLOCK_DOWNGRADE() (rw_downgrade(&idn.grwlock))
-#define IDN_GUNLOCK() (rw_exit(&idn.grwlock))
-#define IDN_GLOCK_IS_EXCL() (RW_WRITE_HELD(&idn.grwlock))
-#define IDN_GLOCK_IS_SHARED() (RW_READ_HELD(&idn.grwlock))
-#define IDN_GLOCK_IS_HELD() (RW_LOCK_HELD(&idn.grwlock))
-
-#define IDN_SYNC_LOCK() (mutex_enter(&idn.sync.sz_mutex))
-#define IDN_SYNC_TRYLOCK() (mutex_tryenter(&idn.sync.sz_mutex))
-#define IDN_SYNC_UNLOCK() (mutex_exit(&idn.sync.sz_mutex))
-#define IDN_SYNC_IS_LOCKED() (MUTEX_HELD(&idn.sync.sz_mutex))
-
-/*
- * Macro to reset some globals necessary in preparing
- * for initialization of HW for IDN.
- */
-#define IDN_PREP_HWINIT() \
- { \
- ASSERT(IDN_GLOCK_IS_EXCL()); \
- lock_clear(&idn.first_swlink); \
- lock_clear(&idn.first_hwlink); \
- idn.first_hwmasterid = (short)IDN_NIL_DOMID; \
- }
-
-/*
- * Return values of idn_send_data.
- */
-#define IDNXMIT_OKAY 0 /* xmit successful */
-#define IDNXMIT_LOOP 1 /* loopback */
-#define IDNXMIT_DROP 2 /* drop packet */
-#define IDNXMIT_RETRY 3 /* retry packet (requeue and qenable) */
-#define IDNXMIT_REQUEUE 4 /* requeue packet, but don't qenable */
-
-/*
- * ---------------------------------------------------------------------
- * ss_rwlock must be acquired _before_ any idn_domain locks are
- * acquired if both structs need to be accessed.
- * idn.struprwlock is acquired when traversing IDN's strup list
- * and when adding or deleting entries.
- *
- * ss_nextp Linked list of streams.
- * ss_rq Respective read queue.
- * ss_sip Attached device.
- * ss_state Current DL state.
- * ss_sap Bound SAP.
- * ss_flags Misc. flags.
- * ss_mccount # enabled multicast addrs.
- * ss_mctab Table of multicast addrs.
- * ss_minor Minor device number.
- * ss_rwlock Protects ss_linkup fields and DLPI state machine.
- * ss_linkup Boolean flag indicating whether particular (domain) link
- * is up.
- * ---------------------------------------------------------------------
- */
-struct idnstr { /* gets shoved into q_ptr */
- struct idnstr *ss_nextp;
- queue_t *ss_rq;
- struct idn *ss_sip;
- t_uscalar_t ss_state;
- t_uscalar_t ss_sap;
- uint_t ss_flags;
- uint_t ss_mccount;
- struct ether_addr *ss_mctab;
- minor_t ss_minor;
- krwlock_t ss_rwlock;
-};
-
-/*
- * idnstr.ss_flags - Per-stream flags
- */
-#define IDNSFAST 0x01 /* "M_DATA fastpath" mode */
-#define IDNSRAW 0x02 /* M_DATA plain raw mode */
-#define IDNSALLPHYS 0x04 /* "promiscuous mode" */
-#define IDNSALLMULTI 0x08 /* enable all multicast addresses */
-#define IDNSALLSAP 0x10 /* enable all ether type values */
-
-/*
- * Maximum number of multicast address per stream.
- */
-#define IDNMAXMC 64
-#define IDNMCALLOC (IDNMAXMC * sizeof (struct ether_addr))
-
-/*
- * Full DLSAP address length (in struct dladdr format).
- */
-#define IDNADDRL (ETHERADDRL + sizeof (ushort_t))
-
-struct idndladdr {
- struct ether_addr dl_phys;
- ushort_t dl_sap;
-};
-
-#define IDNHEADROOM 64
-#define IDNROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1))
-
-/*
- * Respective interpretation of bytes in 6 byte ethernet address.
- */
-#define IDNETHER_ZERO 0
-#define IDNETHER_COOKIE1 1
-#define IDNETHER_COOKIE1_VAL 0xe5
-#define IDNETHER_COOKIE2 2
-#define IDNETHER_COOKIE2_VAL 0x82
-#define IDNETHER_NETID 3
-#define IDNETHER_CHANNEL 4
-#define IDNETHER_RESERVED 5
-#define IDNETHER_RESERVED_VAL 0x64
-
-/*
- * IDN driver supports multliple instances, however they
- * still all refer to the same "physical" device. Multiple
- * instances are supported primarily to allow increased
- * STREAMs bandwidth since each instance has it's own IP queue.
- * This structure is primarily defined to be consistent with
- * other network drivers and also to hold the kernel stats.
- */
-struct idn_kstat {
- ulong_t si_ipackets; /* # packets received */
- ulong_t si_ierrors; /* # total input errors */
- ulong_t si_opackets; /* # packets sent */
- ulong_t si_oerrors; /* # total output errors */
-
- ulong_t si_txcoll; /* # xmit collisions */
- ulong_t si_rxcoll; /* # recv collisions */
- ulong_t si_crc; /* # recv crc errors */
- ulong_t si_buff; /* # recv pkt sz > buf sz */
-
- ulong_t si_nolink; /* # loss of connection */
- ulong_t si_linkdown; /* # link is down */
- ulong_t si_inits; /* # driver inits */
- ulong_t si_nocanput; /* # canput() failures */
-
- ulong_t si_allocbfail; /* # allocb() failures */
- ulong_t si_notbufs; /* # out of xmit buffers */
- ulong_t si_reclaim; /* # reclaim failures */
- ulong_t si_smraddr; /* # bad SMR addrs */
-
- ulong_t si_txmax; /* # xmit over limit */
- ulong_t si_txfull; /* # xmit mbox full */
- ulong_t si_xdcall; /* # xdcalls sent */
- ulong_t si_sigsvr; /* # data server wakeups */
-
- ulong_t si_mboxcrc; /* # send mbox crc errors */
- /*
- * MIB II kstat variables
- */
- ulong_t si_rcvbytes; /* # bytes received */
- ulong_t si_xmtbytes; /* # bytes transmitted */
- ulong_t si_multircv; /* # multicast packets received */
-
- ulong_t si_multixmt; /* # multicast packets for xmit */
- ulong_t si_brdcstrcv; /* # broadcast packets received */
- ulong_t si_brdcstxmt; /* # broadcast packets for xmit */
- ulong_t si_norcvbuf; /* # rcv packets discarded */
-
- ulong_t si_noxmtbuf; /* # xmit packets discarded */
- /*
- * PSARC 1997/198 : 64 bit kstats
- */
- uint64_t si_ipackets64; /* # packets received */
- uint64_t si_opackets64; /* # packets transmitted */
- uint64_t si_rbytes64; /* # bytes received */
- uint64_t si_obytes64; /* # bytes transmitted */
- /*
- * PSARC 1997/247 : RFC 1643 dot3Stats...
- */
- ulong_t si_fcs_errors; /* FCSErrors */
- ulong_t si_macxmt_errors; /* InternalMacTransmitErrors */
- ulong_t si_toolong_errors; /* FrameTooLongs */
- ulong_t si_macrcv_errors; /* InternalMacReceiveErrors */
-};
-
-/*
- * Per logical interface private data structure.
- */
-struct idn {
- struct idn *si_nextp; /* linked instances */
- dev_info_t *si_dip; /* assoc. dev_info */
- struct ether_addr si_ouraddr; /* enet address */
-
- uint_t si_flags; /* misc. flags */
- uint_t si_wantw; /* xmit: out of res. */
- queue_t *si_ip4q; /* ip (v4) read queue */
- queue_t *si_ip6q; /* ip (v6) read queue */
-
- kstat_t *si_ksp; /* kstat pointer */
- struct idn_kstat si_kstat; /* per-inst kstat */
-};
-
-struct idn_gkstat {
- ulong_t gk_reconfigs; /* # reconfigs */
- ulong_t gk_reconfig_last; /* timestamep */
- ulong_t gk_reaps; /* # of reap request */
- ulong_t gk_reap_last; /* timestamep */
-
- ulong_t gk_links; /* # of IDN links */
- ulong_t gk_link_last; /* timestamep */
- ulong_t gk_unlinks; /* # of IDN unlinks */
- ulong_t gk_unlink_last; /* timestamep */
-
- ulong_t gk_buffail; /* # bad bufalloc */
- ulong_t gk_buffail_last; /* timestamp */
- ulong_t gk_slabfail; /* # bad slaballoc */
- ulong_t gk_slabfail_last; /* timestamp */
-
- ulong_t gk_reap_count; /* # of slabs reaped */
- ulong_t gk_dropped_intrs; /* dropped intrs */
-};
-
-extern struct idn_gkstat sg_kstat;
-
-#ifdef IDN_NO_KSTAT
-
-#define IDN_KSTAT_INC(s, i)
-#define IDN_KSTAT_ADD(s, i, n)
-#define IDN_GKSTAT_INC(i)
-#define IDN_GKSTAT_ADD(vvv, iii)
-#define IDN_GKSTAT_GLOBAL_EVENT(vvv, nnn)
-
-#else /* IDN_NO_KSTAT */
-
-#define IDN_KSTAT_INC(sss, vvv) \
- ((((struct idn *)(sss))->si_kstat.vvv)++)
-#define IDN_KSTAT_ADD(sss, vvv, nnn) \
- ((((struct idn *)(sss))->si_kstat.vvv) += (nnn))
-#define IDN_GKSTAT_INC(vvv) ((sg_kstat.vvv)++)
-#define IDN_GKSTAT_ADD(vvv, iii) ((sg_kstat.vvv) += (iii))
-#define IDN_GKSTAT_GLOBAL_EVENT(vvv, ttt) \
- ((sg_kstat.vvv)++, ((sg_kstat.ttt) = ddi_get_lbolt()))
-
-#endif /* IDN_NO_KSTAT */
-
-/*
- * idn.si_flags
- */
-#define IDNRUNNING 0x01 /* IDNnet is UP */
-#define IDNPROMISC 0x02 /* promiscuous mode enabled */
-#define IDNSUSPENDED 0x04 /* suspended (DR) */
-
-typedef struct kstat_named kstate_named_t;
-
-struct idn_kstat_named {
- kstat_named_t sk_ipackets; /* # packets received */
- kstat_named_t sk_ierrors; /* # total input errors */
- kstat_named_t sk_opackets; /* # packets sent */
- kstat_named_t sk_oerrors; /* # total output errors */
-
- kstat_named_t sk_txcoll; /* # xmit collisions */
- kstat_named_t sk_rxcoll; /* # recv collisions */
- kstat_named_t sk_crc; /* # recv crc errors */
- kstat_named_t sk_buff; /* # recv pkt sz > buf sz */
-
- kstat_named_t sk_nolink; /* # loss of connection */
- kstat_named_t sk_linkdown; /* # link is down */
- kstat_named_t sk_inits; /* # driver inits */
- kstat_named_t sk_nocanput; /* # canput() failures */
-
- kstat_named_t sk_allocbfail; /* # allocb() failures */
- kstat_named_t sk_notbufs; /* # out of xmit buffers */
- kstat_named_t sk_reclaim; /* # reclaim failures */
- kstat_named_t sk_smraddr; /* # bad SMR addrs */
-
- kstat_named_t sk_txmax; /* # xmit over limit */
- kstat_named_t sk_txfull; /* # xmit mbox full */
- kstat_named_t sk_xdcall; /* # xdcalls sent */
- kstat_named_t sk_sigsvr; /* # data server wakeups */
-
- kstat_named_t sk_mboxcrc; /* # send mbox crc errors */
- /*
- * MIB II kstat variables
- */
- kstat_named_t sk_rcvbytes; /* # bytes received */
- kstat_named_t sk_xmtbytes; /* # bytes transmitted */
- kstat_named_t sk_multircv; /* # multicast packets received */
-
- kstat_named_t sk_multixmt; /* # multicast packets for xmit */
- kstat_named_t sk_brdcstrcv; /* # broadcast packets received */
- kstat_named_t sk_brdcstxmt; /* # broadcast packets for xmit */
- kstat_named_t sk_norcvbuf; /* # rcv packets discarded */
-
- kstat_named_t sk_noxmtbuf; /* # xmit packets discarded */
- /*
- * PSARC 1997/198 : 64bit kstats
- */
- kstat_named_t sk_ipackets64; /* # packets received */
- kstat_named_t sk_opackets64; /* # packets transmitted */
- kstat_named_t sk_rbytes64; /* # bytes received */
- kstat_named_t sk_obytes64; /* # bytes transmitted */
- /*
- * PSARC 1997/247 : RFC 1643 dot3Stats...
- */
- kstat_named_t sk_fcs_errors; /* FCSErr */
- kstat_named_t sk_macxmt_errors; /* InternalMacXmtErr */
- kstat_named_t sk_toolong_errors; /* FrameTooLongs */
- kstat_named_t sk_macrcv_errors; /* InternalMacRcvErr */
-};
-
-/*
- * Stats for global events of interest (non-counters).
- */
-struct idn_gkstat_named {
- kstat_named_t sk_curtime; /* current time */
- kstat_named_t sk_reconfigs; /* # master recfgs */
- kstat_named_t sk_reconfig_last; /* timestamp */
- kstat_named_t sk_reaps; /* # of reap req */
- kstat_named_t sk_reap_last; /* timestamp */
- kstat_named_t sk_links; /* # of links */
- kstat_named_t sk_link_last; /* timestamp */
- kstat_named_t sk_unlinks; /* # of unlinks */
- kstat_named_t sk_unlink_last; /* timestamp */
- kstat_named_t sk_buffail; /* # bad buf alloc */
- kstat_named_t sk_buffail_last; /* timestamp */
- kstat_named_t sk_slabfail; /* # bad buf alloc */
- kstat_named_t sk_slabfail_last; /* timestamp */
- kstat_named_t sk_reap_count; /* # slabs reaped */
- kstat_named_t sk_dropped_intrs; /* intrs dropped */
-};
-
-/*
- * ---------------------------------------------------------------------
- */
-#ifdef DEBUG
-#define IDNXDC(d, mt, a1, a2, a3, a4) \
- ((void) debug_idnxdc("idnxdc", (int)(d), (mt), \
- (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4)))
-#else /* DEBUG */
-#define IDNXDC(d, mt, a1, a2, a3, a4) \
- (idnxdc((int)(d), (mt), \
- (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4)))
-#endif /* DEBUG */
-#define IDNXDC_BROADCAST(ds, mt, a1, a2, a3, a4) \
- (idnxdc_broadcast((domainset_t)(ds), (mt), \
- (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4)))
-
-/*
- * ---------------------------------------------------------------------
- */
-#define SET_XARGS(x, a0, a1, a2, a3) \
- ((x)[0] = (uint_t)(a0), (x)[1] = (uint_t)(a1), \
- (x)[2] = (uint_t)(a2), (x)[3] = (uint_t)(a3))
-
-#define GET_XARGS(x, a0, a1, a2, a3) \
- ((*(uint_t *)(a0) = (x)[0]), \
- (*(uint_t *)(a1) = (x)[1]), \
- (*(uint_t *)(a2) = (x)[2]), \
- (*(uint_t *)(a3) = (x)[3]))
-
-#define CLR_XARGS(x) \
- ((x)[0] = (x)[1] = (x)[2] = (x)[3] = 0)
-
-#define GET_XARGS_NEGO_TICKET(x) ((uint_t)(x)[0])
-#define GET_XARGS_NEGO_DSET(x, d) \
- ((d)[0] = (x)[1], (d)[1] = (x)[2], (d)[2] = (x)[3])
-#define SET_XARGS_NEGO_TICKET(x, t) ((x)[0] = (uint_t)(t))
-#define SET_XARGS_NEGO_DSET(x, d) \
- ((x)[1] = (uint_t)(d)[0], \
- (x)[2] = (uint_t)(d)[1], \
- (x)[3] = (uint_t)(d)[2])
-
-#define GET_XARGS_CON_TYPE(x) ((idn_con_t)(x)[0])
-#define GET_XARGS_CON_DOMSET(x) ((domainset_t)(x)[1])
-#define SET_XARGS_CON_TYPE(x, t) ((x)[0] = (uint_t)(t))
-#define SET_XARGS_CON_DOMSET(x, s) ((x)[1] = (uint_t)(s))
-
-#define GET_XARGS_FIN_TYPE(x) GET_FIN_TYPE((x)[0])
-#define GET_XARGS_FIN_ARG(x) GET_FIN_ARG((x)[0])
-#define GET_XARGS_FIN_DOMSET(x) ((domainset_t)(x)[1])
-#define GET_XARGS_FIN_OPT(x) ((idn_finopt_t)(x)[2])
-#define GET_XARGS_FIN_MASTER(x) ((uint_t)(x)[3])
-#define SET_XARGS_FIN_TYPE(x, t) SET_FIN_TYPE((x)[0], (t))
-#define SET_XARGS_FIN_ARG(x, a) SET_FIN_ARG((x)[0], (a))
-#define SET_XARGS_FIN_DOMSET(x, s) ((x)[1] = (uint_t)(s))
-#define SET_XARGS_FIN_OPT(x, o) ((x)[2] = (uint_t)(o))
-#define SET_XARGS_FIN_MASTER(x, m) ((x)[3] = (uint_t)(m))
-
-#define GET_XARGS_NACK_TYPE(x) ((idn_nack_t)(x)[0])
-#define GET_XARGS_NACK_ARG1(x) ((x)[1])
-#define GET_XARGS_NACK_ARG2(x) ((x)[2])
-#define SET_XARGS_NACK_TYPE(x, t) ((x)[0] = (uint_t)(t))
-#define SET_XARGS_NACK_ARG1(x, a1) ((x)[1] = (uint_t)(a1))
-#define SET_XARGS_NACK_ARG2(x, a2) ((x)[2] = (uint_t)(a2))
-
-#define GET_XARGS_CFG_PHASE(x) ((int)(x)[0])
-#define SET_XARGS_CFG_PHASE(x, p) ((x)[0] = (uint_t)(p))
-
-/*
- * ---------------------------------------------------------------------
- */
-/*
- * Device instance to SIP (IDN instance pointer).
- */
-#ifdef DEBUG
-#define IDN_INST2SIP(i) \
- (ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))), \
- idn_i2s_table[i])
-#else /* DEBUG */
-#define IDN_INST2SIP(i) (idn_i2s_table[i])
-#endif /* DEBUG */
-
-#define IDN_SET_INST2SIP(i, s) \
- { \
- ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))); \
- idn_i2s_table[i] = (s); \
- }
-
-#define IDN_NETID2DOMID(n) (VALID_UDOMAINID(n) ? \
- ((int)(n)) : IDN_NIL_DOMID)
-#define IDN_DOMID2NETID(d) ((ushort_t)(d))
-
-#ifdef DEBUG
-#define IDNDL_ETHER2DOMAIN(eap) \
- (_idndl_ether2domain(eap))
-#define IDNDL_ETHER2SIP(eap) \
- (_idndl_ether2sip(eap))
-#else
-/*
- * The following values can be returned from IDNDL_ETHER2DOMAIN:
- * IDN_NIL_DOMID
- * Ether address is broadcast (0xff) or domain doesn't exist.
- * domid Domain id with drwlock(reader) held.
- */
-#define IDNDL_ETHER2DOMAIN(eap) \
- (IDN_NETID2DOMID((eap)->ether_addr_octet[IDNETHER_NETID]))
-#define IDNDL_ETHER2SIP(eap) \
- (((eap)->ether_addr_octet[IDNETHER_CHANNEL] == 0xff) ? NULL : \
- IDN_INST2SIP((int)(eap)->ether_addr_octet[IDNETHER_CHANNEL]))
-#endif /* DEBUG */
-
-#define UPPER32_CPUMASK(s) _upper32cpumask(s)
-#define LOWER32_CPUMASK(s) _lower32cpumask(s)
-#define MAKE64_CPUMASK(s, u, l) _make64cpumask(&(s), (u), (l))
-
-#ifdef DEBUG
-extern caddr_t _idn_getstruct(char *structname, int size);
-extern void _idn_freestruct(caddr_t ptr, char *structname, int size);
-
-#define GETSTRUCT(structure, num) \
- ((structure *)_idn_getstruct("structure", sizeof (structure)*(num)))
-#define FREESTRUCT(ptr, structure, num) \
- (_idn_freestruct((caddr_t)ptr, "structure", sizeof (structure)*(num)))
-#else /* DEBUG */
-#define GETSTRUCT(structure, num) \
- ((structure *)kmem_zalloc((uint_t)(sizeof (structure) * (num)), \
- KM_SLEEP))
-#define FREESTRUCT(ptr, structure, num) \
- (kmem_free((caddr_t)(ptr), sizeof (structure) * (num)))
-#endif /* DEBUG */
-
-extern int idn_debug;
-extern idn_global_t idn;
-extern idn_domain_t idn_domain[];
-extern struct idn *idn_i2s_table[];
-extern int idn_history;
-extern struct idn_history idnhlog;
-
-extern int idn_smr_size;
-extern int idn_nwr_size;
-extern int idn_protocol_nservers;
-extern int idn_awolmsg_interval;
-extern int idn_smr_bufsize;
-extern int idn_slab_bufcount;
-extern int idn_slab_prealloc;
-extern int idn_slab_mintotal;
-extern int idn_window_max;
-extern int idn_window_incr;
-extern int idn_reclaim_min;
-extern int idn_reclaim_max;
-extern int idn_mbox_per_net;
-extern int idn_max_nets;
-
-extern int idn_netsvr_spin_count;
-extern int idn_netsvr_wait_min;
-extern int idn_netsvr_wait_max;
-extern int idn_netsvr_wait_shift;
-
-extern int idn_checksum;
-
-extern int idn_msgwait_nego;
-extern int idn_msgwait_cfg;
-extern int idn_msgwait_con;
-extern int idn_msgwait_fin;
-extern int idn_msgwait_cmd;
-extern int idn_msgwait_data;
-
-extern int idn_retryfreq_nego;
-extern int idn_retryfreq_con;
-extern int idn_retryfreq_fin;
-
-extern int idn_window_emax; /* calculated */
-extern int idn_slab_maxperdomain; /* calculated */
-
-/*
- * ---------------------------------------------------------------------
- * io/idn.c
- * ---------------------------------------------------------------------
- */
-extern int board_to_ready_cpu(int board, cpuset_t cpuset);
-extern int idn_open_domain(int domid, int cpuid, uint_t ticket);
-extern void idn_close_domain(int domid);
-extern void inum2str(uint_t inum, char str[]);
-extern idn_timer_t *idn_timer_alloc();
-extern void idn_timer_free(idn_timer_t *tp);
-extern void idn_timerq_init(idn_timerq_t *tq);
-extern void idn_timerq_deinit(idn_timerq_t *tq);
-extern void idn_timerq_free(idn_timerq_t *tq);
-extern ushort_t idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp,
- clock_t tval);
-extern int idn_timer_stopall(idn_timer_t *tp);
-extern void idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp);
-extern void idn_timer_stop(idn_timerq_t *tq, int subtype, ushort_t tcookie);
-extern idn_timer_t *idn_timer_get(idn_timerq_t *tq, int subtype,
- ushort_t tcookie);
-extern void idn_domain_resetentry(idn_domain_t *dp);
-extern void idn_strlinks_enable(uint_t netaddr, int domid);
-extern void idn_strlinks_disable(uint_t domset, uint_t netaddr,
- int disconnect);
-extern void idn_dopcache_init();
-extern void idn_dopcache_deinit();
-extern void *idn_init_op(idn_opflag_t opflag, boardset_t boardset,
- idnsb_error_t *sep);
-extern void idn_add_op(idn_opflag_t opflag, domainset_t domset);
-extern void idn_update_op(idn_opflag_t opflag, domainset_t domset,
- idnsb_error_t *sep);
-extern void idn_deinit_op(void *cookie);
-extern int idn_wait_op(void *cookie, boardset_t *domsetp,
- int wait_timeout);
-extern int idn_wakeup_op(boardset_t boardset, uint_t domset,
- idn_opflag_t opflag, int error);
-extern void idn_error_op(uint_t domset, boardset_t boardset, int error);
-extern void cpuset2str(cpuset_t cset, char buffer[]);
-extern void domainset2str(domainset_t dset, char buffer[]);
-extern void boardset2str(boardset_t bset, char buffer[]);
-extern void mask2str(uint_t mask, char buffer[], int maxnum);
-extern int idnxdc(int domid, idn_msgtype_t *mtp,
- uint_t arg1, uint_t arg2,
- uint_t arg3, uint_t arg4);
-extern void idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp,
- uint_t arg1, uint_t arg2,
- uint_t arg3, uint_t arg4);
-extern void idn_awol_event_set(boardset_t boardset);
-extern void idn_awol_event_clear(boardset_t boardset);
-#ifdef DEBUG
-extern int debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp,
- uint_t arg1, uint_t arg2,
- uint_t arg3, uint_t arg4);
-#endif /* DEBUG */
-extern boardset_t cpuset2boardset(cpuset_t portset);
-extern uint_t _upper32cpumask(cpuset_t cset);
-extern uint_t _lower32cpumask(cpuset_t cset);
-extern void _make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower);
-
-/*
- * ---------------------------------------------------------------------
- * io/idn_proto.c
- * ---------------------------------------------------------------------
- */
-extern void idn_assign_cookie(int domid);
-extern int idn_rput_data(queue_t *q, mblk_t *mp, int isput);
-extern int idn_wput_data(queue_t *q, mblk_t *mp, int isput);
-extern int idn_send_data(int dst_domid, idn_netaddr_t dst_netaddr,
- queue_t *wq, mblk_t *mp);
-extern void idn_recv_signal(mblk_t *mp);
-extern int idn_link(int domid, int cpuid, int pri, int waittime,
- idnsb_error_t *sep);
-extern int idn_unlink(int domid, boardset_t idnset, idn_fin_t fintype,
- idn_finopt_t finopt, int waittime,
- idnsb_error_t *sep);
-extern int idnh_recv_dataack(int domid, int src_proc,
- uint_t acknack, idn_xdcargs_t xargs);
-extern int idnh_recv_other(int sourceid, int src_proc, int dst_proc,
- uint_t inum, uint_t acknack,
- idn_xdcargs_t xargs);
-extern void idn_send_cmd(int domid, idn_cmd_t cmdtype,
- uint_t arg1, uint_t arg2, uint_t arg3);
-extern void idn_send_cmdresp(int domid, idn_msgtype_t *mtp,
- idn_cmd_t cmdtype, uint_t arg1,
- uint_t arg2, uint_t cerrno);
-extern void idn_broadcast_cmd(idn_cmd_t cmdtype,
- uint_t arg1, uint_t arg2, uint_t arg3);
-extern int idn_reclaim_mboxdata(int domid, int channel, int nbufs);
-extern void idn_clear_awol(int domid);
-extern int idn_protocol_init(int nservers);
-extern void idn_protocol_deinit();
-extern void idn_timer_expired(void *arg);
-extern int idn_open_channel(int channel);
-extern void idn_close_channel(int channel, idn_chanop_t chanop);
-extern idn_mainmbox_t *idn_mainmbox_init(int domid, int mbx);
-extern void idn_mainmbox_deinit(int domid, idn_mainmbox_t *mmp);
-extern void idn_signal_data_server(int domid, ushort_t channel);
-extern int idn_chanservers_init();
-extern void idn_chanservers_deinit();
-extern void idn_chanserver_bind(int net, int cpuid);
-extern int idn_retry_terminate(uint_t token);
-extern idn_protojob_t *idn_protojob_alloc(int kmflag);
-extern void idn_protojob_submit(int cookie, idn_protojob_t *jp);
-extern int idn_domain_is_registered(int domid, int channel,
- idn_chanset_t *chansetp);
-extern void idn_xmit_monitor_kickoff(int chan_wanted);
-extern void idn_sync_exit(int domid, idn_synccmd_t cmd);
-/*
- * ---------------------------------------------------------------------
- * io/idn_xf.c
- * ---------------------------------------------------------------------
- */
-extern void idnxf_flushall_ecache();
-extern int idnxf_shmem_add(int is_master, boardset_t boardset,
- pfn_t pfnbase, pfn_t pfnlimit,
- uint_t *mcadr);
-extern int idnxf_shmem_sub(int is_master, boardset_t boardset);
-extern int idn_cpu_per_board(void *p2o, cpuset_t cset,
- struct hwconfig *hwp);
-/*
- * ---------------------------------------------------------------------
- * io/idn_dlpi.c
- * ---------------------------------------------------------------------
- */
-extern int idndl_init(struct idn *sip);
-extern void idndl_uninit(struct idn *sip);
-extern void idndl_statinit(struct idn *sip);
-extern void idndl_dodetach(struct idnstr *);
-extern int idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsize);
-extern void idndl_localetheraddr(struct idn *sip, struct ether_addr *eap);
-extern int idndl_domain_etheraddr(int domid, int instance,
- struct ether_addr *eap);
-extern void idndl_dlpi_init();
-extern int idndl_start(queue_t *wq, mblk_t *mp, struct idn *sip);
-extern void idndl_read(struct idn *sip, mblk_t *mp);
-extern void idndl_proto(queue_t *wq, mblk_t *mp);
-extern void idndl_sendup(struct idn *, mblk_t *, struct idnstr *(*)());
-extern struct idnstr *idndl_accept(struct idnstr *, struct idn *, int,
- struct ether_addr *);
-extern struct idnstr *idndl_paccept(struct idnstr *, struct idn *, int,
- struct ether_addr *);
-extern void idndl_wenable(struct idn *);
-/*
- * ---------------------------------------------------------------------
- * io/idn_smr.c
- * ---------------------------------------------------------------------
- */
-extern void smr_slabwaiter_open(domainset_t domset);
-extern void smr_slabwaiter_close(domainset_t domset);
-/*
- * ---------------------------------------------------------------------
- */
-extern void idn_smrsize_init();
-extern void idn_init_autolink();
-extern void idn_deinit_autolink();
-
-extern void idn_dmv_handler(void *arg);
-extern void idnxf_init_mondo(uint64_t dmv_word0,
- uint64_t dmv_word1, uint64_t dmv_word2);
-extern int idnxf_send_mondo(int upaid);
-
-extern clock_t idn_msg_waittime[];
-extern clock_t idn_msg_retrytime[];
-
-#endif /* !_ASM */
-#endif /* _KERNEL */
-
-#ifndef _ASM
-/*
- * ---------------------------------------------------------------------
- */
-#define IDN_NIL_DOMID -1
-#define IDN_NIL_DCPU -1
-
-/*
- * ---------------------------------------------------------------------
- */
-
-/*
- * IOCTL Interface
- *
- * Commands must stay in the range (1 - 4096) since only 12 bits
- * are allotted.
- */
-#define _IDN(n) (('I' << 20) | ('D' << 12) | (n))
-#define IDNIOC_LINK _IDN(1) /* domain_link */
-#define IDNIOC_UNLINK _IDN(2) /* domain_unlink */
-#define IDNIOC_unused0 _IDN(3)
-#define IDNIOC_unused1 _IDN(4)
-#define IDNIOC_unused2 _IDN(5)
-#define IDNIOC_unused3 _IDN(6)
-#define IDNIOC_unused4 _IDN(7)
-#define IDNIOC_DLPI_ON _IDN(8) /* Turn ON DLPI on str */
-#define IDNIOC_DLPI_OFF _IDN(9) /* Turn OFF DLPI on str */
-#define IDNIOC_PING _IDN(10) /* For latency testing */
-#define IDNIOC_PING_INIT _IDN(11)
-#define IDNIOC_PING_DEINIT _IDN(12)
-#define IDNIOC_MEM_RW _IDN(13) /* Random R/W of SMR */
-
-
-#define VALID_NDOP(op) (((op) == ND_SET) || ((op) == ND_GET))
-
-#define VALID_DLPIOP(op) (((op) == DLIOCRAW) || \
- ((op) == DL_IOC_HDR_INFO))
-
-#define VALID_IDNOP(op) (((op) >= _IDN(1)) && ((op) <= _IDN(13)))
-
-#define VALID_IDNIOCTL(op) (VALID_IDNOP(op) || \
- VALID_NDOP(op) || \
- VALID_DLPIOP(op))
-
-typedef union idnop {
- struct {
- int domid; /* input */
- int cpuid; /* input */
- int master; /* input */
- int wait; /* input */
- } link;
- struct {
- int domid; /* input */
- int cpuid; /* input */
- int force; /* input */
- int wait; /* input */
- } unlink;
- struct {
- int domid; /* input */
- int cpuid; /* input */
- } ping;
- struct {
- uint_t lo_off; /* input */
- uint_t hi_off; /* input */
- int blksize; /* input */
- int num; /* input */
- int rw; /* input */
- int goawol; /* input */
- } rwmem;
-} idnop_t;
-
-#ifdef _KERNEL
-/*
- * ndd support for IDN tunables.
- */
-typedef struct idnparam {
- ulong_t sp_min;
- ulong_t sp_max;
- ulong_t sp_val;
- char *sp_name;
-} idnparam_t;
-
-extern idnparam_t idn_param_arr[];
-
-#define idn_modunloadable idn_param_arr[0].sp_val
-#ifdef IDN_PERF
-#define _LP 0
-#define _xxx_tbd idn_param_arr[_LP+1].sp_val
-#endif /* IDN_PERF */
-
-/*
- * =====================================================================
- */
-
-/*
- * Some junk to pretty print board lists and cpu lists in
- * log/console messages. Length is big enough to display 64 double
- * digit cpus separated by a command and single space. (Board list
- * is similar, but only 16 entries possible.
- */
-#define _DSTRLEN 400
-#define ALLOC_DISPSTRING() ((char *)kmem_alloc(_DSTRLEN, KM_NOSLEEP))
-#define FREE_DISPSTRING(b) (kmem_free((void *)(b), _DSTRLEN))
-
-/*
- * These are declared in idn.c.
- */
-extern const char *idnds_str[];
-extern const char *idnxs_str[];
-extern const char *idngs_str[];
-extern const char *idncmd_str[];
-extern const char *idncon_str[];
-extern const char *idnfin_str[];
-extern const char *idnfinarg_str[];
-extern const char *idnfinopt_str[];
-extern const char *idnreg_str[];
-extern const char *idnnack_str[];
-extern const char *idnop_str[];
-extern const char *idnsync_str[];
-extern const char *chanop_str[];
-extern const char *chanaction_str[];
-extern const char *inum_str[];
-extern const int inum_bump;
-extern const int inum_max;
-extern const int acknack_shift;
-
-extern const char *timer_str[];
-extern const char *res_str[];
-
-#endif /* _KERNEL */
-#endif /* !_ASM */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_IDN_H */
diff --git a/usr/src/uts/sun4u/starfire/sys/idn_sigb.h b/usr/src/uts/sun4u/starfire/sys/idn_sigb.h
deleted file mode 100644
index 9e1d256d9a..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/idn_sigb.h
+++ /dev/null
@@ -1,401 +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.
- *
- * Inter-Domain Network Sigblock Interface.
- *
- * ******************************************************
- * ******************************************************
- * IMPORTANT: THE DEFINITIONS HERE ARE DUPLICATES OF
- * THE cbe_idn_sigb.h FILE IN cbe/cbutils.
- * ANY CHANGES THERE MUST BE RELECTED
- * HERE AND VICE VERSA. WE CANNOT INCLUDE
- * THIS HEADER IN THE BUILD OF CBE.
- * ******************************************************
- * ******************************************************
- */
-
-#ifndef _SYS_IDN_SIGB_H
-#define _SYS_IDN_SIGB_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _SSP
-#include <domain_config.h>
-#include <sigblock.h>
-#define _MAX_DOMAINS MAX_DOMAINS_PER_MACH
-#else /* _SSP */
-#include <sys/starfire.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/cpu_sgn.h>
-#define MAX_BOARDS STARFIRE_MAX_BOARDS
-#define MAX_DOMAINS MAX_BOARDS
-#define _MAX_DOMAINS MAX_DOMAINS
-#endif /* _SSP */
-
-#define SSI_LINK (('I' << 8) | 0x01)
-#define SSI_UNLINK (('I' << 8) | 0x02)
-#define SSI_INFO (('I' << 8) | 0x03)
-#define SSI_ACK 0x10
-
-#define VALID_IDNSIGBCMD(c) ((((c) & ~SSI_ACK) == SSI_LINK) || \
- (((c) & ~SSI_ACK) == SSI_UNLINK) || \
- (((c) & ~SSI_ACK) == SSI_INFO))
-
-/*
- * SSI_LINK
- * timeout field must be first.
- */
-typedef struct {
- int32_t timeout; /* seconds */
- int32_t cpuid;
- int32_t domid;
- int32_t master_pri;
-} idnsb_link_t;
-
-
-/*
- * SSI_UNLINK
- * timeout field must be first.
- *
- * If both cpuid and domid are specified then they must match the
- * correct domain from the local domain's perspective. The cpuid
- * and/or domid have precedence over the boardset parameter.
- * The boardset parameter is provided if the caller is unable to
- * determine the cpuid/domid of the target domain. This may happen
- * if the target domain is currently down.
- *
- * idnsb_unlink_t.force values.
- */
-#define SSIFORCE_OFF 0
-#define SSIFORCE_SOFT 1
-#define SSIFORCE_HARD 2
-
-typedef struct {
- int32_t timeout; /* seconds */
- int32_t cpuid;
- int32_t domid;
- ushort_t boardset;
- short force;
- ushort_t idnset;
-} idnsb_unlink_t;
-
-
-/*
- * SSI_INFO
- * Assumes max of 16 boards/domain.
- *
- * idnsb_info_t.idn_active values.
- */
-#define SSISTATE_INACTIVE 0
-#define SSISTATE_BUSY 1
-#define SSISTATE_ACTIVE 2
-
-typedef struct {
- ushort_t domain_boardset[_MAX_DOMAINS];
- uchar_t idn_active;
- uchar_t idn_state; /* same as GSTATE */
- uchar_t local_index;
- uchar_t local_cpuid;
- uchar_t master_index;
- uchar_t master_cpuid;
- ushort_t awol_domset;
- ushort_t conn_domset;
- ushort_t _filler;
-} idnsb_info_t;
-
-#define INIT_IDNKERR(ep) \
- (bzero((caddr_t)(ep), sizeof (idnsb_error_t)))
-#define SET_IDNKERR_ERRNO(ep, err) ((ep)->k_errno = (int)(err))
-#define SET_IDNKERR_IDNERR(ep, err) ((ep)->k_idnerr = (int)(err))
-#define SET_IDNKERR_PARAM0(ep, p0) ((ep)->k_param[0] = (uint_t)(p0))
-#define SET_IDNKERR_PARAM1(ep, p1) ((ep)->k_param[1] = (uint_t)(p1))
-#define SET_IDNKERR_PARAM2(ep, p2) ((ep)->k_param[2] = (uint_t)(p2))
-#define GET_IDNKERR_ERRNO(ep) ((ep)->k_errno)
-#define GET_IDNKERR_IDNERR(ep) ((ep)->k_idnerr)
-#define GET_IDNKERR_PARAM0(ep) ((ep)->k_param[0])
-#define GET_IDNKERR_PARAM1(ep) ((ep)->k_param[1])
-#define GET_IDNKERR_PARAM2(ep) ((ep)->k_param[2])
-
-#define IDNKERR_DRV_DISABLED 0x100 /* IDN driver disabled */
- /* param=none */
-#define IDNKERR_DATA_LEN 0x101 /* invalid length of idnsb_data_t */
- /* p0=length */
-#define IDNKERR_INFO_FAILED 0x102 /* SSI_INFO failed */
- /* param=none */
-#define IDNKERR_INVALID_DOMAIN 0x103 /* invalid domain specified */
- /* p0=domid, p1=cpuid */
-#define IDNKERR_INVALID_FORCE 0x104 /* invalid force option specified */
- /* p0=force */
-#define IDNKERR_INVALID_CMD 0x105 /* invalid IDN/SSI command req */
- /* p0=cmd */
-#define IDNKERR_INVALID_WTIME 0x106 /* invalid waittime specified */
- /* p0=waittime */
-#define IDNKERR_SMR_CORRUPTED 0x107 /* SMR memory is corrupted */
- /* p0=domid (against who detected) */
-#define IDNKERR_CPU_CONFIG 0x108 /* missing a cpu per board */
- /* p0=domid */
-#define IDNKERR_HW_ERROR 0x109 /* error programming hardware */
- /* p0=domid */
-#define IDNKERR_SIGBINTR_LOCKED 0x10a /* sigbintr is locked */
-#define IDNKERR_SIGBINTR_BUSY 0x10b /* sigbintr is busy working */
-#define IDNKERR_SIGBINTR_NOTRDY 0x10c /* sigbintr thread not ready */
-#define IDNKERR_CONFIG_FATAL 0x10d /* fatal error during config */
-#define IDNKERR_CONFIG_MULTIPLE 0x10e /* multiple config conflicts */
- /* p0=domid, p1=count */
- /*
- * For all CONFIG errors:
- * p0=domid, p1=expected, p2=actual.
- */
-#define IDNKERR_CONFIG_MTU 0x10f /* MTU configs conflict */
-#define IDNKERR_CONFIG_BUF 0x110 /* SMR_BUF_SIZE conflicts */
-#define IDNKERR_CONFIG_SLAB 0x111 /* slab-size conflicts */
-#define IDNKERR_CONFIG_NWR 0x112 /* NWR sizes conflict */
-#define IDNKERR_CONFIG_NETS 0x113 /* MAX_NETS conflict */
-#define IDNKERR_CONFIG_MBOX 0x114 /* MBOX_PER_NETS conflict */
-#define IDNKERR_CONFIG_NMCADR 0x115 /* Number of MCADRS conflicts */
-#define IDNKERR_CONFIG_MCADR 0x116 /* Missing MCADR */
-#define IDNKERR_CONFIG_CKSUM 0x117 /* checksum setting conflicts */
-#define IDNKERR_CONFIG_SMR 0x118 /* master's SMR too large */
-
-typedef struct {
- int k_errno;
- int k_idnerr;
- uint_t k_param[3];
-} idnsb_error_t;
-
-typedef struct {
- union {
- int _ssb_timeout; /* link & unlink only (secs) */
- idnsb_link_t _ssb_link;
- idnsb_unlink_t _ssb_unlink;
- idnsb_info_t _ssb_info;
- } _u;
- idnsb_error_t ssb_error;
-} idnsb_data_t;
-
-#define ssb_timeout _u._ssb_timeout
-#define ssb_link _u._ssb_link
-#define ssb_unlink _u._ssb_unlink
-#define ssb_info _u._ssb_info
-
-
-/*
- * Boot information set by IDN driver when loaded.
- * SSIEVENT_BOOT Indicates IDN driver is ready for linking.
- * If this nibble is cleared (0) it
- * indicates domain has halted.
- * SSIEVENT_AWOL Indicates local IDN has reported
- * some domains (boards) have gone AWOL.
- * (event_handled) is primarily used by SSP/CB applications for
- * synchronization with respect to handling event triggered in (event).
- * The respective bits from (event) are set in (event_handled)
- * when the event has been successfully processed by IDNevent(SSP).
- * It is cleared by CBE based TCL scripts (mon_signatures.tcl, idn.tcl)
- * when event is detected and needs processing.
- * SSIEVENT_VERSION represents the version of the SSP side of
- * the IDN software. While idnsb_event_t.version represents the
- * version of the OS side of the IDN software.
- *
- * Protocol: Host SSP
- * ---- ---
- * event
- * - 1 -> evt[].e_handled
- * - X -> evt[].e_event
- * - Y -> evt[].e_event_data
- * - 0 -> evt[].e_handled
- * (!evt[].e_handled)
- * ...process(evt[].e_event)
- * - evt[].e_handled_data =
- * evt[].e_event_data
- * - evt[].e_handled = 1
- */
-#define SSIEVENT_COOKIE "IDN"
-#define SSIEVENT_COOKIE_LEN 3
-#define SSIEVENT_VERSION 1
-
-#define SSIEVENT_BOOT 0 /* index to evt[] */
-#define _SSIEVENT_BOOT_VAL 0xb
-#define _SSIEVENT_BOOT_SHIFT (SSIEVENT_BOOT << 2)
-#define _SSIEVENT_BOOT_MASK (_SSIEVENT_BOOT_VAL << _SSIEVENT_BOOT_SHIFT)
-
-#define SSIEVENT_AWOL 1
-#define _SSIEVENT_AWOL_VAL 0xa
-#define _SSIEVENT_AWOL_SHIFT (SSIEVENT_AWOL << 2)
-#define _SSIEVENT_AWOL_MASK (_SSIEVENT_AWOL_VAL << _SSIEVENT_AWOL_SHIFT)
-
-#define SSIEVENT_NUM 2 /* actual max simultaneous events */
-#define SSIEVENT_MAXNUM 3 /* last one in reserve */
-
-#define _SSIEVENT_VALUE(i) \
- ((i == 0) ? _SSIEVENT_BOOT_VAL : ((i == 1) ? _SSIEVENT_AWOL_VAL : 0))
-
-#define _SSIEVENT_MASKS(i) \
- ((i == 0) ? _SSIEVENT_BOOT_MASK : ((i == 1) ? _SSIEVENT_AWOL_MASK : 0))
-/*
- * Get a bitmask of the current "state".
- */
-#define SSIEVENT_GET_STATE_MASK(s) \
- (((s).idn_evt[SSIEVENT_BOOT].e_event ? _SSIEVENT_BOOT_MASK : 0) \
- | ((s).idn_evt[SSIEVENT_AWOL].e_event ? _SSIEVENT_AWOL_MASK : 0))
-
-#define SSIEVENT_GET_STATE(s, e) \
- ((s).idn_evt[e].e_event ? _SSIEVENT_VALUE(e) : 0)
-#define SSIEVENT_CLR_STATE(s, e) \
- ((s).idn_evt[e].e_event = 0)
-#define SSIEVENT_SET_STATE(s, e) \
- ((s).idn_evt[e].e_event = _SSIEVENT_VALUE(e))
-
-/*
- * Get a bitmask of the currently handled states.
- */
-#define SSIEVENT_GET_HANDLED_MASK(s) \
- (((s).idn_evt[SSIEVENT_BOOT].e_handled ? _SSIEVENT_BOOT_MASK : 0) \
- | ((s).idn_evt[SSIEVENT_AWOL].e_handled ? _SSIEVENT_AWOL_MASK : 0))
-
-#define SSIEVENT_GET_HANDLED(s, e) \
- ((s).idn_evt[e].e_handled ? _SSIEVENT_VALUE(e) : 0)
-#define SSIEVENT_CLR_HANDLED(s, e) \
- ((s).idn_evt[e].e_handled = 0)
-#define SSIEVENT_SET_HANDLED(s, e) \
- ((s).idn_evt[e].e_handled = _SSIEVENT_VALUE(e))
-#define SSIEVENT_SET_HANDLED_DATA(s, e, d) \
- ((s).idn_evt[e].e_handled_data = (ushort_t)(d))
-#define SSIEVENT_GET_HANDLED_EVT(i, e) \
- ((i).e_handled ? _SSIEVENT_VALUE(e) : 0)
-#define SSIEVENT_CLR_HANDLED_EVT(i) ((i).e_handled = 0)
-#define SSIEVENT_SET_HANDLED_EVT(i, e) ((i).e_handled = _SSIEVENT_VALUE(e))
-
-/*
- * Check for the state of a particular event within a state bitmask.
- */
-#define SSIEVENT_CHK_STATE_MASK(m, e) \
- ((((m) & (0xf << ((e) << 2))) == _SSIEVENT_MASKS(e)) ? 1 : 0)
-#define SSIEVENT_CHK_HANDLED_MASK(m, e) SSIEVENT_CHK_STATE_MASK((m), (e))
-
-/*
- * Build the state mask managed in the cbe to represent the state
- * of the respective events above.
- */
-#define SSIEVENT_DEL_STATE_MASK(m, e) ((m) &= ~(0xf << ((e) << 2)))
-#define SSIEVENT_ADD_STATE_MASK(m, e) \
- (SSIEVENT_DEL_STATE_MASK((m), (e)), \
- ((m) |= _SSIEVENT_MASKS(e)))
-#define SSIEVENT_STATE_MASK (_SSIEVENT_BOOT_MASK | _SSIEVENT_AWOL_MASK)
-#define SSIEVENT_STATE_NIL 0
-
-#ifdef _KERNEL
-#define SSIEVENT_SET(s, e, d) { \
- SSIEVENT_SET_HANDLED(*(s), (e)); \
- membar_stst_stld(); \
- SSIEVENT_SET_STATE(*(s), (e)); \
- (s)->idn_evt[e].e_event_data = (ushort_t)(d); \
- membar_stst_stld(); \
- SSIEVENT_CLR_HANDLED(*(s), (e)); \
-}
-#define SSIEVENT_CLEAR(s, e, d) { \
- SSIEVENT_SET_HANDLED(*(s), (e)); \
- membar_stst_stld(); \
- SSIEVENT_CLR_STATE(*(s), (e)); \
- (s)->idn_evt[e].e_event_data &= (ushort_t)~(d); \
- membar_stst_stld(); \
- SSIEVENT_CLR_HANDLED(*(s), (e)); \
-}
-#define SSIEVENT_ADD(s, e, d) { \
- SSIEVENT_SET_HANDLED(*(s), (e)); \
- membar_stst_stld(); \
- SSIEVENT_SET_STATE(*(s), (e)); \
- (s)->idn_evt[e].e_event_data |= (ushort_t)(d); \
- membar_stst_stld(); \
- SSIEVENT_CLR_HANDLED(*(s), (e)); \
-}
-#define SSIEVENT_DEL(s, e, d) { \
- SSIEVENT_SET_HANDLED(*(s), (e)); \
- membar_stst_stld(); \
- (s)->idn_evt[e].e_event_data &= (ushort_t)~(d); \
- if ((s)->idn_evt[e].e_event_data != 0) { \
- SSIEVENT_SET_STATE(*(s), (e)); \
- membar_stst_stld(); \
- SSIEVENT_CLR_HANDLED(*(s), (e)); \
- } else { \
- membar_stst_stld(); \
- SSIEVENT_CLR_STATE(*(s), (e)); \
- } \
-}
-#endif /* _KERNEL */
-
-typedef struct idnevent {
- uchar_t e_event;
- uchar_t e_handled;
- ushort_t e_event_data;
- ushort_t e_handled_data;
- ushort_t reserved;
-} idnevent_t;
-
-/*
- * IMPORTANT: This data structure must be the size of a sigbmbox_t
- * so that it fits in the space it steals in the sigblock.
- * Also, any changes to this structure must be cross-checked
- * with (struct idnsb) in <sun4u1/sys/idn.h> with respect
- * the area from reserved1 on down.
- */
-#define IDNSB_EVENT_SIZE (sizeof (sigbmbox_t))
-typedef struct {
- struct _idnsb_event {
- union {
- struct {
- char _cookie[SSIEVENT_COOKIE_LEN];
- uchar_t _version;
- } _ss;
- struct {
- uint_t _cookie : 24;
- uint_t _version : 8;
- } _sn;
- } _u;
- uint_t _reserved1; /* reserved for IDN driver */
- idnevent_t _evt[SSIEVENT_MAXNUM];
- } _s;
-
- /* reserved for IDN driver */
- char reserved2[IDNSB_EVENT_SIZE - sizeof (struct _idnsb_event)];
-} idnsb_event_t;
-
-#define idn_evt _s._evt
-#define idn_reserved1 _s._reserved1
-#define idn_cookie_str _s._u._ss._cookie
-#define idn_version_byte _s._u._ss._version
-#define idn_cookie _s._u._sn._cookie
-#define idn_version _s._u._sn._version
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_IDN_SIGB_H */
diff --git a/usr/src/uts/sun4u/starfire/sys/idn_smr.h b/usr/src/uts/sun4u/starfire/sys/idn_smr.h
deleted file mode 100644
index 8a0e4cddb2..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/idn_smr.h
+++ /dev/null
@@ -1,230 +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 by Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Inter-Domain Network - SMR support.
- */
-
-#ifndef _SYS_IDN_SMR_H
-#define _SYS_IDN_SMR_H
-
-#include <sys/sysmacros.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef uint_t smr_offset_t;
-
-#define IDN_NIL_SMROFFSET ((smr_offset_t)-1)
-
-/*
- * ---------------------------------------------------------------------
- * Data in the SMR is automatically aligned on 64 byte boundaries due
- * to the large IDN_SMR_BUFSIZE, however the streams buffers may not be
- * so we bump them in order to allow us to align appropriately and thus
- * maximize bcopy performance.
- * ---------------------------------------------------------------------
- */
-#define IDN_ALIGNSIZE 64
-/*
- * Align the pointer "p" to the same relative offset as the reference
- * pointer "r" within IDN_ALIGNSIZE bytes.
- */
-#define IDN_ALIGNPTR(p, r) ((uintptr_t)(p) + (((uintptr_t)(r) - \
- (uintptr_t)(p)) & \
- (uintptr_t)(IDN_ALIGNSIZE - 1)))
-
-#define IDN_OFFSET2ADDR(off) ((caddr_t)((uintptr_t)(off) + \
- (uintptr_t)idn.smr.vaddr))
-#define IDN_ADDR2OFFSET(va) ((smr_offset_t)((caddr_t)(va) - idn.smr.vaddr))
-#define IDN_BUF2DATA(b, o) ((caddr_t)((uintptr_t)(b) + (uintptr_t)(o)))
-#define IDN_BUF2HDR(b) ((smr_pkthdr_t *)(b))
-
-#define IDN_CKSUM_PKT_COUNT (offsetof(smr_pkthdr_t, b_cksum) / 2)
-
-#define IDN_CKSUM_PKT(h) \
- (IDN_CHECKSUM ? \
- idn_cksum((ushort_t *)(h), IDN_CKSUM_PKT_COUNT) : 0)
-
-typedef struct smr_pkthdr {
- uint_t b_netaddr;
- uint_t b_netports;
- smr_offset_t b_offset;
- int b_length;
-
- ushort_t b_rawio;
- ushort_t b_cksum;
- smr_offset_t b_next; /* used during reclamation */
-} smr_pkthdr_t;
-
-/*
- * ---------------------------------------------------------------------
- * IDN Slab related definitions.
- *
- * Domains are allocated SMR buffers in slabs. Slaves keep track of
- * their own slabs in their respective idn_domain entry. The Master
- * keeps track of slave slabs via their respective idn_domain entry.
- * The global slab pools representing all of the SMR and managed by
- * the master are maintained in the idn_global structure.
- *
- * The minimum number of slabs is chosen so that there is at least
- * one slab available for every possible domain that might be attached.
- *
- * NOTE: idn_slab_bufcount * idn_smr_bufsize should be on a 64-byte
- * (IDN_ALIGNSIZE) boundary for maximum bcopy performance.
- * ---------------------------------------------------------------------
- */
-#define IDN_SLAB_BUFCOUNT idn_slab_bufcount
-#define IDN_SLAB_SIZE (IDN_SLAB_BUFCOUNT * IDN_SMR_BUFSIZE)
-#define IDN_SLAB_MAXNUM (idn.slabpool->ntotslabs)
-#define IDN_SLAB_MINPERPOOL 3
-#define IDN_SLAB_MINTOTAL idn_slab_mintotal
-#define IDN_SLAB_PREALLOC idn_slab_prealloc
-
-/*
- * ---------------------------------------------------------------------
- * Maximum number of slabs per domain the master will
- * allow to be allocated. Further requests simply result
- * in a failed allocation.
- * Nominal value is 1/6 of the total available (~10).
- * Maximum number of bufs a domain can expect based on
- * IDN_SLAB_MAXPERDOMAIN.
- * ---------------------------------------------------------------------
- */
-#define IDN_SLAB_MAXPERDOMAIN idn_slab_maxperdomain
-#define IDN_BUF_MAXPERDOMAIN (IDN_SLAB_MAXPERDOMAIN * IDN_SLAB_BUFCOUNT)
-/*
- * ---------------------------------------------------------------------
- * If the total number of available slabs managed by the master
- * goes below this minimum total threshold, then the master kicks
- * off a reap request to all domains to check for free slabs and
- * to give them up. For performance reasons, domains do not
- * automatically flush out free slabs. They rely on the master
- * to tell them to look for some.
- * ---------------------------------------------------------------------
- */
-#define IDN_SLAB_THRESHOLD MIN(MAX_DOMAINS, \
- (IDN_SLAB_MINTOTAL + \
- (IDN_SLAB_MINTOTAL / 5)))
-#define IDN_REAP_INTERVAL (2 * hz)
-
-#define SMR_SLABPOOL_HASH(d) ((d) % idn.slabpool->npools)
-#define SMR_SLABPOOL_HASHSTEP(p) (((p)+4) % idn.slabpool->npools)
-#define SMR_SLAB_HASH(p, d) \
- ((d) % idn.slabpool->pool[p].nslabs)
-#define SMR_SLAB_HASHSTEP(p, s) \
- (((s)+1) % idn.slabpool->pool[p].nslabs)
-
-/*
- * ---------------------------------------------------------------------
- * There is one smr_slabbuf for each buffer in the respective slab.
- *
- * sb_domid Domainid currently owning respective buffer.
- * Local domains use this field to determine what buffers
- * are outstanding at which domains. The master uses this
- * field to know which domain owns given slab.
- * sb_bufp Actual pointer to (VA) buffer.
- * sb_next Used to manage free and in-use lists.
- * ---------------------------------------------------------------------
- */
-typedef struct smr_slabbuf {
- int sb_domid;
- caddr_t sb_bufp;
- struct smr_slabbuf *sb_next;
-} smr_slabbuf_t;
-
-/*
- * ---------------------------------------------------------------------
- * There is one smr_slab per slab of buffers.
- *
- * sl_next List of slabs allocated to same requester.
- * sl_start Base virtual address (SMR) of slab.
- * sl_end Points to byte immediately following end of slab.
- * sl_lock Atomic lock used to manage free/inuse lists.
- * sl_domid Used by Master to indicate which slave owns
- * respective slab.
- * sl_free Freelist of available buffers.
- * sl_inuse List of buffers currently allocated and in-use.
- * sl_head Pointer to memory allocated to hold smr_slabbuf_t's.
- * ---------------------------------------------------------------------
- */
-typedef struct smr_slab {
- struct smr_slab *sl_next;
- caddr_t sl_start,
- sl_end;
- lock_t sl_lock;
-
- union {
- int _sl_domid;
- struct {
- smr_slabbuf_t *_sl_free;
- smr_slabbuf_t *_sl_inuse;
- smr_slabbuf_t *_sl_head;
- } _s;
- } _u;
-} smr_slab_t;
-
-#define sl_domid _u._sl_domid
-#define sl_free _u._s._sl_free
-#define sl_inuse _u._s._sl_inuse
-#define sl_head _u._s._sl_head
-
-/*
- * ---------------------------------------------------------------------
- * io/idn_smr.c
- * ---------------------------------------------------------------------
- */
-extern void smr_slab_reap(int domid, int *nslabs);
-extern int smr_slab_alloc(int domid, smr_slab_t **spp);
-extern void smr_slab_free(int domid, smr_slab_t *sp);
-extern void smr_slab_garbage_collection(smr_slab_t *sp);
-extern int smr_slab_busy(smr_slab_t *sp);
-extern int smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp);
-extern int smr_buf_free(int domid, caddr_t bufp, uint_t len);
-extern int smr_buf_free_locked(int domid, caddr_t bufp, uint_t len);
-extern int smr_buf_free_all(int domid);
-extern int smr_buf_reclaim(int domid, int nbufs);
-extern int smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag,
- int serrno);
-extern void smr_alloc_buflist(smr_slab_t *sp);
-extern void smr_free_buflist(smr_slab_t *sp);
-extern int smr_slabwaiter_init();
-extern void smr_slabwaiter_deinit();
-extern int smr_slabwaiter_abort(int domid, int serrno);
-extern smr_slab_t *smr_slaballoc_get(int domid, caddr_t bufp,
- caddr_t ebufp);
-extern int smr_slabpool_init(size_t reserved_size,
- caddr_t *reserved_area);
-extern void smr_slabpool_deinit();
-extern void smr_remap(struct as *as, register caddr_t vaddr,
- register pfn_t new_pfn, uint_t mblen);
-
-extern int idn_slab_prealloc;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_IDN_SMR_H */
diff --git a/usr/src/uts/sun4u/starfire/sys/idn_xf.h b/usr/src/uts/sun4u/starfire/sys/idn_xf.h
deleted file mode 100644
index e23b9005d3..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/idn_xf.h
+++ /dev/null
@@ -1,133 +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 by Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Inter-Domain Network - Xfire specifics.
- */
-
-#ifndef _SYS_IDN_XF_H
-#define _SYS_IDN_XF_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/pda.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/idn_sigb.h>
-#include <sys/starfire.h>
-
-#include <sys/idn.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * These address bits fit into PA[17:9].
- */
-#define CIC_CONFIG0_ADDR 0x002
-#define CIC_CONFIG1_ADDR 0x003
-#define CIC_DOMAIN_MASK_ADDR 0x004
-#define CIC_SM_MASK_ADDR 0x005
-#define CIC_SM_BAR_LSB_ADDR 0x006
-#define CIC_SM_BAR_MSB_ADDR 0x007
-#define CIC_SM_LAR_LSB_ADDR 0x008
-#define CIC_SM_LAR_MSB_ADDR 0x009
-
-#define CIC_CONFIG0_BUSMODE_MASK 0x3
-#define CIC_CONFIG0_BUSMODE_SHIFT 2
-#define CIC_CONFIG0_BUSMODE(c) \
- (((c) >> CIC_CONFIG0_BUSMODE_SHIFT) & CIC_CONFIG0_BUSMODE_MASK)
-#define CIC_CONFIG1_SMMASK_MASK 0x1
-#define CIC_CONFIG1_SMMASK_SHIFT 1
-#define CIC_CONFIG1_SMMASK_BIT(c) \
- (((c) >> CIC_CONFIG1_SMMASK_SHIFT) & CIC_CONFIG1_SMMASK_MASK)
-
-#define CIC_CSR_ADDR_MASK 0x1ff
-#define CIC_CSR_ADDR_SHIFT 9
-#define CSR_TYPE_CIC 0xe
-
-#define CSR_BOARD_MASK 0xf /* PA[39:36] */
-#define CSR_BOARD_SHIFT 36
-
-#define CSR_TYPE_MASK 0xf /* PA[35:32] */
-#define CSR_TYPE_SHIFT 32
-
-#define CSR_BUS_MASK 0x3
-#define CSR_BUS_SHIFT 6 /* XXX - depends on config/shuffle */
-
- /* bd=board, t=type, a=addr, bs=bus */
-#define MAKE_CIC_CSR_PA(bd, t, a, bs) \
- (((u_longlong_t)1 << 40) \
- | ((u_longlong_t)((bd) & CSR_BOARD_MASK) \
- << CSR_BOARD_SHIFT) \
- | ((u_longlong_t)((t) & CSR_TYPE_MASK) \
- << CSR_TYPE_SHIFT) \
- | ((u_longlong_t)((a) & CIC_CSR_ADDR_MASK) \
- << CIC_CSR_ADDR_SHIFT) \
- | ((u_longlong_t)((bs) & CSR_BUS_MASK) \
- << CSR_BUS_SHIFT))
-
-#define STARFIRE_PC_MADR_VALIDBIT 0x80000000
-
-/*
- * Macro to calculate address of CIC prep buffer
- * that resides in PC.
- * This macro really belongs in <sys/starfire.h>
- */
-#define STARFIRE_PC_CICBUF_ADDR(bb, p) \
- (STARFIRE_BRD_TO_PSI(bb) | \
- ((uint64_t)(p) << STARFIRE_UPS_MID_SHIFT) | \
- STARFIRE_PSI_PCREG_OFF | \
- STARFIRE_PC_CIC_WRITE_DATA)
-
-/*
- * ---------------------------------------------------------------------
- */
-
-extern cpu_t cpu0;
-
-extern int get_hw_config(struct hwconfig *loc_hw);
-extern int update_local_hw_config(idn_domain_t *ldp,
- struct hwconfig *loc_hw);
-extern boardset_t cic_read_domain_mask(int board, int bus);
-extern boardset_t cic_read_sm_mask(int board, int bus);
-extern uint_t cic_read_sm_bar(int board, int bus);
-extern uint_t cic_read_sm_lar(int board, int bus);
-extern void pc_read_madr(pda_handle_t ph, int lboard,
- uint_t mc_adr[], int local_only);
-extern void mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[],
- int *nmcadr);
-extern int post2obp_valid(post2obp_info_t *p2o);
-
-extern uint_t xf_physio_rdword(u_longlong_t physaddr);
-extern void xf_physio_wrword(u_longlong_t physaddr, uint_t value);
-extern ushort_t xf_physio_rdhword(u_longlong_t physaddr);
-extern void xf_physio_wrhword(u_longlong_t physaddr, ushort_t value);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_IDN_XF_H */
diff --git a/usr/src/uts/sun4u/starfire/sys/pda.h b/usr/src/uts/sun4u/starfire/sys/pda.h
deleted file mode 100644
index 0725f45347..0000000000
--- a/usr/src/uts/sun4u/starfire/sys/pda.h
+++ /dev/null
@@ -1,226 +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 1998-2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_PDA_H
-#define _SYS_PDA_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-
-/*
- * Contains definitions used for PDA (Post Descriptor Array) [post2obp]
- * support.
- *
- * XXX - These data structures is defined in SSP-land in:
- * src/post/export/xf_postif.h. It is not anticipated
- * that any future changes will be made to this data
- * structure so we'll allow this hack on this go around.
- */
-
-#define MAX_ABUSES 4 /* Address buses */
-#define MAX_DBUSES 2 /* Data buses */
-
-#define MAX_SYSBDS 16 /* no more than 16 system boards */
-#define MAX_PROCMODS 4 /* Per system board */
-#define MAX_PC 3 /* Per system board */
-#define MAX_XDB 4 /* Per system board */
-#define MAX_CIC 4 /* Per system board */
-#define MAX_MGROUPS 4 /* Per MC and system board */
-#define MAX_IOCS 2 /* Per system board */
-#define MAX_SLOTS_PER_IOC 4 /* Per ioc */
-
-typedef struct {
- ushort_t bda_board; /* BDAN 0|Anyred|mem|Board */
- ushort_t bda_proc; /* BDAN Processor 3:0 */
- ushort_t bda_pc; /* BDAN PC asic 2:0 */
- ushort_t bda_xdb; /* BDAN XDB asic 3:0 */
- ushort_t bda_cic; /* BDAN CIC asic 3:0 */
- ushort_t bda_ldpath; /* BDAN 0|0| ldpath [dbus] */
- ushort_t bda_ioc; /* BDAN 0|0| ioc 1:0 */
- ushort_t bda_ios[MAX_IOCS]; /* BDAN Scard 3:0 */
- ushort_t bda_mgroup; /* BDAN memory group 3:0 */
-} board_desc_t;
-
-typedef struct {
- ushort_t bada_proc [MAX_PROCMODS]; /* Extra status on procs */
- uchar_t bada_iom_type; /* I/O module type. */
- uchar_t bada_fill[3];
- ushort_t bada_ioc[MAX_IOCS]; /* Extra status on iocs */
-} board_auxdesc_t;
-
-/*
- * The three lsb of bada_proc holds the ecache size of that proc
- * module, as (log-base-2 - 19), so 1/2 MB is 0, 1 MB is 1, ...
- * 32 MB is 6. 7 is a bogus value.
- */
-#define BADA_PROC_GET_ECL2M19(bada_proc) ((bada_proc) & 0x7)
-
-typedef struct {
- uint32_t bmda_adr; /* MC ADR */
- uint32_t bmda_gab_bank_sel; /* MC gab bank sel reg */
- ushort_t bmda_bank_setup; /* MC gab bank setup reg */
- ushort_t bmda_filler;
- int32_t bmda_badpage[MAX_MGROUPS];
- /*
- * One bad page offset per
- * mgroup is allowed. No
- * bad page if < 0.
- */
-} board_mdesc_t;
-
-/*
- * BDA nibble status definitions:
- * These are ordered in terms of preserving interesting information
- * in POST displays where all configurations are displayed in a
- * single value. The highest value for a resource over all
- * configurations is shown.
- * Of course, this is just for help to engineers/technicians in
- * understanding what happened; for the most part, everything
- * except "GOOD" is just different flavors of "BAD".
- * Note the special macro SET_BDA_NBL_CRUNCH below which requires
- * that BDAN_CRUNCH be 0.
- */
-#define BDAN_CRUNCH 0x0 /* Unusable by implication */
-#define BDAN_UNDEFINED 0x1 /* Architecturally Missing */
-#define BDAN_MISS 0x2 /* Missing */
-#define BDAN_FAIL 0x3 /* Tested and failed */
-#define BDAN_BLACK 0x4 /* Blacklisted */
-#define BDAN_RED 0x5 /* Redlisted */
-#define BDAN_EXCLUDED 0x6 /* Board is not in this domain */
-#define BDAN_UNCONFIG 0x7 /* Good, but not in config. */
-#define BDAN_GOOD 0x8 /* Like it says. */
-#define BDAN_MASK 0xF
-
-
-/* Macros for accessing BDA nibbles */
-#define BDA_NBL(shrt, nibix) \
- (((shrt) >> ((nibix) << 2)) & BDAN_MASK)
-#define SET_BDA_NBL(shrt, nibix, val) \
-{ \
- shrt &= ~(BDAN_MASK << ((nibix) << 2)); \
- shrt |= (val) << ((nibix) << 2); \
-}
-
-/*
- * This exists to keep lint from complaining about statements with
- * null efect when we OR in a constant 0 in SET_BDA_NBL. It's a pain,
- * but it does save the code optimizer some work. ;-{
- */
-#define SET_BDA_NBL_CRUNCH(shrt, nibix) \
- (shrt &= ~(BDAN_MASK << ((nibix) << 2)))
-
-/* Definitions for nibbles in the bda_board element: */
-#define BDA_GEN_NBL 0 /* Overall state of the board */
-#define BDA_MC_NBL 1 /* State of the memory. */
-/*
- * BDAN_RED if anything red on board, or board is BDAN_EXCLUDED;
- * otherwise BDAN_GOOD
- */
-#define BDA_ANYRED_NBL 2
-/*
- * Macro BDA_PAGESHIFT hides Solaris page size to Starfire POST, as POST
- * assumes Solaris basic page size as 8K.
- * Note: Only BDA_PAGESHIFT is used, BDA_PAGESIZE is added for readability.
- */
-#define BDA_PAGESHIFT 13
-#define BDA_PAGESIZE (1<<BDA_PAGESHIFT)
-
-typedef struct { /* Memory Total Descriptor */
- int32_t Memt_NumPages; /* 8 KB each */
- int32_t Memt_NumChunks;
-} MemoryTotal_t;
-
-typedef struct { /* Chunk Descriptor */
- uint32_t Memc_StartAddress; /* In 8 KB pages */
- int32_t Memc_Size; /* In 8 KB pages */
-} MemChunk_t;
-
-
-#define P2OBP_MAGIC "XFPOST_2OBP"
-#define VAR_ARRAY_LEN 1
-
-typedef struct {
- char p2o_magic[12]; /* magic cookie = P2OBP_MAGIC */
- int32_t p2o_struct_version; /* equal to P2OBP_VERSION */
- uint32_t p2o_csum; /* sum(uint[]) */
- uint32_t p2o_post_time; /* creation time */
- uint32_t p2o_post_pid; /* pid of sequencer on SSP */
- uint32_t p2o_post_level; /* level at which hpost ran */
- short p2o_abus_mask; /* [3:0] = Valid PA buses */
- /* [5:4] = bus shuffle mode */
- short p2o_dbus_mask; /* Valid physdata buses */
- uint32_t p2o_intercon_freq; /* hz */
- uint32_t p2o_procssor_freq; /* hz */
- int32_t p2o_post_private;
- uint32_t p2o_flags; /* See P2OFLAG_XXX */
- uchar_t p2o_procint_intx_freq_ratio; /* 0 if not known */
- uchar_t p2o_fill_byte[3];
- uint_t p2o_filler[6]; /* for expansion */
- board_desc_t p2o_bdinfo[MAX_SYSBDS];
- board_mdesc_t p2o_bdminfo[MAX_SYSBDS];
- board_auxdesc_t p2o_auxinfo[MAX_SYSBDS];
- MemoryTotal_t p2o_memtotal;
- /*
- * Array of descriptors of existing memory.
- * Number of descriptors is given in memtotal.NumChunks.
- */
- MemChunk_t p2o_mchunks[VAR_ARRAY_LEN];
-} post2obp_info_t;
-
-#ifdef _KERNEL
-/*
- * Following definitions in support of DR.
- */
-typedef void *pda_handle_t;
-
-extern pda_handle_t pda_open();
-extern void pda_close(pda_handle_t ph);
-extern int pda_board_present(pda_handle_t ph, int boardnum);
-extern void *pda_get_board_info(pda_handle_t ph, int boardnum);
-extern uint_t pda_get_mem_size(pda_handle_t ph, int boardnum);
-extern void pda_mem_add_span(pda_handle_t ph,
- uint64_t basepa,
- uint64_t nbytes);
-extern void pda_mem_del_span(pda_handle_t ph,
- uint64_t basepa,
- uint64_t nbytes);
-extern void pda_mem_sync(pda_handle_t ph, int board, int unit);
-extern void pda_get_busmask(pda_handle_t ph,
- short *amask, short *dmask);
-extern int pda_is_valid(pda_handle_t ph);
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_PDA_H */
diff --git a/usr/src/uts/sun4u/starfire/unix/Makefile b/usr/src/uts/sun4u/starfire/unix/Makefile
deleted file mode 100644
index e474a9fe90..0000000000
--- a/usr/src/uts/sun4u/starfire/unix/Makefile
+++ /dev/null
@@ -1,189 +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 unix (and unix.o).
-#
-# sun4u starfire implementation architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../../..
-
-#
-# Define the module and object file sets.
-#
-UNIX = unix
-OBJECTS = $(SPECIAL_OBJS:%=$(OBJS_DIR)/%) \
- $(CORE_OBJS:%=$(OBJS_DIR)/%) \
- $(MACH_NOT_YET_KMODS:%=$(OBJS_DIR)/%)
-LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \
- $(CORE_OBJS:%.o=$(LINTS_DIR)/%.ln) \
- $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \
- $(LINTS_DIR)/vers.ln \
- $(LINTS_DIR)/modstubs.ln
-
-KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile
-KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%)
-KRTLD_O = $(OBJS_DIR)/krtld.o
-
-ROOTMODULE = $(ROOT_STARFIRE_KERN_DIR)/$(UNIX)
-UNIX32_LINK = $(ROOT_STARFIRE_KERN_DIR_32)/$(UNIX)
-UNIX_BIN = $(OBJS_DIR)/$(UNIX)
-
-LIBS = $(GENLIB) $(PLATLIB) $(CPULIB)
-
-GENUNIX = genunix
-GENUNIX_DIR = ../../$(GENUNIX)
-GENOPTS = -L $(GENUNIX_DIR)/$(OBJS_DIR) -l $(GENUNIX)
-
-CPU_DIR = .
-CPUOPTS = -L $(CPU_DIR)/$(OBJS_DIR) -l $(CPUNAME)
-
-PLAT_DIR = ../../platmod
-PLATOPTS = -L $(PLAT_DIR)/$(OBJS_DIR) -l $(PLATMOD)
-
-LIBOPTS = $(GENOPTS) $(PLATOPTS) $(CPUOPTS)
-
-CTFEXTRAOBJS = $(OBJS_DIR)/vers.o
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.starfire
-
-#
-# Define targets
-#
-ALL_TARGET = $(UNIX_BIN)
-LINT_TARGET = $(LINT_LIB)
-INSTALL_TARGET = $(UNIX_BIN) $(ROOTMODULE) $(UNIX32_LINK)
-
-#
-# This is UNIX_DIR. Use a short path.
-#
-UNIX_DIR = .
-
-#
-# Overrides
-#
-CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \
- $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \
- $(CPU_OBJ) $(CPULIB) \
- $(DTRACESTUBS_O) $(DTRACESTUBS)
-
-CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN)
-CLEANLINTFILES += $(LINT_LIB)
-
-#
-# lint pass one enforcement
-# Turn on doubleword alignment for 64 bit counter timer registers
-#
-CFLAGS += $(CCVERBOSE) -dalign
-
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-uninitialized
-CERRWARN += -_gcc=-Wno-char-subscripts
-CERRWARN += -_gcc=-Wno-unused-variable
-CERRWARN += -_gcc=-Wno-unused-function
-CERRWARN += -_gcc=-Wno-unused-label
-CERRWARN += -_gcc=-Wno-type-limits
-CERRWARN += -_gcc=-Wno-clobbered
-CERRWARN += -_gcc=-Wno-empty-body
-CERRWARN += -_gcc=-Wno-unused-value
-CERRWARN += -_gcc=-Wno-switch
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-lint: $(LINT_DEPS)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \
- $(DTRACESTUBS)
- $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \
- $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS)
- $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX)
- $(POST_PROCESS)
- $(CHK4UBINARY)
-
-$(UNIX32_LINK): $(ROOT_PSM_KERN_DIR_32) $(UNIX_BIN)
- -$(RM) $@; ln -s $(SUBDIR64)/$(UNIX) $@
-
-symcheck: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS)
- $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \
- $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS)
-
-$(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o
- $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o
-
-$(KRTLD_O): $(KRTLD_OBJECTS)
- $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS)
-
-#
-# CPU_OBJ now comprises of 2 object files which come from sun4 common
-# and from architecture dependent code. OBJS_DIR is prepended where
-# CPU_OBJ is defined to allow for building multiple CPU_OBJ's
-#
-$(CPULIB): $(CPU_OBJ)
- $(BUILD.SO) $(CPU_OBJ)
-
-#
-# The global lint target builds the kernel lint library (llib-lunix.ln)
-# which is equivalent to a lint of /unix.o. Then all kernel modules for
-# this architecture are linted against the kernel lint library.
-#
-# Note: lint errors in the kernel lint library will be repeated for
-# each module. It is important that the kernel lint library
-# be clean to keep the textual output to a reasonable level.
-#
-
-$(LINT_LIB): $(LINT_LIB_DIR) $(LINTS)
- @-$(ECHO) "\n$(UNIX): (library construction):"
- @$(LINT) -o $(UNIX) $(LINTFLAGS) $(LINTS)
- @$(MV) $(@F) $@
-
-lintlib: $(LINT_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/starfire/Makefile.targ
diff --git a/usr/src/uts/sun4u/sys/Makefile b/usr/src/uts/sun4u/sys/Makefile
index 8e73425995..612e09ecb8 100644
--- a/usr/src/uts/sun4u/sys/Makefile
+++ b/usr/src/uts/sun4u/sys/Makefile
@@ -20,6 +20,7 @@
#
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright 2019 Peter Tribble.
#
# uts/sun4u/sys/Makefile
#
@@ -90,7 +91,6 @@ HDRS= \
pte.h \
sbd_ioctl.h \
spitregs.h \
- starfire.h \
sysioerr.h \
sysiosbus.h \
todmostek.h \
diff --git a/usr/src/uts/sun4u/sys/machintreg.h b/usr/src/uts/sun4u/sys/machintreg.h
index 2ca8a37b46..1610f9148a 100644
--- a/usr/src/uts/sun4u/sys/machintreg.h
+++ b/usr/src/uts/sun4u/sys/machintreg.h
@@ -23,12 +23,13 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_MACHINTREG_H
#define _SYS_MACHINTREG_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -150,16 +151,6 @@ extern "C" {
#define INR_EN_SHIFT 31
#define INR_PID_SHIFT 26
#define INR_PID_MASK (IRSR_PID_MASK << (INR_PID_SHIFT))
-#ifdef _STARFIRE
-/*
- * Starfire interrupt group number is 7 bits
- * Starfire's IGN (inter group #) is not the same as upaid
- */
-#define IGN_SIZE 7 /* Interrupt Group Number bit size */
-#define UPAID_TO_IGN(upaid) ((((upaid & 0x3C) >> 1) | (upaid & 0x1)) | \
- (((upaid & 0x2) << 4) | \
- ((upaid & 0x40) ^ 0x40)))
-#else
/*
* IGN_SIZE can be defined in a platform's makefile. If it is not defined,
* use a default of 5.
@@ -168,7 +159,6 @@ extern "C" {
#define IGN_SIZE 5 /* Interrupt Group Number bit size */
#endif
#define UPAID_TO_IGN(upaid) (upaid)
-#endif /* _STARFIRE */
#define IR_CPU_CLEAR 0x4 /* clear pending register for cpu */
#define IR_MASK_OFFSET 0x4
diff --git a/usr/src/uts/sun4u/sys/machparam.h b/usr/src/uts/sun4u/sys/machparam.h
index b0130af21f..a205b21be1 100644
--- a/usr/src/uts/sun4u/sys/machparam.h
+++ b/usr/src/uts/sun4u/sys/machparam.h
@@ -19,6 +19,9 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2019 Peter Tribble.
+ */
+/*
* Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -54,28 +57,17 @@ extern "C" {
* The maximum possible number of UPA devices in a system.
* MAX_UPA maybe defined in a platform's makefile.
*/
-#ifdef _STARFIRE
-/*
- * We have a 7 bit id space for UPA devices in Xfire
- */
-#define MAX_UPA 128
-#else
#ifndef MAX_UPA
#define MAX_UPA 32
#endif
-#endif /* _STARFIRE */
/*
* Maximum cpuid value that we support. NCPU can be defined in a platform's
* makefile.
*/
-#if (defined(_STARFIRE) && !defined(lint))
-#define NCPU 64
-#else
#ifndef NCPU
#define NCPU 32
#endif
-#endif /* _STARFIRE && !lint */
#if (NCPU <= 1)
#define NCPU_LOG2 0
@@ -323,11 +315,7 @@ extern "C" {
#define PFN_TO_BUSTYPE(pfn) (((pfn) >> 19) & 0x1FF)
#define IO_BUSTYPE(pfn) ((PFN_TO_BUSTYPE(pfn) & 0x100) >> 8)
-#ifdef _STARFIRE
-#define PFN_TO_UPAID(pfn) BUSTYPE_TO_UPAID(PFN_TO_BUSTYPE(pfn))
-#else
#define PFN_TO_UPAID(pfn) (((pfn) >> 20) & 0x1F)
-#endif /* _STARFIRE */
/*
* Defines used for the ptl1_panic parameter, which is passed to the
diff --git a/usr/src/uts/sun4u/sys/machthread.h b/usr/src/uts/sun4u/sys/machthread.h
index 7b844bea44..d72dc7c91a 100644
--- a/usr/src/uts/sun4u/sys/machthread.h
+++ b/usr/src/uts/sun4u/sys/machthread.h
@@ -22,12 +22,13 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_MACHTHREAD_H
#define _SYS_MACHTHREAD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/asi.h>
#include <sys/sun4asi.h>
#include <sys/machasi.h>
@@ -51,31 +52,7 @@ extern "C" {
sll out, 16, out; \
srl out, 16, out;
-#ifdef _STARFIRE
-/*
- * CPU_INDEX(r, scr)
- * Returns cpu id in r.
- * On Starfire, this is read from the Port Controller's Port ID
- * register in local space.
- *
- * Need to load the 64 bit address of the PC's PortID reg
- * using only one register. Kludge the 41 bits address constant to
- * be 32bits by shifting it 12 bits to the right first.
- */
-#define LOCAL_PC_PORTID_ADDR_SRL12 0x1FFF4000
-#define PC_PORT_ID 0xD0
-
-#define CPU_INDEX(r, scr) \
- rdpr %pstate, scr; \
- andn scr, PSTATE_IE | PSTATE_AM, r; \
- wrpr r, 0, %pstate; \
- set LOCAL_PC_PORTID_ADDR_SRL12, r; \
- sllx r, 12, r; \
- or r, PC_PORT_ID, r; \
- lduwa [r]ASI_IO, r; \
- wrpr scr, 0, %pstate
-
-#elif defined(_OPL)
+#ifdef _OPL
/*
* For OPL platform, we get CPU_INDEX from ASI_EIDR.
*/
@@ -84,7 +61,7 @@ extern "C" {
and r, 0xfff, r
-#else /* _STARFIRE */
+#else /* _OPL */
/*
* UPA supports up to 32 devices while Safari supports up to
@@ -112,7 +89,7 @@ extern "C" {
srlx r, 17, r; \
and r, CPU_MASK, r
-#endif /* _STARFIRE */
+#endif /* _OPL */
/*
* Given a cpu id extract the appropriate word
diff --git a/usr/src/uts/sun4u/sys/pci/pci_cb.h b/usr/src/uts/sun4u/sys/pci/pci_cb.h
index 6907fc3b4f..8584e5cf31 100644
--- a/usr/src/uts/sun4u/sys/pci/pci_cb.h
+++ b/usr/src/uts/sun4u/sys/pci/pci_cb.h
@@ -23,12 +23,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_PCI_CB_H
#define _SYS_PCI_CB_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -78,10 +79,6 @@ struct cb {
uint64_t cb_obsta_pa; /* 1st-attached-side sta reg base PA */
uint64_t *cb_imr_save;
-
-#ifdef _STARFIRE
- caddr_t cb_ittrans_cookie; /* intr tgt translation */
-#endif
};
#define CB_INO_TO_MONDO(cb_p, ino) ((cb_p)->cb_ign << PCI_INO_BITS | (ino))
diff --git a/usr/src/uts/sun4u/sys/pci/pci_ib.h b/usr/src/uts/sun4u/sys/pci/pci_ib.h
index c85f972a8a..b034043ced 100644
--- a/usr/src/uts/sun4u/sys/pci/pci_ib.h
+++ b/usr/src/uts/sun4u/sys/pci/pci_ib.h
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_PCI_IB_H
#define _SYS_PCI_IB_H
@@ -178,17 +181,6 @@ struct ib_ino_info {
#define IB_IS_OBIO_INO(ino) (ino & 0x20)
-#ifdef _STARFIRE
-/*
- * returns a uniq ino per interrupt mapping register
- * For on board devices, inos are not shared. But for plugin devices,
- * return the 1st ino of the 4 that are sharing the same mapping register.
- */
-#define IB_GET_MAPREG_INO(ino) \
- ((volatile uint64_t *)(uintptr_t)((ino & 0x20) ? \
- ino : ((ino >> 2) << 2)))
-#endif /* _STARFIRE */
-
#define IB_IGN_TO_MONDO(ign, ino) (((ign) << PCI_INO_BITS) | (ino))
#define IB_INO_TO_MONDO(ib_p, ino) IB_IGN_TO_MONDO((ib_p)->ib_ign, ino)
diff --git a/usr/src/uts/sun4u/sys/pci/pci_regs.h b/usr/src/uts/sun4u/sys/pci/pci_regs.h
index 74aa47a6aa..724cdb3cfb 100644
--- a/usr/src/uts/sun4u/sys/pci/pci_regs.h
+++ b/usr/src/uts/sun4u/sys/pci/pci_regs.h
@@ -22,12 +22,13 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_PCI_REGS_H
#define _SYS_PCI_REGS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -65,8 +66,6 @@ extern "C" {
/*
* (psycho and schizo) control register bit definitions:
*/
-#define COMMON_CB_CONTROL_STATUS_IGN 0x0007c00000000000ull
-#define COMMON_CB_CONTROL_STATUS_IGN_SHIFT 46
#define COMMON_CB_CONTROL_STATUS_APCKEN 0x0000000000000008ull
#define COMMON_CB_CONTROL_STATUS_APERR 0x0000000000000004ull
#define COMMON_CB_CONTROL_STATUS_IAP 0x0000000000000002ull
diff --git a/usr/src/uts/sun4u/sys/prom_plat.h b/usr/src/uts/sun4u/sys/prom_plat.h
index 66ea55b2c1..39616187ca 100644
--- a/usr/src/uts/sun4u/sys/prom_plat.h
+++ b/usr/src/uts/sun4u/sys/prom_plat.h
@@ -22,12 +22,13 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_PROM_PLAT_H
#define _SYS_PROM_PLAT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/feature_tests.h>
#include <sys/cpuvar.h>
@@ -262,16 +263,6 @@ extern int prom_starcat_iosram_write(uint32_t key, uint32_t offset,
uint32_t len, caddr_t buf);
/*
- * Starfire-specific routines
- */
-extern int prom_starfire_add_brd(uint_t cpuid);
-extern int prom_starfire_rm_brd(uint_t brdnum);
-extern void prom_starfire_add_cpu(uint_t cpuid);
-extern void prom_starfire_rm_cpu(uint_t cpuid);
-extern int prom_starfire_move_cpu0(uint_t cpuid);
-extern void prom_starfire_init_console(uint_t cpuid);
-
-/*
* OPL-specific routines
*/
extern void prom_opl_get_tod(time_t *time, int64_t *stickval);
diff --git a/usr/src/uts/sun4u/sys/sbd_ioctl.h b/usr/src/uts/sun4u/sys/sbd_ioctl.h
index 16efc10bd7..e8c8ca1e2b 100644
--- a/usr/src/uts/sun4u/sys/sbd_ioctl.h
+++ b/usr/src/uts/sun4u/sys/sbd_ioctl.h
@@ -22,6 +22,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SBD_IOCTL_H
#define _SBD_IOCTL_H
@@ -505,34 +508,6 @@ typedef struct {
#define ESTC_NWSWITCH 1037
/* Cannot unconfigure I/O board: network switch failed */
-/* Starfire error codes */
-
-#define ESTF_NONE 2000 /* No error */
-#define ESTF_GETPROP 2001 /* Cannot read property value */
-#define ESTF_GETPROPLEN 2002 /* Cannot determine property length */
-#define ESTF_BNUM 2003 /* Invalid board number */
-#define ESTF_CONFIGBUSY 2004
- /* Cannot proceed; Board is configured or busy */
-#define ESTF_NOCPUID 2005 /* No CPU specified for connect */
-#define ESTF_PROBE 2006 /* Firmware probe failed */
-#define ESTF_DEPROBE 2007 /* Firmware deprobe failed */
-#define ESTF_MOVESIGB 2008 /* Firmware move-cpu0 failed */
-#define ESTF_JUGGLE 2009 /* Cannot move SIGB assignment */
-#define ESTF_HASSIGB 2010
- /* Cannot disconnect CPU; SIGB is currently assigned */
-#define ESTF_SUPPORT 2011 /* Operation not supported */
-#define ESTF_DRVFAIL 2012 /* Device driver failure */
-#define ESTF_SETCPUVAL 2013
- /* Must specify a CPU on the given board */
-#define ESTF_NODEV 2014 /* No such device */
-#define ESTF_INTERBOARD 2015
- /* Memory configured with inter-board interleaving */
-#define ESTF_UNKPTCMD 2016 /* Unrecognized platform command */
-#define ESTF_NOTID 2017 /* drmach parameter is not a valid ID */
-#define ESTF_INAPPROP 2018
- /* drmach parameter is inappropriate for operation */
-#define ESTF_INTERNAL 2019 /* Unexpected internal condition */
-
/* Daktari error codes */
#define EDAK_NONE 3000 /* no error */
diff --git a/usr/src/uts/sun4u/sys/spitregs.h b/usr/src/uts/sun4u/sys/spitregs.h
index 492990c720..1c246f1446 100644
--- a/usr/src/uts/sun4u/sys/spitregs.h
+++ b/usr/src/uts/sun4u/sys/spitregs.h
@@ -23,12 +23,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_SPITREGS_H
#define _SYS_SPITREGS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -37,24 +38,11 @@ extern "C" {
* This file is cpu dependent.
*/
-#ifdef _STARFIRE
-/*
- * Starfire's cpu upaids are not the same
- * as cpuids.
- * XXX - our obp took the liberty of
- * converting cpu upaids into cpuids when
- * presenting it as upa-portid property.
- */
-#define CPUID_TO_UPAID(upaid) (((upaid & 0x3C) << 1) | \
- ((upaid & 0x40) >> 4) | \
- (upaid &0x3))
-#else
/*
* The mid is the same as the cpu id.
* We might want to change this later
*/
#define CPUID_TO_UPAID(cpuid) (cpuid)
-#endif /* _STARFIRE */
/*
* LSU Control Register
diff --git a/usr/src/uts/sun4u/sys/starfire.h b/usr/src/uts/sun4u/sys/starfire.h
deleted file mode 100644
index 038f0b3c0e..0000000000
--- a/usr/src/uts/sun4u/sys/starfire.h
+++ /dev/null
@@ -1,248 +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) 1996-2000 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef _STARFIRE_H
-#define _STARFIRE_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* I/O space definitions */
-#define STARFIRE_IO_BASE 0x10000000000ULL
-
-/* UPA Port Space (UPS) definitions */
-#define STARFIRE_UPS_MID_SHIFT 33 /* MID is 7 bits */
-#define STARFIRE_UPS_BRD_SHIFT 36
-#define STARFIRE_UPS_BUS_SHIFT 6
-
-/* Starfire Interconnect Space (IS) definitions */
-#define STARFIRE_IS_MC_BASE 0x10e80000000ULL /* MC Register Space */
-
-
-/* Port Specific Interconnect Space (PSI) */
-#define STARFIRE_PSI_BASE \
- 0x100f8000000ULL /* put mid in [39:33] */
-#define STARFIRE_PSI_PCREG_OFF \
- 0x4000000ULL /* PSI offset for PC regs */
-#define STARFIRE_BRD_TO_PSI(board) \
- (STARFIRE_PSI_BASE | \
- (((uint64_t)board) << STARFIRE_UPS_BRD_SHIFT))
-
-
-/* Starfire BootBus Space (BS) definitions */
-#define STARFIRE_PSI_BS_BASE \
- STARFIRE_PSI_BASE /* BS at start of PSI Space */
-
-#define STARFIRE_UPAID2PSI_BS(upaid) \
- (STARFIRE_PSI_BS_BASE | \
- ((u_longlong_t)STARFIRE_UPAID2HWMID(upaid) << \
- STARFIRE_UPS_MID_SHIFT))
-
-#define STARFIRE_DEV2UPAID(b, p, i) \
- ((((i) & 0x1) << 6) | \
- (((b) & 0xf) << 2) | \
- ((p) & 0x3))
-
-/* Starfire Port Controller Register offsets */
-#define STARFIRE_PC_CONF 0x000000UL /* Configuration Reg */
-#define STARFIRE_PC_COMP_ID 0x000010UL /* Component ID Reg */
-#define STARFIRE_PC_BUS_CONF 0x000020UL /* Bus Configuration Reg */
-#define STARFIRE_PC_TO_HOLD_CONF 0x000030UL /* Timeout/Hold Config Reg */
-#define STARFIRE_PC_CIC_WRITE_DATA 0x000040UL /* CIC Write Data Reg */
-#define STARFIRE_PC_FORCE_PARITY_ERR 0x000050UL /* Force Parity Err Reg */
-#define STARFIRE_PC_ERR_0_MASK 0x000060UL /* Err 0 Mask Reg */
-#define STARFIRE_PC_ERR_1_MASK 0x000070UL /* Err 1 Mask Reg */
-#define STARFIRE_PC_ERR_0 0x000080UL /* Err 0 Reg */
-#define STARFIRE_PC_ERR_1 0x000090UL /* Err 1 Reg */
-#define STARFIRE_PC_ERR_DATA_SRC 0x0000a0UL /* Err Data Src Reg */
-#define STARFIRE_PC_ERR_DATA_LOW 0x0000b0UL /* Err Data Lower Reg */
-#define STARFIRE_PC_ERR_DATA_HI 0x0000c0UL /* Err Data Upper Reg */
-#define STARFIRE_PC_PORT_ID 0x0000d0UL
-#define STARFIRE_PC_PERF_COUNT_0 0x0000e0UL
-#define STARFIRE_PC_PERF_COUNT_1 0x0000f0UL
-#define STARFIRE_PC_PERF_COUNT_CNTRL 0x000100UL
-#define STARFIRE_PC_BLOCK 0x0001c0UL /* 512 Byte scr area */
-#define STARFIRE_PC_INT_MAP 0x000200UL /* 32 regs 00.0200-00.03f0 */
-#define STARFIRE_PC_MADR 0x000400UL /* 16 regs 00.0400-00.04f0 */
-
-/* Starfire PC definitions/macros */
-#define STARFIRE_PC_MADR_BOARD_SHIFT 4
-#define STARFIRE_PC_MADR_ADDR(bb, rb, p) \
- (STARFIRE_BRD_TO_PSI(bb) | \
- ((uint64_t)(p) << STARFIRE_UPS_MID_SHIFT) | \
- ((uint64_t)(rb) << STARFIRE_PC_MADR_BOARD_SHIFT) | \
- STARFIRE_PSI_PCREG_OFF | \
- STARFIRE_PC_MADR)
-
-/* Starfire BB (BootBus) definitions/macros */
-#define STARFIRE_BB_SYSRESET_CNTRL 0x800000ULL
-#define STARFIRE_BB_PAUSE_FLUSH 0x800016ULL
-
-#define STARFIRE_BB_PC_PAUSE(i) ((uchar_t)(1 << (i)))
-#define STARFIRE_BB_PC_FLUSH(i) ((uchar_t)(1 << ((i)+2)))
-#define STARFIRE_BB_PC_IDLE(i) ((uchar_t)(1 << ((i)+4)))
-
-#define STARFIRE_BB_SYSRESET(i) ((uchar_t)(1 << (i)))
-
-#define STARFIRE_BB_PC_ADDR(bb, p, io) \
- (STARFIRE_UPAID2PSI_BS(STARFIRE_DEV2UPAID((bb), (p), (io))) | \
- STARFIRE_BB_PAUSE_FLUSH)
-#define STARFIRE_BB_RESET_ADDR(bb, p) \
- (STARFIRE_UPAID2PSI_BS(STARFIRE_DEV2UPAID((bb), (p), 0)) | \
- STARFIRE_BB_SYSRESET_CNTRL)
-
-/* Starfire Memory Controller Register offsets */
-#define STARFIRE_MC_ASR 0x000400U /* Addr Select Reg */
-#define STARFIRE_MC_DIMMTYPE 0x00c800U /* DIMM Type Code Reg */
-#define STARFIRE_MC_IDLE 0x00cc00U /* Idle MC Reg */
-
-/* Starfire MC definitions/macros */
-#define STARFIRE_MC_MEM_PRESENT_MASK 0x80000000U
-#define STARFIRE_MC_MEM_BASEADDR_MASK 0x7fff0000U
-#define STARFIRE_MC_IDLE_MASK 0x00008000U
-#define STARFIRE_MC_MASK_MASK 0x00007f00U
-#define STARFIRE_MC_DIMMSIZE_MASK 0x0000001fU
-#define STARFIRE_MC_INTERLEAVE_MASK 0x00000001U
-#define STARFIRE_MC_MASK_SHIFT 18
-#define STARFIRE_MC_BASE_SHIFT 10
-#define STARFIRE_MC_ADDR_HIBITS 0x1fe00000000ULL
-#define STARFIRE_MC_ASR_ADDR(reg) ((reg) | (uint64_t)STARFIRE_MC_ASR)
-#define STARFIRE_MC_IDLE_ADDR(reg) ((reg) | (uint64_t)STARFIRE_MC_IDLE)
-#define STARFIRE_MC_DIMMTYPE_ADDR(reg) ((reg) | (uint64_t)STARFIRE_MC_DIMMTYPE)
-#define STARFIRE_MC_ASR_ADDR_BOARD(b) \
- (((uint64_t)(b) << STARFIRE_UPS_BRD_SHIFT) | \
- STARFIRE_IS_MC_BASE | \
- (uint64_t)STARFIRE_MC_ASR)
-
-/*
- * Memory boards on Starfire are aligned on 8GB
- * boundaries, i.e. the physical address space
- * is not physically contiguous.
- */
-#define STARFIRE_MC_MEMBOARD_SHIFT 33
-#define STARFIRE_MC_MEMBOARD_ALIGNMENT \
- (UINT64_C(1) << STARFIRE_MC_MEMBOARD_SHIFT)
-
-/*
- * Starfire has a special regspec for the "reg" property of the
- * mem-unit node since this node is homegrown.
- */
-struct sf_memunit_regspec {
- uint_t regspec_addr_hi;
- uint_t regspec_addr_lo;
- uint_t regspec_size_hi;
- uint_t regspec_size_lo;
-};
-
-/*
- * Conversion macros
- */
-
-/*
- * Starfire hardware version of the upaid (commonly known as
- * HWMID) is different from the software version (also known as upaid).
- * HW version BBBBIPp == SW version IBBBBPp
- */
-#define STARFIRE_UPAID2HWMID(upaid) (((upaid & 0x3C) << 1) | \
- ((upaid & 0x40) >> 4) | (upaid & 0x3))
-
-
-/* Xfire UPA ID to UPA Port Specific Space */
-#define STARFIRE_UPAID2UPS(upaid) \
- (((u_longlong_t)STARFIRE_UPAID2HWMID(upaid) << \
- STARFIRE_UPS_MID_SHIFT) | STARFIRE_IO_BASE)
-
-/*
- * Macro to convert our 7 bits HW MID to 7 bits SW MID
- * That is "BBBBIPp" to "IBBBBPp".
- */
-#define STARFIRE_HWMID2SWMID(mid) ((mid & 0x3) | ((mid & 0x78) >> 1) | \
- ((mid & 0x4) << 4))
-
-/*
- * Macro to convert our 7 bits UPAid to Sun's 5 bit HW Interrupt
- * group number required in some hardware registers (sysios).
- * That is "IBBBBPp" to "BBBBp", where "BBBB" is the board number,
- * "IP" is the PC id and "p" is the port number.
- */
-#define STARFIRE_UPAID2HWIGN(upaid) \
- (((upaid & 0x3C) >> 1) | (upaid & 0x1))
-
-/*
- * Macro to convert our UPAid to a 7 bit Starfire version of the
- * interrupt group number. This so-called IGN is part of
- * the interrupt vector number read by the CPU serving this interrupt.
- * Thanks to the warp minds of our hardware guys, it is in this
- * convoluted weird format. Note that the interrupt vector number is
- * then used to index into the interrupt dispatch table to get its
- * interrupt handler.
- * Convert "IBBBBPp" to "XPBBBBp" where "BBBB" is the 4bit board #,
- * "IP" is the 2 bit PC id, "p" is the port # and "X" is ~I.
- */
-#define STARFIRE_UPAID2IGN(upaid) (STARFIRE_UPAID2HWIGN(upaid) | \
- ((upaid & 0x2) << 4) | \
- ((upaid & 0x40) ^ 0x40))
-
-/*
- * Starfire platform specific routines currently only defined
- * in starfire.c and referenced by DR.
- */
-extern int plat_max_boards();
-extern int plat_max_cpu_units_per_board();
-extern int plat_max_mem_units_per_board();
-extern int plat_max_io_units_per_board();
-
-/*
- * Starfire platform specific interrupt translation routines
- */
-extern void pc_ittrans_init(int, caddr_t *);
-extern void pc_ittrans_uninit(caddr_t);
-extern int pc_translate_tgtid(caddr_t, int, volatile uint64_t *);
-extern void pc_ittrans_cleanup(caddr_t, volatile uint64_t *);
-
-/*
- * Maximum number of system boards supported in a Starfire.
- */
-#define STARFIRE_MAX_BOARDS 16
-
-/*
- * We reserve some "fake" DMV values for Starfire IDN. These are treated
- * as hardware interrupt numbers, but they don't correspond to an actual UPA
- * port; they can thus be allocated as "well-known" numbers for IDN purposes.
- */
-#define STARFIRE_DMV_EXTRA 4
-#define STARFIRE_DMV_HWINT (MAX_UPA+STARFIRE_DMV_EXTRA)
-#define STARFIRE_DMV_IDN_BASE (MAX_UPA)
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _STARFIRE_H */
diff --git a/usr/src/uts/sun4u/sys/sysiosbus.h b/usr/src/uts/sun4u/sys/sysiosbus.h
index d72c1c0aa3..05029e9fb8 100644
--- a/usr/src/uts/sun4u/sys/sysiosbus.h
+++ b/usr/src/uts/sun4u/sys/sysiosbus.h
@@ -23,12 +23,13 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
#ifndef _SYS_SYSIOSBUS_H
#define _SYS_SYSIOSBUS_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifndef _ASM
#include <sys/avintr.h>
#include <sys/vmem.h>
@@ -319,9 +320,6 @@ struct sbus_soft_state {
pfn_t sbus_io_hi_pfn;
struct iophyslist *sbus_io_ranges;
int intr_mapping_ign; /* placeholder for the IGN */
-#ifdef _STARFIRE
- caddr_t ittrans_cookie; /* starfire intr target translation */
-#endif /* _STARFIRE */
#ifdef DEBUG
kmutex_t iomemlock; /* Memory usage lock (debug only) */
struct io_mem_list *iomem; /* Memory usage list (debug only) */
diff --git a/usr/src/uts/sun4u/todstarfire/Makefile b/usr/src/uts/sun4u/todstarfire/Makefile
deleted file mode 100644
index cbaee6f875..0000000000
--- a/usr/src/uts/sun4u/todstarfire/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/todmostek/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 todstarfire
-# kernel module.
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = todstarfire
-OBJECTS = $(TODSTARFIRE_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(TODSTARFIRE_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_PSM_TOD_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sun4u/Makefile.sun4u
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-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)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sun4u/Makefile.targ
diff --git a/usr/src/uts/sun4v/os/mach_mp_startup.c b/usr/src/uts/sun4v/os/mach_mp_startup.c
index 06a6f59279..a0c3928a2f 100644
--- a/usr/src/uts/sun4v/os/mach_mp_startup.c
+++ b/usr/src/uts/sun4v/os/mach_mp_startup.c
@@ -23,6 +23,10 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright 2019 Peter Tribble.
+ */
+
#include <sys/machsystm.h>
#include <sys/cpu_module.h>
#include <sys/dtrace.h>
@@ -70,11 +74,6 @@ init_cpu_info(struct cpu *cp)
(void) strcpy(pi->pi_fputypes, "sparcv9");
/*
- * StarFire requires the signature block stuff setup here
- */
- CPU_SGN_MAPIN(cpuid);
-
- /*
* cpu0 is always initialized at boot time, but it can be initialized
* again if it is dynamically removed and then re-added. We check if
* we are booting by verifying cpu_list. During boot, cpu0 is already