changeset 21384:1108cc2db905

Merge pull request #476 from hadfl/upstream_merge/2019052901 Upstream merge/2019052901
author Tobias Oetiker <tobi@oetiker.ch>
date Fri, 31 May 2019 14:32:40 +0200
parents 1bc1ea62c4c3 (current diff) 96f983818898 (diff)
children b91f8e5b7b85 c98678c112b6 2145b03e5008
files usr/src/cmd/cvcd/Makefile usr/src/cmd/cvcd/cvc.xml usr/src/cmd/cvcd/sparc/Makefile usr/src/cmd/cvcd/sparc/sun4u/Makefile usr/src/cmd/cvcd/sparc/sun4u/starcat/Makefile usr/src/cmd/cvcd/sparc/sun4u/starcat/cvcd.c usr/src/cmd/cvcd/svc-cvcd usr/src/cmd/fm/eversholt/files/sparc/SUNW,Sun-Fire-15000/Makefile usr/src/cmd/fm/eversholt/files/sparc/SUNW,Sun-Fire-15000/SUNW,Sun-Fire-15000.esc usr/src/cmd/mdb/intel/amd64/libmlsvc/Makefile usr/src/cmd/mdb/intel/ia32/libmlsvc/Makefile usr/src/cmd/svc/profile/platform_SUNW,Sun-Fire-15000.xml usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Makefile usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Sun-Fire-15000-hc-topology.xml usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/Makefile usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/Makefile usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/iob_platform.c usr/src/lib/libprtdiag_psr/sparc/starcat/Makefile usr/src/lib/libprtdiag_psr/sparc/starcat/common/starcat.c usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb usr/src/lib/smbclnt/libfksmbfs/common/llib-lfksmbfs usr/src/man/man1m/cvcd.1m usr/src/man/man7d/cvc.7d usr/src/man/man7d/cvcredir.7d usr/src/man/man7d/schpc.7d usr/src/pkg/manifests/SUNWcvc.mf usr/src/pkg/manifests/SUNWdrcr.mf usr/src/psm/promif/ieee1275/sun4u/prom_starcat.c usr/src/uts/sun4u/io/pci/pci_axq.c usr/src/uts/sun4u/io/todstarcat.c usr/src/uts/sun4u/opl/sys/sckm_io.h usr/src/uts/sun4u/starcat/Makefile usr/src/uts/sun4u/starcat/Makefile.files usr/src/uts/sun4u/starcat/Makefile.rules usr/src/uts/sun4u/starcat/Makefile.starcat usr/src/uts/sun4u/starcat/Makefile.targ usr/src/uts/sun4u/starcat/axq/Makefile usr/src/uts/sun4u/starcat/cheetah/Makefile usr/src/uts/sun4u/starcat/cheetahplus/Makefile usr/src/uts/sun4u/starcat/cvc/Makefile usr/src/uts/sun4u/starcat/cvcredir/Makefile usr/src/uts/sun4u/starcat/dman/Makefile usr/src/uts/sun4u/starcat/dr/Makefile usr/src/uts/sun4u/starcat/drmach/Makefile usr/src/uts/sun4u/starcat/fcgp2/Makefile usr/src/uts/sun4u/starcat/genassym/Makefile usr/src/uts/sun4u/starcat/gptwo_pci/Makefile usr/src/uts/sun4u/starcat/io/axq.c usr/src/uts/sun4u/starcat/io/cvc.c usr/src/uts/sun4u/starcat/io/cvc.conf usr/src/uts/sun4u/starcat/io/cvcredir.c usr/src/uts/sun4u/starcat/io/cvcredir.conf usr/src/uts/sun4u/starcat/io/dman.c usr/src/uts/sun4u/starcat/io/dman.conf usr/src/uts/sun4u/starcat/io/dman_domain.c usr/src/uts/sun4u/starcat/io/dr.conf usr/src/uts/sun4u/starcat/io/drmach.c usr/src/uts/sun4u/starcat/io/fcgp2.c usr/src/uts/sun4u/starcat/io/gptwo_pci.c usr/src/uts/sun4u/starcat/io/iosram.c usr/src/uts/sun4u/starcat/io/mboxsc.c usr/src/uts/sun4u/starcat/io/sc_gptwocfg.c usr/src/uts/sun4u/starcat/io/schpc.c usr/src/uts/sun4u/starcat/io/schpc.conf usr/src/uts/sun4u/starcat/io/sckmdrv.c usr/src/uts/sun4u/starcat/io/sckmdrv.conf usr/src/uts/sun4u/starcat/io/scosmb.c usr/src/uts/sun4u/starcat/iosram/Makefile usr/src/uts/sun4u/starcat/mboxsc/Makefile usr/src/uts/sun4u/starcat/ml/drmach.il.cpp usr/src/uts/sun4u/starcat/ml/drmach_asm.s usr/src/uts/sun4u/starcat/ml/starcat_asm.s usr/src/uts/sun4u/starcat/os/starcat.c usr/src/uts/sun4u/starcat/platmod/Makefile usr/src/uts/sun4u/starcat/sc_gptwocfg/Makefile usr/src/uts/sun4u/starcat/schpc/Makefile usr/src/uts/sun4u/starcat/sckmdrv/Makefile usr/src/uts/sun4u/starcat/scosmb/Makefile usr/src/uts/sun4u/starcat/sys/Makefile usr/src/uts/sun4u/starcat/sys/axq.h usr/src/uts/sun4u/starcat/sys/dman.h usr/src/uts/sun4u/starcat/sys/domaind.h usr/src/uts/sun4u/starcat/sys/dr_mbx.h usr/src/uts/sun4u/starcat/sys/drmach.h usr/src/uts/sun4u/starcat/sys/gptwo_pci.h usr/src/uts/sun4u/starcat/sys/iosramio.h usr/src/uts/sun4u/starcat/sys/iosramreg.h usr/src/uts/sun4u/starcat/sys/iosramvar.h usr/src/uts/sun4u/starcat/sys/mboxsc.h usr/src/uts/sun4u/starcat/sys/mboxsc_impl.h usr/src/uts/sun4u/starcat/sys/post/scat_asicbrd_types.h usr/src/uts/sun4u/starcat/sys/post/scat_const.h usr/src/uts/sun4u/starcat/sys/post/scat_dcd.h usr/src/uts/sun4u/starcat/sys/post/scat_pa_space.h usr/src/uts/sun4u/starcat/sys/sc_cvc.h usr/src/uts/sun4u/starcat/sys/sc_cvcio.h usr/src/uts/sun4u/starcat/sys/sc_gptwocfg.h usr/src/uts/sun4u/starcat/sys/schpc.h usr/src/uts/sun4u/starcat/sys/schpc_msg.h usr/src/uts/sun4u/starcat/sys/sckm_io.h usr/src/uts/sun4u/starcat/sys/sckm_msg.h usr/src/uts/sun4u/starcat/sys/starcat.h usr/src/uts/sun4u/starcat/unix/Makefile usr/src/uts/sun4u/sys/pci/pci_axq.h usr/src/uts/sun4u/todstarcat/Makefile
diffstat 218 files changed, 4723 insertions(+), 54137 deletions(-) [+]
line wrap: on
line diff
--- a/exception_lists/packaging	Wed May 29 18:07:38 2019 +0200
+++ b/exception_lists/packaging	Fri May 31 14:32:40 2019 +0200
@@ -344,7 +344,6 @@
 var/svc/manifest/platform/sun4v					i386
 etc/svc/profile/platform_sun4v.xml				i386
 etc/svc/profile/platform_SUNW,SPARC-Enterprise.xml		i386
-etc/svc/profile/platform_SUNW,Sun-Fire-15000.xml		i386
 etc/svc/profile/platform_SUNW,Sun-Fire-880.xml			i386
 etc/svc/profile/platform_SUNW,Sun-Fire-V890.xml			i386
 etc/svc/profile/platform_SUNW,Sun-Fire.xml			i386
@@ -596,6 +595,8 @@
 usr/lib/mdb/proc/libfksmbsrv.so
 usr/lib/mdb/proc/amd64/libfksmbsrv.so		i386
 usr/lib/mdb/proc/sparcv9/libfksmbsrv.so		sparc
+usr/lib/mdb/proc/amd64/libmlsvc.so		i386
+usr/lib/mdb/proc/sparcv9/libmlsvc.so		sparc
 usr/lib/smbsrv/bind-helper
 usr/lib/smbsrv/fksmbd
 usr/lib/smbsrv/libfksmbsrv.so
--- a/usr/src/boot/sys/boot/common/module.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/boot/sys/boot/common/module.c	Fri May 31 14:32:40 2019 +0200
@@ -54,42 +54,43 @@
 
 struct moduledir {
 	char	*d_path;	/* path of modules directory */
-	u_char	*d_hints;	/* content of linker.hints file */
+	uchar_t	*d_hints;	/* content of linker.hints file */
 	int	d_hintsz;	/* size of hints data */
 	int	d_flags;
 	STAILQ_ENTRY(moduledir) d_link;
 };
 
-static int			file_load(char *filename, vm_offset_t dest, struct preloaded_file **result);
-static int			file_load_dependencies(struct preloaded_file *base_mod);
-static char *			file_search(const char *name, const char **extlist);
-static struct kernel_module *	file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo);
-static int			file_havepath(const char *name);
-static char			*mod_searchmodule(char *name, struct mod_depend *verinfo);
-static void			file_insert_tail(struct preloaded_file *mp);
-struct file_metadata*		metadata_next(struct file_metadata *base_mp, int type);
-static void			moduledir_readhints(struct moduledir *mdp);
-static void			moduledir_rebuild(void);
+static int file_load(char *, vm_offset_t, struct preloaded_file **);
+static int file_load_dependencies(struct preloaded_file *);
+static char *file_search(const char *, const char **);
+static struct kernel_module *file_findmodule(struct preloaded_file *, char *,
+    struct mod_depend *);
+static int file_havepath(const char *);
+static char *mod_searchmodule(char *, struct mod_depend *);
+static void file_insert_tail(struct preloaded_file *);
+struct file_metadata *metadata_next(struct file_metadata *, int);
+static void moduledir_readhints(struct moduledir *);
+static void moduledir_rebuild(void);
 
 /* load address should be tweaked by first module loaded (kernel) */
-static vm_offset_t	loadaddr = 0;
+static vm_offset_t loadaddr = 0;
 
 #if defined(LOADER_FDT_SUPPORT)
-static const char	*default_searchpath =
-    "/boot/kernel;/boot/modules;/boot/dtb";
+static const char *default_searchpath = "/boot/kernel;/boot/modules;/boot/dtb";
 #else
-static const char	*default_searchpath ="/platform/i86pc";
+static const char *default_searchpath = "/platform/i86pc";
 #endif
 
-static STAILQ_HEAD(, moduledir) moduledir_list = STAILQ_HEAD_INITIALIZER(moduledir_list);
+static STAILQ_HEAD(, moduledir) moduledir_list =
+    STAILQ_HEAD_INITIALIZER(moduledir_list);
 
 struct preloaded_file *preloaded_files = NULL;
 
 static const char *kld_ext_list[] = {
-    ".ko",
-    "",
-    ".debug",
-    NULL
+	".ko",
+	"",
+	".debug",
+	NULL
 };
 
 
@@ -110,149 +111,110 @@
 static int
 command_load(int argc, char *argv[])
 {
-    char	*typestr;
-    int		dofile, dokld, ch, error;
+	char *typestr;
+	int dofile, dokld, ch, error;
+
+	dokld = dofile = 0;
+	optind = 1;
+	optreset = 1;
+	typestr = NULL;
+	if (argc == 1) {
+		command_errmsg = "no filename specified";
+		return (CMD_CRIT);
+	}
+	while ((ch = getopt(argc, argv, "kt:")) != -1) {
+		switch (ch) {
+		case 'k':
+			dokld = 1;
+			break;
+		case 't':
+			typestr = optarg;
+			dofile = 1;
+			break;
+		case '?':
+		default:
+			/* getopt has already reported an error */
+			return (CMD_OK);
+		}
+	}
+	argv += (optind - 1);
+	argc -= (optind - 1);
+
+	printf("Loading %s...\n", argv[1]);
+	/*
+	 * Request to load a raw file?
+	 */
+	if (dofile) {
+		struct preloaded_file *fp;
 
-    dokld = dofile = 0;
-    optind = 1;
-    optreset = 1;
-    typestr = NULL;
-    if (argc == 1) {
-	command_errmsg = "no filename specified";
-	return (CMD_CRIT);
-    }
-    while ((ch = getopt(argc, argv, "kt:")) != -1) {
-	switch(ch) {
-	case 'k':
-	    dokld = 1;
-	    break;
-	case 't':
-	    typestr = optarg;
-	    dofile = 1;
-	    break;
-	case '?':
-	default:
-	    /* getopt has already reported an error */
-	    return (CMD_OK);
+		if ((typestr == NULL) || (*typestr == 0)) {
+			command_errmsg = "invalid load type";
+			return (CMD_CRIT);
+		}
+
+		if (file_findfile(argv[1], typestr) != NULL) {
+			snprintf(command_errbuf, sizeof (command_errbuf),
+			    "warning: file '%s' already loaded", argv[1]);
+			return (CMD_WARN);
+		}
+
+		fp = file_loadraw(argv[1], typestr, argc - 2, argv + 2, 1);
+		if (fp != NULL)
+			return (CMD_OK);
+
+		/* Failing to load mfs_root is never going to end well! */
+		if (strcmp("mfs_root", typestr) == 0)
+			return (CMD_FATAL);
+
+		return (CMD_ERROR);
 	}
-    }
-    argv += (optind - 1);
-    argc -= (optind - 1);
+	/*
+	 * Do we have explicit KLD load ?
+	 */
+	if (dokld || file_havepath(argv[1])) {
+		error = mod_loadkld(argv[1], argc - 2, argv + 2);
+		if (error == EEXIST) {
+			snprintf(command_errbuf, sizeof (command_errbuf),
+			    "warning: KLD '%s' already loaded", argv[1]);
+			return (CMD_WARN);
+		}
 
-    printf("Loading %s...\n", argv[1]);
-    /*
-     * Request to load a raw file?
-     */
-    if (dofile) {
-	if ((typestr == NULL) || (*typestr == 0)) {
-	    command_errmsg = "invalid load type";
-	    return (CMD_CRIT);
+		return (error == 0 ? CMD_OK : CMD_CRIT);
 	}
-
-	if (file_findfile(argv[1], typestr) != NULL) {
+	/*
+	 * Looks like a request for a module.
+	 */
+	error = mod_load(argv[1], NULL, argc - 2, argv + 2);
+	if (error == EEXIST) {
 		snprintf(command_errbuf, sizeof (command_errbuf),
-		    "warning: file '%s' already loaded", argv[1]);
+		    "warning: module '%s' already loaded", argv[1]);
 		return (CMD_WARN);
 	}
 
-	if (file_loadraw(argv[1], typestr, argc - 2, argv + 2, 1) != NULL)
-		return (CMD_OK);
-
-	/* Failing to load mfs_root is never going to end well! */
-	if (strcmp("mfs_root", typestr) == 0)
-		return (CMD_FATAL);
-
-	return (CMD_ERROR);
-    }
-    /*
-     * Do we have explicit KLD load ?
-     */
-    if (dokld || file_havepath(argv[1])) {
-	error = mod_loadkld(argv[1], argc - 2, argv + 2);
-	if (error == EEXIST) {
-	    snprintf(command_errbuf, sizeof (command_errbuf),
-		"warning: KLD '%s' already loaded", argv[1]);
-	    return (CMD_WARN);
-	}
-
 	return (error == 0 ? CMD_OK : CMD_CRIT);
-    }
-    /*
-     * Looks like a request for a module.
-     */
-    error = mod_load(argv[1], NULL, argc - 2, argv + 2);
-    if (error == EEXIST) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "warning: module '%s' already loaded", argv[1]);
-	return (CMD_WARN);
-    }
-
-    return (error == 0 ? CMD_OK : CMD_CRIT);
 }
 
-#ifdef __FreeBSD__
-COMMAND_SET(load_geli, "load_geli", "load a geli key", command_load_geli);
-
-static int
-command_load_geli(int argc, char *argv[])
-{
-    char	typestr[80];
-    char	*cp;
-    int		ch, num;
-
-    if (argc < 3) {
-	    command_errmsg = "usage is [-n key#] <prov> <file>";
-	    return(CMD_ERROR);
-    }
-
-    num = 0;
-    optind = 1;
-    optreset = 1;
-    while ((ch = getopt(argc, argv, "n:")) != -1) {
-	switch(ch) {
-	case 'n':
-	    num = strtol(optarg, &cp, 0);
-	    if (cp == optarg) {
-		    snprintf(command_errbuf, sizeof (command_errbuf),
-			"bad key index '%s'", optarg);
-		    return(CMD_ERROR);
-	    }
-	    break;
-	case '?':
-	default:
-	    /* getopt has already reported an error */
-	    return(CMD_OK);
-	}
-    }
-    argv += (optind - 1);
-    argc -= (optind - 1);
-    sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
-    return (file_loadraw(argv[2], typestr, 0, NULL, 1) ? CMD_OK : CMD_ERROR);
-}
-#endif /* __FreeBSD__ */
-
 void
 unload(void)
 {
-    struct preloaded_file *fp;
+	struct preloaded_file *fp;
 
-    while (preloaded_files != NULL) {
-	fp = preloaded_files;
-	preloaded_files = preloaded_files->f_next;
-	file_discard(fp);
-    }
-    loadaddr = 0;
-    unsetenv("kernelname");
+	while (preloaded_files != NULL) {
+		fp = preloaded_files;
+		preloaded_files = preloaded_files->f_next;
+		file_discard(fp);
+	}
+	loadaddr = 0;
+	unsetenv("kernelname");
 }
 
 COMMAND_SET(unload, "unload", "unload all modules", command_unload);
 
 static int
-command_unload(int argc __attribute((unused)),
-    char *argv[] __attribute((unused)))
+command_unload(int argc __unused, char *argv[] __unused)
 {
-    unload();
-    return(CMD_OK);
+	unload();
+	return (CMD_OK);
 }
 
 COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
@@ -260,85 +222,91 @@
 static int
 command_lsmod(int argc, char *argv[])
 {
-    struct preloaded_file	*fp;
-    struct kernel_module	*mp;
-    struct file_metadata	*md;
-    char			lbuf[80];
-    int				ch, verbose, hash, ret = 0;
+	struct preloaded_file *fp;
+	struct kernel_module *mp;
+	struct file_metadata *md;
+	char lbuf[80];
+	int ch, verbose, hash, ret = 0;
 
-    verbose = 0;
-    hash = 0;
-    optind = 1;
-    optreset = 1;
-    while ((ch = getopt(argc, argv, "vs")) != -1) {
-	switch(ch) {
-	case 'v':
-	    verbose = 1;
-	    break;
-	case 's':
-	    hash = 1;
-	    break;
-	case '?':
-	default:
-	    /* getopt has already reported an error */
-	    return(CMD_OK);
+	verbose = 0;
+	hash = 0;
+	optind = 1;
+	optreset = 1;
+	while ((ch = getopt(argc, argv, "vs")) != -1) {
+		switch (ch) {
+		case 'v':
+			verbose = 1;
+			break;
+		case 's':
+			hash = 1;
+			break;
+		case '?':
+		default:
+			/* getopt has already reported an error */
+			return (CMD_OK);
+		}
 	}
-    }
 
-    pager_open();
-    for (fp = preloaded_files; fp; fp = fp->f_next) {
-	sprintf(lbuf, " %p: ", (void *) fp->f_addr);
-	pager_output(lbuf);
-	pager_output(fp->f_name);
-	sprintf(lbuf, " (%s, 0x%lx)\n", fp->f_type, (long)fp->f_size);
-	if (pager_output(lbuf))
-	    break;
-	if (fp->f_args != NULL) {
-	    pager_output("    args: ");
-	    pager_output(fp->f_args);
-	    if (pager_output("\n"))
-		break;
-	    if (strcmp(fp->f_type, "hash") == 0) {
-		pager_output("    contents: ");
-		strncpy(lbuf, PTOV(fp->f_addr), fp->f_size);
+	pager_open();
+	for (fp = preloaded_files; fp; fp = fp->f_next) {
+		sprintf(lbuf, " %p: ", (void *) fp->f_addr);
+		pager_output(lbuf);
+		pager_output(fp->f_name);
+		sprintf(lbuf, " (%s, 0x%lx)\n", fp->f_type, (long)fp->f_size);
 		if (pager_output(lbuf))
 			break;
-	    }
-	}
+		if (fp->f_args != NULL) {
+			pager_output("    args: ");
+			pager_output(fp->f_args);
+			if (pager_output("\n"))
+				break;
+			if (strcmp(fp->f_type, "hash") == 0) {
+				pager_output("    contents: ");
+				strncpy(lbuf, PTOV(fp->f_addr), fp->f_size);
+				if (pager_output(lbuf))
+					break;
+			}
+		}
 
-	if (hash == 1) {
-		void *ptr = PTOV(fp->f_addr);
+		if (hash == 1) {
+			void *ptr = PTOV(fp->f_addr);
+
+			pager_output("  hash: ");
+			sha1(ptr, fp->f_size, (uint8_t *)lbuf);
+			for (int i = 0; i < SHA1_DIGEST_LENGTH; i++)
+				printf("%02x", (int)(lbuf[i] & 0xff));
+			if (pager_output("\n"))
+				break;
+		}
 
-		pager_output("  hash: ");
-		sha1(ptr, fp->f_size, (uint8_t *)lbuf);
-		for (int i = 0; i < SHA1_DIGEST_LENGTH; i++)
-			printf("%02x", (int)(lbuf[i] & 0xff));
-		if (pager_output("\n"))
+		if (fp->f_modules) {
+			pager_output("  modules: ");
+			for (mp = fp->f_modules; mp; mp = mp->m_next) {
+				sprintf(lbuf, "%s.%d ", mp->m_name,
+				    mp->m_version);
+				pager_output(lbuf);
+			}
+			if (pager_output("\n"))
+				break;
+		}
+		if (verbose) {
+			/*
+			 * XXX could add some formatting smarts here to
+			 * display some better
+			 */
+			for (md = fp->f_metadata; md != NULL;
+			    md = md->md_next) {
+				sprintf(lbuf, "      0x%04x, 0x%lx\n",
+				    md->md_type, (long)md->md_size);
+				if ((ret = pager_output(lbuf)))
+					break;
+			}
+		}
+		if (ret != 0)
 			break;
 	}
-
-	if (fp->f_modules) {
-	    pager_output("  modules: ");
-	    for (mp = fp->f_modules; mp; mp = mp->m_next) {
-		sprintf(lbuf, "%s.%d ", mp->m_name, mp->m_version);
-		pager_output(lbuf);
-	    }
-	    if (pager_output("\n"))
-		break;
-	}
-	if (verbose) {
-	    /* XXX could add some formatting smarts here to display some better */
-	    for (md = fp->f_metadata; md != NULL; md = md->md_next) {
-		sprintf(lbuf, "      0x%04x, 0x%lx\n", md->md_type, (long) md->md_size);
-		if ((ret = pager_output(lbuf)))
-		    break;
-	    }
-	}
-	if (ret)
-	    break;
-    }
-    pager_close();
-    return(CMD_OK);
+	pager_close();
+	return (CMD_OK);
 }
 
 /*
@@ -347,89 +315,93 @@
 int
 file_load(char *filename, vm_offset_t dest, struct preloaded_file **result)
 {
-    static int last_file_format = 0;
-    struct preloaded_file *fp;
-    int error;
-    int i;
+	static int last_file_format = 0;
+	struct preloaded_file *fp;
+	int error;
+	int i;
 
-    if (preloaded_files == NULL)
-	last_file_format = 0;
+	if (preloaded_files == NULL)
+		last_file_format = 0;
 
-    if (archsw.arch_loadaddr != NULL)
-	dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest);
+	if (archsw.arch_loadaddr != NULL)
+		dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest);
 
-    error = EFTYPE;
-    for (i = last_file_format, fp = NULL;
-	file_formats[i] && fp == NULL; i++) {
-	error = (file_formats[i]->l_load)(filename, dest, &fp);
-	if (error == 0) {
-	    fp->f_loader = last_file_format = i; /* remember the loader */
-	    *result = fp;
-	    break;
-	} else if (last_file_format == i && i != 0) {
-	    /* Restart from the beginning */
-	    i = -1;
-	    last_file_format = 0;
-	    fp = NULL;
-	    continue;
+	error = EFTYPE;
+	for (i = last_file_format, fp = NULL;
+	    file_formats[i] && fp == NULL; i++) {
+		error = (file_formats[i]->l_load)(filename, dest, &fp);
+		if (error == 0) {
+			/* remember the loader */
+			fp->f_loader = last_file_format = i;
+			*result = fp;
+			break;
+		} else if (last_file_format == i && i != 0) {
+			/* Restart from the beginning */
+			i = -1;
+			last_file_format = 0;
+			fp = NULL;
+			continue;
+		}
+		if (error == EFTYPE)
+			continue;	/* Unknown to this handler? */
+		if (error) {
+			snprintf(command_errbuf, sizeof (command_errbuf),
+			    "can't load file '%s': %s", filename,
+			    strerror(error));
+			break;
+		}
 	}
-	if (error == EFTYPE)
-	    continue;		/* Unknown to this handler? */
-	if (error) {
-	    snprintf(command_errbuf, sizeof (command_errbuf),
-		"can't load file '%s': %s", filename, strerror(error));
-	    break;
-	}
-    }
-    return (error);
+	return (error);
 }
 
 static int
 file_load_dependencies(struct preloaded_file *base_file)
 {
-    struct file_metadata *md;
-    struct preloaded_file *fp;
-    struct mod_depend *verinfo;
-    struct kernel_module *mp;
-    char *dmodname;
-    int error;
+	struct file_metadata *md;
+	struct preloaded_file *fp;
+	struct mod_depend *verinfo;
+	struct kernel_module *mp;
+	char *dmodname;
+	int error;
 
-    md = file_findmetadata(base_file, MODINFOMD_DEPLIST);
-    if (md == NULL)
-	return (0);
-    error = 0;
-    do {
-	verinfo = (struct mod_depend*)md->md_data;
-	dmodname = (char *)(verinfo + 1);
-	if (file_findmodule(NULL, dmodname, verinfo) == NULL) {
-	    printf("loading required module '%s'\n", dmodname);
-	    error = mod_load(dmodname, verinfo, 0, NULL);
-	    if (error)
-		break;
-	    /*
-	     * If module loaded via kld name which isn't listed
-	     * in the linker.hints file, we should check if it have
-	     * required version.
-	     */
-	    mp = file_findmodule(NULL, dmodname, verinfo);
-	    if (mp == NULL) {
-		snprintf(command_errbuf, sizeof (command_errbuf),
-		    "module '%s' exists but with wrong version", dmodname);
-		error = ENOENT;
-		break;
-	    }
+	md = file_findmetadata(base_file, MODINFOMD_DEPLIST);
+	if (md == NULL)
+		return (0);
+	error = 0;
+	do {
+		verinfo = (struct mod_depend *)md->md_data;
+		dmodname = (char *)(verinfo + 1);
+		if (file_findmodule(NULL, dmodname, verinfo) == NULL) {
+			printf("loading required module '%s'\n", dmodname);
+			error = mod_load(dmodname, verinfo, 0, NULL);
+			if (error)
+				break;
+			/*
+			 * If module loaded via kld name which isn't listed
+			 * in the linker.hints file, we should check if it have
+			 * required version.
+			 */
+			mp = file_findmodule(NULL, dmodname, verinfo);
+			if (mp == NULL) {
+				snprintf(command_errbuf,
+				    sizeof (command_errbuf),
+				    "module '%s' exists but with wrong version",
+				    dmodname);
+				error = ENOENT;
+				break;
+			}
+		}
+		md = metadata_next(md, MODINFOMD_DEPLIST);
+	} while (md);
+	if (!error)
+		return (0);
+	/* Load failed; discard everything */
+	while (base_file != NULL) {
+		fp = base_file;
+		base_file = base_file->f_next;
+		file_discard(fp);
 	}
-	md = metadata_next(md, MODINFOMD_DEPLIST);
-    } while (md);
-    if (!error)
-	return (0);
-    /* Load failed; discard everything */
-    while (base_file != NULL) {
-        fp = base_file;
-        base_file = base_file->f_next;
-        file_discard(fp);
-    }
-    return (error);
+	return (error);
 }
 
 /*
@@ -642,105 +614,108 @@
 struct preloaded_file *
 file_loadraw(const char *fname, char *type, int argc, char **argv, int insert)
 {
-    struct preloaded_file	*fp;
-    char			*name;
-    int				fd, got;
-    vm_offset_t			laddr;
-    struct stat			st;
+	struct preloaded_file *fp;
+	char *name;
+	int fd, got;
+	vm_offset_t laddr;
+	struct stat st;
 
-    /* We can't load first */
-    if ((file_findfile(NULL, NULL)) == NULL) {
-	command_errmsg = "can't load file before kernel";
-	return(NULL);
-    }
+	/* We can't load first */
+	if ((file_findfile(NULL, NULL)) == NULL) {
+		command_errmsg = "can't load file before kernel";
+		return (NULL);
+	}
 
-    /* locate the file on the load path */
-    name = file_search(fname, NULL);
-    if (name == NULL) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "can't find '%s'", fname);
-	return(NULL);
-    }
+	/* locate the file on the load path */
+	name = file_search(fname, NULL);
+	if (name == NULL) {
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "can't find '%s'", fname);
+		return (NULL);
+	}
 
-    if ((fd = open(name, O_RDONLY)) < 0) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "can't open '%s': %s", name, strerror(errno));
-	free(name);
-	return(NULL);
-    }
-    if (fstat(fd, &st) < 0) {
-	close(fd);
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "stat error '%s': %s", name, strerror(errno));
-	free(name);
-	return(NULL);
-    }
+	if ((fd = open(name, O_RDONLY)) < 0) {
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "can't open '%s': %s", name, strerror(errno));
+		free(name);
+		return (NULL);
+	}
+	if (fstat(fd, &st) < 0) {
+		close(fd);
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "stat error '%s': %s", name, strerror(errno));
+		free(name);
+		return (NULL);
+	}
 
-    if (archsw.arch_loadaddr != NULL)
-	loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
-    if (loadaddr == 0) {
-	close(fd);
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "no memory to load %s", name);
-	free(name);
-	return(NULL);
-    }
+	if (archsw.arch_loadaddr != NULL)
+		loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
+	if (loadaddr == 0) {
+		close(fd);
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "no memory to load %s", name);
+		free(name);
+		return (NULL);
+	}
 
-    laddr = loadaddr;
-    for (;;) {
-	/* read in 4k chunks; size is not really important */
-	got = archsw.arch_readin(fd, laddr, 4096);
-	if (got == 0)				/* end of file */
-	    break;
-	if (got < 0) {				/* error */
-	    snprintf(command_errbuf, sizeof (command_errbuf),
-		"error reading '%s': %s", name, strerror(errno));
-	    free(name);
-	    close(fd);
-	    if (archsw.arch_free_loadaddr != NULL)
-		archsw.arch_free_loadaddr(loadaddr,
-		    (uint64_t)(roundup2(st.st_size, PAGE_SIZE) >> 12));
-	    return(NULL);
+	laddr = loadaddr;
+	for (;;) {
+		/* read in 4k chunks; size is not really important */
+		got = archsw.arch_readin(fd, laddr, 4096);
+		if (got == 0)			/* end of file */
+			break;
+		if (got < 0) {			/* error */
+			snprintf(command_errbuf, sizeof (command_errbuf),
+			    "error reading '%s': %s", name, strerror(errno));
+			free(name);
+			close(fd);
+			if (archsw.arch_free_loadaddr != NULL) {
+				archsw.arch_free_loadaddr(loadaddr,
+				    (uint64_t)
+				    (roundup2(st.st_size, PAGE_SIZE) >> 12));
+			}
+			return (NULL);
+		}
+		laddr += got;
 	}
-	laddr += got;
-    }
 
-    /* Looks OK so far; create & populate control structure */
-    fp = file_alloc();
-    if (fp == NULL) {
-	if (archsw.arch_free_loadaddr != NULL)
-	    archsw.arch_free_loadaddr(loadaddr,
-		(uint64_t)(roundup2(st.st_size, PAGE_SIZE) >> 12));
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "no memory to load %s", name);
-	free(name);
+	/* Looks OK so far; create & populate control structure */
+	fp = file_alloc();
+	if (fp == NULL) {
+		if (archsw.arch_free_loadaddr != NULL)
+			archsw.arch_free_loadaddr(loadaddr,
+			    (uint64_t)(roundup2(st.st_size, PAGE_SIZE) >> 12));
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "no memory to load %s", name);
+		free(name);
+		close(fd);
+		return (NULL);
+	}
+
+	fp->f_name = name;
+	fp->f_args = unargv(argc, argv);
+	fp->f_type = strdup(type);
+	fp->f_metadata = NULL;
+	fp->f_loader = -1;
+	fp->f_addr = loadaddr;
+	fp->f_size = laddr - loadaddr;
+
+	if (fp->f_type == NULL ||
+	    (argc != 0 && fp->f_args == NULL)) {
+		close(fd);
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "no memory to load %s", name);
+		file_discard(fp);
+		return (NULL);
+	}
+	/* recognise space consumption */
+	loadaddr = laddr;
+
+	/* Add to the list of loaded files */
+	if (insert != 0)
+		file_insert_tail(fp);
 	close(fd);
-	return (NULL);
-    }
-    fp->f_name = name;
-    fp->f_args = unargv(argc, argv);
-    fp->f_type = strdup(type);
-    fp->f_metadata = NULL;
-    fp->f_loader = -1;
-    fp->f_addr = loadaddr;
-    fp->f_size = laddr - loadaddr;
-
-    if (fp->f_type == NULL ||
-        (argc != 0 && fp->f_args == NULL)) {
-	close(fd);
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "no memory to load %s", name);
-	file_discard(fp);
-	return (NULL);
-    }
-    /* recognise space consumption */
-    loadaddr = laddr;
-
-    /* Add to the list of loaded files */
-    if (insert != 0)
-	file_insert_tail(fp);
-    close(fd);
-    return(fp);
+	return (fp);
 }
 
 /*
@@ -751,33 +726,34 @@
 int
 mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[])
 {
-    struct kernel_module	*mp;
-    int				err;
-    char			*filename;
+	struct kernel_module *mp;
+	int err;
+	char *filename;
 
-    if (file_havepath(modname)) {
-	printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname);
-	return (mod_loadkld(modname, argc, argv));
-    }
-    /* see if module is already loaded */
-    mp = file_findmodule(NULL, modname, verinfo);
-    if (mp) {
-	free(mp->m_args);
-	mp->m_args = unargv(argc, argv);
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "warning: module '%s' already loaded", mp->m_name);
-	return (0);
-    }
-    /* locate file with the module on the search path */
-    filename = mod_searchmodule(modname, verinfo);
-    if (filename == NULL) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "can't find '%s'", modname);
-	return (ENOENT);
-    }
-    err = mod_loadkld(filename, argc, argv);
-    free(filename);
-    return (err);
+	if (file_havepath(modname)) {
+		printf("Warning: mod_load() called instead of mod_loadkld() "
+		    "for module '%s'\n", modname);
+		return (mod_loadkld(modname, argc, argv));
+	}
+	/* see if module is already loaded */
+	mp = file_findmodule(NULL, modname, verinfo);
+	if (mp != NULL) {
+		free(mp->m_args);
+		mp->m_args = unargv(argc, argv);
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "warning: module '%s' already loaded", mp->m_name);
+		return (0);
+	}
+	/* locate file with the module on the search path */
+	filename = mod_searchmodule(modname, verinfo);
+	if (filename == NULL) {
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "can't find '%s'", modname);
+		return (ENOENT);
+	}
+	err = mod_loadkld(filename, argc, argv);
+	free(filename);
+	return (err);
 }
 
 /*
@@ -787,57 +763,57 @@
 int
 mod_loadkld(const char *kldname, int argc, char *argv[])
 {
-    struct preloaded_file	*fp, *last_file;
-    int				err;
-    char			*filename;
+	struct preloaded_file *fp, *last_file;
+	int err;
+	char *filename;
 
-    /*
-     * Get fully qualified KLD name
-     */
-    filename = file_search(kldname, kld_ext_list);
-    if (filename == NULL) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "can't find '%s'", kldname);
-	return (ENOENT);
-    }
-    /*
-     * Check if KLD already loaded
-     */
-    fp = file_findfile(filename, NULL);
-    if (fp) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "warning: KLD '%s' already loaded", filename);
+	/*
+	 * Get fully qualified KLD name
+	 */
+	filename = file_search(kldname, kld_ext_list);
+	if (filename == NULL) {
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "can't find '%s'", kldname);
+		return (ENOENT);
+	}
+	/*
+	 * Check if KLD already loaded
+	 */
+	fp = file_findfile(filename, NULL);
+	if (fp != NULL) {
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "warning: KLD '%s' already loaded", filename);
+		free(filename);
+		return (0);
+	}
+	for (last_file = preloaded_files;
+	    last_file != NULL && last_file->f_next != NULL;
+	    last_file = last_file->f_next)
+		;
+
+	do {
+		err = file_load(filename, loadaddr, &fp);
+		if (err)
+			break;
+		fp->f_args = unargv(argc, argv);
+		loadaddr = fp->f_addr + fp->f_size;
+		file_insert_tail(fp);	/* Add to the list of loaded files */
+		if (file_load_dependencies(fp) != 0) {
+			err = ENOENT;
+			last_file->f_next = NULL;
+			loadaddr = last_file->f_addr + last_file->f_size;
+			fp = NULL;
+			break;
+		}
+	} while (0);
+	if (err == EFTYPE) {
+		snprintf(command_errbuf, sizeof (command_errbuf),
+		    "don't know how to load module '%s'", filename);
+	}
+	if (err)
+		file_discard(fp);
 	free(filename);
-	return (0);
-    }
-    for (last_file = preloaded_files;
-	 last_file != NULL && last_file->f_next != NULL;
-	 last_file = last_file->f_next)
-	;
-
-    do {
-	err = file_load(filename, loadaddr, &fp);
-	if (err)
-	    break;
-	fp->f_args = unargv(argc, argv);
-	loadaddr = fp->f_addr + fp->f_size;
-	file_insert_tail(fp);		/* Add to the list of loaded files */
-	if (file_load_dependencies(fp) != 0) {
-	    err = ENOENT;
-	    last_file->f_next = NULL;
-	    loadaddr = last_file->f_addr + last_file->f_size;
-	    fp = NULL;
-	    break;
-	}
-    } while(0);
-    if (err == EFTYPE) {
-	snprintf(command_errbuf, sizeof (command_errbuf),
-	    "don't know how to load module '%s'", filename);
-    }
-    if (err)
-	file_discard(fp);
-    free(filename);
-    return (err);
+	return (err);
 }
 
 /*
@@ -847,14 +823,14 @@
 struct preloaded_file *
 file_findfile(const char *name, const char *type)
 {
-    struct preloaded_file *fp;
+	struct preloaded_file *fp;
 
-    for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
-	if (((name == NULL) || !strcmp(name, fp->f_name)) &&
-	    ((type == NULL) || !strcmp(type, fp->f_type)))
-	    break;
-    }
-    return (fp);
+	for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
+		if (((name == NULL) || strcmp(name, fp->f_name) == 0) &&
+		    ((type == NULL) || strcmp(type, fp->f_type) == 0))
+			break;
+	}
+	return (fp);
 }
 
 /*
@@ -863,37 +839,37 @@
  */
 struct kernel_module *
 file_findmodule(struct preloaded_file *fp, char *modname,
-	struct mod_depend *verinfo)
+    struct mod_depend *verinfo)
 {
-    struct kernel_module *mp, *best;
-    int bestver, mver;
+	struct kernel_module *mp, *best;
+	int bestver, mver;
 
-    if (fp == NULL) {
-	for (fp = preloaded_files; fp; fp = fp->f_next) {
-	    mp = file_findmodule(fp, modname, verinfo);
-	    if (mp)
-		return (mp);
+	if (fp == NULL) {
+		for (fp = preloaded_files; fp; fp = fp->f_next) {
+			mp = file_findmodule(fp, modname, verinfo);
+			if (mp != NULL)
+				return (mp);
+		}
+		return (NULL);
 	}
-	return (NULL);
-    }
-    best = NULL;
-    bestver = 0;
-    for (mp = fp->f_modules; mp; mp = mp->m_next) {
-        if (strcmp(modname, mp->m_name) == 0) {
-	    if (verinfo == NULL)
-		return (mp);
-	    mver = mp->m_version;
-	    if (mver == verinfo->md_ver_preferred)
-		return (mp);
-	    if (mver >= verinfo->md_ver_minimum &&
-		mver <= verinfo->md_ver_maximum &&
-		mver > bestver) {
-		best = mp;
-		bestver = mver;
-	    }
+	best = NULL;
+	bestver = 0;
+	for (mp = fp->f_modules; mp; mp = mp->m_next) {
+		if (strcmp(modname, mp->m_name) == 0) {
+			if (verinfo == NULL)
+				return (mp);
+			mver = mp->m_version;
+			if (mver == verinfo->md_ver_preferred)
+				return (mp);
+			if (mver >= verinfo->md_ver_minimum &&
+			    mver <= verinfo->md_ver_maximum &&
+			    mver > bestver) {
+				best = mp;
+				bestver = mver;
+			}
+		}
 	}
-    }
-    return (best);
+	return (best);
 }
 /*
  * Make a copy of (size) bytes of data from (p), and associate them as
@@ -921,23 +897,24 @@
 struct file_metadata *
 file_findmetadata(struct preloaded_file *fp, int type)
 {
-    struct file_metadata *md;
+	struct file_metadata *md;
 
-    for (md = fp->f_metadata; md != NULL; md = md->md_next)
-	if (md->md_type == type)
-	    break;
-    return(md);
+	for (md = fp->f_metadata; md != NULL; md = md->md_next)
+		if (md->md_type == type)
+			break;
+	return (md);
 }
 
 struct file_metadata *
 metadata_next(struct file_metadata *md, int type)
 {
-    if (md == NULL)
-	return (NULL);
-    while((md = md->md_next) != NULL)
-	if (md->md_type == type)
-	    break;
-    return (md);
+
+	if (md == NULL)
+		return (NULL);
+	while ((md = md->md_next) != NULL)
+		if (md->md_type == type)
+			break;
+	return (md);
 }
 
 static const char *emptyextlist[] = { "", NULL };
@@ -946,38 +923,39 @@
  * Check if the given file is in place and return full path to it.
  */
 static char *
-file_lookup(const char *path, const char *name, int namelen, const char **extlist)
+file_lookup(const char *path, const char *name, int namelen,
+    const char **extlist)
 {
-    struct stat	st;
-    char	*result, *cp;
-    const char **cpp;
-    int		pathlen, extlen, len;
+	struct stat st;
+	char *result, *cp;
+	const char **cpp;
+	int pathlen, extlen, len;
 
-    pathlen = strlen(path);
-    extlen = 0;
-    if (extlist == NULL)
-	extlist = emptyextlist;
-    for (cpp = extlist; *cpp; cpp++) {
-	len = strlen(*cpp);
-	if (len > extlen)
-	    extlen = len;
-    }
-    result = malloc(pathlen + namelen + extlen + 2);
-    if (result == NULL)
+	pathlen = strlen(path);
+	extlen = 0;
+	if (extlist == NULL)
+		extlist = emptyextlist;
+	for (cpp = extlist; *cpp; cpp++) {
+		len = strlen(*cpp);
+		if (len > extlen)
+			extlen = len;
+	}
+	result = malloc(pathlen + namelen + extlen + 2);
+	if (result == NULL)
+		return (NULL);
+	bcopy(path, result, pathlen);
+	if (pathlen > 0 && result[pathlen - 1] != '/')
+		result[pathlen++] = '/';
+	cp = result + pathlen;
+	bcopy(name, cp, namelen);
+	cp += namelen;
+	for (cpp = extlist; *cpp; cpp++) {
+		strcpy(cp, *cpp);
+		if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
+			return (result);
+	}
+	free(result);
 	return (NULL);
-    bcopy(path, result, pathlen);
-    if (pathlen > 0 && result[pathlen - 1] != '/')
-	result[pathlen++] = '/';
-    cp = result + pathlen;
-    bcopy(name, cp, namelen);
-    cp += namelen;
-    for (cpp = extlist; *cpp; cpp++) {
-	strcpy(cp, *cpp);
-	if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
-	    return result;
-    }
-    free(result);
-    return NULL;
 }
 
 /*
@@ -986,10 +964,10 @@
 static int
 file_havepath(const char *name)
 {
-    const char		*cp;
+	const char *cp;
 
-    archsw.arch_getdev(NULL, name, &cp);
-    return (cp != name || strchr(name, '/') != NULL);
+	archsw.arch_getdev(NULL, name, &cp);
+	return (cp != name || strchr(name, '/') != NULL);
 }
 
 /*
@@ -1005,104 +983,108 @@
 static char *
 file_search(const char *name, const char **extlist)
 {
-    struct moduledir	*mdp;
-    struct stat		sb;
-    char		*result;
-    int			namelen;
+	struct moduledir *mdp;
+	struct stat sb;
+	char *result;
+	int namelen;
 
-    /* Don't look for nothing */
-    if (name == NULL)
-	return(NULL);
+	/* Don't look for nothing */
+	if (name == NULL)
+		return (NULL);
 
-    if (*name == 0)
-	return(strdup(name));
+	if (*name == '\0')
+		return (strdup(name));
 
-    if (file_havepath(name)) {
-	/* Qualified, so just see if it exists */
-	if (stat(name, &sb) == 0)
-	    return(strdup(name));
-	return(NULL);
-    }
-    moduledir_rebuild();
-    result = NULL;
-    namelen = strlen(name);
-    STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
-	result = file_lookup(mdp->d_path, name, namelen, extlist);
-	if (result)
-	    break;
-    }
-    return(result);
+	if (file_havepath(name)) {
+		/* Qualified, so just see if it exists */
+		if (stat(name, &sb) == 0)
+			return (strdup(name));
+		return (NULL);
+	}
+	moduledir_rebuild();
+	result = NULL;
+	namelen = strlen(name);
+	STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
+		result = file_lookup(mdp->d_path, name, namelen, extlist);
+		if (result != NULL)
+			break;
+	}
+	return (result);
 }
 
 #define	INT_ALIGN(base, ptr)	ptr = \
-	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
+	(base) + (((ptr) - (base) + sizeof (int) - 1) & ~(sizeof (int) - 1))
 
 static char *
 mod_search_hints(struct moduledir *mdp, const char *modname,
-	struct mod_depend *verinfo)
+    struct mod_depend *verinfo)
 {
-    u_char	*cp, *recptr, *bufend, *best;
-    char	*result;
-    int		*intp, bestver, blen, clen, found, ival, modnamelen, reclen;
+	uchar_t *cp, *recptr, *bufend, *best;
+	char *result;
+	int *intp, bestver, blen, clen, ival, modnamelen, reclen;
+	bool found;
 
-    moduledir_readhints(mdp);
-    modnamelen = strlen(modname);
-    found = 0;
-    result = NULL;
-    bestver = 0;
-    if (mdp->d_hints == NULL)
-	goto bad;
-    recptr = mdp->d_hints;
-    bufend = recptr + mdp->d_hintsz;
-    clen = blen = 0;
-    best = cp = NULL;
-    while (recptr < bufend && !found) {
-	intp = (int*)recptr;
-	reclen = *intp++;
-	ival = *intp++;
-	cp = (u_char*)intp;
-	switch (ival) {
-	case MDT_VERSION:
-	    clen = *cp++;
-	    if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
-		break;
-	    cp += clen;
-	    INT_ALIGN(mdp->d_hints, cp);
-	    ival = *(int*)cp;
-	    cp += sizeof(int);
-	    clen = *cp++;
-	    if (verinfo == NULL || ival == verinfo->md_ver_preferred) {
-		found = 1;
-		break;
-	    }
-	    if (ival >= verinfo->md_ver_minimum &&
-		ival <= verinfo->md_ver_maximum &&
-		ival > bestver) {
-		bestver = ival;
-		best = cp;
-		blen = clen;
-	    }
-	    break;
-	default:
-	    break;
+	moduledir_readhints(mdp);
+	modnamelen = strlen(modname);
+	found = false;
+	result = NULL;
+	bestver = 0;
+	if (mdp->d_hints == NULL)
+		goto bad;
+	recptr = mdp->d_hints;
+	bufend = recptr + mdp->d_hintsz;
+	clen = blen = 0;
+	best = cp = NULL;
+	while (recptr < bufend && !found) {
+		intp = (int *)recptr;
+		reclen = *intp++;
+		ival = *intp++;
+		cp = (uchar_t *)intp;
+		switch (ival) {
+		case MDT_VERSION:
+			clen = *cp++;
+			if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
+				break;
+			cp += clen;
+			INT_ALIGN(mdp->d_hints, cp);
+			ival = *(int *)cp;
+			cp += sizeof (int);
+			clen = *cp++;
+			if (verinfo == NULL ||
+			    ival == verinfo->md_ver_preferred) {
+				found = true;
+				break;
+			}
+			if (ival >= verinfo->md_ver_minimum &&
+			    ival <= verinfo->md_ver_maximum &&
+			    ival > bestver) {
+				bestver = ival;
+				best = cp;
+				blen = clen;
+			}
+			break;
+		default:
+			break;
+		}
+		recptr += reclen + sizeof (int);
 	}
-	recptr += reclen + sizeof(int);
-    }
-    /*
-     * Finally check if KLD is in the place
-     */
-    if (found)
-	result = file_lookup(mdp->d_path, (char *)cp, clen, NULL);
-    else if (best)
-	result = file_lookup(mdp->d_path, (char *)best, blen, NULL);
+	/*
+	 * Finally check if KLD is in the place
+	 */
+	if (found)
+		result = file_lookup(mdp->d_path, (char *)cp, clen, NULL);
+	else if (best)
+		result = file_lookup(mdp->d_path, (char *)best, blen, NULL);
 bad:
-    /*
-     * If nothing found or hints is absent - fallback to the old way
-     * by using "kldname[.ko]" as module name.
-     */
-    if (!found && !bestver && result == NULL)
-	result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list);
-    return result;
+	/*
+	 * If nothing found or hints is absent - fallback to the old way
+	 * by using "kldname[.ko]" as module name.
+	 */
+	if (!found && bestver == 0 && result == NULL) {
+		result = file_lookup(mdp->d_path, modname, modnamelen,
+		    kld_ext_list);
+	}
+	return (result);
 }
 
 /*
@@ -1111,50 +1093,50 @@
 static char *
 mod_searchmodule(char *name, struct mod_depend *verinfo)
 {
-    struct	moduledir *mdp;
-    char	*result;
+	struct moduledir *mdp;
+	char *result;
 
-    moduledir_rebuild();
-    /*
-     * Now we ready to lookup module in the given directories
-     */
-    result = NULL;
-    STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
-	result = mod_search_hints(mdp, name, verinfo);
-	if (result)
-	    break;
-    }
+	moduledir_rebuild();
+	/*
+	 * Now we ready to lookup module in the given directories
+	 */
+	result = NULL;
+	STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
+		result = mod_search_hints(mdp, name, verinfo);
+		if (result != NULL)
+			break;
+	}
 
-    return(result);
+	return (result);
 }
 
 int
 file_addmodule(struct preloaded_file *fp, char *modname, int version,
-	struct kernel_module **newmp)
+    struct kernel_module **newmp)
 {
-    struct kernel_module *mp;
-    struct mod_depend mdepend;
+	struct kernel_module *mp;
+	struct mod_depend mdepend;
 
-    bzero(&mdepend, sizeof(mdepend));
-    mdepend.md_ver_preferred = version;
-    mp = file_findmodule(fp, modname, &mdepend);
-    if (mp)
-	return (EEXIST);
-    mp = calloc(1, sizeof(struct kernel_module));
-    if (mp == NULL)
-	return (ENOMEM);
-    mp->m_name = strdup(modname);
-    if (mp->m_name == NULL) {
-	free(mp);
-	return (ENOMEM);
-    }
-    mp->m_version = version;
-    mp->m_fp = fp;
-    mp->m_next = fp->f_modules;
-    fp->f_modules = mp;
-    if (newmp)
-	*newmp = mp;
-    return (0);
+	bzero(&mdepend, sizeof (mdepend));
+	mdepend.md_ver_preferred = version;
+	mp = file_findmodule(fp, modname, &mdepend);
+	if (mp != NULL)
+		return (EEXIST);
+	mp = calloc(1, sizeof (struct kernel_module));
+	if (mp == NULL)
+		return (ENOMEM);
+	mp->m_name = strdup(modname);
+	if (mp->m_name == NULL) {
+		free(mp);
+		return (ENOMEM);
+	}
+	mp->m_version = version;
+	mp->m_fp = fp;
+	mp->m_next = fp->f_modules;
+	fp->f_modules = mp;
+	if (newmp)
+		*newmp = mp;
+	return (0);
 }
 
 /*
@@ -1163,32 +1145,34 @@
 void
 file_discard(struct preloaded_file *fp)
 {
-    struct file_metadata	*md, *md1;
-    struct kernel_module	*mp, *mp1;
-    if (fp == NULL)
-	return;
+	struct file_metadata *md, *md1;
+	struct kernel_module *mp, *mp1;
 
-    if (archsw.arch_free_loadaddr != NULL && fp->f_addr)
-	archsw.arch_free_loadaddr(fp->f_addr,
-	    (uint64_t)(roundup2(fp->f_size, PAGE_SIZE) >> 12));
+	if (fp == NULL)
+		return;
+
+	if (archsw.arch_free_loadaddr != NULL && fp->f_addr) {
+		archsw.arch_free_loadaddr(fp->f_addr,
+		    (uint64_t)(roundup2(fp->f_size, PAGE_SIZE) >> 12));
+	}
 
-    md = fp->f_metadata;
-    while (md) {
-	md1 = md;
-	md = md->md_next;
-	free(md1);
-    }
-    mp = fp->f_modules;
-    while (mp) {
-	free(mp->m_name);
-	mp1 = mp;
-	mp = mp->m_next;
-	free(mp1);
-    }
-    free(fp->f_name);
-    free(fp->f_type);
-    free(fp->f_args);
-    free(fp);
+	md = fp->f_metadata;
+	while (md != NULL) {
+		md1 = md;
+		md = md->md_next;
+		free(md1);
+	}
+	mp = fp->f_modules;
+	while (mp != NULL) {
+		free(mp->m_name);
+		mp1 = mp;
+		mp = mp->m_next;
+		free(mp1);
+	}
+	free(fp->f_name);
+	free(fp->f_type);
+	free(fp->f_args);
+	free(fp);
 }
 
 /*
@@ -1199,7 +1183,7 @@
 file_alloc(void)
 {
 
-    return (calloc(1, sizeof (struct preloaded_file)));
+	return (calloc(1, sizeof (struct preloaded_file)));
 }
 
 /*
@@ -1208,31 +1192,31 @@
 static void
 file_insert_tail(struct preloaded_file *fp)
 {
-    struct preloaded_file	*cm;
+	struct preloaded_file *cm;
 
-    /* Append to list of loaded file */
-    fp->f_next = NULL;
-    if (preloaded_files == NULL) {
-	preloaded_files = fp;
-    } else {
-	for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
-	    ;
-	cm->f_next = fp;
-    }
+	/* Append to list of loaded file */
+	fp->f_next = NULL;
+	if (preloaded_files == NULL) {
+		preloaded_files = fp;
+	} else {
+		for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
+			;
+		cm->f_next = fp;
+	}
 }
 
 static char *
 moduledir_fullpath(struct moduledir *mdp, const char *fname)
 {
-    char *cp;
+	char *cp;
 
-    cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2);
-    if (cp == NULL)
-	return NULL;
-    strcpy(cp, mdp->d_path);
-    strcat(cp, "/");
-    strcat(cp, fname);
-    return (cp);
+	cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2);
+	if (cp == NULL)
+		return (NULL);
+	strcpy(cp, mdp->d_path);
+	strcat(cp, "/");
+	strcat(cp, fname);
+	return (cp);
 }
 
 /*
@@ -1241,39 +1225,39 @@
 static void
 moduledir_readhints(struct moduledir *mdp)
 {
-    struct stat	st;
-    char	*path;
-    int		fd, size, version;
+	struct stat st;
+	char *path;
+	int fd, size, version;
 
-    if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS))
-	return;
-    path = moduledir_fullpath(mdp, "linker.hints");
-    if (stat(path, &st) != 0 ||
-	st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) ||
-	st.st_size > LINKER_HINTS_MAX || (fd = open(path, O_RDONLY)) < 0) {
+	if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS))
+		return;
+	path = moduledir_fullpath(mdp, "linker.hints");
+	if (stat(path, &st) != 0 ||
+	    st.st_size < (ssize_t)(sizeof (version) + sizeof (int)) ||
+	    st.st_size > LINKER_HINTS_MAX ||
+	    (fd = open(path, O_RDONLY)) < 0) {
+		free(path);
+		mdp->d_flags |= MDIR_NOHINTS;
+		return;
+	}
 	free(path);
-	mdp->d_flags |= MDIR_NOHINTS;
+	size = read(fd, &version, sizeof (version));
+	if (size != sizeof (version) || version != LINKER_HINTS_VERSION)
+		goto bad;
+	size = st.st_size - size;
+	mdp->d_hints = malloc(size);
+	if (mdp->d_hints == NULL)
+		goto bad;
+	if (read(fd, mdp->d_hints, size) != size)
+		goto bad;
+	mdp->d_hintsz = size;
+	close(fd);
 	return;
-    }
-    free(path);
-    size = read(fd, &version, sizeof(version));
-    if (size != sizeof(version) || version != LINKER_HINTS_VERSION)
-	goto bad;
-    size = st.st_size - size;
-    mdp->d_hints = malloc(size);
-    if (mdp->d_hints == NULL)
-	goto bad;
-    if (read(fd, mdp->d_hints, size) != size)
-	goto bad;
-    mdp->d_hintsz = size;
-    close(fd);
-    return;
 bad:
-    close(fd);
-    free(mdp->d_hints);
-    mdp->d_hints = NULL;
-    mdp->d_flags |= MDIR_NOHINTS;
-    return;
+	close(fd);
+	free(mdp->d_hints);
+	mdp->d_hints = NULL;
+	mdp->d_flags |= MDIR_NOHINTS;
 }
 
 /*
@@ -1282,62 +1266,63 @@
 static void
 moduledir_rebuild(void)
 {
-    struct	moduledir *mdp, *mtmp;
-    const char	*path, *cp, *ep;
-    size_t	cplen;
+	struct moduledir *mdp, *mtmp;
+	const char *path, *cp, *ep;
+	size_t cplen;
 
-    path = getenv("module_path");
-    if (path == NULL)
-	path = default_searchpath;
-    /*
-     * Rebuild list of module directories if it changed
-     */
-    STAILQ_FOREACH(mdp, &moduledir_list, d_link)
-	mdp->d_flags |= MDIR_REMOVED;
+	path = getenv("module_path");
+	if (path == NULL)
+		path = default_searchpath;
+	/*
+	 * Rebuild list of module directories if it changed
+	 */
+	STAILQ_FOREACH(mdp, &moduledir_list, d_link)
+		mdp->d_flags |= MDIR_REMOVED;
 
-    for (ep = path; *ep != 0;  ep++) {
-	cp = ep;
-	for (; *ep != 0 && *ep != ';'; ep++)
-	    ;
-	/*
-	 * Ignore trailing slashes
-	 */
-	for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--)
-	    ;
-	STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
-	    if (strlen(mdp->d_path) != cplen ||	bcmp(cp, mdp->d_path, cplen) != 0)
-		continue;
-	    mdp->d_flags &= ~MDIR_REMOVED;
-	    break;
+	for (ep = path; *ep != 0; ep++) {
+		cp = ep;
+		for (; *ep != 0 && *ep != ';'; ep++)
+			;
+		/*
+		 * Ignore trailing slashes
+		 */
+		for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/';
+		    cplen--)
+			;
+		STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
+			if (strlen(mdp->d_path) != cplen ||
+			    bcmp(cp, mdp->d_path, cplen) != 0)
+				continue;
+			mdp->d_flags &= ~MDIR_REMOVED;
+			break;
+		}
+		if (mdp == NULL) {
+			mdp = malloc(sizeof (*mdp) + cplen + 1);
+			if (mdp == NULL)
+				return;
+			mdp->d_path = (char *)(mdp + 1);
+			bcopy(cp, mdp->d_path, cplen);
+			mdp->d_path[cplen] = 0;
+			mdp->d_hints = NULL;
+			mdp->d_flags = 0;
+			STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
+		}
+		if (*ep == '\0')
+			break;
 	}
-	if (mdp == NULL) {
-	    mdp = malloc(sizeof(*mdp) + cplen + 1);
-	    if (mdp == NULL)
-		return;
-	    mdp->d_path = (char*)(mdp + 1);
-	    bcopy(cp, mdp->d_path, cplen);
-	    mdp->d_path[cplen] = 0;
-	    mdp->d_hints = NULL;
-	    mdp->d_flags = 0;
-	    STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
+	/*
+	 * Delete unused directories if any
+	 */
+	mdp = STAILQ_FIRST(&moduledir_list);
+	while (mdp) {
+		if ((mdp->d_flags & MDIR_REMOVED) == 0) {
+			mdp = STAILQ_NEXT(mdp, d_link);
+		} else {
+			free(mdp->d_hints);
+			mtmp = mdp;
+			mdp = STAILQ_NEXT(mdp, d_link);
+			STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
+			free(mtmp);
+		}
 	}
-	if (*ep == 0)
-	    break;
-    }
-    /*
-     * Delete unused directories if any
-     */
-    mdp = STAILQ_FIRST(&moduledir_list);
-    while (mdp) {
-	if ((mdp->d_flags & MDIR_REMOVED) == 0) {
-	    mdp = STAILQ_NEXT(mdp, d_link);
-	} else {
-	    free(mdp->d_hints);
-	    mtmp = mdp;
-	    mdp = STAILQ_NEXT(mdp, d_link);
-	    STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
-	    free(mtmp);
-	}
-    }
-    return;
 }
--- a/usr/src/cmd/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -497,7 +497,6 @@
 	xvm
 
 sparc_SUBDIRS=		\
-	cvcd		\
 	dcs		\
 	device_remap	\
 	drd		\
--- a/usr/src/cmd/Makefile.check	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/Makefile.check	Fri May 31 14:32:40 2019 +0200
@@ -24,6 +24,7 @@
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
 # Copyright (c) 2011, 2017 by Delphix. All rights reserved.
 # Copyright 2017 Nexenta Systems, Inc.
+# Copyright 2019 Peter Tribble
 #
 
 include ../Makefile.master
@@ -39,7 +40,6 @@
 	consadm				\
 	coreadm				\
 	cron				\
-	cvcd				\
 	dispadmin			\
 	drd				\
 	dumpadm				\
--- a/usr/src/cmd/cvcd/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +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.
-# Copyright 2019 Peter Tribble.
-#
-# Makefile definitions for Starcat Network Console related items.
-#
-# cmd/cvcd/Makefile
-#
-# These utilities are specific to the Sun-Fire-15000 platform at this
-# time.
-#
-
-PROG=		cvcd
-MANIFEST=	cvc.xml
-SVCMETHOD=	svc-$(PROG)
-
-include ../Makefile.cmd
-
-SUBDIRS	=	sparc
-
-ROOTMANIFESTDIR=	$(ROOTSVCSYSTEM)
-
-all :=		TARGET= all
-install :=	TARGET= install
-clean :=	TARGET= clean
-clobber :=	TARGET= clobber
-lint :=		TARGET= lint
-
-.KEEP_STATE:
-
-all lint clean clobber: $(SUBDIRS)
-
-install: $(SUBDIRS) $(ROOTMANIFEST) $(ROOTSVCMETHOD)
-
-check:	$(CHKMANIFEST)
-
-$(SUBDIRS): FRC
-	@cd $@; pwd; $(MAKE) $(TARGET)
-
-FRC:
-
-include ../Makefile.targ
--- a/usr/src/cmd/cvcd/cvc.xml	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
-<!--
- Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
- Copyright 2019 Peter Tribble.
-
- 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
-
-	NOTE:  This service manifest is not editable; its contents will
-	be overwritten by package or patch operations, including
-	operating system upgrade.  Make customizations in a different
-	file.
-
-	Service manifest for cvcd.
--->
-
-<service_bundle type='manifest' name='SUNWcvcr.u:cvcd'>
-
-<service name='system/cvc' type='service' version='1'>
-
-	<create_default_instance enabled='false' />
-
-	<single_instance />
-
-	<dependency
-	    name='network'
-	    grouping='require_all'
-	    restart_on='none'
-	    type='service'>
-		<service_fmri value='svc:/network/loopback' />
-	</dependency>
-
-	<!-- sckmd is required on OPL and Starcat -->
-	<dependency
-	    name='sckmd'
-	    grouping='optional_all'
-	    restart_on='none'
-	    type='service'>
-		<service_fmri value='svc:/platform/sun4u/sckmd' />
-	</dependency>
-
-	<dependency 
-	    name='cryptosvc'
-	    grouping='require_all'
-	    restart_on='none'
-	    type='service'>
-		<service_fmri value='svc:/system/cryptosvc' />
-	</dependency>
-
-	<dependency
-	    name='nodename'
-	    grouping='require_all'
-	    restart_on='none' 
-	    type='service'>
-		<service_fmri value='svc:/system/identity:node' />
-	</dependency>
-
-	<dependency
-	    name='filesystem_usr'
-	    grouping='require_all'
-	    restart_on='none' 
-	    type='service'>
-		<service_fmri value='svc:/system/filesystem/usr' />
-	</dependency>
-
-	<exec_method
-	    type='method'
-	    name='start'
-	    exec='/lib/svc/method/svc-cvcd'
-	    timeout_seconds='60' />
-
-	<exec_method
-	    type='method'
-	    name='stop'
-	    exec=':kill -9'
-	    timeout_seconds='60' />
-
-	<!-- these are passed to cvcd in the method script -->
-	<property_group name='cvc' type='application'>
-		<propval name='ah_auth' type='astring' value='md5' />
-		<propval name='esp_encr' type='astring' value='none' />
-		<propval name='esp_auth' type='astring' value='none' />
-	</property_group>
-
-	<stability value='Unstable' />
-
-	<template>
-		<common_name>
-			<loctext xml:lang='C'>
-				network virtual console
-			</loctext>
-		</common_name>
-
-		<documentation>
-			<manpage title='cvcd' section='1M'
-				manpath='/usr/share/man' />
-		</documentation>
-	</template>
-</service>
-
-</service_bundle>
--- a/usr/src/cmd/cvcd/sparc/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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) 1997 by Sun Microsystems, Inc.
-# All rights reserved.
-# Copyright 2019 Peter Tribble.
-#
-# Makefile definitions for Starcat's Network Console related items.
-#
-# cmd/cvcd/sparc/Makefile
-#
-
-SUBDIRS	=	sun4u
-
-all :=		TARGET= all
-install :=	TARGET= install
-clean :=	TARGET= clean
-clobber :=	TARGET= clobber
-lint :=		TARGET= lint
-
-.KEEP_STATE:
-
-all install lint clean clobber: $(SUBDIRS)
-
-$(SUBDIRS): FRC
-	@cd $@; pwd; $(MAKE) $(TARGET)
-
-FRC:
--- a/usr/src/cmd/cvcd/sparc/sun4u/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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 2019 Peter Tribble.
-#
-# Makefile definitions for Starcat Network Console related items.
-#
-# cmd/cvcd/sparc/sun4u/Makefile
-#
-
-SUBDIRS	=	starcat
-
-all :=		TARGET= all
-install :=	TARGET= install
-clean :=	TARGET= clean
-clobber :=	TARGET= clobber
-lint :=		TARGET= lint
-
-.KEEP_STATE:
-
-all install lint clean clobber: $(SUBDIRS)
-
-$(SUBDIRS): FRC
-	@cd $@; pwd; $(MAKE) $(TARGET)
-
-FRC:
--- a/usr/src/cmd/cvcd/sparc/sun4u/starcat/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# cmd/cvcd/sparc/sun4u/starcat/cvcd
-#
-PROG=		cvcd
-ROOTFS_PROG=	$(PROG)
-PLATFORM=	SUNW,Sun-Fire-15000
-
-#	Create default so empty rules don't confuse make
-CLASS=		32
-
-SRCS=		$(PROG:%=%.c)
-OBJS=		$(PROG:%=%.o)
-
-include ../../../../Makefile.cmd
-include ../../../../../Makefile.psm
-
-FILEMODE= 0755
-
-ROOTPSMPROG	= $(ROOT_PSM_LIB_DIR)/$(PROG)
-
-CPPFLAGS = -I$(USR_PSM_INCL_DIR) -I$(SRC)/uts/sun4u/starcat $(CPPFLAGS.master)
-CERRWARN += -_gcc=-Wno-unused-variable
-CERRWARN += -_gcc=-Wno-uninitialized
-
-LDLIBS +=	-lsocket
-
-.KEEP_STATE:
-
-all: $(ROOTFS_PROG) 
-
-install: all .WAIT $(ROOTPSMPROG)
-
-clean:
-	$(RM) $(PROG) $(OBJS)
-
-lint: lint_PROG
-
-include ../../../../Makefile.targ
-include ../../../../../Makefile.psm.targ
--- a/usr/src/cmd/cvcd/sparc/sun4u/starcat/cvcd.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,888 +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 code implements the Starcat Virtual Console host daemon (see cvcd(1M)).
- * It accepts one TCP connection at a time on a well-known port.  Once a
- * connection is accepted, the console redirection driver (cvcdredir(7D)) is
- * opened, and console I/O is routed back and forth between the two file
- * descriptors (network and redirection driver).  Per-socket IPsec is used to
- * secure the connection if it is enabled with the "-a", "-u" and or "-e"
- * command line options.
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-
-#include <fcntl.h>
-#include <sys/filio.h>		/* Just to get FIONBIO... */
-#include <unistd.h>
-#include <errno.h>
-#include <stropts.h>
-#include <signal.h>
-#include <syslog.h>
-#include <sys/utsname.h>
-#include <sys/stat.h>
-#include <locale.h>
-#include <limits.h>
-
-#include <sys/priocntl.h>
-#include <sys/tspriocntl.h>
-#include <sys/rtpriocntl.h>
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <tiuser.h>
-
-#include <sys/sc_cvcio.h>
-
-
-/*
- * Header files for per-socket IPsec
- */
-#include <netinet/in.h>
-#include <net/pfkeyv2.h>
-
-/*
- * The IPsec socket option struct, from ipsec(7P):
- *
- *     typedef struct ipsec_req {
- *         uint_t      ipsr_ah_req;            AH request
- *         uint_t      ipsr_esp_req;           ESP request
- *         uint_t      ipsr_self_encap_req;    Self-Encap request
- *         uint8_t     ipsr_auth_alg;          Auth algs for AH
- *         uint8_t     ipsr_esp_alg;           Encr algs for ESP
- *         uint8_t     ipsr_esp_auth_alg;      Auth algs for ESP
- *     } ipsec_req_t;
- *
- * The -a option sets the ipsr_auth_alg field. Allowable arguments
- * are "none", "md5", or "sha1". The -e option sets the ipsr_esp_alg
- * field. Allowable arguments are "none", "des", or "3des". "none"
- * is the default for both options. The -u option sets ipsr_esp_auth_alg.
- * Allowable arguments are the same as -a.
- *
- * The arguments ("md5", "des", etc.) are named so that they match
- * kmd(1m)'s accepted arguments which are listed on the SC in
- * /etc/opt/SUNWSMS/SMS/config/kmd_policy.cf.
- */
-#define	AH_REQ		(IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE)
-#define	ESP_REQ		(IPSEC_PREF_REQUIRED | IPSEC_PREF_UNIQUE)
-#define	SELF_ENCAP_REQ	0x0
-
-/*
- * A type to hold the command line argument string used to select a
- * particular authentication header (AH) or encapsulating security
- * payload (ESP) algorithm and the ID used for that algorithm when
- * filling the ipsec_req_t structure which is passed to
- * setsockopt(3SOCKET).
- */
-typedef struct cvcd_alg {
-	char		*arg_name;
-	uint8_t		alg_id;
-} cvcd_alg_t;
-
-/*
- *  Misc. defines.
- */
-#define	NODENAME	"/etc/nodename"
-#define	NETWORK_PFD	0
-#define	REDIR_PFD	1
-#define	LISTEN_PFD	2
-#define	NUM_PFDS	3
-
-/*
- * Function prototypes
- */
-static void cvcd_set_priority(void);
-static int  cvcd_init_host_socket(int port, uint8_t ah_auth_alg,
-    uint8_t esp_encr_alg, uint8_t esp_auth_alg);
-static void cvcd_do_network_console(void);
-static void cvcd_err(int code, char *format, ...);
-static void cvcd_usage(void);
-static uint8_t cvcd_get_alg(cvcd_alg_t *algs, char *arg);
-static boolean_t cvcd_global_policy(void);
-
-/*
- *  Globals
- */
-static struct pollfd	pfds[NUM_PFDS];
-static char		progname[MAXPATHLEN];
-static int		debug = 0;
-
-/*
- * Array of acceptable -a, -u and -e arguments.
- */
-static cvcd_alg_t auth_algs_array[] = {
-	{ "none",	SADB_AALG_NONE },	/* -a none or -u none */
-	{ "md5",	SADB_AALG_MD5HMAC },	/* -a md5  or -u md5 */
-	{ "sha1",	SADB_AALG_SHA1HMAC },	/* -a sha1 or -u sha1 */
-	{ NULL,		0x0 }
-}, esp_algs_array[] = {
-	{ "none",	SADB_EALG_NONE },	/* -e none */
-	{ "des",	SADB_EALG_DESCBC },	/* -e des  */
-	{ "3des",	SADB_EALG_3DESCBC },	/* -e 3des */
-	{ NULL,		0x0 }
-};
-
-
-int
-main(int argc, char **argv)
-{
-	int			err;
-	int			opt;
-	int			tport = 0;
-	char			*hostname;
-	struct utsname		utsname;
-	int			fd;
-	int			i;
-	struct servent		*se;
-	char 			prefix[256];
-	uint8_t			ah_auth_alg 	= SADB_AALG_NONE;
-	uint8_t			esp_encr_alg  	= SADB_EALG_NONE;
-	uint8_t			esp_auth_alg  	= SADB_AALG_NONE;
-
-	(void) setlocale(LC_ALL, "");
-	(void) strcpy(progname, argv[0]);
-
-#ifdef DEBUG
-	while ((opt = getopt(argc, argv, "a:e:u:dp:")) != EOF) {
-#else
-	while ((opt = getopt(argc, argv, "a:e:u:")) != EOF) {
-#endif
-		switch (opt) {
-			case 'a' :
-			case 'u' :
-					if (opt == 'a')
-						ah_auth_alg = cvcd_get_alg(
-						    auth_algs_array, optarg);
-					else
-						esp_auth_alg = cvcd_get_alg(
-						    auth_algs_array, optarg);
-					break;
-
-			case 'e' :	esp_encr_alg = cvcd_get_alg(
-					    esp_algs_array, optarg);
-					break;
-#ifdef DEBUG
-			case 'd' :	debug = 1;
-					break;
-
-			case 'p' :	tport = atoi(optarg);
-					break;
-#endif  /* DEBUG */
-
-			default  :	cvcd_usage();
-					exit(1);
-		}
-	}
-
-	if (uname(&utsname) == -1) {
-		perror("HOSTNAME not defined");
-		exit(1);
-	}
-	hostname = utsname.nodename;
-
-	/*
-	 * hostname may still be NULL, depends on when cvcd was started
-	 * in the boot sequence.  If it is NULL, try one more time
-	 * to get a hostname -> look in the /etc/nodename file.
-	 */
-	if (!strlen(hostname)) {
-		/*
-		 * try to get the hostname from the /etc/nodename file
-		 * we reuse the utsname.nodename buffer here!  hostname
-		 * already points to it.
-		 */
-		if ((fd = open(NODENAME, O_RDONLY)) > 0) {
-			if ((i = read(fd, utsname.nodename, SYS_NMLN)) <= 0) {
-				cvcd_err(LOG_WARNING,
-				    "failed to acquire hostname");
-			} else {
-				utsname.nodename[i-1] = '\0';
-			}
-			(void) close(fd);
-		}
-	}
-	/*
-	 * If all attempts to get the hostname have failed, put something
-	 * meaningful in the buffer.
-	 */
-	if (!strlen(hostname)) {
-		(void) strcpy(utsname.nodename, "(unknown)");
-	}
-
-	/*
-	 * Must be root.
-	 */
-	if (debug == 0 && geteuid() != 0) {
-		fprintf(stderr, "cvcd: Must be root");
-		exit(1);
-	}
-
-	/*
-	 * Daemonize...
-	 */
-	if (debug == 0) {
-		closefrom(0);
-		(void) chdir("/");
-		(void) umask(0);
-		if (fork() != 0) {
-			exit(0);
-		}
-		(void) setpgrp();
-		(void) sprintf(prefix, "%s-(HOSTNAME:%s)", progname, hostname);
-		openlog(prefix, LOG_CONS | LOG_NDELAY, LOG_LOCAL0);
-	}
-
-	/*
-	 * Initialize the array of pollfds used to track the listening socket,
-	 * the connection to the console redirection driver, and the network
-	 * connection.
-	 */
-	(void) memset((void *)pfds, 0, NUM_PFDS * sizeof (struct pollfd));
-	for (i = 0; i < NUM_PFDS; i++) {
-		pfds[i].fd = -1;
-	}
-
-	/* SPR 94004 */
-	(void) sigignore(SIGTERM);
-
-	/*
-	 * SPR 83644: cvc and kadb are not compatible under heavy loads.
-	 *	Fix: will give cvcd highest TS priority at execution time.
-	 */
-	cvcd_set_priority();
-
-	/*
-	 * If not already determined by a command-line flag, figure out which
-	 * port we're supposed to be listening on.
-	 */
-	if (tport == 0) {
-		if ((se = getservbyname(CVCD_SERVICE, "tcp")) == NULL) {
-			cvcd_err(LOG_ERR, "getservbyname(%s) not found",
-				CVCD_SERVICE);
-			exit(1);
-		}
-		tport = se->s_port;
-	}
-
-	if (debug == 1) {
-		cvcd_err(LOG_DEBUG, "tport = %d, debug = %d", tport, debug);
-	}
-
-	/*
-	 * Attempt to initialize the socket we'll use to listen for incoming
-	 * connections.  No need to check the return value, as the call will
-	 * exit if it fails.
-	 */
-	pfds[LISTEN_PFD].fd = cvcd_init_host_socket(tport, ah_auth_alg,
-	    esp_encr_alg, esp_auth_alg);
-
-	/*
-	 * Now that we're all set up, we loop forever waiting for connections
-	 * (one at a time) and then driving network console activity over them.
-	 */
-	for (;;) {
-		/*
-		 * Start by waiting for an incoming connection.
-		 */
-		do {
-			pfds[LISTEN_PFD].events = POLLIN;
-			err = poll(&(pfds[LISTEN_PFD]), 1, -1);
-			if (err == -1) {
-				cvcd_err(LOG_ERR, "poll: %s", strerror(errno));
-				exit(1);
-			}
-			if ((err > 0) &&
-			    (pfds[LISTEN_PFD].revents & POLLIN)) {
-				fd = accept(pfds[LISTEN_PFD].fd, NULL, NULL);
-				if ((fd == -1) && (errno != EWOULDBLOCK)) {
-					cvcd_err(LOG_ERR, "accept: %s",
-					    strerror(errno));
-					exit(1);
-				}
-			}
-		} while (fd == -1);
-
-		/*
-		 * We have a connection.  Set the new socket nonblocking, and
-		 * initialize the appropriate pollfd.  In theory, the new socket
-		 * is _already_ non-blocking because accept() is supposed to
-		 * hand us a socket with the same properties as the socket we're
-		 * listening on, but it won't hurt to make sure.
-		 */
-		opt = 1;
-		err = ioctl(fd, FIONBIO, &opt);
-		if (err == -1) {
-			cvcd_err(LOG_ERR, "ioctl: %s", strerror(errno));
-			(void) close(fd);
-			continue;
-		}
-		pfds[NETWORK_PFD].fd = fd;
-
-		/*
-		 * Since we're ready to do network console stuff, go ahead and
-		 * open the Network Console redirection driver, which will
-		 * switch traffic from the IOSRAM path to the network path if
-		 * the network path has been selected in cvc.
-		 */
-		fd = open(CVCREDIR_DEV, O_RDWR|O_NDELAY);
-		if (fd == -1) {
-			cvcd_err(LOG_ERR, "open(redir): %s", strerror(errno));
-			exit(1);
-		}
-		pfds[REDIR_PFD].fd = fd;
-
-		/*
-		 * We have a network connection and we have the redirection
-		 * driver open, so drive the network console until something
-		 * changes.
-		 */
-		cvcd_do_network_console();
-
-		/*
-		 * cvcd_do_network_console doesn't return until there's a
-		 * problem, so we need to close the network connection and the
-		 * redirection driver and start the whole loop over again.
-		 */
-		(void) close(pfds[NETWORK_PFD].fd);
-		pfds[NETWORK_PFD].fd = -1;
-		(void) close(pfds[REDIR_PFD].fd);
-		pfds[REDIR_PFD].fd = -1;
-	}
-
-	/* NOTREACHED */
-	return (1);
-}
-
-/*
- * cvcd_get_alg
- *
- * Returns the ID of the first algorithm found in
- * the 'algs' array with a name matching 'arg'. If
- * there is no matching algorithm, the function does
- * not return. The 'algs' array must be terminated
- * by an entry containing a NULL 'arg_name' field.
- */
-static uint8_t
-cvcd_get_alg(cvcd_alg_t *algs, char *arg)
-{
-	cvcd_alg_t *alg;
-
-	for (alg = algs; alg->arg_name != NULL && arg != NULL; alg++) {
-		if (strncmp(alg->arg_name, arg, strlen(alg->arg_name) + 1)
-		    == 0) {
-			return (alg->alg_id);
-		}
-	}
-
-	cvcd_usage();
-	exit(1);
-	/* NOTREACHED */
-}
-
-/*
- * cvcd_set_priority
- *
- * DESCRIBE
- * SPR 83644: cvc and kadb are not compatible under heavy loads.
- *	Fix: will give cvcd highest TS priority at execution time.
- */
-static void
-cvcd_set_priority(void)
-{
-	id_t		pid, tsID;
-	pcparms_t	pcparms;
-	tsparms_t	*tsparmsp;
-	short		tsmaxpri;
-	pcinfo_t	info;
-
-	pid = getpid();
-	pcparms.pc_cid = PC_CLNULL;
-	tsparmsp = (tsparms_t *)pcparms.pc_clparms;
-
-	/* Get scheduler properties for this PID */
-	if (priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcparms) == -1L) {
-		cvcd_err(LOG_ERR, "Warning: can't set priority.");
-		cvcd_err(LOG_ERR, "priocntl(GETPARMS): %s", strerror(errno));
-		return;
-	}
-
-	/* Get class ID and maximum priority for TS process class */
-	(void) strcpy(info.pc_clname, "TS");
-	if (priocntl(0L, 0L, PC_GETCID, (caddr_t)&info) == -1L) {
-		cvcd_err(LOG_ERR, "Warning: can't set priority.");
-		cvcd_err(LOG_ERR, "priocntl(GETCID): %s", strerror(errno));
-		return;
-	}
-	tsmaxpri = ((struct tsinfo *)info.pc_clinfo)->ts_maxupri;
-	tsID = info.pc_cid;
-
-	/* Print priority info in debug mode */
-	if (debug) {
-		if (pcparms.pc_cid == tsID) {
-			cvcd_err(LOG_DEBUG,
-			    "PID: %d, current priority: %d, Max priority: %d.",
-			    pid, tsparmsp->ts_upri, tsmaxpri);
-		}
-	}
-	/* Change proc's priority to maxtspri */
-	pcparms.pc_cid = tsID;
-	tsparmsp->ts_upri = tsmaxpri;
-	tsparmsp->ts_uprilim = tsmaxpri;
-
-	if (priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&pcparms) == -1L) {
-		cvcd_err(LOG_ERR, "Warning: can't set priority.");
-		cvcd_err(LOG_ERR, "priocntl(SETPARMS): %s", strerror(errno));
-	}
-
-	/* Print new priority info in debug mode */
-	if (debug) {
-		if (priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcparms) ==
-		    -1L) {
-			cvcd_err(LOG_ERR, "priocntl(GETPARMS): %s",
-			    strerror(errno));
-		} else {
-			cvcd_err(LOG_DEBUG, "PID: %d, new priority: %d.", pid,
-			    tsparmsp->ts_upri);
-		}
-	}
-}
-
-
-/*
- * cvcd_init_host_socket
- *
- * Given a TCP port number, create and initialize a socket appropriate for
- * accepting incoming connections to that port.
- */
-static int
-cvcd_init_host_socket(int port, uint8_t ah_auth_alg, uint8_t esp_encr_alg,
-	uint8_t esp_auth_alg)
-{
-	int			err;
-	int			fd;
-	int			optval;
-	int 			optlen = sizeof (optval);
-	ipsec_req_t		ipsec_req;	/* For per-socket IPsec */
-	struct sockaddr_in6	sin6;		/* IPv6 listen socket   */
-
-	/*
-	 * Start by creating the socket, which needs to support IPv6.
-	 */
-	fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
-	if (fd == -1) {
-		cvcd_err(LOG_ERR, "socket: %s", strerror(errno));
-		exit(1);
-	}
-
-	/*
-	 * Set the SO_REUSEADDR option, and make the socket non-blocking.
-	 */
-	optval = 1;
-	err = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
-	if (err == -1) {
-		cvcd_err(LOG_ERR, "setsockopt: %s", strerror(errno));
-		exit(1);
-	}
-
-	err = ioctl(fd, FIONBIO, &optval);
-	if (err == -1) {
-		cvcd_err(LOG_ERR, "ioctl: %s", strerror(errno));
-		exit(1);
-	}
-
-	/*
-	 * Enable per-socket IPsec if the user specified an AH or ESP
-	 * algorithm to use and global policy is not in effect.
-	 */
-	if (!cvcd_global_policy() &&
-	    (ah_auth_alg != SADB_AALG_NONE || esp_encr_alg != SADB_EALG_NONE ||
-	    esp_auth_alg != SADB_AALG_NONE)) {
-		bzero(&ipsec_req, sizeof (ipsec_req));
-
-		/* Hardcoded values */
-		ipsec_req.ipsr_self_encap_req	= SELF_ENCAP_REQ;
-		/* User defined */
-		ipsec_req.ipsr_auth_alg		= ah_auth_alg;
-		ipsec_req.ipsr_esp_alg		= esp_encr_alg;
-		if (ah_auth_alg != SADB_AALG_NONE)
-			ipsec_req.ipsr_ah_req		= AH_REQ;
-		if (esp_encr_alg != SADB_EALG_NONE ||
-		    esp_auth_alg != SADB_AALG_NONE) {
-			ipsec_req.ipsr_esp_req		= ESP_REQ;
-			ipsec_req.ipsr_esp_auth_alg	= esp_auth_alg;
-		}
-
-		err = setsockopt(fd, IPPROTO_IPV6, IPV6_SEC_OPT,
-		    (void *)&ipsec_req, sizeof (ipsec_req));
-
-		if (err == -1) {
-			cvcd_err(LOG_ERR, "failed to enable per-socket IPsec");
-			cvcd_err(LOG_ERR, "setsockopt: %s", strerror(errno));
-			exit(1);
-		}
-	}
-
-	/*
-	 * Bind the socket to our local address and port.
-	 */
-	bzero(&sin6, sizeof (sin6));
-	sin6.sin6_family = AF_INET6;
-	sin6.sin6_port = htons(port);
-	sin6.sin6_addr = in6addr_any;
-	err = bind(fd, (struct sockaddr *)&sin6, sizeof (sin6));
-	if (err == -1) {
-		cvcd_err(LOG_ERR, "bind: %s", strerror(errno));
-		exit(1);
-	}
-
-	/*
-	 * Indicate that we want to accept connections on this socket.  Since we
-	 * only allow one connection at a time anyway, specify a maximum backlog
-	 * of 1.
-	 */
-	err = listen(fd, 1);
-	if (err == -1) {
-		cvcd_err(LOG_ERR, "listen: %s", strerror(errno));
-		exit(1);
-	}
-
-	return (fd);
-}
-
-
-/*
- * cvcd_do_network_console
- *
- * With established connections to the network and the redirection driver,
- * shuttle data between the two until something goes wrong.
- */
-static void
-cvcd_do_network_console(void)
-{
-	int	i;
-	int	err;
-	int	count;
-	short	revents;
-	int	input_len = 0;
-	int	output_len = 0;
-	int	input_off = 0;
-	int	output_off = 0;
-	char	input_buf[MAXPKTSZ];
-	char	output_buf[MAXPKTSZ];
-
-	for (;;) {
-		/*
-		 * Wait for activity on any of the open file descriptors, which
-		 * includes the ability to write data if we have any to write.
-		 * If poll() fails, break out of the network console processing
-		 * loop.
-		 */
-		pfds[LISTEN_PFD].events = POLLIN;
-		pfds[NETWORK_PFD].events = POLLIN;
-		if (output_len != 0) {
-			pfds[NETWORK_PFD].events |= POLLOUT;
-		}
-		pfds[REDIR_PFD].events = POLLIN;
-		if (input_len != 0) {
-			pfds[REDIR_PFD].events |= POLLOUT;
-		}
-		err = poll(pfds, NUM_PFDS, -1);
-		if (err == -1) {
-			cvcd_err(LOG_ERR, "poll: %s", strerror(errno));
-			break;
-		}
-
-		/*
-		 * If any errors or hangups were detected, or one of our file
-		 * descriptors is bad, bail out of the network console
-		 * processing loop.
-		 */
-		for (i = 0; i < NUM_PFDS; i++) {
-			revents = pfds[i].revents;
-			if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
-				cvcd_err(LOG_NOTICE,
-				    "poll: status on %s fd:%s%s%s",
-				    ((i == LISTEN_PFD) ? "listen" :
-				    ((i == NETWORK_PFD) ? "network" : "redir")),
-				    (revents & POLLERR) ? " error" : "",
-				    (revents & POLLHUP) ? " hangup" : "",
-				    (revents & POLLNVAL) ? " bad fd" : "");
-				goto fail;	/* 'break' wouldn't work here */
-			}
-		}
-
-		/*
-		 * Start by rejecting any connection attempts, since we only
-		 * allow one network connection at a time.
-		 */
-		if (pfds[LISTEN_PFD].revents & POLLIN) {
-			int	fd;
-
-			fd = accept(pfds[LISTEN_PFD].fd, NULL, NULL);
-			if (fd > 0) {
-				(void) close(fd);
-			}
-		}
-
-		/*
-		 * If we have data waiting to be written in one direction or the
-		 * other, go ahead and try to send the data on its way.  We're
-		 * going to attempt the writes regardless of whether the poll
-		 * indicated that the destinations are ready, because we want to
-		 * find out if either descriptor has a problem (e.g. broken
-		 * network link).
-		 * If an "unexpected" error is detected, give up and break out
-		 * of the network console processing loop.
-		 */
-		if (output_len != 0) {
-			count = write(pfds[NETWORK_PFD].fd,
-			    &(output_buf[output_off]), output_len);
-			if ((count == -1) && (errno != EAGAIN)) {
-				cvcd_err(LOG_ERR, "write(network): %s",
-				    strerror(errno));
-				break;
-			} else if (count > 0) {
-				output_len -= count;
-				if (output_len == 0) {
-					output_off = 0;
-				} else {
-					output_off += count;
-				}
-			}
-		}
-
-		if (input_len != 0) {
-			count = write(pfds[REDIR_PFD].fd,
-			    &(input_buf[input_off]), input_len);
-			if ((count == -1) && (errno != EAGAIN)) {
-				cvcd_err(LOG_ERR, "write(redir): %s",
-				    strerror(errno));
-				break;
-			} else if (count > 0) {
-				input_len -= count;
-				if (input_len == 0) {
-					input_off = 0;
-				} else {
-					input_off += count;
-				}
-			}
-		}
-
-		/*
-		 * Finally, take a look at each data source and, if there isn't
-		 * any residual data from that source still waiting to be
-		 * processed, see if more data can be read.  We don't want to
-		 * read more data from a source if we haven't finished
-		 * processing the last data we read from it because doing so
-		 * would maximize the amount of data lost if the network console
-		 * failed or was closed.
-		 * If an "unexpected" error is detected, give up and break out
-		 * of the network console processing loop.
-		 * The call to read() appears to be in the habit of returning 0
-		 * when you've read all of the data from a stream that has been
-		 * hung up, and poll apparently feels that that condition
-		 * justifies setting POLLIN, so we're going to treat 0 as an
-		 * error return from read().
-		 */
-		if ((output_len == 0) && (pfds[REDIR_PFD].revents & POLLIN)) {
-			count = read(pfds[REDIR_PFD].fd, output_buf, MAXPKTSZ);
-			if (count <= 0) {
-				/*
-				 * Reading 0 simply means there is no data
-				 * available, since this is a terminal.
-				 */
-				if ((count < 0) && (errno != EAGAIN)) {
-					cvcd_err(LOG_ERR, "read(redir): %s",
-					    strerror(errno));
-					break;
-				}
-			} else {
-				output_len = count;
-				output_off = 0;
-			}
-		}
-
-		if ((input_len == 0) && (pfds[NETWORK_PFD].revents & POLLIN)) {
-			count = read(pfds[NETWORK_PFD].fd, input_buf, MAXPKTSZ);
-			if (count <= 0) {
-				/*
-				 * Reading 0 here implies a hangup, since this
-				 * is a non-blocking socket that poll() reported
-				 * as having data available.  This will
-				 * typically occur when the console user drops
-				 * to OBP or intentially switches to IOSRAM
-				 * mode.
-				 */
-				if (count == 0) {
-					cvcd_err(LOG_NOTICE,
-					    "read(network): hangup detected");
-					break;
-				} else if (errno != EAGAIN) {
-					cvcd_err(LOG_ERR, "read(network): %s",
-					    strerror(errno));
-					break;
-				}
-			} else {
-				input_len = count;
-				input_off = 0;
-			}
-		}
-	} /* End forever loop */
-
-	/*
-	 * If we get here, something bad happened during an attempt to access
-	 * either the redirection driver or the network connection.  There
-	 * doesn't appear to be any way to avoid the possibility of losing
-	 * console input and/or input in that case, so we should at least report
-	 * the loss if it happens.
-	 * XXX - We could do more, but is it worth the effort?  Logging the
-	 *	 lost data would be pretty easy... actually preserving it
-	 *	 in the console flow would be a lot harder.  We're more robust
-	 *	 than the previous generation at this point, at least, so
-	 *	 perhaps that's enough for now?
-	 */
-fail:
-	if (input_len != 0) {
-		cvcd_err(LOG_ERR, "console input lost");
-	}
-	if (output_len != 0) {
-		cvcd_err(LOG_ERR, "console output lost");
-	}
-}
-
-
-static void
-cvcd_usage()
-{
-#if defined(DEBUG)
-	(void) printf("%s [-d] [-p port] "
-	    "[-a none|md5|sha1] [-e none|des|3des] [-u none|md5|sha1]\n",
-	    progname);
-#else
-	(void) printf("%s [-a none|md5|sha1] [-e none|des|3des] "
-	    "[-u none|md5|sha1]\n", progname);
-#endif  /* DEBUG */
-}
-
-/*
- * cvcd_err ()
- *
- * Description:
- * Log messages via syslog daemon.
- *
- * Input:
- * code - logging code
- * format - messages to log
- *
- * Output:
- * void
- *
- */
-static void
-cvcd_err(int code, char *format, ...)
-{
-	va_list	varg_ptr;
-	char	buf[MAXPKTSZ];
-
-	va_start(varg_ptr, format);
-	(void) vsnprintf(buf, MAXPKTSZ, format, varg_ptr);
-	va_end(varg_ptr);
-
-	if (debug == 0) {
-		syslog(code, buf);
-	} else {
-		(void) fprintf(stderr, "%s: %s\n", progname, buf);
-	}
-}
-
-/*
- * has_cvcd_token
- *
- * Look for "?port [cvc_hostd|442]" in input buf.
- * Assume only a single thread calls here.
- */
-static boolean_t
-has_cvcd_token(char *buf)
-{
-	char 		*token;
-	char		*delims = "{} \t\n";
-	boolean_t 	port = B_FALSE;
-
-	while ((token = strtok(buf, delims)) != NULL) {
-		buf = NULL;
-		if (port == B_TRUE) {
-			if (strcmp(token, "cvc_hostd") == 0 ||
-			    strcmp(token, "442") == 0) {
-				return (B_TRUE);
-			} else {
-				return (B_FALSE);
-			}
-		}
-		if (strlen(token) == 5) {
-			token++;
-			if (strcmp(token, "port") == 0) {
-				port = B_TRUE;
-				continue;
-			}
-		}
-	}
-	return (B_FALSE);
-}
-
-/*
- * cvcd_global_policy
- *
- * Check global policy file for cvcd entry. Just covers common cases.
- */
-static boolean_t
-cvcd_global_policy()
-{
-	FILE		*fp;
-	char		buf[256];
-	boolean_t	rv = B_FALSE;
-
-	fp = fopen("/etc/inet/ipsecinit.conf", "r");
-	if (fp == NULL)
-		return (B_FALSE);
-	while (fgets(buf, sizeof (buf), fp) != NULL) {
-		if (buf[0] == '#')
-			continue;
-		if (has_cvcd_token(buf)) {
-			rv = B_TRUE;
-			cvcd_err(LOG_NOTICE, "cvcd using global policy");
-			break;
-		}
-	}
-	(void) fclose(fp);
-	return (rv);
-}
--- a/usr/src/cmd/cvcd/svc-cvcd	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-#!/sbin/sh
-#
-# 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.
-# Copyright 2019 Peter Tribble.
-#
-# Start script for cvcd
-#
-# For modifying parameters passed to cvcd, do not edit
-# this script. Instead use svccfg(1m) to modify the SMF
-# repository. For example:
-#
-# svccfg
-# svc:> select system/cvc
-# svc:system/cvc> setprop cvc/ah_auth = "md5"
-# svc:/system/cvc> exit
-
-
-. /lib/svc/share/smf_include.sh
-
-getproparg() {
-	val=`svcprop -p $2 $SMF_FMRI`
-	[ -n "$val" ] && [ "$val" != 'none' ] &&  echo $1 $val
-}
-
-platform=`/sbin/uname -i`
-starcat="SUNW,Sun-Fire-15000" 
-
-if [ $platform = "$starcat" ]; then
-	args=""
-	args="$args `getproparg -a cvc/ah_auth`"
-	args="$args `getproparg -e cvc/esp_encr`"
-	args="$args `getproparg -u cvc/esp_auth`"
-	/platform/$platform/lib/cvcd $args	# Fail if can't execute
-	exit					# Use cvcd's exit status
-else
-	echo "$SMF_FMRI is not supported on this platform."
-	exit $SMF_EXIT_ERR_CONFIG
-fi
-
-exit 0
--- a/usr/src/cmd/dcs/sparc/sun4u/dcs.xml	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/dcs/sparc/sun4u/dcs.xml	Fri May 31 14:32:40 2019 +0200
@@ -4,6 +4,7 @@
 <!--
  Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  Use is subject to license terms.
+ Copyright 2019 Peter Tribble.
 
  CDDL HEADER START
 
@@ -24,8 +25,6 @@
 
  CDDL HEADER END
 
-	ident	"%Z%%M%	%I%	%E% SMI"
-
 	NOTE:  This service manifest is not editable; its contents will
 	be overwritten by package or patch operations, including
 	operating system upgrade.  Make customizations in a different
@@ -49,7 +48,7 @@
 			<service_fmri value='svc:/network/loopback' />
 	</dependency>
 
-	<!-- sckmd is required on OPL and Starcat but Not Starfile -->
+	<!-- sckmd is only required on OPL -->
 	<dependency
 		name='sckmd'
 		grouping='optional_all'
@@ -58,7 +57,7 @@
 			<service_fmri value='svc:/platform/sun4u/sckmd' />
 	</dependency>
 
-	<dependency 
+	<dependency
 		name='cryptosvc'
 		grouping='require_all'
 		restart_on='none'
@@ -66,7 +65,7 @@
 			<service_fmri value='svc:/system/cryptosvc' />
 	</dependency>
 
-	<dependency 
+	<dependency
 		name='filesystem_usr'
 		grouping='require_all'
 		restart_on='none'
@@ -96,13 +95,6 @@
 		timeout_seconds='60'>
 	</exec_method>
 
-	<!-- these are passed to dcs in the method script -->
-	<property_group name='dcs' type='application'>
-		<propval name='ah_auth' type='astring' value='md5' />
-		<propval name='esp_encr' type='astring' value='none' />
-		<propval name='esp_auth' type='astring' value='none' />
-	</property_group>
-
 	<stability value='Unstable' />
 
 	<template>
--- a/usr/src/cmd/dcs/sparc/sun4u/svc-dcs	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/dcs/sparc/sun4u/svc-dcs	Fri May 31 14:32:40 2019 +0200
@@ -27,40 +27,16 @@
 #
 # Start script for dcs
 #
-# For modifying parameters passed to dcs, do not edit
-# this script. Instead use svccfg(1m) to modify the SMF
-# repository. For example:
-#
-# svccfg
-# svc:> select platform/sun4u/dcs
-# svc:/platform/sun4u/dcs> setprop dcs/ah_auth = "md5"
-# svc:/platform/sun4u/dcs> exit
-
 
 . /lib/svc/share/smf_include.sh
 
-getproparg() {
-	val=`svcprop -p $2 $SMF_FMRI`
-	[ -n "$val" ] && [ "$val" != 'none' ] &&  echo $1 $val
-}
-
 DCS=/usr/lib/dcs
 platform=`/sbin/uname -i`
-sf15k="SUNW,Sun-Fire-15000"
 opl="SUNW,SPARC-Enterprise"
 
-args=""
-if [ $platform = "$sf15k" ]; then
-	args="$args `getproparg -a dcs/ah_auth`"
-	args="$args `getproparg -e dcs/esp_encr`"
-	args="$args `getproparg -u dcs/esp_auth`"
-elif [ $platform = "$opl" ]; then
-	args="-l"
-fi
-
-if [ $platform = "$sf15k" -o $platform = "$opl" ]; then
-	$DCS $args			# Fail if can't execute
-	exit				# Use dcs's exit status
+if [ $platform = "$opl" ]; then
+	$DCS -l			# Fail if can't execute
+	exit			# Use dcs's exit status
 else
 	echo "$SMF_FMRI is not supported on this platform."
 	exit $SMF_EXIT_ERR_CONFIG
--- a/usr/src/cmd/fm/eversholt/files/sparc/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/fm/eversholt/files/sparc/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -20,9 +20,10 @@
 #
 #
 # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2019 Peter Tribble.
 #
 
-SUBDIRS=sun4u sun4v SUNW,Sun-Fire-15000
+SUBDIRS=sun4u sun4v
 EFT_COMMON_FILES=		\
 	disk.eft		\
 	neptune_xaui.eft	\
@@ -31,7 +32,7 @@
 	pciex.eft		\
 	pciexrc.eft		\
 	sca500.eft		\
-	sca1000.eft 		\
+	sca1000.eft		\
 	sensor.eft		\
 	storage.eft
 
--- a/usr/src/cmd/fm/eversholt/files/sparc/SUNW,Sun-Fire-15000/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +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"
-
-EFT_PLAT= SUNW,Sun-Fire-15000 
-EFT_PLAT_FILES= SUNW,Sun-Fire-15000.eft
-
-include ../../Makefile.com
--- a/usr/src/cmd/fm/eversholt/files/sparc/SUNW,Sun-Fire-15000/SUNW,Sun-Fire-15000.esc	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#pragma dictionary "SUN4U"
-
-#define	AGENT_ID_MASK	0x1f
-#define	AGENT_ID_SHIFT	24
-
-#define CPU_FIT 500
-
-fru cpu;
-
-event fault.io.datapath@cpu, retire=0,
-    FITrate=CPU_FIT, FRU=cpu;
-
-event ereport.io.psy.ecc.pue@hostbridge{within(5s)};
-event ereport.io.sch.ecc.pue@hostbridge{within(5s)};
-event ereport.io.xmits.ecc.pue@hostbridge{within(5s)};
-event ereport.io.cpu.ecc.thresh@cpu;
-
-/*
- * For Starcat we need to apply the following logic to calculate the
- * Agentid of the system board in question.
- */
-prop fault.io.datapath@cpu[cpuid] (0)->
-    ereport.io.psy.ecc.pue@hostbridge
-    {((payloadprop("ecc-afsr") >> AGENT_ID_SHIFT) & AGENT_ID_MASK) ==
-    ((cpuid >> 5) & AGENT_ID_MASK)},
-    ereport.io.sch.ecc.pue@hostbridge
-    {((payloadprop("ecc-afsr") >> AGENT_ID_SHIFT) & AGENT_ID_MASK) ==
-    ((cpuid >> 5) & AGENT_ID_MASK)},
-    ereport.io.xmits.ecc.pue@hostbridge
-    {((payloadprop("ecc-afsr") >> AGENT_ID_SHIFT) & AGENT_ID_MASK) ==
-    ((cpuid >> 5) & AGENT_ID_MASK)},
-    ereport.io.cpu.ecc.thresh@cpu[cpuid];
-
-engine serd.io.cpu.ecc@cpu,
-    N=3, T=1day, method=persistent,
-    trip=ereport.io.cpu.ecc.thresh@cpu;
-
-event upset.io.datapath@cpu,
-    engine=serd.io.cpu.ecc@cpu;
-
-event ereport.io.psy.ecc.pce@hostbridge{within(5s)};
-event ereport.io.sch.ecc.pce@hostbridge{within(5s)};
-event ereport.io.xmits.ecc.pce@hostbridge{within(5s)};
-
-prop upset.io.datapath@cpu[cpuid] (0)->
-    ereport.io.psy.ecc.pce@hostbridge
-    {((payloadprop("ecc-afsr") >> AGENT_ID_SHIFT) & AGENT_ID_MASK) ==
-    ((cpuid >> 5) & AGENT_ID_MASK)},
-    ereport.io.sch.ecc.pce@hostbridge
-    {((payloadprop("ecc-afsr") >> AGENT_ID_SHIFT) & AGENT_ID_MASK) ==
-    ((cpuid >> 5) & AGENT_ID_MASK)},
-    ereport.io.xmits.ecc.pce@hostbridge
-    {((payloadprop("ecc-afsr") >> AGENT_ID_SHIFT) & AGENT_ID_MASK) ==
-    ((cpuid >> 5) & AGENT_ID_MASK)};
--- a/usr/src/cmd/fm/modules/sun4/cpumem-diagnosis/cmd_cpu.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/fm/modules/sun4/cpumem-diagnosis/cmd_cpu.c	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,7 @@
 /*
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2019 Peter Tribble.
  */
 
 /*
@@ -115,8 +116,6 @@
 }
 
 const char *fmd_fmri_get_platform();
-#define	is_starcat	(strcmp(fmd_fmri_get_platform(), \
-"SUNW,Sun-Fire-15000") == 0)
 #define	is_serengeti	(strcmp(fmd_fmri_get_platform(), \
 "SUNW,Sun-Fire") == 0)
 
@@ -127,8 +126,6 @@
 	switch (type) {
 #ifdef sun4u
 
-#define	US4P_SCAT_CPUS_PER_CORE		2
-#define	US4P_SCAT_CPU_CORE_STEP		4
 #define	US4P_SGTI_CPUS_PER_CORE		2
 #define	US4P_SGTI_CPU_CORE_STEP		512
 #define	US4P_DAKC_CPUS_PER_CORE		2
@@ -137,9 +134,7 @@
 	case CPU_ULTRASPARC_IVplus:
 		switch (level) {
 		case CMD_CPU_LEVEL_CORE:
-			if (is_starcat)
-				*cpustep = US4P_SCAT_CPU_CORE_STEP;
-			else if (is_serengeti)
+			if (is_serengeti)
 				*cpustep = US4P_SGTI_CPU_CORE_STEP;
 			else
 				*cpustep = US4P_DAKC_CPU_CORE_STEP;
@@ -207,22 +202,15 @@
 }
 
 uint32_t
-cmd_cpu2core(uint32_t cpuid, cmd_cpu_type_t type, uint8_t level) {
-
+cmd_cpu2core(uint32_t cpuid, cmd_cpu_type_t type, uint8_t level)
+{
 	switch (type) {
 #ifdef sun4u
 
-#define	US4P_SCAT_CORE_SYSBD_STEP	32
-
 	case CPU_ULTRASPARC_IVplus:
 		switch (level) {
 		case CMD_CPU_LEVEL_CORE:
-			if (is_starcat)
-				return ((cpuid /
-				    US4P_SCAT_CORE_SYSBD_STEP) *
-				    US4P_SCAT_CORE_SYSBD_STEP +
-				    (cpuid % US4P_SCAT_CPU_CORE_STEP));
-			else if (is_serengeti)
+			if (is_serengeti)
 				return (cpuid % US4P_SGTI_CPU_CORE_STEP);
 			else
 				return (cpuid % US4P_DAKC_CPU_CORE_STEP);
--- a/usr/src/cmd/fm/modules/sun4u/datapath-retire/cda_main.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/fm/modules/sun4u/datapath-retire/cda_main.c	Fri May 31 14:32:40 2019 +0200
@@ -25,7 +25,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
 
 #include <cda.h>
 
@@ -175,8 +177,7 @@
 		return (0);
 	}
 
-	if (strcmp(buf, "SUNW,Sun-Fire-15000") == 0 ||
-	    strcmp(buf, "SUNW,Sun-Fire") == 0 ||
+	if (strcmp(buf, "SUNW,Sun-Fire") == 0 ||
 	    strcmp(buf, "SUNW,Netra-T12") == 0)
 		return (1);
 	else
@@ -209,7 +210,7 @@
 	cda.cda_cpu_delay.tv_nsec = nsec % NANOSEC;
 
 	cda.cda_cpu_dooffline = fmd_prop_get_int32(hdl,
-		"cpu_offline_enable");
+	    "cpu_offline_enable");
 	cda.cda_cpu_forcedoffline = fmd_prop_get_int32(hdl,
 	    "cpu_forced_offline");
 }
--- a/usr/src/cmd/fm/schemes/mem/mem_unum.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/fm/schemes/mem/mem_unum.c	Fri May 31 14:32:40 2019 +0200
@@ -24,7 +24,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
 
 #include <mem.h>
 #include <fm/fmd_fmri.h>
@@ -113,7 +115,7 @@
 };
 
 /*
- * Burst Serengeti and Starcat-style unums.
+ * Burst Serengeti-style unums.
  * A DIMM unum string is expected to be in this form:
  * "[/N0/]SB12/P0/B0/D2 [J13500]"
  * A bank unum string is expected to be in this form:
@@ -259,12 +261,11 @@
 	const char *platform = fmd_fmri_get_platform();
 
 	/*
-	 * Call mem_unum_burst_sgsc() for Starcat, Serengeti, and
+	 * Call mem_unum_burst_sgsc() for Serengeti and
 	 * Lightweight 8 platforms.  Call mem_unum_burst_pattern()
 	 * for all other platforms.
 	 */
-	if (strcmp(platform, "SUNW,Sun-Fire-15000") == 0 ||
-	    strcmp(platform, "SUNW,Sun-Fire") == 0 ||
+	if (strcmp(platform, "SUNW,Sun-Fire") == 0 ||
 	    strcmp(platform, "SUNW,Netra-T12") == 0)
 		return (mem_unum_burst_sgsc(pat, dimmsp, ndimmsp));
 	else
--- a/usr/src/cmd/mdb/Makefile.common	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/mdb/Makefile.common	Fri May 31 14:32:40 2019 +0200
@@ -22,7 +22,7 @@
 #
 # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
 # Copyright 2016 Joyent, Inc.
-# Copyright 2017 Nexenta Systems, Inc.
+# Copyright 2018 Nexenta Systems, Inc.
 #
 
 #
@@ -38,6 +38,7 @@
 	libfknsmb \
 	libfksmbfs \
 	libfksmbsrv \
+	libmlsvc \
 	libnvpair \
 	libproc \
 	libpython \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/libmlsvc/mlsvc.c	Fri May 31 14:32:40 2019 +0200
@@ -0,0 +1,197 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * mdb module for libmlsvc, which contains interesting data structures
+ * including: the share cache
+ */
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
+
+#include <synch.h>
+#include <smbsrv/hash_table.h>
+#include <smbsrv/libsmb.h>
+#include <smbsrv/smb_share.h>
+
+#define	MLSVC_OBJNAME	"libmlsvc.so.1"
+#define	MLSVC_SCOPE	MLSVC_OBJNAME "`"
+
+#define	AFLAG		1
+#define	VFLAG		2
+
+typedef struct dump_shr_args {
+	uint_t dsa_opts;
+	uintptr_t dsa_hdl;
+	smb_share_t dsa_shr;
+} dump_shr_args_t;
+
+/*ARGSUSED*/
+static int
+dump_shr_cb(uintptr_t addr, const void *data, void *varg)
+{
+	dump_shr_args_t *args = varg;
+	const HT_ITEM *hi = data;
+	smb_share_t *shr = &args->dsa_shr;
+
+	if (hi->hi_data == NULL)
+		return (WALK_NEXT);
+
+	if ((hi->hi_flags & HT_DELETE) != 0 &&
+	    (args->dsa_opts & AFLAG) == 0)
+		return (WALK_NEXT);
+
+	if (args->dsa_opts & VFLAG) {
+		mdb_arg_t argv;
+		int flags = DCMD_ADDRSPEC;
+
+		argv.a_type = MDB_TYPE_STRING;
+		argv.a_un.a_str = MLSVC_SCOPE "smb_share_t";
+		/* Don't fail the walk if this fails. */
+		mdb_printf("%-?p ", hi->hi_data);
+		mdb_call_dcmd("print", (uintptr_t)hi->hi_data,
+		    flags, 1, &argv);
+	} else {
+		if (mdb_vread(shr, sizeof (*shr),
+		    (uintptr_t)hi->hi_data) == -1) {
+			mdb_warn("failed to read %s at %p",
+			    "smb_share_t", hi->hi_data);
+			return (WALK_NEXT);
+		}
+
+		mdb_printf("%-?p ", hi->hi_data);
+		mdb_printf("name=%s path=%s desc=\"%s\"\n",
+		    shr->shr_name, shr->shr_path, shr->shr_cmnt);
+	}
+
+	return (WALK_NEXT);
+}
+
+
+/*
+ * *************************** Top level dcmds ****************************
+ */
+
+typedef struct mdb_smb_shr_cache {
+	HT_HANDLE	*sc_cache;
+	rwlock_t	sc_cache_lck;
+	mutex_t		sc_mtx;
+	cond_t		sc_cv;
+	uint32_t	sc_state;
+	uint32_t	sc_nops;
+} mdb_smb_shr_cache_t;
+
+
+static void
+smb_shr_cache_help(void)
+{
+	mdb_printf(
+	    "Displays the list of shares in the smbd smb_shr_cache.\n"
+	    "With -a, also show deleted entries.\n"
+	    "With -v, print full smb_share_t objects.\n\n");
+}
+
+/*
+ * ::smb_shr_cache
+ */
+/*ARGSUSED*/
+static int
+smb_shr_cache_dcmd(uintptr_t addr, uint_t flags, int argc,
+    const mdb_arg_t *argv)
+{
+	dump_shr_args_t *args;
+	mdb_smb_shr_cache_t *ssc;
+
+	args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC);
+
+	if (mdb_getopts(argc, argv,
+	    'a', MDB_OPT_SETBITS, AFLAG, &args->dsa_opts,
+	    'v', MDB_OPT_SETBITS, VFLAG, &args->dsa_opts,
+	    NULL) != argc)
+		return (DCMD_USAGE);
+
+	if (!(flags & DCMD_ADDRSPEC)) {
+		GElf_Sym	sym;
+
+		/* Locate the shr hash head. */
+		if (mdb_lookup_by_obj(MLSVC_OBJNAME, "smb_shr_cache", &sym)) {
+			mdb_warn("failed to lookup `smb_shr_cache'\n");
+			return (DCMD_ERR);
+		}
+		addr = sym.st_value;
+	}
+
+	ssc = mdb_zalloc(sizeof (*ssc), UM_SLEEP | UM_GC);
+	if (mdb_ctf_vread(ssc, MLSVC_SCOPE "smb_shr_cache_t",
+	    "mdb_smb_shr_cache_t", addr, 0) < 0) {
+		mdb_warn("failed to read smb_shr_cache at %p", addr);
+		return (DCMD_ERR);
+	}
+
+	/* Now walk HT_HANDLE *sc_cache */
+	args->dsa_hdl = (uintptr_t)ssc->sc_cache;
+
+	if (mdb_pwalk(MLSVC_SCOPE "smb_ht_walker",
+	    dump_shr_cb, args, args->dsa_hdl) == -1) {
+		mdb_warn("cannot walk smb_shr_cache list");
+		return (DCMD_ERR);
+	}
+	return (DCMD_OK);
+}
+
+
+
+/*
+ * MDB module linkage information:
+ *
+ * We declare a list of structures describing our dcmds, a list of structures
+ * describing our walkers and a function named _mdb_init to return a pointer
+ * to our module information.
+ */
+static const mdb_dcmd_t dcmds[] = {
+
+	/* Avoiding name conflict with smbsrv`smb_shr_cache */
+	{   "smbd_shr_cache",
+	    "[-av]",
+	    "print SMB share cache",
+	    smb_shr_cache_dcmd,
+	    smb_shr_cache_help },
+
+	{ NULL }
+};
+
+int smb_ht_walk_init(mdb_walk_state_t *wsp);
+int smb_ht_walk_step(mdb_walk_state_t *wsp);
+
+static const mdb_walker_t walkers[] = {
+	{   "smb_ht_walker",
+	    "walk an smb_hash_t structure",
+	    smb_ht_walk_init,
+	    smb_ht_walk_step,
+	    NULL,
+	    NULL },
+	{ NULL }
+};
+
+static const mdb_modinfo_t modinfo = {
+	MDB_API_VERSION, dcmds, walkers
+};
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+	return (&modinfo);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c	Fri May 31 14:32:40 2019 +0200
@@ -0,0 +1,106 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * walker for libsmb : smb_ht.c (hash tables)
+ */
+
+#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
+
+#include <smbsrv/hash_table.h>
+
+/* smb_ht_walk info */
+struct hw_info {
+	HT_HANDLE hw_handle;	/* struct ht_handle being walked */
+	HT_TABLE_ENTRY hw_tblent;
+	HT_ITEM hw_item;
+	int hw_idx;
+};
+
+/*
+ * Walker for libsmb/smb_ht.c code.  Calls the call-back function with
+ * each HT_ITEM object.  Top-level is HT_HANDLE, passed to _walk_init.
+ */
+int
+smb_ht_walk_init(mdb_walk_state_t *wsp)
+{
+	struct hw_info *hw;
+	uintptr_t addr = wsp->walk_addr;
+	HT_HANDLE *ht;
+
+	if (addr == NULL) {
+		mdb_printf("require address of an HT_HANDLE\n");
+		return (WALK_ERR);
+	}
+
+	/*
+	 * allocate the AVL walk data
+	 */
+	wsp->walk_data = hw = mdb_zalloc(sizeof (*hw), UM_GC|UM_SLEEP);
+
+	/*
+	 * get an mdb copy of the HT_HANDLE being walked
+	 */
+	ht = &hw->hw_handle;
+	if (mdb_vread(ht, sizeof (*ht), wsp->walk_addr) == -1) {
+		mdb_warn("failed to read %s at %#lx",
+		    "HT_HANDLE", wsp->walk_addr);
+		return (WALK_ERR);
+	}
+
+	hw->hw_idx = -1;
+	wsp->walk_addr = NULL;
+	wsp->walk_data = hw;
+
+	return (WALK_NEXT);
+}
+
+int
+smb_ht_walk_step(mdb_walk_state_t *wsp)
+{
+	struct hw_info *hw = wsp->walk_data;
+	HT_TABLE_ENTRY *he = &hw->hw_tblent;
+	HT_ITEM *hi = &hw->hw_item;
+	uintptr_t he_addr;
+	int rv;
+
+	while (wsp->walk_addr == NULL) {
+		if (++hw->hw_idx >= hw->hw_handle.ht_table_size)
+			return (WALK_DONE);
+		he_addr = (uintptr_t)hw->hw_handle.ht_table +
+		    (hw->hw_idx * sizeof (HT_TABLE_ENTRY));
+		if (mdb_vread(he, sizeof (*he), he_addr) == -1) {
+			mdb_warn("failed to read %s at %p",
+			    "HT_TABLE_ENTRY", wsp->walk_addr);
+			return (WALK_ERR);
+		}
+		wsp->walk_addr = (uintptr_t)he->he_head;
+	}
+
+	if (mdb_vread(hi, sizeof (*hi), wsp->walk_addr) == -1) {
+		mdb_warn("failed to read %s at %p",
+		    "HT_ITEM", wsp->walk_addr);
+		return (WALK_ERR);
+	}
+
+	rv = wsp->walk_callback(wsp->walk_addr, hi,
+	    wsp->walk_cbdata);
+
+	wsp->walk_addr = (uintptr_t)hi->hi_next;
+
+	return (rv);
+}
--- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <mdb/mdb_modapi.h>
@@ -2092,20 +2092,37 @@
 typedef struct mdb_smb_node {
 	smb_node_state_t	n_state;
 	uint32_t		n_refcnt;
-
 	uint32_t		n_open_count;
 	uint32_t		n_opening_count;
 	smb_llist_t		n_ofile_list;
 	smb_llist_t		n_lock_list;
 	volatile int		flags;
-	smb_node_fcn_t		n_fcn;
 	smb_oplock_t		n_oplock;
 	struct smb_node		*n_dnode;
 	struct smb_node		*n_unode;
 	char			od_name[MAXNAMELEN];
 	vnode_t			*vp;
 	smb_audit_buf_node_t	*n_audit_buf;
+	/* Newer members (not in old kernels) - keep last! */
+	smb_llist_t		n_wlock_list;
 } mdb_smb_node_t;
+typedef struct mdb_smb_node_old {
+	/* Note: MUST be layout as above! */
+	smb_node_state_t	n_state;
+	uint32_t		n_refcnt;
+	uint32_t		n_open_count;
+	uint32_t		n_opening_count;
+	smb_llist_t		n_ofile_list;
+	smb_llist_t		n_lock_list;
+	volatile int		flags;
+	smb_oplock_t		n_oplock;
+	struct smb_node		*n_dnode;
+	struct smb_node		*n_unode;
+	char			od_name[MAXNAMELEN];
+	vnode_t			*vp;
+	smb_audit_buf_node_t	*n_audit_buf;
+	/* Newer members omitted from _old */
+} mdb_smb_node_old_t;
 
 static void
 smbnode_help(void)
@@ -2130,6 +2147,7 @@
 static int
 smbnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 {
+	static smb_llist_t zero_llist = {0};
 	mdb_smb_node_t	node;
 	int		rc;
 	int		verbose = FALSE;
@@ -2162,34 +2180,21 @@
 	}
 
 	/*
-	 * If this is the first invocation of the command, print a nice
-	 * header line for the output that will follow.
-	 */
-	if (DCMD_HDRSPEC(flags)) {
-		if (verbose) {
-			mdb_printf("%<b>%<u>SMB node information:%</u>%</b>\n");
-		} else {
-			mdb_printf(
-			    "%<b>%<u>%-?s "
-			    "%-?s "
-			    "%-18s "
-			    "%-6s "
-			    "%-6s "
-			    "%-8s "
-			    "%-6s%</u>%</b>\n",
-			    "ADDR", "VP", "NODE-NAME", "OFILES", "LOCKS",
-			    "OPLOCK", "REF");
-		}
-	}
-
-	/*
 	 * For each smb_node, we just need to read the smb_node_t struct, read
 	 * and then print out the following fields.
 	 */
 	if (mdb_ctf_vread(&node, SMBSRV_SCOPE "smb_node_t",
 	    "mdb_smb_node_t", addr, 0) < 0) {
-		mdb_warn("failed to read struct smb_node at %p", addr);
-		return (DCMD_ERR);
+		/*
+		 * Fall-back handling for mdb_smb_node_old_t
+		 * Should remove after a while.
+		 */
+		if (mdb_ctf_vread(&node, SMBSRV_SCOPE "smb_node_t",
+		    "mdb_smb_node_old_t", addr, 0) < 0) {
+			mdb_warn("failed to read struct smb_node at %p", addr);
+			return (DCMD_ERR);
+		}
+		node.n_wlock_list = zero_llist;
 	}
 
 	(void) mdb_snprintf(od_name, sizeof (od_name), "%s",
@@ -2205,25 +2210,43 @@
 		}
 	}
 	if (verbose) {
-		int nll_off, nol_off, ll_off;
+		int nll_off, wll_off, nol_off, ll_off;
 
 		GET_OFFSET(nll_off, smb_node_t, n_lock_list);
 		GET_OFFSET(nol_off, smb_node_t, n_oplock);
 		GET_OFFSET(ll_off, smb_llist_t, ll_list);
-
+		/* This one is optional (for now). */
+		/* GET_OFFSET(wll_off, smb_node_t, n_wlock_list); */
+		wll_off = mdb_ctf_offsetof_by_name(
+		    "smb_node_t", "n_wlock_list");
+
+		mdb_printf("%<b>%<u>SMB node information "
+		    "(%p):%</u>%</b>\n", addr);
 		mdb_printf("VP: %p\n", node.vp);
 		mdb_printf("Name: %s\n", od_name);
 		if (print_full_path)
 			mdb_printf("V-node Path: %s\n", path_name);
 		mdb_printf("Ofiles: %u\n", node.n_ofile_list.ll_count);
-		mdb_printf("Range Locks: %u\n",
+		mdb_printf("Granted Locks: %u\n",
 		    node.n_lock_list.ll_count);
 		if (node.n_lock_list.ll_count != 0) {
 			(void) mdb_inc_indent(SMB_DCMD_INDENT);
 			list_addr = addr + nll_off + ll_off;
 			if (mdb_pwalk_dcmd("list", "smblock", 0,
 			    NULL, list_addr)) {
-				mdb_warn("failed to walk node's active"
+				mdb_warn("failed to walk node's granted"
+				    " locks");
+			}
+			(void) mdb_dec_indent(SMB_DCMD_INDENT);
+		}
+		mdb_printf("Waiting Locks: %u\n",
+		    node.n_wlock_list.ll_count);
+		if (node.n_wlock_list.ll_count != 0 && wll_off != -1) {
+			(void) mdb_inc_indent(SMB_DCMD_INDENT);
+			list_addr = addr + wll_off + ll_off;
+			if (mdb_pwalk_dcmd("list", "smblock", 0,
+			    NULL, list_addr)) {
+				mdb_warn("failed to walk node's waiting"
 				    " locks");
 			}
 			(void) mdb_dec_indent(SMB_DCMD_INDENT);
@@ -2241,9 +2264,23 @@
 		}
 		mdb_printf("Reference Count: %u\n\n", node.n_refcnt);
 	} else {
-		mdb_printf("%-?p %-?p %-18s %-6d %-6d %-8d %-6d ",
+		if (DCMD_HDRSPEC(flags)) {
+			mdb_printf(
+			    "%<b>%<u>%-?s "
+			    "%-?s "
+			    "%-18s "
+			    "%-6s "
+			    "%-6s "
+			    "%-8s "
+			    "%-8s "
+			    "%-6s%</u>%</b>\n",
+			    "ADDR", "VP", "NODE-NAME", "OFILES", "LOCKS",
+			    "WLOCKS", "OPLOCK", "REF");
+		}
+
+		mdb_printf("%-?p %-?p %-18s %-6d %-6d %-8d %-8d %-6d ",
 		    addr, node.vp, od_name, node.n_ofile_list.ll_count,
-		    node.n_lock_list.ll_count,
+		    node.n_lock_list.ll_count, node.n_wlock_list.ll_count,
 		    node.n_oplock.ol_count, node.n_refcnt);
 
 		if (print_full_path)
@@ -2374,28 +2411,33 @@
  */
 
 typedef struct mdb_smb_lock {
-	smb_slist_t		l_conflict_list;
-
-	smb_session_t		*l_session;
 	smb_ofile_t		*l_file;
-	struct smb_request	*l_sr;
-
-	uint32_t		l_flags;
-	struct smb_lock		*l_blocked_by; /* Debug info only */
-
-	uint32_t		l_pid;
-	uint16_t		l_uid;
-	uint32_t		l_type;
+	struct smb_lock		*l_blocked_by;
 	uint64_t		l_start;
 	uint64_t		l_length;
+	uint32_t		l_pid;
+	uint32_t		l_type;
+	uint32_t		l_flags;
+	/* Newer members (not in old kernels) - keep last! */
+	uint32_t		l_conflicts;
 } mdb_smb_lock_t;
+typedef struct mdb_smb_lock_old {
+	/* Note: MUST be same layout as above! */
+	smb_ofile_t		*l_file;
+	struct smb_lock		*l_blocked_by;
+	uint64_t		l_start;
+	uint64_t		l_length;
+	uint32_t		l_pid;
+	uint32_t		l_type;
+	uint32_t		l_flags;
+	/* Newer members omitted from _old */
+} mdb_smb_lock_old_t;
 
 static int
 smblock_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 {
 	mdb_smb_lock_t	lock;
 	int		verbose = FALSE;
-	uintptr_t	list_addr;
 	char		*lock_type;
 
 	if (mdb_getopts(argc, argv,
@@ -2409,23 +2451,18 @@
 	if (!(flags & DCMD_ADDRSPEC))
 		return (DCMD_USAGE);
 
-	/*
-	 * If this is the first invocation of the command, print a nice
-	 * header line for the output that will follow.
-	 */
-	if (DCMD_HDRSPEC(flags)) {
-		if (verbose)
-			mdb_printf("SMB lock information:\n\n");
-		else
-			mdb_printf("%<u>%-?s %4s %16s %8s %9s%</u>\n",
-			    "Locks: ", "TYPE", "START", "LENGTH",
-			    "CONFLICTS");
-	}
-
 	if (mdb_ctf_vread(&lock, SMBSRV_SCOPE "smb_lock_t",
 	    "mdb_smb_lock_t", addr, 0) < 0) {
-		mdb_warn("failed to read struct smb_request at %p", addr);
-		return (DCMD_ERR);
+		/*
+		 * Fall-back handling for mdb_smb_lock_old_t
+		 * Should remove after a while.
+		 */
+		if (mdb_ctf_vread(&lock, SMBSRV_SCOPE "smb_lock_t",
+		    "mdb_smb_lock_old_t", addr, 0) < 0) {
+			mdb_warn("failed to read struct smb_lock at %p", addr);
+			return (DCMD_ERR);
+		}
+		lock.l_conflicts = 0;
 	}
 
 	switch (lock.l_type) {
@@ -2436,50 +2473,39 @@
 		lock_type = "RO";
 		break;
 	default:
-		lock_type = "N/A";
+		lock_type = "?";
 		break;
 	}
 	if (verbose) {
-		int lcl_off, sl_off;
-
-		GET_OFFSET(lcl_off, smb_lock_t, l_conflict_list);
-		GET_OFFSET(sl_off, smb_slist_t, sl_list);
+		mdb_printf("%<b>%<u>SMB lock information "
+		    "(%p):%</u>%</b>\n", addr);
 
 		mdb_printf("Type             :\t%s (%u)\n",
 		    lock_type, lock.l_type);
-		mdb_printf("Start            :\t%llx\n",
+		mdb_printf("Start            :\t%llu\n",
 		    lock.l_start);
-		mdb_printf("Length           :\t%lx\n",
+		mdb_printf("Length           :\t%llu\n",
 		    lock.l_length);
-		mdb_printf("Session          :\t%p\n",
-		    lock.l_session);
-		mdb_printf("File             :\t%p\n",
+		mdb_printf("OFile            :\t%p\n",
 		    lock.l_file);
-		mdb_printf("User ID          :\t%u\n",
-		    lock.l_uid);
 		mdb_printf("Process ID       :\t%u\n",
 		    lock.l_pid);
 		mdb_printf("Conflicts        :\t%u\n",
-		    lock.l_conflict_list.sl_count);
-		if (lock.l_conflict_list.sl_count != 0) {
-			(void) mdb_inc_indent(SMB_DCMD_INDENT);
-			list_addr = addr + lcl_off + sl_off;
-			if (mdb_pwalk_dcmd("list", "smb_lock",
-			    0, NULL, list_addr)) {
-				mdb_warn("failed to walk conflict "
-				    "locks ");
-			}
-			(void) mdb_dec_indent(SMB_DCMD_INDENT);
-		}
+		    lock.l_conflicts);
 		mdb_printf("Blocked by       :\t%p\n",
 		    lock.l_blocked_by);
 		mdb_printf("Flags            :\t0x%x\n",
 		    lock.l_flags);
 		mdb_printf("\n");
 	} else {
-		mdb_printf("%?p %4s %16llx %08lx %9x", addr,
-		    lock_type, lock.l_start, lock.l_length,
-		    lock.l_conflict_list.sl_count);
+		if (DCMD_HDRSPEC(flags)) {
+			mdb_printf("%<u>%-?s %4s %16s %8s %9s %-?s%</u>\n",
+			    "Locks: ", "TYPE", "START", "LENGTH",
+			    "CONFLICTS", "BLOCKED-BY");
+		}
+		mdb_printf("%?p %4s %16llx %08llx %9u %?p",
+		    addr, lock_type, lock.l_start, lock.l_length,
+		    lock.l_conflicts, lock.l_blocked_by);
 	}
 
 	return (DCMD_OK);
@@ -2494,10 +2520,6 @@
 typedef struct mdb_smb_oplock_grant {
 	uint8_t			og_breaking;
 	uint8_t			og_level;
-	uint16_t		og_fid;
-	uint16_t		og_tid;
-	uint16_t		og_uid;
-	struct smb_session	*og_session;
 	struct smb_ofile	*og_ofile;
 } mdb_smb_oplock_grant_t;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/amd64/libmlsvc/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+# Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
+#
+
+MODULE = libmlsvc.so
+MDBTGT = proc
+
+MODSRCS = mlsvc.c smb_ht.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/libmlsvc
+
+# CPPFLAGS += -I$(SRC)/lib/smbsrv/libmlsvc
+CPPFLAGS += -I$(SRC)/uts/common
+
+CSTD=	$(CSTD_GNU99)
+C99MODE=	-xc99=%all
+C99LMODE=	-Xc99=%all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/ia32/libmlsvc/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+# Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
+#
+
+MODULE = libmlsvc.so
+MDBTGT = proc
+
+MODSRCS = mlsvc.c smb_ht.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/libmlsvc
+
+# CPPFLAGS += -I$(SRC)/lib/smbsrv/libmlsvc
+CPPFLAGS += -I$(SRC)/uts/common
+
+CSTD=	$(CSTD_GNU99)
+C99MODE=	-xc99=%all
+C99LMODE=	-Xc99=%all
--- a/usr/src/cmd/psrinfo/psrinfo.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/psrinfo/psrinfo.c	Fri May 31 14:32:40 2019 +0200
@@ -752,7 +752,7 @@
 		return (EXIT_SUCCESS);
 	}
 
-	if (opt_t != NULL) {
+	if (opt_t != 0) {
 		if (optind != argc)
 			usage(_("cannot specify CPUs with -t"));
 		if (opt_s || opt_v)
--- a/usr/src/cmd/sckmd/sparc/sun4u/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/sckmd/sparc/sun4u/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,7 @@
 #
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
+# Copyright 2019 Peter Tribble.
 #
 # Makefile definitions for Sun Fire 15000 Key Management Daemon (sckmd)
 #
@@ -50,7 +51,7 @@
 #
 # FLAGS:
 #
-CPPFLAGS= 	-I$(USR_PSM_INCL_DIR) -I$(SRC)/uts/sun4u/starcat $(CPPFLAGS.master)
+CPPFLAGS=	-I$(USR_PSM_INCL_DIR) -I$(SRC)/uts/sun4u/opl $(CPPFLAGS.master)
 
 LINT_FLAGS=	-c -Nlevel=4 -Ncheck
 
--- a/usr/src/cmd/sckmd/svc-sckmd	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/sckmd/svc-sckmd	Fri May 31 14:32:40 2019 +0200
@@ -22,8 +22,7 @@
 #
 # Copyright 2006 Sun Microsystems, Inc.	 All rights reserved.
 # Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
+# Copyright 2019 Peter Tribble.
 #
 
 #
@@ -33,13 +32,11 @@
 . /lib/svc/share/smf_include.sh
 
 platform=${_INIT_UTS_PLATFORM:-`/sbin/uname -i`}
-starcat="SUNW,Sun-Fire-15000" 
-opl="SUNW,SPARC-Enterprise" 
+opl="SUNW,SPARC-Enterprise"
 sckmd="/usr/platform/sun4u/lib/sckmd"
 
-if [ ${platform} = "${starcat}" -o  \
-     ${platform} = "${opl}" ]; then
-	if [ -x ${sckmd} ]; then 
+if [ ${platform} = "${opl}" ]; then
+	if [ -x ${sckmd} ]; then
 		${sckmd}
 		exit $SMF_EXIT_OK
 	fi
--- a/usr/src/cmd/smbsrv/fksmbd/fksmbd_shr.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_shr.c	Fri May 31 14:32:40 2019 +0200
@@ -123,3 +123,13 @@
 
 	return (NULL);
 }
+
+void
+smb_shr_load_execinfo()
+{
+}
+
+void
+smb_shr_unload()
+{
+}
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -1406,13 +1406,14 @@
 		/*
 		 * We are given a SID.  Just use it.
 		 *
-		 * We'e like the real account type if we can get it,
+		 * We'd like the real account type if we can get it,
 		 * but don't want to error out if we can't get it.
+		 * Lacking other info, assume it's a group.
 		 */
 		sidstr = mname;
 		rc = smb_lookup_sid(sidstr, &acct);
 		if ((rc != 0) || (acct.a_status != NT_STATUS_SUCCESS))
-			acct.a_sidtype = SidTypeUnknown;
+			acct.a_sidtype = SidTypeGroup;
 	} else {
 		rc = smb_lookup_name(mname, SidTypeUnknown, &acct);
 		if ((rc != 0) || (acct.a_status != NT_STATUS_SUCCESS)) {
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
@@ -630,7 +630,9 @@
 	/* This reloads the in-kernel config. */
 	(void) smbd_kernel_bind();
 
-	smbd_load_shares();
+	/* On refresh load share properties only, not the shares themselves */
+	smb_shr_load_execinfo();
+
 	smbd_load_printers();
 	smbd_spool_start();
 }
@@ -689,7 +691,7 @@
 smbd_already_running(void)
 {
 	door_info_t	info;
-	char 		*door_name;
+	char		*door_name;
 	int		door;
 
 	door_name = getenv("SMBD_DOOR_NAME");
@@ -833,6 +835,10 @@
 		smbd_report("unable to load disk shares: %s", strerror(errno));
 }
 
+/*
+ * This wrapper function is used to avoid casting smb_shr_load() in
+ * pthread_create() above. It is called very infrequently.
+ */
 static void *
 smbd_share_loader(void *args)
 {
--- a/usr/src/cmd/svc/profile/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/svc/profile/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -42,7 +42,6 @@
 	ns_nis.xml \
 	ns_none.xml \
 	platform_SUNW,SPARC-Enterprise.xml \
-	platform_SUNW,Sun-Fire-15000.xml \
 	platform_SUNW,Sun-Fire-880.xml \
 	platform_SUNW,Sun-Fire.xml \
 	platform_SUNW,UltraSPARC-IIi-Netract.xml \
--- a/usr/src/cmd/svc/profile/platform_SUNW,Sun-Fire-15000.xml	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<?xml version='1.0'?>
-<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
-<!--
- Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (the "License").
- You may not use this file except in compliance with the License.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
-    ident	"%Z%%M%	%I%	%E% SMI"
-
-    NOTE:  This service profile is not editable; its contents will be
-    overwritten by package or patch operations, including operating
-    system upgrade.
-
-    SunFire 15000 platform service profile.
--->
-<service_bundle type='profile' name='default'>
-	<service name='system/cvc' version='1' type='service'>
-		<instance name='default' enabled='true'/>
-	</service>
-	<service name='platform/sun4u/dcs' version='1' type='service'>
-		<instance name='default' enabled='true'/>
-	</service>
-	<service name='platform/sun4u/efdaemon' version='1' type='service'>
-		<instance name='default' enabled='true'/>
-	</service>
-	<service name='platform/sun4u/sckmd' version='1' type='service'>
-		<instance name='default' enabled='true'/>
-	</service>
-</service_bundle>
--- a/usr/src/cmd/vtfontcvt/vtfontcvt.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/cmd/vtfontcvt/vtfontcvt.c	Fri May 31 14:32:40 2019 +0200
@@ -243,12 +243,12 @@
 static int
 dedup_mapping(unsigned int map_idx)
 {
-	struct mapping *mp_bold, *mp_normal;
+	struct mapping *tmp, *mp_bold, *mp_normal;
 	unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD;
 
 	assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RH);
 	mp_normal = TAILQ_FIRST(&maps[normal_map_idx]);
-	TAILQ_FOREACH(mp_bold, &maps[map_idx], m_list) {
+	TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, tmp) {
 		while (mp_normal->m_char < mp_bold->m_char)
 			mp_normal = TAILQ_NEXT(mp_normal, m_list);
 		if (mp_bold->m_char != mp_normal->m_char)
--- a/usr/src/common/acl/acl_common.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/common/acl/acl_common.c	Fri May 31 14:32:40 2019 +0200
@@ -1636,7 +1636,7 @@
 int
 acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count)
 {
-	int 		index = 0;
+	int		index = 0;
 	int		error;
 	trivial_acl_t	masks;
 
@@ -1696,7 +1696,7 @@
 	uint64_t cookie = 0;
 
 	while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))
-	    != NULL) {
+	    != 0) {
 		switch (flags & ACE_TYPE_FLAGS) {
 		case ACE_OWNER:
 		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
--- a/usr/src/lib/cfgadm_plugins/Makefile.com	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/cfgadm_plugins/Makefile.com	Fri May 31 14:32:40 2019 +0200
@@ -53,7 +53,6 @@
 LINKED_PLATFORMS	+= SUNW,Sun-Fire-V250
 LINKED_PLATFORMS	+= SUNW,Sun-Fire-V440
 LINKED_PLATFORMS	+= SUNW,Sun-Fire-280R
-LINKED_PLATFORMS	+= SUNW,Sun-Fire-15000
 LINKED_PLATFORMS	+= SUNW,Sun-Fire-880
 LINKED_PLATFORMS	+= SUNW,Sun-Fire-480R
 LINKED_PLATFORMS	+= SUNW,Sun-Fire-V890
--- a/usr/src/lib/fm/topo/maps/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/fm/topo/maps/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -23,6 +23,7 @@
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 # Copyright (c) 2018, Joyent, Inc.
+# Copyright 2019 Peter Tribble.
 #
 
 sparc_SUBDIRS =	sun4u \
@@ -30,7 +31,6 @@
 		sparc \
 		SUNW,Sun-Fire \
 		SUNW,Sun-Fire-T200 \
-		SUNW,Sun-Fire-15000 \
 		SUNW,SPARC-Enterprise \
 		SUNW,Sun-Blade-T6300 \
 		SUNW,Sun-Blade-T6320 \
--- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +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.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-
-PLATFORMS = SUNW,Sun-Fire-15000
-CLASS = platform
-DTDFILE = topology.dtd.1
-TOPOFILE = Sun-Fire-15000-hc-topology.xml
-SRCDIR = ../SUNW,Sun-Fire-15000
-
-include ../Makefile.map
--- a/usr/src/lib/fm/topo/maps/SUNW,Sun-Fire-15000/Sun-Fire-15000-hc-topology.xml	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1">
-<!--
- Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- Use is subject to license terms.
-
- CDDL HEADER START
-
- The contents of this file are subject to the terms of the
- Common Development and Distribution License (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"
--->
-
-<topology name='SUNW,Sun-Fire-15000' scheme='hc'>
-  <range name='interconnect' min='0' max='0'>
-    <node instance='0'>
-      <propgroup name='protocol' version='1'
-        name-stability='Private' data-stability='Private' >
-        <propval name='FRU' type='fmri'
-          value='hc:///component=interconnect' />
-        <propval name='label' type='string'
-          value='interconnect' />
-      </propgroup>
-    </node>
-    <dependents grouping='children'>
-      <range name='ioboard' min='0' max='17'>
-        <enum-method name='ioboard' version='1' />
-      </range>
-      <range name='cpu' min='0' max='100'>
-        <enum-method name='chip' version='1' />
-      </range>
-    </dependents>
-  </range>
-  <range name='ses-enclosure' min='0' max='1024'>
-     <enum-method name='ses' version='1' />
-  </range>
-</topology>
--- a/usr/src/lib/fm/topo/modules/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/fm/topo/modules/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -22,13 +22,12 @@
 #
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
+# Copyright 2019 Peter Tribble.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
 
 sparc_SUBDIRS =	sun4u \
 		sun4v \
 		SUNW,Sun-Fire \
-		SUNW,Sun-Fire-15000 \
 		SUNW,SPARC-Enterprise
 
 i386_SUBDIRS = i86pc
--- a/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +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"
-
-SUBDIRS = ioboard
-
-.PARALLEL: $(SUBDIRS)
-
-include ../../../Makefile.subdirs
--- a/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +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"
-
-CLASS = plat
-PLATFORMS = SUNW,Sun-Fire-15000
-
-include ../../sun4/ioboard/Makefile.iob
--- a/usr/src/lib/fm/topo/modules/SUNW,Sun-Fire-15000/ioboard/iob_platform.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +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"
-
-/*
- * SUNW,Sun-Fire platform ioboard topology enumerator
- */
-
-#include <string.h>
-#include <libdevinfo.h>
-#include <fm/topo_mod.h>
-#include <fm/topo_hc.h>
-
-#include <did.h>
-#include <hostbridge.h>
-#include <ioboard.h>
-#include <util.h>
-
-/*ARGSUSED*/
-int
-platform_iob_label(topo_mod_t *mod, tnode_t *node, nvlist_t *ignored,
-    nvlist_t **out)
-{
-	/*
-	 * For E15K, the label is simply IOXX where XX is the
-	 * instance number of the ioboard.
-	 */
-	char buf[10];	/* up to a million I/O boards :-) */
-
-	*out = NULL;
-	(void) snprintf(buf, 10, "IO%d", topo_node_instance(node));
-	if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) == 0 &&
-	    nvlist_add_string(*out, TOPO_METH_LABEL_RET_STR, buf) == 0)
-		return (0);
-	nvlist_free(*out);
-	*out = NULL;
-	return (-1);
-}
-
-#define	IOB_BASEADDR	0x1c
-#define	BUS_ADDRDIST	0x20
-
-/*ARGSUSED*/
-int
-platform_iob_enum(topo_mod_t *mod, tnode_t *parent, topo_instance_t imin,
-    topo_instance_t imax)
-{
-	/*
-	 * An E15K and its successors may have up to 18 I/O boards,
-	 * numbered 0 through 17.  Each board has two hostbridges, and
-	 * there are a pair of PCI buses under each hostbridge.  We can
-	 * discover the existence of a board by the presence of
-	 * devinfo nodes for those hostbridges.  We let the hostbridge
-	 * enumerator actually create nodes for the hostbridges,
-	 * passing them the did_t's for all the hostbridge nodes we
-	 * know indicate that the ioboard exists.
-	 */
-	di_node_t devtree;
-	di_node_t pnode;
-	did_t *iobs[18][2][2];
-	int brd, br, bus, i;
-
-	devtree = topo_mod_devinfo(mod);
-	if (devtree == DI_NODE_NIL) {
-		topo_mod_dprintf(mod, "devinfo init failed.");
-		return (-1);
-	}
-
-	for (i = 0; i < 18; i++) {
-		iobs[i][0][0] = iobs[i][0][1] = NULL;
-		iobs[i][1][0] = iobs[i][1][1] = NULL;
-	}
-
-	pnode = di_drv_first_node(SCHIZO, devtree);
-	while (pnode != DI_NODE_NIL) {
-		did_t *d;
-
-		d = split_bus_address(mod,
-		    pnode, IOB_BASEADDR, BUS_ADDRDIST, 0, 17, &brd, &br, &bus);
-		if (d == NULL) {
-			pnode = di_drv_next_node(pnode);
-			continue;
-		}
-		iobs[brd][br][bus] = d;
-		pnode = di_drv_next_node(pnode);
-	}
-
-	for (i = 0; i < 18; i++) {
-		tnode_t *ion;
-		/*
-		 * Make sure we found all the buses and bridges
-		 */
-		if (iobs[i][0][0] == NULL || iobs[i][0][1] == NULL ||
-		    iobs[i][1][0] == NULL || iobs[i][1][1] == NULL)
-			continue;
-		did_did_link_set(iobs[i][0][0], iobs[i][0][1]);
-		did_did_link_set(iobs[i][1][0], iobs[i][1][1]);
-		did_did_chain_set(iobs[i][0][0], iobs[i][1][0]);
-		if ((ion = ioboard_declare(mod, parent, i, iobs[i][0][0]))
-		    == NULL) {
-			topo_mod_dprintf(mod,
-			    "Creation of tnode for %s%d failed.\n", IOBOARD, i);
-			continue;
-		}
-		if (topo_mod_enumerate(mod, ion, HOSTBRIDGE, HOSTBRIDGE, 0, 0,
-		    iobs[i][0][0]) < 0) {
-			topo_mod_dprintf(mod,
-			    "Enumeration of %s%d/%s%d failed.\n",
-			    IOBOARD, i, HOSTBRIDGE, 0);
-			continue;
-		}
-		if (topo_mod_enumerate(mod, ion, HOSTBRIDGE, HOSTBRIDGE, 1, 1,
-		    iobs[i][0][0]) < 0) {
-			topo_mod_dprintf(mod,
-			    "Enumeration of %s%d/%s%d failed.\n",
-			    IOBOARD, i, HOSTBRIDGE, 1);
-			continue;
-		}
-	}
-	return (0);
-}
--- a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
  */
 
 /*
@@ -773,8 +773,8 @@
 	char		*s;
 	int64_t		*nblocksp;
 	uint64_t	nblocks;
-	int		*dblksizep;
-	uint_t		dblksize;
+	int		*blksizep;
+	uint_t		blksize;
 	char		lentry[MAXPATHLEN];
 	int		pathcount;
 	int		*inq_dtype, itype;
@@ -1032,15 +1032,15 @@
 		nblocks = (uint64_t)*nblocksp;
 		/*
 		 * To save kernel memory, the driver may not define
-		 * "device-dblksize" when its value is default DEV_BSIZE.
+		 * "device-blksize" when its value is default DEV_BSIZE.
 		 */
 		if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
-		    "device-dblksize", &dblksizep) > 0)
-			dblksize = (uint_t)*dblksizep;
+		    "device-blksize", &blksizep) > 0)
+			blksize = (uint_t)*blksizep;
 		else
-			dblksize = DEV_BSIZE;		/* default value */
+			blksize = DEV_BSIZE;		/* default value */
 		(void) snprintf(lentry, sizeof (lentry),
-		    "%" PRIu64, nblocks * dblksize);
+		    "%" PRIu64, nblocks * blksize);
 		if ((dnode->ddn_cap = topo_mod_strdup(mod, lentry)) == NULL)
 			goto error;
 	}
--- a/usr/src/lib/libc/capabilities/sun4u-us3/common/mapfile-cap	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/libc/capabilities/sun4u-us3/common/mapfile-cap	Fri May 31 14:32:40 2019 +0200
@@ -34,7 +34,6 @@
 	PLATFORM += "SUNW,Sun-Blade-1000";
 	PLATFORM += "SUNW,Sun-Blade-1500";
 	PLATFORM += "SUNW,Sun-Blade-2500";
-	PLATFORM += "SUNW,Sun-Fire-15000";
 	PLATFORM += "SUNW,Sun-Fire-280R";
 	PLATFORM += "SUNW,Sun-Fire-480R";
 	PLATFORM += "SUNW,Sun-Fire-880";
--- a/usr/src/lib/libfakekernel/Makefile.com	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/libfakekernel/Makefile.com	Fri May 31 14:32:40 2019 +0200
@@ -18,6 +18,7 @@
 VERS =		.1
 
 COBJS = \
+	callout.o \
 	clock.o \
 	cond.o \
 	copy.o \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libfakekernel/common/callout.c	Fri May 31 14:32:40 2019 +0200
@@ -0,0 +1,96 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
+ */
+
+/*
+ * Implement timeout(9f), untimeout(9f) on top of
+ * libc timer_create, timer_settime, etc.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <time.h>
+
+typedef void (*sigev_notify_func_t)(union sigval);
+
+/*
+ * We never actually reference anything in this array, using it
+ * just as a collection of addresses mapped from/to int values.
+ * It would be fine to take addresses even beyond the end, but
+ * to avoid confusion it's sized larger than _TIMER_MAX (32).
+ */
+static char timeout_base[100];
+
+timeout_id_t
+timeout(void (*func)(void *), void *arg, clock_t delta)
+{
+	struct sigevent sev;
+	struct itimerspec its;
+	timer_t tid;
+	int err;
+
+	if (delta <= 0)
+		return (NULL);
+
+	bzero(&sev, sizeof (sev));
+	sev.sigev_notify = SIGEV_THREAD;
+	sev.sigev_value.sival_ptr = arg;
+	sev.sigev_notify_function = (sigev_notify_func_t)func;
+	err = timer_create(CLOCK_REALTIME, &sev, &tid);
+	if (err != 0)
+		return (NULL);
+
+	bzero(&its, sizeof (its));
+	TICK_TO_TIMESTRUC(delta, &its.it_value);
+	err = timer_settime(tid, 0, &its, NULL);
+	if (err != 0) {
+		(void) timer_delete(tid);
+		return (NULL);
+	}
+
+	/* Convert return to a (sort of) pointer */
+	return (timeout_base + tid);
+}
+
+clock_t
+untimeout(timeout_id_t id_arg)
+{
+	struct itimerspec its;
+	char *id_cp = id_arg;
+	clock_t delta;
+	timer_t tid;
+	int rc;
+
+	if (id_arg == NULL)
+		return (-1);
+
+	/* Convert id_arg back to small integer. */
+	tid = (int)(id_cp - timeout_base);
+
+	bzero(&its, sizeof (its));
+	rc = timer_settime(tid, 0, &its, &its);
+	if (rc != 0) {
+		delta = 0;
+	} else {
+		delta = TIMESTRUC_TO_TICK(&its.it_value);
+		if (delta < 0)
+			delta = 0;
+	}
+
+	rc = timer_delete(tid);
+	if (rc != 0)
+		delta = -1;
+
+	return (delta);
+}
--- a/usr/src/lib/libfakekernel/common/mapfile-vers	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/libfakekernel/common/mapfile-vers	Fri May 31 14:32:40 2019 +0200
@@ -228,9 +228,11 @@
 	tsd_destroy;
 
 	tick_per_msec;
+	timeout;
 	tsignal;
 	uiomove;
 	uioskip;
+	untimeout;
 	usec_per_tick;
 	vcmn_err;
 	vmem_qcache_reap;
--- a/usr/src/lib/libprtdiag_psr/sparc/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/libprtdiag_psr/sparc/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -26,7 +26,7 @@
 # lib/libprtdiag_psr/sparc/Makefile
 
 PRTDIAG_PLATFORMS=	desktop tazmo javelin sunfire serengeti \
-			montecarlo littleneck starcat daktari cherrystone \
+			montecarlo littleneck daktari cherrystone \
 			lw8 snowbird ontario schumacher opl montoya monza
 
 all :=		TARGET= all
--- a/usr/src/lib/libprtdiag_psr/sparc/starcat/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# lib/libprtdiag_psr/sparc/starcat/Makefile
-
-UTSBASE   = ../../../../uts
-
-PLATFORM_OBJECTS= starcat.o
-
-include ../Makefile.com
-
-IFLAGS = -I$(USR_PLAT_DIR)/sun4u/include -I ../../../libprtdiag/inc
-LINTFLAGS += $(IFLAGS)
-
-PLATFORM=SUNW,Sun-Fire-15000
-
-$(USR_PLAT_DIR)/$(PLATFORM)/lib/libprtdiag_psr.so.1 := FILEMODE= 0755
-
-.KEEP_STATE:
-
-PLATLIBS= $(USR_PLAT_DIR)/$(PLATFORM)/lib/
-
-install:	all $(USR_PSM_LIBS)
-
-$(USR_PSM_LIB_DIR):
-	cd $(UTSBASE)/sun4u/starcat; $(MAKE) $(USR_PSM_LIB_DIR)
-
-#
-# install rule
-#
-$(USR_PSM_LIB_DIR)/%: % $(USR_PSM_LIB_DIR)
-	$(INS.file)
-
-#
-# used for message files
-#
-POFILE=         libprtdiag_psr_starcat.po
-POFILES=        starcat.po
-
-
-_msg:   $(MSGDOMAIN) $(POFILE)
-	$(RM) $(MSGDOMAIN)/$(POFILE)
-	$(CP) $(POFILE) $(MSGDOMAIN)
-
-$(POFILE):      $(POFILES)
-	$(RM) $@
-	$(CAT) $(POFILES) > $@
-
-$(POFILES):
-	$(RM) messages.po
-	$(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext common/starcat.c`
-	$(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@
-	$(RM) messages.po
--- a/usr/src/lib/libprtdiag_psr/sparc/starcat/common/starcat.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1168 +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.
- *
- * Starcat Platform specific functions.
- *
- * 	called when :
- *	machine_type == MTYPE_STARCAT
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <string.h>
-#include <kvm.h>
-#include <varargs.h>
-#include <time.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/utsname.h>
-#include <sys/openpromio.h>
-#include <libintl.h>
-#include <syslog.h>
-#include <sys/dkio.h>
-#include <pdevinfo.h>
-#include <display.h>
-#include <pdevinfo_sun4u.h>
-#include <display_sun4u.h>
-#include <libprtdiag.h>
-
-#define	HZ_TO_MHZ(x)		(((x) + 500000) / 1000000)
-#define	PORTID_TO_EXPANDER(p)	(((p) >> 5) & 0x1f)
-#define	PORTID_TO_SLOT(p)	(((p) >> 3) & 0x1)
-#define	PORTID_TO_INSTANCE(p)	((p) & 0x3)
-#define	SCHIZO_COMPATIBLE	"pci108e,8001"
-#define	XMITS_COMPATIBLE	"pci108e,8002"
-#define	SC_BOARD_TYPE(id)	(PORTID_TO_SLOT(id) ? "IO" : "SB")
-
-#ifndef	TEXT_DOMAIN
-#define	TEXT_DOMAIN	"SYS_TEST"
-#endif	/* TEXT_DOMAIN */
-
-#define	DEFAULT_MAX_FREQ	66	/* 66 MHz */
-#define	PCIX_MAX_FREQ		90	/* 90 MHz */
-
-/*
- * these functions will overlay the symbol table of libprtdiag
- * at runtime (Starcat systems only)
- */
-
-int	do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag);
-void	*get_prop_val(Prop *prop);
-Prop	*find_prop(Prom_node *pnode, char *name);
-char	*get_node_name(Prom_node *pnode);
-char	*get_node_type(Prom_node *pnode);
-void	add_node(Sys_tree *, Prom_node *);
-void	display_pci(Board_node *);
-void	display_ffb(Board_node *, int);
-void	display_io_cards(struct io_card *list);
-void	display_cpu_devices(Sys_tree *tree);
-void	display_cpus(Board_node *board);
-void	display_memoryconf(Sys_tree *tree, struct grp_info *grps);
-void	print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
-	    char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id);
-void	display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
-		struct system_kstat_data *kstats);
-
-/* Local Functions */
-static void	starcat_disp_hw_revisions(Prom_node *root);
-static void display_io_max_bus_speed(struct io_card *p);
-static void display_io_slot_info(struct io_card *p);
-
-/* The bus max freq is determined based on board level in use */
-int	board_bus_max_freq = DEFAULT_MAX_FREQ;	/* 66MHz default */
-
-/*
- * display_pci
- * Display all the PCI IO cards on this board.
- */
-void
-display_pci(Board_node *board)
-{
-	struct io_card *card_list = NULL;
-	struct io_card card;
-	void *value;
-	Prom_node *pci;
-	Prom_node *card_node;
-	Prom_node *pci_bridge_node = NULL;
-	char	*slot_name_arr[MAX_SLOTS_PER_IO_BD] = {NULL};
-	char	*slot_name = NULL;
-	int	slot_name_bits;
-	int	slot_name_offset = 0;
-	char	*child_name;
-	char	*name, *type;
-	char	buf[MAXSTRLEN];
-	int	*int_val;
-	int	pci_bus;
-	int	pci_bridge = 0;
-	int	pci_bridge_dev_no;
-	int	child_dev_no;
-	int	i;
-	int	portid;
-	int	version, *pversion;
-
-	if (board == NULL)
-		return;
-
-	/* Initialize all the common information */
-	card.display = TRUE;
-	card.board = board->board_num;
-	card.node_id = board->node_id;
-
-	/*
-	 * Search for each schizo, then find/display all nodes under
-	 * each schizo node found.  Since the model property "SUNW,schizo"
-	 * is not supported on Starcat, we must match on the compatible
-	 * property "pci108e,8001".
-	 */
-	for (pci = dev_find_node_by_compatible(board->nodes, SCHIZO_COMPATIBLE);
-	    pci != NULL;
-	    pci = dev_next_node_by_compatible(pci, SCHIZO_COMPATIBLE)) {
-
-		/* set max freq for this board */
-		board_bus_max_freq = DEFAULT_MAX_FREQ;
-		/*
-		 * Find out if this is a PCI or cPCI IO Board.
-		 * If "enum-impl" property exists in pci node => cPCI.
-		 */
-		value = get_prop_val(find_prop(pci, "enum-impl"));
-		if (value == NULL) {
-			(void) sprintf(card.bus_type, "PCI");
-		} else {
-			(void) sprintf(card.bus_type, "cPCI");
-		}
-
-		if (strstr((char *)get_prop_val(
-		    find_prop(pci, "compatible")), XMITS_COMPATIBLE)) {
-			sprintf(card.notes, "%s", XMITS_COMPATIBLE);
-			/*
-			 * With XMITS 3.X and PCI-X mode, the bus speed
-			 * can be higher than 66MHZ.
-			 */
-			value = (int *)get_prop_val
-			    (find_prop(pci, "module-revision#"));
-			if (value) {
-				pversion = (int *)value;
-				version = *pversion;
-				if (version >= 4)
-					board_bus_max_freq = PCIX_MAX_FREQ;
-			}
-		} else if (strstr((char *)get_prop_val(
-		    find_prop(pci, "compatible")), SCHIZO_COMPATIBLE))
-			sprintf(card.notes, "%s", SCHIZO_COMPATIBLE);
-		else
-			sprintf(card.notes, " ");
-
-		/*
-		 * Get slot-names property from parent node and
-		 * store the individual slot names in an array.
-		 * This is more general than Starcat requires, but
-		 * it is correct, according to the slot-names property.
-		 */
-		value = (char *)get_prop_val(find_prop(pci, "slot-names"));
-		if (value == NULL) {
-			/*
-			 * No slot_names property.  This could be an Xmits
-			 * card, so check the child node for slot-names property
-			 */
-			value = (char *)get_prop_val(
-			    find_prop(pci->child, "slot-names"));
-		}
-
-		if (value != NULL) {
-			/* Get the 4 byte bitmask and pointer to first name */
-			slot_name_bits = *(int *)value;
-			if (slot_name_bits > 0)
-				slot_name_offset = slot_name_bits - 1;
-			slot_name = (char *)value + sizeof (int);
-
-			for (i = 0; i < MAX_SLOTS_PER_IO_BD; i++) {
-				if (! (slot_name_bits & (1 << i))) {
-					slot_name_arr[i] = (char *)NULL;
-					continue;
-				}
-
-				/*
-				 * Save the name pointer into the array
-				 * and advance it past the end of this
-				 * slot name
-				 */
-				slot_name_arr[i] = slot_name;
-				slot_name += strlen(slot_name) + 1;
-			}
-			slot_name = (char *)NULL;
-		}
-
-		/*
-		 * Search for Children of this node ie. Cards.
-		 * Note: any of these cards can be a pci-bridge
-		 *	that itself has children. If we find a
-		 *	pci-bridge we need to handle it specially.
-		 */
-		card_node = pci->child;
-		while (card_node != NULL) {
-			pci_bridge = 0;
-
-			/* If it doesn't have a name, skip it */
-			name = (char *)get_prop_val(
-			    find_prop(card_node, "name"));
-			if (name == NULL) {
-				card_node = card_node->sibling;
-				continue;
-			}
-
-			/*
-			 * get dev# and func# for this card from the
-			 * 'reg' property.
-			 */
-			int_val = (int *)get_prop_val(
-			    find_prop(card_node, "reg"));
-			if (int_val != NULL) {
-				card.dev_no = (((*int_val) & 0xF800) >> 11);
-				card.func_no = (((*int_val) & 0x700) >> 8);
-			} else {
-				card.dev_no = -1;
-				card.func_no = -1;
-			}
-
-			/*
-			 * If this is a pci-bridge, then store it's dev#
-			 * as its children nodes need this to get their slot#.
-			 * We set the pci_bridge flag so that we know we are
-			 * looking at a pci-bridge node. This flag gets reset
-			 * every time we enter this while loop.
-			 */
-
-			/*
-			 * Check for a PCI-PCI Bridge for PCI and cPCI
-			 * IO Boards using the name and type properties.
-			 */
-			type = (char *)get_prop_val(
-			    find_prop(card_node, "device_type"));
-			if ((type != NULL) &&
-			    (strncmp(name, "pci", 3) == 0) &&
-			    (strcmp(type, "pci") == 0)) {
-				pci_bridge_dev_no = card.dev_no;
-				pci_bridge_node = card_node;
-				pci_bridge = TRUE;
-			}
-
-			/*
-			 * Get slot-names property from slot_names_arr.
-			 * If we are the child of a pci_bridge we use the
-			 * dev# of the pci_bridge as an index to get
-			 * the slot number. We know that we are a child of
-			 * a pci-bridge if our parent is the same as the last
-			 * pci_bridge node found above.
-			 */
-			if (card.dev_no != -1) {
-				/*
-				 * We compare this card's parent node with the
-				 * pci_bridge_node to see if it's a child.
-				 */
-				if (card_node->parent == pci_bridge_node) {
-					/* use dev_no of pci_bridge */
-					child_dev_no = pci_bridge_dev_no - 1;
-				} else {
-					/* use card's own dev_no */
-					child_dev_no = card.dev_no - 1;
-				}
-
-				if (child_dev_no < MAX_SLOTS_PER_IO_BD &&
-				    child_dev_no >= 0 &&
-				    slot_name_arr
-				    [child_dev_no + slot_name_offset] != NULL) {
-
-					slot_name = slot_name_arr[
-					    child_dev_no + slot_name_offset];
-				} else
-					slot_name = (char *)NULL;
-
-				if (slot_name != NULL && slot_name[0] != '\0') {
-					(void) sprintf(card.slot_str, "%s",
-					    slot_name);
-				} else {
-					(void) sprintf(card.slot_str, "-");
-				}
-			} else {
-				(void) sprintf(card.slot_str, "%c", '-');
-			}
-
-			/*
-			 * Get the portid of the schizo that this card
-			 * lives under.
-			 */
-			portid = -1;
-			value = get_prop_val(find_prop(pci, "portid"));
-			if (value != NULL) {
-				portid = *(int *)value;
-			}
-			card.schizo_portid = portid;
-
-#ifdef	DEBUG
-			(void) sprintf(card.notes, "%s portid [%d]"
-			    " dev_no [%d] slot_name[%s] name_bits[%#x]",
-			    card.notes, portid, card.dev_no,
-			    ((slot_name != NULL) ? slot_name : "NULL"),
-			    slot_name_bits);
-#endif	/* DEBUG */
-
-			/*
-			 * Find out whether this is PCI bus A or B
-			 * using the 'reg' property.
-			 */
-			int_val = (int *)get_prop_val
-			    (find_prop(pci, "reg"));
-
-			if (int_val != NULL) {
-				int_val ++; /* skip over first integer */
-				pci_bus = ((*int_val) & 0x7f0000);
-				if (pci_bus == 0x600000)
-					card.pci_bus = 'A';
-				else if (pci_bus == 0x700000)
-					card.pci_bus = 'B';
-				else
-					card.pci_bus = '-';
-			} else {
-				card.pci_bus = '-';
-			}
-
-
-			/*
-			 * Check for failed status.
-			 */
-			if (node_failed(card_node))
-				strcpy(card.status, "fail");
-			else
-				strcpy(card.status, "ok");
-
-			/* Get the model of this card */
-			value = get_prop_val(find_prop(card_node, "model"));
-			if (value == NULL)
-				card.model[0] = '\0';
-			else {
-				(void) sprintf(card.model, "%s", (char *)value);
-				/*
-				 * If we wish to exclude onboard devices
-				 * (such as SBBC) then this is the place
-				 * and here is how to do it:
-				 *
-				 * if (strcmp(card.model, "SUNW,sbbc") == 0) {
-				 *	card_node = card_node->sibling;
-				 *	continue;
-				 * }
-				 */
-			}
-
-			/*
-			 * The card may have a "clock-frequency" but we
-			 * are not interested in that. Instead we get the
-			 * "clock-frequency" of the PCI Bus that the card
-			 * resides on. PCI-A can operate at 33Mhz or 66Mhz
-			 * depending on what card is plugged into the Bus.
-			 * PCI-B always operates at 33Mhz.
-			 *
-			 */
-			int_val = get_prop_val(find_prop(pci,
-			    "clock-frequency"));
-			if (int_val != NULL) {
-				card.freq = HZ_TO_MHZ(*int_val);
-			} else {
-				card.freq = -1;
-			}
-
-			/*
-			 * Figure out how we want to display the name
-			 */
-			value = get_prop_val(find_prop(card_node,
-			    "compatible"));
-			if (value != NULL) {
-				/* use 'name'-'compatible' */
-				(void) sprintf(buf, "%s-%s", name,
-				    (char *)value);
-			} else {
-				/* just use 'name' */
-				(void) sprintf(buf, "%s", name);
-			}
-			name = buf;
-
-			/*
-			 * If this node has children, add the device_type
-			 * of the child to the name value of this card.
-			 */
-			child_name = (char *)get_node_name(card_node->child);
-			if ((card_node->child != NULL) &&
-			    (child_name != NULL)) {
-				value = get_prop_val(find_prop(card_node->child,
-				    "device_type"));
-				if (value != NULL) {
-					/* add device_type of child to name */
-					(void) sprintf(card.name, "%s/%s (%s)",
-					    name, child_name,
-					    (char *)value);
-				} else {
-					/* just add child's name */
-					(void) sprintf(card.name, "%s/%s",
-					    name, child_name);
-				}
-			} else {
-				/* childless, just the card's name */
-				(void) sprintf(card.name, "%s", (char *)name);
-			}
-
-			/*
-			 * If this is a pci-bridge, then add the word
-			 * 'pci-bridge' to its model.
-			 */
-			if (pci_bridge) {
-				if (card.model[0] == '\0')
-					(void) sprintf(card.model,
-					    "%s", "pci-bridge");
-				else
-					(void) strcat(card.model,
-					    "/pci-bridge");
-			}
-
-			/* insert this card in the list to be displayed later */
-			card_list = insert_io_card(card_list, &card);
-
-			/*
-			 * If we are dealing with a pci-bridge, we need to move
-			 * down to the children of this bridge, if there are
-			 * any, otherwise its siblings.
-			 *
-			 * If not a bridge, we are either dealing with a regular
-			 * card (in which case we move onto the sibling of this
-			 * card) or we are dealing with a child of a pci-bridge
-			 * (in which case we move onto the child's siblings or
-			 * if there are no more siblings for this child, we
-			 * move onto the parent's siblings).  I hope you're
-			 * getting all this, there will be an exam later.
-			 */
-			if (pci_bridge) {
-				if (card_node->child != NULL)
-					card_node = card_node->child;
-				else
-					card_node = card_node->sibling;
-			} else {
-				/*
-				 * If our parent is a pci-bridge but there
-				 * are no more of its children to process we
-				 * move back up to our parent's sibling,
-				 * otherwise we move onto our own sibling.
-				 */
-				if ((card_node->parent == pci_bridge_node) &&
-				    (card_node->sibling == NULL))
-					card_node =
-					    pci_bridge_node->sibling;
-				else
-					card_node = card_node->sibling;
-			}
-
-		} /* end while (card_node ...) loop */
-
-	} /* end for (pci ...) loop */
-
-	display_io_cards(card_list);
-	free_io_cards(card_list);
-}
-
-/*
- * display_ffb
- *
- * There are no FFB's on a Starcat, however in the generic library,
- * the display_ffb() function is implemented so we have to define an
- * empty function here.
- */
-/*ARGSUSED0*/
-void
-display_ffb(Board_node *board, int table)
-{
-}
-
-/*
- * add_node
- *
- * This function adds a board node to the board structure where that
- * that node's physical component lives.
- */
-void
-add_node(Sys_tree *root, Prom_node *pnode)
-{
-	int	portid = -1;
-	int	nodeid = -1;
-	void	*value;
-	Board_node	*bnode;
-	Prom_node	*p;
-	char	*type;
-
-	/* Get the board number of this board from the portid prop */
-	if ((value = get_prop_val(find_prop(pnode, "portid"))) == NULL) {
-		if (type = get_node_type(pnode))
-			if (strcmp(type, "cpu") == 0)
-				value = get_prop_val(find_prop(pnode->parent,
-				    "portid"));
-	}
-	if (value != NULL) {
-		portid = *(int *)value;
-		nodeid = PORTID_TO_EXPANDER(portid);
-	}
-
-	/* find the board node with the same board number */
-	if ((bnode = find_board(root, portid)) == NULL) {
-		bnode = insert_board(root, portid);
-		bnode->board_type = UNKNOWN_BOARD;
-		bnode->node_id = nodeid;
-	}
-
-	/* now attach this prom node to the board list */
-	/* Insert this node at the end of the list */
-	pnode->sibling = NULL;
-	if (bnode->nodes == NULL)
-		bnode->nodes = pnode;
-	else {
-		p = bnode->nodes;
-		while (p->sibling != NULL)
-			p = p->sibling;
-		p->sibling = pnode;
-	}
-}
-
-
-
-/*
- * Print out all the io cards in the list.  Also print the column
- * headers if told to do so.
- */
-void
-display_io_cards(struct io_card *list)
-{
-	char	*hdrfmt = "%-10.10s  %-4.4s %-4.4s %-4.4s %-4.4s %-4.4s"
-	    " %-4.4s %-5.5s %-32.32s  %-22.22s"
-#ifdef	DEBUG
-	    "  %-22.22s"
-#endif	/* DEBUG */
-	    "\n";
-
-	static int banner = FALSE; /* Have we printed the column headings? */
-	struct io_card *p;
-
-	if (list == NULL)
-		return;
-
-	(void) textdomain(TEXT_DOMAIN);
-
-	if (banner == FALSE) {
-		log_printf(hdrfmt,
-		    "", "", "", "",
-		    gettext("Bus"),
-		    gettext("Max"),
-		    "", "", "", "",
-#ifdef	DEBUG
-		    "",
-#endif	/* DEBUG */
-		    0);
-
-		log_printf(hdrfmt,
-		    "",
-		    gettext("IO"),
-		    gettext("Port"),
-		    gettext("Bus"),
-		    gettext("Freq"),
-		    gettext("Bus"),
-		    gettext("Dev,"),
-		    "", "", "",
-#ifdef	DEBUG
-		    "",
-#endif	/* DEBUG */
-		    0);
-
-		log_printf(hdrfmt,
-		    gettext("Slot ID"),
-		    gettext("Type"),
-		    gettext(" ID"),
-		    gettext("Side"),
-		    gettext("MHz"),
-		    gettext("Freq"),
-		    gettext("Func"),
-		    gettext("State"),
-		    gettext("Name"),
-		    gettext("Model"),
-#ifdef	DEBUG
-		    gettext("Notes"),
-#endif	/* DEBUG */
-		    0);
-
-		log_printf(hdrfmt,
-		    "----------", "----", "----", "----", "----", "----",
-		    "----", "-----", "--------------------------------",
-		    "----------------------",
-#ifdef	DEBUG
-		    "----------------------",
-#endif	/* DEBUG */
-		    0);
-
-		banner = TRUE;
-	}
-
-	for (p = list; p != NULL; p = p -> next) {
-
-		display_io_slot_info(p);
-
-		display_io_max_bus_speed(p);
-
-		log_printf("\n", 0);
-	}
-}
-
-
-static void
-display_io_slot_info(struct io_card *p)
-{
-	/*
-	 * Onboard devices are distinguished by Slot IDs that
-	 * indicate only the I/O board.  Plug-in cards indicate
-	 * their leaf and Schizo.
-	 */
-
-	if (p->slot_str[0] == '-') {
-		log_printf("/%-2s%02d       ",
-		    SC_BOARD_TYPE(p->board),
-		    PORTID_TO_EXPANDER(p->board), 0);
-	} else {
-		char	c;
-		if (strcmp(p->notes, XMITS_COMPATIBLE) == 0) {
-			log_printf("/%-2s%02d/%s  ",
-			    SC_BOARD_TYPE(p->board),
-			    PORTID_TO_EXPANDER(p->board),
-			    p->slot_str, 0);
-		} else {
-			if (p->pci_bus == 'A')
-				c = '3';
-			else if (p->pci_bus == 'B') {
-				c = '5';
-			} else
-				c = '-';
-			log_printf("/%-2s%02d/C%cV%1d  ",
-			    SC_BOARD_TYPE(p->board),
-			    PORTID_TO_EXPANDER(p->board), c,
-			    PORTID_TO_INSTANCE(p->schizo_portid),
-			    0);
-		}
-	}
-	log_printf("%-4.4s ", gettext(p->bus_type), 0);
-	log_printf("%3d  ", p->schizo_portid, 0);
-	log_printf(" %c  ", p->pci_bus, 0);
-	log_printf(" %3d  ", p->freq, 0);
-}
-
-#define	BUS_SPEED_PRINT(speed)	log_printf(" %d  ", speed, 0)
-
-static void
-display_io_max_bus_speed(struct io_card *p)
-{
-	int speed = board_bus_max_freq;
-
-	switch (p->pci_bus) {
-	case 'A':
-		BUS_SPEED_PRINT(speed);
-		break;
-	case 'B':
-		if (strcmp(p->notes, XMITS_COMPATIBLE) == 0) {
-			if (PORTID_TO_INSTANCE(p->schizo_portid) == 0)
-				BUS_SPEED_PRINT(33);
-			else
-				BUS_SPEED_PRINT(speed);
-		} else
-			BUS_SPEED_PRINT(33);
-		break;
-	default:
-		log_printf("  -  ", 0);
-		break;
-	}
-
-	log_printf("%-1d,%-1d  ", p->dev_no, p->func_no, 0);
-	log_printf("%-5.5s ", gettext(p->status), 0);
-	log_printf("%-32.32s%c ", p->name,
-	    ((strlen(p->name) > 32) ? '+' : ' '), 0);
-	log_printf("%-22.22s%c", p->model,
-	    ((strlen(p->model) > 22) ? '+' : ' '), 0);
-#ifdef	DEBUG
-	log_printf(" %s", p->notes, 0);
-#endif	/* DEBUG */
-}
-
-void
-display_cpu_devices(Sys_tree *tree)
-{
-	Board_node *bnode;
-	char	*hdrfmt = "%-8.8s  %-7.7s  %-4.4s  %-4.4s  %-7.7s  %-4.4s\n";
-
-	(void) textdomain(TEXT_DOMAIN);
-
-	/*
-	 * Display the table header for CPUs . Then display the CPU
-	 * frequency, cache size, and processor revision of all cpus.
-	 */
-	log_printf("\n", 0);
-	log_printf("=========================", 0);
-	log_printf(gettext(" CPUs "), 0);
-	log_printf("=========================", 0);
-	log_printf("\n\n", 0);
-
-	log_printf(hdrfmt,
-	    "",
-	    gettext("CPU "),
-	    gettext("Run"),
-	    gettext(" E$"),
-	    gettext(" CPU"),
-	    gettext("CPU"), 0);
-
-	log_printf(hdrfmt,
-	    gettext("Slot ID"),
-	    gettext("ID "),
-	    gettext("MHz"),
-	    gettext(" MB"),
-	    gettext("Impl."),
-	    gettext("Mask"), 0);
-
-	log_printf(hdrfmt,
-	    "--------", "-------", "----", "----", "-------",  "----", 0);
-
-	/* Now display all of the cpus on each board */
-	bnode = tree->bd_list;
-	while (bnode != NULL) {
-		display_cpus(bnode);
-		bnode = bnode->next;
-	}
-
-	log_printf("\n", 0);
-}
-
-/*
- * Display the CPUs present on this board.
- */
-void
-display_cpus(Board_node *board)
-{
-	Prom_node *cpu;
-	uint_t freq;		/* CPU clock frequency */
-	int ecache_size;	/* External cache size */
-	int *impl;
-	int *mask;
-	int decoded_mask;
-	int *cpuid;
-	int *coreid;
-	int cpuid_prev = -1;
-	int ecache_size_prev = 0;
-
-	(void) textdomain(TEXT_DOMAIN);
-	/*
-	 * display the CPUs' operating frequency, cache size, impl. field
-	 * and mask revision.
-	 */
-	for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
-	    cpu = dev_next_type(cpu, "cpu")) {
-
-		freq = HZ_TO_MHZ(get_cpu_freq(cpu));
-		ecache_size = get_ecache_size(cpu);
-		impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
-		mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
-		cpuid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
-		if (cpuid == NULL)
-			cpuid = &board->board_num;
-
-		/* Do not display a failed CPU node */
-		if ((freq == 0) || (impl == 0) || (node_failed(cpu)))
-			continue;
-
-		if (CPU_IMPL_IS_CMP(*impl)) {
-			coreid = (int *)get_prop_val(find_prop(cpu,
-			    "reg"));
-			if (coreid == NULL) {
-				continue;
-			}
-
-			/*
-			 * The assumption is made that 2 cores will always be
-			 * listed together in the device tree. If either core
-			 * is "bad" then the FRU will not be listed.
-			 */
-			if (cpuid_prev == -1) {
-				cpuid_prev = *cpuid;
-				ecache_size_prev = ecache_size;
-				continue;
-			} else {
-				/*
-				 * Jaguar has a split E$, so the size for both
-				 * cores must be added together to get the total
-				 * size for the entire chip.
-				 *
-				 * Panther E$ (L3) is logically shared, so the
-				 * total size is equal to the core size.
-				 */
-				if (IS_JAGUAR(*impl)) {
-					ecache_size += ecache_size_prev;
-				}
-
-				ecache_size_prev = 0;
-			}
-		}
-
-		/*
-		 * Print out cpu data.
-		 *
-		 * Slot ID
-		 */
-		log_printf("/%-2s%02d/P%1d  ",
-		    SC_BOARD_TYPE(*cpuid),
-		    PORTID_TO_EXPANDER(*cpuid),
-		    PORTID_TO_INSTANCE(*cpuid), 0);
-
-		/* CPU ID */
-		if (CPU_IMPL_IS_CMP(*impl)) {
-			log_printf("%3d,%3d  ", cpuid_prev,
-			    *cpuid, 0);
-			cpuid_prev = -1;
-		} else
-			log_printf("%3d      ", *cpuid, 0);
-
-		/* Running frequency */
-		log_printf("%4u  ", freq, 0);
-
-		/* Ecache size */
-		if (ecache_size == 0)
-			log_printf("%-4.4s  ", gettext("N/A"), 0);
-		else
-			log_printf("%4.1f  ",
-			    (float)ecache_size / (float)(1<<20),
-			    0);
-
-		/* Implementation */
-		switch (*impl) {
-		case CHEETAH_IMPL:
-			log_printf("%-7.7s  ",
-			    gettext("US-III"), 0);
-			break;
-		case CHEETAH_PLUS_IMPL:
-			log_printf("%-7.7s  ",
-			    gettext("US-III+"), 0);
-			break;
-		case JAGUAR_IMPL:
-			log_printf("%-7.7s  ",
-			    gettext("US-IV"), 0);
-			break;
-		case PANTHER_IMPL:
-			log_printf("%-7.7s  ",
-			    gettext("US-IV+"), 0);
-			break;
-		default:
-			log_printf("%-7x  ", *impl, 0);
-			break;
-		}
-
-		/* CPU Mask */
-		if (mask == NULL) {
-			log_printf("%-4.4s", gettext("N/A"), 0);
-		} else {
-			if (IS_CHEETAH(*impl))
-				decoded_mask = REMAP_CHEETAH_MASK(*mask);
-			else
-				decoded_mask = *mask;
-
-			log_printf("%d.%d",
-			    (decoded_mask >> 4) & 0xf,
-			    decoded_mask & 0xf, 0);
-		}
-
-		log_printf("\n", 0);
-	}
-}
-
-
-/*ARGSUSED1*/
-void
-display_memoryconf(Sys_tree *tree, struct grp_info *grps)
-{
-	Board_node	*bnode = tree->bd_list;
-	char	*hdrfmt = "\n%-11.11s  %-4.4s  %-7.7s  %-7.7s  %-8.8s  %-6.6s"
-	    "  %-10.10s  %-10.10s";
-
-	(void) textdomain(TEXT_DOMAIN);
-
-	log_printf("=========================", 0);
-	log_printf(gettext(" Memory Configuration "), 0);
-	log_printf("=========================", 0);
-	log_printf("\n", 0);
-
-	log_printf(hdrfmt,
-	    "", "",
-	    gettext("Logical"),
-	    gettext("Logical"),
-	    gettext("Logical"),
-	    "", "", "", 0);
-
-	log_printf(hdrfmt,
-	    "",
-	    gettext("Port"),
-	    gettext("Bank"),
-	    gettext("Bank"),
-	    gettext("Bank"),
-	    gettext(" DIMM"),
-	    gettext("Interleave"),
-	    gettext("Interleave"), 0);
-
-	log_printf(hdrfmt,
-	    gettext("Slot ID"),
-	    gettext(" ID"),
-	    gettext("Number"),
-	    gettext("Size"),
-	    gettext("Status"),
-	    gettext(" Size"),
-	    gettext("Factor"),
-	    gettext("Segment"), 0);
-
-	log_printf(hdrfmt,
-	    "-----------", "----", "-------", "-------", "--------",
-	    "------", "----------", "----------", 0);
-
-	while (bnode != NULL) {
-		if (get_us3_mem_regs(bnode)) {
-			log_printf(
-			    gettext(
-			    "\nFailed to get memory information.\n"),
-			    0);
-			return;
-		}
-		bnode = bnode->next;
-	}
-
-	/* Display what we have found */
-	display_us3_banks();
-}
-
-
-/*
- * This function provides Starcat's formatting of the memory config
- * information that get_us3_mem_regs() and display_us3_banks() code has
- * gathered. It overrides the generic print_us3_memory_line() code
- * which prints an error message.
- */
-void
-print_us3_memory_line(int portid, int bank_id, uint64_t bank_size,
-	char *bank_status, uint64_t dimm_size, uint32_t intlv, int seg_id)
-{
-	(void) textdomain(TEXT_DOMAIN);
-
-	/* Slot ID */
-	log_printf("\n/%-2s%02d/P%1d/B%1d  ",
-	    SC_BOARD_TYPE(portid), PORTID_TO_EXPANDER(portid),
-	    PORTID_TO_INSTANCE(portid), (bank_id & 0x1), 0);
-
-	/* Port ID */
-	log_printf("%3d   ", portid, 0);
-
-	/* Logical Bank Number */
-	log_printf("   %1d     ", (bank_id & 0x3), 0);
-
-	/* Logical Bank Size */
-	log_printf("%4lldMB   ", bank_size, 0);
-
-	/* Logical Bank Status */
-	log_printf("%-8.8s  ", gettext(bank_status), 0);
-
-	/* DIMM Size */
-	log_printf("%4lldMB  ", dimm_size, 0);
-
-	/* Interleave Factor */
-	log_printf("  %2d-%-3.3s    ", intlv, gettext("way"), 0);
-
-	/* Interleave Segment */
-	log_printf("   %3d", seg_id, 0);
-}
-
-/*ARGSUSED2*/
-void
-display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
-	struct system_kstat_data *kstats)
-{
-	if (flag) {
-		/*
-		 * display time of latest powerfail. Not all systems
-		 * have this capability. For those that do not, this
-		 * is just a no-op.
-		 */
-		disp_powerfail(root);
-
-		(void) textdomain(TEXT_DOMAIN);
-
-		/* Print the header */
-		log_printf("\n", 0);
-		log_printf("=========================", 0);
-		log_printf(gettext(" Diagnostic Information "), 0);
-		log_printf("=========================", 0);
-		log_printf("\n\n", 0);
-		log_printf(gettext("For diagnostic information,"), 0);
-		log_printf("\n", 0);
-		log_printf(gettext(
-		    "see /var/opt/SUNWSMS/adm/[A-R]/messages on the SC."),
-		    0);
-		log_printf("\n", 0);
-
-		/* Print the PROM revisions here */
-		starcat_disp_hw_revisions(root);
-	}
-}
-
-/*
- * local functions -  functions that are only needed inside this library
- */
-
-static void
-starcat_disp_hw_revisions(Prom_node *root)
-{
-	Prom_node	*pnode;
-	char		*version;
-
-	(void) textdomain(TEXT_DOMAIN);
-
-	/* Print the header */
-	log_printf("\n", 0);
-	log_printf("=========================", 0);
-	log_printf(gettext(" Hardware Revisions "), 0);
-	log_printf("=========================", 0);
-	log_printf("\n\n", 0);
-
-	/* Display Prom revision header */
-	log_printf(gettext("OpenBoot firmware revision:"), 0);
-	log_printf("\n---------------------------\n", 0);
-
-	/*
-	 * Display OBP version info
-	 */
-	pnode = dev_find_node(root, "openprom");
-	if (pnode != NULL) {
-		version = (char *)get_prop_val(find_prop(pnode, "version"));
-		log_printf("%s\n\n", version, 0);
-	}
-}
-
-/*
- * We call do_devinfo() in order to use the libdevinfo device tree
- * instead of OBP's device tree.
- */
-int
-do_prominfo(int syserrlog, char *pgname, int log_flag, int prt_flag)
-{
-
-	return (do_devinfo(syserrlog, pgname, log_flag, prt_flag));
-
-}
-
-/*
- * return the property value for the Prop
- * passed in. (When using libdevinfo)
- */
-void *
-get_prop_val(Prop *prop)
-{
-	if (prop == NULL)
-		return (NULL);
-
-	return ((void *)(prop->value.val_ptr));
-}
-
-/*
- * Search a Prom node and retrieve the property with the correct
- * name. (When using libdevinfo)
- */
-Prop *
-find_prop(Prom_node *pnode, char *name)
-{
-	Prop *prop;
-
-	if (pnode == NULL)
-		return (NULL);
-
-	for (prop = pnode->props; prop != NULL; prop = prop->next) {
-		if (prop->name.val_ptr != NULL &&
-		    strcmp((char *)(prop->name.val_ptr), name) == 0)
-			break;
-	}
-
-	return (prop);
-}
-
-/*
- * This function searches through the properties of the node passed in
- * and returns a pointer to the value of the name property.
- * (When using libdevinfo)
- */
-char *
-get_node_name(Prom_node *pnode)
-{
-	Prop *prop;
-
-	if (pnode == NULL) {
-		return (NULL);
-	}
-
-	prop = pnode->props;
-	while (prop != NULL) {
-		if (strcmp("name", (char *)prop->name.val_ptr) == 0)
-			return (prop->value.val_ptr);
-		prop = prop->next;
-	}
-	return (NULL);
-}
-
-/*
- * This function searches through the properties of the node passed in
- * and returns a pointer to the value of the device_type property.
- * (When using libdevinfo)
- */
-char *
-get_node_type(Prom_node *pnode)
-{
-	Prop *prop;
-
-	if (pnode == NULL) {
-		return (NULL);
-	}
-
-	prop = pnode->props;
-	while (prop != NULL) {
-		if (strcmp("device_type", (char *)prop->name.val_ptr) == 0)
-			return (prop->value.val_ptr);
-		prop = prop->next;
-	}
-	return (NULL);
-}
--- a/usr/src/lib/libshare/smb/libshare_smb.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/libshare/smb/libshare_smb.c	Fri May 31 14:32:40 2019 +0200
@@ -98,7 +98,7 @@
 static int interface_validator(int, char *);
 static int smb_update_optionset_props(sa_handle_t, sa_resource_t, nvlist_t *);
 
-static boolean_t smb_saprop_getbool(sa_optionset_t, char *);
+static boolean_t smb_saprop_getbool(sa_optionset_t, char *, boolean_t);
 static boolean_t smb_saprop_getstr(sa_optionset_t, char *, char *, size_t);
 
 static struct {
@@ -178,6 +178,7 @@
 	{ SHOPT_GUEST,		OPT_TYPE_BOOLEAN },
 	{ SHOPT_DFSROOT,	OPT_TYPE_BOOLEAN },
 	{ SHOPT_DESCRIPTION,	OPT_TYPE_STRING },
+	{ SHOPT_QUOTAS,		OPT_TYPE_BOOLEAN },
 	{ NULL, NULL }
 };
 
@@ -2147,18 +2148,23 @@
 	if (opts == NULL)
 		return (SA_OK);
 
-	if (smb_saprop_getbool(opts, SHOPT_CATIA))
+	if (smb_saprop_getbool(opts, SHOPT_CATIA, B_FALSE))
 		si->shr_flags |= SMB_SHRF_CATIA;
 
-	if (smb_saprop_getbool(opts, SHOPT_ABE))
+	if (smb_saprop_getbool(opts, SHOPT_ABE, B_FALSE))
 		si->shr_flags |= SMB_SHRF_ABE;
 
-	if (smb_saprop_getbool(opts, SHOPT_GUEST))
+	if (smb_saprop_getbool(opts, SHOPT_GUEST, B_FALSE))
 		si->shr_flags |= SMB_SHRF_GUEST_OK;
 
-	if (smb_saprop_getbool(opts, SHOPT_DFSROOT))
+	if (smb_saprop_getbool(opts, SHOPT_DFSROOT, B_FALSE))
 		si->shr_flags |= SMB_SHRF_DFSROOT;
 
+	/* Quotas are enabled by default. */
+	si->shr_flags |= SMB_SHRF_QUOTAS;
+	if (!smb_saprop_getbool(opts, SHOPT_QUOTAS, B_TRUE))
+		si->shr_flags &= ~SMB_SHRF_QUOTAS;
+
 	(void) smb_saprop_getstr(opts, SHOPT_AD_CONTAINER, si->shr_container,
 	    sizeof (si->shr_container));
 
@@ -2423,20 +2429,29 @@
 }
 
 static boolean_t
-smb_saprop_getbool(sa_optionset_t opts, char *propname)
+smb_saprop_getbool(sa_optionset_t opts, char *propname, boolean_t def)
 {
 	sa_property_t prop;
 	char *val;
-	boolean_t propval = B_FALSE;
+	boolean_t ret = def;
 
 	prop = sa_get_property(opts, propname);
 	if ((val = sa_get_property_attr(prop, "value")) != NULL) {
-		if ((strcasecmp(val, "true") == 0) || (strcmp(val, "1") == 0))
-			propval = B_TRUE;
+		if (def) {
+			/* Default is true, ret false if... */
+			if ((strcasecmp(val, "false") == 0) ||
+			    (strcmp(val, "0") == 0))
+				ret = B_FALSE;
+		} else {
+			/* Default is false, ret true if... */
+			if ((strcasecmp(val, "true") == 0) ||
+			    (strcmp(val, "1") == 0))
+				ret = B_TRUE;
+		}
 		free(val);
 	}
 
-	return (propval);
+	return (ret);
 }
 
 static boolean_t
--- a/usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * This file and its contents are supplied under the terms of the
- * Common Development and Distribution License ("CDDL"), version 1.0.
- * You may only use this file in accordance with the terms of version
- * 1.0 of the CDDL.
- *
- * A full copy of the text of the CDDL should have accompanied this
- * source.  A copy of the CDDL is also available via the Internet at
- * http://www.illumos.org/license/CDDL.
- */
-
-/*
- * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
- */
-
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-
-#include <libfknsmb.h>
--- a/usr/src/lib/smbclnt/libfksmbfs/common/llib-lfksmbfs	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * This file and its contents are supplied under the terms of the
- * Common Development and Distribution License ("CDDL"), version 1.0.
- * You may only use this file in accordance with the terms of version
- * 1.0 of the CDDL.
- *
- * A full copy of the text of the CDDL should have accompanied this
- * source.  A copy of the CDDL is also available via the Internet at
- * http://www.illumos.org/license/CDDL.
- */
-
-/*
- * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
- */
-
-/*LINTLIBRARY*/
-/*PROTOLIB1*/
-
-#include <libfksmbfs.h>
--- a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com	Fri May 31 14:32:40 2019 +0200
@@ -22,7 +22,7 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+# Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
 #
 # Copyright (c) 2018, Joyent, Inc.
 
--- a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c	Fri May 31 14:32:40 2019 +0200
@@ -858,6 +858,18 @@
 	cred_t *cr,
 	caller_context_t *ct)
 {
+#if defined(_LP64)
+	offset_t maxoffset = INT64_MAX;
+#elif defined(_ILP32)
+	/*
+	 * Sadly, the fcntl API enforces 32-bit offsets,
+	 * even though we have _FILE_OFFSET_BITS=64
+	 */
+	offset_t maxoffset = INT32_MAX;
+#else
+#error "unsupported env."
+#endif
+
 	/* See fs_frlock */
 
 	switch (cmd) {
@@ -870,6 +882,30 @@
 		return (EINVAL);
 	}
 
+	/* We only get SEEK_SET ranges here. */
+	if (bfp->l_whence != 0)
+		return (EINVAL);
+
+	/*
+	 * One limitation of using fcntl(2) F_SETLK etc is that
+	 * the real kernel limits the offsets we can use.
+	 * (Maybe the fcntl API should loosen that up?)
+	 * See syscall/fcntl.c:flock_check()
+	 *
+	 * Here in libfksmbsrv we can just ignore such locks,
+	 * or ignore the part that extends beyond maxoffset.
+	 * The SMB layer still keeps track of such locks for
+	 * conflict detection, so not reflecting such locks
+	 * into the real FS layer is OK.  Note: this may
+	 * modify the pased bfp->l_len.
+	 */
+	if (bfp->l_start < 0 || bfp->l_start > maxoffset)
+		return (0);
+	if (bfp->l_len < 0 || bfp->l_len > maxoffset)
+		return (0);
+	if (bfp->l_len > (maxoffset - bfp->l_start + 1))
+		bfp->l_len = (maxoffset - bfp->l_start + 1);
+
 	if (fcntl(vp->v_fd, cmd, bfp) == -1)
 		return (errno);
 
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
 #
 #
 # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+# Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
 #
 
 #
@@ -72,6 +72,7 @@
 	smb_shr_iterinit;
 	smb_shr_list;
 	smb_shr_load;
+	smb_shr_load_execinfo;
 	smb_shr_modify;
 	smb_shr_remove;
 	smb_shr_rename;
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c	Fri May 31 14:32:40 2019 +0200
@@ -59,8 +59,8 @@
 static boolean_t netr_isadmin(struct netr_validation_info3 *);
 static uint32_t netr_setup_domain_groups(struct netr_validation_info3 *,
     smb_ids_t *);
-static uint32_t netr_setup_token_info3(struct netr_validation_info3 *,
-    smb_token_t *);
+static uint32_t netr_setup_krb5res_groups(struct krb5_validation_info *,
+    smb_ids_t *);
 static uint32_t netr_setup_token_wingrps(struct netr_validation_info3 *,
     smb_token_t *);
 
@@ -82,6 +82,7 @@
 {
 	struct krb5_validation_info info;
 	ndr_buf_t *nbuf;
+	smb_sid_t *domsid;
 	uint32_t status = NT_STATUS_NO_MEMORY;
 	int rc;
 
@@ -99,10 +100,47 @@
 		goto out;
 	}
 
-	status = netr_setup_token_info3(&info.info3, token);
+	/*
+	 * Copy the decoded info into the token,
+	 * similar to netr_setup_token()
+	 */
+	domsid = (smb_sid_t *)info.info3.LogonDomainId;
+
+	token->tkn_user.i_sid = smb_sid_splice(domsid,
+	    info.info3.UserId);
+	if (token->tkn_user.i_sid == NULL)
+		goto out;
+
+	token->tkn_primary_grp.i_sid = smb_sid_splice(domsid,
+	    info.info3.PrimaryGroupId);
+	if (token->tkn_primary_grp.i_sid == NULL)
+		goto out;
 
-	/* Deal with the "resource groups"? */
+	if (info.info3.EffectiveName.str) {
+		token->tkn_account_name =
+		    strdup((char *)info.info3.EffectiveName.str);
+		if (token->tkn_account_name == NULL)
+			goto out;
+	}
 
+	if (info.info3.LogonDomainName.str) {
+		token->tkn_domain_name =
+		    strdup((char *)info.info3.LogonDomainName.str);
+		if (token->tkn_domain_name == NULL)
+			goto out;
+	}
+
+	status = netr_setup_domain_groups(&info.info3, &token->tkn_win_grps);
+	if (status != NT_STATUS_SUCCESS)
+		goto out;
+
+	if (info.rg_rid_cnt != 0) {
+		status = netr_setup_krb5res_groups(&info, &token->tkn_win_grps);
+		if (status != NT_STATUS_SUCCESS)
+			goto out;
+	}
+
+	status = netr_setup_token_wingrps(&info.info3, token);
 
 out:
 	if (nbuf != NULL)
@@ -112,46 +150,6 @@
 }
 
 /*
- * Code factored out of netr_setup_token()
- */
-static uint32_t
-netr_setup_token_info3(struct netr_validation_info3 *info3,
-    smb_token_t *token)
-{
-	smb_sid_t *domsid;
-
-	domsid = (smb_sid_t *)info3->LogonDomainId;
-
-	token->tkn_user.i_sid = smb_sid_splice(domsid,
-	    info3->UserId);
-	if (token->tkn_user.i_sid == NULL)
-		goto errout;
-
-	token->tkn_primary_grp.i_sid = smb_sid_splice(domsid,
-	    info3->PrimaryGroupId);
-	if (token->tkn_primary_grp.i_sid == NULL)
-		goto errout;
-
-	if (info3->EffectiveName.str) {
-		token->tkn_account_name =
-		    strdup((char *)info3->EffectiveName.str);
-		if (token->tkn_account_name == NULL)
-			goto errout;
-	}
-
-	if (info3->LogonDomainName.str) {
-		token->tkn_domain_name =
-		    strdup((char *)info3->LogonDomainName.str);
-		if (token->tkn_domain_name == NULL)
-			goto errout;
-	}
-
-	return (netr_setup_token_wingrps(info3, token));
-errout:
-	return (NT_STATUS_INSUFF_SERVER_RESOURCES);
-}
-
-/*
  * Abort impending domain logon requests.
  */
 void
@@ -423,6 +421,10 @@
 	if (token->tkn_account_name == NULL || token->tkn_domain_name == NULL)
 		return (NT_STATUS_NO_MEMORY);
 
+	status = netr_setup_domain_groups(info3, &token->tkn_win_grps);
+	if (status != NT_STATUS_SUCCESS)
+		return (status);
+
 	status = netr_setup_token_wingrps(info3, token);
 	if (status != NT_STATUS_SUCCESS)
 		return (status);
@@ -812,44 +814,24 @@
 }
 
 /*
- * Sets up domain, local and well-known group membership for the given
- * token. Two assumptions have been made here:
- *
- *   a) token already contains a valid user SID so that group
- *      memberships can be established
- *
- *   b) token belongs to a domain user
+ * Add local and well-known group membership to the given
+ * token.  Called after domain groups have been added.
  */
 static uint32_t
 netr_setup_token_wingrps(struct netr_validation_info3 *info3,
     smb_token_t *token)
 {
-	smb_ids_t tkn_grps;
 	uint32_t status;
 
-	tkn_grps.i_cnt = 0;
-	tkn_grps.i_ids = NULL;
-
-	status = netr_setup_domain_groups(info3, &tkn_grps);
-	if (status != NT_STATUS_SUCCESS) {
-		smb_ids_free(&tkn_grps);
+	status = smb_sam_usr_groups(token->tkn_user.i_sid,
+	    &token->tkn_win_grps);
+	if (status != NT_STATUS_SUCCESS)
 		return (status);
-	}
-
-	status = smb_sam_usr_groups(token->tkn_user.i_sid, &tkn_grps);
-	if (status != NT_STATUS_SUCCESS) {
-		smb_ids_free(&tkn_grps);
-		return (status);
-	}
 
 	if (netr_isadmin(info3))
 		token->tkn_flags |= SMB_ATF_ADMIN;
 
-	status = smb_wka_token_groups(token->tkn_flags, &tkn_grps);
-	if (status == NT_STATUS_SUCCESS)
-		token->tkn_win_grps = tkn_grps;
-	else
-		smb_ids_free(&tkn_grps);
+	status = smb_wka_token_groups(token->tkn_flags, &token->tkn_win_grps);
 
 	return (status);
 }
@@ -912,6 +894,37 @@
 }
 
 /*
+ * Converts additional "resource" groups (from krb5_validation_info)
+ * into the internal representation (gids), appending to the list
+ * already put in place by netr_setup_domain_groups().
+ */
+static uint32_t netr_setup_krb5res_groups(struct krb5_validation_info *info,
+    smb_ids_t *gids)
+{
+	smb_sid_t *domain_sid;
+	smb_id_t *ids;
+	int i, total_cnt;
+
+	total_cnt = gids->i_cnt + info->rg_rid_cnt;
+
+	gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t));
+	if (gids->i_ids == NULL)
+		return (NT_STATUS_NO_MEMORY);
+
+	domain_sid = (smb_sid_t *)info->rg_dom_sid;
+
+	ids = gids->i_ids + gids->i_cnt;
+	for (i = 0; i < info->rg_rid_cnt; i++, gids->i_cnt++, ids++) {
+		ids->i_sid = smb_sid_splice(domain_sid, info->rg_rids[i].rid);
+		if (ids->i_sid == NULL)
+			return (NT_STATUS_NO_MEMORY);
+		ids->i_attrs = info->rg_rids[i].attributes;
+	}
+
+	return (0);
+}
+
+/*
  * Determines if the given user is the domain Administrator or a
  * member of Domain Admins
  */
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c	Fri May 31 14:32:40 2019 +0200
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  *
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
  */
 
 /*
@@ -389,6 +389,7 @@
 	struct stat st;
 	smb_share_t *cached_si;
 	nvlist_t *shrlist;
+	boolean_t created_zfs = B_FALSE;
 	uint32_t status;
 	int rc;
 
@@ -416,8 +417,34 @@
 		/*
 		 * If share type is STYPE_DISKTREE then the path to the
 		 * share should exist so that we can add the share to cache.
+		 * If path is ZFS, add the .zfs/shares/<share> entry.
+		 *
+		 * Both actions may require privileges that main dropped,
+		 * so we need to temporarily make those effective.
 		 */
-		rc = stat(si->shr_path, &st);
+		if (smb_proc_takesem() == 0) {
+
+			(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+			    PRIV_FILE_DAC_READ,
+			    PRIV_FILE_DAC_SEARCH,
+			    PRIV_FILE_DAC_WRITE,
+			    NULL);
+
+			rc = stat(si->shr_path, &st);
+			if (rc == 0) {
+				smb_shr_zfs_add(si);
+				created_zfs = B_TRUE;
+			}
+
+			(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+			    PRIV_FILE_DAC_READ,
+			    PRIV_FILE_DAC_SEARCH,
+			    PRIV_FILE_DAC_WRITE,
+			    NULL);
+			smb_proc_givesem();
+		} else {
+			rc = NERR_InternalError;
+		}
 		if (rc != 0) {
 			smb_shr_cache_unlock();
 			return (NERR_ItemNotFound);
@@ -425,6 +452,7 @@
 	}
 
 	if ((status = smb_shr_cache_addent(si)) != NERR_Success) {
+		/* This error should be impossible after findent above. */
 		smb_shr_cache_unlock();
 		return (status);
 	}
@@ -440,9 +468,6 @@
 		if (rc == 0) {
 			smb_shr_publish(si->shr_name, si->shr_container);
 
-			/* If path is ZFS, add the .zfs/shares/<share> entry. */
-			smb_shr_zfs_add(si);
-
 			if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
 				dfs_namespace_load(si->shr_name);
 
@@ -450,11 +475,34 @@
 		}
 	}
 
+	/*
+	 * Error code path, i.e. when the kernel could not accept
+	 * the new share for some reason.
+	 */
 	if (smb_shr_cache_lock(SMB_SHR_CACHE_WRLOCK) == NERR_Success) {
 		smb_shr_cache_delent(si->shr_name);
 		smb_shr_cache_unlock();
 	}
 
+	if (created_zfs && smb_proc_takesem() == 0) {
+
+		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_shr_zfs_remove(si);
+
+		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_proc_givesem();
+	}
+
 	/*
 	 * rc == ENOENT means the shared directory doesn't exist
 	 */
@@ -505,9 +553,28 @@
 
 	/*
 	 * If path is ZFS, remove the .zfs/shares/<share> entry.  Need
-	 * to remove before cleanup of cache occurs.
+	 * to remove before cleanup of cache occurs.  These actions
+	 * require temporary elevation of privileges.
 	 */
-	smb_shr_zfs_remove(si);
+	if (smb_proc_takesem() == 0) {
+
+		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_shr_zfs_remove(si);
+
+		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_proc_givesem();
+	}
+
 	(void) smb_shr_encode(si, &shrlist);
 
 	(void) strlcpy(container, si->shr_container, sizeof (container));
@@ -570,9 +637,25 @@
 	bcopy(from_si, &to_si, sizeof (smb_share_t));
 	(void) strlcpy(to_si.shr_name, to_name, sizeof (to_si.shr_name));
 
-
 	/* If path is ZFS, rename the .zfs/shares/<share> entry. */
-	smb_shr_zfs_rename(from_si, &to_si);
+	if (smb_proc_takesem() == 0) {
+
+		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_shr_zfs_rename(from_si, &to_si);
+
+		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_proc_givesem();
+	}
 
 	if ((status = smb_shr_cache_addent(&to_si)) != NERR_Success) {
 		smb_shr_cache_unlock();
@@ -628,14 +711,15 @@
  *   o comment
  *   o AD container
  *   o host access
- *   o abe
+ *   o flags
  */
 uint32_t
 smb_shr_modify(smb_share_t *new_si)
 {
+	smb_share_t old_si;
 	smb_share_t *si;
 	boolean_t adc_changed = B_FALSE;
-	char old_container[MAXPATHLEN];
+	boolean_t quota_flag_changed = B_FALSE;
 	uint32_t access, flag;
 	nvlist_t *shrlist;
 
@@ -655,16 +739,20 @@
 		return (ERROR_ACCESS_DENIED);
 	}
 
+	/*
+	 * Keep a copy of what the share entry looks like before we
+	 * modify it.  We need this for things like unpublishing
+	 * from the old share container, removing the quota dir.
+	 */
+	bcopy(si, &old_si, sizeof (old_si));
+
+	/* Share comment */
 	(void) strlcpy(si->shr_cmnt, new_si->shr_cmnt, sizeof (si->shr_cmnt));
 
-	adc_changed = (strcmp(new_si->shr_container, si->shr_container) != 0);
-	if (adc_changed) {
-		/* save current container - needed for unpublishing */
-		(void) strlcpy(old_container, si->shr_container,
-		    sizeof (old_container));
-		(void) strlcpy(si->shr_container, new_si->shr_container,
-		    sizeof (si->shr_container));
-	}
+	/* Container */
+	(void) strlcpy(si->shr_container, new_si->shr_container,
+	    sizeof (si->shr_container));
+	adc_changed = (strcmp(old_si.shr_container, si->shr_container) != 0);
 
 	flag = (new_si->shr_flags & SMB_SHRF_ABE);
 	si->shr_flags &= ~SMB_SHRF_ABE;
@@ -682,6 +770,12 @@
 	si->shr_flags &= ~SMB_SHRF_DFSROOT;
 	si->shr_flags |= flag;
 
+	flag = (new_si->shr_flags & SMB_SHRF_QUOTAS);
+	si->shr_flags &= ~SMB_SHRF_QUOTAS;
+	si->shr_flags |= flag;
+	if ((old_si.shr_flags ^ si->shr_flags) & SMB_SHRF_QUOTAS)
+		quota_flag_changed = B_TRUE;
+
 	flag = (new_si->shr_flags & SMB_SHRF_CSC_MASK);
 	si->shr_flags &= ~SMB_SHRF_CSC_MASK;
 	si->shr_flags |= flag;
@@ -715,10 +809,31 @@
 	}
 
 	if (adc_changed) {
-		smb_shr_unpublish(new_si->shr_name, old_container);
+		smb_shr_unpublish(old_si.shr_name, old_si.shr_container);
 		smb_shr_publish(new_si->shr_name, new_si->shr_container);
 	}
 
+	/* The following required privileges we dropped. */
+	if (quota_flag_changed && smb_proc_takesem() == 0) {
+
+		(void) priv_set(PRIV_ON, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_shr_zfs_remove(&old_si);
+		smb_shr_zfs_add(si);
+
+		(void) priv_set(PRIV_OFF, PRIV_EFFECTIVE,
+		    PRIV_FILE_DAC_READ,
+		    PRIV_FILE_DAC_SEARCH,
+		    PRIV_FILE_DAC_WRITE,
+		    NULL);
+
+		smb_proc_givesem();
+	}
+
 	return (NERR_Success);
 }
 
@@ -1447,10 +1562,7 @@
 	char *gstate;
 	boolean_t gdisabled;
 
-	(void) mutex_lock(&smb_shr_exec_mtx);
-	(void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
-	    MAXPATHLEN);
-	(void) mutex_unlock(&smb_shr_exec_mtx);
+	smb_shr_load_execinfo();
 
 	if ((handle = smb_shr_sa_enter()) == NULL) {
 		syslog(LOG_ERR, "smb_shr_load: load failed");
@@ -1481,6 +1593,15 @@
 	return (NULL);
 }
 
+void
+smb_shr_load_execinfo()
+{
+	(void) mutex_lock(&smb_shr_exec_mtx);
+	(void) smb_config_get_execinfo(smb_shr_exec_map, smb_shr_exec_unmap,
+	    MAXPATHLEN);
+	(void) mutex_unlock(&smb_shr_exec_mtx);
+}
+
 /*
  * Load the shares contained in the specified group.
  *
@@ -1648,6 +1769,16 @@
 		free(val);
 	}
 
+	val = smb_shr_sa_getprop(opts, SHOPT_QUOTAS);
+	if (val != NULL) {
+		/* Turn the flag on or off */
+		smb_shr_sa_setflag(val, si, SMB_SHRF_QUOTAS);
+		free(val);
+	} else {
+		/* Default for this is enabled. */
+		si->shr_flags |= SMB_SHRF_QUOTAS;
+	}
+
 	val = smb_shr_sa_getprop(opts, SHOPT_CSC);
 	if (val != NULL) {
 		smb_shr_sa_csc_option(val, si);
@@ -2023,8 +2154,8 @@
 
 /*
  * If the share path refers to a ZFS file system, add the
- * .zfs/shares/<share> object and call smb_quota_add_fs()
- * to initialize quota support for the share.
+ * .zfs/shares/<share> object and add or remove the special
+ * directory and file telling clients about quota support.
  */
 static void
 smb_shr_zfs_add(smb_share_t *si)
@@ -2051,26 +2182,31 @@
 		syslog(LOG_INFO, "share: failed to add ACL object: %s: %s\n",
 		    si->shr_name, strerror(errno));
 
-	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
-	    NULL, NULL, 0, B_FALSE) == 0) {
-		smb_quota_add_fs(buf);
+	ret = zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT,
+	    buf, MAXPATHLEN, NULL, NULL, 0, B_FALSE);
+	if (ret != 0) {
+		syslog(LOG_INFO, "share: failed to get mountpoint: "
+		    "%s\n", si->shr_name);
+	} else {
+		if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0) {
+			smb_quota_add_fs(buf);
+		} else {
+			smb_quota_remove_fs(buf);
+		}
 	}
 
-
 	zfs_close(zfshd);
 	libzfs_fini(libhd);
 }
 
 /*
  * If the share path refers to a ZFS file system, remove the
- * .zfs/shares/<share> object, and call smb_quota_remove_fs()
- * to end quota support for the share.
+ * .zfs/shares/<share> object.
  */
 static void
 smb_shr_zfs_remove(smb_share_t *si)
 {
 	libzfs_handle_t *libhd;
-	zfs_handle_t *zfshd;
 	int ret;
 	char buf[MAXPATHLEN];	/* dataset or mountpoint */
 
@@ -2080,23 +2216,18 @@
 	if ((libhd = libzfs_init()) == NULL)
 		return;
 
-	if ((zfshd = zfs_open(libhd, buf, ZFS_TYPE_FILESYSTEM)) == NULL) {
-		libzfs_fini(libhd);
-		return;
-	}
-
 	errno = 0;
 	ret = zfs_smb_acl_remove(libhd, buf, si->shr_path, si->shr_name);
 	if (ret != 0 && errno != EAGAIN)
 		syslog(LOG_INFO, "share: failed to remove ACL object: %s: %s\n",
 		    si->shr_name, strerror(errno));
 
-	if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN,
-	    NULL, NULL, 0, B_FALSE) == 0) {
-		smb_quota_remove_fs(buf);
-	}
-
-	zfs_close(zfshd);
+	/*
+	 * We could remove the quotas directory here, but that adds
+	 * significantly to the time required for a zpool export,
+	 * so just leave it here and fixup when we share next.
+	 */
+
 	libzfs_fini(libhd);
 }
 
@@ -2415,9 +2546,11 @@
 		rc |= nvlist_add_string(smb, SHOPT_GUEST, "true");
 	if ((si->shr_flags & SMB_SHRF_DFSROOT) != 0)
 		rc |= nvlist_add_string(smb, SHOPT_DFSROOT, "true");
+	if ((si->shr_flags & SMB_SHRF_QUOTAS) != 0)
+		rc |= nvlist_add_string(smb, SHOPT_QUOTAS, "true");
 
 	if ((si->shr_flags & SMB_SHRF_AUTOHOME) != 0) {
-		rc |= nvlist_add_string(smb, "Autohome", "true");
+		rc |= nvlist_add_string(smb, SHOPT_AUTOHOME, "true");
 		rc |= nvlist_add_uint32(smb, "uid", si->shr_uid);
 		rc |= nvlist_add_uint32(smb, "gid", si->shr_gid);
 	}
--- a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c	Fri May 31 14:32:40 2019 +0200
@@ -20,9 +20,9 @@
  */
 
 /*
- * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 RackTop Systems.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <stdlib.h>
@@ -142,8 +142,12 @@
 	uint16_t m_type;
 } smb_lgmid_t;
 
+/* Buffer size to hold hex form of the above (>24). */
 #define	SMB_LGRP_MID_HEXSZ	32
 
+/* Size of idx,rid parts of above, in hex form. */
+#define	SMB_LGRP_IDXRID_LEN	16
+
 /* Member list */
 typedef struct smb_lgmlist {
 	uint32_t	m_cnt;
@@ -2039,6 +2043,10 @@
  * memory for out_members by calling free().
  *
  * in_members and out_members are hex strings.
+ *
+ * Note that we ignore the SID "type" when matching because
+ * we always want to delete when the SID part matches.
+ * The "type" part can be fiction.
  */
 static int
 smb_lgrp_mlist_del(smb_lgmlist_t *in_members, smb_lgmid_t *mid,
@@ -2073,7 +2081,8 @@
 
 	in_list = in_members->m_ids;
 	for (i = 0, out_cnt = 0; i < in_members->m_cnt; i++) {
-		if (strncmp(in_list, mid_hex, mid_hexsz)) {
+		/* Keep only those NOT matching in IDX,RID */
+		if (strncmp(in_list, mid_hex, SMB_LGRP_IDXRID_LEN)) {
 			(void) strncat(out_list, in_list, mid_hexsz);
 			out_cnt++;
 		}
--- a/usr/src/man/man1m/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/man/man1m/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -17,9 +17,10 @@
 # Copyright 2016 Toomas Soome <tsoome@me.com>
 # Copyright 2018 Nexenta Systems, Inc.
 # Copyright (c) 2017, Chris Fraire <cfraire@me.com>.
+# Copyright 2019 Peter Tribble
 #
 
-include		$(SRC)//Makefile.master
+include		$(SRC)/Makefile.master
 
 MANSECT=	1m
 
@@ -546,8 +547,7 @@
 		nvmeadm.1m		\
 		pptadm.1m
 
-sparc_MANFILES=	cvcd.1m			\
-		dcs.1m			\
+sparc_MANFILES=	dcs.1m			\
 		drd.1m			\
 		efdaemon.1m		\
 		ldmad.1m		\
--- a/usr/src/man/man1m/cvcd.1m	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-'\" te
-.\"  Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
-.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
-.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH CVCD 1M "Mar 9, 2006"
-.SH NAME
-cvcd \- virtual console daemon
-.SH SYNOPSIS
-.LP
-.nf
-\fB/platform\fI\fR/\fIplatform_name\fR/cvcd\fR [\fB-a\fR \fIauth\fR] [\fB-e\fR \fIencr\fR]
-     [\fB-u\fR \fIesp_auth\fR]
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-The virtual console daemon, \fBcvcd\fR, is a server process that supports the
-network console provided on some platforms. The \fBcvcd\fR daemon accepts
-network console connections from a remote host (only one host at any given
-time). Console input is read from this connection and forwarded to
-\fBcvc\fR(7D) by way of \fBcvcredir\fR(7D).
-.sp
-.LP
-Similarly, console output is read from \fBcvcredir\fR(7D) and forwarded across
-the network console connection. If \fBcvcd\fR dies, console traffic is
-automatically rerouted through an internal hardware interface.
-.sp
-.LP
-The \fBcvcd\fR daemon normally starts at system boot time. Each domain supports
-only one \fBcvcd\fR process at a time.
-.LP
-Caution -
-.sp
-.RS 2
-On Sun Enterprise 10000 domains, \fBcvcd\fR uses a configuration file
-(\fB/etc/ssphostname\fR) to determine the name of the host from which network
-console connections are allowed. If the remote console host is renamed, you
-must edit the configuration file to reflect that change.
-.RE
-.sp
-.LP
-The \fBcvcd\fR daemon supports per-socket IP Security Architecture (IPsec)
-through the options described below. See \fBipsec\fR(7P).
-.SH OPTIONS
-.sp
-.LP
-The \fBcvcd\fR daemon supports the options listed below.
-.sp
-.ne 2
-.na
-\fB\fB-a\fR \fIauth\fR\fR
-.ad
-.RS 15n
-Controls the IPsec Authentication Header (AH) algorithm. \fIauth\fR can be one
-of \fBnone\fR, \fBmd5\fR, or \fBsha1\fR.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fB-e\fR \fIencr\fR\fR
-.ad
-.RS 15n
-Controls the IPsec Encapsulating Security Payload (ESP) encryption algorithm.
-\fIencr\fR can be one of \fBnone\fR, \fBdes\fR, or \fB3des\fR.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fB-u\fR \fIesp_auth\fR\fR
-.ad
-.RS 15n
-Controls the IPsec Encapsulating Security Payload (ESP) authentication
-algorithm. \fIesp_auth\fR can be one of \fBnone\fR, \fBmd5\fR, or \fBsha1\fR.
-.RE
-
-.SH OPERANDS
-.sp
-.LP
-The following operands are supported:
-.sp
-.ne 2
-.na
-\fB\fIplatform_name\fR\fR
-.ad
-.RS 17n
-The official Sun platform name used in packaging and code. For example, for Sun
-Fire 15K servers, the \fIplatform_name\fR would be \fBSUNW,Sun-Fire-15000\fR.
-.RE
-
-.SH EXAMPLES
-.LP
-\fBExample 1 \fRSetting an IPSec Option
-.sp
-.LP
-The command below sets the value of the IPsec Authentication Header algorithm
-to \fBmd5\fR. As a result of this command, \fBcvcd\fR will use the HMAC-MD5
-authentication algorithm.
-
-.sp
-.in +2
-.nf
-# \fBsvccfg -s svc:/system/cvc setprop cvc/ah_auth = "md5"\fR
-# \fBsvccfg -s svc:/system/cvc setprop cvc/esp_encr = "none"\fR
-# \fBsvccfg -s svc:/system/cvc setprop cvc/esp_auth = "none"\fR
-# \fBsvcadm refresh svc:/system/cvc\fR
-.fi
-.in -2
-.sp
-
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE	ATTRIBUTE VALUE
-_
-Architecture	T{
-Sun Enterprise 10000 servers, Sun Fire High-End Systems
-T}
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBsvcs\fR(1), \fBsvcadm\fR(1M), \fBsvccfg\fR(1M), \fBservices\fR(4),
-\fBattributes\fR(5), \fBsmf\fR(5), \fBcvc\fR(7D), \fBcvcredir\fR(7D),
-\fBipsec\fR(7P)
-.sp
-.LP
-\fISun Enterprise 10000 SSP Reference Manual\fR
-.sp
-.LP
-\fISystem Management Services (SMS) Reference Manual\fR
-.SH NOTES
-.sp
-.LP
-The \fBcvcd\fR service is managed by the service management facility,
-\fBsmf\fR(5), under the fault management resource identifier (FMRI):
-.sp
-.in +2
-.nf
-svc:/system/cvc
-.fi
-.in -2
-.sp
-
-.sp
-.LP
-Administrative actions on this service, such as enabling, disabling, or
-requesting restart, can be performed using \fBsvcadm\fR(1M) or
-\fBsvccfg\fR(1M). The service's status can be queried using the \fBsvcs\fR(1)
-command.
--- a/usr/src/man/man1m/dcs.1m	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/man/man1m/dcs.1m	Fri May 31 14:32:40 2019 +0200
@@ -1,20 +1,19 @@
 '\" te
 .\" Copyright 2005 (c), Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright 2019 Peter Tribble.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DCS 1M "Apr 25, 2006"
+.TH DCS 1M "Apr 3, 2019"
 .SH NAME
 dcs \- domain configuration server
 .SH SYNOPSIS
 .LP
 .nf
-\fB/usr/lib/dcs\fR [\fB-s\fR \fIsessions\fR]
-     [ [\fB-a\fR \fIauth\fR] [\fB-e\fR \fIencr\fR] [\fB-u\fR \fIesp_auth\fR] ] [\fB-l\fR]
+\fB/usr/lib/dcs\fR [\fB-s\fR \fIsessions\fR] [\fB-l\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The Domain Configuration Server (DCS) is a daemon process that runs on Sun
 servers that support remote Dynamic Reconfiguration (DR) clients. It is started
@@ -26,7 +25,7 @@
 .sp
 .LP
 The DCS listens on the network service labeled \fBsun-dr\fR. Its underlying
-protocol is TCP. It is invoked as a server program by the SMF using the TCP
+protocol is TCP. It is invoked as a server program by SMF using the TCP
 transport. The fault management resource identifier (FMRI) for DCS is:
 .sp
 .in +2
@@ -42,58 +41,17 @@
 There is no negative impact on the server.
 .sp
 .LP
-Security for the DCS connection is provided differently based upon the
-architecture of the system. The SMF specifies the correct options when invoking
-the DCS daemon, based upon the current architecture. For all architectures,
-security is provided on a per-connection basis.
-.sp
-.LP
-The DCS daemon has no security options that are applicable when used on a Sun
-Enterprise 10000 system. So there are no options applicable to that
-architecture.
-.sp
-.LP
-The security options for Sun Fire high-end systems are based on IPsec options
-defined as SMF properties. These options include the \fB-a\fR \fIauth\fR,
-\fB-e\fR \fIencr\fR, and \fB-u\fR \fIesp_auth\fR options, and can be set using
-the \fBsvccfg\fR(1M) command. These options must match the IPsec policies
-defined for DCS on the system controller. Refer to the \fBkmd(1M)\fR man page
-in the \fISystem Management Services (SMS) Reference Manual\fR. The
-\fBkmd(1M)\fR man page is not part of the SunOS man page collection.
-.sp
-.LP
 Security on SPARC Enterprise Servers is not configurable. The DCS daemon uses a
 platform-specific library to configure its security options when running on
-such systems. The \fB-l\fR option is provided by the SMF when invoking the DCS
+such systems. The \fB-l\fR option is provided by SMF when invoking the DCS
 daemon on SPARC Enterprise Servers. No other security options to the DCS daemon
 should be used on SPARC Enterprise Servers.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
 .ne 2
 .na
-\fB\fB-a\fR \fIauth\fR\fR
-.ad
-.RS 15n
-Controls the IPsec Authentication Header (AH) algorithm. \fIauth\fR can be one
-of \fBnone\fR, \fBmd5\fR, or \fBsha1\fR.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fB-e\fR \fIencr\fR\fR
-.ad
-.RS 15n
-Controls the IPsec Encapsulating Security Payload (ESP) encryption algorithm.
-\fIencr\fR can be one of \fBnone\fR, \fBdes\fR, or \fB3des\fR.
-.RE
-
-.sp
-.ne 2
-.na
 \fB\fB-l\fR\fR
 .ad
 .RS 15n
@@ -113,38 +71,7 @@
 a default value of 128 is used.
 .RE
 
-.sp
-.ne 2
-.na
-\fB\fB-u\fR \fIesp_auth\fR\fR
-.ad
-.RS 15n
-Controls the IPsec Encapsulating Security Payload (ESP) authentication
-algorithm. \fIesp_auth\fR can be one of \fBnone\fR, \fBmd5\fR, or \fBsha1\fR.
-.RE
-
-.SH EXAMPLES
-.LP
-\fBExample 1 \fRSetting an IPSec Option
-.sp
-.LP
-The following command sets the Authentication Header algorithm for the DCS
-daemon to use the HMAC-MD5 authentication algorithm. These settings are only
-applicable for using the DCS daemon on a Sun Fire high-end system.
-
-.sp
-.in +2
-.nf
-# \fBsvccfg -s svc:/platform/sun4u/dcs setprop dcs/ah_auth = "md5"\fR
-# \fBsvccfg -s svc:/platform/sun4u/dcs setprop dcs/esp_encr = "none"\fR
-# \fBsvccfg -s svc:/platform/sun4u/dcs setprop dcs/esp_auth = "none"\fR
-# \fBsvcadm refresh svc:/platform/sun4u/dcs\fR
-.fi
-.in -2
-.sp
-
 .SH ERRORS
-.sp
 .LP
 The DCS uses \fBsyslog\fR(3C) to report status and error messages. All of the
 messages are logged with the \fBLOG_DAEMON\fR facility. Error messages are
@@ -153,7 +80,6 @@
 entries in the \fB/etc/syslog.conf\fR file log all of the DCS error messages to
 the \fB/var/adm/messages\fR log.
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -169,13 +95,11 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBsvcs\fR(1), \fBcfgadm_sbd\fR(1M), \fBsvcadm\fR(1M), \fBsvccfg\fR(1M),
+\fBsvcs\fR(1), \fBcfgadm_sbd\fR(1M), \fBsvcadm\fR(1M),
 \fBsyslog\fR(3C), \fBconfig_admin\fR(3CFGADM), \fBlibcfgadm\fR(3LIB),
 \fBsyslog.conf\fR(4), \fBattributes\fR(5), \fBsmf\fR(5), \fBdr\fR(7D)
 .SH NOTES
-.sp
 .LP
 The \fBdcs\fR service is managed by the service management facility,
 \fBsmf\fR(5), under the fault management resource identifier (FMRI):
--- a/usr/src/man/man1m/sckmd.1m	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/man/man1m/sckmd.1m	Fri May 31 14:32:40 2019 +0200
@@ -1,9 +1,10 @@
 '\" te
 .\" Copyright (c) 2005, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2019 Peter Tribble.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SCKMD 1M "Apr 25, 2006"
+.TH SCKMD 1M "Apr 3, 2019"
 .SH NAME
 sckmd \- Sun cryptographic key management daemon
 .SH SYNOPSIS
@@ -13,13 +14,12 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 \fBsckmd\fR is a server process that resides on a high-end system domain to
 maintain the Internet Protocol Security (\fBIPsec\fR) Security Associations
 (\fBSAs\fR) needed to secure communications between a Service Processor or
 System Controller (SC) and platform management software running within a
-domain. The \fBcvcd\fR(1M) and \fBdcs\fR(1M) daemons use these Security
+domain. The \fBdcs\fR(1M) daemon uses these Security
 Associations. See \fBipsec\fR(7P) for a description of Security Associations.
 .sp
 .LP
@@ -42,7 +42,6 @@
 .LP
 A domain supports only one running \fBsckmd\fR process at a time.
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -58,20 +57,18 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBcvcd\fR(1M), \fBdcs\fR(1M), \fBipsecconf\fR(1M), \fBipsecalgs\fR(1M),
+\fBdcs\fR(1M), \fBipsecconf\fR(1M), \fBipsecalgs\fR(1M),
 \fBattributes\fR(5), \fBipsec\fR(7P), \fBipsecah\fR(7P), \fBipsecesp\fR(7P),
 \fBpf_key\fR(7P)
 .SH NOTES
-.sp
 .LP
-The \fBsckmd\fR service is used only on Sun Fire high-end systems and the
-\fBSPARC\fR Enterprise Server family. It provides a mechanism for exchanging
+The \fBsckmd\fR service is used only on Sun Fire high-end systems.
+It provides a mechanism for exchanging
 \fBIPsec\fR keys between a domain and its System Controller (\fBSC\fR) or
 Service Processor. These platforms use \fBIPsec\fR to secure the communications
-between the \fBSC\fR or Service Processor and certain platform-specific daemons
-in the domain. Such daemons currently include \fBcvcd\fR(1M) and \fBdcs\fR(1M).
+between the \fBSC\fR or Service Processor and a platform-specific daemon
+in the domain, such as \fBdcs\fR(1M).
 .sp
 .LP
 The documentation for each platform that supports \fBsckmd\fR describes how to
--- a/usr/src/man/man7d/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/man/man7d/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
 
 include		$(SRC)/Makefile.master
 
-MANSECT= 	7d
+MANSECT=	7d
 
 _MANFILES=	aac.7d		\
 		afe.7d		\
@@ -152,8 +152,6 @@
 sparc_MANFILES=	audiocs.7d	\
 		bbc_beep.7d	\
 		ctsmc.7d	\
-		cvc.7d		\
-		cvcredir.7d	\
 		dad.7d		\
 		dm2s.7d		\
 		dr.7d		\
@@ -171,7 +169,6 @@
 		pcicmu.7d	\
 		pcipsy.7d	\
 		pcisch.7d	\
-		schpc.7d	\
 		sf.7d		\
 		smbus.7d	\
 		socal.7d	\
--- a/usr/src/man/man7d/cvc.7d	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-'\" te
-.\"  Copyright (c) 2000, Sun Microsystems, Inc.  All Rights Reserved
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
-.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
-.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH CVC 7D "Sep 15, 2000"
-.SH NAME
-cvc \- virtual console driver
-.SH DESCRIPTION
-.sp
-.LP
-The \fBcvc\fR virtual console driver is a STREAMS-based pseudo driver that
-supports the network console. The \fBcvc\fR driver interfaces with
-\fBconsole\fR(7D).
-.sp
-.LP
-Logically, the  \fBcvc\fR driver sits below the  \fBconsole\fR driver. It
-redirects console output to the \fBcvcredir\fR(7D) driver if a network console
-connection is active. If a network console connection is not active, it
-redirects console output to an internal hardware interface.
-.sp
-.LP
-The \fBcvc\fR driver receives console input from  \fBcvcredir\fR and internal
-hardware and passes it to the process associated with \fB/dev/console\fR.
-.SH NOTES
-.sp
-.LP
-The  \fBcvc\fR facility supersedes the SunOS \fBwscons\fR(7D) facility, which
-should  \fInot\fR be used in conjunction with  \fBcvc\fR. The  \fBwscons\fR
-driver is useful for systems with directly attached consoles (frame buffers and
-keyboards), but is not useful with platforms using \fBcvc\fR, which have no
-local keyboard or frame buffer.
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE	ATTRIBUTE VALUE
-_
-Architecture	T{
-Sun Enterprise 10000 servers,  Sun Fire 15000 servers
-T}
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBcvcd\fR(1M), \fBattributes\fR(5), \fBconsole\fR(7D), \fBcvcredir\fR(7D),
-\fBwscons\fR(7D)
-.sp
-.LP
-\fISun Enterprise 10000 SSP Reference Manual\fR
-.sp
-.LP
-\fISun System Management Services (SMS) Reference Manual\fR
--- a/usr/src/man/man7d/cvcredir.7d	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-'\" te
-.\"  Copyright (c) 2000, Sun Microsystems, Inc.  All Rights Reserved
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
-.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
-.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH CVCREDIR 7D "Sep 15, 2000"
-.SH NAME
-cvcredir \- virtual console redirection driver
-.SH DESCRIPTION
-.sp
-.LP
-The \fBcvcredir\fR virtual console redirection driver is a STREAMS-based pseudo
-driver that supports the network console provided on some platforms. The
-\fBcvcredir\fR driver interfaces with the virtual console driver \fBcvc\fR(7D),
-and the  virtual console  daemon,  \fBcvcd\fR(1M).
-.sp
-.LP
-The  \fBcvcredir\fR driver receives console output from \fBcvc\fR and passes it
-to  \fBcvcd\fR. It receives console input from  \fBcvcd\fR and passes it to
-\fBcvc\fR.
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE	ATTRIBUTE VALUE
-_
-Architecture	T{
-Sun Enterprise 10000 servers, Sun Fire 15K servers
-T}
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBcvcd\fR(1M), \fBattributes\fR(5), \fBconsole\fR(7D), \fBcvc\fR(7D)
-.sp
-.LP
-\fISun Enterprise 10000 SSP Reference Manual \fR
-.sp
-.LP
-\fISun System Management Services (SMS) Reference Manual\fR
--- a/usr/src/man/man7d/schpc.7d	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-'\" te
-.\" Copyright (c) 2005, Sun Microsystems, Inc.  All Rights Reserved
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
-.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
-.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SCHPC 7D "May 26, 2005"
-.SH NAME
-schpc \- StarCat Hot Plug Controller Driver
-.SH DESCRIPTION
-.sp
-.LP
-The \fBschpc\fR driver controls all hot-plug operations on high-end Sun Fire
-E15K and E25K enterprise servers.
-.SH FILES
-.sp
-.ne 2
-.na
-\fB\fB/platform/SUNW,Sun-Fire-15000/kernel/drv/sparcv9/schpc\fR\fR
-.ad
-.sp .6
-.RS 4n
-64-bit ELF kernel module.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fB/platform/SUNW,Sun-Fire-15000/kernel/drv/schpc.conf\fR\fR
-.ad
-.sp .6
-.RS 4n
-Driver configuration file.
-.RE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBcfgadm\fR(1M)
--- a/usr/src/man/man7d/wscons.7d	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/man/man7d/wscons.7d	Fri May 31 14:32:40 2019 +0200
@@ -1,9 +1,10 @@
 '\" te
 .\" Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+.\" Copyright 2019 Peter Tribble.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH WSCONS 7D "May 26, 2006"
+.TH WSCONS 7D "Apr 3, 2019"
 .SH NAME
 wscons \- workstation console
 .SH SYNOPSIS
@@ -23,7 +24,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBwscons\fR workstation console consists of a workstation keyboard and
 frame buffer that act together to emulate an \fBASCII\fR terminal. It includes
@@ -31,7 +31,6 @@
 diverted to a STREAMS device, enabling window systems to redirect output that
 would otherwise appear directly on the frame buffer in corrupted form.
 .SS "Redirection"
-.sp
 .LP
 The \fBwscons\fR redirection facility maintains a list of devices that are
 designated as redirection targets through the \fBSRIOCSREDIR\fR ioctl described
@@ -65,7 +64,6 @@
 .RE
 
 .SS "ANSI Standard Terminal Emulation"
-.sp
 .LP
 The Solaris kernel terminal emulator provides ANSI X3.64 emulation both on
 SPARC and x86 systems.
@@ -111,7 +109,6 @@
 below). The line-feed function scrolls the screen up by one or more lines
 before moving the cursor to the first character position on the next line.
 .SS "Control Sequence Syntax"
-.sp
 .LP
 The \fBwscons\fR console defines a number of control sequences that may occur
 during input.  When a control sequence is written to the console, it affects
@@ -246,7 +243,6 @@
 is \fInot\fR equivalent to \fBESC[5;M\fR (interpreted as `\fBESC[5;1M\fR')
 which is ultimately interpreted as `\fBESC[1M\fR').
 .SS "ANSI Control Functions"
-.sp
 .LP
 The following paragraphs specify the \fBANSI\fR control functions implemented
 by the console.  Each description provides:
@@ -288,7 +284,6 @@
 initial settings, use the \fBSUNRESET\fR escape sequence.
 .RE
 .SS "Control Character Functions"
-.sp
 .LP
 The \fBwscons \fRcontrol character functions are:
 .sp
@@ -449,7 +444,6 @@
 .RE
 
 .SS "Escape Sequence Functions"
-.sp
 .LP
 The \fBwscons \fRescape sequence functions are:
 .sp
@@ -966,7 +960,6 @@
 .RE
 
 .SH RETURN VALUES
-.sp
 .LP
 When there are no errors, the redirection ioctls have return values as
 described above. Otherwise, they return  \fB\(mi1\fR and set \fBerrno\fR to
@@ -977,7 +970,6 @@
 If the \fItarget\fR stream is in an error state, \fBerrno\fR is set
 accordingly.
 .SH ERRORS
-.sp
 .ne 2
 .na
 \fB\fBEBADF\fR\fR
@@ -996,7 +988,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/dev/wscons\fR\fR
@@ -1034,7 +1025,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -1050,19 +1040,12 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
-\fBcvcd\fR(1M), \fBeeprom\fR(1M), \fBioctl\fR(2), \fBpoll\fR(2), \fBread\fR(2),
-\fBwrite\fR(2), \fBcvc\fR(7D), \fBconsole\fR(7D), \fBvisual_io\fR(7I)
+\fBeeprom\fR(1M), \fBioctl\fR(2), \fBpoll\fR(2), \fBread\fR(2),
+\fBwrite\fR(2), \fBconsole\fR(7D), \fBvisual_io\fR(7I)
 .SH WARNINGS
-.sp
 .LP
 The redirection ioctls block while there is I/O outstanding on the device
 instance being redirected. If you try to redirect the workstation console while
 there is a outstanding read, the workstation console will hang until the read
 completes.
-.SH NOTES
-.sp
-.LP
-The \fBcvc \fRfacility supersedes the SunOS \fBwscons \fRfacility and should
-not be used with \fBwscons\fR.
--- a/usr/src/pkg/manifests/SUNWcs.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/SUNWcs.mf	Fri May 31 14:32:40 2019 +0200
@@ -450,8 +450,6 @@
 file path=etc/svc/profile/ns_none.xml group=sys mode=0444
 $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,SPARC-Enterprise.xml \
     group=sys mode=0444
-$(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire-15000.xml \
-    group=sys mode=0444
 $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire-880.xml \
     group=sys mode=0444
 $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire.xml group=sys \
--- a/usr/src/pkg/manifests/SUNWcvc.mf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-#
-
-set name=pkg.fmri value=pkg:/SUNWcvc@0.5.11,5.11-0.133
-set name=pkg.renamed value=true
-set name=variant.arch value=sparc
-depend fmri=pkg:/system/network-console@0.5.11,5.11-0.133 type=require
--- a/usr/src/pkg/manifests/SUNWdrcr.mf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-#
-
-set name=pkg.fmri value=pkg:/SUNWdrcr@0.5.11,5.11-0.133
-set name=pkg.renamed value=true
-set name=variant.arch value=sparc
-depend \
-    fmri=pkg:/system/kernel/dynamic-reconfiguration/sun-fire-15000@0.5.11,5.11-0.133 \
-    type=require
--- a/usr/src/pkg/manifests/developer-apptrace-platform.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/developer-apptrace-platform.mf	Fri May 31 14:32:40 2019 +0200
@@ -53,8 +53,6 @@
 dir path=usr/platform/SUNW,Sun-Blade-2500 group=sys
 dir path=usr/platform/SUNW,Sun-Blade-2500/lib
 dir path=usr/platform/SUNW,Sun-Fire group=sys
-dir path=usr/platform/SUNW,Sun-Fire-15000 group=sys
-dir path=usr/platform/SUNW,Sun-Fire-15000/lib
 dir path=usr/platform/SUNW,Sun-Fire-280R group=sys
 dir path=usr/platform/SUNW,Sun-Fire-280R/lib
 dir path=usr/platform/SUNW,Sun-Fire-480R group=sys
--- a/usr/src/pkg/manifests/service-fault-management.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/service-fault-management.mf	Fri May 31 14:32:40 2019 +0200
@@ -23,6 +23,7 @@
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 # Copyright (c) 2019, Joyent, Inc.
 # Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2019 Peter Tribble.
 #
 
 #
@@ -166,13 +167,6 @@
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Blade-T6320/lib/fm/topo
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Blade-T6320/lib/fm/topo/maps
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire group=sys
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000 group=sys
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib/fm
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/eft
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/maps
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/plugins
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-T200 group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-T200/lib
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-T200/lib/fm
@@ -625,15 +619,6 @@
     path=usr/platform/SUNW,Sun-Blade-T6320/lib/fm/topo/maps/Sun-Blade-T6320-hc-topology.xml \
     mode=0444
 $(sparc_ONLY)file \
-    path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/eft/SUNW,Sun-Fire-15000.eft \
-    mode=0444
-$(sparc_ONLY)file \
-    path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/maps/Sun-Fire-15000-hc-topology.xml \
-    mode=0444
-$(sparc_ONLY)file \
-    path=usr/platform/SUNW,Sun-Fire-15000/lib/fm/topo/plugins/ioboard.so \
-    mode=0555
-$(sparc_ONLY)file \
     path=usr/platform/SUNW,Sun-Fire-T200/lib/fm/fmd/plugins/etm.conf
 $(sparc_ONLY)file \
     path=usr/platform/SUNW,Sun-Fire-T200/lib/fm/topo/maps/Netra-T2000-hc-topology.xml \
--- a/usr/src/pkg/manifests/service-file-system-smb.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/service-file-system-smb.mf	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+# Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/service/file-system/smb@$(PKGVERS)
@@ -49,6 +49,7 @@
 dir path=usr/lib/mdb group=sys
 dir path=usr/lib/mdb/kvm group=sys
 dir path=usr/lib/mdb/kvm/$(ARCH64) group=sys
+dir path=usr/lib/mdb/proc group=sys
 dir path=usr/lib/reparse
 dir path=usr/lib/security
 dir path=usr/lib/smbsrv
@@ -74,6 +75,7 @@
 file path=usr/lib/fs/smb/$(ARCH64)/libshare_smb.so.1
 file path=usr/lib/fs/smb/libshare_smb.so.1
 file path=usr/lib/mdb/kvm/$(ARCH64)/smbsrv.so group=sys mode=0555
+file path=usr/lib/mdb/proc/libmlsvc.so group=sys mode=0555
 file path=usr/lib/reparse/libreparse_smb.so.1
 file path=usr/lib/security/pam_smb_passwd.so.1
 file path=usr/lib/smbsrv/dtrace/smbd-all.d mode=0555
--- a/usr/src/pkg/manifests/service-key-management-sun-fire-15000.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/service-key-management-sun-fire-15000.mf	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,7 @@
 
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2019 Peter Tribble.
 #
 
 #
@@ -30,41 +31,6 @@
 #
 <include global_zone_only_component>
 set name=pkg.fmri value=pkg:/service/key-management/sun-fire-15000@$(PKGVERS)
-set name=pkg.description value="Key Management Modules for Sun Fire 15000"
-set name=pkg.summary value="Key Management Modules for Sun Fire 15000"
-set name=info.classification \
-    value="org.opensolaris.category.2008:System/Enterprise Management"
+set name=pkg.obsolete value=true
+set name=org.opensolaris.noincorp value=true
 set name=variant.arch value=sparc
-dir path=lib
-dir path=lib/svc
-dir path=lib/svc/manifest group=sys
-dir path=lib/svc/manifest/platform group=sys
-dir path=lib/svc/manifest/platform/sun4u group=sys
-dir path=lib/svc/method
-dir path=platform group=sys
-dir path=platform/SUNW,Sun-Fire-15000 group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/drv group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64) group=sys
-dir path=usr group=sys
-dir path=usr/platform group=sys
-dir path=usr/platform/sun4u group=sys
-dir path=usr/platform/sun4u/lib
-dir path=usr/share/man/man1m
-driver name=sckmdrv perms="* 0600 root sys"
-file path=lib/svc/manifest/platform/sun4u/sckmd.xml group=sys mode=0444
-file path=lib/svc/method/svc-sckmd mode=0555
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/sckmdrv group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/sckmdrv.conf group=sys
-file path=usr/platform/sun4u/lib/sckmd group=sys mode=0755
-file path=usr/share/man/man1m/sckmd.1m
-legacy pkg=SUNWsckm.u arch=$(ARCH).sun4u \
-    desc="Key Management Modules for Sun Fire 15000" \
-    name="Key Management Modules for Sun Fire 15000"
-legacy pkg=SUNWsckmr desc="SMF service for the Key Management daemon" \
-    name="SMF service for the Key Management daemon"
-legacy pkg=SUNWsckmu.u arch=$(ARCH).sun4u \
-    desc="Key Management daemon for exchanging security keys from the Service Processor" \
-    name="Key Management daemon"
-license cr_Sun license=cr_Sun
-license lic_CDDL license=lic_CDDL
--- a/usr/src/pkg/manifests/system-domain-service-processor-protocol-sparc-enterprise.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/system-domain-service-processor-protocol-sparc-enterprise.mf	Fri May 31 14:32:40 2019 +0200
@@ -22,6 +22,7 @@
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 # Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2019 Peter Tribble.
 #
 
 #
@@ -54,13 +55,17 @@
 dir path=usr/platform/SUNW,SPARC-Enterprise group=sys
 dir path=usr/platform/SUNW,SPARC-Enterprise/lib
 dir path=usr/platform/SUNW,SPARC-Enterprise/sbin
+dir path=usr/platform/sun4u group=sys
+dir path=usr/platform/sun4u/lib
 dir path=usr/share/man
 dir path=usr/share/man/man1m
 dir path=usr/share/man/man7d
 driver name=dm2s
 driver name=oplkmdrv
 file path=lib/svc/manifest/platform/sun4u/dscp.xml group=sys mode=0444
+file path=lib/svc/manifest/platform/sun4u/sckmd.xml group=sys mode=0444
 file path=lib/svc/method/svc-dscp mode=0555
+file path=lib/svc/method/svc-sckmd mode=0555
 file path=platform/SUNW,SPARC-Enterprise/kernel/drv/$(ARCH64)/dm2s group=sys
 file path=platform/SUNW,SPARC-Enterprise/kernel/drv/$(ARCH64)/oplkmdrv \
     group=sys
@@ -70,7 +75,9 @@
     mode=0555
 file path=usr/platform/SUNW,SPARC-Enterprise/lib/libdscp.so.1
 file path=usr/platform/SUNW,SPARC-Enterprise/sbin/prtdscp mode=0755
+file path=usr/platform/sun4u/lib/sckmd group=sys mode=0755
 file path=usr/share/man/man1m/prtdscp.1m
+file path=usr/share/man/man1m/sckmd.1m
 file path=usr/share/man/man7d/dm2s.7d
 file path=usr/share/man/man7d/oplkmdrv.7d
 legacy pkg=SUNWdscpr.u arch=$(ARCH).sun4u \
--- a/usr/src/pkg/manifests/system-header.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/system-header.mf	Fri May 31 14:32:40 2019 +0200
@@ -140,7 +140,6 @@
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Blade-1500 group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Blade-2500 group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire group=sys
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000 group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-280R group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-480R group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-880 group=sys
@@ -1983,8 +1982,6 @@
     target=../sun4u/include
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Blade-2500/include \
     target=../sun4u/include
-$(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-15000/include \
-    target=../sun4u/include
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-280R/include \
     target=../sun4u/include
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-480R/include \
--- a/usr/src/pkg/manifests/system-kernel-dynamic-reconfiguration-sun-fire-15000.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/system-kernel-dynamic-reconfiguration-sun-fire-15000.mf	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,7 @@
 
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2019 Peter Tribble.
 #
 
 #
@@ -31,32 +32,6 @@
 <include global_zone_only_component>
 set name=pkg.fmri \
     value=pkg:/system/kernel/dynamic-reconfiguration/sun-fire-15000@$(PKGVERS)
-set name=pkg.description \
-    value="Dynamic Reconfiguration Modules for Sun Fire 15000"
-set name=pkg.summary \
-    value="Dynamic Reconfiguration Modules for Sun Fire 15000"
-set name=info.classification \
-    value="org.opensolaris.category.2008:System/Enterprise Management"
+set name=pkg.obsolete value=true
+set name=org.opensolaris.noincorp value=true
 set name=variant.arch value=sparc
-dir path=platform group=sys
-dir path=platform/SUNW,Sun-Fire-15000 group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/drv group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64) group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/misc group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64) group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/dr group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/dr.conf group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/drmach group=sys \
-    mode=0755
-file path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/fcgp2 group=sys \
-    mode=0755
-file path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/gptwo_pci \
-    group=sys mode=0755
-file path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/sc_gptwocfg \
-    group=sys mode=0755
-legacy pkg=SUNWdrcr.u arch=$(ARCH).sun4u \
-    desc="Dynamic Reconfiguration Modules for Sun Fire 15000" \
-    name="Dynamic Reconfiguration Modules for Sun Fire 15000"
-license cr_Sun license=cr_Sun
-license lic_CDDL license=lic_CDDL
--- a/usr/src/pkg/manifests/system-kernel-platform.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/system-kernel-platform.mf	Fri May 31 14:32:40 2019 +0200
@@ -141,21 +141,6 @@
 $(sparc_ONLY)dir path=platform/SUNW,Sun-Blade-2500/kernel/misc/$(ARCH64) \
     group=sys
 $(sparc_ONLY)dir path=platform/SUNW,Sun-Fire group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000 group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/$(ARCH64) group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/cpu group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/cpu/$(ARCH64) \
-    group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/crypto group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/crypto/$(ARCH64) \
-    group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/drv group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64) \
-    group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/misc group=sys
-$(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64) \
-    group=sys
 $(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-280R group=sys
 $(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-280R/kernel group=sys
 $(sparc_ONLY)dir path=platform/SUNW,Sun-Fire-280R/kernel/crypto group=sys
@@ -354,7 +339,6 @@
 $(i386_ONLY)driver name=amd_iommu perms="* 0644 root sys" \
     alias=pci1002,5a23 \
     alias=pci1022,11ff
-$(sparc_ONLY)driver name=axq alias=SUNW,axq
 $(i386_ONLY)driver name=balloon perms="* 0444 root sys"
 $(sparc_ONLY)driver name=bbc_beep alias=SUNW,bbc-beep
 $(sparc_ONLY)driver name=central
@@ -382,7 +366,6 @@
     alias=pci108e,6722 \
     alias=pciclass,060940 \
     alias=pciclass,060980
-$(sparc_ONLY)driver name=dman perms="* 0600 root sys"
 $(i386_ONLY)driver name=domcaps perms="* 0444 root sys"
 $(sparc_ONLY)driver name=dr
 $(sparc_ONLY)driver name=ebus class=ebus \
@@ -412,7 +395,6 @@
     alias=i2c-hpc3130
 $(sparc_ONLY)driver name=i2bsc alias=SUNW,i2bsc
 $(sparc_ONLY)driver name=ics951601 alias=i2c-ics951601
-$(sparc_ONLY)driver name=iosram
 $(i386_ONLY)driver name=isa alias=pciclass,060100 class=sysbus
 $(sparc_ONLY)driver name=isadma
 $(sparc_ONLY)driver name=jbusppm alias=jbus-ppm
@@ -489,7 +471,6 @@
 $(sparc_ONLY)driver name=sbus class=sbus
 $(sparc_ONLY)driver name=sbusmem
 $(sparc_ONLY)driver name=scfd alias=FJSV,scfc
-$(sparc_ONLY)driver name=schpc
 $(sparc_ONLY)driver name=schppm alias=gp2-ppm
 $(sparc_ONLY)driver name=seeprom \
     alias=i2c-at24c64 \
@@ -647,35 +628,6 @@
 $(sparc_ONLY)file \
     path=platform/SUNW,Sun-Blade-2500/kernel/misc/$(ARCH64)/platmod group=sys \
     mode=0755
-$(sparc_ONLY)file path=platform/SUNW,Sun-Fire-15000/kernel/$(ARCH64)/unix \
-    group=sys mode=0755
-$(sparc_ONLY)file \
-    path=platform/SUNW,Sun-Fire-15000/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-III \
-    group=sys mode=0755
-$(sparc_ONLY)file \
-    path=platform/SUNW,Sun-Fire-15000/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-III+ \
-    group=sys mode=0755
-$(sparc_ONLY)file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/axq \
-    group=sys
-$(sparc_ONLY)file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/dman \
-    group=sys
-$(sparc_ONLY)file \
-    path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/iosram group=sys
-$(sparc_ONLY)file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/schpc \
-    group=sys
-$(sparc_ONLY)file path=platform/SUNW,Sun-Fire-15000/kernel/drv/dman.conf \
-    group=sys
-$(sparc_ONLY)file path=platform/SUNW,Sun-Fire-15000/kernel/drv/schpc.conf \
-    group=sys
-$(sparc_ONLY)file \
-    path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/mboxsc group=sys \
-    mode=0755
-$(sparc_ONLY)file \
-    path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/platmod group=sys \
-    mode=0755
-$(sparc_ONLY)file \
-    path=platform/SUNW,Sun-Fire-15000/kernel/misc/$(ARCH64)/scosmb group=sys \
-    mode=0755
 $(sparc_ONLY)file \
     path=platform/SUNW,Sun-Fire-280R/kernel/drv/$(ARCH64)/pcf8574 group=sys
 $(sparc_ONLY)file \
@@ -1387,8 +1339,6 @@
     mode=0755
 $(sparc_ONLY)file path=platform/sun4u/kernel/tod/$(ARCH64)/todsg group=sys \
     mode=0755
-$(sparc_ONLY)file path=platform/sun4u/kernel/tod/$(ARCH64)/todstarcat \
-    group=sys mode=0755
 $(sparc_ONLY)file path=platform/sun4v/bootlst group=sys reboot-needed=true
 $(sparc_ONLY)file path=platform/sun4v/kernel/$(ARCH64)/genunix group=sys \
     mode=0755
@@ -1451,7 +1401,6 @@
 $(sparc_ONLY)file path=usr/share/man/man7d/pcicmu.7d
 $(sparc_ONLY)file path=usr/share/man/man7d/pcipsy.7d
 $(sparc_ONLY)file path=usr/share/man/man7d/pcisch.7d
-$(sparc_ONLY)file path=usr/share/man/man7d/schpc.7d
 $(sparc_ONLY)file path=usr/share/man/man7d/smbus.7d
 $(sparc_ONLY)file path=usr/share/man/man7d/su.7d
 $(sparc_ONLY)file path=usr/share/man/man7d/todopl.7d
@@ -1776,15 +1725,6 @@
 $(sparc_ONLY)link \
     path=platform/SUNW,Sun-Blade-2500/kernel/crypto/$(ARCH64)/aes \
     target=../../../../sun4u-us3/kernel/crypto/$(ARCH64)/aes
-$(sparc_ONLY)link \
-    path=platform/SUNW,Sun-Fire-15000/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-IV \
-    target=SUNW,UltraSPARC-III+
-$(sparc_ONLY)link \
-    path=platform/SUNW,Sun-Fire-15000/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-IV+ \
-    target=SUNW,UltraSPARC-III+
-$(sparc_ONLY)link \
-    path=platform/SUNW,Sun-Fire-15000/kernel/crypto/$(ARCH64)/aes \
-    target=../../../../sun4u-us3/kernel/crypto/$(ARCH64)/aes
 $(sparc_ONLY)link path=platform/SUNW,Sun-Fire-280R/kernel/crypto/$(ARCH64)/aes \
     target=../../../../sun4u-us3/kernel/crypto/$(ARCH64)/aes
 $(sparc_ONLY)link path=platform/SUNW,Sun-Fire-480R/kernel/crypto/$(ARCH64)/aes \
--- a/usr/src/pkg/manifests/system-library-platform.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/system-library-platform.mf	Fri May 31 14:32:40 2019 +0200
@@ -77,8 +77,6 @@
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Blade-T6320 group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Blade-T6320/lib
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire group=sys
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000 group=sys
-$(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-15000/lib
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-280R group=sys
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-280R/lib
 $(sparc_ONLY)dir path=usr/platform/SUNW,Sun-Fire-480R group=sys
@@ -159,8 +157,6 @@
 $(sparc_ONLY)file path=usr/platform/SUNW,SPARC-Enterprise/lib/cfgadm/scsi.so.1
 $(sparc_ONLY)file \
     path=usr/platform/SUNW,SPARC-Enterprise/lib/libprtdiag_psr.so.1
-$(sparc_ONLY)file \
-    path=usr/platform/SUNW,Sun-Fire-15000/lib/libprtdiag_psr.so.1
 $(sparc_ONLY)file path=usr/platform/SUNW,Sun-Fire-280R/lib/libprtdiag_psr.so.1
 $(sparc_ONLY)file path=usr/platform/SUNW,Sun-Fire-480R/lib/libprtdiag_psr.so.1
 $(sparc_ONLY)file path=usr/platform/SUNW,Sun-Fire-880/lib/libprtdiag_psr.so.1
@@ -355,12 +351,6 @@
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Blade-T6320/sbin \
     target=../sun4v/sbin
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Blade-T6340 target=SUNW,T5140
-$(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-15000/lib/cfgadm \
-    target=../../sun4u/lib/cfgadm
-$(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-15000/lib/fs \
-    target=../../sun4u/lib/fs
-$(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-15000/sbin \
-    target=../sun4u/sbin
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-280R/lib/cfgadm \
     target=../../sun4u/lib/cfgadm
 $(sparc_ONLY)link path=usr/platform/SUNW,Sun-Fire-280R/lib/fs \
--- a/usr/src/pkg/manifests/system-network-console.mf	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/pkg/manifests/system-network-console.mf	Fri May 31 14:32:40 2019 +0200
@@ -31,39 +31,6 @@
 #
 <include global_zone_only_component>
 set name=pkg.fmri value=pkg:/system/network-console@$(PKGVERS)
-set name=pkg.description value="Network Console"
-set name=pkg.summary value="Network Console"
-set name=info.classification value=org.opensolaris.category.2008:System/Core
+set name=pkg.obsolete value=true
+set name=org.opensolaris.noincorp value=true
 set name=variant.arch value=sparc
-dir path=lib
-dir path=lib/svc
-dir path=lib/svc/manifest group=sys
-dir path=lib/svc/manifest/system group=sys
-dir path=lib/svc/method
-dir path=platform group=sys
-dir path=platform/SUNW,Sun-Fire-15000 group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/drv group=sys
-dir path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64) group=sys
-dir path=platform/SUNW,Sun-Fire-15000/lib
-dir path=usr/share/man
-dir path=usr/share/man/man1m
-dir path=usr/share/man/man7d
-driver name=cvc perms="* 0600 root sys"
-driver name=cvcredir perms="* 0600 root sys"
-file path=lib/svc/manifest/system/cvc.xml group=sys mode=0444
-file path=lib/svc/method/svc-cvcd mode=0555
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/cvc group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/$(ARCH64)/cvcredir group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/cvc.conf group=sys
-file path=platform/SUNW,Sun-Fire-15000/kernel/drv/cvcredir.conf group=sys
-file path=platform/SUNW,Sun-Fire-15000/lib/cvcd group=sys mode=0755
-file path=usr/share/man/man1m/cvcd.1m
-file path=usr/share/man/man7d/cvc.7d
-file path=usr/share/man/man7d/cvcredir.7d
-legacy pkg=SUNWcvc.u arch=$(ARCH).sun4u desc="Network Console" \
-    name="Network Console"
-legacy pkg=SUNWcvcr.u arch=$(ARCH).sun4u desc="Network Console daemon" \
-    name="Network Console daemon"
-license cr_Sun license=cr_Sun
-license lic_CDDL license=lic_CDDL
--- a/usr/src/psm/promif/ieee1275/sun4u/Makefile.files	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/psm/promif/ieee1275/sun4u/Makefile.files	Fri May 31 14:32:40 2019 +0200
@@ -25,7 +25,7 @@
 #
 # psm/promif/ieee1275/sun4u/Makefile.files
 #
-#	This Makefile defines all the promif file modules for the 
+#	This Makefile defines all the promif file modules for the
 #	directory psm/promif/ieee1275/sun4u.
 #
 
@@ -53,7 +53,6 @@
 	prom_serengeti.o		\
 	prom_set_traptable.o		\
 	prom_sparc.o			\
-	prom_starcat.o			\
 	prom_sunfire.o			\
 	prom_tlb.o			\
 	prom_vercheck.o			\
--- a/usr/src/psm/promif/ieee1275/sun4u/prom_starcat.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +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.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <sys/promif.h>
-#include <sys/promimpl.h>
-
-/*
- * This file contains the implementations of all Starcat-specific promif
- * routines.  Refer to FWARC case 2000/420 for the definitions of the
- * platform-specific interfaces provided by Starcat OBP.
- */
-
-static char *switch_tunnel_cmd	= "SUNW,Starcat,switch-tunnel";
-static char *iosram_read_cmd	= "SUNW,Starcat,iosram-read";
-static char *iosram_write_cmd	= "SUNW,Starcat,iosram-write";
-
-/*
- * Given the portid of the IOB to which the tunnel should be moved and the type
- * of move that should be performed, ask OBP to switch the IOSRAM tunnel from
- * its current host IOB to a new location.  If the move type is 0, OBP will
- * coordinate the change with SMS and will copy data from the current location
- * to the new location.  If the move type is 1, OBP will simply mark the new
- * location valid and start using it, without doing any data copying and without
- * communicating with SMS.  Return 0 on success, non-zero on failure.
- */
-int
-prom_starcat_switch_tunnel(uint_t portid, uint_t msgtype)
-{
-	static uint8_t	warned = 0;
-	cell_t		ci[6];
-	int		rv;
-
-	/*
-	 * Make sure we have the necessary support in OBP.
-	 */
-	if (prom_test(switch_tunnel_cmd) == 0) {
-		ci[0] = p1275_ptr2cell(switch_tunnel_cmd); /* name */
-	} else {
-		if (!warned) {
-			warned = 1;
-			prom_printf(
-			    "Warning: No prom support for switch-tunnel!\n");
-		}
-		return (-1);
-	}
-
-	/*
-	 * Set up the arguments and call into OBP.
-	 */
-	ci[1] = (cell_t)2;				/* #argument cells */
-	ci[2] = (cell_t)1;				/* #result cells */
-	ci[3] = p1275_uint2cell(portid);
-	ci[4] = p1275_uint2cell(msgtype);
-
-	promif_preprom();
-	rv = p1275_cif_handler(&ci);
-	promif_postprom();
-
-	/*
-	 * p1275_cif_handler will return 0 on success, non-zero on failure.  If
-	 * it fails, the return cell from OBP is meaningless, because the OBP
-	 * client interface probably wasn't even invoked.  OBP will return 0 on
-	 * failure and non-zero on success for this interface.
-	 */
-	if (rv != 0) {
-		return (rv);
-	} else if (p1275_cell2int(ci[5]) == 0)	{
-		return (-1);
-	} else {
-		return (0);
-	}
-}
-
-/*
- * Request that OBP read 'len' bytes, starting at 'offset' in the IOSRAM chunk
- * associated with 'key', into the memory indicated by 'buf'.  Although there is
- * a driver that provides this functionality, there are certain cases where the
- * OS requires access to IOSRAM before the driver is loaded.  Return 0 on
- * success, non-zero on failure.
- */
-int
-prom_starcat_iosram_read(uint32_t key, uint32_t offset, uint32_t len,
-    caddr_t buf)
-{
-	static uint8_t	warned = 0;
-	cell_t		ci[8];
-	int		rv;
-
-	/*
-	 * Make sure we have the necessary support in OBP.
-	 */
-	if (prom_test(iosram_read_cmd) == 0) {
-		ci[0] = p1275_ptr2cell(iosram_read_cmd); /* name */
-	} else {
-		if (!warned) {
-			warned = 1;
-			prom_printf(
-			    "Warning: No prom support for iosram-read!\n");
-		}
-		return (-1);
-	}
-
-	/*
-	 * Set up the arguments and call into OBP.  Note that the argument order
-	 * needs to be reversed to accomodate OBP.  The order must remain as it
-	 * is in the function prototype to maintain intercompatibility with the
-	 * IOSRAM driver's equivalent routine.
-	 */
-	ci[1] = (cell_t)4;				/* #argument cells */
-	ci[2] = (cell_t)1;				/* #result cells */
-	ci[3] = p1275_ptr2cell(buf);
-	ci[4] = p1275_uint2cell(len);
-	ci[5] = p1275_uint2cell(offset);
-	ci[6] = p1275_uint2cell(key);
-
-	promif_preprom();
-	rv = p1275_cif_handler(&ci);
-	promif_postprom();
-
-	/*
-	 * p1275_cif_handler will return 0 on success, non-zero on failure.  If
-	 * it fails, the return cell from OBP is meaningless, because the OBP
-	 * client interface probably wasn't even invoked.  OBP will return 0 on
-	 * success and non-zero on failure for this interface.
-	 */
-	if (rv != 0) {
-		return (rv);
-	} else if (p1275_cell2int(ci[7]) == 0)	{
-		return (0);
-	} else {
-		return (-1);
-	}
-}
-
-/*
- * Request that OBP write 'len' bytes from the memory indicated by 'buf' into
- * the IOSRAM chunk associated with 'key', starting at 'offset'.  Although there
- * is a driver that provides this functionality, there are certain cases where
- * the OS requires access to IOSRAM before the driver is loaded.  Return 0 on
- * success, non-zero on failure.
- */
-int
-prom_starcat_iosram_write(uint32_t key, uint32_t offset, uint32_t len,
-    caddr_t buf)
-{
-	static uint8_t	warned = 0;
-	cell_t 		ci[8];
-	int 		rv;
-
-	/*
-	 * Make sure we have the necessary support in OBP.
-	 */
-	if (prom_test(iosram_write_cmd) == 0) {
-		ci[0] = p1275_ptr2cell(iosram_write_cmd); /* name */
-	} else {
-		if (!warned) {
-			warned = 1;
-			prom_printf(
-			    "Warning: No prom support for iosram-write!\n");
-		}
-		return (-1);
-	}
-
-	/*
-	 * Set up the arguments and call into OBP.  Note that the argument order
-	 * needs to be reversed to accomodate OBP.  The order must remain as it
-	 * is in the function prototype to maintain intercompatibility with the
-	 * IOSRAM driver's equivalent routine.
-	 */
-	ci[1] = (cell_t)4;				/* #argument cells */
-	ci[2] = (cell_t)1;				/* #result cells */
-	ci[3] = p1275_ptr2cell(buf);
-	ci[4] = p1275_uint2cell(len);
-	ci[5] = p1275_uint2cell(offset);
-	ci[6] = p1275_uint2cell(key);
-
-	promif_preprom();
-	rv = p1275_cif_handler(&ci);
-	promif_postprom();
-
-	/*
-	 * p1275_cif_handler will return 0 on success, non-zero on failure.  If
-	 * it fails, the return cell from OBP is meaningless, because the OBP
-	 * client interface probably wasn't even invoked.  OBP will return 0 on
-	 * success and non-zero on failure for this interface.
-	 */
-	if (rv != 0) {
-		return (rv);
-	} else if (p1275_cell2int(ci[7]) == 0)	{
-		return (0);
-	} else {
-		return (-1);
-	}
-}
--- a/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -49,7 +49,6 @@
 PLATLINKS	+= SUNW,Sun-Fire-V250
 PLATLINKS	+= SUNW,Sun-Fire-V440
 PLATLINKS	+= SUNW,Sun-Fire-280R
-PLATLINKS	+= SUNW,Sun-Fire-15000
 PLATLINKS	+= SUNW,Sun-Fire-880
 PLATLINKS	+= SUNW,Sun-Fire-480R
 PLATLINKS	+= SUNW,Sun-Fire-V890
@@ -86,7 +85,7 @@
 
 .KEEP_STATE:
 
-all: 
+all:
 
 install: all $(LINKED_DIRS) $(LINKED_LIB_DIRS) $(LINKED_LIB_FS_DIRS)
 
--- a/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -50,7 +50,6 @@
 PLATLINKS       += SUNW,Sun-Fire-V250
 PLATLINKS	+= SUNW,Sun-Fire-V440
 PLATLINKS	+= SUNW,Sun-Fire-280R
-PLATLINKS	+= SUNW,Sun-Fire-15000
 PLATLINKS	+= SUNW,Sun-Fire-880
 PLATLINKS	+= SUNW,Sun-Fire-480R
 PLATLINKS	+= SUNW,Sun-Fire-V890
--- a/usr/src/test/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/test/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib	Fri May 31 14:32:40 2019 +0200
@@ -27,6 +27,7 @@
 #
 # Copyright (c) 2013, 2016 by Delphix. All rights reserved.
 # Copyright (c) 2017 Datto Inc.
+# Copyright 2019 Joyent, Inc.
 #
 
 . $STF_SUITE/include/libtest.shlib
@@ -48,6 +49,8 @@
 	set -A cksums
 	set -A newcksums
 
+	scrub_pool # Make sure we have a clean pool before starting the test.
+
 	while (( atfile < FILE_COUNT )); do
 		files[$atfile]=$TESTDIR/file.$atfile
 		log_must file_write -o create -f $TESTDIR/file.$atfile \
@@ -86,3 +89,20 @@
 
 	sync_pool $TESTPOOL
 }
+
+# Scrub the pool and wait for completion.
+function scrub_pool
+{
+        typeset pool=$TESTPOOL
+        log_note "Scrubbing $TESTPOOL"
+
+        # Flush all the pool data.
+        log_must zpool scrub $pool
+
+        while ! is_pool_scrubbed $pool; do
+                if is_pool_resilvered $pool ; then
+                        log_fail "$pool should not have been resilvered"
+                fi
+                log_must sleep 2
+        done
+}
--- a/usr/src/test/zfs-tests/tests/functional/clean_mirror/cleanup.ksh	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/test/zfs-tests/tests/functional/clean_mirror/cleanup.ksh	Fri May 31 14:32:40 2019 +0200
@@ -27,6 +27,7 @@
 
 #
 # Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2019 Joyent, Inc.
 #
 
 . $STF_SUITE/tests/functional/clean_mirror/default.cfg
@@ -46,4 +47,8 @@
 	log_must cleanup_devices $MIRROR_PRIMARY $MIRROR_SECONDARY
 fi
 
+if [[ -d $TESTDIR ]]; then
+	log_must rmdir $TESTDIR
+fi
+
 log_pass
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_006_pos.ksh	Fri May 31 14:32:40 2019 +0200
@@ -27,6 +27,7 @@
 
 #
 # Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright 2019 RackTop Systems.
 #
 
 . $STF_SUITE/include/libtest.shlib
@@ -98,7 +99,7 @@
 unmounted $TESTPOOL/$TESTFS1 || \
 	log_must force_unmount $TESTPOOL/$TESTFS1
 
-while [[ -n $mtpt ]] ; do
+while [[ $mtpt != $TESTDIR ]] ; do
 	(( depth == MAXDEPTH )) && \
 		log_note "Verify that 'zfs $mountcmd <filesystem>' " \
 		"which mountpoint be the identical of an existing one " \
--- a/usr/src/tools/chk4ubin/chk4ubin.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/tools/chk4ubin/chk4ubin.c	Fri May 31 14:32:40 2019 +0200
@@ -99,7 +99,6 @@
 
 static char *sun4u_bootables[] = {
 	"platform/sun4u/kernel/sparcv9/unix",
-	"platform/SUNW,Sun-Fire-15000/kernel/sparcv9/unix",
 	"platform/sun4u/cprboot",
 	"platform/sun4u/bootlst"
 };
@@ -126,7 +125,7 @@
 static int
 chk4ubin(char *root, char *binary)
 {
-	int  		fd;
+	int		fd;
 	Elf		*elf;
 	Elf_Scn		*symscn;
 	Elf_Scn		*strscn;
--- a/usr/src/tools/quick/make-smbsrv	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/tools/quick/make-smbsrv	Fri May 31 14:32:40 2019 +0200
@@ -216,16 +216,14 @@
 # mdb_arch is both 32-bit & 64-bit
 for a in $mdb_arch
 do
-  (cd $SRC/cmd/mdb/$x/$a/libfksmbsrv &&
-	$make $1 )
+  # We build these libraries (to the proto area), so we need to
+  # build the mdb modules for all dependent libraries too.
 
-# We build these libraries (to the proto area), so we need to
-# build the mdb modules too so mdb will load them.
-  (cd $SRC/cmd/mdb/$x/$a/libcmdutils &&
-	$make $1 )
-  (cd $SRC/cmd/mdb/$x/$a/libavl &&
-	$make $1 )
+  for lib in libfksmbsrv libmlsvc libcmdutils libavl
+  do
+    (cd $SRC/cmd/mdb/$x/$a/$lib && $make $1 )
 
+  done
 done
 }
 
@@ -272,6 +270,7 @@
 usr/lib/fs/smb/libshare_smb.so.1
 usr/lib/libsmbfs.so.1
 usr/lib/mdb/kvm/$arch64/smbsrv.so
+usr/lib/mdb/proc/libmlsvc.so
 usr/lib/reparse/libreparse_smb.so.1
 usr/lib/security/pam_smb_passwd.so.1
 usr/lib/smbsrv/dtrace
--- a/usr/src/uts/common/fs/smbsrv/smb2_cancel.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb2_cancel.c	Fri May 31 14:32:40 2019 +0200
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -19,61 +19,122 @@
 
 #include <smbsrv/smb2_kproto.h>
 
-static void smb2sr_cancel_async(smb_request_t *);
-static void smb2sr_cancel_sync(smb_request_t *);
+static void smb2_cancel_async(smb_request_t *);
+static void smb2_cancel_sync(smb_request_t *);
 
 /*
  * This handles an SMB2_CANCEL request when seen in the reader.
  * (See smb2sr_newrq)  Handle this immediately, rather than
  * going through the normal taskq dispatch mechanism.
  * Note that Cancel does NOT get a response.
+ *
+ * Any non-zero return causes disconnect.
+ * SMB2 header is already decoded.
  */
 int
-smb2sr_newrq_cancel(smb_request_t *sr)
+smb2_newrq_cancel(smb_request_t *sr)
 {
-	int rc;
 
 	/*
-	 * Decode the header
+	 * If we get SMB2 cancel as part of a compound,
+	 * that's a protocol violation.  Drop 'em!
 	 */
-	if ((rc = smb2_decode_header(sr)) != 0)
-		return (rc);
+	if (sr->smb2_next_command != 0)
+		return (EINVAL);
 
 	if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND)
-		smb2sr_cancel_async(sr);
+		smb2_cancel_async(sr);
 	else
-		smb2sr_cancel_sync(sr);
+		smb2_cancel_sync(sr);
 
 	return (0);
 }
 
+/*
+ * Dispatch handler for SMB2_CANCEL.
+ * Note that Cancel does NOT get a response.
+ */
+smb_sdrc_t
+smb2_cancel(smb_request_t *sr)
+{
+
+	/*
+	 * If we get SMB2 cancel as part of a compound,
+	 * that's a protocol violation.  Drop 'em!
+	 */
+	if (sr->smb2_cmd_hdr != 0 || sr->smb2_next_command != 0)
+		return (SDRC_DROP_VC);
+
+	if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND) {
+		smb2_cancel_async(sr);
+	} else {
+		smb2_cancel_sync(sr);
+	}
+
+	return (SDRC_NO_REPLY);
+}
+
+/*
+ * SMB2 Cancel (sync) has an inherent race with the request being
+ * cancelled.  The request may have been received but not yet
+ * executed by a worker thread, in which case we'll mark the
+ * request state as cancelled, and when a worker thread starts
+ * on this request we'll cancel everything in the compound.
+ */
 static void
-smb2sr_cancel_sync(smb_request_t *sr)
+smb2_cancel_sync(smb_request_t *sr)
 {
 	struct smb_request *req;
 	struct smb_session *session = sr->session;
 	int cnt = 0;
 
+	if (sr->smb2_messageid == 0)
+		goto failure;
+
 	smb_slist_enter(&session->s_req_list);
-	req = smb_slist_head(&session->s_req_list);
-	while (req) {
-		ASSERT(req->sr_magic == SMB_REQ_MAGIC);
-		if ((req != sr) &&
-		    (req->smb2_messageid == sr->smb2_messageid)) {
+	for (req = smb_slist_head(&session->s_req_list); req != NULL;
+	    req = smb_slist_next(&session->s_req_list, req)) {
+
+		/* never cancel self */
+		if (req == sr)
+			continue;
+
+		if (sr->smb2_messageid >= req->smb2_first_msgid &&
+		    sr->smb2_messageid < (req->smb2_first_msgid +
+		    req->smb2_total_credits)) {
 			smb_request_cancel(req);
 			cnt++;
 		}
-		req = smb_slist_next(&session->s_req_list, req);
 	}
+	smb_slist_exit(&session->s_req_list);
+
 	if (cnt != 1) {
+	failure:
 		DTRACE_PROBE2(smb2__cancel__error,
 		    uint64_t, sr->smb2_messageid, int, cnt);
+#ifdef	DEBUG
+		/*
+		 * It's somewhat common that we may see a cancel for a
+		 * request that has already completed, so report that
+		 * only in debug builds.
+		 */
+		cmn_err(CE_WARN, "SMB2 cancel failed, "
+		    "client=%s, MID=0x%llx",
+		    sr->session->ip_addr_str,
+		    (u_longlong_t)sr->smb2_messageid);
+#endif
 	}
-	smb_slist_exit(&session->s_req_list);
 }
 
+/*
+ * Note that cancelling an async request doesn't have a race
+ * because the client doesn't learn about the async ID until we
+ * send it to them in an interim reply, and by that point the
+ * request has progressed to the point where smb_cancel can find
+ * the request and cancel it.
+ */
 static void
-smb2sr_cancel_async(smb_request_t *sr)
+smb2_cancel_async(smb_request_t *sr)
 {
 	struct smb_request *req;
 	struct smb_session *session = sr->session;
@@ -93,6 +154,11 @@
 	if (cnt != 1) {
 		DTRACE_PROBE2(smb2__cancel__error,
 		    uint64_t, sr->smb2_async_id, int, cnt);
+		/*
+		 * Not logging here, as this is normal, i.e.
+		 * when both a cancel and a handle close
+		 * terminates an SMB2_notify request.
+		 */
 	}
 	smb_slist_exit(&session->s_req_list);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb2_change_notify.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb2_change_notify.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -30,12 +30,14 @@
 
 #include <smbsrv/smb2_kproto.h>
 
+/* For the output DataOffset fields in here. */
+#define	DATA_OFF	(SMB2_HDR_SIZE + 8)
+
 static smb_sdrc_t smb2_change_notify_async(smb_request_t *);
 
 smb_sdrc_t
 smb2_change_notify(smb_request_t *sr)
 {
-	smb_node_t *node = NULL;
 	uint16_t StructSize;
 	uint16_t iFlags;
 	uint32_t oBufLength;
@@ -61,87 +63,100 @@
 		return (SDRC_ERROR);
 
 	status = smb2sr_lookup_fid(sr, &smb2fid);
-	if (status)
+	if (status != 0)
 		goto puterror;
 
-	node = sr->fid_ofile->f_node;
-	if (node == NULL || !smb_node_is_dir(node)) {
-		status = NT_STATUS_INVALID_PARAMETER;
-		goto puterror;
+	CompletionFilter &= FILE_NOTIFY_VALID_MASK;
+	if (iFlags & SMB2_WATCH_TREE)
+		CompletionFilter |= FILE_NOTIFY_CHANGE_EV_SUBDIR;
+
+	if (oBufLength > smb2_max_trans)
+		oBufLength = smb2_max_trans;
+
+	/*
+	 * Check for events and consume, non-blocking.
+	 * Special return STATUS_PENDING means:
+	 *   No events; caller must call "act2" next.
+	 * SMB2 does that in the "async" handler.
+	 */
+	status = smb_notify_act1(sr, oBufLength, CompletionFilter);
+	if (status == NT_STATUS_PENDING) {
+		status = smb2sr_go_async(sr, smb2_change_notify_async);
 	}
 
-	/*
-	 * Let Change Notify "go async", because it
-	 * may block indefinitely.
-	 */
-	status = smb2sr_go_async(sr, smb2_change_notify_async);
-puterror:
-	ASSERT(status != 0);
-	smb2sr_put_error(sr, status);
+	if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) {
+		sr->smb2_status = status;
+
+		oBufLength = sr->raw_data.chain_offset;
+		(void) smb_mbc_encodef(
+		    &sr->reply, "wwlC",
+		    9,	/* StructSize */	/* w */
+		    DATA_OFF,			/* w */
+		    oBufLength,			/* l */
+		    &sr->raw_data);		/* C */
+	} else {
+	puterror:
+		smb2sr_put_error(sr, status);
+	}
+
 	return (SDRC_SUCCESS);
 }
 
+/*
+ * This is called when the dispatch loop has made it to the end of a
+ * compound request, and we had a notify that will require blocking.
+ */
 static smb_sdrc_t
 smb2_change_notify_async(smb_request_t *sr)
 {
-	uint16_t StructSize;
-	uint16_t iFlags;
-	uint32_t oBufLength;
-	smb2fid_t smb2fid;
-	uint32_t CompletionFilter;
-	uint32_t reserved;
 	uint32_t status;
-	uint16_t DataOff;
-	int rc = 0;
 
-	/*
-	 * SMB2 Change Notify request
-	 */
-	rc = smb_mbc_decodef(
-	    &sr->smb_data,		"wwlqqll",
-	    &StructSize,		/* w */
-	    &iFlags,			/* w */
-	    &oBufLength,		/* l */
-	    &smb2fid.persistent,	/* q */
-	    &smb2fid.temporal,		/* q */
-	    &CompletionFilter,		/* l */
-	    &reserved);			/* l */
-	if (rc || StructSize != 32)
-		return (SDRC_ERROR);
-
-	status = smb2sr_lookup_fid(sr, &smb2fid);
-	if (status != 0) {
-		smb2sr_put_error(sr, status);
-		return (SDRC_SUCCESS);
+	status = smb_notify_act2(sr);
+	if (status == NT_STATUS_PENDING) {
+		/* See next: smb2_change_notify_finish */
+		return (SDRC_SR_KEPT);
 	}
 
-	CompletionFilter &= FILE_NOTIFY_VALID_MASK;
-	if (iFlags & SMB2_WATCH_TREE)
-		CompletionFilter |= NODE_FLAGS_WATCH_TREE;
-
-	if (oBufLength > smb2_max_trans)
-		oBufLength = smb2_max_trans;
-	sr->raw_data.max_bytes = oBufLength;
-
-	status = smb_notify_common(sr, &sr->raw_data, CompletionFilter);
-	if (status != 0) {
-		smb2sr_put_error(sr, status);
-		return (SDRC_SUCCESS);
-	}
+	/* Note: Never NT_STATUS_NOTIFY_ENUM_DIR here. */
+	ASSERT(status != NT_STATUS_NOTIFY_ENUM_DIR);
 
-	/*
-	 * SMB2 Change Notify reply
-	 */
-	DataOff = SMB2_HDR_SIZE + 8;
-	oBufLength = MBC_LENGTH(&sr->raw_data);
-	rc = smb_mbc_encodef(
-	    &sr->reply, "wwlC",
-	    9,	/* StructSize */	/* w */
-	    DataOff,			/* w */
-	    oBufLength,			/* l */
-	    &sr->raw_data);		/* C */
-	if (rc)
-		return (SDRC_ERROR);
+	if (status != 0)
+		smb2sr_put_error(sr, status);
 
 	return (SDRC_SUCCESS);
 }
+
+/*
+ * This is called via taskq_dispatch in smb_notify.c
+ * to finish up an NT transact notify change request.
+ * Build an SMB2 Change Notify reply and send it.
+ */
+void
+smb2_change_notify_finish(void *arg)
+{
+	smb_request_t	*sr = arg;
+	uint32_t status;
+	uint32_t oBufLength;
+
+	SMB_REQ_VALID(sr);
+
+	/*
+	 * Common part of notify, puts data in sr->raw_data
+	 */
+	status = smb_notify_act3(sr);
+	if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) {
+		sr->smb2_status = status;
+
+		oBufLength = sr->raw_data.chain_offset;
+		(void) smb_mbc_encodef(
+		    &sr->reply, "wwlC",
+		    9,	/* StructSize */	/* w */
+		    DATA_OFF,			/* w */
+		    oBufLength,			/* l */
+		    &sr->raw_data);		/* C */
+	} else {
+		smb2sr_put_error(sr, status);
+	}
+
+	smb2sr_finish_async(sr);
+}
--- a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c	Fri May 31 14:32:40 2019 +0200
@@ -113,15 +113,9 @@
 	{  "smb2_ioctl", NULL,
 	    smb2_ioctl, NULL, 0, 0 },
 
-	/*
-	 * Note: Cancel gets the "invalid command" handler because
-	 * that's always handled directly in the reader.  We should
-	 * never get to the function using this table, but note:
-	 * We CAN get here if a nasty client adds cancel to some
-	 * compound message, which is a protocol violation.
-	 */
 	{  "smb2_cancel", NULL,
-	    smb2_invalid_cmd, NULL, 0, 0 },
+	    smb2_cancel, NULL, 0, 0,
+	    SDDF_SUPPRESS_UID | SDDF_SUPPRESS_TID },
 
 	{  "smb2_echo", NULL,
 	    smb2_echo, NULL, 0, 0,
@@ -175,31 +169,79 @@
 int
 smb2sr_newrq(smb_request_t *sr)
 {
+	struct mbuf_chain *mbc = &sr->command;
 	uint32_t magic;
-	uint16_t command;
-	int rc;
+	int rc, skip;
 
-	magic = LE_IN32(sr->sr_request_buf);
-	if (magic != SMB2_PROTOCOL_MAGIC) {
-		smb_request_free(sr);
-		/* will drop the connection */
-		return (EPROTO);
-	}
+	if (smb_mbc_peek(mbc, 0, "l", &magic) != 0)
+		goto drop;
+
+	if (magic != SMB2_PROTOCOL_MAGIC)
+		goto drop;
 
 	/*
-	 * Execute Cancel requests immediately, (here in the
-	 * reader thread) so they won't wait for any other
-	 * commands we might already have in the task queue.
-	 * Cancel also skips signature verification and
-	 * does not consume a sequence number.
-	 * [MS-SMB2] 3.2.4.24 Cancellation...
+	 * Walk the SMB2 commands in this compound message and
+	 * keep track of the range of message IDs it uses.
 	 */
-	command = LE_IN16((uint8_t *)sr->sr_request_buf + 12);
-	if (command == SMB2_CANCEL) {
-		rc = smb2sr_newrq_cancel(sr);
-		smb_request_free(sr);
-		return (rc);
+	for (;;) {
+		if (smb2_decode_header(sr) != 0)
+			goto drop;
+
+		/*
+		 * Cancel requests are special:  They refer to
+		 * an earlier message ID (or an async. ID),
+		 * never a new ID, and are never compounded.
+		 * This is intentionally not "goto drop"
+		 * because rc may be zero (success).
+		 */
+		if (sr->smb2_cmd_code == SMB2_CANCEL) {
+			rc = smb2_newrq_cancel(sr);
+			smb_request_free(sr);
+			return (rc);
+		}
+
+		/*
+		 * Keep track of the total credits in this compound
+		 * and the first (real) message ID (not: 0, -1)
+		 * While we're looking, verify that all (real) IDs
+		 * are (first <= ID < (first + msg_credits))
+		 */
+		if (sr->smb2_credit_charge == 0)
+			sr->smb2_credit_charge = 1;
+		sr->smb2_total_credits += sr->smb2_credit_charge;
+
+		if (sr->smb2_messageid != 0 &&
+		    sr->smb2_messageid != UINT64_MAX) {
+
+			if (sr->smb2_first_msgid == 0)
+				sr->smb2_first_msgid = sr->smb2_messageid;
+
+			if (sr->smb2_messageid < sr->smb2_first_msgid ||
+			    sr->smb2_messageid >= (sr->smb2_first_msgid +
+			    sr->smb2_total_credits)) {
+				long long id = (long long) sr->smb2_messageid;
+				cmn_err(CE_WARN, "clnt %s msg ID 0x%llx "
+				    "out of sequence in compound",
+				    sr->session->ip_addr_str, id);
+			}
+		}
+
+		/* Normal loop exit on next == zero */
+		if (sr->smb2_next_command == 0)
+			break;
+
+		/* Abundance of caution... */
+		if (sr->smb2_next_command < SMB2_HDR_SIZE)
+			goto drop;
+
+		/* Advance to the next header. */
+		skip = sr->smb2_next_command - SMB2_HDR_SIZE;
+		if (MBC_ROOM_FOR(mbc, skip) == 0)
+			goto drop;
+		mbc->chain_offset += skip;
 	}
+	/* Rewind back to the top. */
+	mbc->chain_offset = 0;
 
 	/*
 	 * Submit the request to the task queue, which calls
@@ -210,8 +252,11 @@
 	smb_srqueue_waitq_enter(sr->session->s_srqueue);
 	(void) taskq_dispatch(sr->sr_server->sv_worker_pool,
 	    smb2_tq_work, sr, TQ_SLEEP);
+	return (0);
 
-	return (0);
+drop:
+	smb_request_free(sr);
+	return (-1);
 }
 
 static void
@@ -229,10 +274,14 @@
 	sr->sr_time_active = gethrtime();
 
 	/*
-	 * In contrast with SMB1, SMB2 must _always_ dispatch to
-	 * the handler function, because cancelled requests need
-	 * an error reply (NT_STATUS_CANCELLED).
+	 * Always dispatch to the work function, because cancelled
+	 * requests need an error reply (NT_STATUS_CANCELLED).
 	 */
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state == SMB_REQ_STATE_SUBMITTED)
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+	mutex_exit(&sr->sr_mutex);
+
 	smb2sr_work(sr);
 
 	smb_srqueue_runq_exit(srq);
@@ -259,7 +308,8 @@
  * that begins at smb2_cmd_hdr.  The reply is appended to the
  * sr->reply chain starting at smb2_reply_hdr.
  *
- * This function must always free the smb request.
+ * This function must always free the smb request, or arrange
+ * for it to be completed and free'd later (if SDRC_SR_KEPT).
  */
 void
 smb2sr_work(struct smb_request *sr)
@@ -284,22 +334,21 @@
 	/* temporary until we identify a user */
 	sr->user_cr = zone_kcred();
 
-	mutex_enter(&sr->sr_mutex);
-	switch (sr->sr_state) {
-	case SMB_REQ_STATE_SUBMITTED:
-	case SMB_REQ_STATE_CLEANED_UP:
-		sr->sr_state = SMB_REQ_STATE_ACTIVE;
-		break;
-	default:
-		ASSERT(0);
-		/* FALLTHROUGH */
-	case SMB_REQ_STATE_CANCELED:
-		sr->smb2_status = NT_STATUS_CANCELLED;
-		break;
-	}
-	mutex_exit(&sr->sr_mutex);
+cmd_start:
+	/*
+	 * Note that we don't check sr_state here and abort the
+	 * compound if cancelled (etc.) because some SMB2 command
+	 * handlers need to do work even when cancelled.
+	 *
+	 * We treat some status codes as if "sticky", meaning
+	 * once they're set after some command handler returns,
+	 * all remaining commands get this status without even
+	 * calling the command-specific handler.
+	 */
+	if (sr->smb2_status != NT_STATUS_CANCELLED &&
+	    sr->smb2_status != NT_STATUS_INSUFFICIENT_RESOURCES)
+		sr->smb2_status = 0;
 
-cmd_start:
 	/*
 	 * Decode the request header
 	 *
@@ -307,19 +356,7 @@
 	 * STATUS_INVALID_PARAMETER.  If the decoding problem
 	 * prevents continuing, we'll close the connection.
 	 * [MS-SMB2] 3.3.5.2.6 Handling Incorrectly Formatted...
-	 *
-	 * We treat some status codes as if "sticky", meaning
-	 * once they're set after some command handler returns,
-	 * all remaining commands get this status without even
-	 * calling the command-specific handler. The cancelled
-	 * status is used above, and insufficient_resources is
-	 * used when smb2sr_go_async declines to "go async".
-	 * Otherwise initialize to zero (success).
 	 */
-	if (sr->smb2_status != NT_STATUS_CANCELLED &&
-	    sr->smb2_status != NT_STATUS_INSUFFICIENT_RESOURCES)
-		sr->smb2_status = 0;
-
 	sr->smb2_cmd_hdr = sr->command.chain_offset;
 	if ((rc = smb2_decode_header(sr)) != 0) {
 		cmn_err(CE_WARN, "clnt %s bad SMB2 header",
@@ -644,6 +681,8 @@
 		/* NB: not using pre_op */
 		rc = (*sdd->sdt_function)(sr);
 		/* NB: not using post_op */
+	} else {
+		smb2sr_put_error(sr, sr->smb2_status);
 	}
 
 	MBC_FLUSH(&sr->raw_data);
@@ -724,6 +763,10 @@
 	case SDRC_DROP_VC:
 		disconnect = B_TRUE;
 		goto cleanup;
+
+	case SDRC_NO_REPLY:
+		/* will free sr */
+		goto cleanup;
 	}
 
 	/*
@@ -807,9 +850,9 @@
 smb2sr_do_async(smb_request_t *sr)
 {
 	const smb_disp_entry_t	*sdd;
-	smb_disp_stats_t	*sds;
 	smb2_async_req_t	*ar;
-	int rc = 0;
+	smb_sdrc_t		(*ar_func)(smb_request_t *);
+	int sdrc;
 
 	/*
 	 * Restore what smb2_decode_header found.
@@ -843,6 +886,13 @@
 	    ar->ar_cmd_len - SMB2_HDR_SIZE);
 
 	/*
+	 * Done with sr_async_req
+	 */
+	ar_func = ar->ar_func;
+	kmem_free(ar, sizeof (*ar));
+	sr->sr_async_req = ar = NULL;
+
+	/*
 	 * Setup output mbuf_chain
 	 */
 	MBC_FLUSH(&sr->reply);
@@ -851,8 +901,6 @@
 
 	VERIFY3U(sr->smb2_cmd_code, <, SMB2_INVALID_CMD);
 	sdd = &smb2_disp_table[sr->smb2_cmd_code];
-	sds = sr->session->s_server->sv_disp_stats2;
-	sds = &sds[sr->smb2_cmd_code];
 
 	/*
 	 * Keep the UID, TID, ofile we have.
@@ -874,11 +922,28 @@
 	 *
 	 * Just call the async handler function.
 	 */
-	rc = ar->ar_func(sr);
-	if (rc != 0 && sr->smb2_status == 0)
-		sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
+	sdrc = ar_func(sr);
+	switch (sdrc) {
+	case SDRC_SUCCESS:
+		break;
+	case SDRC_ERROR:
+		if (sr->smb2_status == 0)
+			sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
+		break;
+	case SDRC_SR_KEPT:
+		/* This SR will be completed later. */
+		return;
+	}
 
 cmd_done:
+	smb2sr_finish_async(sr);
+}
+
+void
+smb2sr_finish_async(smb_request_t *sr)
+{
+	smb_disp_stats_t	*sds;
+
 	/*
 	 * Pad the reply to align(8) if necessary.
 	 */
@@ -891,12 +956,11 @@
 	/*
 	 * Record some statistics: (just tx bytes here)
 	 */
-	atomic_add_64(&sds->sdt_txb,
-	    (int64_t)(sr->reply.chain_offset - sr->smb2_reply_hdr));
+	sds = &sr->session->s_server->sv_disp_stats2[sr->smb2_cmd_code];
+	atomic_add_64(&sds->sdt_txb, (int64_t)(sr->reply.chain_offset));
 
 	/*
-	 * Overwrite the SMB2 header for the response of
-	 * this command (possibly part of a compound).
+	 * Put (overwrite) the final SMB2 header.
 	 * The call adds: SMB2_FLAGS_SERVER_TO_REDIR
 	 */
 	(void) smb2_encode_header(sr, B_TRUE);
@@ -909,8 +973,6 @@
 	/*
 	 * Done.  Unlink and free.
 	 */
-	sr->sr_async_req = NULL;
-	kmem_free(ar, sizeof (*ar));
 
 	mutex_enter(&sr->sr_mutex);
 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
--- a/usr/src/uts/common/fs/smbsrv/smb2_lock.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb2_lock.c	Fri May 31 14:32:40 2019 +0200
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -19,16 +19,16 @@
 
 #include <smbsrv/smb2_kproto.h>
 
-struct SMB2_LOCK_ELEMENT {
+typedef struct SMB2_LOCK_ELEMENT {
 	uint64_t Offset;
 	uint64_t Length;
 	uint32_t Flags;
 	uint32_t reserved;
-};
+} lock_elem_t;
 
+static uint32_t smb2_unlock(smb_request_t *);
+static uint32_t smb2_locks(smb_request_t *);
 static smb_sdrc_t smb2_lock_async(smb_request_t *);
-static uint32_t smb2_lock_exec(smb_request_t *, uint16_t);
-static uint32_t smb2_lock_elem(smb_request_t *, struct SMB2_LOCK_ELEMENT *);
 
 /*
  * This is a somewhat arbitrary sanity limit on the length of the
@@ -39,16 +39,14 @@
 smb_sdrc_t
 smb2_lock(smb_request_t *sr)
 {
-	struct SMB2_LOCK_ELEMENT elem;
+	lock_elem_t *lvec, *lk;
 	smb2fid_t smb2fid;
-	uint32_t save_offset;
 	uint32_t LockSequence;
 	uint32_t status;
 	uint16_t StructSize;
 	uint16_t LockCount;
 	uint16_t i;
-	boolean_t MayBlock = B_FALSE;
-	int rc = 0;
+	int rc;
 
 	/*
 	 * SMB2 Lock request
@@ -76,124 +74,49 @@
 	}
 
 	/*
-	 * Process the array of SMB2_LOCK_ELEMENT structs
-	 * We do this twice.  (it's always a short list)
-	 * The first time, just validate the flags, and check
-	 * if any of the locking request might need to block.
-	 * The second time (either here, or in the async
-	 * handler function) process the locks for real.
+	 * Parse the array of SMB2_LOCK_ELEMENT structs.
+	 * This array is free'd in smb_srm_fini.
 	 */
-	save_offset = sr->smb_data.chain_offset;
+	lvec = smb_srm_zalloc(sr, LockCount * sizeof (*lvec));
 	for (i = 0; i < LockCount; i++) {
+		lk = &lvec[i];
 		rc = smb_mbc_decodef(
 		    &sr->smb_data, "qqll",
-		    &elem.Offset,	/* q */
-		    &elem.Length,	/* q */
-		    &elem.Flags,	/* l */
-		    &elem.reserved);	/* l */
+		    &lk->Offset,	/* q */
+		    &lk->Length,	/* q */
+		    &lk->Flags,		/* l */
+		    &lk->reserved);	/* l */
 		if (rc) {
 			status = NT_STATUS_INVALID_PARAMETER;
 			goto errout;
 		}
-
-		/*
-		 * Make sure the flags are valid;
-		 * Find out if we might block.
-		 */
-		switch (elem.Flags) {
-		case SMB2_LOCKFLAG_SHARED_LOCK:
-		case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
-			MayBlock = B_TRUE;
-			break;
-
-		/* BEGIN CSTYLED */
-		case SMB2_LOCKFLAG_SHARED_LOCK |
-		     SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
-		case SMB2_LOCKFLAG_EXCLUSIVE_LOCK |
-		     SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
-		case SMB2_LOCKFLAG_UNLOCK:
-		/* END CSTYLED */
-			break;
-
-		default:
-			status = NT_STATUS_INVALID_PARAMETER;
-			goto errout;
-		}
 	}
 
-	if (MayBlock) {
-		/*
-		 * May need to block.  "Go async".
-		 */
-		status = smb2sr_go_async(sr, smb2_lock_async);
-		goto errout;
+	/*
+	 * [MS-SMB2] 3.3.5.14
+	 * If the flags of the [first element of] the Locks array
+	 * [has] SMB2_LOCKFLAG_UNLOCK set, the server MUST process
+	 * the lock array as a series of unlocks. Otherwise, it
+	 * MUST process the lock array as a series of lock requests.
+	 */
+	sr->arg.lock.lvec = lvec;
+	sr->arg.lock.lcnt = LockCount;
+	sr->arg.lock.lseq = LockSequence;
+	if (lvec[0].Flags & SMB2_LOCKFLAG_UNLOCK) {
+		status = smb2_unlock(sr);
+	} else {
+		status = smb2_locks(sr);
 	}
-
-	sr->smb_data.chain_offset = save_offset;
-	status = smb2_lock_exec(sr, LockCount);
 	if (status)
 		goto errout;
 
 	/*
 	 * SMB2 Lock reply (sync)
 	 */
-	StructSize = 4;
 	(void) smb_mbc_encodef(
 	    &sr->reply, "w..",
-	    StructSize);	/* w */
-	    /* reserved		  .. */
-	return (SDRC_SUCCESS);
-
-errout:
-	smb2sr_put_error(sr, status);
-	return (SDRC_SUCCESS);
-}
-
-static smb_sdrc_t
-smb2_lock_async(smb_request_t *sr)
-{
-	smb2fid_t smb2fid;
-	uint32_t LockSequence;
-	uint32_t status;
-	uint16_t StructSize;
-	uint16_t LockCount;
-	int rc = 0;
-
-	/*
-	 * Decode the lock request again.  It should all decode
-	 * exactly the same as the first time we saw it.  If not,
-	 * report an "internal error".
-	 */
-	rc = smb_mbc_decodef(
-	    &sr->smb_data, "wwlqq",
-	    &StructSize,		/* w */
-	    &LockCount,			/* w */
-	    &LockSequence,		/* l */
-	    &smb2fid.persistent,	/* q */
-	    &smb2fid.temporal);		/* q */
-	if (rc || StructSize != 48)
-		return (SDRC_ERROR);
-
-	status = smb2sr_lookup_fid(sr, &smb2fid);
-	if (status)
-		goto errout;
-	if (sr->fid_ofile->f_node == NULL || LockCount == 0) {
-		status = NT_STATUS_INTERNAL_ERROR;
-		goto errout;
-	}
-
-	status = smb2_lock_exec(sr, LockCount);
-	if (status)
-		goto errout;
-
-	/*
-	 * SMB2 Lock reply (async)
-	 */
-	StructSize = 4;
-	(void) smb_mbc_encodef(
-	    &sr->reply, "w..",
-	    StructSize);	/* w */
-	    /* reserved		  .. */
+	    4); /* StructSize	w */
+	    /* reserved		.. */
 	return (SDRC_SUCCESS);
 
 errout:
@@ -202,92 +125,158 @@
 }
 
 /*
- * Execute the vector of locks.  This is the common function called by
- * either the sync or async code paths.  We've already decoded this
- * request once when we get here, so if there are any decode errors
- * then it's some kind of internal error.
+ * Process what should be an array of unlock requests.
  */
 static uint32_t
-smb2_lock_exec(smb_request_t *sr, uint16_t LockCount)
+smb2_unlock(smb_request_t *sr)
 {
-	struct SMB2_LOCK_ELEMENT elem;
+	lock_elem_t *lk;
+	lock_elem_t *lvec = sr->arg.lock.lvec;
+	uint32_t LockCount = sr->arg.lock.lcnt;
+	uint32_t LockSequence = sr->arg.lock.lseq;
 	uint32_t status = 0;
-	uint16_t i;
-	int rc;
-
-	/*
-	 * On entry, out position in the input data should be
-	 * after both the SMB2 header and the fixed part of
-	 * the SMB Lock request header (24).
-	 */
-	ASSERT(sr->smb_data.chain_offset ==
-	    (sr->smb2_cmd_hdr + SMB2_HDR_SIZE + 24));
-
-	/*
-	 * This is checked by our callers, but let's make sure.
-	 */
-	ASSERT(sr->fid_ofile->f_node != NULL);
+	uint32_t pid = 0;	/* SMB2 ignores lock PIDs. */
+	int i;
 
 	for (i = 0; i < LockCount; i++) {
-		rc = smb_mbc_decodef(
-		    &sr->smb_data, "qqll",
-		    &elem.Offset,	/* q */
-		    &elem.Length,	/* q */
-		    &elem.Flags,	/* l */
-		    &elem.reserved);	/* l */
-		if (rc) {
-			status = NT_STATUS_INTERNAL_ERROR;
+		lk = &lvec[i];
+
+		if (lk->Flags != SMB2_LOCKFLAG_UNLOCK) {
+			status = NT_STATUS_INVALID_PARAMETER;
 			break;
 		}
-		status = smb2_lock_elem(sr, &elem);
-		if (status)
+
+		status = smb_unlock_range(sr, lk->Offset, lk->Length, pid);
+		if (status != 0)
 			break;
 	}
+	(void) LockSequence; /* todo */
+
 	return (status);
 }
 
+/*
+ * Process what should be an array of lock requests.
+ */
 static uint32_t
-smb2_lock_elem(smb_request_t *sr, struct SMB2_LOCK_ELEMENT *elem)
+smb2_locks(smb_request_t *sr)
 {
-	smb_node_t *node = sr->fid_ofile->f_node;
-	uint32_t status;
+	lock_elem_t *lk;
+	lock_elem_t *lvec = sr->arg.lock.lvec;
+	uint32_t LockCount = sr->arg.lock.lcnt;
+	uint32_t i;
 	uint32_t ltype;
+	uint32_t pid = 0;	/* SMB2 ignores lock PIDs */
 	uint32_t timeout = 0;
+	uint32_t status = 0;
 
-	switch (elem->Flags) {
-	case SMB2_LOCKFLAG_SHARED_LOCK:
-		timeout = UINT_MAX;
-		/* FALLTHROUGH */
-	case SMB2_LOCKFLAG_SHARED_LOCK | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
-		ltype = SMB_LOCK_TYPE_READONLY;
-		status = smb_lock_range(sr,
-		    elem->Offset, elem->Length,
-		    timeout, ltype);
-		break;
+	for (i = 0; i < LockCount; i++) {
+		lk = &lvec[i];
+
+		switch (lk->Flags) {
 
-	case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
-		timeout = UINT_MAX;
-		/* FALLTHROUGH */
-	case SMB2_LOCKFLAG_EXCLUSIVE_LOCK | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
-		ltype = SMB_LOCK_TYPE_READWRITE;
-		status = smb_lock_range(sr,
-		    elem->Offset, elem->Length,
-		    timeout, ltype);
-		break;
+		case SMB2_LOCKFLAG_SHARED_LOCK:
+		case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
+			/*
+			 * Blocking locks have special rules:
+			 * Must be exactly one element, else
+			 * invalid parameter.
+			 */
+			if (i == 0 && LockCount == 1) {
+				status = smb2sr_go_async(sr, smb2_lock_async);
+				return (status);
+			}
+			/* FALLTHROUGH */
+		case SMB2_LOCKFLAG_UNLOCK:
+		default:
+			status = NT_STATUS_INVALID_PARAMETER;
+			goto end_loop;
+
+		/* BEGIN CSTYLED */
+		case SMB2_LOCKFLAG_SHARED_LOCK |
+		     SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
+		/* END CSTYLED */
+			ltype = SMB_LOCK_TYPE_READONLY;
+			break;
 
-	case SMB2_LOCKFLAG_UNLOCK:
-		status = smb_unlock_range(sr, node,
-		    elem->Offset, elem->Length);
-		break;
+		/* BEGIN CSTYLED */
+		case SMB2_LOCKFLAG_EXCLUSIVE_LOCK |
+		     SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
+		/* END CSTYLED */
+			ltype = SMB_LOCK_TYPE_READWRITE;
+			break;
+		}
 
-	/*
-	 * We've already checked the flags previously, so any
-	 * surprises here are some kind of internal error.
-	 */
-	default:
-		status = NT_STATUS_INTERNAL_ERROR;
-		break;
+		status = smb_lock_range(sr, lk->Offset, lk->Length, pid,
+		    ltype, timeout);
+		if (status != 0) {
+			goto end_loop;
+		}
+	}
+
+end_loop:
+	if (status != 0) {
+		/*
+		 * Oh... we have to rollback.
+		 */
+		while (i > 0) {
+			--i;
+			lk = &lvec[i];
+			(void) smb_unlock_range(sr,
+			    lk->Offset, lk->Length, pid);
+		}
 	}
 
 	return (status);
 }
+
+/*
+ * Async handler for blocking lock requests.
+ * Always exactly one lock request here.
+ */
+static smb_sdrc_t
+smb2_lock_async(smb_request_t *sr)
+{
+	lock_elem_t *lk = sr->arg.lock.lvec;
+	uint32_t LockCount = sr->arg.lock.lcnt;
+	uint32_t status;
+	uint32_t ltype;
+	uint32_t pid = 0;	/* SMB2 ignores lock PIDs */
+	uint32_t timeout = UINT_MAX;
+
+	ASSERT(sr->fid_ofile->f_node != NULL);
+	ASSERT(LockCount == 1);
+
+	switch (lk->Flags) {
+	case SMB2_LOCKFLAG_SHARED_LOCK:
+		ltype = SMB_LOCK_TYPE_READONLY;
+		break;
+
+	case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
+		ltype = SMB_LOCK_TYPE_READWRITE;
+		break;
+
+	default:
+		ASSERT(0);
+		status = NT_STATUS_INTERNAL_ERROR;
+		goto errout;
+	}
+
+	status = smb_lock_range(sr, lk->Offset, lk->Length, pid,
+	    ltype, timeout);
+	if (status != 0)
+		goto errout;
+
+	/*
+	 * SMB2 Lock reply (async)
+	 */
+	(void) smb_mbc_encodef(
+	    &sr->reply, "w..",
+	    4); /* StructSize	w */
+	    /* reserved		.. */
+	return (SDRC_SUCCESS);
+
+errout:
+	smb2sr_put_error(sr, status);
+	return (SDRC_SUCCESS);
+}
--- a/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c	Fri May 31 14:32:40 2019 +0200
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -206,7 +206,7 @@
 	    &struct_size,	/* w */
 	    &version_cnt,	/* w */
 	    &s->secmode,	/* w */
-	    /* reserved 	(..) */
+	    /* reserved		(..) */
 	    &s->capabilities);	/* l */
 	    /* clnt_uuid	 16. */
 	    /* start_time	  8. */
--- a/usr/src/uts/common/fs/smbsrv/smb2_tree_disconn.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb2_tree_disconn.c	Fri May 31 14:32:40 2019 +0200
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -41,8 +41,8 @@
 	if (sr->uid_user == NULL || sr->tid_tree == NULL)
 		return (SDRC_ERROR);
 
+	smb_tree_disconnect(sr->tid_tree, B_TRUE);
 	smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
-	smb_tree_disconnect(sr->tid_tree, B_TRUE);
 
 	/*
 	 * SMB2 Tree Disconnect reply
--- a/usr/src/uts/common/fs/smbsrv/smb_authenticate.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_authenticate.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -37,10 +37,10 @@
 #include <smbsrv/smb_kproto.h>
 #include <smbsrv/smb_token.h>
 
-static uint32_t smb_authsock_open(smb_user_t *);
+static uint32_t smb_authsock_open(smb_request_t *);
 static int smb_authsock_send(ksocket_t, void *, size_t);
 static int smb_authsock_recv(ksocket_t, void *, size_t);
-static uint32_t smb_authsock_sendrecv(smb_user_t *, smb_lsa_msg_hdr_t *hdr,
+static uint32_t smb_authsock_sendrecv(smb_request_t *, smb_lsa_msg_hdr_t *hdr,
 				void *sndbuf, void **recvbuf);
 /* void smb_authsock_close(smb_user_t *); kproto.h */
 
@@ -75,7 +75,7 @@
 	 * If we can't, it may be busy, or not running.
 	 * Don't log here - this may be frequent.
 	 */
-	if ((status = smb_authsock_open(user)) != 0)
+	if ((status = smb_authsock_open(sr)) != 0)
 		goto errout;
 
 	/*
@@ -114,7 +114,6 @@
 	smb_logon_t	user_info;
 	XDR		xdrs;
 	smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
-	smb_user_t	*user = sr->uid_user;
 	void		*sbuf = NULL;
 	void		*rbuf = NULL;
 	uint32_t	slen = 0;
@@ -153,7 +152,7 @@
 
 	msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
 	msg_hdr.lmh_msglen = slen;
-	status = smb_authsock_sendrecv(user, &msg_hdr, sbuf, &rbuf);
+	status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf);
 	if (status != 0)
 		goto out;
 	rlen = msg_hdr.lmh_msglen;
@@ -252,7 +251,7 @@
 		 * If we can't, it may be busy, or not running.
 		 * Don't log here - this may be frequent.
 		 */
-		if ((status = smb_authsock_open(user)) != 0)
+		if ((status = smb_authsock_open(sr)) != 0)
 			goto errout;
 
 		/*
@@ -280,7 +279,7 @@
 	 * and send it up the authsock with either
 	 */
 	msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
-	status = smb_authsock_sendrecv(user, &msg_hdr,
+	status = smb_authsock_sendrecv(sr, &msg_hdr,
 	    sinfo->ssi_isecblob, &rbuf);
 	if (status != 0)
 		goto errout;
@@ -350,7 +349,6 @@
 {
 	smb_lsa_msg_hdr_t msg_hdr;
 	smb_lsa_clinfo_t clinfo;
-	smb_user_t *user = sr->uid_user;
 	void *rbuf = NULL;
 	uint32_t status;
 
@@ -364,7 +362,7 @@
 	(void) memcpy(clinfo.lci_challenge_key,
 	    sr->session->challenge_key,
 	    sizeof (clinfo.lci_challenge_key));
-	status = smb_authsock_sendrecv(user, &msg_hdr, &clinfo, &rbuf);
+	status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf);
 	/* We don't use this response. */
 	if (rbuf != NULL) {
 		kmem_free(rbuf, msg_hdr.lmh_msglen);
@@ -396,7 +394,7 @@
 	msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
 	msg_hdr.lmh_msglen = 0;
 
-	status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
+	status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf);
 	if (status != 0)
 		goto errout;
 
@@ -512,6 +510,37 @@
 }
 
 /*
+ * Unblock a request that might be blocked reading some
+ * authentication socket.  This can happen when either the
+ * client cancels a session setup or closes the connection.
+ */
+static void
+smb_authsock_cancel(smb_request_t *sr)
+{
+	smb_user_t *user = sr->cancel_arg2;
+	ksocket_t authsock = NULL;
+
+	if (user == NULL)
+		return;
+	ASSERT(user == sr->uid_user);
+
+	/*
+	 * Check user state, and get a hold on the auth socket.
+	 */
+	mutex_enter(&user->u_mutex);
+	if (user->u_state == SMB_USER_STATE_LOGGING_ON) {
+		if ((authsock = user->u_authsock) != NULL)
+			ksocket_hold(authsock);
+	}
+	mutex_exit(&user->u_mutex);
+
+	if (authsock != NULL) {
+		(void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr);
+		ksocket_rele(authsock);
+	}
+}
+
+/*
  * Send/recv a request/reply sequence on the auth socket.
  * Returns zero or an NT status.
  *
@@ -519,9 +548,10 @@
  * With limited authsock instances, this should be rare.
  */
 static uint32_t
-smb_authsock_sendrecv(smb_user_t *user, smb_lsa_msg_hdr_t *hdr,
+smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr,
 	void *sndbuf, void **recvbuf)
 {
+	smb_user_t *user = sr->uid_user;
 	ksocket_t so;
 	uint32_t status;
 	int rc;
@@ -538,25 +568,28 @@
 	ksocket_hold(so);
 	mutex_exit(&user->u_mutex);
 
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
+		mutex_exit(&sr->sr_mutex);
+		status = NT_STATUS_CANCELLED;
+		goto out;
+	}
+	sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
+	sr->cancel_method = smb_authsock_cancel;
+	sr->cancel_arg2 = user;
+	mutex_exit(&sr->sr_mutex);
+
 	rc = smb_authsock_send(so, hdr, sizeof (*hdr));
 	if (rc == 0 && hdr->lmh_msglen != 0) {
 		rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
 	}
-	if (rc)
-		goto out;
-
-	rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
+	if (rc == 0)
+		rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
 	if (rc == 0 && hdr->lmh_msglen != 0) {
 		*recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
 		rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
-		if (rc) {
-			kmem_free(*recvbuf, hdr->lmh_msglen);
-			*recvbuf = NULL;
-		}
 	}
 
-out:
-	ksocket_rele(so);
 	switch (rc) {
 	case 0:
 		status = 0;
@@ -572,6 +605,30 @@
 		break;
 	}
 
+	mutex_enter(&sr->sr_mutex);
+	sr->cancel_method = NULL;
+	sr->cancel_arg2 = NULL;
+	switch (sr->sr_state) {
+	case SMB_REQ_STATE_WAITING_AUTH:
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+		break;
+	case SMB_REQ_STATE_CANCEL_PENDING:
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
+		status = NT_STATUS_CANCELLED;
+		break;
+	default:
+		status = NT_STATUS_INTERNAL_ERROR;
+		break;
+	}
+	mutex_exit(&sr->sr_mutex);
+
+out:
+	ksocket_rele(so);
+
+	if (status != 0 && *recvbuf != NULL) {
+		kmem_free(*recvbuf, hdr->lmh_msglen);
+		*recvbuf = NULL;
+	}
 	return (status);
 }
 
@@ -593,17 +650,28 @@
  */
 struct timeval smb_auth_send_tmo = { 15, 0 };
 
+/*
+ * Maximum time a user object may stay in state LOGGING_ON
+ */
+int smb_auth_total_tmo = 45;	/* seconds */
+
 static uint32_t
-smb_authsock_open(smb_user_t *user)
+smb_authsock_open(smb_request_t *sr)
 {
-	smb_server_t *sv = user->u_server;
+	smb_user_t *user = sr->uid_user;
+	smb_server_t *sv = sr->sr_server;
 	ksocket_t so = NULL;
-	uint32_t status;
+	uint32_t status = 0;
 	int rc;
 
 	/*
-	 * If the auth. service is busy, wait our turn.
-	 * This may be frequent, so don't log.
+	 * If the auth. service is busy, wait our turn.  This threshold
+	 * limits the number of auth sockets we might have trying to
+	 * communicate with the auth. service up in smbd.  Until we've
+	 * set u_authsock, we need to "exit this threshold" in any
+	 * error code paths after this "enter".
+	 *
+	 * Failure to "enter" may be frequent, so don't log.
 	 */
 	if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
 		return (NT_STATUS_NO_LOGON_SERVERS);
@@ -612,11 +680,34 @@
 	    KSOCKET_SLEEP, CRED());
 	if (rc != 0) {
 		cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
+		smb_threshold_exit(&sv->sv_ssetup_ct);
 		status = NT_STATUS_INSUFF_SERVER_RESOURCES;
 		goto errout;
 	}
 
 	/*
+	 * This (new) user object now gets an authsocket.
+	 * Note: u_authsock cleanup in smb_user_logoff.
+	 * After we've set u_authsock, smb_threshold_exit
+	 * is done in smb_authsock_close().  If we somehow
+	 * already have an authsock, close the new one and
+	 * error out.
+	 */
+	mutex_enter(&user->u_mutex);
+	if (user->u_authsock != NULL) {
+		mutex_exit(&user->u_mutex);
+		smb_authsock_close(user, so);
+		status = NT_STATUS_INTERNAL_ERROR;
+		goto errout;
+	}
+	user->u_authsock = so;
+	if (smb_auth_total_tmo != 0) {
+		user->u_auth_tmo = timeout(smb_user_auth_tmo, user,
+		    SEC_TO_TICK(smb_auth_total_tmo));
+	}
+	mutex_exit(&user->u_mutex);
+
+	/*
 	 * Set the send/recv timeouts.
 	 */
 	(void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
@@ -630,30 +721,42 @@
 	 * Would like to set the connect timeout too, but there's
 	 * apparently no easy way to do that for AF_UNIX.
 	 */
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
+		mutex_exit(&sr->sr_mutex);
+		status = NT_STATUS_CANCELLED;
+		goto errout;
+	}
+	sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
+	sr->cancel_method = smb_authsock_cancel;
+	sr->cancel_arg2 = user;
+	mutex_exit(&sr->sr_mutex);
+
 	rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
 	    sizeof (smbauth_sockname), CRED());
 	if (rc != 0) {
 		DTRACE_PROBE1(error, int, rc);
 		status = NT_STATUS_NETLOGON_NOT_STARTED;
-		goto errout;
 	}
 
-	/* Note: u_authsock cleanup in smb_authsock_close() */
-	mutex_enter(&user->u_mutex);
-	if (user->u_authsock != NULL) {
-		mutex_exit(&user->u_mutex);
+	mutex_enter(&sr->sr_mutex);
+	sr->cancel_method = NULL;
+	sr->cancel_arg2 = NULL;
+	switch (sr->sr_state) {
+	case SMB_REQ_STATE_WAITING_AUTH:
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+		break;
+	case SMB_REQ_STATE_CANCEL_PENDING:
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
+		status = NT_STATUS_CANCELLED;
+		break;
+	default:
 		status = NT_STATUS_INTERNAL_ERROR;
-		goto errout;
+		break;
 	}
-	user->u_authsock = so;
-	mutex_exit(&user->u_mutex);
-	return (0);
+	mutex_exit(&sr->sr_mutex);
 
 errout:
-	if (so != NULL)
-		(void) ksocket_close(so, CRED());
-	smb_threshold_exit(&sv->sv_ssetup_ct);
-
 	return (status);
 }
 
@@ -699,14 +802,16 @@
 	return (rc);
 }
 
+/*
+ * Caller has cleared user->u_authsock, passing the last ref
+ * as the 2nd arg here.  This can block, so it's called
+ * after exiting u_mutex.
+ */
 void
-smb_authsock_close(smb_user_t *user)
+smb_authsock_close(smb_user_t *user, ksocket_t so)
 {
 
-	ASSERT(MUTEX_HELD(&user->u_mutex));
-	if (user->u_authsock == NULL)
-		return;
-	(void) ksocket_close(user->u_authsock, CRED());
-	user->u_authsock = NULL;
+	(void) ksocket_shutdown(so, SHUT_RDWR, CRED());
+	(void) ksocket_close(so, CRED());
 	smb_threshold_exit(&user->u_server->sv_ssetup_ct);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_close.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_close.c	Fri May 31 14:32:40 2019 +0200
@@ -22,7 +22,7 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <smbsrv/smb_kproto.h>
@@ -109,8 +109,9 @@
 
 	mtime = smb_time_local_to_gmt(sr, sr->arg.timestamp);
 	smb_ofile_close(sr->fid_ofile, mtime);
+
+	smb_tree_disconnect(sr->tid_tree, B_TRUE);
 	smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
-	smb_tree_disconnect(sr->tid_tree, B_TRUE);
 
 	if (smbsr_encode_empty_result(sr) != 0)
 		return (SDRC_ERROR);
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -310,6 +310,14 @@
 	smb_pathname_t	*pn = &op->fqi.fq_path;
 	smb_server_t	*sv = sr->sr_server;
 
+	/* Get out now if we've been cancelled. */
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
+		mutex_exit(&sr->sr_mutex);
+		return (NT_STATUS_CANCELLED);
+	}
+	mutex_exit(&sr->sr_mutex);
+
 	is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
 
 	/*
--- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c	Fri May 31 14:32:40 2019 +0200
@@ -503,11 +503,13 @@
 	 * smbsr_cleanup for the same request indicate a bug.
 	 */
 	mutex_enter(&sr->sr_mutex);
-	if (sr->sr_state != SMB_REQ_STATE_CANCELED)
+	if (sr->sr_state != SMB_REQ_STATE_CANCELLED)
 		sr->sr_state = SMB_REQ_STATE_CLEANED_UP;
 	mutex_exit(&sr->sr_mutex);
 }
 
+int smb_cancel_in_reader = 1;
+
 /*
  * This is the SMB1 handler for new smb requests, called from
  * smb_session_reader after SMB negotiate is done.  For most SMB
@@ -527,20 +529,58 @@
 int
 smb1sr_newrq(smb_request_t *sr)
 {
-	uint32_t magic;
+	uint16_t pid_hi, pid_lo;
+	int rc, save_offset;
 
-	magic = SMB_READ_PROTOCOL(sr->sr_request_buf);
-	if (magic != SMB_PROTOCOL_MAGIC) {
+	/*
+	 * Decode the SMB header now (peek) so that
+	 * SMB_COM_NT_CANCEL can find this SR.
+	 */
+	save_offset = sr->command.chain_offset;
+	rc = smb_mbc_decodef(&sr->command, SMB_HEADER_ED_FMT,
+	    &sr->smb_com,
+	    &sr->smb_rcls,
+	    &sr->smb_reh,
+	    &sr->smb_err,
+	    &sr->smb_flg,
+	    &sr->smb_flg2,
+	    &pid_hi,
+	    sr->smb_sig,
+	    &sr->smb_tid,
+	    &pid_lo,
+	    &sr->smb_uid,
+	    &sr->smb_mid);
+	sr->command.chain_offset = save_offset;
+	if (rc != 0) {
+		/* Failed decoding the header. Drop 'em. */
 		smb_request_free(sr);
 		return (EPROTO);
 	}
+	sr->smb_pid = (pid_hi << 16) | pid_lo;
 
-	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
-		if (SMB_IS_NT_CANCEL(sr)) {
+	if (sr->smb_com == SMB_COM_NT_CANCEL) {
+		if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
 			sr->session->signing.seqnum++;
 			sr->sr_seqnum = sr->session->signing.seqnum + 1;
 			sr->reply_seqnum = 0;
-		} else {
+		}
+
+		/*
+		 * Normally execute cancel requests immediately,
+		 * (here in the reader thread) so they won't wait
+		 * for other commands already in the task queue.
+		 * Disable this via smb_cancel_in_reader=0 for
+		 * testing or diagnostic efforts, in which case
+		 * cancel runs via taskq_dispatch.
+		 */
+		if (smb_cancel_in_reader != 0) {
+			rc = smb1sr_newrq_cancel(sr);
+			smb_request_free(sr);
+			return (rc);
+		}
+	} else {
+		/* not NT cancel */
+		if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
 			sr->session->signing.seqnum += 2;
 			sr->sr_seqnum = sr->session->signing.seqnum;
 			sr->reply_seqnum = sr->sr_seqnum + 1;
@@ -574,24 +614,17 @@
 	sr->sr_worker = curthread;
 	sr->sr_time_active = gethrtime();
 
+	/*
+	 * Always dispatch to the work function, because cancelled
+	 * requests need an error reply (NT_STATUS_CANCELLED).
+	 */
 	mutex_enter(&sr->sr_mutex);
-	switch (sr->sr_state) {
-	case SMB_REQ_STATE_SUBMITTED:
-		mutex_exit(&sr->sr_mutex);
-		smb1sr_work(sr);
-		sr = NULL;
-		break;
+	if (sr->sr_state == SMB_REQ_STATE_SUBMITTED)
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+	mutex_exit(&sr->sr_mutex);
 
-	default:
-		/*
-		 * SMB1 requests that have been cancelled
-		 * have no reply.  Just free it.
-		 */
-		sr->sr_state = SMB_REQ_STATE_COMPLETED;
-		mutex_exit(&sr->sr_mutex);
-		smb_request_free(sr);
-		break;
-	}
+	smb1sr_work(sr);
+
 	smb_srqueue_runq_exit(srq);
 }
 
@@ -755,11 +788,16 @@
 
 	mutex_enter(&sr->sr_mutex);
 	switch (sr->sr_state) {
-	case SMB_REQ_STATE_SUBMITTED:
+	case SMB_REQ_STATE_ACTIVE:
+		break;
 	case SMB_REQ_STATE_CLEANED_UP:
 		sr->sr_state = SMB_REQ_STATE_ACTIVE;
 		break;
-	case SMB_REQ_STATE_CANCELED:
+	case SMB_REQ_STATE_CANCELLED:
+		/*
+		 * Keep cancelled.  Handlers that might block will
+		 * check the state and return NT_STATUS_CANCELLED.
+		 */
 		break;
 	default:
 		ASSERT(0);
--- a/usr/src/uts/common/fs/smbsrv/smb_fem.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_fem.c	Fri May 31 14:32:40 2019 +0200
@@ -155,6 +155,11 @@
 	smb_fem_initialized = B_FALSE;
 }
 
+/*
+ * Install our fem hooks for change notify.
+ * Not using hold/rele function here because we
+ * remove the fem hooks before node destroy.
+ */
 int
 smb_fem_fcn_install(smb_node_t *node)
 {
@@ -163,7 +168,7 @@
 	if (smb_fcn_ops == NULL)
 		return (ENOSYS);
 	rc = fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ,
-	    (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release);
+	    NULL, NULL);
 	return (rc);
 }
 
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c	Fri May 31 14:32:40 2019 +0200
@@ -1440,14 +1440,21 @@
 		return (rc);
 	}
 
-	ct = smb_ct;
-	ct.cc_pid = sr->fid_ofile->f_uniqid;
-	rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset,
-	    uio->uio_iov->iov_len, svmand, &ct);
-
-	if (rc) {
-		smb_node_end_crit(snode);
-		return (ERANGE);
+	/*
+	 * Note: SMB allows a zero-byte read, which should not
+	 * conflict with any locks.  However nbl_lock_conflict
+	 * takes a zero-byte length as lock to EOF, so we must
+	 * special case that here.
+	 */
+	if (uio->uio_resid > 0) {
+		ct = smb_ct;
+		ct.cc_pid = sr->fid_ofile->f_uniqid;
+		rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset,
+		    uio->uio_resid, svmand, &ct);
+		if (rc != 0) {
+			smb_node_end_crit(snode);
+			return (ERANGE);
+		}
 	}
 
 	rc = smb_vop_read(snode->vp, uio, cr);
@@ -1527,14 +1534,21 @@
 		return (rc);
 	}
 
-	ct = smb_ct;
-	ct.cc_pid = of->f_uniqid;
-	rc = nbl_lock_conflict(vp, NBL_WRITE, uio->uio_loffset,
-	    uio->uio_iov->iov_len, svmand, &ct);
-
-	if (rc) {
-		smb_node_end_crit(snode);
-		return (ERANGE);
+	/*
+	 * Note: SMB allows a zero-byte write, which should not
+	 * conflict with any locks.  However nbl_lock_conflict
+	 * takes a zero-byte length as lock to EOF, so we must
+	 * special case that here.
+	 */
+	if (uio->uio_resid > 0) {
+		ct = smb_ct;
+		ct.cc_pid = of->f_uniqid;
+		rc = nbl_lock_conflict(vp, NBL_WRITE, uio->uio_loffset,
+		    uio->uio_resid, svmand, &ct);
+		if (rc != 0) {
+			smb_node_end_crit(snode);
+			return (ERANGE);
+		}
 	}
 
 	rc = smb_vop_write(vp, uio, ioflag, lcount, cr);
@@ -2644,6 +2658,14 @@
 	 *    bytes. Interestingly if the same lock (same offset and length) is
 	 *    resubmitted Windows will consider that there is an overlap and
 	 *    the granting rules will then apply.
+	 *
+	 * 3) The SMB-level process IDs (smb_pid) are not passed down to the
+	 *    POSIX level in l_pid because (a) the rules about lock PIDs are
+	 *    different in SMB, and (b) we're putting our ofile f_uniqid in
+	 *    the POSIX l_pid field to segregate locks per SMB ofile.
+	 *    (We're also using a "remote" system ID in l_sysid.)
+	 *    All SMB locking PIDs are handled at the SMB level and
+	 *    not exposed in POSIX locking.
 	 */
 	if ((lock->l_length == 0) ||
 	    ((lock->l_start + lock->l_length - 1) < lock->l_start))
--- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c	Fri May 31 14:32:40 2019 +0200
@@ -889,7 +889,9 @@
 	    SMB_SHRF_GUEST_OK);
 	tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_DFSROOT,
 	    SMB_SHRF_DFSROOT);
-	tmp.shr_flags |= smb_kshare_decode_bool(smb, "Autohome",
+	tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_QUOTAS,
+	    SMB_SHRF_QUOTAS);
+	tmp.shr_flags |= smb_kshare_decode_bool(smb, SHOPT_AUTOHOME,
 	    SMB_SHRF_AUTOHOME);
 
 	if ((tmp.shr_flags & SMB_SHRF_AUTOHOME) == SMB_SHRF_AUTOHOME) {
--- a/usr/src/uts/common/fs/smbsrv/smb_lock.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_lock.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -38,17 +38,24 @@
 
 extern caller_context_t smb_ct;
 
+#ifdef	DEBUG
+int smb_lock_debug = 0;
+static void smb_lock_dump1(smb_lock_t *);
+static void smb_lock_dumplist(smb_llist_t *);
+static void smb_lock_dumpnode(smb_node_t *);
+#endif
+
 static void smb_lock_posix_unlock(smb_node_t *, smb_lock_t *, cred_t *);
 static boolean_t smb_is_range_unlocked(uint64_t, uint64_t, uint32_t,
     smb_llist_t *, uint64_t *);
 static int smb_lock_range_overlap(smb_lock_t *, uint64_t, uint64_t);
-static uint32_t smb_lock_range_lckrules(smb_request_t *, smb_ofile_t *,
-    smb_node_t *, smb_lock_t *, smb_lock_t **);
-static clock_t smb_lock_wait(smb_request_t *, smb_lock_t *, smb_lock_t *);
-static uint32_t smb_lock_range_ulckrules(smb_request_t *, smb_node_t *,
-    uint64_t, uint64_t, smb_lock_t **nodelock);
+static uint32_t smb_lock_range_lckrules(smb_ofile_t *, smb_lock_t *,
+    smb_lock_t **);
+static uint32_t smb_lock_wait(smb_request_t *, smb_lock_t *, smb_lock_t *);
+static uint32_t smb_lock_range_ulckrules(smb_ofile_t *,
+    uint64_t, uint64_t, uint32_t, smb_lock_t **);
 static smb_lock_t *smb_lock_create(smb_request_t *, uint64_t, uint64_t,
-    uint32_t, uint32_t);
+    uint32_t, uint32_t, uint32_t);
 static void smb_lock_destroy(smb_lock_t *);
 static void smb_lock_free(smb_lock_t *);
 
@@ -90,30 +97,54 @@
 uint32_t
 smb_unlock_range(
     smb_request_t	*sr,
-    smb_node_t		*node,
     uint64_t		start,
-    uint64_t		length)
+    uint64_t		length,
+    uint32_t		pid)
 {
+	smb_ofile_t	*file = sr->fid_ofile;
+	smb_node_t	*node = file->f_node;
 	smb_lock_t	*lock = NULL;
 	uint32_t	status;
 
+	if (length > 1 &&
+	    (start + length) < start)
+		return (NT_STATUS_INVALID_LOCK_RANGE);
+
+#ifdef	DEBUG
+	if (smb_lock_debug) {
+		cmn_err(CE_CONT, "smb_unlock_range "
+		    "off=0x%llx, len=0x%llx, f=%p, pid=%d\n",
+		    (long long)start, (long long)length,
+		    (void *)sr->fid_ofile, pid);
+	}
+#endif
+
 	/* Apply unlocking rules */
 	smb_llist_enter(&node->n_lock_list, RW_WRITER);
-	status = smb_lock_range_ulckrules(sr, node, start, length, &lock);
+	status = smb_lock_range_ulckrules(file, start, length, pid, &lock);
 	if (status != NT_STATUS_SUCCESS) {
 		/*
 		 * If lock range is not matching in the list
 		 * return error.
 		 */
 		ASSERT(lock == NULL);
-		smb_llist_exit(&node->n_lock_list);
-		return (status);
+	}
+	if (lock != NULL) {
+		smb_llist_remove(&node->n_lock_list, lock);
+		smb_lock_posix_unlock(node, lock, sr->user_cr);
 	}
 
-	smb_llist_remove(&node->n_lock_list, lock);
-	smb_lock_posix_unlock(node, lock, sr->user_cr);
+#ifdef	DEBUG
+	if (smb_lock_debug && lock == NULL) {
+		cmn_err(CE_CONT, "unlock failed, 0x%x\n", status);
+		smb_lock_dumpnode(node);
+	}
+#endif
+
 	smb_llist_exit(&node->n_lock_list);
-	smb_lock_destroy(lock);
+
+	if (lock != NULL)
+		smb_lock_destroy(lock);
 
 	return (status);
 }
@@ -140,58 +171,88 @@
     smb_request_t	*sr,
     uint64_t		start,
     uint64_t		length,
-    uint32_t		timeout,
-    uint32_t		locktype)
+    uint32_t		pid,
+    uint32_t		locktype,
+    uint32_t		timeout)
 {
 	smb_ofile_t	*file = sr->fid_ofile;
 	smb_node_t	*node = file->f_node;
 	smb_lock_t	*lock;
-	smb_lock_t	*clock = NULL;
-	uint32_t	result = NT_STATUS_SUCCESS;
+	smb_lock_t	*conflict = NULL;
+	uint32_t	result;
+	int		rc;
 	boolean_t	lock_has_timeout =
 	    (timeout != 0 && timeout != UINT_MAX);
 
-	lock = smb_lock_create(sr, start, length, locktype, timeout);
+	if (length > 1 &&
+	    (start + length) < start)
+		return (NT_STATUS_INVALID_LOCK_RANGE);
+
+#ifdef	DEBUG
+	if (smb_lock_debug) {
+		cmn_err(CE_CONT, "smb_lock_range "
+		    "off=0x%llx, len=0x%llx, "
+		    "f=%p, pid=%d, typ=%d, tmo=%d\n",
+		    (long long)start, (long long)length,
+		    (void *)sr->fid_ofile, pid, locktype, timeout);
+	}
+#endif
+
+	lock = smb_lock_create(sr, start, length, pid, locktype, timeout);
 
 	smb_llist_enter(&node->n_lock_list, RW_WRITER);
 	for (;;) {
-		clock_t	rc;
 
 		/* Apply locking rules */
-		result = smb_lock_range_lckrules(sr, file, node, lock, &clock);
-
-		if ((result == NT_STATUS_CANCELLED) ||
-		    (result == NT_STATUS_SUCCESS) ||
-		    (result == NT_STATUS_RANGE_NOT_LOCKED)) {
-			ASSERT(clock == NULL);
+		result = smb_lock_range_lckrules(file, lock, &conflict);
+		switch (result) {
+		case NT_STATUS_LOCK_NOT_GRANTED: /* conflict! */
+			/* may need to wait */
 			break;
-		} else if (timeout == 0) {
-			break;
+		case NT_STATUS_SUCCESS:
+		case NT_STATUS_FILE_CLOSED:
+			goto break_loop;
+		default:
+			cmn_err(CE_CONT, "smb_lock_range1, status 0x%x\n",
+			    result);
+			goto break_loop;
 		}
+		if (timeout == 0)
+			goto break_loop;
 
-		ASSERT(result == NT_STATUS_LOCK_NOT_GRANTED);
-		ASSERT(clock);
 		/*
 		 * Call smb_lock_wait holding write lock for
 		 * node lock list.  smb_lock_wait will release
-		 * this lock if it blocks.
+		 * the node list lock if it blocks, so after
+		 * the call, (*conflict) may no longer exist.
 		 */
-		ASSERT(node == clock->l_file->f_node);
-
-		rc = smb_lock_wait(sr, lock, clock);
-		if (rc == 0) {
-			result = NT_STATUS_CANCELLED;
+		result = smb_lock_wait(sr, lock, conflict);
+		conflict = NULL;
+		switch (result) {
+		case NT_STATUS_SUCCESS:
+			/* conflict gone, try again */
 			break;
-		}
-		if (rc == -1)
+		case NT_STATUS_TIMEOUT:
+			/* try just once more */
 			timeout = 0;
-
-		clock = NULL;
+			break;
+		case NT_STATUS_CANCELLED:
+		case NT_STATUS_FILE_CLOSED:
+			goto break_loop;
+		default:
+			cmn_err(CE_CONT, "smb_lock_range2, status 0x%x\n",
+			    result);
+			goto break_loop;
+		}
 	}
 
+break_loop:
 	lock->l_blocked_by = NULL;
 
 	if (result != NT_STATUS_SUCCESS) {
+		if (result == NT_STATUS_FILE_CLOSED)
+			result = NT_STATUS_RANGE_NOT_LOCKED;
+
 		/*
 		 * Under certain conditions NT_STATUS_FILE_LOCK_CONFLICT
 		 * should be returned instead of NT_STATUS_LOCK_NOT_GRANTED.
@@ -241,11 +302,32 @@
 		 * don't insert into the CIFS lock list unless the
 		 * posix lock worked
 		 */
-		if (smb_fsop_frlock(node, lock, B_FALSE, sr->user_cr))
+		rc = smb_fsop_frlock(node, lock, B_FALSE, sr->user_cr);
+		if (rc != 0) {
+#ifdef	DEBUG
+			if (smb_lock_debug)
+				cmn_err(CE_CONT, "fop_frlock, err=%d\n", rc);
+#endif
 			result = NT_STATUS_FILE_LOCK_CONFLICT;
-		else
-			smb_llist_insert_tail(&node->n_lock_list, lock);
+		} else {
+			/*
+			 * We want unlock to find exclusive locks before
+			 * shared locks, so insert those at the head.
+			 */
+			if (lock->l_type == SMB_LOCK_TYPE_READWRITE)
+				smb_llist_insert_head(&node->n_lock_list, lock);
+			else
+				smb_llist_insert_tail(&node->n_lock_list, lock);
+		}
 	}
+
+#ifdef	DEBUG
+	if (smb_lock_debug && result != 0) {
+		cmn_err(CE_CONT, "lock failed, 0x%x\n", result);
+		smb_lock_dumpnode(node);
+	}
+#endif
+
 	smb_llist_exit(&node->n_lock_list);
 
 	if (result == NT_STATUS_SUCCESS)
@@ -254,7 +336,6 @@
 	return (result);
 }
 
-
 /*
  * smb_lock_range_access
  *
@@ -271,13 +352,25 @@
     smb_request_t	*sr,
     smb_node_t		*node,
     uint64_t		start,
-    uint64_t		length,	 /* zero means to EoF */
+    uint64_t		length,
     boolean_t		will_write)
 {
 	smb_lock_t	*lock;
 	smb_llist_t	*llist;
+	uint32_t	lk_pid = 0;
 	int		status = NT_STATUS_SUCCESS;
 
+	if (length == 0)
+		return (status);
+
+	/*
+	 * What PID to use for lock conflict checks?
+	 * SMB2 locking ignores PIDs (have lk_pid=0)
+	 * SMB1 uses low 16 bits of sr->smb_pid
+	 */
+	if (sr->session->dialect < SMB_VERS_2_BASE)
+		lk_pid = sr->smb_pid & 0xFFFF;
+
 	llist = &node->n_lock_list;
 	smb_llist_enter(llist, RW_READER);
 	/* Search for any applicable lock */
@@ -293,10 +386,21 @@
 			continue;
 
 		if (lock->l_type == SMB_LOCK_TYPE_READWRITE &&
-		    lock->l_session_kid == sr->session->s_kid &&
-		    lock->l_pid == sr->smb_pid)
+		    lock->l_file == sr->fid_ofile &&
+		    lock->l_pid == lk_pid)
 			continue;
 
+#ifdef	DEBUG
+		if (smb_lock_debug) {
+			cmn_err(CE_CONT, "smb_lock_range_access conflict: "
+			    "off=0x%llx, len=0x%llx, "
+			    "f=%p, pid=%d, typ=%d\n",
+			    (long long)lock->l_start,
+			    (long long)lock->l_length,
+			    (void *)lock->l_file,
+			    lock->l_pid, lock->l_type);
+		}
+#endif
 		status = NT_STATUS_FILE_LOCK_CONFLICT;
 		break;
 	}
@@ -304,6 +408,10 @@
 	return (status);
 }
 
+/*
+ * The ofile is being closed.  Wake any waiting locks and
+ * clear any granted locks.
+ */
 void
 smb_node_destroy_lock_by_ofile(smb_node_t *node, smb_ofile_t *file)
 {
@@ -315,6 +423,24 @@
 	ASSERT(node->n_refcnt);
 
 	/*
+	 * Cancel any waiting locks for this ofile
+	 */
+	smb_llist_enter(&node->n_wlock_list, RW_READER);
+	for (lock = smb_llist_head(&node->n_wlock_list);
+	    lock != NULL;
+	    lock = smb_llist_next(&node->n_wlock_list, lock)) {
+
+		if (lock->l_file == file) {
+			mutex_enter(&lock->l_mutex);
+			lock->l_blocked_by = NULL;
+			lock->l_flags |= SMB_LOCK_FLAG_CLOSED;
+			cv_broadcast(&lock->l_cv);
+			mutex_exit(&lock->l_mutex);
+		}
+	}
+	smb_llist_exit(&node->n_wlock_list);
+
+	/*
 	 * Move locks matching the specified file from the node->n_lock_list
 	 * to a temporary list (holding the lock the entire time) then
 	 * destroy all the matching locks.  We can't call smb_lock_destroy
@@ -349,15 +475,75 @@
 	list_destroy(&destroy_list);
 }
 
+/*
+ * Cause a waiting lock to stop waiting and return an error.
+ * returns same status codes as unlock:
+ * NT_STATUS_SUCCESS, NT_STATUS_RANGE_NOT_LOCKED
+ */
+uint32_t
+smb_lock_range_cancel(smb_request_t *sr,
+    uint64_t start, uint64_t length, uint32_t pid)
+{
+	smb_node_t *node;
+	smb_lock_t *lock;
+	uint32_t status = NT_STATUS_RANGE_NOT_LOCKED;
+	int cnt = 0;
+
+	node = sr->fid_ofile->f_node;
+
+	smb_llist_enter(&node->n_wlock_list, RW_READER);
+
+#ifdef	DEBUG
+	if (smb_lock_debug) {
+		cmn_err(CE_CONT, "smb_lock_range_cancel:\n"
+		    "\tstart=0x%llx, len=0x%llx, of=%p, pid=%d\n",
+		    (long long)start, (long long)length,
+		    (void *)sr->fid_ofile, pid);
+	}
+#endif
+
+	for (lock = smb_llist_head(&node->n_wlock_list);
+	    lock != NULL;
+	    lock = smb_llist_next(&node->n_wlock_list, lock)) {
+
+		if ((start == lock->l_start) &&
+		    (length == lock->l_length) &&
+		    lock->l_file == sr->fid_ofile &&
+		    lock->l_pid == pid) {
+
+			mutex_enter(&lock->l_mutex);
+			lock->l_blocked_by = NULL;
+			lock->l_flags |= SMB_LOCK_FLAG_CANCELLED;
+			cv_broadcast(&lock->l_cv);
+			mutex_exit(&lock->l_mutex);
+			status = NT_STATUS_SUCCESS;
+			cnt++;
+		}
+	}
+
+#ifdef	DEBUG
+	if (smb_lock_debug && cnt != 1) {
+		cmn_err(CE_CONT, "cancel found %d\n", cnt);
+		smb_lock_dumpnode(node);
+	}
+#endif
+
+	smb_llist_exit(&node->n_wlock_list);
+
+	return (status);
+}
+
 void
 smb_lock_range_error(smb_request_t *sr, uint32_t status32)
 {
 	uint16_t errcode;
 
-	if (status32 == NT_STATUS_CANCELLED)
-		errcode = ERROR_OPERATION_ABORTED;
-	else
+	if (status32 == NT_STATUS_CANCELLED) {
+		status32 = NT_STATUS_FILE_LOCK_CONFLICT;
+		errcode = ERROR_LOCK_VIOLATION;
+	} else {
 		errcode = ERRlock;
+	}
 
 	smbsr_error(sr, status32, ERRDOS, errcode);
 }
@@ -514,28 +700,27 @@
  *	   irrespective of pid of smb client issuing lock request.
  *
  *	2. Read lock in the overlapped region of write lock
- *	   are allowed if the pervious lock is performed by the
+ *	   are allowed if the previous lock is performed by the
  *	   same pid and connection.
  *
  * return status:
- *	NT_STATUS_SUCCESS - Input lock range adapts to lock rules.
+ *	NT_STATUS_SUCCESS - Input lock range conforms to lock rules.
  *	NT_STATUS_LOCK_NOT_GRANTED - Input lock conflicts lock rules.
- *	NT_STATUS_CANCELLED - Error in processing lock rules
+ *	NT_STATUS_FILE_CLOSED
  */
 static uint32_t
 smb_lock_range_lckrules(
-    smb_request_t	*sr,
     smb_ofile_t		*file,
-    smb_node_t		*node,
-    smb_lock_t		*dlock,
-    smb_lock_t		**clockp)
+    smb_lock_t		*dlock,		/* desired lock */
+    smb_lock_t		**conflictp)
 {
+	smb_node_t	*node = file->f_node;
 	smb_lock_t	*lock;
 	uint32_t	status = NT_STATUS_SUCCESS;
 
 	/* Check if file is closed */
 	if (!smb_ofile_is_open(file)) {
-		return (NT_STATUS_RANGE_NOT_LOCKED);
+		return (NT_STATUS_FILE_CLOSED);
 	}
 
 	/* Caller must hold lock for node->n_lock_list */
@@ -563,16 +748,14 @@
 		 */
 		if ((dlock->l_type == SMB_LOCK_TYPE_READONLY) &&
 		    !(lock->l_type == SMB_LOCK_TYPE_READONLY)) {
-			if (lock->l_file == sr->fid_ofile &&
-			    lock->l_session_kid == sr->session->s_kid &&
-			    lock->l_pid == sr->smb_pid &&
-			    lock->l_uid == sr->smb_uid) {
+			if (lock->l_file == dlock->l_file &&
+			    lock->l_pid == dlock->l_pid) {
 				continue;
 			}
 		}
 
 		/* Conflict in overlapping lock element */
-		*clockp = lock;
+		*conflictp = lock;
 		status = NT_STATUS_LOCK_NOT_GRANTED;
 		break;
 	}
@@ -581,6 +764,28 @@
 }
 
 /*
+ * Cancel method for smb_lock_wait()
+ *
+ * This request is waiting on a lock.  Wakeup everything
+ * waiting on the lock so that the relevant thread regains
+ * control and notices that is has been cancelled.  The
+ * other lock request threads waiting on this lock will go
+ * back to sleep when they discover they are still blocked.
+ */
+static void
+smb_lock_cancel_sr(smb_request_t *sr)
+{
+	smb_lock_t *lock = sr->cancel_arg2;
+
+	ASSERT(lock->l_magic == SMB_LOCK_MAGIC);
+	mutex_enter(&lock->l_mutex);
+	lock->l_blocked_by = NULL;
+	lock->l_flags |= SMB_LOCK_FLAG_CANCELLED;
+	cv_broadcast(&lock->l_cv);
+	mutex_exit(&lock->l_mutex);
+}
+
+/*
  * smb_lock_wait
  *
  * Wait operation for smb overlapping lock to be released.  Caller must hold
@@ -589,87 +794,134 @@
  * within this function during the sleep after the lock dependency has
  * been recorded.
  *
- * return value
- *
- *	0	The request was canceled.
- *	-1	The timeout was reached.
- *	>0	Condition met.
+ * Returns NT_STATUS_SUCCESS when the lock can be granted,
+ * otherwise NT_STATUS_CANCELLED, etc.
  */
-static clock_t
-smb_lock_wait(smb_request_t *sr, smb_lock_t *b_lock, smb_lock_t *c_lock)
+static uint32_t
+smb_lock_wait(smb_request_t *sr, smb_lock_t *lock, smb_lock_t *conflict)
 {
-	clock_t		rc = 0;
+	smb_node_t	*node;
+	clock_t		rc;
+	uint32_t	status = NT_STATUS_SUCCESS;
+
+	node = lock->l_file->f_node;
+	ASSERT(node == conflict->l_file->f_node);
+
+	/*
+	 * Let the blocked lock (lock) l_blocked_by point to the
+	 * conflicting lock (conflict), and increment a count of
+	 * conflicts with the latter.  When the conflicting lock
+	 * is destroyed, we'll search the list of waiting locks
+	 * (on the node) and wake any with l_blocked_by ==
+	 * the formerly conflicting lock.
+	 */
+	mutex_enter(&lock->l_mutex);
+	lock->l_blocked_by = conflict;
+	mutex_exit(&lock->l_mutex);
+
+	mutex_enter(&conflict->l_mutex);
+	conflict->l_conflicts++;
+	mutex_exit(&conflict->l_mutex);
+
+	/*
+	 * Put the blocked lock on the waiting list.
+	 */
+	smb_llist_enter(&node->n_wlock_list, RW_WRITER);
+	smb_llist_insert_tail(&node->n_wlock_list, lock);
+	smb_llist_exit(&node->n_wlock_list);
+
+#ifdef	DEBUG
+	if (smb_lock_debug) {
+		cmn_err(CE_CONT, "smb_lock_wait: lock=%p conflict=%p\n",
+		    (void *)lock, (void *)conflict);
+		smb_lock_dumpnode(node);
+	}
+#endif
+
+	/*
+	 * We come in with n_lock_list already held, and keep
+	 * that hold until we're done with conflict (are now).
+	 * Drop that now, and retake later.  Note that the lock
+	 * (*conflict) may go away once we exit this list.
+	 */
+	smb_llist_exit(&node->n_lock_list);
+	conflict = NULL;
 
-	ASSERT(sr->sr_awaiting == NULL);
+	/*
+	 * Before we actually start waiting, setup the hooks
+	 * smb_request_cancel uses to unblock this wait.
+	 */
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state == SMB_REQ_STATE_ACTIVE) {
+		sr->sr_state = SMB_REQ_STATE_WAITING_LOCK;
+		sr->cancel_method = smb_lock_cancel_sr;
+		sr->cancel_arg2 = lock;
+	} else {
+		status = NT_STATUS_CANCELLED;
+	}
+	mutex_exit(&sr->sr_mutex);
 
+	/*
+	 * Now we're ready to actually wait for the conflicting
+	 * lock to be removed, or for the wait to be ended by
+	 * an external cancel, or a timeout.
+	 */
+	mutex_enter(&lock->l_mutex);
+	while (status == NT_STATUS_SUCCESS &&
+	    lock->l_blocked_by != NULL) {
+		if (lock->l_flags & SMB_LOCK_FLAG_INDEFINITE) {
+			cv_wait(&lock->l_cv, &lock->l_mutex);
+		} else {
+			rc = cv_timedwait(&lock->l_cv,
+			    &lock->l_mutex, lock->l_end_time);
+			if (rc < 0)
+				status = NT_STATUS_TIMEOUT;
+		}
+	}
+	if (status == NT_STATUS_SUCCESS) {
+		if (lock->l_flags & SMB_LOCK_FLAG_CANCELLED)
+			status = NT_STATUS_CANCELLED;
+		if (lock->l_flags & SMB_LOCK_FLAG_CLOSED)
+			status = NT_STATUS_FILE_CLOSED;
+	}
+	mutex_exit(&lock->l_mutex);
+
+	/*
+	 * Done waiting.  Cleanup cancel hooks and
+	 * finish SR state transitions.
+	 */
 	mutex_enter(&sr->sr_mutex);
+	sr->cancel_method = NULL;
+	sr->cancel_arg2 = NULL;
 
 	switch (sr->sr_state) {
-	case SMB_REQ_STATE_ACTIVE:
-		/*
-		 * Wait up till the timeout time keeping track of actual
-		 * time waited for possible retry failure.
-		 */
-		sr->sr_state = SMB_REQ_STATE_WAITING_LOCK;
-		sr->sr_awaiting = c_lock;
-		mutex_exit(&sr->sr_mutex);
+	case SMB_REQ_STATE_WAITING_LOCK:
+		/* Normal wakeup.  Keep status from above. */
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+		break;
 
-		mutex_enter(&c_lock->l_mutex);
-		/*
-		 * The conflict list (l_conflict_list) for a lock contains
-		 * all the locks that are blocked by and in conflict with
-		 * that lock.  Add the new lock to the conflict list for the
-		 * active lock.
-		 *
-		 * l_conflict_list is currently a fancy way of representing
-		 * the references/dependencies on a lock.  It could be
-		 * replaced with a reference count but this approach
-		 * has the advantage that MDB can display the lock
-		 * dependencies at any point in time.  In the future
-		 * we should be able to leverage the list to implement
-		 * an asynchronous locking model.
-		 *
-		 * l_blocked_by is the reverse of the conflict list.  It
-		 * points to the lock that the new lock conflicts with.
-		 * As currently implemented this value is purely for
-		 * debug purposes -- there are windows of time when
-		 * l_blocked_by may be non-NULL even though there is no
-		 * conflict list
-		 */
-		b_lock->l_blocked_by = c_lock;
-		smb_slist_insert_tail(&c_lock->l_conflict_list, b_lock);
-		smb_llist_exit(&c_lock->l_file->f_node->n_lock_list);
-
-		if (SMB_LOCK_INDEFINITE_WAIT(b_lock)) {
-			cv_wait(&c_lock->l_cv, &c_lock->l_mutex);
-		} else {
-			rc = cv_timedwait(&c_lock->l_cv,
-			    &c_lock->l_mutex, b_lock->l_end_time);
-		}
-
-		mutex_exit(&c_lock->l_mutex);
-
-		smb_llist_enter(&c_lock->l_file->f_node->n_lock_list,
-		    RW_WRITER);
-		smb_slist_remove(&c_lock->l_conflict_list, b_lock);
-
-		mutex_enter(&sr->sr_mutex);
-		sr->sr_awaiting = NULL;
-		if (sr->sr_state == SMB_REQ_STATE_CANCELED) {
-			rc = 0;
-		} else {
-			sr->sr_state = SMB_REQ_STATE_ACTIVE;
-		}
+	case SMB_REQ_STATE_CANCEL_PENDING:
+		/* Cancelled via smb_lock_cancel_sr */
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
+		/* FALLTHROUGH */
+	case SMB_REQ_STATE_CANCELLED:
+		if (status == NT_STATUS_SUCCESS)
+			status = NT_STATUS_CANCELLED;
 		break;
 
 	default:
-		ASSERT(sr->sr_state == SMB_REQ_STATE_CANCELED);
-		rc = 0;
 		break;
 	}
 	mutex_exit(&sr->sr_mutex);
 
-	return (rc);
+	/* Return to the caller with n_lock_list held. */
+	smb_llist_enter(&node->n_lock_list, RW_WRITER);
+
+	smb_llist_enter(&node->n_wlock_list, RW_WRITER);
+	smb_llist_remove(&node->n_wlock_list, lock);
+	smb_llist_exit(&node->n_wlock_list);
+
+	return (status);
 }
 
 /*
@@ -685,7 +937,7 @@
  * Return values
  *
  *	NT_STATUS_SUCCESS		Unlock request matches lock record
- *					pointed by 'nodelock' lock structure.
+ *					pointed by 'foundlock' lock structure.
  *
  *	NT_STATUS_RANGE_NOT_LOCKED	Unlock request doen't match any
  *					of lock record in node lock request or
@@ -693,12 +945,13 @@
  */
 static uint32_t
 smb_lock_range_ulckrules(
-    smb_request_t	*sr,
-    smb_node_t		*node,
+    smb_ofile_t		*file,
     uint64_t		start,
     uint64_t		length,
-    smb_lock_t		**nodelock)
+    uint32_t		pid,
+    smb_lock_t		**foundlock)
 {
+	smb_node_t	*node = file->f_node;
 	smb_lock_t	*lock;
 	uint32_t	status = NT_STATUS_RANGE_NOT_LOCKED;
 
@@ -709,11 +962,9 @@
 
 		if ((start == lock->l_start) &&
 		    (length == lock->l_length) &&
-		    lock->l_file == sr->fid_ofile &&
-		    lock->l_session_kid == sr->session->s_kid &&
-		    lock->l_pid == sr->smb_pid &&
-		    lock->l_uid == sr->smb_uid) {
-			*nodelock = lock;
+		    lock->l_file == file &&
+		    lock->l_pid == pid) {
+			*foundlock = lock;
 			status = NT_STATUS_SUCCESS;
 			break;
 		}
@@ -727,6 +978,7 @@
     smb_request_t *sr,
     uint64_t start,
     uint64_t length,
+    uint32_t pid,
     uint32_t locktype,
     uint32_t timeout)
 {
@@ -735,14 +987,12 @@
 	ASSERT(locktype == SMB_LOCK_TYPE_READWRITE ||
 	    locktype == SMB_LOCK_TYPE_READONLY);
 
-	lock = kmem_zalloc(sizeof (smb_lock_t), KM_SLEEP);
+	lock = kmem_cache_alloc(smb_cache_lock, KM_SLEEP);
+	bzero(lock, sizeof (*lock));
 	lock->l_magic = SMB_LOCK_MAGIC;
-	lock->l_sr = sr; /* Invalid after lock is active */
-	lock->l_session_kid = sr->session->s_kid;
-	lock->l_session = sr->session;
 	lock->l_file = sr->fid_ofile;
-	lock->l_uid = sr->smb_uid;
-	lock->l_pid = sr->smb_pid;
+	/* l_file == fid_ofile implies same connection (see ofile lookup) */
+	lock->l_pid = pid;
 	lock->l_type = locktype;
 	lock->l_start = start;
 	lock->l_length = length;
@@ -756,8 +1006,6 @@
 
 	mutex_init(&lock->l_mutex, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&lock->l_cv, NULL, CV_DEFAULT, NULL);
-	smb_slist_constructor(&lock->l_conflict_list, sizeof (smb_lock_t),
-	    offsetof(smb_lock_t, l_conflict_lnd));
 
 	return (lock);
 }
@@ -765,11 +1013,12 @@
 static void
 smb_lock_free(smb_lock_t *lock)
 {
-	smb_slist_destructor(&lock->l_conflict_list);
+
+	lock->l_magic = 0;
 	cv_destroy(&lock->l_cv);
 	mutex_destroy(&lock->l_mutex);
 
-	kmem_free(lock, sizeof (smb_lock_t));
+	kmem_cache_free(smb_cache_lock, lock);
 }
 
 /*
@@ -780,19 +1029,49 @@
 static void
 smb_lock_destroy(smb_lock_t *lock)
 {
+	smb_lock_t *tl;
+	smb_node_t *node;
+	uint32_t ccnt;
+
 	/*
-	 * Caller must hold node->n_lock_list lock.
+	 * Wake any waiting locks that were blocked by this.
+	 * We want them to wake and continue in FIFO order,
+	 * so enter/exit the llist every time...
 	 */
 	mutex_enter(&lock->l_mutex);
-	cv_broadcast(&lock->l_cv);
+	ccnt = lock->l_conflicts;
+	lock->l_conflicts = 0;
 	mutex_exit(&lock->l_mutex);
 
-	/*
-	 * The cv_broadcast above should wake up any locks that previous
-	 * had conflicts with this lock.  Wait for the locking threads
-	 * to remove their references to this lock.
-	 */
-	smb_slist_wait_for_empty(&lock->l_conflict_list);
+	node = lock->l_file->f_node;
+	while (ccnt) {
+
+		smb_llist_enter(&node->n_wlock_list, RW_READER);
+
+		for (tl = smb_llist_head(&node->n_wlock_list);
+		    tl != NULL;
+		    tl = smb_llist_next(&node->n_wlock_list, tl)) {
+			mutex_enter(&tl->l_mutex);
+			if (tl->l_blocked_by == lock) {
+				tl->l_blocked_by = NULL;
+				cv_broadcast(&tl->l_cv);
+				mutex_exit(&tl->l_mutex);
+				goto woke_one;
+			}
+			mutex_exit(&tl->l_mutex);
+		}
+		/* No more in the list blocked by this lock. */
+		ccnt = 0;
+	woke_one:
+		smb_llist_exit(&node->n_wlock_list);
+		if (ccnt) {
+			/*
+			 * Let the thread we woke have a chance to run
+			 * before we wake competitors for their lock.
+			 */
+			delay(MSEC_TO_TICK(1));
+		}
+	}
 
 	smb_lock_free(lock);
 }
@@ -887,3 +1166,42 @@
 	/* the range is completely unlocked */
 	return (B_TRUE);
 }
+
+#ifdef	DEBUG
+static void
+smb_lock_dump1(smb_lock_t *lock)
+{
+	cmn_err(CE_CONT, "\t0x%p: 0x%llx, 0x%llx, %p, %d\n",
+	    (void *)lock,
+	    (long long)lock->l_start,
+	    (long long)lock->l_length,
+	    (void *)lock->l_file,
+	    lock->l_pid);
+
+}
+
+static void
+smb_lock_dumplist(smb_llist_t *llist)
+{
+	smb_lock_t *lock;
+
+	for (lock = smb_llist_head(llist);
+	    lock != NULL;
+	    lock = smb_llist_next(llist, lock)) {
+		smb_lock_dump1(lock);
+	}
+}
+
+static void
+smb_lock_dumpnode(smb_node_t *node)
+{
+	cmn_err(CE_CONT, "Granted Locks on %p (%d)\n",
+	    (void *)node, node->n_lock_list.ll_count);
+	smb_lock_dumplist(&node->n_lock_list);
+
+	cmn_err(CE_CONT, "Waiting Locks on %p (%d)\n",
+	    (void *)node, node->n_wlock_list.ll_count);
+	smb_lock_dumplist(&node->n_wlock_list);
+}
+
+#endif
--- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 /*
  * SMB: lock_byte_range
@@ -72,11 +74,15 @@
 	DTRACE_SMB_1(op__LockByteRange__done, smb_request_t *, sr);
 }
 
+/*
+ * Legacy SMB command; takes an exclusive byte-range lock
+ */
 smb_sdrc_t
 smb_com_lock_byte_range(struct smb_request *sr)
 {
 	uint32_t	count;
 	uint32_t	off;
+	uint32_t	lk_pid;
 	DWORD		result;
 	int		rc;
 
@@ -90,14 +96,11 @@
 		return (SDRC_ERROR);
 	}
 
-	/*
-	 * The last parameter is lock type. This is dependent on
-	 * lock flag (3rd parameter). Since the lock flag is
-	 * set to be exclusive, lock type is passed as
-	 * normal lock (write lock).
-	 */
-	result = smb_lock_range(sr, (u_offset_t)off, (uint64_t)count,  0,
-	    SMB_LOCK_TYPE_READWRITE);
+	/* Note: SMB1 locking uses 16-bit PIDs. */
+	lk_pid = sr->smb_pid & 0xFFFF;
+
+	result = smb_lock_range(sr, (u_offset_t)off, (uint64_t)count,
+	    lk_pid, SMB_LOCK_TYPE_READWRITE, 0);
 	if (result != NT_STATUS_SUCCESS) {
 		smb_lock_range_error(sr, result);
 		return (SDRC_ERROR);
--- a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -212,6 +212,12 @@
 
 #include <smbsrv/smb_kproto.h>
 
+/*
+ * This is a somewhat arbitrary sanity limit on the length of the
+ * SMB2_LOCK_ELEMENT array.  It usually has length one or two.
+ */
+int smb_lock_max_elem = 1024;
+
 smb_sdrc_t
 smb_pre_locking_andx(smb_request_t *sr)
 {
@@ -225,6 +231,13 @@
 	DTRACE_SMB_1(op__LockingX__done, smb_request_t *, sr);
 }
 
+struct lreq {
+	uint64_t off;
+	uint64_t len;
+	uint32_t pid;
+	uint32_t reserved;
+};
+
 smb_sdrc_t
 smb_com_locking_andx(smb_request_t *sr)
 {
@@ -234,16 +247,16 @@
 	uint32_t	timeout;	/* Milliseconds to wait for lock */
 	unsigned short	unlock_num;	/* # unlock range structs */
 	unsigned short	lock_num;	/* # lock range structs */
-	uint32_t	save_pid;	/* Process Id of owner */
-	uint32_t	offset32, length32;
-	uint64_t	offset64;
-	uint64_t	length64;
 	DWORD		result;
 	int 		rc;
 	uint32_t	ltype;
 	smb_ofile_t	*ofile;
 	uint16_t	tmp_pid;	/* locking uses 16-bit pids */
 	uint8_t		brk;
+	uint32_t	lrv_tot;
+	struct lreq	*lrv_ul;
+	struct lreq	*lrv_lk;
+	struct lreq	*lr;
 
 	rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
 	    &oplock_level, &timeout, &unlock_num, &lock_num);
@@ -262,13 +275,18 @@
 		return (SDRC_ERROR);
 	}
 
+	if (unlock_num > smb_lock_max_elem ||
+	    lock_num > smb_lock_max_elem) {
+		smbsr_error(sr, NT_STATUS_INSUFFICIENT_RESOURCES,
+		    ERRDOS, ERROR_NO_SYSTEM_RESOURCES);
+		return (SDRC_ERROR);
+	}
+
 	if (lock_type & LOCKING_ANDX_SHARED_LOCK)
 		ltype = SMB_LOCK_TYPE_READONLY;
 	else
 		ltype = SMB_LOCK_TYPE_READWRITE;
 
-	save_pid = sr->smb_pid;	/* Save the original pid */
-
 	if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
 		if (oplock_level == 0)
 			brk = SMB_OPLOCK_BREAK_TO_NONE;
@@ -289,15 +307,6 @@
 		return (SDRC_ERROR);
 	}
 
-	/*
-	 * No support for cancel lock (smbtorture expects this)
-	 */
-	if (lock_type & LOCKING_ANDX_CANCEL_LOCK) {
-		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
-		    ERRDOS, ERROR_INVALID_PARAMETER);
-		return (SDRC_ERROR);
-	}
-
 	if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 		/*
 		 * negotiated protocol should be NT LM 0.12 or later
@@ -307,84 +316,95 @@
 			    ERRDOS, ERROR_INVALID_PARAMETER);
 			return (SDRC_ERROR);
 		}
-
-		for (i = 0; i < unlock_num; i++) {
-			rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
-			    &tmp_pid, &offset64, &length64);
-			if (rc) {
-				/*
-				 * This is the error returned by Windows 2000
-				 * even when STATUS32 has been negotiated.
-				 */
-				smbsr_error(sr, 0, ERRSRV, ERRerror);
-				return (SDRC_ERROR);
-			}
-			sr->smb_pid = tmp_pid;	/* NB: 16-bit */
+	}
 
-			result = smb_unlock_range(sr, sr->fid_ofile->f_node,
-			    offset64, length64);
-			if (result != NT_STATUS_SUCCESS) {
-				smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
-				    ERRDOS, ERROR_NOT_LOCKED);
-				return (SDRC_ERROR);
-			}
-		}
-
-		for (i = 0; i < lock_num; i++) {
-			rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
-			    &tmp_pid, &offset64, &length64);
-			if (rc) {
-				smbsr_error(sr, 0, ERRSRV, ERRerror);
-				return (SDRC_ERROR);
-			}
-			sr->smb_pid = tmp_pid;	/* NB: 16-bit */
+	/*
+	 * Parse the unlock, lock vectors.  Will parse all the
+	 * unlock + lock records into one array, and then use
+	 * pointers to the unlock and lock parts.
+	 */
+	lrv_tot = unlock_num + lock_num;
+	lrv_ul = smb_srm_zalloc(sr, lrv_tot * sizeof (*lrv_ul));
+	lrv_lk = &lrv_ul[unlock_num];
 
-			result = smb_lock_range(sr, offset64, length64, timeout,
-			    ltype);
-			if (result != NT_STATUS_SUCCESS) {
-				smb_lock_range_error(sr, result);
-				return (SDRC_ERROR);
-			}
+	for (i = 0; i < lrv_tot; i++) {
+		lr = &lrv_ul[i];
+		if (lock_type & LOCKING_ANDX_LARGE_FILES) {
+			rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
+			    &tmp_pid, &lr->off, &lr->len);
+		} else {
+			uint32_t	offset32, length32;
+			rc = smb_mbc_decodef(&sr->smb_data, "wll",
+			    &tmp_pid, &offset32, &length32);
+			lr->off = offset32;
+			lr->len = length32;
 		}
-	} else {
-		for (i = 0; i < unlock_num; i++) {
-			rc = smb_mbc_decodef(&sr->smb_data, "wll", &tmp_pid,
-			    &offset32, &length32);
-			if (rc) {
-				smbsr_error(sr, 0, ERRSRV, ERRerror);
-				return (SDRC_ERROR);
-			}
-			sr->smb_pid = tmp_pid;	/* NB: 16-bit */
-
-			result = smb_unlock_range(sr, sr->fid_ofile->f_node,
-			    (uint64_t)offset32, (uint64_t)length32);
-			if (result != NT_STATUS_SUCCESS) {
-				smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
-				    ERRDOS, ERROR_NOT_LOCKED);
-				return (SDRC_ERROR);
-			}
-		}
-
-		for (i = 0; i < lock_num; i++) {
-			rc = smb_mbc_decodef(&sr->smb_data, "wll", &tmp_pid,
-			    &offset32, &length32);
-			if (rc) {
-				smbsr_error(sr, 0, ERRSRV, ERRerror);
-				return (SDRC_ERROR);
-			}
-			sr->smb_pid = tmp_pid;	/* NB: 16-bit */
-
-			result = smb_lock_range(sr, (uint64_t)offset32,
-			    (uint64_t)length32, timeout, ltype);
-			if (result != NT_STATUS_SUCCESS) {
-				smb_lock_range_error(sr, result);
-				return (SDRC_ERROR);
-			}
+		lr->pid = tmp_pid;	/* 16-bit PID */
+		if (rc) {
+			/*
+			 * This is the error returned by Windows 2000
+			 * even when STATUS32 has been negotiated.
+			 */
+			smbsr_error(sr, 0, ERRSRV, ERRerror);
+			return (SDRC_ERROR);
 		}
 	}
 
-	sr->smb_pid = save_pid;
-	if (smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0))
+	/*
+	 * Cancel waiting locks.  MS-CIFS says one place that
+	 * this cancels all waiting locks for this FID+PID,
+	 * but smbtorture insists this cancels just one.
+	 * Tests with Windows 7 confirms that.
+	 */
+	if ((lock_type & LOCKING_ANDX_CANCEL_LOCK) != 0) {
+		lr = lrv_lk;
+
+		result = smb_lock_range_cancel(sr, lr->off, lr->len, lr->pid);
+
+		if (result != NT_STATUS_SUCCESS) {
+			smbsr_error(sr, 0, ERRDOS,
+			    ERROR_CANCEL_VIOLATION);
+			return (SDRC_ERROR);
+		}
+		goto out;
+	}
+
+	/*
+	 * Normal unlock and lock list
+	 */
+	for (i = 0; i < unlock_num; i++) {
+		lr = &lrv_ul[i];
+
+		result = smb_unlock_range(sr, lr->off, lr->len, lr->pid);
+		if (result != NT_STATUS_SUCCESS) {
+			smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
+			    ERRDOS, ERROR_NOT_LOCKED);
+			return (SDRC_ERROR);
+		}
+	}
+	for (i = 0; i < lock_num; i++) {
+		lr = &lrv_lk[i];
+
+		result = smb_lock_range(sr, lr->off, lr->len, lr->pid,
+		    ltype, timeout);
+		if (result != NT_STATUS_SUCCESS) {
+			/*
+			 * Oh... we have to rollback.
+			 */
+			while (i > 0) {
+				--i;
+				lr = &lrv_lk[i];
+				(void) smb_unlock_range(sr,
+				    lr->off, lr->len, lr->pid);
+			}
+			smb_lock_range_error(sr, result);
+			return (SDRC_ERROR);
+		}
+	}
+
+out:
+	if (smbsr_encode_result(sr, 2, 0, "bb.ww",
+	    2, sr->andx_com, 0x27, 0) != 0)
 		return (SDRC_ERROR);
 	return (SDRC_SUCCESS);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 /*
  * SMB Node State Machine
@@ -694,7 +694,7 @@
 	 * and get out of the way.  FILE_ACTION_DELETE_PENDING
 	 * is a special, internal-only action for this purpose.
 	 */
-	smb_notify_event(node, FILE_ACTION_DELETE_PENDING, NULL);
+	smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL);
 
 	return (NT_STATUS_SUCCESS);
 }
@@ -847,73 +847,86 @@
  */
 
 void
-smb_node_fcn_subscribe(smb_node_t *node, smb_request_t *sr)
+smb_node_fcn_subscribe(smb_node_t *node)
 {
-	smb_node_fcn_t		*fcn = &node->n_fcn;
 
-	mutex_enter(&fcn->fcn_mutex);
-	if (fcn->fcn_count == 0)
+	mutex_enter(&node->n_mutex);
+	if (node->n_fcn_count == 0)
 		(void) smb_fem_fcn_install(node);
-	fcn->fcn_count++;
-	list_insert_tail(&fcn->fcn_watchers, sr);
-	mutex_exit(&fcn->fcn_mutex);
+	node->n_fcn_count++;
+	mutex_exit(&node->n_mutex);
 }
 
 void
-smb_node_fcn_unsubscribe(smb_node_t *node, smb_request_t *sr)
+smb_node_fcn_unsubscribe(smb_node_t *node)
 {
-	smb_node_fcn_t		*fcn = &node->n_fcn;
 
-	mutex_enter(&fcn->fcn_mutex);
-	list_remove(&fcn->fcn_watchers, sr);
-	fcn->fcn_count--;
-	if (fcn->fcn_count == 0)
+	mutex_enter(&node->n_mutex);
+	node->n_fcn_count--;
+	if (node->n_fcn_count == 0)
 		smb_fem_fcn_uninstall(node);
-	mutex_exit(&fcn->fcn_mutex);
+	mutex_exit(&node->n_mutex);
 }
 
 void
 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
 {
+	smb_ofile_t	*of;
+
 	SMB_NODE_VALID(node);
 
-	smb_notify_event(node, action, name);
+	smb_llist_enter(&node->n_ofile_list, RW_READER);
+	of = smb_llist_head(&node->n_ofile_list);
+	while (of) {
+		/*
+		 * We'd rather deliver events only to ofiles that have
+		 * subscribed.  There's no explicit synchronization with
+		 * where this flag is set, but other actions cause this
+		 * value to reach visibility soon enough for events to
+		 * start arriving by the time we need them to start.
+		 * Once nc_subscribed is set, it stays set for the
+		 * life of the ofile.
+		 */
+		if (of->f_notify.nc_subscribed)
+			smb_notify_ofile(of, action, name);
+		of = smb_llist_next(&node->n_ofile_list, of);
+	}
+	smb_llist_exit(&node->n_ofile_list);
 
 	/*
-	 * These two events come as a pair:
-	 *   FILE_ACTION_RENAMED_OLD_NAME
-	 *   FILE_ACTION_RENAMED_NEW_NAME
-	 * Only do the parent notify for "new".
+	 * After changes that add or remove a name,
+	 * we know the directory attributes changed,
+	 * and we can tell the immediate parent.
 	 */
-	if (action == FILE_ACTION_RENAMED_OLD_NAME)
-		return;
-
-	smb_node_notify_parents(node);
-}
+	switch (action) {
+	case FILE_ACTION_ADDED:
+	case FILE_ACTION_REMOVED:
+	case FILE_ACTION_RENAMED_NEW_NAME:
+		/*
+		 * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally
+		 * omitted, because it's always followed by another
+		 * event with FILE_ACTION_RENAMED_NEW_NAME posted to
+		 * the same directory, and we only need/want one.
+		 */
+		if (node->n_dnode != NULL) {
+			smb_node_notify_change(node->n_dnode,
+			    FILE_ACTION_MODIFIED, node->od_name);
+		}
+		break;
+	}
 
-/*
- * smb_node_notify_parents
- *
- * Iterate up the directory tree notifying any parent
- * directories that are being watched for changes in
- * their sub directories.
- * Stop at the root node, which has a NULL parent node.
- */
-void
-smb_node_notify_parents(smb_node_t *dnode)
-{
-	smb_node_t *pnode;	/* parent */
-
-	SMB_NODE_VALID(dnode);
-	pnode = dnode->n_dnode;
-
-	while (pnode != NULL) {
-		SMB_NODE_VALID(pnode);
-		smb_notify_event(pnode, FILE_ACTION_SUBDIR_CHANGED, NULL);
-		/* cd .. */
-		dnode = pnode;
-		pnode = dnode->n_dnode;
-	}
+	/*
+	 * If we wanted to support recursive notify events
+	 * (where a notify call on some directory receives
+	 * events from all objects below that directory),
+	 * we might deliver _SUBDIR_CHANGED to all our
+	 * parents, grandparents etc, here.  However, we
+	 * don't currently subscribe to changes on all the
+	 * child (and grandchild) objects that would be
+	 * needed to make that work. It's prohibitively
+	 * expensive to do that, and support for recursive
+	 * notify is optional anyway, so don't bother.
+	 */
 }
 
 /*
@@ -1195,6 +1208,7 @@
 	node->n_magic = 0;
 	VERIFY(!list_link_active(&node->n_lnd));
 	VERIFY(node->n_lock_list.ll_count == 0);
+	VERIFY(node->n_wlock_list.ll_count == 0);
 	VERIFY(node->n_ofile_list.ll_count == 0);
 	VERIFY(node->n_oplock.ol_count == 0);
 	VERIFY(node->n_oplock.ol_xthread == NULL);
@@ -1221,9 +1235,8 @@
 	    offsetof(smb_ofile_t, f_nnd));
 	smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
 	    offsetof(smb_lock_t, l_lnd));
-	mutex_init(&node->n_fcn.fcn_mutex, NULL, MUTEX_DEFAULT, NULL);
-	list_create(&node->n_fcn.fcn_watchers, sizeof (smb_request_t),
-	    offsetof(smb_request_t, sr_ncr.nc_lnd));
+	smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t),
+	    offsetof(smb_lock_t, l_lnd));
 	cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
 	mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
 	list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t),
@@ -1249,9 +1262,8 @@
 	rw_destroy(&node->n_lock);
 	cv_destroy(&node->n_oplock.ol_cv);
 	mutex_destroy(&node->n_oplock.ol_mutex);
-	list_destroy(&node->n_fcn.fcn_watchers);
-	mutex_destroy(&node->n_fcn.fcn_mutex);
 	smb_llist_destructor(&node->n_lock_list);
+	smb_llist_destructor(&node->n_wlock_list);
 	smb_llist_destructor(&node->n_ofile_list);
 	list_destroy(&node->n_oplock.ol_grants);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_notify.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_notify.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -85,247 +85,474 @@
  * FILE_ACTION_ADDED_STREAM     0x00000006
  * FILE_ACTION_REMOVED_STREAM   0x00000007
  * FILE_ACTION_MODIFIED_STREAM  0x00000008
+ *
+ * The internal interface between SMB1 and/or SMB2 protocol handlers
+ * and this module has some sophistication to allow for:
+ * (1) code sharing between SMB1 and SMB2(+)
+ * (2) efficient handling of non-blocking scenarios
+ * (3) long blocking calls without tying up a thread
+ *
+ * The interface has three calls (like a three act play)
+ *
+ * smb_notify_act1:
+ *	Validate parameters, setup ofile buffer.
+ *	If data already available, return it, all done.
+ * 	(In the "all done" case, skip act2 & act3.)
+ * 	If no data available, return a special error
+ *	("STATUS_PENDING") to tell the caller they must
+ *	proceed with calls to act2 & act3.
+ *
+ * smb_notify_act2:
+ *	Arrange wakeup after event delivery or cancellation.
+ *	Return leaving the SR with no worker thread.
+ *
+ * smb_notify_act3:
+ *	New taskq work thread runs this after the wakeup
+ *	or cancellation arranged in act2 happens.  This
+ *	returns the notification data and retires the SR.
+ *
+ * In the SMB2 notify handler, we call act1 during the initial
+ * synchronous handling of the request.  If that returns anything
+ * other than STATUS_PENDING, that request is fully complete.
+ * If act1 returns STATUS_PENDING, SMB2 calls act2 as it's
+ * "go async" handler, which arranges to call act3 later.
+ *
+ * In the SMB1 notify handler there is not separate sync. & async
+ * handler so act1 and (if necessary) act2 are both called during
+ * the initial handling of the request.
+ *
+ * About notify event buffering:
+ *
+ * An important (and poorly documented) feature of SMB notify is
+ * that once a notify call has happened on a given directory handle,
+ * the system CONTINUES to post events to the notify event buffer
+ * for the handle, even when SMB notify calls are NOT running.
+ * When the client next comes back with a notify call, we return
+ * any events that were posted while they were "away".  This is
+ * how clients track directory changes without missing events.
+ *
+ * About simultaneous notify calls:
+ *
+ * Note that SMB "notify" calls are destructive to events, much like
+ * reading data from a pipe.  It therefore makes little sense to
+ * allow multiple simultaneous callers.  However, we permit it
+ * (like Windows does) as follows:  When multiple notify calls
+ * are waiting for events, the next event wakes them all, and
+ * only the last one out clears the event buffer.  They all get
+ * whatever events are pending at the time they woke up.
+ *
+ * About NT_STATUS_NOTIFY_ENUM_DIR
+ *
+ * One more caution about NT_STATUS_NOTIFY_ENUM_DIR:  Some clients
+ * are stupid about re-reading the directory almost continuously when
+ * there are changes happening in the directory.  We want to bound
+ * the rate of such directory re-reading, so before returning an
+ * NT_STATUS_NOTIFY_ENUM_DIR, we delay just a little.  The length
+ * of the delay can be adjusted via smb_notify_enum_dir_delay,
+ * though it's not expected that should need to be changed.
  */
 
 #include <smbsrv/smb_kproto.h>
 #include <sys/sdt.h>
 
-static void smb_notify_sr(smb_request_t *, uint_t, const char *);
-static uint32_t smb_notify_encode_action(struct smb_request *,
-	mbuf_chain_t *, uint32_t, char *);
+/*
+ * Length of the short delay we impose before returning
+ * NT_STATUS_NOTIFY_ENUM_DIR (See above)
+ */
+int smb_notify_enum_dir_delay = 100; /* mSec. */
 
+static uint32_t smb_notify_get_events(smb_request_t *);
+static void smb_notify_cancel(smb_request_t *);
+static void smb_notify_wakeup(smb_request_t *);
+static void smb_notify_dispatch2(smb_request_t *);
+static void smb_notify_encode_action(smb_ofile_t *,
+	uint32_t, const char *);
+
+
+/*
+ * smb_notify_act1()
+ *
+ * Check for events and consume, non-blocking.
+ * Special return STATUS_PENDING means:
+ * No events; caller must call "act2" next.
+ *
+ * See overall design notes, top of file.
+ */
 uint32_t
-smb_notify_common(smb_request_t *sr, mbuf_chain_t *mbc,
-	uint32_t CompletionFilter)
+smb_notify_act1(smb_request_t *sr, uint32_t buflen, uint32_t filter)
 {
-	smb_notify_change_req_t *nc;
+	smb_ofile_t	*of;
 	smb_node_t	*node;
+	smb_notify_t	*nc;
+	uint32_t	status;
+
+	/*
+	 * Validate parameters
+	 */
+	if ((of = sr->fid_ofile) == NULL)
+		return (NT_STATUS_INVALID_HANDLE);
+	nc = &of->f_notify;
+	node = of->f_node;
+	if (node == NULL || !smb_node_is_dir(node)) {
+		/* Notify change is only valid on directories. */
+		return (NT_STATUS_INVALID_PARAMETER);
+	}
+
+	mutex_enter(&of->f_mutex);
+
+	/*
+	 * On the first FCN call with this ofile, subscribe to
+	 * events on the node.  The corresponding unsubscribe
+	 * happens in smb_ofile_delete().
+	 */
+	if (nc->nc_subscribed == B_FALSE) {
+		nc->nc_subscribed = B_TRUE;
+		smb_node_fcn_subscribe(node);
+		/* In case this happened before we subscribed. */
+		if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
+			nc->nc_events |= FILE_NOTIFY_CHANGE_EV_DELETE;
+		}
+		/*
+		 * Windows only lets you set these on the first call,
+		 * so we may as well do the same.
+		 */
+		nc->nc_buffer.max_bytes = buflen;
+		nc->nc_filter = filter;
+	}
+	/*
+	 * If we already have events, consume them.
+	 */
+	sr->raw_data.max_bytes = buflen;
+	if (nc->nc_events != 0) {
+		status = smb_notify_get_events(sr);
+	} else {
+		/* Caller will come back for act2 */
+		status = NT_STATUS_PENDING;
+	}
+
+	mutex_exit(&of->f_mutex);
+
+	/*
+	 * See: About NT_STATUS_NOTIFY_ENUM_DIR (above)
+	 */
+	if (status == NT_STATUS_NOTIFY_ENUM_DIR &&
+	    smb_notify_enum_dir_delay > 0)
+		delay(MSEC_TO_TICK(smb_notify_enum_dir_delay));
+
+	return (status);
+}
+
+/*
+ * smb_notify_act2()
+ *
+ * Prepare to wait for events after act1 found that none were pending.
+ * Assume the wait may be for a very long time.  (hours, days...)
+ * Special return STATUS_PENDING means the SR will later be
+ * scheduled again on a new worker thread, and this thread
+ * MUST NOT touch it any longer (return SDRC_SR_KEPT).
+ *
+ * See overall design notes, top of file.
+ */
+uint32_t
+smb_notify_act2(smb_request_t *sr)
+{
+	smb_ofile_t	*of;
+	smb_notify_t	*nc;
 	uint32_t	status;
 
-	if (sr->fid_ofile == NULL)
+	/*
+	 * Sanity checks.
+	 */
+	if ((of = sr->fid_ofile) == NULL)
 		return (NT_STATUS_INVALID_HANDLE);
+	nc = &of->f_notify;
+
+	mutex_enter(&of->f_mutex);
+
+	/*
+	 * Prepare for a potentially long wait for events.
+	 * Normally transition from ACTIVE to WAITING_FCN1.
+	 *
+	 * Note we hold both of->f_mutex, sr->sr_mutex here,
+	 * taken in that order.
+	 */
+	mutex_enter(&sr->sr_mutex);
+	switch (sr->sr_state) {
+	case SMB_REQ_STATE_ACTIVE:
+		/*
+		 * This sr has no worker thread until smb_notify_act3
+		 * or smb_notify_cancel (later, via taskq_dispatch).
+		 */
+		sr->sr_state = SMB_REQ_STATE_WAITING_FCN1;
+		sr->cancel_method = smb_notify_cancel;
+		sr->sr_worker = NULL;
+		list_insert_tail(&nc->nc_waiters, sr);
+		status = NT_STATUS_PENDING;
+		break;
+
+	case SMB_REQ_STATE_CANCELLED:
+		status = NT_STATUS_CANCELLED;
+		break;
+	default:
+		status = NT_STATUS_INTERNAL_ERROR;
+		break;
+	}
+	mutex_exit(&sr->sr_mutex);
+
+	/*
+	 * In case we missed any events before setting
+	 * state FCN1, schedule our own wakeup.
+	 */
+	if (status == NT_STATUS_PENDING && nc->nc_events != 0) {
+		smb_notify_wakeup(sr);
+	}
+
+	mutex_exit(&of->f_mutex);
+
+	/* Note: Never NT_STATUS_NOTIFY_ENUM_DIR here. */
+	ASSERT(status != NT_STATUS_NOTIFY_ENUM_DIR);
+
+	return (status);
+}
+
+/*
+ * smb_notify_act3()
+ *
+ * This runs via the 2nd taskq_dispatch call, after we've either
+ * seen a change notify event, or the request has been cancelled.
+ * Complete it here.  This returns to SMB1 or SMB2 code to send
+ * the response and free the request.
+ *
+ * See overall design notes, top of file.
+ */
+uint32_t
+smb_notify_act3(smb_request_t *sr)
+{
+	smb_ofile_t	*of;
+	smb_notify_t	*nc;
+	uint32_t	status;
+
+	of = sr->fid_ofile;
+	ASSERT(of != NULL);
+	nc = &of->f_notify;
+
+	mutex_enter(&of->f_mutex);
 
-	node = sr->fid_ofile->f_node;
-	if (node == NULL || !smb_node_is_dir(node)) {
+	mutex_enter(&sr->sr_mutex);
+	ASSERT3P(sr->sr_worker, ==, NULL);
+	sr->sr_worker = curthread;
+	sr->cancel_method = NULL;
+
+	list_remove(&nc->nc_waiters, sr);
+
+	switch (sr->sr_state) {
+	case SMB_REQ_STATE_WAITING_FCN2:
+		/*
+		 * Got smb_notify_wakeup.
+		 */
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+		status = 0;
+		break;
+
+	case SMB_REQ_STATE_CANCEL_PENDING:
 		/*
-		 * Notify change is only valid on directories.
+		 * Got smb_notify_cancel
 		 */
-		return (NT_STATUS_INVALID_PARAMETER);
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
+		status = NT_STATUS_CANCELLED;
+		break;
+	default:
+		status = NT_STATUS_INTERNAL_ERROR;
+		break;
+	}
+	mutex_exit(&sr->sr_mutex);
+
+	if (status == 0)
+		status = smb_notify_get_events(sr);
+
+	mutex_exit(&of->f_mutex);
+
+	/*
+	 * See: About NT_STATUS_NOTIFY_ENUM_DIR (above)
+	 */
+	if (status == NT_STATUS_NOTIFY_ENUM_DIR &&
+	    smb_notify_enum_dir_delay > 0)
+		delay(MSEC_TO_TICK(smb_notify_enum_dir_delay));
+
+	return (status);
+}
+
+static uint32_t
+smb_notify_get_events(smb_request_t *sr)
+{
+	smb_ofile_t	*of;
+	smb_notify_t	*nc;
+	uint32_t	status;
+	int		len;
+
+	of = sr->fid_ofile;
+	ASSERT(of != NULL);
+	ASSERT(MUTEX_HELD(&of->f_mutex));
+	nc = &of->f_notify;
+
+	DTRACE_PROBE2(notify__get__events,
+	    smb_request_t, sr,
+	    uint32_t, nc->nc_events);
+
+	/*
+	 * Special events which override other events
+	 */
+	if (nc->nc_events & FILE_NOTIFY_CHANGE_EV_CLOSED) {
+		status = NT_STATUS_NOTIFY_CLEANUP;
+		goto out;
+	}
+	if (nc->nc_events & FILE_NOTIFY_CHANGE_EV_DELETE) {
+		status = NT_STATUS_DELETE_PENDING;
+		goto out;
+	}
+	if (nc->nc_events & FILE_NOTIFY_CHANGE_EV_SUBDIR) {
+		status = NT_STATUS_NOTIFY_ENUM_DIR;
+		goto out;
+	}
+	if (nc->nc_events & FILE_NOTIFY_CHANGE_EV_OVERFLOW) {
+		status = NT_STATUS_NOTIFY_ENUM_DIR;
+		goto out;
 	}
 
 	/*
-	 * Prepare to receive event data.
-	 */
-	nc = &sr->sr_ncr;
-	nc->nc_flags = CompletionFilter;
-	ASSERT(nc->nc_action == 0);
-	ASSERT(nc->nc_fname == NULL);
-	nc->nc_fname = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
-
-	/*
-	 * Subscribe to events on this node.
-	 */
-	smb_node_fcn_subscribe(node, sr);
-
-	/*
-	 * Wait for subscribed events to arrive.
-	 * Expect SMB_REQ_STATE_EVENT_OCCURRED
-	 * or SMB_REQ_STATE_CANCELED when signaled.
-	 * Note it's possible (though rare) to already
-	 * have SMB_REQ_STATE_CANCELED here.
+	 * Normal events (FILE_NOTIFY_VALID_MASK)
+	 *
+	 * At this point there should be some, or else
+	 * some sort of bug woke us up for nothing.
 	 */
-	mutex_enter(&sr->sr_mutex);
-	if (sr->sr_state == SMB_REQ_STATE_ACTIVE)
-		sr->sr_state = SMB_REQ_STATE_WAITING_EVENT;
-	while (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT) {
-		cv_wait(&nc->nc_cv, &sr->sr_mutex);
-	}
-	if (sr->sr_state == SMB_REQ_STATE_EVENT_OCCURRED)
-		sr->sr_state = SMB_REQ_STATE_ACTIVE;
-	mutex_exit(&sr->sr_mutex);
-
-	/*
-	 * Unsubscribe from events on this node.
-	 */
-	smb_node_fcn_unsubscribe(node, sr);
-
-	/*
-	 * Why did we wake up?
-	 */
-	switch (sr->sr_state) {
-	case SMB_REQ_STATE_ACTIVE:
-		break;
-	case SMB_REQ_STATE_CANCELED:
-		status = NT_STATUS_CANCELLED;
-		goto out;
-	default:
+	if ((nc->nc_events & FILE_NOTIFY_VALID_MASK) == 0) {
 		status = NT_STATUS_INTERNAL_ERROR;
 		goto out;
 	}
 
 	/*
-	 * We have SMB_REQ_STATE_ACTIVE.
-	 *
-	 * If we have event data, marshall it now, else just
-	 * say "many things changed". Note that when we get
-	 * action FILE_ACTION_SUBDIR_CHANGED, we don't have
-	 * any event details and only know that some subdir
-	 * changed, so just report "many things changed".
+	 * Many Windows clients call change notify with a
+	 * zero-length buffer, expecting all events to be
+	 * reported as _ENUM_DIR.  Testing max_bytes here
+	 * because ROOM_FOR check below says "yes" if both
+	 * max_bytes and the amount we ask for are zero.
 	 */
-	switch (nc->nc_action) {
+	if (nc->nc_buffer.max_bytes <= 0) {
+		status = NT_STATUS_NOTIFY_ENUM_DIR;
+		goto out;
+	}
 
-	case FILE_ACTION_ADDED:
-	case FILE_ACTION_REMOVED:
-	case FILE_ACTION_MODIFIED:
-	case FILE_ACTION_RENAMED_OLD_NAME:
-	case FILE_ACTION_RENAMED_NEW_NAME:
-	case FILE_ACTION_ADDED_STREAM:
-	case FILE_ACTION_REMOVED_STREAM:
-	case FILE_ACTION_MODIFIED_STREAM:
-		/*
-		 * Build the reply
-		 */
-		status = smb_notify_encode_action(sr, mbc,
-		    nc->nc_action, nc->nc_fname);
-		break;
-
-	case FILE_ACTION_SUBDIR_CHANGED:
-		status = NT_STATUS_NOTIFY_ENUM_DIR;
-		break;
-
-	case FILE_ACTION_DELETE_PENDING:
-		status = NT_STATUS_DELETE_PENDING;
-		break;
-
-	default:
-		ASSERT(0);
+	/*
+	 * Client gave us a non-zero output buffer, and
+	 * there was no overflow event (checked above)
+	 * so there should be some event data.
+	 */
+	if ((len = nc->nc_buffer.chain_offset) <= 0) {
 		status = NT_STATUS_INTERNAL_ERROR;
-		break;
+		goto out;
 	}
 
+	/*
+	 * If the current SR has a smaller output buffer
+	 * then what was setup by some previous notify,
+	 * we could have more data than will fit.
+	 */
+	if (!MBC_ROOM_FOR(&sr->raw_data, len)) {
+		/* Would overflow caller's buffer. */
+		status = NT_STATUS_NOTIFY_ENUM_DIR;
+		goto out;
+	}
+
+	/*
+	 * Copy the event data to sr->raw_data.  In the copy,
+	 * zap the NextEntryOffset in the last entry, and
+	 * trim any extra bytes at the tail.
+	 */
+	(void) smb_mbc_copy(&sr->raw_data, &nc->nc_buffer, 0, len);
+	(void) smb_mbc_poke(&sr->raw_data, nc->nc_last_off, "l", 0);
+	smb_mbuf_trim(sr->raw_data.chain, len);
+	status = 0;
+
 out:
-	kmem_free(nc->nc_fname, MAXNAMELEN);
-	nc->nc_fname = NULL;
+	/*
+	 * If there are no other SRs waiting on this ofile,
+	 * mark all events consumed, except for those that
+	 * remain until the ofile is closed.  That means
+	 * clear all bits EXCEPT: _EV_CLOSED, _EV_DELETE
+	 *
+	 * If there are other waiters (rare) all will get
+	 * the currently pending events, and then the
+	 * the last one out will clear the events.
+	 */
+	if (list_is_empty(&nc->nc_waiters)) {
+		nc->nc_buffer.chain_offset = 0;
+		nc->nc_events &= (FILE_NOTIFY_CHANGE_EV_CLOSED |
+		    FILE_NOTIFY_CHANGE_EV_DELETE);
+	}
+
 	return (status);
 }
 
 /*
- * Encode a FILE_NOTIFY_INFORMATION struct.
- *
- * We only ever put one of these in a response, so this
- * does not bother handling appending additional ones.
+ * Called by common code after a transition from
+ * state WAITING_FCN1 to state CANCEL_PENDING.
  */
-static uint32_t
-smb_notify_encode_action(struct smb_request *sr, mbuf_chain_t *mbc,
-	uint32_t action, char *fname)
+static void
+smb_notify_cancel(smb_request_t *sr)
 {
-	uint32_t namelen;
-
-	ASSERT(FILE_ACTION_ADDED <= action &&
-	    action <= FILE_ACTION_MODIFIED_STREAM);
-
-	if (fname == NULL)
-		return (NT_STATUS_INTERNAL_ERROR);
-	namelen = smb_wcequiv_strlen(fname);
-	if (namelen == 0)
-		return (NT_STATUS_INTERNAL_ERROR);
-
-	if (smb_mbc_encodef(mbc, "%lllU", sr,
-	    0, /* NextEntryOffset */
-	    action, namelen, fname))
-		return (NT_STATUS_NOTIFY_ENUM_DIR);
-
-	return (0);
+	ASSERT3U(sr->sr_state, ==, SMB_REQ_STATE_CANCEL_PENDING);
+	smb_notify_dispatch2(sr);
 }
 
 /*
- * smb_notify_file_closed
- *
- * Cancel any change-notify calls on this open file.
+ * Called after ofile event delivery to take a waiting smb request
+ * from state FCN1 to state FCN2.  This may be called many times
+ * (as events are delivered) but it must (exactly once) schedule
+ * the taskq job to run smb_notify_act3().  Only the event that
+ * takes us from state FCN1 to FCN2 schedules the taskq job.
  */
-void
-smb_notify_file_closed(struct smb_ofile *of)
+static void
+smb_notify_wakeup(smb_request_t *sr)
 {
-	smb_session_t	*ses;
-	smb_request_t	*sr;
-	smb_slist_t	*list;
-
-	SMB_OFILE_VALID(of);
-	ses = of->f_session;
-	SMB_SESSION_VALID(ses);
-	list = &ses->s_req_list;
+	boolean_t do_disp = B_FALSE;
 
-	smb_slist_enter(list);
+	SMB_REQ_VALID(sr);
 
-	sr = smb_slist_head(list);
-	while (sr) {
-		SMB_REQ_VALID(sr);
-		if (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT &&
-		    sr->fid_ofile == of) {
-			smb_request_cancel(sr);
-		}
-		sr = smb_slist_next(list, sr);
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state == SMB_REQ_STATE_WAITING_FCN1) {
+		sr->sr_state = SMB_REQ_STATE_WAITING_FCN2;
+		do_disp = B_TRUE;
 	}
+	mutex_exit(&sr->sr_mutex);
 
-	smb_slist_exit(list);
+	if (do_disp) {
+		smb_notify_dispatch2(sr);
+	}
 }
 
-
 /*
- * smb_notify_event
- *
- * Post an event to the watchers on a given node.
- *
- * This makes one exception for RENAME, where we expect a
- * pair of events for the {old,new} directory element names.
- * This only delivers an event for the "new" name.
- *
- * The event delivery mechanism does not implement delivery of
- * multiple events for one "NT Notify" call.  One could do that,
- * but modern clients don't actually use the event data.  They
- * set a max. received data size of zero, which means we discard
- * the data and send the special "lots changed" error instead.
- * Given that, there's not really any point in implementing the
- * delivery of multiple events.  In fact, we don't even need to
- * implement single event delivery, but do so for completeness,
- * for debug convenience, and to be nice to older clients that
- * may actually want some event data instead of the error.
- *
- * Given that we only deliver a single event for an "NT Notify"
- * caller, we want to deliver the "new" name event.  (The "old"
- * name event is less important, even ignored by some clients.)
- * Since we know these are delivered in pairs, we can simply
- * discard the "old" name event, knowing that the "new" name
- * event will be delivered immediately afterwards.
- *
- * So, why do event sources post the "old name" event at all?
- * (1) For debugging, so we see both {old,new} names here.
- * (2) If in the future someone decides to implement the
- * delivery of both {old,new} events, the changes can be
- * mostly isolated to this file.
+ * smb_notify_dispatch2()
+ * Schedule a 2nd taskq call to finish up a change notify request;
+ * (smb_notify_act3) either completing it or cancelling it.
  */
-void
-smb_notify_event(smb_node_t *node, uint_t action, const char *name)
+static void
+smb_notify_dispatch2(smb_request_t *sr)
 {
-	smb_request_t	*sr;
-	smb_node_fcn_t	*fcn;
-
-	SMB_NODE_VALID(node);
-	fcn = &node->n_fcn;
+	void (*tq_func)(void *);
 
-	if (action == FILE_ACTION_RENAMED_OLD_NAME)
-		return; /* see above */
-
-	mutex_enter(&fcn->fcn_mutex);
+	/*
+	 * Both of these call smb_notify_act3(), returning
+	 * to version-specific code to send the response.
+	 */
+	if (sr->session->dialect >= SMB_VERS_2_BASE)
+		tq_func = smb2_change_notify_finish;
+	else
+		tq_func = smb_nt_transact_notify_finish;
 
-	sr = list_head(&fcn->fcn_watchers);
-	while (sr) {
-		smb_notify_sr(sr, action, name);
-		sr = list_next(&fcn->fcn_watchers, sr);
-	}
+	(void) taskq_dispatch(sr->sr_server->sv_worker_pool,
+	    tq_func, sr, TQ_SLEEP);
+}
 
-	mutex_exit(&fcn->fcn_mutex);
-}
 
 /*
  * What completion filter (masks) apply to each of the
@@ -371,52 +598,158 @@
 	FILE_NOTIFY_CHANGE_STREAM_WRITE,
 
 	/* FILE_ACTION_SUBDIR_CHANGED */
-	NODE_FLAGS_WATCH_TREE,
+	FILE_NOTIFY_CHANGE_EV_SUBDIR,
 
 	/* FILE_ACTION_DELETE_PENDING */
-	NODE_FLAGS_WATCH_TREE |
-	FILE_NOTIFY_VALID_MASK,
+	FILE_NOTIFY_CHANGE_EV_DELETE,
+
+	/* FILE_ACTION_HANDLE_CLOSED */
+	FILE_NOTIFY_CHANGE_EV_CLOSED,
 };
 static const int smb_notify_action_nelm =
 	sizeof (smb_notify_action_mask) /
 	sizeof (smb_notify_action_mask[0]);
 
 /*
- * smb_notify_sr
+ * smb_notify_ofile
  *
- * Post an event to an smb request waiting on some node.
- *
- * Note that node->fcn.mutex is held.  This implies a
- * lock order: node->fcn.mutex, then sr_mutex
+ * Post an event to the change notify buffer for this ofile,
+ * subject to the mask that selects subscribed event types.
+ * If an SR is waiting for events and we've delivered some,
+ * wake the SR.
  */
-static void
-smb_notify_sr(smb_request_t *sr, uint_t action, const char *name)
+void
+smb_notify_ofile(smb_ofile_t *of, uint_t action, const char *name)
 {
-	smb_notify_change_req_t	*ncr;
-	uint32_t	mask;
+	smb_notify_t	*nc;
+	smb_request_t	*sr;
+	uint32_t	filter, events;
+
+	SMB_OFILE_VALID(of);
+
+	mutex_enter(&of->f_mutex);
+	nc = &of->f_notify;
 
-	SMB_REQ_VALID(sr);
-	ncr = &sr->sr_ncr;
+	/*
+	 * Compute the filter & event bits for this action,
+	 * which determine whether we'll post the event.
+	 * Note: always sensitive to: delete, closed.
+	 */
+	filter = nc->nc_filter |
+	    FILE_NOTIFY_CHANGE_EV_DELETE |
+	    FILE_NOTIFY_CHANGE_EV_CLOSED;
+	VERIFY(action < smb_notify_action_nelm);
+	events = smb_notify_action_mask[action];
+	if ((filter & events) == 0)
+		goto unlock_out;
 
 	/*
-	 * Compute the completion filter mask bits for which
-	 * we will signal waiting notify requests.
+	 * OK, we're going to post this event.
 	 */
-	VERIFY(action < smb_notify_action_nelm);
-	mask = smb_notify_action_mask[action];
+	switch (action) {
+	case FILE_ACTION_ADDED:
+	case FILE_ACTION_REMOVED:
+	case FILE_ACTION_MODIFIED:
+	case FILE_ACTION_RENAMED_OLD_NAME:
+	case FILE_ACTION_RENAMED_NEW_NAME:
+	case FILE_ACTION_ADDED_STREAM:
+	case FILE_ACTION_REMOVED_STREAM:
+	case FILE_ACTION_MODIFIED_STREAM:
+		/*
+		 * Append this event to the buffer.
+		 * Also keep track of events seen.
+		 */
+		smb_notify_encode_action(of, action, name);
+		nc->nc_events |= events;
+		break;
 
-	mutex_enter(&sr->sr_mutex);
-	if (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT &&
-	    (ncr->nc_flags & mask) != 0) {
-		sr->sr_state = SMB_REQ_STATE_EVENT_OCCURRED;
+	case FILE_ACTION_SUBDIR_CHANGED:
+	case FILE_ACTION_DELETE_PENDING:
+	case FILE_ACTION_HANDLE_CLOSED:
 		/*
-		 * Save event data in the sr_ncr field so the
-		 * reply handler can return it.
+		 * These are "internal" events, and therefore
+		 * are not appended to the response buffer.
+		 * Just record the event flags and wakeup.
 		 */
-		ncr->nc_action = action;
-		if (name != NULL)
-			(void) strlcpy(ncr->nc_fname, name, MAXNAMELEN);
-		cv_signal(&ncr->nc_cv);
+		nc->nc_events |= events;
+		break;
+
+	default:
+		ASSERT(0);	/* bogus action */
+		break;
+	}
+
+	sr = list_head(&nc->nc_waiters);
+	while (sr != NULL) {
+		smb_notify_wakeup(sr);
+		sr = list_next(&nc->nc_waiters, sr);
 	}
-	mutex_exit(&sr->sr_mutex);
+
+unlock_out:
+	mutex_exit(&of->f_mutex);
 }
+
+/*
+ * Encode a FILE_NOTIFY_INFORMATION struct.
+ */
+static void
+smb_notify_encode_action(smb_ofile_t *of,
+    uint32_t action, const char *fname)
+{
+	smb_notify_t *nc = &of->f_notify;
+	mbuf_chain_t *mbc;
+	uint32_t namelen, totlen;
+
+	ASSERT(nc != NULL);
+	ASSERT(FILE_ACTION_ADDED <= action &&
+	    action <= FILE_ACTION_MODIFIED_STREAM);
+	ASSERT(fname != NULL);
+	ASSERT(MUTEX_HELD(&of->f_mutex));
+
+	/* Once we've run out of room, stop trying to append. */
+	if ((nc->nc_events & FILE_NOTIFY_CHANGE_EV_OVERFLOW) != 0)
+		return;
+
+	if (fname == NULL)
+		return;
+	namelen = smb_wcequiv_strlen(fname);
+	if (namelen == 0)
+		return;
+
+	/*
+	 * Layout is: 3 DWORDS, Unicode string, pad(4).
+	 */
+	mbc = &nc->nc_buffer;
+	totlen = (12 + namelen + 3) & ~3;
+	if (MBC_ROOM_FOR(mbc, totlen) == 0) {
+		nc->nc_events |= FILE_NOTIFY_CHANGE_EV_OVERFLOW;
+		return;
+	}
+
+	/*
+	 * Keep track of where this entry starts (nc_last_off)
+	 * because after we put all entries, we need to zap
+	 * the NextEntryOffset field in the last one.
+	 */
+	nc->nc_last_off = mbc->chain_offset;
+
+	/*
+	 * Encode this entry, then 4-byte alignment padding.
+	 *
+	 * Note that smb_mbc_encodef with a "U" code puts a
+	 * Unicode string with a null termination.  We don't
+	 * want a null, but do want alignment padding.  We
+	 * get that by encoding with "U.." at the end of the
+	 * encoding string, which gets us two bytes for the
+	 * Unicode NULL, and two more zeros for the "..".
+	 * We then "back up" the chain_offset (finger) so it's
+	 * correctly 4-byte aligned.  We will sometimes have
+	 * written a couple more bytes than needed, but we'll
+	 * just overwrite those with the next entry.  At the
+	 * end, we trim the mbuf chain to the correct length.
+	 */
+	(void) smb_mbc_encodef(mbc, "lllU..",
+	    totlen, /* NextEntryOffset */
+	    action, namelen, fname);
+	mbc->chain_offset = nc->nc_last_off + totlen;
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
+ *
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -57,11 +58,19 @@
 	DTRACE_SMB_1(op__NtCancel__done, smb_request_t *, sr);
 }
 
+/*
+ * Dispatch handler for SMB_COM_NT_CANCEL.
+ * Note that Cancel does NOT get a response.
+ *
+ * SMB NT Cancel has an inherent race with the request being
+ * cancelled.  See comments at smb_request_cancel().
+ */
 smb_sdrc_t
 smb_com_nt_cancel(smb_request_t *sr)
 {
 	struct smb_request *req;
 	struct smb_session *session;
+	int cnt = 0;
 
 	session = sr->session;
 
@@ -75,10 +84,30 @@
 		    (req->smb_tid == sr->smb_tid) &&
 		    (req->smb_mid == sr->smb_mid)) {
 			smb_request_cancel(req);
+			cnt++;
 		}
 		req = smb_slist_next(&session->s_req_list, req);
 	}
+	if (cnt != 1) {
+		DTRACE_PROBE2(smb__ntcancel__error,
+		    uint16_t, sr->smb_mid, int, cnt);
+	}
 	smb_slist_exit(&session->s_req_list);
 
 	return (SDRC_NO_REPLY);
 }
+
+/*
+ * This handles an SMB_COM_NT_CANCEL request when seen in the reader.
+ * (See smb1sr_newrq)  Handle this immediately, rather than
+ * going through the normal taskq dispatch mechanism.
+ * Note that Cancel does NOT get a response.
+ */
+int
+smb1sr_newrq_cancel(smb_request_t *sr)
+{
+	(void) smb_pre_nt_cancel(sr);
+	(void) smb_com_nt_cancel(sr);
+	smb_post_nt_cancel(sr);
+	return (0);
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -58,15 +58,6 @@
 #include <smbsrv/smb_kproto.h>
 
 /*
- * We add this flag to the CompletionFilter (see above) when the
- * client sets WatchTree.  Must not overlap FILE_NOTIFY_VALID_MASK.
- */
-#define	NODE_FLAGS_WATCH_TREE		0x10000000
-#if (NODE_FLAGS_WATCH_TREE & FILE_NOTIFY_VALID_MASK)
-#error "NODE_FLAGS_WATCH_TREE"
-#endif
-
-/*
  * smb_nt_transact_notify_change
  *
  * Handle and SMB NT transact NOTIFY CHANGE request.
@@ -82,38 +73,168 @@
 smb_sdrc_t
 smb_nt_transact_notify_change(smb_request_t *sr, struct smb_xa *xa)
 {
+	mbuf_chain_t		tmp_mbc;
+	uint32_t		oBufSize;
 	uint32_t		CompletionFilter;
 	unsigned char		WatchTree;
 	uint32_t		status;
-	hrtime_t		t1, t2;
 
 	if (smb_mbc_decodef(&xa->req_setup_mb, "lwb",
 	    &CompletionFilter, &sr->smb_fid, &WatchTree) != 0) {
 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
 		return (SDRC_ERROR);
 	}
-	CompletionFilter &= FILE_NOTIFY_VALID_MASK;
-	if (WatchTree)
-		CompletionFilter |= NODE_FLAGS_WATCH_TREE;
 
 	smbsr_lookup_file(sr);
+	if (sr->fid_ofile == NULL) {
+		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
+		return (SDRC_ERROR);
+	}
 
-	t1 = gethrtime();
-	status = smb_notify_common(sr, &xa->rep_data_mb, CompletionFilter);
-	t2 = gethrtime();
+	oBufSize = xa->rep_param_mb.max_bytes;
+	CompletionFilter &= FILE_NOTIFY_VALID_MASK;
+	if (WatchTree)
+		CompletionFilter |= FILE_NOTIFY_CHANGE_EV_SUBDIR;
 
 	/*
-	 * We don't want to include the (indefinite) wait time of the
-	 * smb_notify_common() call in the SMB1 transact latency.
-	 * The easiest way to do that, without adding special case
-	 * logic to the common SMB1 dispatch handler is to adjust the
-	 * start time of this request to effectively subtract out the
-	 * time we were blocked in smb_notify_common().
+	 * Check for events and consume, non-blocking.
+	 * Special return STATUS_PENDING means:
+	 *   No events; caller must call "act2" next.
+	 */
+	status = smb_notify_act1(sr, oBufSize, CompletionFilter);
+	if (status == NT_STATUS_PENDING) {
+		status = smb_notify_act2(sr);
+		if (status == NT_STATUS_PENDING) {
+			/* See: smb_nt_transact_notify_finish */
+			return (SDRC_SR_KEPT);
+		}
+		/* else: some other error, or even success */
+	}
+
+	/*
+	 * SMB1 expects an empty trans response after the
+	 * FID we're watching is closed.
 	 */
-	sr->sr_time_start += (t2 - t1);
+	if (status == NT_STATUS_NOTIFY_CLEANUP) {
+		status = 0;
+		MBC_FLUSH(&sr->raw_data);
+	}
 
-	if (status != 0)
-		smbsr_error(sr, status, 0, 0);
+	if (status != 0) {
+		smbsr_status(sr, status, 0, 0);
+		if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
+			return (SDRC_ERROR);
+		/* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
+	}
+
+	/*
+	 * The nt_trans call expects the output in rep_param_mb,
+	 * but our common code puts it in raw_data.  Move it
+	 * where the caller expects it via swaping the two,
+	 * which lets the normal cleanup take care of both.
+	 */
+	tmp_mbc = xa->rep_param_mb;
+	xa->rep_param_mb = sr->raw_data;
+	sr->raw_data = tmp_mbc;
 
 	return (SDRC_SUCCESS);
 }
+
+/*
+ * This is called via taskq_dispatch in smb_notify.c
+ * to finish up an NT transact notify change request.
+ */
+void
+smb_nt_transact_notify_finish(void *arg)
+{
+	smb_request_t	*sr = arg;
+	struct smb_xa	*xa;
+	smb_disp_stats_t *sds;
+	int		total_bytes, n_setup, n_param, n_data;
+	int		param_off, param_pad, data_off, data_pad;
+	uint32_t	status;
+
+	SMB_REQ_VALID(sr);
+
+	/*
+	 * Common part of notify, puts data in sr->raw_data
+	 */
+	status = smb_notify_act3(sr);
+
+	/*
+	 * SMB1 expects an empty trans response after the
+	 * FID we're watching is closed.
+	 */
+	if (status == NT_STATUS_NOTIFY_CLEANUP) {
+		status = 0;
+		MBC_FLUSH(&sr->raw_data);
+	}
+
+	if (status != 0) {
+		smbsr_status(sr, status, 0, 0);
+		if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) {
+			(void) smb_mbc_encodef(&sr->reply, "bwbw",
+			    (short)0, 0L, (short)0, 0L);
+			goto sendit;
+		}
+		/* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
+	}
+
+	/*
+	 * setup the NT transact reply
+	 *
+	 * Note that this is a copy/paste of code from
+	 * smb_nt_trans_dispatch(), with minor changes.
+	 * Intentionally keeping this similar to the
+	 * original rather than hand-optimizing.
+	 *
+	 * The "setup" and "data" parts of this trans reply
+	 * (n_setup, n_data, rep_setup_mb, rep_data_mb) are
+	 * always empty.  sr->raw_data replaces rep_param_mb.
+	 */
+	xa = sr->r_xa;
+	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
+	n_param = MBC_LENGTH(&sr->raw_data);
+	n_data  = MBC_LENGTH(&xa->rep_data_mb);
+
+	n_setup = (n_setup + 1) / 2;	/* Convert to setup words */
+	param_pad = 1;			/* must be one */
+	param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
+	/* Pad to 4 bytes */
+	data_pad = (4 - ((param_off + n_param) & 3)) % 4;
+	/* Param off from hdr */
+	data_off = param_off + n_param + data_pad;
+	total_bytes = param_pad + n_param + data_pad + n_data;
+
+	(void) smbsr_encode_result(sr, 18+n_setup, total_bytes,
+	    "b3.llllllllbCw#.C#.C",
+	    18 + n_setup,	/* wct */
+	    n_param,		/* Total Parameter Bytes */
+	    n_data,		/* Total Data Bytes */
+	    n_param,		/* Total Parameter Bytes this buffer */
+	    param_off,		/* Param offset from header start */
+	    0,			/* Param displacement */
+	    n_data,		/* Total Data Bytes this buffer */
+	    data_off,		/* Data offset from header start */
+	    0,			/* Data displacement */
+	    n_setup,		/* suwcnt */
+	    &xa->rep_setup_mb,	/* setup[] */
+	    total_bytes,	/* Total data bytes */
+	    param_pad,
+	    &sr->raw_data,	/* output mbc */
+	    data_pad,
+	    &xa->rep_data_mb);
+
+sendit:
+	sds = &sr->sr_server->sv_disp_stats1[sr->smb_com];
+	atomic_add_64(&sds->sdt_txb, (int64_t)sr->reply.chain_offset);
+
+	smbsr_send_reply(sr);	/* also puts the SMB header. */
+	smbsr_cleanup(sr);
+
+	mutex_enter(&sr->sr_mutex);
+	sr->sr_state = SMB_REQ_STATE_COMPLETED;
+	mutex_exit(&sr->sr_mutex);
+
+	smb_request_free(sr);
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c	Fri May 31 14:32:40 2019 +0200
@@ -20,9 +20,9 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2016 Syneto S.R.L. All rights reserved.
  * Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -189,8 +189,6 @@
 	uint16_t	fid;
 	smb_attr_t	attr;
 	int		rc;
-	enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT };
-	enum errstates	state = EMPTY;
 
 	if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) {
 		err->status = NT_STATUS_TOO_MANY_OPENED_FILES;
@@ -198,11 +196,16 @@
 		err->errcode = ERROR_TOO_MANY_OPEN_FILES;
 		return (NULL);
 	}
-	state = FIDALLOC;
 
 	of = kmem_cache_alloc(smb_cache_ofile, KM_SLEEP);
 	bzero(of, sizeof (smb_ofile_t));
 	of->f_magic = SMB_OFILE_MAGIC;
+
+	mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
+	list_create(&of->f_notify.nc_waiters, sizeof (smb_request_t),
+	    offsetof(smb_request_t, sr_waiters));
+
+	of->f_state = SMB_OFILE_STATE_OPEN;
 	of->f_refcnt = 1;
 	of->f_fid = fid;
 	of->f_uniqid = uniqid;
@@ -213,10 +216,10 @@
 	of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
 	    smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred;
 	crhold(of->f_cr);
-	state = CRHELD;
 	of->f_ftype = ftype;
 	of->f_server = tree->t_server;
 	of->f_session = tree->t_session;
+
 	/*
 	 * grab a ref for of->f_user
 	 * released in smb_ofile_delete()
@@ -226,10 +229,6 @@
 	of->f_tree = tree;
 	of->f_node = node;
 
-	mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
-	state = MUTEXINIT;
-	of->f_state = SMB_OFILE_STATE_OPEN;
-
 	if (ftype == SMB_FTYPE_MESG_PIPE) {
 		/* See smb_opipe_open. */
 		of->f_pipe = op->pipe;
@@ -246,9 +245,14 @@
 		if ((of->f_granted_access & FILE_DATA_ALL) == FILE_EXECUTE)
 			of->f_flags |= SMB_OFLAGS_EXECONLY;
 
+		/*
+		 * This is an "internal" getattr because we need the
+		 * UID and DOS attributes.  Don't want to fail here
+		 * due to permissions, so use kcred.
+		 */
 		bzero(&attr, sizeof (smb_attr_t));
 		attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR;
-		rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr);
+		rc = smb_node_getattr(NULL, node, zone_kcred(), NULL, &attr);
 		if (rc != 0) {
 			err->status = NT_STATUS_INTERNAL_ERROR;
 			err->errcls = ERRDOS;
@@ -299,22 +303,17 @@
 	return (of);
 
 errout:
-	switch (state) {
-	case MUTEXINIT:
-		mutex_destroy(&of->f_mutex);
-		smb_user_release(of->f_user);
-		/*FALLTHROUGH*/
-	case CRHELD:
-		crfree(of->f_cr);
-		of->f_magic = 0;
-		kmem_cache_free(smb_cache_ofile, of);
-		/*FALLTHROUGH*/
-	case FIDALLOC:
-		smb_idpool_free(&tree->t_fid_pool, fid);
-		/*FALLTHROUGH*/
-	case EMPTY:
-		break;
-	}
+	smb_user_release(of->f_user);
+	crfree(of->f_cr);
+
+	list_destroy(&of->f_notify.nc_waiters);
+	mutex_destroy(&of->f_mutex);
+
+	of->f_magic = 0;
+	kmem_cache_free(smb_cache_ofile, of);
+
+	smb_idpool_free(&tree->t_fid_pool, fid);
+
 	return (NULL);
 }
 
@@ -395,6 +394,25 @@
 			 */
 			if (of->f_odir != NULL)
 				smb_odir_close(of->f_odir);
+			/*
+			 * Cancel any notify change requests that
+			 * might be watching this open file (dir),
+			 * and unsubscribe it from node events.
+			 *
+			 * Can't hold f_mutex when calling smb_notify_ofile.
+			 * Don't really need it when unsubscribing, but
+			 * harmless, and consistent with subscribing.
+			 */
+			if (of->f_notify.nc_subscribed)
+				smb_notify_ofile(of,
+				    FILE_ACTION_HANDLE_CLOSED, NULL);
+			mutex_enter(&of->f_mutex);
+			if (of->f_notify.nc_subscribed) {
+				of->f_notify.nc_subscribed = B_FALSE;
+				smb_node_fcn_unsubscribe(of->f_node);
+				of->f_notify.nc_filter = 0;
+			}
+			mutex_exit(&of->f_mutex);
 		}
 		if (smb_node_dec_open_ofiles(of->f_node) == 0) {
 			/*
@@ -425,13 +443,6 @@
 			    of->f_cr, NULL, pa);
 		}
 
-		/*
-		 * Cancel any notify change requests that
-		 * may be using this open instance.
-		 */
-		if (of->f_node->n_fcn.fcn_count)
-			smb_notify_file_closed(of);
-
 		smb_server_dec_files(of->f_server);
 		break;
 	}
@@ -969,6 +980,21 @@
 	atomic_dec_32(&tree->t_session->s_file_cnt);
 	smb_llist_exit(&tree->t_ofile_list);
 
+	/*
+	 * Remove this ofile from the node's n_ofile_list so it
+	 * can't be found by list walkers like notify or oplock.
+	 * Keep the node ref. until later in this function so
+	 * of->f_node remains valid while we destroy the ofile.
+	 */
+	if (of->f_ftype == SMB_FTYPE_DISK ||
+	    of->f_ftype == SMB_FTYPE_PRINTER) {
+		ASSERT(of->f_node != NULL);
+		/*
+		 * Note smb_ofile_close did smb_node_dec_open_ofiles()
+		 */
+		smb_node_rem_ofile(of->f_node, of);
+	}
+
 	mutex_enter(&of->f_mutex);
 	mutex_exit(&of->f_mutex);
 
@@ -979,9 +1005,16 @@
 		of->f_pipe = NULL;
 		break;
 	case SMB_FTYPE_DISK:
+		ASSERT(of->f_notify.nc_subscribed == B_FALSE);
+		MBC_FLUSH(&of->f_notify.nc_buffer);
 		if (of->f_odir != NULL)
 			smb_odir_release(of->f_odir);
-		smb_node_rem_ofile(of->f_node, of);
+		/* FALLTHROUGH */
+	case SMB_FTYPE_PRINTER:
+		/*
+		 * Did smb_node_rem_ofile above.
+		 */
+		ASSERT(of->f_node != NULL);
 		smb_node_release(of->f_node);
 		break;
 	default:
@@ -990,9 +1023,10 @@
 	}
 
 	of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
+	list_destroy(&of->f_notify.nc_waiters);
 	mutex_destroy(&of->f_mutex);
+	smb_user_release(of->f_user);
 	crfree(of->f_cr);
-	smb_user_release(of->f_user);
 	kmem_cache_free(smb_cache_ofile, of);
 }
 
--- a/usr/src/uts/common/fs/smbsrv/smb_opipe.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_opipe.c	Fri May 31 14:32:40 2019 +0200
@@ -97,6 +97,27 @@
 }
 
 /*
+ * Unblock a request that might be blocked reading some
+ * pipe (AF_UNIX socket).  We don't have an easy way to
+ * interrupt just the thread servicing this request, so
+ * we shutdown(3socket) the socket, waking all readers.
+ * That's a bit heavy-handed, making the socket unusable
+ * after this, so we do this only when disconnecting a
+ * session (i.e. stopping the SMB service), and not when
+ * handling an SMB2_cancel or SMB_nt_cancel request.
+ */
+static void
+smb_opipe_cancel(smb_request_t *sr)
+{
+	ksocket_t so;
+
+	if (sr->session->s_state == SMB_SESSION_STATE_DISCONNECTED &&
+	    (so = sr->cancel_arg2) != NULL) {
+		(void) ksocket_shutdown(so, SHUT_RDWR, sr->user_cr);
+	}
+}
+
+/*
  * Helper for open: build pipe name and connect.
  */
 static int
@@ -167,31 +188,66 @@
 	if (!smb_netuserinfo_xdr(&xdrs, &nui))
 		goto out;
 
-	/*
-	 * If we fail sending the netuserinfo or recv'ing the
-	 * status reponse, we have probably run into the limit
-	 * on the number of open pipes.  That's this status:
-	 */
-	errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
+		mutex_exit(&sr->sr_mutex);
+		errp->status = NT_STATUS_CANCELLED;
+		goto out;
+	}
+	sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
+	sr->cancel_method = smb_opipe_cancel;
+	sr->cancel_arg2 = opipe->p_socket;
+	mutex_exit(&sr->sr_mutex);
 
 	rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
 	    &iocnt, sr->user_cr);
 	if (rc == 0 && iocnt != buflen)
 		rc = EIO;
-	if (rc != 0)
-		goto out;
+	if (rc == 0)
+		rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
+		    0, &iocnt, sr->user_cr);
+	if (rc == 0 && iocnt != sizeof (status))
+		rc = EIO;
 
-	rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0,
-	    &iocnt, sr->user_cr);
-	if (rc != 0 || iocnt != sizeof (status))
-		goto out;
+	mutex_enter(&sr->sr_mutex);
+	sr->cancel_method = NULL;
+	sr->cancel_arg2 = NULL;
+	switch (sr->sr_state) {
+	case SMB_REQ_STATE_WAITING_PIPE:
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+		break;
+	case SMB_REQ_STATE_CANCEL_PENDING:
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
+		rc = EINTR;
+		break;
+	default:
+		/* keep rc from above */
+		break;
+	}
+	mutex_exit(&sr->sr_mutex);
+
 
 	/*
 	 * Return the status we read from the pipe service,
 	 * normally NT_STATUS_SUCCESS, but could be something
 	 * else like NT_STATUS_ACCESS_DENIED.
 	 */
-	errp->status = status;
+	switch (rc) {
+	case 0:
+		errp->status = status;
+		break;
+	case EINTR:
+		errp->status = NT_STATUS_CANCELLED;
+		break;
+	/*
+	 * If we fail sending the netuserinfo or recv'ing the
+	 * status reponse, we have probably run into the limit
+	 * on the number of open pipes.  That's this status:
+	 */
+	default:
+		errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
+		break;
+	}
 
 out:
 	xdr_destroy(&xdrs);
@@ -378,17 +434,45 @@
 	if (sock == NULL)
 		return (EBADF);
 
-	bzero(&msghdr, sizeof (msghdr));
-	msghdr.msg_iov = uio->uio_iov;
-	msghdr.msg_iovlen = uio->uio_iovcnt;
+	mutex_enter(&sr->sr_mutex);
+	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
+		mutex_exit(&sr->sr_mutex);
+		rc = EINTR;
+		goto out;
+	}
+	sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
+	sr->cancel_method = smb_opipe_cancel;
+	sr->cancel_arg2 = sock;
+	mutex_exit(&sr->sr_mutex);
 
 	/*
 	 * This should block only if there's no data.
 	 * A single call to recvmsg does just that.
 	 * (Intentionaly no recv loop here.)
 	 */
+	bzero(&msghdr, sizeof (msghdr));
+	msghdr.msg_iov = uio->uio_iov;
+	msghdr.msg_iovlen = uio->uio_iovcnt;
 	rc = ksocket_recvmsg(sock, &msghdr, 0,
 	    &recvcnt, ofile->f_cr);
+
+	mutex_enter(&sr->sr_mutex);
+	sr->cancel_method = NULL;
+	sr->cancel_arg2 = NULL;
+	switch (sr->sr_state) {
+	case SMB_REQ_STATE_WAITING_PIPE:
+		sr->sr_state = SMB_REQ_STATE_ACTIVE;
+		break;
+	case SMB_REQ_STATE_CANCEL_PENDING:
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
+		rc = EINTR;
+		break;
+	default:
+		/* keep rc from above */
+		break;
+	}
+	mutex_exit(&sr->sr_mutex);
+
 	if (rc != 0)
 		goto out;
 
--- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c	Fri May 31 14:32:40 2019 +0200
@@ -186,7 +186,7 @@
 		if ((!op->op_oplock_levelII) ||
 		    (!smb_session_levelII_oplocks(session)) ||
 		    (smb_oplock_exclusive_grant(grants) != NULL) ||
-		    (smb_lock_range_access(sr, node, 0, 0, B_FALSE))) {
+		    (smb_lock_range_access(sr, node, 0, ~0, B_FALSE))) {
 			/*
 			 * LevelII (shared) oplock not allowed,
 			 * so reply with "none".
@@ -244,6 +244,7 @@
 {
 	smb_oplock_t		*ol;
 	smb_oplock_grant_t	*og;
+	smb_ofile_t		*ofile;
 	list_t			*grants;
 	uint32_t		timeout;
 	uint8_t			brk;
@@ -262,6 +263,7 @@
 	}
 
 	SMB_OPLOCK_GRANT_VALID(og);
+	ofile = og->og_ofile;	/* containing struct */
 
 	/* break levelII oplocks */
 	if (og->og_level == SMB_OPLOCK_LEVEL_II) {
@@ -283,7 +285,7 @@
 	}
 
 	if ((flags & SMB_OPLOCK_BREAK_TO_LEVEL_II) &&
-	    smb_session_levelII_oplocks(og->og_session)) {
+	    smb_session_levelII_oplocks(ofile->f_session)) {
 		brk = SMB_OPLOCK_BREAK_TO_LEVEL_II;
 	} else {
 		brk = SMB_OPLOCK_BREAK_TO_NONE;
@@ -308,8 +310,7 @@
 		return (EAGAIN);
 	}
 
-	if (sr && (sr->session == og->og_session) &&
-	    (sr->smb_uid == og->og_uid)) {
+	if (sr && (sr->uid_user == ofile->f_user)) {
 		timeout = smb_oplock_min_timeout;
 	} else {
 		timeout = smb_oplock_timeout;
@@ -415,11 +416,11 @@
 	 * These holds are released via smb_request_free after
 	 * the oplock break has been sent.
 	 */
-	ofile = og->og_ofile;
+	ofile = og->og_ofile;	/* containing struct */
 	if (!smb_ofile_hold(ofile))
 		return;
 
-	if ((sr = smb_request_alloc(og->og_session, 0)) == NULL) {
+	if ((sr = smb_request_alloc(ofile->f_session, 0)) == NULL) {
 		smb_ofile_release(ofile);
 		return;
 	}
@@ -702,10 +703,7 @@
 	og->og_breaking = 0;
 	og->og_level = level;
 	og->og_ofile = of;
-	og->og_fid = of->f_fid;
-	og->og_tid = of->f_tree->t_tid;
-	og->og_uid = of->f_user->u_uid;
-	og->og_session = of->f_session;
+
 	return (og);
 }
 
--- a/usr/src/uts/common/fs/smbsrv/smb_read.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_read.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <smbsrv/smb_kproto.h>
@@ -179,6 +179,7 @@
 {
 	smb_rw_param_t *param = sr->arg.rw;
 	DWORD status;
+	uint32_t lk_pid;
 	uint16_t count;
 	int rc;
 
@@ -195,8 +196,11 @@
 
 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 
+	/* Note: SMB1 locking uses 16-bit PIDs. */
+	lk_pid = sr->smb_pid & 0xFFFF;
+
 	status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
-	    0, SMB_LOCK_TYPE_READWRITE);
+	    lk_pid, SMB_LOCK_TYPE_READWRITE, 0);
 
 	if (status != NT_STATUS_SUCCESS) {
 		smb_lock_range_error(sr, status);
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c	Fri May 31 14:32:40 2019 +0200
@@ -219,8 +219,6 @@
 #include <smbsrv/smb_door.h>
 #include <smbsrv/smb_kstat.h>
 
-extern void smb_reply_notify_change_request(smb_request_t *);
-
 typedef struct {
 	smb_listener_daemon_t	*ra_listener;
 	smb_session_t		*ra_session;
@@ -270,6 +268,7 @@
 kmem_cache_t		*smb_cache_odir;
 kmem_cache_t		*smb_cache_opipe;
 kmem_cache_t		*smb_cache_event;
+kmem_cache_t		*smb_cache_lock;
 
 /*
  * *****************************************************************************
@@ -325,6 +324,8 @@
 	    sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 	smb_cache_event = kmem_cache_create("smb_event_cache",
 	    sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
+	smb_cache_lock = kmem_cache_create("smb_lock_cache",
+	    sizeof (smb_lock_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
 
 	smb_llist_init();
 	smb_llist_constructor(&smb_servers, sizeof (smb_server_t),
@@ -360,6 +361,7 @@
 	kmem_cache_destroy(smb_cache_odir);
 	kmem_cache_destroy(smb_cache_opipe);
 	kmem_cache_destroy(smb_cache_event);
+	kmem_cache_destroy(smb_cache_lock);
 
 	smb_node_fini();
 	smb_mbc_fini();
@@ -1412,6 +1414,7 @@
 	/*
 	 * Stop the listeners first, so we don't get any more
 	 * new work while we're trying to shut down.
+	 * Also disconnects all sessions under each.
 	 */
 	smb_server_listener_stop(&sv->sv_nbt_daemon);
 	smb_server_listener_stop(&sv->sv_tcp_daemon);
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/atomic.h>
@@ -46,6 +46,25 @@
  */
 uint32_t smb_keep_alive = SMB_PI_KEEP_ALIVE_MIN / 60;
 
+/*
+ * There are many smbtorture test cases that send
+ * racing requests, and where the tests fail if we
+ * don't execute them in exactly the order sent.
+ * These are test bugs.  The protocol makes no
+ * guarantees about execution order of requests
+ * that are concurrently active.
+ *
+ * Nonetheless, smbtorture has many useful tests,
+ * so we have this work-around we can enable to
+ * basically force sequential execution.  When
+ * enabled, insert a delay after each request is
+ * issued a taskq job.  Enable this with mdb by
+ * setting smb_reader_delay to 10.  Don't make it
+ * more than 500 or so or the server will appear
+ * to be so slow that tests may time out.
+ */
+int smb_reader_delay = 0;  /* mSec. */
+
 static int  smbsr_newrq_initial(smb_request_t *);
 
 static void smb_session_cancel(smb_session_t *);
@@ -417,6 +436,8 @@
 void
 smb_request_cancel(smb_request_t *sr)
 {
+	void (*cancel_method)(smb_request_t *) = NULL;
+
 	mutex_enter(&sr->sr_mutex);
 	switch (sr->sr_state) {
 
@@ -424,36 +445,31 @@
 	case SMB_REQ_STATE_SUBMITTED:
 	case SMB_REQ_STATE_ACTIVE:
 	case SMB_REQ_STATE_CLEANED_UP:
-		sr->sr_state = SMB_REQ_STATE_CANCELED;
+		sr->sr_state = SMB_REQ_STATE_CANCELLED;
 		break;
 
+	case SMB_REQ_STATE_WAITING_AUTH:
+	case SMB_REQ_STATE_WAITING_FCN1:
 	case SMB_REQ_STATE_WAITING_LOCK:
+	case SMB_REQ_STATE_WAITING_PIPE:
 		/*
-		 * This request is waiting on a lock.  Wakeup everything
-		 * waiting on the lock so that the relevant thread regains
-		 * control and notices that is has been canceled.  The
-		 * other lock request threads waiting on this lock will go
-		 * back to sleep when they discover they are still blocked.
+		 * These are states that have a cancel_method.
+		 * Make the state change now, to ensure that
+		 * we call cancel_method exactly once.  Do the
+		 * method call below, after we drop sr_mutex.
+		 * When the cancelled request thread resumes,
+		 * it should re-take sr_mutex and set sr_state
+		 * to CANCELLED, then return STATUS_CANCELLED.
 		 */
-		sr->sr_state = SMB_REQ_STATE_CANCELED;
-
-		ASSERT(sr->sr_awaiting != NULL);
-		mutex_enter(&sr->sr_awaiting->l_mutex);
-		cv_broadcast(&sr->sr_awaiting->l_cv);
-		mutex_exit(&sr->sr_awaiting->l_mutex);
+		sr->sr_state = SMB_REQ_STATE_CANCEL_PENDING;
+		cancel_method = sr->cancel_method;
+		VERIFY(cancel_method != NULL);
 		break;
 
-	case SMB_REQ_STATE_WAITING_EVENT:
-		/*
-		 * This request is waiting in change notify.
-		 */
-		sr->sr_state = SMB_REQ_STATE_CANCELED;
-		cv_signal(&sr->sr_ncr.nc_cv);
-		break;
-
-	case SMB_REQ_STATE_EVENT_OCCURRED:
+	case SMB_REQ_STATE_WAITING_FCN2:
 	case SMB_REQ_STATE_COMPLETED:
-	case SMB_REQ_STATE_CANCELED:
+	case SMB_REQ_STATE_CANCEL_PENDING:
+	case SMB_REQ_STATE_CANCELLED:
 		/*
 		 * No action required for these states since the request
 		 * is completing.
@@ -465,6 +481,10 @@
 		SMB_PANIC();
 	}
 	mutex_exit(&sr->sr_mutex);
+
+	if (cancel_method != NULL) {
+		cancel_method(sr);
+	}
 }
 
 /*
@@ -632,6 +652,11 @@
 		sr = NULL;	/* enqueued or freed */
 		if (rc != 0)
 			break;
+
+		/* See notes where this is defined (above). */
+		if (smb_reader_delay) {
+			delay(MSEC_TO_TICK(smb_reader_delay));
+		}
 	}
 	return (rc);
 }
@@ -1170,8 +1195,8 @@
 	while (tree) {
 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
 		ASSERT(tree->t_session == session);
+		smb_tree_disconnect(tree, B_TRUE);
 		smb_session_cancel_requests(session, tree, NULL);
-		smb_tree_disconnect(tree, B_TRUE);
 		next = smb_session_lookup_share(session, sharename, tree);
 		smb_tree_release(tree);
 		tree = next;
@@ -1343,7 +1368,6 @@
 	bzero(sr, sizeof (smb_request_t));
 
 	mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
-	cv_init(&sr->sr_ncr.nc_cv, NULL, CV_DEFAULT, NULL);
 	smb_srm_init(sr);
 	sr->session = session;
 	sr->sr_server = session->s_server;
@@ -1400,7 +1424,6 @@
 	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
 	ASSERT(sr->session);
 	ASSERT(sr->r_xa == NULL);
-	ASSERT(sr->sr_ncr.nc_fname == NULL);
 
 	if (sr->fid_ofile != NULL) {
 		smb_ofile_request_complete(sr->fid_ofile);
@@ -1413,6 +1436,12 @@
 	if (sr->uid_user != NULL)
 		smb_user_release(sr->uid_user);
 
+	/*
+	 * The above may have left work on the delete queues
+	 */
+	smb_llist_flush(&sr->session->s_tree_list);
+	smb_llist_flush(&sr->session->s_user_list);
+
 	smb_slist_remove(&sr->session->s_req_list, sr);
 
 	sr->session = NULL;
@@ -1429,7 +1458,6 @@
 		m_freem(sr->raw_data.chain);
 
 	sr->sr_magic = 0;
-	cv_destroy(&sr->sr_ncr.nc_cv);
 	mutex_destroy(&sr->sr_mutex);
 	kmem_cache_free(smb_cache_request, sr);
 }
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c	Fri May 31 14:32:40 2019 +0200
@@ -1205,6 +1205,13 @@
 			flags |= mtype->mt_flags;
 	}
 
+	/*
+	 * SMB_TREE_QUOTA will be on here if the FS is ZFS.  We want to
+	 * turn it OFF when the share property says false.
+	 */
+	if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
+		flags &= ~SMB_TREE_QUOTA;
+
 	(void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
 	(void) smb_strupr((char *)tree->t_typename);
 
--- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <smbsrv/smb_kproto.h>
@@ -315,8 +315,8 @@
 	if (tcon->flags & SMB_TCONX_DISCONECT_TID) {
 		tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
 		if (tree != NULL) {
+			smb_tree_disconnect(tree, B_TRUE);
 			smb_session_cancel_requests(sr->session, tree, sr);
-			smb_tree_disconnect(tree, B_TRUE);
 		}
 	}
 
@@ -447,8 +447,8 @@
 
 	sr->user_cr = smb_user_getcred(sr->uid_user);
 
+	smb_tree_disconnect(sr->tid_tree, B_TRUE);
 	smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
-	smb_tree_disconnect(sr->tid_tree, B_TRUE);
 
 	if (smbsr_encode_empty_result(sr))
 		return (SDRC_ERROR);
--- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -71,6 +72,7 @@
 {
 	uint32_t	Length;
 	uint32_t	Offset;
+	uint32_t	lk_pid;
 	DWORD		result;
 
 	if (smbsr_decode_vwv(sr, "wll", &sr->smb_fid, &Length, &Offset) != 0)
@@ -82,8 +84,11 @@
 		return (SDRC_ERROR);
 	}
 
-	result = smb_unlock_range(sr, sr->fid_ofile->f_node,
-	    (u_offset_t)Offset, (uint64_t)Length);
+	/* Note: SMB1 locking uses 16-bit PIDs. */
+	lk_pid = sr->smb_pid & 0xFFFF;
+
+	result = smb_unlock_range(sr, (uint64_t)Offset, (uint64_t)Length,
+	    lk_pid);
 	if (result != NT_STATUS_SUCCESS) {
 		smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 		    ERRDOS, ERROR_NOT_LOCKED);
--- a/usr/src/uts/common/fs/smbsrv/smb_user.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_user.c	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2016 by Delphix. All rights reserved.
  */
 
@@ -210,6 +210,7 @@
 
 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
 static void smb_user_auth_logoff(smb_user_t *);
+static void smb_user_logoff_tq(void *);
 
 
 /*
@@ -266,6 +267,8 @@
     uint32_t		privileges,
     uint32_t		audit_sid)
 {
+	ksocket_t authsock = NULL;
+	timeout_id_t tmo = NULL;
 
 	ASSERT(user->u_magic == SMB_USER_MAGIC);
 	ASSERT(cr);
@@ -279,7 +282,15 @@
 		return (-1);
 	}
 
-	smb_authsock_close(user);
+	/*
+	 * In the transition from LOGGING_ON to LOGGED_ON,
+	 * we always have an auth. socket to close.
+	 */
+	authsock = user->u_authsock;
+	ASSERT(authsock != NULL);
+	user->u_authsock = NULL;
+	tmo = user->u_auth_tmo;
+	user->u_auth_tmo = NULL;
 
 	user->u_state = SMB_USER_STATE_LOGGED_ON;
 	user->u_flags = flags;
@@ -293,6 +304,13 @@
 
 	mutex_exit(&user->u_mutex);
 
+	/* Timeout callback takes u_mutex. See untimeout(9f) */
+	if (tmo != NULL)
+		(void) untimeout(tmo);
+
+	/* This close can block, so not under the mutex. */
+	smb_authsock_close(user, authsock);
+
 	return (0);
 }
 
@@ -306,19 +324,24 @@
 smb_user_logoff(
     smb_user_t		*user)
 {
+	ksocket_t authsock = NULL;
+	timeout_id_t tmo = NULL;
+
 	ASSERT(user->u_magic == SMB_USER_MAGIC);
 
 	mutex_enter(&user->u_mutex);
 	ASSERT(user->u_refcnt);
 	switch (user->u_state) {
-	case SMB_USER_STATE_LOGGING_ON: {
-		smb_authsock_close(user);
+	case SMB_USER_STATE_LOGGING_ON:
+		authsock = user->u_authsock;
+		user->u_authsock = NULL;
+		tmo = user->u_auth_tmo;
+		user->u_auth_tmo = NULL;
 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
 		smb_server_dec_users(user->u_server);
 		break;
-	}
 
-	case SMB_USER_STATE_LOGGED_ON: {
+	case SMB_USER_STATE_LOGGED_ON:
 		/*
 		 * The user is moved into a state indicating that the log off
 		 * process has started.
@@ -331,7 +354,7 @@
 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
 		smb_server_dec_users(user->u_server);
 		break;
-	}
+
 	case SMB_USER_STATE_LOGGED_OFF:
 	case SMB_USER_STATE_LOGGING_OFF:
 		break;
@@ -341,6 +364,15 @@
 		break;
 	}
 	mutex_exit(&user->u_mutex);
+
+	/* Timeout callback takes u_mutex. See untimeout(9f) */
+	if (tmo != NULL)
+		(void) untimeout(tmo);
+
+	/* This close can block, so not under the mutex. */
+	if (authsock != NULL) {
+		smb_authsock_close(user, authsock);
+	}
 }
 
 /*
@@ -412,6 +444,77 @@
 }
 
 /*
+ * Timeout handler for user logons that stay too long in
+ * state SMB_USER_STATE_LOGGING_ON.  This is setup by a
+ * timeout call in smb_authsock_open, and called in a
+ * callout thread, so schedule a taskq job to do the
+ * real work of logging off this user.
+ */
+void
+smb_user_auth_tmo(void *arg)
+{
+	smb_user_t *user = arg;
+	smb_request_t *sr;
+
+	SMB_USER_VALID(user);
+
+	/*
+	 * If we can't allocate a request, it means the
+	 * session is being torn down, so nothing to do.
+	 */
+	sr = smb_request_alloc(user->u_session, 0);
+	if (sr == NULL)
+		return;
+
+	/*
+	 * Check user state, and take a hold if it's
+	 * still logging on.  If not, we're done.
+	 */
+	mutex_enter(&user->u_mutex);
+	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
+		mutex_exit(&user->u_mutex);
+		smb_request_free(sr);
+		return;
+	}
+	/* smb_user_hold_internal */
+	user->u_refcnt++;
+	mutex_exit(&user->u_mutex);
+
+	/*
+	 * The user hold is given to the SR, and released in
+	 * smb_user_logoff_tq / smb_request_free
+	 */
+	sr->uid_user = user;
+	sr->user_cr = user->u_cred;
+	sr->sr_state = SMB_REQ_STATE_SUBMITTED;
+
+	(void) taskq_dispatch(
+	    user->u_server->sv_worker_pool,
+	    smb_user_logoff_tq, sr, TQ_SLEEP);
+}
+
+/*
+ * Helper for smb_user_auth_tmo()
+ */
+static void
+smb_user_logoff_tq(void *arg)
+{
+	smb_request_t	*sr = arg;
+
+	SMB_REQ_VALID(sr);
+
+	mutex_enter(&sr->sr_mutex);
+	sr->sr_worker = curthread;
+	sr->sr_state = SMB_REQ_STATE_ACTIVE;
+	mutex_exit(&sr->sr_mutex);
+
+	smb_user_logoff(sr->uid_user);
+
+	sr->sr_state = SMB_REQ_STATE_COMPLETED;
+	smb_request_free(sr);
+}
+
+/*
  * Determine whether or not the user is an administrator.
  * Members of the administrators group have administrative rights.
  */
@@ -533,6 +636,7 @@
 	ASSERT(user->u_refcnt == 0);
 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
 	ASSERT(user->u_authsock == NULL);
+	ASSERT(user->u_auth_tmo == NULL);
 
 	session = user->u_session;
 	smb_llist_enter(&session->s_user_list, RW_WRITER);
--- a/usr/src/uts/common/fs/smbsrv/smb_write.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/smbsrv/smb_write.c	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/sdt.h>
@@ -268,6 +268,7 @@
 smb_com_write_and_unlock(smb_request_t *sr)
 {
 	smb_rw_param_t *param = sr->arg.rw;
+	uint32_t lk_pid;
 	uint32_t status;
 	int rc = 0;
 
@@ -306,8 +307,12 @@
 		return (SDRC_ERROR);
 	}
 
-	status = smb_unlock_range(sr, sr->fid_ofile->f_node, param->rw_offset,
-	    (uint64_t)param->rw_count);
+
+	/* Note: SMB1 locking uses 16-bit PIDs. */
+	lk_pid = sr->smb_pid & 0xFFFF;
+
+	status = smb_unlock_range(sr, param->rw_offset,
+	    (uint64_t)param->rw_count, lk_pid);
 	if (status != NT_STATUS_SUCCESS) {
 		smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 		    ERRDOS, ERROR_NOT_LOCKED);
--- a/usr/src/uts/common/fs/zfs/vdev_disk.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/fs/zfs/vdev_disk.c	Fri May 31 14:32:40 2019 +0200
@@ -22,7 +22,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
- * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ * Copyright 2019 Joyent, Inc.
  */
 
 #include <sys/zfs_context.h>
@@ -858,10 +858,15 @@
 	bp->b_bufsize = zio->io_size;
 	bp->b_iodone = vdev_disk_io_intr;
 
-	zfs_zone_zio_start(zio);
-
-	/* ldi_strategy() will return non-zero only on programming errors */
-	VERIFY(ldi_strategy(dvd->vd_lh, bp) == 0);
+	/*
+	 * In general we would expect ldi_strategy() to return non-zero only
+	 * because of programming errors, but we've also seen this fail shortly
+	 * after a disk dies.
+	 */
+	if (ldi_strategy(dvd->vd_lh, bp) != 0) {
+		zio->io_error = ENXIO;
+		zio_interrupt(zio);
+	}
 }
 
 static void
--- a/usr/src/uts/common/io/lofi.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/io/lofi.c	Fri May 31 14:32:40 2019 +0200
@@ -25,6 +25,7 @@
  * Copyright (c) 2016 Andrey Sokolov
  * Copyright 2016 Toomas Soome <tsoome@me.com>
  * Copyright 2019 Joyent, Inc.
+ * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
  */
 
 /*
@@ -2785,34 +2786,28 @@
 	(void) snprintf(namebuf, sizeof (namebuf), "%d", klip->li_id);
 
 	mutex_enter(&lofi_devlink_cache.ln_lock);
-	do {
+	for (;;) {
 		error = nvlist_lookup_nvlist(lofi_devlink_cache.ln_data,
 		    namebuf, &nvl);
 
-		if (error != 0) {
-			/* No data in cache, wait for some. */
-			ticks = ddi_get_lbolt() +
-			    lofi_timeout * drv_usectohz(1000000);
-			error = cv_timedwait(&lofi_devlink_cache.ln_cv,
-			    &lofi_devlink_cache.ln_lock, ticks);
-			if (error == -1)
-				break;	/* timeout */
-			error = 1;
-			continue;	/* Read again. */
+		if (error == 0 &&
+		    nvlist_lookup_string(nvl, DEV_NAME, &str) == 0 &&
+		    strncmp(str, "/dev/" LOFI_CHAR_NAME,
+		    sizeof ("/dev/" LOFI_CHAR_NAME) - 1) != 0) {
+			(void) strlcpy(klip->li_devpath, str,
+			    sizeof (klip->li_devpath));
+			break;
 		}
-
-		if (nvl != NULL) {
-			if (nvlist_lookup_string(nvl, DEV_NAME, &str) == 0) {
-				if (strncmp(str, "/dev/" LOFI_CHAR_NAME,
-				    sizeof ("/dev/" LOFI_CHAR_NAME) - 1) == 0) {
-					error = 1;
-					continue;
-				}
-				(void) strlcpy(klip->li_devpath, str,
-				    sizeof (klip->li_devpath));
-			}
-		}
-	} while (error != 0);
+		/*
+		 * Either there is no data in the cache, or the
+		 * cache entry still has the wrong device name.
+		 */
+		ticks = ddi_get_lbolt() + lofi_timeout * drv_usectohz(1000000);
+		error = cv_timedwait(&lofi_devlink_cache.ln_cv,
+		    &lofi_devlink_cache.ln_lock, ticks);
+		if (error == -1)
+			break;	/* timeout */
+	}
 	mutex_exit(&lofi_devlink_cache.ln_lock);
 }
 
--- a/usr/src/uts/common/smb/ntstatus.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/smb/ntstatus.h	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _SMB_NTSTATUS_H
@@ -633,6 +633,7 @@
 #define	NT_STATUS_DOMAIN_TRUST_INCONSISTENT		0xC000019B
 #define	NT_STATUS_FS_DRIVER_REQUIRED			0xC000019C
 #define	NT_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME	0xC000019F
+#define	NT_STATUS_INVALID_LOCK_RANGE			0xC00001A1
 #define	NT_STATUS_NO_USER_SESSION_KEY			0xC0000202
 #define	NT_STATUS_USER_SESSION_DELETED			0xC0000203
 #define	NT_STATUS_RESOURCE_LANG_NOT_FOUND		0xC0000204
--- a/usr/src/uts/common/smbsrv/smb.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/smbsrv/smb.h	Fri May 31 14:32:40 2019 +0200
@@ -242,18 +242,7 @@
 #define	FILE_ACTION_ADDED_STREAM	0x00000006
 #define	FILE_ACTION_REMOVED_STREAM	0x00000007
 #define	FILE_ACTION_MODIFIED_STREAM	0x00000008
-/*
- * Note: These action values are not from MS-FSCC.
- * FILE_ACTION_SUBDIR_CHANGED is used internally for
- * "watch tree" support, posted to all parents of a
- * directory that had one of the changes above.
- * FILE_ACTION_DELETE_PENDING is used internally to tell
- * notify change requests when the "delete-on-close" flag
- * has been set on the directory being watched.
- */
-#define	FILE_ACTION_SUBDIR_CHANGED	0x00000009
-#define	FILE_ACTION_DELETE_PENDING	0x0000000a
-
+/* See also: FILE_ACTION_SUBDIR_CHANGED etc. */
 
 /* Lock type flags */
 #define	LOCKING_ANDX_NORMAL_LOCK	0x00
--- a/usr/src/uts/common/smbsrv/smb2_kproto.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/smbsrv/smb2_kproto.h	Fri May 31 14:32:40 2019 +0200
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _SMB2_KPROTO_H_
@@ -35,8 +35,6 @@
 		smb_kstat_req_t *, int, int);
 
 int	smb2sr_newrq(smb_request_t *);
-int	smb2sr_newrq_async(smb_request_t *);
-int	smb2sr_newrq_cancel(smb_request_t *);
 void	smb2sr_work(smb_request_t *);
 
 int smb2_decode_header(smb_request_t *);
@@ -65,7 +63,7 @@
 smb_sdrc_t smb2_write(smb_request_t *);
 smb_sdrc_t smb2_lock(smb_request_t *);
 smb_sdrc_t smb2_ioctl(smb_request_t *);
-/* No smb2_cancel() - see smb2_dispatch.c */
+smb_sdrc_t smb2_cancel(smb_request_t *);
 smb_sdrc_t smb2_echo(smb_request_t *);
 smb_sdrc_t smb2_query_dir(smb_request_t *);
 smb_sdrc_t smb2_change_notify(smb_request_t *);
@@ -74,6 +72,7 @@
 smb_sdrc_t smb2_oplock_break_ack(smb_request_t *);
 
 int smb2_newrq_negotiate(smb_request_t *);
+int smb2_newrq_cancel(smb_request_t *);
 
 uint32_t smb2_aapl_crctx(smb_request_t *,
 	mbuf_chain_t *, mbuf_chain_t *);
@@ -93,6 +92,8 @@
 uint32_t smb2_setinfo_sec(smb_request_t *, smb_setinfo_t *, uint32_t);
 uint32_t smb2_setinfo_quota(smb_request_t *, smb_setinfo_t *);
 
+void smb2sr_finish_async(smb_request_t *);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/uts/common/smbsrv/smb_kproto.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h	Fri May 31 14:32:40 2019 +0200
@@ -21,8 +21,8 @@
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2016 Syneto S.R.L.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -136,6 +136,7 @@
 extern	kmem_cache_t		*smb_cache_odir;
 extern	kmem_cache_t		*smb_cache_opipe;
 extern	kmem_cache_t		*smb_cache_event;
+extern	kmem_cache_t		*smb_cache_lock;
 
 extern	kmem_cache_t		*smb_kshare_cache_vfs;
 
@@ -322,11 +323,15 @@
  * range lock functions - node operations
  */
 uint32_t smb_lock_get_lock_count(smb_node_t *, smb_ofile_t *);
-uint32_t smb_unlock_range(smb_request_t *, smb_node_t *,
-    uint64_t, uint64_t);
+uint32_t smb_unlock_range(smb_request_t *, uint64_t, uint64_t, uint32_t);
 uint32_t smb_lock_range(smb_request_t *, uint64_t, uint64_t, uint32_t,
-    uint32_t locktype);
+    uint32_t, uint32_t);
+uint32_t smb_lock_range_cancel(smb_request_t *, uint64_t, uint64_t, uint32_t);
 void smb_lock_range_error(smb_request_t *, uint32_t);
+
+int smb_lock_range_access(smb_request_t *, smb_node_t *,
+    uint64_t, uint64_t, boolean_t);
+
 DWORD smb_nbl_conflict(smb_node_t *, uint64_t, uint64_t, nbl_op_t);
 
 void smb_mangle(const char *, ino64_t, char *, size_t);
@@ -376,6 +381,7 @@
 		smb_kstat_req_t *, int, int);
 
 int	smb1sr_newrq(smb_request_t *);
+int	smb1sr_newrq_cancel(smb_request_t *);
 void	smb1sr_work(smb_request_t *);
 
 int	smbsr_encode_empty_result(smb_request_t *);
@@ -415,9 +421,6 @@
 void	smbsr_encode_header(smb_request_t *sr, int wct,
 		    int bcc, const char *fmt, ...);
 
-int smb_lock_range_access(smb_request_t *, smb_node_t *,
-    uint64_t, uint64_t, boolean_t);
-
 void smb_encode_sd(mbuf_chain_t *, smb_sd_t *, uint32_t);
 void smb_encode_sid(mbuf_chain_t *, smb_sid_t *);
 smb_sid_t *smb_decode_sid(mbuf_chain_t *, uint32_t);
@@ -549,10 +552,10 @@
 DWORD smb_node_delete_check(smb_node_t *);
 boolean_t smb_node_share_check(smb_node_t *);
 
-void smb_node_fcn_subscribe(smb_node_t *, smb_request_t *);
-void smb_node_fcn_unsubscribe(smb_node_t *, smb_request_t *);
+void smb_node_fcn_subscribe(smb_node_t *);
+void smb_node_fcn_unsubscribe(smb_node_t *);
 void smb_node_notify_change(smb_node_t *, uint_t, const char *);
-void smb_node_notify_parents(smb_node_t *);
+
 int smb_node_getattr(smb_request_t *, smb_node_t *, cred_t *,
     smb_ofile_t *, smb_attr_t *);
 int smb_node_setattr(smb_request_t *, smb_node_t *, cred_t *,
@@ -582,11 +585,15 @@
 void smb_vfs_rele(smb_export_t *, vfs_t *);
 void smb_vfs_rele_all(smb_export_t *);
 
-/* NOTIFY CHANGE */
-
-uint32_t smb_notify_common(smb_request_t *, mbuf_chain_t *, uint32_t);
-void smb_notify_event(smb_node_t *, uint_t, const char *);
-void smb_notify_file_closed(smb_ofile_t *);
+/*
+ * smb_notify.c
+ */
+uint32_t smb_notify_act1(smb_request_t *, uint32_t, uint32_t);
+uint32_t smb_notify_act2(smb_request_t *);
+uint32_t smb_notify_act3(smb_request_t *);
+void smb_notify_ofile(smb_ofile_t *, uint_t, const char *);
+void smb_nt_transact_notify_finish(void *);
+void smb2_change_notify_finish(void *);
 
 int smb_fem_fcn_install(smb_node_t *);
 void smb_fem_fcn_uninstall(smb_node_t *);
@@ -620,7 +627,7 @@
  */
 int smb_authenticate_ext(smb_request_t *);
 int smb_authenticate_old(smb_request_t *);
-void smb_authsock_close(smb_user_t *);
+void smb_authsock_close(smb_user_t *, ksocket_t);
 
 /*
  * session functions (file smb_session.c)
@@ -733,9 +740,10 @@
 smb_user_t *smb_user_new(smb_session_t *);
 int smb_user_logon(smb_user_t *, cred_t *,
     char *, char *, uint32_t, uint32_t, uint32_t);
-smb_user_t *smb_user_dup(smb_user_t *);
 void smb_user_logoff(smb_user_t *);
 void smb_user_delete(void *);
+void smb_user_auth_tmo(void *);
+
 boolean_t smb_user_is_admin(smb_user_t *);
 boolean_t smb_user_namecmp(smb_user_t *, const char *);
 int smb_user_enum(smb_user_t *, smb_svcenum_t *);
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h	Fri May 31 14:32:40 2019 +0200
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -471,20 +471,49 @@
 	smb_thread_t	e_unexport_thread;
 } smb_export_t;
 
-/* NOTIFY CHANGE */
-typedef struct smb_node_fcn {
-	kmutex_t	fcn_mutex;
-	uint32_t	fcn_count;
-	list_t		fcn_watchers;	/* smb_request_t, sr_ncr.nc_lnd */
-} smb_node_fcn_t;
+/*
+ * NOTIFY CHANGE, a.k.a. File Change Notification (FCN)
+ */
+
+/*
+ * These FCN filter mask values are not from MS-FSCC, but
+ * must not overlap with any FILE_NOTIFY_VALID_MASK values.
+ */
+#define	FILE_NOTIFY_CHANGE_EV_SUBDIR	0x00010000
+#define	FILE_NOTIFY_CHANGE_EV_DELETE	0x00020000
+#define	FILE_NOTIFY_CHANGE_EV_CLOSED	0x00040000
+#define	FILE_NOTIFY_CHANGE_EV_OVERFLOW	0x00080000
 
-typedef struct smb_notify_change_req {
-	list_node_t		nc_lnd;	/* n_fcn.fcn_watchers */
-	kcondvar_t		nc_cv;	/* prot: sr_mutex */
-	uint32_t		nc_flags;
-	uint32_t		nc_action;
-	char			*nc_fname;
-} smb_notify_change_req_t;
+/*
+ * Note: These FCN action values are not from MS-FSCC, but must
+ * follow in sequence from FILE_ACTION_MODIFIED_STREAM.
+ *
+ * FILE_ACTION_SUBDIR_CHANGED is used internally for
+ * "watch tree" support, posted to all parents of a
+ * directory that had one of the changes above.
+ *
+ * FILE_ACTION_DELETE_PENDING is used internally to tell
+ * notify change requests when the "delete-on-close" flag
+ * has been set on the directory being watched.
+ *
+ * FILE_ACTION_HANDLE_CLOSED is used to wakeup notify change
+ * requests when the watched directory handle is closed.
+ */
+#define	FILE_ACTION_SUBDIR_CHANGED	0x00000009
+#define	FILE_ACTION_DELETE_PENDING	0x0000000a
+#define	FILE_ACTION_HANDLE_CLOSED	0x0000000b
+
+/*
+ * Sub-struct within smb_ofile_t
+ */
+typedef struct smb_notify {
+	list_t			nc_waiters; /* Waiting SRs */
+	mbuf_chain_t		nc_buffer;
+	uint32_t		nc_filter;
+	uint32_t		nc_events;
+	int			nc_last_off;
+	boolean_t		nc_subscribed;
+} smb_notify_t;
 
 /*
  * SMB operates over a NetBIOS-over-TCP transport (NBT) or directly
@@ -584,10 +613,6 @@
 	uint32_t		og_magic;
 	uint8_t			og_breaking;
 	uint8_t			og_level;
-	uint16_t		og_fid;
-	uint16_t		og_tid;
-	uint16_t		og_uid;
-	struct smb_session	*og_session;
 	struct smb_ofile	*og_ofile;
 } smb_oplock_grant_t;
 
@@ -639,11 +664,13 @@
 	uint32_t		n_open_count;
 	uint32_t		n_opening_count;
 	smb_llist_t		n_ofile_list;
-	smb_llist_t		n_lock_list;
+	/* If entering both, go in order n_lock_list, n_wlock_list */
+	smb_llist_t		n_lock_list;	/* active locks */
+	smb_llist_t		n_wlock_list;	/* waiting locks */
 	uint32_t		n_pending_dosattr;
 	volatile int		flags;
 	u_offset_t		n_allocsz;
-	smb_node_fcn_t		n_fcn;
+	uint32_t		n_fcn_count;
 	smb_oplock_t		n_oplock;
 	struct smb_node		*n_dnode;
 	struct smb_node		*n_unode;
@@ -660,7 +687,6 @@
 #define	NODE_FLAGS_SYSTEM		0x00008000
 #define	NODE_FLAGS_WRITE_THROUGH	0x00100000
 #define	NODE_XATTR_DIR			0x01000000
-#define	NODE_FLAGS_WATCH_TREE		0x10000000	/* smb_notify.c */
 #define	NODE_FLAGS_DELETE_ON_CLOSE	0x40000000
 #define	NODE_FLAGS_EXECUTABLE		0x80000000
 
@@ -914,9 +940,6 @@
 	int			reply_max_bytes;
 	uint16_t		smb_msg_size;
 	uint16_t		smb_max_mpx;
-	uchar_t			*outpipe_data;
-	int			outpipe_datalen;
-	int			outpipe_cookie;
 	smb_srqueue_t		*s_srqueue;
 	uint64_t		start_time;
 	unsigned char		MAC_key[44];
@@ -961,6 +984,7 @@
 	struct smb_server	*u_server;
 	smb_session_t		*u_session;
 	ksocket_t		u_authsock;
+	timeout_id_t		u_auth_tmo;
 	uint16_t		u_name_len;
 	char			*u_name;
 	uint16_t		u_domain_len;
@@ -1287,6 +1311,7 @@
 	boolean_t		f_written;
 	char			f_quota_resume[SMB_SID_STRSZ];
 	smb_oplock_grant_t	f_oplock_grant;
+	smb_notify_t		f_notify;
 } smb_ofile_t;
 
 typedef struct smb_fileinfo {
@@ -1317,19 +1342,13 @@
 	kmutex_t		l_mutex;
 	kcondvar_t		l_cv;
 
-	list_node_t		l_conflict_lnd;
-	smb_slist_t		l_conflict_list;
+	smb_ofile_t		*l_file;
 
-	smb_session_t		*l_session;
-	smb_ofile_t		*l_file;
-	struct smb_request	*l_sr;
-
-	uint32_t		l_flags;
-	uint64_t		l_session_kid;
 	struct smb_lock		*l_blocked_by; /* Debug info only */
 
+	uint32_t		l_conflicts;
+	uint32_t		l_flags;
 	uint32_t		l_pid;
-	uint16_t		l_uid;
 	uint32_t		l_type;
 	uint64_t		l_start;
 	uint64_t		l_length;
@@ -1337,8 +1356,8 @@
 } smb_lock_t;
 
 #define	SMB_LOCK_FLAG_INDEFINITE	0x0004
-#define	SMB_LOCK_INDEFINITE_WAIT(lock) \
-	((lock)->l_flags & SMB_LOCK_FLAG_INDEFINITE)
+#define	SMB_LOCK_FLAG_CLOSED		0x0008
+#define	SMB_LOCK_FLAG_CANCELLED		0x0010
 
 #define	SMB_LOCK_TYPE_READWRITE		101
 #define	SMB_LOCK_TYPE_READONLY		102
@@ -1489,6 +1508,12 @@
 	boolean_t	op_oplock_levelII;	/* TRUE if levelII supported */
 } smb_arg_open_t;
 
+typedef struct smb_arg_lock {
+	void		*lvec;
+	uint32_t	lcnt;
+	uint32_t	lseq;
+} smb_arg_lock_t;
+
 struct smb_async_req;
 
 /*
@@ -1502,11 +1527,11 @@
  * | COMPLETED |                                                        |
  * +-----------+
  *      ^                                                               |
- *      | T15                      +----------+                         v
- * +------------+        T6        |          |                 +--------------+
- * | CLEANED_UP |<-----------------| CANCELED |                 | INITIALIZING |
- * +------------+                  |          |                 +--------------+
- *      |    ^                     +----------+                         |
+ *      | T15                      +-----------+                        v
+ * +------------+        T6        |           |                +--------------+
+ * | CLEANED_UP |<-----------------| CANCELLED |                | INITIALIZING |
+ * +------------+                  |           |                +--------------+
+ *      |    ^                     +-----------+                        |
  *      |    |                        ^  ^ ^ ^                          |
  *      |    |          +-------------+  | | |                          |
  *      |    |    T3    |                | | |               T13        | T1
@@ -1617,11 +1642,14 @@
 	SMB_REQ_STATE_INITIALIZING,
 	SMB_REQ_STATE_SUBMITTED,
 	SMB_REQ_STATE_ACTIVE,
-	SMB_REQ_STATE_WAITING_EVENT,
-	SMB_REQ_STATE_EVENT_OCCURRED,
+	SMB_REQ_STATE_WAITING_AUTH,
+	SMB_REQ_STATE_WAITING_FCN1,
+	SMB_REQ_STATE_WAITING_FCN2,
 	SMB_REQ_STATE_WAITING_LOCK,
+	SMB_REQ_STATE_WAITING_PIPE,
 	SMB_REQ_STATE_COMPLETED,
-	SMB_REQ_STATE_CANCELED,
+	SMB_REQ_STATE_CANCEL_PENDING,
+	SMB_REQ_STATE_CANCELLED,
 	SMB_REQ_STATE_CLEANED_UP,
 	SMB_REQ_STATE_SENTINEL
 } smb_req_state_t;
@@ -1636,8 +1664,10 @@
 	int32_t			sr_gmtoff;
 	smb_session_t		*session;
 	smb_kmod_cfg_t		*sr_cfg;
+	void			(*cancel_method)(struct smb_request *);
+	void			*cancel_arg2;
 
-	smb_notify_change_req_t	sr_ncr;
+	list_node_t		sr_waiters;	/* smb_notify.c */
 
 	/* Info from session service header */
 	uint32_t		sr_req_length; /* Excluding NBT header */
@@ -1645,7 +1675,6 @@
 	/* Request buffer excluding NBT header */
 	void			*sr_request_buf;
 
-	smb_lock_t		*sr_awaiting;
 	struct mbuf_chain	command;
 	struct mbuf_chain	reply;
 	struct mbuf_chain	raw_data;
@@ -1691,9 +1720,11 @@
 	uint16_t		smb2_cmd_code;
 	uint16_t		smb2_credit_request;
 	uint16_t		smb2_credit_response;
+	uint16_t		smb2_total_credits; /* in compound */
 	uint32_t		smb2_hdr_flags;
 	uint32_t		smb2_next_command;
 	uint64_t		smb2_messageid;
+	uint64_t		smb2_first_msgid;
 	/* uint32_t		smb2_pid; use smb_pid */
 	/* uint32_t		smb2_tid; use smb_tid */
 	/* uint64_t		smb2_ssnid; use smb_uid */
@@ -1731,6 +1762,7 @@
 		smb_arg_tcon_t		tcon;
 		smb_arg_dirop_t		dirop;
 		smb_arg_open_t		open;
+		smb_arg_lock_t		lock;
 		smb_rw_param_t		*rw;
 		smb_oplock_grant_t	olbrk;	/* for async oplock break */
 		int32_t			timestamp;
--- a/usr/src/uts/common/smbsrv/smb_share.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/common/smbsrv/smb_share.h	Fri May 31 14:32:40 2019 +0200
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2016 by Delphix. All rights reserved.
  */
 
@@ -57,23 +57,25 @@
  * name			Advertised name of the share
  *
  * ad-container		Active directory container in which the share
- * 			will be published
+ *			will be published
  *
  * abe			Determines whether Access Based Enumeration is applied
  *			to a share
  *
  * csc			Client-side caching (CSC) options applied to this share
- * 	disabled	The client MUST NOT cache any files
- * 	manual		The client should not automatically cache every file
- * 			that it	opens
- * 	auto		The client may cache every file that it opens
- * 	vdo		The client may cache every file that it opens
+ *	disabled	The client MUST NOT cache any files
+ *	manual		The client should not automatically cache every file
+ *			that it	opens
+ *	auto		The client may cache every file that it opens
+ *	vdo		The client may cache every file that it opens
  *			and satisfy file requests from its local cache.
  *
  * catia		CATIA character substitution
  *
  * guestok		Determines whether guest access is allowed
  *
+ * quotas		SMB quotas presented & supported (T/F)
+ *
  * next three properties use access-list a al NFS
  *
  * ro			list of hosts that will have read-only access
@@ -91,6 +93,8 @@
 #define	SHOPT_NONE		"none"
 #define	SHOPT_DFSROOT		"dfsroot"
 #define	SHOPT_DESCRIPTION	"description"
+#define	SHOPT_QUOTAS		"quotas"
+#define	SHOPT_AUTOHOME		"Autohome"
 
 #define	SMB_DEFAULT_SHARE_GROUP	"smb"
 #define	SMB_PROTOCOL_NAME	"smb"
@@ -170,6 +174,8 @@
 #define	SMB_SHRF_ACC_RW		0x0400
 #define	SMB_SHRF_ACC_ALL	0x0F00
 
+#define	SMB_SHRF_QUOTAS		0x1000
+
 /*
  * Runtime flags
  */
@@ -241,6 +247,8 @@
 int smb_shr_start(void);
 void smb_shr_stop(void);
 void *smb_shr_load(void *);
+void smb_shr_load_execinfo(void);
+void smb_shr_unload(void);
 void smb_shr_iterinit(smb_shriter_t *);
 smb_share_t *smb_shr_iterate(smb_shriter_t *);
 void smb_shr_list(int, smb_shrlist_t *);
--- a/usr/src/uts/sun4/sys/platform_module.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4/sys/platform_module.h	Fri May 31 14:32:40 2019 +0200
@@ -23,11 +23,13 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2019 Peter Tribble.
+ */
+
 #ifndef _SYS_PLATFORM_MODULE_H
 #define	_SYS_PLATFORM_MODULE_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/async.h>
 #include <sys/sunddi.h>
 #include <sys/memlist_plat.h>
@@ -109,7 +111,6 @@
     const char *class);
 
 extern caddr_t plat_startup_memlist(caddr_t alloc_base);
-extern int starcat_dr_name(char *name);
 
 #pragma	weak	plat_setprop_enter
 #pragma	weak	plat_setprop_exit
--- a/usr/src/uts/sun4u/Makefile.files	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/Makefile.files	Fri May 31 14:32:40 2019 +0200
@@ -89,7 +89,7 @@
 PCI_COMMON_OBJS	+= pci.o pci_util.o pci_dma.o pci_devctl.o \
 			pci_fdvma.o pci_iommu.o pci_sc.o pci_debug.o \
 			pci_cb.o pci_ib.o pci_ecc.o pci_pbm.o pci_intr.o \
-			pci_space.o pci_counters.o pci_axq.o \
+			pci_space.o pci_counters.o \
 			pci_fm.o pci_reloc.o pci_tools.o pci_asm.o
 RMCLOMV_OBJS	+= rmclomv.o
 
@@ -97,7 +97,7 @@
 SCHIZO_PCI_OBJS	+= $(PCI_COMMON_OBJS) pcisch_asm.o pcisch.o pcix.o
 SIMBA_PCI_OBJS	+= simba.o
 DB21554_OBJS	+= db21554.o
-US_OBJS 	+= cpudrv.o cpudrv_mach.o
+US_OBJS		+= cpudrv.o cpudrv_mach.o
 POWER_OBJS	+= power.o
 EPIC_OBJS	+= epic.o
 GRBEEP_OBJS	+= grbeep.o
@@ -136,7 +136,7 @@
 GPTWOCFG_OBJS	+= gptwocfg.o
 GPTWO_CPU_OBJS	+= gptwo_cpu.o
 
-JBUSPPM_OBJS	+= jbusppm.o 
+JBUSPPM_OBJS	+= jbusppm.o
 RMC_COMM_OBJS	+= rmc_comm.o rmc_comm_crctab.o rmc_comm_dp.o rmc_comm_drvintf.o
 RMCADM_OBJS	+= rmcadm.o
 MEM_CACHE_OBJS	+= mem_cache.o panther_asm.o
@@ -161,7 +161,6 @@
 TODMOSTEK_OBJS	+= todmostek.o
 TODDS1287_OBJS	+= todds1287.o
 TODDS1337_OBJS	+= todds1337.o
-TODSTARCAT_OBJS	+= todstarcat.o
 TODBLADE_OBJS	+= todblade.o
 TODM5819_OBJS	+= todm5819.o
 TODM5819P_RMC_OBJS	+= todm5819p_rmc.o
@@ -198,10 +197,10 @@
 #			cpu modules
 #
 CPU_OBJ		+= $(OBJS_DIR)/mach_cpu_module.o
-SPITFIRE_OBJS 	= spitfire.o spitfire_asm.o spitfire_copy.o spitfire_kdi.o common_asm.o
+SPITFIRE_OBJS	= spitfire.o spitfire_asm.o spitfire_copy.o spitfire_kdi.o common_asm.o
 HUMMINGBIRD_OBJS= $(SPITFIRE_OBJS)
 US3_CMN_OBJS	= us3_common.o us3_common_mmu.o us3_common_asm.o us3_kdi.o cheetah_copy.o common_asm.o
-CHEETAH_OBJS 	= $(US3_CMN_OBJS) us3_cheetah.o us3_cheetah_asm.o
+CHEETAH_OBJS	= $(US3_CMN_OBJS) us3_cheetah.o us3_cheetah_asm.o
 CHEETAHPLUS_OBJS= $(US3_CMN_OBJS) us3_cheetahplus.o us3_cheetahplus_asm.o
 JALAPENO_OBJS   = $(US3_CMN_OBJS) us3_jalapeno.o us3_jalapeno_asm.o
 OLYMPUS_OBJS	= opl_olympus.o opl_olympus_asm.o opl_olympus_copy.o \
--- a/usr/src/uts/sun4u/Makefile.sun4u	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/Makefile.sun4u	Fri May 31 14:32:40 2019 +0200
@@ -104,13 +104,13 @@
 DSF_DIR		 = $(UTSBASE)/$(PLATFORM)/genassym
 LINTS_DIR	 = $(OBJS_DIR)
 LINT_LIB_DIR	 = $(UTSBASE)/$(PLATFORM)/lint-libs/$(OBJS_DIR)
- 
+
 DTRACESTUBS_O	 = $(OBJS_DIR)/dtracestubs.o
 DTRACESTUBS	 = $(OBJS_DIR)/libdtracestubs.so
 
 UNIX_O		 = $(UNIX_DIR)/$(OBJS_DIR)/unix.o
 MODSTUBS_O	 = $(MODSTUBS_DIR)/$(OBJS_DIR)/modstubs.o
-GENLIB	 	 = $(GENLIB_DIR)/$(OBJS_DIR)/libgenunix.so
+GENLIB		 = $(GENLIB_DIR)/$(OBJS_DIR)/libgenunix.so
 
 LINT_LIB	 = $(LINT_LIB_DIR)/llib-lunix.ln
 GEN_LINT_LIB	 = $(LINT_LIB_DIR)/llib-lgenunix.ln
@@ -158,33 +158,32 @@
 include $(UTSBASE)/Makefile.uts
 
 # These come after Makefile.uts.
-IMPLEMENTATIONS		 = tazmo 
-IMPLEMENTATIONS		+= javelin 
-IMPLEMENTATIONS		+= darwin 
-IMPLEMENTATIONS		+= quasar 
-IMPLEMENTATIONS		+= grover 
-IMPLEMENTATIONS		+= enchilada 
-IMPLEMENTATIONS		+= taco 
-IMPLEMENTATIONS		+= mpxu 
-IMPLEMENTATIONS		+= excalibur 
-IMPLEMENTATIONS		+= montecarlo 
-IMPLEMENTATIONS		+= serengeti 
-IMPLEMENTATIONS		+= littleneck 
-IMPLEMENTATIONS		+= starcat 
-IMPLEMENTATIONS		+= daktari 
-IMPLEMENTATIONS		+= cherrystone 
-IMPLEMENTATIONS		+= fjlite 
-IMPLEMENTATIONS		+= snowbird 
-IMPLEMENTATIONS		+= schumacher 
-IMPLEMENTATIONS		+= blade 
-IMPLEMENTATIONS		+= boston 
-IMPLEMENTATIONS		+= seattle 
-IMPLEMENTATIONS		+= chicago 
-IMPLEMENTATIONS		+= sunfire 
-IMPLEMENTATIONS		+= lw8 
-IMPLEMENTATIONS		+= makaha 
-IMPLEMENTATIONS		+= opl 
-IMPLEMENTATIONS		+= lw2plus 
+IMPLEMENTATIONS		 = tazmo
+IMPLEMENTATIONS		+= javelin
+IMPLEMENTATIONS		+= darwin
+IMPLEMENTATIONS		+= quasar
+IMPLEMENTATIONS		+= grover
+IMPLEMENTATIONS		+= enchilada
+IMPLEMENTATIONS		+= taco
+IMPLEMENTATIONS		+= mpxu
+IMPLEMENTATIONS		+= excalibur
+IMPLEMENTATIONS		+= montecarlo
+IMPLEMENTATIONS		+= serengeti
+IMPLEMENTATIONS		+= littleneck
+IMPLEMENTATIONS		+= daktari
+IMPLEMENTATIONS		+= cherrystone
+IMPLEMENTATIONS		+= fjlite
+IMPLEMENTATIONS		+= snowbird
+IMPLEMENTATIONS		+= schumacher
+IMPLEMENTATIONS		+= blade
+IMPLEMENTATIONS		+= boston
+IMPLEMENTATIONS		+= seattle
+IMPLEMENTATIONS		+= chicago
+IMPLEMENTATIONS		+= sunfire
+IMPLEMENTATIONS		+= lw8
+IMPLEMENTATIONS		+= makaha
+IMPLEMENTATIONS		+= opl
+IMPLEMENTATIONS		+= lw2plus
 
 #
 #	machine specific optimization, override default in Makefile.master
@@ -239,7 +238,7 @@
 GENCONST_SRC	 = $(UTSBASE)/sun4/ml/genconst.c
 OFFSETS		 = $(UTSBASE)/sun4/ml/offsets.in
 PLATFORM_OFFSETS = $(UTSBASE)/sun4u/ml/mach_offsets.in
-FDOFFSETS 	 = $(UTSBASE)/sun/io/fd_offsets.in
+FDOFFSETS	 = $(UTSBASE)/sun/io/fd_offsets.in
 
 #
 #	Define the actual specific platforms
@@ -272,7 +271,7 @@
 DEBUG_DEFS		= $(DEBUG_DEFS_$(BUILD_TYPE))
 
 DEBUG_COND_OBJ64	= $(POUND_SIGN)
-DEBUG_COND_DBG64	= 
+DEBUG_COND_DBG64	=
 IF_DEBUG_OBJ		= $(DEBUG_COND_$(BUILD_TYPE))$(OBJS_DIR)/
 
 $(IF_DEBUG_OBJ)trap.o		:=	DEBUG_DEFS	+= -DTRAPDEBUG
@@ -286,7 +285,7 @@
 
 $(IF_TRAPTRACE_OBJ)mach_locore.o	:=	DEBUG_DEFS	+= -DTRAPTRACE
 $(IF_TRAPTRACE_OBJ)mlsetup.o		:=	DEBUG_DEFS	+= -DTRAPTRACE
-$(IF_TRAPTRACE_OBJ)syscall_trap.o 	:=	DEBUG_DEFS	+= -DTRAPTRACE
+$(IF_TRAPTRACE_OBJ)syscall_trap.o	:=	DEBUG_DEFS	+= -DTRAPTRACE
 $(IF_TRAPTRACE_OBJ)startup.o		:=	DEBUG_DEFS	+= -DTRAPTRACE
 $(IF_TRAPTRACE_OBJ)mach_startup.o	:=	DEBUG_DEFS	+= -DTRAPTRACE
 $(IF_TRAPTRACE_OBJ)mp_startup.o		:=	DEBUG_DEFS	+= -DTRAPTRACE
@@ -314,7 +313,7 @@
 #$(IF_DEBUG_OBJ)lock_prim.o	:= DEBUG_DEFS	+= -DDISP_LOCK_STATS
 #$(IF_DEBUG_OBJ)disp.o		:= DEBUG_DEFS	+= -DDISP_LOCK_STATS
 
-# Comment these out if you don't want dispatcher debugging 
+# Comment these out if you don't want dispatcher debugging
 
 #$(IF_DEBUG_OBJ)lock_prim.o	:= DEBUG_DEFS	+= -DDISP_DEBUG
 
@@ -392,7 +391,7 @@
 DRV_KMODS	+= rmclomv
 DRV_KMODS	+= sf
 DRV_KMODS	+= nxge
-DRV_KMODS	+= i2bsc 
+DRV_KMODS	+= i2bsc
 DRV_KMODS	+= mem_cache
 
 #
@@ -459,9 +458,9 @@
 #
 #	sun4u 'TOD' Modules (/platform/.../kernel/tod):
 #
-TOD_KMODS	+= todds1287 todds1337 todmostek 
+TOD_KMODS	+= todds1287 todds1337 todmostek
 TOD_KMODS	+= todm5819 todblade todbq4802 todsg todopl
-TOD_KMODS	+= todm5819p_rmc todstarcat 
+TOD_KMODS	+= todm5819p_rmc
 
 #
 #	Performance Counter BackEnd Modules (/usr/kernel/pcbe):
--- a/usr/src/uts/sun4u/io/gptwocfg.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/io/gptwocfg.c	Fri May 31 14:32:40 2019 +0200
@@ -24,6 +24,10 @@
  */
 
 /*
+ * Copyright 2019 Peter Tribble.
+ */
+
+/*
  * Safari Configurator  (gptwocfg)
  *
  */
@@ -48,7 +52,6 @@
 #include <sys/gp2cfg.h>
 #include <sys/machsystm.h>
 #include <sys/platform_module.h>
-#pragma weak starcat_dr_name
 
 #ifdef DEBUG
 int gptwocfg_debug = 0;
@@ -144,8 +147,7 @@
 }
 
 int
-_info(modinfop)
-struct modinfo *modinfop;
+_info(struct modinfo *modinfop)
 {
 	return (mod_info(&modlinkage, modinfop));
 }
@@ -239,12 +241,6 @@
 	mutex_enter(&gptwo_config_list_lock);
 	config = gptwo_config_list;
 	while (config != NULL) {
-		if (&starcat_dr_name) {
-			if (starcat_dr_name(ddi_node_name(ap)) < 0) {
-				config = config->gptwo_next;
-				continue;
-			}
-		}
 		if (config->gptwo_portid == id) {
 			cmn_err(CE_WARN, "gptwocfg: gptwocfg_configure: "
 			    "0x%x Port already configured\n", id);
@@ -556,13 +552,6 @@
 	while (saf_dev != NULL) {
 		if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS,
 		    "portid", -1) == id) {
-			if (&starcat_dr_name) {
-				if (starcat_dr_name(ddi_node_name(saf_dev))
-				    < 0) {
-					saf_dev = ddi_get_next_sibling(saf_dev);
-					continue;
-				}
-			}
 			nodes++;
 		}
 		saf_dev = ddi_get_next_sibling(saf_dev);
@@ -580,13 +569,6 @@
 	while ((saf_dev != NULL) && (i < nodes)) {
 		if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS,
 		    "portid", -1) == id) {
-			if (&starcat_dr_name) {
-				if (starcat_dr_name(ddi_node_name(saf_dev))
-				    < 0) {
-					saf_dev = ddi_get_next_sibling(saf_dev);
-					continue;
-				}
-			}
 			/*
 			 * Branch rooted at this dip must have been
 			 * held by the DR driver.
--- a/usr/src/uts/sun4u/io/pci/pci.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/io/pci/pci.c	Fri May 31 14:32:40 2019 +0200
@@ -27,6 +27,10 @@
  * PCI nexus driver interface
  */
 
+/*
+ * Copyright 2019 Peter Tribble.
+ */
+
 #include <sys/types.h>
 #include <sys/conf.h>		/* nulldev */
 #include <sys/stat.h>		/* devctl */
@@ -123,7 +127,7 @@
 extern struct mod_ops mod_driverops;
 
 static struct modldrv modldrv = {
-	&mod_driverops, 			/* Type of module - driver */
+	&mod_driverops,				/* Type of module - driver */
 	"Sun4u Host to PCI nexus driver",	/* Name of module. */
 	&pci_ops,				/* driver ops */
 };
@@ -471,15 +475,15 @@
 /*
  * bus map entry point:
  *
- * 	if map request is for an rnumber
+ *	if map request is for an rnumber
  *		get the corresponding regspec from device node
- * 	build a new regspec in our parent's format
+ *	build a new regspec in our parent's format
  *	build a new map_req with the new regspec
  *	call up the tree to complete the mapping
  */
 int
 pci_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
-	off_t off, off_t len, caddr_t *addrp)
+    off_t off, off_t len, caddr_t *addrp)
 {
 	pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip));
 	struct regspec p_regspec;
@@ -538,14 +542,12 @@
 	if (rval == DDI_SUCCESS) {
 		/*
 		 * Set-up access functions for FM access error capable drivers.
-		 * The axq workaround prevents fault management support
 		 */
 		if (DDI_FM_ACC_ERR_CAP(pci_p->pci_fm_cap) &&
 		    DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) &&
 		    mp->map_handlep->ah_acc.devacc_attr_access !=
 		    DDI_DEFAULT_ACC)
 			pci_fm_acc_setup(mp, rdip);
-		pci_axq_setup(mp, pci_p->pci_pbm_p);
 	}
 
 done:
@@ -567,7 +569,7 @@
  */
 int
 pci_dma_setup(dev_info_t *dip, dev_info_t *rdip, ddi_dma_req_t *dmareq,
-	ddi_dma_handle_t *handlep)
+    ddi_dma_handle_t *handlep)
 {
 	pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip));
 	iommu_t *iommu_p = pci_p->pci_iommu_p;
@@ -633,7 +635,7 @@
  */
 int
 pci_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp,
-	int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
+    int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
 {
 	pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip));
 	ddi_dma_impl_t *mp;
@@ -690,8 +692,8 @@
  */
 int
 pci_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
-	ddi_dma_handle_t handle, ddi_dma_req_t *dmareq,
-	ddi_dma_cookie_t *cookiep, uint_t *ccountp)
+    ddi_dma_handle_t handle, ddi_dma_req_t *dmareq,
+    ddi_dma_cookie_t *cookiep, uint_t *ccountp)
 {
 	pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip));
 	iommu_t *iommu_p = pci_p->pci_iommu_p;
@@ -817,8 +819,8 @@
  */
 int
 pci_dma_win(dev_info_t *dip, dev_info_t *rdip,
-	ddi_dma_handle_t handle, uint_t win, off_t *offp,
-	size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
+    ddi_dma_handle_t handle, uint_t win, off_t *offp,
+    size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp)
 {
 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
 	DEBUG2(DBG_DMA_WIN, dip, "rdip=%s%d\n",
@@ -911,8 +913,8 @@
  */
 int
 pci_dma_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
-	enum ddi_dma_ctlops cmd, off_t *offp, size_t *lenp, caddr_t *objp,
-	uint_t cache_flags)
+    enum ddi_dma_ctlops cmd, off_t *offp, size_t *lenp, caddr_t *objp,
+    uint_t cache_flags)
 {
 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
 	DEBUG3(DBG_DMA_CTL, dip, "%s: rdip=%s%d\n", pci_dmactl_str[cmd],
@@ -1205,7 +1207,7 @@
  */
 int
 pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
-	ddi_ctl_enum_t op, void *arg, void *result)
+    ddi_ctl_enum_t op, void *arg, void *result)
 {
 	pci_t *pci_p = get_pci_soft_state(ddi_get_instance(dip));
 
--- a/usr/src/uts/sun4u/io/pci/pci_axq.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +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"
-
-/*
- * PCI nexus driver interface
- */
-#include <sys/types.h>
-#include <sys/conf.h>		/* nulldev */
-#include <sys/stat.h>		/* devctl */
-#include <sys/kmem.h>
-#include <sys/async.h>		/* ecc_flt for pci_ecc.h */
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ontrap.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/ddi_subrdefs.h>
-#include <sys/epm.h>
-#include <sys/membar.h>
-#include <sys/modctl.h>
-#include <sys/hotplug/pci/pcihp.h>
-#include <sys/pci/pci_obj.h>
-
-/*LINTLIBRARY*/
-
-static uint8_t	pci_axq_hack_get8(ddi_acc_impl_t *handle, uint8_t *addr);
-static uint16_t	pci_axq_hack_get16(ddi_acc_impl_t *handle, uint16_t *addr);
-static uint32_t	pci_axq_hack_get32(ddi_acc_impl_t *handle, uint32_t *addr);
-static uint64_t	pci_axq_hack_get64(ddi_acc_impl_t *handle, uint64_t *addr);
-static void	pci_axq_hack_put8(ddi_acc_impl_t *handle, uint8_t *addr,
-			uint8_t data);
-static void	pci_axq_hack_put16(ddi_acc_impl_t *handle, uint16_t *addr,
-			uint16_t data);
-static void	pci_axq_hack_put32(ddi_acc_impl_t *handle, uint32_t *addr,
-			uint32_t data);
-static void	pci_axq_hack_put64(ddi_acc_impl_t *handle, uint64_t *addr,
-			uint64_t data);
-static void	pci_axq_hack_rep_get8(ddi_acc_impl_t *handle,
-			uint8_t *host_addr, uint8_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_get16(ddi_acc_impl_t *handle,
-			uint16_t *host_addr, uint16_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_get32(ddi_acc_impl_t *handle,
-			uint32_t *host_addr, uint32_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_get64(ddi_acc_impl_t *handle,
-			uint64_t *host_addr, uint64_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_put8(ddi_acc_impl_t *handle,
-			uint8_t *host_addr, uint8_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_put16(ddi_acc_impl_t *handle,
-			uint16_t *host_addr, uint16_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_put32(ddi_acc_impl_t *handle,
-			uint32_t *host_addr, uint32_t *dev_addr,
-			size_t repcount, uint_t flags);
-static void	pci_axq_hack_rep_put64(ddi_acc_impl_t *handle,
-			uint64_t *host_addr, uint64_t *dev_addr,
-			size_t repcount, uint_t flags);
-
-/*
- * On Sunfire 15k systems with AXQs less than 6.1
- * we have to use special PIO routines that limit
- * the number of outstanding PIOs.  We setup the
- * handle with pointers to our special functions
- * after it has been succesfully mapped by our
- * parent.
- */
-
-void
-pci_axq_pio_limit(pbm_t *pbm_p)
-{
-	pci_t *pci_p = pbm_p->pbm_pci_p;
-	dev_info_t *dip = pci_p->pci_dip;
-	int (*axq_pio_workaround)(dev_info_t *) = NULL;
-
-	axq_pio_workaround =
-	    (int (*)(dev_info_t *)) modgetsymvalue(
-	    "starcat_axq_pio_workaround", 0);
-
-	if (axq_pio_workaround) {
-		pbm_p->pbm_pio_limit = (axq_pio_workaround)(dip);
-		pbm_p->pbm_pio_counter = pbm_p->pbm_pio_limit;
-	} else
-		pbm_p->pbm_pio_limit = 0;
-}
-
-void
-pci_axq_setup(ddi_map_req_t *mp, pbm_t *pbm_p)
-{
-	ddi_acc_hdl_t *hp;
-	ddi_acc_impl_t *ap;
-
-	if (mp->map_op != DDI_MO_MAP_LOCKED)
-		return;
-	if (!pbm_p->pbm_pio_limit)
-		return;
-
-	hp = (ddi_acc_hdl_t *)mp->map_handlep;
-	ap = (ddi_acc_impl_t *)hp->ah_platform_private;
-
-	ap->ahi_get8 = pci_axq_hack_get8;
-	ap->ahi_get16 = pci_axq_hack_get16;
-	ap->ahi_get32 = pci_axq_hack_get32;
-	ap->ahi_get64 = pci_axq_hack_get64;
-	ap->ahi_put8 = pci_axq_hack_put8;
-	ap->ahi_put16 = pci_axq_hack_put16;
-	ap->ahi_put32 = pci_axq_hack_put32;
-	ap->ahi_put64 = pci_axq_hack_put64;
-	ap->ahi_rep_get8 = pci_axq_hack_rep_get8;
-	ap->ahi_rep_get16 = pci_axq_hack_rep_get16;
-	ap->ahi_rep_get32 = pci_axq_hack_rep_get32;
-	ap->ahi_rep_get64 = pci_axq_hack_rep_get64;
-	ap->ahi_rep_put8 = pci_axq_hack_rep_put8;
-	ap->ahi_rep_put16 = pci_axq_hack_rep_put16;
-	ap->ahi_rep_put32 = pci_axq_hack_rep_put32;
-	ap->ahi_rep_put64 = pci_axq_hack_rep_put64;
-
-	hp->ah_bus_private = (void *)pbm_p;
-}
-
-/*
- * get/put routines for SunFire 15K systems that have AXQ versions
- * less than 6.1.  These routines limit the number of outsanding
- * PIOs issues across a PCI Bus.
- */
-static uint8_t
-pci_axq_hack_get8(ddi_acc_impl_t *handle, uint8_t *addr)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint8_t data;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	data = i_ddi_get8(handle, addr);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-
-	return (data);
-}
-
-static uint16_t
-pci_axq_hack_get16(ddi_acc_impl_t *handle, uint16_t *addr)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint16_t data;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	data = i_ddi_swap_get16(handle, addr);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-
-	return (data);
-}
-
-static uint32_t
-pci_axq_hack_get32(ddi_acc_impl_t *handle, uint32_t *addr)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t data;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	data = i_ddi_swap_get32(handle, addr);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-
-	return (data);
-}
-
-static uint64_t
-pci_axq_hack_get64(ddi_acc_impl_t *handle, uint64_t *addr)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint64_t data;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	data = i_ddi_swap_get64(handle, addr);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-
-	return (data);
-}
-
-static void
-pci_axq_hack_put8(ddi_acc_impl_t *handle, uint8_t *addr, uint8_t data)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_put8(handle, addr, data);
-	membar_sync();
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_put16(ddi_acc_impl_t *handle, uint16_t *addr, uint16_t data)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_swap_put16(handle, addr, data);
-	membar_sync();
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_put32(ddi_acc_impl_t *handle, uint32_t *addr, uint32_t data)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_swap_put32(handle, addr, data);
-	membar_sync();
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_put64(ddi_acc_impl_t *handle, uint64_t *addr, uint64_t data)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_swap_put64(handle, addr, data);
-	membar_sync();
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
-	uint8_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_rep_get8(handle, host_addr, dev_addr, repcount, flags);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
-	uint16_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_swap_rep_get16(handle, host_addr, dev_addr, repcount, flags);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
-	uint32_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_swap_rep_get32(handle, host_addr, dev_addr, repcount, flags);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
-	uint64_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	i_ddi_swap_rep_get64(handle, host_addr, dev_addr, repcount, flags);
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
-	uint8_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	while (repcount--) {
-		i_ddi_put8(handle, dev_addr, *host_addr);
-		membar_sync();
-		if (flags == DDI_DEV_AUTOINCR)
-			dev_addr++;
-		host_addr++;
-	}
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
-	uint16_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	while (repcount--) {
-		i_ddi_put16(handle, dev_addr, *host_addr);
-		membar_sync();
-		if (flags == DDI_DEV_AUTOINCR)
-			dev_addr++;
-		host_addr++;
-	}
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-
-static void
-pci_axq_hack_rep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
-	uint32_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	while (repcount--) {
-		i_ddi_put32(handle, dev_addr, *host_addr);
-		membar_sync();
-		if (flags == DDI_DEV_AUTOINCR)
-			dev_addr++;
-		host_addr++;
-	}
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
-static void
-pci_axq_hack_rep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
-	uint64_t *dev_addr, size_t repcount, uint_t flags)
-{
-	pbm_t *pbm_p = (pbm_t *)handle->ahi_common.ah_bus_private;
-	uint32_t spl;
-
-	spl = ddi_enter_critical();
-	PIO_LIMIT_ENTER(pbm_p);
-	while (repcount--) {
-		i_ddi_put64(handle, dev_addr, *host_addr);
-		membar_sync();
-		if (flags == DDI_DEV_AUTOINCR)
-			dev_addr++;
-		host_addr++;
-	}
-	PIO_LIMIT_EXIT(pbm_p);
-	ddi_exit_critical(spl);
-}
--- a/usr/src/uts/sun4u/io/pci/pci_fm.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/io/pci/pci_fm.c	Fri May 31 14:32:40 2019 +0200
@@ -23,7 +23,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
 
 #include <sys/types.h>
 #include <sys/sunddi.h>
@@ -180,7 +182,7 @@
 	if (derr.fme_status == DDI_FM_OK) {
 		if (pci_check_error(pci_p) != 0) {
 			(void) pci_pbm_err_handler(pci_p->pci_dip, &derr,
-					(const void *)pci_p, PCI_BUS_EXIT_CALL);
+			    (const void *)pci_p, PCI_BUS_EXIT_CALL);
 		}
 	}
 	mutex_exit(&pci_p->pci_common_p->pci_fm_mutex);
@@ -224,7 +226,7 @@
 
 	if (pci_check_error(pci_p) != 0) {
 		int err = pci_pbm_err_handler(pci_p->pci_dip, derr,
-				(const void *)pci_p, PCI_TRAP_CALL);
+		    (const void *)pci_p, PCI_TRAP_CALL);
 		if (err == DDI_FM_FATAL)
 			fatal++;
 		else if (err == DDI_FM_NONFATAL)
@@ -258,10 +260,10 @@
 	 */
 	if (pci_ecc_queue == NULL) {
 		pci_ecc_queue = errorq_create("pci_ecc_queue",
-				(errorq_func_t)ecc_err_drain,
-				(void *)pci_p->pci_ecc_p,
-				ECC_MAX_ERRS, sizeof (ecc_errstate_t),
-				PIL_2, ERRORQ_VITAL);
+		    (errorq_func_t)ecc_err_drain,
+		    (void *)pci_p->pci_ecc_p,
+		    ECC_MAX_ERRS, sizeof (ecc_errstate_t),
+		    PIL_2, ERRORQ_VITAL);
 		if (pci_ecc_queue == NULL)
 			panic("failed to create required system error queue");
 	}
@@ -273,20 +275,15 @@
 
 	/*
 	 * Initialize FMA support
-	 * The axq workaround prevents fault management of access errors
 	 */
-	if (pci_p->pci_pbm_p->pbm_pio_limit == 0)
-		pci_p->pci_fm_cap = DDI_FM_EREPORT_CAPABLE |
-			DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE |
-			DDI_FM_ERRCB_CAPABLE;
-	else
-		pci_p->pci_fm_cap = DDI_FM_EREPORT_CAPABLE |
-			DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE;
+	pci_p->pci_fm_cap = DDI_FM_EREPORT_CAPABLE |
+	    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE |
+	    DDI_FM_ERRCB_CAPABLE;
 	/*
 	 * Call parent to get it's capablity
 	 */
 	ddi_fm_init(pci_p->pci_dip, &pci_p->pci_fm_cap,
-			&pci_p->pci_fm_ibc);
+	    &pci_p->pci_fm_ibc);
 	/*
 	 * Need to be ereport and error handler cabable
 	 */
@@ -297,14 +294,13 @@
 	 */
 	if (cmn_p->pci_common_refcnt == 0) {
 		mutex_init(&cmn_p->pci_fm_mutex, NULL, MUTEX_DRIVER,
-				(void *)pci_p->pci_fm_ibc);
+		    (void *)pci_p->pci_fm_ibc);
 	}
 
 	/*
 	 * Register error callback with our parent.
 	 */
-	ddi_fm_handler_register(pci_p->pci_dip, pci_err_callback,
-			pci_p);
+	ddi_fm_handler_register(pci_p->pci_dip, pci_err_callback, pci_p);
 
 }
 
--- a/usr/src/uts/sun4u/io/pci/pci_pbm.c	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/io/pci/pci_pbm.c	Fri May 31 14:32:40 2019 +0200
@@ -23,7 +23,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright 2019 Peter Tribble.
+ */
 
 /*
  * PCI PBM implementation:
@@ -75,12 +77,12 @@
 	pbm_p->pbm_pci_p = pci_p;
 
 	len = snprintf(pbm_p->pbm_nameinst_str,
-		sizeof (pbm_p->pbm_nameinst_str),
-		"%s%d", NAMEINST(dip));
+	    sizeof (pbm_p->pbm_nameinst_str),
+	    "%s%d", NAMEINST(dip));
 	pbm_p->pbm_nameaddr_str = pbm_p->pbm_nameinst_str + ++len;
 	(void) snprintf(pbm_p->pbm_nameaddr_str,
-		sizeof (pbm_p->pbm_nameinst_str) - len,
-		"%s@%s", NAMEADDR(dip));
+	    sizeof (pbm_p->pbm_nameinst_str) - len,
+	    "%s@%s", NAMEADDR(dip));
 
 	pci_pbm_setup(pbm_p);
 
@@ -109,11 +111,11 @@
 	pbm_p->pbm_last_pfn = mmu_btop(last_addr);
 
 	DEBUG4(DBG_ATTACH, dip,
-		"pbm_create: ctrl=%x, afsr=%x, afar=%x, diag=%x\n",
-		pbm_p->pbm_ctrl_reg, pbm_p->pbm_async_flt_status_reg,
-		pbm_p->pbm_async_flt_addr_reg, pbm_p->pbm_diag_reg);
+	    "pbm_create: ctrl=%x, afsr=%x, afar=%x, diag=%x\n",
+	    pbm_p->pbm_ctrl_reg, pbm_p->pbm_async_flt_status_reg,
+	    pbm_p->pbm_async_flt_addr_reg, pbm_p->pbm_diag_reg);
 	DEBUG1(DBG_ATTACH, dip, "pbm_create: conf=%x\n",
-		pbm_p->pbm_config_header);
+	    pbm_p->pbm_config_header);
 
 	/*
 	 * Register a function to disable pbm error interrupts during a panic.
@@ -136,12 +138,6 @@
 	}
 
 	pbm_configure(pbm_p);
-
-	/*
-	 * Determine if we need to apply the Sun Fire 15k AXQ/PIO
-	 * workaround.
-	 */
-	pci_axq_pio_limit(pbm_p);
 }
 
 int
@@ -234,7 +230,7 @@
 		 */
 		ASSERT(MUTEX_HELD(&pbm_p->pbm_pokefault_mutex));
 		ddi_fm_acc_err_get(pbm_p->pbm_excl_handle, &derr,
-				DDI_FME_VERSION);
+		    DDI_FME_VERSION);
 		ASSERT(derr.fme_flag == DDI_FM_ERR_EXPECTED);
 		derr.fme_acc_handle = pbm_p->pbm_excl_handle;
 		err = pci_pbm_err_handler(pci_p->pci_dip, &derr, (void *)pci_p,
@@ -248,7 +244,7 @@
 		membar_sync();
 		derr.fme_flag = DDI_FM_ERR_POKE;
 		err = pci_pbm_err_handler(pci_p->pci_dip, &derr, (void *)pci_p,
-				PCI_INTR_CALL);
+		    PCI_INTR_CALL);
 	} else if (pci_check_error(pci_p) != 0) {
 		/*
 		 * unprotected error, check for all errors.
@@ -257,15 +253,15 @@
 			(void) ldphysio(pci_errtrig_pa);
 		derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
 		err = pci_pbm_err_handler(pci_p->pci_dip, &derr, (void *)pci_p,
-				PCI_INTR_CALL);
+		    PCI_INTR_CALL);
 	}
 
 	if (err == DDI_FM_FATAL) {
 		if (pci_panic_on_fatal_errors) {
 			mutex_exit(&pci_p->pci_common_p->pci_fm_mutex);
 			fm_panic("%s-%d: Fatal PCI bus error(s)\n",
-				ddi_driver_name(pci_p->pci_dip),
-				ddi_get_instance(pci_p->pci_dip));
+			    ddi_driver_name(pci_p->pci_dip),
+			    ddi_get_instance(pci_p->pci_dip));
 		}
 	}
 
--- a/usr/src/uts/sun4u/io/todstarcat.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +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 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * tod driver module for Starcat
- * This module implements a soft tod since
- * starcat 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/sunddi.h>
-#include <sys/iosramio.h>
-#include <sys/domaind.h>
-
-#define	abs(x)	((x) < 0 ? -(x) : (x))
-
-#define	TODSC_SET_THRESHOLD	30
-
-static timestruc_t	todsc_get(void);
-static void		todsc_set(timestruc_t);
-static uint_t		todsc_set_watchdog_timer(uint_t);
-static uint_t		todsc_clear_watchdog_timer(void);
-static void		todsc_set_power_alarm(timestruc_t);
-static void		todsc_clear_power_alarm(void);
-static uint64_t		todsc_get_cpufrequency(void);
-
-/*
- * Module linkage information for the kernel.
- */
-static struct modlmisc modlmisc = {
-	&mod_miscops, "Soft tod module for Sun Fire 15000"
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1, (void *)&modlmisc, NULL
-};
-
-static uint32_t heartbeat = 0;
-
-int
-_init(void)
-{
-	if (strcmp(tod_module_name, "todstarcat") == 0) {
-		uint32_t ssc_time32 = 0;
-		char obp_string[40];
-
-		/*
-		 * To obtain the initial start of day time, we use an
-		 * OBP callback; this is because the iosram is not yet
-		 * accessible from the OS at this early stage of startup.
-		 */
-
-		/*
-		 * Set the string to pass to OBP
-		 * for now, we assume we always get a 32bit value
-		 */
-		(void) sprintf(obp_string, "h# %p unix-gettod",
-			(void *) &ssc_time32);
-
-		prom_interpret(obp_string, 0, 0, 0, 0, 0);
-
-		hrestime.tv_sec = (time_t)ssc_time32;
-
-		/*
-		 * A date of zero causes the root filesystem driver
-		 * to try to set the date from the last shutdown.
-		 */
-
-		/*
-		 * Check for a zero date.
-		 */
-		if (ssc_time32 == 0) {
-			cmn_err(CE_WARN, "Initial date is invalid.");
-			cmn_err(CE_CONT, "Attempting to set the date and time "
-				"based on the last shutdown.\n");
-			cmn_err(CE_CONT, "Please inspect the date and time and "
-				"correct if necessary.\n");
-		}
-
-		/*
-		 * Check that the date has not overflowed a 32-bit integer.
-		 */
-		if (TIMESPEC_OVERFLOW(&hrestime)) {
-			cmn_err(CE_WARN, "Date overflow detected.");
-			cmn_err(CE_CONT, "Attempting to set the date and time "
-				"based on the last shutdown.\n");
-			cmn_err(CE_CONT, "Please inspect the date and time and "
-				"correct if necessary.\n");
-
-			hrestime.tv_sec = (time_t)0;
-		}
-
-		tod_ops.tod_get = todsc_get;
-		tod_ops.tod_set = todsc_set;
-		tod_ops.tod_set_watchdog_timer = todsc_set_watchdog_timer;
-		tod_ops.tod_clear_watchdog_timer = todsc_clear_watchdog_timer;
-		tod_ops.tod_set_power_alarm = todsc_set_power_alarm;
-		tod_ops.tod_clear_power_alarm = todsc_clear_power_alarm;
-		tod_ops.tod_get_cpufrequency = todsc_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, "todstarcat") == 0)
-		return (EBUSY);
-	else
-		return (mod_remove(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-
-/*
- * Starcat tod_get is simplified to return hrestime and to
- * update the domain heartbeat.
- * Must be called with tod_lock held.
- */
-static timestruc_t
-todsc_get(void)
-{
-	ASSERT(MUTEX_HELD(&tod_lock));
-
-	heartbeat++;
-	(void) iosram_wr(DOMD_MAGIC, DOMD_HEARTBEAT_OFFSET,
-		sizeof (uint32_t), (caddr_t)&heartbeat);
-	return (hrestime);
-}
-
-/*
- * Must be called with tod_lock held.
- *
- * When running NTP, tod_set is called at least once per second in order
- * to update the hardware clock - for Starcat, we don't want to sync
- * the non-existent hardware clock, and only want to record significant
- * time changes on the SC (i.e. when date(1M) is run).  So, we have a
- * threshold requirement before recording the time change.
- */
-/* ARGSUSED */
-static void
-todsc_set(timestruc_t ts)
-{
-	char obp_string[40];
-
-	ASSERT(MUTEX_HELD(&tod_lock));
-
-	heartbeat++;
-	(void) iosram_wr(DOMD_MAGIC, DOMD_HEARTBEAT_OFFSET,
-		sizeof (uint32_t), (caddr_t)&heartbeat);
-
-	if (abs(hrestime.tv_sec - ts.tv_sec) > TODSC_SET_THRESHOLD) {
-		/*
-		 * Update the SSC with the new UTC domain time
-		 */
-		(void) sprintf(obp_string, "h# %x unix-settod",
-			(int)ts.tv_sec);
-
-		prom_interpret(obp_string, 0, 0, 0, 0, 0);
-#ifdef DEBUG
-		cmn_err(CE_NOTE, "todsc_set: new domain time 0x%lx\n",
-			ts.tv_sec);
-#endif
-	}
-}
-
-/*
- * No watchdog function.
- */
-/* ARGSUSED */
-static uint_t
-todsc_set_watchdog_timer(uint_t timeoutval)
-{
-	ASSERT(MUTEX_HELD(&tod_lock));
-	return (0);
-}
-
-/*
- * No watchdog function
- */
-static uint_t
-todsc_clear_watchdog_timer(void)
-{
-	ASSERT(MUTEX_HELD(&tod_lock));
-	return (0);
-}
-
-/*
- * Null function.
- */
-/* ARGSUSED */
-static void
-todsc_set_power_alarm(timestruc_t ts)
-{
-	ASSERT(MUTEX_HELD(&tod_lock));
-}
-
-/*
- * Null function
- */
-static void
-todsc_clear_power_alarm()
-{
-	ASSERT(MUTEX_HELD(&tod_lock));
-}
-
-/*
- * Get clock freq from the cpunode.  This function is only called
- * when use_stick = 0, otherwise, system_clock_freq gets used instead.
- */
-uint64_t
-todsc_get_cpufrequency(void)
-{
-	return (cpunodes[CPU->cpu_id].clock_freq);
-}
--- a/usr/src/uts/sun4u/opl/oplkmdrv/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/opl/oplkmdrv/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -21,8 +21,7 @@
 #
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
+# Copyright 2019 Peter Tribble.
 #
 #	This makefile drives the production of the oplkmdrv driver
 #	kernel module.
@@ -34,7 +33,7 @@
 #	Path to the base of the uts directory tree (usually /usr/src/uts).
 #
 UTSBASE	= ../../..
-INC_PATH	+= -I$(UTSBASE)/sun4u/starcat/
+INC_PATH	+= -I$(UTSBASE)/sun4u/opl/
 
 #
 #	Define the module and object file sets.
--- a/usr/src/uts/sun4u/opl/sys/Makefile	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/opl/sys/Makefile	Fri May 31 14:32:40 2019 +0200
@@ -21,6 +21,7 @@
 #
 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
+# Copyright 2019 Peter Tribble.
 #
 # uts/sun4u/opl/sys/Makefile
 #
@@ -45,7 +46,8 @@
 		fiomp.h		\
 		mc-opl.h	\
 		oplkm.h		\
-		oplkm_msg.h
+		oplkm_msg.h	\
+		sckm_io.h
 
 OPLMSUHDRS=	oplmsu.h	\
 		oplmsu_proto.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/sun4u/opl/sys/sckm_io.h	Fri May 31 14:32:40 2019 +0200
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright 2019 Peter Tribble.
+ */
+
+#ifndef	_SYS_SCKM_IO_H
+#define	_SYS_SCKM_IO_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * This header file defines the interface between the sckmd daemon and
+ * the sckmdrv driver.
+ */
+
+#include <sys/types.h>
+
+#define	SCKM_IOC	('s' << 8)
+
+enum sckm_ioctl {
+	SCKM_IOCTL_GETREQ = SCKM_IOC,
+	SCKM_IOCTL_STATUS
+};
+
+/*
+ * Structure passed by sckmd daemon to the sckmdrv driver during
+ * a SCKM_IOCTL_GETREQ ioctl call.
+ */
+typedef struct sckm_ioctl_getreq {
+	uint64_t transid;	/* returned by driver */
+	uint32_t type;		/* message type */
+	caddr_t buf;		/* user buffer to store msg */
+	uint32_t buf_len;	/* size of buf */
+} sckm_ioctl_getreq_t;
+
+#if defined(_SYSCALL32)
+typedef struct sckm_ioctl_getreq_32 {
+	uint64_t transid;	/* returned by driver */
+	uint32_t type;		/* message type */
+	caddr32_t buf;		/* user buffer to store msg */
+	uint32_t buf_len;	/* size of buf */
+} sckm_ioctl_getreq32_t;
+#endif /* defined(_SYSCALL32) */
+
+/*
+ * Structure passed by sckmd daemon to the sckmdrv driver during
+ * a SCKM_IOCTL_STATUS ioctl call.
+ */
+typedef struct sckm_ioctl_status {
+	uint64_t transid;		/* set by daemon */
+	uint32_t status;		/* execution status */
+	uint32_t sadb_msg_errno;	/* PF_KEY errno, if applicable */
+	uint32_t sadb_msg_version;	/* PF_KEY version, if applicable */
+} sckm_ioctl_status_t;
+
+/*
+ * Valid request types returned by the SCKM_IOCTL_GETREQ ioctl.
+ */
+#define	SCKM_IOCTL_REQ_SADB		0x0	/* SADB message */
+
+/*
+ * Valid values for the status field of the sckm_ioctl_status structure.
+ */
+#define	SCKM_IOCTL_STAT_SUCCESS		0x0	/* operation success */
+#define	SCKM_IOCTL_STAT_ERR_PFKEY	0x1	/* PF_KEY error */
+#define	SCKM_IOCTL_STAT_ERR_REQ		0x2	/* invalid request */
+#define	SCKM_IOCTL_STAT_ERR_VERSION	0x3	/* not supp. PF_KEY version */
+#define	SCKM_IOCTL_STAT_ERR_TIMEOUT	0x4	/* no response from PF_KEY */
+#define	SCKM_IOCTL_STAT_ERR_OTHER	0x5	/* other daemon error */
+#define	SCKM_IOCTL_STAT_ERR_SADB_TYPE	0x6	/* bad SADB msg type */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _SYS_SCKM_IO_H */
--- a/usr/src/uts/sun4u/starcat/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#
-#	This makefile drives the production of the sun4u starcat platform
-#	module.
-#
-#	sun4u starcat implementation architecture dependent
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE	= ../..
-
-#
-#       Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-def		:=	TARGET= def
-all		:=	TARGET= all
-install		:=	TARGET= install
-install_h	:=	TARGET= install_h
-clean		:=	TARGET= clean
-clobber		:=	TARGET= clobber
-lint		:=	TARGET= lint
-lintlib		:=	TARGET= lintlib
-modlintlib	:=	TARGET= modlintlib
-modlist		:=	TARGET= modlist
-modlist		:=	NO_STATE= -K $$MODSTATE$$$$
-clean.lint	:=	TARGET= clean.lint
-check		:=	TARGET= check
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def all clean clobber clean.lint: genassym unix .WAIT \
-		$(STARCAT_CPU_KMODS) $(STARCAT_KMODS)
-
-modlist:	unix \
-		$(STARCAT_CPU_KMODS) $(STARCAT_KMODS)
-
-lintlib:	unix
-
-modlintlib:	$(STARCAT_KMODS)
-
-IMPLEMENTED_PLATFORM	= SUNW,Sun-Fire-15000
-
-install: $(ROOT_STARCAT_DIR) $(USR_STARCAT_DIR) \
-	$(USR_STARCAT_INC_DIR) \
-	$(USR_STARCAT_SBIN_DIR) \
-	$(USR_STARCAT_LIB_DIR) \
-	$(STARCAT_CRYPTO_LINKS) \
-	genassym unix .WAIT $(STARCAT_CPU_KMODS) \
-	$(STARCAT_KMODS)
-
-genassym unix $(STARCAT_KMODS) $(STARCAT_CPU_KMODS): FRC
-	@cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET)
-
-$(STARCAT_CRYPTO_LINKS): $(ROOT_STARCAT_CRYPTO_DIR_64)
-	-$(RM) $(ROOT_STARCAT_CRYPTO_DIR_64)/$@;
-	$(SYMLINK) $(ROOT_US3_CRYPTO_LINK)/$@ $(ROOT_STARCAT_CRYPTO_DIR_64)/$@
-
-install_h check:	FRC
-	@cd sys; pwd; $(MAKE) $(TARGET)
-
-lint:	modlintlib
-
-
-#
-# The 'lint.platmod' target lints the starcat platform module against
-# the sun4u kernel.  This ends up doing all the kernel cross-checks,
-# so it takes a couple of minutes.
-# Due to the low ROI, it's not run by default, but it's a good
-# idea to run this if you change os/starcat.c.
-#
-
-LINT_LIBS	= $(LINT_LIB) \
-		  -L$(STARCAT_LINT_LIB_DIR) \
-		  -L$(LINT_LIB_DIR) $(LINT_KMODS:%=-l%) \
-		      $(CLOSED_LINT_KMODS:%=-l%) \
-		  -L$(SPARC_LIB_DIR) $(SPARC_LINTS:%=-l%)
-
-lint.platmod:   modlintlib
-	@-$(ECHO) "\nStarcat Platform-dependent module: global crosschecks:"
-	@-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2)
-
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/Makefile.files	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#	This Makefile defines all file modules for the directory
-#	uts/sun4u/starcat and its children. These are the source files which
-#	are starcat "implementation architecture" dependent.
-#
-
-#
-# Object lists
-#
-
-STARCAT_OBJS	= starcat.o starcat_asm.o plat_ecc_unum.o plat_ecc_dimm.o
-
-#
-# Starcat specific driver related modules
-#
-
-AXQ_OBJS +=	axq.o
-CVC_OBJS +=	cvc.o
-CVCREDIR_OBJS +=	cvcredir.o
-DMAN_OBJS +=	dman.o dman_domain.o
-DRMACH_OBJS +=	drmach.o drmach_asm.o dr_util.o drmach_err.o
-FCGP2_OBJS +=	fcgp2.o
-GPTWO_PCI_OBJS +=	gptwo_pci.o
-IOSRAM_OBJS +=	iosram.o
-MBOXSC_OBJS +=	mboxsc.o
-SC_GPTWO_OBJS +=	sc_gptwocfg.o
-SC_PCICFG_OBJS +=	sc_pcicfg.o
-SCHPC_OBJS +=	schpc.o
-SCKMDRV_OBJS += sckmdrv.o
-SCOSMB_OBJS +=	scosmb.o
-
-#
-# Miscellaneous
-#
-INC_PATH	+= -I$(UTSBASE)/sun4u/starcat
-INC_PATH	+= -I$(UTSBASE)/sun4u/starcat/sys
-
-#
-# 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
--- a/usr/src/uts/sun4u/starcat/Makefile.rules	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +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/starcat and its children.
-#
-
-#
-# 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
-#
-
-DRMACH_IL=$(OBJS_DIR)/drmach.il
-
-$(OBJS_DIR)/drmach.o	:= CC_XARCH_32 = -xarch=v8plusa
-$(OBJS_DIR)/%.o:		$(UTSBASE)/sun4u/starcat/io/%.c $(DRMACH_IL)
-	$(COMPILE.c) $(DRMACH_IL) -o $@ $<
-	$(CTFCONVERT_O)
-
-$(OBJS_DIR)/%.o:		$(UTSBASE)/sun4u/starcat/os/%.c
-	$(COMPILE.c) -o $@ $<
-	$(CTFCONVERT_O)
-
-$(OBJS_DIR)/%.o:		$(UTSBASE)/sun4u/starcat/ml/%.s
-	$(COMPILE.s) -o $@ $<
-
-STARCAT_IO=$(UTSBASE)/sun4u/starcat/io
-
-CLEANFILES += $(STARCAT_IO)/drmach_err.c
-
-$(STARCAT_IO)/drmach_err.c: $(SBDGENERR) $(SBD_IOCTL)
-	$(RM) $@
-	$(SBDGENERRCMD) ESTC <$(SBD_IOCTL) >$@
-
-# inline stuff
-
-CLEANFILES += $(DRMACH_IL)
-
-$(DRMACH_IL):		$(UTSBASE)/sun4u/starcat/ml/drmach.il.cpp
-	$(IL_CPP) $(UTSBASE)/sun4u/starcat/ml/drmach.il.cpp > $@
-
-#
-#	Section 1b: Lint object build rules
-#
-
-$(LINTS_DIR)/%.ln:		$(UTSBASE)/sun4u/starcat/os/%.c
-	@($(LHEAD) $(LINT.c) $< $(LTAIL))
-
-$(LINTS_DIR)/drmach.ln		:= LINTFLAGS += -I../sys
-$(LINTS_DIR)/sc_gptwoctfg.ln	:= LINTFLAGS += -I../sys
-
-$(LINTS_DIR)/%.ln:		$(UTSBASE)/sun4u/starcat/io/%.c
-	@($(LHEAD) $(LINT.c) $< $(LTAIL))
-
-$(LINTS_DIR)/%.ln:		$(UTSBASE)/sun4u/starcat/ml/%.s
-	@($(LHEAD) $(LINT.s) $< $(LTAIL))
--- a/usr/src/uts/sun4u/starcat/Makefile.starcat	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#	Global definitions for sun4u starcat implementation specific modules.
-#
-
-#
-#	Define directories.
-#
-ROOT_STARCAT_DIR	= $(ROOT_PLAT_DIR)/SUNW,Sun-Fire-15000
-ROOT_STARCAT_MOD_DIR	= $(ROOT_STARCAT_DIR)/kernel
-ROOT_STARCAT_KERN_DIR_32 = $(ROOT_STARCAT_MOD_DIR)
-ROOT_STARCAT_KERN_DIR_64 = $(ROOT_STARCAT_MOD_DIR)/$(SUBDIR64)
-ROOT_STARCAT_MISC_DIR_32 = $(ROOT_STARCAT_MOD_DIR)/misc
-ROOT_STARCAT_MISC_DIR_64 = $(ROOT_STARCAT_MOD_DIR)/misc/$(SUBDIR64)
-ROOT_STARCAT_DRV_DIR_32 = $(ROOT_STARCAT_MOD_DIR)/drv
-ROOT_STARCAT_DRV_DIR_64 = $(ROOT_STARCAT_MOD_DIR)/drv/$(SUBDIR64)
-ROOT_STARCAT_CPU_DIR_32 = $(ROOT_STARCAT_MOD_DIR)/cpu
-ROOT_STARCAT_CPU_DIR_64 = $(ROOT_STARCAT_MOD_DIR)/cpu/$(SUBDIR64)
-ROOT_STARCAT_CRYPTO_DIR_32 = $(ROOT_STARCAT_MOD_DIR)/crypto
-ROOT_STARCAT_CRYPTO_DIR_64 = $(ROOT_STARCAT_MOD_DIR)/crypto/$(SUBDIR64)
-
-ROOT_STARCAT_KERN_DIR	= $(ROOT_STARCAT_KERN_DIR_$(CLASS))
-ROOT_STARCAT_MISC_DIR	= $(ROOT_STARCAT_MISC_DIR_$(CLASS))
-ROOT_STARCAT_DRV_DIR	= $(ROOT_STARCAT_DRV_DIR_$(CLASS))
-ROOT_STARCAT_CPU_DIR	= $(ROOT_STARCAT_CPU_DIR_$(CLASS))
-ROOT_STARCAT_CRYPTO_DIR	= $(ROOT_STARCAT_CRYPTO_DIR_$(CLASS))
-
-ROOT_PLAT_MOD_DIRS	+= $(ROOT_STARCAT_MOD_DIR)
-ROOT_PLAT_MISC_DIRS_32	+= $(ROOT_STARCAT_MISC_DIR_32)
-
-USR_STARCAT_DIR	= $(USR_PLAT_DIR)/SUNW,Sun-Fire-15000
-USR_STARCAT_LIB_DIR	= $(USR_STARCAT_DIR)/lib
-USR_STARCAT_SBIN_DIR	= $(USR_STARCAT_DIR)/sbin
-USR_STARCAT_INC_DIR	= $(USR_STARCAT_DIR)/include
-USR_STARCAT_ISYS_DIR	= $(USR_STARCAT_INC_DIR)/sys
-
-STARCAT_LINT_LIB_DIR	= $(UTSBASE)/$(PLATFORM)/starcat/lint-libs/$(OBJS_DIR)
-
-#
-#	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/starcat/Makefile.files
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/Makefile.sun4u
-
-#
-#	Define modules
-#
-STARCAT_KMODS	+= axq
-STARCAT_KMODS	+= cvc
-STARCAT_KMODS	+= cvcredir
-STARCAT_KMODS	+= dman
-STARCAT_KMODS	+= dr
-STARCAT_KMODS	+= drmach
-STARCAT_KMODS	+= fcgp2
-STARCAT_KMODS	+= gptwo_pci
-STARCAT_KMODS	+= iosram
-STARCAT_KMODS	+= mboxsc
-STARCAT_KMODS	+= platmod
-STARCAT_KMODS	+= sc_gptwocfg
-STARCAT_KMODS	+= schpc
-STARCAT_KMODS	+= sckmdrv
-STARCAT_KMODS	+= scosmb
-
-#
-#	Define CPU modules.
-#
-STARCAT_CPU_KMODS	+= cheetah cheetahplus
-
-#
-#	Links to UltraSparc III crypto modules
-#
-STARCAT_CRYPTO_LINKS	= aes
-
-#
-#	Everybody needs to know how to build modstubs.o and to locate unix.o
-#
-UNIX_DIR	= $(UTSBASE)/$(PLATFORM)/starcat/unix
-MODSTUBS_DIR	= $(UNIX_DIR)
-DSF_DIR		= $(UTSBASE)/$(PLATFORM)/starcat/genassym
-LINTS_DIR	= $(OBJS_DIR)
-LINT_LIB_DIR	= $(UTSBASE)/$(PLATFORM)/starcat/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 -DMP -DMIXEDCPU_DR_SUPPORTED
-MACHINE_DEFS	+= -D_CPU_SIGNATURE
-
-#
-#	Define platform specific value
-#
-MACHINE_DEFS	+= -DNCPU=558
-MACHINE_DEFS	+= -DMAX_CPU_CHIPID=554
-MACHINE_DEFS	+= -DMAX_UPA=1024
-MACHINE_DEFS	+= -DIGN_SIZE=10
-MACHINE_DEFS	+= -DMAX_MEM_NODES=18
-
-#
-#	Define for inline pre-processing since
-#	cpp not smart about v9 yet.
-#	It's not smart about __sparc either since it only predefines sparc.
-CPP_DEFS_32	= -D__sparc
-CPP_DEFS_64	= -D__sparc -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
--- a/usr/src/uts/sun4u/starcat/Makefile.targ	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +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 starcat implementation specific modules.
-#
-
-.KEEP_STATE:
-
-#
-# Rules for implementation subdirectories.
-#
-$(ROOT_STARCAT_DIR): $(ROOT_PLAT_DIR)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_MOD_DIR): $(ROOT_STARCAT_DIR)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_CPU_DIR_32): $(ROOT_STARCAT_MOD_DIR)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_CPU_DIR_64): $(ROOT_STARCAT_CPU_DIR_32)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_DRV_DIR_32): $(ROOT_STARCAT_MOD_DIR)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_DRV_DIR_64): $(ROOT_STARCAT_DRV_DIR_32)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_MISC_DIR_32): $(ROOT_STARCAT_MOD_DIR)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_MISC_DIR_64): $(ROOT_STARCAT_MISC_DIR_32)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_CRYPTO_DIR_32): $(ROOT_STARCAT_MOD_DIR)
-	-$(INS.dir)
-
-$(ROOT_STARCAT_CRYPTO_DIR_64): $(ROOT_STARCAT_CRYPTO_DIR_32)
-	-$(INS.dir)
-
-$(USR_STARCAT_DIR): $(USR_PLAT_DIR)
-	-$(INS.dir)
-
-$(USR_STARCAT_INC_DIR): $(USR_STARCAT_DIR)
-	$(INS.slink4)
-
-$(USR_STARCAT_SBIN_DIR): $(USR_STARCAT_DIR)
-	-$(INS.slink5)
-
-$(USR_STARCAT_LIB_DIR): $(USR_STARCAT_DIR)
-	-$(INS.dir)
-
-$(USR_STARCAT_ISYS_DIR): $(USR_STARCAT_INC_DIR)
-	$(INS.dir)
-
-$(ROOT_STARCAT_KERN_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARCAT_KERN_DIR) FRC
-	$(INS.file)
-
-$(ROOT_STARCAT_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARCAT_DRV_DIR) FRC
-	$(INS.file)
-
-$(ROOT_STARCAT_CPU_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARCAT_CPU_DIR) FRC
-	$(INS.file)
-
-$(ROOT_STARCAT_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARCAT_MISC_DIR) FRC
-	$(INS.file)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sun4u/ngdr/Makefile.rules
-include $(UTSBASE)/sun4u/starcat/Makefile.rules
-include $(UTSBASE)/sun4u/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/axq/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#	This makefile drives the production of the Starcat AXQ
-#	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		= axq
-OBJECTS		= $(AXQ_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(AXQ_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_DRV_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# Turn on doubleword alignment for 64 bit registers
-#
-CFLAGS += -dalign
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS)
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/cheetah/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +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 Starcat specific
-#	UltraSPARC-III driver module.
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE	= ../../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= SUNW,UltraSPARC-III
-OBJECTS		= $(CHEETAH_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(CHEETAH_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_CPU_DIR)/$(MODULE)
-ROOTSOFTLINKS	= $(SOFTLINKS:%=$(ROOT_STARCAT_CPU_DIR)/%)
-
-CPU_DIR		= .
-HERE		= ../cheetah
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Override defaults
-#
-CLEANFILES	+= $(CPULIB) $(SYM_MOD)
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(SYM_MOD)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= def $(BINARY) $(ROOTMODULE) $(ROOTSOFTLINKS)
-
-#
-#       Overrides
-#
-ALL_BUILDS      = $(ALL_BUILDSONLY64)
-DEF_BUILDS      = $(DEF_BUILDSONLY64)
-CLEANLINTFILES  += $(LINT32_FILES)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-CERRWARN	+= -_gcc=-Wno-parentheses
-CERRWARN	+= -_gcc=-Wno-uninitialized
-CERRWARN	+= -_gcc=-Wno-type-limits
-CERRWARN	+= -_gcc=-Wno-clobbered
-
-#
-# cpu-module-specific flags
-#
-CPPFLAGS += -DCPU_MODULE -DCHEETAH
-AS_CPPFLAGS += -DCPU_MODULE -DCHEETAH
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS) lint32
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-$(CPULIB):	$(OBJECTS)
-	$(BUILD.SO) $(OBJECTS)
-
-$(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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/cheetahplus/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +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 Starcat specific
-#	UltraSPARC-III+ driver module.
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE	= ../../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= SUNW,UltraSPARC-III+
-OBJECTS		= $(CHEETAHPLUS_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(CHEETAHPLUS_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_CPU_DIR)/$(MODULE)
-SOFTLINKS	= SUNW,UltraSPARC-IV SUNW,UltraSPARC-IV+
-ROOTSOFTLINKS	= $(SOFTLINKS:%=$(ROOT_STARCAT_CPU_DIR)/%)
-
-CPU_DIR		= .
-HERE		= ../cheetahplus
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Override defaults
-#
-CLEANFILES	+= $(CPULIB) $(SYM_MOD)
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(SYM_MOD)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= def $(BINARY) $(ROOTMODULE) $(ROOTSOFTLINKS)
-
-#
-#       Overrides
-#
-ALL_BUILDS      = $(ALL_BUILDSONLY64)
-DEF_BUILDS      = $(DEF_BUILDSONLY64)
-CLEANLINTFILES  += $(LINT32_FILES)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE) -DCHEETAH -DCHEETAH_PLUS -DCPU_IMP_L1_CACHE_PARITY \
-	     -DCPU_IMP_ECACHE_ASSOC -DCPU_IMP_DUAL_PAGESIZE -DCPU_IMP_AFSR_EXT
-ASFLAGS +=  -DCHEETAH -DCHEETAH_PLUS -DCPU_IMP_L1_CACHE_PARITY \
-	    -DCPU_IMP_ECACHE_ASSOC -DCPU_IMP_DUAL_PAGESIZE -DCPU_IMP_AFSR_EXT
-
-CERRWARN	+= -_gcc=-Wno-parentheses
-CERRWARN	+= -_gcc=-Wno-uninitialized
-CERRWARN	+= -_gcc=-Wno-unused-variable
-CERRWARN	+= -_gcc=-Wno-type-limits
-CERRWARN	+= -_gcc=-Wno-clobbered
-
-#
-# cpu-module-specific flags
-#
-CPPFLAGS += -DCPU_MODULE -DCHEETAH -DCHEETAH_PLUS -DCPU_IMP_L1_CACHE_PARITY \
-	    -DCPU_IMP_ECACHE_ASSOC -DCPU_IMP_DUAL_PAGESIZE -DCPU_IMP_AFSR_EXT
-AS_CPPFLAGS += -DCPU_MODULE -DCHEETAH -DCHEETAH_PLUS -DCPU_IMP_L1_CACHE_PARITY \
-	       -DCPU_IMP_ECACHE_ASSOC -DCPU_IMP_DUAL_PAGESIZE -DCPU_IMP_AFSR_EXT
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS) lint32
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS)
-
-$(CPULIB):	$(OBJECTS)
-	$(BUILD.SO) $(OBJECTS)
-
-$(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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/cvc/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#	This makefile drives the production of the cvc driver module.
-#
-#	sun4u starcat 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_STARCAT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/sun4u/starcat/io
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) .WAIT $(ROOT_CONFFILE)
-
-#
-#       Overrides
-#
-ALL_BUILDS      = $(ALL_BUILDSONLY64)
-DEF_BUILDS      = $(DEF_BUILDSONLY64)
-CLEANLINTFILES  += $(LINT32_FILES)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Ndrv/iosram -Ndrv/sbbc
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/cvcredir/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#	This makefile drives the production of the cvcredir driver module.
-#
-#	sun4u starcat 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_STARCAT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/sun4u/starcat/io
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) .WAIT $(ROOT_CONFFILE)
-
-#
-#       Overrides
-#
-ALL_BUILDS      = $(ALL_BUILDSONLY64)
-DEF_BUILDS      = $(DEF_BUILDSONLY64)
-CLEANLINTFILES  += $(LINT32_FILES)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Ndrv/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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/dman/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the pruction of the Management Network
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= dman
-OBJECTS		= $(DMAN_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(DMAN_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/sun4u/starcat/io
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-LDFLAGS += -dy -Ndrv/ip -Ndrv/eri -Ndrv/iosram -Nmisc/mboxsc
-
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-uninitialized
-CERRWARN += -_gcc=-Wno-unused-label
-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)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/dr/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 dr driver module.
-#
-#	sun4u starcat 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		= dr
-OBJECTS		= $(DR_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(DR_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/sun4u/starcat/io
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE) -I../sys
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/drmach
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/drmach/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the production of the drmach loadable module.
-#
-#	sun4u starcat 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		= drmach 
-OBJECTS		= $(DRMACH_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(DRMACH_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-MACHINE_DEFS    += -DCHEETAH_PLUS
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE) -I../sys -I$(UTSBASE)/sun4u/starcat/sys
-CERRWARN += -_gcc=-Wno-parentheses
-CERRWARN += -_gcc=-Wno-unused-variable
-CERRWARN += -_gcc=-Wno-uninitialized
-CERRWARN += -_gcc=-Wno-type-limits
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/mboxsc -Ndrv/iosram -Ndrv/axq -Nmisc/fcpci \
-	   -Nmisc/fcodem -Nmisc/sc_gptwocfg -Ndrv/schpc
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/fcgp2/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the production of the fcgp2
-#	miscellaneous module.
-#
-#	sun4u starcat 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		= fcgp2
-OBJECTS		= $(FCGP2_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(FCGP2_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/fcodem -Nmisc/busra
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/genassym/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-#
-#
-#pragma 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 starcat 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/starcat/Makefile.starcat
-
-#
-#	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
-ALL_BUILDS      = $(ALL_BUILDSONLY64)
-DEF_BUILDS      = $(DEF_BUILDSONLY64)
-CLEANLINTFILES  += $(LINT32_FILES)
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/gptwo_pci/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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 makefile drives the production of the pci/schizo portion of
-#	of the Safari Configurator. 
-#
-#	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		= gptwo_pci
-OBJECTS		= $(GPTWO_PCI_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(GPTWO_PCI_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	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/starcat/io/gptwo_pci.il
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/gptwocfg -Nmisc/fcgp2 -Nmisc/fcodem -Nmisc/busra
-
-#
-# 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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/io/axq.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1746 +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.
- */
-
-
-
-#include <sys/types.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/obpdefs.h>
-#include <sys/cmn_err.h>
-#include <sys/errno.h>
-#include <sys/kmem.h>
-#include <sys/debug.h>
-#include <sys/sysmacros.h>
-#include <sys/autoconf.h>
-#include <sys/modctl.h>
-#include <sys/sunndi.h>
-
-#include <sys/axq.h>
-#include <sys/promif.h>
-#include <sys/cpuvar.h>
-#include <sys/starcat.h>
-#include <sys/callb.h>
-
-#define	REG_ADDR(b, o)	(uint32_t *)((caddr_t)(b) + (o))
-
-/*
- * Function prototypes
- */
-
-/* autoconfig entry point function definitions */
-static int axq_attach(dev_info_t *, ddi_attach_cmd_t);
-static int axq_detach(dev_info_t *, ddi_detach_cmd_t);
-static int axq_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
-
-/* internal axq definitions */
-static void axq_init(struct axq_soft_state *);
-static void axq_init_local(struct axq_local_regs *);
-
-/* axq kstats */
-static void axq_add_picN_kstats(dev_info_t *dip);
-static void axq_add_kstats(struct axq_soft_state *);
-static int axq_counters_kstat_update(kstat_t *, int);
-
-/*
- * Configuration data structures
- */
-static struct cb_ops axq_cb_ops = {
-	nulldev,			/* open */
-	nulldev,			/* close */
-	nulldev,			/* strategy */
-	nulldev,			/* print */
-	nodev,				/* dump */
-	nulldev,			/* read */
-	nulldev,			/* write */
-	nulldev,			/* ioctl */
-	nodev,				/* devmap */
-	nodev,				/* mmap */
-	nodev,				/* segmap */
-	nochpoll,			/* poll */
-	ddi_prop_op,			/* cb_prop_op */
-	0,				/* streamtab */
-	D_MP | D_NEW,			/* Driver compatibility flag */
-	CB_REV,				/* rev */
-	nodev,				/* cb_aread */
-	nodev				/* cb_awrite */
-};
-
-static struct dev_ops axq_ops = {
-	DEVO_REV,			/* rev */
-	0,				/* refcnt  */
-	axq_getinfo,			/* getinfo */
-	nulldev,			/* identify */
-	nulldev,			/* probe */
-	axq_attach,			/* attach */
-	axq_detach,			/* detach */
-	nulldev,			/* reset */
-	&axq_cb_ops,			/* cb_ops */
-	(struct bus_ops *)0,		/* bus_ops */
-	nulldev,			/* power */
-	ddi_quiesce_not_supported,	/* devo_quiesce */
-};
-
-
-/*
- * AXQ globals
- */
-struct axq_soft_state *axq_array[AXQ_MAX_EXP][AXQ_MAX_SLOT_PER_EXP];
-krwlock_t axq_array_lock;
-struct axq_local_regs axq_local;
-int use_axq_iopause = 1;	/* enable flag axq iopause by default */
-/*
- * If non-zero, iopause will be asserted during DDI_SUSPEND.
- * Clients using the axq_iopause_*_all interfaces should set this to zero.
- */
-int axq_suspend_iopause = 1;
-
-/*
- * loadable module support
- */
-extern struct mod_ops mod_driverops;
-
-static struct modldrv modldrv = {
-	&mod_driverops,		/* Type of module.  This one is a driver */
-	"AXQ driver",	/* name of module */
-	&axq_ops,		/* driver ops */
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modldrv,
-	NULL
-};
-
-static void *axq_softp;
-
-/*
- * AXQ Performance counters
- * We statically declare a array of the known
- * AXQ event-names and event masks. The number
- * of events in this array is AXQ_NUM_EVENTS.
- */
-static axq_event_mask_t axq_events[AXQ_NUM_EVENTS] = {
-	{"count_clk", COUNT_CLK}, {"freeze_cnt", FREEZE_CNT},
-	{"ha_input_fifo", HA_INPUT_FIFO}, {"ha_intr_info", HA_INTR_INFO},
-	{"ha_pio_fifo", HA_PIO_FIFO}, {"ha_adr_fifo_lk3", HA_ADR_FIFO_LK3},
-	{"ha_adr_fifo_lk2", HA_ADR_FIFO_LK2},
-	{"ha_adr_fifo_lk1", HA_ADR_FIFO_LK1},
-	{"ha_adr_fifo_lk0", HA_ADR_FIFO_LK0},
-	{"ha_dump_q", HA_DUMP_Q},
-	{"ha_rd_f_stb_q", HA_RD_F_STB_Q},
-	{"ha_dp_wr_q", HA_DP_WR_Q},
-	{"ha_int_q", HA_INT_Q},
-	{"ha_wrb_q", HA_WRB_Q},
-	{"ha_wr_mp_q", HA_WR_MP_Q},
-	{"ha_wrtag_q", HA_WRTAG_Q},
-	{"ha_wt_wait_fifo", HA_WT_WAIT_FIFO},
-	{"ha_wrb_stb_fifo", HA_WRB_STB_FIFO},
-	{"ha_ap0_q", HA_AP0_Q},
-	{"ha_ap1_q", HA_AP1_Q},
-	{"ha_new_wr_q", HA_NEW_WR_Q},
-	{"ha_dp_rd_q", HA_DP_RD_Q},
-	{"ha_unlock_q", HA_UNLOCK_Q},
-	{"ha_cdc_upd_q", HA_CDC_UPD_Q},
-	{"ha_ds_q", HA_DS_Q},
-	{"ha_unlk_wait_q", HA_UNLK_WAIT_Q},
-	{"ha_rd_mp_q", HA_RD_MP_Q},
-	{"l2_io_q", L2_IO_Q},
-	{"l2_sb_q", L2_SB_Q},
-	{"l2_ra_q", L2_RA_Q},
-	{"l2_ha_q", L2_HA_Q},
-	{"l2_sa_q", L2_SA_Q},
-	{"ra_wait_fifo", RA_WAIT_FIFO},
-	{"ra_wrb_inv_fifo", RA_WRB_INV_FIFO},
-	{"ra_wrb_fifo", RA_WRB_FIFO},
-	{"ra_cc_ptr_fifo", RA_CC_PTR_FIFO},
-	{"ra_io_ptr_fifo", RA_IO_PTR_FIFO},
-	{"ra_int_ptr_fifo", RA_INT_PTR_FIFO},
-	{"ra_rp_q", RA_RP_Q},
-	{"ra_wrb_rp_q", RA_WRB_RP_Q},
-	{"ra_dp_q", RA_DP_Q},
-	{"ra_dp_stb_q", RA_DP_STB_Q},
-	{"ra_gtarg_q", RA_GTARG_Q},
-	{"sdc_recv_q",	SDC_RECV_Q},
-	{"sdc_redir_io_q", SDC_REDIR_IO_Q},
-	{"sdc_redir_sb_q", SDC_REDIR_SB_Q},
-	{"sdc_outb_io_q", SDC_OUTB_IO_Q},
-	{"sdc_outb_sb_q", SDC_OUTB_SB_Q},
-	{"sa_add1_input_q", SA_ADD1_INPUT_Q},
-	{"sa_add2_input_q", SA_ADD2_INPUT_Q},
-	{"sa_inv_q", SA_INV_Q},
-	{"sa_no_inv_q", SA_NO_INV_Q},
-	{"sa_int_dp_q", SA_INT_DP_Q},
-	{"sa_dp_q", SA_DP_Q},
-	{"sl_wrtag_q", SL_WRTAG_Q},
-	{"sl_rto_dp_q", SL_RTO_DP_Q},
-	{"syreg_input_q", SYSREG_INPUT_Q},
-	{"sdi_sys_status1", SDI_SYS_STATUS1},
-	{"sdi_sys_status0", SDI_SYS_STATUS0},
-	{"cdc_hits", CDC_HITS},
-	{"total_cdc_read", TOTAL_CDC_READ},
-	{"ha_watranid_sd", HA_WATRANID_SD},
-	{"ha_stb_sd", HA_STB_SD},
-	{"ha_l2_irq_sd", HA_L2_IRQ_SD},
-	{"ha_sl_wrtag_sd", HA_SL_WRTAG_SD},
-	{"aa_home_cc_full", AA_HOME_CC_FULL},
-	{"aa_home_io_full", AA_HOME_IO_FULL},
-	{"aa_slave_full", AA_SLAVE_FULL},
-	{"aa_rp_full", AA_RP_FULL}
-};
-
-static kstat_t *axq_picN_ksp[AXQ_NUM_PICS];	/* picN kstats */
-static int axq_attachcnt = 0;		/* # of instances attached */
-static kmutex_t axq_attachcnt_lock;	/* lock for attachcnt */
-
-static int axq_map_phys(dev_info_t *, struct regspec *,  caddr_t *,
-    ddi_device_acc_attr_t *, ddi_acc_handle_t *);
-static void axq_unmap_phys(ddi_acc_handle_t *);
-
-int starcat_axq_pio_workaround(dev_info_t *);
-static int axq_slot1_idle(struct axq_soft_state *);
-
-static boolean_t axq_panic_callb(void *, int);
-static callb_id_t axq_panic_cb_id;
-
-/*
- * These are the module initialization routines.
- */
-
-int
-_init(void)
-{
-	int error;
-
-	if ((error = ddi_soft_state_init(&axq_softp,
-	    sizeof (struct axq_soft_state), 1)) != 0)
-		return (error);
-
-	rw_init(&axq_array_lock, NULL, RW_DEFAULT, NULL);
-
-	mutex_init(&axq_local.axq_local_lock, NULL, MUTEX_DRIVER, NULL);
-
-	mutex_init(&axq_attachcnt_lock, NULL, MUTEX_DRIVER, NULL);
-
-	axq_local.initflag = 0;
-
-	if ((error = mod_install(&modlinkage)) != 0) {
-		ddi_soft_state_fini(&axq_softp);
-		mutex_destroy(&axq_attachcnt_lock);
-		mutex_destroy(&axq_local.axq_local_lock);
-		rw_destroy(&axq_array_lock);
-		return (error);
-	}
-
-	axq_panic_cb_id = callb_add(axq_panic_callb, (void *)NULL,
-	    CB_CL_PANIC, "axq_panic");
-
-	return (0);
-}
-
-int
-_fini(void)
-{
-	int error;
-
-	if ((error = mod_remove(&modlinkage)) != 0)
-		return (error);
-
-	ddi_soft_state_fini(&axq_softp);
-	mutex_destroy(&axq_attachcnt_lock);
-	mutex_destroy(&axq_local.axq_local_lock);
-	rw_destroy(&axq_array_lock);
-
-	(void) callb_delete(axq_panic_cb_id);
-
-	return (0);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-static int
-axq_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-	int instance;
-	struct axq_soft_state *softsp;
-	ddi_device_acc_attr_t attr;
-	extern uint64_t va_to_pa(void *);
-
-	instance = ddi_get_instance(devi);
-
-	switch (cmd) {
-	case DDI_ATTACH:
-		break;
-
-	case DDI_RESUME:
-		/*
-		 * Reenable the axq io pause if it is
-		 * employed. See the DDI_SUSPEND comments
-		 */
-		softsp = ddi_get_soft_state(axq_softp, instance);
-		if (softsp->slotnum && softsp->paused && use_axq_iopause &&
-		    axq_suspend_iopause) {
-			*softsp->axq_domain_ctrl &= ~AXQ_DOMCTRL_PAUSE;
-			softsp->paused = 0;
-		}
-		return (DDI_SUCCESS);
-
-	default:
-		return (DDI_FAILURE);
-	}
-
-	if (ddi_soft_state_zalloc(axq_softp, instance) != DDI_SUCCESS)
-		return (DDI_FAILURE);
-
-	softsp = ddi_get_soft_state(axq_softp, instance);
-
-	/* Set the dip in the soft state */
-	softsp->dip = devi;
-
-	/* Get the "portid" property */
-	if ((softsp->portid = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
-	    DDI_PROP_DONTPASS, "portid", -1)) == -1) {
-		cmn_err(CE_WARN, "Unable to retrieve safari portid"
-		    "property.");
-		goto bad;
-	}
-
-	softsp->expid = softsp->portid >> 5;
-
-	/*
-	 * derive the slot # from the portid - for starcat, it is
-	 * either 0 or 1 based on the lsb of the axq portid.
-	 */
-	softsp->slotnum = softsp->portid & 0x1;
-
-	/*
-	 * map in the regs. There are two regspecs - one
-	 * in safari config space and the other in local space.
-	 */
-	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
-	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
-	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
-	if (ddi_regs_map_setup(softsp->dip, 0, &softsp->address, 0, 0,
-	    &attr, &softsp->ac0) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s%d: unable to map reg set 0\n",
-		    ddi_get_name(softsp->dip),
-		    ddi_get_instance(softsp->dip));
-		goto bad;
-	}
-
-	/*
-	 * This is a hack for support DR copy rename scripting
-	 * Get the physical address of the start of the
-	 * AXQ config space and save it.
-	 */
-	softsp->axq_phyaddr = va_to_pa((caddr_t)softsp->address);
-
-	axq_init(softsp);
-
-	/*
-	 * Map in the regs for local space access
-	 * This is global for all axq instances.
-	 * Make sure that some axq instance does
-	 * it for the rest of the gang..
-	 * Note that this mapping is never removed.
-	 */
-	mutex_enter(&axq_local.axq_local_lock);
-	if (!axq_local.initflag) {
-		/* initialize and map in the local space */
-		if (ddi_regs_map_setup(softsp->dip, 1,
-		    &axq_local.laddress, 0, 0,
-		    &attr, &axq_local.ac) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s%d: unable to map reg set 1\n",
-			    ddi_get_name(softsp->dip),
-			    ddi_get_instance(softsp->dip));
-			ddi_regs_map_free(&softsp->ac0);
-			mutex_exit(&axq_local.axq_local_lock);
-			goto bad;
-		}
-		axq_init_local(&axq_local);
-		axq_local.initflag = 1;
-	}
-	mutex_exit(&axq_local.axq_local_lock);
-
-	mutex_init(&softsp->axq_lock, NULL, MUTEX_DRIVER, NULL);
-
-	/* update the axq array for this new instance */
-	rw_enter(&axq_array_lock, RW_WRITER);
-	ASSERT(axq_array[softsp->expid][softsp->slotnum] == NULL);
-	axq_array[softsp->expid][softsp->slotnum] = softsp;
-	rw_exit(&axq_array_lock);
-
-	axq_add_kstats(softsp);
-
-	ddi_report_dev(devi);
-
-	return (DDI_SUCCESS);
-
-bad:
-	ddi_soft_state_free(axq_softp, instance);
-	return (DDI_FAILURE);
-}
-
-
-static void
-axq_init(struct axq_soft_state *softsp)
-{
-	int i;
-
-	/*
-	 * Setup the AXQ registers
-	 * Some offsets and availability are dependent on the slot type
-	 */
-	if (softsp->slotnum == 0) {
-		/* This is a slot type 0 AXQ */
-		softsp->axq_domain_ctrl = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_DOMCTRL);
-		softsp->axq_cdc_addrtest = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_ADR_TEST);
-		softsp->axq_cdc_ctrltest = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_CTL_TEST);
-		softsp->axq_cdc_datawrite0 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_DATA_WR0);
-		softsp->axq_cdc_datawrite1 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_DATA_WR1);
-		softsp->axq_cdc_datawrite2 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_DATA_WR2);
-		softsp->axq_cdc_datawrite3 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_DATA_WR3);
-		softsp->axq_cdc_counter = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_CNT_TEST);
-		softsp->axq_cdc_readdata0 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_RD_DATA0);
-		softsp->axq_cdc_readdata1 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_RD_DATA1);
-		softsp->axq_cdc_readdata2 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_RD_DATA2);
-		softsp->axq_cdc_readdata3 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_CDC_RD_DATA3);
-		softsp->axq_pcr = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_PERFCNT_SEL);
-		softsp->axq_pic0 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_PERFCNT0);
-		softsp->axq_pic1 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_PERFCNT1);
-		softsp->axq_pic2 = REG_ADDR(softsp->address,
-		    AXQ_SLOT0_PERFCNT2);
-		softsp->axq_nasm = REG_ADDR(softsp->address, AXQ_SLOT0_NASM);
-	} else {
-		/* slot type 1 AXQ */
-		softsp->axq_domain_ctrl = REG_ADDR(softsp->address,
-		    AXQ_SLOT1_DOMCTRL);
-		softsp->axq_pcr = REG_ADDR(softsp->address,
-		    AXQ_SLOT1_PERFCNT_SEL);
-		softsp->axq_pic0 = REG_ADDR(softsp->address,
-		    AXQ_SLOT1_PERFCNT0);
-		softsp->axq_pic1 = REG_ADDR(softsp->address,
-		    AXQ_SLOT1_PERFCNT1);
-		softsp->axq_pic2 = REG_ADDR(softsp->address,
-		    AXQ_SLOT1_PERFCNT2);
-		softsp->axq_nasm = REG_ADDR(softsp->address, AXQ_SLOT1_NASM);
-	}
-
-	/* setup CASM slots */
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		softsp->axq_casm_slot[i] = REG_ADDR(softsp->address,
-		    (AXQ_CASM_SLOT_START + AXQ_REGOFF(i)));
-	}
-
-	/* setup SDI timeout register accesses */
-	softsp->axq_sdi_timeout_rd = REG_ADDR(softsp->address,
-	    AXQ_SLOT_SDI_TIMEOUT_RD);
-	softsp->axq_sdi_timeout_rdclr = REG_ADDR(softsp->address,
-	    AXQ_SLOT_SDI_TIMEOUT_RDCLR);
-
-	/*
-	 * Save the CDC state (enabled or disabled)
-	 * as originally setup by Post.
-	 */
-	if (softsp->slotnum == 0) {
-		softsp->axq_cdc_state = *softsp->axq_cdc_ctrltest &
-		    AXQ_CDC_DIS;
-	}
-
-#ifndef _AXQ_LOCAL_ACCESS_SUPPORTED
-	/*
-	 * Setup cpu2ssc intr register in explicit expander
-	 * space. Local space addressing for this is broken,
-	 * we'll use explicit addressing for now.
-	 */
-	softsp->axq_cpu2ssc_intr = REG_ADDR(softsp->address,
-	    AXQ_SLOT_CPU2SSC_INTR);
-#endif /* _AXQ_LOCAL_ACCESS_SUPPORTED */
-}
-
-
-static void
-axq_init_local(struct axq_local_regs *localregs)
-{
-	/*
-	 * local access to cpu2ssc intr register will
-	 * be the only one that may work properly in the
-	 * next revision of the AXQ asics.
-	 * Set it up here for now.
-	 */
-	localregs->axq_cpu2ssc_intr = REG_ADDR(localregs->laddress,
-	    AXQ_SLOT_CPU2SSC_INTR);
-}
-
-/* ARGSUSED */
-static int
-axq_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
-	int instance;
-	int i;
-	struct axq_soft_state *softsp;
-	processorid_t cpuid;
-
-	/* get the instance of this devi */
-	instance = ddi_get_instance(devi);
-
-	/* get the soft state pointer for this device node */
-	softsp = ddi_get_soft_state(axq_softp, instance);
-
-	switch (cmd) {
-	case DDI_SUSPEND:
-		/*
-		 * Depending on the variable "use_axq_iopause"
-		 * we set the axq iopause bit as a paranoid
-		 * safety net. This is assuming all the devices
-		 * associated with the slot are already suspended.
-		 * Care must be taken to not set iopause when CPUs
-		 * are known to be present on the slot 1 board,
-		 * i.e. MCPU board type.
-		 * This io pause bit only applies to slot 1 axq,
-		 */
-		if (softsp->slotnum && use_axq_iopause && axq_suspend_iopause) {
-			/*
-			 * Do not enable AXQ_DOMCTRL_PAUSE if CPUs are
-			 * known to be present in slot 1.
-			 */
-			mutex_enter(&cpu_lock);
-			for (i = 0; i < STARCAT_SLOT1_CPU_MAX; i++) {
-				cpuid = MAKE_CPUID(softsp->expid,
-				    softsp->slotnum, i);
-				if (cpu[cpuid]) {
-					mutex_exit(&cpu_lock);
-					return (DDI_SUCCESS);
-				}
-			}
-			mutex_exit(&cpu_lock);
-
-			/*
-			 * Make sure that there is no outstanding
-			 * I/O activity by reading the domain ctrl reg.
-			 * A non-zero lsb indicates no I/O activity.
-			 */
-			if (axq_slot1_idle(softsp) == DDI_FAILURE) {
-				cmn_err(CE_WARN, "%s%d: busy! suspend failed",
-				    ddi_get_name(softsp->dip),
-				    ddi_get_instance(softsp->dip));
-				return (DDI_FAILURE);
-			}
-
-			*softsp->axq_domain_ctrl |= AXQ_DOMCTRL_PAUSE;
-			softsp->paused = 1;
-		}
-		return (DDI_SUCCESS);
-
-	case DDI_DETACH:
-		rw_enter(&axq_array_lock, RW_WRITER);
-		ASSERT(axq_array[softsp->expid][softsp->slotnum]
-		    != NULL);
-		axq_array[softsp->expid][softsp->slotnum] = NULL;
-		rw_exit(&axq_array_lock);
-
-		ddi_regs_map_free(&softsp->ac0);
-
-		/*
-		 * remove counter kstats for this device
-		 */
-		if (softsp->axq_counters_ksp != (kstat_t *)NULL) {
-			kstat_delete(softsp->axq_counters_ksp);
-		}
-
-		/*
-		 * See if we are the last instance to detach.
-		 * If so, we need to remove the picN kstats
-		 */
-		mutex_enter(&axq_attachcnt_lock);
-		if (--axq_attachcnt == 0) {
-			for (i = 0; i < AXQ_NUM_PICS; i++) {
-				if (axq_picN_ksp[i] != (kstat_t *)NULL) {
-					kstat_delete(axq_picN_ksp[i]);
-					axq_picN_ksp[i] = NULL;
-				}
-			}
-		}
-		mutex_exit(&axq_attachcnt_lock);
-
-		ddi_soft_state_free(axq_softp, instance);
-
-		return (DDI_SUCCESS);
-	default:
-		return (DDI_FAILURE);
-	}
-}
-
-
-/* ARGSUSED0 */
-static int
-axq_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
-	dev_t dev = (dev_t)arg;
-	struct axq_soft_state *softsp;
-	int instance, ret;
-
-	instance = getminor(dev);
-
-	switch (infocmd) {
-		case DDI_INFO_DEVT2DEVINFO:
-			softsp = (struct axq_soft_state *)
-			    ddi_get_soft_state(axq_softp, instance);
-			if (softsp == NULL) {
-				ret = DDI_FAILURE;
-			} else {
-				*result = softsp->dip;
-				ret = DDI_SUCCESS;
-			}
-			break;
-		case DDI_INFO_DEVT2INSTANCE:
-			*result = (void *)(uintptr_t)instance;
-			ret = DDI_SUCCESS;
-			break;
-		default:
-			ret = DDI_FAILURE;
-			break;
-	}
-	return (ret);
-}
-
-/*
- * Flush the CDC Sram of the slot0 axq
- * indicated by the expid argument
- */
-int
-axq_cdc_flush(uint32_t expid, int held, int disabled)
-{
-	struct axq_soft_state *softsp;
-	uint32_t axq_ctrl_test_save0;
-	uint32_t tmpval;
-	int retval = 0;
-	int i;
-
-	if (!held)
-		rw_enter(&axq_array_lock, RW_READER);
-
-	ASSERT(axq_array[expid][SLOT0_AXQ] != NULL);
-
-	softsp = axq_array[expid][SLOT0_AXQ];
-
-	mutex_enter(&softsp->axq_lock);
-
-	/* save the value of the ctrl test reg */
-	axq_ctrl_test_save0 = *softsp->axq_cdc_ctrltest;
-
-	/* disable sram and setup the ctrl test reg for flushing */
-	tmpval = axq_ctrl_test_save0 & (AXQ_CDC_DATA_ECC_CHK_EN |
-	    AXQ_CDC_ADR_PAR_CHK_EN |
-	    AXQ_CDC_DATA_ECC_GEN_EN |
-	    AXQ_CDC_ADR_PAR_GEN_EN);
-	*softsp->axq_cdc_ctrltest = tmpval | AXQ_CDC_TMODE_WR
-	    | AXQ_CDC_DATA2PAR_MUX_SEL_DATA
-	    | AXQ_CDC_ADR2SRAM_MUX_SEL_TEST
-	    | AXQ_CDC_ADR_INCR_XOR_CTRL
-	    | AXQ_CDC_DIS;
-
-	/* Enable CDC test in the CDC Address test reg */
-	*softsp->axq_cdc_addrtest = AXQ_CDC_ADR_TEST_EN;
-
-	/* clear the CDC Data write regs */
-	*softsp->axq_cdc_datawrite0 = *softsp->axq_cdc_datawrite1 = 0;
-	*softsp->axq_cdc_datawrite2 = *softsp->axq_cdc_datawrite3 = 0;
-
-	/*
-	 * write in the size of the sram to clear
-	 * into the CDC Counter test reg
-	 */
-	*softsp->axq_cdc_counter = AXQ_CDC_SRAM_SIZE;
-
-	/* wait for flush to complete */
-	for (i = 0; i < AXQ_CDC_FLUSH_WAIT; i++) {
-		DELAY(3000); /* should take only 1750 usecs */
-		if (((*softsp->axq_cdc_counter) &
-		    AXQ_CDC_CNT_TEST_DONE) != 0) {
-			break;
-		}
-	}
-	if (i >= AXQ_CDC_FLUSH_WAIT) {
-		retval = DDI_FAILURE;
-		cmn_err(CE_WARN, "axq_cdc_flush failed on expander %d",
-		    expid);
-	}
-
-	/*
-	 * Disable test mode in CDC address test reg
-	 */
-	*softsp->axq_cdc_addrtest = 0;
-
-	/*
-	 * If "disabled" option is requested, leave
-	 * the CDC disabled.
-	 */
-	if (disabled) {
-		axq_ctrl_test_save0 |= AXQ_CDC_DIS;
-		*softsp->axq_cdc_ctrltest = axq_ctrl_test_save0;
-	} else {
-		*softsp->axq_cdc_ctrltest = axq_ctrl_test_save0;
-	}
-
-	mutex_exit(&softsp->axq_lock);
-
-	if (!held)
-		rw_exit(&axq_array_lock);
-
-	return (retval);
-}
-
-
-/*
- * Flush all the CDC srams for all the AXQs in
- * the local domain.
- */
-int
-axq_cdc_flush_all()
-{
-	int retval;
-	int i;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if (axq_array[i][SLOT0_AXQ] != NULL) {
-			retval = axq_cdc_flush(i, 1, 0);
-			if (retval != DDI_SUCCESS) break;
-		}
-	}
-	rw_exit(&axq_array_lock);
-	return (retval);
-}
-
-/*
- * Disable and flush all CDC srams for all the AXQs
- * in the local domain.
- */
-int
-axq_cdc_disable_flush_all()
-{
-	int retval;
-	int i;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	/*
-	 * Disable and flush all the CDC srams
-	 */
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if (axq_array[i][SLOT0_AXQ] != NULL) {
-			retval = axq_cdc_flush(i, 1, 1);
-			if (retval != DDI_SUCCESS) break;
-		}
-	}
-	rw_exit(&axq_array_lock);
-
-	if (retval != DDI_SUCCESS) {
-		axq_cdc_enable_all();
-	}
-	return (retval);
-}
-
-
-/*
- * Enable the CDC srams for all the AXQs in the
- * the local domain. This routine is used in
- * conjunction with axq_cdc_disable_flush_all().
- */
-void
-axq_cdc_enable_all()
-{
-	struct axq_soft_state *softsp;
-	int i;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	/*
-	 * Enable all the CDC sram
-	 */
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if ((softsp = axq_array[i][SLOT0_AXQ]) != NULL) {
-			mutex_enter(&softsp->axq_lock);
-			if (softsp->axq_cdc_state != AXQ_CDC_DIS) {
-				*softsp->axq_cdc_ctrltest &= ~AXQ_CDC_DIS;
-			}
-			mutex_exit(&softsp->axq_lock);
-		}
-	}
-	rw_exit(&axq_array_lock);
-}
-
-/*
- * Interface for DR to enable slot1 iopause after cpus have been idled.
- * Precondition is for all devices to have been suspended (including axq).
- * This routine avoids locks as it is called by DR with cpus paused.
- */
-int
-axq_iopause_enable_all(uint32_t *errexp)
-{
-	int i, j;
-	int retval = DDI_SUCCESS;
-	processorid_t cpuid;
-	struct axq_soft_state *softsp;
-
-	DELAY(1000);
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if ((softsp = axq_array[i][SLOT1_AXQ]) != NULL &&
-		    use_axq_iopause) {
-			/*
-			 * Do not enable if cpus configured in slot1.
-			 * Unconfigured cpus should be idle in nc space.
-			 */
-			for (j = 0; j < STARCAT_SLOT1_CPU_MAX; j++) {
-				cpuid = MAKE_CPUID(softsp->expid,
-				    softsp->slotnum, j);
-				if (cpu[cpuid]) {
-					break;
-				}
-			}
-			if (j < STARCAT_SLOT1_CPU_MAX) {
-				continue;
-			}
-
-			retval = axq_slot1_idle(softsp);
-			if (retval == DDI_FAILURE) {
-				break;
-			}
-
-			*softsp->axq_domain_ctrl |= AXQ_DOMCTRL_PAUSE;
-			softsp->paused = 1;
-		}
-	}
-
-	if (retval != DDI_SUCCESS) {
-		ASSERT(errexp);
-		*errexp = i;
-		axq_iopause_disable_all();
-	}
-	return (retval);
-}
-
-/*
- * De-assert axq iopause on all slot1 boards. This routine avoids locks
- * as it is called by DR with cpus paused.
- */
-void
-axq_iopause_disable_all()
-{
-	int i;
-	struct axq_soft_state *softsp;
-
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if ((softsp = axq_array[i][SLOT1_AXQ]) != NULL &&
-		    softsp->paused) {
-			*softsp->axq_domain_ctrl &= ~AXQ_DOMCTRL_PAUSE;
-			softsp->paused = 0;
-		}
-	}
-}
-
-/*
- * Attempt to wait for slot1 activity to go idle.
- */
-static int
-axq_slot1_idle(struct axq_soft_state *softsp)
-{
-	int i;
-
-	ASSERT(softsp->slotnum == SLOT1_AXQ);
-	for (i = 0; i < 10; i++) {
-		if ((*(softsp->axq_domain_ctrl) & AXQ_DOMCTRL_BUSY) != 0) {
-			return (DDI_SUCCESS);
-		}
-		DELAY(50);
-	}
-	return (DDI_FAILURE);
-}
-
-/*
- * Read a particular NASM entry
- */
-int
-axq_nasm_read(uint32_t expid, uint32_t slot, uint32_t nasm_entry,
-    uint32_t *data)
-{
-	axq_nasm_read_u aread;
-	axq_nasm_write_u awrite;
-	struct axq_soft_state *softsp;
-
-	if (slot > AXQ_MAX_SLOT_PER_EXP ||
-	    expid > AXQ_MAX_EXP ||
-	    nasm_entry > AXQ_NASM_SIZE) {
-		return (DDI_FAILURE);
-	}
-
-	awrite.bit.rw = 0;	/* read operation */
-	awrite.bit.addr = nasm_entry;
-	awrite.bit.data = 0;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	softsp = axq_array[expid][slot];
-	if (softsp == NULL) {
-		rw_exit(&axq_array_lock);
-		return (DDI_FAILURE);
-	}
-
-	mutex_enter(&softsp->axq_lock);
-
-	*(softsp->axq_nasm) = awrite.val;
-	aread.val = *(softsp->axq_nasm);
-
-	mutex_exit(&softsp->axq_lock);
-	rw_exit(&axq_array_lock);
-
-	if (aread.bit.valid) {
-		*data = aread.bit.data;
-		return (DDI_SUCCESS);
-	}
-	return (DDI_FAILURE);
-}
-
-/*
- * Write a particular NASM entry
- */
-static int
-axq_nasm_write_one(uint32_t expid, uint32_t slot, uint32_t nasm_entry,
-    uint32_t data)
-{
-	axq_nasm_write_u awrite;
-	struct axq_soft_state *softsp;
-
-	/*
-	 * Note: need to make sure axq_array_lock held first, so that a
-	 * paused thread is not holding softsp->axq_lock, which could
-	 * result in deadlock.
-	 */
-	ASSERT(RW_LOCK_HELD(&axq_array_lock));
-
-	if (slot > AXQ_MAX_SLOT_PER_EXP ||
-	    expid > AXQ_MAX_EXP ||
-	    nasm_entry > AXQ_NASM_SIZE) {
-		return (DDI_FAILURE);
-	}
-
-	awrite.bit.rw = 1;	/* write operation */
-	awrite.bit.addr = nasm_entry;
-	awrite.bit.data = data;
-
-	softsp = axq_array[expid][slot];
-	if (softsp == NULL) {
-		return (DDI_FAILURE);
-	}
-
-	mutex_enter(&softsp->axq_lock);
-
-	*(softsp->axq_nasm) = awrite.val;
-
-	mutex_exit(&softsp->axq_lock);
-
-	return (DDI_SUCCESS);
-}
-
-int
-axq_nasm_write(uint32_t expid, uint32_t slot, uint32_t nasm_entry,
-    uint32_t data)
-{
-	int rc;
-
-	rw_enter(&axq_array_lock, RW_READER);
-	rc = axq_nasm_write_one(expid, slot, nasm_entry, data);
-	rw_exit(&axq_array_lock);
-	return (rc);
-}
-
-/*
- * Write a particular NASM entry for all the
- * axqs in the domain
- * Note: other CPUs are paused when this function called.
- */
-int
-axq_nasm_write_all(uint32_t nasm_entry, uint32_t data)
-{
-	int i;
-	int rc;
-
-	ASSERT(RW_WRITE_HELD(&axq_array_lock));
-
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if (axq_array[i][SLOT0_AXQ] != NULL) {
-			rc = axq_nasm_write_one(i, SLOT0_AXQ, nasm_entry,
-			    data);
-			if (rc != DDI_SUCCESS) {
-				return (DDI_FAILURE);
-			}
-		}
-		if (axq_array[i][SLOT1_AXQ] != NULL) {
-			rc = axq_nasm_write_one(i, SLOT1_AXQ, nasm_entry,
-			    data);
-			if (rc != DDI_SUCCESS) {
-				return (DDI_FAILURE);
-			}
-		}
-	}
-
-	return (DDI_SUCCESS);
-}
-
-/*
- * Take write lock for axq_nasm_write_all() outside
- * critical section where other CPUs are paused.
- */
-void
-axq_array_rw_enter(void)
-{
-	rw_enter(&axq_array_lock, RW_WRITER);
-}
-
-/*
- * Release write lock for axq_nasm_write_all() outside
- * critical section where other CPUs are paused.
- */
-void
-axq_array_rw_exit(void)
-{
-	rw_exit(&axq_array_lock);
-}
-
-/*
- * Read a particular CASM entry
- */
-uint32_t
-axq_casm_read(uint32_t expid, uint32_t slot, int casmslot)
-{
-	struct axq_soft_state *softsp;
-	uint32_t retval;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	ASSERT(axq_array[expid][slot] != NULL);
-	ASSERT(casmslot >= 0 && casmslot < AXQ_MAX_EXP);
-
-	softsp = axq_array[expid][slot];
-
-	mutex_enter(&softsp->axq_lock);
-
-	retval = *(softsp->axq_casm_slot[casmslot]);
-
-	mutex_exit(&softsp->axq_lock);
-	rw_exit(&axq_array_lock);
-
-	return (retval);
-}
-
-
-/*
- * Write a particular CASM entry
- */
-
-int
-axq_casm_write(uint32_t expid, uint32_t slot, int casmslot,
-		uint32_t value)
-{
-	struct axq_soft_state *softsp;
-	int retval;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	ASSERT(axq_array[expid][slot] != NULL);
-	ASSERT(casmslot >= 0 && casmslot < AXQ_MAX_EXP);
-
-	softsp = axq_array[expid][slot];
-
-	mutex_enter(&softsp->axq_lock);
-
-	/*
-	 * first read the casm slot in question
-	 * it should be non-zero to indicate that
-	 * we have write permission to update it.
-	 * Note that if we write it without valid
-	 * permission, we can get an exception.
-	 */
-	if (*(softsp->axq_casm_slot[casmslot])) {
-		*(softsp->axq_casm_slot[casmslot]) = value;
-		retval = DDI_SUCCESS;
-	} else {
-		retval = DDI_FAILURE;
-	}
-
-	mutex_exit(&softsp->axq_lock);
-	rw_exit(&axq_array_lock);
-	return (retval);
-}
-
-/*
- * Write a particular CASM entry for all the
- * axqs in the domain
- */
-
-int
-axq_casm_write_all(int casmslot, uint32_t value)
-{
-	int i;
-	struct axq_soft_state *softsp;
-
-	/*
-	 * Since we are updating all the AXQs,
-	 * it will be easier to simply grab
-	 * exclusive access to the AXQs by obtaining
-	 * the RW_WRITER access to the axq_array.
-	 */
-	rw_enter(&axq_array_lock, RW_WRITER);
-
-	/*
-	 * Paranoid check: run thru all the avail AXQs
-	 * and make sure we can write into that slot in question
-	 * We check it by reading the slot and it should be
-	 * non-zero.
-	 */
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if ((softsp = axq_array[i][SLOT0_AXQ]) != NULL) {
-			if (*(softsp->axq_casm_slot[casmslot])
-			    == 0) {
-				break;
-			}
-		}
-		if ((softsp = axq_array[i][SLOT1_AXQ]) != NULL) {
-			if (*(softsp->axq_casm_slot[casmslot])
-			    == 0) {
-				break;
-			}
-		}
-	}
-
-	if (i < AXQ_MAX_EXP) {
-		/*
-		 * We have no write permission for some AXQ
-		 * for the CASM slot in question. Flag it
-		 * as an error
-		 */
-		rw_exit(&axq_array_lock);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * everything looks good - do the update
-	 */
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if ((softsp = axq_array[i][SLOT0_AXQ]) != NULL) {
-			*softsp->axq_casm_slot[casmslot] = value;
-		}
-		if ((softsp = axq_array[i][SLOT1_AXQ]) != NULL) {
-			*softsp->axq_casm_slot[casmslot] = value;
-		}
-	}
-
-	rw_exit(&axq_array_lock);
-	return (DDI_SUCCESS);
-}
-
-
-/*
- * Construct a script of <physicaladdr, data> tuple pairs that
- * reprogram the all the AXQs in the local domain to swap the
- * contents of casmslot0 with casmslot1.
- */
-int
-axq_do_casm_rename_script(uint64_t **script_elm, int casmslot0,
-	int casmslot1)
-{
-	struct axq_soft_state *softsp;
-	int i, slot;
-	uint32_t val0, val1;
-	uint64_t *s_elm = *script_elm;
-	uint64_t paddr;
-
-	/*
-	 * There should be some global locking at the
-	 * DR level to do this - since this is one of
-	 * the sequence of steps in copyrename.
-	 * For now, we grab the RW_WRITER lock for
-	 * script construction.
-	 */
-	rw_enter(&axq_array_lock, RW_WRITER);
-
-	/*
-	 * Construct the <physicaladdr, data> tuple pairs
-	 * for reprogramming the AXQs so that the value in
-	 * casmslot0 is swapped with the content in casmslot1.
-	 * Paranoid check: We make sure that we can write to
-	 * both slots in all the AXQs by reading the slots and
-	 * they should be non-zero.
-	 */
-	for (slot = SLOT0_AXQ; slot <= SLOT1_AXQ; slot++) {
-		for (i = 0; i < AXQ_MAX_EXP; i++) {
-		if ((softsp = axq_array[i][slot]) != NULL) {
-			paddr = softsp->axq_phyaddr;
-			val0 = *(softsp->axq_casm_slot[casmslot0]);
-			val1 = *(softsp->axq_casm_slot[casmslot1]);
-			if (val0 != 0 && val1 != 0) {
-				*s_elm++ = paddr + AXQ_CASM_SLOT_START +
-				    AXQ_REGOFF(casmslot0);
-				*s_elm++ = val1;
-				*s_elm++ = paddr + AXQ_CASM_SLOT_START +
-				    AXQ_REGOFF(casmslot1);
-				*s_elm++ = val0;
-			} else {
-				/*
-				 * Somehow we can't access one of
-				 * the casm slot - quit.
-				 */
-				break;
-			}
-		}
-		}
-		if (i < AXQ_MAX_EXP) break;
-	}
-
-	rw_exit(&axq_array_lock);
-
-	if (slot > SLOT1_AXQ) {
-		/* successful */
-		*script_elm = s_elm;
-		return (DDI_SUCCESS);
-	} else {
-		return (DDI_FAILURE);
-	}
-}
-
-
-/*
- * Send an interrupt to the SSC passing
- * a 8 bit cookie value
- */
-int
-axq_cpu2ssc_intr(uint8_t cookie)
-{
-	int retval, i;
-	volatile uint32_t *intr_reg;
-
-#ifndef	_AXQ_LOCAL_SPACE_SUPPORTED
-	/* Local space access not available */
-
-	int exp, slot;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	/* Make sure the current cpu is not switched out */
-	kpreempt_disable();
-
-	/*
-	 * Compute the exp# and slot# of the current cpu
-	 * so that we know which AXQ cpu2ssc intr reg to
-	 * use.
-	 */
-	exp = CPU->cpu_id >> 5;
-	slot = (CPU->cpu_id >> 3) & 0x1;
-
-	intr_reg = axq_array[exp][slot]->axq_cpu2ssc_intr;
-#else
-	/* use local space */
-	intr_reg = axq_local.axq_cpu2ssc_intr;
-#endif /* _AXQ_LOCAL_SPACE_SUPPORTED */
-
-	ASSERT(intr_reg != 0);
-
-	retval = DDI_FAILURE;
-	for (i = 0; i < AXQ_INTR_PEND_WAIT; i++) {
-		if (!(*intr_reg & AXQ_CPU2SSC_INTR_PEND)) {
-			*intr_reg = cookie;
-			retval = DDI_SUCCESS;
-			break;
-		}
-		DELAY(200);
-	}
-
-#ifndef	_AXQ_LOCAL_SPACE_SUPPORTED
-	kpreempt_enable();
-	rw_exit(&axq_array_lock);
-#endif
-	return (retval);
-}
-
-
-/*
- * Read the SDI timeout register (SRD use)
- * This routine accepts a clear flag to indicate
- * whether the register should be cleared after
- * the read.
- */
-uint32_t
-axq_read_sdi_timeout_reg(uint32_t expid, uint32_t slot, int clearflag)
-{
-	struct axq_soft_state *softsp;
-	uint32_t retval;
-
-	rw_enter(&axq_array_lock, RW_READER);
-
-	ASSERT(axq_array[expid][slot] != NULL);
-
-	softsp = axq_array[expid][slot];
-
-	mutex_enter(&softsp->axq_lock);
-
-	if (clearflag) {
-		/* read and then clear register */
-		retval = *softsp->axq_sdi_timeout_rdclr;
-	} else {
-		retval = *softsp->axq_sdi_timeout_rd;
-	}
-
-	mutex_exit(&softsp->axq_lock);
-	rw_exit(&axq_array_lock);
-
-	return (retval);
-}
-
-
-/*
- * Routine to create a kstat for each %pic that
- * the AXQ has (there are 3 of them). These read-only
- * kstats export event names that the respective %pic
- * supports. Pic0 and Pic1 are similar and they both have
- * a 128-input mux. Pic2 counts the clock and can set up
- * to count or freeze.
- * Note that all AXQ instances use the same events, we only
- * need to create one set of the picN kstats.
- */
-static void
-axq_add_picN_kstats(dev_info_t *dip)
-{
-	struct kstat_named *axq_pic_named_data;
-	int event, pic;
-	int instance = ddi_get_instance(dip);
-	int pic_shift = 0;
-
-	/*
-	 * Create the picN kstat for Pic0 and Pic1
-	 * Both have similar set of events. Add one
-	 * extra event for the clear_event mask.
-	 */
-	for (pic = 0; pic < AXQ_NUM_PICS; pic++) {
-		char pic_name[20];
-		int num_events, i;
-
-		(void) sprintf(pic_name, "pic%d", pic);
-
-		num_events = (pic <= 1) ? AXQ_PIC0_1_NUM_EVENTS :
-		    AXQ_PIC2_NUM_EVENTS;
-
-		if ((axq_picN_ksp[pic] = kstat_create("axq",
-		    instance, pic_name, "bus", KSTAT_TYPE_NAMED,
-		    num_events + 1, NULL)) == NULL) {
-			cmn_err(CE_WARN, "axq %s: kstat_create failed",
-			    pic_name);
-
-			/* remove pic kstats that was created earlier */
-			for (i = 0; i < pic; i++) {
-				kstat_delete(axq_picN_ksp[i]);
-				axq_picN_ksp[i] = NULL;
-			}
-			return;
-		}
-
-		axq_pic_named_data =
-		    (struct kstat_named *)(axq_picN_ksp[pic]->ks_data);
-
-		pic_shift = pic * AXQ_PIC_SHIFT;
-
-		/*
-		 * for each picN event, write a kstat record of
-		 * name = EVENT & value.ui64 = PCR_MASK.
-		 */
-		for (event = 0; event < num_events; event++) {
-			/* pcr_mask */
-			axq_pic_named_data[event].value.ui64 =
-			    axq_events[event].pcr_mask << pic_shift;
-
-			/* event name */
-			kstat_named_init(&axq_pic_named_data[event],
-			    axq_events[event].event_name,
-			    KSTAT_DATA_UINT64);
-		}
-
-		/*
-		 * Add the clear pic event and mask as the last
-		 * record in the kstat.
-		 */
-		axq_pic_named_data[num_events].value.ui64 =
-		    (uint32_t)~(AXQ_PIC_CLEAR_MASK << pic_shift);
-
-		kstat_named_init(&axq_pic_named_data[num_events],
-		    "clear_pic", KSTAT_DATA_UINT64);
-
-		kstat_install(axq_picN_ksp[pic]);
-	}
-}
-
-
-static  void
-axq_add_kstats(struct axq_soft_state *softsp)
-{
-	struct kstat *axq_counters_ksp;
-	struct kstat_named *axq_counters_named_data;
-
-	/*
-	 * Create the picN kstats if we are the first instance
-	 * to attach. We use axq_attachcnt as a count of how
-	 * many instances have attached. This is protected by
-	 * a lock.
-	 */
-	mutex_enter(&axq_attachcnt_lock);
-	if (axq_attachcnt++ == 0)
-		axq_add_picN_kstats(softsp->dip);
-
-	mutex_exit(&axq_attachcnt_lock);
-
-	/*
-	 * A "counter" kstat is created for each axq
-	 * instance that provides access to the %pcr and %pic
-	 * registers for that instance.
-	 *
-	 * The size of this kstat is AXQ_NUM_PICS + 1 for %pcr
-	 */
-	if ((axq_counters_ksp = kstat_create("axq",
-	    ddi_get_instance(softsp->dip), "counters",
-	    "bus", KSTAT_TYPE_NAMED, AXQ_NUM_PICS + 1,
-	    KSTAT_FLAG_WRITABLE)) == NULL) {
-			cmn_err(CE_WARN, "axq%d counters: kstat_create"
-			" failed", ddi_get_instance(softsp->dip));
-		return;
-	}
-
-	axq_counters_named_data =
-	    (struct kstat_named *)(axq_counters_ksp->ks_data);
-
-	/* initialize the named kstats */
-	kstat_named_init(&axq_counters_named_data[0],
-	    "pcr", KSTAT_DATA_UINT32);
-
-	kstat_named_init(&axq_counters_named_data[1],
-	    "pic0", KSTAT_DATA_UINT32);
-
-	kstat_named_init(&axq_counters_named_data[2],
-	    "pic1", KSTAT_DATA_UINT32);
-
-	kstat_named_init(&axq_counters_named_data[3],
-	    "pic2", KSTAT_DATA_UINT32);
-
-	axq_counters_ksp->ks_update = axq_counters_kstat_update;
-	axq_counters_ksp->ks_private = (void *)softsp;
-
-	kstat_install(axq_counters_ksp);
-
-	/* update the softstate */
-	softsp->axq_counters_ksp = axq_counters_ksp;
-}
-
-
-static  int
-axq_counters_kstat_update(kstat_t *ksp, int rw)
-{
-	struct kstat_named *axq_counters_data;
-	struct axq_soft_state *softsp;
-
-	axq_counters_data = (struct kstat_named *)ksp->ks_data;
-	softsp = (struct axq_soft_state *)ksp->ks_private;
-
-	if (rw == KSTAT_WRITE) {
-		/*
-		 * Write the pcr value to the softsp->axq_pcr.
-		 * The pic register is read-only so we don't
-		 * attempt to write to it.
-		 */
-		*softsp->axq_pcr = (uint32_t)axq_counters_data[0].value.ui64;
-	} else {
-		/*
-		 * Read %pcr and %pic register values and write them
-		 * into counters kstat.
-		 *
-		 */
-
-		/* pcr */
-		axq_counters_data[0].value.ui64 = (uint64_t)
-		    (*softsp->axq_pcr);
-
-		/* pic0 */
-		axq_counters_data[1].value.ui64 = (uint64_t)
-		    (*softsp->axq_pic0);
-
-		/* pic1 */
-		axq_counters_data[2].value.ui64 = (uint64_t)
-		    *softsp->axq_pic1;
-
-		/* pic2 */
-		axq_counters_data[3].value.ui64 = (uint64_t)
-		    *softsp->axq_pic2;
-	}
-	return (0);
-}
-
-struct gptwo_phys_spec {
-	uint_t gptwo_phys_hi;   /* child's address, hi word */
-	uint_t gptwo_phys_low;  /* child's address, low word */
-	uint_t gptwo_size_hi;   /* high word of size field */
-	uint_t gptwo_size_low;  /* low word of size field */
-};
-
-int axq_pio_workaround_disable = 0;
-int axq_pio_limit = 3;
-
-int
-starcat_axq_pio_workaround(dev_info_t *dip)
-{
-	dev_info_t *axq_dip, *cdip, *pdip;
-	int portid, axq_portid;
-	char *name;
-	int size, circ;
-	uint_t *base_addr, *io_domain_control_addr;
-	int32_t io_domain_control;
-	ddi_device_acc_attr_t acc;
-	ddi_acc_handle_t handle;
-	struct gptwo_phys_spec *gptwo_spec;
-	struct regspec phys_spec;
-
-	if (axq_pio_workaround_disable)
-		return (0);
-
-	/*
-	 * Get the portid for the PCI (Schizo) device).
-	 */
-	if ((portid = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "portid", -1)) < 0) {
-		cmn_err(CE_WARN, "%s: no portid\n", ddi_get_name(dip));
-		return (0);
-	}
-
-	/*
-	 * Calculate the portid for the Slot 1 AXQ.  The portid for
-	 * Schizo 0 EEEEE11100
-	 * Schizo 1 EEEEE11101
-	 * AXQ 0    EEEEE11110
-	 * AXQ 1    EEEEE11111
-	 * where EEEEE is the 5 bit expander number.  So the portid for
-	 * AXQ 1 can be easily calculated by oring a 3 to the portid of
-	 * Schizo 0 or 1.
-	 */
-	axq_portid = portid | 3;
-
-	/*
-	 * Look for AXQ nodes that have the portid we calculated.
-	 */
-	axq_dip = NULL;
-	pdip = ddi_root_node();
-	ndi_devi_enter(pdip, &circ);
-	for (cdip = ddi_get_child(pdip); cdip != NULL;
-	    cdip = ddi_get_next_sibling(cdip)) {
-
-		if (ddi_getlongprop(DDI_DEV_T_ANY, cdip,
-		    DDI_PROP_DONTPASS, "name", (caddr_t)&name, &size)
-		    != DDI_PROP_SUCCESS) {
-			continue;
-		}
-
-		if (strcmp(name, "address-extender-queue") != 0) {
-			kmem_free(name, size);
-			continue;
-		}
-
-		/*
-		 * Found an AXQ node.
-		 */
-
-		kmem_free(name, size);
-
-		portid = ddi_getprop(DDI_DEV_T_ANY, cdip, 0, "portid", -1);
-
-		if (portid == axq_portid) {
-
-			/*
-			 * We found the correct AXQ node.
-			 */
-			ndi_hold_devi(cdip);
-			axq_dip = cdip;
-			break;
-		}
-	}
-	ndi_devi_exit(pdip, circ);
-
-	if (axq_dip == NULL) {
-		cmn_err(CE_WARN, "can't find axq node with portid=0x%x\n",
-		    axq_portid);
-		return (0);
-	}
-
-	if (ddi_getlongprop(DDI_DEV_T_ANY, axq_dip, DDI_PROP_DONTPASS, "reg",
-	    (caddr_t)&gptwo_spec, &size) != DDI_PROP_SUCCESS) {
-		cmn_err(CE_WARN, "%s: no regspec\n", ddi_get_name(axq_dip));
-		ndi_rele_devi(axq_dip);
-		return (0);
-	}
-
-	phys_spec.regspec_bustype = gptwo_spec->gptwo_phys_hi;
-	phys_spec.regspec_addr = gptwo_spec->gptwo_phys_low;
-	phys_spec.regspec_size = gptwo_spec->gptwo_size_low;
-
-	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
-	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
-	acc.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
-
-	if (axq_map_phys(axq_dip, &phys_spec, (caddr_t *)&base_addr,
-	    &acc, &handle)) {
-		cmn_err(CE_WARN, "%s: map phys failed\n",
-		    ddi_get_name(axq_dip));
-		kmem_free(gptwo_spec, size);
-		ndi_rele_devi(axq_dip);
-		return (0);
-	}
-
-	kmem_free(gptwo_spec, size);
-
-	io_domain_control_addr = REG_ADDR(base_addr, AXQ_SLOT1_DOMCTRL);
-
-	if (ddi_peek32(axq_dip, (int32_t *)io_domain_control_addr,
-	    (int32_t *)&io_domain_control)) {
-		cmn_err(CE_WARN, "%s: peek failed\n", ddi_get_name(axq_dip));
-		ndi_rele_devi(axq_dip);
-		return (0);
-	}
-
-	axq_unmap_phys(&handle);
-
-	ndi_rele_devi(axq_dip);
-
-	/*
-	 * If bit 6 of the IO Domain Control Register is a one,
-	 * then this AXQ version does not have the PIO Limit problem.
-	 */
-	if (io_domain_control & AXQ_DOMCTRL_PIOFIX)
-		return (0);
-
-	return (axq_pio_limit);
-}
-
-static int
-axq_map_phys(dev_info_t *dip, struct regspec *phys_spec,
-	caddr_t *addrp, ddi_device_acc_attr_t *accattrp,
-	ddi_acc_handle_t *handlep)
-{
-	ddi_map_req_t mr;
-	ddi_acc_hdl_t *hp;
-	int result;
-	struct regspec *ph;
-
-	*handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL);
-	hp = impl_acc_hdl_get(*handlep);
-	hp->ah_vers = VERS_ACCHDL;
-	hp->ah_dip = dip;
-	hp->ah_rnumber = 0;
-	hp->ah_offset = 0;
-	hp->ah_len = 0;
-	hp->ah_acc = *accattrp;
-	ph = kmem_zalloc(sizeof (struct regspec), KM_SLEEP);
-	*ph = *phys_spec;
-	hp->ah_bus_private = ph;	/* cache a copy of the reg spec */
-
-	mr.map_op = DDI_MO_MAP_LOCKED;
-	mr.map_type = DDI_MT_REGSPEC;
-	mr.map_obj.rp = phys_spec;
-	mr.map_prot = PROT_READ | PROT_WRITE;
-	mr.map_flags = DDI_MF_KERNEL_MAPPING;
-	mr.map_handlep = hp;
-	mr.map_vers = DDI_MAP_VERSION;
-
-	result = ddi_map(dip, &mr, 0, 0, addrp);
-
-	if (result != DDI_SUCCESS) {
-		impl_acc_hdl_free(*handlep);
-		*handlep = NULL;
-	} else {
-		hp->ah_addr = *addrp;
-	}
-
-	return (result);
-}
-
-static void
-axq_unmap_phys(ddi_acc_handle_t *handlep)
-{
-	ddi_map_req_t mr;
-	ddi_acc_hdl_t *hp;
-	struct regspec *ph;
-
-	hp = impl_acc_hdl_get(*handlep);
-	ASSERT(hp);
-	ph = hp->ah_bus_private;
-
-	mr.map_op = DDI_MO_UNMAP;
-	mr.map_type = DDI_MT_REGSPEC;
-	mr.map_obj.rp = ph;
-	mr.map_prot = PROT_READ | PROT_WRITE;
-	mr.map_flags = DDI_MF_KERNEL_MAPPING;
-	mr.map_handlep = hp;
-	mr.map_vers = DDI_MAP_VERSION;
-
-	(void) ddi_map(hp->ah_dip, &mr, hp->ah_offset,
-	    hp->ah_len, &hp->ah_addr);
-
-	impl_acc_hdl_free(*handlep);
-	kmem_free(ph, sizeof (struct regspec));	/* Free the cached copy */
-	*handlep = NULL;
-}
-
-/* ARGSUSED */
-static boolean_t
-axq_panic_callb(void *arg, int code)
-{
-	axq_iopause_disable_all();
-	return (B_TRUE);
-}
--- a/usr/src/uts/sun4u/starcat/io/cvc.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1437 +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/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/disp.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 <sys/tty.h>
-#include <sys/ptyvar.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/sc_cvc.h>
-#include <sys/sc_cvcio.h>
-#include <sys/iosramio.h>
-
-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_reioctl(void *);
-static void	cvc_input_daemon(void);
-static void	cvc_send_to_iosram(mblk_t **chainpp);
-static void	cvc_flush_queue(void *);
-static void	cvc_iosram_ops(uint8_t);
-static void	cvc_getstr(char *cp);
-static void	cvc_win_resize(int clear_flag);
-
-#define	ESUCCESS 0
-#ifndef	TRUE
-#define	TRUE	1
-#define	FALSE	0
-#endif
-
-/*
- * Private copy of devinfo pointer; cvc_info uses it.
- */
-static dev_info_t	*cvcdip;
-
-/*
- * This structure reflects the layout of data in CONI and CONO.  If you are
- * going to add fields that don't get written into those chunks, be sure to
- * place them _after_ the buffer field.
- */
-typedef struct cvc_buf {
-	ushort_t	count;
-	uchar_t		buffer[MAX_XFER_COUTPUT];
-} cvc_buf_t;
-
-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 */
-};
-
-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;
-
-kthread_id_t		cvc_input_daemon_thread; /* just to aid debugging */
-static kmutex_t		cvcmutex;	/* protects input */
-static kmutex_t		cvc_iosram_input_mutex; /* protects IOSRAM inp buff */
-static int		input_ok = 0;	/* true when stream is valid */
-
-static int		via_iosram = 0; /* toggle switch */
-static timeout_id_t	cvc_timeout_id = (timeout_id_t)-1;
-static int		input_daemon_started = 0;
-
-/* debugging functions */
-#ifdef DEBUG
-uint32_t cvc_dbg_flags = 0x0;
-static void cvc_dbg(uint32_t flag, char *fmt,
-	uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5);
-#endif
-
-/*
- * Module linkage information for the kernel.
- */
-
-DDI_DEFINE_STREAM_OPS(cvcops, nulldev, nulldev, cvc_attach, cvc_detach,
-		    nodev, cvc_info, (D_NEW|D_MTPERQ|D_MP), &cvcinfo,
-		    ddi_quiesce_not_supported);
-
-extern int nodev(), nulldev();
-extern struct mod_ops mod_driverops;
-
-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()
-{
-	int	status;
-
-	status = mod_install(&modlinkage);
-	if (status == 0) {
-		mutex_init(&cvcmutex, NULL, MUTEX_DEFAULT, NULL);
-	}
-	return (status);
-}
-
-int
-_fini()
-{
-	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;
-		if (cvcinput_q != NULL) {
-			qenable(WR(cvcinput_q));
-		}
-		return (DDI_SUCCESS);
-	}
-
-	mutex_enter(&cvcmutex);
-	if (!been_here) {
-		been_here = 1;
-		mutex_init(&cvc_iosram_input_mutex, NULL, MUTEX_DEFAULT, NULL);
-		rw_init(&cvclock, NULL, RW_DRIVER, NULL);
-		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 */
-		mutex_exit(&cvcmutex);
-		return (DDI_SUCCESS);
-	}
-	mutex_exit(&cvcmutex);
-
-	if (ddi_create_minor_node(devi, "cvc", S_IFCHR,
-	    0, NULL, NULL) == DDI_FAILURE) {
-		ddi_remove_minor_node(devi, NULL);
-		return (-1);
-	}
-	cvcdip = devi;
-	cvcinput_q = NULL;
-	cvcoutput_q = NULL;
-
-	CVC_DBG0(CVC_DBG_ATTACH, "Attached");
-
-	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);
-		}
-	}
-
-	CVC_DBG0(CVC_DBG_DETACH, "Detached");
-
-	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 = DDI_SUCCESS;
-	tty_common_t		*tty;
-	cvc_t			*cp;
-
-	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;
-
-	/*
-	 * Start the thread that handles input polling if it hasn't been started
-	 * previously.
-	 */
-	if (!input_daemon_started) {
-		input_daemon_started = 1;
-		mutex_exit(&cvcmutex);
-
-		cvc_input_daemon_thread = thread_create(NULL, 0,
-		    cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri);
-		CVC_DBG0(CVC_DBG_IOSRAM_RD, "Started input daemon");
-	} else {
-		mutex_exit(&cvcmutex);
-	}
-
-	/*
-	 * Set the console window size.
-	 */
-	mutex_enter(&cvc_iosram_input_mutex);
-	cvc_win_resize(FALSE);
-	mutex_exit(&cvc_iosram_input_mutex);
-
-	CVC_DBG0(CVC_DBG_OPEN, "Plumbed successfully");
-
-	return (err);
-}
-
-/* ARGSUSED */
-static int
-cvc_close(queue_t *q, int flag, cred_t *crp)
-{
-	register int		err = DDI_SUCCESS;
-	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);
-
-	CVC_DBG0(CVC_DBG_CLOSE, "Un-plumbed successfully");
-
-	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 to cvcredir, if the
- *	network path is available and selected, or to IOSRAM otherwise.  Data is
- *	sent to cvcredir via its read queue (cvcoutput_q, which gets set in
- *	cvc_register()).  If the IOSRAM path is selected, or if previous mblks
- *	are currently queued up for processing, the new mblk will be queued
- *	and handled later on by cvc_wsrv.
- */
-static int
-cvc_wput(queue_t *q, mblk_t *mp)
-{
-	int		error = 0;
-
-	rw_enter(&cvclock, RW_READER);
-
-	CVC_DBG2(CVC_DBG_WPUT, "mp 0x%x db_type 0x%x",
-	    mp, mp->b_datap->db_type);
-
-	switch (mp->b_datap->db_type) {
-
-		case M_IOCTL:
-		case M_CTL: {
-			struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
-
-			switch (iocp->ioc_cmd) {
-				/*
-				 * These ioctls are only supposed to be
-				 * processed after everything else that is
-				 * already queued awaiting processing, so throw
-				 * them on the queue and let cvc_wsrv handle
-				 * them.
-				 */
-				case TCSETSW:
-				case TCSETSF:
-				case TCSETAW:
-				case TCSETAF:
-				case TCSBRK:
-					(void) putq(q, mp);
-					break;
-
-				default:
-					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: unexpected mblk type - mp ="
-			    " 0x%p, type = 0x%x", (void *)mp,
-			    mp->b_datap->db_type);
-			freemsg(mp);
-			break;
-
-		case M_DATA:
-			/*
-			 * If there are other mblks queued up for transmission,
-			 * or we're using IOSRAM either because cvcredir hasn't
-			 * registered yet or because we were configured that
-			 * way, or cvc has been stopped or suspended, place this
-			 * mblk on the input queue for future processing.
-			 * Otherwise, hand it off to cvcredir for transmission
-			 * via the network.
-			 */
-			if (q->q_first != NULL || cvcoutput_q == NULL ||
-			    via_iosram || cvc_stopped == 1 ||
-			    cvc_suspended == 1) {
-				(void) putq(q, mp);
-			} else {
-				/*
-				 * XXX - should canputnext be called here?
-				 * Starfire's cvc doesn't do that, and it
-				 * appears to work anyway.
-				 */
-				(void) putnext(cvcoutput_q, mp);
-			}
-			break;
-
-	}
-	rw_exit(&cvclock);
-	return (error);
-}
-
-/*
- * cvc_wsrv()
- *	cvc_wsrv handles mblks that have been queued by cvc_wput either because
- *	the IOSRAM path was selected or the queue contained preceding mblks.  To
- *	optimize processing (particularly if the IOSRAM path is selected), all
- *	mblks are pulled off of the queue and chained together.  Then, if there
- *	are any mblks on the chain, they are either forwarded to cvcredir or
- *	sent for IOSRAM processing as appropriate given current circumstances.
- *	IOSRAM processing may not be able to handle all of the data in the
- *	chain, in which case the remaining data is placed back on the queue and
- *	a timeout routine is registered to reschedule cvc_wsrv in the future.
- *	Automatic scheduling of the queue is disabled (noenable(q)) while
- *	cvc_wsrv is running to avoid superfluous calls.
- */
-static int
-cvc_wsrv(queue_t *q)
-{
-	mblk_t *total_mp = NULL;
-	mblk_t *mp;
-
-	if (cvc_stopped == 1 || cvc_suspended == 1) {
-		return (0);
-	}
-
-	rw_enter(&cvclock, RW_READER);
-	noenable(q);
-
-	/*
-	 * If there's already a timeout registered for scheduling this routine
-	 * in the future, it's a safe bet that we don't want to run right now.
-	 */
-	if (cvc_timeout_id != (timeout_id_t)-1) {
-		enableok(q);
-		rw_exit(&cvclock);
-		return (0);
-	}
-
-	/*
-	 * Start by linking all of the queued M_DATA mblks into a single chain
-	 * so we can flush as much as possible to IOSRAM (if we choose that
-	 * route).
-	 */
-	while ((mp = getq(q)) != NULL) {
-		/*
-		 * Technically, certain IOCTLs are supposed to be processed only
-		 * after all preceding data has completely "drained".  In an
-		 * attempt to support that, we delay processing of those IOCTLs
-		 * until this point.  It is still possible that an IOCTL will be
-		 * processed before all preceding data is drained, for instance
-		 * in the case where not all of the preceding data would fit
-		 * into IOSRAM and we have to place it back on the queue.
-		 * However, since none of these IOCTLs really appear to have any
-		 * relevance for cvc, and we weren't supporting delayed
-		 * processing at _all_ previously, this partial implementation
-		 * should suffice.  (Fully implementing the delayed IOCTL
-		 * processing would be unjustifiably difficult given the nature
-		 * of the underlying IOSRAM console protocol.)
-		 */
-		if (mp->b_datap->db_type == M_IOCTL) {
-			cvc_ioctl(q, mp);
-			continue;
-		}
-
-		/*
-		 * We know that only M_IOCTL and M_DATA blocks are placed on our
-		 * queue.  Since this block isn't an M_IOCTL, it must be M_DATA.
-		 */
-		if (total_mp != NULL) {
-			linkb(total_mp, mp);
-		} else {
-			total_mp = mp;
-		}
-	}
-
-	/*
-	 * Do we actually have anything to do?
-	 */
-	if (total_mp == NULL) {
-		enableok(q);
-		rw_exit(&cvclock);
-		return (0);
-	}
-
-	/*
-	 * Yes, we do, so send the data to either cvcredir or IOSRAM as
-	 * appropriate.  In the latter case, we might not be able to transmit
-	 * everything right now, so re-queue the remainder.
-	 */
-	if (cvcoutput_q != NULL && !via_iosram) {
-		CVC_DBG0(CVC_DBG_NETWORK_WR, "Sending to cvcredir.");
-		/*
-		 * XXX - should canputnext be called here?  Starfire's cvc
-		 * doesn't do that, and it appears to work anyway.
-		 */
-		(void) putnext(cvcoutput_q, total_mp);
-	} else {
-		CVC_DBG0(CVC_DBG_IOSRAM_WR, "Send to IOSRAM.");
-		cvc_send_to_iosram(&total_mp);
-		if (total_mp != NULL) {
-			(void) putbq(q, total_mp);
-		}
-	}
-
-	/*
-	 * If there is still data queued at this point, make sure the queue
-	 * gets scheduled again after an appropriate delay (which has been
-	 * somewhat arbitrarily selected as half of the SC's input polling
-	 * frequency).
-	 */
-	enableok(q);
-	if (q->q_first != NULL) {
-		if (cvc_timeout_id == (timeout_id_t)-1) {
-			cvc_timeout_id = timeout(cvc_flush_queue,
-			    NULL, drv_usectohz(CVC_IOSRAM_POLL_USECS / 2));
-		}
-	}
-	rw_exit(&cvclock);
-	return (0);
-}
-
-
-/*
- * cvc_ioctl()
- *	handle normal console ioctls.
- */
-static void
-cvc_ioctl(register queue_t *q, register mblk_t *mp)
-{
-	register cvc_t			*cp = q->q_ptr;
-	int				datasize;
-	int				error = 0;
-
-	/*
-	 * Let ttycommon_ioctl take the first shot at processing the ioctl.  If
-	 * it fails because it can't allocate memory, schedule processing of the
-	 * ioctl later when a proper buffer is available.  The mblk that
-	 * couldn't be processed will have been stored in the tty structure by
-	 * ttycommon_ioctl.
-	 */
-	datasize = ttycommon_ioctl(&cp->cvc_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;
-	}
-
-	/*
-	 * ttycommon_ioctl didn't do anything, but there's nothing we really
-	 * support either with the exception of TCSBRK, which is supported
-	 * only to appear a bit more like a serial device for software that
-	 * expects TCSBRK to work.
-	 */
-	if (error != 0) {
-		struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
-
-		if (iocp->ioc_cmd == TCSBRK) {
-			miocack(q, mp, 0, 0);
-		} else {
-			miocnak(q, mp, 0, EINVAL);
-		}
-	} else {
-		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.
- */
-int
-cvc_redir(mblk_t *mp)
-{
-	register struct iocblk	*iocp;
-	int			rv = 1;
-
-	/*
-	 * This function shouldn't be called if cvcredir hasn't registered yet.
-	 */
-	if (cvcinput_q == NULL) {
-		/*
-		 * Need to let caller know that it may be necessary for them to
-		 * free the message buffer, so return 0.
-		 */
-		CVC_DBG0(CVC_DBG_REDIR, "redirection not enabled");
-		cmn_err(CE_WARN, "cvc_redir: cvcinput_q NULL!");
-		return (0);
-	}
-
-	CVC_DBG1(CVC_DBG_REDIR, "type 0x%x", mp->b_datap->db_type);
-	if (mp->b_datap->db_type == M_DATA) {
-		/*
-		 * XXX - should canputnext be called here?  Starfire's cvc
-		 * doesn't do that, and it appears to work anyway.
-		 */
-		CVC_DBG1(CVC_DBG_NETWORK_RD, "Sending mp 0x%x", mp);
-		(void) putnext(cvcinput_q, mp);
-	} else if (mp->b_datap->db_type == M_IOCTL) {
-		/*
-		 * The cvcredir driver filters out ioctl mblks we wouldn't
-		 * understand, so we don't have to check for every conceivable
-		 * ioc_cmd.  However, additional ioctls may be supported (again)
-		 * some day, so the code is structured to check the value even
-		 * though there's only one that is currently supported.
-		 */
-		iocp = (struct iocblk *)mp->b_rptr;
-		if (iocp->ioc_cmd == CVC_DISCONNECT) {
-			(void) putnextctl(cvcinput_q, M_HANGUP);
-		}
-	} else {
-		/*
-		 * Since we don't know what this mblk is, we're not going to
-		 * process it.
-		 */
-		CVC_DBG1(CVC_DBG_REDIR, "unrecognized mblk type: %d",
-		    mp->b_datap->db_type);
-		rv = 0;
-	}
-
-	return (rv);
-}
-
-
-/*
- * 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);
-	}
-	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;
-	}
-	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_iosram_ops()
- *	Process commands sent to cvc from netcon_server via IOSRAM
- */
-static void
-cvc_iosram_ops(uint8_t op)
-{
-	int		rval = ESUCCESS;
-	static uint8_t	stale_op = 0;
-
-	ASSERT(MUTEX_HELD(&cvc_iosram_input_mutex));
-
-	CVC_DBG1(CVC_DBG_IOSRAM_CNTL, "cntl msg 0x%x", op);
-
-	/*
-	 * If this is a repeated notice of a command that was previously
-	 * processed but couldn't be cleared due to EAGAIN (tunnel switch in
-	 * progress), just clear the data_valid flag and return.
-	 */
-	if (op == stale_op) {
-		if (iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID,
-		    IOSRAM_INT_NONE) == 0) {
-			stale_op = 0;
-		}
-		return;
-	}
-	stale_op = 0;
-
-	switch (op) {
-		case CVC_IOSRAM_BREAK:		/* A console break (L1-A) */
-			abort_sequence_enter((char *)NULL);
-			break;
-
-		case CVC_IOSRAM_DISCONNECT:	/* Break connection, hang up */
-			if (cvcinput_q)
-				(void) putnextctl(cvcinput_q, M_HANGUP);
-			break;
-
-		case CVC_IOSRAM_VIA_NET:	/* console via network */
-			via_iosram = 0;
-			break;
-
-		case CVC_IOSRAM_VIA_IOSRAM:	/* console via iosram */
-			via_iosram = 1;
-			/*
-			 * Tell cvcd to close any network connection it has.
-			 */
-			rw_enter(&cvclock, RW_READER);
-			if (cvcoutput_q != NULL) {
-				(void) putnextctl(cvcoutput_q, M_HANGUP);
-			}
-			rw_exit(&cvclock);
-			break;
-
-		case CVC_IOSRAM_WIN_RESIZE:	/* console window size data */
-			/*
-			 * In the case of window resizing, we don't want to
-			 * record a stale_op value because we should always use
-			 * the most recent winsize info, which could change
-			 * between the time that we fail to clear the flag and
-			 * the next time we try to process the command.  So,
-			 * we'll just let cvc_win_resize clear the data_valid
-			 * flag itself (hence the TRUE parameter) and not worry
-			 * about whether or not it succeeds.
-			 */
-			cvc_win_resize(TRUE);
-			return;
-			/* NOTREACHED */
-
-		default:
-			cmn_err(CE_WARN, "cvc: unknown IOSRAM opcode %d", op);
-			break;
-	}
-
-	/*
-	 * Clear CONC's data_valid flag to indicate that the chunk is available
-	 * for further communications.  If the flag can't be cleared due to an
-	 * error, record the op value so we'll know to ignore it when we see it
-	 * on the next poll.
-	 */
-	rval = iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID,
-	    IOSRAM_INT_NONE);
-	if (rval != 0) {
-		stale_op = op;
-		if (rval != EAGAIN) {
-			cmn_err(CE_WARN,
-			    "cvc_iosram_ops: set flag for cntlbuf ret %d",
-			    rval);
-		}
-	}
-}
-
-
-/*
- * cvc_send_to_iosram()
- *	Flush as much data as possible to the CONO chunk.  If successful, free
- *	any mblks that were completely transmitted, update the b_rptr field in
- *	the first remaining mblk if it was partially transmitted, and update the
- *	caller's pointer to the new head of the mblk chain.  Since the software
- *	that will be pulling this data out of IOSRAM (dxs on the SC) is just
- *	polling at some frequency, we avoid attempts to flush data to IOSRAM any
- *	faster than a large divisor of that polling frequency.
- *
- *	Note that "cvc_buf_t out" is only declared "static" to keep it from
- *	being allocated on the stack.  Allocating 1K+ structures on the stack
- *	seems rather antisocial.
- */
-static void
-cvc_send_to_iosram(mblk_t **chainpp)
-{
-	int			rval;
-	uint8_t			dvalid;
-	uchar_t			*cp;
-	mblk_t			*mp;
-	mblk_t			*last_empty_mp;
-	static clock_t		last_flush = (clock_t)-1;
-	static cvc_buf_t	out;   /* see note above about static */
-
-	ASSERT(chainpp != NULL);
-
-	/*
-	 * We _do_ have something to do, right?
-	 */
-	if (*chainpp == NULL) {
-		return;
-	}
-
-	/*
-	 * We can actually increase throughput by throttling back on attempts to
-	 * flush data to IOSRAM, since trying to write every little bit of data
-	 * as it shows up will actually generate more delays waiting for the SC
-	 * to pick up each of those bits.  Instead, we'll avoid attempting to
-	 * write data to IOSRAM any faster than half of the polling frequency we
-	 * expect the SC to be using.
-	 */
-	if (ddi_get_lbolt() - last_flush <
-	    drv_usectohz(CVC_IOSRAM_POLL_USECS / 2)) {
-		return;
-	}
-
-	/*
-	 * If IOSRAM is inaccessible or the CONO chunk still holds data that
-	 * hasn't been picked up by the SC, there's nothing we can do right now.
-	 */
-	rval = iosram_get_flag(IOSRAM_KEY_CONO, &dvalid, NULL);
-	if ((rval != 0) || (dvalid == IOSRAM_DATA_VALID)) {
-		if ((rval != 0) && (rval != EAGAIN)) {
-			cmn_err(CE_WARN, "cvc_send_to_iosram: get_flag ret %d",
-			    rval);
-		}
-		return;
-	}
-
-	/*
-	 * Copy up to MAX_XFER_COUTPUT chars from the mblk chain into a buffer.
-	 * Don't change any of the mblks just yet, since we can't be certain
-	 * that we'll be successful in writing data to the CONO chunk.
-	 */
-	out.count = 0;
-	mp = *chainpp;
-	cp = mp->b_rptr;
-	last_empty_mp = NULL;
-	while ((mp != NULL) && (out.count < MAX_XFER_COUTPUT)) {
-		/*
-		 * Process as many of the characters in the current mblk as
-		 * possible.
-		 */
-		while ((cp != mp->b_wptr) && (out.count < MAX_XFER_COUTPUT)) {
-			out.buffer[out.count++] = *cp++;
-		}
-
-		/*
-		 * Did we process that entire mblk?  If so, move on to the next
-		 * one.  If not, we're done filling the buffer even if there's
-		 * space left, because apparently there wasn't room to process
-		 * the next character.
-		 */
-		if (cp != mp->b_wptr) {
-			break;
-		}
-
-		/*
-		 * When this loop terminates, last_empty_mp will point to the
-		 * last mblk that was completely processed, mp will point to the
-		 * following mblk (or NULL if no more mblks exist), and cp will
-		 * point to the first untransmitted character in the mblk
-		 * pointed to by mp.  We'll need this data to update the mblk
-		 * chain if all of the data is successfully transmitted.
-		 */
-		last_empty_mp = mp;
-		mp = mp->b_cont;
-		cp = (mp != NULL) ? mp->b_rptr : NULL;
-	}
-
-	/*
-	 * If we succeeded in preparing some data, try to transmit it through
-	 * IOSRAM.  First write the count and the data, which can be done in a
-	 * single operation thanks to the buffer structure we use, then set the
-	 * data_valid flag if the first step succeeded.
-	 */
-	if (out.count != 0) {
-		rval = iosram_wr(IOSRAM_KEY_CONO, COUNT_OFFSET,
-		    CONSBUF_COUNT_SIZE + out.count, (caddr_t)&out);
-		if ((rval != 0) && (rval != EAGAIN)) {
-			cmn_err(CE_WARN, "cvc_putc: write ret %d", rval);
-		}
-
-		/* if the data write succeeded, set the data_valid flag */
-		if (rval == 0) {
-			rval = iosram_set_flag(IOSRAM_KEY_CONO,
-			    IOSRAM_DATA_VALID, IOSRAM_INT_NONE);
-			if ((rval != 0) && (rval != EAGAIN)) {
-				cmn_err(CE_WARN,
-				    "cvc_putc: set flags for outbuf ret %d",
-				    rval);
-			}
-		}
-
-		/*
-		 * If we successfully transmitted any data, modify the caller's
-		 * mblk chain to remove the data that was transmitted, freeing
-		 * all mblks that were completely processed.
-		 */
-		if (rval == 0) {
-			last_flush = ddi_get_lbolt();
-
-			/*
-			 * If any data is left over, update the b_rptr field of
-			 * the first remaining mblk in case some of its data was
-			 * processed.
-			 */
-			if (mp != NULL) {
-				mp->b_rptr = cp;
-			}
-
-			/*
-			 * If any mblks have been emptied, unlink them from the
-			 * residual chain, free them, and update the caller's
-			 * mblk pointer.
-			 */
-			if (last_empty_mp != NULL) {
-				last_empty_mp->b_cont = NULL;
-				freemsg(*chainpp);
-				*chainpp = mp;
-			}
-		}
-	}
-}
-
-
-/*
- * cvc_flush_queue()
- *	Tell the STREAMS subsystem to schedule cvc_wsrv to process the queue we
- *	use to gather console output.
- */
-/* ARGSUSED */
-static void
-cvc_flush_queue(void *notused)
-{
-	rw_enter(&cvclock, RW_WRITER);
-	if (cvcinput_q != NULL) {
-		qenable(WR(cvcinput_q));
-	}
-
-	cvc_timeout_id = (timeout_id_t)-1;
-	rw_exit(&cvclock);
-}
-
-
-/*
- * cvc_getstr()
- *	Poll IOSRAM for console input while available.
- */
-static void
-cvc_getstr(char *cp)
-{
-	short		count;
-	uint8_t		command = 0;
-	int		rval = ESUCCESS;
-	uint8_t		dvalid = IOSRAM_DATA_INVALID;
-	uint8_t		intrpending = 0;
-
-	mutex_enter(&cvc_iosram_input_mutex);
-	while (dvalid == IOSRAM_DATA_INVALID) {
-		/*
-		 * Check the CONC data_valid flag to see if a control message is
-		 * available.
-		 */
-		rval = iosram_get_flag(IOSRAM_KEY_CONC, &dvalid, &intrpending);
-		if ((rval != 0) && (rval != EAGAIN)) {
-			cmn_err(CE_WARN,
-			    "cvc_getstr: get flag for cntl ret %d", rval);
-		}
-
-		/*
-		 * If a control message is available, try to read and process
-		 * it.
-		 */
-		if ((dvalid == IOSRAM_DATA_VALID) && (rval == 0)) {
-			/* read the control reg offset */
-			rval = iosram_rd(IOSRAM_KEY_CONC,
-			    CVC_CTL_OFFSET(command), CVC_CTL_SIZE(command),
-			    (caddr_t)&command);
-			if ((rval != 0) && (rval != EAGAIN)) {
-				cmn_err(CE_WARN,
-				    "cvc_getstr: read for command ret %d",
-				    rval);
-			}
-
-			/* process the cntl msg and clear the data_valid flag */
-			if (rval == 0) {
-				cvc_iosram_ops(command);
-			}
-		}
-
-		/*
-		 * Check the CONI data_valid flag to see if console input data
-		 * is available.
-		 */
-		rval = iosram_get_flag(IOSRAM_KEY_CONI, &dvalid, &intrpending);
-		if ((rval != 0) && (rval != EAGAIN)) {
-			cmn_err(CE_WARN,
-			    "cvc_getstr: get flag for inbuf ret %d",
-			    rval);
-		}
-		if ((rval != 0) || (dvalid != IOSRAM_DATA_VALID)) {
-			goto retry;
-		}
-
-		/*
-		 * Try to read the count.
-		 */
-		rval = iosram_rd(IOSRAM_KEY_CONI, COUNT_OFFSET,
-		    CONSBUF_COUNT_SIZE, (caddr_t)&count);
-		if (rval != 0) {
-			if (rval != EAGAIN) {
-				cmn_err(CE_WARN,
-				    "cvc_getstr: read for count ret %d", rval);
-			}
-			goto retry;
-		}
-
-		/*
-		 * If there is data to be read, try to read it.
-		 */
-		if (count != 0) {
-			rval = iosram_rd(IOSRAM_KEY_CONI, DATA_OFFSET, count,
-			    (caddr_t)cp);
-			if (rval != 0) {
-				if (rval != EAGAIN) {
-					cmn_err(CE_WARN,
-					    "cvc_getstr: read for count ret %d",
-					    rval);
-				}
-				goto retry;
-			}
-			cp[count] = '\0';
-		}
-
-		/*
-		 * Try to clear the data_valid flag to indicate that whatever
-		 * was in CONI was read successfully.  If successful, and some
-		 * data was read, break out of the loop to return to the caller.
-		 */
-		rval = iosram_set_flag(IOSRAM_KEY_CONI, IOSRAM_DATA_INVALID,
-		    IOSRAM_INT_NONE);
-		if (rval != 0) {
-			if (rval != EAGAIN) {
-				cmn_err(CE_WARN,
-				    "cvc_getstr: set flag for inbuf ret %d",
-				    rval);
-			}
-		} else if (count != 0) {
-			CVC_DBG1(CVC_DBG_IOSRAM_RD, "Read 0x%x", count);
-			break;
-		}
-
-		/*
-		 * Use a smaller delay between checks of IOSRAM for input
-		 * when cvcd/cvcredir are not running or "via_iosram" 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 IOSRAM
-		 * to switch if the network is down or hung.
-		 */
-retry:
-		if ((cvcoutput_q == NULL) || (via_iosram))
-			delay(drv_usectohz(CVC_IOSRAM_POLL_USECS));
-		else
-			delay(drv_usectohz(CVC_IOSRAM_POLL_USECS * 10));
-
-	}
-
-	mutex_exit(&cvc_iosram_input_mutex);
-}
-
-
-/*
- * cvc_input_daemon()
- *	this function runs as a separate kernel thread and polls IOSRAM 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_iosram
- *		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.
- */
-/* ARGSUSED */
-static void
-cvc_input_daemon(void)
-{
-	char		linebuf[MAX_XFER_CINPUT + 1];
-	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 IOSRAM reads");
-			}
-			dropped_read++;
-			continue;
-		}
-
-		if (dropped_read) {
-			cmn_err(CE_WARN,
-			    "cvc_input_daemon: dropped %d IOSRAM reads",
-			    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 {
-				/*
-				 * XXX - should canputnext be called here?
-				 * Starfire's cvc doesn't do that, and it
-				 * appears to work anyway.
-				 */
-				(void) putnext(cvcinput_q, mbp);
-			}
-		} else {
-			freemsg(mbp);
-		}
-		mutex_exit(&cvcmutex);
-	}
-
-	/* NOTREACHED */
-}
-
-/*
- * cvc_win_resize()
- *	cvc_win_resize will read winsize data from the CONC IOSRAM chunk and set
- *	the console window size accordingly.  If indicated by the caller, CONC's
- *	data_valid flag will also be cleared.  The flag isn't cleared in all
- *	cases because we need to process winsize data at startup without waiting
- *	for a command.
- */
-static void
-cvc_win_resize(int clear_flag)
-{
-	int		rval;
-	uint16_t	rows;
-	uint16_t	cols;
-	uint16_t	xpixels;
-	uint16_t	ypixels;
-	tty_common_t	*tty;
-	cvc_t		*cp;
-	struct winsize	ws;
-
-	/*
-	 * Start by reading the new window size out of the CONC chunk and, if
-	 * requested, clearing CONC's data_valid flag.  If any of that fails,
-	 * return immediately.  (Note that the rather bulky condition in the
-	 * two "if" statements takes advantage of C's short-circuit logic
-	 * evaluation)
-	 */
-	if (((rval = iosram_rd(IOSRAM_KEY_CONC, CVC_CTL_OFFSET(winsize_rows),
-	    CVC_CTL_SIZE(winsize_rows), (caddr_t)&rows)) != 0) ||
-	    ((rval = iosram_rd(IOSRAM_KEY_CONC, CVC_CTL_OFFSET(winsize_cols),
-	    CVC_CTL_SIZE(winsize_cols), (caddr_t)&cols)) != 0) ||
-	    ((rval = iosram_rd(IOSRAM_KEY_CONC,
-	    CVC_CTL_OFFSET(winsize_xpixels), CVC_CTL_SIZE(winsize_xpixels),
-	    (caddr_t)&xpixels)) != 0) || ((rval = iosram_rd(IOSRAM_KEY_CONC,
-	    CVC_CTL_OFFSET(winsize_ypixels), CVC_CTL_SIZE(winsize_ypixels),
-	    (caddr_t)&ypixels)) != 0)) {
-		if (rval != EAGAIN) {
-			cmn_err(CE_WARN,
-			    "cvc_win_resize: read for ctlbuf ret %d", rval);
-		}
-		return;
-	}
-
-	if (clear_flag && ((rval = iosram_set_flag(IOSRAM_KEY_CONC,
-	    IOSRAM_DATA_INVALID, IOSRAM_INT_NONE)) != 0)) {
-		if (rval != EAGAIN) {
-			cmn_err(CE_WARN,
-			    "cvc_win_resize: set_flag for ctlbuf ret %d", rval);
-		}
-		return;
-	}
-
-	/*
-	 * Copy the parameters from IOSRAM to a winsize struct.
-	 */
-	ws.ws_row = rows;
-	ws.ws_col = cols;
-	ws.ws_xpixel = xpixels;
-	ws.ws_ypixel = ypixels;
-
-	/*
-	 * This code was taken from Starfire, and it appears to work correctly.
-	 * However, since the original developer felt it necessary to add the
-	 * following comment, it's probably worth preserving:
-	 *
-	 * XXX I hope this is safe...
-	 */
-	cp = cvcinput_q->q_ptr;
-	tty = &cp->cvc_tty;
-	mutex_enter(&tty->t_excl);
-	if (bcmp((caddr_t)&tty->t_size, (caddr_t)&ws,
-	    sizeof (struct winsize))) {
-		tty->t_size = ws;
-		mutex_exit(&tty->t_excl);
-		(void) putnextctl1(cvcinput_q, M_PCSIG,
-			SIGWINCH);
-	} else {
-		mutex_exit(&tty->t_excl);
-	}
-}
-
-#ifdef DEBUG
-
-void
-cvc_dbg(uint32_t flag, char *fmt,
-	uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
-{
-	char *s = NULL;
-	char buf[256];
-
-	if (cvc_dbg_flags && ((cvc_dbg_flags & flag) == flag)) {
-		switch (flag) {
-		case CVC_DBG_ATTACH:
-			s = "attach";
-			break;
-		case CVC_DBG_DETACH:
-			s = "detach";
-			break;
-		case CVC_DBG_OPEN:
-			s = "open";
-			break;
-		case CVC_DBG_CLOSE:
-			s = "close";
-			break;
-		case CVC_DBG_IOCTL:
-			s = "ioctl";
-			break;
-		case CVC_DBG_REDIR:
-			s = "redir";
-			break;
-		case CVC_DBG_WPUT:
-			s = "wput";
-			break;
-		case CVC_DBG_WSRV:
-			s = "wsrv";
-			break;
-		case CVC_DBG_IOSRAM_WR:
-			s = "iosram_wr";
-			break;
-		case CVC_DBG_IOSRAM_RD:
-			s = "iosram_rd";
-			break;
-		case CVC_DBG_NETWORK_WR:
-			s = "network_wr";
-			break;
-		case CVC_DBG_NETWORK_RD:
-			s = "network_rd";
-			break;
-		case CVC_DBG_IOSRAM_CNTL:
-			s = "iosram_cntlmsg";
-			break;
-		default:
-			s = "Unknown debug flag";
-			break;
-		}
-
-		(void) sprintf(buf, "!%s_%s(%d): %s", ddi_driver_name(cvcdip),
-		    s, cvc_instance, fmt);
-		cmn_err(CE_NOTE, buf, a1, a2, a3, a4, a5);
-	}
-}
-
-#endif /* DEBUG */
--- a/usr/src/uts/sun4u/starcat/io/cvc.conf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-#
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-# Copyright (c) 2000 by Sun Microsystems, Inc.
-# All rights reserved.
-#
-name="cvc" parent="pseudo" instance=0;
--- a/usr/src/uts/sun4u/starcat/io/cvcredir.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +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 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/sc_cvcio.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);
-
-extern struct mod_ops mod_driverops;
-
-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()
-{
-	return (mod_install(&modlinkage));
-}
-
-int
-_fini()
-{
-	return (mod_remove(&modlinkage));
-}
-
-int
-_info(modinfop)
-	struct modinfo *modinfop;
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-/*ARGSUSED*/
-static int
-cvcr_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-	if (cmd == DDI_RESUME) {
-		if (cvcr_suspend) {
-			cvcr_suspend = 0;
-		}
-	} else {
-		if (ddi_create_minor_node(devi, "cvcredir", S_IFCHR,
-		    0, NULL, 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) {
-		if (!cvcr_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 network-transmitted control messages
-	 */
-	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))
-		freemsg(mp);
-	return (0);
-}
-
-static void
-cvcr_ioctl(queue_t *q, mblk_t *mp)
-{
-	struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
-
-	/*
-	 * If this is a CVC_BREAK, drop to OBP/kmdb from here rather than
-	 * passing the mblk on to cvc.  If it is a disconnect, pass it on to
-	 * cvc.  Nothing else is currently supported, so NAK all others.
-	 * Note that cvc_redir doesn't free the mblk passed in, so we can
-	 * reuse it for ACKing.
-	 */
-	if (iocp->ioc_cmd == CVC_BREAK) {
-		abort_sequence_enter((char *)NULL);
-		miocack(q, mp, 0, 0);
-	} else if (iocp->ioc_cmd == CVC_DISCONNECT) {
-		(void) cvc_redir(mp);
-		miocack(q, mp, 0, 0);
-	} else {
-		miocnak(q, mp, 0, EINVAL);
-	}
-}
--- a/usr/src/uts/sun4u/starcat/io/cvcredir.conf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-#
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-# Copyright (c) 2000 by Sun Microsystems, Inc.
-# All rights reserved.
-#
-name="cvcredir" parent="pseudo" instance=0;
--- a/usr/src/uts/sun4u/starcat/io/dman.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8327 +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.
- * Copyright (c) 2019 Peter Tribble.
- */
-
-
-/*
- * Starcat Management Network Driver
- *
- * ****** NOTICE **** This file also resides in the SSC gate as
- * ****** NOTICE **** usr/src/uts/sun4u/scman/scman.c. Any changes
- * ****** NOTICE **** made here must be propogated there as well.
- *
- */
-
-#include <sys/types.h>
-#include <sys/proc.h>
-#include <sys/disp.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/kstat.h>
-#include <sys/ksynch.h>
-#include <sys/stream.h>
-#include <sys/dlpi.h>
-#include <sys/stropts.h>
-#include <sys/strsubr.h>
-#include <sys/debug.h>
-#include <sys/conf.h>
-#include <sys/kstr.h>
-#include <sys/errno.h>
-#include <sys/ethernet.h>
-#include <sys/byteorder.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunldi.h>
-#include <sys/modctl.h>
-#include <sys/strsun.h>
-#include <sys/callb.h>
-#include <sys/pci.h>
-#include <netinet/in.h>
-#include <inet/common.h>
-#include <inet/mi.h>
-#include <inet/nd.h>
-#include <sys/socket.h>
-#include <netinet/igmp_var.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <inet/ip.h>
-#include <inet/ip6.h>
-#include <sys/file.h>
-#include <sys/dman.h>
-#include <sys/autoconf.h>
-#include <sys/zone.h>
-
-extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
-
-#define	MAN_IDNAME	"dman"
-#define	DMAN_INT_PATH	"/devices/pseudo/dman@0:dman"
-#define	DMAN_PATH	"/devices/pseudo/clone@0:dman"
-#define	ERI_IDNAME	"eri"
-#define	ERI_PATH	"/devices/pseudo/clone@0:eri"
-
-#if defined(DEBUG)
-
-static void man_print_msp(manstr_t *);
-static void man_print_man(man_t *);
-static void man_print_mdp(man_dest_t *);
-static void man_print_dev(man_dev_t *);
-static void man_print_mip(mi_path_t *);
-static void man_print_mtp(mi_time_t *);
-static void man_print_mpg(man_pg_t *);
-static void man_print_path(man_path_t *);
-static void man_print_work(man_work_t *);
-
-/*
- * Set manstr_t dlpistate (upper half of multiplexor)
- */
-#define	SETSTATE(msp, state) \
-	MAN_DBG(MAN_DLPI, ("msp=0x%p @ %d state %s=>%s\n",		\
-		    (void *)msp, __LINE__, dss[msp->ms_dlpistate],	\
-		    dss[(state)]));					\
-		    msp->ms_dlpistate = (state);
-/*
- * Set man_dest_t dlpistate (lower half of multiplexor)
- */
-#define	D_SETSTATE(mdp, state) \
-	MAN_DBG(MAN_DLPI, ("dst=0x%p @ %d state %s=>%s\n",	   \
-		    (void *)mdp, __LINE__, dss[mdp->md_dlpistate], \
-		    dss[(state)]));				   \
-		    mdp->md_dlpistate = (state);
-
-static char *promisc[] = {	/* DLPI promisc Strings */
-	"not used",		/* 0x00 */
-	"DL_PROMISC_PHYS",	/* 0x01 */
-	"DL_PROMISC_SAP",	/* 0x02 */
-	"DL_PROMISC_MULTI"	/* 0x03 */
-};
-
-static char *dps[] = {			/* DLPI Primitive Strings */
-	"DL_INFO_REQ",			/* 0x00 */
-	"DL_BIND_REQ",			/* 0x01 */
-	"DL_UNBIND_REQ",		/* 0x02 */
-	"DL_INFO_ACK",			/* 0x03 */
-	"DL_BIND_ACK",			/* 0x04 */
-	"DL_ERROR_ACK",			/* 0x05 */
-	"DL_OK_ACK",			/* 0x06 */
-	"DL_UNITDATA_REQ",		/* 0x07 */
-	"DL_UNITDATA_IND",		/* 0x08 */
-	"DL_UDERROR_IND",		/* 0x09 */
-	"DL_UDQOS_REQ",			/* 0x0a */
-	"DL_ATTACH_REQ",		/* 0x0b */
-	"DL_DETACH_REQ",		/* 0x0c */
-	"DL_CONNECT_REQ",		/* 0x0d */
-	"DL_CONNECT_IND",		/* 0x0e */
-	"DL_CONNECT_RES",		/* 0x0f */
-	"DL_CONNECT_CON",		/* 0x10 */
-	"DL_TOKEN_REQ",			/* 0x11 */
-	"DL_TOKEN_ACK",			/* 0x12 */
-	"DL_DISCONNECT_REQ",		/* 0x13 */
-	"DL_DISCONNECT_IND",		/* 0x14 */
-	"DL_SUBS_UNBIND_REQ",		/* 0x15 */
-	"DL_LIARLIARPANTSONFIRE",	/* 0x16 */
-	"DL_RESET_REQ",			/* 0x17 */
-	"DL_RESET_IND",			/* 0x18 */
-	"DL_RESET_RES",			/* 0x19 */
-	"DL_RESET_CON",			/* 0x1a */
-	"DL_SUBS_BIND_REQ",		/* 0x1b */
-	"DL_SUBS_BIND_ACK",		/* 0x1c */
-	"DL_ENABMULTI_REQ",		/* 0x1d */
-	"DL_DISABMULTI_REQ",		/* 0x1e */
-	"DL_PROMISCON_REQ",		/* 0x1f */
-	"DL_PROMISCOFF_REQ",		/* 0x20 */
-	"DL_DATA_ACK_REQ",		/* 0x21 */
-	"DL_DATA_ACK_IND",		/* 0x22 */
-	"DL_DATA_ACK_STATUS_IND",	/* 0x23 */
-	"DL_REPLY_REQ",			/* 0x24 */
-	"DL_REPLY_IND",			/* 0x25 */
-	"DL_REPLY_STATUS_IND",		/* 0x26 */
-	"DL_REPLY_UPDATE_REQ",		/* 0x27 */
-	"DL_REPLY_UPDATE_STATUS_IND",	/* 0x28 */
-	"DL_XID_REQ",			/* 0x29 */
-	"DL_XID_IND",			/* 0x2a */
-	"DL_XID_RES",			/* 0x2b */
-	"DL_XID_CON",			/* 0x2c */
-	"DL_TEST_REQ",			/* 0x2d */
-	"DL_TEST_IND",			/* 0x2e */
-	"DL_TEST_RES",			/* 0x2f */
-	"DL_TEST_CON",			/* 0x30 */
-	"DL_PHYS_ADDR_REQ",		/* 0x31 */
-	"DL_PHYS_ADDR_ACK",		/* 0x32 */
-	"DL_SET_PHYS_ADDR_REQ",		/* 0x33 */
-	"DL_GET_STATISTICS_REQ",	/* 0x34 */
-	"DL_GET_STATISTICS_ACK",	/* 0x35 */
-};
-
-#define	MAN_DLPI_MAX_PRIM	0x35
-
-static char *dss[] = {			/* DLPI State Strings */
-	"DL_UNBOUND",			/* 0x00	*/
-	"DL_BIND_PENDING",		/* 0x01	*/
-	"DL_UNBIND_PENDING",		/* 0x02	*/
-	"DL_IDLE",			/* 0x03	*/
-	"DL_UNATTACHED",		/* 0x04	*/
-	"DL_ATTACH_PENDING",		/* 0x05	*/
-	"DL_DETACH_PENDING",		/* 0x06	*/
-	"DL_UDQOS_PENDING",		/* 0x07	*/
-	"DL_OUTCON_PENDING",		/* 0x08	*/
-	"DL_INCON_PENDING",		/* 0x09	*/
-	"DL_CONN_RES_PENDING",		/* 0x0a	*/
-	"DL_DATAXFER",			/* 0x0b	*/
-	"DL_USER_RESET_PENDING",	/* 0x0c	*/
-	"DL_PROV_RESET_PENDING",	/* 0x0d	*/
-	"DL_RESET_RES_PENDING",		/* 0x0e	*/
-	"DL_DISCON8_PENDING",		/* 0x0f	*/
-	"DL_DISCON9_PENDING",		/* 0x10	*/
-	"DL_DISCON11_PENDING",		/* 0x11	*/
-	"DL_DISCON12_PENDING",		/* 0x12	*/
-	"DL_DISCON13_PENDING",		/* 0x13	*/
-	"DL_SUBS_BIND_PND",		/* 0x14	*/
-	"DL_SUBS_UNBIND_PND",		/* 0x15	*/
-};
-
-static const char *lss[] = {
-	"UNKNOWN",	/* 0x0 */
-	"INIT",		/* 0x1 */
-	"GOOD",		/* 0x2 */
-	"STALE",	/* 0x3 */
-	"FAIL",		/* 0x4 */
-};
-
-static char *_mw_type[] = {
-	"OPEN_CTL",		/* 0x0 */
-	"CLOSE_CTL",		/* 0x1 */
-	"SWITCH",		/* 0x2 */
-	"PATH_UPDATE",		/* 0x3 */
-	"CLOSE",		/* 0x4 */
-	"CLOSE_STREAM",	/* 0x5 */
-	"DRATTACH",		/* 0x6 */
-	"DRDETACH",		/* 0x7 */
-	"STOP",			/* 0x8 */
-	"DRSWITCH",		/* 0x9 */
-	"KSTAT_UPDATE"		/* 0xA */
-};
-
-uint32_t		man_debug = MAN_WARN;
-
-#define	man_kzalloc(a, b)	man_dbg_kzalloc(__LINE__, a, b)
-#define	man_kfree(a, b)		man_dbg_kfree(__LINE__, a, b)
-void	*man_dbg_kzalloc(int line, size_t size, int kmflags);
-void	man_dbg_kfree(int line, void *buf, size_t size);
-
-#else	/* DEBUG */
-
-uint32_t		man_debug = 0;
-/*
- * Set manstr_t dlpistate (upper half of multiplexor)
- */
-#define	SETSTATE(msp, state) msp->ms_dlpistate = (state);
-/*
- * Set man_dest_t dlpistate (lower half of multiplexor)
- */
-#define	D_SETSTATE(mdp, state) mdp->md_dlpistate = (state);
-
-#define	man_kzalloc(a, b)	kmem_zalloc(a, b)
-#define	man_kfree(a, b)		kmem_free(a, b)
-
-#endif	/* DEBUG */
-
-#define	DL_PRIM(mp)	(((union DL_primitives *)(mp)->b_rptr)->dl_primitive)
-#define	DL_PROMISCON_TYPE(mp)	\
-		(((union DL_primitives *)(mp)->b_rptr)->promiscon_req.dl_level)
-#define	IOC_CMD(mp)	(((struct iocblk *)(mp)->b_rptr)->ioc_cmd)
-
-/*
- * Start of kstat-related declarations
- */
-#define	MK_NOT_COUNTER		(1<<0)	/* is it a counter? */
-#define	MK_ERROR		(1<<2)	/* for error statistics */
-#define	MK_NOT_PHYSICAL		(1<<3)	/* no matching physical stat */
-
-typedef struct man_kstat_info_s {
-	char		*mk_name;	/* e.g. align_errors */
-	char		*mk_physname;	/* e.g. framing (NULL for same) */
-	char		*mk_physalias;	/* e.g. framing (NULL for same) */
-	uchar_t		mk_type;	/* e.g. KSTAT_DATA_UINT32 */
-	int		mk_flags;
-} man_kstat_info_t;
-
-/*
- * Master declaration macro, note that it uses token pasting
- */
-#define	MK_DECLARE(name, pname, palias, bits, flags) \
-	{ name,		pname,	palias,	KSTAT_DATA_UINT ## bits, flags }
-
-/*
- * Obsolete forms don't have the _sinceswitch forms, they are all errors
- */
-#define	MK_OBSOLETE32(name, alias) MK_DECLARE(alias, name, alias, 32, MK_ERROR)
-#define	MK_OBSOLETE64(name, alias) MK_DECLARE(alias, name, alias, 64, MK_ERROR)
-
-/*
- * The only non-counters don't have any other aliases
- */
-#define	MK_NOTCOUNTER32(name) MK_DECLARE(name, name, NULL, 32, MK_NOT_COUNTER)
-#define	MK_NOTCOUNTER64(name) MK_DECLARE(name, name, NULL, 64, MK_NOT_COUNTER)
-
-/*
- * Normal counter forms
- */
-#define	MK_DECLARE32(name, alias) \
-	MK_DECLARE(name, name, alias, 32, 0)
-#define	MK_DECLARE64(name, alias) \
-	MK_DECLARE(name, name, alias, 64, 0)
-
-/*
- * Error counters need special MK_ERROR flag only for the non-AP form
- */
-#define	MK_ERROR32(name, alias) \
-	MK_DECLARE(name, name, alias, 32, MK_ERROR)
-#define	MK_ERROR64(name, alias) \
-	MK_DECLARE(name, name, alias, 64, MK_ERROR)
-
-/*
- * These AP-specific stats are not backed by physical statistics
- */
-#define	MK_NOTPHYS32(name) MK_DECLARE(name, NULL, NULL, 32, MK_NOT_PHYSICAL)
-#define	MK_NOTPHYS64(name) MK_DECLARE(name, NULL, NULL, 64, MK_NOT_PHYSICAL)
-
-/*
- * START of the actual man_kstat_info declaration using above macros
- */
-static man_kstat_info_t man_kstat_info[] = {
-	/*
-	 * Link Input/Output stats
-	 */
-	MK_DECLARE32("ipackets", NULL),
-	MK_ERROR32("ierrors", NULL),
-	MK_DECLARE32("opackets", NULL),
-	MK_ERROR32("oerrors", NULL),
-	MK_ERROR32("collisions", NULL),
-	MK_NOTCOUNTER64("ifspeed"),
-	/*
-	 * These are new MIB-II stats, per PSARC 1997/198
-	 */
-	MK_DECLARE32("rbytes", NULL),
-	MK_DECLARE32("obytes", NULL),
-	MK_DECLARE32("multircv", NULL),
-	MK_DECLARE32("multixmt", NULL),
-	MK_DECLARE32("brdcstrcv", NULL),
-	MK_DECLARE32("brdcstxmt", NULL),
-	/*
-	 * Error values
-	 */
-	MK_ERROR32("norcvbuf", NULL),
-	MK_ERROR32("noxmtbuf", NULL),
-	MK_ERROR32("unknowns", NULL),
-	/*
-	 * These are the 64-bit values, they fallback to 32-bit values
-	 */
-	MK_DECLARE64("ipackets64", "ipackets"),
-	MK_DECLARE64("opackets64", "opackets"),
-	MK_DECLARE64("rbytes64", "rbytes"),
-	MK_DECLARE64("obytes64", "obytes"),
-
-	/* New AP switching statistics */
-	MK_NOTPHYS64("man_switches"),
-	MK_NOTPHYS64("man_link_fails"),
-	MK_NOTPHYS64("man_link_stales"),
-	MK_NOTPHYS64("man_icmpv4_probes"),
-	MK_NOTPHYS64("man_icmpv6_probes"),
-
-	MK_ERROR32("align_errors", "framing"),
-	MK_ERROR32("fcs_errors", "crc"),
-	MK_ERROR32("first_collisions", NULL),
-	MK_ERROR32("multi_collisions", NULL),
-	MK_ERROR32("sqe_errors", "sqe"),
-
-	MK_ERROR32("tx_late_collisions", NULL),
-	MK_ERROR32("ex_collisions", "excollisions"),
-	MK_ERROR32("macxmt_errors", NULL),
-	MK_ERROR32("carrier_errors", "nocarrier"),
-	MK_ERROR32("toolong_errors", "buff"),
-	MK_ERROR32("macrcv_errors", NULL),
-
-	MK_OBSOLETE32("framing", "align_errors"),
-	MK_OBSOLETE32("crc", "fcs_errors"),
-	MK_OBSOLETE32("sqe", "sqe_errors"),
-	MK_OBSOLETE32("excollisions", "ex_collisions"),
-	MK_OBSOLETE32("nocarrier", "carrier_errors"),
-	MK_OBSOLETE32("buff", "toolong_errors"),
-};
-
-#define	MAN_NUMSTATS (sizeof (man_kstat_info) / sizeof (man_kstat_info_t))
-
-/*
- * Miscellaneous ethernet stuff.
- *
- * MANs DL_INFO_ACK template.
- */
-static	dl_info_ack_t man_infoack = {
-	DL_INFO_ACK,				/* dl_primitive */
-	ETHERMTU,				/* dl_max_sdu */
-	0,					/* dl_min_sdu */
-	MAN_ADDRL,				/* dl_addr_length */
-	DL_ETHER,				/* dl_mac_type */
-	0,					/* dl_reserved */
-	0,					/* dl_current_state */
-	-2,					/* dl_sap_length */
-	DL_CLDLS,				/* 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) + MAN_ADDRL,	/* dl_brdcst_addr_offset */
-	0					/* dl_growth */
-};
-
-/*
- * Ethernet broadcast address definition.
- */
-static	struct ether_addr	etherbroadcast = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-static struct ether_addr zero_ether_addr = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/*
- * Set via MAN_SET_SC_IPADDRS ioctl.
- */
-man_sc_ipaddrs_t	man_sc_ipaddrs = { 0xffffffffU, 0xffffffffU };
-
-/*
- * Set via MAN_SET_SC_IP6ADDRS ioctl.
- */
-man_sc_ip6addrs_t	man_sc_ip6addrs = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/*
- * IP & ICMP constants
- */
-#ifndef	ETHERTYPE_IPV6
-#define	ETHERTYPE_IPV6 0x86DD
-#endif
-
-/*
- * Function prototypes.
- *
- * Upper multiplexor functions.
- */
-static int	man_attach(dev_info_t *, ddi_attach_cmd_t);
-static int	man_detach(dev_info_t *, ddi_detach_cmd_t);
-static int	man_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int	man_open(register queue_t *, dev_t *, int, int, cred_t *);
-static int	man_configure(queue_t *);
-static int	man_deconfigure(void);
-static int	man_init_dests(man_t *, manstr_t *);
-static void	man_start_dest(man_dest_t *, manstr_t *, man_pg_t *);
-static void	man_set_optimized_dest(manstr_t *);
-static int	man_close(queue_t *, int, cred_t *);
-static void	man_cancel_timers(man_adest_t *);
-static int	man_uwput(queue_t *, mblk_t *);
-static int	man_start(queue_t *, mblk_t *, eaddr_t *);
-static void	man_ioctl(queue_t *, mblk_t *);
-static void	man_set_linkcheck_time(queue_t *, mblk_t *);
-static void	man_setpath(queue_t *, mblk_t *);
-static void	man_geteaddr(queue_t *, mblk_t *);
-static void	man_set_sc_ipaddrs(queue_t *, mblk_t *);
-static void	man_set_sc_ip6addrs(queue_t *, mblk_t *);
-static int	man_get_our_etheraddr(eaddr_t *eap);
-static void	man_nd_getset(queue_t *, mblk_t *);
-static void	man_dl_ioc_hdr_info(queue_t *, mblk_t *);
-static int	man_uwsrv(queue_t *);
-static int	man_proto(queue_t *, mblk_t *);
-static int	man_udreq(queue_t *, mblk_t *);
-static void	man_areq(queue_t *, mblk_t *);
-static mblk_t	*man_alloc_physreq_mp(eaddr_t *);
-static void	man_dreq(queue_t *, mblk_t *);
-static void	man_dodetach(manstr_t *, man_work_t *);
-static void	man_dl_clean(mblk_t **);
-static void	man_breq(queue_t *, mblk_t *);
-static void	man_ubreq(queue_t *, mblk_t *);
-static void	man_ireq(queue_t *, mblk_t *);
-static void	man_ponreq(queue_t *, mblk_t *);
-static void	man_poffreq(queue_t *, mblk_t *);
-static void	man_emreq(queue_t *, mblk_t *);
-static void	man_dmreq(queue_t *, mblk_t *);
-static void	man_pareq(queue_t *, mblk_t *);
-static void	man_spareq(queue_t *, mblk_t *);
-static int	man_dlpi(manstr_t *, mblk_t *);
-static int	man_dlioc(manstr_t *, mblk_t *);
-static int	man_dl_catch(mblk_t **, mblk_t *);
-static void	man_dl_release(mblk_t **, mblk_t *);
-static int	man_match_proto(mblk_t *, mblk_t *);
-static int	man_open_ctl();
-static void	man_close_ctl();
-/*
- * upper/lower multiplexor functions.
- */
-static int	man_dlpi_senddown(manstr_t *, mblk_t *);
-static int	man_start_lower(man_dest_t *, mblk_t *, queue_t *, int caller);
-static int	man_lrput(queue_t *, mblk_t *);
-/*
- * Lower multiplexor functions.
- */
-static int	man_lwsrv(queue_t *);
-static int	man_lrsrv(queue_t *);
-static void	man_dlpi_replay(man_dest_t *, mblk_t *);
-static int	man_dlioc_replay(man_dest_t *);
-/*
- * Link failover routines.
- */
-static int	man_gettimer(int, man_dest_t *);
-static void	man_linkcheck_timer(void *);
-static int	man_needs_linkcheck(man_dest_t *);
-static int	man_do_autoswitch(man_dest_t *);
-static int	man_autoswitch(man_pg_t *, man_dev_t *, man_work_t *);
-static int	man_prep_dests_for_switch(man_pg_t *, man_dest_t **, int *);
-static int	man_str_uses_pg(manstr_t *, man_pg_t *);
-static void	man_do_icmp_bcast(man_dest_t *, t_uscalar_t);
-static mblk_t	*man_alloc_udreq(int, man_dladdr_t *);
-static mblk_t	*man_pinger(t_uscalar_t);
-/*
- * Functions normally executing outside of the STREAMs perimeter.
- */
-/*
- * Functions supporting/processing work requests.
- */
-static void	man_bwork(void);
-static void	man_iwork(void);		/* inside perimeter */
-void		man_work_add(man_workq_t *, man_work_t *);
-man_work_t	*man_work_alloc(int, int);
-void		man_work_free(man_work_t *);
-/*
- * Functions implementing/supporting failover.
- *
- * Executed inside perimeter.
- */
-static int	man_do_dr_attach(man_work_t *);
-static int	man_do_dr_switch(man_work_t *);
-static void	man_do_dr_detach(man_work_t *);
-static int	man_iswitch(man_work_t *);
-static void	man_ifail_dest(man_dest_t *);
-static man_dest_t *man_switch_match(man_dest_t *, int, void *);
-static void	man_add_dests(man_pg_t *);
-static void	man_reset_dlpi(void *);
-static mblk_t	*man_dup_mplist(mblk_t *);
-static mblk_t	*man_alloc_ubreq_dreq();
-/*
- * Executed outside perimeter (us man_lock for synchronization).
- */
-static void	man_bclose(man_adest_t *);
-static void	man_bswitch(man_adest_t *, man_work_t *);
-static int	man_plumb(man_dest_t *);
-static void	man_unplumb(man_dest_t *);
-static void	man_plink(queue_t *, mblk_t *);
-static void	man_unplink(queue_t *, mblk_t *);
-static void	man_linkrec_insert(man_linkrec_t *);
-static queue_t	*man_linkrec_find(int);
-/*
- * Functions supporting pathgroups
- */
-int	man_pg_cmd(mi_path_t *, man_work_t *);
-static int	man_pg_assign(man_pg_t **, mi_path_t *, int);
-static int	man_pg_create(man_pg_t **, man_pg_t **, mi_path_t *);
-static int	man_pg_unassign(man_pg_t **, mi_path_t *);
-static int	man_pg_activate(man_t *, mi_path_t *, man_work_t *);
-static int	man_pg_read(man_pg_t *, mi_path_t *);
-static man_pg_t	*man_find_path_by_dev(man_pg_t *, man_dev_t *, man_path_t **);
-static man_pg_t	*man_find_pg_by_id(man_pg_t *, int);
-static man_path_t	*man_find_path_by_ppa(man_path_t *, int);
-static man_path_t	*man_find_active_path(man_path_t *);
-static man_path_t	*man_find_alternate_path(man_path_t *);
-static void	man_path_remove(man_path_t **, man_path_t *);
-static void	man_path_insert(man_path_t **, man_path_t *);
-static void	man_path_merge(man_path_t **, man_path_t *);
-static int	man_path_kstat_init(man_path_t *);
-static void	man_path_kstat_uninit(man_path_t *);
-/*
- * Functions supporting kstat reporting.
- */
-static int	man_kstat_update(kstat_t *, int);
-static void	man_do_kstats(man_work_t *);
-static void	man_update_path_kstats(man_t *);
-static void 	man_update_dev_kstats(kstat_named_t *, man_path_t *);
-static void	man_sum_dests_kstats(kstat_named_t *, man_pg_t *);
-static void	man_kstat_named_init(kstat_named_t *, int);
-static int	man_kstat_byname(kstat_t *, char *, kstat_named_t *);
-static void	man_sum_kstats(kstat_named_t *, kstat_t *, kstat_named_t *);
-/*
- * Functions supporting ndd.
- */
-static int	man_param_register(param_t *, int);
-static int	man_pathgroups_report(queue_t *, mblk_t *, caddr_t, cred_t *);
-static void	man_preport(man_path_t *, mblk_t *);
-static int	man_set_active_path(queue_t *, mblk_t *, char *, caddr_t,
-			cred_t *);
-static int	man_get_hostinfo(queue_t *, mblk_t *, caddr_t, cred_t *);
-static char	*man_inet_ntoa(in_addr_t);
-static int	man_param_get(queue_t *, mblk_t *, caddr_t, cred_t *);
-static int	man_param_set(queue_t *, mblk_t *, char *, caddr_t, cred_t *);
-static  void    man_param_cleanup(void);
-static  void    man_nd_free(caddr_t *nd_pparam);
-/*
- * MAN SSC/Domain specific externs.
- */
-extern int	man_get_iosram(manc_t *);
-extern int	man_domain_configure(void);
-extern int	man_domain_deconfigure(void);
-extern int	man_dossc_switch(uint32_t);
-extern int	man_is_on_domain;
-
-/*
- * Driver Globals protected by inner perimeter.
- */
-static manstr_t	*man_strup = NULL;	/* list of MAN STREAMS */
-static caddr_t	man_ndlist = NULL;	/* head of ndd var list */
-void		*man_softstate = NULL;
-
-/*
- * Driver globals protected by man_lock.
- */
-kmutex_t		man_lock;		/* lock protecting vars below */
-static kthread_id_t	man_bwork_id = NULL;	/* background thread ID */
-man_workq_t		*man_bwork_q;		/* bgthread work q */
-man_workq_t		*man_iwork_q;		/* inner perim (uwsrv) work q */
-static man_linkrec_t	*man_linkrec_head = NULL;	/* list of linkblks */
-ldi_handle_t		man_ctl_lh = NULL;	/* MAN control handle */
-queue_t			*man_ctl_wq = NULL;	/* MAN control rq */
-static int		man_config_state = MAN_UNCONFIGURED;
-static int		man_config_error = ENODEV;
-
-/*
- * These parameters are accessed via ndd to report the link configuration
- * for the MAN driver. They can also be used to force configuration changes.
- */
-#define	MAN_NOTUSR	0x0f000000
-
-/* ------------------------------------------------------------------------- */
-
-static  param_t	man_param_arr[] = {
-	/* min		max		value		name */
-	{  0,		0xFFFF,		0,		"man_debug_level"},
-};
-
-#define	MAN_NDD_GETABLE	1
-#define	MAN_NDD_SETABLE	2
-
-static  uint32_t	man_param_display[] = {
-/* DISPLAY */
-MAN_NDD_SETABLE,	/* man_debug_level */
-};
-
-/*
- * STREAMs information.
- */
-static struct module_info man_m_info = {
-	MAN_IDNUM,			/* mi_idnum */
-	MAN_IDNAME,			/* mi_idname */
-	MAN_MINPSZ,			/* mi_minpsz */
-	MAN_MAXPSZ,			/* mi_maxpsz */
-	MAN_HIWAT,			/* mi_hiwat */
-	MAN_LOWAT			/* mi_lowat */
-};
-
-/*
- * Upper read queue does not do anything.
- */
-static struct qinit man_urinit = {
-	NULL,				/* qi_putp */
-	NULL,				/* qi_srvp */
-	man_open,			/* qi_qopen */
-	man_close,			/* qi_qclose */
-	NULL,				/* qi_qadmin */
-	&man_m_info,			/* qi_minfo */
-	NULL				/* qi_mstat */
-};
-
-static struct qinit man_lrinit = {
-	man_lrput,			/* qi_putp */
-	man_lrsrv,			/* qi_srvp */
-	man_open,			/* qi_qopen */
-	man_close,			/* qi_qclose */
-	NULL,				/* qi_qadmin */
-	&man_m_info,			/* qi_minfo */
-	NULL				/* qi_mstat */
-};
-
-static struct qinit man_uwinit = {
-	man_uwput,			/* qi_putp */
-	man_uwsrv,			/* qi_srvp */
-	man_open,			/* qi_qopen */
-	man_close,			/* qi_qclose */
-	NULL,				/* qi_qadmin */
-	&man_m_info,			/* qi_minfo */
-	NULL				/* qi_mstat */
-};
-
-static struct qinit man_lwinit = {
-	NULL,				/* qi_putp */
-	man_lwsrv,			/* qi_srvp */
-	man_open,			/* qi_qopen */
-	man_close,			/* qi_qclose */
-	NULL,				/* qi_qadmin */
-	&man_m_info,			/* qi_minfo */
-	NULL				/* qi_mstat */
-};
-
-static struct streamtab man_maninfo = {
-	&man_urinit,			/* st_rdinit */
-	&man_uwinit,			/* st_wrinit */
-	&man_lrinit,			/* st_muxrinit */
-	&man_lwinit			/* st_muxwrinit */
-};
-
-
-/*
- * Module linkage information for the kernel.
- *
- * Locking Theory:
- * 	D_MTPERMOD -	Only an inner perimeter: All routines single
- * 			threaded (except put, see below).
- *	D_MTPUTSHARED -	Put routines enter inner perimeter shared (not
- *			exclusive) for concurrency/performance reasons.
- *
- *	Anyone who needs exclusive outer perimeter permission (changing
- *	global data structures) does so via qwriter() calls. The
- *	background thread does all its work outside of perimeter and
- *	submits work via qtimeout() when data structures need to be
- *	modified.
- */
-
-#define	MAN_MDEV_FLAGS	(D_MP|D_MTPERMOD|D_MTPUTSHARED)
-
-DDI_DEFINE_STREAM_OPS(man_ops, nulldev, nulldev, man_attach,
-    man_detach, nodev, man_info, MAN_MDEV_FLAGS, &man_maninfo,
-    ddi_quiesce_not_supported);
-
-extern int nodev(), nulldev();
-
-static struct modldrv modldrv = {
-	&mod_driverops, 	/* Module type.  This one is a pseudo driver */
-	"MAN MetaDriver",
-	&man_ops,		/* driver ops */
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *) &modldrv,
-	NULL
-};
-
-
-/* Virtual Driver loader entry points */
-
-int
-_init(void)
-{
-	int		status = DDI_FAILURE;
-
-	MAN_DBG(MAN_INIT, ("_init:"));
-
-	status = mod_install(&modlinkage);
-	if (status != 0) {
-		cmn_err(CE_WARN, "man_init: mod_install failed"
-		    " error = %d", status);
-		return (status);
-	}
-
-	status = ddi_soft_state_init(&man_softstate, sizeof (man_t), 4);
-	if (status != 0) {
-		cmn_err(CE_WARN, "man_init: ddi_soft_state_init failed"
-		    " error = %d", status);
-		(void) mod_remove(&modlinkage);
-		return (status);
-	}
-
-	man_bwork_q = man_kzalloc(sizeof (man_workq_t), KM_SLEEP);
-	man_iwork_q = man_kzalloc(sizeof (man_workq_t), KM_SLEEP);
-
-	mutex_init(&man_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&man_bwork_q->q_cv, NULL, CV_DRIVER, NULL);
-	cv_init(&man_iwork_q->q_cv, NULL, CV_DRIVER, NULL);
-
-	return (0);
-}
-
-/*
- * _info is called by modinfo().
- */
-int
-_info(struct modinfo *modinfop)
-{
-	int	status;
-
-	MAN_DBG(MAN_INIT, ("_info:"));
-
-	status = mod_info(&modlinkage, modinfop);
-
-	MAN_DBG(MAN_INIT, ("_info: returns %d", status));
-
-	return (status);
-}
-
-/*
- * _fini called by modunload() just before driver is unloaded from memory.
- */
-int
-_fini(void)
-{
-	int status = 0;
-
-	MAN_DBG(MAN_INIT, ("_fini:"));
-
-
-	/*
-	 * The only upper stream left should be man_ctl_lh. Note that
-	 * man_close (upper stream) is synchronous (i.e. it waits for
-	 * all STREAMS framework associated with the upper stream to be
-	 * torn down). This guarantees that man_ctl_lh will never become
-	 * NULL until noone is around to notice. This assumption is made
-	 * in a few places like man_plumb, man_unplumb, etc.
-	 */
-	if (man_strup && (man_strup->ms_next != NULL))
-		return (EBUSY);
-
-	/*
-	 * Deconfigure the driver.
-	 */
-	status = man_deconfigure();
-	if (status)
-		goto exit;
-
-	/*
-	 * need to detach every instance of the driver
-	 */
-	status = mod_remove(&modlinkage);
-	if (status != 0)
-		goto exit;
-
-	ddi_soft_state_fini(&man_softstate);
-
-	/*
-	 * Free up locks.
-	 */
-	mutex_destroy(&man_lock);
-	cv_destroy(&man_bwork_q->q_cv);
-	cv_destroy(&man_iwork_q->q_cv);
-
-	man_kfree(man_bwork_q, sizeof (man_workq_t));
-	man_kfree(man_iwork_q, sizeof (man_workq_t));
-
-exit:
-
-	MAN_DBG(MAN_INIT, ("_fini: returns %d", status));
-
-	return (status);
-}
-
-/*
- * Deconfigure the MAN driver.
- */
-static int
-man_deconfigure()
-{
-	man_work_t	*wp;
-	int		status = 0;
-
-	MAN_DBG(MAN_CONFIG, ("man_deconfigure:\n"));
-
-	mutex_enter(&man_lock);
-
-	if (man_is_on_domain) {
-		status = man_domain_deconfigure();
-		if (status != 0)
-			goto exit;
-	}
-
-	man_param_cleanup();	/* Free up NDD resources */
-
-	/*
-	 * I may have to handle straggling work requests. Just qwait?
-	 * or cvwait? Called from _fini - TBD
-	 */
-	ASSERT(man_bwork_q->q_work == NULL);
-	ASSERT(man_iwork_q->q_work == NULL);
-
-	MAN_DBG(MAN_CONFIG, ("man_deconfigure: submitting CLOSE_CTL\n"));
-
-	if (man_ctl_lh != NULL) {
-		wp = man_work_alloc(MAN_WORK_CLOSE_CTL, KM_SLEEP);
-		wp->mw_flags = MAN_WFLAGS_CVWAITER;
-		man_work_add(man_bwork_q, wp);
-
-		while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
-			cv_wait(&wp->mw_cv, &man_lock);
-		}
-		man_work_free(wp);
-	}
-
-	MAN_DBG(MAN_CONFIG, ("man_deconfigure: submitting STOP\n"));
-	if (man_bwork_id != NULL) {
-
-		wp = man_work_alloc(MAN_WORK_STOP, KM_SLEEP);
-		wp->mw_flags = MAN_WFLAGS_CVWAITER;
-		man_work_add(man_bwork_q, wp);
-
-		while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
-			cv_wait(&wp->mw_cv, &man_lock);
-		}
-		man_work_free(wp);
-	}
-	man_config_state = MAN_UNCONFIGURED;
-
-exit:
-	mutex_exit(&man_lock);
-
-	MAN_DBG(MAN_CONFIG, ("man_deconfigure: returns %d\n", status));
-
-	return (status);
-}
-
-/*
- * man_attach - allocate resources and attach an instance of the MAN driver
- * The <man>.conf file controls how many instances of the MAN driver are
- * available.
- *
- *	dip - devinfo of node
- * 	cmd - one of DDI_ATTACH | DDI_RESUME
- *
- *	returns	- success - DDI_SUCCESS
- *		- failure - DDI_FAILURE
- */
-static int
-man_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
-	man_t		*manp;		/* per instance data */
-	uchar_t		flag = KSTAT_FLAG_WRITABLE; /* support netstat -kc */
-	kstat_t		*ksp;
-	int		minor_node_created = 0;
-	int		instance;
-	eaddr_t		man_eaddr;
-
-	MAN_DBG(MAN_INIT, ("man_attach: \n"));
-
-	if (cmd != DDI_ATTACH) {
-		MAN_DBG(MAN_INIT, ("man_attach: bad command %d\n", cmd));
-		return (DDI_FAILURE);
-	}
-
-	if (man_get_our_etheraddr(&man_eaddr))
-		return (DDI_FAILURE);
-
-	instance = ddi_get_instance(dip);
-
-	/*
-	 * we assume that instance is always equal to zero.
-	 * and there will always only be one instance.
-	 * this is done because when dman opens itself via DMAN_INT_PATH,
-	 * the path assumes that the instance number is zero.
-	 * if we ever need to support multiple instances of the dman
-	 * driver or non-zero instances, this will have to change.
-	 */
-	ASSERT(instance == 0);
-
-	/*
-	 * Allocate per device info pointer and link in to global list of
-	 * MAN devices.
-	 */
-	if ((ddi_soft_state_zalloc(man_softstate, instance) != DDI_SUCCESS) ||
-	    ((manp = ddi_get_soft_state(man_softstate, instance)) == NULL)) {
-		cmn_err(CE_WARN, "man_attach: cannot zalloc soft state!");
-		return (DDI_FAILURE);
-	}
-
-	ddi_set_driver_private(dip, manp);
-	manp->man_dip = dip;
-	manp->man_meta_major = ddi_driver_major(dip);
-	manp->man_meta_ppa = instance;
-
-	/*
-	 * Set ethernet address. Note that this address is duplicated
-	 * at md_src_eaddr.
-	 */
-	ether_copy(&man_eaddr, &manp->man_eaddr);
-	manp->man_eaddr_v = 1;
-
-	MAN_DBG(MAN_INIT, ("man_attach: set ether to %s",
-	    ether_sprintf(&manp->man_eaddr)));
-
-	/*
-	 * Initialize failover-related fields (timers and such),
-	 * taking values from properties if present.
-	 */
-	manp->man_init_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "init_time", MAN_INIT_TIME);
-
-	manp->man_linkcheck_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "linkcheck_time", MAN_LINKCHECK_TIME);
-
-	manp->man_linkstale_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "man_linkstale_time", MAN_LINKSTALE_TIME);
-
-	manp->man_linkstale_retries = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "man_linkstale_retries", MAN_LINKSTALE_RETRIES);
-
-	manp->man_dr_delay = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "man_dr_delay", MAN_DR_DELAY);
-
-	manp->man_dr_retries = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "man_dr_retries", MAN_DR_RETRIES);
-
-	manp->man_kstat_waittime = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "man_kstat_waittime", MAN_KSTAT_WAITTIME);
-
-	manp->man_dlpireset_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-	    "man_dlpireset_time", MAN_DLPIRESET_TIME);
-
-	if (ddi_create_internal_pathname(dip, MAN_IDNAME, S_IFCHR,
-	    ddi_get_instance(dip)) == DDI_SUCCESS) {
-		minor_node_created = 1;
-	} else {
-		cmn_err(CE_WARN, "man_attach: failed for instance %d",
-		    ddi_get_instance(dip));
-		goto exit;
-	}
-
-	if (ddi_create_minor_node(dip, MAN_IDNAME, S_IFCHR,
-	    ddi_get_instance(dip), DDI_NT_NET, CLONE_DEV) == DDI_SUCCESS) {
-		minor_node_created = 1;
-	} else {
-		cmn_err(CE_WARN, "man_attach: failed for instance %d",
-		    ddi_get_instance(dip));
-		goto exit;
-	}
-
-	/*
-	 * Allocate meta kstat_t for this instance of the driver.
-	 * Note that each of man_path_t keeps track of the kstats
-	 * for the real devices via mp_last_knp.
-	 */
-#ifdef	kstat
-	flag |= KSTAT_FLAG_PERSISTENT;
-#endif
-	ksp = kstat_create(MAN_IDNAME, ddi_get_instance(dip), NULL, "net",
-	    KSTAT_TYPE_NAMED, MAN_NUMSTATS, flag);
-
-	if (ksp == NULL) {
-		cmn_err(CE_WARN, "man_attach(%d): kstat_create failed"
-		    " - manp(0x%p)", manp->man_meta_ppa,
-		    (void *)manp);
-		goto exit;
-	}
-
-	man_kstat_named_init(ksp->ks_data, MAN_NUMSTATS);
-	ksp->ks_update = man_kstat_update;
-	ksp->ks_private = (void *) manp;
-	manp->man_ksp = ksp;
-	kstat_install(manp->man_ksp);
-
-	ddi_report_dev(dip);
-
-	MAN_DBG(MAN_INIT, ("man_attach(%d) returns DDI_SUCCESS",
-	    ddi_get_instance(dip)));
-
-	return (DDI_SUCCESS);
-
-exit:
-	if (minor_node_created)
-		ddi_remove_minor_node(dip, NULL);
-	ddi_set_driver_private(dip, NULL);
-	ddi_soft_state_free(man_softstate, instance);
-
-	MAN_DBG(MAN_INIT, ("man_attach(%d) eaddr returns DDI_FAILIRE",
-	    ddi_get_instance(dip)));
-
-	return (DDI_FAILURE);
-
-}
-
-static int
-man_get_our_etheraddr(eaddr_t *eap)
-{
-	manc_t	manc;
-	int	status = 0;
-
-	if (man_is_on_domain) {
-		if (status = man_get_iosram(&manc))
-			return (status);
-		ether_copy(&manc.manc_dom_eaddr, eap);
-	} else {
-		(void) localetheraddr((struct ether_addr *)NULL, eap);
-	}
-
-	return (status);
-}
-
-/*
- * man_detach - detach an instance of a driver
- *
- *	dip - devinfo of node
- * 	cmd - one of DDI_DETACH | DDI_SUSPEND
- *
- *	returns	- success - DDI_SUCCESS
- *		- failure - DDI_FAILURE
- */
-static int
-man_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
-	register man_t	*manp;		/* per instance data */
-	int		instance;
-
-	MAN_DBG(MAN_INIT, ("man_detach(%d):\n", ddi_get_instance(dip)));
-
-	if (cmd != DDI_DETACH) {
-		MAN_DBG(MAN_INIT, ("man_detach: bad command %d\n", cmd));
-		return (DDI_FAILURE);
-	}
-
-	if (dip == NULL) {
-		MAN_DBG(MAN_INIT, ("man_detach: dip == NULL\n"));
-		return (DDI_FAILURE);
-	}
-
-	instance = ddi_get_instance(dip);
-
-	mutex_enter(&man_lock);
-
-	manp = (man_t *)ddi_get_soft_state(man_softstate, instance);
-	if (manp == NULL) {
-		mutex_exit(&man_lock);
-
-		cmn_err(CE_WARN, "man_detach: unable to get softstate"
-		    " for instance = %d, dip = 0x%p!\n", instance,
-		    (void *)dip);
-		return (DDI_FAILURE);
-	}
-
-	if (manp->man_refcnt != 0) {
-		mutex_exit(&man_lock);
-
-		cmn_err(CE_WARN, "man_detach: %s%d refcnt %d", MAN_IDNAME,
-		    instance, manp->man_refcnt);
-		MAN_DBGCALL(MAN_INIT, man_print_man(manp));
-
-		return (DDI_FAILURE);
-	}
-
-	ddi_remove_minor_node(dip, NULL);
-
-	mutex_exit(&man_lock);
-
-	kstat_delete(manp->man_ksp);
-	ddi_soft_state_free(man_softstate, instance);
-	ddi_set_driver_private(dip, NULL);
-
-	MAN_DBG(MAN_INIT, ("man_detach returns DDI_SUCCESS"));
-
-	return (DDI_SUCCESS);
-}
-
-/*
- * man_info:
- *	As a standard DLPI style-2, man_info() should always return
- *	DDI_FAILURE.
- *
- *	However, man_open() has special treatment for a direct open
- *	via kstr_open() without going through the CLONE driver.
- *	To make this special kstr_open() work, we need to map
- *	minor of 0 to instance 0.
- */
-/*ARGSUSED*/
-static int
-man_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
-	minor_t minor;
-
-	switch (infocmd) {
-	case DDI_INFO_DEVT2DEVINFO:
-		break;
-
-	case DDI_INFO_DEVT2INSTANCE:
-		minor = getminor((dev_t)arg);
-		if (minor == 0) {
-			*result = (void *)(uintptr_t)minor;
-			return (DDI_SUCCESS);
-		}
-		break;
-	default:
-		break;
-	}
-	return (DDI_FAILURE);
-}
-
-/* Standard Device Driver entry points */
-
-/*
- * man_open - open the device
- *
- *	rq - upper read queue of the stream
- *	devp - pointer to a device number
- *	flag - information passed from the user program open(2) system call
- *	sflag - stream flags
- *	credp - pointer to the cred(9S) user credential structure
- *
- *	returns	- success - 0
- *		- failure - errno value for failure
- */
-/*ARGSUSED*/
-static int
-man_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
-{
-	int			minordev = -1;
-	manstr_t		*msp;
-	manstr_t		*tsp;
-	manstr_t		**prevmsp;
-	int			status = 0;
-
-	MAN_DBG(MAN_OCLOSE, ("man_open: rq(0x%p) sflag(0x%x)\n",
-	    (void *)rq, sflag));
-
-	ASSERT(rq);
-	ASSERT(sflag != MODOPEN);
-
-	/*
-	 * reopen; q_ptr set to msp at open completion.
-	 */
-	if (rq->q_ptr) {
-		return (0);
-	}
-
-	/*
-	 * Allocate and initialize manstr_t for this device.
-	 */
-	msp = man_kzalloc(sizeof (manstr_t), KM_SLEEP);
-	SETSTATE(msp, DL_UNATTACHED);
-	msp->ms_meta_ppa = -1;
-	msp->ms_rq = rq;
-	rq->q_ptr = WR(rq)->q_ptr = msp;
-
-	/*
-	 * Get the MAN driver configured on 1st open.  Note that the only way
-	 * we get sflag != CLONEOPEN is via the call in man_plumbctl().  All
-	 * CLONEOPEN calls to man_open will be via the file system
-	 * device node /dev/man, a pseudo clone device.
-	 */
-
-	qprocson(rq);
-
-	if (sflag == CLONEOPEN && man_config_state != MAN_CONFIGURED) {
-		/*
-		 * First open calls man_configure. Everyone qwaits until
-		 * we get it open. See man_open_ctl() comments for mutex
-		 * lock/synchronization info.
-		 */
-
-		mutex_enter(&man_lock);
-
-		if (man_config_state == MAN_UNCONFIGURED) {
-			man_config_state = MAN_CONFIGURING;
-			mutex_exit(&man_lock);
-			status = man_configure(rq);
-			if (status != 0)
-				goto exit;
-		} else {
-			while (man_config_state == MAN_CONFIGURING) {
-
-				mutex_exit(&man_lock);
-				status = qwait_sig(rq);
-
-				if (status == 0) {
-					status = EINTR;
-					goto exit;
-				}
-
-				mutex_enter(&man_lock);
-			}
-			mutex_exit(&man_lock);
-
-			if (man_config_error) {
-				status = man_config_error;
-				goto exit;
-			}
-		}
-	}
-
-	/*
-	 * Determine minor device number. man_open serialized by
-	 * D_MTPERMOD.
-	 */
-	prevmsp = &man_strup;
-	if (sflag == CLONEOPEN) {
-
-		minordev = 0;
-		for (; (tsp = *prevmsp) != NULL; prevmsp = &tsp->ms_next) {
-			if (minordev < tsp->ms_minor)
-				break;
-			minordev++;
-		}
-		*devp = makedevice(getmajor(*devp), minordev);
-
-	} else {
-		/*
-		 * Should only get here from man_plumbctl().
-		 */
-		/*LINTED E_ASSIGN_UINT_TO_SIGNED_INT*/
-		minordev = getminor(*devp);
-
-		/*
-		 * No need to protect this here as all opens are
-		 * qwaiting, and the bgthread (who is doing this open)
-		 * is the only one who mucks with this variable.
-		 */
-		man_ctl_wq = WR(rq);
-
-		ASSERT(minordev == 0);	/* TBD delete this */
-	}
-
-	msp->ms_meta_maj = getmajor(*devp);
-	msp->ms_minor = minordev;
-	if (minordev == 0)
-		msp->ms_flags = MAN_SFLAG_CONTROL;
-
-	/*
-	 * Link new entry into global list of active entries.
-	 */
-	msp->ms_next = *prevmsp;
-	*prevmsp = msp;
-
-
-	/*
-	 * Disable automatic enabling of our write service procedure.
-	 * We control this explicitly.
-	 */
-	noenable(WR(rq));
-
-exit:
-	MAN_DBG(MAN_OCLOSE, ("man_open: exit rq(0x%p) minor %d errno %d\n",
-	    (void *)rq, minordev, status));
-
-	/*
-	 * Clean up on error.
-	 */
-	if (status) {
-		qprocsoff(rq);
-		rq->q_ptr = WR(rq)->q_ptr = NULL;
-		man_kfree((char *)msp, sizeof (manstr_t));
-	} else
-		(void) qassociate(rq, -1);
-
-	return (status);
-}
-
-/*
- * Get the driver configured.  Called from first man_open with exclusive
- * inner perimeter.
- */
-static int
-man_configure(queue_t *rq)
-{
-	man_work_t	*wp;
-	int		status = 0;
-
-	MAN_DBG(MAN_CONFIG, ("man_configure:"));
-
-	/*
-	 * Initialize NDD parameters.
-	 */
-	if (!man_ndlist &&
-	    !man_param_register(man_param_arr, A_CNT(man_param_arr))) {
-		cmn_err(CE_WARN, "man_configure: man_param_register failed!");
-		man_config_error = ENOMEM;
-		goto exit;
-	}
-
-	mutex_enter(&man_lock);
-
-	/*
-	 * Start up background thread.
-	 */
-	if (man_bwork_id == NULL)
-		man_bwork_id = thread_create(NULL, 2 * DEFAULTSTKSZ,
-		    man_bwork, NULL, 0, &p0, TS_RUN, minclsyspri);
-
-	/*
-	 * Submit work to get control stream opened. Qwait until its
-	 * done. See man_open_ctl for mutex lock/synchronization info.
-	 */
-
-	if (man_ctl_lh == NULL) {
-		wp = man_work_alloc(MAN_WORK_OPEN_CTL, KM_SLEEP);
-		wp->mw_flags |= MAN_WFLAGS_QWAITER;
-		wp->mw_q = WR(rq);
-
-		/*
-		 * Submit work and wait. When man_open_ctl exits
-		 * man_open, it will cause qwait below to return.
-		 */
-		man_work_add(man_bwork_q, wp);
-		while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
-			mutex_exit(&man_lock);
-			qwait(rq);
-			mutex_enter(&man_lock);
-		}
-		status = wp->mw_status;
-		man_work_free(wp);
-
-	}
-	mutex_exit(&man_lock);
-
-	/*
-	 * If on domain, setup IOSRAM and build the pathgroups
-	 * automatically.
-	 */
-	if ((status == 0) && man_is_on_domain)
-		status = man_domain_configure();
-
-exit:
-	mutex_enter(&man_lock);
-
-	man_config_error = status;
-	if (status != 0)
-		man_config_state = MAN_UNCONFIGURED;
-	else
-		man_config_state = MAN_CONFIGURED;
-
-	mutex_exit(&man_lock);
-
-	MAN_DBG(MAN_CONFIG, ("man_configure: returns %d\n", status));
-
-	return (status);
-}
-
-/*
- * man_close - close the device
- *
- *	rq - upper read queue of the stream
- *
- *	returns	- success - 0
- *		- failure - errno value for failure
- */
-static int
-man_close(queue_t *rq, int flag __unused, cred_t *cr __unused)
-{
-	manstr_t		*close_msp;
-	manstr_t		*msp;
-
-	MAN_DBG(MAN_OCLOSE, ("man_close: rq(0x%p)\n", (void *)rq));
-
-	qprocsoff(rq);
-	close_msp = (manstr_t *)rq->q_ptr;
-
-	/*
-	 * Unlink the per-Stream entry from the active list and free it.
-	 */
-	if (close_msp == man_strup)
-		man_strup = close_msp->ms_next;
-	else {
-		for (msp = man_strup; msp && msp->ms_next != close_msp; )
-			msp = msp->ms_next;
-
-		if (msp == NULL) {
-			cmn_err(CE_WARN, "man_close: no stream!");
-			return (ENODEV);
-		}
-
-		msp->ms_next = close_msp->ms_next;
-	}
-
-	if (close_msp->ms_dests != NULL) {
-		/*
-		 * Still DL_ATTACHED
-		 */
-		man_work_t *wp;
-
-		wp = man_work_alloc(MAN_WORK_CLOSE_STREAM, KM_SLEEP);
-		man_dodetach(close_msp, wp);
-	}
-
-	if (close_msp->ms_flags & MAN_SFLAG_CONTROL) {
-		/*
-		 * Driver about to unload.
-		 */
-		man_ctl_wq = NULL;
-	}
-
-	rq->q_ptr = WR(rq)->q_ptr = NULL;
-	man_kfree((char *)close_msp, sizeof (manstr_t));
-	(void) qassociate(rq, -1);
-
-	MAN_DBG(MAN_OCLOSE, ("man_close: exit\n"));
-
-	return (0);
-}
-
-/*
- * Ask bgthread to tear down lower stream and qwait
- * until its done.
- */
-static void
-man_dodetach(manstr_t *msp, man_work_t *wp)
-{
-	man_dest_t	*mdp;
-	int		i;
-	mblk_t		*mp;
-
-	mdp = msp->ms_dests;
-	msp->ms_dests = NULL;
-	msp->ms_destp = NULL;
-
-	/*
-	 * Excise lower dests array, set it closing and hand it to
-	 * background thread to dispose of.
-	 */
-	for (i = 0; i < MAN_MAX_DESTS; i++) {
-
-		mdp[i].md_state |= MAN_DSTATE_CLOSING;
-		mdp[i].md_msp = NULL;
-		mdp[i].md_rq = NULL;
-
-		if (mdp[i].md_lc_timer_id != 0) {
-			(void) quntimeout(man_ctl_wq, mdp[i].md_lc_timer_id);
-			mdp[i].md_lc_timer_id = 0;
-		}
-		if (mdp[i].md_bc_id != 0) {
-			qunbufcall(man_ctl_wq, mdp[i].md_bc_id);
-			mdp[i].md_bc_id = 0;
-		}
-
-		mutex_enter(&mdp[i].md_lock);
-		while ((mp = mdp[i].md_dmp_head) != NULL) {
-			mdp[i].md_dmp_head = mp->b_next;
-			mp->b_next = NULL;
-			freemsg(mp);
-		}
-		mdp[i].md_dmp_count = 0;
-		mdp[i].md_dmp_tail = NULL;
-		mutex_exit(&mdp[i].md_lock);
-	}
-
-	/*
-	 * Dump any DL type messages previously caught.
-	 */
-	man_dl_clean(&msp->ms_dl_mp);
-	man_dl_clean(&msp->ms_dlioc_mp);
-
-	/*
-	 * We need to clear fast path flag when dlioc messages are cleaned.
-	 */
-	msp->ms_flags &= ~MAN_SFLAG_FAST;
-
-	/*
-	 * MAN_WORK_CLOSE_STREAM work request preallocated by caller.
-	 */
-	ASSERT(wp->mw_type == MAN_WORK_CLOSE_STREAM);
-	ASSERT(mdp != NULL);
-	wp->mw_arg.a_mdp = mdp;
-	wp->mw_arg.a_ndests = MAN_MAX_DESTS;
-	wp->mw_arg.a_pg_id = -1;	/* Don't care */
-
-	mutex_enter(&man_lock);
-	man_work_add(man_bwork_q, wp);
-	msp->ms_manp->man_refcnt--;
-	mutex_exit(&man_lock);
-
-	msp->ms_manp = NULL;
-
-}
-
-
-/*
- * man_uwput - handle DLPI messages issued from upstream, the write
- * side of the upper half of multiplexor. Called with shared access to
- * the inner perimeter.
- *
- *	wq - upper write queue of mxx
- *	mp - mblk ptr to DLPI request
- */
-static int
-man_uwput(register queue_t *wq, register mblk_t *mp)
-{
-	register manstr_t	*msp;		/* per stream data */
-	register man_t		*manp;		/* per instance data */
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	MAN_DBG(MAN_UWPUT, ("man_uwput: wq(0x%p) mp(0x%p) db_type(0x%x)"
-	    " msp(0x%p)\n",
-	    (void *)wq, (void *)mp, DB_TYPE(mp), (void *)msp));
-#if DEBUG
-	if (man_debug & MAN_UWPUT) {
-		if (DB_TYPE(mp) == M_IOCTL) {
-			struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
-			MAN_DBG(MAN_UWPUT,
-			    ("man_uwput: M_IOCTL ioc_cmd(0x%x)\n",
-			    iocp->ioc_cmd));
-		} else if (DB_TYPE(mp) == M_CTL) {
-			struct iocblk	*iocp = (struct iocblk *)mp->b_rptr;
-			MAN_DBG(MAN_UWPUT,
-			    ("man_uwput: M_CTL ioc_cmd(0x%x)\n",
-			    iocp->ioc_cmd));
-		}
-	}
-#endif	/* DEBUG */
-
-
-	switch (DB_TYPE(mp)) {
-	case M_DATA:
-		manp = msp->ms_manp;
-
-		if (((msp->ms_flags & (MAN_SFLAG_FAST | MAN_SFLAG_RAW)) == 0) ||
-		    (msp->ms_dlpistate != DL_IDLE) ||
-		    (manp == NULL)) {
-
-			merror(wq, mp, EPROTO);
-			break;
-		}
-
-		if (wq->q_first) {
-			(void) putq(wq, mp);
-			qenable(wq);
-		} else {
-			ehdr_t	*ep = (ehdr_t *)mp->b_rptr;
-
-			(void) man_start(wq, mp, &ep->ether_dhost);
-		}
-		break;
-
-	case M_PROTO:
-	case M_PCPROTO:
-		if ((DL_PRIM(mp) == DL_UNITDATA_IND) && !wq->q_first) {
-			(void) man_udreq(wq, mp);
-		} else {
-			(void) putq(wq, mp);
-			qenable(wq);
-		}
-		break;
-
-	case M_IOCTL:
-	case M_IOCDATA:
-		qwriter(wq, mp, man_ioctl, PERIM_INNER);
-		break;
-
-	case M_CTL:
-		freemsg(mp);
-		break;
-
-	case M_FLUSH:
-		MAN_DBG(MAN_UWPUT, ("man_wput: M_FLUSH\n"));
-		if (*mp->b_rptr & FLUSHW)
-			flushq(wq, FLUSHDATA);
-		if (*mp->b_rptr & FLUSHR) {
-			flushq(RD(wq), FLUSHDATA);
-			*mp->b_rptr &= ~FLUSHW;
-			qreply(wq, mp);
-		} else {
-			freemsg(mp);
-		}
-		break;
-
-	default:
-		MAN_DBG(MAN_WARN,
-		    ("man_uwput: illegal mblk(0x%p) type(0x%x)\n",
-		    (void *)mp, DB_TYPE(mp)));
-		freemsg(mp);
-		break;
-	} /* End switch */
-
-	MAN_DBG(MAN_UWPUT, ("man_uwput: exit wq(0x%p) mp(0x%p)\n",
-	    (void *)wq, (void *)mp));
-
-	return (0);
-}
-
-/*
- * man_start - handle data messages issued from upstream.  Send down
- * to particular man_dest based on ether_addr, otherwise send out to all
- * valid man_dests.
- *
- *	wq - upper write queue of mxx
- *	mp - mblk ptr to DLPI request
- * 	caller - Caller ID for decision making on canput failure
- *
- * Returns:
- *	0	- Data xmitted or No flow control situation detected.
- *	1	- Flow control situation detected.
- *
- * STREAMS Flow Control: can be used if there is only one destination
- * for a stream (1 to 1 multiplexor). In this case, we will use the upper
- * write queue to store mblks when in flow control. If there are multiple
- * destinations, we cannot use the STREAMs based flow control (1 to many
- * multiplexor). In this case, we will use the lower write queue to store
- * mblks when in flow control. Since destinations come and go, we may
- * transition between 1-to-1 and 1-to-m. So it may be the case that we have
- * some mblks stored on the upper queue, and some on the lower queue. However,
- * we will never send mblks out of order. See man_uwput and man_start_lower().
- *
- * A simple flow control mechanism is implemented for the deferred mblk list,
- * as this list is expected to be used temporarily for a very short
- * period required for switching paths. This flow control mechanism is
- * used only as a defensive approach to avoid infinite growth of this list.
- */
-static int
-man_start(register queue_t *wq, register mblk_t *mp, eaddr_t *eap)
-{
-	register manstr_t	*msp;		/* per stream data */
-	register man_dest_t	*mdp = NULL;	/* destination */
-	mblk_t			*tmp;
-	int			i;
-	int			status = 0;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	MAN_DBG(MAN_DATA, ("man_start: msp(0x%p) ether_addr(%s)\n",
-	    (void *)msp, ether_sprintf(eap)));
-
-	if (msp->ms_dests == NULL) {
-		cmn_err(CE_WARN, "man_start: no destinations");
-		freemsg(mp);
-		return (0);
-	}
-
-	/*
-	 * Optimization if only one valid destination.
-	 */
-	mdp = msp->ms_destp;
-
-	if (IS_UNICAST(eap)) {
-		queue_t			*flow_wq = NULL;
-
-		if (mdp == NULL) {
-			/*
-			 * TDB - This needs to be optimized (some bits in
-			 * ehp->dhost will act as an index.
-			 */
-			for (i = 0; i < MAN_MAX_DESTS; i++) {
-
-				mdp = &msp->ms_dests[i];
-
-				if ((mdp->md_state == MAN_DSTATE_READY) &&
-				    (ether_cmp(eap, &mdp->md_dst_eaddr) == 0))
-					break;
-				mdp = NULL;
-			}
-		} else {
-			/*
-			 * 1 to 1 multiplexing, use upper wq for flow control.
-			 */
-			flow_wq = wq;
-		}
-
-		if (mdp != NULL) {
-			/*
-			 * Its going somewhere specific
-			 */
-			status =  man_start_lower(mdp, mp, flow_wq, MAN_UPPER);
-
-		} else {
-			MAN_DBG(MAN_DATA, ("man_start: no destination"
-			    " for eaddr %s\n", ether_sprintf(eap)));
-			freemsg(mp);
-		}
-	} else {
-		/*
-		 * Broadcast or multicast - send everone a copy.
-		 */
-		if (mdp == NULL) {
-			for (i = 0; i < MAN_MAX_DESTS; i++) {
-				mdp = &msp->ms_dests[i];
-
-				if (mdp->md_state != MAN_DSTATE_READY)
-					continue;
-
-				if ((tmp = copymsg(mp)) != NULL) {
-					(void) man_start_lower(mdp, tmp,
-					    NULL, MAN_UPPER);
-				} else {
-					MAN_DBG(MAN_DATA, ("man_start: copymsg"
-					    " failed!"));
-				}
-			}
-			freemsg(mp);
-		} else {
-			if (mdp->md_state == MAN_DSTATE_READY)
-				status =  man_start_lower(mdp, mp, wq,
-				    MAN_UPPER);
-			else
-				freemsg(mp);
-		}
-	}
-	return (status);
-}
-
-/*
- * Send a DL_UNITDATA or M_DATA fastpath data mblk to a particular
- * destination. Others mblk types sent down via * man_dlpi_senddown().
- *
- * Returns:
- *	0	- Data xmitted
- *	1	- Data not xmitted due to flow control.
- */
-static int
-man_start_lower(man_dest_t *mdp, mblk_t *mp, queue_t *flow_wq, int caller)
-{
-	queue_t		*wq = mdp->md_wq;
-	int		status = 0;
-
-	/*
-	 * Lower stream ready for data transmit.
-	 */
-	if (mdp->md_state == MAN_DSTATE_READY &&
-	    mdp->md_dlpistate == DL_IDLE) {
-
-		ASSERT(mdp->md_wq != NULL);
-
-		if (caller == MAN_UPPER) {
-			/*
-			 * Check for flow control conditions for lower
-			 * stream.
-			 */
-			if (mdp->md_dmp_head == NULL &&
-			    wq->q_first == NULL && canputnext(wq)) {
-
-				(void) putnext(wq, mp);
-
-			} else {
-				mutex_enter(&mdp->md_lock);
-				if (mdp->md_dmp_head != NULL) {
-					/*
-					 * A simple flow control mechanism.
-					 */
-					if (mdp->md_dmp_count >= MAN_HIWAT) {
-						freemsg(mp);
-					} else {
-						/*
-						 * Add 'mp' to the deferred
-						 * msg list.
-						 */
-						mdp->md_dmp_tail->b_next = mp;
-						mdp->md_dmp_tail = mp;
-						mdp->md_dmp_count +=
-						    msgsize(mp);
-					}
-					mutex_exit(&mdp->md_lock);
-					/*
-					 * Inform flow control situation
-					 * to the caller.
-					 */
-					status = 1;
-					qenable(wq);
-					goto exit;
-				}
-				mutex_exit(&mdp->md_lock);
-				/*
-				 * If 1 to 1 mux, use upper write queue for
-				 * flow control.
-				 */
-				if (flow_wq != NULL) {
-					/*
-					 * putbq() message and indicate
-					 * flow control situation to the
-					 * caller.
-					 */
-					(void) putbq(flow_wq, mp);
-					qenable(flow_wq);
-					status = 1;
-					goto exit;
-				}
-				/*
-				 * 1 to many mux, use lower write queue for
-				 * flow control. Be mindful not to overflow
-				 * the lower MAN STREAM q.
-				 */
-				if (canput(wq)) {
-					(void) putq(wq, mp);
-					qenable(wq);
-				} else {
-					MAN_DBG(MAN_DATA, ("man_start_lower:"
-					    " lower q flow controlled -"
-					    " discarding packet"));
-					freemsg(mp);
-					goto exit;
-				}
-			}
-
-		} else {
-			/*
-			 * man_lwsrv  is draining flow controlled mblks.
-			 */
-			if (canputnext(wq))
-				(void) putnext(wq, mp);
-			else
-				status = 1;
-		}
-		goto exit;
-	}
-
-	/*
-	 * Lower stream in transition, do flow control.
-	 */
-	status = 1;
-
-	if (mdp->md_state == MAN_DSTATE_NOTPRESENT) {
-nodest:
-		cmn_err(CE_WARN,
-		    "man_start_lower: no dest for mdp(0x%p), caller(%d)!",
-		    (void *)mdp, caller);
-		if (caller == MAN_UPPER)
-			freemsg(mp);
-		goto exit;
-	}
-
-	if (mdp->md_state & MAN_DSTATE_CLOSING) {
-		MAN_DBG(MAN_DATA, ("man_start_lower: mdp(0x%p) closing",
-		    (void *)mdp));
-		if (caller == MAN_UPPER)
-			freemsg(mp);
-		goto exit;
-	}
-
-	if ((mdp->md_state & MAN_DSTATE_PLUMBING) ||
-	    (mdp->md_state == MAN_DSTATE_INITIALIZING) ||
-	    (mdp->md_dlpistate != DL_IDLE)) {
-		/*
-		 * Defer until PLUMBED and DL_IDLE. See man_lwsrv().
-		 */
-		if (caller == MAN_UPPER) {
-			/*
-			 * Upper stream sending data down, add to defered mblk
-			 * list for stream.
-			 */
-			mutex_enter(&mdp->md_lock);
-			if (mdp->md_dmp_count >= MAN_HIWAT) {
-				freemsg(mp);
-			} else {
-				if (mdp->md_dmp_head == NULL) {
-					ASSERT(mdp->md_dmp_tail == NULL);
-					mdp->md_dmp_head = mp;
-					mdp->md_dmp_tail = mp;
-				} else {
-					mdp->md_dmp_tail->b_next = mp;
-					mdp->md_dmp_tail = mp;
-				}
-				mdp->md_dmp_count += msgsize(mp);
-			}
-			mutex_exit(&mdp->md_lock);
-		}
-
-		goto exit;
-	}
-
-exit:
-	return (status);
-}
-
-/*
- * man_ioctl - handle ioctl requests for this driver (I_PLINK/I_PUNLINK)
- * or pass thru to the physical driver below.  Note that most M_IOCTLs we
- * care about come down the control msp, but the IOC ones come down the IP.
- * Called with exclusive inner perimeter.
- *
- *	wq - upper write queue of mxx
- *	mp - mblk ptr to DLPI ioctl request
- */
-static void
-man_ioctl(register queue_t *wq, register mblk_t *mp)
-{
-	manstr_t		*msp;
-	struct iocblk		*iocp;
-
-	iocp = (struct iocblk *)mp->b_rptr;
-	msp = (manstr_t *)wq->q_ptr;
-
-#ifdef DEBUG
-	{
-		char			ioc_cmd[30];
-
-		(void) sprintf(ioc_cmd, "not handled IOCTL 0x%x",
-		    iocp->ioc_cmd);
-		MAN_DBG((MAN_SWITCH | MAN_PATH | MAN_DLPI),
-		    ("man_ioctl: wq(0x%p) mp(0x%p) cmd(%s)\n",
-		    (void *)wq, (void *)mp,
-		    (iocp->ioc_cmd == I_PLINK) ? "I_PLINK" :
-		    (iocp->ioc_cmd == I_PUNLINK) ? "I_PUNLINK" :
-		    (iocp->ioc_cmd == MAN_SETPATH) ? "MAN_SETPATH" :
-		    (iocp->ioc_cmd == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
-		    (iocp->ioc_cmd == DLIOCRAW) ? "DLIOCRAW" : ioc_cmd));
-	}
-#endif /* DEBUG */
-
-
-	/*
-	 *  Handle the requests...
-	 */
-	switch ((unsigned int)iocp->ioc_cmd) {
-
-	case I_PLINK:
-		man_plink(wq, mp);
-		break;
-
-	case I_PUNLINK:
-		man_unplink(wq, mp);
-		break;
-
-	case MAN_SETPATH:
-		man_setpath(wq, mp);
-		break;
-
-	case MAN_GETEADDR:
-		man_geteaddr(wq, mp);
-		break;
-
-	case MAN_SET_LINKCHECK_TIME:
-		man_set_linkcheck_time(wq, mp);
-		break;
-
-	case MAN_SET_SC_IPADDRS:
-		man_set_sc_ipaddrs(wq, mp);
-		break;
-
-	case MAN_SET_SC_IP6ADDRS:
-		man_set_sc_ip6addrs(wq, mp);
-		break;
-
-	case DLIOCRAW:
-		if (man_dlioc(msp, mp))
-			miocnak(wq, mp, 0, ENOMEM);
-		else {
-			msp->ms_flags |= MAN_SFLAG_RAW;
-			miocack(wq, mp, 0, 0);
-		}
-		break;
-
-	case DL_IOC_HDR_INFO:
-		man_dl_ioc_hdr_info(wq, mp);
-		break;
-
-	case MAN_ND_GET:
-	case MAN_ND_SET:
-		man_nd_getset(wq, mp);
-		break;
-
-	default:
-		MAN_DBG(MAN_DDI, ("man_ioctl: unknown ioc_cmd %d\n",
-		    (unsigned int)iocp->ioc_cmd));
-		miocnak(wq, mp, 0, EINVAL);
-		break;
-	}
-exit:
-	MAN_DBG((MAN_SWITCH | MAN_PATH | MAN_DLPI), ("man_ioctl: exit\n"));
-
-}
-
-/*
- * man_plink: handle I_PLINK requests on the control stream
- */
-void
-man_plink(queue_t *wq, mblk_t *mp)
-{
-	struct linkblk	*linkp;
-	man_linkrec_t	*lrp;
-	int		status = 0;
-
-	linkp = (struct linkblk *)mp->b_cont->b_rptr;
-
-	/*
-	 * Create a record to hold lower stream info. man_plumb will
-	 * retrieve it after calling ldi_ioctl(I_PLINK)
-	 */
-	lrp = man_kzalloc(sizeof (man_linkrec_t), KM_NOSLEEP);
-	if (lrp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-	lrp->l_muxid = linkp->l_index;
-	lrp->l_wq = linkp->l_qbot;
-	lrp->l_rq = RD(linkp->l_qbot);
-
-	man_linkrec_insert(lrp);
-
-exit:
-	if (status)
-		miocnak(wq, mp, 0, status);
-	else
-		miocack(wq, mp, 0, 0);
-
-}
-
-/*
- * man_unplink - handle I_PUNLINK requests on the control stream
- */
-void
-man_unplink(queue_t *wq, mblk_t *mp)
-{
-	struct linkblk	*linkp;
-
-	linkp = (struct linkblk *)mp->b_cont->b_rptr;
-	RD(linkp->l_qbot)->q_ptr = NULL;
-	WR(linkp->l_qbot)->q_ptr = NULL;
-	miocack(wq, mp, 0, 0);
-}
-
-void
-man_linkrec_insert(man_linkrec_t *lrp)
-{
-	mutex_enter(&man_lock);
-
-	lrp->l_next = man_linkrec_head;
-	man_linkrec_head = lrp;
-
-	mutex_exit(&man_lock);
-
-}
-
-static queue_t *
-man_linkrec_find(int muxid)
-{
-	man_linkrec_t	*lpp;
-	man_linkrec_t	*lp;
-	queue_t		*wq = NULL;
-
-	mutex_enter(&man_lock);
-
-	if (man_linkrec_head == NULL)
-		goto exit;
-
-	lp = lpp = man_linkrec_head;
-	if (lpp->l_muxid == muxid) {
-		man_linkrec_head = lpp->l_next;
-	} else {
-		for (lp = lpp->l_next; lp; lp = lp->l_next) {
-			if (lp->l_muxid == muxid)
-				break;
-			lpp = lp;
-		}
-	}
-
-	if (lp == NULL)
-		goto exit;
-
-	wq = lp->l_wq;
-	ASSERT(wq != NULL);
-
-	lpp->l_next = lp->l_next;
-	man_kfree(lp, sizeof (man_linkrec_t));
-
-exit:
-	mutex_exit(&man_lock);
-
-	return (wq);
-}
-
-/*
- * Set instance linkcheck timer value.
- */
-static void
-man_set_linkcheck_time(queue_t *wq, mblk_t *mp)
-{
-	mi_time_t	*mtp;
-	int		error;
-	man_t		*manp;
-
-	MAN_DBG(MAN_LINK, ("man_set_linkcheck_time: enter"));
-
-	error = miocpullup(mp, sizeof (mi_time_t));
-	if (error != 0)
-		goto exit;
-
-	mtp = (mi_time_t *)mp->b_cont->b_rptr;
-
-	MAN_DBG(MAN_LINK, ("man_set_linkcheck_time: mtp"));
-	MAN_DBGCALL(MAN_LINK, man_print_mtp(mtp));
-
-	manp = ddi_get_soft_state(man_softstate, mtp->mtp_man_ppa);
-	if (manp == NULL) {
-		error = ENODEV;
-		goto exit;
-	}
-
-	manp->man_linkcheck_time = mtp->mtp_time;
-exit:
-	if (error)
-		miocnak(wq, mp, 0, error);
-	else
-		miocack(wq, mp, sizeof (mi_time_t), 0);
-}
-
-/*
- * Man path ioctl processing. Should only happen on the SSC. Called
- * with exclusive inner perimeter.
- */
-static void
-man_setpath(queue_t *wq, mblk_t *mp)
-{
-	mi_path_t		*mip;
-	int			error;
-
-	error = miocpullup(mp, sizeof (mi_path_t));
-	if (error != 0)
-		goto exit;
-
-	mip = (mi_path_t *)mp->b_cont->b_rptr;
-	mutex_enter(&man_lock);
-	error = man_pg_cmd(mip, NULL);
-	mutex_exit(&man_lock);
-
-exit:
-	if (error)
-		miocnak(wq, mp, 0, error);
-	else
-		miocack(wq, mp, sizeof (mi_path_t), 0);
-}
-
-/*
- * Get the local ethernet address of this machine.
- */
-static void
-man_geteaddr(queue_t *wq, mblk_t *mp)
-{
-	eaddr_t			*eap;
-	int			error;
-
-	error = miocpullup(mp, sizeof (eaddr_t));
-	if (error != 0) {
-		miocnak(wq, mp, 0, error);
-		return;
-	}
-
-	eap = (eaddr_t *)mp->b_cont->b_rptr;
-	(void) localetheraddr(NULL, eap);
-	miocack(wq, mp, sizeof (eaddr_t), 0);
-}
-
-/*
- * Set my SC and other SC IPv4 addresses for use in man_pinger routine.
- */
-static void
-man_set_sc_ipaddrs(queue_t *wq, mblk_t *mp)
-{
-	int			error;
-
-	error = miocpullup(mp, sizeof (man_sc_ipaddrs_t));
-	if (error != 0)
-		goto exit;
-
-	man_sc_ipaddrs = *(man_sc_ipaddrs_t *)mp->b_cont->b_rptr;
-
-#ifdef DEBUG
-	{
-		char	buf[INET_ADDRSTRLEN];
-
-		(void) inet_ntop(AF_INET,
-		    (void *) &man_sc_ipaddrs.ip_other_sc_ipaddr,
-		    buf, INET_ADDRSTRLEN);
-		MAN_DBG(MAN_CONFIG, ("ip_other_sc_ipaddr = %s", buf));
-		(void) inet_ntop(AF_INET,
-		    (void *) &man_sc_ipaddrs.ip_my_sc_ipaddr,
-		    buf, INET_ADDRSTRLEN);
-		MAN_DBG(MAN_CONFIG, ("ip_my_sc_ipaddr = %s", buf));
-	}
-#endif /* DEBUG */
-exit:
-	if (error)
-		miocnak(wq, mp, 0, error);
-	else
-		miocack(wq, mp, sizeof (man_sc_ipaddrs_t), 0);
-}
-
-/*
- * Set my SC and other SC IPv6 addresses for use in man_pinger routine.
- */
-static void
-man_set_sc_ip6addrs(queue_t *wq, mblk_t *mp)
-{
-	int			error;
-
-	error = miocpullup(mp, sizeof (man_sc_ip6addrs_t));
-	if (error != 0)
-		goto exit;
-
-	man_sc_ip6addrs = *(man_sc_ip6addrs_t *)mp->b_cont->b_rptr;
-
-#ifdef DEBUG
-	{
-		char	buf[INET6_ADDRSTRLEN];
-
-		(void) inet_ntop(AF_INET6,
-		    (void *) &man_sc_ip6addrs.ip6_other_sc_ipaddr,
-		    buf, INET6_ADDRSTRLEN);
-		MAN_DBG(MAN_CONFIG, ("ip6_other_sc_ipaddr = %s", buf));
-		(void) inet_ntop(AF_INET6,
-		    (void *) &man_sc_ip6addrs.ip6_my_sc_ipaddr,
-		    buf, INET6_ADDRSTRLEN);
-		MAN_DBG(MAN_CONFIG, ("ip6_my_sc_ipaddr = %s", buf));
-	}
-#endif /* DEBUG */
-exit:
-	if (error)
-		miocnak(wq, mp, 0, error);
-	else
-		miocack(wq, mp, sizeof (man_sc_ip6addrs_t), 0);
-}
-
-/*
- * M_DATA fastpath info request.
- */
-static void
-man_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	man_t			*manp;
-	mblk_t			*nmp;
-	man_dladdr_t		*dlap;
-	dl_unitdata_req_t	*dludp;
-	struct	ether_header	*headerp;
-	t_uscalar_t		off, len;
-	int			status = 0;
-
-	MAN_DBG(MAN_DLPI, ("man_dl_ioc_hdr_info: enter"));
-
-	msp = (manstr_t *)wq->q_ptr;
-	manp = msp->ms_manp;
-	if (manp == NULL) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	status = miocpullup(mp, sizeof (dl_unitdata_req_t) + MAN_ADDRL);
-	if (status != 0)
-		goto exit;
-
-	/*
-	 * 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 != MAN_ADDRL) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	dlap = (man_dladdr_t  *)(mp->b_cont->b_rptr + off);
-
-	/*
-	 * Allocate a new mblk to hold the ether header.
-	 */
-	if ((nmp = allocb(ETHERHEADER_SIZE, BPRI_MED)) == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-	/* We only need one dl_ioc_hdr mblk for replay */
-	if (!(msp->ms_flags & MAN_SFLAG_FAST))
-		status = man_dl_catch(&msp->ms_dlioc_mp, mp);
-
-	/* Forward the packet to all lower destinations. */
-	if ((status != 0) || ((status = man_dlpi_senddown(msp, mp)) != 0)) {
-		freemsg(nmp);
-		goto exit;
-	}
-
-	nmp->b_wptr += ETHERHEADER_SIZE;
-
-	/*
-	 * Fill in the ether header.
-	 */
-	headerp = (struct ether_header *)nmp->b_rptr;
-	ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
-	ether_copy(&manp->man_eaddr, &headerp->ether_shost);
-	put_ether_type(headerp, dlap->dl_sap);
-
-	/*
-	 * Link new mblk in after the "request" mblks.
-	 */
-	linkb(mp, nmp);
-
-exit:
-	MAN_DBG(MAN_DLPI, ("man_dl_ioc_hdr_info: returns, status = %d",
-	    status));
-
-	if (status) {
-		miocnak(wq, mp, 0, status);
-	} else {
-		msp = (manstr_t *)wq->q_ptr;
-		msp->ms_flags |= MAN_SFLAG_FAST;
-		miocack(wq, mp, msgsize(mp->b_cont), 0);
-	}
-
-}
-
-/*
- * man_uwsrv - Upper write queue service routine to handle deferred
- * DLPI messages issued from upstream, the write side of the upper half
- * of multiplexor. It is also used by man_bwork to switch the lower
- * multiplexor.
- *
- *	wq - upper write queue of mxx
- */
-static int
-man_uwsrv(queue_t *wq)
-{
-	register mblk_t		*mp;
-	manstr_t		*msp;		/* per stream data */
-	man_t			*manp;		/* per instance data */
-	ehdr_t			*ep;
-	int			status;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	MAN_DBG(MAN_UWSRV, ("man_uwsrv: wq(0x%p) msp", (void *)wq));
-	MAN_DBGCALL(MAN_UWSRV, man_print_msp(msp));
-
-	if (msp == NULL)
-		goto done;
-
-	manp = msp->ms_manp;
-
-	while (mp = getq(wq)) {
-
-		switch (DB_TYPE(mp)) {
-		/*
-		 * Can probably remove this as I never put data messages
-		 * here.
-		 */
-		case M_DATA:
-			if (manp) {
-				ep = (ehdr_t *)mp->b_rptr;
-				status = man_start(wq, mp, &ep->ether_dhost);
-				if (status) {
-					/*
-					 * man_start() indicated flow control
-					 * situation, stop processing now.
-					 */
-					goto break_loop;
-				}
-			} else
-				freemsg(mp);
-			break;
-
-		case M_PROTO:
-		case M_PCPROTO:
-			status = man_proto(wq, mp);
-			if (status) {
-				/*
-				 * man_proto() indicated flow control
-				 * situation detected by man_start(),
-				 * stop processing now.
-				 */
-				goto break_loop;
-			}
-			break;
-
-		default:
-			MAN_DBG(MAN_UWSRV, ("man_uwsrv: discarding mp(0x%p)",
-			    (void *)mp));
-			freemsg(mp);
-			break;
-		}
-	}
-
-break_loop:
-	/*
-	 * Check to see if bgthread wants us to do something inside the
-	 * perimeter.
-	 */
-	if ((msp->ms_flags & MAN_SFLAG_CONTROL) &&
-	    man_iwork_q->q_work != NULL) {
-
-		man_iwork();
-	}
-
-done:
-
-	MAN_DBG(MAN_UWSRV, ("man_uwsrv: returns"));
-
-	return (0);
-}
-
-
-/*
- * man_proto - handle DLPI protocol requests issued from upstream.
- * Called by man_uwsrv().  We disassociate upper and lower multiplexor
- * DLPI state transitions. The upper stream here (manstr_t) transitions
- * appropriately, saves the DLPI requests via man_dlpi(), and then
- * arranges for the DLPI request to be sent down via man_dlpi_senddown() if
- * appropriate.
- *
- *	wq - upper write queue of mxx
- *	mp - mbl ptr to protocol request
- */
-static int
-man_proto(queue_t *wq, mblk_t *mp)
-{
-	union DL_primitives	*dlp;
-	int			flow_status = 0;
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-
-	MAN_DBG((MAN_UWSRV | MAN_DLPI),
-	    ("man_proto: mp(0x%p) prim(%s)\n", (void *)mp,
-	    dps[dlp->dl_primitive]));
-
-	switch (dlp->dl_primitive) {
-	case DL_UNITDATA_REQ:
-		flow_status = man_udreq(wq, mp);
-		break;
-
-	case DL_ATTACH_REQ:
-		man_areq(wq, mp);
-		break;
-
-	case DL_DETACH_REQ:
-		man_dreq(wq, mp);
-		break;
-
-	case DL_BIND_REQ:
-		man_breq(wq, mp);
-		break;
-
-	case DL_UNBIND_REQ:
-		man_ubreq(wq, mp);
-		break;
-
-	case DL_INFO_REQ:
-		man_ireq(wq, mp);
-		break;
-
-	case DL_PROMISCON_REQ:
-		man_ponreq(wq, mp);
-		break;
-
-	case DL_PROMISCOFF_REQ:
-		man_poffreq(wq, mp);
-		break;
-
-	case DL_ENABMULTI_REQ:
-		man_emreq(wq, mp);
-		break;
-
-	case DL_DISABMULTI_REQ:
-		man_dmreq(wq, mp);
-		break;
-
-	case DL_PHYS_ADDR_REQ:
-		man_pareq(wq, mp);
-		break;
-
-	case DL_SET_PHYS_ADDR_REQ:
-		man_spareq(wq, mp);
-		break;
-
-	default:
-		MAN_DBG((MAN_UWSRV | MAN_DLPI), ("man_proto: prim(%d)\n",
-		    dlp->dl_primitive));
-		dlerrorack(wq, mp, dlp->dl_primitive, DL_UNSUPPORTED, 0);
-		break;
-
-	} /* End switch */
-
-	MAN_DBG((MAN_UWSRV | MAN_DLPI), ("man_proto: exit\n"));
-	return (flow_status);
-
-}
-
-static int
-man_udreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	dl_unitdata_req_t	*dludp;
-	mblk_t	*nmp;
-	man_dladdr_t		*dlap;
-	t_uscalar_t 		off, len;
-	int 			flow_status = 0;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-
-	if (msp->ms_dlpistate != DL_IDLE) {
-		dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
-		return (flow_status);
-	}
-	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 != MAN_ADDRL)) {
-		dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0);
-		return (flow_status);
-	}
-
-	/*
-	 * 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 (flow_status);
-	}
-
-	dlap = (man_dladdr_t *)(mp->b_rptr + off);
-
-	flow_status = man_start(wq, mp, &dlap->dl_phys);
-	return (flow_status);
-}
-
-/*
- * Handle DL_ATTACH_REQ.
- */
-static void
-man_areq(queue_t *wq, mblk_t *mp)
-{
-	man_t			*manp;	/* per instance data */
-	manstr_t		*msp;	/* per stream data */
-	short			ppa;
-	union DL_primitives	*dlp;
-	mblk_t			*preq = NULL;
-	int			did_refcnt = FALSE;
-	int			dlerror = 0;
-	int			status = 0;
-
-	msp = (manstr_t *)wq->q_ptr;
-	dlp = (union DL_primitives *)mp->b_rptr;
-
-	/*
-	 * Attach us to MAN PPA (device instance).
-	 */
-	if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
-		dlerror = DL_BADPRIM;
-		goto exit;
-	}
-
-	if (msp->ms_dlpistate != DL_UNATTACHED) {
-		dlerror = DL_OUTSTATE;
-		goto exit;
-	}
-
-	ppa = dlp->attach_req.dl_ppa;
-	if (ppa == -1 || qassociate(wq, ppa) != 0) {
-		dlerror = DL_BADPPA;
-		MAN_DBG(MAN_WARN, ("man_areq: bad PPA %d", ppa));
-		goto exit;
-	}
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, ppa);
-	ASSERT(manp != NULL);	/* qassociate() succeeded */
-
-	manp->man_refcnt++;
-	did_refcnt = TRUE;
-	mutex_exit(&man_lock);
-
-	/*
-	 * Create a DL replay list for the lower stream. These wont
-	 * actually be sent down until the lower streams are made active
-	 * (sometime after the call to man_init_dests below).
-	 */
-	preq = man_alloc_physreq_mp(&manp->man_eaddr);
-	if (preq == NULL) {
-		dlerror = DL_SYSERR;
-		status = ENOMEM;
-		goto exit;
-	}
-
-	/*
-	 * Make copy for dlpi resync of upper and lower streams.
-	 */
-	if (man_dlpi(msp, mp)) {
-		dlerror = DL_SYSERR;
-		status = ENOMEM;
-		goto exit;
-	}
-
-	/* TBD - need to clean off ATTACH req on failure here. */
-	if (man_dlpi(msp, preq)) {
-		dlerror = DL_SYSERR;
-		status = ENOMEM;
-		goto exit;
-	}
-
-	/*
-	 * man_init_dests/man_start_dest needs these set before call.
-	 */
-	msp->ms_manp = manp;
-	msp->ms_meta_ppa = ppa;
-
-	/*
-	 *  Allocate and init lower destination structures.
-	 */
-	ASSERT(msp->ms_dests == NULL);
-	if (man_init_dests(manp, msp)) {
-		mblk_t	 *tmp;
-
-		/*
-		 * If we cant get the lower streams ready, then
-		 * remove the messages from the DL replay list and
-		 * fail attach.
-		 */
-		while ((tmp = msp->ms_dl_mp) != NULL) {
-			msp->ms_dl_mp = msp->ms_dl_mp->b_next;
-			tmp->b_next = tmp->b_prev = NULL;
-			freemsg(tmp);
-		}
-
-		msp->ms_manp = NULL;
-		msp->ms_meta_ppa = -1;
-
-		dlerror = DL_SYSERR;
-		status = ENOMEM;
-		goto exit;
-	}
-
-	MAN_DBG(MAN_DLPI, ("man_areq: ppa 0x%x man_refcnt: %d\n",
-	    ppa, manp->man_refcnt));
-
-	SETSTATE(msp, DL_UNBOUND);
-
-exit:
-	if (dlerror == 0) {
-		dlokack(wq, mp, DL_ATTACH_REQ);
-	} else {
-		if (did_refcnt) {
-			mutex_enter(&man_lock);
-			manp->man_refcnt--;
-			mutex_exit(&man_lock);
-		}
-		dlerrorack(wq, mp, DL_ATTACH_REQ, dlerror, status);
-		(void) qassociate(wq, -1);
-	}
-	if (preq != NULL)
-		freemsg(preq);
-
-}
-
-/*
- * Called at DL_ATTACH time.
- * Man_lock is held to protect pathgroup list(man_pg).
- */
-static int
-man_init_dests(man_t *manp, manstr_t *msp)
-{
-	man_dest_t	*mdp;
-	man_pg_t	*mpg;
-	int		i;
-
-	mdp = man_kzalloc(MAN_DEST_ARRAY_SIZE, KM_NOSLEEP);
-	if (mdp == NULL)
-		return (ENOMEM);
-
-	msp->ms_dests = mdp;
-
-	mutex_enter(&man_lock);
-	for (i = 0; i < MAN_MAX_DESTS; i++) {
-
-		mdp[i].md_muxid = -1;	/* muxid 0 is valid */
-		mutex_init(&mdp->md_lock, NULL, MUTEX_DRIVER, NULL);
-
-		mpg = man_find_pg_by_id(manp->man_pg, i);
-
-		if (mpg && man_find_active_path(mpg->mpg_pathp))
-			man_start_dest(&mdp[i], msp, mpg);
-	}
-	mutex_exit(&man_lock);
-
-	return (0);
-}
-
-/*
- * Get a destination ready for use.
- */
-static void
-man_start_dest(man_dest_t *mdp, manstr_t *msp, man_pg_t *mpg)
-{
-	man_path_t	*ap;
-
-	mdp->md_muxid = -1;
-	mdp->md_dlpistate = DL_UNATTACHED;
-	mdp->md_msp = msp;
-	mdp->md_rq = msp->ms_rq;
-	mdp->md_pg_id = mpg->mpg_pg_id;
-
-	ASSERT(msp->ms_manp);
-
-	ether_copy(&msp->ms_manp->man_eaddr, &mdp->md_src_eaddr);
-	ether_copy(&mpg->mpg_dst_eaddr, &mdp->md_dst_eaddr);
-
-	ap = man_find_active_path(mpg->mpg_pathp);
-	ASSERT(ap);
-	mdp->md_device = ap->mp_device;
-
-	/*
-	 * Set up linktimers so that first time through, we will do
-	 * a failover.
-	 */
-	mdp->md_linkstate = MAN_LINKFAIL;
-	mdp->md_state = MAN_DSTATE_INITIALIZING;
-	mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
-	    (void *)mdp, man_gettimer(MAN_TIMER_INIT, mdp));
-
-	/*
-	 * As an optimization, if there is only one destination,
-	 * remember the destination pointer. Used by man_start().
-	 */
-	man_set_optimized_dest(msp);
-
-	MAN_DBG(MAN_DEST, ("man_start_dest: mdp"));
-	MAN_DBGCALL(MAN_DEST, man_print_mdp(mdp));
-}
-
-static void
-man_set_optimized_dest(manstr_t *msp)
-{
-	int		count = 0;
-	int		i;
-	man_dest_t	*mdp = NULL;
-
-	for (i = 0; i < MAN_MAX_DESTS; i++) {
-		if (msp->ms_dests[i].md_msp != NULL) {
-			count++;
-			mdp = &msp->ms_dests[i];
-		}
-	}
-
-	if (count == 1)
-		msp->ms_destp = mdp;
-	else
-		msp->ms_destp = NULL;
-
-}
-
-/*
- * Catch dlpi message for replaying, and arrange to send it down
- * to any destinations not PLUMBING. See man_dlpi_replay().
- */
-static int
-man_dlpi(manstr_t *msp, mblk_t *mp)
-{
-	int	status;
-
-	status = man_dl_catch(&msp->ms_dl_mp, mp);
-	if (status == 0)
-		status = man_dlpi_senddown(msp, mp);
-
-	return (status);
-}
-
-/*
- * Catch IOCTL type DL_ messages.
- */
-static int
-man_dlioc(manstr_t *msp, mblk_t *mp)
-{
-	int status;
-
-	status = man_dl_catch(&msp->ms_dlioc_mp, mp);
-	if (status == 0)
-		status = man_dlpi_senddown(msp, mp);
-
-	return (status);
-}
-
-/*
- * We catch all DLPI messages that we have to resend to a new AP'ed
- * device to put it in the right state.  We link these messages together
- * w/ their b_next fields and hang it off of msp->ms_dl_mp.  We
- * must be careful to restore b_next fields before doing dupmsg/freemsg!
- *
- *	msp - pointer of stream struct to process
- *	mblk - pointer to DLPI request to catch
- */
-static int
-man_dl_catch(mblk_t **mplist, mblk_t *mp)
-{
-	mblk_t			*dupmp;
-	mblk_t			*tmp;
-	unsigned		prim;
-	int			status = 0;
-
-	dupmp = copymsg(mp);
-	if (dupmp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-
-	if (*mplist == NULL)
-		*mplist = dupmp;
-	else {
-		for (tmp = *mplist; tmp->b_next; )
-			tmp = tmp->b_next;
-
-		tmp->b_next = dupmp;
-	}
-
-	prim = DL_PRIM(mp);
-	MAN_DBG(MAN_DLPI,
-	    ("man_dl_catch: adding %s\n",
-	    (prim == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
-	    (prim == DLIOCRAW) ? "DLIOCRAW" :
-	    (prim == DL_PROMISCON_REQ) ? promisc[DL_PROMISCON_TYPE(mp)] :
-	    dps[prim]));
-
-exit:
-
-	return (status);
-}
-
-/*
- * Send down a single DLPI M_[PC]PROTO to all currently valid dests.
- *
- *	msp - ptr to NDM stream structure DL_ messages was received on.
- *	mp - ptr to mblk containing DL_ request.
- */
-static int
-man_dlpi_senddown(manstr_t *msp, mblk_t *mp)
-{
-	man_dest_t	*mdp;
-	int		i;
-	mblk_t		*rmp[MAN_MAX_DESTS];	/* Copy to replay */
-	int		dstate[MAN_MAX_DESTS];
-	int		no_dests = TRUE;
-	int		status = 0;
-
-	if (msp->ms_dests == NULL)
-		goto exit;
-
-	for (i = 0; i < MAN_MAX_DESTS; i++) {
-		mdp = &msp->ms_dests[i];
-		if (mdp->md_state == MAN_DSTATE_READY) {
-			dstate[i] = TRUE;
-			no_dests = FALSE;
-		} else {
-			dstate[i] = FALSE;
-		}
-		rmp[i] = NULL;
-	}
-
-	if (no_dests)
-		goto exit;
-
-	/*
-	 * Build replay and duplicate list for all possible destinations.
-	 */
-	for (i = 0; i < MAN_MAX_DESTS; i++) {
-		if (dstate[i]) {
-			rmp[i] = copymsg(mp);
-			if (rmp[i] == NULL) {
-				status = ENOMEM;
-				break;
-			}
-		}
-	}
-
-	if (status == 0) {
-		for (i = 0; i < MAN_MAX_DESTS; i++)
-			if (dstate[i]) {
-				mdp = &msp->ms_dests[i];
-
-				ASSERT(mdp->md_wq != NULL);
-				ASSERT(mp->b_next == NULL);
-				ASSERT(mp->b_prev == NULL);
-
-				man_dlpi_replay(mdp, rmp[i]);
-			}
-	} else {
-		for (; i >= 0; i--)
-			if (dstate[i] && rmp[i])
-				freemsg(rmp[i]);
-	}
-
-exit:
-	return (status);
-}
-
-/*
- * man_dlpi_replay - traverse the list of DLPI requests and reapply them to
- * get the upper and lower streams into the same state. Called holding inner
- * perimeter lock exclusive. Note thet we defer M_IOCTL type dlpi messages
- * until we get an OK_ACK to our ATTACH (see man_lrsrv and
- * man_dlioc_replay).
- *
- * 	mdp - pointer to lower queue (destination)
- *	rmp - list of mblks to send down stream.
- */
-static void
-man_dlpi_replay(man_dest_t *mdp, mblk_t *rmp)
-{
-	mblk_t			*mp;
-	union DL_primitives	*dlp = NULL;
-
-	MAN_DBG(MAN_DLPI, ("man_dlpi_replay: mdp(0x%p)", (void *)mdp));
-
-	while (rmp) {
-		mp = rmp;
-		rmp = rmp->b_next;
-		mp->b_prev = mp->b_next = NULL;
-
-		dlp = (union DL_primitives *)mp->b_rptr;
-		MAN_DBG(MAN_DLPI,
-		    ("man_dlpi_replay: mdp(0x%p) sending %s\n",
-		    (void *)mdp,
-		    (dlp->dl_primitive == DL_IOC_HDR_INFO) ?
-		    "DL_IOC_HDR_INFO" : (dlp->dl_primitive == DLIOCRAW) ?
-		    "DLIOCRAW" : dps[(unsigned)(dlp->dl_primitive)]));
-
-		if (dlp->dl_primitive == DL_ATTACH_REQ) {
-			/*
-			 * insert the lower devices ppa.
-			 */
-			dlp->attach_req.dl_ppa = mdp->md_device.mdev_ppa;
-		}
-
-		(void) putnext(mdp->md_wq, mp);
-	}
-
-}
-
-static void
-man_dreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t	*msp;	/* per stream data */
-	man_work_t	*wp;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (msp->ms_dlpistate != DL_UNBOUND) {
-		dlerrorack(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	ASSERT(msp->ms_dests != NULL);
-
-	wp = man_work_alloc(MAN_WORK_CLOSE_STREAM, KM_NOSLEEP);
-	if (wp == NULL) {
-		dlerrorack(wq, mp, DL_DETACH_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-	man_dodetach(msp, wp);
-	(void) qassociate(wq, -1);
-
-	SETSTATE(msp, DL_UNATTACHED);
-
-	dlokack(wq, mp, DL_DETACH_REQ);
-}
-
-static void
-man_dl_clean(mblk_t **mplist)
-{
-	mblk_t	*tmp;
-
-	/*
-	 * Toss everything.
-	 */
-	while ((tmp = *mplist) != NULL) {
-		*mplist = (*mplist)->b_next;
-		tmp->b_next = tmp->b_prev = NULL;
-		freemsg(tmp);
-	}
-
-}
-
-/*
- * man_dl_release - Remove the corresponding DLPI request from the
- * catch list. Walk thru the catch list looking for the other half of
- * the pair and delete it.  If we are detaching, delete the entire list.
- *
- *	msp - pointer of stream struct to process
- *	mp  - pointer to mblk to first half of pair.  We will delete other
- * 		half of pair based on this.
- */
-static void
-man_dl_release(mblk_t **mplist, mblk_t *mp)
-{
-	uchar_t			match_dbtype;
-	mblk_t			*tmp;
-	mblk_t			*tmpp;
-	int			matched = FALSE;
-
-	if (*mplist == NULL)
-		goto exit;
-
-	match_dbtype = DB_TYPE(mp);
-
-	/*
-	 * Currently we only clean DL_ PROTO type messages. There is
-	 * no way to turn off M_CTL or DL_IOC stuff other than sending
-	 * down a DL_DETACH, which resets everything.
-	 */
-	if (match_dbtype != M_PROTO && match_dbtype != M_PCPROTO) {
-		goto exit;
-	}
-
-	/*
-	 * Selectively find a caught mblk that matches this one and
-	 * remove it from the list
-	 */
-	tmp = tmpp = *mplist;
-	matched = man_match_proto(mp, tmp);
-	if (matched) {
-		*mplist = tmp->b_next;
-		tmp->b_next = tmp->b_prev = NULL;
-	} else {
-		for (tmp = tmp->b_next; tmp != NULL; tmp = tmp->b_next) {
-			if (matched = man_match_proto(mp, tmp))
-				break;
-			tmpp = tmp;
-		}
-
-		if (matched) {
-			tmpp->b_next = tmp->b_next;
-			tmp->b_next = tmp->b_prev = NULL;
-		}
-	}
-
-exit:
-	if (matched) {
-
-		MAN_DBG(MAN_DLPI, ("man_dl_release: release %s",
-		    (DL_PRIM(mp) == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
-		    (DL_PRIM(mp) == DLIOCRAW) ? "DLIOCRAW" :
-		    dps[(int)DL_PRIM(mp)]));
-
-		freemsg(tmp);
-	}
-	MAN_DBG(MAN_DLPI, ("man_dl_release: returns"));
-
-}
-
-/*
- * Compare two DL_ messages. If they are complimentary (e.g. DL_UNBIND
- * compliments DL_BIND), return true.
- */
-static int
-man_match_proto(mblk_t *mp1, mblk_t *mp2)
-{
-	t_uscalar_t	prim1;
-	t_uscalar_t	prim2;
-	int		matched = FALSE;
-
-	/*
-	 * Primitive to clean off list.
-	 */
-	prim1 = DL_PRIM(mp1);
-	prim2 = DL_PRIM(mp2);
-
-	switch (prim1) {
-	case DL_UNBIND_REQ:
-		if (prim2 == DL_BIND_REQ)
-			matched = TRUE;
-		break;
-
-	case DL_PROMISCOFF_REQ:
-		if (prim2 == DL_PROMISCON_REQ) {
-			dl_promiscoff_req_t	*poff1;
-			dl_promiscoff_req_t	*poff2;
-
-			poff1 = (dl_promiscoff_req_t *)mp1->b_rptr;
-			poff2 = (dl_promiscoff_req_t *)mp2->b_rptr;
-
-			if (poff1->dl_level == poff2->dl_level)
-				matched = TRUE;
-		}
-		break;
-
-	case DL_DISABMULTI_REQ:
-		if (prim2 == DL_ENABMULTI_REQ) {
-			union DL_primitives	*dlp;
-			t_uscalar_t		off;
-			eaddr_t			*addrp1;
-			eaddr_t			*addrp2;
-
-			dlp = (union DL_primitives *)mp1->b_rptr;
-			off = dlp->disabmulti_req.dl_addr_offset;
-			addrp1 = (eaddr_t *)(mp1->b_rptr + off);
-
-			dlp = (union DL_primitives *)mp2->b_rptr;
-			off = dlp->disabmulti_req.dl_addr_offset;
-			addrp2 = (eaddr_t *)(mp2->b_rptr + off);
-
-			if (ether_cmp(addrp1, addrp2) == 0)
-				matched = 1;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	MAN_DBG(MAN_DLPI, ("man_match_proto returns %d", matched));
-
-	return (matched);
-}
-
-/*
- * Bind upper stream to a particular SAP. Called with exclusive innerperim
- * QPAIR, shared outerperim.
- */
-static void
-man_breq(queue_t *wq, mblk_t *mp)
-{
-	man_t			*manp;	/* per instance data */
-	manstr_t		*msp;	/* per stream data */
-	union DL_primitives	*dlp;
-	man_dladdr_t		man_addr;
-	t_uscalar_t		sap;
-	t_uscalar_t		xidtest;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (msp->ms_dlpistate != DL_UNBOUND) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	manp = msp->ms_manp;			/* valid after attach */
-	sap = dlp->bind_req.dl_sap;
-	xidtest = dlp->bind_req.dl_xidtest_flg;
-
-	ASSERT(manp);
-
-	if (xidtest) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
-		return;
-	}
-
-	if (sap > ETHERTYPE_MAX) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_BADSAP, 0);
-		return;
-	}
-
-	if (man_dlpi(msp, mp)) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	msp->ms_sap = sap;
-
-	SETSTATE(msp, DL_IDLE);
-
-	man_addr.dl_sap = msp->ms_sap;
-	ether_copy(&msp->ms_manp->man_eaddr, &man_addr.dl_phys);
-
-	dlbindack(wq, mp, msp->ms_sap, &man_addr, MAN_ADDRL, 0, 0);
-
-}
-
-static void
-man_ubreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;	/* per stream data */
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (msp->ms_dlpistate != DL_IDLE) {
-		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	if (man_dlpi_senddown(msp, mp)) {
-		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	man_dl_release(&msp->ms_dl_mp, mp);
-
-	SETSTATE(msp, DL_UNBOUND);
-
-	dlokack(wq, mp, DL_UNBIND_REQ);
-
-}
-
-static void
-man_ireq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t	*msp;
-	dl_info_ack_t	*dlip;
-	man_dladdr_t	*dlap;
-	eaddr_t		*ep;
-	size_t	size;
-
-	msp = (manstr_t *)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) + MAN_ADDRL + ETHERADDRL;
-	mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK);
-	if (mp == NULL) {
-		MAN_DBG(MAN_DLPI, ("man_ireq: man_ireq: mp == NULL."));
-		return;
-	}
-
-	/* Fill in the DL_INFO_ACK fields and reply. */
-	dlip = (dl_info_ack_t *)mp->b_rptr;
-	*dlip = man_infoack;
-	dlip->dl_current_state = msp->ms_dlpistate;
-	dlap = (man_dladdr_t *)(mp->b_rptr + dlip->dl_addr_offset);
-	dlap->dl_sap = msp->ms_sap;
-
-	/*
-	 * If attached, return physical address.
-	 */
-	if (msp->ms_manp != NULL) {
-		ether_copy(&msp->ms_manp->man_eaddr, &dlap->dl_phys);
-	} else {
-		bzero((caddr_t)&dlap->dl_phys, ETHERADDRL);
-	}
-
-	ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
-	ether_copy(&etherbroadcast, ep);
-
-	qreply(wq, mp);
-
-}
-
-
-static void
-man_ponreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t	*msp;
-	int		flag;
-
-	msp = (manstr_t *)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:
-		flag = MAN_SFLAG_ALLPHYS;
-		break;
-
-	case DL_PROMISC_SAP:
-		flag = MAN_SFLAG_ALLSAP;
-		break;
-
-	case DL_PROMISC_MULTI:
-		flag = MAN_SFLAG_ALLMULTI;
-		break;
-
-	default:
-		dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
-		return;
-	}
-
-	/*
-	 * Catch request for replay, and forward down to any lower
-	 * lower stream.
-	 */
-	if (man_dlpi(msp, mp)) {
-		dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	msp->ms_flags |= flag;
-
-	dlokack(wq, mp, DL_PROMISCON_REQ);
-
-}
-
-static void
-man_poffreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	int			flag;
-
-	msp = (manstr_t *)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 = MAN_SFLAG_ALLPHYS;
-		break;
-
-	case DL_PROMISC_SAP:
-		flag = MAN_SFLAG_ALLSAP;
-		break;
-
-	case DL_PROMISC_MULTI:
-		flag = MAN_SFLAG_ALLMULTI;
-		break;
-
-	default:
-		dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
-		return;
-	}
-
-	if ((msp->ms_flags & flag) == 0) {
-		dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
-		return;
-	}
-
-	if (man_dlpi_senddown(msp, mp)) {
-		dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	man_dl_release(&msp->ms_dl_mp, mp);
-
-	msp->ms_flags &= ~flag;
-
-	dlokack(wq, mp, DL_PROMISCOFF_REQ);
-
-}
-
-/*
- * Enable multicast requests. We might need to track addresses instead of
- * just passing things through (see eri_dmreq) - TBD.
- */
-static void
-man_emreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	union DL_primitives	*dlp;
-	eaddr_t			*addrp;
-	t_uscalar_t		off;
-	t_uscalar_t		len;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_ENABMULTI_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (msp->ms_dlpistate == 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) ||
-	    ((addrp->ether_addr_octet[0] & 01) == 0)) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
-		return;
-	}
-
-	/*
-	 * Catch request for replay, and forward down to any lower
-	 * lower stream.
-	 */
-	if (man_dlpi(msp, mp)) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	dlokack(wq, mp, DL_ENABMULTI_REQ);
-
-}
-
-static void
-man_dmreq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	union DL_primitives	*dlp;
-	eaddr_t			*addrp;
-	t_uscalar_t		off;
-	t_uscalar_t		len;
-
-	msp = (manstr_t *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_DISABMULTI_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (msp->ms_dlpistate == 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) ||
-	    ((addrp->ether_addr_octet[0] & 01) == 0)) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
-		return;
-	}
-
-	if (man_dlpi_senddown(msp, mp)) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	man_dl_release(&msp->ms_dl_mp, mp);
-
-	dlokack(wq, mp, DL_DISABMULTI_REQ);
-
-}
-
-static void
-man_pareq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	union	DL_primitives	*dlp;
-	uint32_t		type;
-	struct	ether_addr	addr;
-
-	msp = (manstr_t *)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;
-	if (msp->ms_manp == NULL) {
-		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	switch (type) {
-	case	DL_FACT_PHYS_ADDR:
-		(void) localetheraddr((struct ether_addr *)NULL, &addr);
-		break;
-
-	case	DL_CURR_PHYS_ADDR:
-		ether_bcopy(&msp->ms_manp->man_eaddr, &addr);
-		break;
-
-	default:
-		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
-		return;
-	}
-
-	dlphysaddrack(wq, mp, &addr, ETHERADDRL);
-}
-
-/*
- * TBD - this routine probably should be protected w/ an ndd
- * tuneable, or a man.conf parameter.
- */
-static void
-man_spareq(queue_t *wq, mblk_t *mp)
-{
-	manstr_t		*msp;
-	union DL_primitives	*dlp;
-	t_uscalar_t		off;
-	t_uscalar_t		len;
-	eaddr_t			*addrp;
-
-	msp = (manstr_t *)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) ||
-	    ((addrp->ether_addr_octet[0] & 01) == 1) ||
-	    (ether_cmp(addrp, &etherbroadcast) == 0)) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
-		return;
-	}
-	/*
-	 * Error if this stream is not attached to a device.
-	 */
-	if (msp->ms_manp == NULL) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	/*
-	 * We will also resend DL_SET_PHYS_ADDR_REQ for each dest
-	 * when it is linked under us.
-	 */
-	if (man_dlpi_senddown(msp, mp)) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, ENOMEM);
-		return;
-	}
-
-	ether_copy(addrp, msp->ms_manp->man_eaddr.ether_addr_octet);
-
-	MAN_DBG(MAN_DLPI, ("man_sareq: snagged %s\n",
-	    ether_sprintf(&msp->ms_manp->man_eaddr)));
-
-	dlokack(wq, mp, DL_SET_PHYS_ADDR_REQ);
-
-}
-
-/*
- * These routines make up the lower part of the MAN streams framework.
- */
-
-/*
- * man_lwsrv - Deferred mblks for down stream. We end up here when
- * the destination is not DL_IDLE when traffic comes downstream.
- *
- *	wq - lower write queue of mxx
- */
-static int
-man_lwsrv(queue_t *wq)
-{
-	mblk_t		*mp;
-	mblk_t		*mlistp;
-	man_dest_t	*mdp;
-	size_t		count;
-
-	mdp = (man_dest_t *)wq->q_ptr;
-
-	MAN_DBG(MAN_LWSRV, ("man_lwsrv: wq(0x%p) mdp(0x%p)"
-	    " md_rq(0x%p)\n", (void *)wq, (void *)mdp,
-	    mdp ? (void *)mdp->md_rq : NULL));
-
-	if (mdp == NULL)
-		goto exit;
-
-	if (mdp->md_state & MAN_DSTATE_CLOSING) {
-			flushq(wq, FLUSHDATA);
-			flushq(RD(wq), FLUSHDATA);
-			goto exit;
-	}
-
-	/*
-	 * Arrange to send deferred mp's first, then mblks on the
-	 * service queue. Since we are exclusive in the inner perimeter,
-	 * we dont have to worry about md_lock, like the put procedures,
-	 * which are MTPUTSHARED.
-	 */
-	mutex_enter(&mdp->md_lock);
-	mlistp = mdp->md_dmp_head;
-	mdp->md_dmp_head = NULL;
-	count = mdp->md_dmp_count;
-	mdp->md_dmp_count = 0;
-	mutex_exit(&mdp->md_lock);
-
-	while (mlistp != NULL) {
-		mp = mlistp;
-		mlistp = mp->b_next;
-		mp->b_next = NULL;
-		count -= msgsize(mp);
-		if (man_start_lower(mdp, mp, NULL, MAN_LOWER)) {
-
-			mutex_enter(&mdp->md_lock);
-			mdp->md_dmp_count += count + msgsize(mp);
-			mp->b_next = mlistp;
-			mdp->md_dmp_head = mp;
-			mutex_exit(&mdp->md_lock);
-			goto exit;
-		}
-	}
-	mdp->md_dmp_tail = NULL;
-
-	while (mp = getq(wq)) {
-		if (man_start_lower(mdp, mp, NULL, MAN_LOWER)) {
-			/*
-			 * Put it back on queue, making sure to avoid
-			 * infinite loop mentioned in putbq(9F)
-			 */
-			noenable(wq);
-			(void) putbq(wq, mp);
-			enableok(wq);
-
-			break;
-		}
-	}
-
-exit:
-
-	return (0);
-}
-
-/*
- * man_lrput - handle DLPI messages issued from downstream.
- *
- *	rq - lower read queue of mxx
- *	mp - mblk ptr to DLPI request
- *
- *	returns 0
- */
-static int
-man_lrput(queue_t *rq, mblk_t *mp)
-{
-	man_dest_t	*mdp;
-	manstr_t	*msp;
-
-#if defined(DEBUG)
-	union DL_primitives	*dlp;
-	t_uscalar_t		prim = MAN_DLPI_MAX_PRIM + 1;
-	char			*prim_str;
-#endif  /* DEBUG */
-
-	mdp = (man_dest_t *)rq->q_ptr;
-
-#if defined(DEBUG)
-	if (DB_TYPE(mp) == M_PROTO) {
-		dlp = (union DL_primitives *)mp->b_rptr;
-		prim = dlp->dl_primitive;
-	}
-
-	prim_str = (prim > MAN_DLPI_MAX_PRIM) ? "NON DLPI" :
-	    (prim == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
-	    (prim == DLIOCRAW) ? "DLIOCRAW" :
-	    dps[(unsigned int)prim];
-	MAN_DBG(MAN_LRPUT, ("man_lrput: rq(0x%p) mp(0x%p) mdp(0x%p)"
-	    " db_type(0x%x) dl_prim %s", (void *)rq,
-	    (void *)mp, (void *)mdp, DB_TYPE(mp), prim_str));
-	MAN_DBGCALL(MAN_LRPUT2, man_print_mdp(mdp));
-#endif  /* DEBUG */
-
-	if (DB_TYPE(mp) == M_FLUSH) {
-		/* Turn around */
-		if (*mp->b_rptr & FLUSHW) {
-			*mp->b_rptr &= ~FLUSHR;
-			qreply(rq, mp);
-		} else
-			freemsg(mp);
-		return (0);
-	}
-
-	if (mdp == NULL || mdp->md_state != MAN_DSTATE_READY) {
-
-		MAN_DBG(MAN_LRPUT, ("man_lrput: not ready mdp(0x%p),"
-		    " state(%d)", (void *)mdp, mdp ? mdp->md_state : -1));
-		freemsg(mp);
-		return (0);
-	}
-
-	/*
-	 * If we have a destination in the right state, forward on datagrams.
-	 */
-	if (MAN_IS_DATA(mp)) {
-		if (mdp->md_dlpistate == DL_IDLE && canputnext(mdp->md_rq)) {
-
-			msp = mdp->md_msp;
-			if (!(msp->ms_flags & MAN_SFLAG_PROMISC))
-				mdp->md_rcvcnt++; /* Count for failover */
-			/*
-			 * go put mblk_t directly up to next queue.
-			 */
-			MAN_DBG(MAN_LRPUT, ("man_lrput: putnext to rq(0x%p)",
-			    (void *)mdp->md_rq));
-			(void) putnext(mdp->md_rq, mp);
-		} else {
-			freemsg(mp);
-		}
-	} else {
-		/*
-		 * Handle in man_lrsrv with exclusive inner perimeter lock.
-		 */
-		(void) putq(rq, mp);
-	}
-
-	return (0);
-}
-
-/*
- * Either this is a response from our attempt to sync the upper and lower
- * stream states, or its data. If its not data. Do DL_* response processing
- * and transition md_dlpistate accordingly. If its data, toss it.
- */
-static int
-man_lrsrv(queue_t *rq)
-{
-	man_dest_t		*mdp;
-	mblk_t			*mp;
-	union DL_primitives	*dlp;
-	ulong_t			prim;
-	ulong_t			cprim;
-	int			need_dl_reset = FALSE;
-
-#if defined(DEBUG)
-		struct iocblk	*iocp;
-		char		ioc_cmd[256];
-#endif  /* DEBUG */
-
-	MAN_DBG(MAN_LRSRV, ("man_lrsrv: rq(0x%p)", (void *)rq));
-
-	mdp = (man_dest_t *)rq->q_ptr;
-
-	if ((mdp == NULL) || (mdp->md_state & MAN_DSTATE_CLOSING)) {
-			flushq(rq, FLUSHDATA);
-			flushq(WR(rq), FLUSHDATA);
-			goto exit;
-	}
-
-	while (mp = getq(rq)) {
-
-
-	/*
-	 * If we're not connected, or its a datagram, toss it.
-	 */
-	if (MAN_IS_DATA(mp) || mdp->md_state != MAN_DSTATE_READY) {
-
-		MAN_DBG(MAN_LRSRV, ("man_lrsrv: dropping mblk mdp(0x%p)"
-		    " is_data(%d)", (void *)mdp, MAN_IS_DATA(mp)));
-		freemsg(mp);
-		continue;
-	}
-
-	/*
-	 * Should be response to man_dlpi_replay. Discard unless there
-	 * is a failure we care about.
-	 */
-
-	switch (DB_TYPE(mp)) {
-	case M_PROTO:
-	case M_PCPROTO:
-		/* Do proto processing below. */
-		break;
-
-	case M_IOCNAK:
-		/*
-		 * DL_IOC* failed for some reason.
-		 */
-		need_dl_reset = TRUE;
-
-#if defined(DEBUG)
-		iocp = (struct iocblk *)mp->b_rptr;
-
-		(void) sprintf(ioc_cmd, "0x%x", iocp->ioc_cmd);
-		MAN_DBG(MAN_LRSRV, ("man_lrsrv: M_IOCNAK err %d for cmd(%s)\n",
-		    iocp->ioc_error,
-		    (iocp->ioc_cmd == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
-		    (iocp->ioc_cmd == DLIOCRAW) ? "DLIOCRAW" : ioc_cmd));
-#endif  /* DEBUG */
-
-		/* FALLTHRU */
-
-	case M_IOCACK:
-	case M_CTL:
-		/*
-		 * OK response from DL_IOC*, ignore.
-		 */
-		goto dl_reset;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	prim = dlp->dl_primitive;
-
-	MAN_DBG(MAN_LRSRV, ("man_lrsrv: prim %s", dps[(int)prim]));
-
-	/*
-	 * DLPI state processing big theory: We do not rigorously check
-	 * DLPI states (e.g. PENDING stuff). Simple rules:
-	 *
-	 * 	1) If we see an OK_ACK to an ATTACH_REQ, dlpistate = DL_UNBOUND.
-	 *	2) If we see an BIND_ACK to a BIND_REQ, dlpistate = DL_IDLE.
-	 *	3) If we see a OK_ACK response to an UNBIND_REQ
-	 *	   dlpistate = DL_UNBOUND.
-	 *	4) If we see a OK_ACK response to a DETACH_REQ,
-	 *	   dlpistate = DL_UNATTACHED.
-	 *
-	 * Everything that isn't handle by 1-4 above is handled by 5)
-	 *
-	 *	5) A NAK to any DL_* messages we care about causes
-	 *	   dlpistate = DL_UNATTACHED and man_reset_dlpi to run
-	 *
-	 * TBD - need a reset counter so we can try a switch if it gets
-	 * too high.
-	 */
-
-	switch (prim) {
-	case DL_OK_ACK:
-		cprim = dlp->ok_ack.dl_correct_primitive;
-
-		switch (cprim) {
-		case DL_ATTACH_REQ:
-			if (man_dlioc_replay(mdp)) {
-				D_SETSTATE(mdp, DL_UNBOUND);
-			} else {
-				need_dl_reset = TRUE;
-				break;
-			}
-			break;
-
-		case DL_DETACH_REQ:
-			D_SETSTATE(mdp, DL_UNATTACHED);
-			break;
-
-		case DL_UNBIND_REQ:
-			/*
-			 * Cancel timer and set md_dlpistate.
-			 */
-			D_SETSTATE(mdp, DL_UNBOUND);
-
-			ASSERT(mdp->md_bc_id == 0);
-			if (mdp->md_lc_timer_id != 0) {
-				(void) quntimeout(man_ctl_wq,
-				    mdp->md_lc_timer_id);
-				mdp->md_lc_timer_id = 0;
-			}
-		}
-		MAN_DBG(MAN_DLPI,
-		    ("		cprim %s", dps[(int)cprim]));
-		break;
-
-	case DL_BIND_ACK:
-		/*
-		 * We're ready for data. Get man_lwsrv to run to
-		 * process any defered data and start linkcheck timer.
-		 */
-		D_SETSTATE(mdp, DL_IDLE);
-		qenable(mdp->md_wq);
-		mdp->md_linkstate = MAN_LINKGOOD;
-		if (man_needs_linkcheck(mdp)) {
-			mdp->md_lc_timer_id = qtimeout(man_ctl_wq,
-			    man_linkcheck_timer, (void *)mdp,
-			    man_gettimer(MAN_TIMER_LINKCHECK, mdp));
-		}
-
-		break;
-
-	case DL_ERROR_ACK:
-		cprim = dlp->error_ack.dl_error_primitive;
-		switch (cprim) {
-		case DL_ATTACH_REQ:
-		case DL_BIND_REQ:
-		case DL_DISABMULTI_REQ:
-		case DL_ENABMULTI_REQ:
-		case DL_PROMISCON_REQ:
-		case DL_PROMISCOFF_REQ:
-		case DL_SET_PHYS_ADDR_REQ:
-			need_dl_reset = TRUE;
-			break;
-
-		/*
-		 * ignore error TBD (better comment)
-		 */
-		case DL_UNBIND_REQ:
-		case DL_DETACH_REQ:
-			break;
-		}
-
-		MAN_DBG(MAN_DLPI,
-		    ("\tdl_errno %d dl_unix_errno %d cprim %s",
-		    dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno,
-		    dps[(int)cprim]));
-		break;
-
-	case DL_UDERROR_IND:
-		MAN_DBG(MAN_DLPI,
-		    ("\tdl_errno %d unix_errno %d",
-		    dlp->uderror_ind.dl_errno,
-		    dlp->uderror_ind.dl_unix_errno));
-		break;
-
-	case DL_INFO_ACK:
-		break;
-
-	default:
-		/*
-		 * We should not get here.
-		 */
-		cmn_err(CE_WARN, "man_lrsrv: unexpected DL prim 0x%lx!",
-		    prim);
-		need_dl_reset = TRUE;
-		break;
-	}
-
-dl_reset:
-	freemsg(mp);
-
-	if (need_dl_reset) {
-		man_pg_t	*mpg;
-		man_path_t	*mp;
-
-		if (qsize(rq)) {	/* Dump all messages. */
-			flushq(rq, FLUSHDATA);
-			flushq(WR(rq), FLUSHDATA);
-		}
-
-		mdp->md_dlpierrors++;
-		D_SETSTATE(mdp, DL_UNATTACHED);
-		if (mdp->md_lc_timer_id != 0) {
-			(void) quntimeout(man_ctl_wq, mdp->md_lc_timer_id);
-			mdp->md_lc_timer_id = 0;
-		}
-
-		mutex_enter(&man_lock);
-		ASSERT(mdp->md_msp != NULL);
-		ASSERT(mdp->md_msp->ms_manp != NULL);
-		mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg,
-		    mdp->md_pg_id);
-		ASSERT(mpg != NULL);
-		mp = man_find_path_by_ppa(mpg->mpg_pathp,
-		    mdp->md_device.mdev_ppa);
-		ASSERT(mp != NULL);
-		mp->mp_device.mdev_state |= MDEV_FAILED;
-		if ((mdp->md_dlpierrors >= MAN_MAX_DLPIERRORS) &&
-		    (man_is_on_domain ||
-		    mdp->md_msp->ms_manp->man_meta_ppa == 1)) {
-			/*
-			 * Autoswitching is disabled for instance 0
-			 * on the SC as we expect the domain to
-			 * initiate the path switching.
-			 */
-			(void) man_do_autoswitch((man_dest_t *)mdp);
-			MAN_DBG(MAN_WARN, ("man_lrsrv: dlpi failure(%d,%d),"
-			    " switching path", mdp->md_device.mdev_major,
-			    mdp->md_device.mdev_ppa));
-		} else {
-			mdp->md_lc_timer_id = qtimeout(man_ctl_wq,
-			    man_reset_dlpi, (void *)mdp,
-			    man_gettimer(MAN_TIMER_DLPIRESET, mdp));
-		}
-		mutex_exit(&man_lock);
-	}
-
-
-	} /* End while (getq()) */
-
-exit:
-	MAN_DBG(MAN_DLPI, ("man_lrsrv: returns"));
-
-	return (0);
-}
-
-static int
-man_needs_linkcheck(man_dest_t *mdp)
-{
-	/*
-	 * Not ready for linkcheck.
-	 */
-	if (mdp->md_msp == NULL || mdp->md_msp->ms_manp == NULL)
-		return (0);
-
-	/*
-	 * Linkchecking needs to be done on IP streams. For domain, all
-	 * driver instances need checking, for SC only instance 1 needs it.
-	 */
-	if ((man_is_on_domain || mdp->md_msp->ms_manp->man_meta_ppa == 1) &&
-	    (mdp->md_msp->ms_sap == ETHERTYPE_IP ||
-	    mdp->md_msp->ms_sap == ETHERTYPE_IPV6))
-
-		return (1);
-
-	/*
-	 * Linkcheck not need on this link.
-	 */
-	return (0);
-}
-
-/*
- * The following routines process work requests posted to man_iwork_q
- * from the non-STREAMS half of the driver (see man_bwork.c). The work
- * requires access to the inner perimeter lock of the driver. This
- * lock is acquired by man_uwsrv, who calls man_iwork to process the
- * man_iwork_q->
- */
-
-/*
- * The man_bwork has posted some work for us to do inside the
- * perimeter. This mainly involves updating lower multiplexor data
- * structures (non-blocking type stuff). So, we can hold the man_lock
- * until we are done processing all work items. Note that some of these
- * routines in turn submit work back to the bgthread, which they can do
- * since we hold the man_lock.
- */
-static void
-man_iwork()
-{
-	man_work_t	*wp;
-	int		wp_finished;
-
-	MAN_DBG(MAN_SWITCH, ("man_iwork: q_work(0x%p)",
-	    (void *)man_iwork_q->q_work));
-
-	mutex_enter(&man_lock);
-
-	while (man_iwork_q->q_work) {
-
-		wp = man_iwork_q->q_work;
-		man_iwork_q->q_work = wp->mw_next;
-		wp->mw_next = NULL;
-
-		mutex_exit(&man_lock);
-
-		MAN_DBG(MAN_SWITCH, ("man_iwork: type %s",
-		    _mw_type[wp->mw_type]));
-
-		wp_finished = TRUE;
-
-		switch (wp->mw_type) {
-		case MAN_WORK_DRATTACH:
-			(void) man_do_dr_attach(wp);
-			break;
-
-		case MAN_WORK_DRSWITCH:
-			/*
-			 * Return status to man_dr_detach immediately. If
-			 * no error submitting SWITCH request, man_iswitch
-			 * or man_bclose will cv_signal man_dr_detach on
-			 * completion of SWITCH work request.
-			 */
-			if (man_do_dr_switch(wp) == 0)
-				wp_finished = FALSE;
-			break;
-
-		case MAN_WORK_DRDETACH:
-			man_do_dr_detach(wp);
-			break;
-
-		case MAN_WORK_SWITCH:
-			if (man_iswitch(wp))
-				wp_finished = FALSE;
-			break;
-
-		case MAN_WORK_KSTAT_UPDATE:
-			man_do_kstats(wp);
-			break;
-
-		default:
-			cmn_err(CE_WARN, "man_iwork: "
-			    "illegal work type(%d)", wp->mw_type);
-			break;
-		}
-
-		mutex_enter(&man_lock);
-
-		/*
-		 * If we've completed the work request, delete, or
-		 * cv_signal waiter.
-		 */
-		if (wp_finished) {
-			wp->mw_flags |= MAN_WFLAGS_DONE;
-
-			if (wp->mw_flags & MAN_WFLAGS_CVWAITER)
-				cv_signal(&wp->mw_cv);
-			else
-				man_work_free(wp);
-		}
-	}
-
-	mutex_exit(&man_lock);
-}
-
-/*
- * man_dr_detach has submitted a request to DRSWITCH a path.
- * It is in cv_wait_sig(wp->mw_cv). We forward the work request on to
- * man_bwork as a switch request. It should end up back at
- * man_iwork, who will cv_signal(wp->mw_cv) man_dr_detach.
- *
- * Called holding inner perimeter lock.
- * man_lock is held to synchronize access to pathgroup list(man_pg).
- */
-static int
-man_do_dr_switch(man_work_t *wp)
-{
-	man_t		*manp;
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-	man_path_t	*ap;
-	man_adest_t	*adp;
-	mi_path_t	mpath;
-	int		status = 0;
-
-	adp = &wp->mw_arg;
-
-	MAN_DBG(MAN_SWITCH, ("man_do_dr_switch: pg_id %d work:", adp->a_pg_id));
-	MAN_DBGCALL(MAN_SWITCH, man_print_work(wp));
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
-	if (manp == NULL || manp->man_pg == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	mpg = man_find_pg_by_id(manp->man_pg, adp->a_pg_id);
-	if (mpg == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	if (mpg->mpg_flags & MAN_PG_SWITCHING) {
-		status = EAGAIN;
-		goto exit;
-	}
-
-	/*
-	 * Check to see if detaching device is active. If so, activate
-	 * an alternate.
-	 */
-	mp = man_find_active_path(mpg->mpg_pathp);
-	if (mp && mp->mp_device.mdev_ppa == adp->a_sf_dev.mdev_ppa) {
-
-		ap = man_find_alternate_path(mpg->mpg_pathp);
-		if (ap == NULL) {
-			status = EBUSY;
-			goto exit;
-		}
-
-		bzero((char *)&mpath, sizeof (mi_path_t));
-
-		mpath.mip_cmd = MI_PATH_ACTIVATE;
-		mpath.mip_man_ppa = 0;
-		mpath.mip_pg_id = 0;
-		mpath.mip_devs[0] = ap->mp_device;
-		mpath.mip_ndevs = 1;
-		ether_copy(&manp->man_eaddr, &mpath.mip_eaddr);
-
-		/*
-		 * DR thread is sleeping on wp->mw_cv. We change the work
-		 * request from DRSWITCH to SWITCH and submit it to
-		 * for processing by man_bwork (via man_pg_cmd). At
-		 * completion the SWITCH work request is processed by
-		 * man_iswitch() or man_bclose and the DR thread will
-		 * be cv_signal'd.
-		 */
-		wp->mw_type = MAN_WORK_SWITCH;
-		if (status = man_pg_cmd(&mpath, wp))
-			goto exit;
-
-	} else {
-		/*
-		 * Tell man_dr_detach that detaching device is not currently
-		 * in use.
-		 */
-		status = ENODEV;
-	}
-
-exit:
-	if (status) {
-		/*
-		 * ENODEV is a noop, not really an error.
-		 */
-		if (status != ENODEV)
-			wp->mw_status = status;
-	}
-	mutex_exit(&man_lock);
-
-	return (status);
-}
-
-/*
- * man_dr_attach has submitted a request to DRATTACH a path,
- * add that path to the path list.
- *
- * Called holding perimeter lock.
- */
-static int
-man_do_dr_attach(man_work_t *wp)
-{
-	man_t		*manp;
-	man_adest_t	*adp;
-	mi_path_t	mpath;
-	manc_t		manc;
-	int		status = 0;
-
-	adp = &wp->mw_arg;
-
-	MAN_DBG(MAN_SWITCH, ("man_do_dr_attach: pg_id %d work:", adp->a_pg_id));
-	MAN_DBGCALL(MAN_SWITCH, man_print_work(wp));
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
-	if (manp == NULL || manp->man_pg == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	if (status = man_get_iosram(&manc)) {
-		goto exit;
-	}
-	/*
-	 * Extract SC ethernet address from IOSRAM.
-	 */
-	ether_copy(&manc.manc_sc_eaddr, &mpath.mip_eaddr);
-
-	mpath.mip_pg_id = adp->a_pg_id;
-	mpath.mip_man_ppa = adp->a_man_ppa;
-	/*
-	 * man_dr_attach passes the new device info in a_sf_dev.
-	 */
-	MAN_DBG(MAN_DR, ("man_do_dr_attach: "));
-	MAN_DBGCALL(MAN_DR, man_print_dev(&adp->a_sf_dev));
-	mpath.mip_devs[0] = adp->a_sf_dev;
-	mpath.mip_ndevs = 1;
-	mpath.mip_cmd = MI_PATH_ADD;
-	status = man_pg_cmd(&mpath, NULL);
-
-exit:
-	mutex_exit(&man_lock);
-	return (status);
-}
-
-/*
- * man_dr_detach has submitted a request to DRDETACH a path.
- * It is in cv_wait_sig(wp->mw_cv). We remove the path and
- * cv_signal(wp->mw_cv) man_dr_detach.
- *
- * Called holding perimeter lock.
- */
-static void
-man_do_dr_detach(man_work_t *wp)
-{
-	man_t		*manp;
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-	man_adest_t	*adp;
-	manc_t		manc;
-	mi_path_t	mpath;
-	int		i;
-	int		found;
-	int		status = 0;
-
-	adp = &wp->mw_arg;
-
-	MAN_DBG(MAN_SWITCH, ("man_do_dr_detach: pg_id %d work:", adp->a_pg_id));
-	MAN_DBGCALL(MAN_SWITCH, man_print_work(wp));
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
-	if (manp == NULL || manp->man_pg == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	mpg = man_find_pg_by_id(manp->man_pg, adp->a_pg_id);
-	if (mpg == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	if (mpg->mpg_flags & MAN_PG_SWITCHING) {
-		status = EAGAIN;
-		goto exit;
-	}
-
-	/*
-	 * We should have switched detaching path if it was active.
-	 */
-	mp = man_find_active_path(mpg->mpg_pathp);
-	if (mp && mp->mp_device.mdev_ppa == adp->a_sf_dev.mdev_ppa) {
-		status = EAGAIN;
-		goto exit;
-	}
-
-	/*
-	 * Submit an ASSIGN command, minus the detaching device.
-	 */
-	bzero((char *)&mpath, sizeof (mi_path_t));
-
-	if (status = man_get_iosram(&manc)) {
-		goto exit;
-	}
-
-	mpath.mip_cmd = MI_PATH_ASSIGN;
-	mpath.mip_man_ppa = 0;
-	mpath.mip_pg_id = 0;
-
-	mp = mpg->mpg_pathp;
-	i = 0;
-	found = FALSE;
-	while (mp != NULL) {
-		if (mp->mp_device.mdev_ppa != adp->a_sf_dev.mdev_ppa) {
-			mpath.mip_devs[i] = mp->mp_device;
-			i++;
-		} else {
-			found = TRUE;
-		}
-		mp = mp->mp_next;
-	}
-
-	if (found) {
-		/*
-		 * Need to include SCs ethernet address in command.
-		 */
-		mpath.mip_ndevs = i;
-		ether_copy(&manc.manc_sc_eaddr, &mpath.mip_eaddr);
-
-		status = man_pg_cmd(&mpath, NULL);
-	}
-
-	/*
-	 * Hand back status to man_dr_detach request.
-	 */
-exit:
-	if (status != ENODEV)
-		wp->mw_status = status;
-
-	mutex_exit(&man_lock);
-
-}
-
-
-/*
- * The background thread has configured new lower multiplexor streams for
- * the given destinations. Update the appropriate destination data structures
- * inside the inner perimeter. We must take care to deal with destinations
- * whose upper stream has closed or detached from lower streams.
- *
- * Returns
- *	0		Done with work request.
- *	1		Reused work request.
- */
-static int
-man_iswitch(man_work_t *wp)
-{
-	man_adest_t	*adp;
-	man_t		*manp;
-	man_pg_t	*mpg;
-	man_path_t	*mp = NULL;
-	man_dest_t	*mdp;
-	man_dest_t	*tdp;
-	int		i;
-	int		switch_ok = TRUE;
-
-	adp = &wp->mw_arg;
-
-	if (wp->mw_status != 0) {
-		switch_ok = FALSE;	/* Never got things opened */
-	}
-
-	/*
-	 * Update destination structures as appropriate.
-	 */
-	for (i = 0; i < adp->a_ndests; i++) {
-		man_dest_t	tmp;
-
-		/*
-		 * Check to see if lower stream we just switch is still
-		 * around.
-		 */
-		tdp = &adp->a_mdp[i];
-		mdp = man_switch_match(tdp, adp->a_pg_id, tdp->md_switch_id);
-
-		if (mdp == NULL)
-			continue;
-
-		if (switch_ok == FALSE) {
-			/*
-			 * Switch failed for some reason.  Clear
-			 * PLUMBING flag and retry switch again later.
-			 */
-			man_ifail_dest(mdp);
-			continue;
-		}
-
-		/*
-		 * Swap new info, for old. We return the old info to
-		 * man_bwork to close things up below.
-		 */
-		bcopy((char *)mdp, (char *)&tmp, sizeof (man_dest_t));
-
-		ASSERT(mdp->md_state & MAN_DSTATE_PLUMBING);
-		ASSERT(mdp->md_state == tdp->md_state);
-
-		mdp->md_state = tdp->md_state;
-
-		/*
-		 * save the wq from the destination passed(tdp).
-		 */
-		mdp->md_wq = tdp->md_wq;
-		RD(mdp->md_wq)->q_ptr = (void *)(mdp);
-		WR(mdp->md_wq)->q_ptr = (void *)(mdp);
-
-		mdp->md_state &= ~MAN_DSTATE_INITIALIZING;
-		mdp->md_state |= MAN_DSTATE_READY;
-
-		ASSERT(mdp->md_device.mdev_major == adp->a_sf_dev.mdev_major);
-
-		ASSERT(tdp->md_device.mdev_ppa == adp->a_st_dev.mdev_ppa);
-		ASSERT(tdp->md_device.mdev_major == adp->a_st_dev.mdev_major);
-
-		mdp->md_device = tdp->md_device;
-		mdp->md_muxid = tdp->md_muxid;
-		mdp->md_linkstate = MAN_LINKUNKNOWN;
-		(void) drv_getparm(TIME, &mdp->md_lastswitch);
-		mdp->md_state &= ~MAN_DSTATE_PLUMBING;
-		mdp->md_switch_id = 0;
-		mdp->md_switches++;
-		mdp->md_dlpierrors = 0;
-		D_SETSTATE(mdp, DL_UNATTACHED);
-
-		/*
-		 * Resync lower w/ upper dlpi state. This will start link
-		 * timer if/when lower stream goes to DL_IDLE (see man_lrsrv).
-		 */
-		man_reset_dlpi((void *)mdp);
-
-		bcopy((char *)&tmp, (char *)tdp, sizeof (man_dest_t));
-	}
-
-	if (switch_ok) {
-		for (i = 0; i < adp->a_ndests; i++) {
-			tdp = &adp->a_mdp[i];
-
-			tdp->md_state &= ~MAN_DSTATE_PLUMBING;
-			tdp->md_state &= ~MAN_DSTATE_INITIALIZING;
-			tdp->md_state |= MAN_DSTATE_READY;
-		}
-	} else {
-		/*
-		 * Never got switch-to destinations open, free them.
-		 */
-		man_kfree(adp->a_mdp,
-		    sizeof (man_dest_t) * adp->a_ndests);
-	}
-
-	/*
-	 * Clear pathgroup switching flag and update path flags.
-	 */
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
-
-	ASSERT(manp != NULL);
-	ASSERT(manp->man_pg != NULL);
-
-	mpg = man_find_pg_by_id(manp->man_pg, adp->a_pg_id);
-	ASSERT(mpg != NULL);
-	ASSERT(mpg->mpg_flags & MAN_PG_SWITCHING);
-	mpg->mpg_flags &= ~MAN_PG_SWITCHING;
-
-	/*
-	 * Switch succeeded, mark path we switched from as failed, and
-	 * device we switch to as active and clear its failed flag (if set).
-	 * Sync up kstats.
-	 */
-	if (switch_ok) {
-		mp = man_find_active_path(mpg->mpg_pathp);
-		if (mp != NULL) {
-
-			ASSERT(adp->a_sf_dev.mdev_major != 0);
-
-			MAN_DBG(MAN_SWITCH, ("man_iswitch: switch from dev:"));
-			MAN_DBGCALL(MAN_SWITCH, man_print_dev(&adp->a_sf_dev));
-
-			mp->mp_device.mdev_state &= ~MDEV_ACTIVE;
-		} else
-			ASSERT(adp->a_sf_dev.mdev_major == 0);
-
-		MAN_DBG(MAN_SWITCH, ("man_iswitch: switch to dev:"));
-		MAN_DBGCALL(MAN_SWITCH, man_print_dev(&adp->a_st_dev));
-
-		ASSERT(adp->a_st_dev.mdev_major != 0);
-
-		mp = man_find_path_by_ppa(mpg->mpg_pathp,
-		    adp->a_st_dev.mdev_ppa);
-
-		ASSERT(mp != NULL);
-
-		mp->mp_device.mdev_state |= MDEV_ACTIVE;
-	}
-
-	/*
-	 * Decrement manp reference count and hand back work request if
-	 * needed.
-	 */
-	manp->man_refcnt--;
-
-	if (switch_ok) {
-		wp->mw_type = MAN_WORK_CLOSE;
-		man_work_add(man_bwork_q, wp);
-	}
-
-	mutex_exit(&man_lock);
-
-	return (switch_ok);
-}
-
-/*
- * Find the destination in the upper stream that we just switched.
- */
-man_dest_t *
-man_switch_match(man_dest_t *sdp, int pg_id, void *sid)
-{
-	man_dest_t	*mdp = NULL;
-	manstr_t	*msp;
-
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-		/*
-		 * Check if upper stream closed, or detached.
-		 */
-		if (msp != sdp->md_msp)
-			continue;
-
-		if (msp->ms_dests == NULL)
-			break;
-
-		mdp = &msp->ms_dests[pg_id];
-
-		/*
-		 * Upper stream detached and reattached while we were
-		 * switching.
-		 */
-		if (mdp->md_switch_id != sid) {
-			mdp = NULL;
-			break;
-		}
-	}
-
-	return (mdp);
-}
-
-/*
- * bg_thread cant complete the switch for some reason. (Re)start the
- * linkcheck timer again.
- */
-static void
-man_ifail_dest(man_dest_t *mdp)
-{
-	ASSERT(mdp->md_lc_timer_id == 0);
-	ASSERT(mdp->md_bc_id == 0);
-	ASSERT(mdp->md_state & MAN_DSTATE_PLUMBING);
-
-	MAN_DBG(MAN_SWITCH, ("man_ifail_dest"));
-	MAN_DBGCALL(MAN_SWITCH, man_print_mdp(mdp));
-
-	mdp->md_state &= ~MAN_DSTATE_PLUMBING;
-	mdp->md_linkstate = MAN_LINKFAIL;
-
-	/*
-	 * If we have not yet initialized link, or the upper stream is
-	 * DL_IDLE, restart the linktimer.
-	 */
-	if ((mdp->md_state & MAN_DSTATE_INITIALIZING) ||
-	    ((mdp->md_msp->ms_sap == ETHERTYPE_IPV6 ||
-	    mdp->md_msp->ms_sap == ETHERTYPE_IP) &&
-	    mdp->md_msp->ms_dlpistate == DL_IDLE)) {
-
-		mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
-		    (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
-	}
-
-}
-
-/*
- * Arrange to replay all of ms_dl_mp on the new lower stream to get it
- * in sync with the upper stream. Note that this includes setting the
- * physical address.
- *
- * Called from qtimeout with inner perimeter lock.
- */
-static void
-man_reset_dlpi(void *argp)
-{
-	man_dest_t	*mdp = (man_dest_t *)argp;
-	manstr_t	*msp;
-	mblk_t		*mp;
-	mblk_t		*rmp = NULL;
-	mblk_t		*tmp;
-
-	mdp->md_lc_timer_id = 0;
-
-	if (mdp->md_state != MAN_DSTATE_READY) {
-		MAN_DBG(MAN_DLPI, ("man_reset_dlpi: not ready!"));
-		return;
-	}
-
-	msp = mdp->md_msp;
-
-	rmp = man_dup_mplist(msp->ms_dl_mp);
-	if (rmp == NULL)
-		goto fail;
-
-	/*
-	 * Send down an unbind and detach request, just to clean things
-	 * out, we ignore ERROR_ACKs for unbind and detach in man_lrsrv.
-	 */
-	tmp = man_alloc_ubreq_dreq();
-	if (tmp == NULL) {
-		goto fail;
-	}
-	mp = tmp;
-	while (mp->b_next != NULL)
-		mp = mp->b_next;
-	mp->b_next = rmp;
-	rmp = tmp;
-
-	man_dlpi_replay(mdp, rmp);
-
-	return;
-
-fail:
-
-	while (rmp) {
-		mp = rmp;
-		rmp = rmp->b_next;
-		mp->b_next = mp->b_prev = NULL;
-		freemsg(mp);
-	}
-
-	ASSERT(mdp->md_lc_timer_id == 0);
-	ASSERT(mdp->md_bc_id == 0);
-
-	/*
-	 * If low on memory, try again later. I Could use qbufcall, but that
-	 * could fail and I would have to try and recover from that w/
-	 * qtimeout anyway.
-	 */
-	mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_reset_dlpi,
-	    (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
-}
-
-/*
- * Once we receive acknowledgement that DL_ATTACH_REQ was successful,
- * we can send down the DL_* related IOCTLs (e.g. DL_IOC_HDR). If we
- * try and send them downsteam w/o waiting, the ioctl's get processed before
- * the ATTACH_REQ and they are rejected. TBD - could just do the lower
- * dlpi state change in lock step. TBD
- */
-static int
-man_dlioc_replay(man_dest_t *mdp)
-{
-	mblk_t		*rmp;
-	int		status = 1;
-
-	if (mdp->md_msp->ms_dlioc_mp == NULL)
-		goto exit;
-
-	rmp = man_dup_mplist(mdp->md_msp->ms_dlioc_mp);
-	if (rmp == NULL) {
-		status = 0;
-		goto exit;
-	}
-
-	man_dlpi_replay(mdp, rmp);
-exit:
-	return (status);
-}
-
-static mblk_t *
-man_alloc_ubreq_dreq()
-{
-	mblk_t			*dreq;
-	mblk_t			*ubreq = NULL;
-	union DL_primitives	*dlp;
-
-	dreq = allocb(DL_DETACH_REQ_SIZE, BPRI_MED);
-	if (dreq == NULL)
-		goto exit;
-
-	dreq->b_datap->db_type = M_PROTO;
-	dlp = (union DL_primitives *)dreq->b_rptr;
-	dlp->dl_primitive = DL_DETACH_REQ;
-	dreq->b_wptr += DL_DETACH_REQ_SIZE;
-
-	ubreq = allocb(DL_UNBIND_REQ_SIZE, BPRI_MED);
-	if (ubreq == NULL) {
-		freemsg(dreq);
-		goto exit;
-	}
-
-	ubreq->b_datap->db_type = M_PROTO;
-	dlp = (union DL_primitives *)ubreq->b_rptr;
-	dlp->dl_primitive = DL_UNBIND_REQ;
-	ubreq->b_wptr += DL_UNBIND_REQ_SIZE;
-
-	ubreq->b_next = dreq;
-
-exit:
-
-	return (ubreq);
-}
-
-static mblk_t *
-man_dup_mplist(mblk_t *mp)
-{
-	mblk_t	*listp = NULL;
-	mblk_t	*tailp = NULL;
-
-	for (; mp != NULL; mp = mp->b_next) {
-
-		mblk_t	*nmp;
-		mblk_t	*prev;
-		mblk_t	*next;
-
-		prev = mp->b_prev;
-		next = mp->b_next;
-		mp->b_prev = mp->b_next = NULL;
-
-		nmp = copymsg(mp);
-
-		mp->b_prev = prev;
-		mp->b_next = next;
-
-		if (nmp == NULL)
-			goto nomem;
-
-		if (listp == NULL) {
-			listp = tailp = nmp;
-		} else {
-			tailp->b_next = nmp;
-			tailp = nmp;
-		}
-	}
-
-	return (listp);
-nomem:
-
-	while (listp) {
-		mp = listp;
-		listp = mp->b_next;
-		mp->b_next = mp->b_prev = NULL;
-		freemsg(mp);
-	}
-
-	return (NULL);
-
-}
-
-static mblk_t *
-man_alloc_physreq_mp(eaddr_t *man_eap)
-{
-
-	mblk_t			*mp;
-	union DL_primitives	*dlp;
-	t_uscalar_t		off;
-	eaddr_t			*eap;
-
-	mp = allocb(DL_SET_PHYS_ADDR_REQ_SIZE + ETHERADDRL, BPRI_MED);
-	if (mp == NULL)
-		goto exit;
-
-	mp->b_datap->db_type = M_PROTO;
-	dlp = (union DL_primitives *)mp->b_wptr;
-	dlp->set_physaddr_req.dl_primitive = DL_SET_PHYS_ADDR_REQ;
-	dlp->set_physaddr_req.dl_addr_length = ETHERADDRL;
-	off = DL_SET_PHYS_ADDR_REQ_SIZE;
-	dlp->set_physaddr_req.dl_addr_offset =  off;
-	mp->b_wptr += DL_SET_PHYS_ADDR_REQ_SIZE + ETHERADDRL;
-
-	eap = (eaddr_t *)(mp->b_rptr + off);
-	ether_copy(man_eap, eap);
-
-exit:
-	MAN_DBG(MAN_DLPI, ("man_alloc_physreq: physaddr %s\n",
-	    ether_sprintf(eap)));
-
-	return (mp);
-}
-
-/*
- * A new path in a pathgroup has become active for the first time. Setup
- * the lower destinations in prepartion for man_pg_activate to call
- * man_autoswitch.
- */
-static void
-man_add_dests(man_pg_t *mpg)
-{
-	manstr_t	*msp;
-	man_dest_t	*mdp;
-
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-
-		if (!man_str_uses_pg(msp, mpg))
-			continue;
-
-		mdp = &msp->ms_dests[mpg->mpg_pg_id];
-
-/*
- * TBD - Take out
- *		ASSERT(mdp->md_device.mdev_state == MDEV_UNASSIGNED);
- *		ASSERT(mdp->md_state == MAN_DSTATE_NOTPRESENT);
- */
-		if (mdp->md_device.mdev_state != MDEV_UNASSIGNED) {
-			cmn_err(CE_NOTE, "man_add_dests mdev !unassigned");
-			MAN_DBGCALL(MAN_PATH, man_print_mdp(mdp));
-		}
-
-		man_start_dest(mdp, msp, mpg);
-	}
-
-}
-
-static int
-man_remove_dests(man_pg_t *mpg)
-{
-	manstr_t	*msp;
-	int		close_cnt = 0;
-	man_dest_t	*cdp;
-	man_dest_t	*mdp;
-	man_dest_t	*tdp;
-	man_work_t	*wp;
-	mblk_t		*mp;
-	int		status = 0;
-
-	wp = man_work_alloc(MAN_WORK_CLOSE, KM_NOSLEEP);
-	if (wp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-	/*
-	 * Count up number of destinations we need to close.
-	 */
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-		if (!man_str_uses_pg(msp, mpg))
-			continue;
-
-		close_cnt++;
-	}
-
-	if (close_cnt == 0)
-		goto exit;
-
-	cdp = man_kzalloc(sizeof (man_dest_t) * close_cnt, KM_NOSLEEP);
-	if (cdp == NULL) {
-		status = ENOMEM;
-		man_work_free(wp);
-		goto exit;
-	}
-
-	tdp = cdp;
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-		if (!man_str_uses_pg(msp, mpg))
-			continue;
-
-		mdp = &msp->ms_dests[mpg->mpg_pg_id];
-
-		mdp->md_state |= MAN_DSTATE_CLOSING;
-		mdp->md_device.mdev_state = MDEV_UNASSIGNED;
-		mdp->md_msp = NULL;
-		mdp->md_rq = NULL;
-
-		/*
-		 * Clean up optimized destination pointer if we are
-		 * closing it.
-		 */
-		man_set_optimized_dest(msp);
-
-		if (mdp->md_lc_timer_id != 0) {
-			(void) quntimeout(man_ctl_wq, mdp->md_lc_timer_id);
-			mdp->md_lc_timer_id = 0;
-		}
-		if (mdp->md_bc_id != 0) {
-			qunbufcall(man_ctl_wq, mdp->md_bc_id);
-			mdp->md_bc_id = 0;
-		}
-
-		mutex_enter(&mdp->md_lock);
-		while ((mp = mdp->md_dmp_head) != NULL) {
-			mdp->md_dmp_head = mp->b_next;
-			mp->b_next = NULL;
-			freemsg(mp);
-		}
-		mdp->md_dmp_count = 0;
-		mdp->md_dmp_tail = NULL;
-		mutex_exit(&mdp->md_lock);
-
-		*tdp++ = *mdp;
-
-		mdp->md_state = MAN_DSTATE_NOTPRESENT;
-		mdp->md_muxid = -1;
-	}
-
-	wp->mw_arg.a_mdp = cdp;
-	wp->mw_arg.a_ndests = close_cnt;
-	man_work_add(man_bwork_q, wp);
-
-exit:
-	return (status);
-
-}
-
-/*
- * Returns TRUE if stream uses pathgroup, FALSE otherwise.
- */
-static int
-man_str_uses_pg(manstr_t *msp, man_pg_t *mpg)
-{
-	int	status;
-
-	status = ((msp->ms_flags & MAN_SFLAG_CONTROL)	||
-	    (msp->ms_dests == NULL)	||
-	    (msp->ms_manp == NULL)	||
-	    (msp->ms_manp->man_meta_ppa != mpg->mpg_man_ppa));
-
-	return (!status);
-}
-
-static int
-man_gettimer(int timer, man_dest_t *mdp)
-{
-
-	int attached = TRUE;
-	int time = 0;
-
-	if (mdp == NULL || mdp->md_msp == NULL || mdp->md_msp->ms_manp == NULL)
-		attached = FALSE;
-
-	switch (timer) {
-	case MAN_TIMER_INIT:
-		if (attached)
-			time = mdp->md_msp->ms_manp->man_init_time;
-		else
-			time = MAN_INIT_TIME;
-		break;
-
-	case MAN_TIMER_LINKCHECK:
-		if (attached) {
-			if (mdp->md_linkstate == MAN_LINKSTALE)
-				time = mdp->md_msp->ms_manp->man_linkstale_time;
-			else
-				time = mdp->md_msp->ms_manp->man_linkcheck_time;
-		} else
-			time = MAN_LINKCHECK_TIME;
-		break;
-
-	case MAN_TIMER_DLPIRESET:
-		if (attached)
-			time = mdp->md_msp->ms_manp->man_dlpireset_time;
-		else
-			time = MAN_DLPIRESET_TIME;
-		break;
-
-	default:
-		MAN_DBG(MAN_LINK, ("man_gettimer: unknown timer %d", timer));
-		time = MAN_LINKCHECK_TIME;
-		break;
-	}
-
-	return (drv_usectohz(time));
-}
-
-/*
- * Check the links for each active destination. Called inside inner
- * perimeter via qtimeout. This timer only runs on the domain side of the
- * driver. It should never run on the SC side.
- *
- * On a MAN_LINKGOOD link, we check/probe the link health every
- * MAN_LINKCHECK_TIME seconds. If the link goes MAN_LINKSTALE, the we probe
- * the link every MAN_LINKSTALE_TIME seconds, and fail the link after probing
- * the link MAN_LINKSTALE_RETRIES times.
- * The man_lock is held to synchronize access pathgroup list(man_pg).
- */
-void
-man_linkcheck_timer(void *argp)
-{
-	man_dest_t		*mdp = (man_dest_t *)argp;
-	int			restart_timer = TRUE;
-	int			send_ping = TRUE;
-	int			newstate;
-	int			oldstate;
-	man_pg_t		*mpg;
-	man_path_t		*mp;
-
-	MAN_DBG(MAN_LINK, ("man_linkcheck_timer: mdp"));
-	MAN_DBGCALL(MAN_LINK, man_print_mdp(mdp));
-
-	/*
-	 * Clear timeout id and check if someones waiting on us to
-	 * complete a close.
-	 */
-	mdp->md_lc_timer_id = 0;
-
-	if (mdp->md_state == MAN_DSTATE_NOTPRESENT ||
-	    mdp->md_state & MAN_DSTATE_BUSY) {
-
-		MAN_DBG(MAN_LINK, ("man_linkcheck_timer: not ready mdp"));
-		MAN_DBGCALL(MAN_LINK, man_print_mdp(mdp));
-		goto exit;
-	}
-
-	mutex_enter(&man_lock);
-	/*
-	 * If the lower stream needs initializing, just go straight to
-	 * switch code. As the linkcheck timer is started for all
-	 * SAPs, do not send ping packets during the initialization.
-	 */
-	if (mdp->md_state == MAN_DSTATE_INITIALIZING) {
-		send_ping = FALSE;
-		goto do_switch;
-	}
-
-	newstate = oldstate = mdp->md_linkstate;
-
-	if (!man_needs_linkcheck(mdp)) {
-		cmn_err(CE_NOTE,
-		    "man_linkcheck_timer: unneeded linkcheck on mdp(0x%p)",
-		    (void *)mdp);
-		mutex_exit(&man_lock);
-		return;
-	}
-
-	/*
-	 * The above call to  man_needs_linkcheck() validates
-	 * mdp->md_msp and mdp->md_msp->ms_manp pointers.
-	 */
-	mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg, mdp->md_pg_id);
-	ASSERT(mpg != NULL);
-	mp = man_find_path_by_ppa(mpg->mpg_pathp, mdp->md_device.mdev_ppa);
-	ASSERT(mp != NULL);
-
-	/*
-	 * This is the most common case, when traffic is flowing.
-	 */
-	if (mdp->md_rcvcnt != mdp->md_lastrcvcnt) {
-
-		newstate = MAN_LINKGOOD;
-		mdp->md_lastrcvcnt = mdp->md_rcvcnt;
-		send_ping = FALSE;
-
-		/*
-		 * Clear the FAILED flag and update lru.
-		 */
-		mp->mp_device.mdev_state &= ~MDEV_FAILED;
-		(void) drv_getparm(TIME, &mp->mp_lru);
-
-		if (mdp->md_link_updown_msg == MAN_LINK_DOWN_MSG) {
-			man_t *manp = mdp->md_msp->ms_manp;
-
-			cmn_err(CE_NOTE, "%s%d Link up",
-			    ddi_major_to_name(manp->man_meta_major),
-			    manp->man_meta_ppa);
-
-			mdp->md_link_updown_msg = MAN_LINK_UP_MSG;
-		}
-
-		goto done;
-	}
-
-	/*
-	 * If we're here, it means we have not seen any traffic
-	 */
-	switch (oldstate) {
-	case MAN_LINKINIT:
-	case MAN_LINKGOOD:
-		newstate = MAN_LINKSTALE;
-		mdp->md_linkstales++;
-		mdp->md_linkstale_retries =
-		    mdp->md_msp->ms_manp->man_linkstale_retries;
-		break;
-
-	case MAN_LINKSTALE:
-	case MAN_LINKFAIL:
-		mdp->md_linkstales++;
-		mdp->md_linkstale_retries--;
-		if (mdp->md_linkstale_retries < 0) {
-			newstate = MAN_LINKFAIL;
-			mdp->md_linkfails++;
-			mdp->md_linkstale_retries =
-			    mdp->md_msp->ms_manp->man_linkstale_retries;
-			/*
-			 * Mark the destination as FAILED and
-			 * update lru.
-			 */
-			if (oldstate != MAN_LINKFAIL) {
-				mp->mp_device.mdev_state |= MDEV_FAILED;
-				(void) drv_getparm(TIME, &mp->mp_lru);
-			}
-		}
-		break;
-
-	default:
-		cmn_err(CE_WARN, "man_linkcheck_timer: illegal link"
-		    " state %d", oldstate);
-		break;
-	}
-done:
-
-	if (oldstate != newstate) {
-
-		MAN_DBG(MAN_LINK, ("man_linkcheck_timer"
-		    " link state %s -> %s", lss[oldstate],
-		    lss[newstate]));
-
-		mdp->md_linkstate = newstate;
-	}
-
-	/*
-	 * Do any work required from state transitions above.
-	 */
-	if (newstate == MAN_LINKFAIL) {
-do_switch:
-		if (!man_do_autoswitch(mdp)) {
-			/*
-			 * Stop linkcheck timer until switch completes.
-			 */
-			restart_timer = FALSE;
-			send_ping = FALSE;
-		}
-	}
-
-	mutex_exit(&man_lock);
-	if (send_ping)
-		man_do_icmp_bcast(mdp, mdp->md_msp->ms_sap);
-
-	if (restart_timer)
-		mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
-		    (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
-
-exit:
-	MAN_DBG(MAN_LINK, ("man_linkcheck_timer: returns"));
-
-}
-
-/*
- * Handle linkcheck initiated autoswitching.
- * Called with man_lock held.
- */
-static int
-man_do_autoswitch(man_dest_t *mdp)
-{
-	man_pg_t	*mpg;
-	man_path_t	*ap;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	/*
-	 * Set flags and refcnt. Cleared in man_iswitch when SWITCH completes.
-	 */
-	mdp->md_msp->ms_manp->man_refcnt++;
-
-	mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg, mdp->md_pg_id);
-	ASSERT(mpg);
-
-	if (mpg->mpg_flags & MAN_PG_SWITCHING)
-		return (EBUSY);
-
-	mpg->mpg_flags |= MAN_PG_SWITCHING;
-
-	if (mdp->md_state == MAN_DSTATE_INITIALIZING) {
-		/*
-		 * We're initializing, ask for a switch to our currently
-		 * active device.
-		 */
-		status = man_autoswitch(mpg, &mdp->md_device, NULL);
-	} else {
-
-		if (mdp->md_msp != NULL && mdp->md_msp->ms_manp != NULL &&
-		    mdp->md_link_updown_msg == MAN_LINK_UP_MSG) {
-
-			man_t *manp = mdp->md_msp->ms_manp;
-
-			cmn_err(CE_NOTE, "%s%d Link down",
-			    ddi_major_to_name(manp->man_meta_major),
-			    manp->man_meta_ppa);
-		}
-		mdp->md_link_updown_msg = MAN_LINK_DOWN_MSG;
-
-		MAN_DBG(MAN_LINK, ("man_linkcheck_timer: link failure on %s%d",
-		    ddi_major_to_name(mdp->md_device.mdev_major),
-		    mdp->md_device.mdev_ppa));
-
-		ap = man_find_alternate_path(mpg->mpg_pathp);
-
-		if (ap == NULL) {
-			status = ENODEV;
-			goto exit;
-		}
-		status = man_autoswitch(mpg, &ap->mp_device, NULL);
-	}
-exit:
-	if (status != 0) {
-		/*
-		 * man_iswitch not going to run, clean up.
-		 */
-		mpg->mpg_flags &= ~MAN_PG_SWITCHING;
-		mdp->md_msp->ms_manp->man_refcnt--;
-	}
-
-	return (status);
-}
-
-/*
- * Gather up all lower multiplexor streams that have this link open and
- * try to switch them. Called from inner perimeter and holding man_lock.
- *
- *	pg_id		- Pathgroup to do switch for.
- *	st_devp		- New device to switch to.
- *	wait_for_switch	- whether or not to qwait for completion.
- */
-static int
-man_autoswitch(man_pg_t *mpg, man_dev_t *st_devp, man_work_t *waiter_wp)
-{
-	man_work_t	*wp;
-	int		sdp_cnt = 0;
-	man_dest_t	*sdp;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	if (waiter_wp == NULL) {
-		wp = man_work_alloc(MAN_WORK_SWITCH, KM_NOSLEEP);
-		if (wp == NULL) {
-			status = ENOMEM;
-			goto exit;
-		}
-	} else {
-		ASSERT(waiter_wp->mw_type == MAN_WORK_SWITCH);
-		wp = waiter_wp;
-	}
-
-	/*
-	 * Set dests as PLUMBING, cancel timers and return array of dests
-	 * that need a switch.
-	 */
-	status = man_prep_dests_for_switch(mpg, &sdp, &sdp_cnt);
-	if (status) {
-		if (waiter_wp == NULL)
-			man_work_free(wp);
-		goto exit;
-	}
-
-	/*
-	 * If no streams are active, there are no streams to switch.
-	 * Return ENODEV (see man_pg_activate).
-	 */
-	if (sdp_cnt == 0) {
-		if (waiter_wp == NULL)
-			man_work_free(wp);
-		status = ENODEV;
-		goto exit;
-	}
-
-	/*
-	 * Ask the bgthread to switch. See man_bwork.
-	 */
-	wp->mw_arg.a_sf_dev = sdp->md_device;
-	wp->mw_arg.a_st_dev = *st_devp;
-	wp->mw_arg.a_pg_id = mpg->mpg_pg_id;
-	wp->mw_arg.a_man_ppa = mpg->mpg_man_ppa;
-
-	wp->mw_arg.a_mdp = sdp;
-	wp->mw_arg.a_ndests = sdp_cnt;
-	man_work_add(man_bwork_q, wp);
-
-exit:
-
-	return (status);
-}
-
-/*
- * If an alternate path exists for pathgroup, arrange for switch to
- * happen. Note that we need to switch each of msp->dests[pg_id], for
- * all on man_strup. We must:
- *
- *		Cancel any timers
- *		Mark dests as PLUMBING
- *		Submit switch request to man_bwork_q->
- */
-static int
-man_prep_dests_for_switch(man_pg_t *mpg, man_dest_t **mdpp, int *cntp)
-{
-	manstr_t	*msp;
-	man_dest_t	*mdp;
-	int		sdp_cnt = 0;
-	man_dest_t	*sdp = NULL;
-	man_dest_t	*tdp;
-	int		status = 0;
-
-	MAN_DBG(MAN_SWITCH, ("man_prep_dests_for_switch: pg_id %d",
-	    mpg->mpg_pg_id));
-
-	/*
-	 * Count up number of streams, there is one destination that needs
-	 * switching per stream.
-	 */
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-		if (man_str_uses_pg(msp, mpg))
-			sdp_cnt++;
-	}
-
-	if (sdp_cnt == 0)
-		goto exit;
-
-	sdp = man_kzalloc(sizeof (man_dest_t) * sdp_cnt, KM_NOSLEEP);
-	if (sdp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-	tdp = sdp;
-	/*
-	 * Mark each destination as unusable.
-	 */
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-		if (man_str_uses_pg(msp, mpg)) {
-
-			/*
-			 * Mark destination as plumbing and store the
-			 * address of sdp as a way to identify the
-			 * SWITCH request when it comes back (see man_iswitch).
-			 */
-			mdp = &msp->ms_dests[mpg->mpg_pg_id];
-			mdp->md_state |= MAN_DSTATE_PLUMBING;
-			mdp->md_switch_id = sdp;
-
-			/*
-			 * Copy destination info.
-			 */
-			bcopy(mdp, tdp, sizeof (man_dest_t));
-			tdp++;
-
-			/*
-			 * Cancel timers.
-			 */
-			if (mdp->md_lc_timer_id) {
-				(void) quntimeout(man_ctl_wq,
-				    mdp->md_lc_timer_id);
-				mdp->md_lc_timer_id = 0;
-			}
-			if (mdp->md_bc_id) {
-				qunbufcall(man_ctl_wq, mdp->md_bc_id);
-				mdp->md_bc_id = 0;
-			}
-		}
-	}
-
-	*mdpp = sdp;
-	*cntp = sdp_cnt;
-	status = 0;
-exit:
-
-	MAN_DBG(MAN_SWITCH, ("man_prep_dests_for_switch: returns %d"
-	    " sdp(0x%p) sdp_cnt(%d)", status, (void *)sdp, sdp_cnt));
-
-	return (status);
-
-}
-
-/*
- * The code below generates an ICMP echo packet and sends it to the
- * broadcast address in the hopes that the other end will respond
- * and the man_linkcheck_timer logic will see the traffic.
- *
- * This assumes ethernet-like media.
- */
-/*
- * Generate an ICMP packet. Called exclusive inner perimeter.
- *
- *	mdp - destination to send packet to.
- *	sap - either ETHERTYPE_ARP or ETHERTYPE_IPV6
- */
-static void
-man_do_icmp_bcast(man_dest_t *mdp, t_uscalar_t sap)
-{
-	mblk_t			*mp = NULL;
-
-	/* TBD - merge pinger and this routine. */
-
-	ASSERT(sap == ETHERTYPE_IPV6 || sap == ETHERTYPE_IP);
-
-	if (sap == ETHERTYPE_IPV6) {
-		mdp->md_icmpv6probes++;
-	} else {
-		mdp->md_icmpv4probes++;
-	}
-	/*
-	 * Send the ICMP message
-	 */
-	mp = man_pinger(sap);
-
-	MAN_DBG(MAN_LINK, ("man_do_icmp_bcast: sap=0x%x mp=0x%p",
-	    sap, (void *)mp));
-	if (mp == NULL)
-		return;
-
-	/*
-	 * Send it out.
-	 */
-	if (man_start_lower(mdp, mp, NULL, MAN_LOWER)) {
-
-		MAN_DBG(MAN_LINK, ("man_do_icmp_broadcast: xmit failed"));
-
-		freemsg(mp);
-	}
-
-}
-
-static mblk_t *
-man_pinger(t_uscalar_t sap)
-{
-	mblk_t		*mp = NULL;
-	man_dladdr_t	dlsap;
-	icmph_t		*icmph;
-	int		ipver;
-	ipha_t		*ipha;
-	ip6_t		*ip6h;
-	int		iph_hdr_len;
-	int		datalen = 64;
-	uchar_t		*datap;
-	uint16_t	size;
-	uchar_t		i;
-
-	dlsap.dl_sap = htons(sap);
-	bcopy(&etherbroadcast, &dlsap.dl_phys, sizeof (dlsap.dl_phys));
-
-	if (sap == ETHERTYPE_IPV6) {
-		ipver = IPV6_VERSION;
-		iph_hdr_len = sizeof (ip6_t);
-		size = ICMP6_MINLEN;
-	} else {
-		ipver = IPV4_VERSION;
-		iph_hdr_len = sizeof (ipha_t);
-		size = ICMPH_SIZE;
-	}
-	size += (uint16_t)iph_hdr_len;
-	size += datalen;
-
-	mp = man_alloc_udreq(size, &dlsap);
-	if (mp == NULL)
-		goto exit;
-
-	/*
-	 * fill out the ICMP echo packet headers
-	 */
-	mp->b_cont->b_wptr += iph_hdr_len;
-	if (ipver == IPV4_VERSION) {
-		ipha = (ipha_t *)mp->b_cont->b_rptr;
-		ipha->ipha_version_and_hdr_length = (IP_VERSION << 4)
-		    | IP_SIMPLE_HDR_LENGTH_IN_WORDS;
-		ipha->ipha_type_of_service = 0;
-		ipha->ipha_length = size;
-		ipha->ipha_fragment_offset_and_flags = IPH_DF;
-		ipha->ipha_ttl = 1;
-		ipha->ipha_protocol = IPPROTO_ICMP;
-		if (man_is_on_domain) {
-			manc_t		manc;
-
-			if (man_get_iosram(&manc)) {
-				freemsg(mp);
-				mp = NULL;
-				goto exit;
-			}
-
-			/*
-			 * Domain generates ping packets for domain to
-			 * SC network (dman0 <--> scman0).
-			 */
-			ipha->ipha_dst = manc.manc_sc_ipaddr;
-			ipha->ipha_src = manc.manc_dom_ipaddr;
-		} else {
-			/*
-			 * Note that ping packets are only generated
-			 * by the SC across scman1 (SC to SC network).
-			 */
-			ipha->ipha_dst = man_sc_ipaddrs.ip_other_sc_ipaddr;
-			ipha->ipha_src = man_sc_ipaddrs.ip_my_sc_ipaddr;
-		}
-
-		ipha->ipha_ident = 0;
-
-		ipha->ipha_hdr_checksum = 0;
-		ipha->ipha_hdr_checksum = IP_CSUM(mp->b_cont, 0, 0);
-
-	} else {
-		ip6h = (ip6_t *)mp->b_cont->b_rptr;
-		/*
-		 * IP version = 6, priority = 0, flow = 0
-		 */
-		ip6h->ip6_flow = (IPV6_VERSION << 28);
-		ip6h->ip6_plen =
-		    htons((short)(size - iph_hdr_len));
-		ip6h->ip6_nxt = IPPROTO_ICMPV6;
-		ip6h->ip6_hlim = 1;	/* stay on link */
-
-		if (man_is_on_domain) {
-			manc_t		manc;
-
-			if (man_get_iosram(&manc)) {
-				freemsg(mp);
-				mp = NULL;
-				goto exit;
-			}
-
-			/*
-			 * Domain generates ping packets for domain to
-			 * SC network (dman0 <--> scman0).
-			 */
-			ip6h->ip6_src = manc.manc_dom_ipv6addr;
-			ip6h->ip6_dst = manc.manc_sc_ipv6addr;
-		} else {
-			/*
-			 * Note that ping packets are only generated
-			 * by the SC across scman1 (SC to SC network).
-			 */
-			ip6h->ip6_src = man_sc_ip6addrs.ip6_my_sc_ipaddr;
-			ip6h->ip6_dst = man_sc_ip6addrs.ip6_other_sc_ipaddr;
-		}
-	}
-
-	/*
-	 * IPv6 and IP are the same for ICMP as far as I'm concerned.
-	 */
-	icmph = (icmph_t *)mp->b_cont->b_wptr;
-	if (ipver == IPV4_VERSION) {
-		mp->b_cont->b_wptr += ICMPH_SIZE;
-		icmph->icmph_type = ICMP_ECHO_REQUEST;
-		icmph->icmph_code = 0;
-	} else {
-		mp->b_cont->b_wptr += ICMP6_MINLEN;
-		icmph->icmph_type = ICMP6_ECHO_REQUEST;
-		icmph->icmph_code = 0;
-	}
-
-	datap = mp->b_cont->b_wptr;
-	mp->b_cont->b_wptr += datalen;
-
-	for (i = 0; i < datalen; i++)
-		*datap++ = i;
-
-	if (ipver == IPV4_VERSION) {
-		icmph->icmph_checksum = IP_CSUM(mp->b_cont, iph_hdr_len, 0);
-	} else {
-		uint32_t	sum;
-
-		sum = htons(IPPROTO_ICMPV6) + ip6h->ip6_plen;
-		icmph->icmph_checksum = IP_CSUM(mp->b_cont, iph_hdr_len - 32,
-		    (sum & 0xffff) + (sum >> 16));
-	}
-
-/*
- * TBD
- *	icp->icmp_time =  ???;
- */
-
-exit:
-	return (mp);
-}
-
-static mblk_t *
-man_alloc_udreq(int size, man_dladdr_t *dlsap)
-{
-	dl_unitdata_req_t	*udreq;
-	mblk_t			*bp;
-	mblk_t			*mp;
-
-	mp = allocb(sizeof (dl_unitdata_req_t) + sizeof (*dlsap), BPRI_MED);
-
-	if (mp == NULL) {
-		cmn_err(CE_NOTE, "man_preparepkt: allocb failed");
-		return (NULL);
-	}
-
-	if ((bp = allocb(size, BPRI_MED)) == NULL) {
-		freemsg(mp);
-		cmn_err(CE_NOTE, "man_preparepkts: allocb failed");
-		return (NULL);
-	}
-	bzero(bp->b_rptr, size);
-
-	mp->b_cont = bp;
-	mp->b_datap->db_type = M_PROTO;
-	udreq = (dl_unitdata_req_t *)mp->b_wptr;
-	mp->b_wptr += sizeof (dl_unitdata_req_t);
-
-	/*
-	 * phys addr first - TBD
-	 */
-	bcopy((char *)dlsap, mp->b_wptr, sizeof (*dlsap));
-	mp->b_wptr += sizeof (*dlsap);
-
-	udreq->dl_primitive = DL_UNITDATA_REQ;
-	udreq->dl_dest_addr_length = sizeof (*dlsap);
-	udreq->dl_dest_addr_offset = sizeof (*udreq);
-	udreq->dl_priority.dl_min = 0;
-	udreq->dl_priority.dl_max = 0;
-
-	return (mp);
-}
-
-
-/*
- * The routines in this file are executed by the MAN background thread,
- * which executes outside of the STREAMS framework (see man_str.c). It is
- * allowed to do the things required to modify the STREAMS driver (things
- * that are normally done from a user process). These routines do things like
- * open and close drivers, PLINK and PUNLINK streams to/from the multiplexor,
- * etc.
- *
- * The mechanism of communication between the STREAMS portion of the driver
- * and the background thread portion are two work queues, man_bwork_q
- * and man_iwork_q (background work q and streams work q).  Work
- * requests are placed on those queues when one half of the driver wants
- * the other half to do some work for it.
- *
- * The MAN background thread executes the man_bwork routine. Its sole
- * job is to process work requests placed on this work q. The MAN upper
- * write service routine is responsible for processing work requests posted
- * to the man_iwork_q->
- *
- * Both work queues are protected by the global mutex man_lock. The
- * man_bwork is signalged via the condvarman_bwork_q->q_cv. The man_uwsrv
- * routine is signaled by calling qenable (forcing man_uwsrv to run).
- */
-
-/*
- * man_bwork - Work thread for this device.  It is responsible for
- * performing operations which can't occur within the STREAMS framework.
- *
- * Locking:
- *	- Called holding no locks
- *	- Obtains the global mutex man_lock to remove work from
- *	  man_bwork_q, and post work to man_iwork_q->
- *	- Note that we do not want to hold any locks when making
- *	  any ldi_ calls.
- */
-void
-man_bwork()
-{
-	man_work_t	*wp;
-	int		done = 0;
-	callb_cpr_t	cprinfo;
-	int		wp_finished;
-
-	CALLB_CPR_INIT(&cprinfo, &man_lock, callb_generic_cpr,
-	    "mn_work_thrd");
-
-	MAN_DBG(MAN_CONFIG, ("man_bwork: enter"));
-
-	while (done == 0) {
-
-		mutex_enter(&man_lock);
-		/*
-		 * While there is nothing to do, sit in cv_wait.  If work
-		 * request is made, requester will signal.
-		 */
-		while (man_bwork_q->q_work == NULL) {
-
-			CALLB_CPR_SAFE_BEGIN(&cprinfo);
-
-			cv_wait(&man_bwork_q->q_cv, &man_lock);
-
-			CALLB_CPR_SAFE_END(&cprinfo, &man_lock);
-		}
-
-		wp = man_bwork_q->q_work;
-		man_bwork_q->q_work = wp->mw_next;
-		wp->mw_next = NULL;
-		mutex_exit(&man_lock);
-
-		wp_finished = TRUE;
-
-		MAN_DBG(MAN_SWITCH, ("man_bwork: type %s",
-		    _mw_type[wp->mw_type]));
-
-		switch (wp->mw_type) {
-		case MAN_WORK_OPEN_CTL:
-			wp->mw_status = man_open_ctl();
-			break;
-
-		case MAN_WORK_CLOSE_CTL:
-			man_close_ctl();
-			break;
-
-		case MAN_WORK_CLOSE:
-		case MAN_WORK_CLOSE_STREAM:
-			man_bclose(&wp->mw_arg);
-			break;
-
-		case MAN_WORK_SWITCH:
-			man_bswitch(&wp->mw_arg, wp);
-			wp_finished = FALSE;
-			break;
-
-		case MAN_WORK_STOP:		/* man_bwork_stop() */
-			done = 1;
-			mutex_enter(&man_lock);
-			CALLB_CPR_EXIT(&cprinfo); /* Unlocks man_lock */
-			break;
-
-		default:
-			cmn_err(CE_WARN, "man_bwork: "
-			    "illegal work type(%d)", wp->mw_type);
-			break;
-		}
-
-		mutex_enter(&man_lock);
-
-		if (wp_finished) {
-			wp->mw_flags |= MAN_WFLAGS_DONE;
-			if (wp->mw_flags & MAN_WFLAGS_CVWAITER)
-				cv_signal(&wp->mw_cv);
-			else if (wp->mw_flags & MAN_WFLAGS_QWAITER)
-				qenable(wp->mw_q);
-			else
-				man_work_free(wp);
-		}
-
-		mutex_exit(&man_lock);
-	}
-
-	MAN_DBG(MAN_CONFIG, ("man_bwork: thread_exit"));
-
-	mutex_enter(&man_lock);
-	man_bwork_id = NULL;
-	mutex_exit(&man_lock);
-
-	thread_exit();
-}
-
-/*
- * man_open_ctl - Open the control stream.
- *
- *	returns	- success - 0
- *		- failure - errno code
- *
- * Mutex Locking Notes:
- *	We need a way to keep the CLONE_OPEN qwaiters in man_open from
- *	checking the man_config variables after the ldi_open call below
- *	returns from man_open, leaving the inner perimeter. So, we use the
- *	man_lock to synchronize the threads in man_open_ctl and man_open.  We
- *	hold man_lock across this call into man_open, which in general is a
- *	no-no. But, the STREAMs portion of the driver (other than open)
- *	doesn't use it. So, if ldi_open gets hijacked to run any part of
- *	the MAN streams driver, it wont end up recursively trying to acquire
- *	man_lock. Note that the non-CLONE_OPEN portion of man_open doesnt
- *	acquire it either, so again no recursive mutex.
- */
-static int
-man_open_ctl()
-{
-	int		status = 0;
-	ldi_handle_t	ctl_lh = NULL;
-	ldi_ident_t	li = NULL;
-
-	MAN_DBG(MAN_CONFIG, ("man_open_ctl: plumbing control stream\n"));
-
-	/*
-	 * Get eri driver loaded and kstats initialized. Is there a better
-	 * way to do this? - TBD.
-	 */
-	status = ldi_ident_from_mod(&modlinkage, &li);
-	if (status) {
-		cmn_err(CE_WARN,
-		    "man_open_ctl: ident alloc failed, error %d", status);
-		goto exit;
-	}
-
-	status = ldi_open_by_name(ERI_PATH, FREAD | FWRITE | FNOCTTY,
-	    kcred, &ctl_lh, li);
-	if (status) {
-		cmn_err(CE_WARN,
-		    "man_open_ctl: eri open failed, error %d", status);
-		ctl_lh = NULL;
-		goto exit;
-	}
-	(void) ldi_close(ctl_lh, NULL, kcred);
-	ctl_lh = NULL;
-
-	mutex_enter(&man_lock);
-
-	if (man_ctl_lh != NULL) {
-		mutex_exit(&man_lock);
-		goto exit;
-	}
-
-	ASSERT(man_ctl_wq == NULL);
-	mutex_exit(&man_lock);
-
-	status = ldi_open_by_name(DMAN_INT_PATH, FREAD | FWRITE | FNOCTTY,
-	    kcred, &ctl_lh, li);
-	if (status) {
-		cmn_err(CE_WARN,
-		    "man_open_ctl: man control dev open failed, "
-		    "error %d", status);
-		goto exit;
-	}
-
-	/*
-	 * Update global config state. TBD - dont need lock here, since
-	 * everyone is stuck in open until we finish. Only other modifier
-	 * is man_deconfigure via _fini, which returns EBUSY if there is
-	 * any open streams (other than control). Do need to signal qwaiters
-	 * on error.
-	 */
-	mutex_enter(&man_lock);
-	ASSERT(man_config_state == MAN_CONFIGURING);
-	ASSERT(man_ctl_lh == NULL);
-	man_ctl_lh = ctl_lh;
-	mutex_exit(&man_lock);
-
-exit:
-	if (li)
-		ldi_ident_release(li);
-
-	MAN_DBG(MAN_CONFIG, ("man_open_ctl: man_ctl_lh(0x%p) errno = %d\n",
-	    (void *)man_ctl_lh, status));
-
-	return (status);
-}
-
-/*
- * man_close_ctl - Close control stream, we are about to unload driver.
- *
- * Locking:
- *	- Called holding no locks.
- */
-static void
-man_close_ctl()
-{
-	ldi_handle_t tlh;
-
-	MAN_DBG(MAN_CONFIG, ("man_close_ctl: unplumbing control stream\n"));
-
-	mutex_enter(&man_lock);
-	if ((tlh = man_ctl_lh) != NULL)
-		man_ctl_lh = NULL;
-	mutex_exit(&man_lock);
-
-	if (tlh != NULL) {
-		(void) ldi_close(tlh, NULL, kcred);
-	}
-
-}
-
-/*
- * Close the lower streams. Get all the timers canceled, close the lower
- * stream and delete the dest array.
- *
- * Returns:
- *	0	Closed all streams.
- *	1	Couldn't close one or more streams, timers still running.
- *
- * Locking:
- *	- Called holding no locks.
- */
-static void
-man_bclose(man_adest_t *adp)
-{
-	int		i;
-	man_dest_t	*mdp;
-
-	man_cancel_timers(adp);
-
-	for (i = 0; i < adp->a_ndests; i++) {
-		mdp = &adp->a_mdp[i];
-
-		if (mdp->md_muxid != -1)
-			man_unplumb(mdp);
-	}
-
-	mutex_destroy(&mdp->md_lock);
-	man_kfree(adp->a_mdp, sizeof (man_dest_t) * adp->a_ndests);
-	adp->a_mdp = NULL;
-}
-
-/*
- * We want to close down all lower streams. Need to wait until all
- * timers and work related to these lower streams is quiesced.
- *
- * Returns 1 if lower streams are quiesced, 0 if we need to wait
- * a bit longer.
- */
-static void
-man_cancel_timers(man_adest_t *adp)
-{
-	man_dest_t	*mdp;
-	int		cnt;
-	int		i;
-
-	mdp = adp->a_mdp;
-	cnt = adp->a_ndests;
-
-	MAN_DBG(MAN_SWITCH, ("man_cancel_timers: mdp(0x%p) cnt %d",
-	    (void *)mdp, cnt));
-
-	for (i = 0; i < cnt; i++) {
-
-		if (mdp[i].md_lc_timer_id != 0) {
-			(void) quntimeout(man_ctl_wq, mdp[i].md_lc_timer_id);
-			mdp[i].md_lc_timer_id = 0;
-		}
-
-		if (mdp[i].md_bc_id != 0) {
-			qunbufcall(man_ctl_wq, mdp[i].md_bc_id);
-			mdp[i].md_bc_id = 0;
-		}
-	}
-
-	MAN_DBG(MAN_SWITCH, ("man_cancel_timers: returns"));
-}
-
-/*
- * A failover is started at start of day, when the driver detects a
- * link failure (see man_linkcheck_timer), or when DR detaches
- * the IO board containing the current active link between SC and
- * domain (see man_dr_detach, man_iwork, and man_do_dr_detach). A
- * MAN_WORK_SWITCH work request containing all the lower streams that
- * should be switched is posted on the man_bwork_q-> This work request is
- * processed here. Once all lower streams have been switched to an
- * alternate path, the MAN_WORK_SWITCH work request is passed back to
- * man_iwork_q where it is processed within the inner perimeter of the
- * STREAMS framework (see man_iswitch).
- *
- * Note that when the switch fails for whatever reason, we just hand
- * back the lower streams untouched and let another failover happen.
- * Hopefully we will sooner or later succeed at the failover.
- */
-static void
-man_bswitch(man_adest_t *adp, man_work_t *wp)
-{
-	man_dest_t	*tdp;
-	man_t		*manp;
-	int		i;
-	int		status = 0;
-
-	/*
-	 * Make a temporary copy of dest array, updating device to the
-	 * alternate and try to open all lower streams. bgthread can sleep.
-	 */
-
-	tdp = man_kzalloc(sizeof (man_dest_t) * adp->a_ndests,
-	    KM_SLEEP);
-	bcopy(adp->a_mdp, tdp, sizeof (man_dest_t) * adp->a_ndests);
-
-	/*
-	 * Before we switch to the new path, lets sync the kstats.
-	 */
-	mutex_enter(&man_lock);
-
-	manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
-	if (manp != NULL) {
-		man_update_path_kstats(manp);
-	} else
-		status = ENODEV;
-
-	mutex_exit(&man_lock);
-
-	if (status != 0)
-		goto exit;
-
-	for (i = 0; i < adp->a_ndests; i++) {
-
-		tdp[i].md_device = adp->a_st_dev;
-		tdp[i].md_muxid = -1;
-
-		if (man_plumb(&tdp[i]))
-			break;
-	}
-
-	/*
-	 * Didn't plumb everyone, unplumb new lower stuff and return.
-	 */
-	if (i < adp->a_ndests) {
-		int	j;
-
-		for (j = 0; j <= i; j++)
-			man_unplumb(&tdp[j]);
-		status = EAGAIN;
-		goto exit;
-	}
-
-	if (man_is_on_domain && man_dossc_switch(adp->a_st_dev.mdev_exp_id)) {
-		/*
-		 * If we cant set new path on the SSC, then fail the
-		 * failover.
-		 */
-		for (i = 0; i < adp->a_ndests; i++)
-			man_unplumb(&tdp[i]);
-		status = EAGAIN;
-		goto exit;
-	}
-
-	man_kfree(adp->a_mdp, sizeof (man_dest_t) * adp->a_ndests);
-	adp->a_mdp = tdp;
-
-exit:
-	if (status)
-		man_kfree(tdp, sizeof (man_dest_t) * adp->a_ndests);
-
-
-	MAN_DBG(MAN_SWITCH, ("man_bswitch: returns %d", status));
-
-	/*
-	 * Hand processed switch request back to man_iwork for
-	 * processing in man_iswitch.
-	 */
-	wp->mw_status = status;
-
-	mutex_enter(&man_lock);
-	man_work_add(man_iwork_q, wp);
-	mutex_exit(&man_lock);
-
-}
-
-/*
- * man_plumb - Configure a lower stream for this destination.
- *
- * Locking:
- * 	- Called holding no locks.
- *
- * Returns:
- *	- success - 0
- *	- failure - error code of failure
- */
-static int
-man_plumb(man_dest_t *mdp)
-{
-	int		status;
-	int		muxid;
-	ldi_handle_t	lh;
-	ldi_ident_t	li = NULL;
-
-	MAN_DBG(MAN_SWITCH, ("man_plumb: mdp(0x%p) %s%d exp(%d)",
-	    (void *)mdp, ddi_major_to_name(mdp->md_device.mdev_major),
-	    mdp->md_device.mdev_ppa, mdp->md_device.mdev_exp_id));
-
-	/*
-	 * Control stream should already be open.
-	 */
-	if (man_ctl_lh == NULL) {
-		status = EAGAIN;
-		goto exit;
-	}
-
-	mutex_enter(&man_lock);
-	ASSERT(man_ctl_wq != NULL);
-	status = ldi_ident_from_stream(man_ctl_wq, &li);
-	if (status != 0) {
-		cmn_err(CE_WARN,
-		    "man_plumb: ident alloc failed, error %d", status);
-		goto exit;
-	}
-	mutex_exit(&man_lock);
-
-	/*
-	 * previously opens were done by a dev_t of makedev(clone_major,
-	 * mdev_major) which should always map to /devices/pseudo/clone@0:eri
-	 */
-	ASSERT(strcmp(ERI_IDNAME,
-	    ddi_major_to_name(mdp->md_device.mdev_major)) == 0);
-
-	status = ldi_open_by_name(ERI_PATH, FREAD | FWRITE | FNOCTTY,
-	    kcred, &lh, li);
-	if (status) {
-		cmn_err(CE_WARN,
-		    "man_plumb: eri open failed, error %d", status);
-		goto exit;
-	}
-
-	/*
-	 * Link netdev under MAN.
-	 */
-	ASSERT(mdp->md_muxid == -1);
-
-	status = ldi_ioctl(man_ctl_lh, I_PLINK, (intptr_t)lh,
-	    FREAD+FWRITE+FNOCTTY+FKIOCTL, kcred, &muxid);
-	if (status) {
-		cmn_err(CE_WARN,
-		    "man_plumb: ldi_ioctl(I_PLINK) failed, error %d", status);
-		(void) ldi_close(lh, NULL, kcred);
-		goto exit;
-
-	}
-	mdp->md_muxid = muxid;
-	mdp->md_wq = man_linkrec_find(muxid);
-	/*
-	 * If we can't find the linkrec then return an
-	 * error. It will be automatically unplumbed on failure.
-	 */
-	if (mdp->md_wq == NULL)
-		status = EAGAIN;
-
-	(void) ldi_close(lh, NULL, kcred);
-exit:
-	if (li)
-		ldi_ident_release(li);
-
-	MAN_DBG(MAN_SWITCH, ("man_plumb: exit\n"));
-
-	return (status);
-}
-
-/*
- * man_unplumb - tear down the STREAMs framework for the lower multiplexor.
- *
- *	mdp - destination struct of interest
- *
- *	returns	- success - 0
- *		- failure - return error from ldi_ioctl
- */
-static void
-man_unplumb(man_dest_t *mdp)
-{
-	int	status, rval;
-
-	MAN_DBG(MAN_SWITCH, ("man_unplumb: mdp"));
-	MAN_DBGCALL(MAN_SWITCH, man_print_mdp(mdp));
-
-	if (mdp->md_muxid == -1)
-		return;
-
-	ASSERT(man_ctl_lh != NULL);
-
-	/*
-	 * I_PUNLINK causes the multiplexor resources to be freed.
-	 */
-	status = ldi_ioctl(man_ctl_lh, I_PUNLINK, (intptr_t)mdp->md_muxid,
-	    FREAD+FWRITE+FNOCTTY+FKIOCTL, kcred, &rval);
-	if (status) {
-		cmn_err(CE_WARN, "man_unplumb: ldi_ioctl(I_PUNLINK) failed"
-		    " errno %d\n", status);
-	}
-	/*
-	 * Delete linkrec if it exists.
-	 */
-	(void) man_linkrec_find(mdp->md_muxid);
-	mdp->md_muxid = -1;
-
-}
-
-/*
- * The routines below deal with paths and pathgroups. These data structures
- * are used to track the physical devices connecting the domain and SSC.
- * These devices make up the lower streams of the MAN multiplexor. The
- * routines all expect the man_lock to be held.
- *
- * A pathgroup consists of all paths that connect a particular domain and the
- * SSC. The concept of a pathgroup id (pg_id) is used to uniquely identify
- * a pathgroup.  For Domains, there is just one pathgroup, that connecting
- * the domain to the SSC (pg_id == 0). On the SSC, there is one pathgroup per
- * domain. The pg_id field corresponds to the domain tags A-R. A pg_id of
- * 0 means domain tag A, a pg_id of 1 means domain B, etc.
- *
- * The path data structure identifies one path between the SSC and a domain.
- * It describes the information for the path: the major and minor number of
- * the physical device; kstat pointers; and ethernet address of the
- * other end of the path.
- *
- * The pathgroups are anchored at man_pg_head and are protected by the
- * by the inner perimeter. The routines are only called by the STREAMs
- * portion of the driver.
- */
-
-/*
- * Update man instance pathgroup info. Exclusive inner perimeter assures
- * this code is single threaded. man_refcnt assures man_t wont detach
- * while we are playing with man_pg stuff.
- *
- * Returns 0 on success, errno on failure.
- */
-int
-man_pg_cmd(mi_path_t *mip, man_work_t *waiter_wp)
-{
-	int		status = 0;
-	man_t		*manp;
-
-	if (mip->mip_ndevs < 0) {
-		status = EINVAL;
-		cmn_err(CE_WARN, "man_pg_cmd: EINVAL: mip_ndevs %d",
-		    mip->mip_ndevs);
-		goto exit;
-	}
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	manp = ddi_get_soft_state(man_softstate, mip->mip_man_ppa);
-	if (manp == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	MAN_DBG(MAN_PATH, ("man_pg_cmd: mip"));
-	MAN_DBGCALL(MAN_PATH, man_print_mip(mip));
-
-	MAN_DBG(MAN_PATH, ("\tman_t"));
-	MAN_DBGCALL(MAN_PATH, man_print_man(manp));
-
-	switch (mip->mip_cmd) {
-	case MI_PATH_ASSIGN:
-		status = man_pg_assign(&manp->man_pg, mip, FALSE);
-		break;
-
-	case MI_PATH_ADD:
-		status = man_pg_assign(&manp->man_pg, mip, TRUE);
-		break;
-
-	case MI_PATH_UNASSIGN:
-		status = man_pg_unassign(&manp->man_pg, mip);
-		break;
-
-	case MI_PATH_ACTIVATE:
-		status = man_pg_activate(manp, mip, waiter_wp);
-		break;
-
-	case MI_PATH_READ:
-		status = man_pg_read(manp->man_pg, mip);
-		break;
-
-	default:
-		status = EINVAL;
-		cmn_err(CE_NOTE, "man_pg_cmd: invalid command");
-		break;
-	}
-
-exit:
-	MAN_DBG(MAN_PATH, ("man_pg_cmd: returns %d", status));
-
-	return (status);
-}
-
-/*
- * Assign paths to a pathgroup. If pathgroup doesnt exists, create it.
- * If path doesnt exist, create it. If ethernet address of existing
- * pathgroup different, change it. If an existing path is not in the new
- * list, remove it.  If anything changed, send PATH_UPDATE request to
- * man_iwork to update all man_dest_t's.
- *
- * 	mplpp	- man pathgroup list point to point.
- *	mip	- new/updated pathgroup info to assign.
- */
-static int
-man_pg_assign(man_pg_t **mplpp, mi_path_t *mip, int add_only)
-{
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-	man_path_t	*add_paths = NULL;
-	int		cnt;
-	int		i;
-	int		first_pass = TRUE;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-
-	cnt = mip->mip_ndevs;
-	if (cnt == 0) {
-		status = EINVAL;
-		cmn_err(CE_NOTE, "man_pg_assign: mip_ndevs == 0");
-		goto exit;
-	}
-
-	/*
-	 * Assure the devices to be assigned are not assigned to some other
-	 * pathgroup.
-	 */
-	for (i = 0; i < cnt; i++) {
-		mpg = man_find_path_by_dev(*mplpp, &mip->mip_devs[i], NULL);
-
-		if (mpg == NULL)
-			continue;
-
-		if ((mpg->mpg_man_ppa != mip->mip_man_ppa) ||
-		    (mpg->mpg_pg_id != mip->mip_pg_id)) {
-			/*
-			 * Already assigned to some other man instance
-			 * or pathgroup.
-			 */
-			status = EEXIST;
-			goto exit;
-		}
-	}
-
-	/*
-	 * Find pathgroup, or allocate new one if it doesnt exist and
-	 * add it to list at mplpp. Result is that mpg points to
-	 * pathgroup to modify.
-	 */
-	mpg = man_find_pg_by_id(*mplpp, mip->mip_pg_id);
-	if (mpg == NULL) {
-
-		status = man_pg_create(mplpp, &mpg, mip);
-		if (status)
-			goto exit;
-
-	} else if (ether_cmp(&mip->mip_eaddr, &mpg->mpg_dst_eaddr) != 0) {
-
-		cmn_err(CE_WARN, "man_pg_assign: ethernet address mismatch");
-		cmn_err(CE_CONT, "existing %s",
-		    ether_sprintf(&mpg->mpg_dst_eaddr));
-		cmn_err(CE_CONT, "new %s",
-		    ether_sprintf(&mip->mip_eaddr));
-
-		status = EINVAL;
-		goto exit;
-	}
-
-	/*
-	 * Create list of new paths to add to pathgroup.
-	 */
-	for (i = 0; i < cnt; i++) {
-
-		if (man_find_path_by_dev(*mplpp, &mip->mip_devs[i], NULL))
-			continue;	/* Already exists in this pathgroup */
-
-		mp = man_kzalloc(sizeof (man_path_t), KM_NOSLEEP);
-		if (mp == NULL) {
-			status = ENOMEM;
-			goto exit;
-		}
-
-		mp->mp_device = mip->mip_devs[i];
-		mp->mp_device.mdev_state = MDEV_ASSIGNED;
-
-		MAN_DBG(MAN_PATH, ("man_pg_assign: assigning mdp"));
-		MAN_DBGCALL(MAN_PATH, man_print_dev(&mp->mp_device));
-
-		status = man_path_kstat_init(mp);
-		if (status) {
-			man_kfree(mp, sizeof (man_path_t));
-			goto exit;
-		}
-
-		man_path_insert(&add_paths, mp);
-	}
-
-	/*
-	 * man_dr_attach passes only the path which is being DRd in.
-	 * So just add the path and don't worry about removing paths.
-	 */
-	if (add_only == TRUE)
-		goto exit;
-
-
-	/*
-	 * Check if any paths we want to remove are ACTIVE. If not,
-	 * do a second pass and remove them.
-	 */
-again:
-	mp = mpg->mpg_pathp;
-	while (mp != NULL) {
-		int		in_new_list;
-		man_path_t	*rp;
-
-		rp = NULL;
-		in_new_list = FALSE;
-
-		for (i = 0; i < cnt; i++) {
-			if (mp->mp_device.mdev_ppa ==
-			    mip->mip_devs[i].mdev_ppa) {
-
-				in_new_list = TRUE;
-				break;
-			}
-		}
-
-		if (!in_new_list) {
-			if (first_pass) {
-				if (mp->mp_device.mdev_state & MDEV_ACTIVE) {
-					status = EBUSY;
-					goto exit;
-				}
-			} else {
-				rp = mp;
-			}
-		}
-		mp = mp->mp_next;
-
-		if (rp != NULL)
-			man_path_remove(&mpg->mpg_pathp, rp);
-	}
-
-	if (first_pass == TRUE) {
-		first_pass = FALSE;
-		goto again;
-	}
-
-exit:
-	if (status == 0) {
-		if (add_paths)
-			man_path_merge(&mpg->mpg_pathp, add_paths);
-	} else {
-		while (add_paths != NULL) {
-			mp = add_paths;
-			add_paths = mp->mp_next;
-			mp->mp_next = NULL;
-
-			man_path_kstat_uninit(mp);
-			man_kfree(mp, sizeof (man_path_t));
-		}
-	}
-
-	return (status);
-}
-
-/*
- * Remove all paths from a pathgroup (domain shutdown). If there is an
- * active path in the group, shut down all destinations referencing it
- * first.
- */
-static int
-man_pg_unassign(man_pg_t **plpp, mi_path_t *mip)
-{
-	man_pg_t	*mpg;
-	man_pg_t	*tpg;
-	man_pg_t	*tppg;
-	man_path_t	*mp = NULL;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-
-	/*
-	 * Check for existence of pathgroup.
-	 */
-	if ((mpg = man_find_pg_by_id(*plpp, mip->mip_pg_id)) == NULL)
-		goto exit;
-
-	if (man_find_active_path(mpg->mpg_pathp) != NULL) {
-		status = man_remove_dests(mpg);
-		if (status)
-			goto exit;
-	}
-
-	/*
-	 * Free all the paths for this pathgroup.
-	 */
-	while (mpg->mpg_pathp) {
-		mp = mpg->mpg_pathp;
-		mpg->mpg_pathp = mp->mp_next;
-		mp->mp_next = NULL;
-
-		man_path_kstat_uninit(mp);
-		man_kfree(mp, sizeof (man_path_t));
-	}
-
-	/*
-	 * Remove this pathgroup from the list, and free it.
-	 */
-	tpg = tppg = *plpp;
-	if (tpg == mpg) {
-		*plpp = tpg->mpg_next;
-		goto free_pg;
-	}
-
-	for (tpg = tpg->mpg_next; tpg != NULL; tpg = tpg->mpg_next) {
-		if (tpg == mpg)
-			break;
-		tppg = tpg;
-	}
-
-	ASSERT(tpg != NULL);
-
-	tppg->mpg_next = tpg->mpg_next;
-	tpg->mpg_next = NULL;
-
-free_pg:
-	man_kfree(tpg, sizeof (man_pg_t));
-
-exit:
-	return (status);
-
-}
-
-/*
- * Set a new active path. This is done via man_ioctl so we are
- * exclusive in the inner perimeter.
- */
-static int
-man_pg_activate(man_t *manp, mi_path_t *mip, man_work_t *waiter_wp)
-{
-	man_pg_t	*mpg1;
-	man_pg_t	*mpg2;
-	man_pg_t	*plp;
-	man_path_t	*mp;
-	man_path_t	*ap;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	MAN_DBG(MAN_PATH, ("man_pg_activate: dev"));
-	MAN_DBGCALL(MAN_PATH, man_print_dev(mip->mip_devs));
-
-	if (mip->mip_ndevs != 1) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	plp = manp->man_pg;
-	mpg1 = man_find_pg_by_id(plp, mip->mip_pg_id);
-	if (mpg1 == NULL) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	mpg2 = man_find_path_by_dev(plp, mip->mip_devs, &mp);
-	if (mpg2 == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	if (mpg1 != mpg2) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	ASSERT(mp->mp_device.mdev_ppa == mip->mip_devs->mdev_ppa);
-
-	if (mpg1->mpg_flags & MAN_PG_SWITCHING) {
-		status = EAGAIN;
-		goto exit;
-	}
-
-	ap = man_find_active_path(mpg1->mpg_pathp);
-	if (ap == NULL) {
-		/*
-		 * This is the first time a path has been activated for
-		 * this pathgroup. Initialize all upper streams dest
-		 * structure for this pathgroup so autoswitch will find
-		 * them.
-		 */
-		mp->mp_device.mdev_state |= MDEV_ACTIVE;
-		man_add_dests(mpg1);
-		goto exit;
-	}
-
-	/*
-	 * Path already active, nothing to do.
-	 */
-	if (ap == mp)
-		goto exit;
-
-	/*
-	 * Try to autoswitch to requested device. Set flags and refcnt.
-	 * Cleared in man_iswitch when SWITCH completes.
-	 */
-	manp->man_refcnt++;
-	mpg1->mpg_flags |= MAN_PG_SWITCHING;
-
-	/*
-	 * Switch to path specified.
-	 */
-	status = man_autoswitch(mpg1, mip->mip_devs, waiter_wp);
-
-	if (status != 0) {
-		/*
-		 * man_iswitch not going to run, clean up.
-		 */
-		manp->man_refcnt--;
-		mpg1->mpg_flags &= ~MAN_PG_SWITCHING;
-
-		if (status == ENODEV) {
-			/*
-			 * Device not plumbed isn't really an error. Change
-			 * active device setting here, since man_iswitch isn't
-			 * going to be run to do it.
-			 */
-			status = 0;
-			ap->mp_device.mdev_state &= ~MDEV_ACTIVE;
-			mp->mp_device.mdev_state |= MDEV_ACTIVE;
-		}
-	}
-
-exit:
-	MAN_DBG(MAN_PATH, ("man_pg_activate: returns %d", status));
-
-	return (status);
-}
-
-static int
-man_pg_read(man_pg_t *plp, mi_path_t *mip)
-{
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-	int		cnt;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-
-	if ((mpg = man_find_pg_by_id(plp, mip->mip_pg_id)) == NULL) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	cnt = 0;
-	for (mp = mpg->mpg_pathp; mp != NULL; mp = mp->mp_next) {
-		bcopy(&mp->mp_device, &mip->mip_devs[cnt], sizeof (man_dev_t));
-		if (cnt == mip->mip_ndevs)
-			break;
-		cnt++;
-	}
-
-	MAN_DBG(MAN_PATH, ("man_pg_read: pg(0x%p) id(%d) found %d paths",
-	    (void *)mpg, mpg->mpg_pg_id, cnt));
-
-	mip->mip_ndevs = cnt;
-
-	/*
-	 * TBD - What should errno be if user buffer too small ?
-	 */
-	if (mp != NULL) {
-		status = ENOMEM;
-	}
-
-exit:
-
-	return (status);
-}
-
-/*
- * return existing pathgroup, or create it. TBD - Need to update
- * all of destinations if we added a pathgroup. Also, need to update
- * all of man_strup if we add a path.
- *
- * 	mplpp	- man pathgroup list point to pointer.
- * 	mpgp	- returns newly created man pathgroup.
- *	mip	- info to fill in mpgp.
- */
-static int
-man_pg_create(man_pg_t **mplpp, man_pg_t **mpgp, mi_path_t *mip)
-{
-	man_pg_t	*mpg;
-	man_pg_t	*tpg;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-
-	if (ether_cmp(&mip->mip_eaddr, &zero_ether_addr) == 0) {
-		cmn_err(CE_NOTE, "man_ioctl: man_pg_create: ether"
-		    " addresss not set!");
-		status = EINVAL;
-		goto exit;
-	}
-
-	mpg = man_kzalloc(sizeof (man_pg_t), KM_NOSLEEP);
-	if (mpg == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-	mpg->mpg_flags = MAN_PG_IDLE;
-	mpg->mpg_pg_id = mip->mip_pg_id;
-	mpg->mpg_man_ppa = mip->mip_man_ppa;
-	ether_copy(&mip->mip_eaddr, &mpg->mpg_dst_eaddr);
-
-	MAN_DBG(MAN_PATH, ("man_pg_create: new mpg"));
-	MAN_DBGCALL(MAN_PATH, man_print_mpg(mpg));
-
-	tpg = *mplpp;
-	if (tpg == NULL) {
-		*mplpp = mpg;
-	} else {
-		while (tpg->mpg_next != NULL)
-			tpg = tpg->mpg_next;
-		tpg->mpg_next = mpg;
-	}
-
-exit:
-	*mpgp = mpg;
-
-	return (status);
-}
-
-/*
- * Return pointer to pathgroup containing mdevp, null otherwise. Also,
- * if a path pointer is passed in, set it to matching path in pathgroup.
- *
- * Called holding man_lock.
- */
-static man_pg_t *
-man_find_path_by_dev(man_pg_t *plp, man_dev_t *mdevp, man_path_t **mpp)
-{
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	for (mpg = plp; mpg != NULL; mpg = mpg->mpg_next) {
-		for (mp  = mpg->mpg_pathp; mp != NULL; mp = mp->mp_next) {
-			if (mp->mp_device.mdev_major == mdevp->mdev_major &&
-			    mp->mp_device.mdev_ppa == mdevp->mdev_ppa) {
-
-				if (mpp != NULL)
-					*mpp = mp;
-				return (mpg);
-			}
-		}
-	}
-
-	return (NULL);
-}
-
-/*
- * Return pointer to pathgroup assigned to destination, null if not found.
- *
- * Called holding man_lock.
- */
-static man_pg_t *
-man_find_pg_by_id(man_pg_t *mpg, int pg_id)
-{
-	ASSERT(MUTEX_HELD(&man_lock));
-	for (; mpg != NULL; mpg = mpg->mpg_next) {
-		if (mpg->mpg_pg_id == pg_id)
-			return (mpg);
-	}
-
-	return (NULL);
-}
-
-static man_path_t *
-man_find_path_by_ppa(man_path_t *mplist, int ppa)
-{
-	man_path_t	*mp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	for (mp = mplist; mp != NULL; mp = mp->mp_next) {
-		if (mp->mp_device.mdev_ppa == ppa)
-			return (mp);
-	}
-
-	return (NULL);
-}
-
-static man_path_t *
-man_find_active_path(man_path_t *mplist)
-{
-	man_path_t	*mp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	for (mp = mplist; mp != NULL; mp = mp->mp_next)
-		if (mp->mp_device.mdev_state & MDEV_ACTIVE)
-			return (mp);
-
-	return (NULL);
-}
-
-/*
- * Try and find an alternate path.
- */
-static man_path_t *
-man_find_alternate_path(man_path_t *mlp)
-{
-	man_path_t	*ap;		/* Active path */
-	man_path_t	*np;		/* New alternate path */
-	man_path_t	*fp = NULL;	/* LRU failed path */
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	ap = man_find_active_path(mlp);
-
-	/*
-	 * Find a non-failed path, or the lru failed path and switch to it.
-	 */
-	for (np = mlp; np != NULL; np = np->mp_next) {
-		if (np == ap)
-			continue;
-
-		if (np->mp_device.mdev_state == MDEV_ASSIGNED)
-			goto exit;
-
-		if (np->mp_device.mdev_state & MDEV_FAILED) {
-			if (fp == NULL)
-				fp = np;
-			else
-				if (fp->mp_lru > np->mp_lru)
-						fp = np;
-		}
-	}
-
-	/*
-	 * Nowhere to switch to.
-	 */
-	if (np == NULL && (np =  fp) == NULL)
-		goto exit;
-
-exit:
-	return (np);
-}
-
-/*
- * Assumes caller has verified existence.
- */
-static void
-man_path_remove(man_path_t **lpp, man_path_t *mp)
-{
-	man_path_t	*tp;
-	man_path_t	*tpp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	MAN_DBG(MAN_PATH, ("man_path_remove: removing path"));
-	MAN_DBGCALL(MAN_PATH, man_print_path(mp));
-
-	tp = tpp = *lpp;
-	if (tp == mp) {
-		*lpp = tp->mp_next;
-		goto exit;
-	}
-
-	for (tp = tp->mp_next; tp != NULL; tp = tp->mp_next) {
-		if (tp == mp)
-			break;
-		tpp = tp;
-	}
-
-	ASSERT(tp != NULL);
-
-	tpp->mp_next = tp->mp_next;
-	tp->mp_next = NULL;
-
-exit:
-	man_path_kstat_uninit(tp);
-	man_kfree(tp, sizeof (man_path_t));
-
-}
-
-/*
- * Insert path into list, ascending order by ppa.
- */
-static void
-man_path_insert(man_path_t **lpp, man_path_t *mp)
-{
-	man_path_t	*tp;
-	man_path_t	*tpp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	if (*lpp == NULL) {
-		*lpp = mp;
-		return;
-	}
-
-	tp = tpp = *lpp;
-	if (tp->mp_device.mdev_ppa > mp->mp_device.mdev_ppa) {
-		mp->mp_next = tp;
-		*lpp = mp;
-		return;
-	}
-
-	for (tp = tp->mp_next; tp != NULL; tp =  tp->mp_next) {
-		if (tp->mp_device.mdev_ppa > mp->mp_device.mdev_ppa)
-			break;
-		tpp = tp;
-	}
-
-	if (tp == NULL) {
-		tpp->mp_next = mp;
-	} else {
-		tpp->mp_next = mp;
-		mp->mp_next = tp;
-	}
-}
-
-/*
- * Merge npp into lpp, ascending order by ppa. Assumes no
- * duplicates in either list.
- */
-static void
-man_path_merge(man_path_t **lpp, man_path_t *np)
-{
-	man_path_t	*tmp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	while (np != NULL) {
-		tmp = np;
-		np = np->mp_next;
-		tmp->mp_next = NULL;
-
-		man_path_insert(lpp, tmp);
-	}
-
-}
-
-static int
-man_path_kstat_init(man_path_t *mpp)
-{
-
-	kstat_named_t	*dev_knp;
-	int		status = 0;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	MAN_DBG(MAN_PATH, ("man_path_kstat_init: mpp(0x%p)\n", (void *)mpp));
-
-	/*
-	 * Create named kstats for accounting purposes.
-	 */
-	dev_knp = man_kzalloc(MAN_NUMSTATS * sizeof (kstat_named_t),
-	    KM_NOSLEEP);
-	if (dev_knp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-	man_kstat_named_init(dev_knp, MAN_NUMSTATS);
-	mpp->mp_last_knp = dev_knp;
-
-exit:
-
-	MAN_DBG(MAN_PATH, ("man_path_kstat_init: returns %d\n", status));
-
-	return (status);
-}
-
-static void
-man_path_kstat_uninit(man_path_t *mp)
-{
-	ASSERT(MUTEX_HELD(&man_lock));
-	man_kfree(mp->mp_last_knp, MAN_NUMSTATS * sizeof (kstat_named_t));
-}
-
-/*
- * man_work_alloc - allocate and initiate a work request structure
- *
- *	type - type of request to allocate
- *	returns	- success - ptr to an initialized work structure
- *		- failure - NULL
- */
-man_work_t *
-man_work_alloc(int type, int kmflag)
-{
-	man_work_t	*wp;
-
-	wp = man_kzalloc(sizeof (man_work_t), kmflag);
-	if (wp == NULL)
-		goto exit;
-
-	cv_init(&wp->mw_cv, NULL, CV_DRIVER, NULL); \
-	wp->mw_type = type;
-
-exit:
-	return (wp);
-}
-
-/*
- * man_work_free - deallocate a work request structure
- *
- *	wp - ptr to work structure to be freed
- */
-void
-man_work_free(man_work_t *wp)
-{
-	cv_destroy(&wp->mw_cv);
-	man_kfree((void *)wp, sizeof (man_work_t));
-}
-
-/*
- * Post work to a work queue.  The man_bwork sleeps on
- * man_bwork_q->q_cv, and work requesters may sleep on mw_cv.
- * The man_lock is used to protect both cv's.
- */
-void
-man_work_add(man_workq_t *q, man_work_t *wp)
-{
-	man_work_t	*lp = q->q_work;
-
-	if (lp) {
-		while (lp->mw_next != NULL)
-			lp = lp->mw_next;
-
-		lp->mw_next = wp;
-
-	} else {
-		q->q_work = wp;
-	}
-
-	/*
-	 * cv_signal for man_bwork_q, qenable for man_iwork_q
-	 */
-	if (q == man_bwork_q) {
-		cv_signal(&q->q_cv);
-
-	} else {	/* q == man_iwork_q */
-
-		if (man_ctl_wq != NULL)
-			qenable(man_ctl_wq);
-	}
-
-}
-
-/* <<<<<<<<<<<<<<<<<<<<<<< NDD SUPPORT FUNCTIONS	>>>>>>>>>>>>>>>>>>> */
-/*
- * ndd support functions to get/set parameters
- */
-
-/*
- * Register each element of the parameter array with the
- * named dispatch handler. Each element is loaded using
- * nd_load()
- *
- * 	cnt	- the number of elements present in the parameter array
- */
-static int
-man_param_register(param_t *manpa, int cnt)
-{
-	int	i;
-	ndgetf_t getp;
-	ndsetf_t setp;
-	int	status = B_TRUE;
-
-	MAN_DBG(MAN_CONFIG, ("man_param_register: manpa(0x%p) cnt %d\n",
-	    (void *)manpa, cnt));
-
-	getp = man_param_get;
-
-	for (i = 0; i < cnt; i++, manpa++) {
-		switch (man_param_display[i]) {
-		case MAN_NDD_GETABLE:
-			setp = NULL;
-			break;
-
-		case MAN_NDD_SETABLE:
-			setp = man_param_set;
-			break;
-
-		default:
-			continue;
-		}
-
-		if (!nd_load(&man_ndlist, manpa->param_name, getp,
-		    setp, (caddr_t)manpa)) {
-
-			(void) man_nd_free(&man_ndlist);
-			status = B_FALSE;
-			goto exit;
-		}
-	}
-
-	if (!nd_load(&man_ndlist, "man_pathgroups_report",
-	    man_pathgroups_report, NULL, NULL)) {
-
-		(void) man_nd_free(&man_ndlist);
-		status = B_FALSE;
-		goto exit;
-	}
-
-	if (!nd_load(&man_ndlist, "man_set_active_path",
-	    NULL, man_set_active_path, NULL)) {
-
-		(void) man_nd_free(&man_ndlist);
-		status = B_FALSE;
-		goto exit;
-	}
-
-	if (!nd_load(&man_ndlist, "man_get_hostinfo",
-	    man_get_hostinfo, NULL, NULL)) {
-
-		(void) man_nd_free(&man_ndlist);
-		status = B_FALSE;
-		goto exit;
-	}
-
-exit:
-
-	MAN_DBG(MAN_CONFIG, ("man_param_register: returns %d\n", status));
-
-	return (status);
-}
-
-static void
-man_nd_getset(queue_t *wq, mblk_t *mp)
-{
-
-	if (!nd_getset(wq, man_ndlist, mp))
-		miocnak(wq, mp, 0, ENOENT);
-	else
-		qreply(wq, mp);
-}
-
-/*ARGSUSED*/
-static int
-man_pathgroups_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
-
-	man_t		*manp;
-	man_pg_t	*mpg;
-	int		i;
-	char		pad[] = "                 "; /* 17 spaces */
-	int		pad_end;
-
-
-	MAN_DBG(MAN_PATH, ("man_pathgroups_report: wq(0x%p) mp(0x%p)"
-	    " caddr 0x%p", (void *)wq, (void *)mp, (void *)cp));
-
-	(void) mi_mpprintf(mp, "MAN Pathgroup report: (* == failed)");
-	(void) mi_mpprintf(mp, "====================================="
-	    "==========================================");
-
-	mutex_enter(&man_lock);
-
-	for (i = 0; i < 2; i++) {
-		manp = ddi_get_soft_state(man_softstate, i);
-		if (manp == NULL)
-			continue;
-
-	(void) mi_mpprintf(mp,
-	    "Interface\tDestination\t\tActive Path\tAlternate Paths");
-	(void) mi_mpprintf(mp, "---------------------------------------"
-	    "----------------------------------------");
-
-		for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
-
-			(void) mi_mpprintf(mp, "%s%d\t\t",
-			    ddi_major_to_name(manp->man_meta_major),
-			    manp->man_meta_ppa);
-
-			if (man_is_on_domain) {
-				(void) mi_mpprintf_nr(mp, "Master SSC\t");
-				man_preport(mpg->mpg_pathp, mp);
-			} else {
-				if (i == 0) {
-					pad_end = 17 - strlen(ether_sprintf(
-					    &mpg->mpg_dst_eaddr));
-					if (pad_end < 0 || pad_end > 16)
-					pad_end = 0;
-					pad[pad_end] = '\0';
-
-					(void) mi_mpprintf_nr(mp, "%c %s%s",
-					    mpg->mpg_pg_id + 'A',
-					    ether_sprintf(&mpg->mpg_dst_eaddr),
-					    pad);
-
-					pad[pad_end] = ' ';
-				} else {
-					(void) mi_mpprintf_nr(mp,
-					    "Other SSC\t");
-				}
-				man_preport(mpg->mpg_pathp, mp);
-			}
-			(void) mi_mpprintf_nr(mp, "\n");
-		}
-	}
-
-	mutex_exit(&man_lock);
-	MAN_DBG(MAN_PATH, ("man_pathgroups_report: returns"));
-
-	return (0);
-}
-
-static void
-man_preport(man_path_t *plist, mblk_t *mp)
-{
-	man_path_t	*ap;
-
-	ap = man_find_active_path(plist);
-	/*
-	 * Active path
-	 */
-	if (ap != NULL) {
-		(void) mi_mpprintf_nr(mp, "\t%s%d\t\t",
-		    ddi_major_to_name(ap->mp_device.mdev_major),
-		    ap->mp_device.mdev_ppa);
-	} else {
-		(void) mi_mpprintf_nr(mp, "None \t");
-	}
-
-	/*
-	 * Alternate Paths.
-	 */
-	while (plist != NULL) {
-		(void) mi_mpprintf_nr(mp, "%s%d exp %d",
-		    ddi_major_to_name(plist->mp_device.mdev_major),
-		    plist->mp_device.mdev_ppa,
-		    plist->mp_device.mdev_exp_id);
-		if (plist->mp_device.mdev_state & MDEV_FAILED)
-			(void) mi_mpprintf_nr(mp, "*");
-		plist = plist->mp_next;
-		if (plist)
-			(void) mi_mpprintf_nr(mp, ", ");
-	}
-}
-
-/*
- * NDD request to set active path. Calling context is man_ioctl, so we are
- * exclusive in the inner perimeter.
- *
- *	Syntax is "ndd -set /dev/dman <man ppa> <pg_id> <phys ppa>"
- */
-/* ARGSUSED3 */
-static int
-man_set_active_path(queue_t *wq, mblk_t *mp, char *value, caddr_t cp,
-    cred_t *cr)
-{
-	char		*end, *meta_ppap, *phys_ppap, *pg_idp;
-	int		meta_ppa;
-	int		phys_ppa;
-	int		pg_id;
-	man_t		*manp;
-	man_pg_t	*mpg;
-	man_path_t	*np;
-	mi_path_t	mpath;
-	int		status = 0;
-
-	MAN_DBG(MAN_PATH, ("man_set_active_path: wq(0x%p) mp(0x%p)"
-	    " args %s", (void *)wq, (void *)mp, value));
-
-	meta_ppap = value;
-
-	if ((pg_idp = strchr(value, ' ')) == NULL) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	*pg_idp++ = '\0';
-
-	if ((phys_ppap = strchr(pg_idp, ' ')) == NULL) {
-		status = EINVAL;
-		goto exit;
-	}
-
-	*phys_ppap++ = '\0';
-
-	meta_ppa = (int)mi_strtol(meta_ppap, &end, 10);
-	pg_id = (int)mi_strtol(pg_idp, &end, 10);
-	phys_ppa = (int)mi_strtol(phys_ppap, &end, 10);
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, meta_ppa);
-	if (manp == NULL || manp->man_pg == NULL) {
-		status = EINVAL;
-		mutex_exit(&man_lock);
-		goto exit;
-	}
-
-	mpg = man_find_pg_by_id(manp->man_pg, pg_id);
-	if (mpg == NULL) {
-		status = EINVAL;
-		mutex_exit(&man_lock);
-		goto exit;
-	}
-
-	np = man_find_path_by_ppa(mpg->mpg_pathp, phys_ppa);
-
-	if (np == NULL) {
-		status = EINVAL;
-		mutex_exit(&man_lock);
-		goto exit;
-	}
-
-	mpath.mip_cmd = MI_PATH_ACTIVATE;
-	mpath.mip_pg_id = pg_id;
-	mpath.mip_man_ppa = meta_ppa;
-	mpath.mip_devs[0] = np->mp_device;
-	mpath.mip_ndevs = 1;
-
-	status = man_pg_cmd(&mpath, NULL);
-	mutex_exit(&man_lock);
-
-exit:
-
-	MAN_DBG(MAN_PATH, ("man_set_active_path: returns %d", status));
-
-	return (status);
-}
-
-/*
- * Dump out the contents of the IOSRAM handoff structure. Note that if
- * anything changes here, you must make sure that the sysinit script
- * stays in sync with this output.
- */
-/* ARGSUSED */
-static int
-man_get_hostinfo(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
-	manc_t	manc;
-	char	*ipaddr;
-	char	ipv6addr[INET6_ADDRSTRLEN];
-	int	i;
-	int	status;
-
-	if (!man_is_on_domain)
-		return (0);
-
-	if (status = man_get_iosram(&manc)) {
-		return (status);
-	}
-
-	(void) mi_mpprintf(mp, "manc_magic = 0x%x", manc.manc_magic);
-	(void) mi_mpprintf(mp, "manc_version = 0%d", manc.manc_version);
-	(void) mi_mpprintf(mp, "manc_csum = 0x%x", manc.manc_csum);
-
-	if (manc.manc_ip_type == AF_INET) {
-		in_addr_t	netnum;
-
-		(void) mi_mpprintf(mp, "manc_ip_type = AF_INET");
-
-		ipaddr = man_inet_ntoa(manc.manc_dom_ipaddr);
-		(void) mi_mpprintf(mp, "manc_dom_ipaddr = %s", ipaddr);
-
-		ipaddr = man_inet_ntoa(manc.manc_dom_ip_netmask);
-		(void) mi_mpprintf(mp, "manc_dom_ip_netmask = %s", ipaddr);
-
-		netnum = manc.manc_dom_ipaddr & manc.manc_dom_ip_netmask;
-		ipaddr = man_inet_ntoa(netnum);
-		(void) mi_mpprintf(mp, "manc_dom_ip_netnum = %s", ipaddr);
-
-		ipaddr = man_inet_ntoa(manc.manc_sc_ipaddr);
-		(void) mi_mpprintf(mp, "manc_sc_ipaddr = %s", ipaddr);
-
-	} else if (manc.manc_ip_type == AF_INET6) {
-
-		(void) mi_mpprintf(mp, "manc_ip_type = AF_INET6");
-
-		(void) inet_ntop(AF_INET6, (void *)&manc.manc_dom_ipv6addr,
-		    ipv6addr, INET6_ADDRSTRLEN);
-		(void) mi_mpprintf(mp, "manc_dom_ipv6addr = %s", ipv6addr);
-
-		(void) mi_mpprintf(mp, "manc_dom_ipv6_netmask = %d",
-		    manc.manc_dom_ipv6_netmask.s6_addr[0]);
-
-		(void) inet_ntop(AF_INET6, (void *)&manc.manc_sc_ipv6addr,
-		    ipv6addr, INET6_ADDRSTRLEN);
-		(void) mi_mpprintf(mp, "manc_sc_ipv6addr = %s", ipv6addr);
-
-	} else {
-
-		(void) mi_mpprintf(mp, "manc_ip_type = NONE");
-	}
-
-	(void) mi_mpprintf(mp, "manc_dom_eaddr = %s",
-	    ether_sprintf(&manc.manc_dom_eaddr));
-	(void) mi_mpprintf(mp, "manc_sc_eaddr = %s",
-	    ether_sprintf(&manc.manc_sc_eaddr));
-
-	(void) mi_mpprintf(mp, "manc_iob_bitmap = 0x%x\tio boards = ",
-	    manc.manc_iob_bitmap);
-	for (i = 0; i < MAN_MAX_EXPANDERS; i++) {
-		if ((manc.manc_iob_bitmap >> i) & 0x1) {
-			(void) mi_mpprintf_nr(mp, "%d.1, ", i);
-		}
-	}
-	(void) mi_mpprintf(mp, "manc_golden_iob = %d", manc.manc_golden_iob);
-
-	return (0);
-}
-
-static char *
-man_inet_ntoa(in_addr_t in)
-{
-	static char b[18];
-	unsigned char *p;
-
-	p = (unsigned char *)&in;
-	(void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-	return (b);
-}
-
-/*
- * parameter value. cp points to the required parameter.
- */
-/* ARGSUSED */
-static int
-man_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
-{
-	param_t	*manpa = (param_t *)cp;
-
-	(void) mi_mpprintf(mp, "%u", manpa->param_val);
-	return (0);
-}
-
-/*
- * Sets the man parameter to the value in the param_register using
- * nd_load().
- */
-/* ARGSUSED */
-static int
-man_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
-{
-	char *end;
-	size_t new_value;
-	param_t	*manpa = (param_t *)cp;
-
-	new_value = mi_strtol(value, &end, 10);
-
-	if (end == value || new_value < manpa->param_min ||
-	    new_value > manpa->param_max) {
-			return (EINVAL);
-	}
-
-	manpa->param_val = new_value;
-
-	return (0);
-
-}
-
-/*
- * Free the Named Dispatch Table by calling man_nd_free
- */
-static void
-man_param_cleanup()
-{
-	if (man_ndlist != NULL)
-		nd_free(&man_ndlist);
-}
-
-/*
- * Free the table pointed to by 'ndp'
- */
-static void
-man_nd_free(caddr_t *nd_pparam)
-{
-	ND	*nd;
-
-	if ((nd = (ND *)(*nd_pparam)) != NULL) {
-		if (nd->nd_tbl)
-			mi_free((char *)nd->nd_tbl);
-		mi_free((char *)nd);
-		*nd_pparam = NULL;
-	}
-}
-
-
-/*
- * man_kstat_update - update the statistics for a meta-interface.
- *
- *	ksp - kstats struct
- *	rw - flag indicating whether stats are to be read or written.
- *
- *	returns	0
- *
- * The destination specific kstat information is protected by the
- * perimeter lock, so we submit a work request to get the stats
- * updated (see man_do_kstats()), and then collect the results
- * when cv_signal'd. Note that we are doing cv_timedwait_sig()
- * as a precautionary measure only.
- */
-static int
-man_kstat_update(kstat_t *ksp, int rw)
-{
-	man_t			*manp;		/* per instance data */
-	man_work_t		*wp;
-	int			status = 0;
-	kstat_named_t		*knp;
-	kstat_named_t		*man_knp;
-	int			i;
-
-	MAN_DBG(MAN_KSTAT, ("man_kstat_update: %s\n", rw ? "KSTAT_WRITE" :
-	    "KSTAT_READ"));
-
-	mutex_enter(&man_lock);
-	manp = (man_t *)ksp->ks_private;
-	manp->man_refcnt++;
-
-	/*
-	 * If the driver has been configured, get kstats updated by inner
-	 * perimeter prior to retrieving.
-	 */
-	if (man_config_state == MAN_CONFIGURED) {
-		clock_t wait_status;
-
-		man_update_path_kstats(manp);
-		wp = man_work_alloc(MAN_WORK_KSTAT_UPDATE, KM_SLEEP);
-		wp->mw_arg.a_man_ppa = manp->man_meta_ppa;
-		wp->mw_flags = MAN_WFLAGS_CVWAITER;
-		man_work_add(man_iwork_q, wp);
-
-		wait_status = cv_reltimedwait_sig(&wp->mw_cv, &man_lock,
-		    drv_usectohz(manp->man_kstat_waittime), TR_CLOCK_TICK);
-
-		if (wp->mw_flags & MAN_WFLAGS_DONE) {
-			status = wp->mw_status;
-			man_work_free(wp);
-		} else {
-			ASSERT(wait_status <= 0);
-			wp->mw_flags &= ~MAN_WFLAGS_CVWAITER;
-			if (wait_status == 0)
-				status = EINTR;
-			else {
-				MAN_DBG(MAN_KSTAT, ("man_kstat_update: "
-				    "timedout, returning stale stats."));
-				status = 0;
-			}
-		}
-		if (status)
-			goto exit;
-	}
-
-	knp = (kstat_named_t *)ksp->ks_data;
-	man_knp = (kstat_named_t *)manp->man_ksp->ks_data;
-
-	if (rw == KSTAT_READ) {
-		for (i = 0; i < MAN_NUMSTATS; i++) {
-			knp[i].value.ui64 = man_knp[i].value.ui64;
-		}
-	} else {
-		for (i = 0; i < MAN_NUMSTATS; i++) {
-			man_knp[i].value.ui64 = knp[i].value.ui64;
-		}
-	}
-
-exit:
-	manp->man_refcnt--;
-	mutex_exit(&man_lock);
-
-	MAN_DBG(MAN_KSTAT, ("man_kstat_update: returns %d", status));
-
-	return (status);
-}
-
-/*
- * Sum destination kstats for all active paths for a given instance of the
- * MAN driver. Called with perimeter lock.
- */
-static void
-man_do_kstats(man_work_t *wp)
-{
-	man_t		*manp;
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-
-	MAN_DBG(MAN_KSTAT, ("man_do_kstats:"));
-
-	mutex_enter(&man_lock);
-	/*
-	 * Sync mp_last_knp for each path associated with the MAN instance.
-	 */
-	manp = (man_t *)ddi_get_soft_state(man_softstate,
-	    wp->mw_arg.a_man_ppa);
-	for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
-
-		ASSERT(mpg->mpg_man_ppa == manp->man_meta_ppa);
-
-		if ((mp = man_find_active_path(mpg->mpg_pathp)) != NULL) {
-
-			MAN_DBG(MAN_KSTAT, ("\tkstat: path"));
-			MAN_DBGCALL(MAN_KSTAT, man_print_path(mp));
-
-			/*
-			 * We just to update the destination statistics here.
-			 */
-			man_sum_dests_kstats(mp->mp_last_knp, mpg);
-		}
-	}
-	mutex_exit(&man_lock);
-	MAN_DBG(MAN_KSTAT, ("man_do_kstats: returns"));
-}
-
-/*
- * Sum device kstats for all active paths for a given instance of the
- * MAN driver. Called with man_lock.
- */
-static void
-man_update_path_kstats(man_t *manp)
-{
-	kstat_named_t	*man_knp;
-	man_pg_t	*mpg;
-	man_path_t	*mp;
-
-	ASSERT(MUTEX_HELD(&man_lock));
-	MAN_DBG(MAN_KSTAT, ("man_update_path_kstats:"));
-
-	man_knp = (kstat_named_t *)manp->man_ksp->ks_data;
-
-	for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
-
-		ASSERT(mpg->mpg_man_ppa == manp->man_meta_ppa);
-
-		if ((mp = man_find_active_path(mpg->mpg_pathp)) != NULL) {
-
-			man_update_dev_kstats(man_knp, mp);
-
-		}
-	}
-	MAN_DBG(MAN_KSTAT, ("man_update_path_kstats: returns"));
-}
-
-/*
- * Update the device kstats.
- * As man_kstat_update() is called with kstat_chain_lock held,
- * we can safely update the statistics from the underlying driver here.
- */
-static void
-man_update_dev_kstats(kstat_named_t *man_knp, man_path_t *mp)
-{
-	kstat_t		*dev_ksp;
-	major_t		major;
-	int		instance;
-	char		buf[KSTAT_STRLEN];
-
-
-	major = mp->mp_device.mdev_major;
-	instance = mp->mp_device.mdev_ppa;
-	(void) sprintf(buf, "%s%d", ddi_major_to_name(major), instance);
-
-	dev_ksp = kstat_hold_byname(ddi_major_to_name(major), instance, buf,
-	    ALL_ZONES);
-	if (dev_ksp != NULL) {
-
-		KSTAT_ENTER(dev_ksp);
-		KSTAT_UPDATE(dev_ksp, KSTAT_READ);
-		man_sum_kstats(man_knp, dev_ksp, mp->mp_last_knp);
-		KSTAT_EXIT(dev_ksp);
-		kstat_rele(dev_ksp);
-
-	} else {
-		MAN_DBG(MAN_KSTAT,
-		    ("man_update_dev_kstats: no kstat data found for %s(%d,%d)",
-		    buf, major, instance));
-	}
-}
-
-static void
-man_sum_dests_kstats(kstat_named_t *knp, man_pg_t *mpg)
-{
-	int		i;
-	int		flags;
-	char		*statname;
-	manstr_t	*msp;
-	man_dest_t	*mdp;
-	uint64_t	switches = 0;
-	uint64_t	linkfails = 0;
-	uint64_t	linkstales = 0;
-	uint64_t	icmpv4probes = 0;
-	uint64_t	icmpv6probes = 0;
-
-	MAN_DBG(MAN_KSTAT, ("man_sum_dests_kstats: mpg 0x%p", (void *)mpg));
-
-	for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
-
-		if (!man_str_uses_pg(msp, mpg))
-			continue;
-
-		mdp = &msp->ms_dests[mpg->mpg_pg_id];
-
-		switches += mdp->md_switches;
-		linkfails += mdp->md_linkfails;
-		linkstales += mdp->md_linkstales;
-		icmpv4probes += mdp->md_icmpv4probes;
-		icmpv6probes += mdp->md_icmpv6probes;
-	}
-
-	for (i = 0; i < MAN_NUMSTATS; i++) {
-
-		statname = man_kstat_info[i].mk_name;
-		flags = man_kstat_info[i].mk_flags;
-
-		if (!(flags & MK_NOT_PHYSICAL))
-			continue;
-
-		if (strcmp(statname, "man_switches") == 0) {
-			knp[i].value.ui64 = switches;
-		} else if (strcmp(statname, "man_link_fails") == 0) {
-			knp[i].value.ui64 = linkfails;
-		} else if (strcmp(statname, "man_link_stales") == 0) {
-			knp[i].value.ui64 = linkstales;
-		} else if (strcmp(statname, "man_icmpv4_probes") == 0) {
-			knp[i].value.ui64 = icmpv4probes;
-		} else if (strcmp(statname, "man_icmpv6_probes") == 0) {
-			knp[i].value.ui64 = icmpv6probes;
-		}
-	}
-
-	MAN_DBG(MAN_KSTAT, ("man_sum_dests_kstats: returns"));
-}
-
-/*
- * Initialize MAN named kstats in the space provided.
- */
-static void
-man_kstat_named_init(kstat_named_t *knp, int num_stats)
-{
-	int	i;
-
-	MAN_DBG(MAN_KSTAT, ("man_kstat_named_init: knp(0x%p) num_stats = %d",
-	    (void *)knp, num_stats));
-
-	for (i = 0; i < num_stats; i++) {
-		kstat_named_init(&knp[i], man_kstat_info[i].mk_name,
-		    man_kstat_info[i].mk_type);
-	}
-
-	MAN_DBG(MAN_KSTAT, ("man_kstat_named_init: returns"));
-
-}
-
-/*
- * man_kstat_byname - get a kernel stat value from its structure
- *
- *	ksp - kstat_t structure to play with
- *	s   - string to match names with
- *	res - in/out result data pointer
- *
- *	returns	- success - 1 (found)
- *		- failure - 0 (not found)
- */
-static int
-man_kstat_byname(kstat_t *ksp, char *s, kstat_named_t *res)
-{
-	int		found = 0;
-
-	MAN_DBG(MAN_KSTAT2, ("man_kstat_byname: GETTING %s\n", s));
-
-	if (ksp->ks_type == KSTAT_TYPE_NAMED) {
-		kstat_named_t *knp;
-
-		for (knp = KSTAT_NAMED_PTR(ksp);
-		    (caddr_t)knp < ((caddr_t)ksp->ks_data+ksp->ks_data_size);
-		    knp++) {
-
-			if (strcmp(s, knp->name) == NULL) {
-
-				res->data_type = knp->data_type;
-				res->value = knp->value;
-				found++;
-
-				MAN_DBG(MAN_KSTAT2, ("\t%s: %d\n", knp->name,
-				    (int)knp->value.ul));
-			}
-		}
-	} else {
-		MAN_DBG(MAN_KSTAT2, ("\tbad kstats type %d\n", ksp->ks_type));
-	}
-
-	/*
-	 * if getting a value but couldn't find the namestring, result = 0.
-	 */
-	if (!found) {
-		/*
-		 * a reasonable default
-		 */
-		res->data_type = KSTAT_DATA_ULONG;
-		res->value.l = 0;
-		MAN_DBG(MAN_KSTAT2, ("\tcouldn't find, using defaults\n"));
-	}
-
-	MAN_DBG(MAN_KSTAT2, ("man_kstat_byname: returns\n"));
-
-	return (found);
-}
-
-
-/*
- *
- * Accumulate MAN driver kstats from the incremental values of the underlying
- * physical interfaces.
- *
- * Parameters:
- *	sum_knp		- The named kstat area to put cumulative value,
- *			  NULL if we just want to sync next two params.
- *	phys_ksp	- Physical interface kstat_t pointer. Contains
- *			  more current counts.
- * 	phys_last_knp	- counts from the last time we were called for this
- *			  physical interface. Note that the name kstats
- *			  pointed to are actually in MAN format, but they
- *			  hold the mirrored physical devices last read
- *			  kstats.
- * Basic algorithm is:
- *
- * 	for each named kstat variable {
- *	    sum_knp[i] += (phys_ksp->ksp_data[i] - phys_last_knp[i]);
- *	    phys_last_knp[i] = phys_ksp->ksp_data[i];
- *	}
- *
- */
-static void
-man_sum_kstats(kstat_named_t *sum_knp, kstat_t *phys_ksp,
-	kstat_named_t *phys_last_knp)
-{
-	char		*physname;
-	char		*physalias;
-	char		*statname;
-	kstat_named_t	phys_kn_entry;
-	uint64_t	delta64;
-	int		i;
-
-	MAN_DBG(MAN_KSTAT, ("man_sum_kstats: sum_knp(0x%p) phys_ksp(0x%p)"
-	    " phys_last_knp(0x%p)\n", (void *)sum_knp, (void *)phys_ksp,
-	    (void *)phys_last_knp));
-
-	/*
-	 * Now for each entry in man_kstat_info, sum the named kstat.
-	 * Not that all MAN specific kstats will end up !found.
-	 */
-	for (i = 0; i < MAN_NUMSTATS; i++) {
-		int	found = 0;
-		int	flags = 0;
-
-		delta64 = 0;
-
-		statname = man_kstat_info[i].mk_name;
-		physname = man_kstat_info[i].mk_physname;
-		physalias = man_kstat_info[i].mk_physalias;
-		flags = man_kstat_info[i].mk_flags;
-
-		/*
-		 * Update MAN private kstats.
-		 */
-		if (flags & MK_NOT_PHYSICAL) {
-
-			kstat_named_t	*knp = phys_last_knp;
-
-			if (sum_knp == NULL)
-				continue;
-
-			if (strcmp(statname, "man_switches") == 0) {
-				sum_knp[i].value.ui64 = knp[i].value.ui64;
-			} else if (strcmp(statname, "man_link_fails") == 0) {
-				sum_knp[i].value.ui64 = knp[i].value.ui64;
-			} else if (strcmp(statname, "man_link_stales") == 0) {
-				sum_knp[i].value.ui64 = knp[i].value.ui64;
-			} else if (strcmp(statname, "man_icmpv4_probes") == 0) {
-				sum_knp[i].value.ui64 = knp[i].value.ui64;
-			} else if (strcmp(statname, "man_icmpv6_probes") == 0) {
-				sum_knp[i].value.ui64 = knp[i].value.ui64;
-			}
-
-			continue;	/* phys_ksp doesnt have this stat */
-		}
-
-		/*
-		 * first try it by the "official" name
-		 */
-		if (phys_ksp) {
-			if (man_kstat_byname(phys_ksp, physname,
-			    &phys_kn_entry)) {
-
-				found = 1;
-
-			} else if ((physalias) && (man_kstat_byname(phys_ksp,
-			    physalias, &phys_kn_entry))) {
-
-				found = 1;
-			}
-		}
-
-		if (!found) {
-			/*
-			 * clear up the "last" value, no change to the sum
-			 */
-			phys_last_knp[i].value.ui64 = 0;
-			continue;
-		}
-
-		/*
-		 * at this point, we should have the good underlying
-		 * kstat value stored in phys_kn_entry
-		 */
-		if (flags & MK_NOT_COUNTER) {
-			/*
-			 * it isn't a counter, so store the value and
-			 * move on (e.g. ifspeed)
-			 */
-			phys_last_knp[i].value = phys_kn_entry.value;
-			continue;
-		}
-
-		switch (phys_kn_entry.data_type) {
-		case KSTAT_DATA_UINT32:
-
-			/*
-			 * this handles 32-bit wrapping
-			 */
-			if (phys_kn_entry.value.ui32 <
-			    phys_last_knp[i].value.ui32) {
-
-				/*
-				 * we've wrapped!
-				 */
-				delta64 += (UINT_MAX -
-				    phys_last_knp[i].value.ui32);
-				phys_last_knp[i].value.ui32 = 0;
-			}
-
-			delta64 += phys_kn_entry.value.ui32 -
-			    phys_last_knp[i].value.ui32;
-			phys_last_knp[i].value.ui32 = phys_kn_entry.value.ui32;
-			break;
-
-		default:
-			/*
-			 * must be a 64-bit value, we ignore 64-bit
-			 * wraps, since they shouldn't ever happen
-			 * within the life of a machine (if we assume
-			 * machines don't stay up for more than a few
-			 * hundred years without a reboot...)
-			 */
-			delta64 = phys_kn_entry.value.ui64 -
-			    phys_last_knp[i].value.ui64;
-			phys_last_knp[i].value.ui64 = phys_kn_entry.value.ui64;
-		}
-
-		if (sum_knp != NULL) {
-			/*
-			 * now we need to save the value
-			 */
-			switch (sum_knp[i].data_type) {
-			case KSTAT_DATA_UINT32:
-				/* trunk down to 32 bits, possibly lossy */
-				sum_knp[i].value.ui32 += (uint32_t)delta64;
-				break;
-
-			default:
-				sum_knp[i].value.ui64 += delta64;
-				break;
-			}
-		}
-	}
-
-	MAN_DBG(MAN_KSTAT, ("man_sum_kstats: returns\n"));
-}
-
-
-#if defined(DEBUG)
-
-
-static char *_ms_flags[] = {
-	"NONE",
-	"FAST", 	/* 0x1 */
-	"RAW",		/* 0x2 */
-	"ALLPHYS",	/* 0x4 */
-	"ALLMULTI",	/* 0x8 */
-	"ALLSAP",	/* 0x10 */
-	"CKSUM",	/* 0x20 */
-	"MULTI",	/* 0x40 */
-	"SERLPBK",	/* 0x80 */
-	"MACLPBK",	/* 0x100 */
-	"CLOSING",	/* 0x200 */
-	"CLOSE_DONE",	/* 0x400 */
-	"CONTROL"	/* 0x800 */
-};
-
-static void
-man_print_msp(manstr_t *msp)
-{
-	char	buf[512];
-	char	prbuf[512];
-	uint_t	flags;
-	int	i;
-
-	cmn_err(CE_CONT, "\tmsp(0x%p)\n", (void *)msp);
-
-	if (msp == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\t%s%d SAP(0x%x):\n",
-	    ddi_major_to_name(msp->ms_meta_maj), msp->ms_meta_ppa,
-	    msp->ms_sap);
-
-	buf[0] = '\0';
-	prbuf[0] = '\0';
-	flags = msp->ms_flags;
-	for (i = 0; i < A_CNT(_ms_flags); i++) {
-		if ((flags >> i) & 0x1) {
-			(void) sprintf(buf, " %s |", _ms_flags[i+1]);
-			(void) strcat(prbuf, buf);
-		}
-	}
-	prbuf[strlen(prbuf) - 1] = '\0';
-	cmn_err(CE_CONT, "\tms_flags: %s\n", prbuf);
-
-	cmn_err(CE_CONT, "\tms_dlpistate: %s\n", dss[msp->ms_dlpistate]);
-
-	cmn_err(CE_CONT, "\tms_dl_mp: 0x%p\n", (void *)msp->ms_dl_mp);
-
-	cmn_err(CE_CONT, "\tms_manp: 0x%p\n", (void *)msp->ms_manp);
-
-	cmn_err(CE_CONT, "\tms_dests: 0x%p\n", (void *)msp->ms_dests);
-
-}
-
-static char *_md_state[] = {
-	"NOTPRESENT",		/* 0x0 */
-	"INITIALIZING",		/* 0x1 */
-	"READY",		/* 0x2 */
-	"PLUMBING",		/* 0x4 */
-	"CLOSING"		/* 0x8 */
-};
-
-static void
-man_print_mdp(man_dest_t *mdp)
-{
-	uint_t		state;
-	int		i;
-	char		buf[64];
-	char		prbuf[512];
-
-	buf[0] = '\0';
-	prbuf[0] = '\0';
-
-	cmn_err(CE_CONT, "\tmdp(0x%p)\n", (void *)mdp);
-
-	if (mdp == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmd_pg_id: %d\n", mdp->md_pg_id);
-	cmn_err(CE_CONT, "\tmd_dst_eaddr: %s\n",
-	    ether_sprintf(&mdp->md_dst_eaddr));
-	cmn_err(CE_CONT, "\tmd_src_eaddr: %s\n",
-	    ether_sprintf(&mdp->md_src_eaddr));
-	cmn_err(CE_CONT, "\tmd_dlpistate: %s", dss[mdp->md_dlpistate]);
-	cmn_err(CE_CONT, "\tmd_muxid: 0x%u", mdp->md_muxid);
-	cmn_err(CE_CONT, "\tmd_rcvcnt %lu md_lastrcvcnt %lu", mdp->md_rcvcnt,
-	    mdp->md_lastrcvcnt);
-
-	/*
-	 * Print out state as text.
-	 */
-	state = mdp->md_state;
-
-	if (state == 0) {
-		(void) strcat(prbuf, _md_state[0]);
-	} else {
-
-		for (i = 0; i < A_CNT(_md_state); i++) {
-			if ((state >> i) & 0x1)  {
-				(void) sprintf(buf, " %s |", _md_state[i+1]);
-				(void) strcat(prbuf, buf);
-			}
-		}
-		prbuf[strlen(prbuf) -1] = '\0';
-	}
-	cmn_err(CE_CONT, "\tmd_state: %s", prbuf);
-
-	cmn_err(CE_CONT, "\tmd_device:\n");
-	man_print_dev(&mdp->md_device);
-
-}
-
-static void
-man_print_man(man_t *manp)
-{
-	char	buf[512];
-	char	prbuf[512];
-
-	buf[0] = '\0';
-	prbuf[0] = '\0';
-
-	if (manp == NULL)
-		return;
-
-	if (ddi_major_to_name(manp->man_meta_major)) {
-		(void) sprintf(buf, "\t man_device: %s%d\n",
-		    ddi_major_to_name(manp->man_meta_major),
-		    manp->man_meta_ppa);
-	} else {
-		(void) sprintf(buf, "\t major: %d", manp->man_meta_major);
-		(void) sprintf(buf, "\t ppa: %d", manp->man_meta_ppa);
-	}
-
-	cmn_err(CE_CONT, "%s", buf);
-
-}
-
-static char *_mdev_state[] = {
-	"UNASSIGNED  ",
-	"ASSIGNED",
-	"ACTIVE",
-	"FAILED"
-};
-
-static void
-man_print_dev(man_dev_t *mdevp)
-{
-	char	buf[512];
-	char	prbuf[512];
-	int	i;
-	uint_t	state;
-
-	buf[0] = '\0';
-	prbuf[0] = '\0';
-
-	if (mdevp == NULL)
-		return;
-
-	if (mdevp->mdev_major == 0) {
-number:
-		(void) sprintf(buf, "\t mdev_major: %d\n", mdevp->mdev_major);
-	} else if (ddi_major_to_name(mdevp->mdev_major)) {
-		(void) sprintf(buf, "\t mdev_device: %s%d\n",
-		    ddi_major_to_name(mdevp->mdev_major),
-		    mdevp->mdev_ppa);
-	} else
-		goto number;
-
-	cmn_err(CE_CONT, "%s", buf);
-
-	cmn_err(CE_CONT, "\t mdev_exp_id: %d\n", mdevp->mdev_exp_id);
-
-	buf[0] = '\0';
-	prbuf[0] = '\0';
-	state = mdevp->mdev_state;
-
-	if (state == 0) {
-		(void) strcat(prbuf, _mdev_state[0]);
-	} else {
-		for (i = 0; i < A_CNT(_mdev_state); i++) {
-			if ((state >> i) & 0x1) {
-				(void) sprintf(buf, " %s |", _mdev_state[i+1]);
-				(void) strcat(prbuf, buf);
-			}
-		}
-	}
-
-	prbuf[strlen(prbuf) - 2] = '\0';
-
-	cmn_err(CE_CONT, "\t mdev_state: %s\n", prbuf);
-
-}
-
-static char *_mip_cmd[] = {
-	"MI_PATH_READ",
-	"MI_PATH_ASSIGN",
-	"MI_PATH_ACTIVATE",
-	"MI_PATH_DEACTIVATE",
-	"MI_PATH_UNASSIGN"
-};
-
-static void
-man_print_mtp(mi_time_t *mtp)
-{
-	cmn_err(CE_CONT, "\tmtp(0x%p)\n", (void *)mtp);
-
-	if (mtp == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmtp_instance: %d\n", mtp->mtp_man_ppa);
-
-	cmn_err(CE_CONT, "\tmtp_time: %d\n", mtp->mtp_time);
-
-}
-
-static void
-man_print_mip(mi_path_t *mip)
-{
-	cmn_err(CE_CONT, "\tmip(0x%p)\n", (void *)mip);
-
-	if (mip == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmip_pg_id: %d\n", mip->mip_pg_id);
-
-	cmn_err(CE_CONT, "\tmip_cmd: %s\n", _mip_cmd[mip->mip_cmd]);
-
-	cmn_err(CE_CONT, "\tmip_eaddr: %s\n", ether_sprintf(&mip->mip_eaddr));
-
-	cmn_err(CE_CONT, "\tmip_devs: 0x%p\n", (void *)mip->mip_devs);
-
-	cmn_err(CE_CONT, "\tmip_ndevs: %d\n", mip->mip_ndevs);
-
-}
-
-static void
-man_print_mpg(man_pg_t *mpg)
-{
-	cmn_err(CE_CONT, "\tmpg(0x%p)\n", (void *)mpg);
-
-	if (mpg == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmpg_next: 0x%p\n", (void *)mpg->mpg_next);
-
-	cmn_err(CE_CONT, "\tmpg_pg_id: %d\n", mpg->mpg_pg_id);
-
-	cmn_err(CE_CONT, "\tmpg_man_ppa: %d\n", mpg->mpg_man_ppa);
-
-	cmn_err(CE_CONT, "\tmpg_dst_eaddr: %s\n",
-	    ether_sprintf(&mpg->mpg_dst_eaddr));
-
-	cmn_err(CE_CONT, "\tmpg_pathp: 0x%p\n", (void *)mpg->mpg_pathp);
-
-}
-
-static char *_mw_flags[] = {
-	"NOWAITER",		/* 0x0 */
-	"CVWAITER",		/* 0x1 */
-	"QWAITER",		/* 0x2 */
-	"DONE"		/* 0x3 */
-};
-
-static void
-man_print_work(man_work_t *wp)
-{
-	int 	i;
-
-	cmn_err(CE_CONT, "\twp(0x%p)\n\n", (void *)wp);
-
-	if (wp == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmw_type: %s\n", _mw_type[wp->mw_type]);
-
-	cmn_err(CE_CONT, "\tmw_flags: ");
-	for (i = 0; i < A_CNT(_mw_flags); i++) {
-		if ((wp->mw_flags >> i) & 0x1)
-			cmn_err(CE_CONT, "%s", _mw_flags[i]);
-	}
-	cmn_err(CE_CONT, "\n");
-
-	cmn_err(CE_CONT, "\twp_status: %d\n", wp->mw_status);
-
-	cmn_err(CE_CONT, "\twp_arg: 0x%p\n", (void *)&wp->mw_arg);
-
-	cmn_err(CE_CONT, "\tmw_next: 0x%p\n", (void *)wp->mw_next);
-
-	cmn_err(CE_CONT, "\twp_q: 0x%p", (void *)wp->mw_q);
-
-}
-
-static void
-man_print_path(man_path_t *mp)
-{
-	cmn_err(CE_CONT, "\tmp(0x%p)\n\n", (void *)mp);
-
-	if (mp == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmp_device:");
-	man_print_dev(&mp->mp_device);
-
-	cmn_err(CE_CONT, "\tmp_next: 0x%p\n", (void *)mp->mp_next);
-
-	cmn_err(CE_CONT, "\tmp_last_knp: 0x%p\n", (void *)mp->mp_last_knp);
-
-	cmn_err(CE_CONT, "\tmp_lru: 0x%lx", mp->mp_lru);
-
-}
-
-void *
-man_dbg_kzalloc(int line, size_t size, int kmflags)
-{
-	void *tmp;
-
-	tmp = kmem_zalloc(size, kmflags);
-	MAN_DBG(MAN_KMEM, ("0x%p %lu\tzalloc'd @ %d\n", (void *)tmp,
-	    size, line));
-
-	return (tmp);
-
-}
-
-void
-man_dbg_kfree(int line, void *buf, size_t size)
-{
-
-	MAN_DBG(MAN_KMEM, ("0x%p %lu\tfree'd @ %d\n", (void *)buf, size, line));
-
-	kmem_free(buf, size);
-
-}
-
-#endif  /* DEBUG */
--- a/usr/src/uts/sun4u/starcat/io/dman.conf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-name="dman" parent="pseudo" instance=0;
--- a/usr/src/uts/sun4u/starcat/io/dman_domain.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,870 +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.
- */
-
-/*
- * Domain specific portion of the Starcat Management Network Driver
- */
-
-#include <sys/types.h>
-#include <sys/proc.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/kstat.h>
-#include <sys/ksynch.h>
-#include <sys/stream.h>
-#include <sys/dlpi.h>
-#include <sys/stropts.h>
-#include <sys/strsubr.h>
-#include <sys/debug.h>
-#include <sys/conf.h>
-#include <sys/kstr.h>
-#include <sys/errno.h>
-#include <sys/ethernet.h>
-#include <sys/byteorder.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/modctl.h>
-#include <sys/strsun.h>
-#include <sys/pci.h>
-#include <sys/callb.h>
-#include <sys/pci.h>
-#include <sys/iosramio.h>
-#include <sys/mboxsc.h>
-#include <netinet/in.h>
-#include <inet/common.h>
-#include <inet/mi.h>
-#include <inet/nd.h>
-#include <sys/socket.h>
-#include <netinet/igmp_var.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <inet/ip.h>
-#include <inet/ip6.h>
-#include <sys/dman.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/sunndi.h>
-
-#define	MAN_SCHIZO_BINDING_NAME		"pci108e,8001"
-#define	MAN_XMITS_BINDING_NAME		"pci108e,8002"
-
-int	man_is_on_domain = TRUE;
-
-/*
- * Domain side function prototypes.
- */
-int	man_get_iosram(manc_t *);
-int	man_domain_configure(void);
-int	man_domain_deconfigure(void);
-int	man_path_discovery(void);
-int	man_dossc_switch(uint32_t);
-int	man_dr_attach(dev_info_t *);
-int	man_dr_detach(dev_info_t *);
-static int	man_dr_submit_work_wait(dev_info_t *, int);
-static int	man_find_devs(mi_path_t *, uchar_t);
-static int 	man_dip_is_schizoxmits0_pcib(dev_info_t *, int *, int *);
-static int	man_dip_is_eri(dev_info_t *, man_dev_t *);
-static int	man_dip_is_attached(dev_info_t *);
-static int 	man_get_eri_dev_info(dev_info_t *, man_dev_t *);
-static int	man_mbox_initialized = FALSE;
-
-/*
- * Externs
- */
-extern int	man_pg_cmd(mi_path_t *, man_work_t *);
-extern kmutex_t		man_lock;
-extern void		*man_softstate;
-extern man_work_t	*man_work_alloc(int, int);
-extern void		man_work_free(man_work_t *);
-extern void		man_work_add(man_workq_t *, man_work_t *);
-extern man_workq_t	*man_bwork_q;
-extern man_workq_t	*man_iwork_q;
-extern queue_t		*man_ctl_wq;
-
-#if defined(DEBUG)
-static void man_print_manc(manc_t *);
-extern uint32_t	man_debug;
-#endif  /* DEBUG */
-
-int
-man_domain_configure(void)
-{
-	int		status = 0;
-
-	/*
-	 * man_mbox_initialized is protected by inner perimiter lock.
-	 */
-	if (man_mbox_initialized == TRUE)
-		goto exit;
-
-	status = mboxsc_init(IOSRAM_KEY_SCMD, MBOXSC_MBOX_IN, NULL);
-
-	if (status != 0) {
-		cmn_err(CE_WARN, "man_domain_configure: failed to initialize"
-		    " MBOXSC_MBOX_IN, errno = %d", status);
-		goto exit;
-	}
-
-	status = mboxsc_init(IOSRAM_KEY_MDSC, MBOXSC_MBOX_OUT, NULL);
-	if (status != 0) {
-		(void) mboxsc_fini(IOSRAM_KEY_SCMD);
-		cmn_err(CE_WARN, "man_domain_configure: failed to initialize"
-		    " MBOXSC_MBOX_OUT, errno = %d", status);
-		goto exit;
-	}
-
-	man_mbox_initialized = TRUE;
-
-	status = man_path_discovery();
-	if (status != 0) {
-		(void) mboxsc_fini(IOSRAM_KEY_SCMD);
-		(void) mboxsc_fini(IOSRAM_KEY_MDSC);
-		man_mbox_initialized = FALSE;
-	}
-
-exit:
-	return (status);
-}
-
-/*
- * Build pathgroup connecting a domain to the SSC. Only called on domains
- * at first man_open. On the SSC, pathgroups are built by IOCTL requests
- * from the MAN daemon (see man_ioctl and mand(1M)).
- *
- * Locks held
- *	- exclusive innerperim.
- */
-int
-man_path_discovery(void)
-{
-	manc_t		manc;
-	mi_path_t	mpath;
-	int		num_devs;
-	int		status = 0;
-	int		i;
-
-	MAN_DBG(MAN_CONFIG, ("man_path_discovery:"));
-
-	if (status = man_get_iosram(&manc)) {
-		goto exit;
-	}
-
-	/*
-	 * If manc_ip_type indicates MAN network is not enabled
-	 * for this domain, then lets just bailout from here as if no
-	 * devices were found.
-	 */
-	if ((manc.manc_ip_type != AF_INET) &&
-	    (manc.manc_ip_type != AF_INET6)) {
-		goto exit;
-	}
-
-	MAN_DBGCALL(MAN_CONFIG, man_print_manc(&manc));
-
-	/*
-	 * Extract SC ethernet address from IOSRAM.
-	 */
-	ether_copy(&manc.manc_sc_eaddr, &mpath.mip_eaddr);
-
-	mpath.mip_pg_id = 0;	/* SC is always pathgroup ID 0 */
-	mpath.mip_man_ppa = 0;	/* Domain only has one ppa, 0 */
-
-	/*
-	 * Get list of present devices, and update man_paths[] as needed.
-	 */
-	num_devs = man_find_devs(&mpath, MAN_MAX_EXPANDERS);
-	if (num_devs <= 0) {
-		status = ENODEV;
-		goto exit;
-	}
-
-	mpath.mip_cmd = MI_PATH_ASSIGN;
-
-	mutex_enter(&man_lock);
-	status = man_pg_cmd(&mpath, NULL);
-	if (status) {
-		mutex_exit(&man_lock);
-		goto exit;
-	}
-
-	/*
-	 * Now activate the ethernet on the golden io board.
-	 */
-	for (i = 0; i < num_devs; i++) {
-		if (mpath.mip_devs[i].mdev_exp_id == manc.manc_golden_iob)
-			mpath.mip_devs[0] = mpath.mip_devs[i];
-	}
-	mpath.mip_ndevs = 1;
-	mpath.mip_cmd = MI_PATH_ACTIVATE;
-	status = man_pg_cmd(&mpath, NULL);
-	mutex_exit(&man_lock);
-
-exit:
-	MAN_DBG(MAN_CONFIG, ("man_path_discovery: returns %d\n", status));
-
-	return (status);
-}
-
-int
-man_domain_deconfigure(void)
-{
-
-	(void) mboxsc_fini(IOSRAM_KEY_SCMD);
-	(void) mboxsc_fini(IOSRAM_KEY_MDSC);
-	/*
-	 * We are about to unload and know that there are no open
-	 * streams, so this change outside of the perimiter is ok.
-	 */
-	man_mbox_initialized = FALSE;
-
-	return (0);
-}
-
-/*
- * Add a work request to the inner perimeter with the new eri device info.
- */
-/* ARGSUSED */
-int
-man_dr_attach(dev_info_t *dip)
-{
-	man_t		*manp;
-	man_work_t	*wp;
-	int		status = 0;
-	man_dev_t	mdev;
-
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, 0);
-	if (manp == NULL || manp->man_pg == NULL) {
-		goto exit;
-	}
-
-	if (man_get_eri_dev_info(dip, &mdev) == FALSE) {
-		status = ENODEV;
-		goto exit;
-	}
-	MAN_DBG(MAN_DR, ("man_dr_attach: dip major = %d instance =%d",
-	    mdev.mdev_major, mdev.mdev_ppa));
-	wp = man_work_alloc(MAN_WORK_DRATTACH, KM_NOSLEEP);
-	if (wp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-	wp->mw_arg.a_man_ppa = 0;	/* Domain only has one ppa, 0 */
-	wp->mw_arg.a_pg_id = 0;		/* SC is always pathgroup ID 0 */
-	wp->mw_arg.a_sf_dev = mdev;
-	wp->mw_flags = MAN_WFLAGS_NOWAITER;
-
-	man_work_add(man_iwork_q, wp);
-
-	if (man_ctl_wq)
-		qenable(man_ctl_wq);
-
-exit:
-	mutex_exit(&man_lock);
-
-	return (status);
-}
-
-int
-man_dr_detach(dev_info_t *dip)
-{
-	man_t		*manp;
-	int		status = 0;
-	int		retries = 0;
-
-
-	mutex_enter(&man_lock);
-	manp = ddi_get_soft_state(man_softstate, 0);
-	if (manp == NULL || manp->man_pg == NULL) {
-		mutex_exit(&man_lock);
-		goto exit;
-	}
-	mutex_exit(&man_lock);
-
-	/*
-	 * Arrange to have the detaching path switched if it is active.
-	 * We will cv_wait_sig for the switch to complete if it is needed.
-	 */
-again:
-	status = man_dr_submit_work_wait(dip, MAN_WORK_DRSWITCH);
-	if (status == EAGAIN && retries < manp->man_dr_retries) {
-		/*
-		 * Delay a bit and retry.
-		 */
-		MAN_DBG(MAN_DR,
-		    ("man_dr_detach(switch): EAGAIN - retrying..."));
-		retries++;
-		delay(drv_usectohz(manp->man_dr_delay));
-		goto again;
-	}
-
-	if (status)
-		goto exit;
-
-	retries = 0;
-
-	/*
-	 * Detaching device no longer in use, remove it from our
-	 * pathgroup.
-	 */
-	status = man_dr_submit_work_wait(dip, MAN_WORK_DRDETACH);
-	if (status == EAGAIN && retries < manp->man_dr_retries) {
-		MAN_DBG(MAN_DR,
-		    ("man_dr_detach(detach): EAGAIN - retrying..."));
-		retries++;
-		goto again;
-	}
-
-exit:
-	MAN_DBG(MAN_DR, ("man_dr_detach: returns %d", status));
-	return (status);
-}
-
-static int
-man_dr_submit_work_wait(dev_info_t *dip, int work_type)
-{
-	man_work_t	*wp;
-	int		status = 0;
-
-	wp = man_work_alloc(work_type, KM_NOSLEEP);
-	if (wp == NULL) {
-		status = ENOMEM;
-		goto exit;
-	}
-
-	wp->mw_arg.a_man_ppa = 0;
-	wp->mw_arg.a_pg_id = 0;
-	wp->mw_arg.a_sf_dev.mdev_major = ddi_driver_major(dip);
-	wp->mw_arg.a_sf_dev.mdev_ppa = ddi_get_instance(dip);
-
-	mutex_enter(&man_lock);
-	wp->mw_flags = MAN_WFLAGS_CVWAITER;
-	man_work_add(man_iwork_q, wp);
-
-	/* TBD - change to ASSERT ? */
-	if (man_ctl_wq)
-		qenable(man_ctl_wq);
-
-	while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
-		if (!cv_wait_sig(&wp->mw_cv, &man_lock)) {
-			wp->mw_flags &= ~MAN_WFLAGS_CVWAITER;
-			status = EINTR;
-			break;
-		}
-	}
-
-	/*
-	 * Note that if cv_wait_sig() returns zero because a signal
-	 * was received, MAN_WFLAGS_DONE may not be set.
-	 * This will happen if man_dr_submit_work_wait() reacquires
-	 * man_lock before man_iwork() can acquire man_lock just before
-	 * signalling its work is complete.
-	 * In this case, it is not necessary to call man_work_free()
-	 * here because it will be called by man_iwork() because
-	 * MAN_WFLAGS_CVWAITER was cleared.
-	 * Should man_iwork() obtain man_lock to signal completion,
-	 * MAN_WFLAGS_DONE will be set which will ensure man_work_free()
-	 * is called here.
-	 */
-	if (wp->mw_flags & MAN_WFLAGS_DONE) {
-		status = wp->mw_status;
-		man_work_free(wp);
-	}
-
-	mutex_exit(&man_lock);
-
-exit:
-	return (status);
-}
-
-/*
- * Notify SSC of switch request and wait for response.
- */
-int
-man_dossc_switch(uint32_t exp_id)
-{
-	uint64_t	req_tid;
-	uint32_t	req_cmd;
-	uint64_t	resp_tid;
-	uint32_t	resp_cmd;
-	uint32_t	type;
-	man_mbox_msg_t	req;
-	man_mbox_msg_t	resp;
-	uint32_t	length;
-	int		status = 0;
-
-	/*
-	 *  There should be nothing in inbound mailbox.
-	 */
-	resp_tid = resp_cmd = type = 0;
-	length = sizeof (man_mbox_msg_t);
-	bzero((char *)&resp, sizeof (man_mbox_msg_t));
-	while (mboxsc_getmsg(IOSRAM_KEY_SCMD, &type, &resp_cmd, &resp_tid,
-	    &length, &resp, 0) == 0) {
-
-		resp_tid = resp_cmd = type = 0;
-		length = sizeof (man_mbox_msg_t);
-		bzero((char *)&resp, sizeof (man_mbox_msg_t));
-
-		MAN_DBG(MAN_IOSRAM, ("man_dossc_switch: dumping message"));
-		MAN_DBG(MAN_IOSRAM, ("\tcommand = 0x%x", resp_cmd));
-	}
-
-	MAN_DBG(MAN_IOSRAM, ("man_dossc_switch: sending message"));
-
-	bzero((char *)&req, sizeof (man_mbox_msg_t));
-	req.mb_status = 0;
-	req.mb_exp_id = exp_id;
-	req_tid = 0;
-	req_cmd = MAN_WORK_SWITCH;
-
-	status = mboxsc_putmsg(IOSRAM_KEY_MDSC, MBOXSC_MSG_REQUEST,
-	    req_cmd, &req_tid, sizeof (man_mbox_msg_t), &req,
-	    MAN_IOSRAM_TIMEOUT);
-
-	if (status != 0) {
-		cmn_err(CE_WARN, "man_dossc_switch: mboxsc_putmsg failed,"
-		    " errno = %d", status);
-		goto exit;
-	}
-
-	bzero((char *)&resp, sizeof (man_mbox_msg_t));
-
-	resp_tid = type = resp_cmd = 0;
-	length = sizeof (man_mbox_msg_t);
-	status = mboxsc_getmsg(IOSRAM_KEY_SCMD, &type, &resp_cmd, &resp_tid,
-	    &length, (void *)&resp, MAN_IOSRAM_TIMEOUT);
-	if (status != 0) {
-		cmn_err(CE_WARN, "man_dossc_switch: mboxsc_getmsg failed,"
-		    " errno = %d", status);
-		goto exit;
-	}
-
-	MAN_DBG(MAN_IOSRAM, ("man_dossc_switch: received message"));
-
-	if (req_cmd != resp_cmd || req_tid != resp_tid) {
-		cmn_err(CE_WARN, "man_dossc_switch: failed,"
-		    " cmd/transid mismatch (%d, %d)/(%d, %d)",
-		    req_cmd, resp_cmd, (int)req_tid, (int)resp_tid);
-		status = EINVAL;
-		goto exit;
-	}
-
-	status = resp.mb_status;
-	if (status != 0) {
-		cmn_err(CE_WARN, "man_dossc_switch: failed errno == %d",
-		    status);
-	}
-exit:
-	return (status);
-}
-
-
-/*
- *  Read IOSRAM info.
- */
-int
-man_get_iosram(manc_t *mcp)
-{
-	int	status;
-
-	if (mcp == NULL)
-		return (EINVAL);
-
-	status = iosram_rd(IOSRAM_KEY_MANC, 0, sizeof (manc_t), (caddr_t)mcp);
-	if (status) {
-		cmn_err(CE_WARN, "man_get_iosram: iosram_rd failed"
-		    " errno = %d\n", status);
-		return (status);
-	}
-
-	MAN_DBG(MAN_PATH, ("man_get_iosram:"));
-	MAN_DBGCALL(MAN_PATH, man_print_manc(mcp));
-
-	if (mcp->manc_magic != IOSRAM_KEY_MANC) {
-		cmn_err(CE_WARN, "man_get_iosram: bad magic - got(0x%x)"
-		    " expected(0x%x)\n", mcp->manc_magic, IOSRAM_KEY_MANC);
-		status = EIO;
-	} else if (mcp->manc_version != MANC_VERSION) {
-		cmn_err(CE_WARN, "man_get_iosram: version mismatch -"
-		    " got(0x%x) expected(0x%x)\n", mcp->manc_version,
-		    MANC_VERSION);
-		status = EIO;
-	}
-
-	return (status);
-}
-
-#if defined(MAN_NO_IOSRAM)
-
-static manc_t	manc = {
-	IOSRAM_KEY_MANC,
-	MANC_VERSION,
-	0,
-	AF_INET,
-/*	0x10010102,		Two */
-	0x10010103,		/* Scot */
-	0xFF000000,		/* Scot netmask */
-	0x10010101,		/* SC 10.1.1.1 */
-	{0},	/* AF_INET6 addrs */
-	{0},	/* AF_INET6 addrs */
-	{0},
-/*	{0x8, 0x0, 0x20, 0x21, 0x44, 0x83},	Domain eaddr "two" */
-	{0x8, 0x0, 0x20, 0x8f, 0x84, 0x63},	/* Domain eaddr "scot" */
-	{0x8, 0x0, 0x20, 0x1f, 0xe3, 0x46},	/* SC eaddr "one" */
-	0x1,
-	0x1
-};
-
-
-/*
- *  Get IOSRAM info or release it.
- */
-int
-man_get_iosram(manc_t *mcp)
-{
-	int	status = 0;
-
-	if (mcp == NULL)
-		return (EINVAL);
-
-	*mcp = manc;
-
-	if (mcp->manc_magic != IOSRAM_KEY_MANC) {
-		cmn_err(CE_WARN, "man_get_iosram: bad magic - got(0x%x)"
-		    " expected(0x%x)\n", mcp->manc_magic, IOSRAM_KEY_MANC);
-		status = EIO;
-	} else if (mcp->manc_version != MANC_VERSION) {
-		cmn_err(CE_WARN, "man_get_iosram: version mismatch -"
-		    " got(0x%x) expected(0x%x)\n", mcp->manc_version,
-		    MANC_VERSION);
-		status = EIO;
-	}
-
-	return (status);
-}
-#endif  /* MAN_NO_IOSRAM */
-
-/*
- * Find all RIOs on the IO boards for the domain. We walk all the children
- * of the root node looking for a PCI devinfo with a safari port ID of
- * 0xDC that has a child with device ID of 3.  This is gauranteed to be
- * the network portion of the RIO by virtue of the way Starcats are
- * physically built.
- */
-static int
-man_find_devs(mi_path_t *mipathp, uchar_t golden_iob)
-{
-	dev_info_t	*bus_dip;
-	dev_info_t	*eri_dip;
-	dev_info_t	*rdip, *pdip;
-	int		exp_id;
-	int		found = 0;
-	int		circ;
-	int		circ2;
-	man_dev_t	ndev;
-	int		xmits;
-
-	MAN_DBG(MAN_PATH, ("man_find_devs: mdevpp(0x%p) golden_iob(%d)\n",
-	    (void *)(mipathp), golden_iob));
-
-	/*
-	 * Hold parent busy while walking its child list.
-	 */
-	rdip = ddi_root_node();
-	ndi_devi_enter(rdip, &circ);
-	bus_dip = ddi_get_child(rdip);
-
-	while (bus_dip != NULL) {
-		exp_id = -1;
-		xmits = 0;
-		if (man_dip_is_schizoxmits0_pcib(bus_dip, &exp_id, &xmits)) {
-			eri_dip = NULL;
-			pdip = bus_dip;
-			if (xmits) {
-				/*
-				 * If this is XMITS0 PCI_B leaf, then the
-				 * pci_pci bridge which is the only child,
-				 * is the parent to MAN RIO.
-				 */
-				pdip = ddi_get_child(bus_dip);
-				if (pdip == NULL) {
-					bus_dip = ddi_get_next_sibling(bus_dip);
-					continue;
-				}
-			}
-			ndi_devi_enter(pdip, &circ2);
-			eri_dip = ddi_get_child(pdip);
-			while (eri_dip != NULL) {
-				MAN_DBG(MAN_PATH, ("man_find_devs: "
-				    "eri_dip %s\n",
-				    ddi_binding_name(eri_dip)));
-				if (man_dip_is_eri(eri_dip, &ndev) &&
-				    man_dip_is_attached(eri_dip)) {
-
-					ASSERT(exp_id != -1);
-					ndev.mdev_exp_id = exp_id;
-					ndev.mdev_state = MDEV_ASSIGNED;
-					mipathp->mip_devs[found] = ndev;
-					found++;
-
-					MAN_DBG(MAN_PATH,
-					    ("man_find_devs: found eri maj(%d) "
-					    "ppa(%d) on expander(%d)\n",
-					    ndev.mdev_major,
-					    ndev.mdev_ppa, exp_id));
-				}
-				eri_dip = ddi_get_next_sibling(eri_dip);
-			}
-			ndi_devi_exit(pdip, circ2);
-		}
-		bus_dip = ddi_get_next_sibling(bus_dip);
-	}
-	ndi_devi_exit(rdip, circ);
-
-	MAN_DBG(MAN_PATH, ("man_find_devs returns found = %d\n", found));
-
-	mipathp->mip_ndevs = found;
-	return (found);
-}
-
-/*
- * Verify if the dip passed is an instance of 'eri' and set
- * the device info in mdevp.
- */
-static int
-man_get_eri_dev_info(dev_info_t *dip, man_dev_t *mdevp)
-{
-	dev_info_t	*parent_dip;
-	int		exp_id;
-	int		xmits;
-	char		*name;
-
-	ASSERT(dip != NULL);
-	/*
-	 * Verify if the parent is schizo(xmits)0 and pci B leaf.
-	 */
-	if (((parent_dip = ddi_get_parent(dip)) == NULL) ||
-	    ((name = ddi_binding_name(parent_dip)) == NULL))
-		return (FALSE);
-	if (strcmp(name, MAN_SCHIZO_BINDING_NAME) != 0) {
-		/*
-		 * This RIO could be on XMITS, so get the dip to
-		 * XMITS PCI Leaf.
-		 */
-		if ((parent_dip = ddi_get_parent(parent_dip)) == NULL)
-			return (FALSE);
-		if (((name = ddi_binding_name(parent_dip)) == NULL) ||
-		    (strcmp(name, MAN_XMITS_BINDING_NAME) != 0)) {
-			return (FALSE);
-		}
-	}
-	if (man_dip_is_schizoxmits0_pcib(parent_dip, &exp_id, &xmits) == FALSE)
-		return (FALSE);
-
-	/*
-	 * Make sure it is attached.
-	 */
-	if (man_dip_is_attached(dip) == FALSE) {
-		MAN_DBG(MAN_DR, ("man_get_eri_dev_info: "
-		    "dip 0x%p not attached\n", (void *)dip));
-		return (FALSE);
-	}
-	mdevp->mdev_exp_id = exp_id;
-	mdevp->mdev_ppa = ddi_get_instance(dip);
-	mdevp->mdev_major = ddi_driver_major(dip);
-	mdevp->mdev_state = MDEV_ASSIGNED;
-	return (TRUE);
-}
-
-/*
- * MAN RIO is connected to SCHIZO/XMITS 0 and PCI_B Leaf.
- * Incase of XMITS, it is actually connected to a PCI Bridge(21154)
- * which is directly connected to the PCI_B leaf of XMITS0.
- *
- * This function verifies if the given dip is SCHIZO/XMITS 0 and
- * PCI_B Leaf. This is done as follows:
- *
- * 	- Check the binding name to verify SCHIZO/XMITS.
- * 	- Verify the Device type to be "pci".
- *	- Verify the PortID to be ending with 0x1C
- * 	- Verify the the CSR base to be 0x70.0000.
- */
-static int
-man_dip_is_schizoxmits0_pcib(dev_info_t *dip, int *exp_id, int *xmits)
-{
-	char			dtype[MAN_DDI_BUFLEN];
-	int			portid;
-	uint_t			pci_csr_base;
-	struct pci_phys_spec	*regbuf = NULL;
-	int			length = MAN_DDI_BUFLEN;
-	char			*name;
-
-	ASSERT(dip != NULL);
-	*exp_id = -1;
-	if ((name = ddi_binding_name(dip)) == NULL)
-		return (FALSE);
-	if (strcmp(name, MAN_SCHIZO_BINDING_NAME) == 0) {
-		MAN_DBG(MAN_PATH, ("man_dip_is_schizoxmits0_pcib: "
-		    "SCHIZO found 0x%p\n", (void *)dip));
-	} else if (strcmp(name, MAN_XMITS_BINDING_NAME) == 0) {
-		*xmits = TRUE;
-		MAN_DBG(MAN_PATH, ("man_dip_is_schizoxmits0_pcib: "
-		    "XMITS found 0x%p\n", (void *)dip));
-	} else
-		return (FALSE);
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, MAN_DEVTYPE_PROP,
-	    (caddr_t)dtype, &length) == DDI_PROP_SUCCESS) {
-
-		MAN_DBG(MAN_PATH, ("dtype: %s\n", dtype));
-		if (strncmp(dtype, MAN_DEVTYPE_PCI, 3) != 0)
-			goto notfound;
-
-		/*
-		 * Get safari ID (DDI port ID).
-		 */
-		if ((portid = (int)ddi_getprop(DDI_DEV_T_ANY, dip, 0,
-		    MAN_PORTID_PROP, -1)) == -1) {
-
-			MAN_DBG(MAN_PATH, ("ddi_getpropp: failed\n"));
-			goto notfound;
-		}
-
-		/*
-		 * All schizo 0 safari IDs end in 0x1C.
-		 */
-		if ((portid & MAN_SCHIZO_MASK) != MAN_SCHIZO_0_ID)
-			goto notfound;
-
-		/*
-		 * All PCI nodes "B" are at configspace 0x70.0000
-		 */
-		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-		    MAN_REG_PROP, (caddr_t)&regbuf,
-		    &length) != DDI_PROP_SUCCESS) {
-
-			MAN_DBG(MAN_PATH, ("ddi_getlongprop_buf: failed"));
-			goto notfound;
-		}
-
-		pci_csr_base = regbuf[0].pci_phys_mid & PCI_CONF_ADDR_MASK;
-		kmem_free(regbuf, length);
-		if (pci_csr_base == MAN_PCI_B_CSR_BASE) {
-
-			MAN_DBG(MAN_PATH, ("man_dip_is_schizoxmits0_pcib:"
-			    " found PCI B at dip(0x%p)\n", (void *)dip));
-
-			*exp_id = portid >> 5;
-			return (TRUE);
-		}
-	}
-
-notfound:
-	return (FALSE);
-}
-
-static int
-man_dip_is_eri(dev_info_t *dip, man_dev_t *ndevp)
-{
-	struct pci_phys_spec	*regbuf = NULL;
-	int			length = 0;
-	uint_t			pci_device;
-	uint_t			pci_function;
-
-	MAN_DBG(MAN_PATH, ("man_dip_is_eri: dip(0x%p) ndevp(0x%p)\n",
-	    (void *)dip, (void *)ndevp));
-	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    MAN_REG_PROP, (caddr_t)&regbuf,
-	    &length) == DDI_PROP_SUCCESS) {
-
-		pci_device = PCI_REG_DEV_G(regbuf->pci_phys_hi);
-		pci_function = PCI_REG_FUNC_G(regbuf->pci_phys_hi);
-		kmem_free(regbuf, length);
-
-		/*
-		 * The network function of the RIO ASIC will always
-		 * be device 3 and function 1 ("network@3,1").
-		 */
-		if (pci_device == 3 && pci_function == 1) {
-			ndevp->mdev_ppa = ddi_get_instance(dip);
-			ndevp->mdev_major = ddi_driver_major(dip);
-
-			MAN_DBG(MAN_PATH, ("man_dip_is_eri: found eri maj(%d)"
-			    " ppa(%d)\n", ndevp->mdev_major, ndevp->mdev_ppa));
-
-			return (TRUE);
-		}
-	}
-
-	MAN_DBG(MAN_PATH, ("man_dip_is_eri: returns FALSE\n"));
-
-	return (FALSE);
-}
-
-static int
-man_dip_is_attached(dev_info_t *dip)
-{
-	int state;
-
-	state = ddi_get_devstate(dip);
-	if (i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP)) {
-		/*
-		 * The instance info is more important for us,
-		 * so verify.
-		 */
-		if (ddi_get_instance(dip) >=  0) {
-			return (TRUE);
-		}
-		cmn_err(CE_WARN, "man_dip_is_attached: "
-		    "eri 0x%p instance is not set yet", (void *)dip);
-
-	}
-	return (FALSE);
-}
-
-#if defined(DEBUG)
-static void
-man_print_manc(manc_t *mcp)
-{
-	cmn_err(CE_CONT, "\tmcp(0x%p)\n\n", (void *)mcp);
-
-	if (mcp == NULL)
-		return;
-
-	cmn_err(CE_CONT, "\tmagic: 0x%x\n", mcp->manc_magic);
-	cmn_err(CE_CONT, "\tversion: 0x%x\n", mcp->manc_version);
-	cmn_err(CE_CONT, "\tcsum: %d\n", mcp->manc_csum);
-	cmn_err(CE_CONT, "\tdom_eaddr: %s\n",
-	    ether_sprintf(&mcp->manc_dom_eaddr));
-	cmn_err(CE_CONT, "\tsc_eaddr: %s\n",
-	    ether_sprintf(&mcp->manc_sc_eaddr));
-	cmn_err(CE_CONT, "\tiob_bitmap: 0x%x\n", mcp->manc_iob_bitmap);
-	cmn_err(CE_CONT, "\tgolden_iob: %d\n", mcp->manc_golden_iob);
-
-}
-
-#endif  /* DEBUG */
--- a/usr/src/uts/sun4u/starcat/io/dr.conf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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) 2000 by Sun Microsystems, Inc.
-# All rights reserved.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-name="dr" parent="pseudo" instance=0;
--- a/usr/src/uts/sun4u/starcat/io/drmach.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8878 +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) 2016 by Delphix. All rights reserved.
- * Copyright 2019 Joyent, Inc.
- */
-
-#include <sys/note.h>
-#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/disp.h>
-#include <sys/processor.h>
-#include <sys/cheetahregs.h>
-#include <sys/cpuvar.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/mboxsc.h>
-#include <sys/plat_ecc_dimm.h>
-
-#include <sys/hotplug/hpctrl.h>		/* XXX should be included by schpc.h */
-#include <sys/schpc.h>
-#include <sys/pci.h>
-
-#include <sys/starcat.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/drmach.h>
-#include <sys/dr_util.h>
-#include <sys/dr_mbx.h>
-#include <sys/sc_gptwocfg.h>
-#include <sys/iosramreg.h>
-#include <sys/iosramio.h>
-#include <sys/iosramvar.h>
-#include <sys/axq.h>
-#include <sys/post/scat_dcd.h>
-#include <sys/kobj.h>
-#include <sys/taskq.h>
-#include <sys/cmp.h>
-#include <sys/sbd_ioctl.h>
-
-#include <sys/sysevent.h>
-#include <sys/sysevent/dr.h>
-#include <sys/sysevent/eventdefs.h>
-
-#include <sys/pci/pcisch.h>
-#include <sys/pci/pci_regs.h>
-
-#include <sys/ontrap.h>
-
-/* defined in ../ml/drmach.il.cpp */
-extern void		bcopy32_il(uint64_t, uint64_t);
-extern void		flush_ecache_il(int64_t physaddr, int size, int linesz);
-extern void		flush_dcache_il(void);
-extern void		flush_icache_il(void);
-extern void		flush_pcache_il(void);
-
-/* defined in ../ml/drmach_asm.s */
-extern uint64_t		lddmcdecode(uint64_t physaddr);
-extern uint64_t		lddsafconfig(void);
-
-/* XXX here until provided by sys/dman.h */
-extern int man_dr_attach(dev_info_t *);
-extern int man_dr_detach(dev_info_t *);
-
-#define	DRMACH_BNUM2EXP(bnum)		((bnum) >> 1)
-#define	DRMACH_BNUM2SLOT(bnum)		((bnum) & 1)
-#define	DRMACH_EXPSLOT2BNUM(exp, slot)	(((exp) << 1) + (slot))
-
-#define	DRMACH_SLICE_MASK		0x1Full
-#define	DRMACH_SLICE_TO_PA(s)		(((s) & DRMACH_SLICE_MASK) << 37)
-#define	DRMACH_PA_TO_SLICE(a)		(((a) >> 37) & DRMACH_SLICE_MASK)
-
-/*
- * DRMACH_MEM_SLICE_SIZE and DRMACH_MEM_USABLE_SLICE_SIZE define the
- * available address space and the usable address space for every slice.
- * There must be a distinction between the available and usable do to a
- * restriction imposed by CDC memory size.
- */
-
-#define	DRMACH_MEM_SLICE_SIZE		(1ull << 37)	/* 128GB */
-#define	DRMACH_MEM_USABLE_SLICE_SIZE	(1ull << 36)	/* 64GB */
-
-#define	DRMACH_MC_NBANKS		4
-
-#define	DRMACH_MC_ADDR(mp, bank)	((mp)->madr_pa + 16 + 8 * (bank))
-#define	DRMACH_MC_ASI_ADDR(mp, bank)	(DRMACH_MC_ADDR(mp, bank) & 0xFF)
-
-#define	DRMACH_EMU_ACT_STATUS_OFFSET	0x50
-#define	DRMACH_EMU_ACT_STATUS_ADDR(mp)	\
-	((mp)->madr_pa + DRMACH_EMU_ACT_STATUS_OFFSET)
-
-/*
- * The Cheetah's Safari Configuration Register and the Schizo's
- * Safari Control/Status Register place the LPA base and bound fields in
- * same bit locations with in their register word. This source code takes
- * advantage of this by defining only one set of LPA encoding/decoding macros
- * which are shared by various Cheetah and Schizo drmach routines.
- */
-#define	DRMACH_LPA_BASE_MASK		(0x3Full	<< 3)
-#define	DRMACH_LPA_BND_MASK		(0x3Full	<< 9)
-
-#define	DRMACH_LPA_BASE_TO_PA(scr)	(((scr) & DRMACH_LPA_BASE_MASK) << 34)
-#define	DRMACH_LPA_BND_TO_PA(scr)	(((scr) & DRMACH_LPA_BND_MASK) << 28)
-#define	DRMACH_PA_TO_LPA_BASE(pa)	(((pa) >> 34) & DRMACH_LPA_BASE_MASK)
-#define	DRMACH_PA_TO_LPA_BND(pa)	(((pa) >> 28) & DRMACH_LPA_BND_MASK)
-
-#define	DRMACH_L1_SET_LPA(b)		\
-	(((b)->flags & DRMACH_NULL_PROC_LPA) == 0)
-
-#define	DRMACH_CPU_SRAM_ADDR    	0x7fff0900000ull
-#define	DRMACH_CPU_SRAM_SIZE    	0x20000ull
-
-/*
- * Name properties for frequently accessed device nodes.
- */
-#define	DRMACH_CPU_NAMEPROP		"cpu"
-#define	DRMACH_CMP_NAMEPROP		"cmp"
-#define	DRMACH_AXQ_NAMEPROP		"address-extender-queue"
-#define	DRMACH_PCI_NAMEPROP		"pci"
-
-/*
- * Maximum value of processor Safari Timeout Log (TOL) field of
- * Safari Config reg (7 secs).
- */
-#define	DRMACH_SAF_TOL_MAX		7 * 1000000
-
-/*
- * drmach_board_t flag definitions
- */
-#define	DRMACH_NULL_PROC_LPA		0x1
-
-typedef struct {
-	uint32_t	reg_addr_hi;
-	uint32_t	reg_addr_lo;
-	uint32_t	reg_size_hi;
-	uint32_t	reg_size_lo;
-} drmach_reg_t;
-
-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));
-	dev_info_t	*(*n_getdip)(struct drmach_node *node);
-	int		 (*n_getproplen)(struct drmach_node *node, char *name,
-				int *len);
-	int		 (*n_getprop)(struct drmach_node *node, char *name,
-				void *buf, int len);
-	int		 (*get_parent)(struct drmach_node *node,
-				struct drmach_node *pnode);
-} drmach_node_t;
-
-typedef struct {
-	int		 min_index;
-	int		 max_index;
-	int		 arr_sz;
-	drmachid_t	*arr;
-} drmach_array_t;
-
-typedef struct {
-	void		*isa;
-
-	void		 (*dispose)(drmachid_t);
-	sbd_error_t	*(*release)(drmachid_t);
-	sbd_error_t	*(*status)(drmachid_t, drmach_status_t *);
-
-	char		 name[MAXNAMELEN];
-} drmach_common_t;
-
-struct drmach_board;
-typedef struct drmach_board drmach_board_t;
-
-typedef struct {
-	drmach_common_t	 cm;
-	const char	*type;
-	drmach_board_t	*bp;
-	drmach_node_t	*node;
-	int		 portid;
-	int		 unum;
-	int		 busy;
-	int		 powered;
-} drmach_device_t;
-
-typedef struct drmach_cpu {
-	drmach_device_t	 dev;
-	uint64_t	 scr_pa;
-	processorid_t	 cpuid;
-	int		 coreid;
-} drmach_cpu_t;
-
-typedef struct drmach_mem {
-	drmach_device_t	 dev;
-	struct drmach_mem *next;
-	uint64_t	 nbytes;
-	uint64_t	 madr_pa;
-} drmach_mem_t;
-
-typedef struct drmach_io {
-	drmach_device_t	 dev;
-	uint64_t	 scsr_pa; /* PA of Schizo Control/Status Register */
-} drmach_io_t;
-
-struct drmach_board {
-	drmach_common_t	 cm;
-	int		 bnum;
-	int		 assigned;
-	int		 powered;
-	int		 connected;
-	int		 empty;
-	int		 cond;
-	uint_t		 cpu_impl;
-	uint_t		 flags;
-	drmach_node_t	*tree;
-	drmach_array_t	*devices;
-	drmach_mem_t	*mem;
-	uint64_t	 stardrb_offset;
-	char		 type[BD_TYPELEN];
-};
-
-typedef struct {
-	int		 flags;
-	drmach_device_t	*dp;
-	sbd_error_t	*err;
-	dev_info_t	*fdip;
-} drmach_config_args_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;
-
-typedef struct drmach_casmslot {
-	int	valid;
-	int	slice;
-} drmach_casmslot_t;
-
-typedef enum {
-	DRMACH_CR_OK,
-	DRMACH_CR_MC_IDLE_ERR,
-	DRMACH_CR_IOPAUSE_ERR,
-	DRMACH_CR_ONTRAP_ERR
-} drmach_cr_err_t;
-
-typedef struct {
-	void		*isa;
-	caddr_t		 data;
-	drmach_mem_t	*s_mp;
-	drmach_mem_t	*t_mp;
-	struct memlist	*c_ml;
-	uint64_t	 s_copybasepa;
-	uint64_t	 t_copybasepa;
-	drmach_cr_err_t	 ecode;
-	void		*earg;
-} drmach_copy_rename_t;
-
-/*
- * The following global is read as a boolean value, non-zero is true.
- * If zero, DR copy-rename and cpu poweron will not set the processor
- * LPA settings (CBASE, CBND of Safari config register) to correspond
- * to the current memory slice map. LPAs of processors present at boot
- * will remain as programmed by POST. LPAs of processors on boards added
- * by DR will remain NULL, as programmed by POST. This can be used to
- * to override the per-board L1SSFLG_THIS_L1_NULL_PROC_LPA flag set by
- * POST in the LDCD (and copied to the GDCD by SMS).
- *
- * drmach_reprogram_lpa and L1SSFLG_THIS_L1_NULL_PROC_LPA do not apply
- * to Schizo device LPAs. These are always set by DR.
- */
-static int		 drmach_reprogram_lpa = 1;
-
-/*
- * There is a known HW bug where a Jaguar CPU in Safari port 0 (SBX/P0)
- * can fail to receive an XIR. To workaround this issue until a hardware
- * fix is implemented, we will exclude the selection of these CPUs.
- * Setting this to 0 will allow their selection again.
- */
-static int		 drmach_iocage_exclude_jaguar_port_zero = 1;
-
-static int		 drmach_initialized;
-static drmach_array_t	*drmach_boards;
-
-static int		 drmach_cpu_delay = 1000;
-static int		 drmach_cpu_ntries = 50000;
-
-static uint32_t		 drmach_slice_table[AXQ_MAX_EXP];
-static kmutex_t		 drmach_slice_table_lock;
-
-tte_t			 drmach_cpu_sram_tte[NCPU];
-caddr_t			 drmach_cpu_sram_va;
-
-/*
- * Setting to non-zero will enable delay before all disconnect ops.
- */
-static int		 drmach_unclaim_delay_all;
-/*
- * Default delay is slightly greater than the max processor Safari timeout.
- * This delay is intended to ensure the outstanding Safari activity has
- * retired on this board prior to a board disconnect.
- */
-static clock_t		 drmach_unclaim_usec_delay = DRMACH_SAF_TOL_MAX + 10;
-
-/*
- * By default, DR of non-Panther procs is not allowed into a Panther
- * domain with large page sizes enabled.  Setting this to 0 will remove
- * the restriction.
- */
-static int		 drmach_large_page_restriction = 1;
-
-/*
- * Used to pass updated LPA values to procs.
- * Protocol is to clear the array before use.
- */
-volatile uchar_t	*drmach_xt_mb;
-volatile uint64_t	 drmach_xt_ready;
-static kmutex_t		 drmach_xt_mb_lock;
-static int		 drmach_xt_mb_size;
-
-uint64_t		 drmach_bus_sync_list[18 * 4 * 4 + 1];
-static kmutex_t		 drmach_bus_sync_lock;
-
-static void		drmach_fini(void);
-
-static sbd_error_t	*drmach_device_new(drmach_node_t *,
-				drmach_board_t *, int, drmachid_t *);
-static sbd_error_t	*drmach_cpu_new(drmach_device_t *, drmachid_t *);
-static sbd_error_t	*drmach_mem_new(drmach_device_t *, drmachid_t *);
-static sbd_error_t	*drmach_pci_new(drmach_device_t *, drmachid_t *);
-static sbd_error_t	*drmach_io_new(drmach_device_t *, drmachid_t *);
-
-static sbd_error_t 	*drmach_board_release(drmachid_t);
-static sbd_error_t 	*drmach_board_status(drmachid_t, drmach_status_t *);
-
-static void 		drmach_cpu_dispose(drmachid_t);
-static sbd_error_t 	*drmach_cpu_release(drmachid_t);
-static sbd_error_t 	*drmach_cpu_status(drmachid_t, drmach_status_t *);
-
-static void 		drmach_mem_dispose(drmachid_t);
-static sbd_error_t 	*drmach_mem_release(drmachid_t);
-static sbd_error_t 	*drmach_mem_status(drmachid_t, drmach_status_t *);
-
-static dev_info_t	*drmach_node_ddi_get_dip(drmach_node_t *np);
-static int		 drmach_node_ddi_get_prop(drmach_node_t *np,
-				char *name, void *buf, int len);
-static int		 drmach_node_ddi_get_proplen(drmach_node_t *np,
-				char *name, int *len);
-
-static dev_info_t	*drmach_node_obp_get_dip(drmach_node_t *np);
-static int		 drmach_node_obp_get_prop(drmach_node_t *np,
-				char *name, void *buf, int len);
-static int		 drmach_node_obp_get_proplen(drmach_node_t *np,
-				char *name, int *len);
-
-static sbd_error_t	*drmach_mbox_trans(uint8_t msgtype, int bnum,
-				caddr_t obufp, int olen,
-				caddr_t ibufp, int ilen);
-
-sbd_error_t		*drmach_io_post_attach(drmachid_t id);
-sbd_error_t		*drmach_io_post_release(drmachid_t id);
-
-static sbd_error_t	*drmach_iocage_setup(dr_testboard_req_t *,
-				drmach_device_t **dpp, cpu_flag_t *oflags);
-static int		drmach_iocage_cpu_return(drmach_device_t *dp,
-				cpu_flag_t oflags);
-static sbd_error_t	*drmach_iocage_mem_return(dr_testboard_reply_t *tbr);
-void			drmach_iocage_mem_scrub(uint64_t nbytes);
-
-static sbd_error_t 	*drmach_i_status(drmachid_t id, drmach_status_t *stat);
-
-static void		drmach_slot1_lpa_set(drmach_board_t *bp);
-
-static void		drmach_cpu_read(uint64_t arg1, uint64_t arg2);
-static int		drmach_cpu_read_scr(drmach_cpu_t *cp, uint64_t *scr);
-
-static void		 drmach_bus_sync_list_update(void);
-static void		 drmach_slice_table_update(drmach_board_t *, int);
-static int		 drmach_portid2bnum(int);
-
-static void		drmach_msg_memslice_init(dr_memslice_t slice_arr[]);
-static void		drmach_msg_memregs_init(dr_memregs_t regs_arr[]);
-
-static int		drmach_panther_boards(void);
-
-static int		drmach_name2type_idx(char *);
-
-#ifdef DEBUG
-
-#define	DRMACH_PR		if (drmach_debug) printf
-#define	DRMACH_MEMLIST_DUMP	if (drmach_debug) MEMLIST_DUMP
-int drmach_debug = 0;		 /* set to non-zero to enable debug messages */
-#else
-
-#define	DRMACH_PR		_NOTE(CONSTANTCONDITION) if (0) printf
-#define	DRMACH_MEMLIST_DUMP	_NOTE(CONSTANTCONDITION) if (0) MEMLIST_DUMP
-#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_INTERNAL_ERROR() \
-	drerr_new(1, ESTC_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 *, drmachid_t *);
-} drmach_name2type[] = {
-	{"cmp",			    DRMACH_DEVTYPE_CMP,    NULL },
-	{"cpu",			    DRMACH_DEVTYPE_CPU,    drmach_cpu_new },
-	{"SUNW,UltraSPARC-III",	    DRMACH_DEVTYPE_CPU,    drmach_cpu_new },
-	{"SUNW,UltraSPARC-III+",    DRMACH_DEVTYPE_CPU,    drmach_cpu_new },
-	{"memory-controller",	    DRMACH_DEVTYPE_MEM,    drmach_mem_new },
-	{"pci",			    DRMACH_DEVTYPE_PCI,    drmach_pci_new },
-	{"SUNW,wci",		    DRMACH_DEVTYPE_WCI,    drmach_io_new  },
-};
-
-/*
- * drmach autoconfiguration data structures and interfaces
- */
-
-extern struct mod_ops mod_miscops;
-
-static struct modlmisc modlmisc = {
-	&mod_miscops,
-	"Sun Fire 15000 DR"
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modlmisc,
-	NULL
-};
-
-/*
- * drmach_boards_rwlock is used to synchronize read/write
- * access to drmach_boards array between status and board lookup
- * as READERS, and assign, and unassign threads as WRITERS.
- */
-static krwlock_t	drmach_boards_rwlock;
-
-static kmutex_t		drmach_i_lock;
-static kmutex_t		drmach_iocage_lock;
-static kcondvar_t 	drmach_iocage_cv;
-static int		drmach_iocage_is_busy = 0;
-uint64_t		drmach_iocage_paddr;
-static caddr_t		drmach_iocage_vaddr;
-static int		drmach_iocage_size = 0;
-static int		drmach_is_cheetah = -1;
-
-int
-_init(void)
-{
-	int	err;
-
-	mutex_init(&drmach_i_lock, NULL, MUTEX_DRIVER, NULL);
-	rw_init(&drmach_boards_rwlock, NULL, RW_DEFAULT, NULL);
-	drmach_xt_mb_size = NCPU * sizeof (uchar_t);
-	drmach_xt_mb = (uchar_t *)vmem_alloc(static_alloc_arena,
-	    drmach_xt_mb_size, VM_SLEEP);
-	bzero((void *)drmach_xt_mb, drmach_xt_mb_size);
-	if ((err = mod_install(&modlinkage)) != 0) {
-		mutex_destroy(&drmach_i_lock);
-		rw_destroy(&drmach_boards_rwlock);
-		vmem_free(static_alloc_arena, (void *)drmach_xt_mb,
-		    drmach_xt_mb_size);
-	}
-
-	return (err);
-}
-
-int
-_fini(void)
-{
-	int		err;
-
-	if ((err = mod_remove(&modlinkage)) == 0)
-		drmach_fini();
-
-	return (err);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-/*
- * drmach_node_* routines serve the purpose of separating the
- * rest of the code from the device tree and OBP.  This is necessary
- * because of In-Kernel-Probing.  Devices probed after stod, are probed
- * by the in-kernel-prober, not OBP.  These devices, therefore, do not
- * have dnode ids.
- */
-
-static int
-drmach_node_obp_get_parent(drmach_node_t *np, drmach_node_t *pp)
-{
-	pnode_t		nodeid;
-	static char	*fn = "drmach_node_obp_get_parent";
-
-	nodeid = np->get_dnode(np);
-	if (nodeid == OBP_NONODE) {
-		cmn_err(CE_WARN, "%s: invalid dnode", fn);
-		return (-1);
-	}
-
-	bcopy(np, pp, sizeof (drmach_node_t));
-
-	pp->here = (void *)(uintptr_t)prom_parentnode(nodeid);
-	if (pp->here == OBP_NONODE) {
-		cmn_err(CE_WARN, "%s: invalid parent dnode", fn);
-		return (-1);
-	}
-
-	return (0);
-}
-
-static pnode_t
-drmach_node_obp_get_dnode(drmach_node_t *np)
-{
-	return ((pnode_t)(uintptr_t)np->here);
-}
-
-typedef struct {
-	drmach_node_walk_args_t	*nwargs;
-	int 			(*cb)(drmach_node_walk_args_t *args);
-	int			err;
-} drmach_node_ddi_walk_args_t;
-
-int
-drmach_node_ddi_walk_cb(dev_info_t *dip, void *arg)
-{
-	drmach_node_ddi_walk_args_t	*nargs;
-
-	nargs = (drmach_node_ddi_walk_args_t *)arg;
-
-	/*
-	 * dip doesn't have to be held here as we are called
-	 * from ddi_walk_devs() which holds the dip.
-	 */
-	nargs->nwargs->node->here = (void *)dip;
-
-	nargs->err = nargs->cb(nargs->nwargs);
-
-	/*
-	 * Set "here" to NULL so that unheld dip is not accessible
-	 * outside ddi_walk_devs()
-	 */
-	nargs->nwargs->node->here = NULL;
-
-	if (nargs->err)
-		return (DDI_WALK_TERMINATE);
-	else
-		return (DDI_WALK_CONTINUE);
-}
-
-static int
-drmach_node_ddi_walk(drmach_node_t *np, void *data,
-		int (*cb)(drmach_node_walk_args_t *args))
-{
-	drmach_node_walk_args_t		args;
-	drmach_node_ddi_walk_args_t	nargs;
-
-	/* initialized args structure for callback */
-	args.node = np;
-	args.data = data;
-
-	nargs.nwargs = &args;
-	nargs.cb = cb;
-	nargs.err = 0;
-
-	/*
-	 * Root node doesn't have to be held in any way.
-	 */
-	ddi_walk_devs(ddi_root_node(), drmach_node_ddi_walk_cb, (void *)&nargs);
-
-	return (nargs.err);
-}
-
-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 within the tree */
-	np->here = (void *)(uintptr_t)nodeid;
-
-	rv = 0;
-	while (nodeid != OBP_NONODE) {
-
-		pnode_t child;
-
-		rv = (*cb)(&args);
-		if (rv)
-			break;
-
-		child = prom_childnode(nodeid);
-		np->here = (void *)(uintptr_t)child;
-
-		while (child != OBP_NONODE) {
-			rv = (*cb)(&args);
-			if (rv)
-				break;
-
-			child = prom_nextnode(child);
-			np->here = (void *)(uintptr_t)child;
-		}
-
-		nodeid = prom_nextnode(nodeid);
-
-		/* save our new position within the tree */
-		np->here = (void *)(uintptr_t)nodeid;
-	}
-
-	return (rv);
-}
-
-static int
-drmach_node_ddi_get_parent(drmach_node_t *np, drmach_node_t *pp)
-{
-	dev_info_t	*ndip;
-	static char	*fn = "drmach_node_ddi_get_parent";
-
-	ndip = np->n_getdip(np);
-	if (ndip == NULL) {
-		cmn_err(CE_WARN, "%s: NULL dip", fn);
-		return (-1);
-	}
-
-	bcopy(np, pp, sizeof (drmach_node_t));
-
-	pp->here = (void *)ddi_get_parent(ndip);
-	if (pp->here == NULL) {
-		cmn_err(CE_WARN, "%s: NULL parent dip", fn);
-		return (-1);
-	}
-
-	return (0);
-}
-
-/*ARGSUSED*/
-static pnode_t
-drmach_node_ddi_get_dnode(drmach_node_t *np)
-{
-	return ((pnode_t)NULL);
-}
-
-static drmach_node_t *
-drmach_node_new(void)
-{
-	drmach_node_t *np;
-
-	np = kmem_zalloc(sizeof (drmach_node_t), KM_SLEEP);
-
-	if (drmach_initialized) {
-		np->get_dnode = drmach_node_ddi_get_dnode;
-		np->walk = drmach_node_ddi_walk;
-		np->n_getdip = drmach_node_ddi_get_dip;
-		np->n_getproplen = drmach_node_ddi_get_proplen;
-		np->n_getprop = drmach_node_ddi_get_prop;
-		np->get_parent = drmach_node_ddi_get_parent;
-	} else {
-		np->get_dnode = drmach_node_obp_get_dnode;
-		np->walk = drmach_node_obp_walk;
-		np->n_getdip = drmach_node_obp_get_dip;
-		np->n_getproplen = drmach_node_obp_get_proplen;
-		np->n_getprop = drmach_node_obp_get_prop;
-		np->get_parent = drmach_node_obp_get_parent;
-	}
-
-	return (np);
-}
-
-static void
-drmach_node_dispose(drmach_node_t *np)
-{
-	kmem_free(np, sizeof (*np));
-}
-
-/*
- * Check if a CPU node is part of a CMP.
- */
-static int
-drmach_is_cmp_child(dev_info_t *dip)
-{
-	dev_info_t *pdip;
-
-	if (strcmp(ddi_node_name(dip), DRMACH_CPU_NAMEPROP) != 0) {
-		return (0);
-	}
-
-	pdip = ddi_get_parent(dip);
-
-	ASSERT(pdip);
-
-	if (strcmp(ddi_node_name(pdip), DRMACH_CMP_NAMEPROP) == 0) {
-		return (1);
-	}
-
-	return (0);
-}
-
-static dev_info_t *
-drmach_node_obp_get_dip(drmach_node_t *np)
-{
-	pnode_t		nodeid;
-	dev_info_t	*dip;
-
-	nodeid = np->get_dnode(np);
-	if (nodeid == OBP_NONODE)
-		return (NULL);
-
-	dip = e_ddi_nodeid_to_dip(nodeid);
-	if (dip) {
-		/*
-		 * The branch rooted at dip will have been previously
-		 * held, or it will be the child of a CMP. In either
-		 * case, the hold acquired in e_ddi_nodeid_to_dip()
-		 * is not needed.
-		 */
-		ddi_release_devi(dip);
-		ASSERT(drmach_is_cmp_child(dip) || e_ddi_branch_held(dip));
-	}
-
-	return (dip);
-}
-
-static dev_info_t *
-drmach_node_ddi_get_dip(drmach_node_t *np)
-{
-	return ((dev_info_t *)np->here);
-}
-
-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_ddi_get_prop(drmach_node_t *np, char *name, void *buf, int len)
-{
-	int		rv = 0;
-	dev_info_t	*ndip;
-	static char	*fn = "drmach_node_ddi_get_prop";
-
-	ndip = np->n_getdip(np);
-	if (ndip == NULL) {
-		cmn_err(CE_WARN, "%s: NULL dip", fn);
-		rv = -1;
-	} else if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ndip,
-	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, name,
-	    (caddr_t)buf, &len) != DDI_PROP_SUCCESS) {
-		rv = -1;
-	}
-
-	return (rv);
-}
-
-/* ARGSUSED */
-static int
-drmach_node_obp_get_prop(drmach_node_t *np, char *name, void *buf, int len)
-{
-	int		rv = 0;
-	pnode_t		nodeid;
-	static char	*fn = "drmach_node_obp_get_prop";
-
-	nodeid = np->get_dnode(np);
-	if (nodeid == OBP_NONODE) {
-		cmn_err(CE_WARN, "%s: invalid dnode", fn);
-		rv = -1;
-	} else if (prom_getproplen(nodeid, (caddr_t)name) < 0) {
-		rv = -1;
-	} else {
-		(void) prom_getprop(nodeid, (caddr_t)name, (caddr_t)buf);
-	}
-
-	return (rv);
-}
-
-static int
-drmach_node_ddi_get_proplen(drmach_node_t *np, char *name, int *len)
-{
-	int		rv = 0;
-	dev_info_t	*ndip;
-
-	ndip = np->n_getdip(np);
-	if (ndip == NULL) {
-		rv = -1;
-	} else if (ddi_getproplen(DDI_DEV_T_ANY, ndip, DDI_PROP_DONTPASS,
-	    name, len) != DDI_PROP_SUCCESS) {
-		rv = -1;
-	}
-
-	return (rv);
-}
-
-static int
-drmach_node_obp_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;
-	dup->get_dnode = np->get_dnode;
-	dup->walk = np->walk;
-	dup->n_getdip = np->n_getdip;
-	dup->n_getproplen = np->n_getproplen;
-	dup->n_getprop = np->n_getprop;
-	dup->get_parent = np->get_parent;
-
-	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);
-
-		/* clear the array entry */
-		rv = drmach_array_set(arr, idx, NULL);
-		ASSERT(rv == 0);
-
-		rv = drmach_array_next(arr, &idx, &val);
-	}
-
-	kmem_free(arr->arr, arr->arr_sz);
-	kmem_free(arr, sizeof (*arr));
-}
-
-
-static gdcd_t *
-drmach_gdcd_new()
-{
-	gdcd_t *gdcd;
-
-	gdcd = kmem_zalloc(sizeof (gdcd_t), KM_SLEEP);
-
-	/* read the gdcd, bail if magic or ver #s are not what is expected */
-	if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
-bail:
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (NULL);
-	} else if (gdcd->h.dcd_magic != GDCD_MAGIC) {
-		goto bail;
-	} else if (gdcd->h.dcd_version != DCD_VERSION) {
-		goto bail;
-	}
-
-	return (gdcd);
-}
-
-static void
-drmach_gdcd_dispose(gdcd_t *gdcd)
-{
-	kmem_free(gdcd, sizeof (gdcd_t));
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_configure(drmachid_t id, int flags)
-{
-	drmach_device_t	*dp;
-	dev_info_t	*rdip;
-	sbd_error_t	*err = NULL;
-
-	/*
-	 * On Starcat, there is no CPU driver, so it is
-	 * not necessary to configure any CPU nodes.
-	 */
-	if (DRMACH_IS_CPU_ID(id)) {
-		return (NULL);
-	}
-
-	for (; id; ) {
-		dev_info_t	*fdip = NULL;
-
-		if (!DRMACH_IS_DEVICE_ID(id))
-			return (drerr_new(0, ESTC_INAPPROP, NULL));
-		dp = id;
-
-		rdip = dp->node->n_getdip(dp->node);
-
-		/*
-		 * We held this branch earlier, so at a minimum its
-		 * root should still be present in the device tree.
-		 */
-		ASSERT(rdip);
-
-		DRMACH_PR("drmach_configure: configuring DDI branch");
-
-		ASSERT(e_ddi_branch_held(rdip));
-		if (e_ddi_branch_configure(rdip, &fdip, 0) != 0) {
-			if (err == NULL) {
-				/*
-				 * Record first failure but don't stop
-				 */
-				char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-				dev_info_t *dip = (fdip != NULL) ? fdip : rdip;
-
-				(void) ddi_pathname(dip, path);
-				err = drerr_new(1, ESTC_DRVFAIL, path);
-
-				kmem_free(path, MAXPATHLEN);
-			}
-
-			/*
-			 * If non-NULL, fdip is returned held and must be
-			 * released.
-			 */
-			if (fdip != NULL) {
-				ddi_release_devi(fdip);
-			}
-		}
-
-		if (DRMACH_IS_MEM_ID(id)) {
-			drmach_mem_t	*mp = id;
-			id = mp->next;
-		} else {
-			id = NULL;
-		}
-	}
-
-	return (err);
-}
-
-static sbd_error_t *
-drmach_device_new(drmach_node_t *node,
-	drmach_board_t *bp, int portid, drmachid_t *idp)
-{
-	int		i, rv, device_id, unum;
-	char		name[OBP_MAXDRVNAME];
-	drmach_device_t	proto;
-
-	rv = node->n_getprop(node, "name", name, OBP_MAXDRVNAME);
-	if (rv) {
-		sbd_error_t *err;
-
-		/* every node is expected to have a name */
-		err = drerr_new(1, ESTC_GETPROP,
-		    "dip: 0x%p: property %s",
-		    node->n_getdip(node), OBP_NAME);
-
-		return (err);
-	}
-
-	i = drmach_name2type_idx(name);
-
-	if (i < 0 || strcmp(name, "cmp") == 0) {
-		/*
-		 * Not a node of interest to dr - including "cmp",
-		 * but it is in drmach_name2type[], which lets gptwocfg
-		 * driver to check if node is OBP created.
-		 */
-		*idp = (drmachid_t)0;
-		return (NULL);
-	}
-
-	/*
-	 * Derive a best-guess unit number from the portid value.
-	 * Some drmach_*_new constructors (drmach_pci_new, for example)
-	 * will overwrite the prototype unum value with one that is more
-	 * appropriate for the device.
-	 */
-	device_id = portid & 0x1f;
-	if (device_id < 4)
-		unum = device_id;
-	else if (device_id == 8) {
-		unum = 0;
-	} else if (device_id == 9) {
-		unum = 1;
-	} else if (device_id == 0x1c) {
-		unum = 0;
-	} else if (device_id == 0x1d) {
-		unum = 1;
-	} else {
-		return (DRMACH_INTERNAL_ERROR());
-	}
-
-	bzero(&proto, sizeof (proto));
-	proto.type = drmach_name2type[i].type;
-	proto.bp = bp;
-	proto.node = node;
-	proto.portid = portid;
-	proto.unum = unum;
-
-	return (drmach_name2type[i].new(&proto, idp));
-}
-
-static void
-drmach_device_dispose(drmachid_t id)
-{
-	drmach_device_t *self = id;
-
-	self->cm.dispose(id);
-}
-
-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->tree = drmach_node_new();
-
-	(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;
-	caddr_t		obufp;
-	dr_showboard_t	shb;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	bp = id;
-
-	/*
-	 * we need to know if the board's connected before
-	 * issuing a showboard message.  If it's connected, we just
-	 * reply with status composed of cached info
-	 */
-
-	if (!bp->connected) {
-		obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-		err = drmach_mbox_trans(DRMSG_SHOWBOARD, bp->bnum, obufp,
-		    sizeof (dr_proto_hdr_t), (caddr_t)&shb,
-		    sizeof (dr_showboard_t));
-
-		kmem_free(obufp, sizeof (dr_proto_hdr_t));
-		if (err)
-			return (err);
-
-		bp->connected = (shb.bd_assigned && shb.bd_active);
-		(void) strncpy(bp->type, shb.board_type, sizeof (bp->type));
-		stat->assigned = bp->assigned = shb.bd_assigned;
-		stat->powered = bp->powered = shb.power_on;
-		stat->empty = bp->empty = shb.slot_empty;
-
-		switch (shb.test_status) {
-			case DR_TEST_STATUS_UNKNOWN:
-			case DR_TEST_STATUS_IPOST:
-			case DR_TEST_STATUS_ABORTED:
-				stat->cond = bp->cond = SBD_COND_UNKNOWN;
-				break;
-			case DR_TEST_STATUS_PASSED:
-				stat->cond = bp->cond = SBD_COND_OK;
-				break;
-			case DR_TEST_STATUS_FAILED:
-				stat->cond = bp->cond = SBD_COND_FAILED;
-				break;
-			default:
-				stat->cond = bp->cond = SBD_COND_UNKNOWN;
-				DRMACH_PR("Unknown test status=0x%x from SC\n",
-				    shb.test_status);
-				break;
-
-		}
-
-		(void) strncpy(stat->type, shb.board_type, sizeof (stat->type));
-		(void) snprintf(stat->info, sizeof (stat->info),
-		    "Test Level=%d", shb.test_level);
-	} else {
-		stat->assigned = bp->assigned;
-		stat->powered = bp->powered;
-		stat->empty = bp->empty;
-		stat->cond = bp->cond;
-		(void) strncpy(stat->type, bp->type, sizeof (stat->type));
-	}
-
-	stat->busy = 0;			/* assume not busy */
-	stat->configured = 0;		/* assume not configured */
-	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_i_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);
-}
-
-typedef struct drmach_msglist {
-	kcondvar_t		s_cv; 		/* condvar for sending msg */
-	kmutex_t		s_lock;		/* mutex for sending */
-	kcondvar_t		g_cv;		/* condvar for getting reply */
-	kmutex_t		g_lock;		/* mutex for getting reply */
-	struct drmach_msglist	*prev;		/* link to previous entry */
-	struct drmach_msglist	*next;		/* link to next entry */
-	struct drmach_msglist	*link;		/* link to related entry */
-	caddr_t			o_buf;		/* address of output buffer */
-	caddr_t			i_buf; 		/* address of input buffer */
-	uint32_t		o_buflen;	/* output buffer length */
-	uint32_t		i_buflen;	/* input buffer length */
-	uint32_t		msgid;		/* message identifier */
-	int			o_nretry;	/* number of sending retries */
-	int			f_error;	/* mailbox framework error */
-	uint8_t			e_code;		/* error code returned by SC */
-	uint8_t			p_flag	:1,	/* successfully putmsg */
-				m_reply	:1,	/* msg reply received */
-				unused	:6;
-} drmach_msglist_t;
-
-kmutex_t		drmach_g_mbox_mutex;	/* mutex for mailbox globals */
-kmutex_t		drmach_ri_mbox_mutex;	/* mutex for mailbox reinit */
-kmutex_t		drmach_msglist_mutex;	/* mutex for message list */
-drmach_msglist_t	*drmach_msglist_first;	/* first entry in msg list */
-drmach_msglist_t	*drmach_msglist_last;	/* last entry in msg list */
-uint32_t		drmach_msgid;		/* current message id */
-kthread_t		*drmach_getmsg_thread;	/* ptr to getmsg thread */
-volatile int		drmach_getmsg_thread_run; /* run flag for getmsg thr */
-kmutex_t		drmach_sendmsg_mutex;	/* mutex for sendmsg cv */
-kcondvar_t		drmach_sendmsg_cv;	/* signaled to send new msg */
-kthread_t		*drmach_sendmsg_thread; /* ptr to sendmsg thread */
-volatile int		drmach_sendmsg_thread_run; /* run flag for sendmsg */
-int			drmach_mbox_istate;	/* mailbox init state */
-int			drmach_mbox_iflag;	/* set if init'd with SC */
-int			drmach_mbox_ipending;	/* set if reinit scheduled */
-
-/*
- * Timeout values (in seconds) used when waiting for replies (from the SC) to
- * requests that we sent.  Since we only receive boardevent messages, and they
- * are events rather than replies, there is no boardevent timeout.
- */
-int	drmach_to_mbxinit	= 60;		/* 1 minute */
-int	drmach_to_assign	= 60;		/* 1 minute */
-int	drmach_to_unassign	= 60;		/* 1 minute */
-int	drmach_to_claim		= 3600;		/* 1 hour */
-int	drmach_to_unclaim	= 3600;		/* 1 hour */
-int	drmach_to_poweron	= 480;		/* 8 minutes */
-int	drmach_to_poweroff	= 480;		/* 8 minutes */
-int	drmach_to_testboard	= 43200;	/* 12 hours */
-int	drmach_to_aborttest	= 180;		/* 3 minutes */
-int	drmach_to_showboard	= 180;		/* 3 minutes */
-int	drmach_to_unconfig	= 180;		/* 3 minutes */
-
-/*
- * Delay (in seconds) used after receiving a non-transient error indication from
- * an mboxsc_getmsg call in the thread that loops waiting for incoming messages.
- */
-int	drmach_mbxerr_delay	= 15;		/* 15 seconds */
-
-/*
- * Timeout values (in milliseconds) for mboxsc_putmsg and mboxsc_getmsg calls.
- */
-clock_t	drmach_to_putmsg;			/* set in drmach_mbox_init */
-clock_t	drmach_to_getmsg	= 31000;	/* 31 seconds */
-
-/*
- * Normally, drmach_to_putmsg is set dynamically during initialization in
- * drmach_mbox_init.  This has the potentially undesirable side effect of
- * clobbering any value that might have been set in /etc/system.  To prevent
- * dynamic setting of drmach_to_putmsg (thereby allowing it to be tuned in
- * /etc/system), set drmach_use_tuned_putmsg_to to 1.
- */
-int	drmach_use_tuned_putmsg_to	= 0;
-
-
-/* maximum conceivable message size for future mailbox protocol versions */
-#define	DRMACH_MAX_MBOX_MSG_SIZE	4096
-
-/*ARGSUSED*/
-void
-drmach_mbox_prmsg(dr_mbox_msg_t *mbp, int dir)
-{
-	int		i, j;
-	dr_memregs_t	*memregs;
-	dr_proto_hdr_t	*php = &mbp->p_hdr;
-	dr_msg_t	*mp = &mbp->msgdata;
-
-#ifdef DEBUG
-	switch (php->command) {
-		case DRMSG_BOARDEVENT:
-			if (dir) {
-				DRMACH_PR("ERROR!! outgoing BOARDEVENT\n");
-			} else {
-				DRMACH_PR("BOARDEVENT received:\n");
-				DRMACH_PR("init=%d ins=%d rem=%d asgn=%d\n",
-				    mp->dm_be.initialized,
-				    mp->dm_be.board_insertion,
-				    mp->dm_be.board_removal,
-				    mp->dm_be.slot_assign);
-				DRMACH_PR("unasgn=%d avail=%d unavail=%d\n",
-				    mp->dm_be.slot_unassign,
-				    mp->dm_be.slot_avail,
-				    mp->dm_be.slot_unavail);
-			}
-			break;
-		case DRMSG_MBOX_INIT:
-			if (dir) {
-				DRMACH_PR("MBOX_INIT Request:\n");
-			} else {
-				DRMACH_PR("MBOX_INIT Reply:\n");
-			}
-			break;
-		case DRMSG_ASSIGN:
-			if (dir) {
-				DRMACH_PR("ASSIGN Request:\n");
-			} else {
-				DRMACH_PR("ASSIGN Reply:\n");
-			}
-			break;
-		case DRMSG_UNASSIGN:
-			if (dir) {
-				DRMACH_PR("UNASSIGN Request:\n");
-			} else {
-				DRMACH_PR("UNASSIGN Reply:\n");
-			}
-			break;
-		case DRMSG_CLAIM:
-			if (!dir) {
-				DRMACH_PR("CLAIM Reply:\n");
-				break;
-			}
-
-			DRMACH_PR("CLAIM Request:\n");
-			for (i = 0; i < 18; ++i) {
-				DRMACH_PR("exp%d: val=%d slice=0x%x\n", i,
-				    mp->dm_cr.mem_slice[i].valid,
-				    mp->dm_cr.mem_slice[i].slice);
-				memregs = &(mp->dm_cr.mem_regs[i]);
-				for (j = 0; j < S0_LPORT_COUNT; j++) {
-					DRMACH_PR("  MC %2d: "
-					    "MADR[%d] = 0x%lx, "
-					    "MADR[%d] = 0x%lx\n", j,
-					    0, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][0]),
-					    1, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][1]));
-					DRMACH_PR("       : "
-					    "MADR[%d] = 0x%lx, "
-					    "MADR[%d] = 0x%lx\n",
-					    2, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][2]),
-					    3, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][3]));
-				}
-			}
-			break;
-		case DRMSG_UNCLAIM:
-			if (!dir) {
-				DRMACH_PR("UNCLAIM Reply:\n");
-				break;
-			}
-
-			DRMACH_PR("UNCLAIM Request:\n");
-			for (i = 0; i < 18; ++i) {
-				DRMACH_PR("exp%d: val=%d slice=0x%x\n", i,
-				    mp->dm_ur.mem_slice[i].valid,
-				    mp->dm_ur.mem_slice[i].slice);
-				memregs = &(mp->dm_ur.mem_regs[i]);
-				for (j = 0; j < S0_LPORT_COUNT; j++) {
-					DRMACH_PR("  MC %2d: "
-					    "MADR[%d] = 0x%lx, "
-					    "MADR[%d] = 0x%lx\n", j,
-					    0, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][0]),
-					    1, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][1]));
-					DRMACH_PR("       : "
-					    "MADR[%d] = 0x%lx, "
-					    "MADR[%d] = 0x%lx\n",
-					    2, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][2]),
-					    3, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][3]));
-				}
-			}
-			DRMACH_PR(" mem_clear=%d\n", mp->dm_ur.mem_clear);
-			break;
-		case DRMSG_UNCONFIG:
-			if (!dir) {
-				DRMACH_PR("UNCONFIG Reply:\n");
-				break;
-			}
-
-			DRMACH_PR("UNCONFIG Request:\n");
-			for (i = 0; i < 18; ++i) {
-				DRMACH_PR("exp%d: val=%d slice=0x%x\n", i,
-				    mp->dm_uc.mem_slice[i].valid,
-				    mp->dm_uc.mem_slice[i].slice);
-				memregs = &(mp->dm_uc.mem_regs[i]);
-				for (j = 0; j < S0_LPORT_COUNT; j++) {
-					DRMACH_PR("  MC %2d: "
-					    "MADR[%d] = 0x%lx, "
-					    "MADR[%d] = 0x%lx\n", j,
-					    0, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][0]),
-					    1, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][1]));
-					DRMACH_PR("       : "
-					    "MADR[%d] = 0x%lx, "
-					    "MADR[%d] = 0x%lx\n",
-					    2, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][2]),
-					    3, DRMACH_MCREG_TO_U64(
-					    memregs->madr[j][3]));
-				}
-			}
-			break;
-		case DRMSG_POWERON:
-			if (dir) {
-				DRMACH_PR("POWERON Request:\n");
-			} else {
-				DRMACH_PR("POWERON Reply:\n");
-			}
-			break;
-		case DRMSG_POWEROFF:
-			if (dir) {
-				DRMACH_PR("POWEROFF Request:\n");
-			} else {
-				DRMACH_PR("POWEROFF Reply:\n");
-			}
-			break;
-		case DRMSG_TESTBOARD:
-			if (dir) {
-				DRMACH_PR("TESTBOARD Request:\n");
-				DRMACH_PR("\tmemaddrhi=0x%x memaddrlo=0x%x ",
-				    mp->dm_tb.memaddrhi,
-				    mp->dm_tb.memaddrlo);
-				DRMACH_PR("memlen=0x%x cpu_portid=0x%x\n",
-				    mp->dm_tb.memlen, mp->dm_tb.cpu_portid);
-				DRMACH_PR("\tforce=0x%x imm=0x%x\n",
-				    mp->dm_tb.force, mp->dm_tb.immediate);
-			} else {
-				DRMACH_PR("TESTBOARD Reply:\n");
-				DRMACH_PR("\tmemaddrhi=0x%x memaddrlo=0x%x ",
-				    mp->dm_tr.memaddrhi,
-				    mp->dm_tr.memaddrlo);
-				DRMACH_PR("memlen=0x%x cpu_portid=0x%x\n",
-				    mp->dm_tr.memlen, mp->dm_tr.cpu_portid);
-				DRMACH_PR("\trecovered=0x%x test status=0x%x\n",
-				    mp->dm_tr.cpu_recovered,
-				    mp->dm_tr.test_status);
-
-			}
-			break;
-		case DRMSG_ABORT_TEST:
-			if (dir) {
-				DRMACH_PR("ABORT_TEST Request:\n");
-			} else {
-				DRMACH_PR("ABORT_TEST Reply:\n");
-			}
-
-			DRMACH_PR("\tmemaddrhi=0x%x memaddrlo=0x%x ",
-			    mp->dm_ta.memaddrhi,
-			    mp->dm_ta.memaddrlo);
-			DRMACH_PR("memlen=0x%x cpu_portid=0x%x\n",
-			    mp->dm_ta.memlen, mp->dm_ta.cpu_portid);
-			break;
-		case DRMSG_SHOWBOARD:
-			if (dir) {
-				DRMACH_PR("SHOWBOARD Request:\n");
-			} else {
-				DRMACH_PR("SHOWBOARD Reply:\n");
-
-				DRMACH_PR(": empty=%d power=%d assigned=%d",
-				    mp->dm_sb.slot_empty,
-				    mp->dm_sb.power_on,
-				    mp->dm_sb.bd_assigned);
-				DRMACH_PR(": active=%d t_status=%d t_level=%d ",
-				    mp->dm_sb.bd_active,
-				    mp->dm_sb.test_status,
-				    mp->dm_sb.test_level);
-				DRMACH_PR(": type=%s ", mp->dm_sb.board_type);
-			}
-			break;
-		default:
-			DRMACH_PR("Unknown message type\n");
-			break;
-	}
-
-	DRMACH_PR("dr hdr:\n\tid=0x%x vers=0x%x cmd=0x%x exp=0x%x slot=0x%x\n",
-	    php->message_id, php->drproto_version, php->command,
-	    php->expbrd, php->slot);
-#endif
-	DRMACH_PR("\treply_status=0x%x error_code=0x%x\n", php->reply_status,
-	    php->error_code);
-}
-
-/*
- * Callback function passed to taskq_dispatch when a mailbox reinitialization
- * handshake needs to be scheduled.  The handshake can't be performed by the
- * thread that determines it is needed, in most cases, so this function is
- * dispatched on the system-wide taskq pool of threads.  Failure is reported but
- * otherwise ignored, since any situation that requires a mailbox initialization
- * handshake will continue to request the handshake until it succeeds.
- */
-static void
-drmach_mbox_reinit(void *unused)
-{
-	_NOTE(ARGUNUSED(unused))
-
-	caddr_t		obufp = NULL;
-	sbd_error_t	*serr = NULL;
-
-	DRMACH_PR("scheduled mailbox reinit running\n");
-
-	mutex_enter(&drmach_ri_mbox_mutex);
-	mutex_enter(&drmach_g_mbox_mutex);
-	if (drmach_mbox_iflag == 0) {
-		/* need to initialize the mailbox */
-		mutex_exit(&drmach_g_mbox_mutex);
-
-		cmn_err(CE_NOTE, "!reinitializing DR mailbox");
-		obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-		serr = drmach_mbox_trans(DRMSG_MBOX_INIT, 0, obufp,
-		    sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
-		kmem_free(obufp, sizeof (dr_proto_hdr_t));
-
-		if (serr) {
-			cmn_err(CE_WARN,
-			    "mbox_init: MBOX_INIT failed ecode=0x%x",
-			    serr->e_code);
-			sbd_err_clear(&serr);
-		}
-		mutex_enter(&drmach_g_mbox_mutex);
-		if (!serr) {
-			drmach_mbox_iflag = 1;
-		}
-	}
-	drmach_mbox_ipending = 0;
-	mutex_exit(&drmach_g_mbox_mutex);
-	mutex_exit(&drmach_ri_mbox_mutex);
-}
-
-/*
- * To ensure sufficient compatibility with future versions of the DR mailbox
- * protocol, we use a buffer that is large enough to receive the largest message
- * that could possibly be sent to us.  However, since that ends up being fairly
- * large, allocating it on the stack is a bad idea.  Fortunately, this function
- * does not need to be MT-safe since it is only invoked by the mailbox
- * framework, which will never invoke it multiple times concurrently.  Since
- * that is the case, we can use a static buffer.
- */
-void
-drmach_mbox_event(void)
-{
-	static uint8_t	buf[DRMACH_MAX_MBOX_MSG_SIZE];
-	dr_mbox_msg_t	*msg = (dr_mbox_msg_t *)buf;
-	int		err;
-	uint32_t	type = MBOXSC_MSG_EVENT;
-	uint32_t	command = DRMSG_BOARDEVENT;
-	uint64_t	transid = 0;
-	uint32_t	length = DRMACH_MAX_MBOX_MSG_SIZE;
-	char		*hint = "";
-	int		logsys = 0;
-
-	do {
-		err = mboxsc_getmsg(KEY_SCDR, &type, &command, &transid,
-		    &length, (void *)msg, 0);
-	} while (err == EAGAIN);
-
-	/* don't try to interpret anything with the wrong version number */
-	if ((err == 0) && (msg->p_hdr.drproto_version != DRMBX_VERSION)) {
-		cmn_err(CE_WARN, "mailbox version mismatch 0x%x vs 0x%x",
-		    msg->p_hdr.drproto_version, DRMBX_VERSION);
-		mutex_enter(&drmach_g_mbox_mutex);
-		drmach_mbox_iflag = 0;
-		/* schedule a reinit handshake if one isn't pending */
-		if (!drmach_mbox_ipending) {
-			if (taskq_dispatch(system_taskq, drmach_mbox_reinit,
-			    NULL, TQ_NOSLEEP) != TASKQID_INVALID) {
-				drmach_mbox_ipending = 1;
-			} else {
-				cmn_err(CE_WARN,
-				    "failed to schedule mailbox reinit");
-			}
-		}
-		mutex_exit(&drmach_g_mbox_mutex);
-		return;
-	}
-
-	if ((err != 0) || (msg->p_hdr.reply_status != DRMSG_REPLY_OK)) {
-		cmn_err(CE_WARN,
-		    "Unsolicited mboxsc_getmsg failed: err=0x%x code=0x%x",
-		    err, msg->p_hdr.error_code);
-	} else {
-		dr_boardevent_t	*be;
-		be = (dr_boardevent_t *)&msg->msgdata;
-
-		/* check for initialization event */
-		if (be->initialized) {
-			mutex_enter(&drmach_g_mbox_mutex);
-			drmach_mbox_iflag = 0;
-			/* schedule a reinit handshake if one isn't pending */
-			if (!drmach_mbox_ipending) {
-				if (taskq_dispatch(system_taskq,
-				    drmach_mbox_reinit, NULL, TQ_NOSLEEP)
-				    != TASKQID_INVALID) {
-					drmach_mbox_ipending = 1;
-				} else {
-					cmn_err(CE_WARN, "failed to schedule "
-					    "mailbox reinit");
-				}
-			}
-			mutex_exit(&drmach_g_mbox_mutex);
-			cmn_err(CE_NOTE, "!Mailbox Init event received");
-		}
-
-		/* anything else will be a log_sysevent call */
-
-		if (be->board_insertion) {
-			DRMACH_PR("Board Insertion event received");
-			hint = DR_HINT_INSERT;
-			logsys++;
-	}
-		if (be->board_removal) {
-			DRMACH_PR("Board Removal event received");
-			hint = DR_HINT_REMOVE;
-			logsys++;
-		}
-		if (be->slot_assign) {
-			DRMACH_PR("Slot Assign event received");
-			logsys++;
-		}
-		if (be->slot_unassign) {
-			DRMACH_PR("Slot Unassign event received");
-			logsys++;
-		}
-		if (be->slot_avail) {
-			DRMACH_PR("Slot Available event received");
-			logsys++;
-		}
-		if (be->slot_unavail) {
-			DRMACH_PR("Slot Unavailable event received");
-			logsys++;
-		}
-		if (be->power_on) {
-			DRMACH_PR("Power ON event received");
-			logsys++;
-		}
-		if (be->power_off) {
-			DRMACH_PR("Power OFF event received");
-			logsys++;
-		}
-
-		if (logsys)
-			(void) drmach_log_sysevent(
-			    DRMACH_EXPSLOT2BNUM(msg->p_hdr.expbrd,
-			    msg->p_hdr.slot), hint, SE_NOSLEEP, 1);
-	}
-}
-
-static uint32_t
-drmach_get_msgid()
-{
-	uint32_t	rv;
-	mutex_enter(&drmach_msglist_mutex);
-	if (!(++drmach_msgid))
-		++drmach_msgid;
-	rv = drmach_msgid;
-	mutex_exit(&drmach_msglist_mutex);
-	return (rv);
-}
-
-/*
- *	unlink an entry from the message transaction list
- *
- *	caller must hold drmach_msglist_mutex
- */
-void
-drmach_msglist_unlink(drmach_msglist_t *entry)
-{
-	ASSERT(mutex_owned(&drmach_msglist_mutex));
-	if (entry->prev) {
-		entry->prev->next = entry->next;
-		if (entry->next)
-			entry->next->prev = entry->prev;
-	} else {
-		drmach_msglist_first = entry->next;
-		if (entry->next)
-			entry->next->prev = NULL;
-	}
-	if (entry == drmach_msglist_last) {
-		drmach_msglist_last = entry->prev;
-	}
-}
-
-void
-drmach_msglist_link(drmach_msglist_t *entry)
-{
-	mutex_enter(&drmach_msglist_mutex);
-	if (drmach_msglist_last) {
-		entry->prev = drmach_msglist_last;
-		drmach_msglist_last->next = entry;
-		drmach_msglist_last = entry;
-	} else {
-		drmach_msglist_last = drmach_msglist_first = entry;
-	}
-	mutex_exit(&drmach_msglist_mutex);
-}
-
-void
-drmach_mbox_getmsg()
-{
-	int			err;
-	register int		msgid;
-	static uint8_t		buf[DRMACH_MAX_MBOX_MSG_SIZE];
-	dr_mbox_msg_t		*msg = (dr_mbox_msg_t *)buf;
-	dr_proto_hdr_t		*php;
-	drmach_msglist_t	*found, *entry;
-	uint32_t		type = MBOXSC_MSG_REPLY;
-	uint32_t		command;
-	uint64_t		transid;
-	uint32_t		length;
-
-	php = &msg->p_hdr;
-
-	while (drmach_getmsg_thread_run != 0) {
-		/* get a reply message */
-		command = 0;
-		transid = 0;
-		length = DRMACH_MAX_MBOX_MSG_SIZE;
-		err = mboxsc_getmsg(KEY_SCDR, &type, &command, &transid,
-		    &length, (void *)msg, drmach_to_getmsg);
-
-		if (err) {
-			/*
-			 * If mboxsc_getmsg returns ETIMEDOUT or EAGAIN, then
-			 * the "error" is really just a normal, transient
-			 * condition and we can retry the operation right away.
-			 * Any other error suggests a more serious problem,
-			 * ranging from a message being too big for our buffer
-			 * (EMSGSIZE) to total failure of the mailbox layer.
-			 * This second class of errors is much less "transient",
-			 * so rather than retrying over and over (and getting
-			 * the same error over and over) as fast as we can,
-			 * we'll sleep for a while before retrying.
-			 */
-			if ((err != ETIMEDOUT) && (err != EAGAIN)) {
-				cmn_err(CE_WARN,
-				    "mboxsc_getmsg failed, err=0x%x", err);
-				delay(drmach_mbxerr_delay * hz);
-			}
-			continue;
-		}
-
-		drmach_mbox_prmsg(msg, 0);
-
-		if (php->drproto_version != DRMBX_VERSION) {
-			cmn_err(CE_WARN,
-			    "mailbox version mismatch 0x%x vs 0x%x",
-			    php->drproto_version, DRMBX_VERSION);
-
-			mutex_enter(&drmach_g_mbox_mutex);
-			drmach_mbox_iflag = 0;
-			/* schedule a reinit handshake if one isn't pending */
-			if (!drmach_mbox_ipending) {
-				if (taskq_dispatch(system_taskq,
-				    drmach_mbox_reinit, NULL, TQ_NOSLEEP)
-				    != TASKQID_INVALID) {
-					drmach_mbox_ipending = 1;
-				} else {
-					cmn_err(CE_WARN, "failed to schedule "
-					    "mailbox reinit");
-				}
-			}
-			mutex_exit(&drmach_g_mbox_mutex);
-
-			continue;
-		}
-
-		msgid = php->message_id;
-		found = NULL;
-		mutex_enter(&drmach_msglist_mutex);
-		entry = drmach_msglist_first;
-		while (entry != NULL) {
-			if (entry->msgid == msgid) {
-				found = entry;
-				drmach_msglist_unlink(entry);
-				entry = NULL;
-			} else
-				entry = entry->next;
-		}
-
-		if (found) {
-			mutex_enter(&found->g_lock);
-
-			found->e_code = php->error_code;
-			if (found->i_buflen > 0)
-				bcopy((caddr_t)&msg->msgdata, found->i_buf,
-				    found->i_buflen);
-			found->m_reply = 1;
-
-			cv_signal(&found->g_cv);
-			mutex_exit(&found->g_lock);
-		} else {
-			cmn_err(CE_WARN, "!mbox_getmsg: no match for id 0x%x",
-			    msgid);
-			cmn_err(CE_WARN, "!    cmd = 0x%x, exb = %d, slot = %d",
-			    php->command, php->expbrd, php->slot);
-		}
-
-		mutex_exit(&drmach_msglist_mutex);
-	}
-	cmn_err(CE_WARN, "mbox_getmsg: exiting");
-	mutex_enter(&drmach_msglist_mutex);
-	entry = drmach_msglist_first;
-	while (entry != NULL) {
-		if (entry->p_flag == 1) {
-			entry->f_error = -1;
-			mutex_enter(&entry->g_lock);
-			cv_signal(&entry->g_cv);
-			mutex_exit(&entry->g_lock);
-			drmach_msglist_unlink(entry);
-		}
-		entry = entry->next;
-	}
-	mutex_exit(&drmach_msglist_mutex);
-	drmach_getmsg_thread_run = -1;
-	thread_exit();
-}
-
-void
-drmach_mbox_sendmsg()
-{
-	int		err, retry;
-	drmach_msglist_t *entry;
-	dr_mbox_msg_t   *mp;
-	dr_proto_hdr_t  *php;
-
-	while (drmach_sendmsg_thread_run != 0) {
-		/*
-		 * Search through the list to find entries awaiting
-		 * transmission to the SC
-		 */
-		mutex_enter(&drmach_msglist_mutex);
-		entry = drmach_msglist_first;
-		retry = 0;
-		while (entry != NULL) {
-			if (entry->p_flag == 1) {
-				entry = entry->next;
-				continue;
-			}
-
-			mutex_exit(&drmach_msglist_mutex);
-
-			if (!retry)
-				mutex_enter(&entry->s_lock);
-			mp = (dr_mbox_msg_t *)entry->o_buf;
-			php = &mp->p_hdr;
-
-			drmach_mbox_prmsg(mp, 1);
-
-			err = mboxsc_putmsg(KEY_DRSC, MBOXSC_MSG_REQUEST,
-			    php->command, NULL, entry->o_buflen, (void *)mp,
-			    drmach_to_putmsg);
-
-			if (err) {
-				switch (err) {
-
-				case EAGAIN:
-				case EBUSY:
-					++retry;
-					mutex_enter(&drmach_msglist_mutex);
-					continue;
-
-				case ETIMEDOUT:
-					if (--entry->o_nretry <= 0) {
-						mutex_enter(
-						    &drmach_msglist_mutex);
-						drmach_msglist_unlink(entry);
-						mutex_exit(
-						    &drmach_msglist_mutex);
-						entry->f_error = err;
-						entry->p_flag = 1;
-						cv_signal(&entry->s_cv);
-					} else {
-						++retry;
-						mutex_enter(
-						    &drmach_msglist_mutex);
-						continue;
-					}
-					break;
-				default:
-					mutex_enter(&drmach_msglist_mutex);
-					drmach_msglist_unlink(entry);
-					mutex_exit(&drmach_msglist_mutex);
-					entry->f_error = err;
-					entry->p_flag = 1;
-					cv_signal(&entry->s_cv);
-					break;
-				}
-			} else {
-				entry->p_flag = 1;
-				cv_signal(&entry->s_cv);
-			}
-
-			mutex_exit(&entry->s_lock);
-			retry = 0;
-			mutex_enter(&drmach_msglist_mutex);
-			entry = drmach_msglist_first;
-		}
-		mutex_exit(&drmach_msglist_mutex);
-
-		mutex_enter(&drmach_sendmsg_mutex);
-		(void) cv_reltimedwait(&drmach_sendmsg_cv,
-		    &drmach_sendmsg_mutex, (5 * hz), TR_CLOCK_TICK);
-		mutex_exit(&drmach_sendmsg_mutex);
-	}
-	cmn_err(CE_WARN, "mbox_sendmsg: exiting");
-	mutex_enter(&drmach_msglist_mutex);
-	entry = drmach_msglist_first;
-	while (entry != NULL) {
-		if (entry->p_flag == 0) {
-			entry->f_error = -1;
-			mutex_enter(&entry->s_lock);
-			cv_signal(&entry->s_cv);
-			mutex_exit(&entry->s_lock);
-			drmach_msglist_unlink(entry);
-		}
-		entry = entry->next;
-	}
-	mutex_exit(&drmach_msglist_mutex);
-	cv_destroy(&drmach_sendmsg_cv);
-	mutex_destroy(&drmach_sendmsg_mutex);
-
-	drmach_sendmsg_thread_run = -1;
-	thread_exit();
-}
-
-void
-drmach_msglist_destroy(drmach_msglist_t *listp)
-{
-	if (listp != NULL) {
-		drmach_msglist_t	*entry;
-
-		mutex_enter(&drmach_msglist_mutex);
-		entry = drmach_msglist_first;
-		while (entry) {
-			if (listp == entry) {
-				drmach_msglist_unlink(listp);
-				entry = NULL;
-			} else
-				entry = entry->next;
-		}
-
-		mutex_destroy(&listp->s_lock);
-		cv_destroy(&listp->s_cv);
-		mutex_destroy(&listp->g_lock);
-		cv_destroy(&listp->g_cv);
-		kmem_free(listp, sizeof (drmach_msglist_t));
-
-		mutex_exit(&drmach_msglist_mutex);
-	}
-}
-
-static drmach_msglist_t	*
-drmach_msglist_new(caddr_t ibufp, uint32_t ilen, dr_proto_hdr_t *hdrp,
-	uint32_t olen, int nrtry)
-{
-	drmach_msglist_t	*listp;
-
-	listp = kmem_zalloc(sizeof (drmach_msglist_t), KM_SLEEP);
-	mutex_init(&listp->s_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&listp->s_cv, NULL, CV_DRIVER, NULL);
-	mutex_init(&listp->g_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&listp->g_cv, NULL, CV_DRIVER, NULL);
-	listp->o_buf = (caddr_t)hdrp;
-	listp->o_buflen = olen;
-	listp->i_buf = ibufp;
-	listp->i_buflen = ilen;
-	listp->o_nretry = nrtry;
-	listp->msgid = hdrp->message_id;
-
-	return (listp);
-}
-
-static drmach_msglist_t *
-drmach_mbox_req_rply(dr_proto_hdr_t *hdrp, uint32_t olen, caddr_t ibufp,
-	uint32_t ilen, int timeout, int nrtry, int nosig,
-	drmach_msglist_t *link)
-{
-	int		crv;
-	drmach_msglist_t *listp;
-	clock_t		to_val;
-	dr_proto_hdr_t	*php;
-
-	/* setup transaction list entry */
-	listp = drmach_msglist_new(ibufp, ilen, hdrp, olen, nrtry);
-
-	/* send mailbox message, await reply */
-	mutex_enter(&listp->s_lock);
-	mutex_enter(&listp->g_lock);
-
-	listp->link = link;
-	drmach_msglist_link(listp);
-
-	mutex_enter(&drmach_sendmsg_mutex);
-	cv_signal(&drmach_sendmsg_cv);
-	mutex_exit(&drmach_sendmsg_mutex);
-
-	while (listp->p_flag == 0) {
-		cv_wait(&listp->s_cv, &listp->s_lock);
-	}
-
-	to_val = ddi_get_lbolt() + (timeout * hz);
-
-	if (listp->f_error) {
-		listp->p_flag = 0;
-		cmn_err(CE_WARN, "!mboxsc_putmsg failed: 0x%x", listp->f_error);
-		php = (dr_proto_hdr_t *)listp->o_buf;
-		cmn_err(CE_WARN, "!    cmd = 0x%x, exb = %d, slot = %d",
-		    php->command, php->expbrd, php->slot);
-	} else {
-		while (listp->m_reply == 0 && listp->f_error == 0) {
-			if (nosig)
-				crv = cv_timedwait(&listp->g_cv, &listp->g_lock,
-				    to_val);
-			else
-				crv = cv_timedwait_sig(&listp->g_cv,
-				    &listp->g_lock, to_val);
-			switch (crv) {
-				case -1: /* timed out */
-					cmn_err(CE_WARN,
-					    "!msgid=0x%x reply timed out",
-					    hdrp->message_id);
-					php = (dr_proto_hdr_t *)listp->o_buf;
-					cmn_err(CE_WARN, "!    cmd = 0x%x, "
-					    "exb = %d, slot = %d", php->command,
-					    php->expbrd, php->slot);
-					listp->f_error = ETIMEDOUT;
-					break;
-				case 0: /* signal received */
-					cmn_err(CE_WARN,
-					    "operation interrupted by signal");
-					listp->f_error = EINTR;
-					break;
-				default:
-					break;
-				}
-		}
-
-		/*
-		 * If link is set for this entry, check to see if
-		 * the linked entry has been replied to.  If not,
-		 * wait for the response.
-		 * Currently, this is only used for ABORT_TEST functionality,
-		 * wherein a check is made for the TESTBOARD reply when
-		 * the ABORT_TEST reply is received.
-		 */
-
-		if (link) {
-			mutex_enter(&link->g_lock);
-			/*
-			 * If the reply to the linked entry hasn't been
-			 * received, clear the existing link->f_error,
-			 * and await the reply.
-			 */
-			if (link->m_reply == 0) {
-				link->f_error = 0;
-			}
-			to_val =  ddi_get_lbolt() + (timeout * hz);
-			while (link->m_reply == 0 && link->f_error == 0) {
-				crv = cv_timedwait(&link->g_cv, &link->g_lock,
-				    to_val);
-				switch (crv) {
-				case -1: /* timed out */
-					cmn_err(CE_NOTE,
-					    "!link msgid=0x%x reply timed out",
-					    link->msgid);
-					link->f_error = ETIMEDOUT;
-					break;
-				default:
-					break;
-				}
-			}
-			mutex_exit(&link->g_lock);
-		}
-	}
-	mutex_exit(&listp->g_lock);
-	mutex_exit(&listp->s_lock);
-	return (listp);
-}
-
-static sbd_error_t *
-drmach_mbx2sbderr(drmach_msglist_t *mlp)
-{
-	char		a_pnt[MAXNAMELEN];
-	dr_proto_hdr_t	*php;
-	int		bnum;
-
-	if (mlp->f_error) {
-		/*
-		 * If framework failure is due to signal, return "no error"
-		 * error.
-		 */
-		if (mlp->f_error == EINTR)
-			return (drerr_new(0, ESTC_NONE, NULL));
-
-		mutex_enter(&drmach_g_mbox_mutex);
-		drmach_mbox_iflag = 0;
-		mutex_exit(&drmach_g_mbox_mutex);
-		if (!mlp->p_flag)
-			return (drerr_new(1, ESTC_MBXRQST, NULL));
-		else
-			return (drerr_new(1, ESTC_MBXRPLY, NULL));
-	}
-	php = (dr_proto_hdr_t *)mlp->o_buf;
-	bnum = 2 * php->expbrd + php->slot;
-	a_pnt[0] = '\0';
-	(void) drmach_board_name(bnum, a_pnt, MAXNAMELEN);
-
-	switch (mlp->e_code) {
-		case 0:
-			return (NULL);
-		case DRERR_NOACL:
-			return (drerr_new(0, ESTC_NOACL, "%s", a_pnt));
-		case DRERR_NOT_ASSIGNED:
-			return (drerr_new(0, ESTC_NOT_ASSIGNED, "%s", a_pnt));
-		case DRERR_NOT_ACTIVE:
-			return (drerr_new(0, ESTC_NOT_ACTIVE, "%s", a_pnt));
-		case DRERR_EMPTY_SLOT:
-			return (drerr_new(0, ESTC_EMPTY_SLOT, "%s", a_pnt));
-		case DRERR_POWER_OFF:
-			return (drerr_new(0, ESTC_POWER_OFF, "%s", a_pnt));
-		case DRERR_TEST_IN_PROGRESS:
-			return (drerr_new(0, ESTC_TEST_IN_PROGRESS, "%s",
-			    a_pnt));
-		case DRERR_TESTING_BUSY:
-			return (drerr_new(0, ESTC_TESTING_BUSY, "%s", a_pnt));
-		case DRERR_TEST_REQUIRED:
-			return (drerr_new(0, ESTC_TEST_REQUIRED, "%s", a_pnt));
-		case DRERR_UNAVAILABLE:
-			return (drerr_new(0, ESTC_UNAVAILABLE, "%s", a_pnt));
-		case DRERR_RECOVERABLE:
-			return (drerr_new(0, ESTC_SMS_ERR_RECOVERABLE, "%s",
-			    a_pnt));
-		case DRERR_UNRECOVERABLE:
-			return (drerr_new(1, ESTC_SMS_ERR_UNRECOVERABLE, "%s",
-			    a_pnt));
-		default:
-			return (drerr_new(1, ESTC_MBOX_UNKNOWN, NULL));
-	}
-}
-
-static sbd_error_t *
-drmach_mbox_trans(uint8_t msgtype, int bnum, caddr_t obufp, int olen,
-	caddr_t ibufp, int ilen)
-{
-	int			timeout = 0;
-	int			ntries = 0;
-	int			nosignals = 0;
-	dr_proto_hdr_t 		*hdrp;
-	drmach_msglist_t 	*mlp;
-	sbd_error_t		*err = NULL;
-
-	if (msgtype != DRMSG_MBOX_INIT) {
-		mutex_enter(&drmach_ri_mbox_mutex);
-		mutex_enter(&drmach_g_mbox_mutex);
-		if (drmach_mbox_iflag == 0) {
-			/* need to initialize the mailbox */
-			dr_proto_hdr_t	imsg;
-
-			mutex_exit(&drmach_g_mbox_mutex);
-
-			imsg.command = DRMSG_MBOX_INIT;
-
-			imsg.message_id = drmach_get_msgid();
-			imsg.drproto_version = DRMBX_VERSION;
-			imsg.expbrd = 0;
-			imsg.slot = 0;
-
-			cmn_err(CE_WARN, "!reinitializing DR mailbox");
-			mlp = drmach_mbox_req_rply(&imsg, sizeof (imsg), 0, 0,
-			    10, 5, 0, NULL);
-			err = drmach_mbx2sbderr(mlp);
-			/*
-			 * If framework failure incoming is encountered on
-			 * the MBOX_INIT [timeout on SMS reply], the error
-			 * type must be changed before returning to caller.
-			 * This is to prevent drmach_board_connect() and
-			 * drmach_board_disconnect() from marking boards
-			 * UNUSABLE based on MBOX_INIT failures.
-			 */
-			if ((err != NULL) && (err->e_code == ESTC_MBXRPLY)) {
-				cmn_err(CE_WARN,
-				    "!Changed mbox incoming to outgoing"
-				    " failure on reinit");
-				sbd_err_clear(&err);
-				err = drerr_new(0, ESTC_MBXRQST, NULL);
-			}
-			drmach_msglist_destroy(mlp);
-			if (err) {
-				mutex_exit(&drmach_ri_mbox_mutex);
-				return (err);
-			}
-			mutex_enter(&drmach_g_mbox_mutex);
-			drmach_mbox_iflag = 1;
-		}
-		mutex_exit(&drmach_g_mbox_mutex);
-		mutex_exit(&drmach_ri_mbox_mutex);
-	}
-
-	hdrp = (dr_proto_hdr_t *)obufp;
-
-	/* setup outgoing mailbox header */
-	hdrp->command = msgtype;
-	hdrp->message_id = drmach_get_msgid();
-	hdrp->drproto_version = DRMBX_VERSION;
-	hdrp->expbrd = DRMACH_BNUM2EXP(bnum);
-	hdrp->slot = DRMACH_BNUM2SLOT(bnum);
-
-	switch (msgtype) {
-
-		case DRMSG_MBOX_INIT:
-			timeout = drmach_to_mbxinit;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_ASSIGN:
-			timeout = drmach_to_assign;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_UNASSIGN:
-			timeout = drmach_to_unassign;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_POWERON:
-			timeout = drmach_to_poweron;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_POWEROFF:
-			timeout = drmach_to_poweroff;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_SHOWBOARD:
-			timeout = drmach_to_showboard;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_CLAIM:
-			timeout = drmach_to_claim;
-			ntries = 1;
-			nosignals = 1;
-			break;
-
-		case DRMSG_UNCLAIM:
-			timeout = drmach_to_unclaim;
-			ntries = 1;
-			nosignals = 1;
-			break;
-
-		case DRMSG_UNCONFIG:
-			timeout = drmach_to_unconfig;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		case DRMSG_TESTBOARD:
-			timeout = drmach_to_testboard;
-			ntries = 1;
-			nosignals = 0;
-			break;
-
-		default:
-			cmn_err(CE_WARN, "Unknown outgoing message type 0x%x",
-			    msgtype);
-			err = DRMACH_INTERNAL_ERROR();
-			break;
-	}
-
-	if (err == NULL) {
-		mlp = drmach_mbox_req_rply(hdrp, olen, ibufp, ilen, timeout,
-		    ntries, nosignals, NULL);
-		err = drmach_mbx2sbderr(mlp);
-
-		/*
-		 * For DRMSG_TESTBOARD attempts which have timed out, or
-		 * been aborted due to a signal received after mboxsc_putmsg()
-		 * has succeeded in sending the message, a DRMSG_ABORT_TEST
-		 * must be sent.
-		 */
-		if ((msgtype == DRMSG_TESTBOARD) && (err != NULL) &&
-		    ((mlp->f_error == EINTR) || ((mlp->f_error == ETIMEDOUT) &&
-		    (mlp->p_flag != 0)))) {
-			drmach_msglist_t	*abmlp;
-			dr_abort_test_t		abibuf;
-
-			hdrp->command = DRMSG_ABORT_TEST;
-			hdrp->message_id = drmach_get_msgid();
-			abmlp = drmach_mbox_req_rply(hdrp,
-			    sizeof (dr_abort_test_t), (caddr_t)&abibuf,
-			    sizeof (abibuf), drmach_to_aborttest, 5, 1, mlp);
-			cmn_err(CE_WARN, "test aborted");
-			drmach_msglist_destroy(abmlp);
-		}
-
-		drmach_msglist_destroy(mlp);
-	}
-
-	return (err);
-}
-
-static int
-drmach_mbox_init()
-{
-	int			err;
-	caddr_t			obufp;
-	sbd_error_t		*serr = NULL;
-	mboxsc_timeout_range_t	mbxtoz;
-
-	drmach_mbox_istate = 0;
-	/* register the outgoing mailbox */
-	if ((err = mboxsc_init(KEY_DRSC, MBOXSC_MBOX_OUT,
-	    NULL)) != 0) {
-		cmn_err(CE_WARN, "DR - SC mboxsc_init failed: 0x%x", err);
-		return (-1);
-	}
-	drmach_mbox_istate = 1;
-
-	/* setup the mboxsc_putmsg timeout value */
-	if (drmach_use_tuned_putmsg_to) {
-		cmn_err(CE_NOTE, "!using tuned drmach_to_putmsg = 0x%lx\n",
-		    drmach_to_putmsg);
-	} else {
-		if ((err = mboxsc_ctrl(KEY_DRSC,
-		    MBOXSC_CMD_PUTMSG_TIMEOUT_RANGE, &mbxtoz)) != 0) {
-			cmn_err(CE_WARN, "mboxsc_ctrl failed: 0x%x", err);
-			drmach_to_putmsg = 60000;
-		} else {
-			drmach_to_putmsg = mboxsc_putmsg_def_timeout() * 6;
-			DRMACH_PR("putmsg range is 0x%lx - 0x%lx value"
-			    " is 0x%lx\n", mbxtoz.min_timeout,
-			    mbxtoz.max_timeout, drmach_to_putmsg);
-		}
-	}
-
-	/* register the incoming mailbox */
-	if ((err = mboxsc_init(KEY_SCDR, MBOXSC_MBOX_IN,
-	    drmach_mbox_event)) != 0) {
-		cmn_err(CE_WARN, "SC - DR mboxsc_init failed: 0x%x", err);
-		return (-1);
-	}
-	drmach_mbox_istate = 2;
-
-	/* initialize mutex for mailbox globals */
-	mutex_init(&drmach_g_mbox_mutex, NULL, MUTEX_DRIVER, NULL);
-
-	/* initialize mutex for mailbox re-init */
-	mutex_init(&drmach_ri_mbox_mutex, NULL, MUTEX_DRIVER, NULL);
-
-	/* initialize mailbox message list elements */
-	drmach_msglist_first = drmach_msglist_last = NULL;
-	mutex_init(&drmach_msglist_mutex, NULL, MUTEX_DRIVER, NULL);
-
-	mutex_init(&drmach_sendmsg_mutex, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&drmach_sendmsg_cv, NULL, CV_DRIVER, NULL);
-
-	drmach_mbox_istate = 3;
-
-	/* start mailbox sendmsg thread */
-	drmach_sendmsg_thread_run = 1;
-	if (drmach_sendmsg_thread == NULL)
-		drmach_sendmsg_thread = thread_create(NULL, 0,
-		    (void (*)())drmach_mbox_sendmsg, NULL, 0, &p0,
-		    TS_RUN, minclsyspri);
-
-	/* start mailbox getmsg thread */
-	drmach_getmsg_thread_run = 1;
-	if (drmach_getmsg_thread == NULL)
-		drmach_getmsg_thread = thread_create(NULL, 0,
-		    (void (*)())drmach_mbox_getmsg, NULL, 0, &p0,
-		    TS_RUN, minclsyspri);
-
-	obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-	serr = drmach_mbox_trans(DRMSG_MBOX_INIT, 0, obufp,
-	    sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
-	kmem_free(obufp, sizeof (dr_proto_hdr_t));
-	if (serr) {
-		cmn_err(CE_WARN, "mbox_init: MBOX_INIT failed ecode=0x%x",
-		    serr->e_code);
-		sbd_err_clear(&serr);
-		return (-1);
-	}
-	mutex_enter(&drmach_g_mbox_mutex);
-	drmach_mbox_iflag = 1;
-	drmach_mbox_ipending = 0;
-	mutex_exit(&drmach_g_mbox_mutex);
-
-	return (0);
-}
-
-static int
-drmach_mbox_fini()
-{
-	int err, rv = 0;
-
-	if (drmach_mbox_istate > 2) {
-		drmach_getmsg_thread_run = 0;
-		drmach_sendmsg_thread_run = 0;
-		cmn_err(CE_WARN,
-		    "drmach_mbox_fini: waiting for mbox threads...");
-		while ((drmach_getmsg_thread_run == 0) ||
-		    (drmach_sendmsg_thread_run == 0)) {
-			continue;
-		}
-		cmn_err(CE_WARN, "drmach_mbox_fini: mbox threads done.");
-		mutex_destroy(&drmach_msglist_mutex);
-
-	}
-	if (drmach_mbox_istate) {
-		/* de-register the outgoing mailbox */
-		if ((err = mboxsc_fini(KEY_DRSC)) != 0) {
-			cmn_err(CE_WARN, "DR - SC mboxsc_fini failed: 0x%x",
-			    err);
-			rv = -1;
-		}
-	}
-	if (drmach_mbox_istate > 1) {
-		/* de-register the incoming mailbox */
-		if ((err = mboxsc_fini(KEY_SCDR)) != 0) {
-			cmn_err(CE_WARN, "SC - DR mboxsc_fini failed: 0x%x",
-			    err);
-			rv = -1;
-		}
-	}
-	mutex_destroy(&drmach_g_mbox_mutex);
-	mutex_destroy(&drmach_ri_mbox_mutex);
-	return (rv);
-}
-
-static int
-drmach_portid2bnum(int portid)
-{
-	int slot;
-
-	switch (portid & 0x1f) {
-	case 0: case 1: case 2: case 3:	/* cpu/wci devices */
-	case 0x1e:			/* slot 0 axq registers */
-		slot = 0;
-		break;
-
-	case 8: case 9:			/* cpu devices */
-	case 0x1c: case 0x1d:		/* schizo/wci devices */
-	case 0x1f:			/* slot 1 axq registers */
-		slot = 1;
-		break;
-
-	default:
-		ASSERT(0);		/* catch in debug kernels */
-	}
-
-	return (((portid >> 4) & 0x7e) | slot);
-}
-
-extern int axq_suspend_iopause;
-
-static int
-hold_rele_branch(dev_info_t *rdip, void *arg)
-{
-	int	i;
-	int	*holdp	= (int *)arg;
-	char	*name = ddi_node_name(rdip);
-
-	/*
-	 * For Starcat, we must be children of the root devinfo node
-	 */
-	ASSERT(ddi_get_parent(rdip) == ddi_root_node());
-
-	i = drmach_name2type_idx(name);
-
-	/*
-	 * Only children of the root devinfo node need to be
-	 * held/released since they are the only valid targets
-	 * of tree operations. This corresponds to the node types
-	 * listed in the drmach_name2type array.
-	 */
-	if (i < 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;
-	gdcd_t		*gdcd;
-	int		bnum;
-	dev_info_t	*rdip;
-	int		hold, circ;
-
-	mutex_enter(&drmach_i_lock);
-	if (drmach_initialized) {
-		mutex_exit(&drmach_i_lock);
-		return (0);
-	}
-
-	gdcd = drmach_gdcd_new();
-	if (gdcd == NULL) {
-		mutex_exit(&drmach_i_lock);
-		cmn_err(CE_WARN, "drmach_init: failed to access GDCD\n");
-		return (-1);
-	}
-
-	drmach_boards = drmach_array_new(0, MAX_BOARDS - 1);
-
-	nodeid = prom_childnode(prom_rootnode());
-	do {
-		int		 len;
-		int		 portid;
-		drmachid_t	 id;
-
-		len = prom_getproplen(nodeid, "portid");
-		if (len != sizeof (portid))
-			continue;
-
-		portid = -1;
-		(void) prom_getprop(nodeid, "portid", (caddr_t)&portid);
-		if (portid == -1)
-			continue;
-
-		bnum = drmach_portid2bnum(portid);
-
-		if (drmach_array_get(drmach_boards, bnum, &id) == -1) {
-			/* portid translated to an invalid board number */
-			cmn_err(CE_WARN, "OBP node 0x%x has"
-			    " invalid property value, %s=%u",
-			    nodeid, "portid", portid);
-
-			/* clean up */
-			drmach_array_dispose(drmach_boards,
-			    drmach_board_dispose);
-			drmach_gdcd_dispose(gdcd);
-			mutex_exit(&drmach_i_lock);
-			return (-1);
-		} else if (id == NULL) {
-			drmach_board_t	*bp;
-			l1_slot_stat_t	*dcd;
-			int		exp, slot;
-
-			bp = drmach_board_new(bnum);
-			bp->assigned = !drmach_initialized;
-			bp->powered = !drmach_initialized;
-
-			exp = DRMACH_BNUM2EXP(bnum);
-			slot = DRMACH_BNUM2SLOT(bnum);
-			dcd = &gdcd->dcd_slot[exp][slot];
-			bp->stardrb_offset =
-			    dcd->l1ss_cpu_drblock_xwd_offset << 3;
-			DRMACH_PR("%s: stardrb_offset=0x%lx\n", bp->cm.name,
-			    bp->stardrb_offset);
-
-			if (gdcd->dcd_slot[exp][slot].l1ss_flags &
-			    L1SSFLG_THIS_L1_NULL_PROC_LPA) {
-				bp->flags |= DRMACH_NULL_PROC_LPA;
-				DRMACH_PR("%s: NULL proc LPA\n", bp->cm.name);
-			}
-		}
-	} while ((nodeid = prom_nextnode(nodeid)) != OBP_NONODE);
-
-	drmach_cpu_sram_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
-
-	if (gdcd->dcd_testcage_log2_mbytes_size != DCD_DR_TESTCAGE_DISABLED) {
-		ASSERT(gdcd->dcd_testcage_log2_mbytes_size ==
-		    gdcd->dcd_testcage_log2_mbytes_align);
-		drmach_iocage_paddr =
-		    (uint64_t)gdcd->dcd_testcage_mbyte_PA << 20;
-		drmach_iocage_size =
-		    1 << (gdcd->dcd_testcage_log2_mbytes_size + 20);
-
-		drmach_iocage_vaddr = (caddr_t)vmem_alloc(heap_arena,
-		    drmach_iocage_size, VM_SLEEP);
-		hat_devload(kas.a_hat, drmach_iocage_vaddr, drmach_iocage_size,
-		    mmu_btop(drmach_iocage_paddr),
-		    PROT_READ | PROT_WRITE,
-		    HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
-
-		DRMACH_PR("gdcd size=0x%x align=0x%x PA=0x%x\n",
-		    gdcd->dcd_testcage_log2_mbytes_size,
-		    gdcd->dcd_testcage_log2_mbytes_align,
-		    gdcd->dcd_testcage_mbyte_PA);
-		DRMACH_PR("drmach size=0x%x PA=0x%lx VA=0x%p\n",
-		    drmach_iocage_size, drmach_iocage_paddr,
-		    (void *)drmach_iocage_vaddr);
-	}
-
-	if (drmach_iocage_size == 0) {
-		drmach_array_dispose(drmach_boards, drmach_board_dispose);
-		drmach_boards = NULL;
-		vmem_free(heap_arena, drmach_cpu_sram_va, PAGESIZE);
-		drmach_gdcd_dispose(gdcd);
-		mutex_exit(&drmach_i_lock);
-		cmn_err(CE_WARN, "drmach_init: iocage not available\n");
-		return (-1);
-	}
-
-	drmach_gdcd_dispose(gdcd);
-
-	mutex_init(&drmach_iocage_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&drmach_iocage_cv, NULL, CV_DRIVER, NULL);
-	mutex_init(&drmach_xt_mb_lock, NULL, MUTEX_DRIVER, NULL);
-	mutex_init(&drmach_bus_sync_lock, NULL, MUTEX_DRIVER, NULL);
-	mutex_init(&drmach_slice_table_lock, NULL, MUTEX_DRIVER, NULL);
-
-	mutex_enter(&cpu_lock);
-	mutex_enter(&drmach_iocage_lock);
-	ASSERT(drmach_iocage_is_busy == 0);
-	drmach_iocage_is_busy = 1;
-	drmach_iocage_mem_scrub(drmach_iocage_size);
-	drmach_iocage_is_busy = 0;
-	cv_signal(&drmach_iocage_cv);
-	mutex_exit(&drmach_iocage_lock);
-	mutex_exit(&cpu_lock);
-
-
-	if (drmach_mbox_init() == -1) {
-		cmn_err(CE_WARN, "DR - SC mailbox initialization Failed");
-	}
-
-	/*
-	 * 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;
-
-	/*
-	 * To avoid a circular patch dependency between DR and AXQ, the AXQ
-	 * rev introducing the axq_iopause_*_all interfaces should not regress
-	 * when installed without the DR rev using those interfaces. The default
-	 * is for iopause to be enabled/disabled during axq suspend/resume. By
-	 * setting the following axq flag to zero, axq will not enable iopause
-	 * during suspend/resume, instead DR will call the axq_iopause_*_all
-	 * interfaces during drmach_copy_rename.
-	 */
-	axq_suspend_iopause = 0;
-
-	mutex_exit(&drmach_i_lock);
-
-	return (0);
-}
-
-static void
-drmach_fini(void)
-{
-	dev_info_t	*rdip;
-	int		hold, circ;
-
-	if (drmach_initialized) {
-		rw_enter(&drmach_boards_rwlock, RW_WRITER);
-		drmach_array_dispose(drmach_boards, drmach_board_dispose);
-		drmach_boards = NULL;
-		rw_exit(&drmach_boards_rwlock);
-
-		mutex_destroy(&drmach_slice_table_lock);
-		mutex_destroy(&drmach_xt_mb_lock);
-		mutex_destroy(&drmach_bus_sync_lock);
-		cv_destroy(&drmach_iocage_cv);
-		mutex_destroy(&drmach_iocage_lock);
-
-		vmem_free(heap_arena, drmach_cpu_sram_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);
-
-		drmach_initialized = 0;
-	}
-
-	(void) drmach_mbox_fini();
-	if (drmach_xt_mb != NULL) {
-		vmem_free(static_alloc_arena, (void *)drmach_xt_mb,
-		    drmach_xt_mb_size);
-	}
-	rw_destroy(&drmach_boards_rwlock);
-	mutex_destroy(&drmach_i_lock);
-}
-
-static void
-drmach_mem_read_madr(drmach_mem_t *mp, int bank, uint64_t *madr)
-{
-	kpreempt_disable();
-
-	/* get register address, read madr value */
-	if (STARCAT_CPUID_TO_PORTID(CPU->cpu_id) == mp->dev.portid) {
-		*madr = lddmcdecode(DRMACH_MC_ASI_ADDR(mp, bank));
-	} else {
-		*madr = lddphysio(DRMACH_MC_ADDR(mp, bank));
-	}
-
-	kpreempt_enable();
-}
-
-
-static uint64_t *
-drmach_prep_mc_rename(uint64_t *p, int local,
-	drmach_mem_t *mp, uint64_t current_basepa, uint64_t new_basepa)
-{
-	int bank;
-
-	for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
-		uint64_t madr, bank_offset;
-
-		/* fetch mc's bank madr register value */
-		drmach_mem_read_madr(mp, bank, &madr);
-		if (madr & DRMACH_MC_VALID_MASK) {
-			uint64_t bankpa;
-
-			bank_offset = (DRMACH_MC_UM_TO_PA(madr) |
-			    DRMACH_MC_LM_TO_PA(madr)) - current_basepa;
-			bankpa = new_basepa + bank_offset;
-
-			/* encode new base pa into madr */
-			madr &= ~DRMACH_MC_UM_MASK;
-			madr |= DRMACH_MC_PA_TO_UM(bankpa);
-			madr &= ~DRMACH_MC_LM_MASK;
-			madr |= DRMACH_MC_PA_TO_LM(bankpa);
-
-			if (local)
-				*p++ = DRMACH_MC_ASI_ADDR(mp, bank);
-			else
-				*p++ = DRMACH_MC_ADDR(mp, bank);
-
-			*p++ = madr;
-		}
-	}
-
-	return (p);
-}
-
-static uint64_t *
-drmach_prep_schizo_script(uint64_t *p, drmach_mem_t *mp, uint64_t new_basepa)
-{
-	drmach_board_t	*bp;
-	int		 rv;
-	int		 idx;
-	drmachid_t	 id;
-	uint64_t	 last_scsr_pa = 0;
-
-	/* memory is always in slot 0 */
-	ASSERT(DRMACH_BNUM2SLOT(mp->dev.bp->bnum) == 0);
-
-	/* look up slot 1 board on same expander */
-	idx = DRMACH_EXPSLOT2BNUM(DRMACH_BNUM2EXP(mp->dev.bp->bnum), 1);
-	rv = drmach_array_get(drmach_boards, idx, &id);
-	bp = id; /* bp will be NULL if board not found */
-
-	/* look up should never be out of bounds */
-	ASSERT(rv == 0);
-
-	/* nothing to do when board is not found or has no devices */
-	if (rv == -1 || bp == NULL || bp->devices == NULL)
-		return (p);
-
-	rv = drmach_array_first(bp->devices, &idx, &id);
-	while (rv == 0) {
-		if (DRMACH_IS_IO_ID(id)) {
-			drmach_io_t *io = id;
-
-			/*
-			 * Skip all non-Schizo IO devices (only IO nodes
-			 * that are Schizo devices have non-zero scsr_pa).
-			 * Filter out "other" leaf to avoid writing to the
-			 * same Schizo Control/Status Register twice.
-			 */
-			if (io->scsr_pa && io->scsr_pa != last_scsr_pa) {
-				uint64_t scsr;
-
-				scsr  = lddphysio(io->scsr_pa);
-				scsr &= ~(DRMACH_LPA_BASE_MASK |
-				    DRMACH_LPA_BND_MASK);
-				scsr |= DRMACH_PA_TO_LPA_BASE(new_basepa);
-				scsr |= DRMACH_PA_TO_LPA_BND(
-				    new_basepa + DRMACH_MEM_SLICE_SIZE);
-
-				*p++ = io->scsr_pa;
-				*p++ = scsr;
-
-				last_scsr_pa = io->scsr_pa;
-			}
-		}
-		rv = drmach_array_next(bp->devices, &idx, &id);
-	}
-
-	return (p);
-}
-
-/*
- * For Panther MCs, append the MC idle reg address and drmach_mem_t pointer.
- * The latter is returned when drmach_rename fails to idle a Panther MC and
- * is used to identify the MC for error reporting.
- */
-static uint64_t *
-drmach_prep_pn_mc_idle(uint64_t *p, drmach_mem_t *mp, int local)
-{
-	/* only slot 0 has memory */
-	ASSERT(DRMACH_BNUM2SLOT(mp->dev.bp->bnum) == 0);
-	ASSERT(IS_PANTHER(mp->dev.bp->cpu_impl));
-
-	for (mp = mp->dev.bp->mem; mp != NULL; mp = mp->next) {
-		ASSERT(DRMACH_IS_MEM_ID(mp));
-
-		if (mp->dev.portid == STARCAT_CPUID_TO_PORTID(CPU->cpu_id)) {
-			if (local) {
-				*p++ = ASI_EMU_ACT_STATUS_VA;	/* local ASI */
-				*p++ = (uintptr_t)mp;
-			}
-		} else if (!local) {
-			*p++ = DRMACH_EMU_ACT_STATUS_ADDR(mp);	/* PIO */
-			*p++ = (uintptr_t)mp;
-		}
-	}
-
-	return (p);
-}
-
-static sbd_error_t *
-drmach_prep_rename_script(drmach_mem_t *s_mp, drmach_mem_t *t_mp,
-	uint64_t t_slice_offset, caddr_t buf, int buflen)
-{
-	_NOTE(ARGUNUSED(buflen))
-
-	uint64_t		*p = (uint64_t *)buf, *q;
-	sbd_error_t		*err;
-	int			 rv;
-	drmach_mem_t		*mp, *skip_mp;
-	uint64_t		 s_basepa, t_basepa;
-	uint64_t		 s_new_basepa, t_new_basepa;
-
-	/* verify supplied buffer space is adequate */
-	ASSERT(buflen >=
-	    /* addr for all possible MC banks */
-	    (sizeof (uint64_t) * 4 * 4 * 18) +
-	    /* list section terminator */
-	    (sizeof (uint64_t) * 1) +
-	    /* addr/id tuple for local Panther MC idle reg */
-	    (sizeof (uint64_t) * 2) +
-	    /* list section terminator */
-	    (sizeof (uint64_t) * 1) +
-	    /* addr/id tuple for 2 boards with 4 Panther MC idle regs */
-	    (sizeof (uint64_t) * 2 * 2 * 4) +
-	    /* list section terminator */
-	    (sizeof (uint64_t) * 1) +
-	    /* addr/val tuple for 1 proc with 4 MC banks */
-	    (sizeof (uint64_t) * 2 * 4) +
-	    /* list section terminator */
-	    (sizeof (uint64_t) * 1) +
-	    /* addr/val tuple for 2 boards w/ 2 schizos each */
-	    (sizeof (uint64_t) * 2 * 2 * 2) +
-	    /* addr/val tuple for 2 boards w/ 16 MC banks each */
-	    (sizeof (uint64_t) * 2 * 2 * 16) +
-	    /* list section terminator */
-	    (sizeof (uint64_t) * 1) +
-	    /* addr/val tuple for 18 AXQs w/ two slots each */
-	    (sizeof (uint64_t) * 2 * 2 * 18) +
-	    /* list section terminator */
-	    (sizeof (uint64_t) * 1) +
-	    /* list terminator */
-	    (sizeof (uint64_t) * 1));
-
-	/* copy bank list to rename script */
-	mutex_enter(&drmach_bus_sync_lock);
-	for (q = drmach_bus_sync_list; *q; q++, p++)
-		*p = *q;
-	mutex_exit(&drmach_bus_sync_lock);
-
-	/* list section terminator */
-	*p++ = 0;
-
-	/*
-	 * Write idle script for MC on this processor.  A script will be
-	 * produced only if this is a Panther processor on the source or
-	 * target board.
-	 */
-	if (IS_PANTHER(s_mp->dev.bp->cpu_impl))
-		p = drmach_prep_pn_mc_idle(p, s_mp, 1);
-
-	if (IS_PANTHER(t_mp->dev.bp->cpu_impl))
-		p = drmach_prep_pn_mc_idle(p, t_mp, 1);
-
-	/* list section terminator */
-	*p++ = 0;
-
-	/*
-	 * Write idle script for all other MCs on source and target
-	 * Panther boards.
-	 */
-	if (IS_PANTHER(s_mp->dev.bp->cpu_impl))
-		p = drmach_prep_pn_mc_idle(p, s_mp, 0);
-
-	if (IS_PANTHER(t_mp->dev.bp->cpu_impl))
-		p = drmach_prep_pn_mc_idle(p, t_mp, 0);
-
-	/* list section terminator */
-	*p++ = 0;
-
-	/*
-	 * Step 1:	Write source base address to target MC
-	 *		with present bit off.
-	 * Step 2:	Now rewrite target reg with present bit on.
-	 */
-	err = drmach_mem_get_base_physaddr(s_mp, &s_basepa);
-	ASSERT(err == NULL);
-	err = drmach_mem_get_base_physaddr(t_mp, &t_basepa);
-	ASSERT(err == NULL);
-
-	/* exchange base pa. include slice offset in new target base pa */
-	s_new_basepa = t_basepa & ~ (DRMACH_MEM_SLICE_SIZE - 1);
-	t_new_basepa = (s_basepa & ~ (DRMACH_MEM_SLICE_SIZE - 1)) +
-	    t_slice_offset;
-
-	DRMACH_PR("s_new_basepa 0x%lx\n", s_new_basepa);
-	DRMACH_PR("t_new_basepa 0x%lx\n", t_new_basepa);
-
-	DRMACH_PR("preparing MC MADR rename script (master is CPU%d):\n",
-	    CPU->cpu_id);
-
-	/*
-	 * Write rename script for MC on this processor.  A script will
-	 * be produced only if this processor is on the source or target
-	 * board.
-	 */
-
-	skip_mp = NULL;
-	mp = s_mp->dev.bp->mem;
-	while (mp != NULL && skip_mp == NULL) {
-		if (mp->dev.portid == STARCAT_CPUID_TO_PORTID(CPU->cpu_id)) {
-			skip_mp = mp;
-			p = drmach_prep_mc_rename(p, 1, mp, s_basepa,
-			    s_new_basepa);
-		}
-
-		mp = mp->next;
-	}
-
-	mp = t_mp->dev.bp->mem;
-	while (mp != NULL && skip_mp == NULL) {
-		if (mp->dev.portid == STARCAT_CPUID_TO_PORTID(CPU->cpu_id)) {
-			skip_mp = mp;
-			p = drmach_prep_mc_rename(p, 1, mp, t_basepa,
-			    t_new_basepa);
-		}
-
-		mp = mp->next;
-	}
-
-	/* list section terminator */
-	*p++ = 0;
-
-	/*
-	 * Write rename script for all other MCs on source and target
-	 * boards.
-	 */
-
-	for (mp = s_mp->dev.bp->mem; mp; mp = mp->next) {
-		if (mp == skip_mp)
-			continue;
-		p = drmach_prep_mc_rename(p, 0, mp, s_basepa, s_new_basepa);
-	}
-
-	for (mp = t_mp->dev.bp->mem; mp; mp = mp->next) {
-		if (mp == skip_mp)
-			continue;
-		p = drmach_prep_mc_rename(p, 0, mp, t_basepa, t_new_basepa);
-	}
-
-	/* Write rename script for Schizo LPA_BASE/LPA_BND */
-	p = drmach_prep_schizo_script(p, s_mp, s_new_basepa);
-	p = drmach_prep_schizo_script(p, t_mp, t_new_basepa);
-
-	/* list section terminator */
-	*p++ = 0;
-
-	DRMACH_PR("preparing AXQ CASM rename script (EXP%d <> EXP%d):\n",
-	    DRMACH_BNUM2EXP(s_mp->dev.bp->bnum),
-	    DRMACH_BNUM2EXP(t_mp->dev.bp->bnum));
-
-	rv = axq_do_casm_rename_script(&p,
-	    DRMACH_PA_TO_SLICE(s_new_basepa),
-	    DRMACH_PA_TO_SLICE(t_new_basepa));
-	if (rv == DDI_FAILURE)
-		return (DRMACH_INTERNAL_ERROR());
-
-	/* list section & final terminator */
-	*p++ = 0;
-	*p++ = 0;
-
-#ifdef DEBUG
-	{
-		uint64_t *q = (uint64_t *)buf;
-
-		/* paranoia */
-		ASSERT((caddr_t)p <= buf + buflen);
-
-		DRMACH_PR("MC bank base pa list:\n");
-		while (*q) {
-			uint64_t a = *q++;
-
-			DRMACH_PR("0x%lx\n", a);
-		}
-
-		/* skip terminator */
-		q += 1;
-
-		DRMACH_PR("local Panther MC idle reg (via ASI 0x4a):\n");
-		while (*q) {
-			DRMACH_PR("addr=0x%lx, mp=0x%lx\n", *q, *(q + 1));
-			q += 2;
-		}
-
-		/* skip terminator */
-		q += 1;
-
-		DRMACH_PR("non-local Panther MC idle reg (via ASI 0x15):\n");
-		while (*q) {
-			DRMACH_PR("addr=0x%lx, mp=0x%lx\n", *q, *(q + 1));
-			q += 2;
-		}
-
-		/* skip terminator */
-		q += 1;
-
-		DRMACH_PR("MC reprogramming script (via ASI 0x72):\n");
-		while (*q) {
-			uint64_t r = *q++;	/* register address */
-			uint64_t v = *q++;	/* new register value */
-
-			DRMACH_PR("0x%lx = 0x%lx, basepa 0x%lx\n",
-			    r, v, (long)(DRMACH_MC_UM_TO_PA(v)|
-			    DRMACH_MC_LM_TO_PA(v)));
-		}
-
-		/* skip terminator */
-		q += 1;
-
-		DRMACH_PR("MC/SCHIZO reprogramming script:\n");
-		while (*q) {
-			DRMACH_PR("0x%lx = 0x%lx\n", *q, *(q + 1));
-			q += 2;
-		}
-
-		/* skip terminator */
-		q += 1;
-
-		DRMACH_PR("AXQ reprogramming script:\n");
-		while (*q) {
-			DRMACH_PR("0x%lx = 0x%lx\n", *q, *(q + 1));
-			q += 2;
-		}
-
-		/* verify final terminator is present */
-		ASSERT(*(q + 1) == 0);
-
-		DRMACH_PR("copy-rename script 0x%p, len %d\n",
-		    (void *)buf, (int)((intptr_t)p - (intptr_t)buf));
-
-		if (drmach_debug)
-			DELAY(10000000);
-	}
-#endif
-
-	return (NULL);
-}
-
-static void
-drmach_prep_xt_mb_for_slice_update(drmach_board_t *bp, uchar_t slice)
-{
-	int		 rv;
-
-	ASSERT(MUTEX_HELD(&drmach_xt_mb_lock));
-
-	if (bp->devices) {
-		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)) {
-				drmach_cpu_t	*cp = d_id;
-				processorid_t	 cpuid = cp->cpuid;
-
-				mutex_enter(&cpu_lock);
-				if (cpu[cpuid] && cpu[cpuid]->cpu_flags)
-					drmach_xt_mb[cpuid] = 0x80 | slice;
-				mutex_exit(&cpu_lock);
-			}
-			rv = drmach_array_next(bp->devices, &d_idx, &d_id);
-		}
-	}
-	if (DRMACH_BNUM2SLOT(bp->bnum) == 0) {
-		drmach_board_t	*s1bp = NULL;
-
-		rv = drmach_array_get(drmach_boards, bp->bnum + 1,
-		    (void *) &s1bp);
-		if (rv == 0 && s1bp != NULL) {
-			ASSERT(DRMACH_IS_BOARD_ID(s1bp));
-			ASSERT(DRMACH_BNUM2SLOT(s1bp->bnum) == 1);
-			drmach_prep_xt_mb_for_slice_update(s1bp, slice);
-		}
-	}
-}
-
-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 *cr_id)
-{
-	extern void drmach_rename(uint64_t *, uint_t *, uint64_t *);
-	extern void drmach_rename_end(void);
-
-	drmach_mem_t	*s_mp, *t_mp;
-	struct memlist	*x_ml;
-	uint64_t	 off_mask, s_copybasepa, t_copybasepa, t_basepa;
-	int		 len;
-	caddr_t		 bp, wp;
-	uint_t		*p, *q;
-	sbd_error_t	*err;
-	tte_t		*tte;
-	drmach_copy_rename_t *cr;
-
-	if (!DRMACH_IS_MEM_ID(s_id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	if (!DRMACH_IS_MEM_ID(t_id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	s_mp = s_id;
-	t_mp = 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 = DRMACH_MEM_SLICE_SIZE - 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");
-	DRMACH_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);
-	}
-#endif /* DEBUG */
-
-	/* Map in appropriate cpu sram page */
-	tte = &drmach_cpu_sram_tte[CPU->cpu_id];
-	ASSERT(TTE_IS_VALID(tte) && TTE_IS_8K(tte) &&
-	    TTE_IS_PRIVILEGED(tte) && TTE_IS_LOCKED(tte));
-	sfmmu_dtlb_ld_kva(drmach_cpu_sram_va, tte);
-	sfmmu_itlb_ld_kva(drmach_cpu_sram_va, tte);
-
-	bp = wp = drmach_cpu_sram_va;
-
-	/* Make sure the rename routine will fit */
-	len = (ptrdiff_t)drmach_rename_end - (ptrdiff_t)drmach_rename;
-	ASSERT(wp + len < bp + PAGESIZE);
-
-	/* copy text. standard bcopy not designed to work in nc space */
-	p = (uint_t *)wp;
-	q = (uint_t *)drmach_rename;
-	while (q < (uint_t *)drmach_rename_end)
-		*p++ = *q++;
-
-	/* zero remainder. standard bzero not designed to work in nc space */
-	while (p < (uint_t *)(bp + PAGESIZE))
-		*p++ = 0;
-
-	DRMACH_PR("drmach_rename function 0x%p, len %d\n", (void *)wp, len);
-	wp += (len + 15) & ~15;
-
-	err = drmach_prep_rename_script(s_mp, t_mp, t_slice_offset, wp,
-	    PAGESIZE - (wp - bp));
-	if (err) {
-cleanup:
-		xt_one(CPU->cpu_id, vtag_flushpage_tl1,
-		    (uint64_t)drmach_cpu_sram_va, (uint64_t)ksfmmup);
-		return (err);
-	}
-
-	/* disable and flush CDC */
-	if (axq_cdc_disable_flush_all() != DDI_SUCCESS) {
-		axq_cdc_enable_all();	/* paranoia */
-		err = DRMACH_INTERNAL_ERROR();
-		goto cleanup;
-	}
-
-	/* mark both memory units busy */
-	t_mp->dev.busy++;
-	s_mp->dev.busy++;
-
-	cr = vmem_alloc(static_alloc_arena, sizeof (drmach_copy_rename_t),
-	    VM_SLEEP);
-	cr->isa = (void *)drmach_copy_rename_init;
-	cr->data = wp;
-	cr->c_ml = c_ml;
-	cr->s_mp = s_mp;
-	cr->t_mp = t_mp;
-	cr->s_copybasepa = s_copybasepa;
-	cr->t_copybasepa = t_copybasepa;
-	cr->ecode = DRMACH_CR_OK;
-
-	mutex_enter(&drmach_slice_table_lock);
-
-	mutex_enter(&drmach_xt_mb_lock);
-	bzero((void *)drmach_xt_mb, drmach_xt_mb_size);
-
-	if (DRMACH_L1_SET_LPA(s_mp->dev.bp) && drmach_reprogram_lpa) {
-		drmach_prep_xt_mb_for_slice_update(s_mp->dev.bp,
-		    DRMACH_PA_TO_SLICE(t_copybasepa));
-	}
-	if (DRMACH_L1_SET_LPA(t_mp->dev.bp) && drmach_reprogram_lpa) {
-		drmach_prep_xt_mb_for_slice_update(t_mp->dev.bp,
-		    DRMACH_PA_TO_SLICE(s_copybasepa));
-	}
-
-	*cr_id = cr;
-	return (NULL);
-}
-
-int drmach_rename_count;
-int drmach_rename_ntries;
-
-sbd_error_t *
-drmach_copy_rename_fini(drmachid_t id)
-{
-	drmach_copy_rename_t	*cr = id;
-	sbd_error_t		*err = NULL;
-	dr_mbox_msg_t		*obufp;
-
-	ASSERT(cr->isa == (void *)drmach_copy_rename_init);
-
-	axq_cdc_enable_all();
-
-	xt_one(CPU->cpu_id, vtag_flushpage_tl1,
-	    (uint64_t)drmach_cpu_sram_va, (uint64_t)ksfmmup);
-
-	switch (cr->ecode) {
-	case DRMACH_CR_OK:
-		break;
-	case DRMACH_CR_MC_IDLE_ERR: {
-		dev_info_t	*dip = NULL;
-		drmach_mem_t	*mp = (drmach_mem_t *)cr->earg;
-		char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-
-		ASSERT(DRMACH_IS_MEM_ID(mp));
-
-		err = drmach_get_dip(mp, &dip);
-
-		ASSERT(err == NULL);
-		ASSERT(dip != NULL);
-
-		err = drerr_new(0, ESBD_MEMFAIL, NULL);
-		(void) ddi_pathname(dip, path);
-		cmn_err(CE_WARN, "failed to idle memory controller %s on %s: "
-		    "copy-rename aborted", path, mp->dev.bp->cm.name);
-		kmem_free(path, MAXPATHLEN);
-		break;
-	}
-	case DRMACH_CR_IOPAUSE_ERR:
-		ASSERT((uintptr_t)cr->earg >= 0 &&
-		    (uintptr_t)cr->earg < AXQ_MAX_EXP);
-
-		err = drerr_new(0,  ESBD_SUSPEND, "EX%d", (uintptr_t)cr->earg);
-		cmn_err(CE_WARN, "failed to idle EX%ld AXQ slot1 activity prior"
-		    " to copy-rename", (uintptr_t)cr->earg);
-		break;
-	case DRMACH_CR_ONTRAP_ERR:
-		err = drerr_new(0, ESBD_MEMFAIL, NULL);
-		cmn_err(CE_WARN, "copy-rename aborted due to uncorrectable "
-		    "memory error");
-		break;
-	default:
-		err = DRMACH_INTERNAL_ERROR();
-		cmn_err(CE_WARN, "unknown copy-rename error code (%d)\n",
-		    cr->ecode);
-		break;
-	}
-
-#ifdef DEBUG
-	if ((DRMACH_L1_SET_LPA(cr->s_mp->dev.bp) ||
-	    DRMACH_L1_SET_LPA(cr->t_mp->dev.bp)) && drmach_reprogram_lpa) {
-		int	i;
-		for (i = 0; i < NCPU; i++) {
-			if (drmach_xt_mb[i])
-				DRMACH_PR("cpu%d ignored drmach_xt_mb", i);
-		}
-	}
-#endif
-	mutex_exit(&drmach_xt_mb_lock);
-
-	if (cr->c_ml != NULL)
-		memlist_delete(cr->c_ml);
-
-	cr->t_mp->dev.busy--;
-	cr->s_mp->dev.busy--;
-
-	if (err) {
-		mutex_exit(&drmach_slice_table_lock);
-		goto done;
-	}
-
-	/* update casm shadow for target and source board */
-	drmach_slice_table_update(cr->t_mp->dev.bp, 0);
-	drmach_slice_table_update(cr->s_mp->dev.bp, 0);
-	mutex_exit(&drmach_slice_table_lock);
-
-	mutex_enter(&drmach_bus_sync_lock);
-	drmach_bus_sync_list_update();
-	mutex_exit(&drmach_bus_sync_lock);
-
-	/*
-	 * Make a good-faith effort to notify the SC about the copy-rename, but
-	 * don't worry if it fails, since a subsequent claim/unconfig/unclaim
-	 * will duplicate the update.
-	 */
-	obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
-	mutex_enter(&drmach_slice_table_lock);
-	drmach_msg_memslice_init(obufp->msgdata.dm_uc.mem_slice);
-	drmach_msg_memregs_init(obufp->msgdata.dm_uc.mem_regs);
-	mutex_exit(&drmach_slice_table_lock);
-	(void) drmach_mbox_trans(DRMSG_UNCONFIG, cr->s_mp->dev.bp->bnum,
-	    (caddr_t)obufp, sizeof (dr_mbox_msg_t), (caddr_t)NULL, 0);
-	kmem_free(obufp, sizeof (dr_mbox_msg_t));
-
-done:
-	vmem_free(static_alloc_arena, cr, sizeof (drmach_copy_rename_t));
-
-	DRMACH_PR("waited %d out of %d tries for drmach_rename_wait on %d cpus",
-	    drmach_rename_ntries, drmach_cpu_ntries, drmach_rename_count);
-
-	return (err);
-}
-
-int drmach_slow_copy = 0;
-
-void
-drmach_copy_rename(drmachid_t id)
-{
-	extern uint_t		 getpstate(void);
-	extern void		 setpstate(uint_t);
-
-	extern xcfunc_t		 drmach_rename_wait;
-	extern xcfunc_t		 drmach_rename_done;
-	extern xcfunc_t		 drmach_rename_abort;
-
-	drmach_copy_rename_t	*cr = id;
-	uint64_t		 neer;
-	struct memlist		*ml;
-	int			 i, count;
-	int			 csize, lnsize;
-	uint64_t		 caddr;
-	cpuset_t		 cpuset;
-	uint_t			 pstate;
-	uint32_t		 exp = 0;
-	on_trap_data_t		 otd;
-	xcfunc_t		*drmach_end_wait_xcall = drmach_rename_done;
-
-	ASSERT(cr->isa == (void *)drmach_copy_rename_init);
-	ASSERT(MUTEX_HELD(&cpu_lock));
-	ASSERT(cr->ecode == DRMACH_CR_OK);
-
-	/*
-	 * Prevent slot1 IO from accessing Safari memory bus.
-	 */
-	if (axq_iopause_enable_all(&exp) != DDI_SUCCESS) {
-		ASSERT(exp >= 0 && exp < AXQ_MAX_EXP);
-		cr->ecode = DRMACH_CR_IOPAUSE_ERR;
-		cr->earg = (void *)(uintptr_t)exp;
-		return;
-	}
-
-	cpuset = cpu_ready_set;
-	CPUSET_DEL(cpuset, CPU->cpu_id);
-	count = ncpus - 1;
-	drmach_rename_count = count;	/* for debug */
-
-	drmach_xt_ready = 0;
-	xt_some(cpuset, drmach_rename_wait, NULL, NULL);
-
-	for (i = 0; i < drmach_cpu_ntries; i++) {
-		if (drmach_xt_ready == count)
-			break;
-		DELAY(drmach_cpu_delay);
-	}
-
-	drmach_rename_ntries = i;	/* for debug */
-
-	drmach_xt_ready = 0;		/* steal the line back */
-	for (i = 0; i < NCPU; i++)	/* steal the line back, preserve data */
-		drmach_xt_mb[i] = drmach_xt_mb[i];
-
-	caddr = drmach_iocage_paddr;
-	csize = cpunodes[CPU->cpu_id].ecache_size;
-	lnsize = cpunodes[CPU->cpu_id].ecache_linesize;
-
-	/* disable CE reporting */
-	neer = get_error_enable();
-	set_error_enable(neer & ~EN_REG_CEEN);
-
-	/* disable interrupts (paranoia) */
-	pstate = getpstate();
-	setpstate(pstate & ~PSTATE_IE);
-
-	/*
-	 * Execute copy-rename under on_trap to protect against a panic due
-	 * to an uncorrectable error. Instead, DR will abort the copy-rename
-	 * operation and rely on the OS to do the error reporting.
-	 *
-	 * In general, trap handling on any cpu once the copy begins
-	 * can result in an inconsistent memory image on the target.
-	 */
-	if (on_trap(&otd, OT_DATA_EC)) {
-		cr->ecode = DRMACH_CR_ONTRAP_ERR;
-		goto copy_rename_end;
-	}
-
-	/*
-	 * DO COPY.
-	 */
-	for (ml = cr->c_ml; ml; ml = ml->ml_next) {
-		uint64_t	s_pa, t_pa;
-		uint64_t	nbytes;
-
-		s_pa = cr->s_copybasepa + ml->ml_address;
-		t_pa = cr->t_copybasepa + ml->ml_address;
-		nbytes = ml->ml_size;
-
-		while (nbytes != 0ull) {
-			/* 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));
-
-			if (drmach_slow_copy) {	/* for debug */
-				uint64_t i = 13 * 50;
-				while (i--)
-					;
-			}
-		}
-	}
-
-	/*
-	 * XXX CHEETAH SUPPORT
-	 * For cheetah, we need to grab the iocage lock since iocage
-	 * memory is used for e$ flush.
-	 *
-	 * NOTE: This code block is dangerous at this point in the
-	 * copy-rename operation. It modifies memory after the copy
-	 * has taken place which means that any persistent state will
-	 * be abandoned after the rename operation. The code is also
-	 * performing thread synchronization at a time when all but
-	 * one processors are paused. This is a potential deadlock
-	 * situation.
-	 *
-	 * This code block must be moved to drmach_copy_rename_init.
-	 */
-	if (drmach_is_cheetah) {
-		mutex_enter(&drmach_iocage_lock);
-		while (drmach_iocage_is_busy)
-			cv_wait(&drmach_iocage_cv, &drmach_iocage_lock);
-		drmach_iocage_is_busy = 1;
-		drmach_iocage_mem_scrub(ecache_size * 2);
-		mutex_exit(&drmach_iocage_lock);
-	}
-
-	/*
-	 * bcopy32_il is implemented as a series of ldxa/stxa via
-	 * ASI_MEM instructions. Following the copy loop, the E$
-	 * of the master (this) processor will have lines in state
-	 * O that correspond to lines of home memory in state gI.
-	 * An E$ flush is necessary to commit these lines before
-	 * proceeding with the rename operation.
-	 *
-	 * Flushing the E$ will automatically flush the W$, but
-	 * the D$ and I$ must be flushed separately and explicitly.
-	 */
-	flush_ecache_il(caddr, csize, lnsize);	/* inline version */
-
-	/*
-	 * Each line of home memory is now in state gM, except in
-	 * the case of a cheetah processor when the E$ flush area
-	 * is included within the copied region. In such a case,
-	 * the lines of home memory for the upper half of the
-	 * flush area are in state gS.
-	 *
-	 * Each line of target memory is in state gM.
-	 *
-	 * Each line of this processor's E$ is in state I, except
-	 * those of a cheetah processor. All lines of a cheetah
-	 * processor's E$ are in state S and correspond to the lines
-	 * in upper half of the E$ flush area.
-	 *
-	 * It is vital at this point that none of the lines in the
-	 * home or target memories are in state gI and that none
-	 * of the lines in this processor's E$ are in state O or Os.
-	 * A single instance of such a condition will cause loss of
-	 * coherency following the rename operation.
-	 */
-
-	/*
-	 * Rename
-	 */
-	(*(void(*)())drmach_cpu_sram_va)(cr->data, &cr->ecode, &cr->earg);
-
-	/*
-	 * Rename operation complete. The physical address space
-	 * of the home and target memories have been swapped, the
-	 * routing data in the respective CASM entries have been
-	 * swapped, and LPA settings in the processor and schizo
-	 * devices have been reprogrammed accordingly.
-	 *
-	 * In the case of a cheetah processor, the E$ remains
-	 * populated with lines in state S that correspond to the
-	 * lines in the former home memory. Now that the physical
-	 * addresses have been swapped, these E$ lines correspond
-	 * to lines in the new home memory which are in state gM.
-	 * This combination is invalid. An additional E$ flush is
-	 * necessary to restore coherency. The E$ flush will cause
-	 * the lines of the new home memory for the flush region
-	 * to transition from state gM to gS. The former home memory
-	 * remains unmodified. This additional E$ flush has no effect
-	 * on a cheetah+ processor.
-	 */
-	flush_ecache_il(caddr, csize, lnsize);	/* inline version */
-
-	/*
-	 * The D$ and I$ must be flushed to ensure that coherency is
-	 * maintained. Any line in a cache that is in the valid
-	 * state has its corresponding line of the new home memory
-	 * in the gM state. This is an invalid condition. When the
-	 * flushes are complete the cache line states will be
-	 * resynchronized with those in the new home memory.
-	 */
-	flush_icache_il();			/* inline version */
-	flush_dcache_il();			/* inline version */
-	flush_pcache_il();			/* inline version */
-
-copy_rename_end:
-
-	no_trap();
-
-	/* enable interrupts */
-	setpstate(pstate);
-
-	/* enable CE reporting */
-	set_error_enable(neer);
-
-	if (cr->ecode != DRMACH_CR_OK)
-		drmach_end_wait_xcall = drmach_rename_abort;
-
-	/*
-	 * XXX CHEETAH SUPPORT
-	 */
-	if (drmach_is_cheetah) {
-		mutex_enter(&drmach_iocage_lock);
-		drmach_iocage_mem_scrub(ecache_size * 2);
-		drmach_iocage_is_busy = 0;
-		cv_signal(&drmach_iocage_cv);
-		mutex_exit(&drmach_iocage_lock);
-	}
-
-	axq_iopause_disable_all();
-
-	xt_some(cpuset, drmach_end_wait_xcall, NULL, NULL);
-}
-
-static void drmach_io_dispose(drmachid_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_pci_new(drmach_device_t *proto, drmachid_t *idp)
-{
-	drmach_node_t	*node = proto->node;
-	sbd_error_t	*err;
-	drmach_reg_t	 regs[3];
-	int		 rv;
-	int		 len = 0;
-
-	rv = node->n_getproplen(node, "reg", &len);
-	if (rv != 0 || len != sizeof (regs)) {
-		sbd_error_t *err;
-
-		/* pci nodes are expected to have regs */
-		err = drerr_new(1, ESTC_GETPROP,
-		    "Device Node 0x%x: property %s",
-		    (uint_t)node->get_dnode(node), "reg");
-		return (err);
-	}
-
-	rv = node->n_getprop(node, "reg", (void *)regs, sizeof (regs));
-	if (rv) {
-		sbd_error_t *err;
-
-		err = drerr_new(1, ESTC_GETPROP,
-		    "Device Node 0x%x: property %s",
-		    (uint_t)node->get_dnode(node), "reg");
-
-		return (err);
-	}
-
-	/*
-	 * Fix up unit number so that Leaf A has a lower unit number
-	 * than Leaf B.
-	 */
-	if ((proto->portid % 2) != 0) {
-		if ((regs[0].reg_addr_lo & 0x700000) == 0x700000)
-			proto->unum = 0;
-		else
-			proto->unum = 1;
-	} else {
-		if ((regs[0].reg_addr_lo & 0x700000) == 0x700000)
-			proto->unum = 2;
-		else
-			proto->unum = 3;
-	}
-
-	err = drmach_io_new(proto, idp);
-	if (err == NULL) {
-		drmach_io_t *self = *idp;
-
-		/* reassemble 64-bit base address */
-		self->scsr_pa  = (uint64_t)regs[1].reg_addr_hi << 32;
-		self->scsr_pa |= (uint64_t)regs[1].reg_addr_lo;
-	}
-
-	return (err);
-}
-
-static sbd_error_t *
-drmach_io_new(drmach_device_t *proto, drmachid_t *idp)
-{
-	drmach_io_t	*ip;
-
-	ip = kmem_zalloc(sizeof (drmach_io_t), KM_SLEEP);
-	bcopy(proto, &ip->dev, sizeof (ip->dev));
-	ip->dev.node = drmach_node_dup(proto->node);
-	ip->dev.cm.isa = (void *)drmach_io_new;
-	ip->dev.cm.dispose = drmach_io_dispose;
-	ip->dev.cm.release = drmach_io_release;
-	ip->dev.cm.status = drmach_io_status;
-
-	(void) snprintf(ip->dev.cm.name, sizeof (ip->dev.cm.name), "%s%d",
-	    ip->dev.type, ip->dev.unum);
-
-	*idp = (drmachid_t)ip;
-	return (NULL);
-}
-
-static void
-drmach_io_dispose(drmachid_t id)
-{
-	drmach_io_t *self;
-
-	ASSERT(DRMACH_IS_IO_ID(id));
-
-	self = id;
-	if (self->dev.node)
-		drmach_node_dispose(self->dev.node);
-
-	kmem_free(self, sizeof (*self));
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_pre_op(int cmd, drmachid_t id, drmach_opts_t *opts)
-{
-	drmach_board_t	*bp = (drmach_board_t *)id;
-	sbd_error_t	*err = NULL;
-
-	if (id && DRMACH_IS_BOARD_ID(id)) {
-		switch (cmd) {
-			case SBD_CMD_TEST:
-			case SBD_CMD_STATUS:
-			case SBD_CMD_GETNCM:
-				break;
-			case SBD_CMD_CONNECT:
-				if (bp->connected)
-					err = drerr_new(0, ESBD_STATE, NULL);
-
-				if (bp->cond == SBD_COND_UNUSABLE)
-					err = drerr_new(0,
-					    ESBD_FATAL_STATE, NULL);
-				break;
-			case SBD_CMD_DISCONNECT:
-				if (!bp->connected)
-					err = drerr_new(0, ESBD_STATE, NULL);
-
-				if (bp->cond == SBD_COND_UNUSABLE)
-					err = drerr_new(0,
-					    ESBD_FATAL_STATE, NULL);
-				break;
-			default:
-				if (bp->cond == SBD_COND_UNUSABLE)
-					err = drerr_new(0,
-					    ESBD_FATAL_STATE, NULL);
-				break;
-
-		}
-	}
-
-	return (err);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_post_op(int cmd, drmachid_t id, drmach_opts_t *opts)
-{
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_board_assign(int bnum, drmachid_t *id)
-{
-	sbd_error_t	*err = NULL;
-	caddr_t		obufp;
-
-	if (!drmach_initialized && drmach_init() == -1) {
-		err = DRMACH_INTERNAL_ERROR();
-	}
-
-	rw_enter(&drmach_boards_rwlock, RW_WRITER);
-
-	if (!err) {
-		if (drmach_array_get(drmach_boards, bnum, id) == -1) {
-			err = drerr_new(0, ESTC_BNUM, "%d", bnum);
-		} else {
-			drmach_board_t	*bp;
-
-			if (*id)
-				rw_downgrade(&drmach_boards_rwlock);
-
-			obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-			err = drmach_mbox_trans(DRMSG_ASSIGN, bnum, obufp,
-			    sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
-			kmem_free(obufp, sizeof (dr_proto_hdr_t));
-
-			if (!err) {
-				bp = *id;
-				if (!*id)
-					bp = *id  =
-					    (drmachid_t)drmach_board_new(bnum);
-				bp->assigned = 1;
-			}
-		}
-	}
-	rw_exit(&drmach_boards_rwlock);
-	return (err);
-}
-
-static uint_t
-drmach_board_non_panther_cpus(gdcd_t *gdcd, uint_t exp, uint_t slot)
-{
-	uint_t	port, port_start, port_end;
-	uint_t	non_panther_cpus = 0;
-	uint_t	impl;
-
-	ASSERT(gdcd != NULL);
-
-	/*
-	 * Determine PRD port indices based on slot location.
-	 */
-	switch (slot) {
-	case 0:
-		port_start = 0;
-		port_end = 3;
-		break;
-	case 1:
-		port_start = 4;
-		port_end = 5;
-		break;
-	default:
-		ASSERT(0);
-		/* check all */
-		port_start = 0;
-		port_end = 5;
-		break;
-	}
-
-	for (port = port_start; port <= port_end; port++) {
-		if (gdcd->dcd_prd[exp][port].prd_ptype == SAFPTYPE_CPU &&
-		    RSV_GOOD(gdcd->dcd_prd[exp][port].prd_prsv)) {
-			/*
-			 * This Safari port passed POST and represents a
-			 * cpu, so check the implementation.
-			 */
-			impl = (gdcd->dcd_prd[exp][port].prd_ver_reg >> 32)
-			    & 0xffff;
-
-			switch (impl) {
-			case CHEETAH_IMPL:
-			case CHEETAH_PLUS_IMPL:
-			case JAGUAR_IMPL:
-				non_panther_cpus++;
-				break;
-			case PANTHER_IMPL:
-				break;
-			default:
-				ASSERT(0);
-				non_panther_cpus++;
-				break;
-			}
-		}
-	}
-
-	DRMACH_PR("drmach_board_non_panther_cpus: exp=%d, slot=%d, "
-	    "non_panther_cpus=%d", exp, slot, non_panther_cpus);
-
-	return (non_panther_cpus);
-}
-
-sbd_error_t *
-drmach_board_connect(drmachid_t id, drmach_opts_t *opts)
-{
-	_NOTE(ARGUNUSED(opts))
-
-	drmach_board_t		*bp = (drmach_board_t *)id;
-	sbd_error_t		*err;
-	dr_mbox_msg_t		*obufp;
-	gdcd_t			*gdcd = NULL;
-	uint_t			exp, slot;
-	sc_gptwocfg_cookie_t	scc;
-	int			panther_pages_enabled;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	/*
-	 * Build the casm info portion of the CLAIM message.
-	 */
-	obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
-	mutex_enter(&drmach_slice_table_lock);
-	drmach_msg_memslice_init(obufp->msgdata.dm_cr.mem_slice);
-	drmach_msg_memregs_init(obufp->msgdata.dm_cr.mem_regs);
-	mutex_exit(&drmach_slice_table_lock);
-	err = drmach_mbox_trans(DRMSG_CLAIM, bp->bnum, (caddr_t)obufp,
-	    sizeof (dr_mbox_msg_t), (caddr_t)NULL, 0);
-	kmem_free(obufp, sizeof (dr_mbox_msg_t));
-
-	if (err) {
-		/*
-		 * if mailbox timeout or unrecoverable error from SC,
-		 * board cannot be touched.  Mark the status as
-		 * unusable.
-		 */
-		if ((err->e_code == ESTC_SMS_ERR_UNRECOVERABLE) ||
-		    (err->e_code == ESTC_MBXRPLY))
-			bp->cond = SBD_COND_UNUSABLE;
-		return (err);
-	}
-
-	gdcd = drmach_gdcd_new();
-	if (gdcd == NULL) {
-		cmn_err(CE_WARN, "failed to read GDCD info for %s\n",
-		    bp->cm.name);
-		return (DRMACH_INTERNAL_ERROR());
-	}
-
-	/*
-	 * Read CPU SRAM DR buffer offset from GDCD.
-	 */
-	exp = DRMACH_BNUM2EXP(bp->bnum);
-	slot = DRMACH_BNUM2SLOT(bp->bnum);
-	bp->stardrb_offset =
-	    gdcd->dcd_slot[exp][slot].l1ss_cpu_drblock_xwd_offset << 3;
-	DRMACH_PR("%s: stardrb_offset=0x%lx\n", bp->cm.name,
-	    bp->stardrb_offset);
-
-	/*
-	 * Read board LPA setting from GDCD.
-	 */
-	bp->flags &= ~DRMACH_NULL_PROC_LPA;
-	if (gdcd->dcd_slot[exp][slot].l1ss_flags &
-	    L1SSFLG_THIS_L1_NULL_PROC_LPA) {
-		bp->flags |= DRMACH_NULL_PROC_LPA;
-		DRMACH_PR("%s: NULL proc LPA\n", bp->cm.name);
-	}
-
-	/*
-	 * XXX Until the Solaris large pages support heterogeneous cpu
-	 * domains, DR needs to prevent the addition of non-Panther cpus
-	 * to an all-Panther domain with large pages enabled.
-	 */
-	panther_pages_enabled = (page_num_pagesizes() > DEFAULT_MMU_PAGE_SIZES);
-	if (drmach_board_non_panther_cpus(gdcd, exp, slot) > 0 &&
-	    panther_pages_enabled && drmach_large_page_restriction) {
-		cmn_err(CE_WARN, "Domain shutdown is required to add a non-"
-		    "UltraSPARC-IV+ board into an all UltraSPARC-IV+ domain");
-		err = drerr_new(0, ESTC_SUPPORT, NULL);
-	}
-
-	if (err == NULL) {
-		/* do saf configurator stuff */
-		DRMACH_PR("calling sc_probe_board for bnum=%d\n", bp->bnum);
-		scc = sc_probe_board(bp->bnum);
-		if (scc == NULL)
-			err = drerr_new(0, ESTC_PROBE, bp->cm.name);
-	}
-
-	if (err) {
-		/* flush CDC srams */
-		if (axq_cdc_flush_all() != DDI_SUCCESS) {
-			goto out;
-		}
-
-		/*
-		 * Build the casm info portion of the UNCLAIM message.
-		 */
-		obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
-		mutex_enter(&drmach_slice_table_lock);
-		drmach_msg_memslice_init(obufp->msgdata.dm_ur.mem_slice);
-		drmach_msg_memregs_init(obufp->msgdata.dm_ur.mem_regs);
-		mutex_exit(&drmach_slice_table_lock);
-		(void) drmach_mbox_trans(DRMSG_UNCLAIM, bp->bnum,
-		    (caddr_t)obufp, sizeof (dr_mbox_msg_t),
-		    (caddr_t)NULL, 0);
-
-		kmem_free(obufp, sizeof (dr_mbox_msg_t));
-
-		/*
-		 * we clear the connected flag just in case it would have
-		 * been set by a concurrent drmach_board_status() thread
-		 * before the UNCLAIM completed.
-		 */
-		bp->connected = 0;
-		goto out;
-	}
-
-	/*
-	 * Now that the board has been successfully attached, obtain
-	 * platform-specific DIMM serial id information for the board.
-	 */
-	if ((DRMACH_BNUM2SLOT(bp->bnum) == 0) &&
-	    plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE)) {
-		(void) plat_request_mem_sids(DRMACH_BNUM2EXP(bp->bnum));
-	}
-
-out:
-	if (gdcd != NULL)
-		drmach_gdcd_dispose(gdcd);
-
-	return (err);
-}
-
-static void
-drmach_slice_table_update(drmach_board_t *bp, int invalidate)
-{
-	static char		*axq_name = "address-extender-queue";
-	static dev_info_t	*axq_dip = NULL;
-	static int		 axq_exp = -1;
-	static int		 axq_slot;
-	int			 e, s, slice;
-
-	ASSERT(MUTEX_HELD(&drmach_slice_table_lock));
-
-	e = DRMACH_BNUM2EXP(bp->bnum);
-	if (invalidate) {
-		ASSERT(DRMACH_BNUM2SLOT(bp->bnum) == 0);
-
-		/* invalidate cached casm value */
-		drmach_slice_table[e] = 0;
-
-		/* invalidate cached axq info if for same exp */
-		if (e == axq_exp && axq_dip) {
-			ndi_rele_devi(axq_dip);
-			axq_dip = NULL;
-		}
-	}
-
-	if (axq_dip == NULL || !i_ddi_devi_attached(axq_dip)) {
-		int i, portid;
-
-		/* search for an attached slot0 axq instance */
-		for (i = 0; i < AXQ_MAX_EXP * AXQ_MAX_SLOT_PER_EXP; i++) {
-			if (axq_dip)
-				ndi_rele_devi(axq_dip);
-			axq_dip = ddi_find_devinfo(axq_name, i, 0);
-			if (axq_dip && DDI_CF2(axq_dip)) {
-				portid = ddi_getprop(DDI_DEV_T_ANY, axq_dip,
-				    DDI_PROP_DONTPASS, "portid", -1);
-				if (portid == -1) {
-					DRMACH_PR("cant get portid of axq "
-					    "instance %d\n", i);
-					continue;
-				}
-
-				axq_exp = (portid >> 5) & 0x1f;
-				axq_slot = portid & 1;
-
-				if (invalidate && axq_exp == e)
-					continue;
-
-				if (axq_slot == 0)
-					break;	/* found */
-			}
-		}
-
-		if (i == AXQ_MAX_EXP * AXQ_MAX_SLOT_PER_EXP) {
-			if (axq_dip) {
-				ndi_rele_devi(axq_dip);
-				axq_dip = NULL;
-			}
-			DRMACH_PR("drmach_slice_table_update: failed to "
-			    "update axq dip\n");
-			return;
-		}
-
-	}
-
-	ASSERT(axq_dip);
-	ASSERT(axq_slot == 0);
-
-	if (invalidate)
-		return;
-
-	s = DRMACH_BNUM2SLOT(bp->bnum);
-	DRMACH_PR("using AXQ casm %d.%d for slot%d.%d\n", axq_exp, axq_slot,
-	    e, s);
-
-	/* invalidate entry */
-	drmach_slice_table[e] &= ~0x20;
-
-	/*
-	 * find a slice that routes to expander e. If no match
-	 * is found, drmach_slice_table[e] will remain invalid.
-	 *
-	 * The CASM is a routing table indexed by slice number.
-	 * Each element in the table contains permission bits,
-	 * a destination expander number and a valid bit. The
-	 * valid bit must true for the element to be meaningful.
-	 *
-	 * CASM entry structure
-	 *   Bits 15..6 ignored
-	 *   Bit  5	valid
-	 *   Bits 0..4	expander number
-	 *
-	 * NOTE: the for loop is really enumerating the range of slices,
-	 * which is ALWAYS equal to the range of expanders. Hence,
-	 * AXQ_MAX_EXP is okay to use in this loop.
-	 */
-	for (slice = 0; slice < AXQ_MAX_EXP; slice++) {
-		uint32_t casm = axq_casm_read(axq_exp, axq_slot, slice);
-
-		if ((casm & 0x20) && (casm & 0x1f) == e)
-			drmach_slice_table[e] = 0x20 | slice;
-	}
-}
-
-/*
- * Get base and bound PAs for slot 1 board lpa programming
- * If a cpu/mem board is present in the same expander, use slice
- * information corresponding to the CASM.  Otherwise, set base and
- * bound PAs to 0.
- */
-static void
-drmach_lpa_bb_get(drmach_board_t *s1bp, uint64_t *basep, uint64_t *boundp)
-{
-	drmachid_t s0id;
-
-	ASSERT(mutex_owned(&drmach_slice_table_lock));
-	ASSERT(DRMACH_BNUM2SLOT(s1bp->bnum) == 1);
-
-	*basep = *boundp = 0;
-	if (drmach_array_get(drmach_boards, s1bp->bnum - 1, &s0id) == 0 &&
-	    s0id != 0) {
-
-		uint32_t slice;
-		if ((slice = drmach_slice_table[DRMACH_BNUM2EXP(s1bp->bnum)])
-		    & 0x20) {
-			*basep = DRMACH_SLICE_TO_PA(slice & DRMACH_SLICE_MASK);
-			*boundp = *basep + DRMACH_MEM_SLICE_SIZE;
-		}
-	}
-}
-
-
-/*
- * Reprogram slot 1 lpa's as required.
- * The purpose of this routine is maintain the LPA settings of the devices
- * in slot 1. To date we know Schizo and Cheetah are the only devices that
- * require this attention. The LPA setting must match the slice field in the
- * CASM element for the local expander. This field is guaranteed to be
- * programmed in accordance with the cacheable address space on the slot 0
- * board of the local expander. If no memory is present on the slot 0 board,
- * there is no cacheable address space and, hence, the CASM slice field will
- * be zero or its valid bit will be false (or both).
- */
-
-static void
-drmach_slot1_lpa_set(drmach_board_t *bp)
-{
-	drmachid_t	id;
-	drmach_board_t	*s1bp = NULL;
-	int		rv, idx, is_maxcat = 1;
-	uint64_t	last_scsr_pa = 0;
-	uint64_t	new_basepa, new_boundpa;
-
-	if (DRMACH_BNUM2SLOT(bp->bnum)) {
-		s1bp = bp;
-		if (s1bp->devices == NULL) {
-			DRMACH_PR("drmach...lpa_set: slot1=%d not present",
-			    bp->bnum);
-			return;
-		}
-	} else {
-		rv = drmach_array_get(drmach_boards, bp->bnum + 1, &id);
-		/* nothing to do when board is not found or has no devices */
-		s1bp = id;
-		if (rv == -1 || s1bp == NULL || s1bp->devices == NULL) {
-			DRMACH_PR("drmach...lpa_set: slot1=%d not present",
-			    bp->bnum + 1);
-			return;
-		}
-		ASSERT(DRMACH_IS_BOARD_ID(id));
-	}
-	mutex_enter(&drmach_slice_table_lock);
-	drmach_lpa_bb_get(s1bp, &new_basepa, &new_boundpa);
-	DRMACH_PR("drmach_...lpa_set: bnum=%d base=0x%lx bound=0x%lx\n",
-	    s1bp->bnum, new_basepa, new_boundpa);
-
-	rv = drmach_array_first(s1bp->devices, &idx, &id);
-	while (rv == 0) {
-		if (DRMACH_IS_IO_ID(id)) {
-			drmach_io_t *io = id;
-
-			is_maxcat = 0;
-
-			/*
-			 * Skip all non-Schizo IO devices (only IO nodes
-			 * that are Schizo devices have non-zero scsr_pa).
-			 * Filter out "other" leaf to avoid writing to the
-			 * same Schizo Control/Status Register twice.
-			 */
-			if (io->scsr_pa && io->scsr_pa != last_scsr_pa) {
-				uint64_t scsr;
-
-				scsr  = lddphysio(io->scsr_pa);
-				DRMACH_PR("drmach...lpa_set: old scsr=0x%lx\n",
-				    scsr);
-				scsr &= ~(DRMACH_LPA_BASE_MASK |
-				    DRMACH_LPA_BND_MASK);
-				scsr |= DRMACH_PA_TO_LPA_BASE(new_basepa);
-				scsr |= DRMACH_PA_TO_LPA_BND(new_boundpa);
-
-				stdphysio(io->scsr_pa, scsr);
-				DRMACH_PR("drmach...lpa_set: new scsr=0x%lx\n",
-				    scsr);
-
-				last_scsr_pa = io->scsr_pa;
-			}
-		}
-		rv = drmach_array_next(s1bp->devices, &idx, &id);
-	}
-
-	if (is_maxcat && DRMACH_L1_SET_LPA(s1bp) && drmach_reprogram_lpa) {
-		extern xcfunc_t	drmach_set_lpa;
-
-		DRMACH_PR("reprogramming maxcat lpa's");
-
-		mutex_enter(&cpu_lock);
-		rv = drmach_array_first(s1bp->devices, &idx, &id);
-		while (rv == 0 && id != NULL) {
-			if (DRMACH_IS_CPU_ID(id)) {
-				int ntries;
-				processorid_t cpuid;
-
-				cpuid = ((drmach_cpu_t *)id)->cpuid;
-
-				/*
-				 * Check for unconfigured or powered-off
-				 * MCPUs.  If CPU_READY flag is clear, the
-				 * MCPU cannot be xcalled.
-				 */
-				if ((cpu[cpuid] == NULL) ||
-				    (cpu[cpuid]->cpu_flags &
-				    CPU_READY) == 0) {
-
-					rv = drmach_array_next(s1bp->devices,
-					    &idx, &id);
-					continue;
-				}
-
-				/*
-				 * XXX CHEETAH SUPPORT
-				 * for cheetah, we need to clear iocage
-				 * memory since it will be used for e$ flush
-				 * in drmach_set_lpa.
-				 */
-				if (drmach_is_cheetah) {
-					mutex_enter(&drmach_iocage_lock);
-					while (drmach_iocage_is_busy)
-						cv_wait(&drmach_iocage_cv,
-						    &drmach_iocage_lock);
-					drmach_iocage_is_busy = 1;
-					drmach_iocage_mem_scrub(ecache_size *
-					    2);
-					mutex_exit(&drmach_iocage_lock);
-				}
-
-				/*
-				 * drmach_slice_table[*]
-				 *	bit 5	valid
-				 *	bit 0:4	slice number
-				 *
-				 * drmach_xt_mb[*] format for drmach_set_lpa
-				 *	bit 7	valid
-				 *	bit 6	set null LPA
-				 *			(overrides bits 0:4)
-				 *	bit 0:4	slice number
-				 *
-				 * drmach_set_lpa derives processor CBASE and
-				 * CBND from bits 6 and 0:4 of drmach_xt_mb.
-				 * If bit 6 is set, then CBASE = CBND = 0.
-				 * Otherwise, CBASE = slice number;
-				 * CBND = slice number + 1.
-				 * No action is taken if bit 7 is zero.
-				 */
-
-				mutex_enter(&drmach_xt_mb_lock);
-				bzero((void *)drmach_xt_mb,
-				    drmach_xt_mb_size);
-
-				if (new_basepa == 0 && new_boundpa == 0)
-					drmach_xt_mb[cpuid] = 0x80 | 0x40;
-				else
-					drmach_xt_mb[cpuid] = 0x80 |
-					    DRMACH_PA_TO_SLICE(new_basepa);
-
-				drmach_xt_ready = 0;
-
-				xt_one(cpuid, drmach_set_lpa, NULL, NULL);
-
-				ntries = drmach_cpu_ntries;
-				while (!drmach_xt_ready && ntries) {
-					DELAY(drmach_cpu_delay);
-					ntries--;
-				}
-				mutex_exit(&drmach_xt_mb_lock);
-				drmach_xt_ready = 0;
-
-				/*
-				 * XXX CHEETAH SUPPORT
-				 * for cheetah, we need to clear iocage
-				 * memory since it was used for e$ flush
-				 * in performed drmach_set_lpa.
-				 */
-				if (drmach_is_cheetah) {
-					mutex_enter(&drmach_iocage_lock);
-					drmach_iocage_mem_scrub(ecache_size *
-					    2);
-					drmach_iocage_is_busy = 0;
-					cv_signal(&drmach_iocage_cv);
-					mutex_exit(&drmach_iocage_lock);
-				}
-			}
-			rv = drmach_array_next(s1bp->devices, &idx, &id);
-		}
-		mutex_exit(&cpu_lock);
-	}
-	mutex_exit(&drmach_slice_table_lock);
-}
-
-/*
- * Return the number of connected Panther boards in the domain.
- */
-static int
-drmach_panther_boards(void)
-{
-	int		rv;
-	int		b_idx;
-	drmachid_t	b_id;
-	drmach_board_t	*bp;
-	int		npanther = 0;
-
-	rv = drmach_array_first(drmach_boards, &b_idx, &b_id);
-	while (rv == 0) {
-		ASSERT(DRMACH_IS_BOARD_ID(b_id));
-		bp = b_id;
-
-		if (IS_PANTHER(bp->cpu_impl))
-			npanther++;
-
-		rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
-	}
-
-	return (npanther);
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_board_disconnect(drmachid_t id, drmach_opts_t *opts)
-{
-	drmach_board_t	*bp;
-	dr_mbox_msg_t	*obufp;
-	sbd_error_t	*err = NULL;
-
-	sc_gptwocfg_cookie_t	scc;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	bp = id;
-
-	/*
-	 * Build the casm info portion of the UNCLAIM message.
-	 * This must be done prior to calling for saf configurator
-	 * deprobe, to ensure that the associated axq instance
-	 * is not detached.
-	 */
-	obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
-	mutex_enter(&drmach_slice_table_lock);
-	drmach_msg_memslice_init(obufp->msgdata.dm_ur.mem_slice);
-
-	/*
-	 * If disconnecting slot 0 board, update the casm slice table
-	 * info now, for use by drmach_slot1_lpa_set()
-	 */
-	if (DRMACH_BNUM2SLOT(bp->bnum) == 0)
-		drmach_slice_table_update(bp, 1);
-
-	drmach_msg_memregs_init(obufp->msgdata.dm_ur.mem_regs);
-	mutex_exit(&drmach_slice_table_lock);
-
-	/*
-	 * Update LPA information for slot1 board
-	 */
-	drmach_slot1_lpa_set(bp);
-
-	/* disable and flush CDC */
-	if (axq_cdc_disable_flush_all() != DDI_SUCCESS) {
-		axq_cdc_enable_all();	/* paranoia */
-		err = DRMACH_INTERNAL_ERROR();
-	}
-
-	/*
-	 * call saf configurator for deprobe
-	 * It's done now before sending an UNCLAIM message because
-	 * IKP will probe boards it doesn't know about <present at boot>
-	 * prior to unprobing them.  If this happens after sending the
-	 * UNCLAIM, it will cause a dstop for domain transgression error.
-	 */
-
-	if (!err) {
-		scc = sc_unprobe_board(bp->bnum);
-		axq_cdc_enable_all();
-		if (scc != NULL) {
-			err = drerr_new(0, ESTC_DEPROBE, bp->cm.name);
-		}
-	}
-
-	/*
-	 * If disconnecting a board from a Panther domain, wait a fixed-
-	 * time delay for pending Safari transactions to complete on the
-	 * disconnecting board's processors.  The bus sync list read used
-	 * in drmach_shutdown_asm to synchronize with outstanding Safari
-	 * transactions assumes no read-bypass-write mode for all memory
-	 * controllers.  Since Panther supports read-bypass-write, a
-	 * delay is used that is slightly larger than the maximum Safari
-	 * timeout value in the Safari/Fireplane Config Reg.
-	 */
-	if (drmach_panther_boards() > 0 || drmach_unclaim_delay_all) {
-		clock_t	stime = ddi_get_lbolt();
-
-		delay(drv_usectohz(drmach_unclaim_usec_delay));
-
-		stime = ddi_get_lbolt() - stime;
-		DRMACH_PR("delayed %ld ticks (%ld secs) before disconnecting "
-		    "board %s from domain\n", stime, stime / hz, bp->cm.name);
-	}
-
-	if (!err) {
-		obufp->msgdata.dm_ur.mem_clear = 0;
-
-		err = drmach_mbox_trans(DRMSG_UNCLAIM, bp->bnum, (caddr_t)obufp,
-		    sizeof (dr_mbox_msg_t), (caddr_t)NULL, 0);
-
-		if (err) {
-			/*
-			 * if mailbox timeout or unrecoverable error from SC,
-			 * board cannot be touched.  Mark the status as
-			 * unusable.
-			 */
-			if ((err->e_code == ESTC_SMS_ERR_UNRECOVERABLE) ||
-			    (err->e_code == ESTC_MBXRPLY))
-				bp->cond = SBD_COND_UNUSABLE;
-			else {
-				DRMACH_PR("UNCLAIM failed for bnum=%d\n",
-				    bp->bnum);
-				DRMACH_PR("calling sc_probe_board: bnum=%d\n",
-				    bp->bnum);
-				scc = sc_probe_board(bp->bnum);
-				if (scc == NULL) {
-					cmn_err(CE_WARN,
-					"sc_probe_board failed for bnum=%d",
-					    bp->bnum);
-				} else {
-					if (DRMACH_BNUM2SLOT(bp->bnum) == 0) {
-						mutex_enter(
-						    &drmach_slice_table_lock);
-						drmach_slice_table_update(bp,
-						    0);
-						mutex_exit(
-						    &drmach_slice_table_lock);
-					}
-					drmach_slot1_lpa_set(bp);
-				}
-			}
-		} else {
-			bp->connected = 0;
-			/*
-			 * Now that the board has been successfully detached,
-			 * discard platform-specific DIMM serial id information
-			 * for the board.
-			 */
-			if ((DRMACH_BNUM2SLOT(bp->bnum) == 0) &&
-			    plat_ecc_capability_sc_get(
-			    PLAT_ECC_DIMM_SID_MESSAGE)) {
-				(void) plat_discard_mem_sids(
-				    DRMACH_BNUM2EXP(bp->bnum));
-			}
-		}
-	}
-	kmem_free(obufp, sizeof (dr_mbox_msg_t));
-
-	return (err);
-}
-
-static int
-drmach_get_portid(drmach_node_t *np)
-{
-	drmach_node_t	pp;
-	int		portid;
-	char		type[OBP_MAXPROPNAME];
-
-	if (np->n_getprop(np, "portid", &portid, sizeof (portid)) == 0)
-		return (portid);
-
-	/*
-	 * Get the device_type property to see if we should
-	 * continue processing this node.
-	 */
-	if (np->n_getprop(np, "device_type", &type, sizeof (type)) != 0)
-		return (-1);
-
-	/*
-	 * If the device is a CPU without a 'portid' property,
-	 * it is a CMP core. For such cases, the parent node
-	 * has the portid.
-	 */
-	if (strcmp(type, DRMACH_CPU_NAMEPROP) == 0) {
-		if (np->get_parent(np, &pp) != 0)
-			return (-1);
-
-		if (pp.n_getprop(&pp, "portid", &portid, sizeof (portid)) == 0)
-			return (portid);
-	}
-
-	return (-1);
-}
-
-/*
- * This is a helper function to determine if a given
- * node should be considered for a dr operation according
- * to predefined dr type nodes and the node's name.
- * Formal Parameter : The name of a device node.
- * Return Value: -1, name does not map to a valid dr type.
- *		 A value greater or equal to 0, name is a valid dr type.
- */
-static int
-drmach_name2type_idx(char *name)
-{
-	int 	index, ntypes;
-
-	if (name == NULL)
-		return (-1);
-
-	/*
-	 * Determine how many possible types are currently supported
-	 * for dr.
-	 */
-	ntypes = sizeof (drmach_name2type) / sizeof (drmach_name2type[0]);
-
-	/* Determine if the node's name correspond to a predefined type. */
-	for (index = 0; index < ntypes; index++) {
-		if (strcmp(drmach_name2type[index].name, name) == 0)
-			/* The node is an allowed type for dr. */
-			return (index);
-	}
-
-	/*
-	 * If the name of the node does not map to any of the
-	 * types in the array drmach_name2type then the node is not of
-	 * interest to dr.
-	 */
-	return (-1);
-}
-
-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, portid;
-	drmachid_t	id;
-	drmach_device_t	*device;
-	char	name[OBP_MAXDRVNAME];
-
-	portid = drmach_get_portid(node);
-	if (portid == -1) {
-		/*
-		 * if the node does not have a portid property, then
-		 * by that information alone it is known that drmach
-		 * is not interested in it.
-		 */
-		return (0);
-	}
-	rv = node->n_getprop(node, "name", name, OBP_MAXDRVNAME);
-
-	/* The node must have a name */
-	if (rv)
-		return (0);
-
-	/*
-	 * Ignore devices whose portid do not map to this board,
-	 * or that their name property is not mapped to a valid
-	 * dr device name.
-	 */
-	if ((drmach_portid2bnum(portid) != obj->bnum) ||
-	    (drmach_name2type_idx(name) < 0))
-		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, portid, &id);
-	if (data->err)
-		return (-1);
-	else if (!id) {
-		/*
-		 * drmach_device_new examined the node we passed in
-		 * and determined that it was either one not of
-		 * interest to drmach or the PIM dr layer.
-		 * So, it is skipped.
-		 */
-		return (0);
-	}
-
-	rv = drmach_array_set(obj->devices, data->ndevs++, id);
-	if (rv) {
-		data->err = DRMACH_INTERNAL_ERROR();
-		return (-1);
-	}
-
-	device = id;
-
-#ifdef DEBUG
-	DRMACH_PR("%d %s %d %p\n", portid, device->type, device->unum, id);
-	if (DRMACH_IS_IO_ID(id))
-		DRMACH_PR("ndevs = %d dip/node = %p", data->ndevs, node->here);
-#endif
-
-	data->err = (*data->found)(data->a, device->type, device->unum, id);
-	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))
-{
-	drmach_board_t		*bp = (drmach_board_t *)id;
-	sbd_error_t		*err;
-	int			 max_devices;
-	int			 rv;
-	drmach_board_cb_data_t	data;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	max_devices  = plat_max_cpu_units_per_board();
-	max_devices += plat_max_mem_units_per_board();
-	max_devices += plat_max_io_units_per_board();
-
-	bp->devices = drmach_array_new(0, max_devices);
-
-	if (bp->tree == NULL)
-		bp->tree = drmach_node_new();
-
-	data.obj = bp;
-	data.ndevs = 0;
-	data.found = found;
-	data.a = a;
-	data.err = NULL;
-
-	mutex_enter(&drmach_slice_table_lock);
-	mutex_enter(&drmach_bus_sync_lock);
-
-	rv = drmach_node_walk(bp->tree, &data, drmach_board_find_devices_cb);
-
-	drmach_slice_table_update(bp, 0);
-	drmach_bus_sync_list_update();
-
-	mutex_exit(&drmach_bus_sync_lock);
-	mutex_exit(&drmach_slice_table_lock);
-
-	if (rv == 0) {
-		err = NULL;
-		drmach_slot1_lpa_set(bp);
-	} else {
-		drmach_array_dispose(bp->devices, drmach_device_dispose);
-		bp->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;
-		return (-1);
-	}
-	rw_enter(&drmach_boards_rwlock, RW_WRITER);
-	if (drmach_array_get(drmach_boards, bnum, id)) {
-		*id = 0;
-		rv = -1;
-	} else {
-		caddr_t		obufp;
-		dr_showboard_t	shb;
-		sbd_error_t	*err = NULL;
-		drmach_board_t	*bp;
-
-		bp = *id;
-
-		if (bp)
-			rw_downgrade(&drmach_boards_rwlock);
-
-		obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-		err = drmach_mbox_trans(DRMSG_SHOWBOARD, bnum, obufp,
-		    sizeof (dr_proto_hdr_t), (caddr_t)&shb,
-		    sizeof (dr_showboard_t));
-		kmem_free(obufp, sizeof (dr_proto_hdr_t));
-
-		if (err) {
-			if (err->e_code == ESTC_UNAVAILABLE) {
-				*id = 0;
-				rv = -1;
-			}
-			sbd_err_clear(&err);
-		} else {
-			if (!bp)
-				bp = *id  = (drmachid_t)drmach_board_new(bnum);
-			bp->connected = (shb.bd_assigned && shb.bd_active);
-			bp->empty = shb.slot_empty;
-
-			switch (shb.test_status) {
-				case DR_TEST_STATUS_UNKNOWN:
-				case DR_TEST_STATUS_IPOST:
-				case DR_TEST_STATUS_ABORTED:
-					bp->cond = SBD_COND_UNKNOWN;
-					break;
-				case DR_TEST_STATUS_PASSED:
-					bp->cond = SBD_COND_OK;
-					break;
-				case DR_TEST_STATUS_FAILED:
-					bp->cond = SBD_COND_FAILED;
-					break;
-				default:
-					bp->cond = SBD_COND_UNKNOWN;
-				DRMACH_PR("Unknown test status=0x%x from SC\n",
-				    shb.test_status);
-					break;
-			}
-			(void) strncpy(bp->type, shb.board_type,
-			    sizeof (bp->type));
-			bp->assigned = shb.bd_assigned;
-			bp->powered = shb.power_on;
-		}
-	}
-	rw_exit(&drmach_boards_rwlock);
-	return (rv);
-}
-
-sbd_error_t *
-drmach_board_name(int bnum, char *buf, int buflen)
-{
-	(void) snprintf(buf, buflen, "%s%d", DRMACH_BNUM2SLOT(bnum) ?
-	    "IO" : "SB", DRMACH_BNUM2EXP(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, ESTC_INAPPROP, NULL));
-	bp = id;
-
-	err = drmach_board_status(id, &stat);
-	if (!err) {
-		if (stat.configured || stat.busy)
-			err = drerr_new(0, ESTC_CONFIGBUSY, bp->cm.name);
-		else {
-			caddr_t	obufp;
-
-			obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-			err = drmach_mbox_trans(DRMSG_POWEROFF, bp->bnum, obufp,
-			    sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
-			kmem_free(obufp, sizeof (dr_proto_hdr_t));
-			if (!err)
-				bp->powered = 0;
-		}
-	}
-	return (err);
-}
-
-sbd_error_t *
-drmach_board_poweron(drmachid_t id)
-{
-	drmach_board_t	*bp;
-	caddr_t		obufp;
-	sbd_error_t	*err;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	bp = id;
-
-	obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-	err = drmach_mbox_trans(DRMSG_POWERON, bp->bnum, obufp,
-	    sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
-	if (!err)
-		bp->powered = 1;
-
-	kmem_free(obufp, sizeof (dr_proto_hdr_t));
-
-	return (err);
-}
-
-static sbd_error_t *
-drmach_board_release(drmachid_t id)
-{
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_board_test(drmachid_t id, drmach_opts_t *opts, int force)
-{
-	drmach_board_t		*bp;
-	drmach_device_t		*dp[MAX_CORES_PER_CMP];
-	dr_mbox_msg_t		*obufp;
-	sbd_error_t		*err;
-	dr_testboard_reply_t	tbr;
-	int			cpylen;
-	char			*copts;
-	int			is_io;
-	cpu_flag_t		oflags[MAX_CORES_PER_CMP];
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	bp = id;
-
-	/*
-	 * If the board is an I/O or MAXCAT board, setup I/O cage for
-	 * testing. Slot 1 indicates I/O or MAXCAT board.
-	 */
-
-	is_io = DRMACH_BNUM2SLOT(bp->bnum);
-
-	obufp = kmem_zalloc(sizeof (dr_mbox_msg_t), KM_SLEEP);
-
-	if (force)
-		obufp->msgdata.dm_tb.force = 1;
-
-	obufp->msgdata.dm_tb.immediate = 1;
-
-	if ((opts->size > 0) && ((copts = opts->copts) != NULL)) {
-		cpylen = (opts->size > DR_HPOPTLEN ? DR_HPOPTLEN : opts->size);
-		bcopy(copts, obufp->msgdata.dm_tb.hpost_opts, cpylen);
-	}
-
-	if (is_io) {
-		err = drmach_iocage_setup(&obufp->msgdata.dm_tb, dp, oflags);
-
-		if (err) {
-			kmem_free(obufp, sizeof (dr_mbox_msg_t));
-			return (err);
-		}
-	}
-
-	err = drmach_mbox_trans(DRMSG_TESTBOARD, bp->bnum, (caddr_t)obufp,
-	    sizeof (dr_mbox_msg_t), (caddr_t)&tbr, sizeof (tbr));
-
-	if (!err)
-		bp->cond = SBD_COND_OK;
-	else
-		bp->cond = SBD_COND_UNKNOWN;
-
-	if ((!err) && (tbr.test_status != DR_TEST_STATUS_PASSED)) {
-		/* examine test status */
-		switch (tbr.test_status) {
-			case DR_TEST_STATUS_IPOST:
-				bp->cond = SBD_COND_UNKNOWN;
-				err = drerr_new(0, ESTC_TEST_IN_PROGRESS, NULL);
-				break;
-			case DR_TEST_STATUS_UNKNOWN:
-				bp->cond = SBD_COND_UNKNOWN;
-				err = drerr_new(1,
-				    ESTC_TEST_STATUS_UNKNOWN, NULL);
-				break;
-			case DR_TEST_STATUS_FAILED:
-				bp->cond = SBD_COND_FAILED;
-				err = drerr_new(1, ESTC_TEST_FAILED, NULL);
-				break;
-			case DR_TEST_STATUS_ABORTED:
-				bp->cond = SBD_COND_UNKNOWN;
-				err = drerr_new(1, ESTC_TEST_ABORTED, NULL);
-				break;
-			default:
-				bp->cond = SBD_COND_UNKNOWN;
-				err = drerr_new(1, ESTC_TEST_RESULT_UNKNOWN,
-				    NULL);
-				break;
-		}
-	}
-
-	/*
-	 * If I/O cage test was performed, check for availability of the
-	 * cpu used.  If cpu has been returned, it's OK to proceed with
-	 * reconfiguring it for use.
-	 */
-	if (is_io) {
-		DRMACH_PR("drmach_board_test: tbr.cpu_recovered: %d",
-		    tbr.cpu_recovered);
-		DRMACH_PR("drmach_board_test: port id: %d",
-		    tbr.cpu_portid);
-
-		/*
-		 * Check the cpu_recovered flag in the testboard reply, or
-		 * if the testboard request message was not sent to SMS due
-		 * to an mboxsc_putmsg() failure, it's OK to recover the
-		 * cpu since hpost hasn't touched it.
-		 */
-		if ((tbr.cpu_recovered && tbr.cpu_portid ==
-		    obufp->msgdata.dm_tb.cpu_portid) ||
-		    ((err) && (err->e_code == ESTC_MBXRQST))) {
-
-			int i;
-
-			mutex_enter(&cpu_lock);
-			for (i = 0; i < MAX_CORES_PER_CMP; i++) {
-				if (dp[i] != NULL) {
-					(void) drmach_iocage_cpu_return(dp[i],
-					    oflags[i]);
-				}
-			}
-			mutex_exit(&cpu_lock);
-		} else {
-			cmn_err(CE_WARN, "Unable to recover port id %d "
-			    "after I/O cage test: cpu_recovered=%d, "
-			    "returned portid=%d",
-			    obufp->msgdata.dm_tb.cpu_portid,
-			    tbr.cpu_recovered, tbr.cpu_portid);
-		}
-		(void) drmach_iocage_mem_return(&tbr);
-	}
-	kmem_free(obufp, sizeof (dr_mbox_msg_t));
-
-	return (err);
-}
-
-sbd_error_t *
-drmach_board_unassign(drmachid_t id)
-{
-	drmach_board_t	*bp;
-	sbd_error_t	*err;
-	drmach_status_t	 stat;
-	caddr_t		obufp;
-
-	rw_enter(&drmach_boards_rwlock, RW_WRITER);
-
-	if (!DRMACH_IS_BOARD_ID(id)) {
-		rw_exit(&drmach_boards_rwlock);
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	}
-	bp = id;
-
-	err = drmach_board_status(id, &stat);
-	if (err) {
-		rw_exit(&drmach_boards_rwlock);
-		return (err);
-	}
-
-	if (stat.configured || stat.busy) {
-		err = drerr_new(0, ESTC_CONFIGBUSY, bp->cm.name);
-	} else {
-
-		obufp = kmem_zalloc(sizeof (dr_proto_hdr_t), KM_SLEEP);
-		err = drmach_mbox_trans(DRMSG_UNASSIGN, bp->bnum, obufp,
-		    sizeof (dr_proto_hdr_t), (caddr_t)NULL, 0);
-		kmem_free(obufp, sizeof (dr_proto_hdr_t));
-		if (!err) {
-			if (drmach_array_set(drmach_boards, bp->bnum, 0) != 0)
-				err = DRMACH_INTERNAL_ERROR();
-			else
-				drmach_board_dispose(bp);
-		}
-	}
-	rw_exit(&drmach_boards_rwlock);
-	return (err);
-}
-
-static sbd_error_t *
-drmach_read_reg_addr(drmach_device_t *dp, uint64_t *p)
-{
-	int		len;
-	drmach_reg_t	reg;
-	drmach_node_t	pp;
-	drmach_node_t	*np = dp->node;
-
-	/*
-	 * If the node does not have a portid property,
-	 * it represents a CMP device. For a CMP, the reg
-	 * property of the parent holds the information of
-	 * interest.
-	 */
-	if (dp->node->n_getproplen(dp->node, "portid", &len) != 0) {
-
-		if (dp->node->get_parent(dp->node, &pp) != 0) {
-			return (DRMACH_INTERNAL_ERROR());
-		}
-		np = &pp;
-	}
-
-	if (np->n_getproplen(np, "reg", &len) != 0)
-		return (DRMACH_INTERNAL_ERROR());
-
-	if (len != sizeof (reg))
-		return (DRMACH_INTERNAL_ERROR());
-
-	if (np->n_getprop(np, "reg", &reg, sizeof (reg)) != 0)
-		return (DRMACH_INTERNAL_ERROR());
-
-	/* reassemble 64-bit base address */
-	*p = ((uint64_t)reg.reg_addr_hi << 32) | reg.reg_addr_lo;
-
-	return (NULL);
-}
-
-static void
-drmach_cpu_read(uint64_t arg1, uint64_t arg2)
-{
-	uint64_t	*saf_config_reg = (uint64_t *)arg1;
-	uint_t		*reg_read = (uint_t *)arg2;
-
-	*saf_config_reg = lddsafconfig();
-	*reg_read = 0x1;
-}
-
-/*
- * A return value of 1 indicates success and 0 indicates a failure
- */
-static int
-drmach_cpu_read_scr(drmach_cpu_t *cp, uint64_t *scr)
-{
-
-	int 	rv = 0x0;
-
-	*scr = 0x0;
-
-	/*
-	 * Confirm cpu was in ready set when xc was issued.
-	 * This is done by verifying rv which is
-	 * set to 0x1 when xc_one is successful.
-	 */
-	xc_one(cp->dev.portid, (xcfunc_t *)drmach_cpu_read,
-	    (uint64_t)scr, (uint64_t)&rv);
-
-	return (rv);
-
-}
-
-static sbd_error_t *
-drmach_cpu_read_cpuid(drmach_cpu_t *cp, processorid_t *cpuid)
-{
-	drmach_node_t	*np;
-
-	np = cp->dev.node;
-
-	/*
-	 * If a CPU does not have a portid property, it must
-	 * be a CMP device with a cpuid property.
-	 */
-	if (np->n_getprop(np, "portid", cpuid, sizeof (*cpuid)) != 0) {
-
-		if (np->n_getprop(np, "cpuid", cpuid, sizeof (*cpuid)) != 0) {
-			return (DRMACH_INTERNAL_ERROR());
-		}
-	}
-
-	return (NULL);
-}
-
-/* Starcat CMP core id is bit 2 of the cpuid */
-#define	DRMACH_COREID_MASK	(1u << 2)
-#define	DRMACH_CPUID2SRAM_IDX(id) \
-		((id & DRMACH_COREID_MASK) >> 1 | (id & 0x1))
-
-static sbd_error_t *
-drmach_cpu_new(drmach_device_t *proto, drmachid_t *idp)
-{
-	sbd_error_t	*err;
-	uint64_t	scr_pa;
-	drmach_cpu_t	*cp = NULL;
-	pfn_t		pfn;
-	uint64_t	cpu_stardrb_offset, cpu_sram_pa;
-	int		idx;
-	int		impl;
-	processorid_t	cpuid;
-
-	err = drmach_read_reg_addr(proto, &scr_pa);
-	if (err) {
-		goto fail;
-	}
-
-	cp = kmem_zalloc(sizeof (drmach_cpu_t), KM_SLEEP);
-	bcopy(proto, &cp->dev, sizeof (cp->dev));
-	cp->dev.node = drmach_node_dup(proto->node);
-	cp->dev.cm.isa = (void *)drmach_cpu_new;
-	cp->dev.cm.dispose = drmach_cpu_dispose;
-	cp->dev.cm.release = drmach_cpu_release;
-	cp->dev.cm.status = drmach_cpu_status;
-	cp->scr_pa = scr_pa;
-
-	err = drmach_cpu_read_cpuid(cp, &cpuid);
-	if (err) {
-		goto fail;
-	}
-
-	err = drmach_cpu_get_impl(cp, &impl);
-	if (err) {
-		goto fail;
-	}
-
-	cp->cpuid = cpuid;
-	cp->coreid = STARCAT_CPUID_TO_COREID(cp->cpuid);
-	cp->dev.unum = STARCAT_CPUID_TO_AGENT(cp->cpuid);
-
-	/*
-	 * Init the board cpu type.  Assumes all board cpus are the same type.
-	 */
-	if (cp->dev.bp->cpu_impl == 0) {
-		cp->dev.bp->cpu_impl = impl;
-	}
-	ASSERT(cp->dev.bp->cpu_impl == impl);
-
-	/*
-	 * XXX CHEETAH SUPPORT
-	 * determine if the domain uses Cheetah procs
-	 */
-	if (drmach_is_cheetah < 0) {
-		drmach_is_cheetah = IS_CHEETAH(impl);
-	}
-
-	/*
-	 * Initialize TTE for mapping CPU SRAM STARDRB buffer.
-	 * The STARDRB buffer (16KB on Cheetah+ boards, 32KB on
-	 * Jaguar/Panther boards) is shared by all cpus in a Safari port
-	 * pair. Each cpu uses 8KB according to the following layout:
-	 *
-	 * Page 0:	even numbered Cheetah+'s and Panther/Jaguar core 0's
-	 * Page 1:	odd numbered Cheetah+'s and Panther/Jaguar core 0's
-	 * Page 2:	even numbered Panther/Jaguar core 1's
-	 * Page 3:	odd numbered Panther/Jaguar core 1's
-	 */
-	idx = DRMACH_CPUID2SRAM_IDX(cp->cpuid);
-	cpu_stardrb_offset = cp->dev.bp->stardrb_offset + (PAGESIZE * idx);
-	cpu_sram_pa = DRMACH_CPU_SRAM_ADDR + cpu_stardrb_offset;
-	pfn = cpu_sram_pa >> PAGESHIFT;
-
-	ASSERT(drmach_cpu_sram_tte[cp->cpuid].tte_inthi == 0 &&
-	    drmach_cpu_sram_tte[cp->cpuid].tte_intlo == 0);
-	drmach_cpu_sram_tte[cp->cpuid].tte_inthi = TTE_PFN_INTHI(pfn) |
-	    TTE_VALID_INT | TTE_SZ_INT(TTE8K);
-	drmach_cpu_sram_tte[cp->cpuid].tte_intlo = TTE_PFN_INTLO(pfn) |
-	    TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT;
-
-	DRMACH_PR("drmach_cpu_new: cpuid=%d, coreid=%d, stardrb_offset=0x%lx, "
-	    "cpu_sram_offset=0x%lx, idx=%d\n", cp->cpuid, cp->coreid,
-	    cp->dev.bp->stardrb_offset, cpu_stardrb_offset, idx);
-
-	(void) snprintf(cp->dev.cm.name, sizeof (cp->dev.cm.name), "%s%d",
-	    cp->dev.type, cp->dev.unum);
-
-	*idp = (drmachid_t)cp;
-	return (NULL);
-
-fail:
-	if (cp) {
-		drmach_node_dispose(cp->dev.node);
-		kmem_free(cp, sizeof (*cp));
-	}
-
-	*idp = (drmachid_t)0;
-	return (err);
-}
-
-static void
-drmach_cpu_dispose(drmachid_t id)
-{
-	drmach_cpu_t	*self;
-	processorid_t	cpuid;
-
-	ASSERT(DRMACH_IS_CPU_ID(id));
-
-	self = id;
-	if (self->dev.node)
-		drmach_node_dispose(self->dev.node);
-
-	cpuid = self->cpuid;
-	ASSERT(TTE_IS_VALID(&drmach_cpu_sram_tte[cpuid]) &&
-	    TTE_IS_8K(&drmach_cpu_sram_tte[cpuid]) &&
-	    TTE_IS_PRIVILEGED(&drmach_cpu_sram_tte[cpuid]) &&
-	    TTE_IS_LOCKED(&drmach_cpu_sram_tte[cpuid]));
-	drmach_cpu_sram_tte[cpuid].tte_inthi = 0;
-	drmach_cpu_sram_tte[cpuid].tte_intlo = 0;
-
-	kmem_free(self, sizeof (*self));
-}
-
-static int
-drmach_cpu_start(struct cpu *cp)
-{
-	extern xcfunc_t	drmach_set_lpa;
-	extern void	restart_other_cpu(int);
-	int		cpuid = cp->cpu_id;
-	int		rv, bnum;
-	drmach_board_t	*bp;
-
-	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);
-
-	if (prom_hotaddcpu(cpuid) != 0) {
-		cmn_err(CE_PANIC, "prom_hotaddcpu() for cpuid=%d failed.",
-		    cpuid);
-	}
-
-	restart_other_cpu(cpuid);
-
-	bnum = drmach_portid2bnum(cpunodes[cpuid].portid);
-	rv = drmach_array_get(drmach_boards, bnum, (drmachid_t)&bp);
-	if (rv == -1 || bp == NULL) {
-		DRMACH_PR("drmach_cpu_start: cannot read board info for "
-		    "cpuid=%d: rv=%d, bp=%p\n", cpuid, rv, (void *)bp);
-	} else if (DRMACH_L1_SET_LPA(bp) && drmach_reprogram_lpa) {
-		int exp;
-		int ntries;
-
-		mutex_enter(&drmach_xt_mb_lock);
-		mutex_enter(&drmach_slice_table_lock);
-		bzero((void *)drmach_xt_mb, drmach_xt_mb_size);
-
-		/*
-		 * drmach_slice_table[*]
-		 *	bit 5	valid
-		 *	bit 0:4	slice number
-		 *
-		 * drmach_xt_mb[*] format for drmach_set_lpa
-		 *	bit 7	valid
-		 *	bit 6	set null LPA (overrides bits 0:4)
-		 *	bit 0:4	slice number
-		 *
-		 * drmach_set_lpa derives processor CBASE and CBND
-		 * from bits 6 and 0:4 of drmach_xt_mb.  If bit 6 is
-		 * set, then CBASE = CBND = 0. Otherwise, CBASE = slice
-		 * number; CBND = slice number + 1.
-		 * No action is taken if bit 7 is zero.
-		 */
-		exp = (cpuid >> 5) & 0x1f;
-		if (drmach_slice_table[exp] & 0x20) {
-			drmach_xt_mb[cpuid] = 0x80 |
-			    (drmach_slice_table[exp] & 0x1f);
-		} else {
-			drmach_xt_mb[cpuid] = 0x80 | 0x40;
-		}
-
-		drmach_xt_ready = 0;
-
-		xt_one(cpuid, drmach_set_lpa, NULL, NULL);
-
-		ntries = drmach_cpu_ntries;
-		while (!drmach_xt_ready && ntries) {
-			DELAY(drmach_cpu_delay);
-			ntries--;
-		}
-
-		mutex_exit(&drmach_slice_table_lock);
-		mutex_exit(&drmach_xt_mb_lock);
-
-		DRMACH_PR(
-		    "waited %d out of %d tries for drmach_set_lpa on cpu%d",
-		    drmach_cpu_ntries - ntries, drmach_cpu_ntries,
-		    cp->cpu_id);
-	}
-
-	xt_one(cpuid, vtag_flushpage_tl1, (uint64_t)drmach_cpu_sram_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 the STARDRB data buffer located
- *	   in this cpu's sram. There is one TTE per cpu, initialized in
- *	   drmach_cpu_new(). The cpuid is used to select which TTE to use.
- *	   Each Safari port pair shares the CPU SRAM on a Serengeti CPU/MEM
- *	   board. The STARDRB buffer is 16KB on Cheetah+ boards, 32KB on Jaguar
- *	   boards. Each STARDRB buffer is logically divided by DR into one
- *	   8KB page per cpu (or Jaguar core).
- *	2) Copy the target function (drmach_shutdown_asm) into buffer.
- *	3) Jump to function now in the cpu sram.
- *	   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 and I-TLB entries.
- *	   3.5) Set LPA to NULL
- *	   3.6) Clear xt_mb to signal completion. Note: cache line is
- *	        recovered by drmach_cpu_poweroff().
- *	4) Jump into an infinite loop.
- */
-
-static void
-drmach_cpu_stop_self(void)
-{
-	extern void drmach_shutdown_asm(uint64_t, uint64_t, int, int, uint64_t);
-	extern void drmach_shutdown_asm_end(void);
-
-	tte_t		*tte;
-	uint_t		*p, *q;
-	uint64_t	 stack_pointer;
-
-	ASSERT(((ptrdiff_t)drmach_shutdown_asm_end -
-	    (ptrdiff_t)drmach_shutdown_asm) < PAGESIZE);
-
-	tte = &drmach_cpu_sram_tte[CPU->cpu_id];
-	ASSERT(TTE_IS_VALID(tte) && TTE_IS_8K(tte) && TTE_IS_PRIVILEGED(tte) &&
-	    TTE_IS_LOCKED(tte));
-	sfmmu_dtlb_ld_kva(drmach_cpu_sram_va, tte);
-	sfmmu_itlb_ld_kva(drmach_cpu_sram_va, tte);
-
-	/* copy text. standard bcopy not designed to work in nc space */
-	p = (uint_t *)drmach_cpu_sram_va;
-	q = (uint_t *)drmach_shutdown_asm;
-	while (q < (uint_t *)drmach_shutdown_asm_end)
-		*p++ = *q++;
-
-	/* zero to assist debug */
-	q = (uint_t *)(drmach_cpu_sram_va + PAGESIZE);
-	while (p < q)
-		*p++ = 0;
-
-	/* a parking spot for the stack pointer */
-	stack_pointer = (uint64_t)q;
-
-	/* call copy of drmach_shutdown_asm */
-	(*(void (*)())drmach_cpu_sram_va)(
-	    stack_pointer,
-	    drmach_iocage_paddr,
-	    cpunodes[CPU->cpu_id].ecache_size,
-	    cpunodes[CPU->cpu_id].ecache_linesize,
-	    va_to_pa((void *)&drmach_xt_mb[CPU->cpu_id]));
-}
-
-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);
-}
-
-static sbd_error_t *
-drmach_cpu_release(drmachid_t id)
-{
-	drmach_cpu_t	*cp;
-	struct cpu	*cpu;
-	sbd_error_t	*err;
-
-	if (!DRMACH_IS_CPU_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	cp = id;
-
-	ASSERT(MUTEX_HELD(&cpu_lock));
-
-	cpu = cpu_get(cp->cpuid);
-	if (cpu == NULL)
-		err = DRMACH_INTERNAL_ERROR();
-	else
-		err = NULL;
-
-	return (err);
-}
-
-static sbd_error_t *
-drmach_cpu_status(drmachid_t id, drmach_status_t *stat)
-{
-	drmach_cpu_t	*cp;
-	drmach_device_t	*dp;
-
-	ASSERT(DRMACH_IS_CPU_ID(id));
-	cp = id;
-	dp = &cp->dev;
-
-	stat->assigned = dp->bp->assigned;
-	stat->powered = dp->bp->powered;
-	mutex_enter(&cpu_lock);
-	stat->configured = (cpu_get(cp->cpuid) != 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)
-{
-	if (!DRMACH_IS_CPU_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_cpu_get_id(drmachid_t id, processorid_t *cpuid)
-{
-	drmach_cpu_t	*cpu;
-
-	if (!DRMACH_IS_CPU_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	cpu = id;
-
-	*cpuid = cpu->cpuid;
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_cpu_get_impl(drmachid_t id, int *ip)
-{
-	drmach_node_t	*np;
-	int		impl;
-
-	if (!DRMACH_IS_CPU_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	np = ((drmach_device_t *)id)->node;
-
-	if (np->n_getprop(np, "implementation#", &impl, sizeof (impl)) == -1) {
-		return (DRMACH_INTERNAL_ERROR());
-	}
-
-	*ip = impl;
-
-	return (NULL);
-}
-
-/*
- * Flush this cpu's ecache, then ensure all outstanding safari
- * transactions have retired.
- */
-void
-drmach_cpu_flush_ecache_sync(void)
-{
-	uint64_t *p;
-
-	ASSERT(curthread->t_bound_cpu == CPU);
-
-	cpu_flush_ecache();
-
-	mutex_enter(&drmach_bus_sync_lock);
-	for (p = drmach_bus_sync_list; *p; p++)
-		(void) ldphys(*p);
-	mutex_exit(&drmach_bus_sync_lock);
-
-	cpu_flush_ecache();
-}
-
-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, ESTC_INAPPROP, NULL));
-	dp = id;
-
-	*dip = dp->node->n_getdip(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, ESTC_INAPPROP, NULL));
-	dp = id;
-
-	dip = dp->node->n_getdip(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);
-}
-
-static int
-drmach_dip_is_schizo_xmits_0_pci_b(dev_info_t *dip)
-{
-	char			dtype[OBP_MAXPROPNAME];
-	int			portid;
-	uint_t			pci_csr_base;
-	struct pci_phys_spec	*regbuf = NULL;
-	int			rv, len;
-
-	ASSERT(dip != NULL);
-	rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "device_type", &len);
-	if ((rv != DDI_PROP_SUCCESS) || (len > sizeof (dtype)))
-		return (0);
-
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "device_type",
-	    (caddr_t)dtype, &len) == DDI_PROP_SUCCESS) {
-
-		if (strncmp(dtype, "pci", 3) == 0) {
-
-			/*
-			 * Get safari portid. All schizo/xmits 0
-			 * safari IDs end in 0x1C.
-			 */
-			rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "portid",
-			    &len);
-
-			if ((rv != DDI_PROP_SUCCESS) ||
-			    (len > sizeof (portid)))
-				return (0);
-
-			rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0,
-			    "portid", (caddr_t)&portid, &len);
-
-			if (rv != DDI_PROP_SUCCESS)
-				return (0);
-
-			if ((portid & 0x1F) != 0x1C)
-				return (0);
-
-			if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
-			    DDI_PROP_DONTPASS, "reg", (caddr_t)&regbuf,
-			    &len) == DDI_PROP_SUCCESS) {
-
-				pci_csr_base = regbuf[0].pci_phys_mid &
-				    PCI_CONF_ADDR_MASK;
-				kmem_free(regbuf, len);
-				/*
-				 * All PCI B-Leafs are at configspace 0x70.0000.
-				 */
-				if (pci_csr_base == 0x700000)
-					return (1);
-			}
-		}
-	}
-	return (0);
-}
-
-#define	SCHIZO_BINDING_NAME		"pci108e,8001"
-#define	XMITS_BINDING_NAME		"pci108e,8002"
-
-/*
- * Verify if the dip is an instance of MAN 'eri'.
- */
-static int
-drmach_dip_is_man_eri(dev_info_t *dip)
-{
-	struct pci_phys_spec	*regbuf = NULL;
-	dev_info_t		*parent_dip;
-	char			*name;
-	uint_t			pci_device;
-	uint_t			pci_function;
-	int			len;
-
-	if (dip == NULL)
-		return (0);
-	/*
-	 * Verify if the parent is schizo(xmits)0 and pci B leaf.
-	 */
-	if (((parent_dip = ddi_get_parent(dip)) == NULL) ||
-	    ((name = ddi_binding_name(parent_dip)) == NULL))
-		return (0);
-	if (strcmp(name, SCHIZO_BINDING_NAME) != 0) {
-		/*
-		 * This RIO could be on XMITS, so get the dip to
-		 * XMITS PCI Leaf.
-		 */
-		if ((parent_dip = ddi_get_parent(parent_dip)) == NULL)
-			return (0);
-		if (((name = ddi_binding_name(parent_dip)) == NULL) ||
-		    (strcmp(name, XMITS_BINDING_NAME) != 0)) {
-			return (0);
-		}
-	}
-	if (!drmach_dip_is_schizo_xmits_0_pci_b(parent_dip))
-		return (0);
-	/*
-	 * Finally make sure it is the MAN eri.
-	 */
-	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "reg", (caddr_t)&regbuf, &len) == DDI_PROP_SUCCESS) {
-
-		pci_device = PCI_REG_DEV_G(regbuf->pci_phys_hi);
-		pci_function = PCI_REG_FUNC_G(regbuf->pci_phys_hi);
-		kmem_free(regbuf, len);
-
-		/*
-		 * The network function of the RIO ASIC will always be
-		 * device 3 and function 1 ("network@3,1").
-		 */
-		if ((pci_device == 3) && (pci_function == 1))
-			return (1);
-	}
-	return (0);
-}
-
-typedef struct {
-	int		iosram_inst;
-	dev_info_t	*eri_dip;
-	int		bnum;
-} drmach_io_inst_t;
-
-int
-drmach_board_find_io_insts(dev_info_t *dip, void *args)
-{
-	drmach_io_inst_t	*ios = (drmach_io_inst_t *)args;
-
-	int	rv;
-	int	len;
-	int	portid;
-	char	name[OBP_MAXDRVNAME];
-
-	rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "portid", &len);
-
-	if ((rv != DDI_PROP_SUCCESS) || (len > sizeof (portid))) {
-		return (DDI_WALK_CONTINUE);
-	}
-
-	rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0,
-	    "portid", (caddr_t)&portid, &len);
-	if (rv != DDI_PROP_SUCCESS)
-		return (DDI_WALK_CONTINUE);
-
-	/* ignore devices that are not on this board */
-	if (drmach_portid2bnum(portid) != ios->bnum)
-		return (DDI_WALK_CONTINUE);
-
-	if ((ios->iosram_inst < 0) || (ios->eri_dip == NULL)) {
-		rv = ddi_getproplen(DDI_DEV_T_ANY, dip, 0, "name", &len);
-		if (rv == DDI_PROP_SUCCESS) {
-
-			rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
-			    0, "name",
-			    (caddr_t)name, &len);
-			if (rv != DDI_PROP_SUCCESS)
-				return (DDI_WALK_CONTINUE);
-
-			if (strncmp("iosram", name, 6) == 0) {
-				ios->iosram_inst = ddi_get_instance(dip);
-				if (ios->eri_dip == NULL)
-					return (DDI_WALK_CONTINUE);
-				else
-					return (DDI_WALK_TERMINATE);
-			} else {
-				if (drmach_dip_is_man_eri(dip)) {
-					ASSERT(ios->eri_dip == NULL);
-					ndi_hold_devi(dip);
-					ios->eri_dip = dip;
-					if (ios->iosram_inst < 0)
-						return (DDI_WALK_CONTINUE);
-					else
-						return (DDI_WALK_TERMINATE);
-				}
-			}
-		}
-	}
-	return (DDI_WALK_CONTINUE);
-}
-
-sbd_error_t *
-drmach_io_pre_release(drmachid_t id)
-{
-	drmach_io_inst_t	ios;
-	drmach_board_t		*bp;
-	int			rv = 0;
-	sbd_error_t		*err = NULL;
-	drmach_device_t		*dp;
-	dev_info_t		*rdip;
-	int			circ;
-
-	if (!DRMACH_IS_IO_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	dp = id;
-	bp = dp->bp;
-
-	rdip = dp->node->n_getdip(dp->node);
-
-	/* walk device tree to find iosram instance for the board */
-	ios.iosram_inst = -1;
-	ios.eri_dip = NULL;
-	ios.bnum = bp->bnum;
-
-	ndi_devi_enter(rdip, &circ);
-	ddi_walk_devs(ddi_get_child(rdip), drmach_board_find_io_insts,
-	    (void *)&ios);
-
-	DRMACH_PR("drmach_io_pre_release: bnum=%d iosram=%d eri=0x%p\n",
-	    ios.bnum, ios.iosram_inst, (void *)ios.eri_dip);
-	ndi_devi_exit(rdip, circ);
-
-	if (ios.eri_dip) {
-		/*
-		 * Release hold acquired in drmach_board_find_io_insts()
-		 */
-		ndi_rele_devi(ios.eri_dip);
-	}
-	if (ios.iosram_inst >= 0) {
-		/* call for tunnel switch */
-		do {
-			DRMACH_PR("calling iosram_switchfrom(%d)\n",
-			    ios.iosram_inst);
-			rv = iosram_switchfrom(ios.iosram_inst);
-			if (rv)
-				DRMACH_PR("iosram_switchfrom returned %d\n",
-				    rv);
-		} while (rv == EAGAIN);
-
-		if (rv)
-			err = drerr_new(0, ESTC_IOSWITCH, NULL);
-	}
-	return (err);
-}
-
-sbd_error_t *
-drmach_io_unrelease(drmachid_t id)
-{
-	dev_info_t	*dip;
-	sbd_error_t	*err = NULL;
-	drmach_device_t	*dp;
-
-	if (!DRMACH_IS_IO_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	dp = id;
-
-	dip = dp->node->n_getdip(dp->node);
-
-	if (dip == NULL)
-		err = DRMACH_INTERNAL_ERROR();
-	else {
-		int (*func)(dev_info_t *dip);
-
-		func = (int (*)(dev_info_t *))kobj_getsymvalue("man_dr_attach",
-		    0);
-
-		if (func) {
-			drmach_io_inst_t ios;
-			dev_info_t	*pdip;
-			int		circ;
-
-			/*
-			 * Walk device tree to find rio dip for the board
-			 * Since we are not interested in iosram instance here,
-			 * initialize it to 0, so that the walk terminates as
-			 * soon as eri dip is found.
-			 */
-			ios.iosram_inst = 0;
-			ios.eri_dip = NULL;
-			ios.bnum = dp->bp->bnum;
-
-			if (pdip = ddi_get_parent(dip)) {
-				ndi_hold_devi(pdip);
-				ndi_devi_enter(pdip, &circ);
-			}
-			/*
-			 * Root node doesn't have to be held in any way.
-			 */
-			ddi_walk_devs(dip, drmach_board_find_io_insts,
-			    (void *)&ios);
-
-			if (pdip) {
-				ndi_devi_exit(pdip, circ);
-				ndi_rele_devi(pdip);
-			}
-
-			DRMACH_PR("drmach_io_unrelease: bnum=%d eri=0x%p\n",
-			    ios.bnum, (void *)ios.eri_dip);
-
-			if (ios.eri_dip) {
-				DRMACH_PR("calling man_dr_attach\n");
-				if ((*func)(ios.eri_dip))
-					err = drerr_new(0, ESTC_NWSWITCH, NULL);
-				/*
-				 * Release hold acquired in
-				 * drmach_board_find_io_insts()
-				 */
-				ndi_rele_devi(ios.eri_dip);
-			}
-		} else
-			DRMACH_PR("man_dr_attach NOT present\n");
-	}
-	return (err);
-}
-
-static sbd_error_t *
-drmach_io_release(drmachid_t id)
-{
-	dev_info_t	*dip;
-	sbd_error_t	*err = NULL;
-	drmach_device_t	*dp;
-
-	if (!DRMACH_IS_IO_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	dp = id;
-
-	dip = dp->node->n_getdip(dp->node);
-
-	if (dip == NULL)
-		err = DRMACH_INTERNAL_ERROR();
-	else {
-		int (*func)(dev_info_t *dip);
-
-		func = (int (*)(dev_info_t *))kobj_getsymvalue("man_dr_detach",
-		    0);
-
-		if (func) {
-			drmach_io_inst_t ios;
-			dev_info_t	*pdip;
-			int		circ;
-
-			/*
-			 * Walk device tree to find rio dip for the board
-			 * Since we are not interested in iosram instance here,
-			 * initialize it to 0, so that the walk terminates as
-			 * soon as eri dip is found.
-			 */
-			ios.iosram_inst = 0;
-			ios.eri_dip = NULL;
-			ios.bnum = dp->bp->bnum;
-
-			if (pdip = ddi_get_parent(dip)) {
-				ndi_hold_devi(pdip);
-				ndi_devi_enter(pdip, &circ);
-			}
-			/*
-			 * Root node doesn't have to be held in any way.
-			 */
-			ddi_walk_devs(dip, drmach_board_find_io_insts,
-			    (void *)&ios);
-
-			if (pdip) {
-				ndi_devi_exit(pdip, circ);
-				ndi_rele_devi(pdip);
-			}
-
-			DRMACH_PR("drmach_io_release: bnum=%d eri=0x%p\n",
-			    ios.bnum, (void *)ios.eri_dip);
-
-			if (ios.eri_dip) {
-				DRMACH_PR("calling man_dr_detach\n");
-				if ((*func)(ios.eri_dip))
-					err = drerr_new(0, ESTC_NWSWITCH, NULL);
-				/*
-				 * Release hold acquired in
-				 * drmach_board_find_io_insts()
-				 */
-				ndi_rele_devi(ios.eri_dip);
-			}
-		} else
-			DRMACH_PR("man_dr_detach NOT present\n");
-	}
-	return (err);
-}
-
-sbd_error_t *
-drmach_io_post_release(drmachid_t id)
-{
-	char 		*path;
-	dev_info_t	*rdip;
-	drmach_device_t	*dp;
-
-	if (!DRMACH_IS_DEVICE_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	dp = id;
-
-	rdip = dp->node->n_getdip(dp->node);
-
-	/*
-	 * Always called after drmach_unconfigure() which on Starcat
-	 * unconfigures the branch but doesn't remove it so the
-	 * dip must always exist.
-	 */
-	ASSERT(rdip);
-
-	ASSERT(e_ddi_branch_held(rdip));
-#ifdef DEBUG
-	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-	(void) ddi_pathname(rdip, path);
-	DRMACH_PR("post_release dip path is: %s\n", path);
-	kmem_free(path, MAXPATHLEN);
-#endif
-
-	if (strcmp(dp->type, DRMACH_DEVTYPE_PCI) == 0) {
-		if (schpc_remove_pci(rdip)) {
-			DRMACH_PR("schpc_remove_pci failed\n");
-			return (drerr_new(0, ESBD_OFFLINE, NULL));
-		} else {
-			DRMACH_PR("schpc_remove_pci succeeded\n");
-		}
-	}
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_io_post_attach(drmachid_t id)
-{
-	int		circ;
-	dev_info_t	*dip;
-	dev_info_t	*pdip;
-	drmach_device_t	*dp;
-	drmach_io_inst_t ios;
-
-	if (!DRMACH_IS_DEVICE_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	dp = id;
-
-	dip = dp->node->n_getdip(dp->node);
-
-	/*
-	 * We held the branch rooted at dip earlier, so at a minimum the
-	 * root i.e. dip must be present in the device tree.
-	 */
-	ASSERT(dip);
-
-	if (strcmp(dp->type, DRMACH_DEVTYPE_PCI) == 0) {
-		if (schpc_add_pci(dip)) {
-			DRMACH_PR("schpc_add_pci failed\n");
-		} else {
-			DRMACH_PR("schpc_add_pci succeeded\n");
-		}
-	}
-
-	/*
-	 * Walk device tree to find rio dip for the board
-	 * Since we are not interested in iosram instance here,
-	 * initialize it to 0, so that the walk terminates as
-	 * soon as eri dip is found.
-	 */
-	ios.iosram_inst = 0;
-	ios.eri_dip = NULL;
-	ios.bnum = dp->bp->bnum;
-
-	if (pdip = ddi_get_parent(dip)) {
-		ndi_hold_devi(pdip);
-		ndi_devi_enter(pdip, &circ);
-	}
-	/*
-	 * Root node doesn't have to be held in any way.
-	 */
-	ddi_walk_devs(dip, drmach_board_find_io_insts, (void *)&ios);
-	if (pdip) {
-		ndi_devi_exit(pdip, circ);
-		ndi_rele_devi(pdip);
-	}
-
-	DRMACH_PR("drmach_io_post_attach: bnum=%d eri=0x%p\n",
-	    ios.bnum, (void *)ios.eri_dip);
-
-	if (ios.eri_dip) {
-		int (*func)(dev_info_t *dip);
-
-		func =
-		    (int (*)(dev_info_t *))kobj_getsymvalue("man_dr_attach", 0);
-
-		if (func) {
-			DRMACH_PR("calling man_dr_attach\n");
-			(void) (*func)(ios.eri_dip);
-		} else {
-			DRMACH_PR("man_dr_attach NOT present\n");
-		}
-
-		/*
-		 * Release hold acquired in drmach_board_find_io_insts()
-		 */
-		ndi_rele_devi(ios.eri_dip);
-
-	}
-
-	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);
-}
-
-sbd_error_t *
-drmach_mem_init_size(drmachid_t id)
-{
-	drmach_mem_t	*mp;
-	sbd_error_t	*err;
-	gdcd_t		*gdcd;
-	mem_chunk_t	*chunk;
-	uint64_t	 chunks, pa, mask, sz;
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	mp = id;
-
-	err = drmach_mem_get_base_physaddr(id, &pa);
-	if (err)
-		return (err);
-
-	mask = ~ (DRMACH_MEM_SLICE_SIZE - 1);
-	pa &= mask;
-
-	gdcd = drmach_gdcd_new();
-	if (gdcd == NULL)
-		return (DRMACH_INTERNAL_ERROR());
-
-	sz = 0;
-	chunk = gdcd->dcd_chunk_list.dcl_chunk;
-	chunks = gdcd->dcd_chunk_list.dcl_chunks;
-	while (chunks-- != 0) {
-		if ((chunk->mc_base_pa & mask) == pa) {
-			sz += chunk->mc_mbytes * 1048576;
-		}
-
-		++chunk;
-	}
-	mp->nbytes = sz;
-
-	drmach_gdcd_dispose(gdcd);
-	return (NULL);
-}
-
-/*
- * Hardware registers are organized into consecutively
- * addressed registers.  The reg property's hi and lo fields
- * together describe the base address of the register set for
- * this memory-controller.  Register descriptions and offsets
- * (from the base address) are as follows:
- *
- * Description				Offset	Size (bytes)
- * Memory Timing Control Register I	0x00	8
- * Memory Timing Control Register II	0x08	8
- * Memory Address Decoding Register I	0x10	8
- * Memory Address Decoding Register II	0x18	8
- * Memory Address Decoding Register III	0x20	8
- * Memory Address Decoding Register IV	0x28	8
- * Memory Address Control Register	0x30	8
- * Memory Timing Control Register III	0x38	8
- * Memory Timing Control Register IV	0x40	8
- * Memory Timing Control Register V  	0x48	8 (Jaguar, Panther only)
- * EMU Activity Status Register		0x50	8 (Panther only)
- *
- * Only the Memory Address Decoding Register and EMU Activity Status
- * Register addresses are needed for DRMACH.
- */
-static sbd_error_t *
-drmach_mem_new(drmach_device_t *proto, drmachid_t *idp)
-{
-	sbd_error_t	*err;
-	uint64_t	 madr_pa;
-	drmach_mem_t	*mp;
-	int		 bank, count;
-
-	err = drmach_read_reg_addr(proto, &madr_pa);
-	if (err)
-		return (err);
-
-	mp = kmem_zalloc(sizeof (drmach_mem_t), KM_SLEEP);
-	bcopy(proto, &mp->dev, sizeof (mp->dev));
-	mp->dev.node = drmach_node_dup(proto->node);
-	mp->dev.cm.isa = (void *)drmach_mem_new;
-	mp->dev.cm.dispose = drmach_mem_dispose;
-	mp->dev.cm.release = drmach_mem_release;
-	mp->dev.cm.status = drmach_mem_status;
-	mp->madr_pa = madr_pa;
-
-	(void) snprintf(mp->dev.cm.name,
-	    sizeof (mp->dev.cm.name), "%s", mp->dev.type);
-
-	for (count = bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
-		uint64_t madr;
-
-		drmach_mem_read_madr(mp, bank, &madr);
-		if (madr & DRMACH_MC_VALID_MASK) {
-			count += 1;
-			break;
-		}
-	}
-
-	/*
-	 * If none of the banks had their valid bit set, that means
-	 * post did not configure this MC to participate in the
-	 * domain.  So, pretend this node does not exist by returning
-	 * a drmachid of zero.
-	 */
-	if (count == 0) {
-		/* drmach_mem_dispose frees board mem list */
-		drmach_node_dispose(mp->dev.node);
-		kmem_free(mp, sizeof (*mp));
-		*idp = (drmachid_t)0;
-		return (NULL);
-	}
-
-	/*
-	 * Only one mem unit per board is exposed to the
-	 * PIM layer.  The first mem unit encountered during
-	 * tree walk is used to represent all mem units on
-	 * the same board.
-	 */
-	if (mp->dev.bp->mem == NULL) {
-		/* start list of mem units on this board */
-		mp->dev.bp->mem = mp;
-
-		/*
-		 * force unum to zero since this is the only mem unit
-		 * that will be visible to the PIM layer.
-		 */
-		mp->dev.unum = 0;
-
-		/*
-		 * board memory size kept in this mem unit only
-		 */
-		err = drmach_mem_init_size(mp);
-		if (err) {
-			mp->dev.bp->mem = NULL;
-			/* drmach_mem_dispose frees board mem list */
-			drmach_node_dispose(mp->dev.node);
-			kmem_free(mp, sizeof (*mp));
-			*idp = (drmachid_t)0;
-			return (NULL);
-		}
-
-		/*
-		 * allow this instance (the first encountered on this board)
-		 * to be visible to the PIM layer.
-		 */
-		*idp = (drmachid_t)mp;
-	} else {
-		drmach_mem_t *lp;
-
-		/* hide this mem instance behind the first. */
-		for (lp = mp->dev.bp->mem; lp->next; lp = lp->next)
-			;
-		lp->next = mp;
-
-		/*
-		 * hide this instance from the caller.
-		 * See drmach_board_find_devices_cb() for details.
-		 */
-		*idp = (drmachid_t)0;
-	}
-
-	return (NULL);
-}
-
-static void
-drmach_mem_dispose(drmachid_t id)
-{
-	drmach_mem_t *mp, *next;
-	drmach_board_t *bp;
-
-	ASSERT(DRMACH_IS_MEM_ID(id));
-
-	mutex_enter(&drmach_bus_sync_lock);
-
-	mp = id;
-	bp = mp->dev.bp;
-
-	do {
-		if (mp->dev.node)
-			drmach_node_dispose(mp->dev.node);
-
-		next = mp->next;
-		kmem_free(mp, sizeof (*mp));
-		mp = next;
-	} while (mp);
-
-	bp->mem = NULL;
-
-	drmach_bus_sync_list_update();
-	mutex_exit(&drmach_bus_sync_lock);
-}
-
-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);
-	int		rv;
-
-	ASSERT(size != 0);
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	rv = kcage_range_add(basepfn, npages, KCAGE_DOWN);
-	if (rv == ENOMEM) {
-		cmn_err(CE_WARN, "%lu megabytes not available"
-		    " to kernel cage", size >> 20);
-	} else if (rv != 0) {
-		/* catch this in debug kernels */
-		ASSERT(0);
-
-		cmn_err(CE_WARN, "unexpected kcage_range_add"
-		    " return value %d", rv);
-	}
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_del_span(drmachid_t id, uint64_t basepa, uint64_t size)
-{
-	pfn_t		 basepfn = (pfn_t)(basepa >> PAGESHIFT);
-	pgcnt_t		 npages = (pgcnt_t)(size >> PAGESHIFT);
-	int		 rv;
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	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());
-		}
-	}
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_disable(drmachid_t id)
-{
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	else
-		return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_enable(drmachid_t id)
-{
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	else
-		return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_get_alignment(drmachid_t id, uint64_t *mask)
-{
-#define	MB(mb) ((mb) * 1048576ull)
-
-	static struct {
-		uint_t		uk;
-		uint64_t	segsz;
-	}  uk2segsz[] = {
-		{ 0x003,	MB(256)	  },
-		{ 0x007,	MB(512)	  },
-		{ 0x00f,	MB(1024)  },
-		{ 0x01f,	MB(2048)  },
-		{ 0x03f,	MB(4096)  },
-		{ 0x07f,	MB(8192)  },
-		{ 0x0ff,	MB(16384) },
-		{ 0x1ff,	MB(32768) },
-		{ 0x3ff,	MB(65536) },
-		{ 0x7ff,	MB(131072) }
-	};
-	static int len = sizeof (uk2segsz) / sizeof (uk2segsz[0]);
-
-#undef MB
-
-	uint64_t	 largest_sz = 0;
-	drmach_mem_t	*mp;
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	/* prime the result with a default value */
-	*mask = (DRMACH_MEM_SLICE_SIZE - 1);
-
-	for (mp = id; mp; mp = mp->next) {
-		int bank;
-
-		for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
-			int		i;
-			uint_t		uk;
-			uint64_t	madr;
-
-			/* get register value, extract uk and normalize */
-			drmach_mem_read_madr(mp, bank, &madr);
-
-			if (!(madr & DRMACH_MC_VALID_MASK))
-				continue;
-
-			uk = DRMACH_MC_UK(madr);
-
-			/* match uk value */
-			for (i = 0; i < len; i++)
-				if (uk == uk2segsz[i].uk)
-					break;
-
-			if (i < len) {
-				uint64_t sz = uk2segsz[i].segsz;
-
-				/*
-				 * remember largest segment size,
-				 * update mask result
-				 */
-				if (sz > largest_sz) {
-					largest_sz = sz;
-					*mask = sz - 1;
-				}
-			} else {
-				/*
-				 * uk not in table, punt using
-				 * entire slice size. no longer any
-				 * reason to check other banks.
-				 */
-				*mask = (DRMACH_MEM_SLICE_SIZE - 1);
-				return (NULL);
-			}
-		}
-	}
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_get_base_physaddr(drmachid_t id, uint64_t *base_addr)
-{
-	drmach_mem_t *mp;
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	*base_addr = (uint64_t)-1;
-	for (mp = id; mp; mp = mp->next) {
-		int bank;
-
-		for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
-			uint64_t addr, madr;
-
-			drmach_mem_read_madr(mp, bank, &madr);
-			if (madr & DRMACH_MC_VALID_MASK) {
-				addr = DRMACH_MC_UM_TO_PA(madr) |
-				    DRMACH_MC_LM_TO_PA(madr);
-
-				if (addr < *base_addr)
-					*base_addr = addr;
-			}
-		}
-	}
-
-	/* should not happen, but ... */
-	if (*base_addr == (uint64_t)-1)
-		return (DRMACH_INTERNAL_ERROR());
-
-	return (NULL);
-}
-
-void
-drmach_bus_sync_list_update(void)
-{
-	int		rv, idx, cnt = 0;
-	drmachid_t	id;
-
-	ASSERT(MUTEX_HELD(&drmach_bus_sync_lock));
-
-	rv = drmach_array_first(drmach_boards, &idx, &id);
-	while (rv == 0) {
-		drmach_board_t		*bp = id;
-		drmach_mem_t		*mp = bp->mem;
-
-		while (mp) {
-			int bank;
-
-			for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
-				uint64_t madr;
-
-				drmach_mem_read_madr(mp, bank, &madr);
-				if (madr & DRMACH_MC_VALID_MASK) {
-					uint64_t pa;
-
-					pa  = DRMACH_MC_UM_TO_PA(madr);
-					pa |= DRMACH_MC_LM_TO_PA(madr);
-
-					/*
-					 * The list is zero terminated.
-					 * Offset the pa by a doubleword
-					 * to avoid confusing a pa value of
-					 * of zero with the terminator.
-					 */
-					pa += sizeof (uint64_t);
-
-					drmach_bus_sync_list[cnt++] = pa;
-				}
-			}
-
-			mp = mp->next;
-		}
-
-		rv = drmach_array_next(drmach_boards, &idx, &id);
-	}
-
-	drmach_bus_sync_list[cnt] = 0;
-}
-
-sbd_error_t *
-drmach_mem_get_memlist(drmachid_t id, struct memlist **ml)
-{
-	sbd_error_t	*err;
-	struct memlist	*mlist;
-	gdcd_t		*gdcd;
-	mem_chunk_t	*chunk;
-	uint64_t	 chunks, pa, mask;
-
-	err = drmach_mem_get_base_physaddr(id, &pa);
-	if (err)
-		return (err);
-
-	gdcd = drmach_gdcd_new();
-	if (gdcd == NULL)
-		return (DRMACH_INTERNAL_ERROR());
-
-	mask = ~ (DRMACH_MEM_SLICE_SIZE - 1);
-	pa &= mask;
-
-	mlist = NULL;
-	chunk = gdcd->dcd_chunk_list.dcl_chunk;
-	chunks = gdcd->dcd_chunk_list.dcl_chunks;
-	while (chunks-- != 0) {
-		if ((chunk->mc_base_pa & mask) == pa) {
-			mlist = memlist_add_span(mlist, chunk->mc_base_pa,
-			    chunk->mc_mbytes * 1048576);
-		}
-
-		++chunk;
-	}
-
-	drmach_gdcd_dispose(gdcd);
-
-#ifdef DEBUG
-	DRMACH_PR("GDCD derived memlist:");
-	memlist_dump(mlist);
-#endif
-
-	*ml = mlist;
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_get_size(drmachid_t id, uint64_t *bytes)
-{
-	drmach_mem_t	*mp;
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	mp = id;
-
-	ASSERT(mp->nbytes != 0);
-	*bytes = mp->nbytes;
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_mem_get_slice_size(drmachid_t id, uint64_t *bytes)
-{
-	sbd_error_t	*err;
-	drmach_device_t	*mp;
-
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	mp = id;
-
-	switch (DRMACH_BNUM2SLOT(mp->bp->bnum)) {
-		case 0:	*bytes = DRMACH_MEM_USABLE_SLICE_SIZE;
-			err = NULL;
-			break;
-
-		case 1: *bytes = 0;
-			err = NULL;
-			break;
-
-		default:
-			err = DRMACH_INTERNAL_ERROR();
-			break;
-	}
-
-	return (err);
-}
-
-processorid_t drmach_mem_cpu_affinity_nail;
-
-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)) {
-				drmach_cpu_t	*cp = d_id;
-
-				mutex_enter(&cpu_lock);
-				cpuid = cp->cpuid;
-				if (cpu[cpuid] && CPU_ACTIVE(cpu[cpuid])) {
-					mutex_exit(&cpu_lock);
-					return (cpuid);
-				} else {
-					mutex_exit(&cpu_lock);
-				}
-			}
-
-			rv = drmach_array_next(bp->devices, &d_idx, &d_id);
-		}
-	}
-
-	/* otherwise, this proc, wherever it is */
-	return (CPU_CURRENT);
-}
-
-static sbd_error_t *
-drmach_mem_release(drmachid_t id)
-{
-	if (!DRMACH_IS_MEM_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	return (NULL);
-}
-
-static sbd_error_t *
-drmach_mem_status(drmachid_t id, drmach_status_t *stat)
-{
-	drmach_mem_t	*mp;
-	sbd_error_t	*err;
-	uint64_t	 pa, slice_size;
-	struct memlist	*ml;
-
-	ASSERT(DRMACH_IS_MEM_ID(id));
-	mp = 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 = DRMACH_MEM_SLICE_SIZE;
-	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 = mp->dev.bp->assigned;
-	stat->powered = mp->dev.bp->powered;
-	stat->configured = (ml != NULL);
-	stat->busy = mp->dev.busy;
-	(void) strncpy(stat->type, mp->dev.type, sizeof (stat->type));
-	stat->info[0] = '\0';
-
-	return (NULL);
-}
-
-sbd_error_t *
-drmach_board_deprobe(drmachid_t id)
-{
-	drmach_board_t	*bp;
-	sbd_error_t	*err = NULL;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	bp = id;
-
-	if (bp->tree) {
-		drmach_node_dispose(bp->tree);
-		bp->tree = NULL;
-	}
-	if (bp->devices) {
-		drmach_array_dispose(bp->devices, drmach_device_dispose);
-		bp->devices = NULL;
-		bp->mem = NULL;  /* TODO: still needed? */
-	}
-	return (err);
-}
-
-/*ARGSUSED1*/
-static sbd_error_t *
-drmach_pt_showlpa(drmachid_t id, drmach_opts_t *opts)
-{
-	drmach_device_t	*dp;
-	uint64_t	val;
-	int		err = 1;
-
-	if (DRMACH_IS_CPU_ID(id)) {
-		drmach_cpu_t *cp = id;
-		if (drmach_cpu_read_scr(cp, &val))
-			err = 0;
-	} else if (DRMACH_IS_IO_ID(id) && ((drmach_io_t *)id)->scsr_pa != 0) {
-		drmach_io_t *io = id;
-		val = lddphysio(io->scsr_pa);
-		err = 0;
-	}
-	if (err)
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	dp = id;
-	uprintf("showlpa %s::%s portid %d, base pa %lx, bound pa %lx\n",
-	    dp->bp->cm.name,
-	    dp->cm.name,
-	    dp->portid,
-	    (long)(DRMACH_LPA_BASE_TO_PA(val)),
-	    (long)(DRMACH_LPA_BND_TO_PA(val)));
-
-	return (NULL);
-}
-
-/*ARGSUSED*/
-static sbd_error_t *
-drmach_pt_ikprobe(drmachid_t id, drmach_opts_t *opts)
-{
-	drmach_board_t		*bp = (drmach_board_t *)id;
-	sbd_error_t		*err;
-	sc_gptwocfg_cookie_t	scc;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-
-	/* do saf configurator stuff */
-	DRMACH_PR("calling sc_probe_board for bnum=%d\n", bp->bnum);
-	scc = sc_probe_board(bp->bnum);
-	if (scc == NULL) {
-		err = drerr_new(0, ESTC_PROBE, bp->cm.name);
-		return (err);
-	}
-
-	return (err);
-}
-
-/*ARGSUSED*/
-static sbd_error_t *
-drmach_pt_ikdeprobe(drmachid_t id, drmach_opts_t *opts)
-{
-	drmach_board_t	*bp;
-	sbd_error_t	*err = NULL;
-	sc_gptwocfg_cookie_t	scc;
-
-	if (!DRMACH_IS_BOARD_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	bp = id;
-
-	cmn_err(CE_CONT, "DR: in-kernel unprobe board %d\n", bp->bnum);
-	scc = sc_unprobe_board(bp->bnum);
-	if (scc != NULL) {
-		err = drerr_new(0, ESTC_DEPROBE, bp->cm.name);
-	}
-
-	if (err == NULL)
-		err = drmach_board_deprobe(id);
-
-	return (err);
-}
-
-static sbd_error_t *
-drmach_pt_readmem(drmachid_t id, drmach_opts_t *opts)
-{
-	_NOTE(ARGUNUSED(id))
-	_NOTE(ARGUNUSED(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 src_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 sbd_error_t *
-drmach_pt_recovercpu(drmachid_t id, drmach_opts_t *opts)
-{
-	_NOTE(ARGUNUSED(opts))
-
-	drmach_cpu_t	*cp;
-
-	if (!DRMACH_IS_CPU_ID(id))
-		return (drerr_new(0, ESTC_INAPPROP, NULL));
-	cp = id;
-
-	mutex_enter(&cpu_lock);
-	(void) drmach_iocage_cpu_return(&(cp->dev),
-	    CPU_ENABLE | CPU_EXISTS | CPU_READY | CPU_RUNNING);
-	mutex_exit(&cpu_lock);
-
-	return (NULL);
-}
-
-/*
- * Starcat DR passthrus are for debugging purposes only.
- */
-static struct {
-	const char	*name;
-	sbd_error_t	*(*handler)(drmachid_t id, drmach_opts_t *opts);
-} drmach_pt_arr[] = {
-	{ "showlpa",		drmach_pt_showlpa		},
-	{ "ikprobe",		drmach_pt_ikprobe		},
-	{ "ikdeprobe",		drmach_pt_ikdeprobe		},
-	{ "readmem",		drmach_pt_readmem		},
-	{ "recovercpu",		drmach_pt_recovercpu		},
-
-	/* 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, ESTC_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, ESTC_INAPPROP, NULL));
-	cp = id;
-
-	return (cp->release(id));
-}
-
-sbd_error_t *
-drmach_status(drmachid_t id, drmach_status_t *stat)
-{
-	drmach_common_t *cp;
-	sbd_error_t	*err;
-
-	rw_enter(&drmach_boards_rwlock, RW_READER);
-
-	if (!DRMACH_IS_ID(id)) {
-		rw_exit(&drmach_boards_rwlock);
-		return (drerr_new(0, ESTC_NOTID, NULL));
-	}
-
-	cp = id;
-
-	err = cp->status(id, stat);
-	rw_exit(&drmach_boards_rwlock);
-	return (err);
-}
-
-static sbd_error_t *
-drmach_i_status(drmachid_t id, drmach_status_t *stat)
-{
-	drmach_common_t *cp;
-
-	if (!DRMACH_IS_ID(id))
-		return (drerr_new(0, ESTC_NOTID, NULL));
-	cp = id;
-
-	return (cp->status(id, stat));
-}
-
-/*ARGSUSED*/
-sbd_error_t *
-drmach_unconfigure(drmachid_t id, int flags)
-{
-	drmach_device_t	*dp;
-	dev_info_t 	*rdip;
-
-	char	name[OBP_MAXDRVNAME];
-	int rv;
-
-	/*
-	 * Since CPU nodes are not configured, it is
-	 * necessary to skip the unconfigure step as
-	 * well.
-	 */
-	if (DRMACH_IS_CPU_ID(id)) {
-		return (NULL);
-	}
-
-	for (; id; ) {
-		dev_info_t	*fdip = NULL;
-
-		if (!DRMACH_IS_DEVICE_ID(id))
-			return (drerr_new(0, ESTC_INAPPROP, NULL));
-		dp = id;
-
-		rdip = dp->node->n_getdip(dp->node);
-
-		/*
-		 * drmach_unconfigure() is always called on a configured branch.
-		 * So the root of the branch was held earlier and must exist.
-		 */
-		ASSERT(rdip);
-
-		DRMACH_PR("drmach_unconfigure: unconfiguring DDI branch");
-
-		rv = dp->node->n_getprop(dp->node,
-		    "name", name, OBP_MAXDRVNAME);
-
-		/* The node must have a name */
-		if (rv)
-			return (0);
-
-		if (drmach_name2type_idx(name) < 0) {
-			if (DRMACH_IS_MEM_ID(id)) {
-				drmach_mem_t	*mp = id;
-				id = mp->next;
-			} else {
-				id = NULL;
-			}
-			continue;
-		}
-
-		/*
-		 * NOTE: FORCE flag is no longer needed under devfs
-		 */
-		ASSERT(e_ddi_branch_held(rdip));
-		if (e_ddi_branch_unconfigure(rdip, &fdip, 0) != 0) {
-			sbd_error_t *err = NULL;
-			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 {
-				(void) ddi_pathname(rdip, path);
-			}
-
-			err = drerr_new(1, ESTC_DRVFAIL, path);
-
-			kmem_free(path, MAXPATHLEN);
-
-			/*
-			 * If we were unconfiguring an IO board, a call was
-			 * made to man_dr_detach.  We now need to call
-			 * man_dr_attach to regain man use of the eri.
-			 */
-			if (DRMACH_IS_IO_ID(id)) {
-				int (*func)(dev_info_t *dip);
-
-				func = (int (*)(dev_info_t *))kobj_getsymvalue\
-				    ("man_dr_attach", 0);
-
-				if (func) {
-					drmach_io_inst_t ios;
-					dev_info_t 	*pdip;
-					int		circ;
-
-					/*
-					 * Walk device tree to find rio dip for
-					 * the board
-					 * Since we are not interested in iosram
-					 * instance here, initialize it to 0, so
-					 * that the walk terminates as soon as
-					 * eri dip is found.
-					 */
-					ios.iosram_inst = 0;
-					ios.eri_dip = NULL;
-					ios.bnum = dp->bp->bnum;
-
-					if (pdip = ddi_get_parent(rdip)) {
-						ndi_hold_devi(pdip);
-						ndi_devi_enter(pdip, &circ);
-					}
-					/*
-					 * Root node doesn't have to be held in
-					 * any way.
-					 */
-					ASSERT(e_ddi_branch_held(rdip));
-					ddi_walk_devs(rdip,
-					    drmach_board_find_io_insts,
-					    (void *)&ios);
-
-					DRMACH_PR("drmach_unconfigure: bnum=%d"
-					    " eri=0x%p\n",
-					    ios.bnum, (void *)ios.eri_dip);
-
-					if (pdip) {
-						ndi_devi_exit(pdip, circ);
-						ndi_rele_devi(pdip);
-					}
-
-					if (ios.eri_dip) {
-						DRMACH_PR("calling"
-						    " man_dr_attach\n");
-						(void) (*func)(ios.eri_dip);
-						/*
-						 * Release hold acquired in
-						 * drmach_board_find_io_insts()
-						 */
-						ndi_rele_devi(ios.eri_dip);
-					}
-				}
-			}
-			return (err);
-		}
-
-		if (DRMACH_IS_MEM_ID(id)) {
-			drmach_mem_t	*mp = id;
-			id = mp->next;
-		} else {
-			id = NULL;
-		}
-	}
-
-	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;
-	processorid_t	cpuid;
-	void		drmach_cpu_shutdown_self(void);
-
-	DRMACH_PR("drmach_cpu_poweroff: stopping cpuid %d\n", cp->cpu_id);
-
-	ASSERT(MUTEX_HELD(&cpu_lock));
-
-	/*
-	 * XXX CHEETAH SUPPORT
-	 * for cheetah, we need to grab the iocage lock since iocage
-	 * memory is used for e$ flush.
-	 */
-	if (drmach_is_cheetah) {
-		mutex_enter(&drmach_iocage_lock);
-		while (drmach_iocage_is_busy)
-			cv_wait(&drmach_iocage_cv, &drmach_iocage_lock);
-		drmach_iocage_is_busy = 1;
-		drmach_iocage_mem_scrub(ecache_size * 2);
-		mutex_exit(&drmach_iocage_lock);
-	}
-
-	cpuid = cp->cpu_id;
-
-	/*
-	 * Set affinity to ensure consistent reading and writing of
-	 * drmach_xt_mb[cpuid] by one "master" CPU directing
-	 * the shutdown of the target CPU.
-	 */
-	affinity_set(CPU->cpu_id);
-
-	/*
-	 * 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 CPUs remain paused and the prom_mutex is known to be free.
-	 * This prevents 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);
-
-	(void) prom_hotremovecpu(cpuid);
-
-	start_cpus();
-
-	/* setup xt_mb, will be cleared by drmach_shutdown_asm when ready */
-	drmach_xt_mb[cpuid] = 0x80;
-
-	xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall,
-	    (uint64_t)drmach_cpu_shutdown_self, NULL);
-
-	ntries = drmach_cpu_ntries;
-	while (drmach_xt_mb[cpuid] && ntries) {
-		DELAY(drmach_cpu_delay);
-		ntries--;
-	}
-
-	drmach_xt_mb[cpuid] = 0;	/* steal the cache line back */
-
-	membar_sync();			/* make sure copy-back retires */
-
-	affinity_clear();
-
-	/*
-	 * XXX CHEETAH SUPPORT
-	 */
-	if (drmach_is_cheetah) {
-		mutex_enter(&drmach_iocage_lock);
-		drmach_iocage_mem_scrub(ecache_size * 2);
-		drmach_iocage_is_busy = 0;
-		cv_signal(&drmach_iocage_cv);
-		mutex_exit(&drmach_iocage_lock);
-	}
-
-	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);
-
-	/*
-	 * Do this here instead of drmach_cpu_shutdown_self() to
-	 * avoid an assertion failure panic in turnstile.c.
-	 */
-	CPU_SIGNATURE(OS_SIG, SIGST_DETACHED, SIGSUBST_NULL, cpuid);
-
-	return (0);
-}
-
-void
-drmach_iocage_mem_scrub(uint64_t nbytes)
-{
-	extern uint32_t drmach_bc_bzero(void*, size_t);
-	uint32_t	rv;
-
-	ASSERT(MUTEX_HELD(&cpu_lock));
-
-	affinity_set(CPU->cpu_id);
-
-	rv = drmach_bc_bzero(drmach_iocage_vaddr, nbytes);
-	if (rv != 0) {
-		DRMACH_PR(
-		"iocage scrub failed, drmach_bc_bzero returned %d\n", rv);
-		rv = drmach_bc_bzero(drmach_iocage_vaddr, drmach_iocage_size);
-		if (rv != 0)
-			cmn_err(CE_PANIC,
-			    "iocage scrub failed, drmach_bc_bzero rv=%d\n",
-			    rv);
-	}
-
-	cpu_flush_ecache();
-
-	affinity_clear();
-}
-
-#define	ALIGN(x, a)	((a) == 0 ? (uintptr_t)(x) : \
-	(((uintptr_t)(x) + (uintptr_t)(a) - 1l) & ~((uintptr_t)(a) - 1l)))
-
-static sbd_error_t *
-drmach_iocage_mem_get(dr_testboard_req_t *tbrq)
-{
-	pfn_t		basepfn;
-	pgcnt_t		npages;
-	extern int	memscrub_delete_span(pfn_t, pgcnt_t);
-	uint64_t	drmach_iocage_paddr_mbytes;
-
-	ASSERT(drmach_iocage_paddr != -1);
-
-	basepfn = (pfn_t)(drmach_iocage_paddr >> PAGESHIFT);
-	npages = (pgcnt_t)(drmach_iocage_size >> PAGESHIFT);
-
-	(void) memscrub_delete_span(basepfn, npages);
-
-	mutex_enter(&cpu_lock);
-	drmach_iocage_mem_scrub(drmach_iocage_size);
-	mutex_exit(&cpu_lock);
-
-	/*
-	 * HPOST wants the address of the cage to be 64 megabyte-aligned
-	 * and in megabyte units.
-	 * The size of the cage is also in megabyte units.
-	 */
-	ASSERT(drmach_iocage_paddr == ALIGN(drmach_iocage_paddr, 0x4000000));
-
-	drmach_iocage_paddr_mbytes = drmach_iocage_paddr / 0x100000;
-
-	tbrq->memaddrhi = (uint32_t)(drmach_iocage_paddr_mbytes >> 32);
-	tbrq->memaddrlo = (uint32_t)drmach_iocage_paddr_mbytes;
-	tbrq->memlen = drmach_iocage_size / 0x100000;
-
-	DRMACH_PR("drmach_iocage_mem_get: hi: 0x%x", tbrq->memaddrhi);
-	DRMACH_PR("drmach_iocage_mem_get: lo: 0x%x", tbrq->memaddrlo);
-	DRMACH_PR("drmach_iocage_mem_get: size: 0x%x", tbrq->memlen);
-
-	return (NULL);
-}
-
-static sbd_error_t *
-drmach_iocage_mem_return(dr_testboard_reply_t *tbr)
-{
-	_NOTE(ARGUNUSED(tbr))
-
-	pfn_t		basepfn;
-	pgcnt_t		npages;
-	extern int	memscrub_add_span(pfn_t, pgcnt_t);
-
-	ASSERT(drmach_iocage_paddr != -1);
-
-	basepfn = (pfn_t)(drmach_iocage_paddr >> PAGESHIFT);
-	npages = (pgcnt_t)(drmach_iocage_size >> PAGESHIFT);
-
-	(void) memscrub_add_span(basepfn, npages);
-
-	mutex_enter(&cpu_lock);
-	mutex_enter(&drmach_iocage_lock);
-	drmach_iocage_mem_scrub(drmach_iocage_size);
-	drmach_iocage_is_busy = 0;
-	cv_signal(&drmach_iocage_cv);
-	mutex_exit(&drmach_iocage_lock);
-	mutex_exit(&cpu_lock);
-
-	return (NULL);
-}
-
-static int
-drmach_cpu_intr_disable(cpu_t *cp)
-{
-	if (cpu_intr_disable(cp) != 0)
-		return (-1);
-	return (0);
-}
-
-static int
-drmach_iocage_cpu_acquire(drmach_device_t *dp, cpu_flag_t *oflags)
-{
-	struct cpu	*cp;
-	processorid_t	cpuid;
-	static char	*fn = "drmach_iocage_cpu_acquire";
-	sbd_error_t 	*err;
-	int 		impl;
-
-	ASSERT(DRMACH_IS_CPU_ID(dp));
-	ASSERT(MUTEX_HELD(&cpu_lock));
-
-	cpuid = ((drmach_cpu_t *)dp)->cpuid;
-
-	DRMACH_PR("%s: attempting to acquire CPU id %d", fn, cpuid);
-
-	if (dp->busy)
-		return (-1);
-
-	if ((cp = cpu_get(cpuid)) == NULL) {
-		DRMACH_PR("%s: cpu_get(%d) returned NULL", fn, cpuid);
-		return (-1);
-	}
-
-	if (!CPU_ACTIVE(cp)) {
-		DRMACH_PR("%s: skipping offlined CPU id %d", fn, cpuid);
-		return (-1);
-	}
-
-	/*
-	 * There is a known HW bug where a Jaguar CPU in Safari port 0 (SBX/P0)
-	 * can fail to receive an XIR. To workaround this issue until a hardware
-	 * fix is implemented, we will exclude the selection of these CPUs.
-	 *
-	 * Once a fix is implemented in hardware, this code should be updated
-	 * to allow Jaguar CPUs that have the fix to be used. However, support
-	 * must be retained to skip revisions that do not have this fix.
-	 */
-
-	err = drmach_cpu_get_impl(dp, &impl);
-	if (err) {
-		DRMACH_PR("%s: error getting impl. of CPU id %d", fn, cpuid);
-		sbd_err_clear(&err);
-		return (-1);
-	}
-
-	if (IS_JAGUAR(impl) && (STARCAT_CPUID_TO_LPORT(cpuid) == 0) &&
-	    drmach_iocage_exclude_jaguar_port_zero) {
-		DRMACH_PR("%s: excluding CPU id %d: port 0 on jaguar",
-		    fn, cpuid);
-		return (-1);
-	}
-
-	ASSERT(oflags);
-	*oflags = cp->cpu_flags;
-
-	if (cpu_offline(cp, 0)) {
-		DRMACH_PR("%s: cpu_offline failed for CPU id %d", fn, cpuid);
-		return (-1);
-	}
-
-	if (cpu_poweroff(cp)) {
-		DRMACH_PR("%s: cpu_poweroff failed for CPU id %d", fn, cpuid);
-		if (cpu_online(cp, 0)) {
-			cmn_err(CE_WARN, "failed to online CPU id %d "
-			    "during I/O cage test selection", cpuid);
-		}
-		if (CPU_ACTIVE(cp) && cpu_flagged_nointr(*oflags) &&
-		    drmach_cpu_intr_disable(cp) != 0) {
-			cmn_err(CE_WARN, "failed to restore CPU id %d "
-			    "no-intr during I/O cage test selection", cpuid);
-		}
-		return (-1);
-	}
-
-	if (cpu_unconfigure(cpuid)) {
-		DRMACH_PR("%s: cpu_unconfigure failed for CPU id %d", fn,
-		    cpuid);
-		(void) cpu_configure(cpuid);
-		if ((cp = cpu_get(cpuid)) == NULL) {
-			cmn_err(CE_WARN, "failed to reconfigure CPU id %d "
-			    "during I/O cage test selection", cpuid);
-			dp->busy = 1;
-			return (-1);
-		}
-		if (cpu_poweron(cp) || cpu_online(cp, 0)) {
-			cmn_err(CE_WARN, "failed to %s CPU id %d "
-			    "during I/O cage test selection",
-			    cpu_is_poweredoff(cp) ?
-			    "poweron" : "online", cpuid);
-		}
-		if (CPU_ACTIVE(cp) && cpu_flagged_nointr(*oflags) &&
-		    drmach_cpu_intr_disable(cp) != 0) {
-			cmn_err(CE_WARN, "failed to restore CPU id %d "
-			    "no-intr during I/O cage test selection", cpuid);
-		}
-		return (-1);
-	}
-
-	dp->busy = 1;
-
-	DRMACH_PR("%s: acquired CPU id %d", fn, cpuid);
-
-	return (0);
-}
-
-/*
- * Attempt to acquire all the CPU devices passed in. It is
- * assumed that all the devices in the list are the cores of
- * a single CMP device. Non CMP devices can be handled as a
- * single core CMP by passing in a one element list.
- *
- * Success is only returned if *all* the devices in the list
- * can be acquired. In the failure case, none of the devices
- * in the list will be held as acquired.
- */
-static int
-drmach_iocage_cmp_acquire(drmach_device_t **dpp, cpu_flag_t *oflags)
-{
-	int	curr;
-	int	i;
-	int	rv = 0;
-
-	ASSERT((dpp != NULL) && (*dpp != NULL));
-
-	/*
-	 * Walk the list of CPU devices (cores of a CMP)
-	 * and attempt to acquire them. Bail out if an
-	 * error is encountered.
-	 */
-	for (curr = 0; curr < MAX_CORES_PER_CMP; curr++) {
-
-		/* check for the end of the list */
-		if (dpp[curr] == NULL) {
-			break;
-		}
-
-		ASSERT(DRMACH_IS_CPU_ID(dpp[curr]));
-		ASSERT(dpp[curr]->portid == (*dpp)->portid);
-
-		rv = drmach_iocage_cpu_acquire(dpp[curr], &oflags[curr]);
-		if (rv != 0) {
-			break;
-		}
-	}
-
-	/*
-	 * Check for an error.
-	 */
-	if (rv != 0) {
-		/*
-		 * Make a best effort attempt to return any cores
-		 * that were already acquired before the error was
-		 * encountered.
-		 */
-		for (i = 0; i < curr; i++) {
-			(void) drmach_iocage_cpu_return(dpp[i], oflags[i]);
-		}
-	}
-
-	return (rv);
-}
-
-static int
-drmach_iocage_cpu_return(drmach_device_t *dp, cpu_flag_t oflags)
-{
-	processorid_t	cpuid;
-	struct cpu	*cp;
-	int		rv = 0;
-	static char	*fn = "drmach_iocage_cpu_return";
-
-	ASSERT(DRMACH_IS_CPU_ID(dp));
-	ASSERT(MUTEX_HELD(&cpu_lock));
-
-	cpuid = ((drmach_cpu_t *)dp)->cpuid;
-
-	DRMACH_PR("%s: attempting to return CPU id: %d", fn, cpuid);
-
-	if (cpu_configure(cpuid)) {
-		cmn_err(CE_WARN, "failed to reconfigure CPU id %d "
-		    "after I/O cage test", cpuid);
-		/*
-		 * The component was never set to unconfigured during the IO
-		 * cage test, so we need to leave marked as busy to prevent
-		 * further DR operations involving this component.
-		 */
-		return (-1);
-	}
-
-	if ((cp = cpu_get(cpuid)) == NULL) {
-		cmn_err(CE_WARN, "cpu_get failed on CPU id %d after "
-		    "I/O cage test", cpuid);
-		dp->busy = 0;
-		return (-1);
-	}
-
-	if (cpu_poweron(cp) || cpu_online(cp, 0)) {
-		cmn_err(CE_WARN, "failed to %s CPU id %d after I/O "
-		    "cage test", cpu_is_poweredoff(cp) ?
-		    "poweron" : "online", cpuid);
-		rv = -1;
-	}
-
-	/*
-	 * drmach_iocage_cpu_acquire will accept cpus in state P_ONLINE or
-	 * P_NOINTR. Need to return to previous user-visible state.
-	 */
-	if (CPU_ACTIVE(cp) && cpu_flagged_nointr(oflags) &&
-	    drmach_cpu_intr_disable(cp) != 0) {
-		cmn_err(CE_WARN, "failed to restore CPU id %d "
-		    "no-intr after I/O cage test", cpuid);
-		rv = -1;
-	}
-
-	dp->busy = 0;
-
-	DRMACH_PR("%s: returned CPU id: %d", fn, cpuid);
-
-	return (rv);
-}
-
-static sbd_error_t *
-drmach_iocage_cpu_get(dr_testboard_req_t *tbrq, drmach_device_t **dpp,
-    cpu_flag_t *oflags)
-{
-	drmach_board_t	*bp;
-	int		b_rv;
-	int		b_idx;
-	drmachid_t	b_id;
-	int		found;
-
-	mutex_enter(&cpu_lock);
-
-	ASSERT(drmach_boards != NULL);
-
-	found = 0;
-
-	/*
-	 * Walk the board list.
-	 */
-	b_rv = drmach_array_first(drmach_boards, &b_idx, &b_id);
-
-	while (b_rv == 0) {
-
-		int		d_rv;
-		int		d_idx;
-		drmachid_t	d_id;
-
-		bp = b_id;
-
-		if (bp->connected == 0 || bp->devices == NULL) {
-			b_rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
-			continue;
-		}
-
-		/* An AXQ restriction disqualifies MCPU's as candidates. */
-		if (DRMACH_BNUM2SLOT(bp->bnum) == 1) {
-			b_rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
-			continue;
-		}
-
-		/*
-		 * Walk the device list of this board.
-		 */
-		d_rv = drmach_array_first(bp->devices, &d_idx, &d_id);
-
-		while (d_rv == 0) {
-
-			drmach_device_t	*ndp;
-
-			/* only interested in CPU devices */
-			if (!DRMACH_IS_CPU_ID(d_id)) {
-				d_rv = drmach_array_next(bp->devices, &d_idx,
-				    &d_id);
-				continue;
-			}
-
-			/*
-			 * The following code assumes two properties
-			 * of a CMP device:
-			 *
-			 *   1. All cores of a CMP are grouped together
-			 *	in the device list.
-			 *
-			 *   2. There will only be a maximum of two cores
-			 *	present in the CMP.
-			 *
-			 * If either of these two properties change,
-			 * this code will have to be revisited.
-			 */
-
-			dpp[0] = d_id;
-			dpp[1] = NULL;
-
-			/*
-			 * Get the next device. It may or may not be used.
-			 */
-			d_rv = drmach_array_next(bp->devices, &d_idx, &d_id);
-			ndp = d_id;
-
-			if ((d_rv == 0) && DRMACH_IS_CPU_ID(d_id)) {
-				/*
-				 * The second device is only interesting for
-				 * this pass if it has the same portid as the
-				 * first device. This implies that both are
-				 * cores of the same CMP.
-				 */
-				if (dpp[0]->portid == ndp->portid) {
-					dpp[1] = d_id;
-				}
-			}
-
-			/*
-			 * Attempt to acquire all cores of the CMP.
-			 */
-			if (drmach_iocage_cmp_acquire(dpp, oflags) == 0) {
-				found = 1;
-				break;
-			}
-
-			/*
-			 * Check if the search for the second core was
-			 * successful. If not, the next iteration should
-			 * use that device.
-			 */
-			if (dpp[1] == NULL) {
-				continue;
-			}
-
-			d_rv = drmach_array_next(bp->devices, &d_idx, &d_id);
-		}
-
-		if (found)
-			break;
-
-		b_rv = drmach_array_next(drmach_boards, &b_idx, &b_id);
-	}
-
-	mutex_exit(&cpu_lock);
-
-	if (!found) {
-		return (drerr_new(1, ESTC_IOCAGE_NO_CPU_AVAIL, NULL));
-	}
-
-	tbrq->cpu_portid = (*dpp)->portid;
-
-	return (NULL);
-}
-
-/*
- * Setup an iocage by acquiring a cpu and memory.
- */
-static sbd_error_t *
-drmach_iocage_setup(dr_testboard_req_t *tbrq, drmach_device_t **dpp,
-    cpu_flag_t *oflags)
-{
-	sbd_error_t *err;
-
-	err = drmach_iocage_cpu_get(tbrq, dpp, oflags);
-	if (!err) {
-		mutex_enter(&drmach_iocage_lock);
-		while (drmach_iocage_is_busy)
-			cv_wait(&drmach_iocage_cv, &drmach_iocage_lock);
-		drmach_iocage_is_busy = 1;
-		mutex_exit(&drmach_iocage_lock);
-		err = drmach_iocage_mem_get(tbrq);
-		if (err) {
-			mutex_enter(&drmach_iocage_lock);
-			drmach_iocage_is_busy = 0;
-			cv_signal(&drmach_iocage_cv);
-			mutex_exit(&drmach_iocage_lock);
-		}
-	}
-	return (err);
-}
-
-#define	DRMACH_SCHIZO_PCI_LEAF_MAX	2
-#define	DRMACH_SCHIZO_PCI_SLOT_MAX	8
-#define	DRMACH_S1P_SAMPLE_MAX		2
-
-typedef enum {
-	DRMACH_POST_SUSPEND = 0,
-	DRMACH_PRE_RESUME
-} drmach_sr_iter_t;
-
-typedef struct {
-	dev_info_t	*dip;
-	uint32_t	portid;
-	uint32_t	pcr_sel_save;
-	uint32_t	pic_l2_io_q[DRMACH_S1P_SAMPLE_MAX];
-	uint64_t	reg_basepa;
-} drmach_s1p_axq_t;
-
-typedef struct {
-	dev_info_t		*dip;
-	uint32_t		portid;
-	uint64_t		csr_basepa;
-	struct {
-		uint64_t 	slot_intr_state_diag;
-		uint64_t 	obio_intr_state_diag;
-		uint_t		nmap_regs;
-		uint64_t	*intr_map_regs;
-	} regs[DRMACH_S1P_SAMPLE_MAX];
-} drmach_s1p_pci_t;
-
-typedef struct {
-	uint64_t		csr_basepa;
-	struct {
-		uint64_t	csr;
-		uint64_t	errctrl;
-		uint64_t	errlog;
-	} regs[DRMACH_S1P_SAMPLE_MAX];
-	drmach_s1p_pci_t	pci[DRMACH_SCHIZO_PCI_LEAF_MAX];
-} drmach_s1p_schizo_t;
-
-typedef struct {
-	drmach_s1p_axq_t	axq;
-	drmach_s1p_schizo_t	schizo[STARCAT_SLOT1_IO_MAX];
-} drmach_slot1_pause_t;
-
-/*
- * Table of saved state for paused slot1 devices.
- */
-static drmach_slot1_pause_t *drmach_slot1_paused[STARCAT_BDSET_MAX];
-static int drmach_slot1_pause_init = 1;
-
-#ifdef DEBUG
-int drmach_slot1_pause_debug = 1;
-#else
-int drmach_slot1_pause_debug = 0;
-#endif /* DEBUG */
-
-static int
-drmach_is_slot1_pause_axq(dev_info_t *dip, char *name, int *id, uint64_t *reg)
-{
-	int		portid, exp, slot, i;
-	drmach_reg_t	regs[2];
-	int		reglen = sizeof (regs);
-
-	if ((portid = ddi_getprop(DDI_DEV_T_ANY, dip,
-	    DDI_PROP_DONTPASS, "portid", -1)) == -1) {
-		return (0);
-	}
-
-	exp = (portid >> 5) & 0x1f;
-	slot = portid & 0x1;
-
-	if (slot == 0 || strncmp(name, DRMACH_AXQ_NAMEPROP,
-	    strlen(DRMACH_AXQ_NAMEPROP))) {
-		return (0);
-	}
-
-	mutex_enter(&cpu_lock);
-	for (i = 0; i < STARCAT_SLOT1_CPU_MAX; i++) {
-		if (cpu[MAKE_CPUID(exp, slot, i)]) {
-			/* maxcat cpu present */
-			mutex_exit(&cpu_lock);
-			return (0);
-		}
-	}
-	mutex_exit(&cpu_lock);
-
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "reg", (caddr_t)regs, &reglen) != DDI_PROP_SUCCESS) {
-		DRMACH_PR("drmach_is_slot1_pause_axq: no reg prop for "
-		    "axq dip=%p\n", (void *)dip);
-		return (0);
-	}
-
-	ASSERT(id && reg);
-	*reg = (uint64_t)regs[0].reg_addr_hi << 32;
-	*reg |= (uint64_t)regs[0].reg_addr_lo;
-	*id = portid;
-
-	return (1);
-}
-
-/*
- * Allocate an entry in the slot1_paused state table.
- */
-static void
-drmach_slot1_pause_add_axq(dev_info_t *axq_dip, char *axq_name, int axq_portid,
-    uint64_t reg, drmach_slot1_pause_t **slot1_paused)
-{
-	int	axq_exp;
-	drmach_slot1_pause_t *slot1;
-
-	axq_exp = (axq_portid >> 5) & 0x1f;
-
-	ASSERT(axq_portid & 0x1);
-	ASSERT(slot1_paused[axq_exp] == NULL);
-	ASSERT(strncmp(axq_name, DRMACH_AXQ_NAMEPROP,
-	    strlen(DRMACH_AXQ_NAMEPROP)) == 0);
-
-	slot1 = kmem_zalloc(sizeof (*slot1), KM_SLEEP);
-
-	/*
-	 * XXX This dip should really be held (via ndi_hold_devi())
-	 * before saving it in the axq pause structure. However that
-	 * would prevent DR as the pause data structures persist until
-	 * the next suspend. drmach code should be modified to free the
-	 * the slot 1 pause data structures for a boardset when its
-	 * slot 1 board is DRed out. The dip can then be released via
-	 * ndi_rele_devi() when the pause data structure is freed
-	 * allowing DR to proceed. Until this change is made, drmach
-	 * code should be careful about dereferencing the saved dip
-	 * as it may no longer exist.
-	 */
-	slot1->axq.dip = axq_dip;
-	slot1->axq.portid = axq_portid;
-	slot1->axq.reg_basepa = reg;
-	slot1_paused[axq_exp] = slot1;
-}
-
-static void
-drmach_s1p_pci_free(drmach_s1p_pci_t *pci)
-{
-	int	i;
-
-	for (i = 0; i < DRMACH_S1P_SAMPLE_MAX; i++) {
-		if (pci->regs[i].intr_map_regs != NULL) {
-			ASSERT(pci->regs[i].nmap_regs > 0);
-			kmem_free(pci->regs[i].intr_map_regs,
-			    pci->regs[i].nmap_regs * sizeof (uint64_t));
-		}
-	}
-}
-
-static void
-drmach_slot1_pause_free(drmach_slot1_pause_t **slot1_paused)
-{
-	int	i, j, k;
-	drmach_slot1_pause_t *slot1;
-
-	for (i = 0; i < STARCAT_BDSET_MAX; i++) {
-		if ((slot1 = slot1_paused[i]) == NULL)
-			continue;
-
-		for (j = 0; j < STARCAT_SLOT1_IO_MAX; j++)
-			for (k = 0; k < DRMACH_SCHIZO_PCI_LEAF_MAX; k++)
-				drmach_s1p_pci_free(&slot1->schizo[j].pci[k]);
-
-		kmem_free(slot1, sizeof (*slot1));
-		slot1_paused[i] = NULL;
-	}
-}
-
-/*
- * Tree walk callback routine. If dip represents a Schizo PCI leaf,
- * fill in the appropriate info in the slot1_paused state table.
- */
-static int
-drmach_find_slot1_io(dev_info_t *dip, void *arg)
-{
-	int		portid, exp, ioc_unum, leaf_unum;
-	char		buf[OBP_MAXDRVNAME];
-	int		buflen = sizeof (buf);
-	drmach_reg_t	regs[3];
-	int		reglen = sizeof (regs);
-	uint32_t	leaf_offset;
-	uint64_t	schizo_csr_pa, pci_csr_pa;
-	drmach_s1p_pci_t *pci;
-	drmach_slot1_pause_t **slot1_paused = (drmach_slot1_pause_t **)arg;
-
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "name", (caddr_t)buf, &buflen) != DDI_PROP_SUCCESS ||
-	    strncmp(buf, DRMACH_PCI_NAMEPROP, strlen(DRMACH_PCI_NAMEPROP))) {
-		return (DDI_WALK_CONTINUE);
-	}
-
-	if ((portid = ddi_getprop(DDI_DEV_T_ANY, dip,
-	    DDI_PROP_DONTPASS, "portid", -1)) == -1) {
-		return (DDI_WALK_CONTINUE);
-	}
-
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "reg", (caddr_t)regs, &reglen) != DDI_PROP_SUCCESS) {
-		DRMACH_PR("drmach_find_slot1_io: no reg prop for pci "
-		    "dip=%p\n", (void *)dip);
-		return (DDI_WALK_CONTINUE);
-	}
-
-	exp = portid >> 5;
-	ioc_unum = portid & 0x1;
-	leaf_offset = regs[0].reg_addr_lo & 0x7fffff;
-	pci_csr_pa = (uint64_t)regs[0].reg_addr_hi << 32;
-	pci_csr_pa |= (uint64_t)regs[0].reg_addr_lo;
-	schizo_csr_pa = (uint64_t)regs[1].reg_addr_hi << 32;
-	schizo_csr_pa |= (uint64_t)regs[1].reg_addr_lo;
-
-	ASSERT(exp >= 0 && exp < STARCAT_BDSET_MAX);
-	ASSERT(slot1_paused[exp] != NULL);
-	ASSERT(leaf_offset == 0x600000 || leaf_offset == 0x700000);
-	ASSERT(slot1_paused[exp]->schizo[ioc_unum].csr_basepa == 0x0UL ||
-	    slot1_paused[exp]->schizo[ioc_unum].csr_basepa == schizo_csr_pa);
-
-	leaf_unum = (leaf_offset == 0x600000) ? 0 : 1;
-	slot1_paused[exp]->schizo[ioc_unum].csr_basepa = schizo_csr_pa;
-	pci = &slot1_paused[exp]->schizo[ioc_unum].pci[leaf_unum];
-
-	/*
-	 * XXX This dip should really be held (via ndi_hold_devi())
-	 * before saving it in the pci pause structure. However that
-	 * would prevent DR as the pause data structures persist until
-	 * the next suspend. drmach code should be modified to free the
-	 * the slot 1 pause data structures for a boardset when its
-	 * slot 1 board is DRed out. The dip can then be released via
-	 * ndi_rele_devi() when the pause data structure is freed
-	 * allowing DR to proceed. Until this change is made, drmach
-	 * code should be careful about dereferencing the saved dip as
-	 * it may no longer exist.
-	 */
-	pci->dip = dip;
-	pci->portid = portid;
-	pci->csr_basepa = pci_csr_pa;
-
-	DRMACH_PR("drmach_find_slot1_io: name=%s, portid=0x%x, dip=%p\n",
-	    buf, portid, (void *)dip);
-
-	return (DDI_WALK_PRUNECHILD);
-}
-
-static void
-drmach_slot1_pause_add_io(drmach_slot1_pause_t **slot1_paused)
-{
-	/*
-	 * Root node doesn't have to be held
-	 */
-	ddi_walk_devs(ddi_root_node(), drmach_find_slot1_io,
-	    (void *)slot1_paused);
-}
-
-/*
- * Save the interrupt mapping registers for each non-idle interrupt
- * represented by the bit pairs in the saved interrupt state
- * diagnostic registers for this PCI leaf.
- */
-static void
-drmach_s1p_intr_map_reg_save(drmach_s1p_pci_t *pci, drmach_sr_iter_t iter)
-{
-	int	 i, cnt, ino;
-	uint64_t reg;
-	char	 *dname;
-	uchar_t	 Xmits;
-
-	dname = ddi_binding_name(pci->dip);
-	Xmits = (strcmp(dname, XMITS_BINDING_NAME) == 0)  ?  1 : 0;
-
-	/*
-	 * 1st pass allocates, 2nd pass populates.
-	 */
-	for (i = 0; i < 2; i++) {
-		cnt = ino = 0;
-
-		/*
-		 * PCI slot interrupts
-		 */
-		reg = pci->regs[iter].slot_intr_state_diag;
-		while (reg) {
-			/*
-			 * Xmits Interrupt Number Offset(ino) Assignments
-			 *   00-17 PCI Slot Interrupts
-			 *   18-1f Not Used
-			 */
-			if ((Xmits) && (ino > 0x17))
-				break;
-			if ((reg & COMMON_CLEAR_INTR_REG_MASK) !=
-			    COMMON_CLEAR_INTR_REG_IDLE) {
-				if (i) {
-					pci->regs[iter].intr_map_regs[cnt] =
-					    lddphysio(pci->csr_basepa +
-					    SCHIZO_IB_INTR_MAP_REG_OFFSET +
-					    ino * sizeof (reg));
-				}
-				++cnt;
-			}
-			++ino;
-			reg >>= 2;
-		}
-
-		/*
-		 * Xmits Interrupt Number Offset(ino) Assignments
-		 *   20-2f Not Used
-		 *   30-37 Internal interrupts
-		 *   38-3e Not Used
-		 */
-		ino = (Xmits)  ?  0x30 : 0x20;
-
-		/*
-		 * OBIO and internal schizo interrupts
-		 * Each PCI leaf has a set of mapping registers for all
-		 * possible interrupt sources except the NewLink interrupts.
-		 */
-		reg = pci->regs[iter].obio_intr_state_diag;
-		while (reg && ino <= 0x38) {
-			if ((reg & COMMON_CLEAR_INTR_REG_MASK) !=
-			    COMMON_CLEAR_INTR_REG_IDLE) {
-				if (i) {
-					pci->regs[iter].intr_map_regs[cnt] =
-					    lddphysio(pci->csr_basepa +
-					    SCHIZO_IB_INTR_MAP_REG_OFFSET +
-					    ino * sizeof (reg));
-				}
-				++cnt;
-			}
-			++ino;
-			reg >>= 2;
-		}
-
-		if (!i) {
-			pci->regs[iter].nmap_regs = cnt;
-			pci->regs[iter].intr_map_regs =
-			    kmem_zalloc(cnt * sizeof (reg), KM_SLEEP);
-		}
-	}
-}
-
-static void
-drmach_s1p_axq_update(drmach_s1p_axq_t *axq, drmach_sr_iter_t iter)
-{
-	uint32_t	reg;
-
-	if (axq->reg_basepa == 0x0UL)
-		return;
-
-	if (iter == DRMACH_POST_SUSPEND) {
-		axq->pcr_sel_save = ldphysio(axq->reg_basepa +
-		    AXQ_SLOT1_PERFCNT_SEL);
-		/*
-		 * Select l2_io_queue counter by writing L2_IO_Q mux
-		 * input to bits 0-6 of perf cntr select reg.
-		 */
-		reg = axq->pcr_sel_save;
-		reg &= ~AXQ_PIC_CLEAR_MASK;
-		reg |= L2_IO_Q;
-
-		stphysio(axq->reg_basepa + AXQ_SLOT1_PERFCNT_SEL, reg);
-	}
-
-	axq->pic_l2_io_q[iter] = ldphysio(axq->reg_basepa + AXQ_SLOT1_PERFCNT0);
-
-	if (iter == DRMACH_PRE_RESUME) {
-		stphysio(axq->reg_basepa + AXQ_SLOT1_PERFCNT_SEL,
-		    axq->pcr_sel_save);
-	}
-
-	DRMACH_PR("drmach_s1p_axq_update: axq #%d pic_l2_io_q[%d]=%d\n",
-	    ddi_get_instance(axq->dip), iter, axq->pic_l2_io_q[iter]);
-}
-
-static void
-drmach_s1p_schizo_update(drmach_s1p_schizo_t *schizo, drmach_sr_iter_t iter)
-{
-	int	i;
-	drmach_s1p_pci_t *pci;
-
-	if (schizo->csr_basepa == 0x0UL)
-		return;
-
-	schizo->regs[iter].csr =
-	    lddphysio(schizo->csr_basepa + SCHIZO_CB_CSR_OFFSET);
-	schizo->regs[iter].errctrl =
-	    lddphysio(schizo->csr_basepa + SCHIZO_CB_ERRCTRL_OFFSET);
-	schizo->regs[iter].errlog =
-	    lddphysio(schizo->csr_basepa + SCHIZO_CB_ERRLOG_OFFSET);
-
-	for (i = 0; i < DRMACH_SCHIZO_PCI_LEAF_MAX; i++) {
-		pci = &schizo->pci[i];
-		if (pci->dip != NULL && pci->csr_basepa != 0x0UL) {
-			pci->regs[iter].slot_intr_state_diag =
-			    lddphysio(pci->csr_basepa +
-			    COMMON_IB_SLOT_INTR_STATE_DIAG_REG);
-
-			pci->regs[iter].obio_intr_state_diag =
-			    lddphysio(pci->csr_basepa +
-			    COMMON_IB_OBIO_INTR_STATE_DIAG_REG);
-
-			drmach_s1p_intr_map_reg_save(pci, iter);
-		}
-	}
-}
-
-/*
- * Called post-suspend and pre-resume to snapshot the suspend state
- * of slot1 AXQs and Schizos.
- */
-static void
-drmach_slot1_pause_update(drmach_slot1_pause_t **slot1_paused,
-    drmach_sr_iter_t iter)
-{
-	int	i, j;
-	drmach_slot1_pause_t *slot1;
-
-	for (i = 0; i < STARCAT_BDSET_MAX; i++) {
-		if ((slot1 = slot1_paused[i]) == NULL)
-			continue;
-
-		drmach_s1p_axq_update(&slot1->axq, iter);
-		for (j = 0; j < STARCAT_SLOT1_IO_MAX; j++)
-			drmach_s1p_schizo_update(&slot1->schizo[j], iter);
-	}
-}
-
-/*
- * Starcat hPCI Schizo devices.
- *
- * The name field is overloaded. NULL means the slot (interrupt concentrator
- * bus) is not used. intr_mask is a bit mask representing the 4 possible
- * interrupts per slot, on if valid (rio does not use interrupt lines 0, 1).
- */
-static struct {
-	char	*name;
-	uint8_t	intr_mask;
-} drmach_schz_slot_intr[][DRMACH_SCHIZO_PCI_LEAF_MAX] = {
-	/* Schizo 0 */		/* Schizo 1 */
-	{{"C3V0", 0xf},		{"C3V1", 0xf}},		/* slot 0 */
-	{{"C5V0", 0xf},		{"C5V1", 0xf}},		/* slot 1 */
-	{{"rio", 0xc},		{NULL, 0x0}},		/* slot 2 */
-	{{NULL, 0x0},		{NULL, 0x0}},		/* slot 3 */
-	{{"sbbc", 0xf},		{NULL, 0x0}},		/* slot 4 */
-	{{NULL, 0x0},		{NULL, 0x0}},		/* slot 5 */
-	{{NULL, 0x0},		{NULL, 0x0}},		/* slot 6 */
-	{{NULL, 0x0},		{NULL, 0x0}}		/* slot 7 */
-};
-
-/*
- * See Schizo Specification, Revision 51 (May 23, 2001), Section 22.4.4
- * "Interrupt Registers", Table 22-69, page 306.
- */
-static char *
-drmach_schz_internal_ino2str(int ino)
-{
-	int	intr;
-
-	ASSERT(ino >= 0x30 && ino <= 0x37);
-
-	intr = ino & 0x7;
-	switch (intr) {
-		case (0x0):	return ("Uncorrectable ECC error");
-		case (0x1):	return ("Correctable ECC error");
-		case (0x2):	return ("PCI Bus A Error");
-		case (0x3):	return ("PCI Bus B Error");
-		case (0x4):	return ("Safari Bus Error");
-		default:	return ("Reserved");
-	}
-}
-
-#define	DRMACH_INTR_MASK_SHIFT(ino)	((ino) << 1)
-
-static void
-drmach_s1p_decode_slot_intr(int exp, int unum, drmach_s1p_pci_t *pci,
-    int ino, drmach_sr_iter_t iter)
-{
-	uint8_t		intr_mask;
-	char		*slot_devname;
-	char		namebuf[OBP_MAXDRVNAME];
-	int		slot, intr_line, slot_valid, intr_valid;
-
-	ASSERT(ino >= 0 && ino <= 0x1f);
-	ASSERT((pci->regs[iter].slot_intr_state_diag &
-	    (COMMON_CLEAR_INTR_REG_MASK << DRMACH_INTR_MASK_SHIFT(ino))) !=
-	    COMMON_CLEAR_INTR_REG_IDLE);
-
-	slot = (ino >> 2) & 0x7;
-	intr_line = ino & 0x3;
-
-	slot_devname = drmach_schz_slot_intr[slot][unum].name;
-	slot_valid = (slot_devname == NULL) ? 0 : 1;
-	if (!slot_valid) {
-		(void) snprintf(namebuf, sizeof (namebuf), "slot %d (INVALID)",
-		    slot);
-		slot_devname = namebuf;
-	}
-
-	intr_mask = drmach_schz_slot_intr[slot][unum].intr_mask;
-	intr_valid = (1 << intr_line) & intr_mask;
-
-	prom_printf("IO%d/P%d PCI slot interrupt: ino=0x%x, source device=%s, "
-	    "interrupt line=%d%s\n", exp, unum, ino, slot_devname, intr_line,
-	    (slot_valid && !intr_valid) ? " (INVALID)" : "");
-}
-
-/*
- * Log interrupt source device info for all valid, pending interrupts
- * on each Schizo PCI leaf. Called if Schizo has logged a Safari bus
- * error in the error ctrl reg.
- */
-static void
-drmach_s1p_schizo_log_intr(drmach_s1p_schizo_t *schizo, int exp,
-    int unum, drmach_sr_iter_t iter)
-{
-	uint64_t	reg;
-	int		i, n, ino;
-	drmach_s1p_pci_t *pci;
-
-	ASSERT(exp >= 0 && exp < STARCAT_BDSET_MAX);
-	ASSERT(unum < STARCAT_SLOT1_IO_MAX);
-
-	/*
-	 * Check the saved interrupt mapping registers. If interrupt is valid,
-	 * map the ino to the Schizo source device and check that the pci
-	 * slot and interrupt line are valid.
-	 */
-	for (i = 0; i < DRMACH_SCHIZO_PCI_LEAF_MAX; i++) {
-		pci = &schizo->pci[i];
-		for (n = 0; n < pci->regs[iter].nmap_regs; n++) {
-			reg = pci->regs[iter].intr_map_regs[n];
-			if (reg & COMMON_INTR_MAP_REG_VALID) {
-				ino = reg & COMMON_INTR_MAP_REG_INO;
-
-				if (ino <= 0x1f) {
-					/*
-					 * PCI slot interrupt
-					 */
-					drmach_s1p_decode_slot_intr(exp, unum,
-					    pci, ino, iter);
-				} else if (ino <= 0x2f) {
-					/*
-					 * OBIO interrupt
-					 */
-					prom_printf("IO%d/P%d OBIO interrupt: "
-					    "ino=0x%x\n", exp, unum, ino);
-				} else if (ino <= 0x37) {
-					/*
-					 * Internal interrupt
-					 */
-					prom_printf("IO%d/P%d Internal "
-					    "interrupt: ino=0x%x (%s)\n",
-					    exp, unum, ino,
-					    drmach_schz_internal_ino2str(ino));
-				} else {
-					/*
-					 * NewLink interrupt
-					 */
-					prom_printf("IO%d/P%d NewLink "
-					    "interrupt: ino=0x%x\n", exp,
-					    unum, ino);
-				}
-
-				DRMACH_PR("drmach_s1p_schizo_log_intr: "
-				    "exp=%d, schizo=%d, pci_leaf=%c, "
-				    "ino=0x%x, intr_map_reg=0x%lx\n",
-				    exp, unum, (i == 0) ? 'A' : 'B', ino, reg);
-			}
-		}
-	}
-}
-
-/*
- * See Schizo Specification, Revision 51 (May 23, 2001), Section 22.2.4
- * "Safari Error Control/Log Registers", Table 22-11, page 248.
- */
-#define	DRMACH_SCHIZO_SAFARI_UNMAPPED_ERR	(0x1ull << 4)
-
-/*
- * Check for possible error indicators prior to resuming the
- * AXQ driver, which will de-assert slot1 AXQ_DOMCTRL_PAUSE.
- */
-static void
-drmach_slot1_pause_verify(drmach_slot1_pause_t **slot1_paused,
-    drmach_sr_iter_t iter)
-{
-	int	i, j;
-	int 	errflag = 0;
-	drmach_slot1_pause_t *slot1;
-
-	/*
-	 * Check for logged schizo bus error and pending interrupts.
-	 */
-	for (i = 0; i < STARCAT_BDSET_MAX; i++) {
-		if ((slot1 = slot1_paused[i]) == NULL)
-			continue;
-
-		for (j = 0; j < STARCAT_SLOT1_IO_MAX; j++) {
-			if (slot1->schizo[j].csr_basepa == 0x0UL)
-				continue;
-
-			if (slot1->schizo[j].regs[iter].errlog &
-			    DRMACH_SCHIZO_SAFARI_UNMAPPED_ERR) {
-				if (!errflag) {
-					prom_printf("DR WARNING: interrupt "
-					    "attempt detected during "
-					    "copy-rename (%s):\n",
-					    (iter == DRMACH_POST_SUSPEND) ?
-					    "post suspend" : "pre resume");
-					++errflag;
-				}
-				drmach_s1p_schizo_log_intr(&slot1->schizo[j],
-				    i, j, iter);
-			}
-		}
-	}
-
-	/*
-	 * Check for changes in axq l2_io_q performance counters (2nd pass only)
-	 */
-	if (iter == DRMACH_PRE_RESUME) {
-		for (i = 0; i < STARCAT_BDSET_MAX; i++) {
-			if ((slot1 = slot1_paused[i]) == NULL)
-				continue;
-
-			if (slot1->axq.pic_l2_io_q[DRMACH_POST_SUSPEND] !=
-			    slot1->axq.pic_l2_io_q[DRMACH_PRE_RESUME]) {
-				prom_printf("DR WARNING: IO transactions "
-				    "detected on IO%d during copy-rename: "
-				    "AXQ l2_io_q performance counter "
-				    "start=%d, end=%d\n", i,
-				    slot1->axq.pic_l2_io_q[DRMACH_POST_SUSPEND],
-				    slot1->axq.pic_l2_io_q[DRMACH_PRE_RESUME]);
-			}
-		}
-	}
-}
-
-struct drmach_sr_list {
-	dev_info_t		*dip;
-	struct drmach_sr_list	*next;
-	struct drmach_sr_list	*prev;
-};
-
-static struct drmach_sr_ordered {
-	char			*name;
-	struct drmach_sr_list	*ring;
-} drmach_sr_ordered[] = {
-	{ "iosram",			NULL },
-	{ "address-extender-queue",	NULL },
-	{ NULL,				NULL }, /* terminator -- required */
-};
-
-static void
-drmach_sr_insert(struct drmach_sr_list **lp, dev_info_t *dip)
-{
-	struct drmach_sr_list *np;
-
-	DRMACH_PR("drmach_sr_insert: adding dip %p\n", (void *)dip);
-
-	np = (struct drmach_sr_list *)kmem_alloc(
-	    sizeof (struct drmach_sr_list), KM_SLEEP);
-
-	ndi_hold_devi(dip);
-	np->dip = dip;
-
-	if (*lp == NULL) {
-		/* establish list */
-		*lp = np->next = np->prev = np;
-	} else {
-		/* place new node behind head node on ring list */
-		np->prev = (*lp)->prev;
-		np->next = *lp;
-		np->prev->next = np;
-		np->next->prev = np;
-	}
-}
-
-static void
-drmach_sr_delete(struct drmach_sr_list **lp, dev_info_t *dip)
-{
-	DRMACH_PR("drmach_sr_delete: searching for dip %p\n", (void *)dip);
-
-	if (*lp) {
-		struct drmach_sr_list *xp;
-
-		/* start search with mostly likely node */
-		xp = (*lp)->prev;
-		do {
-			if (xp->dip == dip) {
-				xp->prev->next = xp->next;
-				xp->next->prev = xp->prev;
-
-				if (xp == *lp)
-					*lp = xp->next;
-				if (xp == *lp)
-					*lp = NULL;
-				xp->dip = NULL;
-				ndi_rele_devi(dip);
-				kmem_free(xp, sizeof (*xp));
-
-				DRMACH_PR("drmach_sr_delete:"
-				    " disposed sr node for dip %p",
-				    (void *)dip);
-				return;
-			}
-
-			DRMACH_PR("drmach_sr_delete: still searching\n");
-
-			xp = xp->prev;
-		} while (xp != (*lp)->prev);
-	}
-
-	/* every dip should be found during resume */
-	DRMACH_PR("ERROR: drmach_sr_delete: can't find dip %p", (void *)dip);
-}
-
-int
-drmach_verify_sr(dev_info_t *dip, int sflag)
-{
-	int	rv;
-	int	len;
-	char    name[OBP_MAXDRVNAME];
-
-	if (drmach_slot1_pause_debug) {
-		if (sflag && drmach_slot1_pause_init) {
-			drmach_slot1_pause_free(drmach_slot1_paused);
-			drmach_slot1_pause_init = 0;
-		} else if (!sflag && !drmach_slot1_pause_init) {
-			/* schedule init for next suspend */
-			drmach_slot1_pause_init = 1;
-		}
-	}
-
-	rv = ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "name", &len);
-	if (rv == DDI_PROP_SUCCESS) {
-		int		portid;
-		uint64_t	reg;
-		struct drmach_sr_ordered *op;
-
-		rv = ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
-		    DDI_PROP_DONTPASS, "name", (caddr_t)name, &len);
-
-		if (rv != DDI_PROP_SUCCESS)
-			return (0);
-
-		if (drmach_slot1_pause_debug && sflag &&
-		    drmach_is_slot1_pause_axq(dip, name, &portid, &reg)) {
-			drmach_slot1_pause_add_axq(dip, name, portid, reg,
-			    drmach_slot1_paused);
-		}
-
-		for (op = drmach_sr_ordered; op->name; op++) {
-			if (strncmp(op->name, name, strlen(op->name)) == 0) {
-				if (sflag)
-					drmach_sr_insert(&op->ring, dip);
-				else
-					drmach_sr_delete(&op->ring, dip);
-				return (1);
-			}
-		}
-	}
-
-	return (0);
-}
-
-static void
-drmach_sr_dip(dev_info_t *dip, int suspend)
-{
-	int	 rv;
-	major_t	 maj;
-	char	*name, *name_addr, *aka;
-
-	if ((name = ddi_get_name(dip)) == NULL)
-		name = "<null name>";
-	else if ((maj = ddi_name_to_major(name)) != -1)
-		aka = ddi_major_to_name(maj);
-	else
-		aka = "<unknown>";
-
-	if ((name_addr = ddi_get_name_addr(dip)) == NULL)
-		name_addr = "<null>";
-
-	prom_printf("\t%s %s@%s (aka %s)\n",
-	    suspend ? "suspending" : "resuming",
-	    name, name_addr, aka);
-
-	if (suspend) {
-		rv = devi_detach(dip, DDI_SUSPEND);
-	} else {
-		rv = devi_attach(dip, DDI_RESUME);
-	}
-
-	if (rv != DDI_SUCCESS) {
-		prom_printf("\tFAILED to %s %s@%s\n",
-		    suspend ? "suspend" : "resume",
-		    name, name_addr);
-	}
-}
-
-void
-drmach_suspend_last()
-{
-	struct drmach_sr_ordered *op;
-
-	if (drmach_slot1_pause_debug)
-		drmach_slot1_pause_add_io(drmach_slot1_paused);
-
-	/*
-	 * The ordering array declares the strict sequence in which
-	 * the named drivers are to suspended. Each element in
-	 * the array may have a double-linked ring list of driver
-	 * instances (dip) in the order in which they were presented
-	 * to drmach_verify_sr. If present, walk the list in the
-	 * forward direction to suspend each instance.
-	 */
-	for (op = drmach_sr_ordered; op->name; op++) {
-		if (op->ring) {
-			struct drmach_sr_list *rp;
-
-			rp = op->ring;
-			do {
-				drmach_sr_dip(rp->dip, 1);
-				rp = rp->next;
-			} while (rp != op->ring);
-		}
-	}
-
-	if (drmach_slot1_pause_debug) {
-		drmach_slot1_pause_update(drmach_slot1_paused,
-		    DRMACH_POST_SUSPEND);
-		drmach_slot1_pause_verify(drmach_slot1_paused,
-		    DRMACH_POST_SUSPEND);
-	}
-}
-
-void
-drmach_resume_first()
-{
-	struct drmach_sr_ordered *op = drmach_sr_ordered +
-	    (sizeof (drmach_sr_ordered) / sizeof (drmach_sr_ordered[0]));
-
-	if (drmach_slot1_pause_debug) {
-		drmach_slot1_pause_update(drmach_slot1_paused,
-		    DRMACH_PRE_RESUME);
-		drmach_slot1_pause_verify(drmach_slot1_paused,
-		    DRMACH_PRE_RESUME);
-	}
-
-	op -= 1;	/* point at terminating element */
-
-	/*
-	 * walk ordering array and rings backwards to resume dips
-	 * in reverse order in which they were suspended
-	 */
-	while (--op >= drmach_sr_ordered) {
-		if (op->ring) {
-			struct drmach_sr_list *rp;
-
-			rp = op->ring->prev;
-			do {
-				drmach_sr_dip(rp->dip, 0);
-				rp = rp->prev;
-			} while (rp != op->ring->prev);
-		}
-	}
-}
-
-/*
- * 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);
-}
-
-/*
- * Initialize the mem_slice portion of a claim/unconfig/unclaim mailbox message.
- * Only the valid entries are modified, so the array should be zeroed out
- * initially.
- */
-static void
-drmach_msg_memslice_init(dr_memslice_t slice_arr[]) {
-	int	i;
-	char	c;
-
-	ASSERT(mutex_owned(&drmach_slice_table_lock));
-
-	for (i = 0; i < AXQ_MAX_EXP; i++) {
-		c = drmach_slice_table[i];
-
-		if (c & 0x20) {
-			slice_arr[i].valid = 1;
-			slice_arr[i].slice = c & 0x1f;
-		}
-	}
-}
-
-/*
- * Initialize the mem_regs portion of a claim/unconfig/unclaim mailbox message.
- * Only the valid entries are modified, so the array should be zeroed out
- * initially.
- */
-static void
-drmach_msg_memregs_init(dr_memregs_t regs_arr[]) {
-	int		rv, exp, mcnum, bank;
-	uint64_t	madr;
-	drmachid_t	id;
-	drmach_board_t	*bp;
-	drmach_mem_t	*mp;
-	dr_memregs_t	*memregs;
-
-	/* CONSTCOND */
-	ASSERT(DRMACH_MC_NBANKS == (PMBANKS_PER_PORT * LMBANKS_PER_PMBANK));
-
-	for (exp = 0; exp < 18; exp++) {
-		rv = drmach_array_get(drmach_boards,
-		    DRMACH_EXPSLOT2BNUM(exp, 0), &id);
-		ASSERT(rv == 0);	/* should never be out of bounds */
-		if (id == NULL) {
-			continue;
-		}
-
-		memregs = &regs_arr[exp];
-		bp = (drmach_board_t *)id;
-		for (mp = bp->mem; mp != NULL; mp = mp->next) {
-			mcnum = mp->dev.portid & 0x3;
-			for (bank = 0; bank < DRMACH_MC_NBANKS; bank++) {
-				drmach_mem_read_madr(mp, bank, &madr);
-				if (madr & DRMACH_MC_VALID_MASK) {
-					DRMACH_PR("%d.%d.%d.madr = 0x%lx\n",
-					    exp, mcnum, bank, madr);
-					memregs->madr[mcnum][bank].hi =
-					    DRMACH_U64_TO_MCREGHI(madr);
-					memregs->madr[mcnum][bank].lo =
-					    DRMACH_U64_TO_MCREGLO(madr);
-				}
-			}
-		}
-	}
-}
-
-/*
- * Do not allow physical address range modification if either board on this
- * expander has processors in NULL LPA mode (CBASE=CBND=NULL).
- *
- * A side effect of NULL proc LPA mode in Starcat SSM is that local reads will
- * install the cache line as owned/dirty as a result of the RTSR transaction.
- * See section 5.2.3 of the Safari spec.  All processors will read the bus sync
- * list before the rename after flushing local caches.  When copy-rename
- * requires changing the physical address ranges (i.e. smaller memory target),
- * the bus sync list contains physical addresses that will not exist after the
- * rename.  If these cache lines are owned due to a RTSR, a system error can
- * occur following the rename when these cache lines are evicted and a writeback
- * is attempted.
- *
- * Incoming parameter represents either the copy-rename source or a candidate
- * target memory board.  On Starcat, only slot0 boards may have memory.
- */
-int
-drmach_allow_memrange_modify(drmachid_t s0id)
-{
-	drmach_board_t	*s0bp, *s1bp;
-	drmachid_t	s1id;
-	int		rv;
-
-	s0bp = s0id;
-
-	ASSERT(DRMACH_IS_BOARD_ID(s0id));
-	ASSERT(DRMACH_BNUM2SLOT(s0bp->bnum) == 0);
-
-	if (s0bp->flags & DRMACH_NULL_PROC_LPA) {
-		/*
-		 * This is reason enough to fail the request, no need
-		 * to check the device list for cpus.
-		 */
-		return (0);
-	}
-
-	/*
-	 * Check for MCPU board on the same expander.
-	 *
-	 * The board flag DRMACH_NULL_PROC_LPA can be set for all board
-	 * types, as it is derived at from the POST gdcd board flag
-	 * L1SSFLG_THIS_L1_NULL_PROC_LPA, which can be set (and should be
-	 * ignored) for boards with no processors.  Since NULL proc LPA
-	 * applies only to processors, we walk the devices array to detect
-	 * MCPUs.
-	 */
-	rv = drmach_array_get(drmach_boards, s0bp->bnum + 1, &s1id);
-	s1bp = s1id;
-	if (rv == 0 && s1bp != NULL) {
-
-		ASSERT(DRMACH_IS_BOARD_ID(s1id));
-		ASSERT(DRMACH_BNUM2SLOT(s1bp->bnum) == 1);
-		ASSERT(DRMACH_BNUM2EXP(s0bp->bnum) ==
-		    DRMACH_BNUM2EXP(s1bp->bnum));
-
-		if ((s1bp->flags & DRMACH_NULL_PROC_LPA) &&
-		    s1bp->devices != NULL) {
-			int		d_idx;
-			drmachid_t	d_id;
-
-			rv = drmach_array_first(s1bp->devices, &d_idx, &d_id);
-			while (rv == 0) {
-				if (DRMACH_IS_CPU_ID(d_id)) {
-					/*
-					 * Fail MCPU in NULL LPA mode.
-					 */
-					return (0);
-				}
-
-				rv = drmach_array_next(s1bp->devices, &d_idx,
-				    &d_id);
-			}
-		}
-	}
-
-	return (1);
-}
--- a/usr/src/uts/sun4u/starcat/io/fcgp2.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,997 +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.
- */
-
-/*
- * fcgp2.c: Framework gp2 (Safari) fcode ops
- */
-#include <sys/types.h>
-#include <sys/kmem.h>
-#include <sys/systm.h>
-#include <sys/pci.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ddidmareq.h>
-#include <sys/modctl.h>
-#include <sys/ndi_impldefs.h>
-#include <sys/fcode.h>
-#include <sys/promif.h>
-#include <sys/promimpl.h>
-
-static int gfc_map_in(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_map_out(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_register_fetch(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_register_store(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_claim_address(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_claim_memory(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_release_memory(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_vtop(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_master_intr(dev_info_t *, fco_handle_t, fc_ci_t *);
-
-static int gfc_config_child(dev_info_t *, fco_handle_t, fc_ci_t *);
-
-static int gfc_get_fcode_size(dev_info_t *, fco_handle_t, fc_ci_t *);
-static int gfc_get_fcode(dev_info_t *, fco_handle_t, fc_ci_t *);
-
-int prom_get_fcode_size(char *);
-int prom_get_fcode(char *, char *);
-
-int fcpci_unloadable;
-int no_advisory_dma;
-
-#define	HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
-#define	LOADDR(n)((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
-#define	LADDR(lo, hi)    (((uint64_t)(hi) << 32) | (uint32_t)(lo))
-#define	PCI_4GIG_LIMIT 0xFFFFFFFFUL
-
-
-/*
- * Module linkage information for the kernel.
- */
-static struct modlmisc modlmisc = {
-	&mod_miscops, "FCode gp2 (safari) bus functions"
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1, (void *)&modlmisc, NULL
-};
-
-int
-_init(void)
-{
-	return (mod_install(&modlinkage));
-}
-
-int
-_fini(void)
-{
-	if (fcpci_unloadable)
-		return (mod_remove(&modlinkage));
-	return (EBUSY);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-
-struct gfc_ops_v {
-	char *svc_name;
-	fc_ops_t *f;
-};
-
-struct gfc_ops_v gp2_pov[] = {
-	{	"map-in",		gfc_map_in},
-	{	"map-out",		gfc_map_out},
-	{	"rx@",			gfc_register_fetch},
-	{	"rl@",			gfc_register_fetch},
-	{	"rw@",			gfc_register_fetch},
-	{	"rb@",			gfc_register_fetch},
-	{	"rx!",			gfc_register_store},
-	{	"rl!",			gfc_register_store},
-	{	"rw!",			gfc_register_store},
-	{	"rb!",			gfc_register_store},
-	{	"claim-address",	gfc_claim_address},
-	{	"master-interrupt",	gfc_master_intr},
-	{	"claim-memory",		gfc_claim_memory},
-	{	"release-memory",	gfc_release_memory},
-	{	"vtop",			gfc_vtop},
-	{	FC_CONFIG_CHILD,	gfc_config_child},
-	{	FC_GET_FCODE_SIZE,	gfc_get_fcode_size},
-	{	FC_GET_FCODE,		gfc_get_fcode},
-	{	NULL,			NULL}
-};
-
-struct gfc_ops_v gp2_shared_pov[] = {
-	{	NULL,			NULL}
-};
-
-static int gp2_map_phys(dev_info_t *, struct regspec *,  caddr_t *,
-    ddi_device_acc_attr_t *, ddi_acc_handle_t *);
-static void gp2_unmap_phys(ddi_acc_handle_t *);
-
-fco_handle_t
-gp2_fc_ops_alloc_handle(dev_info_t *ap, dev_info_t *child,
-    void *fcode, size_t fcode_size, char *unit_address,
-    char *my_args)
-{
-	fco_handle_t rp;
-	phandle_t h;
-
-	rp = kmem_zalloc(sizeof (struct fc_resource_list), KM_SLEEP);
-	rp->next_handle = fc_ops_alloc_handle(ap, child, fcode, fcode_size,
-	    unit_address, NULL);
-	rp->ap = ap;
-	rp->child = child;
-	rp->fcode = fcode;
-	rp->fcode_size = fcode_size;
-	rp->my_args = my_args;
-
-	if (unit_address) {
-		char *buf;
-
-		buf = kmem_zalloc(strlen(unit_address) + 1, KM_SLEEP);
-		(void) strcpy(buf, unit_address);
-		rp->unit_address = buf;
-	}
-
-	/*
-	 * Add the child's nodeid to our table...
-	 */
-	h = ddi_get_nodeid(rp->child);
-	fc_add_dip_to_phandle(fc_handle_to_phandle_head(rp), rp->child, h);
-
-	return (rp);
-}
-
-void
-gp2_fc_ops_free_handle(fco_handle_t rp)
-{
-	struct fc_resource *ip, *np;
-
-	ASSERT(rp);
-
-	if (rp->next_handle)
-		fc_ops_free_handle(rp->next_handle);
-	if (rp->unit_address)
-		kmem_free(rp->unit_address, strlen(rp->unit_address) + 1);
-	if (rp->my_args != NULL)
-		kmem_free(rp->my_args, strlen(rp->my_args) + 1);
-
-	/*
-	 * Release all the resources from the resource list
-	 */
-	for (ip = rp->head; ip != NULL; ip = np) {
-		np = ip->next;
-		switch (ip->type) {
-		case RT_MAP:
-			FC_DEBUG1(1, CE_CONT, "gp2_fc_ops_free: "
-			    " map handle - %p\n", ip->fc_map_handle);
-			break;
-		case RT_DMA:
-			/* DMA has to be freed up at exit time */
-			cmn_err(CE_CONT, "gfc_fc_ops_free: DMA seen!\n");
-			break;
-		case RT_CONTIGIOUS:
-			FC_DEBUG2(1, CE_CONT, "gp2_fc_ops_free: "
-			    "Free claim-memory resource 0x%lx size 0x%x\n",
-			    ip->fc_contig_virt, ip->fc_contig_len);
-
-			(void) ndi_ra_free(ddi_root_node(),
-			    (uint64_t)ip->fc_contig_virt,
-			    ip->fc_contig_len, "gptwo-contigousmem",
-			    NDI_RA_PASS);
-
-			break;
-		default:
-			cmn_err(CE_CONT, "gp2_fc_ops_free: "
-			    "unknown resource type %d\n", ip->type);
-			break;
-		}
-		fc_rem_resource(rp, ip);
-		kmem_free(ip, sizeof (struct fc_resource));
-	}
-	kmem_free(rp, sizeof (struct fc_resource_list));
-}
-
-int
-gp2_fc_ops(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	struct gfc_ops_v *pv;
-	char *name = fc_cell2ptr(cp->svc_name);
-
-	ASSERT(rp);
-
-	/*
-	 * First try the generic fc_ops. If the ops is a shared op,
-	 * also call our local function.
-	 */
-	if (fc_ops(ap, rp->next_handle, cp) == 0) {
-		for (pv = gp2_shared_pov; pv->svc_name != NULL; ++pv)
-			if (strcmp(pv->svc_name, name) == 0)
-				return (pv->f(ap, rp, cp));
-		return (0);
-	}
-
-	for (pv = gp2_pov; pv->svc_name != NULL; ++pv)
-		if (strcmp(pv->svc_name, name) == 0)
-			return (pv->f(ap, rp, cp));
-
-	FC_DEBUG1(9, CE_CONT, "gp2_fc_ops: <%s> not serviced\n", name);
-
-	return (-1);
-}
-
-/*
- * map-in  (phys.lo phys.hi size -- virt )
- */
-static int
-gfc_map_in(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	size_t len;
-	int error;
-	caddr_t virt;
-	struct fc_resource *ip;
-	struct regspec r;
-	ddi_device_acc_attr_t acc;
-	ddi_acc_handle_t h;
-
-	if (fc_cell2int(cp->nargs) != 3)
-		return (fc_syntax_error(cp, "nargs must be 3"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	r.regspec_size = len = fc_cell2size(fc_arg(cp, 0));
-	r.regspec_bustype = fc_cell2uint(fc_arg(cp, 1));
-	r.regspec_addr = fc_cell2uint(fc_arg(cp, 2));
-
-	acc.devacc_attr_version = DDI_DEVICE_ATTR_V0;
-	acc.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
-	acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
-
-	FC_DEBUG3(1, CE_CONT, "gfc_map_in: attempting map in "
-	    "address 0x%08x.%08x length %x\n", r.regspec_bustype,
-	    r.regspec_addr, r.regspec_size);
-
-	error = gp2_map_phys(rp->child, &r, &virt, &acc, &h);
-
-	if (error)  {
-		FC_DEBUG3(1, CE_CONT, "gfc_map_in: map in failed - "
-		    "address 0x%08x.%08x length %x\n", r.regspec_bustype,
-		    r.regspec_addr, r.regspec_size);
-
-		return (fc_priv_error(cp, "gp2 map-in failed"));
-	}
-
-	FC_DEBUG1(3, CE_CONT, "gp2_map_in: returning virt %p\n", virt);
-
-	cp->nresults = fc_int2cell(1);
-	fc_result(cp, 0) = fc_ptr2cell(virt);
-
-	/*
-	 * Log this resource ...
-	 */
-	ip = kmem_zalloc(sizeof (struct fc_resource), KM_SLEEP);
-	ip->type = RT_MAP;
-	ip->fc_map_virt = virt;
-	ip->fc_map_len = len;
-	ip->fc_map_handle = h;
-	fc_add_resource(rp, ip);
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-/*
- * map-out ( virt size -- )
- */
-static int
-gfc_map_out(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	caddr_t virt;
-	size_t len;
-	struct fc_resource *ip;
-
-	if (fc_cell2int(cp->nargs) != 2)
-		return (fc_syntax_error(cp, "nargs must be 2"));
-
-	virt = fc_cell2ptr(fc_arg(cp, 1));
-
-	len = fc_cell2size(fc_arg(cp, 0));
-
-	FC_DEBUG2(1, CE_CONT, "gp2_map_out: attempting map out %p %x\n",
-	    virt, len);
-
-	/*
-	 * Find if this request matches a mapping resource we set up.
-	 */
-	fc_lock_resource_list(rp);
-	for (ip = rp->head; ip != NULL; ip = ip->next) {
-		if (ip->type != RT_MAP)
-			continue;
-		if (ip->fc_map_virt != virt)
-			continue;
-		if (ip->fc_map_len == len)
-			break;
-	}
-	fc_unlock_resource_list(rp);
-
-	if (ip == NULL)
-		return (fc_priv_error(cp, "request doesn't match a "
-		    "known mapping"));
-
-	gp2_unmap_phys(&ip->fc_map_handle);
-
-	/*
-	 * remove the resource from the list and release it.
-	 */
-	fc_rem_resource(rp, ip);
-	kmem_free(ip, sizeof (struct fc_resource));
-
-	cp->nresults = fc_int2cell(0);
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gfc_register_fetch(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	size_t len;
-	caddr_t virt;
-	int error = 0;
-	uint64_t x;
-	uint32_t l;
-	uint16_t w;
-	uint8_t b;
-	char *name = fc_cell2ptr(cp->svc_name);
-	struct fc_resource *ip;
-
-	if (fc_cell2int(cp->nargs) != 1)
-		return (fc_syntax_error(cp, "nargs must be 1"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	virt = fc_cell2ptr(fc_arg(cp, 0));
-
-	/*
-	 * Determine the access width .. we can switch on the 2nd
-	 * character of the name which is "rx@", "rl@", "rb@" or "rw@"
-	 */
-	switch (*(name + 1)) {
-	case 'x':	len = sizeof (x); break;
-	case 'l':	len = sizeof (l); break;
-	case 'w':	len = sizeof (w); break;
-	case 'b':	len = sizeof (b); break;
-	}
-
-	/*
-	 * Check the alignment ...
-	 */
-	if (((intptr_t)virt & (len - 1)) != 0)
-		return (fc_priv_error(cp, "unaligned access"));
-
-	/*
-	 * Find if this virt is 'within' a request we know about
-	 */
-	fc_lock_resource_list(rp);
-	for (ip = rp->head; ip != NULL; ip = ip->next) {
-		if (ip->type == RT_MAP) {
-		    if ((virt >= (caddr_t)ip->fc_map_virt) && ((virt + len) <=
-			((caddr_t)ip->fc_map_virt + ip->fc_map_len)))
-				break;
-		} else if (ip->type == RT_CONTIGIOUS) {
-		    if ((virt >= (caddr_t)ip->fc_contig_virt) && ((virt + len)
-			<= ((caddr_t)ip->fc_contig_virt + ip->fc_contig_len)))
-				break;
-		}
-	}
-	fc_unlock_resource_list(rp);
-
-	if (ip == NULL) {
-		return (fc_priv_error(cp, "request not within a "
-		    "known mapping or contigious adddress"));
-	}
-
-	switch (len) {
-	case sizeof (x):
-		if (ip->type == RT_MAP)
-		    error = ddi_peek64(rp->child,
-			(int64_t *)virt, (int64_t *)&x);
-		else /* RT_CONTIGIOUS */
-		    x = *(int64_t *)virt;
-		break;
-	case sizeof (l):
-		if (ip->type == RT_MAP)
-		    error = ddi_peek32(rp->child,
-			(int32_t *)virt, (int32_t *)&l);
-		else /* RT_CONTIGIOUS */
-		    l = *(int32_t *)virt;
-		break;
-	case sizeof (w):
-		if (ip->type == RT_MAP)
-		    error = ddi_peek16(rp->child,
-			(int16_t *)virt, (int16_t *)&w);
-		else /* RT_CONTIGIOUS */
-		    w = *(int16_t *)virt;
-		break;
-	case sizeof (b):
-		if (ip->type == RT_MAP)
-		    error = ddi_peek8(rp->child,
-			(int8_t *)virt, (int8_t *)&b);
-		else /* RT_CONTIGIOUS */
-		    b = *(int8_t *)virt;
-		break;
-	}
-
-	if (error) {
-		FC_DEBUG2(1, CE_CONT, "gfc_register_fetch: access error "
-		    "accessing virt %p len %d\n", virt, len);
-		return (fc_priv_error(cp, "access error"));
-	}
-
-	cp->nresults = fc_int2cell(1);
-	switch (len) {
-	case sizeof (x): fc_result(cp, 0) = x; break;
-	case sizeof (l): fc_result(cp, 0) = fc_uint32_t2cell(l); break;
-	case sizeof (w): fc_result(cp, 0) = fc_uint16_t2cell(w); break;
-	case sizeof (b): fc_result(cp, 0) = fc_uint8_t2cell(b); break;
-	}
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gfc_register_store(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	size_t len;
-	caddr_t virt;
-	uint64_t x;
-	uint32_t l;
-	uint16_t w;
-	uint8_t b;
-	char *name = fc_cell2ptr(cp->svc_name);
-	struct fc_resource *ip;
-	int error = 0;
-
-	if (fc_cell2int(cp->nargs) != 2)
-		return (fc_syntax_error(cp, "nargs must be 2"));
-
-	virt = fc_cell2ptr(fc_arg(cp, 0));
-
-	/*
-	 * Determine the access width .. we can switch on the 2nd
-	 * character of the name which is "rx!", "rl!", "rb!" or "rw!"
-	 */
-	switch (*(name + 1)) {
-	case 'x': len = sizeof (x); x = fc_arg(cp, 1); break;
-	case 'l': len = sizeof (l); l = fc_cell2uint32_t(fc_arg(cp, 1)); break;
-	case 'w': len = sizeof (w); w = fc_cell2uint16_t(fc_arg(cp, 1)); break;
-	case 'b': len = sizeof (b); b = fc_cell2uint8_t(fc_arg(cp, 1)); break;
-	}
-
-	/*
-	 * Check the alignment ...
-	 */
-	if (((intptr_t)virt & (len - 1)) != 0)
-		return (fc_priv_error(cp, "unaligned access"));
-
-	/*
-	 * Find if this virt is 'within' a request we know about
-	 */
-	fc_lock_resource_list(rp);
-	for (ip = rp->head; ip != NULL; ip = ip->next) {
-		if (ip->type == RT_MAP) {
-		    if ((virt >= (caddr_t)ip->fc_map_virt) && ((virt + len) <=
-			((caddr_t)ip->fc_map_virt + ip->fc_map_len)))
-				break;
-		} else if (ip->type == RT_CONTIGIOUS) {
-		    if ((virt >= (caddr_t)ip->fc_contig_virt) && ((virt + len)
-			<= ((caddr_t)ip->fc_contig_virt + ip->fc_contig_len)))
-				break;
-		}
-	}
-	fc_unlock_resource_list(rp);
-
-	if (ip == NULL)
-		return (fc_priv_error(cp, "request not within a "
-		    "known mapping or contigious address"));
-
-	switch (len) {
-	case sizeof (x):
-		if (ip->type == RT_MAP)
-			error = ddi_poke64(rp->child, (int64_t *)virt, x);
-		else if (ip->type == RT_CONTIGIOUS)
-			*(uint64_t *)virt = x;
-		break;
-	case sizeof (l):
-		if (ip->type == RT_MAP)
-			error = ddi_poke32(rp->child, (int32_t *)virt, l);
-		else if (ip->type == RT_CONTIGIOUS)
-			*(uint32_t *)virt = l;
-		break;
-	case sizeof (w):
-		if (ip->type == RT_MAP)
-			error = ddi_poke16(rp->child, (int16_t *)virt, w);
-		else if (ip->type == RT_CONTIGIOUS)
-			*(uint16_t *)virt = w;
-		break;
-	case sizeof (b):
-		if (ip->type == RT_MAP)
-			error = ddi_poke8(rp->child, (int8_t *)virt, b);
-		else if (ip->type == RT_CONTIGIOUS)
-			*(uint8_t *)virt = b;
-		break;
-	}
-
-	if (error == DDI_FAILURE) {
-		FC_DEBUG2(1, CE_CONT, "gfc_register_store: access error "
-		    "accessing virt %p len %d\n", virt, len);
-		return (fc_priv_error(cp, "access error"));
-	}
-
-	cp->nresults = fc_int2cell(0);
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gfc_master_intr(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	int xt, portid;
-
-	if (fc_cell2int(cp->nargs) != 2)
-		return (fc_syntax_error(cp, "nargs must be 4"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	xt = fc_cell2int(fc_arg(cp, 1));
-	portid = fc_cell2int(fc_arg(cp, 0));
-
-	FC_DEBUG2(1, CE_CONT, "gfc_master_intr: reset-int-xt=%x portid=%x",
-	    xt, portid);
-
-	cp->nresults = fc_int2cell(1);
-	fc_result(cp, 0) = 0;
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-/*
- * gfc_claim_address
- *
- * claim-address (size.lo size.hi type align bar portid -- base.lo base.hi )
- */
-static int
-gfc_claim_address(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	int bar, portid;
-	uint64_t exp, slot, port, slice;
-	uint64_t paddr;
-
-	if (fc_cell2int(cp->nargs) != 6)
-		return (fc_syntax_error(cp, "nargs must be 6"));
-
-	if (fc_cell2int(cp->nresults) < 2)
-		return (fc_syntax_error(cp, "nresults must be 2"));
-
-	bar = fc_cell2int(fc_arg(cp, 1));
-	portid = fc_cell2int(fc_arg(cp, 0));
-
-	exp = portid >> 5;
-	slot = (0x8 & portid) >> 3;
-	port = portid & 0x1;
-
-	switch (bar) {
-	case 0: /* PCI IO Bus A */
-		paddr = (exp << 28) | (port << 26) | (slot << 27) |
-		    ((uint64_t)0x402 << 32);
-
-		break;
-	case 1: /* PCI Memory Bus A */
-		slice = (exp * 2) + slot + 1;
-
-		paddr = ((uint64_t)1 << 42) | ((uint64_t)slice << 34) |
-		    ((uint64_t)port << 33);
-
-		break;
-	case 2: /* PCI IO Bus B */
-		paddr = (exp << 28) | (port << 26) | (slot << 27) |
-		    ((uint64_t)0x402 << 32)  | (1 << 25);
-
-		break;
-	case 3: /* PCI Memory Bus B */
-		slice = (exp * 2) + slot + 1;
-
-		paddr = ((uint64_t)1 << 42) | ((uint64_t)slice << 34) |
-		    ((uint64_t)port << 33);
-
-		paddr |= ((uint64_t)1 << 32);
-
-		break;
-	default:
-		cmn_err(CE_WARN,
-		    "gfc_claim_address - invalid BAR=0x%x\n", bar);
-
-		return (fc_syntax_error(cp, "invalid argument"));
-	}
-
-	FC_DEBUG1(1, CE_CONT, "gfc_claim_address: returning 0x%lx\n", paddr);
-
-	cp->nresults = fc_int2cell(2);
-	fc_result(cp, 0) = LOADDR(paddr);
-	fc_result(cp, 1) = HIADDR(paddr);
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-/*
- * gfc_claim_memory
- *
- * claim-memory ( align size vhint -- vaddr)
- */
-static int
-gfc_claim_memory(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	int align, size, vhint;
-	ndi_ra_request_t request;
-	uint64_t answer, alen;
-	struct fc_resource *ip;
-
-	if (fc_cell2int(cp->nargs) != 3)
-		return (fc_syntax_error(cp, "nargs must be 3"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	vhint = fc_cell2int(fc_arg(cp, 2));
-	size = fc_cell2int(fc_arg(cp, 1));
-	align = fc_cell2int(fc_arg(cp, 0));
-
-	FC_DEBUG3(1, CE_CONT, "gfc_claim_memory: align=0x%x size=0x%x "
-	    "vhint=0x%x\n", align, size, vhint);
-
-	if (size == 0) {
-		cmn_err(CE_WARN, " gfc_claim_memory - unable to allocate "
-		    "contigiuos memory of size zero\n");
-		return (fc_priv_error(cp, "allocation error"));
-	}
-
-	if (vhint) {
-		cmn_err(CE_WARN, "gfc_claim_memory - vhint is not zero "
-		    "vhint=0x%x - Ignoring Argument\n", vhint);
-	}
-
-	bzero((caddr_t)&request, sizeof (ndi_ra_request_t));
-	request.ra_flags  = NDI_RA_ALLOC_BOUNDED;
-	request.ra_boundbase = 0;
-	request.ra_boundlen = 0xffffffff;
-	request.ra_len = size;
-	request.ra_align_mask = align - 1;
-
-	if (ndi_ra_alloc(ddi_root_node(), &request, &answer, &alen,
-	    "gptwo-contigousmem", NDI_RA_PASS) != NDI_SUCCESS) {
-		cmn_err(CE_WARN, " gfc_claim_memory - unable to allocate "
-		    "contigiuos memory\n");
-		return (fc_priv_error(cp, "allocation error"));
-
-	}
-
-	FC_DEBUG2(1, CE_CONT, "gfc_claim_memory: address allocated=0x%lx "
-	    "size=0x%x\n", answer, alen);
-
-	cp->nresults = fc_int2cell(1);
-	fc_result(cp, 0) = answer;
-
-	/*
-	 * Log this resource ...
-	 */
-	ip = kmem_zalloc(sizeof (struct fc_resource), KM_SLEEP);
-	ip->type = RT_CONTIGIOUS;
-	ip->fc_contig_virt = (void *)answer;
-	ip->fc_contig_len = size;
-	fc_add_resource(rp, ip);
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-/*
- * gfc_release_memory
- *
- * release-memory ( size vaddr -- )
- */
-static int
-gfc_release_memory(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	int32_t vaddr, size;
-	struct fc_resource *ip;
-
-	if (fc_cell2int(cp->nargs) != 2)
-		return (fc_syntax_error(cp, "nargs must be 2"));
-
-	if (fc_cell2int(cp->nresults) != 0)
-		return (fc_syntax_error(cp, "nresults must be 0"));
-
-	vaddr = fc_cell2int(fc_arg(cp, 1));
-	size = fc_cell2int(fc_arg(cp, 0));
-
-	FC_DEBUG2(1, CE_CONT, "gfc_release_memory: vaddr=0x%x size=0x%x\n",
-	    vaddr, size);
-	/*
-	 * Find if this request matches a mapping resource we set up.
-	 */
-	fc_lock_resource_list(rp);
-	for (ip = rp->head; ip != NULL; ip = ip->next) {
-		if (ip->type != RT_CONTIGIOUS)
-			continue;
-		if (ip->fc_contig_virt != (void *)(uintptr_t)vaddr)
-			continue;
-		if (ip->fc_contig_len == size)
-			break;
-	}
-	fc_unlock_resource_list(rp);
-
-	if (ip == NULL)
-		return (fc_priv_error(cp, "request doesn't match a "
-		    "known mapping"));
-
-	(void) ndi_ra_free(ddi_root_node(), vaddr, size,
-	    "gptwo-contigousmem", NDI_RA_PASS);
-
-	/*
-	 * remove the resource from the list and release it.
-	 */
-	fc_rem_resource(rp, ip);
-	kmem_free(ip, sizeof (struct fc_resource));
-
-	cp->nresults = fc_int2cell(0);
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-/*
- * gfc_vtop
- *
- * vtop ( vaddr -- paddr.lo paddr.hi)
- */
-static int
-gfc_vtop(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	int vaddr;
-	uint64_t paddr;
-	struct fc_resource *ip;
-
-	if (fc_cell2int(cp->nargs) != 1)
-		return (fc_syntax_error(cp, "nargs must be 1"));
-
-	if (fc_cell2int(cp->nresults) >= 3)
-		return (fc_syntax_error(cp, "nresults must be less than 2"));
-
-	vaddr = fc_cell2int(fc_arg(cp, 0));
-
-	/*
-	 * Find if this request matches a mapping resource we set up.
-	 */
-	fc_lock_resource_list(rp);
-	for (ip = rp->head; ip != NULL; ip = ip->next) {
-		if (ip->type != RT_CONTIGIOUS)
-			continue;
-		if (ip->fc_contig_virt == (void *)(uintptr_t)vaddr)
-				break;
-	}
-	fc_unlock_resource_list(rp);
-
-	if (ip == NULL)
-		return (fc_priv_error(cp, "request doesn't match a "
-		    "known mapping"));
-
-
-	paddr = va_to_pa((void *)(uintptr_t)vaddr);
-
-	FC_DEBUG2(1, CE_CONT, "gfc_vtop: vaddr=0x%x paddr=0x%x\n",
-	    vaddr, paddr);
-
-	cp->nresults = fc_int2cell(2);
-
-	fc_result(cp, 0) = paddr;
-	fc_result(cp, 1) = 0;
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gfc_config_child(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	fc_phandle_t h;
-
-	if (fc_cell2int(cp->nargs) != 0)
-		return (fc_syntax_error(cp, "nargs must be 0"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	h = fc_dip_to_phandle(fc_handle_to_phandle_head(rp), rp->child);
-
-	cp->nresults = fc_int2cell(1);
-	fc_result(cp, 0) = fc_phandle2cell(h);
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gfc_get_fcode(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	caddr_t name_virt, fcode_virt;
-	char *name, *fcode;
-	int fcode_len, status;
-
-	if (fc_cell2int(cp->nargs) != 3)
-		return (fc_syntax_error(cp, "nargs must be 3"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	name_virt = fc_cell2ptr(fc_arg(cp, 0));
-
-	fcode_virt = fc_cell2ptr(fc_arg(cp, 1));
-
-	fcode_len = fc_cell2int(fc_arg(cp, 2));
-
-	name = kmem_zalloc(FC_SVC_NAME_LEN, KM_SLEEP);
-
-	if (copyinstr(fc_cell2ptr(name_virt), name,
-	    FC_SVC_NAME_LEN - 1, NULL))  {
-		FC_DEBUG1(1, CE_CONT, "gfc_get_fcode: "
-		    "fault copying in drop in name %p\n", name_virt);
-		status = 0;
-	} else {
-
-		fcode = kmem_zalloc(fcode_len, KM_SLEEP);
-
-		if ((status = prom_get_fcode(name, fcode)) != 0) {
-
-			if (copyout((void *)fcode, (void *)fcode_virt,
-			    fcode_len)) {
-				cmn_err(CE_WARN, " gfc_get_fcode: Unable "
-				    "to copy out fcode image\n");
-				status = 0;
-			}
-		}
-
-		kmem_free(fcode, fcode_len);
-	}
-
-	kmem_free(name, FC_SVC_NAME_LEN);
-
-	cp->nresults = fc_int2cell(1);
-	fc_result(cp, 0) = status;
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gfc_get_fcode_size(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp)
-{
-	caddr_t virt;
-	char *name;
-	int len;
-
-	if (fc_cell2int(cp->nargs) != 1)
-		return (fc_syntax_error(cp, "nargs must be 1"));
-
-	if (fc_cell2int(cp->nresults) < 1)
-		return (fc_syntax_error(cp, "nresults must be >= 1"));
-
-	virt = fc_cell2ptr(fc_arg(cp, 0));
-
-	name = kmem_zalloc(FC_SVC_NAME_LEN, KM_SLEEP);
-
-	if (copyinstr(fc_cell2ptr(virt), name,
-	    FC_SVC_NAME_LEN - 1, NULL))  {
-		FC_DEBUG1(1, CE_CONT, "gfc_get_fcode_size: "
-		    "fault copying in drop in name %p\n", virt);
-		len = 0;
-	} else {
-
-		len = prom_get_fcode_size(name);
-	}
-
-	kmem_free(name, FC_SVC_NAME_LEN);
-
-	cp->nresults = fc_int2cell(1);
-	fc_result(cp, 0) = len;
-
-	return (fc_success_op(ap, rp, cp));
-}
-
-static int
-gp2_map_phys(dev_info_t *dip, struct regspec *phys_spec,
-	caddr_t *addrp, ddi_device_acc_attr_t *accattrp,
-	ddi_acc_handle_t *handlep)
-{
-	ddi_map_req_t mr;
-	ddi_acc_hdl_t *hp;
-	int result;
-	struct regspec *ph;
-
-	*handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL);
-	hp = impl_acc_hdl_get(*handlep);
-	hp->ah_vers = VERS_ACCHDL;
-	hp->ah_dip = dip;
-	hp->ah_rnumber = 0;
-	hp->ah_offset = 0;
-	hp->ah_len = 0;
-	hp->ah_acc = *accattrp;
-	ph = kmem_zalloc(sizeof (struct regspec), KM_SLEEP);
-	*ph = *phys_spec;
-	hp->ah_bus_private = ph;	/* cache a copy of the reg spec */
-
-	mr.map_op = DDI_MO_MAP_LOCKED;
-	mr.map_type = DDI_MT_REGSPEC;
-	mr.map_obj.rp = (struct regspec *)phys_spec;
-	mr.map_prot = PROT_READ | PROT_WRITE;
-	mr.map_flags = DDI_MF_KERNEL_MAPPING;
-	mr.map_handlep = hp;
-	mr.map_vers = DDI_MAP_VERSION;
-
-	result = ddi_map(dip, &mr, 0, 0, addrp);
-
-	if (result != DDI_SUCCESS) {
-		impl_acc_hdl_free(*handlep);
-		*handlep = (ddi_acc_handle_t)NULL;
-	} else {
-		hp->ah_addr = *addrp;
-	}
-
-	return (result);
-}
-
-static void
-gp2_unmap_phys(ddi_acc_handle_t *handlep)
-{
-	ddi_map_req_t mr;
-	ddi_acc_hdl_t *hp;
-	struct regspec_t *ph;
-
-	hp = impl_acc_hdl_get(*handlep);
-	ASSERT(hp);
-	ph = hp->ah_bus_private;
-
-	mr.map_op = DDI_MO_UNMAP;
-	mr.map_type = DDI_MT_REGSPEC;
-	mr.map_obj.rp = (struct regspec *)ph;
-	mr.map_prot = PROT_READ | PROT_WRITE;
-	mr.map_flags = DDI_MF_KERNEL_MAPPING;
-	mr.map_handlep = hp;
-	mr.map_vers = DDI_MAP_VERSION;
-
-	(void) ddi_map(hp->ah_dip, &mr, hp->ah_offset,
-		hp->ah_len, &hp->ah_addr);
-
-	impl_acc_hdl_free(*handlep);
-	kmem_free(ph, sizeof (struct regspec));	/* Free the cached copy */
-	*handlep = (ddi_acc_handle_t)NULL;
-}
--- a/usr/src/uts/sun4u/starcat/io/gptwo_pci.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,492 +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.
- */
-
-/*
- * Schizo/PCI Functions to the Safari Configurator
- *
- */
-
-#include <sys/types.h>
-#include <sys/cred.h>
-#include <sys/mman.h>
-#include <sys/kmem.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/modctl.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/autoconf.h>
-#include <sys/ksynch.h>
-#include <sys/promif.h>
-#include <sys/ndi_impldefs.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/machsystm.h>
-#include <sys/gp2cfg.h>
-#include <sys/gptwo_pci.h>
-
-#ifdef DEBUG
-int gptwo_pci_debug = 0;
-
-static void debug(char *, uintptr_t, uintptr_t,
-    uintptr_t, uintptr_t, uintptr_t);
-
-#define	GPTWO_DEBUG0(level, flag, s) if (gptwo_pci_debug >= level) \
-    cmn_err(flag, s)
-#define	GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwo_pci_debug >= level) \
-    debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
-#define	GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwo_pci_debug >= level) \
-    debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
-#define	GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \
-    if (gptwo_pci_debug >= level) \
-    debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0);
-#else
-#define	GPTWO_DEBUG0(level, flag, s)
-#define	GPTWO_DEBUG1(level, flag, fmt, a1)
-#define	GPTWO_DEBUG2(level, flag, fmt, a1, a2)
-#define	GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3)
-#endif
-
-void gptwocfg_devi_attach_to_parent(dev_info_t *);
-static char *gptwo_get_probe_string(spcd_t *, int);
-static void gptwo_find_nodes(dev_info_t *, int, gptwo_new_nodes_t *);
-
-extern caddr_t efcode_vaddr;
-extern int efcode_size;
-
-/*
- * Module linkage information for the kernel.
- */
-
-extern struct mod_ops mod_miscops;
-
-static struct modlmisc modlmisc = {
-	&mod_miscops, /* Type of module */
-	"gptwo->pci configurator",
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1, (void *)&modlmisc, NULL
-};
-
-int
-_init(void)
-{
-	int err = 0;
-
-	/*
-	 * Create a resource map for the contigous memory allocated
-	 * at start-of-day in startup.c
-	 */
-	if (ndi_ra_map_setup(ddi_root_node(), "gptwo-contigousmem")
-	    == NDI_FAILURE) {
-		GPTWO_DEBUG0(1, CE_WARN,
-		    "Can not setup resource map - gptwo-contigousmem\n");
-		return (1);
-	}
-
-	/*
-	 * Put the allocated memory into the pool.
-	 */
-	(void) ndi_ra_free(ddi_root_node(), (uint64_t)efcode_vaddr,
-	    (uint64_t)efcode_size, "gptwo-contigousmem", 0);
-
-	/* register devices with the configurator */
-	gptwocfg_register_ops(SAFPTYPE_sPCI, gptwo_configure_pci,
-	    gptwo_unconfigure_pci);
-	gptwocfg_register_ops(SAFPTYPE_cPCI, gptwo_configure_pci,
-	    gptwo_unconfigure_pci);
-	gptwocfg_register_ops(SAFPTYPE_PCIX, gptwo_configure_pci,
-	    gptwo_unconfigure_pci);
-
-	if ((err = mod_install(&modlinkage)) != 0) {
-		GPTWO_DEBUG1(1, CE_WARN, "gptwo_pci (PCI Functions) "
-		"failed to load, error=%d\n", err);
-		gptwocfg_unregister_ops(SAFPTYPE_sPCI);
-		gptwocfg_unregister_ops(SAFPTYPE_cPCI);
-		gptwocfg_unregister_ops(SAFPTYPE_PCIX);
-	} else {
-		GPTWO_DEBUG0(1, CE_WARN, "gptwo_pci (PCI Functions) "
-		"has been loaded.\n");
-	}
-	return (err);
-}
-
-int
-_fini(void)
-{
-	gptwocfg_unregister_ops(SAFPTYPE_sPCI);
-	gptwocfg_unregister_ops(SAFPTYPE_cPCI);
-	gptwocfg_unregister_ops(SAFPTYPE_PCIX);
-	return (mod_remove(&modlinkage));
-}
-
-int
-_info(modinfop)
-struct modinfo *modinfop;
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-/*ARGSUSED*/
-static int
-set_name_prop(dev_info_t *dip, void *arg, uint_t flags)
-{
-	if (ndi_prop_update_string(DDI_DEV_T_NONE, dip,
-	    "name", "pci") != DDI_SUCCESS) {
-		return (DDI_WALK_ERROR);
-	}
-
-	return (DDI_WALK_TERMINATE);
-}
-
-/*ARGSUSED*/
-static void
-get_new_child(dev_info_t *rdip, void *arg, uint_t flags)
-{
-	dev_info_t **dipp = (dev_info_t **)arg;
-
-	ASSERT(dipp && (*dipp == NULL));
-
-	*dipp = rdip;
-}
-
-gptwo_new_nodes_t *
-gptwo_configure_pci(dev_info_t *ap, spcd_t *pcd, uint_t id)
-{
-	fco_handle_t fco_handle;
-	int error, i, circ, freq;
-	dev_info_t *new_child;
-	char unit_address[64];
-	gptwo_new_nodes_t *new_nodes;
-	char *probe_string;
-	devi_branch_t b = {0};
-
-	GPTWO_DEBUG2(1, CE_CONT, "gptwo_configure_pci: id=%x pcd=%lx\n",
-	    id, pcd);
-
-	new_nodes = gptwocfg_allocate_node_list(IOBUS_PER_PORT);
-
-	i = IOBUS_PER_PORT;
-
-	while (i) {
-		i--;
-
-		if (pcd->spcd_iobus_rsv[i] != SPCD_RSV_PASS) {
-
-			cmn_err(CE_WARN, "gptwo_configure_pci: saf id=0x%x "
-			    "leaf %d - Can not be probed\n", id, i);
-
-			continue;
-		}
-
-		/*
-		 * Ideally, fcode would be run from the "sid_branch_create"
-		 * callback (that is the primary purpose of that callback).
-		 * However, the fcode interpreter was written with the
-		 * assumption that the "new_child" was linked into the
-		 * device tree. The callback is invoked with the devinfo node
-		 * in the DS_PROTO state. More investigation is needed before
-		 * we can invoke the interpreter from the callback. For now,
-		 * we create the "new_child" in the BOUND state, invoke the
-		 * fcode interpreter and then rebind the dip to use any
-		 * compatible properties created by fcode.
-		 */
-
-		new_child = NULL;
-
-		b.arg = &new_child;
-		b.type = DEVI_BRANCH_SID;
-		b.create.sid_branch_create = set_name_prop;
-		b.devi_branch_callback = get_new_child;
-
-		/*
-		 * Prevent any changes to new_child
-		 * until we have bound it to the correct driver.
-		 */
-		ndi_devi_enter(ap, &circ);
-		if (e_ddi_branch_create(ap, &b, NULL, 0)) {
-			ASSERT(new_child == NULL);
-
-			if (new_nodes->gptwo_nodes[0] == NULL) {
-				GPTWO_DEBUG0(1, CE_CONT, "gptwo_configure_pci: "
-				    "No nodes configured - "
-				    "removing new_nodes\n");
-				gptwocfg_free_node_list(new_nodes);
-				new_nodes = NULL;
-			}
-
-			ndi_devi_exit(ap, circ);
-
-			return (new_nodes);
-		}
-
-		/*
-		 * The platform DR interfaces created the dip in
-		 * bound state. Bring devinfo node down to linked
-		 * state and hold it there until compatible
-		 * properties are created.
-		 */
-		e_ddi_branch_rele(new_child);
-		(void) i_ndi_unconfig_node(new_child, DS_LINKED, 0);
-		ASSERT(i_ddi_node_state(new_child) == DS_LINKED);
-		e_ddi_branch_hold(new_child);
-
-		mutex_enter(&DEVI(new_child)->devi_lock);
-		DEVI(new_child)->devi_flags |= DEVI_NO_BIND;
-		mutex_exit(&DEVI(new_child)->devi_lock);
-
-		/*
-		 * Drop the busy-hold on parent before calling
-		 * fcode_interpreter to prevent potential deadlocks
-		 */
-		ndi_devi_exit(ap, circ);
-
-		(void) sprintf(unit_address, "%x", id);
-
-		/*
-		 * Build the probe string from the PCD that will be passed
-		 * in to the interpreter as my-args.  This will tell the
-		 * fcode what pci devices to probe after the pci node has
-		 * been probed.
-		 */
-		probe_string = gptwo_get_probe_string(pcd, i);
-
-		GPTWO_DEBUG3(1, CE_CONT, "gptwo_configure_pci: args to "
-		    "interpreter ap=%lx new_child=%lx unit_address=%s\n",
-		    ap, new_child, unit_address);
-
-		if (probe_string)
-			GPTWO_DEBUG1(1, CE_CONT, "gptwo_configure_pci: "
-			    "probe string=%s\n", probe_string);
-
-		fco_handle = gp2_fc_ops_alloc_handle(ap, new_child, NULL, NULL,
-		    unit_address, probe_string);
-
-		GPTWO_DEBUG0(1, CE_CONT,
-		    "gptwocfg: Calling Fcode Interpeter...\n");
-
-		error = fcode_interpreter(ap, &gp2_fc_ops, fco_handle);
-
-		GPTWO_DEBUG1(1, CE_CONT,
-		    "gptwo_configure_pci: fcode_interpreter "
-		    " returned %x\n", error);
-
-		if (error) {
-			cmn_err(CE_WARN, "gptwo_pci: Unable to probe pci leaf "
-			    "%s\n", unit_address);
-
-			gp2_fc_ops_free_handle(fco_handle);
-
-			(void) e_ddi_branch_destroy(new_child, NULL, 0);
-		} else {
-			gptwocfg_save_handle(new_child, fco_handle);
-
-			/*
-			 * Compatible properties (if any) have been created,
-			 * so bind driver.
-			 */
-			ndi_devi_enter(ap, &circ);
-			ASSERT(i_ddi_node_state(new_child) <= DS_LINKED);
-
-			mutex_enter(&DEVI(new_child)->devi_lock);
-			DEVI(new_child)->devi_flags &= ~DEVI_NO_BIND;
-			mutex_exit(&DEVI(new_child)->devi_lock);
-
-			ndi_devi_exit(ap, circ);
-
-			if (ndi_devi_bind_driver(new_child, 0) !=
-			    DDI_SUCCESS) {
-				cmn_err(CE_WARN, "gptwo_pci: Unable to bind"
-				    " new pci child at dip=0x%p\n",
-				    (void *)new_child);
-			}
-
-			/*
-			 * If POST provided a frequency, the clock-frequency
-			 * property needs to be updated.
-			 */
-			if (pcd->spcd_afreq) {
-
-				/*
-				 * The upper byte is for leaf B and the lower
-				 * byte is for leaf A.
-				 */
-				if (i)
-					freq = pcd->spcd_afreq >> 8;
-				else
-					freq = pcd->spcd_afreq & 0x00ff;
-
-				(void) ndi_prop_update_int(DDI_DEV_T_NONE,
-				    new_child, "clock-frequency",
-				    (freq * 1000 * 1000));
-			}
-		}
-	}
-
-	gptwo_find_nodes(ap, id, new_nodes);
-
-	if (new_nodes->gptwo_nodes[0] == NULL) {
-		GPTWO_DEBUG0(1, CE_CONT, "gptwo_configure_pci: "
-		    "No nodes configured - removing new_nodes\n");
-		gptwocfg_free_node_list(new_nodes);
-		new_nodes = NULL;
-	}
-
-	GPTWO_DEBUG1(1, CE_CONT, "gptwo_configure_pci: "
-	    "Returning new_nodes=%p\n", new_nodes);
-
-	return (new_nodes);
-}
-
-dev_info_t *
-gptwo_unconfigure_pci(dev_info_t *dip)
-{
-	fco_handle_t fco_handle;
-
-	fco_handle = gptwocfg_get_handle(dip);
-
-	if (fco_handle != NULL) {
-		/*
-		 * If there is a handle, there may be resources
-		 * that need to be freed from when the
-		 * devices's fcode ran.
-		 */
-		GPTWO_DEBUG1(1, CE_CONT, "fco_handle=%lx\n", fco_handle);
-		gp2_fc_ops_free_handle(fco_handle);
-	}
-	return (NULL);
-}
-
-static void
-gptwo_find_nodes(dev_info_t *ap, int id, gptwo_new_nodes_t *new_nodes)
-{
-	dev_info_t *saf_dev;
-	int found, j, circ;
-	int i = 0;
-
-	GPTWO_DEBUG1(1, CE_CONT, "gptwo_find_nodes - id=%x\n", id);
-
-	/*
-	 * We are walking child list of ap, so hold it busy
-	 */
-	ndi_devi_enter(ap, &circ);
-
-	saf_dev = ddi_get_child(ap);
-	while (saf_dev != NULL) {
-		if (ddi_getprop(DDI_DEV_T_ANY, saf_dev,
-		    DDI_PROP_DONTPASS, "portid", -1) == id) {
-			if (i < IOBUS_PER_PORT) {
-
-				GPTWO_DEBUG2(1, CE_CONT,
-				    "gptwo_find_nodes - "
-				    "Found %d %p\n", i, saf_dev);
-
-				found = 0;
-				for (j = 0; j < IOBUS_PER_PORT; j++) {
-					if (new_nodes->gptwo_nodes[j] ==
-					    saf_dev) {
-						found = 1;
-					}
-				}
-				if (!found) {
-					/*
-					 * Branch rooted at saf-dev was
-					 * held earlier.
-					 */
-					ASSERT(e_ddi_branch_held(saf_dev));
-					new_nodes->gptwo_nodes[i] = saf_dev;
-					i++;
-				}
-			} else {
-				GPTWO_DEBUG0(1, CE_CONT,
-				    "gptwo_find_nodes - "
-				    "No room in new_nodes\n");
-			}
-		}
-		saf_dev = ddi_get_next_sibling(saf_dev);
-	}
-
-	ndi_devi_exit(ap, circ);
-}
-
-static char *
-gptwo_get_probe_string(spcd_t *pcd, int bus_number)
-{
-	int i, str_size;
-	char temp[64];
-	char num[8];
-	char *probe;
-
-	GPTWO_DEBUG2(1, CE_CONT, "gptwo_get_probe_string - %p %x\n", pcd,
-	    bus_number);
-
-	temp[0] = NULL;
-
-	for (i = 0; i < IOCARD_PER_BUS; i++) {
-
-		GPTWO_DEBUG2(1, CE_CONT, "gptwo_get_probe_string - "
-		    "card status %x %x\n",
-		    i, pcd->spcd_iocard_rsv[bus_number][i]);
-
-		if (pcd->spcd_iocard_rsv[bus_number][i] == SPCD_RSV_PASS) {
-			numtos(i, num);
-			if (temp[0] == NULL)
-				(void) sprintf(temp, "%s", num);
-			else
-				(void) sprintf(temp, "%s,%s", temp, num);
-		}
-	}
-
-	if (bus_number == 0)
-		(void) sprintf(temp, "%sa", temp); /* Append a 'a' for leaf A */
-	else
-		(void) sprintf(temp, "%sb", temp); /* Append a 'b' for leaf B */
-
-	str_size = strlen(temp);
-
-	if (str_size == 0)
-		return (NULL);
-
-	probe = kmem_zalloc(str_size + 1, KM_SLEEP);
-
-	(void) strcpy(probe, temp);
-
-	GPTWO_DEBUG1(1, CE_CONT, "gptwo_get_probe_string - Returning %s\n",
-	    probe);
-
-	return (probe);
-}
-
-#ifdef DEBUG
-static void
-debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
-	uintptr_t a4, uintptr_t a5)
-{
-	cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
-}
-#endif
--- a/usr/src/uts/sun4u/starcat/io/iosram.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3532 +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.
- */
-
-/*
- * IOSRAM leaf driver to SBBC nexus driver.  This driver is used
- * by Starcat Domain SW to read/write from/to the IO sram.
- */
-
-#include <sys/types.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/obpdefs.h>
-#include <sys/promif.h>
-#include <sys/prom_plat.h>
-#include <sys/cmn_err.h>
-#include <sys/conf.h>		/* req. by dev_ops flags MTSAFE etc. */
-#include <sys/modctl.h>		/* for modldrv */
-#include <sys/stat.h>		/* ddi_create_minor_node S_IFCHR */
-#include <sys/errno.h>
-#include <sys/kmem.h>
-#include <sys/kstat.h>
-#include <sys/debug.h>
-
-#include <sys/axq.h>
-#include <sys/iosramreg.h>
-#include <sys/iosramio.h>
-#include <sys/iosramvar.h>
-
-
-#if defined(DEBUG)
-int	iosram_debug = 0;
-static void iosram_dprintf(const char *fmt, ...);
-#define	DPRINTF(level, arg)	\
-		{ if (iosram_debug >= level) iosram_dprintf arg; }
-#else	/* !DEBUG */
-#define	DPRINTF(level, arg)
-#endif	/* !DEBUG */
-
-
-/*
- * IOSRAM module global state
- */
-static void	*iosramsoft_statep;	/* IOSRAM state pointer */
-static kmutex_t	iosram_mutex;		/* mutex lock */
-
-static iosram_chunk_t	*chunks = NULL;	/* array of TOC entries */
-static int	nchunks = 0;		/* # of TOC entries */
-static iosram_chunk_t	*iosram_hashtab[IOSRAM_HASHSZ];	/* key hash table */
-
-static kcondvar_t	iosram_tswitch_wait;	/* tunnel switch wait cv */
-static int	iosram_tswitch_wakeup = 0;	/* flag indicationg one or */
-						/* more threads waiting on */
-						/* iosram_tswitch_wait cv */
-static int	iosram_tswitch_active = 0;	/* tunnel switch active flag */
-static int	iosram_tswitch_aborted = 0;	/* tunnel switch abort flag */
-static clock_t	iosram_tswitch_tstamp = 0;	/* lbolt of last tswitch end */
-static kcondvar_t	iosram_rw_wait;		/* read/write wait cv */
-static int	iosram_rw_wakeup = 0;		/* flag indicationg one or */
-						/* more threads waiting on */
-						/* iosram_rw_wait cv */
-static int	iosram_rw_active = 0;		/* # threads accessing IOSRAM */
-#if defined(DEBUG)
-static int	iosram_rw_active_max = 0;
-#endif
-
-static struct iosramsoft *iosram_new_master = NULL;	/* new tunnel target */
-static struct iosramsoft *iosram_master = NULL;		/* master tunnel */
-static struct iosramsoft *iosram_instances = NULL;	/* list of softstates */
-
-static ddi_acc_handle_t	iosram_handle = NULL;	/* master IOSRAM map handle */
-
-static void	(*iosram_hdrchange_handler)() = NULL;
-
-#if IOSRAM_STATS
-static struct	iosram_stat iosram_stats;	/* IOSRAM statistics */
-static void	iosram_print_stats();		/* forward declaration */
-#endif /* IOSRAM_STATS */
-
-
-#if IOSRAM_LOG
-kmutex_t 	iosram_log_mutex;
-int		iosram_log_level = 1;
-int		iosram_log_print = 0;		/* print log when recorded */
-uint32_t	iosram_logseq;
-iosram_log_t	iosram_logbuf[IOSRAM_MAXLOG];
-static void	iosram_print_log(int cnt);	/* forward declaration */
-#endif	/* IOSRAM_LOG */
-
-
-/* driver entry point fn definitions */
-static int 	iosram_open(dev_t *, int, int, cred_t *);
-static int	iosram_close(dev_t, int, int, cred_t *);
-static int	iosram_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
-
-/* configuration entry point fn definitions */
-static int 	iosram_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int	iosram_attach(dev_info_t *, ddi_attach_cmd_t);
-static int	iosram_detach(dev_info_t *, ddi_detach_cmd_t);
-
-
-/* forward declaractions */
-static iosram_chunk_t	*iosram_find_chunk(uint32_t key);
-static void	iosram_set_master(struct iosramsoft *softp);
-static int	iosram_is_chosen(struct iosramsoft *softp);
-static int	iosram_tunnel_capable(struct iosramsoft *softp);
-static int	iosram_read_toc(struct iosramsoft *softp);
-static void	iosram_init_hashtab(void);
-static void	iosram_update_addrs(struct iosramsoft *softp);
-
-static int	iosram_setup_map(struct iosramsoft *softp);
-static void	iosram_remove_map(struct iosramsoft *softp);
-static int	iosram_add_intr(iosramsoft_t *);
-static int	iosram_remove_intr(iosramsoft_t *);
-
-static void	iosram_add_instance(struct iosramsoft *softp);
-static void	iosram_remove_instance(int instance);
-static int	iosram_switch_tunnel(iosramsoft_t *softp);
-static void	iosram_abort_tswitch();
-
-#if defined(DEBUG)
-/* forward declaractions for debugging */
-static int	iosram_get_keys(iosram_toc_entry_t *buf, uint32_t *len);
-static void	iosram_print_cback();
-static void	iosram_print_state(int);
-static void	iosram_print_flags();
-#endif
-
-
-
-/*
- * cb_ops
- */
-static struct cb_ops iosram_cb_ops = {
-	iosram_open,		/* cb_open */
-	iosram_close,		/* cb_close */
-	nodev,			/* cb_strategy */
-	nodev,			/* cb_print */
-	nodev,			/* cb_dump */
-	nodev,			/* cb_read */
-	nodev,			/* cb_write */
-	iosram_ioctl,		/* cb_ioctl */
-	nodev,			/* cb_devmap */
-	nodev,			/* cb_mmap */
-	nodev,			/* cb_segmap */
-	nochpoll,		/* cb_chpoll */
-	ddi_prop_op,		/* cb_prop_op */
-	NULL,			/* cb_stream */
-	(int)(D_NEW | D_MP | D_HOTPLUG)	/* cb_flag */
-};
-
-/*
- * Declare ops vectors for auto configuration.
- */
-struct dev_ops  iosram_ops = {
-	DEVO_REV,		/* devo_rev */
-	0,			/* devo_refcnt */
-	iosram_getinfo,		/* devo_getinfo */
-	nulldev,		/* devo_identify */
-	nulldev,		/* devo_probe */
-	iosram_attach,		/* devo_attach */
-	iosram_detach,		/* devo_detach */
-	nodev,			/* devo_reset */
-	&iosram_cb_ops,		/* devo_cb_ops */
-	(struct bus_ops *)NULL,	/* devo_bus_ops */
-	nulldev,		/* devo_power */
-	ddi_quiesce_not_supported,	/* devo_quiesce */
-};
-
-/*
- * Loadable module support.
- */
-extern struct mod_ops mod_driverops;
-
-static struct modldrv iosrammodldrv = {
-	&mod_driverops,		/* type of module - driver */
-	"IOSRAM Leaf driver",
-	&iosram_ops,
-};
-
-static struct modlinkage iosrammodlinkage = {
-	MODREV_1,
-	&iosrammodldrv,
-	NULL
-};
-
-
-int
-_init(void)
-{
-	int    error;
-	int	i;
-
-	mutex_init(&iosram_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
-	cv_init(&iosram_tswitch_wait, NULL, CV_DRIVER, NULL);
-	cv_init(&iosram_rw_wait, NULL, CV_DRIVER, NULL);
-#if defined(IOSRAM_LOG)
-	mutex_init(&iosram_log_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
-#endif
-
-	DPRINTF(1, ("_init:IOSRAM\n"));
-
-	for (i = 0; i < IOSRAM_HASHSZ; i++) {
-		iosram_hashtab[i] = NULL;
-	}
-
-	if ((error = ddi_soft_state_init(&iosramsoft_statep,
-	    sizeof (struct iosramsoft), 1)) != 0) {
-		goto failed;
-	}
-	if ((error = mod_install(&iosrammodlinkage)) != 0) {
-		ddi_soft_state_fini(&iosramsoft_statep);
-		goto failed;
-	}
-
-	IOSRAMLOG(0, "_init:IOSRAM ... error:%d  statep:%p\n",
-	    error, iosramsoft_statep, NULL, NULL);
-
-	return (error);
-
-failed:
-	cv_destroy(&iosram_tswitch_wait);
-	cv_destroy(&iosram_rw_wait);
-	mutex_destroy(&iosram_mutex);
-#if defined(IOSRAM_LOG)
-	mutex_destroy(&iosram_log_mutex);
-#endif
-	IOSRAMLOG(0, "_init:IOSRAM ... error:%d  statep:%p\n",
-	    error, iosramsoft_statep, NULL, NULL);
-
-	return (error);
-}
-
-
-int
-_fini(void)
-{
-#ifndef DEBUG
-	return (EBUSY);
-#else /* !DEBUG */
-	int    error;
-
-	if ((error = mod_remove(&iosrammodlinkage)) == 0) {
-		ddi_soft_state_fini(&iosramsoft_statep);
-
-		cv_destroy(&iosram_tswitch_wait);
-		cv_destroy(&iosram_rw_wait);
-		mutex_destroy(&iosram_mutex);
-#if defined(IOSRAM_LOG)
-		mutex_destroy(&iosram_log_mutex);
-#endif
-	}
-	DPRINTF(1, ("_fini:IOSRAM  error:%d\n", error));
-
-	return (error);
-#endif /* !DEBUG */
-}
-
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (mod_info(&iosrammodlinkage, modinfop));
-}
-
-
-static int
-iosram_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
-	int	instance;
-	int	propval;
-	int	length;
-	char	name[32];
-	struct	iosramsoft *softp;
-
-	instance = ddi_get_instance(dip);
-
-	DPRINTF(1, ("iosram(%d): attach dip:%p\n", instance, (void *)dip));
-
-	IOSRAMLOG(1, "ATTACH: dip:%p instance %d ... start\n",
-	    dip, instance, NULL, NULL);
-	switch (cmd) {
-	case DDI_ATTACH:
-		break;
-	case DDI_RESUME:
-		if (!(softp = ddi_get_soft_state(iosramsoft_statep,
-		    instance))) {
-			return (DDI_FAILURE);
-		}
-		mutex_enter(&iosram_mutex);
-		mutex_enter(&softp->intr_mutex);
-		if (!softp->suspended) {
-			mutex_exit(&softp->intr_mutex);
-			mutex_exit(&iosram_mutex);
-			return (DDI_FAILURE);
-		}
-		softp->suspended = 0;
-
-		/*
-		 * enable SBBC interrupts if SBBC is mapped in
-		 * restore the value saved during detach
-		 */
-		if (softp->sbbc_region) {
-			ddi_put32(softp->sbbc_handle,
-			    &(softp->sbbc_region->int_enable.reg),
-			    softp->int_enable_sav);
-		}
-
-		/*
-		 * Trigger soft interrupt handler to process any pending
-		 * interrupts.
-		 */
-		if (softp->intr_pending && !softp->intr_busy &&
-		    (softp->softintr_id != NULL)) {
-			ddi_trigger_softintr(softp->softintr_id);
-		}
-
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-
-		return (DDI_SUCCESS);
-
-	default:
-		return (DDI_FAILURE);
-	}
-
-	if (ddi_soft_state_zalloc(iosramsoft_statep, instance) != 0) {
-		return (DDI_FAILURE);
-	}
-
-	if ((softp = ddi_get_soft_state(iosramsoft_statep, instance)) == NULL) {
-			return (DDI_FAILURE);
-	}
-	softp->dip = dip;
-	softp->instance = instance;
-	softp->sbbc_region = NULL;
-
-	/*
-	 * If this instance is not tunnel capable, we don't attach it.
-	 */
-	if (iosram_tunnel_capable(softp) == 0) {
-		DPRINTF(1, ("iosram(%d): not tunnel_capable\n", instance));
-		IOSRAMLOG(1, "ATTACH(%d): not tunnel_capable\n", instance, NULL,
-		    NULL, NULL);
-		goto attach_fail;
-	}
-
-	/*
-	 * Need to create an "interrupt-priorities" property to define the PIL
-	 * to be used with the interrupt service routine.
-	 */
-	if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "interrupt-priorities", &length) == DDI_PROP_NOT_FOUND) {
-		DPRINTF(1, ("iosram(%d): creating interrupt priority property",
-		    instance));
-		propval = IOSRAM_PIL;
-		if (ddi_prop_create(DDI_DEV_T_NONE, dip, 0,
-		    "interrupt-priorities", (caddr_t)&propval, sizeof (propval))
-		    != DDI_PROP_SUCCESS) {
-			cmn_err(CE_WARN,
-			    "iosram_attach: failed to create property");
-			goto attach_fail;
-		}
-	}
-
-	/*
-	 * Get interrupts cookies and initialize per-instance mutexes
-	 */
-	if (ddi_get_iblock_cookie(softp->dip, 0, &softp->real_iblk)
-	    != DDI_SUCCESS) {
-		IOSRAMLOG(1, "ATTACH(%d): cannot get soft intr cookie\n",
-		    instance, NULL, NULL, NULL);
-		goto attach_fail;
-	}
-	mutex_init(&softp->intr_mutex, NULL, MUTEX_DRIVER,
-	    (void *)softp->real_iblk);
-
-	/*
-	 * Add this instance to the iosram_instances list so that it can be used
-	 * for tunnel in future.
-	 */
-	mutex_enter(&iosram_mutex);
-	softp->state = IOSRAM_STATE_INIT;
-	iosram_add_instance(softp);
-
-	/*
-	 * If this is the chosen IOSRAM and there is no master IOSRAM yet, then
-	 * let's set this instance as the master.
-	 */
-	if (iosram_master == NULL && iosram_is_chosen(softp)) {
-		(void) iosram_switch_tunnel(softp);
-
-		/*
-		 * XXX Do we need to panic if unable to setup master IOSRAM?
-		 */
-		if (iosram_master == NULL) {
-			cmn_err(CE_WARN,
-			    "iosram(%d): can't setup master tunnel\n",
-			    instance);
-			softp->state = 0;
-			iosram_remove_instance(softp->instance);
-			mutex_exit(&iosram_mutex);
-			mutex_destroy(&softp->intr_mutex);
-			goto attach_fail;
-		}
-	}
-
-	mutex_exit(&iosram_mutex);
-
-	/*
-	 * Create minor node
-	 */
-	(void) sprintf(name, "iosram%d", instance);
-	if (ddi_create_minor_node(dip, name, S_IFCHR, instance, NULL, NULL) ==
-	    DDI_FAILURE) {
-		/*
-		 * Minor node seems to be needed only for debugging purposes.
-		 * Therefore, there is no need to fail this attach request.
-		 * Simply print a message out.
-		 */
-		cmn_err(CE_NOTE, "!iosram(%d): can't create minor node\n",
-		    instance);
-	}
-	ddi_report_dev(dip);
-
-	DPRINTF(1, ("iosram_attach(%d): success.\n", instance));
-	IOSRAMLOG(1, "ATTACH: dip:%p instance:%d ... success  softp:%p\n",
-	    dip, instance, softp, NULL);
-
-	return (DDI_SUCCESS);
-
-attach_fail:
-	DPRINTF(1, ("iosram_attach(%d):failed.\n", instance));
-	IOSRAMLOG(1, "ATTACH: dip:%p instance:%d ... failed.\n",
-	    dip, instance, NULL, NULL);
-
-	ddi_soft_state_free(iosramsoft_statep, instance);
-	return (DDI_FAILURE);
-}
-
-
-static int
-iosram_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
-	int			instance;
-	struct iosramsoft	*softp;
-
-	instance = ddi_get_instance(dip);
-	if (!(softp = ddi_get_soft_state(iosramsoft_statep, instance))) {
-		return (DDI_FAILURE);
-	}
-
-	IOSRAMLOG(1, "DETACH: dip:%p instance %d softp:%p\n",
-	    dip, instance, softp, NULL);
-
-	switch (cmd) {
-	case DDI_DETACH:
-		break;
-	case DDI_SUSPEND:
-		mutex_enter(&iosram_mutex);
-		mutex_enter(&softp->intr_mutex);
-		if (softp->suspended) {
-			mutex_exit(&softp->intr_mutex);
-			mutex_exit(&iosram_mutex);
-			return (DDI_FAILURE);
-		}
-		softp->suspended = 1;
-		/*
-		 * Disable SBBC interrupts if SBBC is mapped in
-		 */
-		if (softp->sbbc_region) {
-			/* save current interrupt enable register */
-			softp->int_enable_sav = ddi_get32(softp->sbbc_handle,
-			    &(softp->sbbc_region->int_enable.reg));
-			ddi_put32(softp->sbbc_handle,
-			    &(softp->sbbc_region->int_enable.reg), 0x0);
-		}
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		return (DDI_SUCCESS);
-
-	default:
-		return (DDI_FAILURE);
-	}
-
-
-	/*
-	 * Indicate that this instance is being detached so that this instance
-	 * does not become a target for tunnel switch in future.
-	 */
-	mutex_enter(&iosram_mutex);
-	softp->state |= IOSRAM_STATE_DETACH;
-
-	/*
-	 * If this instance is currently the master or the target of the tunnel
-	 * switch, then we need to wait and switch tunnel, if necessary.
-	 */
-	if (iosram_master == softp || (softp->state & IOSRAM_STATE_TSWITCH)) {
-		mutex_exit(&iosram_mutex);
-		(void) iosram_switchfrom(instance);
-		mutex_enter(&iosram_mutex);
-	}
-
-	/*
-	 * If the tunnel switch is in progress and we are the master or target
-	 * of tunnel relocation, then we can't detach this instance right now.
-	 */
-	if (softp->state & IOSRAM_STATE_TSWITCH) {
-		softp->state &= ~IOSRAM_STATE_DETACH;
-		mutex_exit(&iosram_mutex);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * We can't allow master IOSRAM to be detached as we won't be able to
-	 * communicate otherwise.
-	 */
-	if (iosram_master == softp) {
-		softp->state &= ~IOSRAM_STATE_DETACH;
-		mutex_exit(&iosram_mutex);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * Now remove our instance from the iosram_instances list.
-	 */
-	iosram_remove_instance(instance);
-	mutex_exit(&iosram_mutex);
-
-	/*
-	 * Instances should only ever be mapped if they are the master and/or
-	 * participating in a tunnel switch.  Neither should be the case here.
-	 */
-	ASSERT((softp->state & IOSRAM_STATE_MAPPED) == 0);
-
-	/*
-	 * Destroy per-instance mutexes
-	 */
-	mutex_destroy(&softp->intr_mutex);
-
-	ddi_remove_minor_node(dip, NULL);
-
-	/*
-	 * Finally remove our soft state structure
-	 */
-	ddi_soft_state_free(iosramsoft_statep, instance);
-
-	return (DDI_SUCCESS);
-}
-
-
-/* ARGSUSED0 */
-static int
-iosram_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
-		void **result)
-{
-	dev_t			dev = (dev_t)arg;
-	struct iosramsoft	*softp;
-	int			instance, ret;
-
-	instance = getminor(dev);
-
-	IOSRAMLOG(2, "GETINFO: dip:%x instance %d dev:%x infocmd:%x\n",
-	    dip, instance, dev, infocmd);
-
-	switch (infocmd) {
-		case DDI_INFO_DEVT2DEVINFO:
-			softp = ddi_get_soft_state(iosramsoft_statep, instance);
-			if (softp == NULL) {
-				*result = NULL;
-				ret = DDI_FAILURE;
-			} else {
-				*result = softp->dip;
-				ret = DDI_SUCCESS;
-			}
-			break;
-		case DDI_INFO_DEVT2INSTANCE:
-			*result = (void *)(uintptr_t)instance;
-			ret = DDI_SUCCESS;
-			break;
-		default:
-			ret = DDI_FAILURE;
-			break;
-	}
-
-	return (ret);
-}
-
-
-/*ARGSUSED1*/
-static int
-iosram_open(dev_t *dev, int flag, int otype, cred_t *credp)
-{
-	struct iosramsoft	*softp;
-	int			instance;
-
-	instance = getminor(*dev);
-	softp = ddi_get_soft_state(iosramsoft_statep, instance);
-
-	if (softp == NULL) {
-		return (ENXIO);
-	}
-
-	IOSRAMLOG(1, "OPEN: dev:%p otype:%x ... instance:%d softp:%p\n",
-	    *dev, otype, softp->instance, softp);
-
-	return (0);
-}
-
-
-/*ARGSUSED1*/
-static int
-iosram_close(dev_t dev, int flag, int otype, cred_t *credp)
-{
-	struct iosramsoft	*softp;
-	int			instance;
-
-	instance = getminor(dev);
-	softp = ddi_get_soft_state(iosramsoft_statep, instance);
-	if (softp == NULL) {
-		return (ENXIO);
-	}
-
-	IOSRAMLOG(1, "CLOSE: dev:%p otype:%x ... instance:%d softp:%p\n",
-	    dev, otype, softp->instance, softp);
-
-	return (0);
-}
-
-
-int
-iosram_rd(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr)
-{
-	iosram_chunk_t		*chunkp;
-	uint32_t		chunk_len;
-	uint8_t			*iosramp;
-	ddi_acc_handle_t	handle;
-	int			boff;
-	union {
-		uchar_t	cbuf[UINT32SZ];
-		uint32_t  data;
-	} word;
-
-	int			error = 0;
-	uint8_t			*buf = (uint8_t *)dptr;
-
-	/*
-	 * We try to read from the IOSRAM using double word or word access
-	 * provided both "off" and "buf" are (or can be) double word or word
-	 * aligned.  Othewise, we try to align the "off" to a word boundary and
-	 * then try to read data from the IOSRAM using word access, but store it
-	 * into buf buffer using byte access.
-	 *
-	 * If the leading/trailing portion of the IOSRAM data is not word
-	 * aligned, it will always be copied using byte access.
-	 */
-	IOSRAMLOG(1, "RD: key: 0x%x off:%x len:%x buf:%p\n",
-	    key, off, len, buf);
-
-	/*
-	 * Acquire lock and look for the requested chunk.  If it exists, make
-	 * sure the requested read is within the chunk's bounds and no tunnel
-	 * switch is active.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-	chunk_len = (chunkp != NULL) ? chunkp->toc_data.len : 0;
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if (chunkp == NULL) {
-		error = EINVAL;
-	} else if ((off >= chunk_len) || (len > chunk_len) ||
-	    ((off + len) > chunk_len)) {
-		error = EMSGSIZE;
-	} else if (iosram_tswitch_active) {
-		error = EAGAIN;
-	}
-
-	if (error) {
-		mutex_exit(&iosram_mutex);
-		return (error);
-	}
-
-	/*
-	 * Bump reference count to indicate #thread accessing IOSRAM and release
-	 * the lock.
-	 */
-	iosram_rw_active++;
-#if defined(DEBUG)
-	if (iosram_rw_active > iosram_rw_active_max) {
-		iosram_rw_active_max = iosram_rw_active;
-	}
-#endif
-	mutex_exit(&iosram_mutex);
-
-	IOSRAM_STAT(read);
-	IOSRAM_STAT_ADD(bread, len);
-
-	/* Get starting address and map handle */
-	iosramp = chunkp->basep + off;
-	handle = iosram_handle;
-
-	/*
-	 * Align the off to word boundary and then try reading/writing data
-	 * using double word or word access.
-	 */
-	if ((boff = ((uintptr_t)iosramp & (UINT32SZ - 1))) != 0) {
-		int	cnt = UINT32SZ - boff;
-
-		if (cnt > len) {
-			cnt = len;
-		}
-		IOSRAMLOG(2,
-		    "RD: align rep_get8(buf:%p sramp:%p cnt:%x) len:%x\n",
-		    buf, iosramp, cnt, len);
-		ddi_rep_get8(handle, buf, iosramp, cnt, DDI_DEV_AUTOINCR);
-		buf += cnt;
-		iosramp += cnt;
-		len -= cnt;
-	}
-
-	if ((len >= UINT64SZ) &&
-	    ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT64SZ - 1)) == 0)) {
-		/*
-		 * Both source and destination are double word aligned
-		 */
-		int cnt = len/UINT64SZ;
-
-		IOSRAMLOG(2,
-		    "RD: rep_get64(buf:%p sramp:%p cnt:%x) len:%x\n",
-		    buf, iosramp, cnt, len);
-		ddi_rep_get64(handle, (uint64_t *)buf, (uint64_t *)iosramp,
-		    cnt, DDI_DEV_AUTOINCR);
-		iosramp += cnt * UINT64SZ;
-		buf += cnt * UINT64SZ;
-		len -= cnt * UINT64SZ;
-
-		/*
-		 * read remaining data using word and byte access
-		 */
-		if (len >= UINT32SZ) {
-			IOSRAMLOG(2,
-			    "RD: get32(buf:%p sramp:%p) len:%x\n",
-			    buf, iosramp, len, NULL);
-			*(uint32_t *)buf = ddi_get32(handle,
-			    (uint32_t *)iosramp);
-			iosramp += UINT32SZ;
-			buf += UINT32SZ;
-			len -= UINT32SZ;
-		}
-
-		if (len != 0) {
-			ddi_rep_get8(handle, buf, iosramp, len,
-			    DDI_DEV_AUTOINCR);
-		}
-	} else if ((len >= UINT32SZ) &&
-	    ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT32SZ - 1)) == 0)) {
-		/*
-		 * Both source and destination are word aligned
-		 */
-		int cnt = len/UINT32SZ;
-
-		IOSRAMLOG(2,
-		    "RD: rep_get32(buf:%p sramp:%p cnt:%x) len:%x\n",
-		    buf, iosramp, cnt, len);
-		ddi_rep_get32(handle, (uint32_t *)buf, (uint32_t *)iosramp,
-		    cnt, DDI_DEV_AUTOINCR);
-		iosramp += cnt * UINT32SZ;
-		buf += cnt * UINT32SZ;
-		len -= cnt * UINT32SZ;
-
-		/*
-		 * copy the remainder using byte access
-		 */
-		if (len != 0) {
-			ddi_rep_get8(handle, buf, iosramp, len,
-			    DDI_DEV_AUTOINCR);
-		}
-	} else if (len != 0) {
-		/*
-		 * We know that the "off" (i.e. iosramp) is at least word
-		 * aligned. We need to read IOSRAM word at a time and copy it
-		 * byte at a time.
-		 */
-		ASSERT(((uintptr_t)iosramp & (UINT32SZ - 1)) == 0);
-
-		IOSRAMLOG(2,
-		    "RD: unaligned get32(buf:%p sramp:%p) len:%x\n",
-		    buf, iosramp, len, NULL);
-		for (; len >= UINT32SZ; len -= UINT32SZ, iosramp += UINT32SZ) {
-			word.data =  ddi_get32(handle, (uint32_t *)iosramp);
-			*buf++ = word.cbuf[0];
-			*buf++ = word.cbuf[1];
-			*buf++ = word.cbuf[2];
-			*buf++ = word.cbuf[3];
-		}
-
-		/*
-		 * copy the remaining data using byte access
-		 */
-		if (len != 0) {
-			ddi_rep_get8(handle, buf, iosramp, len,
-			    DDI_DEV_AUTOINCR);
-		}
-	}
-
-	/*
-	 * Reacquire mutex lock, decrement refcnt and if refcnt is 0 and any
-	 * threads are waiting for r/w activity to complete, wake them up.
-	 */
-	mutex_enter(&iosram_mutex);
-	ASSERT(iosram_rw_active > 0);
-
-	if ((--iosram_rw_active == 0) && iosram_rw_wakeup) {
-		iosram_rw_wakeup = 0;
-		cv_broadcast(&iosram_rw_wait);
-	}
-	mutex_exit(&iosram_mutex);
-
-	return (error);
-}
-
-
-/*
- * _iosram_write(key, off, len, dptr, force)
- *	Internal common routine to write to the IOSRAM.
- */
-static int
-_iosram_write(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr, int force)
-{
-	iosram_chunk_t		*chunkp;
-	uint32_t		chunk_len;
-	uint8_t			*iosramp;
-	ddi_acc_handle_t	handle;
-	int			boff;
-	union {
-		uint8_t	cbuf[UINT32SZ];
-		uint32_t data;
-	} word;
-
-	int			error = 0;
-	uint8_t			*buf = (uint8_t *)dptr;
-
-	/*
-	 * We try to write to the IOSRAM using double word or word access
-	 * provided both "off" and "buf" are (or can be) double word or word
-	 * aligned.  Othewise, we try to align the "off" to a word boundary and
-	 * then try to write data to the IOSRAM using word access, but read data
-	 * from the buf buffer using byte access.
-	 *
-	 * If the leading/trailing portion of the IOSRAM data is not word
-	 * aligned, it will always be written using byte access.
-	 */
-	IOSRAMLOG(1, "WR: key: 0x%x off:%x len:%x buf:%p\n",
-	    key, off, len, buf);
-
-	/*
-	 * Acquire lock and look for the requested chunk.  If it exists, make
-	 * sure the requested write is within the chunk's bounds and no tunnel
-	 * switch is active.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-	chunk_len = (chunkp != NULL) ? chunkp->toc_data.len : 0;
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if (chunkp == NULL) {
-		error = EINVAL;
-	} else if ((off >= chunk_len) || (len > chunk_len) ||
-	    ((off+len) > chunk_len)) {
-		error = EMSGSIZE;
-	} else if (iosram_tswitch_active && !force) {
-		error = EAGAIN;
-	}
-
-	if (error) {
-		mutex_exit(&iosram_mutex);
-		return (error);
-	}
-
-	/*
-	 * If this is a forced write and there's a tunnel switch in progress,
-	 * abort the switch.
-	 */
-	if (iosram_tswitch_active && force) {
-		cmn_err(CE_NOTE, "!iosram: Aborting tswitch on force_write");
-		iosram_abort_tswitch();
-	}
-
-	/*
-	 * Bump reference count to indicate #thread accessing IOSRAM
-	 * and release the lock.
-	 */
-	iosram_rw_active++;
-#if defined(DEBUG)
-	if (iosram_rw_active > iosram_rw_active_max) {
-		iosram_rw_active_max = iosram_rw_active;
-	}
-#endif
-	mutex_exit(&iosram_mutex);
-
-
-	IOSRAM_STAT(write);
-	IOSRAM_STAT_ADD(bwrite, len);
-
-	/* Get starting address and map handle */
-	iosramp = chunkp->basep + off;
-	handle = iosram_handle;
-
-	/*
-	 * Align the off to word boundary and then try reading/writing
-	 * data using double word or word access.
-	 */
-	if ((boff = ((uintptr_t)iosramp & (UINT32SZ - 1))) != 0) {
-		int	cnt = UINT32SZ - boff;
-
-		if (cnt > len) {
-			cnt = len;
-		}
-		IOSRAMLOG(2,
-		    "WR: align rep_put8(buf:%p sramp:%p cnt:%x) len:%x\n",
-		    buf, iosramp, cnt, len);
-		ddi_rep_put8(handle, buf, iosramp, cnt, DDI_DEV_AUTOINCR);
-		buf += cnt;
-		iosramp += cnt;
-		len -= cnt;
-	}
-
-	if ((len >= UINT64SZ) &&
-	    ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT64SZ - 1)) == 0)) {
-		/*
-		 * Both source and destination are double word aligned
-		 */
-		int cnt = len/UINT64SZ;
-
-		IOSRAMLOG(2,
-		    "WR: rep_put64(buf:%p sramp:%p cnt:%x) len:%x\n",
-		    buf, iosramp, cnt, len);
-		ddi_rep_put64(handle, (uint64_t *)buf, (uint64_t *)iosramp,
-		    cnt, DDI_DEV_AUTOINCR);
-		iosramp += cnt * UINT64SZ;
-		buf += cnt * UINT64SZ;
-		len -= cnt * UINT64SZ;
-
-		/*
-		 * Copy the remaining data using word & byte access
-		 */
-		if (len >= UINT32SZ) {
-			IOSRAMLOG(2,
-			    "WR: put32(buf:%p sramp:%p) len:%x\n", buf, iosramp,
-			    len, NULL);
-			ddi_put32(handle, (uint32_t *)iosramp,
-			    *(uint32_t *)buf);
-			iosramp += UINT32SZ;
-			buf += UINT32SZ;
-			len -= UINT32SZ;
-		}
-
-		if (len != 0) {
-			ddi_rep_put8(handle, buf, iosramp, len,
-			    DDI_DEV_AUTOINCR);
-		}
-	} else if ((len >= UINT32SZ) &&
-	    ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT32SZ - 1)) == 0)) {
-		/*
-		 * Both source and destination are word aligned
-		 */
-		int cnt = len/UINT32SZ;
-
-		IOSRAMLOG(2,
-		    "WR: rep_put32(buf:%p sramp:%p cnt:%x) len:%x\n",
-		    buf, iosramp, cnt, len);
-		ddi_rep_put32(handle, (uint32_t *)buf, (uint32_t *)iosramp,
-		    cnt, DDI_DEV_AUTOINCR);
-		iosramp += cnt * UINT32SZ;
-		buf += cnt * UINT32SZ;
-		len -= cnt * UINT32SZ;
-
-		/*
-		 * copy the remainder using byte access
-		 */
-		if (len != 0) {
-			ddi_rep_put8(handle, buf, iosramp, len,
-			    DDI_DEV_AUTOINCR);
-		}
-	} else if (len != 0) {
-		/*
-		 * We know that the "off" is at least word aligned. We
-		 * need to read data from buf buffer byte at a time, and
-		 * write it to the IOSRAM word at a time.
-		 */
-
-		ASSERT(((uintptr_t)iosramp & (UINT32SZ - 1)) == 0);
-
-		IOSRAMLOG(2,
-		    "WR: unaligned put32(buf:%p sramp:%p) len:%x\n",
-		    buf, iosramp, len, NULL);
-		for (; len >= UINT32SZ; len -= UINT32SZ, iosramp += UINT32SZ) {
-			word.cbuf[0] = *buf++;
-			word.cbuf[1] = *buf++;
-			word.cbuf[2] = *buf++;
-			word.cbuf[3] = *buf++;
-			ddi_put32(handle, (uint32_t *)iosramp, word.data);
-		}
-
-		/*
-		 * copy the remaining data using byte access
-		 */
-		if (len != 0) {
-			ddi_rep_put8(handle, buf, iosramp,
-			    len, DDI_DEV_AUTOINCR);
-		}
-	}
-
-	/*
-	 * Reacquire mutex lock, decrement refcnt and if refcnt is 0 and
-	 * any threads are waiting for r/w activity to complete, wake them up.
-	 */
-	mutex_enter(&iosram_mutex);
-	ASSERT(iosram_rw_active > 0);
-
-	if ((--iosram_rw_active == 0) && iosram_rw_wakeup) {
-		iosram_rw_wakeup = 0;
-		cv_broadcast(&iosram_rw_wait);
-	}
-	mutex_exit(&iosram_mutex);
-
-	return (error);
-}
-
-
-int
-iosram_force_write(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr)
-{
-	return (_iosram_write(key, off, len, dptr, 1 /* force */));
-}
-
-
-int
-iosram_wr(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr)
-{
-	return (_iosram_write(key, off, len, dptr, 0));
-}
-
-
-/*
- * iosram_register(key, handler, arg)
- *	Register a handler and an arg for the specified chunk.  This handler
- *	will be invoked when an interrupt is received from the other side and
- *	the int_pending flag for the corresponding key is marked
- *	IOSRAM_INT_TO_DOM.
- */
-/* ARGSUSED */
-int
-iosram_register(uint32_t key, void (*handler)(), void *arg)
-{
-	struct iosram_chunk	*chunkp;
-	int			error = 0;
-
-	/*
-	 * Acquire lock and look for the requested chunk.  If it exists, and no
-	 * other callback is registered, proceed with the registration.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if (chunkp == NULL) {
-		error = EINVAL;
-	} else if (chunkp->cback.handler != NULL) {
-		error = EBUSY;
-	} else {
-		chunkp->cback.busy = 0;
-		chunkp->cback.unregister = 0;
-		chunkp->cback.handler = handler;
-		chunkp->cback.arg = arg;
-	}
-	mutex_exit(&iosram_mutex);
-
-	IOSRAMLOG(1, "REG: key: 0x%x hdlr:%p arg:%p error:%d\n",
-	    key, handler, arg, error);
-
-	return (error);
-}
-
-
-/*
- * iosram_unregister()
- *	Unregister handler associated with the specified chunk.
- */
-int
-iosram_unregister(uint32_t key)
-{
-	struct iosram_chunk	*chunkp;
-	int			error = 0;
-
-	/*
-	 * Acquire lock and look for the requested chunk.  If it exists and has
-	 * a callback registered, unregister it.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if (chunkp == NULL) {
-		error = EINVAL;
-	} else if (chunkp->cback.busy) {
-		/*
-		 * If the handler is already busy (being invoked), then we flag
-		 * it so it will be unregistered after the invocation completes.
-		 */
-		DPRINTF(1, ("IOSRAM(%d): unregister: delaying unreg k:0x%08x\n",
-		    iosram_master->instance, key));
-		chunkp->cback.unregister = 1;
-	} else if (chunkp->cback.handler != NULL) {
-		chunkp->cback.handler = NULL;
-		chunkp->cback.arg = NULL;
-	}
-	mutex_exit(&iosram_mutex);
-
-	IOSRAMLOG(1, "UNREG: key:%x error:%d\n", key, error, NULL, NULL);
-	return (error);
-}
-
-
-/*
- * iosram_get_flag():
- *	Get data_valid and/or int_pending flags associated with the
- *	specified key.
- */
-int
-iosram_get_flag(uint32_t key, uint8_t *data_valid, uint8_t *int_pending)
-{
-	iosram_chunk_t	*chunkp;
-	iosram_flags_t	flags;
-	int		error = 0;
-
-	/*
-	 * Acquire lock and look for the requested chunk.  If it exists, and no
-	 * tunnel switch is in progress, read the chunk's flags.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if (chunkp == NULL) {
-		error = EINVAL;
-	} else if (iosram_tswitch_active) {
-		error = EAGAIN;
-	} else {
-		IOSRAM_STAT(getflag);
-
-		/*
-		 * Read the flags
-		 */
-		ddi_rep_get8(iosram_handle, (uint8_t *)&flags,
-		    (uint8_t *)(chunkp->flagsp), sizeof (iosram_flags_t),
-		    DDI_DEV_AUTOINCR);
-
-		/*
-		 * Get each flag value that the caller is interested in.
-		 */
-		if (data_valid != NULL) {
-			*data_valid = flags.data_valid;
-		}
-
-		if (int_pending != NULL) {
-			*int_pending = flags.int_pending;
-		}
-	}
-	mutex_exit(&iosram_mutex);
-
-	IOSRAMLOG(1, "GetFlag key:%x data_valid:%x int_pending:%x error:%d\n",
-	    key, flags.data_valid, flags.int_pending, error);
-	return (error);
-}
-
-
-/*
- * iosram_set_flag():
- *	Set data_valid and int_pending flags associated with the specified key.
- */
-int
-iosram_set_flag(uint32_t key, uint8_t data_valid, uint8_t int_pending)
-{
-	iosram_chunk_t	*chunkp;
-	iosram_flags_t	flags;
-	int		error = 0;
-
-	/*
-	 * Acquire lock and look for the requested chunk.  If it exists, and no
-	 * tunnel switch is in progress, write the chunk's flags.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if ((chunkp == NULL) ||
-	    ((data_valid != IOSRAM_DATA_INVALID) &&
-	    (data_valid != IOSRAM_DATA_VALID)) ||
-	    ((int_pending != IOSRAM_INT_NONE) &&
-	    (int_pending != IOSRAM_INT_TO_SSC) &&
-	    (int_pending != IOSRAM_INT_TO_DOM))) {
-		error = EINVAL;
-	} else if (iosram_tswitch_active) {
-		error = EAGAIN;
-	} else {
-		IOSRAM_STAT(setflag);
-		flags.data_valid = data_valid;
-		flags.int_pending = int_pending;
-		ddi_rep_put8(iosram_handle, (uint8_t *)&flags,
-		    (uint8_t *)(chunkp->flagsp), sizeof (iosram_flags_t),
-		    DDI_DEV_AUTOINCR);
-	}
-	mutex_exit(&iosram_mutex);
-
-	IOSRAMLOG(1, "SetFlag key:%x data_valid:%x int_pending:%x error:%d\n",
-	    key, flags.data_valid, flags.int_pending, error);
-	return (error);
-}
-
-
-/*
- * iosram_ctrl()
- *	This function provides access to a variety of services not available
- *	through the basic API.
- */
-int
-iosram_ctrl(uint32_t key, uint32_t cmd, void *arg)
-{
-	struct iosram_chunk	*chunkp;
-	int			error = 0;
-
-	/*
-	 * Acquire lock and do some argument sanity checking.
-	 */
-	mutex_enter(&iosram_mutex);
-	chunkp = iosram_find_chunk(key);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else if (chunkp == NULL) {
-		error = EINVAL;
-	}
-
-	if (error != 0) {
-		mutex_exit(&iosram_mutex);
-		return (error);
-	}
-
-	/*
-	 * Arguments seem okay so far, so process the command.
-	 */
-	switch (cmd) {
-		case IOSRAM_CMD_CHUNKLEN:
-			/*
-			 * Return the length of the chunk indicated by the key.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			*(uint32_t *)arg = chunkp->toc_data.len;
-			break;
-
-		default:
-			error = ENOTSUP;
-			break;
-	}
-
-	mutex_exit(&iosram_mutex);
-	return (error);
-}
-
-
-/*
- * iosram_hdr_ctrl()
- *	This function provides an interface for the Mailbox Protocol
- *	implementation to use when interacting with the IOSRAM header.
- */
-int
-iosram_hdr_ctrl(uint32_t cmd, void *arg)
-{
-	int	error = 0;
-
-	/*
-	 * Acquire lock and do some argument sanity checking.
-	 */
-	mutex_enter(&iosram_mutex);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	}
-
-	if (error != 0) {
-		mutex_exit(&iosram_mutex);
-		return (error);
-	}
-
-	switch (cmd) {
-		case IOSRAM_HDRCMD_GET_SMS_MBOX_VER:
-			/*
-			 * Return the value of the sms_mbox_version field.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			*(uint32_t *)arg = IOSRAM_GET_HDRFIELD32(iosram_master,
-			    sms_mbox_version);
-			break;
-
-		case IOSRAM_HDRCMD_SET_OS_MBOX_VER:
-			/*
-			 * Set the value of the os_mbox_version field.
-			 */
-			IOSRAM_SET_HDRFIELD32(iosram_master, os_mbox_version,
-			    (uint32_t)(uintptr_t)arg);
-			IOSRAM_SET_HDRFIELD32(iosram_master, os_change_mask,
-			    IOSRAM_HDRFIELD_OS_MBOX_VER);
-			(void) iosram_send_intr();
-			break;
-
-		case IOSRAM_HDRCMD_REG_CALLBACK:
-			iosram_hdrchange_handler = (void (*)())arg;
-			break;
-
-		default:
-			error = ENOTSUP;
-			break;
-	}
-
-	mutex_exit(&iosram_mutex);
-	return (error);
-}
-
-
-/*
- * iosram_softintr()
- *	IOSRAM soft interrupt handler
- */
-static uint_t
-iosram_softintr(caddr_t arg)
-{
-	uint32_t	hdr_changes;
-	iosramsoft_t	*softp = (iosramsoft_t *)arg;
-	iosram_chunk_t	*chunkp;
-	void		(*handler)();
-	int		i;
-	uint8_t		flag;
-
-	DPRINTF(1, ("iosram(%d): in iosram_softintr\n", softp->instance));
-
-	IOSRAMLOG(2, "SINTR arg/softp:%p  pending:%d busy:%d\n",
-	    arg, softp->intr_pending, softp->intr_busy, NULL);
-
-	mutex_enter(&iosram_mutex);
-	mutex_enter(&softp->intr_mutex);
-
-	/*
-	 * Do not process interrupt if interrupt handler is already running or
-	 * no interrupts are pending.
-	 */
-	if (softp->intr_busy || !softp->intr_pending) {
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM(%d): softintr: busy=%d pending=%d\n",
-		    softp->instance, softp->intr_busy, softp->intr_pending));
-		return (softp->intr_pending ? DDI_INTR_CLAIMED :
-		    DDI_INTR_UNCLAIMED);
-	}
-
-	/*
-	 * It's possible for the SC to send an interrupt on the new master
-	 * before we are able to set our internal state.  If so, we'll retrigger
-	 * soft interrupt right after tunnel switch completion.
-	 */
-	if (softp->state & IOSRAM_STATE_TSWITCH) {
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM(%d): softintr: doing switch "
-		    "state=0x%x\n", softp->instance, softp->state));
-		return (DDI_INTR_CLAIMED);
-	}
-
-	/*
-	 * Do not process interrupt if we are not the master.
-	 */
-	if (!(softp->state & IOSRAM_STATE_MASTER)) {
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM(%d): softintr: no master state=0x%x\n ",
-		    softp->instance, softp->state));
-		return (DDI_INTR_CLAIMED);
-	}
-
-	IOSRAM_STAT(sintr_recv);
-
-	/*
-	 * If the driver is suspended, then we should not process any
-	 * interrupts.  Instead, we trigger a soft interrupt when the driver
-	 * resumes.
-	 */
-	if (softp->suspended) {
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM(%d): softintr: suspended\n",
-		    softp->instance));
-		return (DDI_INTR_CLAIMED);
-	}
-
-	/*
-	 * Indicate that the IOSRAM interrupt handler is busy.  Note that this
-	 * includes incrementing the reader/writer count, since we don't want
-	 * any tunnel switches to start up while we're processing callbacks.
-	 */
-	softp->intr_busy = 1;
-	iosram_rw_active++;
-#if defined(DEBUG)
-	if (iosram_rw_active > iosram_rw_active_max) {
-		iosram_rw_active_max = iosram_rw_active;
-	}
-#endif
-
-	do {
-		DPRINTF(1, ("IOSRAM(%d): softintr: processing interrupt\n",
-		    softp->instance));
-
-		softp->intr_pending = 0;
-
-		mutex_exit(&softp->intr_mutex);
-
-		/*
-		 * Process changes to the IOSRAM header.
-		 */
-		hdr_changes = IOSRAM_GET_HDRFIELD32(iosram_master,
-		    sms_change_mask);
-		if (hdr_changes != 0) {
-			int	error;
-
-			IOSRAM_SET_HDRFIELD32(iosram_master, sms_change_mask,
-			    0);
-			if (hdr_changes & IOSRAM_HDRFIELD_TOC_INDEX) {
-				/*
-				 * XXX is it safe to temporarily release the
-				 * iosram_mutex here?
-				 */
-				mutex_exit(&iosram_mutex);
-				error = iosram_read_toc(iosram_master);
-				mutex_enter(&iosram_mutex);
-				if (error) {
-					cmn_err(CE_WARN, "iosram_read_toc: new"
-					    " TOC invalid; using old TOC.");
-				}
-				iosram_update_addrs(iosram_master);
-			}
-
-			if (iosram_hdrchange_handler != NULL) {
-				mutex_exit(&iosram_mutex);
-				iosram_hdrchange_handler();
-				mutex_enter(&iosram_mutex);
-			}
-		}
-
-		/*
-		 * Get data_valid/int_pending flags and generate a callback if
-		 * applicable.  For now, we read only those flags for which a
-		 * callback has been registered.  We can optimize reading of
-		 * flags by reading them all at once and then process them
-		 * later.
-		 */
-		for (i = 0, chunkp = chunks; i < nchunks; i++,
-		    chunkp++) {
-#if DEBUG
-			flag =  ddi_get8(iosram_handle,
-			    &(chunkp->flagsp->int_pending));
-			DPRINTF(1, ("IOSRAM(%d): softintr chunk #%d "
-			    "flag=0x%x handler=%p\n",
-			    softp->instance, i, (int)flag,
-			    (void *)chunkp->cback.handler));
-#endif
-			if ((handler = chunkp->cback.handler) == NULL) {
-				continue;
-			}
-			flag = ddi_get8(iosram_handle,
-			    &(chunkp->flagsp->int_pending));
-			if (flag == IOSRAM_INT_TO_DOM) {
-				DPRINTF(1,
-				    ("IOSRAM(%d): softintr: invoking handler\n",
-				    softp->instance));
-				IOSRAMLOG(1,
-				    "SINTR invoking hdlr:%p arg:%p index:%d\n",
-				    handler, chunkp->cback.arg, i, NULL);
-				IOSRAM_STAT(callbacks);
-
-				ddi_put8(iosram_handle,
-				    &(chunkp->flagsp->int_pending),
-				    IOSRAM_INT_NONE);
-				chunkp->cback.busy = 1;
-				mutex_exit(&iosram_mutex);
-				(*handler)(chunkp->cback.arg);
-				mutex_enter(&iosram_mutex);
-				chunkp->cback.busy = 0;
-
-				/*
-				 * If iosram_unregister was called while the
-				 * callback was being invoked, complete the
-				 * unregistration here.
-				 */
-				if (chunkp->cback.unregister) {
-					DPRINTF(1, ("IOSRAM(%d): softintr: "
-					    "delayed unreg k:0x%08x\n",
-					    softp->instance,
-					    chunkp->toc_data.key));
-					chunkp->cback.handler = NULL;
-					chunkp->cback.arg = NULL;
-					chunkp->cback.unregister = 0;
-				}
-			}
-
-			/*
-			 * If there's a tunnel switch waiting to run, give it
-			 * higher priority than these callbacks by bailing out.
-			 * They'll still be invoked on the new master iosram
-			 * when the tunnel switch is done.
-			 */
-			if (iosram_tswitch_active) {
-				break;
-			}
-		}
-
-		mutex_enter(&softp->intr_mutex);
-
-	} while (softp->intr_pending && !softp->suspended &&
-	    !iosram_tswitch_active);
-
-	/*
-	 * Indicate IOSRAM interrupt handler is not BUSY any more
-	 */
-	softp->intr_busy = 0;
-
-	ASSERT(iosram_rw_active > 0);
-	if ((--iosram_rw_active == 0) && iosram_rw_wakeup) {
-		iosram_rw_wakeup = 0;
-		cv_broadcast(&iosram_rw_wait);
-	}
-
-	mutex_exit(&softp->intr_mutex);
-	mutex_exit(&iosram_mutex);
-
-	DPRINTF(1, ("iosram(%d): softintr exit\n", softp->instance));
-
-	return (DDI_INTR_CLAIMED);
-}
-
-
-/*
- * iosram_intr()
- *	IOSRAM real interrupt handler
- */
-static uint_t
-iosram_intr(caddr_t arg)
-{
-	iosramsoft_t	*softp = (iosramsoft_t *)arg;
-	int		result = DDI_INTR_UNCLAIMED;
-	uint32_t	int_status;
-
-	DPRINTF(2, ("iosram(%d): in iosram_intr\n", softp->instance));
-
-	mutex_enter(&softp->intr_mutex);
-
-	if (softp->sbbc_handle == NULL) {
-		/*
-		 * The SBBC registers region is not mapped in.
-		 * Set the interrupt pending flag here, and process the
-		 * interrupt after the tunnel switch.
-		 */
-		DPRINTF(1, ("IOSRAM(%d): iosram_intr: SBBC not mapped\n",
-		    softp->instance));
-		softp->intr_pending = 1;
-		mutex_exit(&softp->intr_mutex);
-		return (DDI_INTR_UNCLAIMED);
-	}
-
-	int_status = ddi_get32(softp->sbbc_handle,
-	    &(softp->sbbc_region->int_status.reg));
-	DPRINTF(1, ("iosram_intr: int_status = 0x%08x\n", int_status));
-
-	if (int_status & IOSRAM_SBBC_INT0) {
-		result = DDI_INTR_CLAIMED;
-		DPRINTF(1, ("iosram_intr: int0 detected!\n"));
-	}
-
-	if (int_status & IOSRAM_SBBC_INT1) {
-		result = DDI_INTR_CLAIMED;
-		DPRINTF(1, ("iosram_intr: int1 detected!\n"));
-	}
-
-	if (result == DDI_INTR_CLAIMED) {
-		ddi_put32(softp->sbbc_handle,
-		    &(softp->sbbc_region->int_status.reg), int_status);
-		int_status = ddi_get32(softp->sbbc_handle,
-		    &(softp->sbbc_region->int_status.reg));
-		DPRINTF(1, ("iosram_intr: int_status = 0x%08x\n",
-		    int_status));
-
-		softp->intr_pending = 1;
-		/*
-		 * Trigger soft interrupt if not executing and
-		 * not suspended.
-		 */
-		if (!softp->intr_busy && !softp->suspended &&
-		    (softp->softintr_id != NULL)) {
-			DPRINTF(1, ("iosram(%d): trigger softint\n",
-			    softp->instance));
-			ddi_trigger_softintr(softp->softintr_id);
-		}
-	}
-
-	IOSRAM_STAT(intr_recv);
-
-	mutex_exit(&softp->intr_mutex);
-
-	IOSRAMLOG(2, "INTR arg/softp:%p  pending:%d busy:%d\n",
-	    arg, softp->intr_pending, softp->intr_busy, NULL);
-	DPRINTF(1, ("iosram(%d): iosram_intr exit\n", softp->instance));
-
-	return (result);
-}
-
-
-/*
- * iosram_send_intr()
- *	Send an interrupt to the SSP side via AXQ driver
- */
-int
-iosram_send_intr()
-{
-	IOSRAMLOG(1, "SendIntr called\n", NULL, NULL, NULL, NULL);
-	IOSRAM_STAT(intr_send);
-	DPRINTF(1, ("iosram iosram_send_intr invoked\n"));
-
-	return (axq_cpu2ssc_intr(0));
-}
-
-
-#if defined(DEBUG)
-static void
-iosram_dummy_cback(void *arg)
-{
-	DPRINTF(1, ("iosram_dummy_cback invoked arg:%p\n", arg));
-}
-#endif /* DEBUG */
-
-
-/*ARGSUSED1*/
-static int
-iosram_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
-		int *rvalp)
-{
-	struct iosramsoft	*softp;
-	int			error = DDI_SUCCESS;
-
-	softp = ddi_get_soft_state(iosramsoft_statep, getminor(dev));
-	if (softp == NULL) {
-		return (ENXIO);
-	}
-	IOSRAMLOG(1, "IOCTL: dev:%p cmd:%x arg:%p ... instance %d\n",
-	    dev, cmd, arg, softp->instance);
-
-	switch (cmd) {
-#if defined(DEBUG)
-	case IOSRAM_GET_FLAG:
-		{
-		iosram_io_t	req;
-		uint8_t		data_valid, int_pending;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_GET_FLAG(key:%x\n", req.key));
-
-		req.retval = iosram_get_flag(req.key, &data_valid,
-		    &int_pending);
-		req.data_valid = (uint32_t)data_valid;
-		req.int_pending = (uint32_t)int_pending;
-
-		if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
-			DPRINTF(1,
-			    ("IOSRAM_GET_FLAG: can't copyout req.retval (%x)",
-			    req.retval));
-			error = EFAULT;
-		}
-
-		return (error);
-		}
-
-	case IOSRAM_SET_FLAG:
-		{
-		iosram_io_t	req;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_SET_FLAG(key:%x data_valid:%x "
-		    "int_pending:%x\n", req.key, req.data_valid,
-		    req.int_pending));
-
-		req.retval = iosram_set_flag(req.key, req.data_valid,
-		    req.int_pending);
-
-		if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
-			DPRINTF(1, ("IOSRAM_SET_FLAG: can't copyout req.retval"
-			    " (%x)\n", req.retval));
-			error = EFAULT;
-		}
-
-		return (error);
-		}
-
-	case IOSRAM_RD:
-		{
-		caddr_t		bufp;
-		int		len;
-		iosram_io_t	req;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_RD(k:%x o:%x len:%x bufp:%p\n", req.key,
-		    req.off, req.len, (void *)(uintptr_t)req.bufp));
-
-		len = req.len;
-		bufp = kmem_alloc(len, KM_SLEEP);
-
-		req.retval = iosram_rd(req.key, req.off, req.len, bufp);
-
-		if (ddi_copyout(bufp, (void *)(uintptr_t)req.bufp, len, mode)) {
-			DPRINTF(1, ("IOSRAM_RD: copyout(%p, %p,%x,%x) failed\n",
-			    (void *)bufp, (void *)(uintptr_t)req.bufp, len,
-			    mode));
-			error = EFAULT;
-		} else if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
-			DPRINTF(1, ("IOSRAM_RD: can't copyout retval (%x)\n",
-			    req.retval));
-			error = EFAULT;
-		}
-
-		kmem_free(bufp, len);
-		return (error);
-		}
-
-	case IOSRAM_WR:
-		{
-		caddr_t		bufp;
-		iosram_io_t	req;
-		int		len;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_WR(k:%x o:%x len:%x bufp:%p\n",
-		    req.key, req.off, req.len, (void *)(uintptr_t)req.bufp));
-		len = req.len;
-		bufp = kmem_alloc(len, KM_SLEEP);
-		if (ddi_copyin((void *)(uintptr_t)req.bufp, bufp, len, mode)) {
-			error = EFAULT;
-		} else {
-			req.retval = iosram_wr(req.key, req.off, req.len,
-			    bufp);
-
-			if (ddi_copyout(&req, (void *)arg, sizeof (req),
-			    mode)) {
-				error = EFAULT;
-			}
-		}
-		kmem_free(bufp, len);
-		return (error);
-		}
-
-	case IOSRAM_TOC:
-		{
-		caddr_t		bufp;
-		int		len;
-		iosram_io_t	req;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_TOC (req.bufp:%x req.len:%x) \n",
-		    req.bufp, req.len));
-
-		len = req.len;
-		bufp = kmem_alloc(len, KM_SLEEP);
-
-		req.retval = iosram_get_keys((iosram_toc_entry_t *)bufp,
-		    &req.len);
-
-		if (ddi_copyout(bufp, (void *)(uintptr_t)req.bufp, req.len,
-		    mode)) {
-			DPRINTF(1,
-			    ("IOSRAM_TOC: copyout(%p, %p,%x,%x) failed\n",
-			    (void *)bufp, (void *)(uintptr_t)req.bufp, req.len,
-			    mode));
-			error = EFAULT;
-		} else if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
-			DPRINTF(1, ("IOSRAM_TOC: can't copyout retval (%x)\n",
-			    req.retval));
-			error = EFAULT;
-		}
-		kmem_free(bufp, len);
-		return (error);
-		}
-
-	case IOSRAM_SEND_INTR:
-		{
-		DPRINTF(2, ("IOSRAM_SEND_INTR\n"));
-
-		switch ((int)arg) {
-		case 0x11:
-		case 0x22:
-		case 0x44:
-		case 0x88:
-			ddi_put32(softp->sbbc_handle,
-			    &(softp->sbbc_region->int_enable.reg), (int)arg);
-			DPRINTF(1, ("Wrote 0x%x to int_enable.reg\n",
-			    (int)arg));
-			break;
-		case 0xBB:
-			ddi_put32(softp->sbbc_handle,
-			    &(softp->sbbc_region->p0_int_gen.reg), 1);
-			DPRINTF(1, ("Wrote 1 to p0_int_gen.reg\n"));
-			break;
-		default:
-			error = iosram_send_intr();
-		}
-
-		return (error);
-		}
-
-	case IOSRAM_PRINT_CBACK:
-		iosram_print_cback();
-		break;
-
-	case IOSRAM_PRINT_STATE:
-		iosram_print_state((int)arg);
-		break;
-
-#if IOSRAM_STATS
-	case IOSRAM_PRINT_STATS:
-		iosram_print_stats();
-		break;
-#endif
-
-#if IOSRAM_LOG
-	case IOSRAM_PRINT_LOG:
-		iosram_print_log((int)arg);
-		break;
-#endif
-
-	case IOSRAM_TUNNEL_SWITCH:
-		error = iosram_switchfrom((int)arg);
-		break;
-
-	case IOSRAM_PRINT_FLAGS:
-		iosram_print_flags();
-		break;
-
-	case IOSRAM_REG_CBACK:
-		{
-		iosram_io_t	req;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_REG_CBACK(k:%x)\n", req.key));
-
-		req.retval = iosram_register(req.key, iosram_dummy_cback,
-		    (void *)(uintptr_t)req.key);
-		if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
-			error = EFAULT;
-		}
-
-		return (error);
-		}
-
-	case IOSRAM_UNREG_CBACK:
-		{
-		iosram_io_t	req;
-
-		if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
-			return (EFAULT);
-		}
-
-		DPRINTF(2, ("IOSRAM_REG_CBACK(k:%x)\n", req.key));
-
-		req.retval = iosram_unregister(req.key);
-		if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
-			error = EFAULT;
-		}
-
-		return (error);
-		}
-
-	case IOSRAM_SEMA_ACQUIRE:
-	{
-		DPRINTF(1, ("IOSRAM_SEMA_ACQUIRE\n"));
-		error = iosram_sema_acquire(NULL);
-		return (error);
-	}
-
-	case IOSRAM_SEMA_RELEASE:
-	{
-		DPRINTF(1, ("IOSRAM_SEMA_RELEASE\n"));
-		error = iosram_sema_release();
-		return (error);
-	}
-
-#endif /* DEBUG */
-
-	default:
-		DPRINTF(1, ("iosram_ioctl: Illegal command %x\n", cmd));
-		error = ENOTTY;
-	}
-
-	return (error);
-}
-
-
-/*
- * iosram_switch_tunnel(softp)
- *	Switch master tunnel to the specified instance
- *	Must be called while holding iosram_mutex
- */
-/*ARGSUSED*/
-static int
-iosram_switch_tunnel(iosramsoft_t *softp)
-{
-#ifdef DEBUG
-	int		instance = softp->instance;
-#endif
-	int		error = 0;
-	iosramsoft_t	*prev_master;
-
-	ASSERT(mutex_owned(&iosram_mutex));
-
-	DPRINTF(1, ("tunnel switch new master:%p (%d) current master:%p (%d)\n",
-	    (void *)softp, instance, (void *)iosram_master,
-	    ((iosram_master) ? iosram_master->instance : -1)));
-	IOSRAMLOG(1, "TSWTCH: new_master:%p (%p) iosram_master:%p (%d)\n",
-	    softp, instance, iosram_master,
-	    ((iosram_master) ? iosram_master->instance : -1));
-
-	if (softp == NULL || (softp->state & IOSRAM_STATE_DETACH)) {
-		return (ENXIO);
-	}
-	if (iosram_master == softp) {
-		return (0);
-	}
-
-
-	/*
-	 * We protect against the softp structure being deallocated by setting
-	 * the IOSRAM_STATE_TSWITCH state flag. The detach routine will check
-	 * for this flag and if set, it will wait for this flag to be reset or
-	 * refuse the detach operation.
-	 */
-	iosram_new_master = softp;
-	softp->state |= IOSRAM_STATE_TSWITCH;
-	prev_master = iosram_master;
-	if (prev_master) {
-		prev_master->state |= IOSRAM_STATE_TSWITCH;
-	}
-	mutex_exit(&iosram_mutex);
-
-	/*
-	 * Map the target IOSRAM, read the TOC, and register interrupts if not
-	 * already done.
-	 */
-	DPRINTF(1, ("iosram(%d): mapping IOSRAM and SBBC\n",
-	    softp->instance));
-	IOSRAMLOG(1, "TSWTCH: mapping instance:%d  softp:%p\n",
-	    instance, softp, NULL, NULL);
-
-	if (iosram_setup_map(softp) != DDI_SUCCESS) {
-		error = ENXIO;
-	} else if ((chunks == NULL) && (iosram_read_toc(softp) != 0)) {
-		iosram_remove_map(softp);
-		error = EINVAL;
-	} else if (iosram_add_intr(softp) != DDI_SUCCESS) {
-		/*
-		 * If there was no previous master, purge the TOC data that
-		 * iosram_read_toc() created.
-		 */
-		if ((prev_master == NULL) && (chunks != NULL)) {
-			kmem_free(chunks, nchunks * sizeof (iosram_chunk_t));
-			chunks = NULL;
-			nchunks = 0;
-			iosram_init_hashtab();
-		}
-		iosram_remove_map(softp);
-		error = ENXIO;
-	}
-
-	/*
-	 * If we are asked to abort tunnel switch, do so now, before invoking
-	 * the OBP callback.
-	 */
-	if (iosram_tswitch_aborted) {
-
-		/*
-		 * Once the tunnel switch is aborted, this thread should not
-		 * resume.  If it does, we simply log a message.  We can't unmap
-		 * the new master IOSRAM as it may be accessed in
-		 * iosram_abort_tswitch(). It will be unmapped when it is
-		 * detached.
-		 */
-		IOSRAMLOG(1,
-		    "TSWTCH: aborted (pre OBP cback). Thread resumed.\n",
-		    NULL, NULL, NULL, NULL);
-		error = EIO;
-	}
-
-	if (error) {
-		IOSRAMLOG(1,
-		    "TSWTCH: map failed instance:%d  softp:%p error:%x\n",
-		    instance, softp, error, NULL);
-		goto done;
-	}
-
-	if (prev_master != NULL) {
-		int	result;
-
-		/*
-		 * Now invoke the OBP interface to do the tunnel switch.
-		 */
-		result = prom_starcat_switch_tunnel(softp->portid,
-		    OBP_TSWITCH_REQREPLY);
-		if (result != 0) {
-			error = EIO;
-		}
-		IOSRAMLOG(1,
-		    "TSWTCH: OBP tswitch portid:%x result:%x error:%x\n",
-		    softp->portid, result, error, NULL);
-		IOSRAM_STAT(tswitch);
-		iosram_tswitch_tstamp = ddi_get_lbolt();
-	}
-
-	mutex_enter(&iosram_mutex);
-	if (iosram_tswitch_aborted) {
-		/*
-		 * Tunnel switch aborted.  This thread should not resume.
-		 * For now, we simply log a message, but don't unmap any
-		 * IOSRAM at this stage as it may be accessed within the
-		 * isoram_abort_tswitch(). The IOSRAM will be unmapped
-		 * when that instance is detached.
-		 */
-		if (iosram_tswitch_aborted) {
-			IOSRAMLOG(1,
-			    "TSWTCH: aborted (post OBP cback). Thread"
-			    " resumed.\n", NULL, NULL, NULL, NULL);
-			error = EIO;
-			mutex_exit(&iosram_mutex);
-		}
-	} else if (error) {
-		/*
-		 * Tunnel switch failed.  Continue using previous tunnel.
-		 * However, unmap new (target) IOSRAM.
-		 */
-		iosram_new_master = NULL;
-		mutex_exit(&iosram_mutex);
-		(void) iosram_remove_intr(softp);
-		iosram_remove_map(softp);
-	} else {
-		/*
-		 * Tunnel switch was successful.  Set the new master.
-		 * Also unmap old master IOSRAM and remove any interrupts
-		 * associated with that.
-		 *
-		 * Note that a call to iosram_force_write() allows access
-		 * to the IOSRAM while tunnel switch is in progress.  That
-		 * means we need to set the new master before unmapping
-		 * the old master.
-		 */
-		iosram_set_master(softp);
-		iosram_new_master = NULL;
-		mutex_exit(&iosram_mutex);
-
-		if (prev_master) {
-			IOSRAMLOG(1, "TSWTCH: unmapping prev_master:%p (%d)\n",
-			    prev_master, prev_master->instance, NULL, NULL);
-			(void) iosram_remove_intr(prev_master);
-			iosram_remove_map(prev_master);
-		}
-	}
-
-done:
-	mutex_enter(&iosram_mutex);
-
-	/*
-	 * Clear the tunnel switch flag on the source and destination
-	 * instances.
-	 */
-	if (prev_master) {
-		prev_master->state &= ~IOSRAM_STATE_TSWITCH;
-	}
-	softp->state &= ~IOSRAM_STATE_TSWITCH;
-
-	/*
-	 * Since incoming interrupts could get lost during a tunnel switch,
-	 * trigger a soft interrupt just in case.  No harm other than a bit
-	 * of wasted effort will be caused if no interrupts were dropped.
-	 */
-	mutex_enter(&softp->intr_mutex);
-	iosram_master->intr_pending = 1;
-	if ((iosram_master->softintr_id != NULL) &&
-	    (iosram_master->intr_busy == 0)) {
-		ddi_trigger_softintr(iosram_master->softintr_id);
-	}
-	mutex_exit(&softp->intr_mutex);
-
-	IOSRAMLOG(1, "TSWTCH: done error:%d iosram_master:%p instance:%d\n",
-	    error, iosram_master,
-	    (iosram_master) ? iosram_master->instance : -1, NULL);
-
-	return (error);
-}
-
-
-/*
- * iosram_abort_tswitch()
- * Must be called while holding iosram_mutex.
- */
-static void
-iosram_abort_tswitch()
-{
-	uint32_t  master_valid, new_master_valid;
-
-	ASSERT(mutex_owned(&iosram_mutex));
-
-	if ((!iosram_tswitch_active) || iosram_tswitch_aborted) {
-		return;
-	}
-
-	ASSERT(iosram_master != NULL);
-
-	IOSRAMLOG(1, "ABORT: iosram_master:%p (%d) iosram_new_master:%p (%d)\n",
-	    iosram_master, iosram_master->instance, iosram_new_master,
-	    (iosram_new_master == NULL) ? -1 : iosram_new_master->instance);
-
-	/*
-	 * The first call to iosram_force_write() in the middle of tunnel switch
-	 * will get here. We lookup IOSRAM VALID location and setup appropriate
-	 * master, if one is still valid.  We also set iosram_tswitch_aborted to
-	 * prevent reentering this code and to catch if the OBP callback thread
-	 * somehow resumes.
-	 */
-	iosram_tswitch_aborted = 1;
-
-	if ((iosram_new_master == NULL) ||
-	    (iosram_new_master = iosram_master)) {
-		/*
-		 * New master hasn't been selected yet, or OBP callback
-		 * succeeded and we already selected new IOSRAM as master, but
-		 * system crashed in the middle of unmapping previous master or
-		 * cleaning up state.  Use the existing master.
-		 */
-		ASSERT(iosram_master->iosramp != NULL);
-		ASSERT(IOSRAM_GET_HDRFIELD32(iosram_master, status) ==
-		    IOSRAM_VALID);
-		IOSRAMLOG(1, "ABORT: master (%d) already determined.\n",
-		    iosram_master->instance, NULL, NULL, NULL);
-
-		return;
-	}
-
-	/*
-	 * System crashed in the middle of tunnel switch and we know that the
-	 * new target has not been marked master yet.  That means, the old
-	 * master should still be mapped.  We need to abort the tunnel switch
-	 * and setup a valid master, if possible, so that we can write to the
-	 * IOSRAM.
-	 *
-	 * We select a new master based upon the IOSRAM header status fields in
-	 * the previous master IOSRAM and the target IOSRAM as follows:
-	 *
-	 *	iosram_master	iosram-tswitch
-	 * 	(Prev Master)	(New Target)	Decision
-	 *	---------------	---------------	-----------
-	 *	  VALID		  don't care	prev master
-	 *	  INTRANSIT	  INVALID	prev master
-	 *	  INTRANSIT	  INTRANSIT	prev master
-	 *	  INTRANSIT	  VALID		new target
-	 *	  INVALID	  INVALID	shouldn't ever happen
-	 *	  INVALID	  INTRANSIT	shouldn't ever happen
-	 *	  INVALID	  VALID		new target
-	 */
-
-	master_valid = (iosram_master->iosramp != NULL) ?
-	    IOSRAM_GET_HDRFIELD32(iosram_master, status) : IOSRAM_INVALID;
-	new_master_valid = (iosram_new_master->iosramp != NULL) ?
-	    IOSRAM_GET_HDRFIELD32(iosram_new_master, status) : IOSRAM_INVALID;
-
-	if (master_valid == IOSRAM_VALID) {
-		/* EMPTY */
-		/*
-		 * OBP hasn't been called yet or, if it has, it hasn't started
-		 * copying yet.  Use the existing master.  Note that the new
-		 * master may not be mapped yet.
-		 */
-		IOSRAMLOG(1, "ABORT: prev master(%d) is VALID\n",
-		    iosram_master->instance, NULL, NULL, NULL);
-	} else if (master_valid == IOSRAM_INTRANSIT) {
-		/*
-		 * The system crashed after OBP started processing the tunnel
-		 * switch but before the iosram driver determined that it was
-		 * complete.  Use the new master if it has been marked valid,
-		 * meaning that OBP finished copying data to it, or the old
-		 * master otherwise.
-		 */
-		IOSRAMLOG(1, "ABORT: prev master(%d) is INTRANSIT\n",
-		    iosram_master->instance, NULL, NULL, NULL);
-
-		if (new_master_valid == IOSRAM_VALID) {
-			iosram_set_master(iosram_new_master);
-			IOSRAMLOG(1, "ABORT: new master(%d) is VALID\n",
-			    iosram_new_master->instance, NULL, NULL,
-			    NULL);
-		} else {
-			(void) prom_starcat_switch_tunnel(iosram_master->portid,
-			    OBP_TSWITCH_NOREPLY);
-
-			IOSRAMLOG(1, "ABORT: new master(%d) is INVALID\n",
-			    iosram_new_master->instance, NULL, NULL,
-			    NULL);
-		}
-	} else {
-		/*
-		 * The system crashed after OBP marked the old master INVALID,
-		 * which means the new master is the way to go.
-		 */
-		IOSRAMLOG(1, "ABORT: prev master(%d) is INVALID\n",
-		    iosram_master->instance, NULL, NULL, NULL);
-
-		ASSERT(new_master_valid == IOSRAM_VALID);
-
-		iosram_set_master(iosram_new_master);
-	}
-
-	IOSRAMLOG(1, "ABORT: Instance %d selected as master\n",
-	    iosram_master->instance, NULL, NULL, NULL);
-}
-
-
-/*
- * iosram_switchfrom(instance)
- *	Switch master tunnel away from the specified instance
- */
-/*ARGSUSED*/
-int
-iosram_switchfrom(int instance)
-{
-	struct iosramsoft	*softp;
-	int			error = 0;
-	int			count;
-	clock_t			current_tstamp;
-	clock_t			tstamp_interval;
-	struct iosramsoft	*last_master = NULL;
-	static int		last_master_instance = -1;
-
-	IOSRAMLOG(1, "SwtchFrom: instance:%d  iosram_master:%p (%d)\n",
-	    instance, iosram_master,
-	    ((iosram_master) ? iosram_master->instance : -1), NULL);
-
-	mutex_enter(&iosram_mutex);
-
-	/*
-	 * Wait if another tunnel switch is in progress
-	 */
-	for (count = 0; iosram_tswitch_active && count < IOSRAM_TSWITCH_RETRY;
-	    count++) {
-		iosram_tswitch_wakeup = 1;
-		cv_wait(&iosram_tswitch_wait, &iosram_mutex);
-	}
-
-	if (iosram_tswitch_active) {
-		mutex_exit(&iosram_mutex);
-		return (EAGAIN);
-	}
-
-	/*
-	 * Check if the specified instance holds the tunnel. If not,
-	 * then we are done.
-	 */
-	if ((iosram_master == NULL) || (iosram_master->instance != instance)) {
-		mutex_exit(&iosram_mutex);
-		return (0);
-	}
-
-	/*
-	 * Before beginning the tunnel switch process, wait for any outstanding
-	 * read/write activity to complete.
-	 */
-	iosram_tswitch_active = 1;
-	while (iosram_rw_active) {
-		iosram_rw_wakeup = 1;
-		cv_wait(&iosram_rw_wait, &iosram_mutex);
-	}
-
-	/*
-	 * If a previous tunnel switch just completed, we have to make sure
-	 * HWAD has enough time to find the new tunnel before we switch
-	 * away from it.  Otherwise, OBP's mailbox message to OSD will never
-	 * get through.  Just to be paranoid about synchronization of lbolt
-	 * across different CPUs, make sure the current attempt isn't noted
-	 * as starting _before_ the last tunnel switch completed.
-	 */
-	current_tstamp = ddi_get_lbolt();
-	if (current_tstamp > iosram_tswitch_tstamp) {
-		tstamp_interval = current_tstamp - iosram_tswitch_tstamp;
-	} else {
-		tstamp_interval = 0;
-	}
-	if (drv_hztousec(tstamp_interval) < IOSRAM_TSWITCH_DELAY_US) {
-		mutex_exit(&iosram_mutex);
-		delay(drv_usectohz(IOSRAM_TSWITCH_DELAY_US) - tstamp_interval);
-		mutex_enter(&iosram_mutex);
-	}
-
-	/*
-	 * The specified instance holds the tunnel.  We need to move it to some
-	 * other IOSRAM.  Try out all possible IOSRAMs listed in
-	 * iosram_instances.  For now, we always search from the first entry.
-	 * In future, it may be desirable to start where we left off.
-	 */
-	for (softp = iosram_instances; softp != NULL; softp = softp->next) {
-		if (iosram_tswitch_aborted) {
-			break;
-		}
-
-		/* we can't switch _to_ the instance we're switching _from_ */
-		if (softp->instance == instance) {
-			continue;
-		}
-
-		/* skip over instances being detached */
-		if (softp->state & IOSRAM_STATE_DETACH) {
-			continue;
-		}
-
-		/*
-		 * Try to avoid reverting to the last instance we switched away
-		 * from, as we expect that one to be detached eventually.  Keep
-		 * track of it, though, so we can go ahead and try switching to
-		 * it if no other viable candidates are found.
-		 */
-		if (softp->instance == last_master_instance) {
-			last_master = softp;
-			continue;
-		}
-
-		/*
-		 * Do the tunnel switch.  If successful, record the instance of
-		 * the master we just left behind so we can try to avoid
-		 * reverting to it next time.
-		 */
-		if (iosram_switch_tunnel(softp) == 0) {
-			last_master_instance = instance;
-			break;
-		}
-	}
-
-	/*
-	 * If we failed to switch the tunnel, but we skipped over an instance
-	 * that had previously been switched out of because we expected it to be
-	 * detached, go ahead and try it anyway (unless the tswitch was aborted
-	 * or the instance we skipped is finally being detached).
-	 */
-	if ((softp == NULL) && (last_master != NULL) &&
-	    !iosram_tswitch_aborted &&
-	    !(last_master->state & IOSRAM_STATE_DETACH)) {
-		if (iosram_switch_tunnel(last_master) == 0) {
-			softp = last_master;
-			last_master_instance = instance;
-		}
-	}
-
-	if ((softp == NULL) || (iosram_tswitch_aborted)) {
-		error = EIO;
-	}
-
-	/*
-	 * If there are additional tunnel switches queued up waiting for this
-	 * one to complete, wake them up.
-	 */
-	if (iosram_tswitch_wakeup) {
-		iosram_tswitch_wakeup = 0;
-		cv_broadcast(&iosram_tswitch_wait);
-	}
-	iosram_tswitch_active = 0;
-	mutex_exit(&iosram_mutex);
-	return (error);
-}
-
-
-/*
- * iosram_tunnel_capable(softp)
- *	Check if this IOSRAM instance is tunnel-capable by looing at
- *	"tunnel-capable" property.
- */
-static int
-iosram_tunnel_capable(struct iosramsoft *softp)
-{
-	int	proplen;
-	int	tunnel_capable;
-
-	/*
-	 * Look up IOSRAM_TUNNELOK_PROP property, if any.
-	 */
-	proplen = sizeof (tunnel_capable);
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, softp->dip,
-	    DDI_PROP_DONTPASS, IOSRAM_TUNNELOK_PROP, (caddr_t)&tunnel_capable,
-	    &proplen) != DDI_PROP_SUCCESS) {
-		tunnel_capable = 0;
-	}
-	return (tunnel_capable);
-}
-
-
-static int
-iosram_sbbc_setup_map(struct iosramsoft *softp)
-{
-	int				rv;
-	struct ddi_device_acc_attr	attr;
-	dev_info_t			*dip = softp->dip;
-	uint32_t			sema_val;
-
-	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
-	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
-	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
-
-	mutex_enter(&iosram_mutex);
-	mutex_enter(&softp->intr_mutex);
-
-	/*
-	 * Map SBBC region in
-	 */
-	if ((rv = ddi_regs_map_setup(dip, IOSRAM_SBBC_MAP_INDEX,
-	    (caddr_t *)&softp->sbbc_region,
-	    IOSRAM_SBBC_MAP_OFFSET, sizeof (iosram_sbbc_region_t),
-	    &attr, &softp->sbbc_handle)) != DDI_SUCCESS) {
-		DPRINTF(1, ("Failed to map SBBC region.\n"));
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		return (rv);
-	}
-
-	/*
-	 * Disable SBBC interrupts. SBBC interrupts are enabled
-	 * once the interrupt handler is registered.
-	 */
-	ddi_put32(softp->sbbc_handle,
-	    &(softp->sbbc_region->int_enable.reg), 0x0);
-
-	/*
-	 * Clear hardware semaphore value if appropriate.
-	 * When the first SBBC is mapped in by the IOSRAM driver,
-	 * the value of the semaphore should be initialized only
-	 * if it is not held by SMS. For subsequent SBBC's, the
-	 * semaphore will be always initialized.
-	 */
-	sema_val = IOSRAM_SEMA_RD(softp);
-
-	if (!iosram_master) {
-		/* the first SBBC is being mapped in */
-		if (!(IOSRAM_SEMA_IS_HELD(sema_val) &&
-		    IOSRAM_SEMA_GET_IDX(sema_val) == IOSRAM_SEMA_SMS_IDX)) {
-			/* not held by SMS, we clear the semaphore */
-			IOSRAM_SEMA_WR(softp, 0);
-		}
-	} else {
-		/* not the first SBBC, we clear the semaphore */
-		IOSRAM_SEMA_WR(softp, 0);
-	}
-
-	mutex_exit(&softp->intr_mutex);
-	mutex_exit(&iosram_mutex);
-	return (0);
-}
-
-
-static int
-iosram_setup_map(struct iosramsoft *softp)
-{
-	int				instance = softp->instance;
-	dev_info_t			*dip = softp->dip;
-	int				portid;
-	int				proplen;
-	caddr_t				propvalue;
-	struct ddi_device_acc_attr	attr;
-
-	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
-	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
-	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
-
-	/*
-	 * Lookup IOSRAM_REG_PROP property to find out our IOSRAM length
-	 */
-	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
-	    DDI_PROP_DONTPASS, IOSRAM_REG_PROP, (caddr_t)&propvalue,
-	    &proplen) != DDI_PROP_SUCCESS) {
-		cmn_err(CE_WARN, "iosram(%d): can't find register property.\n",
-		    instance);
-		return (DDI_FAILURE);
-	} else {
-		iosram_reg_t	*regprop = (iosram_reg_t *)propvalue;
-
-		DPRINTF(1, ("SetupMap(%d): Got reg prop: %x %x %x\n",
-		    instance, regprop->addr_hi,
-		    regprop->addr_lo, regprop->size));
-
-		softp->iosramlen = regprop->size;
-
-		kmem_free(propvalue, proplen);
-	}
-	DPRINTF(1, ("SetupMap(%d): IOSRAM length: 0x%x\n", instance,
-	    softp->iosramlen));
-	softp->handle = NULL;
-
-	/*
-	 * To minimize boot time, we map the entire IOSRAM as opposed to
-	 * mapping individual chunk via ddi_regs_map_setup() call.
-	 */
-	if (ddi_regs_map_setup(dip, 0, (caddr_t *)&softp->iosramp,
-	    0x0, softp->iosramlen, &attr, &softp->handle) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "iosram(%d): failed to map IOSRAM len:%x\n",
-		    instance, softp->iosramlen);
-		iosram_remove_map(softp);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * Lookup PORTID property on my parent hierarchy
-	 */
-	proplen = sizeof (portid);
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
-	    0, IOSRAM_PORTID_PROP, (caddr_t)&portid,
-	    &proplen) != DDI_PROP_SUCCESS) {
-		cmn_err(CE_WARN, "iosram(%d): can't find portid property.\n",
-		    instance);
-		iosram_remove_map(softp);
-		return (DDI_FAILURE);
-	}
-	softp->portid = portid;
-
-	if (iosram_sbbc_setup_map(softp) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "iosram(%d): can't map SBBC region.\n",
-		    instance);
-		iosram_remove_map(softp);
-		return (DDI_FAILURE);
-	}
-
-	mutex_enter(&iosram_mutex);
-	softp->state |= IOSRAM_STATE_MAPPED;
-	mutex_exit(&iosram_mutex);
-
-	return (DDI_SUCCESS);
-}
-
-
-static void
-iosram_remove_map(struct iosramsoft *softp)
-{
-	mutex_enter(&iosram_mutex);
-
-	ASSERT((softp->state & IOSRAM_STATE_MASTER) == 0);
-
-	if (softp->handle) {
-		ddi_regs_map_free(&softp->handle);
-		softp->handle = NULL;
-	}
-	softp->iosramp = NULL;
-
-	/*
-	 * Umap SBBC registers region. Shared with handler for SBBC
-	 * interrupts, take intr_mutex.
-	 */
-	mutex_enter(&softp->intr_mutex);
-	if (softp->sbbc_region) {
-		ddi_regs_map_free(&softp->sbbc_handle);
-		softp->sbbc_region = NULL;
-	}
-	mutex_exit(&softp->intr_mutex);
-
-	softp->state &= ~IOSRAM_STATE_MAPPED;
-
-	mutex_exit(&iosram_mutex);
-}
-
-
-/*
- * iosram_is_chosen(struct iosramsoft *softp)
- *
- *	Looks up "chosen" node property to
- *	determine if it is the chosen IOSRAM.
- */
-static int
-iosram_is_chosen(struct iosramsoft *softp)
-{
-	char		chosen_iosram[MAXNAMELEN];
-	char		pn[MAXNAMELEN];
-	int		nodeid;
-	int		chosen;
-	pnode_t		dnode;
-
-	/*
-	 * Get /chosen node info. prom interface will handle errors.
-	 */
-	dnode = prom_chosennode();
-
-	/*
-	 * Look for the "iosram" property on the chosen node with a prom
-	 * interface as ddi_find_devinfo() couldn't be used (calls
-	 * ddi_walk_devs() that creates one extra lock on the device tree).
-	 */
-	if (prom_getprop(dnode, IOSRAM_CHOSEN_PROP, (caddr_t)&nodeid) <= 0) {
-		/*
-		 * Can't find IOSRAM_CHOSEN_PROP property under chosen node
-		 */
-		cmn_err(CE_WARN,
-		    "iosram(%d): can't find chosen iosram property\n",
-		    softp->instance);
-		return (0);
-	}
-
-	DPRINTF(1, ("iosram(%d): Got '%x' for chosen '%s' property\n",
-	    softp->instance, nodeid, IOSRAM_CHOSEN_PROP));
-
-	/*
-	 * get the full OBP pathname of this node
-	 */
-	if (prom_phandle_to_path((phandle_t)nodeid, chosen_iosram,
-	    sizeof (chosen_iosram)) < 0) {
-		cmn_err(CE_NOTE, "prom_phandle_to_path(%x) failed\n", nodeid);
-		return (0);
-	}
-	DPRINTF(1, ("iosram(%d): prom_phandle_to_path(%x) is '%s'\n",
-	    softp->instance, nodeid, chosen_iosram));
-
-	(void) ddi_pathname(softp->dip, pn);
-	DPRINTF(1, ("iosram(%d): ddi_pathname(%p) is '%s'\n",
-	    softp->instance, (void *)softp->dip, pn));
-
-	chosen = (strcmp(chosen_iosram, pn) == 0) ? 1 : 0;
-	DPRINTF(1, ("iosram(%d): ... %s\n", softp->instance,
-	    chosen ? "MASTER" : "SLAVE"));
-	IOSRAMLOG(1, "iosram(%d): ... %s\n", softp->instance,
-	    (chosen ? "MASTER" : "SLAVE"), NULL, NULL);
-
-	return (chosen);
-}
-
-
-/*
- * iosram_set_master(struct iosramsoft *softp)
- *
- *	Set master tunnel to the specified IOSRAM
- *	Must be called while holding iosram_mutex.
- */
-static void
-iosram_set_master(struct iosramsoft *softp)
-{
-	ASSERT(mutex_owned(&iosram_mutex));
-	ASSERT(softp != NULL);
-	ASSERT(softp->state & IOSRAM_STATE_MAPPED);
-	ASSERT(IOSRAM_GET_HDRFIELD32(softp, status) == IOSRAM_VALID);
-
-	/*
-	 * Clear MASTER flag on any previous IOSRAM master, if any
-	 */
-	if (iosram_master && (iosram_master != softp)) {
-		iosram_master->state &= ~IOSRAM_STATE_MASTER;
-	}
-
-	/*
-	 * Setup new IOSRAM master
-	 */
-	iosram_update_addrs(softp);
-	iosram_handle = softp->handle;
-	softp->state |= IOSRAM_STATE_MASTER;
-	softp->tswitch_ok++;
-	iosram_master = softp;
-
-	IOSRAMLOG(1, "SETMASTER: softp:%p instance:%d\n", softp,
-	    softp->instance, NULL, NULL);
-}
-
-
-/*
- * iosram_read_toc()
- *
- *	Read the TOC from an IOSRAM instance that has been mapped in.
- *	If the TOC is flawed or the IOSRAM isn't valid, return an error.
- */
-static int
-iosram_read_toc(struct iosramsoft *softp)
-{
-	int			i;
-	int			instance = softp->instance;
-	uint8_t			*toc_entryp;
-	iosram_flags_t		*flagsp = NULL;
-	int			new_nchunks;
-	iosram_chunk_t		*new_chunks;
-	iosram_chunk_t		*chunkp;
-	iosram_chunk_t		*old_chunkp;
-	iosram_toc_entry_t	index;
-
-	/*
-	 * Never try to read the TOC out of an unmapped IOSRAM.
-	 */
-	ASSERT(softp->state & IOSRAM_STATE_MAPPED);
-
-	mutex_enter(&iosram_mutex);
-
-	/*
-	 * Check to make sure this IOSRAM is marked valid.  Return
-	 * an error if it isn't.
-	 */
-	if (IOSRAM_GET_HDRFIELD32(softp, status) != IOSRAM_VALID) {
-		DPRINTF(1, ("iosram_read_toc(%d): IOSRAM not flagged valid\n",
-		    instance));
-		mutex_exit(&iosram_mutex);
-		return (EINVAL);
-	}
-
-	/*
-	 * Get the location of the TOC.
-	 */
-	toc_entryp = softp->iosramp + IOSRAM_GET_HDRFIELD32(softp, toc_offset);
-
-	/*
-	 * Read the index entry from the TOC and make sure it looks correct.
-	 */
-	ddi_rep_get8(softp->handle, (uint8_t *)&index, toc_entryp,
-	    sizeof (iosram_toc_entry_t), DDI_DEV_AUTOINCR);
-	if ((index.key != IOSRAM_INDEX_KEY) ||
-	    (index.off != IOSRAM_INDEX_OFF)) {
-		cmn_err(CE_WARN, "iosram(%d): invalid TOC index.\n", instance);
-		mutex_exit(&iosram_mutex);
-		return (EINVAL);
-	}
-
-	/*
-	 * Allocate storage for the new chunks array and initialize it with data
-	 * from the TOC and callback data from the corresponding old chunk, if
-	 * it exists.
-	 */
-	new_nchunks = index.len - 1;
-	new_chunks = (iosram_chunk_t *)kmem_zalloc(new_nchunks *
-	    sizeof (iosram_chunk_t), KM_SLEEP);
-	for (i = 0, chunkp = new_chunks; i < new_nchunks; i++, chunkp++) {
-		toc_entryp += sizeof (iosram_toc_entry_t);
-		ddi_rep_get8(softp->handle, (uint8_t *)&(chunkp->toc_data),
-		    toc_entryp, sizeof (iosram_toc_entry_t), DDI_DEV_AUTOINCR);
-		chunkp->hash = NULL;
-		if ((chunkp->toc_data.off < softp->iosramlen) &&
-		    (chunkp->toc_data.len <= softp->iosramlen) &&
-		    ((chunkp->toc_data.off + chunkp->toc_data.len) <=
-		    softp->iosramlen)) {
-			chunkp->basep = softp->iosramp + chunkp->toc_data.off;
-			DPRINTF(1,
-			    ("iosram_read_toc(%d): k:%x o:%x l:%x p:%p\n",
-			    instance, chunkp->toc_data.key,
-			    chunkp->toc_data.off, chunkp->toc_data.len,
-			    (void *)chunkp->basep));
-		} else {
-			cmn_err(CE_WARN, "iosram(%d): TOC entry %d"
-			    "out of range... off:%x  len:%x\n",
-			    instance, i + 1, chunkp->toc_data.off,
-			    chunkp->toc_data.len);
-			kmem_free(new_chunks, new_nchunks *
-			    sizeof (iosram_chunk_t));
-			mutex_exit(&iosram_mutex);
-			return (EINVAL);
-		}
-
-		/*
-		 * Note the existence of the flags chunk, which is required in
-		 * a correct TOC.
-		 */
-		if (chunkp->toc_data.key == IOSRAM_FLAGS_KEY) {
-			flagsp = (iosram_flags_t *)chunkp->basep;
-		}
-
-		/*
-		 * If there was an entry for this chunk in the old list, copy
-		 * the callback data from old to new storage.
-		 */
-		if ((nchunks > 0) &&
-		    ((old_chunkp = iosram_find_chunk(chunkp->toc_data.key)) !=
-		    NULL)) {
-			bcopy(&(old_chunkp->cback), &(chunkp->cback),
-			    sizeof (iosram_cback_t));
-		}
-	}
-	/*
-	 * The TOC is malformed if there is no entry for the flags chunk.
-	 */
-	if (flagsp == NULL) {
-		kmem_free(new_chunks, new_nchunks * sizeof (iosram_chunk_t));
-		mutex_exit(&iosram_mutex);
-		return (EINVAL);
-	}
-
-	/*
-	 * Free any memory that is no longer needed and install the new data
-	 * as current data.
-	 */
-	if (chunks != NULL) {
-		kmem_free(chunks, nchunks * sizeof (iosram_chunk_t));
-	}
-	chunks = new_chunks;
-	nchunks = new_nchunks;
-	iosram_init_hashtab();
-
-	mutex_exit(&iosram_mutex);
-	return (0);
-}
-
-
-/*
- * iosram_init_hashtab()
- *
- *	Initialize the hash table and populate it with the IOSRAM
- *	chunks previously read from the TOC.  The caller must hold the
- *	ioram_mutex lock.
- */
-static void
-iosram_init_hashtab(void)
-{
-	int		i, bucket;
-	iosram_chunk_t	*chunkp;
-
-	ASSERT(mutex_owned(&iosram_mutex));
-
-	for (i = 0; i < IOSRAM_HASHSZ; i++) {
-		iosram_hashtab[i] = NULL;
-	}
-
-	if (chunks) {
-		for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
-			/*
-			 * Hide the flags chunk by leaving it out of the hash
-			 * table.
-			 */
-			if (chunkp->toc_data.key == IOSRAM_FLAGS_KEY) {
-				continue;
-			}
-
-			/*
-			 * Add the current chunk to the hash table.
-			 */
-			bucket = IOSRAM_HASH(chunkp->toc_data.key);
-			chunkp->hash = iosram_hashtab[bucket];
-			iosram_hashtab[bucket] = chunkp;
-		}
-	}
-}
-
-
-/*
- * iosram_update_addrs()
- *
- *	Process the chunk list, updating each chunk's basep, which is a pointer
- *	to the beginning of the chunk's memory in kvaddr space.  Record the
- *	basep value of the flags chunk to speed up flag access.  The caller
- *	must hold the iosram_mutex lock.
- */
-static void
-iosram_update_addrs(struct iosramsoft *softp)
-{
-	int		i;
-	iosram_flags_t	*flagsp;
-	iosram_chunk_t	*chunkp;
-
-	ASSERT(mutex_owned(&iosram_mutex));
-
-	/*
-	 * First go through all of the chunks updating their base pointers and
-	 * looking for the flags chunk.
-	 */
-	for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
-		chunkp->basep = softp->iosramp + chunkp->toc_data.off;
-		if (chunkp->toc_data.key == IOSRAM_FLAGS_KEY) {
-			flagsp = (iosram_flags_t *)(chunkp->basep);
-			DPRINTF(1,
-			    ("iosram_update_addrs flags: o:0x%08x p:%p",
-			    chunkp->toc_data.off, (void *)flagsp));
-		}
-	}
-
-	/*
-	 * Now, go through and update each chunk's flags pointer.  This can't be
-	 * done in the first loop because we don't have the address of the flags
-	 * chunk yet.
-	 */
-	for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
-		chunkp->flagsp = flagsp++;
-		DPRINTF(1, ("iosram_update_addrs: k:0x%x f:%p\n",
-		    chunkp->toc_data.key, (void *)chunkp->flagsp));
-	}
-}
-
-/*
- * iosram_find_chunk(key)
- *
- *	Return a pointer to iosram_chunk structure corresponding to the
- *	"key" IOSRAM chunk.  The caller must hold the iosram_mutex lock.
- */
-static iosram_chunk_t *
-iosram_find_chunk(uint32_t key)
-{
-	iosram_chunk_t	*chunkp;
-	int		index = IOSRAM_HASH(key);
-
-	ASSERT(mutex_owned(&iosram_mutex));
-
-	for (chunkp = iosram_hashtab[index]; chunkp; chunkp = chunkp->hash) {
-		if (chunkp->toc_data.key == key) {
-			break;
-		}
-	}
-
-	return (chunkp);
-}
-
-
-/*
- * iosram_add_intr(iosramsoft_t *)
- */
-static int
-iosram_add_intr(iosramsoft_t *softp)
-{
-	IOSRAMLOG(2, "ADDINTR: softp:%p  instance:%d\n",
-	    softp, softp->instance, NULL, NULL);
-
-	if (ddi_add_softintr(softp->dip, DDI_SOFTINT_MED,
-	    &softp->softintr_id, &softp->soft_iblk, NULL,
-	    iosram_softintr, (caddr_t)softp) != DDI_SUCCESS) {
-		cmn_err(CE_WARN,
-		    "iosram(%d): Can't register softintr.\n",
-		    softp->instance);
-		return (DDI_FAILURE);
-	}
-
-	if (ddi_add_intr(softp->dip, 0, &softp->real_iblk, NULL,
-	    iosram_intr, (caddr_t)softp) != DDI_SUCCESS) {
-		cmn_err(CE_WARN,
-		    "iosram(%d): Can't register intr"
-		    " handler.\n", softp->instance);
-		ddi_remove_softintr(softp->softintr_id);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * Enable SBBC interrupts
-	 */
-	ddi_put32(softp->sbbc_handle, &(softp->sbbc_region->int_enable.reg),
-	    IOSRAM_SBBC_INT0|IOSRAM_SBBC_INT1);
-
-	return (DDI_SUCCESS);
-}
-
-
-/*
- * iosram_remove_intr(iosramsoft_t *)
- */
-static int
-iosram_remove_intr(iosramsoft_t *softp)
-{
-	IOSRAMLOG(2, "REMINTR: softp:%p  instance:%d\n",
-	    softp, softp->instance, NULL, NULL);
-
-	/*
-	 * Disable SBBC interrupts if SBBC is mapped in
-	 */
-	if (softp->sbbc_region) {
-		ddi_put32(softp->sbbc_handle,
-		    &(softp->sbbc_region->int_enable.reg), 0);
-	}
-
-	/*
-	 * Remove SBBC interrupt handler
-	 */
-	ddi_remove_intr(softp->dip, 0, softp->real_iblk);
-
-	/*
-	 * Remove soft interrupt handler
-	 */
-	mutex_enter(&iosram_mutex);
-	if (softp->softintr_id != NULL) {
-		ddi_remove_softintr(softp->softintr_id);
-		softp->softintr_id = NULL;
-	}
-	mutex_exit(&iosram_mutex);
-
-	return (0);
-}
-
-
-/*
- * iosram_add_instance(iosramsoft_t *)
- * Must be called while holding iosram_mutex
- */
-static void
-iosram_add_instance(iosramsoft_t *new_softp)
-{
-#ifdef DEBUG
-	int		instance = new_softp->instance;
-	iosramsoft_t	*softp;
-#endif
-
-	ASSERT(mutex_owned(&iosram_mutex));
-
-#if defined(DEBUG)
-	/* Verify that this instance is not in the list */
-	for (softp = iosram_instances; softp != NULL; softp = softp->next) {
-		ASSERT(softp->instance != instance);
-	}
-#endif
-
-	/*
-	 * Add this instance to the list
-	 */
-	if (iosram_instances != NULL) {
-		iosram_instances->prev = new_softp;
-	}
-	new_softp->next = iosram_instances;
-	new_softp->prev = NULL;
-	iosram_instances = new_softp;
-}
-
-
-/*
- * iosram_remove_instance(int instance)
- * Must be called while holding iosram_mutex
- */
-static void
-iosram_remove_instance(int instance)
-{
-	iosramsoft_t *softp;
-
-	/*
-	 * Remove specified instance from the iosram_instances list so that
-	 * it can't be chosen for tunnel in future.
-	 */
-	ASSERT(mutex_owned(&iosram_mutex));
-
-	for (softp = iosram_instances; softp != NULL; softp = softp->next) {
-		if (softp->instance == instance) {
-			if (softp->next != NULL) {
-				softp->next->prev = softp->prev;
-			}
-			if (softp->prev != NULL) {
-				softp->prev->next = softp->next;
-			}
-			if (iosram_instances == softp) {
-				iosram_instances = softp->next;
-			}
-
-			return;
-		}
-	}
-}
-
-
-/*
- * iosram_sema_acquire: Acquire hardware semaphore.
- * Return 0 if the semaphore could be acquired, or one of the following
- * possible values:
- * EAGAIN: there is a tunnel switch in progress
- * EBUSY: the semaphore was already "held"
- * ENXIO:  an IO error occured (e.g. SBBC not mapped)
- * If old_value is not NULL, the location it points to will be updated
- * with the semaphore value read when attempting to acquire it.
- */
-int
-iosram_sema_acquire(uint32_t *old_value)
-{
-	struct iosramsoft	*softp;
-	int			rv;
-	uint32_t		sema_val;
-
-	DPRINTF(2, ("IOSRAM: in iosram_sema_acquire\n"));
-
-	mutex_enter(&iosram_mutex);
-
-	/*
-	 * Disallow access if there is a tunnel switch in progress.
-	 */
-	if (iosram_tswitch_active) {
-		mutex_exit(&iosram_mutex);
-		return (EAGAIN);
-	}
-
-	/*
-	 * Use current master IOSRAM for operation, fail if none is
-	 * currently active.
-	 */
-	if ((softp = iosram_master) == NULL) {
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM: iosram_sema_acquire: no master\n"));
-		return (ENXIO);
-	}
-
-	mutex_enter(&softp->intr_mutex);
-
-	/*
-	 * Fail if SBBC region has not been mapped. This shouldn't
-	 * happen if we have a master IOSRAM, but we double-check.
-	 */
-	if (softp->sbbc_region == NULL) {
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM(%d): iosram_sema_acquire: "
-		    "SBBC not mapped\n", softp->instance));
-		return (ENXIO);
-	}
-
-	/* read semaphore value */
-	sema_val = IOSRAM_SEMA_RD(softp);
-	if (old_value != NULL)
-		*old_value = sema_val;
-
-	if (IOSRAM_SEMA_IS_HELD(sema_val)) {
-		/* semaphore was held by someone else */
-		rv = EBUSY;
-	} else {
-		/* semaphore was not held, we just acquired it */
-		rv = 0;
-	}
-
-	mutex_exit(&softp->intr_mutex);
-	mutex_exit(&iosram_mutex);
-
-	DPRINTF(1, ("IOSRAM(%d): iosram_sema_acquire: "
-	    "old value=0x%x rv=%d\n", softp->instance, sema_val, rv));
-
-	return (rv);
-}
-
-
-/*
- * iosram_sema_release: Release hardware semaphore.
- * This function will "release" the hardware semaphore, and return 0 on
- * success. If an error occured, one of the following values will be
- * returned:
- * EAGAIN: there is a tunnel switch in progress
- * ENXIO:  an IO error occured (e.g. SBBC not mapped)
- */
-int
-iosram_sema_release(void)
-{
-	struct iosramsoft	*softp;
-
-	DPRINTF(2, ("IOSRAM: in iosram_sema_release\n"));
-
-	mutex_enter(&iosram_mutex);
-
-	/*
-	 * Disallow access if there is a tunnel switch in progress.
-	 */
-	if (iosram_tswitch_active) {
-		mutex_exit(&iosram_mutex);
-		return (EAGAIN);
-	}
-
-	/*
-	 * Use current master IOSRAM for operation, fail if none is
-	 * currently active.
-	 */
-	if ((softp = iosram_master) == NULL) {
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM: iosram_sema_release: no master\n"));
-		return (ENXIO);
-	}
-
-	mutex_enter(&softp->intr_mutex);
-
-	/*
-	 * Fail if SBBC region has not been mapped in. This shouldn't
-	 * happen if we have a master IOSRAM, but we double-check.
-	 */
-	if (softp->sbbc_region == NULL) {
-		mutex_exit(&softp->intr_mutex);
-		mutex_exit(&iosram_mutex);
-		DPRINTF(1, ("IOSRAM(%d): iosram_sema_release: "
-		    "SBBC not mapped\n", softp->instance));
-		return (ENXIO);
-	}
-
-	/* Release semaphore by clearing our semaphore register */
-	IOSRAM_SEMA_WR(softp, 0);
-
-	mutex_exit(&softp->intr_mutex);
-	mutex_exit(&iosram_mutex);
-
-	DPRINTF(1, ("IOSRAM(%d): iosram_sema_release: success\n",
-	    softp->instance));
-
-	return (0);
-}
-
-
-#if defined(IOSRAM_LOG)
-void
-iosram_log(caddr_t fmt, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
-{
-	uint32_t	seq;
-	iosram_log_t	*logp;
-
-	mutex_enter(&iosram_log_mutex);
-
-	seq = iosram_logseq++;
-	logp = &iosram_logbuf[seq % IOSRAM_MAXLOG];
-	logp->seq = seq;
-	logp->tstamp = ddi_get_lbolt();
-	logp->fmt = fmt;
-	logp->arg1 = a1;
-	logp->arg2 = a2;
-	logp->arg3 = a3;
-	logp->arg4 = a4;
-
-	mutex_exit(&iosram_log_mutex);
-
-	if (iosram_log_print) {
-		cmn_err(CE_CONT, "#%x @%lx ", logp->seq, logp->tstamp);
-		if (logp->fmt) {
-			cmn_err(CE_CONT, logp->fmt, logp->arg1, logp->arg2,
-			    logp->arg3, logp->arg4);
-			if (logp->fmt[strlen(logp->fmt)-1] != '\n') {
-				cmn_err(CE_CONT, "\n");
-			}
-		} else {
-			cmn_err(CE_CONT, "fmt:%p args: %lx %lx %lx %lx\n",
-			    (void *)logp->fmt, logp->arg1, logp->arg2,
-			    logp->arg3, logp->arg4);
-		}
-	}
-}
-#endif /* IOSRAM_LOG */
-
-
-#if defined(DEBUG)
-/*
- * iosram_get_keys(buf, len)
- *	Return IOSRAM TOC in the specified buffer
- */
-static int
-iosram_get_keys(iosram_toc_entry_t *bufp, uint32_t *len)
-{
-	struct iosram_chunk	*chunkp;
-	int			error = 0;
-	int			i;
-	int			cnt = (*len) / sizeof (iosram_toc_entry_t);
-
-	IOSRAMLOG(2, "iosram_get_keys(bufp:%p *len:%x)\n", bufp, *len, NULL,
-	    NULL);
-
-	/*
-	 * Copy data while holding the lock to prevent any data
-	 * corruption or invalid pointer dereferencing.
-	 */
-	mutex_enter(&iosram_mutex);
-
-	if (iosram_master == NULL) {
-		error = EIO;
-	} else {
-		for (i = 0, chunkp = chunks; i < nchunks && i < cnt;
-		    i++, chunkp++) {
-			bufp[i].key = chunkp->toc_data.key;
-			bufp[i].off = chunkp->toc_data.off;
-			bufp[i].len = chunkp->toc_data.len;
-			bufp[i].unused = chunkp->toc_data.unused;
-		}
-		*len = i * sizeof (iosram_toc_entry_t);
-	}
-
-	mutex_exit(&iosram_mutex);
-	return (error);
-}
-
-
-/*
- * iosram_print_state(instance)
- */
-static void
-iosram_print_state(int instance)
-{
-	struct iosramsoft	*softp;
-	char			pn[MAXNAMELEN];
-
-	if (instance < 0) {
-		softp = iosram_master;
-	} else {
-		softp = ddi_get_soft_state(iosramsoft_statep, instance);
-	}
-
-	if (softp == NULL) {
-		cmn_err(CE_CONT, "iosram_print_state: Can't find instance %d\n",
-		    instance);
-		return;
-	}
-	instance = softp->instance;
-
-	mutex_enter(&iosram_mutex);
-	mutex_enter(&softp->intr_mutex);
-
-	cmn_err(CE_CONT, "iosram_print_state(%d): ... %s\n", instance,
-	    ((softp == iosram_master) ? "MASTER" : "SLAVE"));
-
-	(void) ddi_pathname(softp->dip, pn);
-	cmn_err(CE_CONT, "  pathname:%s\n", pn);
-	cmn_err(CE_CONT, "  instance:%d  portid:%d iosramlen:0x%x\n",
-	    softp->instance, softp->portid, softp->iosramlen);
-	cmn_err(CE_CONT, "  softp:%p  handle:%p  iosramp:%p\n", (void *)softp,
-	    (void *)softp->handle, (void *)softp->iosramp);
-	cmn_err(CE_CONT, "  state:0x%x  tswitch_ok:%x  tswitch_fail:%x\n",
-	    softp->state, softp->tswitch_ok, softp->tswitch_fail);
-	cmn_err(CE_CONT, "  softintr_id:%p  intr_busy:%x  intr_pending:%x\n",
-	    (void *)softp->softintr_id, softp->intr_busy, softp->intr_pending);
-
-	mutex_exit(&softp->intr_mutex);
-	mutex_exit(&iosram_mutex);
-}
-
-
-/*
- * iosram_print_stats()
- */
-static void
-iosram_print_stats()
-{
-	uint32_t	calls;
-
-	cmn_err(CE_CONT, "iosram_stats:\n");
-	calls = iosram_stats.read;
-	cmn_err(CE_CONT, " read  ... calls:%x  bytes:%lx  avg_sz:%x\n",
-	    calls, iosram_stats.bread,
-	    (uint32_t)((calls != 0) ? (iosram_stats.bread/calls) : 0));
-
-	calls = iosram_stats.write;
-	cmn_err(CE_CONT, " write ... calls:%x  bytes:%lx  avg_sz:%x\n",
-	    calls, iosram_stats.bwrite,
-	    (uint32_t)((calls != 0) ? (iosram_stats.bwrite/calls) : 0));
-
-	cmn_err(CE_CONT, " intr recv (real:%x  soft:%x)  sent:%x  cback:%x\n",
-	    iosram_stats.intr_recv, iosram_stats.sintr_recv,
-	    iosram_stats.intr_send, iosram_stats.callbacks);
-
-	cmn_err(CE_CONT, " tswitch: %x  getflag:%x  setflag:%x\n",
-	    iosram_stats.tswitch, iosram_stats.getflag,
-	    iosram_stats.setflag);
-
-	cmn_err(CE_CONT, " iosram_rw_active_max: %x\n", iosram_rw_active_max);
-}
-
-
-static void
-iosram_print_cback()
-{
-	iosram_chunk_t	*chunkp;
-	int		i;
-
-	/*
-	 * Print callback handlers
-	 */
-	mutex_enter(&iosram_mutex);
-
-	cmn_err(CE_CONT, "IOSRAM callbacks:\n");
-	for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
-		if (chunkp->cback.handler) {
-			cmn_err(CE_CONT, "  %2d: key:0x%x  hdlr:%p  arg:%p "
-			    "busy:%d unreg:%d\n", i, chunkp->toc_data.key,
-			    (void *)chunkp->cback.handler,
-			    (void *)chunkp->cback.arg,
-			    chunkp->cback.busy, chunkp->cback.unregister);
-		}
-	}
-	mutex_exit(&iosram_mutex);
-}
-
-
-static void
-iosram_print_flags()
-{
-	int		i;
-	uint32_t	*keys;
-	iosram_flags_t	*flags;
-
-	mutex_enter(&iosram_mutex);
-
-	if (iosram_master == NULL) {
-		mutex_exit(&iosram_mutex);
-		cmn_err(CE_CONT, "IOSRAM Flags: not accessible\n");
-		return;
-	}
-
-	keys = kmem_alloc(nchunks * sizeof (uint32_t), KM_SLEEP);
-	flags = kmem_alloc(nchunks * sizeof (iosram_flags_t), KM_SLEEP);
-
-	for (i = 0; i < nchunks; i++) {
-		keys[i] = chunks[i].toc_data.key;
-		ddi_rep_get8(iosram_handle, (uint8_t *)&(flags[i]),
-		    (uint8_t *)(chunks[i].flagsp), sizeof (iosram_flags_t),
-		    DDI_DEV_AUTOINCR);
-	}
-
-	mutex_exit(&iosram_mutex);
-
-	cmn_err(CE_CONT, "IOSRAM Flags:\n");
-	for (i = 0; i < nchunks; i++) {
-		cmn_err(CE_CONT,
-		    "  %2d: key: 0x%x  data_valid:%x  int_pending:%x\n",
-		    i, keys[i], flags[i].data_valid, flags[i].int_pending);
-	}
-
-	kmem_free(keys, nchunks * sizeof (uint32_t));
-	kmem_free(flags, nchunks * sizeof (iosram_flags_t));
-}
-
-
-/*PRINTFLIKE1*/
-static void
-iosram_dprintf(const char *fmt, ...)
-{
-	char	msg_buf[256];
-	va_list	adx;
-
-	va_start(adx, fmt);
-	(void) vsprintf(msg_buf, fmt, adx);
-	va_end(adx);
-
-	cmn_err(CE_CONT, "%s", msg_buf);
-}
-#endif /* DEBUG */
-
-
-#if IOSRAM_LOG
-/*
- * iosram_print_log(int cnt)
- *	Print last few entries of the IOSRAM log in reverse order
- */
-static void
-iosram_print_log(int cnt)
-{
-	int	i;
-
-	if (cnt <= 0) {
-		cnt = 20;
-	} else if (cnt > IOSRAM_MAXLOG) {
-		cnt = IOSRAM_MAXLOG;
-	}
-
-
-	cmn_err(CE_CONT,
-	    "\niosram_logseq: 0x%x  lbolt: %lx  iosram_log_level:%x\n",
-	    iosram_logseq, ddi_get_lbolt(), iosram_log_level);
-	cmn_err(CE_CONT, "iosram_logbuf: %p  max entries:0x%x\n",
-	    (void *)iosram_logbuf, IOSRAM_MAXLOG);
-	for (i = iosram_logseq;  --i >= 0 && --cnt >= 0; ) {
-		iosram_log_t	*logp;
-
-		mutex_enter(&iosram_log_mutex);
-
-		logp = &iosram_logbuf[i %IOSRAM_MAXLOG];
-		cmn_err(CE_CONT, "#%x @%lx ", logp->seq, logp->tstamp);
-
-		if (logp->fmt) {
-			cmn_err(CE_CONT, logp->fmt, logp->arg1, logp->arg2,
-			    logp->arg3, logp->arg4);
-			if (logp->fmt[strlen(logp->fmt)-1] != '\n') {
-				cmn_err(CE_CONT, "\n");
-			}
-		} else {
-			cmn_err(CE_CONT, "fmt:%p args: %lx %lx %lx %lx\n",
-			    (void *)logp->fmt, logp->arg1, logp->arg2,
-			    logp->arg3, logp->arg4);
-		}
-
-		mutex_exit(&iosram_log_mutex);
-	}
-}
-#endif	/* IOSRAM_LOG */
--- a/usr/src/uts/sun4u/starcat/io/mboxsc.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2460 +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 file contains the implementation of the mboxsc module, a mailbox layer
- * built upon the Starcat IOSRAM driver.
- */
-
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/modctl.h>
-#include <sys/errno.h>
-#include <sys/ksynch.h>
-#include <sys/kmem.h>
-#include <sys/varargs.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/cmn_err.h>
-#include <sys/debug.h>
-#include <sys/sysmacros.h>
-
-#include <sys/iosramreg.h>
-#include <sys/iosramio.h>
-#include <sys/mboxsc.h>
-#include <sys/mboxsc_impl.h>
-
-/*
- * Debugging facility
- */
-#define	DBGACT_NONE	(0x00000000)
-#define	DBGACT_BREAK	(0x00000001)
-#define	DBGACT_SHOWPOS	(0x00000002)
-#define	DBGACT_DEFAULT	DBGACT_NONE
-
-#define	DBG_DEV		(0x00000001)
-#define	DBG_CALLS	(0x00000002)
-#define	DBG_RETS	(0x00000004)
-#define	DBG_ARGS	(0x00000008)
-#define	DBG_KMEM	(0x00000010)
-#define	DBG_ALL		(0xFFFFFFFF)
-
-#ifdef DEBUG
-static uint32_t	mboxsc_debug_mask = 0x00000000;
-#define	DPRINTF0(class, action, fmt) \
-	mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt))
-#define	DPRINTF1(class, action, fmt, arg1) \
-	mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
-	    (arg1))
-#define	DPRINTF2(class, action, fmt, arg1, arg2) \
-	mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
-	    (arg1), (arg2))
-#define	DPRINTF3(class, action, fmt, arg1, arg2, arg3) \
-	mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
-	    (arg1), (arg2), (arg3))
-#define	DPRINTF4(class, action, fmt, arg1, arg2, arg3, arg4) \
-	mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
-	    (arg1), (arg2), (arg3), (arg4))
-#define	DPRINTF5(class, action, fmt, arg1, arg2, arg3, arg4, arg5) \
-	mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
-	    (arg1), (arg2), (arg3), (arg4), (arg5))
-#else	/* DEBUG */
-#define	DPRINTF0(class, action, fmt)
-#define	DPRINTF1(class, action, fmt, arg1)
-#define	DPRINTF2(class, action, fmt, arg1, arg2)
-#define	DPRINTF3(class, action, fmt, arg1, arg2, arg3)
-#define	DPRINTF4(class, action, fmt, arg1, arg2, arg3, arg4)
-#define	DPRINTF5(class, action, fmt, arg1, arg2, arg3, arg4, arg5)
-#endif	/* DEBUG */
-
-/*
- * Basic constants
- */
-#ifndef TRUE
-#define	TRUE	(1)
-#endif	/* TRUE */
-#ifndef FALSE
-#define	FALSE	(0)
-#endif	/* FALSE */
-
-
-/*
- * Whenever mboxsc_init is called to create a new mailbox, an instance of
- * mboxsc_mbox_t is created and inserted into a hash table to maintain
- * various information about the mailbox.  The mbox_state, mbox_refcount, and
- * mbox_wait fields are all protected by the global mboxsc_lock mutex.
- * If lock contention between mailboxes becomes an issue, each mailbox will
- * need to be given its own mutex to protect the mbox_wait, mbox_state,
- * and mbox_update_wait fields.  The mbox_refcount field will probably need to
- * remain under global protection, however, since it is used to keep track of
- * the number of threads sleeping inside the mailbox's various synchronization
- * mechanisms and would consequently be difficult to protect using those same
- * mechanisms.
- */
-typedef struct mboxsc_mbox {
-	uint32_t		mbox_key;
-	int			mbox_direction;
-	void			(*mbox_callback)(void);
-	uint32_t		mbox_length;
-	uint16_t		mbox_refcount;
-	uint16_t		mbox_state;
-	kcondvar_t		mbox_wait;
-	mboxsc_msghdr_t		mbox_header;
-	struct mboxsc_mbox	*mbox_hash_next;
-} mboxsc_mbox_t;
-
-/*
- * Various state flags that can be set on a mailbox.  Multiple states may
- * be active at the same time.
- */
-#define	STATE_IDLE	(0x0000)
-#define	STATE_WRITING	(0x0001)
-#define	STATE_READING	(0x0002)
-#define	STATE_HDRVALID	(0x0004)
-
-/*
- * Timeout periods for mboxsc_putmsg and mboxsc_getmsg, converted to ticks
- * from the microsecond values found in mboxsc_impl.h.
- */
-#define	EAGAIN_POLL		(drv_usectohz(MBOXSC_EAGAIN_POLL_USECS))
-#define	PUTMSG_POLL		(drv_usectohz(MBOXSC_PUTMSG_POLL_USECS))
-#define	HWLOCK_POLL		(drv_usectohz(MBOXSC_HWLOCK_POLL_USECS))
-#define	LOOP_WARN_INTERVAL	(drv_usectohz(MBOXSC_USECS_PER_SECOND * 15))
-
-/*
- * Various tests that are performed on message header fields.
- */
-#define	IS_UNSOLICITED_TYPE(type)	((type) != MBOXSC_MSG_REPLY)
-#define	MSG_TYPE_MATCHES(type, msgp)	\
-	(((type) == 0) || ((type) & (msgp)->msg_type))
-#define	MSG_CMD_MATCHES(cmd, msgp)	\
-	(((cmd) == 0) || ((cmd) == (msgp)->msg_cmd))
-#define	MSG_TRANSID_MATCHES(tid, msgp)	\
-	(((tid) == 0) || ((tid) == (msgp)->msg_transid))
-
-/*
- * This macro can be used to determine the size of any field in the message
- * header (or any other struct, for that matter).
- */
-#define	FIELD_SIZE(type, field)		(sizeof (((type *)0)->field))
-
-/*
- * Mask used when generating unique transaction ID values.
- * This arbitrarily chosen value will be OR'd together with
- * a counter for each successive internally-generated transaction ID.
- */
-#define	TRANSID_GEN_MASK	(0xFFC0000000000000)
-
-/*
- * All existing mailboxes are stored in a hash table with HASHTBL_SIZE
- * entries so they can be rapidly accessed by their key values.
- */
-#define	HASHTBL_SIZE	(32)
-#define	HASH_KEY(key)	((((key) >> 24) ^ ((key) >> 16) ^ ((key) >> 9) ^\
-			    (key)) & (HASHTBL_SIZE - 1));
-
-/*
- * Unfortunately, it is necessary to calculate checksums on data split up
- * amongst different buffers in some cases.  Consequently, mboxsc_checksum
- * accepts a "seed" value as one of its parameters.  When first starting a
- * checksum calculation, the seed should be 0.
- */
-#define	CHKSUM_INIT	(0)
-
-/*
- * local variables
- */
-static kmutex_t		mboxsc_lock;
-static mboxsc_mbox_t	*mboxsc_hash_table[HASHTBL_SIZE];
-static uint32_t		mboxsc_flaglock_count;
-static uint32_t		mboxsc_active_version = MBOXSC_PROTOCOL_VERSION;
-static kcondvar_t	mboxsc_dereference_cv;
-
-/*
- * Structures from modctl.h used for loadable module support.
- * The mboxsc API is a "miscellaneous" module.
- */
-extern struct mod_ops mod_miscops;
-
-static struct modlmisc modlmisc = {
-	&mod_miscops,
-	"IOSRAM Mailbox API 'mboxsc'",
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modlmisc,
-	NULL
-};
-
-/*
- * Prototypes for local functions
- */
-static void		mboxsc_iosram_callback(void *arg);
-static void		mboxsc_hdrchange_callback(void);
-static int		mboxsc_add_mailbox(mboxsc_mbox_t *mailboxp);
-static void		mboxsc_close_mailbox(mboxsc_mbox_t *mailboxp);
-static void		mboxsc_hashinsert_mailbox(mboxsc_mbox_t *mailboxp);
-static mboxsc_mbox_t	*mboxsc_hashfind_mailbox_by_key(uint32_t key);
-static mboxsc_mbox_t	*mboxsc_hashremove_mailbox_by_key(uint32_t key);
-static mboxsc_chksum_t	mboxsc_checksum(mboxsc_chksum_t seed, uint8_t *buf,
-	uint32_t length);
-static int		mboxsc_lock_flags(uint8_t mandatory, clock_t deadline);
-static int		mboxsc_unlock_flags(uint8_t mandatory);
-static int		mboxsc_timed_read(clock_t deadline, uint32_t key,
-	uint32_t off, uint32_t len, caddr_t dptr);
-static int		mboxsc_timed_write(clock_t deadline, uint32_t key,
-	uint32_t off, uint32_t len, caddr_t dptr);
-static int		mboxsc_timed_get_flag(clock_t deadline, uint32_t key,
-	uint8_t *data_validp, uint8_t *int_pendingp);
-static int		mboxsc_timed_set_flag(clock_t deadline, uint32_t key,
-	uint8_t data_valid, uint8_t int_pending);
-static int		mboxsc_timed_send_intr(clock_t deadline);
-static int		mboxsc_expire_message(uint32_t key, int *resultp);
-static uint64_t		mboxsc_generate_transid(uint64_t prev_transid);
-static void		mboxsc_reference_mailbox(mboxsc_mbox_t *mailboxp);
-static void		mboxsc_dereference_mailbox(mboxsc_mbox_t *mailboxp);
-#ifdef DEBUG
-/*PRINTFLIKE5*/
-static void		mboxsc_dprintf(const char *file, int line,
-	uint32_t class, uint32_t action, const char *fmt, ...);
-int			mboxsc_debug(int cmd, void *arg);
-#endif /* DEBUG */
-
-
-/*
- * _init
- *
- * Loadable module support routine.  Initializes global lock and hash table.
- */
-int
-_init(void)
-{
-	int		i;
-	uint32_t	sms_version;
-	int		error = 0;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "_init called\n");
-
-	/*
-	 * Initialize all module resources.
-	 */
-	mutex_init(&mboxsc_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&mboxsc_dereference_cv, NULL, CV_DRIVER, NULL);
-
-	for (i = 0; i < HASHTBL_SIZE; i++) {
-		mboxsc_hash_table[i] = NULL;
-	}
-	mboxsc_flaglock_count = 0;
-
-	if (mod_install(&modlinkage) != 0) {
-		goto failed;
-	}
-
-	/*
-	 * Set the os_mbox_version field in the IOSRAM header to indicate the
-	 * highest Mailbox Protocol version we support
-	 */
-	error = iosram_hdr_ctrl(IOSRAM_HDRCMD_SET_OS_MBOX_VER,
-	    (void *)MBOXSC_PROTOCOL_VERSION);
-	if (error != 0) {
-		goto failed;
-	}
-
-	/*
-	 * Read the sms_mbox_version field in the IOSRAM header to determine
-	 * what the greatest commonly supported version is.
-	 */
-	error = iosram_hdr_ctrl(IOSRAM_HDRCMD_GET_SMS_MBOX_VER,
-	    (void *)&sms_version);
-	if (error != 0) {
-		goto failed;
-	}
-	mboxsc_active_version = MIN(MBOXSC_PROTOCOL_VERSION, sms_version);
-	DPRINTF2(DBG_DEV, DBGACT_DEFAULT,
-	    "sms version: %d, active version: %d\n", sms_version,
-	    mboxsc_active_version);
-
-	/*
-	 * Register a callback with the IOSRAM driver to receive notification of
-	 * changes to the IOSRAM header, in case the sms_mbox_version field
-	 * changes.
-	 */
-	error = iosram_hdr_ctrl(IOSRAM_HDRCMD_REG_CALLBACK,
-	    (void *)mboxsc_hdrchange_callback);
-	if (error != 0) {
-		goto failed;
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_init ret: 0x%08x\n", error);
-	return (0);
-
-	/*
-	 * If initialization fails, uninitialize resources.
-	 */
-failed:
-	mutex_destroy(&mboxsc_lock);
-	cv_destroy(&mboxsc_dereference_cv);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_init ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * _fini
- *
- * Loadable module support routine. Closes all mailboxes and releases all
- * resources.
- */
-int
-_fini(void)
-{
-	int		i;
-	int		error = 0;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "_fini called\n");
-
-	/*
-	 * Attempt to remove the module.  If successful, close all mailboxes
-	 * and deallocate the global lock.
-	 */
-	error = mod_remove(&modlinkage);
-	if (error == 0) {
-		mutex_enter(&mboxsc_lock);
-
-		(void) iosram_hdr_ctrl(IOSRAM_HDRCMD_REG_CALLBACK, NULL);
-
-		for (i = 0; i < HASHTBL_SIZE; i++) {
-			while (mboxsc_hash_table[i] != NULL) {
-				mailboxp = mboxsc_hash_table[i];
-				mboxsc_close_mailbox(mailboxp);
-			}
-		}
-		mutex_exit(&mboxsc_lock);
-		mutex_destroy(&mboxsc_lock);
-		cv_destroy(&mboxsc_dereference_cv);
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_fini ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * _info
- *
- * Loadable module support routine.
- */
-int
-_info(struct modinfo *modinfop)
-{
-	int		error = 0;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "_info called\n");
-
-	error = mod_info(&modlinkage, modinfop);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_info ret: 0x%08x\n", error);
-
-	return (error);
-}
-
-/*
- * mboxsc_init
- *
- * Attempts to create a new mailbox.
- */
-int
-mboxsc_init(uint32_t key, int direction, void (*event_handler)(void))
-{
-	int		error = 0;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_init called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "direction = %d\n", direction);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "event_handlerp = %p\n",
-	    (void *)event_handler);
-
-	/*
-	 * Check for valid direction and callback specification.
-	 */
-	if (((direction != MBOXSC_MBOX_IN) && (direction != MBOXSC_MBOX_OUT)) ||
-	    ((event_handler != NULL) && (direction != MBOXSC_MBOX_IN))) {
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_init ret: 0x%08x\n",
-		    EINVAL);
-		return (EINVAL);
-	}
-
-	/*
-	 * Allocate memory for the mailbox structure and initialize all
-	 * caller-provided fields.
-	 */
-	mailboxp = (mboxsc_mbox_t *)kmem_zalloc(sizeof (mboxsc_mbox_t),
-	    KM_SLEEP);
-	DPRINTF2(DBG_KMEM, DBGACT_DEFAULT, "kmem_zalloc(%lu) = %p\n",
-	    sizeof (mboxsc_mbox_t), (void *)mailboxp);
-	mailboxp->mbox_key = key;
-	mailboxp->mbox_direction = direction;
-	mailboxp->mbox_callback = event_handler;
-
-	/*
-	 * Attempt to add the mailbox.  If unsuccessful, free the allocated
-	 * memory.
-	 */
-	mutex_enter(&mboxsc_lock);
-	error = mboxsc_add_mailbox(mailboxp);
-	mutex_exit(&mboxsc_lock);
-
-	if (error != 0) {
-		DPRINTF2(DBG_KMEM, DBGACT_DEFAULT, "kmem_free(%p, %lu)\n",
-		    (void *)mailboxp, sizeof (mboxsc_mbox_t));
-		kmem_free(mailboxp, sizeof (mboxsc_mbox_t));
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_init ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_fini
- *
- * Closes the mailbox with the indicated key, if it exists.
- */
-int
-mboxsc_fini(uint32_t key)
-{
-	int		error = 0;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_fini called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-
-	/*
-	 * Attempt to close the mailbox.
-	 */
-	mutex_enter(&mboxsc_lock);
-	mailboxp = mboxsc_hashfind_mailbox_by_key(key);
-	if (mailboxp == NULL) {
-		error = EBADF;
-	} else {
-		while (mailboxp->mbox_refcount != 0) {
-			cv_wait(&mboxsc_dereference_cv, &mboxsc_lock);
-		}
-		mboxsc_close_mailbox(mailboxp);
-	}
-	mutex_exit(&mboxsc_lock);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_fini ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_putmsg
- *
- * Attempt to place a message into an outbound mailbox and signal the
- * recipient.  A successful return (0) indicates that the message was
- * successfully delivered.
- */
-int
-mboxsc_putmsg(uint32_t key, uint32_t type, uint32_t cmd, uint64_t *transidp,
-		uint32_t length, void *datap, clock_t timeout)
-{
-	int		i;
-	int		error = 0;
-	int		result;
-	int		lock_held = 0;
-	int		unlock_err;
-	uint8_t		data_valid;
-	clock_t		deadline;
-	clock_t		remainder;
-	mboxsc_chksum_t	checksum;
-	mboxsc_mbox_t	*mailboxp;
-	mboxsc_msghdr_t	header;
-
-#ifdef DEBUG /* because lint whines about if stmts without consequents */
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_putmsg called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "type = 0x%x\n", type);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "cmd = 0x%x\n", cmd);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "transidp = %p\n", (void *)transidp);
-	if (transidp != NULL) {
-		DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*transidp = 0x%016lx\n",
-		    *transidp);
-	}
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "length = 0x%x\n", length);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "datap = %p\n", datap);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "timeout = %ld\n", timeout);
-#endif /* DEBUG */
-
-	/*
-	 * Perform some basic sanity checks on the message.
-	 */
-	for (i = 0; i < MBOXSC_NUM_MSG_TYPES; i++) {
-		if (type == (1 << i)) {
-			break;
-		}
-	}
-	if ((i == MBOXSC_NUM_MSG_TYPES) || (cmd == 0) ||
-	    ((datap == NULL) && (length != 0)) ||
-	    (timeout < MBOXSC_PUTMSG_MIN_TIMEOUT_MSECS) ||
-	    (timeout > MBOXSC_PUTMSG_MAX_TIMEOUT_MSECS)) {
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_putmsg ret: 0x%08x\n", EINVAL);
-		return (EINVAL);
-	}
-
-	/*
-	 * Initialize the header structure with values provided by the caller.
-	 */
-	header.msg_version = mboxsc_active_version;
-	header.msg_type = type;
-	header.msg_cmd = cmd;
-	header.msg_length = MBOXSC_MSGHDR_SIZE + length;
-	if (transidp != NULL) {
-		header.msg_transid = *transidp;
-	} else {
-		header.msg_transid = 0;
-	}
-
-	/*
-	 * Perform additional sanity checks on the mailbox and message.
-	 * Make sure that the specified mailbox really exists, that the
-	 * given message will fit in it, and that the current message's
-	 * transaction ID isn't the same as the last message's transaction
-	 * ID unless both messages are replies (it's okay, necessary even,
-	 * to reuse a transaction ID when resending a failed reply message,
-	 * but that is the only case in which it is permissible).
-	 */
-	mutex_enter(&mboxsc_lock);
-	mailboxp = mboxsc_hashfind_mailbox_by_key(key);
-
-	if (mailboxp == NULL) {
-		error = EBADF;
-	} else if ((mailboxp->mbox_direction != MBOXSC_MBOX_OUT) ||
-	    (length + MBOXSC_PROTOCOL_SIZE > mailboxp->mbox_length) ||
-	    ((header.msg_transid == mailboxp->mbox_header.msg_transid) &&
-	    ((type & mailboxp->mbox_header.msg_type) != MBOXSC_MSG_REPLY) &&
-	    (header.msg_transid != 0))) {
-		error = EINVAL;
-	}
-
-	if (error != 0) {
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_putmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * If the message's transaction ID is set to 0, generate a unique
-	 * transaction ID and copy it into the message header.  If the message
-	 * is successfully delivered and transidp != NULL, we'll copy this new
-	 * transid into *transidp later.
-	 */
-	if (header.msg_transid == 0) {
-		header.msg_transid =
-		    mboxsc_generate_transid(mailboxp->mbox_header.msg_transid);
-	}
-
-	/*
-	 * Don't allow mboxsc_putmsg to attempt to place a message for
-	 * longer than the caller's timeout.
-	 */
-	deadline = ddi_get_lbolt() +
-	    drv_usectohz(timeout * MBOXSC_USECS_PER_MSEC);
-
-	/*
-	 * Increment the reference count on the mailbox to keep it from being
-	 * closed, and wait for it to become available.
-	 */
-	mboxsc_reference_mailbox(mailboxp);
-	remainder = 1;
-	while ((mailboxp->mbox_state & STATE_WRITING) &&
-	    (remainder > 0)) {
-		remainder = cv_timedwait_sig(&(mailboxp->mbox_wait),
-		    &mboxsc_lock, deadline);
-	}
-
-	/*
-	 * Check to see whether or not the mailbox became available.  If it
-	 * did not, decrement its reference count and return an error to the
-	 * caller.
-	 */
-	if (remainder == -1) {
-		error = ENOSPC;
-	} else if (remainder == 0) {
-		error = EINTR;
-	}
-
-	if (error != 0) {
-		mboxsc_dereference_mailbox(mailboxp);
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_putmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * Since the message is valid and we're going to try to write it to
-	 * IOSRAM, record its header for future reference (e.g. to make sure the
-	 * next message doesn't incorrectly use the same transID).
-	 */
-	bcopy(&header, &(mailboxp->mbox_header), MBOXSC_MSGHDR_SIZE);
-
-	/*
-	 * Flag the mailbox as being in use and release the global lock.
-	 */
-	mailboxp->mbox_state |= STATE_WRITING;
-	mutex_exit(&mboxsc_lock);
-
-	/*
-	 * Calculate the message checksum using the header and the data.
-	 */
-	checksum = mboxsc_checksum(CHKSUM_INIT, (uint8_t *)&header,
-	    MBOXSC_MSGHDR_SIZE);
-	checksum = mboxsc_checksum(checksum, (uint8_t *)datap, length);
-
-	/*
-	 * Attempt to write the message and checksum to IOSRAM until successful,
-	 * or as long as time remains and no errors other than EAGAIN are
-	 * returned from any call to the IOSRAM driver in case there is a tunnel
-	 * switch in progress.
-	 */
-	error = mboxsc_timed_write(deadline, key, MBOXSC_MSGHDR_OFFSET,
-	    MBOXSC_MSGHDR_SIZE, (caddr_t)&header);
-
-	if (error == 0) {
-		error = mboxsc_timed_write(deadline, key, MBOXSC_DATA_OFFSET,
-		    length, (caddr_t)datap);
-	}
-
-	if (error == 0) {
-		error = mboxsc_timed_write(deadline, key, header.msg_length,
-		    MBOXSC_CHKSUM_SIZE, (caddr_t)&checksum);
-	}
-
-	/*
-	 * Lock the flags before setting data_valid.  This isn't strictly
-	 * necessary for correct protocol operation, but it gives us a chance to
-	 * verify that the flags lock is functional before we commit to sending
-	 * the message.
-	 */
-	if (error == 0) {
-		error = mboxsc_lock_flags(FALSE, deadline);
-		if (error == 0) {
-			lock_held = 1;
-		} else if (error == EBUSY) {
-			error = EAGAIN;
-		}
-	}
-
-	if (error == 0) {
-		error = mboxsc_timed_set_flag(deadline, key, IOSRAM_DATA_VALID,
-		    IOSRAM_INT_TO_SSC);
-	}
-
-	/*
-	 * Unlock the flags.  If an error is encountered, only return it if
-	 * another error hasn't been encountered previously.
-	 */
-	if (lock_held) {
-		unlock_err = mboxsc_unlock_flags(TRUE);
-		if ((unlock_err != 0) && ((error == 0) || (error == EAGAIN))) {
-			error = unlock_err;
-		}
-	}
-
-	/*
-	 * If time ran out or an IOSRAM call failed, notify other callers that
-	 * the mailbox is available, decrement its reference count, and return
-	 * an error.
-	 */
-	if (error != 0) {
-		ASSERT((error != EINVAL) && (error != EMSGSIZE));
-		mutex_enter(&mboxsc_lock);
-		mailboxp->mbox_state &= ~STATE_WRITING;
-		cv_broadcast(&(mailboxp->mbox_wait));
-		mboxsc_dereference_mailbox(mailboxp);
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_putmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * Send an interrupt to the remote mailbox interface to announce the
-	 * presence of a new, valid message.
-	 */
-	error = mboxsc_timed_send_intr(deadline);
-
-	/*
-	 * Wait until either the data_valid flag is set INVALID by the
-	 * remote client or time runs out.  Since we're calling delay as
-	 * a part of polling the flag anyway, we don't really need to do
-	 * the usual continuous retry if iosram_get_flag returns EAGAIN.
-	 */
-	data_valid = IOSRAM_DATA_VALID;
-	if (error == DDI_SUCCESS) {
-		do {
-			delay(MIN(PUTMSG_POLL, deadline - ddi_get_lbolt()));
-			error = iosram_get_flag(key, &data_valid, NULL);
-		} while ((data_valid == IOSRAM_DATA_VALID) &&
-		    ((error == EAGAIN) || (error == 0)) &&
-		    (deadline - ddi_get_lbolt() >= 0));
-	}
-
-	/*
-	 * If the data_valid flag was set to INVALID by the other side, the
-	 * message was successfully transmitted.  If it wasn't, but there
-	 * weren't any IOSRAM errors, the operation timed out.  If there was a
-	 * problem with the IOSRAM, pass that info back to the caller.
-	 */
-	if (data_valid == IOSRAM_DATA_INVALID) {
-		result = 0;
-	} else if ((error == 0) || (error == DDI_FAILURE)) {
-		result = ETIMEDOUT;
-	} else {
-		ASSERT(error != EINVAL);
-		result = error;
-	}
-
-	/*
-	 * If the message has not been picked up, expire it. Note that this may
-	 * actually result in detecting successful message delivery if the SC
-	 * picks it up at the last moment.  If expiration fails due to an error,
-	 * return an error to the user even if the message appears to have
-	 * been successfully delivered.
-	 */
-	if (data_valid == IOSRAM_DATA_VALID) {
-		error = mboxsc_expire_message(key, &result);
-		if ((error != 0) && ((result == 0) || (result == ETIMEDOUT))) {
-			result = error;
-		}
-	}
-
-	/*
-	 * If the message was successfully delivered, and we generated a
-	 * transaction ID for the caller, and the caller wants to know what it
-	 * was, give it to them.
-	 */
-	if ((result == 0) && (transidp != NULL) && (*transidp == 0)) {
-		*transidp = header.msg_transid;
-	}
-
-	/*
-	 * Regardless of whether the message was successfully transmitted or
-	 * not, notify other callers that the mailbox is available and decrement
-	 * its reference count.
-	 */
-	mutex_enter(&mboxsc_lock);
-	mailboxp->mbox_state &= ~STATE_WRITING;
-	cv_broadcast(&(mailboxp->mbox_wait));
-	mboxsc_dereference_mailbox(mailboxp);
-	mutex_exit(&mboxsc_lock);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_putmsg ret: 0x%08x\n",
-	    result);
-	return (result);
-}
-
-/*
- * mboxsc_getmsg
- *
- * Attempt to retrieve a message from the mailbox with the given key that
- * matches values provided in msgp.  A successful return (0) indicates that
- * a message matching the caller's request was successfully received within
- * timeout milliseconds.  If a message matching the caller's request is
- * detected, but can't be successfully read, an error will be returned even
- * if the caller's timeout hasn't expired.
- */
-int
-mboxsc_getmsg(uint32_t key, uint32_t *typep, uint32_t *cmdp, uint64_t *transidp,
-		uint32_t *lengthp, void *datap, clock_t timeout)
-{
-	int		error = 0;
-	uint32_t	datalen;
-	uint8_t		data_valid;
-	uint8_t		lock_held;
-	mboxsc_chksum_t	read_checksum;
-	mboxsc_chksum_t	calc_checksum;
-	uint64_t	read_transid;
-	clock_t		deadline;
-	clock_t		remainder;
-	mboxsc_mbox_t	*mailboxp;
-	mboxsc_msghdr_t	header;
-
-#ifdef DEBUG /* because lint whines about if stmts without consequents */
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_getmsg called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "typep = %p\n", (void *)typep);
-	if (typep != NULL) {
-		DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*typep = 0x%x\n", *typep);
-	}
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "cmdp = %p\n", (void *)cmdp);
-	if (cmdp != NULL) {
-		DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*cmdp = 0x%x\n", *cmdp);
-	}
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "transidp = %p\n", (void *)transidp);
-	if (transidp != NULL) {
-		DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*transidp = 0x%lx\n",
-		    *transidp);
-	}
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "lengthp = %p\n", (void *)lengthp);
-	if (lengthp != NULL) {
-		DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*lengthp = 0x%x\n",
-		    *lengthp);
-	}
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "datap = %p\n", datap);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "timeout = %ld\n", timeout);
-#endif /* DEBUG */
-
-	/*
-	 * Perform basic sanity checks on the caller's request.
-	 */
-	if ((typep == NULL) || (*typep >= (1 << MBOXSC_NUM_MSG_TYPES)) ||
-	    (cmdp == NULL) || (transidp == NULL) || (lengthp == NULL) ||
-	    ((datap == NULL) && (*lengthp != 0)) ||
-	    (timeout < MBOXSC_GETMSG_MIN_TIMEOUT_MSECS) ||
-	    (timeout > MBOXSC_GETMSG_MAX_TIMEOUT_MSECS)) {
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_getmsg ret: 0x%08x\n", EINVAL);
-		return (EINVAL);
-	}
-
-	/*
-	 * Don't allow mboxsc_getmsg to attempt to receive a message for
-	 * longer than the caller's timeout.
-	 */
-	deadline = ddi_get_lbolt() +
-	    drv_usectohz(timeout * MBOXSC_USECS_PER_MSEC);
-
-	/*
-	 * Perform additional sanity checks on the client's request and the
-	 * associated mailbox.
-	 */
-	mutex_enter(&mboxsc_lock);
-	mailboxp = mboxsc_hashfind_mailbox_by_key(key);
-	if (mailboxp == NULL) {
-		error = EBADF;
-	} else if (mailboxp->mbox_direction != MBOXSC_MBOX_IN) {
-		error = EINVAL;
-	}
-
-	if (error != 0) {
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_getmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * The request is okay, so reference the mailbox (to keep it from being
-	 * closed), and proceed with the real work.
-	 */
-	mboxsc_reference_mailbox(mailboxp);
-
-	/*
-	 * Certain failures that may occur late in the process of getting a
-	 * message (e.g. checksum error, cancellation by the sender) are
-	 * supposed to leave the recipient waiting for the next message to
-	 * arrive rather than returning an error.  To facilitate restarting
-	 * the message acquisition process, the following label is provided
-	 * as a target for a very few judiciously-placed "goto"s.
-	 *
-	 * The mboxsc_lock mutex MUST be held when jumping to this point.
-	 */
-mboxsc_getmsg_retry:
-	;
-
-	/*
-	 * If there is a valid message in the mailbox right now, check to
-	 * see if it matches the caller's request.  If not, or if another
-	 * caller is already reading it, wait for either the arrival of the
-	 * next message or the expiration of the caller's specified timeout.
-	 */
-	error = 0;
-	while (!(mailboxp->mbox_state & STATE_HDRVALID) ||
-	    (mailboxp->mbox_state & STATE_READING) ||
-	    !MSG_TYPE_MATCHES(*typep, &(mailboxp->mbox_header)) ||
-	    !MSG_CMD_MATCHES(*cmdp, &(mailboxp->mbox_header)) ||
-	    !MSG_TRANSID_MATCHES(*transidp, &(mailboxp->mbox_header))) {
-		remainder = cv_timedwait_sig(&(mailboxp->mbox_wait),
-		    &mboxsc_lock, deadline);
-		if (remainder == -1) {
-			error = ETIMEDOUT;
-		} else if (remainder == 0) {
-			error = EINTR;
-		}
-
-		if (error != 0) {
-			mboxsc_dereference_mailbox(mailboxp);
-			mutex_exit(&mboxsc_lock);
-			DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-			    "mboxsc_getmsg ret: 0x%08x\n", error);
-			return (error);
-		}
-	}
-
-	/*
-	 * If somebody sends us a message using a Mailbox Protocol version
-	 * greater than the highest one we understand, invalidate the message,
-	 * because we can't safely interpret anything beyond the version field.
-	 */
-	if (mailboxp->mbox_header.msg_version > MBOXSC_PROTOCOL_VERSION) {
-		DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
-		    "incoming message with unsupported version %d\n",
-		    mailboxp->mbox_header.msg_version);
-		mailboxp->mbox_state &= ~STATE_HDRVALID;
-		goto mboxsc_getmsg_retry;
-	}
-
-	/*
-	 * At this point, there is a stored message header that matches the
-	 * caller's request, but the actual message may no longer be valid
-	 * in IOSRAM.  Check the data_valid flag to see whether or not
-	 * this is the case.  If the message has expired, go start over.
-	 *
-	 * The global mutex is held while reading flag data from IOSRAM to
-	 * avoid certain race conditions.  One race condition is still
-	 * possible (i.e. SC-side has just set the data_valid flag for a
-	 * new message, but the stored message header hasn't been updated
-	 * yet), but it won't cause incorrect behavior (just some wasted work).
-	 */
-	error = iosram_get_flag(key, &data_valid, NULL);
-
-	ASSERT(error != EINVAL);
-	if (error == 0) {
-		if (data_valid != IOSRAM_DATA_VALID) {
-			mailboxp->mbox_state &= ~STATE_HDRVALID;
-			goto mboxsc_getmsg_retry;
-		}
-	} else if ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0)) {
-		mutex_exit(&mboxsc_lock);
-		delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
-		mutex_enter(&mboxsc_lock);
-		goto mboxsc_getmsg_retry;
-	}
-
-	/*
-	 * If the message is larger than the caller's buffer, provide the caller
-	 * with the length of the message and return an error.
-	 */
-	datalen = mailboxp->mbox_header.msg_length - MBOXSC_MSGHDR_SIZE;
-	if ((error == 0) && (datalen > *lengthp)) {
-		*lengthp = datalen;
-		error = EMSGSIZE;
-	}
-
-	/*
-	 * Note that there's no need to check STATE_HDRVALID before broadcasting
-	 * here because the header is guaranteed to be valid at this point.
-	 */
-	if (error != 0) {
-		cv_broadcast(&(mailboxp->mbox_wait));
-		mboxsc_dereference_mailbox(mailboxp);
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_getmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * Store a copy of the current message header, flag the mailbox to
-	 * indicate that it is being read and attempt to read the message data
-	 * and checksum.
-	 */
-	bcopy(&(mailboxp->mbox_header), &header, MBOXSC_MSGHDR_SIZE);
-	mailboxp->mbox_state |= STATE_READING;
-	mutex_exit(&mboxsc_lock);
-
-	if (datalen > 0) {
-		error = mboxsc_timed_read(deadline, key, MBOXSC_DATA_OFFSET,
-		    datalen, (caddr_t)datap);
-	}
-
-	if (error == 0) {
-		error = mboxsc_timed_read(deadline, key, header.msg_length,
-		    MBOXSC_CHKSUM_SIZE, (caddr_t)&read_checksum);
-	}
-
-	/*
-	 * Check for errors that may have occurred while accessing IOSRAM.
-	 */
-	if (error != 0) {
-		ASSERT((error != EINVAL) && (error != EMSGSIZE));
-		mutex_enter(&mboxsc_lock);
-		mailboxp->mbox_state &= ~STATE_READING;
-		if (mailboxp->mbox_state & STATE_HDRVALID) {
-			cv_broadcast(&(mailboxp->mbox_wait));
-		}
-		mboxsc_dereference_mailbox(mailboxp);
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_getmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * Calculate the checksum for the header and data that was read from
-	 * IOSRAM.
-	 */
-	calc_checksum = mboxsc_checksum(CHKSUM_INIT, (uint8_t *)&header,
-	    MBOXSC_MSGHDR_SIZE);
-	calc_checksum = mboxsc_checksum(calc_checksum, (uint8_t *)datap,
-	    datalen);
-
-	/*
-	 * If the message header has been invalidated, note the change.
-	 * If a the checksum verification fails, invalidate the message
-	 * header.  In either case, go back to the beginning and wait
-	 * for a new message.
-	 */
-	mutex_enter(&mboxsc_lock);
-	if (!(mailboxp->mbox_state & STATE_HDRVALID)) {
-		error = -1;
-		DPRINTF0(DBG_DEV, DBGACT_DEFAULT,
-		    "mboxsc_getmsg - message invalidated while reading\n");
-	} else if (read_checksum != calc_checksum) {
-		error = -1;
-		mailboxp->mbox_state &= ~STATE_HDRVALID;
-		DPRINTF0(DBG_DEV, DBGACT_DEFAULT,
-		    "mboxsc_getmsg - message failed checksum\n");
-		cmn_err(CE_NOTE,
-		    "mboxsc_getmsg - message failed checksum\n");
-	}
-
-	if (error == -1) {
-		mailboxp->mbox_state &= ~STATE_READING;
-		goto mboxsc_getmsg_retry;
-	}
-
-	/*
-	 * Acquire the hardware lock used for synchronization of data_valid flag
-	 * access to avoid race conditions.  If it is acquired, try to check the
-	 * current data_valid flag and transaction ID to verify that the message
-	 * is still valid.
-	 */
-	mutex_exit(&mboxsc_lock);
-
-	if ((error = mboxsc_lock_flags(FALSE, deadline)) != 0) {
-		lock_held = FALSE;
-		/*
-		 * We don't "do" EBUSY here, so treat it as EAGAIN.
-		 */
-		if (error == EBUSY) {
-			error = EAGAIN;
-		}
-	} else {
-		lock_held = TRUE;
-	}
-
-	if (error == 0) {
-		error = mboxsc_timed_get_flag(deadline, key, &data_valid, NULL);
-	}
-
-	if ((error == 0) && (data_valid == IOSRAM_DATA_VALID)) {
-		error = mboxsc_timed_read(deadline, key,
-		    offsetof(mboxsc_msghdr_t, msg_transid),
-		    FIELD_SIZE(mboxsc_msghdr_t, msg_transid),
-		    (caddr_t)&read_transid);
-	}
-
-	/*
-	 * If something failed along the way, either the error is unrecoverable
-	 * or we're just plain out of time, so unlock the flags if they were
-	 * locked, release the mailbox, wake up other potential readers if
-	 * there's still a message around, and return.
-	 */
-	if (error != 0) {
-		ASSERT((error != EINVAL) && (error != EMSGSIZE));
-		if (lock_held) {
-			(void) mboxsc_unlock_flags(TRUE);
-		}
-		mutex_enter(&mboxsc_lock);
-		mailboxp->mbox_state &= ~STATE_READING;
-		if (mailboxp->mbox_state & STATE_HDRVALID) {
-			cv_broadcast(&(mailboxp->mbox_wait));
-		}
-		mboxsc_dereference_mailbox(mailboxp);
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_getmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * If the data_valid flag isn't set to IOSRAM_DATA_VALID, or the
-	 * message transaction ID in IOSRAM has changed, the message being
-	 * read was timed out by its sender.  Since the data_valid flag can't
-	 * change as long as we have the flags locked, we can safely mark the
-	 * stored message header invalid if either the data_valid flag isn't set
-	 * or the stored transaction ID doesn't match the one we read.  (If
-	 * data_valid is set, the transaction ID shouldn't be changing
-	 * underneath us.)  On the other hand, if there may still be a valid
-	 * message, wake up any pending readers.
-	 */
-	if ((data_valid != IOSRAM_DATA_VALID) ||
-	    (read_transid != header.msg_transid)) {
-		mutex_enter(&mboxsc_lock);
-		mailboxp->mbox_state &= ~STATE_READING;
-		if ((data_valid != IOSRAM_DATA_VALID) ||
-		    (mailboxp->mbox_header.msg_transid != read_transid)) {
-			mailboxp->mbox_state &= ~STATE_HDRVALID;
-		} else if (mailboxp->mbox_state & STATE_HDRVALID) {
-			cv_broadcast(&(mailboxp->mbox_wait));
-		}
-
-		/*
-		 * Unfortunately, we can't be holding mboxsc_lock when we unlock
-		 * the flags.  However, we have to hold the flags until here to
-		 * make sure the SC doesn't change the message's state while
-		 * we're checking to see if we should invalidate our stored
-		 * header.
-		 */
-		mutex_exit(&mboxsc_lock);
-		error = mboxsc_unlock_flags(TRUE);
-		mutex_enter(&mboxsc_lock);
-
-		DPRINTF0(DBG_DEV, DBGACT_DEFAULT,
-		    "mboxsc_getmsg() - message invalidated by sender\n");
-		goto mboxsc_getmsg_retry;
-	}
-
-	/*
-	 * If everything has worked up to this point, all that remains is
-	 * to set the data_valid flag to IOSRAM_DATA_INVALID, tidy up, and
-	 * return the message.  If the flag can't be set, the message can't
-	 * be received, so keep trying as long as there is time.
-	 */
-	error = mboxsc_timed_set_flag(deadline, key, IOSRAM_DATA_INVALID,
-	    IOSRAM_INT_NONE);
-
-	(void) mboxsc_unlock_flags(TRUE);
-	mutex_enter(&mboxsc_lock);
-
-	if (error != 0) {
-		ASSERT(error != EINVAL);
-		mboxsc_dereference_mailbox(mailboxp);
-		mailboxp->mbox_state &= ~STATE_READING;
-		if (mailboxp->mbox_state & STATE_HDRVALID) {
-			cv_broadcast(&(mailboxp->mbox_wait));
-		}
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_getmsg ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * If the message was read 100% successfully and the stored message
-	 * header for the mailbox still matches the message that was read,
-	 * invalidate it to prevent other readers from trying to read it.
-	 */
-	if (bcmp(&(mailboxp->mbox_header), &header, MBOXSC_MSGHDR_SIZE) == 0) {
-		mailboxp->mbox_state &= ~STATE_HDRVALID;
-	} else if (mailboxp->mbox_state & STATE_HDRVALID) {
-		cv_broadcast(&(mailboxp->mbox_wait));
-	}
-
-	mboxsc_dereference_mailbox(mailboxp);
-	mailboxp->mbox_state &= ~STATE_READING;
-	mutex_exit(&mboxsc_lock);
-
-	/*
-	 * Since we're successfully returning a message, we need to provide the
-	 * caller with all of the interesting header information.
-	 */
-	*typep = header.msg_type;
-	*cmdp = header.msg_cmd;
-	*transidp = header.msg_transid;
-	*lengthp = datalen;
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_getmsg ret: 0x%08x\n", 0);
-	return (0);
-}
-
-/*
- * mboxsc_ctrl
- *
- * This routine provides access to a variety of services not available through
- * the basic API.
- */
-int
-mboxsc_ctrl(uint32_t key, uint32_t cmd, void *arg)
-{
-	int		error = 0;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_ctrl called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "cmd = 0x%x\n", cmd);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "arg = %p\n", arg);
-
-	mutex_enter(&mboxsc_lock);
-	mailboxp = mboxsc_hashfind_mailbox_by_key(key);
-	if (mailboxp == NULL) {
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_ctrl ret: 0x%08x\n",
-		    EBADF);
-		return (EBADF);
-	}
-
-	switch (cmd) {
-		case MBOXSC_CMD_VERSION:
-			/*
-			 * Return the Protocol version currently in use.  Since
-			 * there is only one version that exists right now, we
-			 * can't be using anything else.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			*(uint32_t *)arg = MBOXSC_PROTOCOL_VERSION;
-			break;
-
-		case MBOXSC_CMD_MAXVERSION:
-			/*
-			 * Return the highest Protocol version that we support.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			*(uint32_t *)arg = MBOXSC_PROTOCOL_VERSION;
-			break;
-
-		case MBOXSC_CMD_MAXDATALEN:
-			/*
-			 * Return the amount of space available for client data
-			 * in the indicated mailbox.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			*(uint32_t *)arg = mailboxp->mbox_length -
-			    MBOXSC_PROTOCOL_SIZE;
-			break;
-
-		case MBOXSC_CMD_PUTMSG_TIMEOUT_RANGE:
-		{
-			mboxsc_timeout_range_t *rangep;
-
-			/*
-			 * Return the range of acceptable timeout values for
-			 * mboxsc_putmsg, expressed in milliseconds.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			rangep = (mboxsc_timeout_range_t *)arg;
-			rangep->min_timeout = MBOXSC_PUTMSG_MIN_TIMEOUT_MSECS;
-			rangep->max_timeout = MBOXSC_PUTMSG_MAX_TIMEOUT_MSECS;
-			break;
-		}
-
-		case MBOXSC_CMD_GETMSG_TIMEOUT_RANGE:
-		{
-			mboxsc_timeout_range_t *rangep;
-
-			/*
-			 * Return the range of acceptable timeout values for
-			 * mboxsc_getmsg, expressed in milliseconds.
-			 */
-			if (arg == NULL) {
-				error = EINVAL;
-				break;
-			}
-
-			rangep = (mboxsc_timeout_range_t *)arg;
-			rangep->min_timeout = MBOXSC_GETMSG_MIN_TIMEOUT_MSECS;
-			rangep->max_timeout = MBOXSC_GETMSG_MAX_TIMEOUT_MSECS;
-			break;
-		}
-
-		default:
-			error = ENOTSUP;
-			break;
-	}
-
-	mutex_exit(&mboxsc_lock);
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_ctrl ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_putmsg_def_timeout
- *
- * This routine returns the default mboxsc_putmsg timeout provided for the
- * convenience of clients.
- */
-clock_t
-mboxsc_putmsg_def_timeout(void)
-{
-	return (MBOXSC_PUTMSG_DEF_TIMEOUT_MSECS);
-}
-
-/*
- * mboxsc_iosram_callback
- *
- * This routine is registered with the IOSRAM driver for all inbound mailboxes,
- * and performs preliminary processing of all new messages.
- */
-static void
-mboxsc_iosram_callback(void *arg)
-{
-	int		error = 0;
-	uint8_t		data_valid;
-	uint32_t	key = (uint32_t)(uintptr_t)arg;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_iosram_callback called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "arg = 0x%x\n", key);
-
-	mutex_enter(&mboxsc_lock);
-	mailboxp = mboxsc_hashfind_mailbox_by_key(key);
-
-	/*
-	 * We shouldn't ever receive a callback for a mailbox that doesn't
-	 * exist or for an output mailbox.
-	 */
-	ASSERT(mailboxp != NULL);
-	ASSERT(mailboxp->mbox_direction == MBOXSC_MBOX_IN);
-
-	/*
-	 * Attempt to read the header of the mailbox.  If the IOSRAM returns
-	 * EAGAIN, indicating a tunnel switch is in progress, do not retry
-	 * the operation.
-	 */
-	mailboxp->mbox_state &= ~STATE_HDRVALID;
-	error = iosram_rd(key, MBOXSC_MSGHDR_OFFSET, MBOXSC_MSGHDR_SIZE,
-	    (caddr_t)&(mailboxp->mbox_header));
-
-	/*
-	 * If somebody sends us a message using a Mailbox Protocol version
-	 * greater than the highest one we understand, ignore the message,
-	 * because we can't safely interpret anything beyond the version field.
-	 */
-	if (mailboxp->mbox_header.msg_version > MBOXSC_PROTOCOL_VERSION) {
-		error = -1;
-		DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
-		    "incoming message with unsupported version %d\n",
-		    mailboxp->mbox_header.msg_version);
-	}
-
-	/*
-	 * If this message is a repeat of a previous message (which should
-	 * only happen with reply messages), it is conceivable that a client
-	 * already executing in mboxsc_getmsg for the previous message could
-	 * end up receiving the new message before this callback gets a chance
-	 * to execute.  If that happens, the data_valid flag will already have
-	 * been cleared.  Call iosram_get_flag to see if that is the case, and
-	 * do not process the message if it is.
-	 */
-	if (error == 0) {
-		error = iosram_get_flag(key, &data_valid, NULL);
-		if ((error == 0) && (data_valid != IOSRAM_DATA_VALID)) {
-			error = -1;
-		}
-	}
-
-	/*
-	 * If the iosram_rd call failed, return.
-	 */
-	if (error != 0) {
-		mutex_exit(&mboxsc_lock);
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_iosram_callback ret (0x%08x)\n", error);
-		return;
-	}
-
-	/*
-	 * If the message read from IOSRAM was unsolicited, invoke
-	 * its callback.  Otherwise, wake all threads that are waiting
-	 * in mboxsc_getmsg.
-	 */
-	mailboxp->mbox_state |= STATE_HDRVALID;
-	if (IS_UNSOLICITED_TYPE(mailboxp->mbox_header.msg_type) &&
-	    (mailboxp->mbox_callback != NULL)) {
-		mboxsc_reference_mailbox(mailboxp);
-		mutex_exit(&mboxsc_lock);
-		(*(mailboxp->mbox_callback))();
-		mutex_enter(&mboxsc_lock);
-		mboxsc_dereference_mailbox(mailboxp);
-	} else {
-		cv_broadcast(&(mailboxp->mbox_wait));
-	}
-
-	mutex_exit(&mboxsc_lock);
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_iosram_callback ret\n");
-}
-
-/*
- * mboxsc_hdrchange_callback
- *
- * This routine is registered with the IOSRAM driver to react to any changes SMS
- * makes to the IOSRAM header.
- */
-static void
-mboxsc_hdrchange_callback(void)
-{
-	int		error;
-	uint32_t	sms_version;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
-	    "mboxsc_hdrchange_callback called\n");
-
-	error = iosram_hdr_ctrl(IOSRAM_HDRCMD_GET_SMS_MBOX_VER,
-	    (void *)&sms_version);
-	if (error == 0) {
-		DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
-		    "sms mailbox version = %d\n", sms_version);
-		mboxsc_active_version = MIN(MBOXSC_PROTOCOL_VERSION,
-		    sms_version);
-	}
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_hdrchange_callback ret\n");
-}
-
-
-/*
- * mboxsc_add_mailbox
- *
- * If no other mailbox exists with the same key as this mailbox, attempt to
- * retrieve its length from the IOSRAM driver and register the mboxsc callback
- * for the associated IOSRAM chunk.  If successful, initialize the
- * non-client-supplied mailbox fields and insert it into the hash table.
- * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
- */
-static int
-mboxsc_add_mailbox(mboxsc_mbox_t *mailboxp)
-{
-	int		error = 0;
-	uint32_t	key = mailboxp->mbox_key;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_add_mailbox called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n", (void *)mailboxp);
-
-	/*
-	 * The global lock must be held by the caller.
-	 */
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	/*
-	 * Don't create the mailbox if it already exists.
-	 */
-	if (mboxsc_hashfind_mailbox_by_key(key) != NULL) {
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_add_mailbox ret: 0x%08x\n", EEXIST);
-		return (EEXIST);
-	}
-
-	/*
-	 * Obtain the mailbox length and register the mboxsc callback with the
-	 * IOSRAM driver.  If either call to the IOSRAM driver fails, or the
-	 * chunk is too small to be used as a mailbox, return an error to the
-	 * caller.
-	 */
-	error = iosram_ctrl(key, IOSRAM_CMD_CHUNKLEN, &(mailboxp->mbox_length));
-
-	if ((error == 0) && (mailboxp->mbox_length < MBOXSC_PROTOCOL_SIZE)) {
-		error = EFAULT;
-	}
-
-	if ((error == 0) && (mailboxp->mbox_direction == MBOXSC_MBOX_IN)) {
-		error = iosram_register(key, mboxsc_iosram_callback,
-		    (void *)(uintptr_t)(key));
-		if (error == EBUSY) {
-			error = EFAULT;
-		}
-	}
-
-	if (error != 0) {
-		DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-		    "mboxsc_add_mailbox ret: 0x%08x\n", error);
-		return (error);
-	}
-
-	/*
-	 * Initialize remaining mailbox fields and insert mailbox into
-	 * hash table.
-	 */
-	mailboxp->mbox_state = STATE_IDLE;
-	mailboxp->mbox_refcount = 0;
-	cv_init(&(mailboxp->mbox_wait), NULL, CV_DRIVER, NULL);
-	mboxsc_hashinsert_mailbox(mailboxp);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_add_mailbox ret: 0x%08x\n",
-	    0);
-	return (0);
-}
-
-/*
- * mboxsc_close_mailbox
- *
- * Remove a mailbox from the hash table, unregister its IOSRAM callback, and
- * deallocate its resources.
- * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
- */
-static void
-mboxsc_close_mailbox(mboxsc_mbox_t *mailboxp)
-{
-	int		error = 0;
-	uint32_t	key = mailboxp->mbox_key;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_close_mailbox called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n", (void *)mailboxp);
-
-	/*
-	 * The global lock must be held by the caller.
-	 */
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	/*
-	 * Unregister the mboxsc callback for this particular mailbox.
-	 */
-	if (mailboxp->mbox_direction == MBOXSC_MBOX_IN) {
-		error = iosram_unregister(key);
-		if (error == EINVAL) {
-			DPRINTF1(DBG_DEV, DBGACT_DEFAULT, "invalid key (0x%08x)"
-			    " reported in mboxsc_close_mailbox.\n", key);
-			error = 0;
-		}
-	}
-
-	/*
-	 * Remove the mailbox from the hash table and deallocate its resources.
-	 */
-	(void) mboxsc_hashremove_mailbox_by_key(key);
-	cv_destroy(&(mailboxp->mbox_wait));
-	DPRINTF2(DBG_KMEM, DBGACT_DEFAULT, "kmem_free(%p, %lu)\n",
-	    (void *)mailboxp, sizeof (mboxsc_mbox_t));
-	kmem_free(mailboxp, sizeof (mboxsc_mbox_t));
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_close_mailbox ret\n");
-}
-
-/*
- * mboxsc_hashinsert_mailbox
- *
- * Insert a fully initialized mailbox into the hash table.  No duplicate
- * checking is performed at this point, so the caller is responsible for
- * duplicate prevention if it is desired.
- * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
- */
-static void
-mboxsc_hashinsert_mailbox(mboxsc_mbox_t *mailboxp)
-{
-	uint32_t	hash;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
-	    "mboxsc_hashinsert_mailbox called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n", (void *)mailboxp);
-
-	/*
-	 * The global lock must be held by the caller.
-	 */
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	hash = HASH_KEY(mailboxp->mbox_key);
-	mailboxp->mbox_hash_next = mboxsc_hash_table[hash];
-	mboxsc_hash_table[hash] = mailboxp;
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_hashinsert_mailbox ret\n");
-}
-
-/*
- * mboxsc_hashfind_mailbox_by_key
- *
- * Locate a mailbox with the given key in the hash table.  Return a pointer
- * to the mailbox if it exists, or NULL if no matching mailbox is found.
- * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
- */
-static mboxsc_mbox_t *
-mboxsc_hashfind_mailbox_by_key(uint32_t key)
-{
-	uint32_t	hash;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
-	    "mboxsc_hashfind_mailbox_by_key called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-
-	/*
-	 * The global lock must be held by the caller.
-	 */
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	hash = HASH_KEY(key);
-	mailboxp = mboxsc_hash_table[hash];
-	while (mailboxp != NULL) {
-		if (mailboxp->mbox_key == key) {
-			break;
-		}
-		mailboxp = mailboxp->mbox_hash_next;
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_hashfind_mailbox_by_key ret: %p\n", (void *)mailboxp);
-	return (mailboxp);
-}
-
-/*
- * mboxsc_hashremove_mailbox_by_key
- *
- * Locate a mailbox with the given key in the hash table.  If it exists,
- * remove it from the hash table and return a pointer to it.  Otherwise,
- * return NULL.
- * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
- */
-static mboxsc_mbox_t *
-mboxsc_hashremove_mailbox_by_key(uint32_t key)
-{
-	uint32_t	hash;
-	mboxsc_mbox_t	*mailboxp;
-	mboxsc_mbox_t	*last;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
-	    "mboxsc_hashremove_mailbox_by_key called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-
-	/*
-	 * The global lock must be held by the caller.
-	 */
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	hash = HASH_KEY(key);
-	mailboxp = mboxsc_hash_table[hash];
-	last = NULL;
-	while (mailboxp != NULL) {
-		if (mailboxp->mbox_key == key) {
-			break;
-		}
-		last = mailboxp;
-		mailboxp = mailboxp->mbox_hash_next;
-	}
-
-	/*
-	 * If a mailbox was found, remove it from the hash table.
-	 */
-	if (mailboxp != NULL) {
-		if (last == NULL) {
-			mboxsc_hash_table[hash] = mailboxp->mbox_hash_next;
-		} else {
-			last->mbox_hash_next = mailboxp->mbox_hash_next;
-		}
-
-		mailboxp->mbox_hash_next = NULL;
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_hashremove_mailbox_by_key ret: %p\n", (void *)mailboxp);
-	return (mailboxp);
-}
-
-/*
- * mboxsc_checksum
- *
- * Given a pointer to a data buffer and its length, calculate the checksum of
- * the data contained therein.
- */
-static mboxsc_chksum_t
-mboxsc_checksum(mboxsc_chksum_t seed, uint8_t *buf, uint32_t length)
-{
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_checksum called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "seed = 0x%x\n", seed);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "buf = %p\n", (void *)buf);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "length = 0x%x\n", length);
-
-	while (length-- > 0) {
-		seed += *(buf++);
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_checksum ret: 0x%08x\n",
-	    seed);
-	return (seed);
-}
-
-/*
- * mboxsc_lock_flags
- *
- * Acquire the hardware lock used for data_valid flag synchronization.  If the
- * lock is currently held by SMS and acquisition is mandatory, just keep on
- * trying until it is acquired.  If acquisition is not mandatory, keep trying
- * until the given deadline has been reached.  To avoid loading the system
- * unreasonably on EBUSY or EAGAIN, sleep for an appropriate amount of time
- * before retrying.  If a hardware error is encountered return it to the caller.
- *
- * If the lock is held, but not by SMS, clear it and acquire it.  Nobody
- * else should be grabbing that lock.
- */
-static int
-mboxsc_lock_flags(uint8_t mandatory, clock_t deadline)
-{
-	int		error;
-	int		warned = 0;
-	uint32_t	sema;
-	clock_t		pause;
-	clock_t		warning_time = ddi_get_lbolt() + LOOP_WARN_INTERVAL;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_lock_flags called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mandatory = 0x%x\n", mandatory);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
-
-	/*
-	 * Keep trying to acquire the lock until successful or (if acquisition
-	 * is not mandatory) time runs out.  If EBUSY (lock is already held) or
-	 * EAGAIN (tunnel switch in progress) is encountered, sleep for an
-	 * appropriate amount of time before retrying.  Any other error is
-	 * unrecoverable.
-	 */
-	do {
-		pause = 0;
-
-		/*
-		 * Since multiple threads could conceivably want the flag lock
-		 * at the same time, we place the lock under a mutex and keep a
-		 * counter indicating how many threads have the flags locked at
-		 * the moment.
-		 */
-		mutex_enter(&mboxsc_lock);
-		if ((mboxsc_flaglock_count > 0) ||
-		    ((error = iosram_sema_acquire(&sema)) == 0)) {
-			mboxsc_flaglock_count++;
-			mutex_exit(&mboxsc_lock);
-
-			if (warned) {
-				cmn_err(CE_WARN, "Flags locked");
-			}
-			DPRINTF0(DBG_RETS, DBGACT_DEFAULT,
-			    "mboxsc_lock_flags ret: 0\n");
-			return (0);
-		}
-
-		/*
-		 * If iosram_sema_acquire returned EBUSY (lock already held),
-		 * make sure the lock is held by SMS, since nobody else should
-		 * ever be holding it.  If EBUSY or EAGAIN (tunnel switch in
-		 * progress) was returned, determine the appropriate amount of
-		 * time to sleep before trying again.
-		 */
-		if (error == EBUSY) {
-			if (IOSRAM_SEMA_GET_IDX(sema) != IOSRAM_SEMA_SMS_IDX) {
-				(void) iosram_sema_release();
-				cmn_err(CE_WARN,
-				    "Incorrect flag lock value read (0x%08x)",
-				    sema);
-			} else {
-				pause = (mandatory ? HWLOCK_POLL :
-				    MIN(HWLOCK_POLL, deadline -
-				    ddi_get_lbolt()));
-			}
-		} else if (error == EAGAIN) {
-			pause = (mandatory ? EAGAIN_POLL : MIN(EAGAIN_POLL,
-			    deadline - ddi_get_lbolt()));
-		}
-
-		/*
-		 * We had to hold the lock until now to protect the potential
-		 * iosram_sema_release call above.
-		 */
-		mutex_exit(&mboxsc_lock);
-
-		/*
-		 * If EAGAIN or EBUSY was encountered, we're looping.
-		 */
-		if ((error == EAGAIN) || (error == EBUSY)) {
-			/*
-			 * If we've been looping here for a while, something is
-			 * probably wrong, so we should generated a warning.
-			 */
-			if (warning_time - ddi_get_lbolt() <= 0) {
-				if (!warned) {
-					warned = 1;
-					cmn_err(CE_WARN,
-					    "Unable to lock flags (0x%08x)",
-					    error);
-				} else {
-					cmn_err(CE_WARN,
-					    "Still unable to lock flags");
-				}
-				warning_time = ddi_get_lbolt() +
-				    LOOP_WARN_INTERVAL;
-			}
-
-			/*
-			 * Sleep a while before trying again.
-			 */
-			delay(pause);
-		}
-	} while (((error == EAGAIN) || (error == EBUSY)) &&
-	    (mandatory || (deadline - ddi_get_lbolt() >= 0)));
-
-	/*
-	 * If something really bad has happened, generate a warning.
-	 */
-	if ((error != EAGAIN) && (error != EBUSY)) {
-		cmn_err(CE_WARN, "Flag locking failed! (%d)", error);
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_lock_flags ret: 0x%08x\n",
-	    error);
-	return (error);
-}
-
-/*
- * mboxsc_unlock_flags
- *
- * Release the hardware lock used for data_valid flag synchronization.
- * If a hardware error is encountered, return it to the caller.  If the
- * mandatory flag is set, loop and retry if EAGAIN is encountered.
- */
-static int
-mboxsc_unlock_flags(uint8_t mandatory)
-{
-	int	error;
-	int	warned = 0;
-	clock_t	warning_time = ddi_get_lbolt() + LOOP_WARN_INTERVAL;
-
-	ASSERT(mboxsc_flaglock_count != 0);
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_unlock_flags called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mandatory = 0x%x\n", mandatory);
-
-	do {
-		/*
-		 * Since multiple threads could conceivably want the flag lock
-		 * at the same time, we place the lock under a mutex and keep a
-		 * counter indicating how many threads have the flags locked at
-		 * the moment.
-		 */
-		mutex_enter(&mboxsc_lock);
-		if ((mboxsc_flaglock_count > 1) ||
-		    ((error = iosram_sema_release()) == 0)) {
-			mboxsc_flaglock_count--;
-			mutex_exit(&mboxsc_lock);
-
-			if (warned) {
-				cmn_err(CE_WARN, "Flags unlocked");
-			}
-			DPRINTF0(DBG_RETS, DBGACT_DEFAULT,
-			    "mboxsc_unlock_flags ret: 0\n");
-			return (0);
-		}
-		mutex_exit(&mboxsc_lock);
-
-		/*
-		 * If iosram_sema_release returned EAGAIN (tunnel switch in
-		 * progress) and unlocking the flags is mandatory, sleep before
-		 * trying again.  If we've been trying for a while, display a
-		 * warning message too.
-		 */
-		if ((error == EAGAIN) && mandatory) {
-			if (warning_time - ddi_get_lbolt() <= 0) {
-				if (!warned) {
-					warned = 1;
-					cmn_err(CE_WARN, "Unable to unlock "
-					    "flags (iosram EAGAIN)");
-				} else {
-					cmn_err(CE_WARN,
-					    "Still unable to unlock flags");
-				}
-				warning_time = ddi_get_lbolt() +
-				    LOOP_WARN_INTERVAL;
-			}
-
-			delay(EAGAIN_POLL);
-		}
-	} while ((error == EAGAIN) && mandatory);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_unlock_flags ret: 0x%08x\n",
-	    error);
-	return (error);
-}
-
-/*
- * mboxsc_timed_read
- *
- * This function is just a wrapper around iosram_rd that will keep sleeping
- * and retrying, up to a given deadline, if iosram_rd returns EAGAIN
- * (presumably due to a tunnel switch).
- */
-static int
-mboxsc_timed_read(clock_t deadline, uint32_t key, uint32_t off, uint32_t len,
-	caddr_t dptr)
-{
-	int error;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_read called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "off = 0x%x\n", off);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "len = 0x%x\n", len);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "dptr = %p\n", (void *)dptr);
-
-	do {
-		error = iosram_rd(key, off, len, dptr);
-		if (error == EAGAIN) {
-			delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
-		}
-	} while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_timed_read ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_timed_write
- *
- * This function is just a wrapper around iosram_wr that will keep sleeping
- * and retrying, up to a given deadline, if iosram_wr returns EAGAIN
- * (presumably due to a tunnel switch).
- */
-static int
-mboxsc_timed_write(clock_t deadline, uint32_t key, uint32_t off, uint32_t len,
-	caddr_t dptr)
-{
-	int error;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_write called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "off = 0x%x\n", off);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "len = 0x%x\n", len);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "dptr = %p\n", (void *)dptr);
-
-	do {
-		error = iosram_wr(key, off, len, dptr);
-		if (error == EAGAIN) {
-			delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
-		}
-	} while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_timed_write ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_timed_get_flag
- *
- * This function is just a wrapper around iosram_get_flag that will keep
- * sleeping and retrying, up to a given deadline, if iosram_get_flag returns
- * EAGAIN (presumably due to a tunnel switch).
- */
-static int
-mboxsc_timed_get_flag(clock_t deadline, uint32_t key, uint8_t *data_validp,
-	uint8_t *int_pendingp)
-{
-	int error;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_get_flag called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "data_validp = %p\n",
-	    (void *)data_validp);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "int_pendingp = %p\n",
-	    (void *)int_pendingp);
-
-	do {
-		error = iosram_get_flag(key, data_validp, int_pendingp);
-		if (error == EAGAIN) {
-			delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
-		}
-	} while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_timed_get_flag ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_timed_set_flag
- *
- * This function is just a wrapper around iosram_set_flag that will keep
- * sleeping and retrying, up to a given deadline, if iosram_set_flag returns
- * EAGAIN (presumably due to a tunnel switch).
- */
-static int
-mboxsc_timed_set_flag(clock_t deadline, uint32_t key, uint8_t data_valid,
-	uint8_t int_pending)
-{
-	int error;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_set_flag called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "data_valid = %d\n", data_valid);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "int_pending = %d\n", int_pending);
-
-	do {
-		error = iosram_set_flag(key, data_valid, int_pending);
-		if (error == EAGAIN) {
-			delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
-		}
-	} while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_timed_set_flag ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_timed_send_intr
- *
- * This function is just a wrapper around iosram_send_intr that will keep
- * sleeping and retrying, up to a given deadline, if iosram_send_intr returns
- * EAGAIN (presumably due to a tunnel switch).
- */
-static int
-mboxsc_timed_send_intr(clock_t deadline)
-{
-	int error;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_send_intr called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
-
-	do {
-		error = iosram_send_intr();
-		if (error == DDI_FAILURE) {
-			delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
-		}
-	} while ((error == DDI_FAILURE) && (deadline - ddi_get_lbolt() >= 0));
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_timed_send_intr ret: 0x%08x\n", error);
-	return (error);
-}
-
-/*
- * mboxsc_expire_message
- *
- * This function is called by mboxsc_putmsg to handle expiration of messages
- * that weren't picked up before they timed out.  It will not return until the
- * message has been picked up (which isn't expected), the message has been
- * successfully expired, or a serious error has been encountered.  If the
- * message is finally picked up, it will set the value pointed to by "resultp"
- * to 0.  Unlike other sections of code, this function will never time out on
- * EAGAIN from the iosram driver, since it is important that both sides of the
- * IOSRAM agree on whether or not a message was delivered successfully.
- */
-static int
-mboxsc_expire_message(uint32_t key, int *resultp)
-{
-	int	error = 0;
-	int	lock_held = 0;
-	int	warned = 0;
-	uint8_t	data_valid;
-	clock_t	warning_time = ddi_get_lbolt() + LOOP_WARN_INTERVAL;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_expire_message called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "resultp = %p\n", (void *)resultp);
-
-	do {
-		error = 0;
-
-		/*
-		 * Lock the flags if they aren't locked already.
-		 */
-		if (!lock_held) {
-			error = mboxsc_lock_flags(TRUE, 0);
-			if (error == 0) {
-				lock_held = 1;
-			}
-		}
-
-		/*
-		 * If the flags were locked successfully, reread the data-valid
-		 * flag.
-		 */
-		if (error == 0) {
-			error = iosram_get_flag(key, &data_valid, NULL);
-		}
-
-		/*
-		 * If the data-valid flag was read successfully, see if it has
-		 * been cleared or not, as the other side may have finally read
-		 * the message.
-		 */
-		if (error == 0) {
-			if (data_valid == IOSRAM_DATA_INVALID) {
-				/*
-				 * Surprise!  The SC finally picked up the
-				 * message, so delivery succeeded after all.
-				 */
-				if (*resultp == ETIMEDOUT) {
-					*resultp = 0;
-				}
-			} else {
-				/*
-				 * The message still hasn't been read, so try to
-				 * clear the data-valid flag.
-				 */
-				error = iosram_set_flag(key,
-				    IOSRAM_DATA_INVALID, IOSRAM_INT_NONE);
-			}
-		}
-
-		/*
-		 * If the flags were locked, unlock them, no matter what else
-		 * has or has not succeeded.  Don't overwrite the existing value
-		 * of "error" unless no errors other than EAGAIN have been
-		 * encountered previously.  If we hit EAGAIN at some point,
-		 * unlocking the flags here is optional.  In all other cases, it
-		 * is mandatory.
-		 */
-		if (lock_held) {
-			int unlock_err;
-
-			if (error == EAGAIN) {
-				unlock_err = mboxsc_unlock_flags(FALSE);
-			} else {
-				unlock_err = mboxsc_unlock_flags(TRUE);
-			}
-
-			if (unlock_err == 0) {
-				lock_held = 0;
-			} else if ((error == 0) || (error == EAGAIN)) {
-				error = unlock_err;
-			}
-		}
-
-		/*
-		 * Did we hit a tunnel switch? (iosram driver returns EAGAIN)
-		 * If so, sleep for a while before trying the whole process
-		 * again.
-		 */
-		if (error == EAGAIN) {
-			/*
-			 * If we've been stuck in this loop for a while,
-			 * something is probably wrong, and we should display a
-			 * warning.
-			 */
-			if (warning_time - ddi_get_lbolt() <= 0) {
-				if (!warned) {
-					warned = 1;
-					cmn_err(CE_WARN, "Unable to clear flag "
-					    "(iosram EAGAIN)");
-				} else {
-					cmn_err(CE_WARN,
-					    "Still unable to clear flag");
-				}
-				warning_time = ddi_get_lbolt() +
-				    LOOP_WARN_INTERVAL;
-			}
-
-			delay(EAGAIN_POLL);
-		}
-	} while (error == EAGAIN);
-
-	/*
-	 * If the data-valid flag was not successfully cleared due to some sort
-	 * of problem, report it.  Otherwise, if we looped for a while on EAGAIN
-	 * and generated a warning about it, indicate that everything is okay
-	 * now.
-	 */
-	if (error != 0) {
-		cmn_err(CE_WARN, "Message expiration failure! (%d)", error);
-	} else if (warned) {
-		cmn_err(CE_WARN, "Flag cleared");
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_expire_message ret: 0x%08x\n", error);
-	return (error);
-}
-
-
-/*
- * mboxsc_generate_transid
- *
- * This function generates unique transaction IDs using an incrementing counter.
- * The value generated is guaranteed not to be the same as the prev_transid
- * value passed in by the caller.
- */
-static uint64_t
-mboxsc_generate_transid(uint64_t prev_transid)
-{
-	uint64_t	new_transid;
-	static uint64_t	transid_counter = 0;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_generate_transid called");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "prev_transid = 0x%016lx\n",
-	    prev_transid);
-
-	do {
-		new_transid = TRANSID_GEN_MASK | transid_counter++;
-		if (transid_counter & TRANSID_GEN_MASK) {
-			transid_counter = 0;
-		}
-	} while (new_transid == prev_transid);
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "mboxsc_generate_transid ret: 0x%016lx", new_transid);
-	return (new_transid);
-}
-
-
-/*
- * mboxsc_reference_mailbox
- *
- * Increment the mailbox's reference count to prevent it from being closed.
- * This really doesn't deserve to be a function, but since a dereference
- * function is needed, having a corresponding reference function makes the code
- * clearer.
- */
-static void
-mboxsc_reference_mailbox(mboxsc_mbox_t *mailboxp)
-{
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_reference_mailbox called");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = 0x%p\n",
-	    (void *)mailboxp);
-
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	mailboxp->mbox_refcount++;
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_reference_mailbox ret");
-}
-
-
-/*
- * mboxsc_dereference_mailbox
- *
- * Decrement the mailbox's reference count, and if the count has gone to zero,
- * signal any threads waiting for mailboxes to be completely dereferenced.
- */
-static void
-mboxsc_dereference_mailbox(mboxsc_mbox_t *mailboxp)
-{
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
-	    "mboxsc_dereference_mailbox called");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = 0x%p\n",
-	    (void *)mailboxp);
-
-	ASSERT(mutex_owned(&mboxsc_lock));
-
-	mailboxp->mbox_refcount--;
-	if (mailboxp->mbox_refcount == 0) {
-		cv_broadcast(&mboxsc_dereference_cv);
-	}
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_dereference_mailbox ret");
-}
-
-
-#ifndef DEBUG
-/* ARGSUSED */
-int
-mboxsc_debug(int cmd, void *arg)
-{
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_debug called");
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_debug ret");
-	return (ENOTSUP);
-}
-#else	/* DEBUG */
-
-static void	print_hash_table(void);
-static int	print_mailbox_by_key(uint32_t key);
-static void	print_mailbox(mboxsc_mbox_t *mailboxp);
-
-int
-mboxsc_debug(int cmd, void *arg)
-{
-	int		error = 0;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_debug called\n");
-
-	switch (cmd) {
-		case MBOXSC_PRNMBOX:
-			error = print_mailbox_by_key((uint32_t)(uintptr_t)arg);
-			break;
-
-		case MBOXSC_PRNHASHTBL:
-			print_hash_table();
-			break;
-
-		case MBOXSC_SETDBGMASK:
-			mboxsc_debug_mask = (uint32_t)(uintptr_t)arg;
-			break;
-
-		default:
-			DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
-			    "Error: unknown mboxsc debug cmd (%d)\n", cmd);
-			error = ENOTTY;
-			break;
-	}
-
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_debug ret: 0x%08x\n", error);
-
-	return (error);
-}
-
-/*PRINTFLIKE5*/
-static void
-mboxsc_dprintf(
-	const char	*file,
-	int		line,
-	uint32_t	class,
-	uint32_t	action,
-	const char	*fmt,
-	...)
-{
-	int		i;
-	char		indent_buf[64];
-	char		msg_buf[256];
-	va_list		adx;
-	static uint32_t	indent = 0;
-
-	if (action & DBGACT_SHOWPOS) {
-		cmn_err(CE_CONT, "%s at line %d:\n", file, line);
-	}
-
-	if (class & DBG_RETS) {
-		indent--;
-	}
-
-	if (class & mboxsc_debug_mask) {
-		indent_buf[0] = '\0';
-		for (i = 0; i < indent; i++) {
-			(void) strcat(indent_buf, "  ");
-		}
-
-		va_start(adx, fmt);
-		(void) vsprintf(msg_buf, fmt, adx);
-		va_end(adx);
-
-		cmn_err(CE_CONT, "%s%s", indent_buf, msg_buf);
-	}
-
-	if (class & DBG_CALLS) {
-		indent++;
-	}
-
-	if (action & DBGACT_BREAK) {
-		debug_enter("");
-	}
-}
-
-static void
-print_hash_table(void)
-{
-	int		i;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "print_hash_table called\n");
-
-	mutex_enter(&mboxsc_lock);
-
-	for (i = 0; i < HASHTBL_SIZE; i++) {
-		DPRINTF1(DBG_DEV, DBGACT_DEFAULT, "hash[%02d]:\n", i);
-
-		for (mailboxp = mboxsc_hash_table[i]; mailboxp != NULL;
-		    mailboxp = mailboxp->mbox_hash_next) {
-			DPRINTF2(DBG_DEV, DBGACT_DEFAULT,
-			    "    key: 0x%08x, dir: %d\n", mailboxp->mbox_key,
-			    mailboxp->mbox_direction);
-		}
-	}
-
-	mutex_exit(&mboxsc_lock);
-
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "print_hash_table ret\n");
-}
-
-static int
-print_mailbox_by_key(uint32_t key)
-{
-	int		error = 0;
-	mboxsc_mbox_t	*mailboxp;
-
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "print_mailbox_by_key called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%08x\n", key);
-
-	mutex_enter(&mboxsc_lock);
-
-	mailboxp = mboxsc_hashfind_mailbox_by_key(key);
-	if (mailboxp != NULL) {
-		print_mailbox(mailboxp);
-		error = 0;
-	} else {
-		DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
-		    "print_mailbox_by_key: no such mbox 0x%08x\n", key);
-		error = EBADF;
-	}
-
-	mutex_exit(&mboxsc_lock);
-	DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
-	    "print_mailbox_by_key ret: 0x%08x\n", error);
-
-	return (error);
-}
-
-/* ARGSUSED */
-static void
-print_mailbox(mboxsc_mbox_t *mailboxp)
-{
-	DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "print_mailbox called\n");
-	DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n",
-	    (void *)mailboxp);
-	if (mailboxp->mbox_direction == MBOXSC_MBOX_IN) {
-		DPRINTF3(DBG_DEV, DBGACT_DEFAULT,
-		    "key = 0x%08x, dir = %d, callback = %p\n",
-		    mailboxp->mbox_key, mailboxp->mbox_direction,
-		    (void *)mailboxp->mbox_callback);
-	} else {
-		DPRINTF2(DBG_DEV, DBGACT_DEFAULT, "key = 0x%08x, dir = %d\n",
-		    (int)mailboxp->mbox_key, mailboxp->mbox_direction);
-	}
-	DPRINTF3(DBG_DEV, DBGACT_DEFAULT,
-	    "length = %d, refcount = %d, state = %d\n",
-	    mailboxp->mbox_length, mailboxp->mbox_refcount,
-	    mailboxp->mbox_state);
-	/* LINTED E_BAD_FORMAT_ARG_TYPE2 */
-	DPRINTF2(DBG_DEV, DBGACT_DEFAULT, "waitcv = %p, hashnext = %p\n",
-	    (void *)&mailboxp->mbox_wait, (void *)mailboxp->mbox_hash_next);
-	if (mailboxp->mbox_direction == MBOXSC_MBOX_IN) {
-		DPRINTF3(DBG_DEV, DBGACT_DEFAULT,
-		    "hdr.type = 0x%x, hdr.cmd = 0x%x, hdr.len = 0x%x\n",
-		    mailboxp->mbox_header.msg_type,
-		    mailboxp->mbox_header.msg_cmd,
-		    mailboxp->mbox_header.msg_length);
-		DPRINTF1(DBG_DEV, DBGACT_DEFAULT, "hdr.tid = 0x%016lx\n",
-		    mailboxp->mbox_header.msg_transid);
-	}
-	DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "print_mailbox ret\n");
-}
-#endif	/* DEBUG */
--- a/usr/src/uts/sun4u/starcat/io/sc_gptwocfg.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1547 +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.
- */
-
-/*
- *     Starcat Specific Glue for Safari Configurator
- */
-
-#include <sys/isa_defs.h>
-#include <sys/conf.h>
-#include <sys/kmem.h>
-#include <sys/debug.h>
-#include <sys/modctl.h>
-#include <sys/autoconf.h>
-#include <sys/hwconf.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ndi_impldefs.h>
-#include <sys/safari_pcd.h>
-#include <sys/gp2cfg.h>
-#include <sys/gptwo_cpu.h>
-#include <sys/gptwo_pci.h>
-#include <sys/sc_gptwocfg.h>
-#include <post/scat_dcd.h>
-#include <sys/machsystm.h>
-
-int sc_gptwocfg_debug = 0;
-
-#define	SC_DEBUG(level, args) if (sc_gptwocfg_debug >= level) cmn_err args
-
-typedef struct sc_gptwocfg_config {
-	int				board;
-	struct gptwocfg_config		*port_cookie;
-	gptwo_aid_t			portid;
-	struct sc_gptwocfg_config	*link;
-	struct sc_gptwocfg_config	*next;
-} sc_gptwocfg_config_t;
-
-static kmutex_t sc_gptwo_config_list_lock;
-static sc_gptwocfg_config_t *sc_gptwo_config_list;
-static dev_info_t *sc_find_axq_node(uint_t);
-static sc_gptwocfg_cookie_t sc_configure(uint_t, int);
-static spcd_t *sc_get_common_pcd(uint_t, uint_t);
-static void sc_free_common_pcd(spcd_t *);
-static gptwo_new_nodes_t *sc_gptwocfg_configure_axq(dev_info_t *, uint_t, int);
-static gptwocfg_config_t *sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *);
-static void dump_config(sc_gptwocfg_config_t *);
-static void dump_pcd(spcd_t *);
-static uint_t sc_get_agent_id(spcd_t *, uint_t, uint_t, uint_t);
-static char *rsv_string(prdrsv_t);
-
-extern gptwo_new_nodes_t *gptwocfg_allocate_node_list(int);
-extern void gptwocfg_free_node_list(gptwo_new_nodes_t *);
-
-static uint8_t *get_memlayout(uint32_t, uint32_t *);
-
-#ifdef NO_IOSRAM
-int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
-#else
-extern int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
-#endif
-extern void gptwocfg_devi_attach_to_parent(dev_info_t *);
-
-/*
- * Module control operations
- */
-
-extern struct mod_ops mod_miscops;
-
-static struct modlmisc modlmisc = {
-	&mod_miscops, /* Type of module */
-	"Sun Fire 15000 gptwocfg"
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1, (void *)&modlmisc, NULL
-};
-
-int
-_init()
-{
-	int err = 0;
-
-	mutex_init(&sc_gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL);
-	sc_gptwo_config_list = NULL;
-
-	/*
-	 * CPU/PCI devices are already registered by their respective modules,
-	 * so all we need to do now is install.
-	 */
-	if ((err = mod_install(&modlinkage)) != 0) {
-		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg failed to load, error=%d\n",
-		    err));
-		mutex_destroy(&sc_gptwo_config_list_lock);
-	} else {
-		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg has been loaded.\n"));
-	}
-	return (err);
-}
-
-int
-_fini(void)
-{
-	mutex_destroy(&sc_gptwo_config_list_lock);
-	return (mod_remove(&modlinkage));
-}
-
-int
-_info(modinfop)
-struct modinfo *modinfop;
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-static spcd_t *
-sc_get_common_pcd(uint_t expander, uint_t prd_slot)
-{
-	spcd_t *pcd;
-	gdcd_t *gdcd;
-	int portid;
-	int i, j, slot;
-	int dimm;
-	char *label1, *label2;
-
-	SC_DEBUG(1, (CE_WARN, "sc_get_common_pcd() expander=%d prd_slot=%d\n",
-	    expander, prd_slot));
-
-	gdcd = (gdcd_t *)kmem_zalloc(sizeof (gdcd_t), KM_SLEEP);
-
-	/*
-	 * Get the Starcat Specific Global DCD Structure from the golden
-	 * IOSRAM.
-	 */
-	if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
-		cmn_err(CE_WARN, "sc_gptwocfg: Unable To Read GDCD "
-		    "From IOSRAM\n");
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (NULL);
-	}
-
-	if (gdcd->h.dcd_magic != GDCD_MAGIC) {
-
-		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Magic 0x%x\n",
-		    gdcd->h.dcd_magic);
-
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (NULL);
-	}
-
-	if (gdcd->h.dcd_version != DCD_VERSION) {
-		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Version: "
-		    "GDCD Version 0x%x Expecting 0x%x\n",
-		    gdcd->h.dcd_version, DCD_VERSION);
-
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (NULL);
-	}
-
-	pcd = (spcd_t *)kmem_zalloc(sizeof (spcd_t), KM_SLEEP);
-
-	/*
-	 * Copy various information from the platform specific Port
-	 * Resource Descriptor (PRD) To the platform independent
-	 * Port Configuration Descriptor.
-	 */
-	pcd->spcd_magic = PCD_MAGIC;
-	pcd->spcd_version = PCD_VERSION;
-	pcd->spcd_ptype = gdcd->dcd_prd[expander][prd_slot].prd_ptype;
-	pcd->spcd_ver_reg = gdcd->dcd_prd[expander][prd_slot].prd_ver_reg;
-
-	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
-		/*
-		 * This will calculate the cpu speed based on the
-		 * the actual frequency ratio * interconnect frequency
-		 * converted to Mhz.
-		 */
-		pcd->spcd_afreq = gdcd->dcd_prd[expander][prd_slot].
-		    prd_afreq_ratio *
-		    (uint16_t)((gdcd->dcd_intercon_freq + 500000) / 1000000);
-	} else {
-		/*
-		 * For non-cpu devices, just pass through the frequency
-		 * unchanged.
-		 */
-		pcd->spcd_afreq =
-		    gdcd->dcd_prd[expander][prd_slot].prd_afreq_ratio;
-	}
-
-	pcd->spcd_cache = gdcd->dcd_prd[expander][prd_slot].prd_cache;
-
-	SC_DEBUG(1, (CE_WARN, "Safari Device Status status=0x%x\n",
-	    gdcd->dcd_prd[expander][prd_slot].prd_prsv));
-
-	/*
-	 * Fill in the entire port status.
-	 */
-	if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].prd_prsv)) {
-		pcd->spcd_prsv = SPCD_RSV_PASS;
-	} else {
-		pcd->spcd_prsv = SPCD_RSV_FAIL;
-	}
-
-	/*
-	 * Fill in the per agent status.
-	 */
-	if (gdcd->dcd_prd[expander][prd_slot].prd_agent[1] == RSV_UNKNOWN) {
-		pcd->spcd_agent[0] = pcd->spcd_prsv;
-		pcd->spcd_agent[1] = SPCD_RSV_FAIL;
-	} else {
-		for (i = 0; i < AGENTS_PER_PORT; i++) {
-
-			if (RSV_GOOD(
-			    gdcd->dcd_prd[expander][prd_slot].prd_agent[i]))
-				pcd->spcd_agent[i] = SPCD_RSV_PASS;
-			else
-				pcd->spcd_agent[i] = SPCD_RSV_FAIL;
-		}
-	}
-
-	/*
-	 * If this is a CPU device calculate the cpuid for it.  For Starcat
-	 * the cpuid is in the following format.
-	 *
-	 * EEEEEPPAPP
-	 *
-	 * where:	EEEEE is the expander
-	 *		PP_PP is the portid
-	 *		__A__ is the sub-agent identifier.
-	 */
-	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
-		for (i = 0; i < AGENTS_PER_PORT; i++) {
-			switch (prd_slot) {
-			case 0:
-			case 1:
-			case 2:
-			case 3:
-				portid = (expander << 5) | prd_slot;
-				break;
-			case 4: /* Maxcat */
-				portid = (expander << 5) | 8;
-				break;
-			case 5: /* Maxcat */
-				portid = (expander << 5) | 9;
-				break;
-			default:
-				cmn_err(CE_WARN, "sc_gptwocfg: invalid "
-				    "prd_slot=%d\n", prd_slot);
-			}
-			pcd->spcd_cpuid[i] = (i << 2) | portid;
-		}
-	}
-
-	/*
-	 * Starcat does not have ports with UPA devices so
-	 * spcd_upadev structure will not be filled in.
-	 */
-
-	/*
-	 * Fill in IO Bus Status
-	 */
-	for (i = 0; i < IOBUS_PER_PORT; i++) {
-
-		SC_DEBUG(1, (CE_WARN, "   IO Bus Status "
-		    "bus=%d status=0x%x\n", i,
-		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i]));
-
-		if (RSV_GOOD(
-		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i])) {
-			pcd->spcd_iobus_rsv[i] = SPCD_RSV_PASS;
-		} else {
-			pcd->spcd_iobus_rsv[i] = SPCD_RSV_FAIL;
-		}
-
-		for (j = 0; j < IOCARD_PER_BUS; j++)
-			pcd->spcd_iocard_rsv[i][j] = SPCD_RSV_FAIL;
-
-		/*
-		 * Fill in IO Card Status
-		 */
-		for (j = 0; j < IOCARD_PER_BUS; j++) {
-
-			SC_DEBUG(1, (CE_WARN, "       Card Status bus=%d "
-			    "slot=%d status=0x%x\n", i, j,
-			    gdcd->dcd_prd[expander][prd_slot].
-			    prd_iocard_rsv[i][j]));
-
-			if (j == 1)
-				continue;
-
-			if (j == 0)
-				slot = 1;
-			else
-				slot = j;
-
-			/*
-			 * If POST marked the card as GOOD or if the slot
-			 * is empty, we want to probe for the device.
-			 */
-			if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].
-			    prd_iocard_rsv[i][j]) ||
-			    (gdcd->dcd_prd[expander][prd_slot].
-			    prd_iocard_rsv[i][j] == RSV_MISS) ||
-			    (gdcd->dcd_prd[expander][prd_slot].
-			    prd_iocard_rsv[i][j] == RSV_EMPTY_CASSETTE))
-				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_PASS;
-			else
-				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_FAIL;
-		}
-	}
-
-	/*
-	 * Fill in WIC Link Status
-	 */
-	for (i = 0; i < LINKS_PER_PORT; i++) {
-		if (RSV_GOOD(
-		    gdcd->dcd_prd[expander][prd_slot].prd_wic_links[i])) {
-			pcd->spcd_wic_links[i] = SPCD_RSV_PASS;
-
-		} else {
-			pcd->spcd_wic_links[i] = SPCD_RSV_FAIL;
-		}
-	}
-
-	/*
-	 * Get data for the "bank-status" property.
-	 */
-	pcd->sprd_bank_rsv[0] =
-	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][0]);
-	pcd->sprd_bank_rsv[1] =
-	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][0]);
-	pcd->sprd_bank_rsv[2] =
-	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][1]);
-	pcd->sprd_bank_rsv[3] =
-	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][1]);
-
-	dimm = 0;
-	for (i = 0; i < PMBANKS_PER_PORT; i++) {
-		for (j = 0; j < DIMMS_PER_PMBANK; j++) {
-			if (dimm < MAX_DIMMS_PER_PORT) {
-				pcd->sprd_dimm[dimm] = rsv_string(
-				    gdcd->dcd_prd[expander][prd_slot].
-				    prd_dimm[i][j]);
-				dimm++;
-			}
-		}
-	}
-
-	/*
-	 * Get data for the "ecache-dimm-label" property.
-	 *
-	 * Right now it is hardcoded, but we should eventually get this
-	 * from the SC.
-	 */
-	label1 = NULL;
-	label2 = NULL;
-
-	switch (prd_slot) {
-	case 0:
-		label1 = "4400";
-		label2 = "4300";
-		break;
-	case 1:
-		label1 = "5400";
-		label2 = "5300";
-		break;
-	case 2:
-		label1 = "6400";
-		label2 = "6300";
-		break;
-	case 3:
-		label1 = "7400";
-		label2 = "7300";
-		break;
-
-	/*
-	 * Maxcat labels.
-	 */
-	case 4:
-		label1 = "6400";
-		label2 = "6300";
-		break;
-	case 5:
-		label1 = "7400";
-		label2 = "7300";
-		break;
-	}
-
-	i = 0;
-	if (label1) {
-		pcd->sprd_ecache_dimm_label[i] =
-		    kmem_alloc(strlen(label1) + 1, KM_SLEEP);
-
-		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label1);
-
-		i++;
-	}
-	if (label2) {
-		pcd->sprd_ecache_dimm_label[i] =
-		    kmem_alloc(strlen(label2) + 1, KM_SLEEP);
-
-		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label2);
-
-		i++;
-
-	}
-
-	kmem_free(gdcd, sizeof (gdcd_t));
-
-#ifdef DEBUG
-	dump_pcd(pcd);
-#endif
-
-	return (pcd);
-}
-
-void
-sc_free_common_pcd(spcd_t *pcd)
-{
-	int i;
-
-	SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd pcd=%p\n", (void *)pcd));
-
-	if (pcd->memory_layout && pcd->memory_layout_size) {
-		SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd: memory_layout %p "
-		    "size=%x", (void *)pcd->memory_layout,
-		    pcd->memory_layout_size));
-		kmem_free(pcd->memory_layout, pcd->memory_layout_size);
-	}
-
-	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
-		if (pcd->sprd_bank_rsv[i]) {
-			kmem_free(pcd->sprd_bank_rsv[i],
-			    strlen(pcd->sprd_bank_rsv[i]) + 1);
-
-			pcd->sprd_bank_rsv[i] = NULL;
-		}
-	}
-
-	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
-		if (pcd->sprd_dimm[i]) {
-			kmem_free(pcd->sprd_dimm[i],
-			    strlen(pcd->sprd_dimm[i]) + 1);
-
-			pcd->sprd_dimm[i] = NULL;
-		}
-		if (pcd->sprd_ecache_dimm_label[i]) {
-			kmem_free(pcd->sprd_ecache_dimm_label[i],
-			    strlen(pcd->sprd_ecache_dimm_label[i]) + 1);
-
-			pcd->sprd_ecache_dimm_label[i] = NULL;
-		}
-	}
-
-	kmem_free(pcd, sizeof (spcd_t));
-}
-
-sc_gptwocfg_cookie_t
-sc_probe_board(uint_t board)
-{
-	return (sc_configure(board, 1));
-}
-
-static sc_gptwocfg_cookie_t
-sc_configure(uint_t board, int create_nodes)
-{
-	spcd_t *pcd;
-	dev_info_t *ap, *axq_dip;
-	uint_t agent_id;
-	uint_t prd_slot, prd_slot_start, prd_slot_end;
-	uint_t expander, slot;
-	gptwo_new_nodes_t *new_nodes;
-	gptwocfg_config_t *port_cookie;
-	struct sc_gptwocfg_config *board_config, *last, *new;
-	int created_node = 0;
-	uint32_t size;
-
-	SC_DEBUG(1, (CE_WARN, "sc_configure: board=%d, create_nodes=%d\n",
-	    board, create_nodes));
-
-	if (board > 35) {
-		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg - probe_board - "
-		    "invalid board 0x%x\n", board));
-		return (NULL);
-	}
-
-	slot = board & 1;	/* Extract Slot Number */
-	expander = board >> 1;	/* Extract Expander Number */
-
-	SC_DEBUG(1, (CE_WARN, "sc_configure: exp=0x%x slot=0x%x\n",
-	    expander, slot));
-
-	/*
-	 * Get the Attachment Point.  For Starcat the parent of all
-	 * Safari children is root node.
-	 */
-	ap = ddi_root_node();
-
-	/*
-	 * Get the agent id of the AXQ.
-	 */
-	agent_id = (expander << 5) | 0x1e | slot;
-
-	/*
-	 * Look to see if the board is already configured by searching for
-	 * its AXQ.
-	 */
-	if (create_nodes && (axq_dip = sc_find_axq_node(agent_id))) {
-		ddi_release_devi(axq_dip);
-		cmn_err(CE_WARN, "Board %d AXQ is already configured\n",
-		    board);
-		return (NULL);
-	}
-
-	/*
-	 * Probe AXQ first
-	 */
-	SC_DEBUG(1, (CE_WARN, "sc_configure: Probing AXQ exp=0x%x brd=0x%x\n",
-	    expander, slot));
-
-	/*
-	 * The generic gptwocfg does not support the AXQ, so we need
-	 * to configure it. The AXQ branch is returned held.
-	 */
-	new_nodes = sc_gptwocfg_configure_axq(ap, agent_id, create_nodes);
-
-	if (new_nodes == NULL) {
-		SC_DEBUG(1, (CE_WARN, "sc_configure: Can not probe AXQ\n"));
-		return (NULL);
-	}
-
-	port_cookie = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP);
-
-	/*
-	 * Build a cookie for the AXQ.
-	 */
-	port_cookie->gptwo_ap = ap;
-	port_cookie->gptwo_portid = agent_id;
-	port_cookie->gptwo_nodes = new_nodes;
-
-	board_config = kmem_zalloc(sizeof (sc_gptwocfg_config_t), KM_SLEEP);
-
-	board_config->port_cookie = port_cookie;
-	board_config->board = board;
-	board_config->portid = agent_id;
-	board_config->link = NULL;
-	last = board_config;
-
-	mutex_enter(&sc_gptwo_config_list_lock);
-	board_config->next = sc_gptwo_config_list;
-	sc_gptwo_config_list = board_config;
-	mutex_exit(&sc_gptwo_config_list_lock);
-
-	SC_DEBUG(1, (CE_WARN, "sc_configure: AXQ Probing Complete. "
-	    "%d nodes added\n", new_nodes->gptwo_number_of_nodes));
-
-	/*
-	 * Determine the starting ending slots of the PRD array.
-	 */
-	switch (slot) {
-	case 0:		/* Full Bandwidth Slot */
-		prd_slot_start = 0;
-		prd_slot_end = 3;
-		break;
-	case 1:		/* Half Bandwidth Slot */
-		prd_slot_start = 4;
-		prd_slot_end = 5;
-		break;
-	default:
-		SC_DEBUG(1, (CE_WARN, "Unknown Board Address - "
-		    "Can not probe\n"));
-		return (board_config);
-	}
-
-	/*
-	 * For each valid PRD entry, determine the agent id which is based
-	 * on what type of device is described by the slot, and then
-	 * call the safari configurator.
-	 */
-	for (prd_slot = prd_slot_start; prd_slot <= prd_slot_end; prd_slot++) {
-
-		pcd = sc_get_common_pcd(expander, prd_slot);
-
-		if (pcd == NULL) {
-
-			/*
-			 * We can not get a PCD for this port so skip it.
-			 */
-			cmn_err(CE_WARN, "sc_gptwocfg: Can not get PCD "
-			    "expander 0x%x prd slot 0x%x\n",
-			    expander, prd_slot);
-
-			return (board_config);
-		}
-
-		/*
-		 * Only configure good devices.
-		 */
-		if (pcd->spcd_prsv == SPCD_RSV_PASS) {
-			/*
-			 * Determine the agent id.
-			 */
-			agent_id = sc_get_agent_id(
-			    pcd, expander, slot, prd_slot);
-
-			pcd->memory_layout = get_memlayout(agent_id, &size);
-			pcd->memory_layout_size = size;
-
-			/*
-			 * Call Platform Independent gptwo configurator to
-			 * create node and properties.
-			 */
-			if (create_nodes) {
-				port_cookie =
-				    gptwocfg_configure(ap, pcd, agent_id);
-				if (port_cookie)
-					created_node++;
-			}
-
-			new = kmem_zalloc
-			    (sizeof (sc_gptwocfg_config_t), KM_SLEEP);
-
-			/*
-			 * XXX Shouldn't port_cookie be NULL if
-			 * !create_nodes ?
-			 */
-			new->port_cookie = port_cookie;
-			new->portid = agent_id;
-			new->link = NULL;
-			last->link = new;
-			last = new;
-		} else {
-			SC_DEBUG(1, (CE_WARN, "sc_configure: Bad Agent "
-			    "Exp=0x%x PRD Slot=0x%x  prsv Status=0x%x\n",
-			    expander, prd_slot, pcd->spcd_prsv));
-		}
-
-		sc_free_common_pcd(pcd);
-
-	} /* for loop */
-
-	dump_config(board_config);
-
-	if (create_nodes && !created_node) {
-		SC_DEBUG(1, (CE_WARN, "sc_configure: GPTWO Devices failed "
-		    "to configure - unprobing board %d\n", board));
-		board_config = sc_unprobe_board(board);
-	}
-
-	SC_DEBUG(1, (CE_WARN, "sc_configure: Returning 0x%p\n",
-	    (void *)board_config));
-
-	return (board_config);
-}
-
-sc_gptwocfg_cookie_t
-sc_unprobe_board(uint_t board)
-{
-	sc_gptwocfg_config_t *board_config, *axq_config, *prior_config;
-	gptwocfg_cookie_t port_cookie;
-
-	SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: board=%d\n", board));
-
-	if (board > 35) {
-		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
-		    "invalid board 0x%x\n", board));
-		return (NULL);
-	}
-	mutex_enter(&sc_gptwo_config_list_lock);
-	board_config = sc_gptwo_config_list;
-	while (board_config != NULL) {
-		if (board_config->board == board) {
-			break;
-		}
-		board_config = board_config->next;
-	}
-	mutex_exit(&sc_gptwo_config_list_lock);
-
-	if (board_config == NULL) {
-
-		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: No "
-		    "config structure board=0x%x\n", board));
-
-		/*
-		 * Configure the board without creating nodes.
-		 */
-		board_config = sc_configure(board, 0);
-
-		if (board_config == NULL) {
-
-			cmn_err(CE_WARN, "sc_gptwocfg: sc_unprobe_board: "
-			    "Unable to unconfigure board %d - board is not "
-			    "configured\n", board);
-
-			return (NULL);
-		}
-	}
-
-	axq_config = board_config;
-
-	/*
-	 * Walk the link of ports on this board and unconfigure them.
-	 * Save the AXQ for last.
-	 */
-	while (board_config->link != NULL) {
-		prior_config = board_config;
-		board_config = board_config->link;
-
-		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
-		    "calling gptwocfg_unconfigure(ap=0x%p portid=0x%x)\n",
-		    (void *)ddi_root_node(), board_config->portid));
-
-		port_cookie = gptwocfg_unconfigure(ddi_root_node(),
-		    board_config->portid);
-
-		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
-		    "gptwocfg_unconfigure returned cookie=0x%p\n",
-		    port_cookie));
-
-		if (port_cookie == NULL) {
-			/*
-			 * Can be removed from list.
-			 */
-			prior_config->link = board_config->link;
-			kmem_free(board_config, sizeof (sc_gptwocfg_config_t));
-			board_config = prior_config;
-		} else {
-			board_config->port_cookie = port_cookie;
-		}
-	}
-
-	if (axq_config->link == NULL) {
-
-		/*
-		 * If all the other Safari devices have been successfully
-		 * unconfigured, then the AXQ can be unconfigured.
-		 */
-		axq_config->port_cookie =
-		    sc_gptwocfg_unconfigure_axq(axq_config->port_cookie);
-
-		if (axq_config->port_cookie == NULL) {
-
-			/*
-			 * If the AXQ was successfully unconfigured, then
-			 * the board is removed from the configured list.
-			 */
-			mutex_enter(&sc_gptwo_config_list_lock);
-			if (sc_gptwo_config_list == axq_config) {
-				sc_gptwo_config_list = axq_config->next;
-			} else {
-				board_config = sc_gptwo_config_list;
-				while (board_config->next != axq_config) {
-					board_config = board_config->next;
-				}
-				board_config->next = axq_config->next;
-			}
-			mutex_exit(&sc_gptwo_config_list_lock);
-			kmem_free(axq_config, sizeof (sc_gptwocfg_config_t));
-			axq_config = NULL;
-		}
-	}
-	dump_config(axq_config);
-	return (axq_config);
-}
-
-int
-sc_next_node(sc_gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next)
-{
-	dev_info_t *dip;
-	sc_gptwocfg_config_t *cookie;
-
-	SC_DEBUG(1, (CE_WARN, "sccfg: sccfg_next_node"
-	    "(c=0x%p, previous=0x%p, next=0x%p)\n", (void *)c,
-	    (void *)previous, (void *)next));
-
-	cookie = (sc_gptwocfg_config_t *)c;
-
-	if (cookie == NULL) {
-		cmn_err(CE_WARN, "sccfg: sccfg_next_node - "
-		    "Invalid Cookie\n");
-		return (0);
-	}
-	if (previous == NULL) {
-		/*
-		 * Start with the AXQ node.
-		 */
-		if (gptwocfg_next_node(cookie->port_cookie, NULL, &dip)) {
-			*next = dip;
-			return (1);
-		} else {
-			return (0);
-		}
-	}
-
-	while (cookie != NULL) {
-		if (gptwocfg_next_node(cookie->port_cookie, previous, &dip)) {
-			if ((dip == NULL) && (cookie->link == NULL)) {
-				*next = NULL;
-				return (1);
-			}
-			if (dip != NULL) {
-				*next = dip;
-				return (1);
-			}
-
-			/* dip == NULL */
-
-			previous = NULL;
-		}
-		cookie = cookie->link;
-	}
-
-	return (0);
-}
-
-static dev_info_t *
-sc_find_axq_node(uint_t axq_id)
-{
-	char *name;
-	int size;
-	gptwo_regspec_t *reg;
-	dev_info_t *dip;
-	uint_t id;
-	int circ;
-
-	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: id=0x%x\n", axq_id));
-
-	/*
-	 * Hold root node busy to walk its child list
-	 */
-	ndi_devi_enter(ddi_root_node(), &circ);
-
-	dip = ddi_get_child(ddi_root_node());
-
-	while (dip != NULL) {
-
-		SC_DEBUG(1, (CE_CONT, "Searching dip=0x%p for our AXQ\n",
-		    (void *)dip));
-
-		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
-		    DDI_PROP_DONTPASS, "name", (caddr_t)&name, &size)
-		    != DDI_PROP_SUCCESS) {
-
-			/*
-			 * This node does not have a name property.
-			 */
-			SC_DEBUG(1, (CE_CONT, "dip=0x%p does not have a "
-			    "'name' property\n", (void *)dip));
-
-			dip = ddi_get_next_sibling(dip);
-			continue;
-		}
-
-		SC_DEBUG(1, (CE_CONT, "dip=0x%p name=%s\n", (void *)dip, name));
-
-		if (strcmp(name, "address-extender-queue")) {
-
-			/*
-			 * This node is not a AXQ node.
-			 */
-			SC_DEBUG(1, (CE_CONT, "dip=0x%p is not an AXQ "
-			    "node\n", (void *)dip));
-			kmem_free(name, size);
-			dip = ddi_get_next_sibling(dip);
-			continue;
-		}
-		kmem_free(name, size);
-
-		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
-		    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &size)
-		    != DDI_PROP_SUCCESS) {
-
-			/*
-			 * This AXQ node does not have a reg property.
-			 */
-			SC_DEBUG(1, (CE_CONT, "dip=0x%p (AXQ Node) does "
-			    "have a 'reg' property\n", (void *)dip));
-			dip = ddi_get_next_sibling(dip);
-			continue;
-		}
-
-		id = ((reg[0].gptwo_phys_hi & 1) << 9) |
-		    ((reg[0].gptwo_phys_low & 0xff800000) >> 23);
-
-		kmem_free(reg, size);
-
-		if (axq_id != id) {
-
-			/*
-			 * This is the wrong AXQ node.
-			 */
-			SC_DEBUG(1, (CE_CONT, "dip=0x%p Wrong node id=0x%x\n",
-			    (void *)dip, id));
-
-			dip = ddi_get_next_sibling(dip);
-			continue;
-
-		}
-
-		/*
-		 * The correct AXQ node was found.
-		 */
-		SC_DEBUG(1, (CE_CONT, "dip=0x%p Found AXQ Node\n",
-		    (void *)dip));
-		ndi_hold_devi(dip);
-		break;
-	}
-	ndi_devi_exit(ddi_root_node(), circ);
-
-	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: Returning 0x%p\n",
-	    (void *)dip));
-
-	return (dip);
-}
-
-struct axq_arg {
-	uint_t id;
-	dev_info_t *axq_dip;
-};
-
-/*ARGSUSED*/
-static int
-axq_set_prop(dev_info_t *axq_dip, void *arg, uint_t flags)
-{
-	struct axq_arg *aqp = (struct axq_arg *)arg;
-	gptwo_regspec_t	reg[2];
-	uint_t		id;
-
-	ASSERT(aqp);
-
-	id = aqp->id;
-
-	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
-	    "name", "address-extender-queue") != DDI_SUCCESS) {
-		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
-		    "to create name property\n"));
-		return (DDI_WALK_ERROR);
-	}
-
-	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
-	    "device_type", "address-extender-queue") != DDI_SUCCESS) {
-		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
-		    "to create device_type property\n"));
-		return (DDI_WALK_ERROR);
-	}
-
-	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
-	    "compatible", "SUNW,axq") != DDI_SUCCESS) {
-		SC_DEBUG(1, (CE_CONT, "sc_gptwocfg: failed "
-		    "to create compatible property\n"));
-		return (DDI_WALK_ERROR);
-	}
-
-	if (ndi_prop_update_int(DDI_DEV_T_NONE, axq_dip,
-	    "portid", id) != DDI_SUCCESS) {
-		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
-		    "to create portid property\n"));
-		return (DDI_WALK_ERROR);
-	}
-
-	reg[0].gptwo_phys_hi = 0x400 | (id >> 9);
-	reg[0].gptwo_phys_low = (id << 23);
-	reg[0].gptwo_size_hi = 0;
-	reg[0].gptwo_size_low = 0x520;
-
-	reg[1].gptwo_phys_hi = 0x401;
-	reg[1].gptwo_phys_low = 0xf0000000;
-	reg[1].gptwo_size_hi = 0;
-	reg[1].gptwo_size_low = 0x520;
-
-	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
-	    axq_dip, "reg", (int *)&reg,
-	    (sizeof (gptwo_regspec_t) * 2)/sizeof (int)) != DDI_SUCCESS) {
-		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
-		    "to create reg property\n"));
-		return (DDI_WALK_ERROR);
-	}
-
-	return (DDI_WALK_TERMINATE);
-}
-
-/*ARGSUSED*/
-static void
-get_axq_dip(dev_info_t *rdip, void *arg, uint_t flags)
-{
-	struct axq_arg *aqp = (struct axq_arg *)arg;
-
-	ASSERT(aqp);
-
-	aqp->axq_dip = rdip;
-}
-
-static gptwo_new_nodes_t *
-sc_gptwocfg_configure_axq(dev_info_t *ap, uint_t id, int create_nodes)
-{
-	struct axq_arg arg = {0};
-	devi_branch_t b = {0};
-	dev_info_t *axq_dip, *fdip = NULL;
-	gptwo_new_nodes_t *new_nodes = NULL;
-	int rv;
-
-	SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: id=0x%x "
-	    "create_nodes=%d\n", id, create_nodes));
-
-	if (!create_nodes) {
-		axq_dip = sc_find_axq_node(id);
-
-		if (axq_dip) {
-			new_nodes = gptwocfg_allocate_node_list(1);
-			new_nodes->gptwo_nodes[0] = axq_dip;
-			ASSERT(!e_ddi_branch_held(axq_dip));
-			e_ddi_branch_hold(axq_dip);
-			/*
-			 * Release hold from sc_find_axq_node()
-			 */
-			ddi_release_devi(axq_dip);
-		}
-
-		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: "
-		    "Returning 0x%p\n", (void *)new_nodes));
-
-		return (new_nodes);
-	}
-
-	arg.id = id;
-	arg.axq_dip = NULL;
-
-	b.arg = &arg;
-	b.type = DEVI_BRANCH_SID;
-	b.create.sid_branch_create = axq_set_prop;
-	b.devi_branch_callback = get_axq_dip;
-
-	rv = e_ddi_branch_create(ap, &b, &fdip, DEVI_BRANCH_CONFIGURE);
-	if (rv != 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(ap, path);
-		}
-
-		SC_DEBUG(1, (CE_WARN, "e_ddi_branch_create failed: "
-		    "path=%s, dip=%p, rv=%d", path, fdip ? (void *)fdip :
-		    (void *)ap, rv));
-
-		kmem_free(path, MAXPATHLEN);
-
-		return (NULL);
-	}
-
-	axq_dip = arg.axq_dip;
-
-	new_nodes = gptwocfg_allocate_node_list(1);
-	new_nodes->gptwo_nodes[0] = axq_dip;
-
-	return (new_nodes);
-}
-
-static gptwocfg_config_t *
-sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *config)
-{
-	int i;
-	int failure = 0;
-	dev_info_t *saf_dip;
-
-	if (config == NULL) {
-		cmn_err(CE_WARN, "sc_gptwocfg: sc_gptwocfg_unconfigure_axq: "
-		    "Invalid AXQ\n");
-		return (NULL);
-	}
-	for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) {
-		int rv;
-		dev_info_t *fdip = NULL;
-
-		saf_dip = config->gptwo_nodes->gptwo_nodes[i];
-		ASSERT(e_ddi_branch_held(saf_dip));
-		rv = e_ddi_branch_destroy(saf_dip, &fdip, 0);
-		if (rv != 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(saf_dip, path);
-			}
-
-			cmn_err(CE_CONT, "AXQ node removal failed: "
-			    "path=%s, dip=%p, rv=%d\n", path,
-			    fdip ? (void *)fdip : (void *)saf_dip, rv);
-
-			kmem_free(path, MAXPATHLEN);
-			failure = 1;
-		} else {
-			config->gptwo_nodes->gptwo_nodes[i] = NULL;
-		}
-	}
-	if (!failure) {
-		gptwocfg_free_node_list(config->gptwo_nodes);
-
-		kmem_free(config, sizeof (gptwocfg_config_t));
-		config = NULL;
-	}
-	return (config);
-}
-
-static uint_t
-sc_get_agent_id(spcd_t *pcd, uint_t expander, uint_t slot, uint_t prd_slot)
-{
-	uint_t agent_id;
-
-	switch (pcd->spcd_ptype) {
-	case SAFPTYPE_CPU:
-		if (slot == 0) {
-			agent_id = prd_slot;
-		} else {
-			if (prd_slot == 4) {
-				agent_id = 8;
-			} else {
-				agent_id = 9;
-			}
-		}
-		break;
-
-	case SAFPTYPE_sPCI:
-	case SAFPTYPE_cPCI:
-	case SAFPTYPE_PCIX:
-		if (prd_slot == 4) {
-			agent_id = 0x1c;
-		} else {
-			agent_id = 0x1d;
-		}
-		break;
-	case SAFPTYPE_WCI:
-		agent_id = 0x1d;
-		break;
-	default:
-		cmn_err(CE_WARN, "sc_gptwocfg: Invalid Safari Port "
-		    "Type 0x%x Slot 0x%x\n",
-		    pcd->spcd_ptype, prd_slot);
-	} /* switch */
-
-	agent_id |= (expander << 5);
-
-	SC_DEBUG(1, (CE_CONT, "sc_get_agent_id(pcd=0x%p, expander=0x%x, "
-	    "prd_slot=0x%x) Returning agent_id=0x%x\n", (void *)pcd, expander,
-	    prd_slot, agent_id));
-
-	return (agent_id);
-}
-
-static void
-dump_config(sc_gptwocfg_config_t *board_config)
-{
-	gptwocfg_config_t *port;
-
-	SC_DEBUG(1, (CE_CONT, "dump_config 0x%p", (void *)board_config));
-	while (board_config != NULL) {
-		SC_DEBUG(1, (CE_CONT, "************* 0x%p ************\n",
-		    (void *)board_config));
-		SC_DEBUG(1, (CE_CONT, "port_cookie - 0x%p\n",
-		    (void *)board_config->port_cookie));
-
-		port = board_config->port_cookie;
-		if (port) {
-			SC_DEBUG(1, (CE_CONT, "     ap     - 0x%p\n",
-			    (void *)port->gptwo_ap));
-			SC_DEBUG(1, (CE_CONT, "     portid - 0x%x\n",
-			    port->gptwo_portid));
-		}
-		SC_DEBUG(1, (CE_CONT, "portid      - 0x%x\n",
-		    board_config->portid));
-		SC_DEBUG(1, (CE_CONT, "board      - 0x%x\n",
-		    board_config->board));
-		SC_DEBUG(1, (CE_CONT, "link        - 0x%p\n",
-		    (void *)board_config->link));
-		SC_DEBUG(1, (CE_CONT, "next        - 0x%p\n",
-		    (void *)board_config->next));
-		board_config = board_config->link;
-	}
-}
-
-static void
-dump_pcd(spcd_t *pcd)
-{
-	int i;
-
-	SC_DEBUG(1, (CE_CONT, "dump_pcd 0x%p", (void *)pcd));
-	SC_DEBUG(1, (CE_CONT, "     magic   - 0x%x\n", pcd->spcd_magic));
-	SC_DEBUG(1, (CE_CONT, "     version - 0x%x\n", pcd->spcd_version));
-	SC_DEBUG(1, (CE_CONT, "     ver.reg - 0x%lx\n", pcd->spcd_ver_reg));
-	SC_DEBUG(1, (CE_CONT, "     afreq   - %d\n", pcd->spcd_afreq));
-	switch (pcd->spcd_ptype) {
-	case SAFPTYPE_CPU:
-		SC_DEBUG(1, (CE_CONT, "     ptype   - CPU\n"));
-		break;
-	case SAFPTYPE_sPCI:
-		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI\n"));
-		break;
-	case SAFPTYPE_cPCI:
-		SC_DEBUG(1, (CE_CONT, "     ptype   - cPCI\n"));
-		break;
-	case SAFPTYPE_PCIX:
-		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI+\n"));
-		break;
-	case SAFPTYPE_WCI:
-		SC_DEBUG(1, (CE_CONT, "     ptype   - WIC\n"));
-		break;
-	default:
-		SC_DEBUG(1, (CE_CONT, "     ptype   - 0x%x\n",
-		    pcd->spcd_ptype));
-		break;
-	}
-	SC_DEBUG(1, (CE_CONT, "     cache   - %d\n", pcd->spcd_cache));
-
-	if (pcd->spcd_prsv == SPCD_RSV_PASS) {
-		SC_DEBUG(1, (CE_CONT, "     prsv    - SPCD_RSV_PASS\n"));
-	} else {
-		SC_DEBUG(1, (CE_CONT, "     prsv    - 0x%x (FAIL)\n",
-		    pcd->spcd_prsv));
-	}
-
-	for (i = 0; i < AGENTS_PER_PORT; i++) {
-		if (pcd->spcd_agent[i] == SPCD_RSV_PASS) {
-			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
-			    "- SPCD_RSV_PASS\n", i));
-		} else {
-			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
-			    "- 0x%x (FAIL)\n", i, pcd->spcd_agent[i]));
-		}
-	}
-
-	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
-		for (i = 0; i < AGENTS_PER_PORT; i++) {
-			SC_DEBUG(1, (CE_CONT, "     cpuid[%d] - 0x%x\n",
-			    i, pcd->spcd_cpuid[i]));
-		}
-	}
-
-	SC_DEBUG(1, (CE_CONT, "     Banks\n"));
-	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
-		if (pcd->sprd_bank_rsv[i]) {
-			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
-			    pcd->sprd_bank_rsv[i]));
-		}
-	}
-
-	SC_DEBUG(1, (CE_CONT, "     Dimms\n"));
-	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
-		if (pcd->sprd_dimm[i]) {
-			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
-			    pcd->sprd_dimm[i]));
-		}
-	}
-	SC_DEBUG(1, (CE_CONT, "     Ecache Dimm Labels\n"));
-	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
-		if (pcd->sprd_ecache_dimm_label[i]) {
-			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
-			    pcd->sprd_ecache_dimm_label[i]));
-		}
-	}
-}
-
-
-typedef struct {
-	char Jnumber[8][8];
-	uint8_t sym_flag;
-	uint8_t d_dimmtable[144];
-	uint8_t d_pintable[576];
-}m_layout;
-
-/*
- * Use 2 bits to represent each bit at a cache line. The table
- * is in big endian order, i.e.
- *      dimmtable[0], ... , dimmtable[143]
- * Q0:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
- *                      .
- *                      .
- * Q3:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
- */
-uint8_t J_dimm_pinTable[] = {
-/* Jnumber */
-/*  0 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x30, 0x00, 0x00,
-/*  1 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x30, 0x00, 0x00,
-/*  2 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x30, 0x00, 0x00,
-/*  3 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x30, 0x00, 0x00,
-/*  4 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x31, 0x00, 0x00,
-/*  5 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x31, 0x00, 0x00,
-/*  6 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x31, 0x00, 0x00,
-/*  7 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x31, 0x00, 0x00,
-/* flag */	0x01,
-/*  -- Q0 --  */
-/*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
-/*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
-/*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
-/*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
-/*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
-/*  -- Q1 --  */
-/*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
-/*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
-/*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
-/*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
-/*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
-/*  -- Q2 --  */
-/*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
-/*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
-/*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
-/*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
-/*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
-/*  -- Q3 --  */
-/*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
-/*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
-/*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
-/*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
-/*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
-/*
- * In the following order
- *      pintable[0], ..., pintable[575]
- * Quadword3, Quadword2, Quadword1, Quadword0
- *      MtagEcc, Mtag, Ecc, Data
- */
-/* -- Q3 -- */
-/*  0  */	227, 227, 227, 227, 111, 111, 111,  22,
-/*  1  */	22,  32, 138, 222,  81, 117, 117, 117,
-/*  2  */	111, 222, 106, 222, 222, 106, 106, 106,
-/*  3  */	217, 101, 212,  96, 217, 101, 212,  96,
-/*  4  */	217, 101, 212,  96, 217, 101, 212,  96,
-/*  5  */	207,  91, 202,  86, 187,  71, 158,  42,
-/*  6  */	187,  71, 158,  42, 153,  37, 148,  32,
-/*  7  */	153,  37, 148,  32, 153,  37, 148,  32,
-/*  8  */	153,  37, 148, 143,  27, 138, 143,  27,
-/*  9  */	143,  27, 138,  22, 207,  91, 202,  86,
-/*  10 */	207,  91, 202,  86, 207,  91, 202,  86,
-/*  11 */	192,  76,  81, 192,  76,  81, 192,  76,
-/*  12 */	197,  81, 192,  76, 187,  71, 158,  42,
-/*  13 */	187,  71, 158,  42, 143,  27, 138,  22,
-/*  14 */	133,  17, 128,  12, 133,  17, 128,  12,
-/*  15 */	133,  17, 128,  12, 133,  17, 128,  12,
-/*  16 */	123,  07, 118,   2, 123,  07, 118,   2,
-/*  17 */	123,  07, 118,   2, 123,  07, 118,   2,
-/* -- Q2 -- */
-/*  0  */	228, 228, 228, 228, 112, 112, 112,  23,
-/*  1  */	23,  33, 139, 223,  82, 118, 118, 118,
-/*  2  */	112, 223, 107, 223, 223, 107, 107, 107,
-/*  3  */	218, 102, 213,  97, 218, 102, 213,  97,
-/*  4  */	218, 102, 213,  97, 218, 102, 213,  97,
-/*  5  */	208,  92, 203,  87, 188,  72, 159,  43,
-/*  6  */	188,  72, 159,  43, 154,  38, 149,  33,
-/*  7  */	154,  38, 149,  33, 154,  38, 149,  33,
-/*  8  */	154,  38, 149, 144,  28, 139, 144,  28,
-/*  9  */	144,  28, 139,  23, 208,  92, 203,  87,
-/*  10 */	208,  92, 203,  87, 208,  92, 203,  87,
-/*  11 */	193,  77,  82, 193,  77,  82, 193,  77,
-/*  12 */	198,  82, 193,  77, 188,  72, 159,  43,
-/*  13 */	188,  72, 159,  43, 144,  28, 139,  23,
-/*  14 */	134,  18, 129,  13, 134,  18, 129,  13,
-/*  15 */	134,  18, 129,  13, 134,  18, 129,  13,
-/*  16 */	124,   8, 119,   3, 124,   8, 119,   3,
-/*  17 */	124,   8, 119,   3, 124,   8, 119,   3,
-/* -- Q1 -- */
-/*  0  */	229, 229, 229, 229, 113, 113, 113,  24,
-/*  1  */	24,  34, 140, 224,  83, 119, 119, 119,
-/*  2  */	113, 224, 108, 224, 224, 108, 108, 108,
-/*  3  */	219, 103, 214,  98, 219, 103, 214,  98,
-/*  4  */	219, 103, 214,  98, 219, 103, 214,  98,
-/*  5  */	209,  93, 204,  88, 189,  73, 160,  44,
-/*  6  */	189,  73, 160,  44, 155,  39, 150,  34,
-/*  7  */	155,  39, 150,  34, 155,  39, 150,  34,
-/*  8  */	155,  39, 150, 145,  29, 140, 145,  29,
-/*  9  */	145,  29, 140,  24, 209,  93, 204,  88,
-/*  10 */	209,  93, 204,  88, 209,  93, 204,  88,
-/*  11 */	194,  78,  83, 194,  78,  83, 194,  78,
-/*  12 */	199,  83, 194,  78, 189,  73, 160,  44,
-/*  13 */	189,  73, 160,  44, 145,  29, 140,  24,
-/*  14 */	135,  19, 130,  14, 135,  19, 130,  14,
-/*  15 */	135,  19, 130,  14, 135,  19, 130,  14,
-/*  16 */	125,   9, 120,   4, 125,   9, 120,   4,
-/*  17 */	125,   9, 120,   4, 125,   9, 120,   4,
-/* -- Q0 -- */
-/*  0  */	230, 230, 230, 230, 114, 114, 114,  25,
-/*  1  */	25,  35, 141, 225,  84, 200, 200, 200,
-/*  2  */	114, 225, 109, 225, 225, 109, 109, 109,
-/*  3  */	220, 104, 215,  99, 220, 104, 215,  99,
-/*  4  */	220, 104, 215,  99, 220, 104, 215,  99,
-/*  5  */	210,  94, 205,  89, 190,  74, 161,  45,
-/*  6  */	190,  74, 161,  45, 156,  40, 151,  35,
-/*  7  */	156,  40, 151,  35, 156,  40, 151,  35,
-/*  8  */	156,  40, 151, 146,  30, 141, 146,  30,
-/*  9  */	146,  30, 141,  25, 210,  94, 205,  89,
-/*  10 */	210,  94, 205,  89, 210,  94, 205,  89,
-/*  11 */	195,  79,  84, 195,  79,  84, 195,  79,
-/*  12 */	200,  84, 195,  79, 190,  74, 161,  45,
-/*  13 */	190,  74, 161,  45, 146,  30, 141,  25,
-/*  14 */	136,  20, 131,  15, 136,  20, 131,  15,
-/*  15 */	136,  20, 131,  15, 136,  20, 131,  15,
-/*  16 */	126,  10, 121,   5, 126,  10, 121,   5,
-/*  17 */	126,  10, 121,   5, 126,  10, 121,   5
-};
-
-/*
- *  This table is for internal reference
- *
- * pintable_internal[]= {
- * -- Q0 --
- * 0  143,143,143,143,139,139,139,35
- * 1  35,51,39,135,91,95,95,95
- * 2  139,135,131,135,135,131,131,131
- * 3  127,123,119,115,127,123,119,115
- * 4  127,123,119,115,127,123,119,115
- * 5  111,107,103,99,79,75,71,67
- * 6  79,75,71,67,63,59,55,51
- * 7  63,59,55,51,63,59,55,51
- * 8  63,59,55,47,43,39,47,43
- * 9  47,43,39,35,111,107,103,99
- * 10  111,107,103,99,111,107,103,99
- * 11  87,83,91,87,83,91,87,83
- * 12  95,91,87,83,79,75,71,67
- * 13  79,75,71,67,47,43,39,35
- * 14  31,27,23,19,31,27,23,19
- * 15  31,27,23,19,31,27,23,19
- * 16  15,11,7,3,15,11,7,3
- * 17  15,11,7,3,15,11,7,3
- * }
- */
-
-char *dimm_Jno[] = {
-/* P0 */	"J13300", "J13400", "J13500", "J13600",
-		"J13301", "J13401", "J13501", "J13601",
-/* P1 */	"J14300", "J14400", "J14500", "J14600",
-		"J14301", "J14401", "J14501", "J14601",
-/* P2 */	"J15300", "J15400", "J15500", "J15600",
-		"J15301", "J15401", "J15501", "J15601",
-/* P3 */	"J16300", "J16400", "J16500", "J16600",
-		"J16301", "J16401", "J16501", "J16601",
-		NULL
-	};
-
-
-static uint8_t *
-get_memlayout(uint32_t cpuid, uint32_t *len)
-{
-	m_layout *LayoutBuf;
-
-	if ((LayoutBuf = (m_layout *)kmem_zalloc(sizeof (m_layout),
-	    KM_SLEEP)) == NULL) {
-		*len = 0;
-		return (NULL);
-	}
-
-	bcopy(J_dimm_pinTable, LayoutBuf, sizeof (m_layout));
-
-	*len = sizeof (m_layout);
-	cpuid &= 0x03;	/* last 2 bits of a 10 bit number */
-
-	bcopy(dimm_Jno[cpuid << 3], LayoutBuf->Jnumber[0], 64);
-
-	return ((uint8_t *)LayoutBuf);
-}
-
-static char *
-rsv_string(prdrsv_t rsv)
-{
-	char *buffer;
-	char *status;
-
-	switch (rsv) {
-	case RSV_UNKNOWN:
-		buffer = "unknown";
-		break;
-	case RSV_PRESENT:
-		buffer = "okay";
-		break;
-	case RSV_CRUNCH:
-		buffer = "disabled";
-		break;
-	case RSV_UNDEFINED:
-		buffer = "undefined";
-		break;
-	case RSV_MISS:
-		buffer = "missing";
-		break;
-	case RSV_EMPTY_CASSETTE:
-		buffer = "disabled";
-		break;
-	case RSV_MISCONFIG:
-		buffer = "misconfigured";
-		break;
-	case RSV_FAIL_OBP:
-		buffer = "fail-obp";
-		break;
-	case RSV_BLACK:
-		buffer = "blacklisted";
-		break;
-	case RSV_RED:
-		buffer = "redlisted";
-		break;
-	case RSV_EXCLUDED:
-		buffer = "disabled";
-		break;
-	case RSV_UNCONFIG:
-		buffer = "disabled";
-		break;
-	case RSV_PASS:
-		buffer = "okay";
-		break;
-	case RSV_FAIL:
-	default:
-		buffer = "fail";
-		break;
-	}
-
-	status = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
-	(void) strcpy(status, buffer);
-
-	return (status);
-}
--- a/usr/src/uts/sun4u/starcat/io/schpc.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4509 +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.
- */
-
-
-/*
- * Starcat IOSRAM/Tunnel PCI Hot Plug Controller Driver
- */
-
-#define	CPCI_ENUM
-
-#include <sys/note.h>
-#include <sys/types.h>
-#include <sys/cmn_err.h>
-#include <sys/kmem.h>
-#include <sys/errno.h>
-#include <sys/open.h>
-#include <sys/stat.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/cmn_err.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/ndi_impldefs.h>
-#include <sys/modctl.h>
-#include <sys/disp.h>
-#include <sys/async.h>
-#include <sys/hotplug/hpcsvc.h>
-#include <sys/mboxsc.h>
-#include <sys/schpc_msg.h>
-#include <sys/schpc.h>
-#include <post/scat_dcd.h>
-#include <sys/taskq.h>
-
-#ifdef DEBUG
-int schpc_dump_save_regs = 0;
-static uint_t schpc_debug_flags = 0;
-#define	SCHPC_DEBUG0(f, s) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n")
-#define	SCHPC_DEBUG1(f, s, a) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n", a)
-#define	SCHPC_DEBUG2(f, s, a, b) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n", a, b)
-#define	SCHPC_DEBUG3(f, s, a, b, c) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n", a, b, c)
-#define	SCHPC_DEBUG4(f, s, a, b, c, d) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n", a, b, c, d)
-#define	SCHPC_DEBUG5(f, s, a, b, c, d, e) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n", a, b, c, d, e)
-#define	SCHPC_DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& schpc_debug_flags) \
-	cmn_err(CE_CONT, "schpc: " s "\n", a, b, c, d, e, ff)
-#else
-
-#define	SCHPC_DEBUG0(f, s)
-#define	SCHPC_DEBUG1(f, s, a)
-#define	SCHPC_DEBUG2(f, s, a, b)
-#define	SCHPC_DEBUG3(f, s, a, b, c)
-#define	SCHPC_DEBUG4(f, s, a, b, c, d)
-#define	SCHPC_DEBUG5(f, s, a, b, c, d, e)
-#define	SCHPC_DEBUG6(f, s, a, b, c, d, e, ff)
-
-#endif
-
-#define	D_IDENTIFY	0x00000001
-#define	D_ATTACH	0x00000002
-#define	D_DETACH	0x00000004
-#define	D_OPEN		0x00000008
-#define	D_GETSLOTSTATUS	0x00000010
-#define	D_SETSLOTSTATUS	0x00000020
-#define	D_IOCTL		0x00010000
-#define	D_IOC_CONNECT	0x00020000
-#define	D_IOC_CONTROL	0x00040000
-#define	D_IOC_CONFIG	0x00080000
-#define	D_IOC_STATUS	0x00100000
-#define	D_IOC_MSG	0x00200000
-#define	D_IOC_TEST	0x00400000
-#define	D_IOC_LED	0x00800000
-#define	D_EVENT		0x01000000
-#define	D_THREAD	0x02000000
-#define	D_TRANSID	0x04000000
-#define	D_SLOTTABLE	0x08000000
-#define	D_FREQCHG	0x10000000
-#define	D_APID		0x20000000
-
-/*
- * driver global data:
- */
-static void *per_schpc_state;		/* soft state head */
-dev_info_t *schpc_devi;
-static schpc_t	*schpc_p;
-
-clock_t schpc_timeout_putmsg = 60 * 1000; /* 60 seconds */
-clock_t schpc_timeout_getmsg = 60 * 1000; /* 60 seconds */
-clock_t schpc_timeout_event = 60 * 5 * 1000; /* 5 minutes */
-
-int schpc_use_legacy_apid = 0;
-
-static mboxsc_timeout_range_t schpc_putmsg_timeout_range;
-static mboxsc_timeout_range_t schpc_getmsg_timeout_range;
-
-static taskq_t *schpc_event_taskq = NULL;
-
-/*
- * replies to mboxsc_getmsg() are handled asynchronously by the
- * schpc_msg_thread using a linked list of schpc_replylist_t
- * elements
- */
-typedef struct schpc_replylist {
-	struct schpc_replylist	*prev;		/* link to previous entry */
-	struct schpc_replylist	*next;		/* link to next entry */
-	kcondvar_t		reply_cv;	/* condvar for getting reply */
-	kmutex_t		reply_lock;	/* mutex for getting reply */
-	uint32_t		type;		/* mboxsc_xxxmsg() msg type */
-	uint32_t		cmd;		/* mboxsc_xxxmsg() cmd */
-	uint64_t		transid;	/* mboxsc_xxxmsg() trans id */
-	uint32_t		length;		/* mboxsc_xxxmsg() length */
-	pcimsg_t		reply;		/* mboxsc_xxxmsg() reply msg */
-	boolean_t		reply_recvd;	/* msg reply received */
-	boolean_t		reply_cexit;	/* client early exit */
-} schpc_replylist_t;
-
-static kmutex_t schpc_replylist_mutex; /* replylist mutex */
-static uint32_t schpc_replylist_count; /* replylist size */
-static schpc_replylist_t *schpc_replylist_first; /* replylist 1st elem */
-static schpc_replylist_t *schpc_replylist_last; /* replylist last elem */
-static boolean_t slots_registered = B_FALSE; /* slots registered? */
-
-typedef struct {
-	char		*cname;
-	char		*caddr;
-	char		schizo;
-	char		leaf;
-	dev_info_t	*dip;
-} find_dev_t;
-
-/*
- * Function prototypes for local functions
- */
-static int schpc_getexpander(dev_info_t *);
-static int schpc_getboard(dev_info_t *);
-static void schpc_event_handler(void *);
-static void schpc_event_filter(pcimsg_t	*msg);
-static void schpc_reply_handler(pcimsg_t *pmsg, uint32_t type, uint32_t cmd,
-				uint64_t transid, uint32_t length);
-static uint64_t schpc_gettransid(schpc_t *, int);
-static int schpc_slot_get_index(schpc_t *, hpc_slot_t);
-static void schpc_register_all_slots(schpc_t *);
-static void schpc_setslotled(int, int, int, uint32_t);
-static void schpc_init_setslot_message(pci_setslot_t *);
-static void schpc_test(caddr_t, int, void *, uint_t);
-static int schpc_getslotstatus(uint32_t, uint32_t, uint32_t, pci_getslot_t *);
-static int schpc_setslotstatus(uint32_t, uint32_t, uint32_t,  pci_setslot_t *);
-static int schpc_match_dip(dev_info_t *, void *);
-static void schpc_buildapid(dev_info_t *, int, char *);
-static int schpc_get_slot_status(uint_t, uint_t, uint_t);
-static void schpc_replylist_unlink(schpc_replylist_t *entry);
-static schpc_replylist_t *schpc_replylist_link(uint32_t cmd, uint64_t transid,
-						uint32_t length);
-static void schpc_msg_thread(void);
-static int schpc_putrequest(uint32_t key, uint32_t type, uint32_t cmd,
-				uint64_t *transidp, uint32_t length,
-				void *datap, clock_t timeout,
-				schpc_replylist_t **entryp);
-static int schpc_getreply(uint32_t key, uint32_t *typep, uint32_t *cmdp,
-			uint64_t *transidp, uint32_t *lengthp, void *datap,
-			clock_t timeout, schpc_replylist_t *listp);
-
-static int schpc_slot_freq(pci_getslot_t *);
-static int schpc_find_dip(dev_info_t *, void *);
-
-static int schpc_save_leaf(int slot);
-static void schpc_restore_leaf(int slot);
-static int schpc_is_leaf_reset_required(int slot);
-static int schpc_is_freq_switchable(int slot);
-static void schpc_save_entry(int slot, int list_entry, int save_entry);
-static void schpc_restore_entry(int slot, int list_entry, int save_entry);
-
-/*
- * Function prototype for Hot Plug Services
- */
-static int schpc_connect(caddr_t, hpc_slot_t, void *, uint_t);
-static int schpc_disconnect(caddr_t, hpc_slot_t, void *, uint_t);
-static int schpc_cpci_control(caddr_t, hpc_slot_t, int, caddr_t);
-static int schpc_pci_control(caddr_t, hpc_slot_t, int, caddr_t);
-
-extern int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
-
-/*
- * cb_ops and dev_ops:
- */
-static struct cb_ops schpc_cb_ops = {
-	nodev,			/* open */
-	nodev,			/* close */
-	nodev,			/* strategy */
-	nodev,			/* print */
-	nodev,			/* dump */
-	nodev,			/* read */
-	nodev,			/* write */
-	nodev,			/* ioctl */
-	nodev,			/* devmap */
-	nodev,			/* mmap */
-	nodev,			/* segmap */
-	nochpoll,		/* poll */
-	ddi_prop_op,		/* prop_op */
-	0,			/* streamtab  */
-	D_NEW | D_MP | D_HOTPLUG /* Driver compatibility flag */
-};
-
-/*
- * Function prototype for dev_ops
- */
-static int schpc_attach(dev_info_t *, ddi_attach_cmd_t);
-static int schpc_detach(dev_info_t *, ddi_detach_cmd_t);
-static int schpc_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
-
-static struct dev_ops schpc_dev_ops = {
-	DEVO_REV,			/* devo_rev, */
-	0,				/* refcnt  */
-	schpc_info,			/* get_dev_info */
-	nulldev,			/* identify */
-	nulldev,			/* probe */
-	schpc_attach,			/* attach */
-	schpc_detach,			/* detach */
-	nodev,				/* reset */
-	&schpc_cb_ops,			/* driver operations */
-	(struct bus_ops *)0,		/* no bus operations */
-	NULL,				/* power */
-	ddi_quiesce_not_supported,	/* devo_quiesce */
-};
-
-/*
- * loadable module declarations:
- */
-static struct modldrv modldrv = {
-	&mod_driverops,
-	"PCI Hot Plug Controller Driver (schpc)",
-	&schpc_dev_ops,
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modldrv,
-	NULL
-};
-
-int
-_init(void)
-{
-	int		ret;
-	int		rv;
-
-	SCHPC_DEBUG0(D_ATTACH, "_init() installing module");
-
-	ret = ddi_soft_state_init(&per_schpc_state, sizeof (schpc_t), 1);
-	if (ret != 0) {
-		return (ret);
-	}
-
-	/*
-	 * Initialize Outgoing Mailbox.
-	 */
-	ret = mboxsc_init(KEY_PCSC, MBOXSC_MBOX_OUT, NULL);
-
-	if (ret != 0) {
-		ddi_soft_state_fini(&per_schpc_state);
-		return (ret);
-	}
-
-	ret = mboxsc_ctrl(KEY_PCSC, MBOXSC_CMD_PUTMSG_TIMEOUT_RANGE,
-	    (void *) &schpc_putmsg_timeout_range);
-
-	if (ret != 0) {
-		ddi_soft_state_fini(&per_schpc_state);
-		return (ret);
-	}
-
-	if (schpc_timeout_putmsg < schpc_putmsg_timeout_range.min_timeout) {
-		schpc_timeout_putmsg = schpc_putmsg_timeout_range.min_timeout;
-		cmn_err(CE_WARN, " schpc: resetting putmsg timeout to %ld\n",
-		    schpc_timeout_putmsg);
-	}
-
-	if (schpc_timeout_putmsg > schpc_putmsg_timeout_range.max_timeout) {
-		schpc_timeout_putmsg = schpc_putmsg_timeout_range.max_timeout;
-		cmn_err(CE_WARN, " schpc: resetting putmsg timeout to %ld\n",
-		    schpc_timeout_putmsg);
-	}
-
-	/*
-	 * Create the schpc_event_taskq for MBOXSC_MSG_EVENT processing.
-	 */
-	schpc_event_taskq = taskq_create("schpc_event_taskq", 2,
-	    minclsyspri, 4, 4, TASKQ_PREPOPULATE);
-
-	/*
-	 * Initialize Incoming Mailbox.
-	 * NOTE: the callback is null because the schpc_msg_thread will
-	 * handle all incoming MBOXSC_MSG_EVENT and MBOXSC_MSG_REPLY
-	 * messages.
-	 */
-	ret = mboxsc_init(KEY_SCPC, MBOXSC_MBOX_IN, NULL);
-
-	if (ret != 0) {
-		cmn_err(CE_WARN, "schpc: can not initialize KEY_SCPC as "
-		    "MBOXSC_MBOX_IN");
-		ddi_soft_state_fini(&per_schpc_state);
-		return (ret);
-	}
-
-	ret = mboxsc_ctrl(KEY_SCPC, MBOXSC_CMD_GETMSG_TIMEOUT_RANGE,
-	    (void *) &schpc_getmsg_timeout_range);
-
-	if (ret != 0) {
-		ddi_soft_state_fini(&per_schpc_state);
-		return (ret);
-	}
-
-	if (schpc_timeout_getmsg < schpc_getmsg_timeout_range.min_timeout) {
-		schpc_timeout_getmsg = schpc_getmsg_timeout_range.min_timeout;
-		cmn_err(CE_WARN, " schpc: resetting getmsg timeout to %ld\n",
-		    schpc_timeout_getmsg);
-	}
-
-	if (schpc_timeout_getmsg > schpc_getmsg_timeout_range.max_timeout) {
-		schpc_timeout_getmsg = schpc_getmsg_timeout_range.max_timeout;
-		cmn_err(CE_WARN, " schpc: resetting putmsg timeout to %ld\n",
-		    schpc_timeout_putmsg);
-	}
-
-	if (schpc_timeout_event < schpc_getmsg_timeout_range.min_timeout) {
-		schpc_timeout_event = schpc_getmsg_timeout_range.min_timeout;
-		cmn_err(CE_WARN, " schpc: resetting event timeout to %ld\n",
-		    schpc_timeout_event);
-	}
-
-	if (schpc_timeout_event > schpc_getmsg_timeout_range.max_timeout) {
-		schpc_timeout_event = schpc_getmsg_timeout_range.max_timeout;
-		cmn_err(CE_WARN, " schpc: resetting event timeout to %ld\n",
-		    schpc_timeout_event);
-	}
-
-	ret = mod_install(&modlinkage);
-	if (ret != 0) {
-		if ((rv = mboxsc_fini(KEY_PCSC)) != 0) {
-			cmn_err(CE_WARN, "schpc: _init() - "
-			    "mboxsc_fini(KEY_PCSC) failed: 0x%x", rv);
-		}
-		if ((rv = mboxsc_fini(KEY_SCPC)) != 0) {
-			cmn_err(CE_WARN, "schpc: _init() - "
-			    "mboxsc_fini(KEY_SCPC) failed: 0x%x", rv);
-		}
-		taskq_destroy(schpc_event_taskq);
-		ddi_soft_state_fini(&per_schpc_state);
-		return (ret);
-	}
-
-	SCHPC_DEBUG0(D_ATTACH, "_init() module installed");
-
-	/*
-	 * Start the schpc_msg_thread to continuously monitor the
-	 * MBOXSC_MBOX_IN mailbox for incoming MBOXSC_MSG_EVENTs and
-	 * MBOXSC_MSG_REPLYs.
-	 */
-	mutex_init(&schpc_replylist_mutex, NULL, MUTEX_DRIVER, NULL);
-	(void) thread_create(NULL, 0, schpc_msg_thread,
-	    NULL, 0, &p0, TS_RUN, minclsyspri);
-
-	SCHPC_DEBUG0(D_ATTACH, "_init() started schpc_msg_thread");
-
-	return (ret);
-}
-
-int
-_fini(void)
-{
-	SCHPC_DEBUG0(D_ATTACH, "_fini()");
-
-	return (DDI_FAILURE);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	SCHPC_DEBUG0(D_ATTACH, "_info() called.");
-
-	return (mod_info(&modlinkage, modinfop));
-}
-
-static int
-schpc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-	int		instance = ddi_get_instance(devi);
-	int		rval;
-
-	SCHPC_DEBUG1(D_ATTACH, "attach(%x) ATTACH", instance);
-
-	switch (cmd) {
-	case DDI_ATTACH:
-
-		/*
-		 * Allocate the soft state structure for this instance.
-		 */
-		rval = ddi_soft_state_zalloc(per_schpc_state, instance);
-
-		if (rval != DDI_SUCCESS) {
-			SCHPC_DEBUG1(D_ATTACH,
-			    "schpc_attach(%x) Can not allocate "
-			    "soft state structure", instance);
-			return (DDI_FAILURE);
-		}
-
-		schpc_p = (schpc_t *)ddi_get_soft_state(per_schpc_state,
-		    instance);
-
-		if (schpc_p == NULL) {
-			return (DDI_FAILURE);
-		}
-
-		mutex_init(&schpc_p->schpc_mutex, NULL, MUTEX_DRIVER, NULL);
-		cv_init(&schpc_p->schpc_cv, NULL, CV_DRIVER, NULL);
-
-		/*
-		 * Put schpc structure on global linked list.
-		 */
-
-		/*
-		 * Initialize starting transaction ID.
-		 */
-		schpc_p->schpc_transid = 0;
-
-		schpc_p->schpc_number_of_slots = STARCAT_MAX_SLOTS;
-
-		SCHPC_DEBUG2(D_ATTACH, "schpc_attach(%x) slot-table property "
-		    "describes %d slots", instance,
-		    schpc_p->schpc_number_of_slots);
-
-		schpc_p->schpc_hotplugmodel = ddi_getprop(DDI_DEV_T_ANY,
-		    devi, 0, "hot-plug-model", SCHPC_HOTPLUGTYPE_CPCIHOTPLUG);
-
-		SCHPC_DEBUG2(D_ATTACH, "attach(%x) ATTACH - Hot Plug Model=%x",
-		    instance, schpc_p->schpc_hotplugmodel);
-
-		/*
-		 * What type of hot plug do these slots support?  The only
-		 * types of slots we support is the cPCI Hot Plug Model
-		 * and Not Hot Pluggable.
-		 */
-		if (schpc_p->schpc_hotplugmodel !=
-		    SCHPC_HOTPLUGTYPE_CPCIHOTPLUG) {
-			schpc_p->schpc_hotplugmodel =
-			    SCHPC_HOTPLUGTYPE_NOTHOTPLUGGABLE;
-		}
-
-		schpc_p->schpc_slot = (schpc_slot_t *)kmem_zalloc((size_t)
-		    (schpc_p->schpc_number_of_slots * sizeof (schpc_slot_t)),
-		    KM_SLEEP);
-
-		schpc_p->schpc_devi = devi;
-		schpc_p->schpc_instance = instance;
-
-		/*
-		 * Start thread to search the device tree and register
-		 * all found pci slots.
-		 */
-		(void) thread_create(NULL, 0, schpc_register_all_slots,
-		    (void *)schpc_p, 0, &p0, TS_RUN, minclsyspri);
-
-		break;
-
-	case DDI_PM_RESUME:
-	case DDI_RESUME:
-		return (DDI_SUCCESS);
-	default:
-		cmn_err(CE_WARN, "schpc%d: Cmd != DDI_ATTACH/DDI_RESUME",
-		    instance);
-
-		return (DDI_FAILURE);
-	}
-
-	SCHPC_DEBUG1(D_ATTACH,
-	    "schpc_attach(%x) Attach - DDI_SUCCESS", instance);
-
-	return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static int
-schpc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
-	int	instance = ddi_get_instance(devi);
-
-	SCHPC_DEBUG1(D_DETACH, "detach(%x) DETACH", instance);
-
-	return (DDI_FAILURE);
-}
-
-/*ARGSUSED*/
-static int
-schpc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
-	void **result)
-{
-	int	error;
-
-	switch (infocmd) {
-	case DDI_INFO_DEVT2DEVINFO:
-		*result = (void *)schpc_devi;
-		error = DDI_SUCCESS;
-		break;
-	case DDI_INFO_DEVT2INSTANCE:
-		*result = (void *)0;
-		error = DDI_SUCCESS;
-		break;
-	default:
-		error = DDI_FAILURE;
-	}
-	return (error);
-}
-
-/*
- * schpc_connect()
- *
- * Called by Hot Plug Services to connect a slot to the bus.
- */
-
-/*ARGSUSED*/
-static int
-schpc_connect(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data, uint_t flags)
-{
-	int		rval;
-	int		expander, board;
-	pci_setslot_t	setslot;
-	pci_getslot_t	getslot;
-	int		slot;
-
-	SCHPC_DEBUG2(D_IOC_CONNECT, "schpc_connect( ops_arg=%p slot_hdl=%p)",
-	    (void *)ops_arg, (void *)slot_hdl);
-
-	mutex_enter(&schpc_p->schpc_mutex);
-
-	slot = schpc_slot_get_index(schpc_p, slot_hdl);
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_HPCINITED)) {
-		SCHPC_DEBUG0(D_IOC_CONNECT, "schpc_connect - HPC Not Inited");
-		mutex_exit(&schpc_p->schpc_mutex);
-		return (HPC_ERR_FAILED);
-	}
-
-	/*
-	 * Check to see if the slot is already connected.
-	 */
-	if (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_CONNECTED) {
-		mutex_exit(&schpc_p->schpc_mutex);
-		return (0);
-	}
-
-	/*
-	 * Block if another thread is executing a HPC command.
-	 */
-	while (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_EXECUTING) {
-		cv_wait(&schpc_p->schpc_cv, &schpc_p->schpc_mutex);
-	}
-
-	schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_EXECUTING;
-
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	expander = schpc_p->schpc_slot[slot].expander; /* get expander */
-	board = schpc_p->schpc_slot[slot].board; /* get board */
-
-	SCHPC_DEBUG3(D_IOC_CONNECT,
-	    "schpc_connect Expander=%x Board=%x Slot=%x",
-	    expander, board, SCHPC_SLOT_NUM(slot));
-
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_OCC_GOOD)) {
-		cmn_err(CE_WARN, "schpc: Hot Plug - Unable to complete "
-		    "connection on Expander %d Board %d Slot %d - "
-		    "Ap_Id=%s : Occupant is in failed state",
-		    expander, board, SCHPC_SLOT_NUM(slot),
-		    schpc_p->schpc_slot[slot].ap_id);
-
-		/* Fault LED should already be illuminated */
-
-		goto failed;
-	}
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_REC_GOOD)) {
-		cmn_err(CE_WARN, "schpc: Hot Plug - Unable to complete "
-		    "connection on Expander %d Board %d Slot %d - "
-		    "Ap_Id=%s : Receptacle is in failed state",
-		    expander, board, SCHPC_SLOT_NUM(slot),
-		    schpc_p->schpc_slot[slot].ap_id);
-
-		/* Fault LED should already be illuminated */
-
-		goto failed;
-	}
-
-	rval = schpc_getslotstatus(expander, board, slot, &getslot);
-
-	if (rval) {
-		/*
-		 * System Controller/Mailbox failure.
-		 */
-		cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : Unable to "
-		    "Communicate with System Controller", expander, board,
-		    SCHPC_SLOT_NUM(slot), schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-		goto failed;
-	}
-
-	if (getslot.slot_replystatus != PCIMSG_REPLY_GOOD) {
-
-		cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : Unable to "
-		    "Read Slot Status", expander, board,
-		    SCHPC_SLOT_NUM(slot), schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-		goto failed;
-	}
-
-	if (getslot.slot_empty) {
-		/*
-		 * If the slot is empty - fail the connection request.
-		 */
-		goto failed;
-	}
-
-	SCHPC_DEBUG3(D_FREQCHG, "Slot %d - slot_freq_setting %d "
-	    "slot_freq_cap %d", slot, getslot.slot_freq_setting,
-	    getslot.slot_freq_cap);
-
-	if (!schpc_is_freq_switchable(slot) &&
-	    (getslot.slot_freq_setting > getslot.slot_freq_cap)) {
-
-		cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-		    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-		    "Bus Speed Mismatch", expander,
-		    board, SCHPC_SLOT_NUM(slot),
-		    schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-		goto failed;
-	}
-
-	if (schpc_is_leaf_reset_required(slot) &&
-	    (schpc_p->schpc_slot[slot].saved_regs == NULL)) {
-
-		SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Save Regs before connect",
-		    slot);
-
-		/*
-		 * A prior disconnect had not saved off the leaf so lets
-		 * save it now. This is probably due to the domain being
-		 * booted with a slot with no cassette.
-		 */
-		if (schpc_save_leaf(slot) != 0) {
-			cmn_err(CE_WARN, "schpc - Unable to save leaf regs on "
-
-			    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : ",
-			    expander, board, slot & 3,
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-			goto failed;
-		}
-	}
-
-	/*
-	 * Initialize Set Slot Command.
-	 */
-	schpc_init_setslot_message(&setslot);
-
-	setslot.slot_power_on = PCIMSG_ON;	   /* Turn slot power on */
-
-	setslot.slot_led_fault = PCIMSG_LED_FLASH; /* Flash Fault LED */
-
-	rval = schpc_setslotstatus(expander, board, slot, &setslot);
-
-	if (rval != 0) {
-		/*
-		 * System Controller/Mailbox failure.
-		 */
-		cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : Unable to "
-		    "Communicate with System Controller", expander, board,
-		    SCHPC_SLOT_NUM(slot), schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-		goto failed;
-	}
-
-	if (setslot.slot_replystatus == PCIMSG_REPLY_GOOD) {
-
-		/*
-		 * The Request was successfully completed.
-		 */
-
-		SCHPC_DEBUG0(D_IOC_CONNECT, "schpc_connect() - setslotstatus "
-		    "succeeded");
-
-		/*
-		 * Need to check HEALTHY# signal.
-		 */
-		rval = schpc_getslotstatus(expander, board, slot, &getslot);
-
-		if (rval) {
-			/*
-			 * System Controller/Mailbox failure.
-			 */
-			cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-			    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "Unable to Communicate with System Controller",
-			    expander, board, SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-			goto failed;
-		}
-
-		if (getslot.slot_replystatus != PCIMSG_REPLY_GOOD) {
-
-			cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-			    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "Unable to Read Slot Status", expander, board,
-			    SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-			goto failed;
-		}
-
-		if ((getslot.slot_powergood != PCIMSG_ON) ||
-		    (getslot.slot_powerfault == PCIMSG_ON)) {
-			cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-			    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "Power failure detected", expander, board,
-			    SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			/*
-			 * Initialize Set Slot Command.
-			 */
-			schpc_init_setslot_message(&setslot);
-
-			/*
-			 * Turn slot power off.
-			 */
-			setslot.slot_power_off = PCIMSG_ON;
-
-			(void) schpc_setslotstatus(expander, board,
-			    slot, &setslot);
-
-			schpc_setslotled(expander, board, slot,
-			    (SERVICE_LED_ON | FAULT_LED_ON));
-
-			goto failed;
-		}
-
-		if (!getslot.slot_HEALTHY) {
-			cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-			    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "Adapter did not assert HEALTHY#", expander, board,
-			    SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			/*
-			 * Initialize Set Slot Command.
-			 */
-			schpc_init_setslot_message(&setslot);
-
-			/*
-			 * Turn slot power off.
-			 */
-			setslot.slot_power_off = PCIMSG_ON;
-
-			(void) schpc_setslotstatus(expander, board, slot,
-			    &setslot);
-
-			schpc_setslotled(expander, board, slot,
-			    (SERVICE_LED_ON | FAULT_LED_ON));
-
-			goto failed;
-		}
-
-		/*
-		 * Initialize Set Slot Command.
-		 */
-		schpc_init_setslot_message(&setslot);
-
-		/*
-		 * Start monitoring ENUM# and HEALTHY#
-		 */
-		setslot.slot_enable_HEALTHY = PCIMSG_ON;
-		setslot.slot_enable_ENUM = PCIMSG_ON;
-
-		rval = schpc_setslotstatus(expander, board, slot, &setslot);
-
-		if (rval != 0) {
-			/*
-			 * System Controller/Mailbox failure.
-			 */
-			cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-			    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "Unable to Communicate with System Controller",
-			    expander, board, SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-			goto failed;
-		}
-		if (setslot.slot_replystatus == PCIMSG_REPLY_GOOD) {
-
-			int		freq;
-			find_dev_t	find_dev;
-
-			/*
-			 * The Request was successfully completed.
-			 */
-
-			SCHPC_DEBUG0(D_IOC_CONNECT,
-			    "schpc_connect() - setslotstatus succeeded");
-
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_CONNECTED;
-
-			schpc_setslotled(expander, board, slot,
-			    (POWER_LED_ON | SERVICE_LED_OFF | FAULT_LED_OFF));
-
-			find_dev.cname = schpc_p->schpc_slot[slot].nexus_path;
-			find_dev.caddr = (char *)kmem_alloc(MAXPATHLEN,
-			    KM_SLEEP);
-			find_dev.dip = NULL;
-
-			/* root node doesn't have to be held */
-			ddi_walk_devs(ddi_root_node(), schpc_find_dip,
-			    &find_dev);
-			if (find_dev.dip != NULL) {
-				/*
-				 * Update the clock-frequency property to
-				 * reflect the new slot-frequency.
-				 */
-				freq = schpc_slot_freq(&getslot);
-				SCHPC_DEBUG2(D_FREQCHG,
-				    "schpc_connect: updating dip=%p freq=%dHZ",
-				    (void *)find_dev.dip, freq);
-				if (ndi_prop_update_int(DDI_DEV_T_NONE,
-				    find_dev.dip, "clock-frequency", freq)
-				    != DDI_SUCCESS) {
-					cmn_err(CE_WARN,
-					    "schpc: - failed to update "
-					    "clock-frequency property for %s",
-					    find_dev.cname);
-				}
-				ndi_rele_devi(find_dev.dip);
-			} else {
-				cmn_err(CE_WARN,
-				    "schpc: couldn't find dip for %s ",
-				    find_dev.cname);
-			}
-			kmem_free(find_dev.caddr, MAXPATHLEN);
-
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-
-			/*
-			 * If leaf registers were saved off, then they
-			 * need to be restored.
-			 */
-			schpc_restore_leaf(slot);
-
-			/*
-			 * Since the device saw a PCI Reset, we need to
-			 * wait 2^25 clock cycles before the first
-			 * Configuration access. The worst case is 33MHz,
-			 * which is a 1 second wait.
-			 */
-			drv_usecwait(1000000);
-
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (0);
-		} else {
-			/*
-			 * The System Controller Rejected the
-			 * connection request.
-			 */
-			cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed "
-			    "on Expander %d Board %d PCI Slot %d - Ap_Id=%s :"
-			    "System Controller failed connection request",
-			    expander, board, SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-			goto failed;
-		}
-	}
-
-	/*
-	 * The System Controller Rejected the connection request.
-	 */
-	cmn_err(CE_WARN, "schpc - Hot Plug Connection Failed on "
-	    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : System Controller "
-	    "failed connection request", expander, board, SCHPC_SLOT_NUM(slot),
-	    schpc_p->schpc_slot[slot].ap_id);
-
-	schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-failed:
-	mutex_enter(&schpc_p->schpc_mutex);
-	schpc_p->schpc_slot[slot].state &=
-	    ~SCHPC_SLOTSTATE_EXECUTING;
-	cv_signal(&schpc_p->schpc_cv);
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	return (HPC_ERR_FAILED);
-}
-
-/*
- * schpc_disconnect()
- *
- * Called by Hot Plug Services to disconnect a slot to the bus.
- */
-
-/*ARGSUSED*/
-static int
-schpc_disconnect(caddr_t ops_arg, hpc_slot_t slot_hdl, void *data,
-	uint_t flags)
-{
-	int		rval;
-	int		expander, board, slot;
-	pci_setslot_t	setslot;
-
-	SCHPC_DEBUG2(D_IOC_CONNECT,
-	    "schpc_disconnect( ops_arg=%p slot_hdl=%p)", (void *)ops_arg,
-	    slot_hdl);
-
-	mutex_enter(&schpc_p->schpc_mutex);
-
-	slot = schpc_slot_get_index(schpc_p, slot_hdl);
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_HPCINITED)) {
-		SCHPC_DEBUG0(D_IOC_CONNECT,
-		    "schpc_disconnect - HPC Not Inited");
-		mutex_exit(&schpc_p->schpc_mutex);
-		return (HPC_ERR_FAILED);
-	}
-
-	/*
-	 * Check to see if we are already disconnected.
-	 */
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_CONNECTED)) {
-		mutex_exit(&schpc_p->schpc_mutex);
-		return (0);
-	}
-
-	/*
-	 * Block if another thread is executing a HPC command.
-	 */
-	while (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_EXECUTING) {
-		cv_wait(&schpc_p->schpc_cv, &schpc_p->schpc_mutex);
-	}
-
-	schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_EXECUTING;
-
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	expander = schpc_p->schpc_slot[slot].expander; /* get expander */
-	board = schpc_p->schpc_slot[slot].board; /* get board */
-
-	/*
-	 * If a leaf reset is going to be asserted due to a mode/freq.
-	 * change, then the leaf registers of the XMITS bridge will need
-	 * to be saved off prior to the connect.
-	 */
-	if (schpc_is_leaf_reset_required(slot)) {
-		if (schpc_save_leaf(slot) != 0) {
-
-			cmn_err(CE_WARN, "schpc - Unable to save leaf regs on "
-			    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : ",
-			    expander, board, slot & 3,
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-			goto failed;
-		}
-	}
-
-	/*
-	 * Initialize Set Slot Command.
-	 */
-	schpc_init_setslot_message(&setslot);
-
-	setslot.slot_power_off = PCIMSG_ON;	   /* Turn Power Off */
-
-	setslot.slot_led_fault = PCIMSG_LED_FLASH; /* Flash the Fault LED */
-
-	setslot.slot_disable_ENUM = PCIMSG_ON;	   /* Mask the ENUM# signal */
-	setslot.slot_disable_HEALTHY = PCIMSG_ON;  /* Mask the HEALTHY# sig */
-
-	rval = schpc_setslotstatus(expander, board, slot, &setslot);
-
-	SCHPC_DEBUG1(D_IOC_CONNECT, "schpc_disconnect() - "
-	    "setslotstatus returned 0x%x", rval);
-
-	if (rval != 0) {
-		/*
-		 * System Controller/Mailbox failure.
-		 */
-		cmn_err(CE_WARN, "schpc - Hot Plug Disconnection Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : Unable to "
-		    "Communicate with System Controller", expander, board,
-		    SCHPC_SLOT_NUM(slot), schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-		goto failed;
-	}
-
-	SCHPC_DEBUG1(D_IOC_CONNECT, "schpc_disconnect() - "
-	    "slot_replystatus returned 0x%x", setslot.slot_replystatus);
-
-	if (setslot.slot_replystatus == PCIMSG_REPLY_GOOD) {
-
-		/*
-		 * The Request was successfully completed.
-		 */
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_CONNECTED;
-
-		schpc_setslotled(expander, board, slot,
-		    (POWER_LED_OFF | SERVICE_LED_ON | FAULT_LED_OFF));
-
-		SCHPC_DEBUG0(D_IOC_CONNECT,
-		    "schpc_disconnect() - setslotstatus succeeded");
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-	}
-	/*
-	 * System Controller/Mailbox failure.
-	 */
-	cmn_err(CE_WARN, "schpc - Hot Plug Disconnection Failed on "
-	    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : System Controller "
-	    "failed disconnection request", expander, board,
-	    SCHPC_SLOT_NUM(slot),
-	    schpc_p->schpc_slot[slot].ap_id);
-
-	schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-
-failed:
-	schpc_restore_leaf(slot);
-	mutex_enter(&schpc_p->schpc_mutex);
-	schpc_p->schpc_slot[slot].state &=
-	    ~SCHPC_SLOTSTATE_EXECUTING;
-	cv_signal(&schpc_p->schpc_cv);
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	return (HPC_ERR_FAILED);
-}
-
-/*
- * schpc_cpci_control
- *
- * Called by Hot Plug Services to perform a attachment point specific
- * on a Hot Pluggable Compact PCI Slot.
- */
-/*ARGSUSED*/
-static int
-schpc_cpci_control(caddr_t ops_arg, hpc_slot_t slot_hdl, int request,
-    caddr_t arg)
-{
-	int		rval;
-	int		expander, board, slot;
-	pci_setslot_t	setslot;
-	pci_getslot_t   slotstatus;
-	hpc_led_info_t	*hpc_led_info;
-
-	SCHPC_DEBUG3(D_IOC_CONTROL,
-	    "schpc_cpci_control(op_args=%p slot_hdl=%p request=%x)",
-	    (void *)ops_arg, (void *)slot_hdl, request);
-
-	mutex_enter(&schpc_p->schpc_mutex);
-
-	slot = schpc_slot_get_index(schpc_p, slot_hdl);
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_HPCINITED)) {
-		SCHPC_DEBUG0(D_IOC_CONNECT,
-		    "schpc_disconnect - HPC Not Inited");
-		mutex_exit(&schpc_p->schpc_mutex);
-		return (HPC_ERR_FAILED);
-	}
-
-	/*
-	 * Block if another thread is executing a HPC command.
-	 */
-	while (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_EXECUTING) {
-		cv_wait(&schpc_p->schpc_cv, &schpc_p->schpc_mutex);
-	}
-
-	schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_EXECUTING;
-
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	expander = schpc_p->schpc_slot[slot].expander; /* get expander */
-	board = schpc_p->schpc_slot[slot].board; /* get board */
-
-	/*
-	 * Initialize Set Slot Command.
-	 */
-	schpc_init_setslot_message(&setslot);
-
-	/*
-	 * Initialize LED to last know state.
-	 */
-	switch (schpc_p->schpc_slot[slot].led.led_power) {
-	case LED_ON:
-		setslot.slot_led_power = PCIMSG_LED_ON;
-		break;
-	case LED_OFF:
-		setslot.slot_led_power = PCIMSG_LED_OFF;
-		break;
-	case LED_FLASH:
-		setslot.slot_led_power = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	switch (schpc_p->schpc_slot[slot].led.led_service) {
-	case LED_ON:
-		setslot.slot_led_service = PCIMSG_LED_ON;
-		break;
-	case LED_OFF:
-		setslot.slot_led_service = PCIMSG_LED_OFF;
-		break;
-	case LED_FLASH:
-		setslot.slot_led_service = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	switch (schpc_p->schpc_slot[slot].led.led_fault) {
-	case LED_ON:
-		setslot.slot_led_fault = PCIMSG_LED_ON;
-		break;
-	case LED_OFF:
-		setslot.slot_led_fault = PCIMSG_LED_OFF;
-		break;
-	case LED_FLASH:
-		setslot.slot_led_fault = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	switch (request) {
-
-	case HPC_CTRL_GET_LED_STATE:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_GET_LED_STATE");
-		hpc_led_info = (hpc_led_info_t *)arg;
-
-		switch (hpc_led_info->led) {
-		case HPC_FAULT_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_fault) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_BLINK;
-				break;
-			}
-			break;
-
-		case HPC_POWER_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_power) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_BLINK;
-				break;
-			}
-			break;
-		case HPC_ATTN_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_fault) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			}
-			break;
-		case HPC_ACTIVE_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_service) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_BLINK;
-				break;
-			}
-			break;
-		default:
-			SCHPC_DEBUG1(D_IOC_CONTROL, "schpc_cpci_control() - "
-			    "Invalid LED %x", hpc_led_info->led);
-
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (HPC_ERR_FAILED);
-		}
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_SET_LED_STATE:
-		hpc_led_info = (hpc_led_info_t *)arg;
-
-		SCHPC_DEBUG1(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_SET_LED_STATE hpc_led_info=%p",
-		    (void *)hpc_led_info);
-
-		switch (hpc_led_info->led) {
-		case HPC_FAULT_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_OFF;
-				setslot.slot_led_fault = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_ON;
-				setslot.slot_led_fault = PCIMSG_LED_ON;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_FLASH;
-				setslot.slot_led_fault = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		case HPC_POWER_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_power =
-				    LED_OFF;
-				setslot.slot_led_power = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_power =
-				    LED_ON;
-				setslot.slot_led_power = PCIMSG_LED_ON;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_power =
-				    LED_FLASH;
-				setslot.slot_led_power = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		case HPC_ATTN_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_OFF;
-				setslot.slot_led_fault = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_FLASH;
-				setslot.slot_led_fault = PCIMSG_LED_FLASH;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_FLASH;
-				setslot.slot_led_fault = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		case HPC_ACTIVE_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_service =
-				    LED_OFF;
-				setslot.slot_led_service = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_service =
-				    LED_ON;
-				setslot.slot_led_service = PCIMSG_LED_ON;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_service =
-				    LED_FLASH;
-				setslot.slot_led_service = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		default:
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (0);
-		}
-
-		(void) schpc_setslotstatus(expander, board, slot, &setslot);
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_GET_SLOT_STATE: {
-		hpc_slot_state_t	*hpc_slot_state;
-
-		hpc_slot_state = (hpc_slot_state_t *)arg;
-
-		SCHPC_DEBUG1(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_GET_SLOT_STATE hpc_slot_state=%p",
-		    (void *)hpc_slot_state);
-
-		rval = schpc_getslotstatus(expander, board, slot, &slotstatus);
-
-		if (!rval) {
-
-			if (slotstatus.slot_replystatus != PCIMSG_REPLY_GOOD) {
-				return (HPC_ERR_FAILED);
-			}
-
-			if (slotstatus.slot_empty == PCIMSG_ON) {
-				*hpc_slot_state = HPC_SLOT_EMPTY;
-				SCHPC_DEBUG0(D_IOC_CONTROL, "Slot Empty");
-			} else if (slotstatus.slot_power_on == PCIMSG_ON) {
-				*hpc_slot_state = HPC_SLOT_CONNECTED;
-				SCHPC_DEBUG0(D_IOC_CONTROL, "Slot Connected");
-				schpc_p->schpc_slot[slot].state |=
-				    SCHPC_SLOTSTATE_CONNECTED;
-			} else {
-				*hpc_slot_state = HPC_SLOT_DISCONNECTED;
-				SCHPC_DEBUG0(D_IOC_CONTROL,
-				    "Slot Disconnected");
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_CONNECTED;
-			}
-		} else {
-			SCHPC_DEBUG0(D_IOC_CONTROL, "Mailbox Command failed");
-
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (HPC_ERR_FAILED);
-		}
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-	}
-	case HPC_CTRL_GET_BOARD_TYPE: {
-		hpc_board_type_t	*hpc_board_type;
-
-		hpc_board_type = (hpc_board_type_t *)arg;
-
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_GET_BOARD_TYPE");
-
-		/*
-		 * The HPC driver does not know what board type
-		 * is plugged in.
-		 */
-		*hpc_board_type = HPC_BOARD_CPCI_HS;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	}
-	case HPC_CTRL_DEV_CONFIGURED:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_DEV_CONFIGURED");
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_DEV_UNCONFIGURED:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_DEV_UNCONFIGURED");
-
-		if (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_ENUM) {
-			/*
-			 * When the occupant is unconfigured, power
-			 * down the slot.
-			 */
-			rval = schpc_disconnect((caddr_t)schpc_p,
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    0, 0);
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_ENUM;
-		}
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_ENABLE_AUTOCFG:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_ENABLE_AUTOCFG");
-
-		schpc_p->schpc_slot[slot].state |=
-		    SCHPC_SLOTSTATE_AUTOCFG_ENABLE;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_DISABLE_AUTOCFG:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_DISABLE_AUTOCFG");
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_AUTOCFG_ENABLE;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_DISABLE_ENUM:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_DISABLE_ENUM");
-
-		setslot.slot_disable_ENUM = PCIMSG_ON;
-
-		rval = schpc_setslotstatus(expander, board, slot, &setslot);
-
-		if (rval)
-			rval = HPC_ERR_FAILED;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (rval);
-
-	case HPC_CTRL_ENABLE_ENUM:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "HPC_CTRL_ENABLE_ENUM");
-
-		setslot.slot_enable_ENUM = PCIMSG_ON;
-
-		rval = schpc_setslotstatus(expander, board, slot, &setslot);
-
-		if (rval)
-			rval = HPC_ERR_FAILED;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (rval);
-
-	default:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_cpci_control() - "
-		    "****NOT SUPPORTED CONTROL CMD");
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (HPC_ERR_NOTSUPPORTED);
-	}
-}
-
-/*
- * schpc_pci_control
- *
- * Called by Hot Plug Services to perform a attachment point specific
- * on a Hot Pluggable Standard PCI Slot.
- */
-/*ARGSUSED*/
-static int
-schpc_pci_control(caddr_t ops_arg, hpc_slot_t slot_hdl, int request,
-    caddr_t arg)
-{
-	int		rval;
-	int		expander, board, slot;
-	pci_setslot_t	setslot;
-	pci_getslot_t   slotstatus;
-	hpc_led_info_t	*hpc_led_info;
-
-	SCHPC_DEBUG3(D_IOC_CONTROL,
-	    "schpc_pci_control(op_args=%p slot_hdl=%p request=%x)",
-	    (void *)ops_arg, (void *)slot_hdl, request);
-
-	mutex_enter(&schpc_p->schpc_mutex);
-
-	slot = schpc_slot_get_index(schpc_p, slot_hdl);
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_HPCINITED)) {
-		SCHPC_DEBUG0(D_IOC_CONNECT,
-		    "schpc_disconnect - HPC Not Inited");
-		mutex_exit(&schpc_p->schpc_mutex);
-		return (HPC_ERR_FAILED);
-	}
-
-	/*
-	 * Block if another thread is executing a HPC command.
-	 */
-	while (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_EXECUTING) {
-		cv_wait(&schpc_p->schpc_cv, &schpc_p->schpc_mutex);
-	}
-
-	schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_EXECUTING;
-
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	expander = schpc_p->schpc_slot[slot].expander; /* get expander */
-	board = schpc_p->schpc_slot[slot].board; /* get board */
-
-	/*
-	 * Initialize Set Slot Command.
-	 */
-	schpc_init_setslot_message(&setslot);
-
-	/*
-	 * Initialize LED to last know state.
-	 */
-	switch (schpc_p->schpc_slot[slot].led.led_power) {
-	case LED_ON:
-		setslot.slot_led_power = PCIMSG_LED_ON;
-		break;
-	case LED_OFF:
-		setslot.slot_led_power = PCIMSG_LED_OFF;
-		break;
-	case LED_FLASH:
-		setslot.slot_led_power = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	switch (schpc_p->schpc_slot[slot].led.led_service) {
-	case LED_ON:
-		setslot.slot_led_service = PCIMSG_LED_ON;
-		break;
-	case LED_OFF:
-		setslot.slot_led_service = PCIMSG_LED_OFF;
-		break;
-	case LED_FLASH:
-		setslot.slot_led_service = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	switch (schpc_p->schpc_slot[slot].led.led_fault) {
-	case LED_ON:
-		setslot.slot_led_fault = PCIMSG_LED_ON;
-		break;
-	case LED_OFF:
-		setslot.slot_led_fault = PCIMSG_LED_OFF;
-		break;
-	case LED_FLASH:
-		setslot.slot_led_fault = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	switch (request) {
-
-
-	case HPC_CTRL_GET_SLOT_STATE: {
-		hpc_slot_state_t	*hpc_slot_state;
-
-		hpc_slot_state = (hpc_slot_state_t *)arg;
-
-		SCHPC_DEBUG1(D_IOC_CONTROL, "schpc_pci_control() - "
-		    "HPC_CTRL_GET_SLOT_STATE hpc_slot_state=%p",
-		    (void *)hpc_slot_state);
-
-		rval = schpc_getslotstatus(expander, board, slot, &slotstatus);
-
-		if (!rval) {
-
-			if (slotstatus.slot_replystatus != PCIMSG_REPLY_GOOD) {
-
-				mutex_enter(&schpc_p->schpc_mutex);
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_EXECUTING;
-				cv_signal(&schpc_p->schpc_cv);
-				mutex_exit(&schpc_p->schpc_mutex);
-
-				return (HPC_ERR_FAILED);
-			}
-
-			if (slotstatus.slot_empty == PCIMSG_ON) {
-				*hpc_slot_state = HPC_SLOT_EMPTY;
-				SCHPC_DEBUG0(D_IOC_CONTROL, "Slot Empty");
-			} else if (slotstatus.slot_power_on == PCIMSG_ON) {
-				*hpc_slot_state = HPC_SLOT_CONNECTED;
-				SCHPC_DEBUG0(D_IOC_CONTROL, "Slot Connected");
-				schpc_p->schpc_slot[slot].state |=
-				    SCHPC_SLOTSTATE_CONNECTED;
-			} else {
-				*hpc_slot_state = HPC_SLOT_DISCONNECTED;
-				SCHPC_DEBUG0(D_IOC_CONTROL,
-				    "Slot Disconnected");
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_CONNECTED;
-			}
-		} else {
-			SCHPC_DEBUG0(D_IOC_CONTROL, "Mailbox Command failed");
-
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (HPC_ERR_FAILED);
-		}
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-	}
-	case HPC_CTRL_GET_BOARD_TYPE: {
-		hpc_board_type_t	*hpc_board_type;
-
-		hpc_board_type = (hpc_board_type_t *)arg;
-
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_pci_control() - "
-		    "HPC_CTRL_GET_BOARD_TYPE");
-
-
-		/*
-		 * The HPC driver does not know what board type
-		 * is plugged in.
-		 */
-		*hpc_board_type = HPC_BOARD_PCI_HOTPLUG;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	}
-	case HPC_CTRL_DEV_UNCONFIG_START:
-	case HPC_CTRL_DEV_CONFIG_START:
-	case HPC_CTRL_DEV_CONFIGURED:
-	case HPC_CTRL_DEV_UNCONFIGURED:
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_GET_LED_STATE:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_pci_control() - "
-		    "HPC_CTRL_GET_LED_STATE");
-		hpc_led_info = (hpc_led_info_t *)arg;
-
-		switch (hpc_led_info->led) {
-		case HPC_FAULT_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_fault) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_BLINK;
-				break;
-			}
-			break;
-
-		case HPC_POWER_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_power) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_BLINK;
-				break;
-			}
-			break;
-		case HPC_ATTN_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_fault) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			}
-			break;
-		case HPC_ACTIVE_LED:
-			switch (schpc_p->schpc_slot[slot].led.led_service) {
-			case LED_OFF:
-				hpc_led_info->state = HPC_LED_OFF;
-				break;
-			case LED_ON:
-				hpc_led_info->state = HPC_LED_ON;
-				break;
-			case LED_FLASH:
-				hpc_led_info->state = HPC_LED_BLINK;
-				break;
-			}
-			break;
-		default:
-			SCHPC_DEBUG1(D_IOC_CONTROL, "schpc_pci_control() - "
-			    "Invalid LED %x", hpc_led_info->led);
-
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (HPC_ERR_FAILED);
-		}
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_SET_LED_STATE:
-		hpc_led_info = (hpc_led_info_t *)arg;
-
-		SCHPC_DEBUG1(D_IOC_CONTROL, "schpc_pci_control() - "
-		    "HPC_CTRL_SET_LED_STATE hpc_led_info=%p",
-		    (void *)hpc_led_info);
-
-		switch (hpc_led_info->led) {
-		case HPC_FAULT_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_OFF;
-				setslot.slot_led_fault = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_ON;
-				setslot.slot_led_fault = PCIMSG_LED_ON;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_FLASH;
-				setslot.slot_led_fault = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		case HPC_POWER_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_power =
-				    LED_OFF;
-				setslot.slot_led_power = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_power =
-				    LED_ON;
-				setslot.slot_led_power = PCIMSG_LED_ON;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_power =
-				    LED_FLASH;
-				setslot.slot_led_power = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		case HPC_ATTN_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_OFF;
-				setslot.slot_led_fault = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_FLASH;
-				setslot.slot_led_fault = PCIMSG_LED_FLASH;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_fault =
-				    LED_FLASH;
-				setslot.slot_led_fault = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		case HPC_ACTIVE_LED:
-			switch (hpc_led_info->state) {
-			case HPC_LED_OFF:
-				schpc_p->schpc_slot[slot].led.led_service =
-				    LED_OFF;
-				setslot.slot_led_service = PCIMSG_LED_OFF;
-				break;
-			case HPC_LED_ON:
-				schpc_p->schpc_slot[slot].led.led_service =
-				    LED_ON;
-				setslot.slot_led_service = PCIMSG_LED_ON;
-				break;
-			case HPC_LED_BLINK:
-				schpc_p->schpc_slot[slot].led.led_service =
-				    LED_FLASH;
-				setslot.slot_led_service = PCIMSG_LED_FLASH;
-				break;
-			}
-			break;
-		default:
-			mutex_enter(&schpc_p->schpc_mutex);
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_EXECUTING;
-			cv_signal(&schpc_p->schpc_cv);
-			mutex_exit(&schpc_p->schpc_mutex);
-
-			return (0);
-		}
-
-		(void) schpc_setslotstatus(expander, board, slot, &setslot);
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_ENABLE_AUTOCFG:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_pci_control() - "
-		    "HPC_CTRL_ENABLE_AUTOCFG");
-
-		schpc_p->schpc_slot[slot].state |=
-		    SCHPC_SLOTSTATE_AUTOCFG_ENABLE;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_DISABLE_AUTOCFG:
-		SCHPC_DEBUG0(D_IOC_CONTROL, "schpc_pci_control() - "
-		    "HPC_CTRL_DISABLE_AUTOCFG");
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_AUTOCFG_ENABLE;
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (0);
-
-	case HPC_CTRL_DISABLE_ENUM:
-	case HPC_CTRL_ENABLE_ENUM:
-	default:
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		return (HPC_ERR_NOTSUPPORTED);
-	}
-}
-
-/*
- * schpc_test
- *
- * Tests the slot.
- */
-/*ARGSUSED*/
-static void
-schpc_test(caddr_t ops_arg, int slot, void *data, uint_t flags)
-{
-	pci_getslot_t	slotstatus;
-	pci_setslot_t	setslot;
-	int		expander, board;
-	int		rval;
-	int		retry = 1;
-
-	SCHPC_DEBUG2(D_IOC_TEST, "schpc_test(op_args=%p slot=%x)",
-	    (void *)ops_arg, SCHPC_SLOT_NUM(slot));
-
-	SCHPC_DEBUG3(D_IOC_TEST,
-	    "    schpc_test() Expander=%d Board=%d Slot=%d",
-	    schpc_p->schpc_slot[slot].expander,
-	    schpc_p->schpc_slot[slot].board, SCHPC_SLOT_NUM(slot));
-
-	expander = schpc_p->schpc_slot[slot].expander;
-	board = schpc_p->schpc_slot[slot].board;
-
-restart_test:
-	/*
-	 * Initial the slot with its occupant and receptacle in good condition.
-	 */
-	schpc_p->schpc_slot[slot].state |=  SCHPC_SLOTSTATE_REC_GOOD;
-	schpc_p->schpc_slot[slot].state |=  SCHPC_SLOTSTATE_OCC_GOOD;
-
-
-	rval = schpc_getslotstatus(expander, board, slot, &slotstatus);
-
-	if (rval) {
-		/*
-		 * System Controller/Mailbox failure.
-		 */
-		cmn_err(CE_WARN, "schpc - Hot Plug Slot Test Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : Unable to "
-		    "Communicate with System Controller", expander, board,
-		    SCHPC_SLOT_NUM(slot), schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_p->schpc_slot[slot].state &=  ~SCHPC_SLOTSTATE_REC_GOOD;
-		return;
-	}
-
-	if (slotstatus.slot_replystatus != PCIMSG_REPLY_GOOD) {
-
-		cmn_err(CE_WARN, "schpc - Expander %d Board %d PCI Slot %d "
-		    "is not hot pluggable\n", expander, board,
-		    SCHPC_SLOT_NUM(slot));
-
-		schpc_p->schpc_slot[slot].state &=  ~SCHPC_SLOTSTATE_REC_GOOD;
-		return;
-	}
-
-	switch (slotstatus.slot_condition) {
-	case PCIMSG_SLOTCOND_OCC_FAIL:
-		cmn_err(CE_WARN, "schpc - Hot Plug Slot Test Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-		    "System Controller/Occupant Failed",
-		    expander, board, SCHPC_SLOT_NUM(slot),
-		    schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot,
-		    (POWER_LED_OFF | SERVICE_LED_ON | FAULT_LED_ON));
-
-		schpc_p->schpc_slot[slot].state &=  ~SCHPC_SLOTSTATE_OCC_GOOD;
-		return;
-	case PCIMSG_SLOTCOND_REC_FAIL:
-		cmn_err(CE_WARN, "schpc - Hot Plug Slot Test Failed on "
-		    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-		    "System Controller/Receptacle Failed",
-		    expander, board, SCHPC_SLOT_NUM(slot),
-		    schpc_p->schpc_slot[slot].ap_id);
-
-		schpc_setslotled(expander, board, slot,
-		    (POWER_LED_OFF | SERVICE_LED_OFF | FAULT_LED_ON));
-
-		schpc_p->schpc_slot[slot].state &=  ~SCHPC_SLOTSTATE_REC_GOOD;
-		return;
-	}
-
-	if (slotstatus.slot_power_on) {
-		schpc_p->schpc_slot[slot].led.led_power = PCIMSG_LED_ON;
-
-		if (!slotstatus.slot_HEALTHY) {
-			/*
-			 * cPCI Adapter is not asserting HEALTHY#.
-			 */
-			cmn_err(CE_WARN, "schpc - Hot Plug Slot Test Failed on "
-			    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "PCI adapter not HEALTHY", expander, board,
-			    SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot,
-			    (POWER_LED_ON | SERVICE_LED_OFF | FAULT_LED_ON));
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_OCC_GOOD;
-
-			return;
-		}
-
-		if (!slotstatus.slot_powergood) {
-			/*
-			 * PCI Power Input is not good.
-			 */
-			cmn_err(CE_WARN, "schpc - Hot Plug Slot Test Failed on "
-			    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "System Controller PCI Power Input Not Good",
-			    expander, board, SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot,
-			    (POWER_LED_ON | SERVICE_LED_OFF | FAULT_LED_ON));
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_OCC_GOOD;
-
-			return;
-		}
-
-		if (slotstatus.slot_powerfault) {
-			/*
-			 * PCI Power Fault.
-			 */
-			cmn_err(CE_WARN, "schpc - Hot Plug Slot Test Failed on "
-			    "Expander %d Board %d PCI Slot %d - Ap_Id=%s : "
-			    "System Controller PCI Power Fault",
-			    expander, board, SCHPC_SLOT_NUM(slot),
-			    schpc_p->schpc_slot[slot].ap_id);
-
-			schpc_setslotled(expander, board, slot,
-			    (POWER_LED_ON | SERVICE_LED_OFF | FAULT_LED_ON));
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_OCC_GOOD;
-
-			return;
-		}
-	}
-
-	SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() Test Successful - ret 0");
-
-	/*
-	 * Is the slot empty?
-	 */
-	if (slotstatus.slot_empty) {
-		SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() Slot Empty");
-
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_PRESENT;
-
-		if (slotstatus.slot_power_on) {
-
-			SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() Empty Slot "
-			    "is powered ON");
-
-			/*
-			 * Tests will be retried once after powering off
-			 * an empty slot.
-			 */
-			if (retry) {
-
-				/*
-				 * Turn off the slot and restart test.
-				 */
-				SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() "
-				    "Turning Empty Slot OFF");
-
-				schpc_init_setslot_message(&setslot);
-				setslot.slot_power_off = PCIMSG_ON;
-				(void) schpc_setslotstatus(
-				    expander, board, slot, &setslot);
-
-				retry = 0;
-
-				goto restart_test;
-			}
-		}
-	} else {
-		SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() Adapter Present");
-
-		if (!slotstatus.slot_power_on) {
-			if (retry) {
-				/*
-				 * If there is a cassette present and the
-				 * power is off, try turning the power on and
-				 * restart the test. This allows access to
-				 * the FRUID when an empty cassette is
-				 * installed.
-				 */
-				SCHPC_DEBUG0(D_IOC_TEST,
-				    "schpc_test() Power On Adapter");
-				schpc_init_setslot_message(&setslot);
-				setslot.slot_power_on = PCIMSG_ON;
-				(void) schpc_setslotstatus(
-				    expander, board, slot, &setslot);
-				retry = 0;
-				goto restart_test;
-			}
-		}
-
-		schpc_p->schpc_slot[slot].state |=
-		    SCHPC_SLOTSTATE_PRESENT;
-	}
-
-	/*
-	 * Is the slot powered up?
-	 */
-	schpc_init_setslot_message(&setslot);
-
-	if (slotstatus.slot_power_on) {
-		SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() Slot Power On");
-
-		schpc_p->schpc_slot[slot].state |=
-		    SCHPC_SLOTSTATE_CONNECTED;
-
-		setslot.slot_led_power = PCIMSG_LED_ON;
-		setslot.slot_led_service = PCIMSG_LED_OFF;
-		setslot.slot_enable_ENUM = PCIMSG_ON;
-		setslot.slot_enable_HEALTHY = PCIMSG_ON;
-	} else {
-		SCHPC_DEBUG0(D_IOC_TEST, "schpc_test() Slot Power Off");
-
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_CONNECTED;
-
-		setslot.slot_led_power = PCIMSG_LED_OFF;
-		setslot.slot_led_service = PCIMSG_LED_ON;
-		setslot.slot_disable_ENUM = PCIMSG_ON;
-		setslot.slot_disable_HEALTHY = PCIMSG_ON;
-	}
-
-	setslot.slot_led_fault = PCIMSG_LED_OFF;
-
-	(void) schpc_setslotstatus(expander, board, slot, &setslot);
-
-	/*
-	 * Save LED State.
-	 */
-	switch (setslot.slot_led_power) {
-	case PCIMSG_LED_ON:
-		schpc_p->schpc_slot[slot].led.led_power = LED_ON;
-		break;
-	case PCIMSG_LED_OFF:
-		schpc_p->schpc_slot[slot].led.led_power = LED_OFF;
-		break;
-	case PCIMSG_LED_FLASH:
-		schpc_p->schpc_slot[slot].led.led_power = LED_FLASH;
-		break;
-	}
-	switch (setslot.slot_led_service) {
-	case PCIMSG_LED_ON:
-		schpc_p->schpc_slot[slot].led.led_service = LED_ON;
-		break;
-	case PCIMSG_LED_OFF:
-		schpc_p->schpc_slot[slot].led.led_service = LED_OFF;
-		break;
-	case PCIMSG_LED_FLASH:
-		schpc_p->schpc_slot[slot].led.led_service = LED_FLASH;
-		break;
-	}
-	switch (setslot.slot_led_fault) {
-	case PCIMSG_LED_ON:
-		schpc_p->schpc_slot[slot].led.led_fault = LED_ON;
-		break;
-	case PCIMSG_LED_OFF:
-		schpc_p->schpc_slot[slot].led.led_fault = LED_OFF;
-		break;
-	case PCIMSG_LED_FLASH:
-		schpc_p->schpc_slot[slot].led.led_fault = LED_FLASH;
-		break;
-	}
-}
-
-
-/*
- * schpc_event_handler
- *
- * Placed on the schpc_event_taskq by schpc_event_filter when an
- * unsolicited MBOXSC_MSG_EVENT is received from the SC.  It handles
- * things like power insertion/removal, ENUM#, etc.
- */
-static void
-schpc_event_handler(void *arg)
-{
-	pci_getslot_t	slotstatus;
-	uint8_t		expander, board, slot;
-	int		rval;
-	pcimsg_t *event = (pcimsg_t *)arg;
-
-	/*
-	 * OK, we got an event message. Since the event message only tells
-	 * us something has changed and not changed to what, we need to get
-	 * the current slot status to find how WHAT was change to WHAT.
-	 */
-
-	slot = event->pcimsg_slot;
-	expander = event->pcimsg_node; /* get expander */
-	board = event->pcimsg_board; /* get board */
-
-	SCHPC_DEBUG3(D_EVENT,
-	    "schpc_event_handler() - exp=%d board=%d slot=%d",
-	    expander, board, slot);
-
-	/* create a slot table index */
-	slot = SCHPC_MAKE_SLOT_INDEX2(expander, slot);
-
-	SCHPC_DEBUG1(D_EVENT,
-	    "schpc_event_handler() - expanded slot %d", slot);
-
-	if (schpc_p == NULL) {
-		cmn_err(CE_WARN, "schpc/Event Handler - Can not find schpc");
-		kmem_free(event, sizeof (pcimsg_t));
-		return;
-	}
-
-	mutex_enter(&schpc_p->schpc_mutex);
-
-	if (!(schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_HPCINITED)) {
-		SCHPC_DEBUG0(D_EVENT, "schpc_event_handler - HPC Not Inited");
-		mutex_exit(&schpc_p->schpc_mutex);
-		kmem_free(event, sizeof (pcimsg_t));
-		return;
-	}
-	/*
-	 * Block if another thread is executing a HPC command.
-	 */
-	while (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_EXECUTING) {
-		SCHPC_DEBUG0(D_EVENT, "schpc_event_handler - Slot is busy");
-		cv_wait(&schpc_p->schpc_cv, &schpc_p->schpc_mutex);
-	}
-
-	schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_EXECUTING;
-
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	rval = schpc_getslotstatus(expander, board, slot, &slotstatus);
-
-	if (rval) {
-		cmn_err(CE_WARN, "schpc/Event Handler - Can not get status "
-		    "for expander=%d board=%d slot=%d\n",
-		    expander, board, SCHPC_SLOT_NUM(slot));
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-		kmem_free(event, sizeof (pcimsg_t));
-		return;
-	}
-
-	if (slotstatus.slot_replystatus != PCIMSG_REPLY_GOOD) {
-		cmn_err(CE_WARN, "schpc/Event Handler - Can not get good "
-		    "status for expander=%d board=%d slot=%d\n",
-		    expander, board, SCHPC_SLOT_NUM(slot));
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		kmem_free(event, sizeof (pcimsg_t));
-		return;
-	}
-
-	SCHPC_DEBUG3(D_EVENT, "Event Received - Expander %d Board %d Slot %d",
-	    expander, board, SCHPC_SLOT_NUM(slot));
-
-	if (schpc_p->schpc_slot[slot].slot_ops == NULL) {
-		SCHPC_DEBUG3(D_EVENT, "schpc/Event Handler - Received event "
-		    "for unregistered slot for expander=%d board=%d slot=%d",
-		    expander, board, SCHPC_SLOT_NUM(slot));
-
-		mutex_enter(&schpc_p->schpc_mutex);
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_EXECUTING;
-		cv_signal(&schpc_p->schpc_cv);
-		mutex_exit(&schpc_p->schpc_mutex);
-
-		kmem_free(event, sizeof (pcimsg_t));
-		return;
-	}
-
-	/* Slot Power Event */
-
-	if (event->pcimsg_type.pcimsg_slotevent.slot_power) {
-		SCHPC_DEBUG0(D_EVENT, "Event Type: Slot Power Event");
-		/*
-		 * The SC may have changed to slot power status.
-		 */
-		if (slotstatus.slot_power_on) {
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_CONNECTED;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_POWER_ON, 0);
-		} else {
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_CONNECTED;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_POWER_OFF, 0);
-		}
-	}
-
-	/* Adapter Insertion/Removal Event */
-
-	if (event->pcimsg_type.pcimsg_slotevent.slot_presence) {
-		if (slotstatus.slot_empty == PCIMSG_ON) {
-
-			/* Adapter Removed */
-
-			SCHPC_DEBUG0(D_EVENT, "Event Type: Adapter Removed");
-
-			if (schpc_p->schpc_slot[slot].state &
-			    SCHPC_SLOTSTATE_CONNECTED) {
-				/*
-				 * If the adapter has been removed while
-				 * there the slot is connected, it could be
-				 * due to a ENUM handling.
-				 */
-				cmn_err(CE_WARN, "Card removed from "
-				    "powered on slot at "
-				    "expander=%d board=%d slot=%d\n",
-				    expander, board, SCHPC_SLOT_NUM(slot));
-
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_EXECUTING;
-				rval = schpc_disconnect((caddr_t)schpc_p,
-				    schpc_p->schpc_slot[slot].slot_handle,
-				    0, 0);
-				mutex_enter(&schpc_p->schpc_mutex);
-				while (schpc_p->schpc_slot[slot].state &
-				    SCHPC_SLOTSTATE_EXECUTING) {
-					SCHPC_DEBUG0(D_EVENT,
-					    "schpc_event_handler - "
-					    "Slot is busy");
-					cv_wait(&schpc_p->schpc_cv,
-					    &schpc_p->schpc_mutex);
-				}
-
-				schpc_p->schpc_slot[slot].state |=
-				    SCHPC_SLOTSTATE_EXECUTING;
-
-				mutex_exit(&schpc_p->schpc_mutex);
-			}
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_OCC_GOOD;
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_PRESENT;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_REMOVAL, 0);
-		} else {
-
-			/* Adapter Inserted */
-
-			SCHPC_DEBUG0(D_EVENT, "Event Type: Adapter Inserted");
-
-			if (schpc_p->schpc_slot[slot].state &
-			    SCHPC_SLOTSTATE_PRESENT) {
-				/*
-				 * If the adapter is already present
-				 * throw the this event away.
-				 */
-
-				SCHPC_DEBUG0(D_EVENT,
-				    "Adapter is already present");
-
-				mutex_enter(&schpc_p->schpc_mutex);
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_EXECUTING;
-				cv_signal(&schpc_p->schpc_cv);
-				mutex_exit(&schpc_p->schpc_mutex);
-
-				kmem_free(event, sizeof (pcimsg_t));
-				return;
-			}
-
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_PRESENT;
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_CONNECTED;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_INSERTION, 0);
-
-			if (schpc_p->schpc_slot[slot].state &
-			    SCHPC_SLOTSTATE_AUTOCFG_ENABLE) {
-				SCHPC_DEBUG0(D_EVENT, "Auto Configuration "
-				    "(Connect/Configure) Started");
-
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_EXECUTING;
-
-				rval = schpc_connect((caddr_t)schpc_p,
-				    schpc_p->schpc_slot[slot].slot_handle,
-				    0, 0);
-
-				if (rval) {
-					cmn_err(CE_WARN, "schpc/Event Handler -"
-					    " Can not connect");
-
-					mutex_enter(&schpc_p->schpc_mutex);
-					schpc_p->schpc_slot[slot].state &=
-					    ~SCHPC_SLOTSTATE_EXECUTING;
-					cv_signal(&schpc_p->schpc_cv);
-					mutex_exit(&schpc_p->schpc_mutex);
-
-					kmem_free(event, sizeof (pcimsg_t));
-					return;
-				}
-				mutex_enter(&schpc_p->schpc_mutex);
-				while (schpc_p->schpc_slot[slot].state &
-				    SCHPC_SLOTSTATE_EXECUTING) {
-					SCHPC_DEBUG0(D_EVENT,
-					    "schpc_event_handler - "
-					    "Slot is busy");
-					cv_wait(&schpc_p->schpc_cv,
-					    &schpc_p->schpc_mutex);
-				}
-
-				schpc_p->schpc_slot[slot].state |=
-				    SCHPC_SLOTSTATE_EXECUTING;
-
-				mutex_exit(&schpc_p->schpc_mutex);
-
-				(void) hpc_slot_event_notify(
-				    schpc_p->schpc_slot[slot].slot_handle,
-				    HPC_EVENT_SLOT_CONFIGURE, 0);
-			} else {
-				schpc_setslotled(expander, board, slot,
-				    SERVICE_LED_ON);
-			}
-		}
-	}
-
-	/* ENUM# signal change event */
-
-	if (event->pcimsg_type.pcimsg_slotevent.slot_ENUM) {
-		/*
-		 * ENUM should only be received to the adapter remove
-		 * procedure.
-		 */
-
-		SCHPC_DEBUG0(D_EVENT, "Event Type: ENUM Asserted");
-
-		schpc_setslotled(expander, board, slot, FAULT_LED_FLASH);
-
-		schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_ENUM;
-
-		(void) hpc_slot_event_notify(
-		    schpc_p->schpc_slot[slot].slot_handle,
-		    HPC_EVENT_SLOT_ENUM, 0);
-	}
-
-	/* HEALTHY# signal change event */
-
-	if (event->pcimsg_type.pcimsg_slotevent.slot_HEALTHY) {
-
-		if (!slotstatus.slot_HEALTHY) {
-
-			SCHPC_DEBUG0(D_EVENT, "Event Type: !HEALTHY ASSERTED");
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_OCC_GOOD;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_NOT_HEALTHY, 0);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-		} else {
-			SCHPC_DEBUG0(D_EVENT, "Event Type: HEALTHY OK");
-
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_OCC_GOOD;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_HEALTHY_OK, 0);
-
-			schpc_setslotled(expander, board, slot,
-			    FAULT_LED_OFF);
-		}
-	}
-
-	/* Good Power change event */
-
-	if (event->pcimsg_type.pcimsg_slotevent.slot_powergood) {
-		if (slotstatus.slot_powergood == PCIMSG_ON) {
-
-			SCHPC_DEBUG0(D_EVENT,
-			    "Event Type: Slot Power Good Detected");
-
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_OCC_GOOD;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_HEALTHY_OK, 0);
-
-			schpc_setslotled(expander, board, slot,
-			    FAULT_LED_OFF);
-		} else {
-			SCHPC_DEBUG0(D_EVENT, "Event Type: Slot Power Not Good "
-			    "Detected");
-
-			if (schpc_p->schpc_slot[slot].state &
-			    SCHPC_SLOTSTATE_CONNECTED) {
-
-				SCHPC_DEBUG0(D_EVENT, "Slot Power Not Good: "
-				    "power failed");
-
-				schpc_p->schpc_slot[slot].state &=
-				    ~SCHPC_SLOTSTATE_OCC_GOOD;
-
-				(void) hpc_slot_event_notify(
-				    schpc_p->schpc_slot[slot].slot_handle,
-				    HPC_EVENT_SLOT_NOT_HEALTHY, 0);
-
-				schpc_setslotled(expander, board, slot,
-				    FAULT_LED_ON);
-			}
-		}
-	}
-
-	/* Power Fault change event */
-
-	if (event->pcimsg_type.pcimsg_slotevent.slot_powerfault) {
-		if (slotstatus.slot_powerfault == PCIMSG_ON) {
-
-			SCHPC_DEBUG0(D_EVENT, "Event Type: Slot Power Fault "
-			    "Detected");
-
-			schpc_p->schpc_slot[slot].state &=
-			    ~SCHPC_SLOTSTATE_OCC_GOOD;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_NOT_HEALTHY, 0);
-
-			schpc_setslotled(expander, board, slot, FAULT_LED_ON);
-		} else {
-			SCHPC_DEBUG0(D_EVENT, "Event Type: Slot Power Fault "
-			    "Cleared");
-
-			schpc_p->schpc_slot[slot].state |=
-			    SCHPC_SLOTSTATE_OCC_GOOD;
-
-			(void) hpc_slot_event_notify(
-			    schpc_p->schpc_slot[slot].slot_handle,
-			    HPC_EVENT_SLOT_HEALTHY_OK, 0);
-
-			schpc_setslotled(expander, board, slot,
-			    FAULT_LED_OFF);
-		}
-	}
-	mutex_enter(&schpc_p->schpc_mutex);
-	schpc_p->schpc_slot[slot].state &=
-	    ~SCHPC_SLOTSTATE_EXECUTING;
-	cv_signal(&schpc_p->schpc_cv);
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	kmem_free(event, sizeof (pcimsg_t));
-}
-
-
-/*
- * schpc_event_filter
- *
- * The schpc_event_filter enqueues MBOXSC_MSG_EVENTs into the
- * schpc_event_taskq for processing by the schpc_event_handler _if_
- * hotpluggable pci slots have been registered; otherwise, the
- * MBOXSC_MSG_EVENTs are discarded in order to keep the incoming mailbox
- * open for future messages.
- */
-static void
-schpc_event_filter(pcimsg_t *pmsg)
-{
-	if (slots_registered == B_TRUE) {
-
-		pcimsg_t *pevent;
-
-		/*
-		 * If hotpluggable pci slots have been registered then enqueue
-		 * the event onto the schpc_event_taskq for processing.
-		 */
-
-		SCHPC_DEBUG0(D_EVENT, "schpc_event_filter() - "
-		    "slots_registered = B_TRUE");
-
-		pevent = (pcimsg_t *)kmem_zalloc(sizeof (pcimsg_t), KM_SLEEP);
-		bcopy(pmsg, pevent, sizeof (pcimsg_t));
-
-		SCHPC_DEBUG0(D_EVENT, "schpc_event_filter() - "
-		    "event alloc'd");
-
-		if (taskq_dispatch(schpc_event_taskq, schpc_event_handler,
-		    (void *)pevent, TQ_SLEEP) == TASKQID_INVALID) {
-			cmn_err(CE_WARN, "schpc: schpc_event_filter - "
-			    "taskq_dispatch failed to enqueue event");
-			kmem_free(pevent, sizeof (pcimsg_t));
-			return;
-		}
-
-		SCHPC_DEBUG0(D_EVENT, "schpc_event_filter() - "
-		    "event was taskq_dispatch'ed to schpc_event_handler");
-	} else {
-		/*
-		 * Oops, schpc received an event _before_ the slots have been
-		 * registered. In that case there is no choice but to toss
-		 * the event.
-		 */
-		cmn_err(CE_WARN, "schpc: schpc_event_filter - discarding "
-		    "premature event");
-	}
-}
-
-
-/*
- * schpc_msg_thread
- * A stand-alone thread that monitors the incoming mailbox for
- * MBOXSC_MSG_REPLYs and MBOXSC_MSG_EVENTs, and removes them from
- * the mailbox for processing.
- *
- * MBOXSC_MSG_REPLYs are matched against outstanding REPLYs in the
- * schpc_replylist, and the waiting thread is notified that its REPLY
- * message has arrived; otherwise, if no REPLY match is found, then it is
- * discarded.
- *
- * MBOXSC_MSG_EVENTs are enqueued into the schpc_event_taskq and processed
- * by the schpc_event_handler.
- *
- * The schpc_msg_thread is started in _init().
- */
-void
-schpc_msg_thread(void)
-{
-	int			err;
-	uint32_t		type;
-	uint32_t		cmd;
-	uint64_t		transid;
-	uint32_t		length;
-	pcimsg_t		msg;
-
-	SCHPC_DEBUG0(D_THREAD, "schpc_msg_thread() running");
-
-	/* CONSTCOND */
-	while (1) {
-
-		/* setup wildcard arguments */
-		type = 0;
-		cmd = 0;
-		transid = 0;
-		length = sizeof (pcimsg_t);
-		bzero(&msg, sizeof (pcimsg_t));
-
-		err = mboxsc_getmsg(KEY_SCPC, &type, &cmd,
-		    &transid, &length, (void *)&msg,
-		    schpc_timeout_getmsg);
-
-		if (err) {
-			switch (err) {
-
-			/*FALLTHROUGH*/
-			case ETIMEDOUT:
-			case EAGAIN:
-				continue;
-
-			default:
-				/*
-				 * unfortunately, we can't do very much here
-				 * because we're wildcarding mboxsc_getmsg
-				 * so if it encounters an error, we can't
-				 * identify which transid it belongs to.
-				 */
-				cmn_err(CE_WARN,
-				"schpc - mboxsc_getmsg failed, err=0x%x", err);
-				delay(drv_usectohz(100000));
-				continue;
-			}
-		}
-
-		if (msg.pcimsg_revision != PCIMSG_REVISION) {
-			/*
-			 * This version of the schpc driver only understands
-			 * version 1.0 of the PCI Hot Plug Message format.
-			 */
-			cmn_err(CE_WARN, " schpc: schpc_msg_thread - "
-			    "discarding event w/ unknown message version %x",
-			    msg.pcimsg_revision);
-			continue;
-		}
-
-		switch (type) {
-
-		case MBOXSC_MSG_EVENT:
-			schpc_event_filter(&msg);
-			break;
-
-		case MBOXSC_MSG_REPLY:
-			schpc_reply_handler(&msg, type, cmd, transid, length);
-			break;
-
-		default:
-			cmn_err(CE_WARN,
-			    "schpc - mboxsc_getmsg unknown msg"
-			    " type=0x%x", type);
-			break;
-		}
-	}
-	/* this thread never exits */
-}
-
-
-void
-schpc_reply_handler(pcimsg_t *pmsg, uint32_t type, uint32_t cmd,
-			uint64_t transid, uint32_t length)
-{
-	schpc_replylist_t	*entry;
-
-	mutex_enter(&schpc_replylist_mutex);
-	entry = schpc_replylist_first;
-	while (entry != NULL) {
-		if (entry->transid == transid) {
-			break;
-		} else
-			entry = entry->next;
-	}
-	if (entry) {
-		SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS,
-		    "schpc_reply_handler() - 0x%lx transid reply "
-		    "received", transid);
-
-		mutex_enter(&entry->reply_lock);
-		if (entry->reply_cexit == B_FALSE) {
-			SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS,
-			    "schpc_reply_handler() - 0x%lx transid"
-			    " cv_signal waiting thread", transid);
-
-			/*
-			 * emulate mboxsc_getmsg by copying the reply
-			 */
-			entry->type = type;
-			entry->cmd = cmd;
-			entry->transid = transid;
-			entry->length = length;
-			bcopy((caddr_t)pmsg, &entry->reply, length);
-
-			/* reply was received */
-			entry->reply_recvd = B_TRUE;
-
-			/*
-			 * wake up thread waiting for reply with transid
-			 */
-			cv_signal(&entry->reply_cv);
-		}
-		mutex_exit(&entry->reply_lock);
-	} else {
-		cmn_err(CE_WARN, "schpc - no match for transid 0x%lx",
-		    transid);
-	}
-	mutex_exit(&schpc_replylist_mutex);
-}
-
-
-/*
- * schpc_putrequest
- *
- * A wrapper around the synchronous call mboxsc_putmsg().
- */
-int
-schpc_putrequest(uint32_t key, uint32_t type, uint32_t cmd, uint64_t *transidp,
-		uint32_t length, void *datap, clock_t timeout,
-		schpc_replylist_t **entryp)
-{
-	int rval;
-
-	/* add the request to replylist to keep track of outstanding requests */
-	*entryp = schpc_replylist_link(cmd, *transidp, length);
-
-	SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS, "schpc_putrequest() - "
-	    "0x%lx transid mboxsc_putmsg called", *transidp);
-
-	/* wait synchronously for request to be sent */
-	rval = mboxsc_putmsg(key, type, cmd, transidp, length,
-	    (void *)datap, timeout);
-
-	SCHPC_DEBUG2(D_GETSLOTSTATUS|D_SETSLOTSTATUS, "schpc_putrequest() - "
-	    "0x%lx transid mboxsc_putmsg returned 0x%x", *transidp, rval);
-
-	/* if problem is encountered then remove the request from replylist */
-	if (rval)
-		schpc_replylist_unlink(*entryp);
-
-	return (rval);
-}
-
-
-/*
- * schpc_getreply
- *
- * Wait for the schpc_msg_thread to respond that a matching reply has
- * arrived; otherwise, timeout and remove the entry from the schpc_replylist.
- */
-/*ARGSUSED*/
-int
-schpc_getreply(uint32_t key, uint32_t *typep, uint32_t *cmdp,
-		uint64_t *transidp, uint32_t *lengthp, void *datap,
-		clock_t timeout, schpc_replylist_t *listp)
-{
-	int rc = 0;
-
-	SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS,
-	    "schpc_getreply() - 0x%lx transid waiting for reply",
-	    *transidp);
-
-	/*
-	 * wait here until schpc_msg_thread because it's always
-	 * looking for reply messages
-	 */
-	mutex_enter(&listp->reply_lock);
-
-	while (listp->reply_recvd == B_FALSE) {
-		/*
-		 * wait for reply or timeout
-		 */
-		rc = cv_timedwait(&listp->reply_cv, &listp->reply_lock,
-		    ddi_get_lbolt() + drv_usectohz(timeout * 1000));
-		switch (rc) {
-		case -1: /* most likely a timeout, but check anyway */
-
-			/* message was received after all */
-			if (listp->reply_recvd == B_TRUE)
-				break;
-
-			/* no, it's really a timeout */
-			listp->reply_cexit = B_TRUE;
-			mutex_exit(&listp->reply_lock);
-			cmn_err(CE_WARN,
-			"schpc - 0x%lx transid reply timed out", *transidp);
-			schpc_replylist_unlink(listp);
-			return (ETIMEDOUT);
-
-		default:
-			break;
-		}
-	}
-
-	*typep = listp->type;
-	*cmdp = listp->cmd;
-	*transidp = listp->transid;
-	*lengthp = listp->length;
-	bcopy((caddr_t)&listp->reply, datap, *lengthp);
-	mutex_exit(&listp->reply_lock);
-	SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS,
-	    "schpc_getreply() - 0x%lx transid received", *transidp);
-	schpc_replylist_unlink(listp);
-	return (0);
-}
-
-
-/*
- * schpc_replylist_unlink
- *
- * Deallocate a schpc_replylist_t element.
- */
-void
-schpc_replylist_unlink(schpc_replylist_t *entry)
-{
-#if DEBUG
-	schpc_replylist_t *dbg_entry;
-#endif	/* DEBUG */
-
-	SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS,
-	    "schpc_replylist_unlink() - 0x%lx transid deleted from replylist",
-	    entry->transid);
-
-	mutex_enter(&schpc_replylist_mutex);
-	if (entry->prev) {
-		entry->prev->next = entry->next;
-		if (entry->next)
-			entry->next->prev = entry->prev;
-	} else {
-		schpc_replylist_first = entry->next;
-		if (entry->next)
-			entry->next->prev = NULL;
-	}
-	if (entry == schpc_replylist_last) {
-		schpc_replylist_last = entry->prev;
-	}
-	kmem_free(entry, sizeof (schpc_replylist_t));
-	schpc_replylist_count--;
-
-#if DEBUG
-	if (schpc_debug_flags & (D_GETSLOTSTATUS|D_SETSLOTSTATUS)) {
-		dbg_entry = schpc_replylist_first;
-		cmn_err(CE_CONT, "schpc: schpc_replylist_unlink() - replylist "
-		    "count = %d\n", schpc_replylist_count);
-		while (dbg_entry != NULL) {
-			cmn_err(CE_CONT, "schpc: schpc_replylist_unlink() - "
-			    "0x%lx transid\n", dbg_entry->transid);
-			dbg_entry = dbg_entry->next;
-		}
-	}
-#endif	/* DEBUG  */
-
-	mutex_exit(&schpc_replylist_mutex);
-}
-
-
-/*
- * schpc_replylist_link
- *
- * Allocate and initialize a schpc_replylist_t element.
- */
-schpc_replylist_t *
-schpc_replylist_link(uint32_t cmd, uint64_t transid, uint32_t length)
-{
-	schpc_replylist_t *entry;
-#if DEBUG
-	schpc_replylist_t *dbg_entry;
-#endif	/* DEBUG */
-
-	SCHPC_DEBUG1(D_GETSLOTSTATUS|D_SETSLOTSTATUS,
-	    "schpc_replylist_link() - 0x%lx transid inserting into replylist",
-	    transid);
-
-	entry = kmem_zalloc(sizeof (schpc_replylist_t), KM_SLEEP);
-	mutex_init(&entry->reply_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&entry->reply_cv, NULL, CV_DRIVER, NULL);
-	entry->type = MBOXSC_MSG_REPLY;
-	entry->cmd  = cmd;
-	entry->transid  = transid;
-	entry->length  = length;
-	entry->reply_recvd = B_FALSE;
-	entry->reply_cexit = B_FALSE;
-
-	mutex_enter(&schpc_replylist_mutex);
-	if (schpc_replylist_last) {
-		entry->prev = schpc_replylist_last;
-		schpc_replylist_last->next = entry;
-		schpc_replylist_last = entry;
-	} else {
-		schpc_replylist_last = schpc_replylist_first = entry;
-	}
-
-	schpc_replylist_count++;
-
-#if DEBUG
-	if (schpc_debug_flags & (D_GETSLOTSTATUS|D_SETSLOTSTATUS)) {
-		dbg_entry = schpc_replylist_first;
-		cmn_err(CE_CONT, "schpc: schpc_replylist_link() - replylist "
-		    "count = %d\n", schpc_replylist_count);
-		while (dbg_entry != NULL) {
-			cmn_err(CE_CONT, "schpc: schpc_replylist_link() - "
-			    "0x%lx transid\n", dbg_entry->transid);
-			dbg_entry = dbg_entry->next;
-		}
-	}
-#endif	/* DEBUG  */
-
-	mutex_exit(&schpc_replylist_mutex);
-
-	return (entry);
-}
-
-
-/*
- * schpc_getslotstatus
- *
- * Issues a Get Slot Status command to the System Controller
- * for a specific slot.
- */
-static int
-schpc_getslotstatus(uint32_t expander, uint32_t board, uint32_t slot,
-    pci_getslot_t *slotstatus)
-{
-	pcimsg_t	request;
-	pcimsg_t	reply;
-	int		rval;
-	uint32_t	type, cmd, length;
-	uint64_t	transid;
-	schpc_replylist_t *entry;
-
-	SCHPC_DEBUG4(D_GETSLOTSTATUS,
-	    "schpc_getslotstatus(expander=%d board=%d "
-	    "slot=%d slotstatus=0x%p", expander, board,
-	    SCHPC_SLOT_NUM(slot), (void *)slotstatus);
-
-	if (schpc_p == NULL) {
-		return (1);
-	}
-
-	bzero(&request, sizeof (pcimsg_t));
-
-	request.pcimsg_node = expander;
-	request.pcimsg_board = board;
-	request.pcimsg_slot = SCHPC_SLOT_NUM(slot);
-	request.pcimsg_revision = PCIMSG_REVISION;
-	request.pcimsg_command = PCIMSG_GETSLOTSTATUS;
-
-	type = MBOXSC_MSG_REQUEST;
-	cmd = PCIMSG_GETSLOTSTATUS;
-	transid =  schpc_gettransid(schpc_p, slot);
-	length = sizeof (pcimsg_t);
-
-	SCHPC_DEBUG1(D_GETSLOTSTATUS, "schpc_getslotstatus() - "
-	    "0x%lx transid schpc_putrequest called", transid);
-
-	rval = schpc_putrequest(KEY_PCSC, type, cmd, &transid, length,
-	    (void *)&request, schpc_timeout_putmsg, &entry);
-
-	SCHPC_DEBUG2(D_GETSLOTSTATUS, "schpc_getslotstatus() - "
-	    "0x%lx transid schpc_putrequest returned 0x%x", transid, rval);
-
-	if (rval) {
-		return (rval);
-	}
-
-	bzero(&reply, sizeof (pcimsg_t));
-	type = MBOXSC_MSG_REPLY;
-
-	SCHPC_DEBUG1(D_GETSLOTSTATUS, "schpc_getslotstatus() - "
-	    "0x%lx transid schpc_getreply called", transid);
-
-	rval = schpc_getreply(KEY_SCPC, &type, &cmd, &transid, &length,
-	    (void *)&reply, schpc_timeout_getmsg, entry);
-
-	SCHPC_DEBUG2(D_GETSLOTSTATUS, "schpc_getslotstatus() - "
-	    "0x%lx transid schpc_getreply returned 0x%x", transid, rval);
-
-	if (rval == 0) {
-		*slotstatus = reply.pcimsg_type.pcimsg_getslot;
-
-		SCHPC_DEBUG0(D_GETSLOTSTATUS, "schpc_getslotstatus()");
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_power_on %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_power_on);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_powergood %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_powergood);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_powerfault %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_powerfault);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_empty %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_empty);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_freq_cap %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_freq_cap);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_freq_setting %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_freq_setting);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_condition %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_condition);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_HEALTHY %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_HEALTHY);
-		SCHPC_DEBUG1(D_GETSLOTSTATUS, "    slot_ENUM %x",
-		    reply.pcimsg_type.pcimsg_getslot.slot_ENUM);
-	}
-
-	return (rval);
-}
-
-
-/*
- * schpc_setslotstatus
- *
- * Issues a Set Slot Status command to the System Controller
- * for a specific slot.
- */
-static int
-schpc_setslotstatus(uint32_t expander, uint32_t board, uint32_t slot,
-    pci_setslot_t *slotstatus)
-{
-	pcimsg_t	request;
-	pcimsg_t	reply;
-	int		rval;
-	uint32_t	type, cmd, length;
-	uint64_t	transid;
-	schpc_replylist_t *entry;
-
-	SCHPC_DEBUG4(D_SETSLOTSTATUS,
-	    "schpc_setslotstatus(expander=%d board=%d "
-	    "slot=%d slotstatus=0x%p", expander, board,
-	    SCHPC_SLOT_NUM(slot), (void *)slotstatus);
-
-	bzero(&request, sizeof (pcimsg_t));
-
-	if (schpc_p == NULL) {
-		return (1);
-	}
-
-	request.pcimsg_node = expander;
-	request.pcimsg_board = board;
-	request.pcimsg_slot = SCHPC_SLOT_NUM(slot);
-	request.pcimsg_revision = PCIMSG_REVISION;
-	request.pcimsg_command = PCIMSG_SETSLOTSTATUS;
-
-	request.pcimsg_type.pcimsg_setslot = *slotstatus;
-
-	SCHPC_DEBUG0(D_IOC_LED, "schpc_setslotstatus() - LED state change");
-	SCHPC_DEBUG3(D_IOC_LED, "LED Power %d Service %d Fault %d",
-	    slotstatus->slot_led_power,
-	    slotstatus->slot_led_service,
-	    slotstatus->slot_led_fault);
-
-	type = MBOXSC_MSG_REQUEST;
-	cmd = PCIMSG_SETSLOTSTATUS;
-	transid =  schpc_gettransid(schpc_p, slot);
-	length = sizeof (pcimsg_t);
-
-	SCHPC_DEBUG1(D_SETSLOTSTATUS, "schpc_setslotstatus() - "
-	    "0x%lx transid schpc_putrequest called", transid);
-
-	rval = schpc_putrequest(KEY_PCSC, type, cmd, &transid, length,
-	    (void *)&request, schpc_timeout_putmsg, &entry);
-
-	SCHPC_DEBUG2(D_SETSLOTSTATUS, "schpc_setslotstatus() - "
-	    "0x%lx transid schpc_putrequest returned 0x%x", transid, rval);
-
-	if (rval) {
-		return (rval);
-	}
-
-	bzero(&reply, sizeof (pcimsg_t));
-	type = MBOXSC_MSG_REPLY;
-
-	SCHPC_DEBUG1(D_SETSLOTSTATUS, "schpc_setslotstatus() - "
-	    "0x%lx transid schpc_getreply called", transid);
-
-	rval = schpc_getreply(KEY_SCPC, &type, &cmd, &transid, &length,
-	    (void *)&reply, schpc_timeout_getmsg, entry);
-
-	SCHPC_DEBUG2(D_SETSLOTSTATUS, "schpc_setslotstatus() - "
-	    "0x%lx transid schpc_getreply returned 0x%x", transid, rval);
-
-	if (rval == 0) {
-		slotstatus->slot_replystatus =
-		    reply.pcimsg_type.pcimsg_setslot.slot_replystatus;
-	}
-
-	return (rval);
-}
-
-/*
- * schpc_setslotled
- *
- * Changes the attention indicators for a given slot.
- */
-static void
-schpc_setslotled(int expander, int board, int slot, uint32_t led_state)
-{
-
-	pci_setslot_t	setslot;
-
-	if (schpc_p == NULL) {
-		return;
-	}
-
-	schpc_init_setslot_message(&setslot);
-
-	if (led_state & POWER_LED_ON) {
-		schpc_p->schpc_slot[slot].led.led_power = PCIMSG_LED_ON;
-	}
-	if (led_state & POWER_LED_OFF) {
-		schpc_p->schpc_slot[slot].led.led_power = PCIMSG_LED_OFF;
-	}
-	if (led_state & POWER_LED_FLASH) {
-		schpc_p->schpc_slot[slot].led.led_power = PCIMSG_LED_FLASH;
-	}
-	if (led_state & SERVICE_LED_ON) {
-		schpc_p->schpc_slot[slot].led.led_service = PCIMSG_LED_ON;
-	}
-	if (led_state & SERVICE_LED_OFF) {
-		schpc_p->schpc_slot[slot].led.led_service = PCIMSG_LED_OFF;
-	}
-	if (led_state & SERVICE_LED_FLASH) {
-		schpc_p->schpc_slot[slot].led.led_service = PCIMSG_LED_FLASH;
-	}
-	if (led_state & FAULT_LED_ON) {
-		schpc_p->schpc_slot[slot].led.led_fault = PCIMSG_LED_ON;
-	}
-	if (led_state & FAULT_LED_OFF) {
-		schpc_p->schpc_slot[slot].led.led_fault = PCIMSG_LED_OFF;
-	}
-	if (led_state & FAULT_LED_FLASH) {
-		schpc_p->schpc_slot[slot].led.led_fault = PCIMSG_LED_FLASH;
-	}
-
-	switch (schpc_p->schpc_slot[slot].led.led_power) {
-	case PCIMSG_LED_ON:
-		setslot.slot_led_power = PCIMSG_LED_ON;
-		break;
-	case PCIMSG_LED_OFF:
-		setslot.slot_led_power = PCIMSG_LED_OFF;
-		break;
-	case PCIMSG_LED_FLASH:
-		setslot.slot_led_power = PCIMSG_LED_FLASH;
-		break;
-	}
-	switch (schpc_p->schpc_slot[slot].led.led_service) {
-	case PCIMSG_LED_ON:
-		setslot.slot_led_service = PCIMSG_LED_ON;
-		break;
-	case PCIMSG_LED_OFF:
-		setslot.slot_led_service = PCIMSG_LED_OFF;
-		break;
-	case PCIMSG_LED_FLASH:
-		setslot.slot_led_service = PCIMSG_LED_FLASH;
-		break;
-	}
-	switch (schpc_p->schpc_slot[slot].led.led_fault) {
-	case PCIMSG_LED_ON:
-		setslot.slot_led_fault = PCIMSG_LED_ON;
-		break;
-	case PCIMSG_LED_OFF:
-		setslot.slot_led_fault = PCIMSG_LED_OFF;
-		break;
-	case PCIMSG_LED_FLASH:
-		setslot.slot_led_fault = PCIMSG_LED_FLASH;
-		break;
-	}
-
-	(void) schpc_setslotstatus(expander, board, slot, &setslot);
-}
-
-/*
- * schpc_init_setslot_message
- *
- * Initialize Set Slot Message before using it.
- */
-static void
-schpc_init_setslot_message(pci_setslot_t *setslot)
-{
-	/*
-	 * Initialize Set Slot Command.
-	 */
-	setslot->slot_power_on = PCIMSG_OFF;
-	setslot->slot_power_off = PCIMSG_OFF;
-	setslot->slot_led_power = PCIMSG_LED_OFF;
-	setslot->slot_led_service = PCIMSG_LED_OFF;
-	setslot->slot_led_fault = PCIMSG_LED_OFF;
-	setslot->slot_disable_ENUM = PCIMSG_OFF;
-	setslot->slot_enable_ENUM = PCIMSG_OFF;
-	setslot->slot_disable_HEALTHY = PCIMSG_OFF;
-	setslot->slot_enable_HEALTHY = PCIMSG_OFF;
-}
-
-/*
- * schpc_gettransid
- *
- * Builds a unique transaction ID.
- */
-static uint64_t
-schpc_gettransid(schpc_t *schpc_p, int slot)
-{
-	uint64_t	trans_id;
-
-	mutex_enter(&schpc_p->schpc_mutex);
-
-	if (++schpc_p->schpc_transid == 0)
-		schpc_p->schpc_transid = 1;
-
-	trans_id = (schpc_p->schpc_slot[slot].expander<<24) |
-	    (schpc_p->schpc_slot[slot].board << 16) | schpc_p->schpc_transid;
-
-	mutex_exit(&schpc_p->schpc_mutex);
-
-	SCHPC_DEBUG1(D_TRANSID, "schpc_gettransid() - 0x%lx transid returning",
-	    trans_id);
-
-	return (trans_id);
-}
-
-/*
- * schpc_slot_get_index
- *
- * get slot table index from the slot handle
- */
-static int
-schpc_slot_get_index(schpc_t *schpc_p, hpc_slot_t slot)
-{
-	int	i;
-	int	rval = -1;
-
-	ASSERT(MUTEX_HELD(&schpc_p->schpc_mutex));
-
-	for (i = 0; i < schpc_p->schpc_number_of_slots; i++) {
-		if (schpc_p->schpc_slot[i].slot_handle == slot)
-			return (i);
-	}
-
-	return (rval);
-}
-
-/*
- * schpc_register_all_slots
- *
- * Search device tree for pci nodes and register attachment points
- * for all hot pluggable slots.
- */
-/*ARGSUSED*/
-static void
-schpc_register_all_slots(schpc_t *schpc_p)
-{
-	int		slot = 0;
-	char		caddr[64];
-	dev_info_t	*pci_dip = NULL;
-	find_dev_t	find_dev;
-	int		leaf, schizo, expander, portid, offset;
-
-	SCHPC_DEBUG1(D_ATTACH,
-	    "schpc_register_all_slots(schpc_p=%p)", (void *)schpc_p);
-
-	/*
-	 * Allow the event_handler to start processing unsolicited
-	 * events now that slots are about to be registered.
-	 */
-	slots_registered = B_TRUE;
-
-	for (slot = 0; slot < STARCAT_MAX_SLOTS; slot++) {
-
-		leaf = SCHPC_SLOT_LEAF(slot);
-		schizo = SCHPC_SLOT_SCHIZO(slot);
-		expander = SCHPC_SLOT_EXPANDER(slot);
-
-		if (schizo == 0)
-			portid = 0x1c;
-		else
-			portid = 0x1d;
-
-		if (leaf == 0)
-			offset = 0x600000;
-		else
-			offset = 0x700000;
-
-		portid = (expander << 5) | portid;
-
-		(void) sprintf(caddr, "%x,%x", portid, offset);
-
-		SCHPC_DEBUG3(D_ATTACH,
-		    "schpc_register_all_slots: searching for pci@%s"
-		    " schizo=%d, leaf=%d", caddr, schizo, leaf);
-
-		find_dev.cname = "pci";
-		find_dev.caddr = caddr;
-		find_dev.schizo = schizo;
-		find_dev.leaf = leaf;
-		find_dev.dip = NULL;
-
-		/* root node doesn't have to be held */
-		ddi_walk_devs(ddi_root_node(), schpc_match_dip,
-		    &find_dev);
-
-		pci_dip = find_dev.dip;
-
-		if (pci_dip == NULL) {
-
-			SCHPC_DEBUG1(D_ATTACH,
-			    "schpc_register_all_slots: pci@%s NOT FOUND",
-			    caddr);
-
-			continue;
-		}
-
-		SCHPC_DEBUG2(D_ATTACH,
-		    "schpc_register_all_slots: pci@%s FOUND dip=0x%p",
-		    caddr, (void *)pci_dip);
-
-		(void) schpc_add_pci(pci_dip);
-
-		/*
-		 * Release hold acquired in schpc_match_dip()
-		 */
-		ndi_rele_devi(pci_dip);
-	}
-
-	SCHPC_DEBUG0(D_ATTACH, "schpc_register_all_slots: Thread Exit");
-
-	thread_exit();
-}
-
-/*
- * schpc_add_pci
- *
- * Routine to add attachments points associated with a pci node.
- * Can be call externally by DR when configuring a PCI I/O Board.
- */
-int
-schpc_add_pci(dev_info_t *bdip)
-{
-	int		portid;
-	int		expander, board, schizo, leaf, slot, status;
-	char		ap_id[MAXNAMELEN];
-	char		caddr[64];
-	char		*naddr;
-	hpc_slot_info_t	slot_info;
-	hpc_slot_ops_t	*slot_ops;
-	dev_info_t 	*sdip = bdip;
-
-	SCHPC_DEBUG1(D_ATTACH, "schpc_add_pci(dip=0x%p)", (void *)sdip);
-
-	if (schpc_p == NULL) {
-		/*
-		 * The schpc driver has not been attached yet.
-		 */
-		return (DDI_SUCCESS);
-	}
-
-	if ((portid = ddi_getprop(DDI_DEV_T_ANY, sdip, 0, "portid", -1)) < 0) {
-		cmn_err(CE_WARN, "schpc_add_pci(dip=0x%p) - no portid\n",
-		    (void *)sdip);
-		return (DDI_FAILURE);
-	}
-
-	expander = schpc_getexpander(sdip);
-	board = schpc_getboard(sdip);
-
-	switch (portid & 0x1f) {
-
-	case 0x1c:
-		schizo = 0;
-		break;
-	case 0x1d:
-		schizo = 1;
-		break;
-	default:
-		cmn_err(CE_WARN, "schpc_add_pci(dip=0x%p) - "
-		    "Invalid pci portid 0x%x\n", (void *)sdip, portid);
-		return (DDI_FAILURE);
-	}
-
-	naddr = ddi_get_name_addr(sdip);
-	if (naddr == NULL) {
-		SCHPC_DEBUG1(D_ATTACH, "schpc_add_pci: ddi_get_name_addr"
-		    "(0x%p) returns null", (void *)sdip);
-		return (DDI_FAILURE);
-	}
-
-	(void) sprintf(caddr, "%x,600000", portid);
-
-	if (strcmp(caddr, naddr) == 0) {
-		leaf = 0;
-	} else {
-		(void) sprintf(caddr, "%x,700000", portid);
-		if (strcmp(caddr, naddr) == 0) {
-			char *name;
-
-			leaf = 1;
-			name = ddi_binding_name(sdip);
-			if ((strcmp(name, "pci108e,8002") == 0) &&
-			    (schizo == 0)) {
-				int circ;
-				dev_info_t *cdip;
-				/*
-				 * XMITS 0 Leaf B will have its hot
-				 * pluggable slot off a PCI-PCI bridge,
-				 * which is the only child.
-				 */
-				ndi_devi_enter(sdip, &circ);
-				cdip = ddi_get_child(sdip);
-				if (cdip == NULL) {
-					cmn_err(CE_WARN,
-					    "schpc_add_pci(dip=0x%p) - "
-					    "Invalid pci name addr %s\n",
-					    (void *)sdip, naddr);
-					ndi_devi_exit(sdip, circ);
-					return (DDI_FAILURE);
-				}
-				ndi_devi_exit(sdip, circ);
-				sdip = cdip;
-			}
-		} else {
-			cmn_err(CE_WARN, "schpc_add_pci(dip=0x%p) - "
-			    "Invalid pci name addr %s\n", (void *)sdip, naddr);
-			return (DDI_FAILURE);
-		}
-	}
-
-	/* create a slot table index */
-	slot = SCHPC_MAKE_SLOT_INDEX3(expander, schizo, leaf);
-
-	if (schpc_p->schpc_slot[slot].devi) {
-		cmn_err(CE_WARN, "schpc_add_pci(dip=0x%p) - "
-		    "pci node already registered\n", (void *)sdip);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * There is no need to hold the dip while saving it in
-	 * the devi field below. The dip is never dereferenced.
-	 * (If that changes, this code should be modified).
-	 * We want to avoid holding the dip here because it
-	 * prevents DR.
-	 *
-	 * NOTE: Even though the slot on XMITS0 Leaf-B
-	 * is connected to a pci_pci bridge, we will be saving
-	 * the busdip in this datastructure. This will make
-	 * it easier to identify the dip being removed in
-	 * schpc_remove_pci().
-	 */
-	schpc_p->schpc_slot[slot].devi = bdip;
-
-	schpc_p->schpc_slot[slot].expander = expander;
-	schpc_p->schpc_slot[slot].board = board;
-	schpc_p->schpc_slot[slot].schizo = schizo;
-	schpc_p->schpc_slot[slot].leaf = leaf;
-
-	/*
-	 * Starcat PCI slots are always PCI device 1.
-	 */
-	schpc_p->schpc_slot[slot].pci_id = 1;
-
-	schpc_buildapid(sdip, slot, (char *)&ap_id);
-
-	(void) strcpy(schpc_p->schpc_slot[slot].ap_id, (char *)&ap_id);
-
-	/* safe to call ddi_pathname(): bdip is held */
-	(void) ddi_pathname(sdip, schpc_p->schpc_slot[slot].nexus_path);
-
-	status = schpc_get_slot_status(expander, board, SCHPC_SLOT_NUM(slot));
-	switch (status) {
-		case RSV_UNKNOWN:
-		case RSV_PRESENT:
-		case RSV_MISS:
-		case RSV_PASS:
-		case RSV_EMPTY_CASSETTE:
-
-			/*
-			 * Test the condition of the slot.
-			 */
-			schpc_test((caddr_t)schpc_p, slot, 0, 0);
-			break;
-		case RSV_BLACK:
-			schpc_p->schpc_slot[slot].state = 0;
-			cmn_err(CE_WARN, "schpc: PCI card blacklisted: "
-			    "expander=%d board=%d slot=%d\n", expander,
-			    board, SCHPC_SLOT_NUM(slot));
-			break;
-		default:
-			schpc_p->schpc_slot[slot].state = 0;
-			cmn_err(CE_WARN, "schpc: PCI card failed by POST: "
-			    "expander=%d board=%d slot=%d failure=0x%x\n",
-			    expander, board, SCHPC_SLOT_NUM(slot), status);
-			break;
-	}
-
-	if (schpc_p->schpc_slot[slot].state & SCHPC_SLOTSTATE_REC_GOOD) {
-
-		/* allocate slot ops */
-
-		slot_ops = hpc_alloc_slot_ops(KM_SLEEP);
-		schpc_p->schpc_slot[slot].slot_ops = slot_ops;
-
-		/*
-		 * Default to Autoconfiguration disabled.
-		 */
-		schpc_p->schpc_slot[slot].state &=
-		    ~SCHPC_SLOTSTATE_AUTOCFG_ENABLE;
-
-		/*
-		 * Fill in the slot information structure that
-		 * describes the slot.
-		 */
-		slot_info.version = HPC_SLOT_OPS_VERSION;
-
-		if (schpc_p->schpc_hotplugmodel ==
-		    SCHPC_HOTPLUGTYPE_CPCIHOTPLUG)
-			slot_info.slot_type = HPC_SLOT_TYPE_PCI;
-		else
-			slot_info.slot_type = HPC_SLOT_TYPE_CPCI;
-
-		slot_info.slot.pci.device_number =
-		    schpc_p->schpc_slot[slot].pci_id;
-
-		slot_info.slot.pci.slot_capabilities = HPC_SLOT_64BITS;
-
-		if (schpc_use_legacy_apid)
-			slot_info.slot_flags = HPC_SLOT_NO_AUTO_ENABLE;
-		else
-			slot_info.slot_flags = HPC_SLOT_NO_AUTO_ENABLE |
-			    HPC_SLOT_CREATE_DEVLINK;
-
-		(void) strcpy(slot_info.slot.pci.slot_logical_name,
-		    schpc_p->schpc_slot[slot].ap_id);
-
-		/*
-		 * Fill in the slot ops structure that tells
-		 * the Hot Plug Services what function we
-		 * support.
-		 */
-		slot_ops->hpc_version = HPC_SLOT_OPS_VERSION;
-		if (schpc_p->schpc_hotplugmodel ==
-		    SCHPC_HOTPLUGTYPE_CPCIHOTPLUG) {
-			slot_ops->hpc_op_connect = schpc_connect;
-			slot_ops->hpc_op_disconnect = schpc_disconnect;
-			slot_ops->hpc_op_insert = NULL;
-			slot_ops->hpc_op_remove = NULL;
-			slot_ops->hpc_op_control = schpc_pci_control;
-		} else {
-			slot_ops->hpc_op_connect = NULL;
-			slot_ops->hpc_op_disconnect = NULL;
-			slot_ops->hpc_op_insert = NULL;
-			slot_ops->hpc_op_remove = NULL;
-			slot_ops->hpc_op_control = schpc_cpci_control;
-		}
-
-		SCHPC_DEBUG5(D_ATTACH, "schpc_add_pci: Registering HPC "
-		    "- nexus =%s schpc_p=%p slot=%d pci number=%d ap_id=%s",
-		    schpc_p->schpc_slot[slot].nexus_path,
-		    (void *)schpc_p, SCHPC_SLOT_NUM(slot),
-		    slot_info.slot.pci.device_number,
-		    slot_info.slot.pci.slot_logical_name);
-
-		if (hpc_slot_register(schpc_p->schpc_devi,
-		    schpc_p->schpc_slot[slot].nexus_path, &slot_info,
-		    &schpc_p->schpc_slot[slot].slot_handle,
-		    slot_ops, (caddr_t)schpc_p, 0) != 0) {
-
-			/*
-			 * If the slot can not be registered,
-			 * then the slot_ops need to be freed.
-			 */
-			cmn_err(CE_WARN, "schpc%d Unable to Register "
-			    "Slot %s", schpc_p->schpc_instance,
-			    slot_info.slot.pci.slot_logical_name);
-
-			hpc_free_slot_ops(schpc_p->schpc_slot[slot].slot_ops);
-
-			schpc_p->schpc_slot[slot].slot_ops = NULL;
-
-			return (DDI_FAILURE);
-		}
-
-		/*
-		 * We are ready to take commands from the HPC Services.
-		 */
-		schpc_p->schpc_slot[slot].state |= SCHPC_SLOTSTATE_HPCINITED;
-	}
-
-	return (DDI_SUCCESS);
-}
-
-/*
- * schpc_remove_pci
- *
- * Routine to remove attachments points associated with a pci node.
- * Can be call externally by DR when unconfiguring a PCI I/O Board.
- */
-int
-schpc_remove_pci(dev_info_t *dip)
-{
-	int slot;
-
-	SCHPC_DEBUG1(D_DETACH, "schpc_remove_pci(dip=0x%p)", (void *)dip);
-
-	if (schpc_p == NULL) {
-		/*
-		 * The schpc driver has not been attached yet.
-		 */
-		return (DDI_SUCCESS);
-	}
-
-	for (slot = 0; slot < schpc_p->schpc_number_of_slots; slot++) {
-		if (schpc_p->schpc_slot[slot].devi == dip) {
-
-			if (schpc_p->schpc_slot[slot].slot_ops) {
-				if (hpc_slot_unregister(
-				    &schpc_p->schpc_slot[slot].slot_handle)) {
-					cmn_err(CE_WARN,
-					    "schpc_remove_pci(dip=0x%p) - "
-					    "unable to unregister pci slots\n",
-					    (void *)dip);
-					return (DDI_FAILURE);
-				} else {
-					hpc_free_slot_ops(
-					    schpc_p->schpc_slot[slot].slot_ops);
-
-					schpc_p->schpc_slot[slot].slot_ops =
-					    NULL;
-
-					schpc_p->schpc_slot[slot].devi = NULL;
-
-					return (DDI_SUCCESS);
-				}
-			} else {
-				schpc_p->schpc_slot[slot].devi = NULL;
-
-				return (DDI_SUCCESS);
-			}
-		}
-	}
-
-	cmn_err(CE_WARN, "schpc_remove_pci(dip=0x%p) "
-	    "dip not found\n", (void *)dip);
-
-	return (DDI_SUCCESS);
-}
-
-/*
- * schpc_match_dip
- *
- * Used by ddi_walk_devs to find PCI Nexus nodes associated with
- * Hot Plug Controllers.
- */
-static int
-schpc_match_dip(dev_info_t *dip, void *arg)
-{
-	char		*naddr;
-	find_dev_t	*find_dev = (find_dev_t *)arg;
-
-	if (strcmp(find_dev->cname, ddi_node_name(dip)) == 0 &&
-	    ((((naddr = ddi_get_name_addr(dip)) != NULL) &&
-	    (strcmp(find_dev->caddr, naddr) == 0)) ||
-	    ((naddr == NULL) && (strlen(find_dev->caddr) == 0)))) {
-		/*
-		 * While ddi_walk_devs() holds dips when invoking this
-		 * callback, this dip is being saved and will be accessible
-		 * to the caller outside ddi_walk_devs(). Therefore it must be
-		 * held.
-		 */
-		ndi_hold_devi(dip);
-		find_dev->dip = dip;
-
-		SCHPC_DEBUG2(D_ATTACH,
-		    "schpc_match_dip: pci@%s FOUND dip=0x%p",
-		    find_dev->caddr, (void *)find_dev->dip);
-
-		return (DDI_WALK_TERMINATE);
-	}
-
-	ASSERT(find_dev->dip == NULL);
-	return (DDI_WALK_CONTINUE);
-}
-
-/*
- * schpc_buildapid
- *
- * Takes a component address and translates it into a ap_id prefix.
- */
-static void
-schpc_buildapid(dev_info_t *dip, int slot, char *ap_id)
-{
-	int r, pci_id_cnt, pci_id_bit;
-	int slots_before, found;
-	unsigned char *slot_names_data, *s;
-	int slot_names_size;
-	int slot_num;
-	unsigned int bit_mask;
-
-	slot_num = SCHPC_SLOT_NUM(slot);
-
-	if (schpc_use_legacy_apid) {
-		SCHPC_DEBUG1(D_APID, "Slot %d - Using Legacy ap-id", slot);
-
-		(void) sprintf(ap_id, "e%02db%dslot%d", schpc_getexpander(dip),
-		    schpc_getboard(dip), slot_num);
-
-		SCHPC_DEBUG2(D_APID, "Slot %d - ap-id=%s", slot, ap_id);
-
-		return;
-	}
-
-	r = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "slot-names", (caddr_t)&slot_names_data,
-	    &slot_names_size);
-
-	if (r == DDI_PROP_SUCCESS) {
-
-		/*
-		 * We can try to use the slot-names property to
-		 * build our ap-id.
-		 */
-		bit_mask = slot_names_data[3] | (slot_names_data[2] << 8) |
-		    (slot_names_data[1] << 16) | (slot_names_data[0] << 24);
-
-		pci_id_bit = 1;
-		pci_id_cnt = slots_before = found = 0;
-
-		SCHPC_DEBUG2(D_APID, "Slot %d - slot-names bitmask=%x",
-		    slot, bit_mask);
-
-		/*
-		 * Walk the bit mask until we find the bit that corresponds
-		 * to our slots device number.  We count how many bits
-		 * we find before we find our slot's bit.
-		 */
-		while (!found && (pci_id_cnt < 32)) {
-
-			while (schpc_p->schpc_slot[slot].pci_id
-			    != pci_id_cnt) {
-
-				/*
-				 * Find the next bit set.
-				 */
-				while (!(bit_mask & pci_id_bit) &&
-				    (pci_id_cnt < 32)) {
-					pci_id_bit = pci_id_bit << 1;
-					pci_id_cnt++;
-				}
-
-				if (schpc_p->schpc_slot[slot].pci_id !=
-				    pci_id_cnt)
-					slots_before++;
-				else
-					found = 1;
-			}
-		}
-
-		if (pci_id_cnt < 32) {
-
-			/*
-			 * Set ptr to first string.
-			 */
-			s = slot_names_data + 4;
-
-			/*
-			 * Increment past all the strings for the slots
-			 * before ours.
-			 */
-			while (slots_before) {
-				while (*s != NULL)
-					s++;
-				s++;
-				slots_before--;
-			}
-
-			/*
-			 * We should be at our string.
-			 */
-
-			(void) sprintf(ap_id, "IO%d_%s",
-			    schpc_getexpander(dip), s);
-
-			SCHPC_DEBUG2(D_APID, "Slot %d - ap-id=%s",
-			    slot, ap_id);
-
-			kmem_free(slot_names_data, slot_names_size);
-			return;
-		}
-
-		SCHPC_DEBUG1(D_APID, "Slot %d - slot-names entry not found",
-		    slot);
-
-		kmem_free(slot_names_data, slot_names_size);
-	} else
-		SCHPC_DEBUG1(D_APID, "Slot %d - No slot-names prop found",
-		    slot);
-
-	/*
-	 * Build the ap-id using the legacy naming scheme.
-	 */
-	(void) sprintf(ap_id, "e%02db%dslot%d", schpc_getexpander(dip),
-	    schpc_getboard(dip), slot_num);
-
-	SCHPC_DEBUG2(D_APID, "Slot %d - ap-id=%s", slot, ap_id);
-}
-
-/*
- * schpc_getexpander
- *
- * Returns the Expander Number (0-17) for the dip passed in. The Expander
- * Number is extracted from the portid property of the pci node. Portid
- * consists of <Expbrd#><1110x>, where x is the schizo number.
- */
-static int
-schpc_getexpander(dev_info_t *dip)
-{
-	int	id;
-
-	id = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "portid", -1);
-
-	if (id != -1)
-		return (id >> 5);
-	else {
-		id = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "expander", -1);
-		return (id);
-	}
-}
-
-/*
- * schpc_getboard
- *
- * Returns the board number (0 or 1) for the dip passed in.
- */
-static int
-schpc_getboard(dev_info_t *dip)
-{
-	_NOTE(ARGUNUSED(dip))
-
-	/*
-	 * Hot Pluggable PCI/cPCI slots are only available on
-	 * Board 1 (half-bandwidth slot).
-	 */
-	return (1);
-}
-
-/*ARGSUSED*/
-static int
-schpc_get_slot_status(uint_t expander, uint_t board, uint_t slot)
-{
-	gdcd_t *gdcd;
-	int prd_slot, status, bus;
-
-	SCHPC_DEBUG3(D_ATTACH, "schpc_get_slot_status() "
-	    "exp=%d board=%d slot=%d", expander, board, slot);
-
-	if ((gdcd = (gdcd_t *)kmem_zalloc(sizeof (gdcd_t),
-	    KM_SLEEP)) == NULL) {
-		return (RSV_UNDEFINED);
-	}
-
-	/*
-	 * Get the Starcat Specific Global DCD Structure from the golden
-	 * IOSRAM.
-	 */
-	if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
-		cmn_err(CE_WARN, "sc_gptwocfg: Unable To Read GDCD "
-		    "From IOSRAM\n");
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (RSV_UNDEFINED);
-	}
-
-	if (gdcd->h.dcd_magic != GDCD_MAGIC) {
-
-		cmn_err(CE_WARN, "schpc: GDCD Bad Magic 0x%x\n",
-		    gdcd->h.dcd_magic);
-
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (RSV_UNDEFINED);
-	}
-
-	if (gdcd->h.dcd_version != DCD_VERSION) {
-		cmn_err(CE_WARN, "schpc: GDCD Bad Version: "
-		    "GDCD Version 0x%x Expecting 0x%x\n",
-		    gdcd->h.dcd_version, DCD_VERSION);
-
-		kmem_free(gdcd, sizeof (gdcd_t));
-		return (RSV_UNDEFINED);
-	}
-
-	if (slot < 2)
-		prd_slot = 4;
-	else
-		prd_slot = 5;
-
-	bus = slot & 0x1;
-
-	status = gdcd->dcd_prd[expander][prd_slot].prd_iocard_rsv[bus][0];
-
-	kmem_free(gdcd, sizeof (gdcd_t));
-
-	SCHPC_DEBUG3(D_ATTACH, "schpc_get_slot_status() "
-	    "prd_slot=%d bus=%d status=%d", prd_slot, bus, status);
-
-	return (status);
-}
-
-#define	LEAF_SAVE_END			0xff
-
-typedef struct {
-	int	reg;
-	int	offset;
-	int	access_size;
-	int	number;
-} save_reg_list_t;
-
-/*
- * Save List Array.  Describes the leaf registers that need to
- * be restored after a leaf reset.
- *
- * Entry 1 - Reg Entry: 0=PCI Leaf CSRs, 2=PCI Config Space
- * Entry 2 - Offset Start
- * Entry 3 - Access Size: 8=64 bit, 4=32 bit, 2=16 bit, 1=8 bit
- * Entry 4 - # of registers to be saved starting at offset,
- */
-save_reg_list_t	save_reg_list[] = {	0, 0x110, 8, 1,
-					0, 0x200, 8, 2,
-					0, 0x1000, 8, 0x18,
-					0, 0x1a00, 8, 1,
-					0, 0x2000, 8, 1,
-					0, 0x2020, 8, 1,
-					0, 0x2040, 8, 1,
-					0, 0x2308, 8, 2,
-					0, 0x2800, 8, 1,
-					2, 0x04, 2, 1,		/* Command */
-					2, 0x0d, 1, 1,		/* Latency */
-					2, 0x40, 1, 1,		/* Bus # */
-					2, 0x41, 1, 1,		/* Sub. Bus # */
-					LEAF_SAVE_END, 0, 0, 0};
-
-static int
-schpc_save_leaf(int slot)
-{
-	int		save_entry, list_entry, reg;
-	caddr_t		leaf_regs;
-	ddi_device_acc_attr_t attr;
-
-	SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Leaf Registers Saved", slot);
-
-	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
-	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
-	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
-
-	/*
-	 * Map in the 3 addresses spaces defined for XMITS.
-	 */
-	for (reg = 0; reg < 3; reg++) {
-		if (ddi_regs_map_setup(schpc_p->schpc_slot[slot].devi, reg,
-		    &leaf_regs, 0, 0, &attr, &schpc_p->schpc_slot[slot].
-		    saved_handle[reg]) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "Mapin failed\n");
-			schpc_p->schpc_slot[slot].saved_regs_va[reg] = NULL;
-			return (1);
-		}
-
-		schpc_p->schpc_slot[slot].saved_regs_va[reg] = leaf_regs;
-	}
-
-
-	/*
-	 * Determine how many entries are in the list so we can
-	 * allocate the save space.
-	 */
-	list_entry = 0;
-	save_entry = 0;
-	while (save_reg_list[list_entry].reg != LEAF_SAVE_END) {
-		save_entry += save_reg_list[list_entry].number;
-		list_entry++;
-	}
-
-	schpc_p->schpc_slot[slot].saved_size = (save_entry * sizeof (uint64_t));
-
-	if (schpc_p->schpc_slot[slot].saved_size == 0)
-		return (0);
-
-	schpc_p->schpc_slot[slot].saved_regs =
-	    (uint64_t *)kmem_zalloc(schpc_p->schpc_slot[slot].saved_size,
-	    KM_SLEEP);
-
-	/*
-	 * Walk through the register list and save contents.
-	 */
-	list_entry = 0;
-	save_entry = 0;
-	while (save_reg_list[list_entry].reg != LEAF_SAVE_END) {
-		schpc_save_entry(slot, list_entry, save_entry);
-		save_entry += save_reg_list[list_entry].number;
-		list_entry ++;
-	}
-
-	SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Leaf Registers Saved", slot);
-
-	return (0);
-}
-
-static void
-schpc_restore_leaf(int slot)
-{
-	int	save_entry, list_entry, reg;
-
-	if (schpc_p->schpc_slot[slot].saved_regs == NULL)
-		return;
-
-	/*
-	 * Walk through the register list and restore contents.
-	 */
-	list_entry = 0;
-	save_entry = 0;
-	while (save_reg_list[list_entry].reg != LEAF_SAVE_END) {
-
-		schpc_restore_entry(slot, list_entry, save_entry);
-
-		save_entry += save_reg_list[list_entry].number;
-		list_entry ++;
-	}
-
-	/*
-	 * Free the mapped in registers.
-	 */
-	for (reg = 0; reg < 3; reg++) {
-		if (schpc_p->schpc_slot[slot].saved_regs_va[reg]) {
-
-			ddi_regs_map_free(
-			    &schpc_p->schpc_slot[slot].saved_handle[reg]);
-
-			schpc_p->schpc_slot[slot].saved_regs_va[reg] = NULL;
-		}
-	}
-
-	kmem_free(schpc_p->schpc_slot[slot].saved_regs,
-	    schpc_p->schpc_slot[slot].saved_size);
-
-	schpc_p->schpc_slot[slot].saved_size = 0;
-	schpc_p->schpc_slot[slot].saved_regs = NULL;
-
-	SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Leaf Registers Restored", slot);
-}
-
-static void
-schpc_save_entry(int slot, int list_entry, int save_entry)
-{
-	int reg, reads = 0;
-
-	reg = save_reg_list[list_entry].reg;
-
-	while (reads < save_reg_list[list_entry].number) {
-		switch (save_reg_list[list_entry].access_size) {
-		case 8:
-			schpc_p->schpc_slot[slot].saved_regs[save_entry] =
-			    ddi_get64(
-			    schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint64_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (reads * sizeof (uint64_t))));
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Save 64 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (reads * sizeof (uint64_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			break;
-		case 4:
-			schpc_p->schpc_slot[slot].saved_regs[save_entry] =
-			    ddi_get32(
-			    schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint32_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (reads * sizeof (uint32_t))));
-
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Save 32 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (reads * sizeof (uint32_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			break;
-		case 2:
-			schpc_p->schpc_slot[slot].saved_regs[save_entry] =
-			    ddi_get16(
-			    schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint16_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (reads * sizeof (uint16_t))));
-
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Save 16 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (reads * sizeof (uint16_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			break;
-		case 1:
-			schpc_p->schpc_slot[slot].saved_regs[save_entry] =
-			    ddi_get8(
-			    schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint8_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (reads * sizeof (uint8_t))));
-
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Save 8 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (reads * sizeof (uint8_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			break;
-		default:
-			cmn_err(CE_WARN,
-			    "schpc: Illegal List Entry\n");
-		}
-		reads++;
-		save_entry++;
-	}
-}
-
-static void
-schpc_restore_entry(int slot, int list_entry, int save_entry)
-{
-	int reg, writes = 0;
-
-	reg = save_reg_list[list_entry].reg;
-
-	while (writes < save_reg_list[list_entry].number) {
-		switch (save_reg_list[list_entry].access_size) {
-		case 8:
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Restore 64 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (writes * sizeof (uint64_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			ddi_put64(schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint64_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (writes * sizeof (uint64_t))),
-			    schpc_p->schpc_slot[slot].saved_regs[save_entry]);
-
-			break;
-		case 4:
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Restore 32 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (writes * sizeof (uint32_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			ddi_put32(schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint32_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (writes * sizeof (uint32_t))),
-			    schpc_p->schpc_slot[slot].saved_regs[save_entry]);
-
-			break;
-		case 2:
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Restore 16 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (writes * sizeof (uint16_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			ddi_put16(schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint16_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (writes * sizeof (uint16_t))),
-			    schpc_p->schpc_slot[slot].saved_regs[save_entry]);
-
-			break;
-		case 1:
-#ifdef DEBUG
-			if (schpc_dump_save_regs)
-				cmn_err(CE_WARN, "Restore 8 %x %lx %lx\n", reg,
-				    save_reg_list[list_entry].offset +
-				    (writes * sizeof (uint8_t)),
-				    schpc_p->schpc_slot[slot].
-				    saved_regs[save_entry]);
-#endif
-
-			ddi_put8(schpc_p->schpc_slot[slot].saved_handle[reg],
-			    (uint8_t *)(schpc_p->schpc_slot[slot].
-			    saved_regs_va[reg]
-			    + save_reg_list[list_entry].offset +
-			    (writes * sizeof (uint8_t))),
-			    schpc_p->schpc_slot[slot].saved_regs[save_entry]);
-
-			break;
-		default:
-			cmn_err(CE_WARN,
-			    "schpc: Illegal List Entry\n");
-		}
-		writes++;
-		save_entry++;
-	}
-}
-
-/*
- * Returns TRUE if a leaf reset is required to change frequencies/mode.
- */
-static int
-schpc_is_leaf_reset_required(int slot)
-{
-	char *name;
-	int32_t mod_rev;
-
-	/*
-	 * Only XMITS 3.0 and greater connected slots will require a
-	 * reset to switch frequency and/or mode.
-	 */
-	name = ddi_binding_name(schpc_p->schpc_slot[slot].devi);
-
-	if (strcmp(name, "pci108e,8002") == 0) {
-		mod_rev = ddi_prop_get_int(DDI_DEV_T_ANY,
-		    schpc_p->schpc_slot[slot].devi,
-		    DDI_PROP_DONTPASS, "module-revision#", 0);
-
-		SCHPC_DEBUG2(D_FREQCHG, "Slot %d - mod_rev=%x", slot, mod_rev);
-
-		/*
-		 * Check for XMITS 3.0 or greater.
-		 */
-		if (mod_rev >= XMITS_30) {
-
-			/*
-			 * The leaf attached to C5V0 (slot 1) should
-			 * not be reset.
-			 */
-			if ((slot & 3) == 1) {
-
-				SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Leaf Reset "
-				    "Not Required - C5V0", slot);
-
-				return (0);
-			}
-
-			SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Leaf Reset "
-			    "Required", slot);
-
-			return (1);
-		}
-	}
-	SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Leaf Reset NOT Required", slot);
-
-	return (0);
-}
-
-/*
- * Returns TRUE if the bus can change frequencies.
- */
-static int
-schpc_is_freq_switchable(int slot)
-{
-	char *name;
-	int32_t mod_rev;
-
-	name = ddi_binding_name(schpc_p->schpc_slot[slot].devi);
-
-	if (strcmp(name, "pci108e,8002") == 0) {
-		mod_rev = ddi_prop_get_int(DDI_DEV_T_ANY,
-		    schpc_p->schpc_slot[slot].devi,
-		    DDI_PROP_DONTPASS, "module-revision#", 0);
-
-		SCHPC_DEBUG2(D_FREQCHG, "Slot %d - mod_rev=%x", slot, mod_rev);
-
-		/*
-		 * We will only report back that XMITS 2.0 (mod_rev = 2)
-		 * or greater will have the ability to switch frequencies.
-		 */
-		if (mod_rev >= XMITS_20) {
-			SCHPC_DEBUG1(D_FREQCHG, "Slot %d - "
-			    "Frequency is switchable", slot);
-			return (1);
-		}
-	}
-
-	SCHPC_DEBUG1(D_FREQCHG, "Slot %d - Frequency is NOT switchable", slot);
-	return (0);
-}
-
-/*
- * schpc_slot_freq
- *
- * Convert the slot frequency setting to integer value.
- */
-static int
-schpc_slot_freq(pci_getslot_t *getslotp)
-{
-	switch (getslotp->slot_freq_setting) {
-	case PCIMSG_FREQ_33MHZ:
-		return (SCHPC_33MHZ);
-	case PCIMSG_FREQ_66MHZ:
-		return (SCHPC_66MHZ);
-	case PCIMSG_FREQ_90MHZ:
-		return (SCHPC_90MHZ);
-	case PCIMSG_FREQ_133MHZ:
-		return (SCHPC_133MHZ);
-	default:
-		return (0);
-	}
-}
-
-/*
- * schpc_find_dip
- *
- * Used by ddi_walk_devs to find the dip which belongs
- * to a certain slot.
- *
- * When this function returns, the dip is held.  It is the
- * responsibility of the caller to release the dip.
- */
-static int
-schpc_find_dip(dev_info_t *dip, void *arg)
-{
-	find_dev_t	*find_dev = (find_dev_t *)arg;
-	char		*pathname = find_dev->caddr;
-
-	(void) ddi_pathname(dip, pathname);
-	if (strcmp(find_dev->cname, pathname) == 0) {
-		ndi_hold_devi(dip);
-		find_dev->dip = dip;
-		return (DDI_WALK_TERMINATE);
-	}
-	return (DDI_WALK_CONTINUE);
-}
--- a/usr/src/uts/sun4u/starcat/io/schpc.conf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-name="schpc" parent="pseudo" instance=0;
-#
-# force attach driver to support hotplug activity
-#
-ddi-forceattach=1;
--- a/usr/src/uts/sun4u/starcat/io/sckmdrv.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,910 +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.
- */
-
-
-/*
- * Starcat IPSec Key Management Driver.
- *
- * This driver runs on a Starcat Domain. It processes requests received
- * from the System Controller (SC) from IOSRAM, passes these requests
- * to the sckmd daemon by means of an open/close/ioctl interface, and
- * sends corresponding status information back to the SC.
- *
- * Requests received from the SC consist of IPsec security associations
- * (SAs) needed to secure the communication between SC and Domain daemons
- * communicating using the Management Network (MAN).
- */
-
-#include <sys/types.h>
-#include <sys/cmn_err.h>
-#include <sys/kmem.h>
-#include <sys/errno.h>
-#include <sys/file.h>
-#include <sys/open.h>
-#include <sys/stat.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/cmn_err.h>
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/ddi_impldefs.h>
-#include <sys/ndi_impldefs.h>
-#include <sys/modctl.h>
-#include <sys/disp.h>
-#include <sys/async.h>
-#include <sys/mboxsc.h>
-#include <sys/sckm_msg.h>
-#include <sys/sckm_io.h>
-#include <sys/taskq.h>
-#include <sys/note.h>
-
-#ifdef DEBUG
-static uint_t sckm_debug_flags = 0x0;
-#define	SCKM_DEBUG0(f, s) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s)
-#define	SCKM_DEBUG1(f, s, a) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s, a)
-#define	SCKM_DEBUG2(f, s, a, b) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s, a, b)
-#define	SCKM_DEBUG3(f, s, a, b, c) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s, a, b, c)
-#define	SCKM_DEBUG4(f, s, a, b, c, d) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s, a, b, c, d)
-#define	SCKM_DEBUG5(f, s, a, b, c, d, e) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s, a, b, c, d, e)
-#define	SCKM_DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& sckm_debug_flags) \
-	cmn_err(CE_CONT, s, a, b, c, d, e, ff)
-#else
-#define	SCKM_DEBUG0(f, s)
-#define	SCKM_DEBUG1(f, s, a)
-#define	SCKM_DEBUG2(f, s, a, b)
-#define	SCKM_DEBUG3(f, s, a, b, c)
-#define	SCKM_DEBUG4(f, s, a, b, c, d)
-#define	SCKM_DEBUG5(f, s, a, b, c, d, e)
-#define	SCKM_DEBUG6(f, s, a, b, c, d, e, ff)
-#endif /* DEBUG */
-
-#define	D_INIT		0x00000001	/* _init/_fini/_info */
-#define	D_ATTACH	0x00000002	/* attach/detach */
-#define	D_OPEN		0x00000008	/* open/close */
-#define	D_IOCTL		0x00010000	/* ioctl */
-#define	D_TASK		0x00100000	/* mailbox task processing */
-#define	D_CALLBACK	0x00200000	/* mailbox callback */
-
-static int sckm_open(dev_t *, int, int, struct cred *);
-static int sckm_close(dev_t, int, int, struct cred *);
-static int sckm_ioctl(dev_t, int, intptr_t, int, struct cred *, int *);
-
-static struct cb_ops sckm_cb_ops = {
-	sckm_open,		/* open */
-	sckm_close,		/* close */
-	nodev,			/* strategy */
-	nodev,			/* print */
-	nodev,			/* dump */
-	nodev,			/* read */
-	nodev,			/* write */
-	sckm_ioctl,		/* ioctl */
-	nodev,			/* devmap */
-	nodev,			/* mmap */
-	nodev,			/* segmap */
-	nochpoll,		/* poll */
-	ddi_prop_op,		/* prop_op */
-	0,			/* streamtab  */
-	D_NEW | D_MP		/* Driver compatibility flag */
-};
-
-static int sckm_attach(dev_info_t *, ddi_attach_cmd_t);
-static int sckm_detach(dev_info_t *, ddi_detach_cmd_t);
-static int sckm_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
-
-static struct dev_ops sckm_ops = {
-	DEVO_REV,		/* devo_rev, */
-	0,			/* refcnt  */
-	sckm_info,		/* get_dev_info */
-	nulldev,		/* identify */
-	nulldev,		/* probe */
-	sckm_attach,		/* attach */
-	sckm_detach,		/* detach */
-	nodev,			/* reset */
-	&sckm_cb_ops,		/* driver operations */
-	(struct bus_ops *)0,	/* no bus operations */
-	NULL,			/* power */
-	ddi_quiesce_not_needed,		/* quiesce */
-};
-
-static struct modldrv modldrv = {
-	&mod_driverops,
-	"Key Management Driver",
-	&sckm_ops,
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	&modldrv,
-	NULL
-};
-
-/*
- * Private definitions.
- */
-#define	SCKM_DEF_GETMSG_TIMEOUT 60	/* in seconds */
-#define	SCKM_DAEMON_TIMEOUT	4000000	/* in microseconds */
-#define	SCKM_NUM_TASKQ		2	/* # of task queue entries */
-
-/*
- * For processing mailbox layer events.
- */
-static kmutex_t sckm_task_mutex;
-static kmutex_t sckm_taskq_ptr_mutex;
-static clock_t sckm_getmsg_timeout = SCKM_DEF_GETMSG_TIMEOUT*1000;
-static taskq_t *sckm_taskq = NULL;
-static sckm_mbox_req_hdr_t *req_data = NULL;
-static sckm_mbox_rep_hdr_t *rep_data = NULL;
-
-
-/*
- * For synchronization with key management daemon.
- */
-static kmutex_t sckm_umutex;
-static kcondvar_t sckm_udata_cv;	/* daemon waits on data */
-static kcondvar_t sckm_cons_cv;		/* wait for daemon to consume data */
-static boolean_t sckm_udata_req = B_FALSE; /* data available for daemon */
-static sckm_ioctl_getreq_t sckm_udata;	/* request for daemon */
-static sckm_ioctl_status_t sckm_udata_status; /* status from daemon */
-
-/*
- * Other misc private variables.
- */
-static dev_info_t *sckm_devi = NULL;
-static boolean_t sckm_oflag = B_FALSE;
-
-/*
- * Private functions prototypes.
- */
-static void sckm_mbox_callback(void);
-static void sckm_mbox_task(void *arg);
-static void sckm_process_msg(uint32_t cmd, uint64_t transid,
-    uint32_t len, sckm_mbox_req_hdr_t *req_data,
-    sckm_mbox_rep_hdr_t *rep_data);
-
-
-int
-_init(void)
-{
-	mboxsc_timeout_range_t timeout_range;
-	int ret;
-
-	SCKM_DEBUG0(D_INIT, "in _init");
-
-	/*
-	 * Initialize outgoing mailbox (KDSC)
-	 */
-	if ((ret = mboxsc_init(KEY_KDSC, MBOXSC_MBOX_OUT, NULL)) != 0) {
-		cmn_err(CE_WARN, "failed initializing outgoing mailbox "
-		    "(%d)", ret);
-		return (ret);
-	}
-
-	/*
-	 * Initialize incoming mailbox (SCKD)
-	 */
-	if ((ret = mboxsc_init(KEY_SCKD, MBOXSC_MBOX_IN,
-	    sckm_mbox_callback)) != 0) {
-		cmn_err(CE_WARN, "failed initializing incoming mailbox "
-		    "(%d)\n", ret);
-		(void) mboxsc_fini(KEY_KDSC);
-		return (ret);
-	}
-
-	if ((ret = mboxsc_ctrl(KEY_SCKD, MBOXSC_CMD_GETMSG_TIMEOUT_RANGE,
-	    (void *)&timeout_range)) != 0) {
-		(void) mboxsc_fini(KEY_SCKD);
-		(void) mboxsc_fini(KEY_KDSC);
-		return (ret);
-	}
-
-	if (sckm_getmsg_timeout < timeout_range.min_timeout) {
-		sckm_getmsg_timeout = timeout_range.min_timeout;
-		cmn_err(CE_WARN, "resetting getmsg timeout to %lx",
-		    sckm_getmsg_timeout);
-	}
-
-	if (sckm_getmsg_timeout > timeout_range.max_timeout) {
-		sckm_getmsg_timeout = timeout_range.max_timeout;
-		cmn_err(CE_WARN, "resetting getmsg timeout to %lx",
-		    sckm_getmsg_timeout);
-	}
-
-	if ((ret = mod_install(&modlinkage)) != 0) {
-		(void) mboxsc_fini(KEY_KDSC);
-		(void) mboxsc_fini(KEY_SCKD);
-		return (ret);
-	}
-
-	/*
-	 * Initialize variables needed for synchronization with daemon.
-	 */
-	sckm_udata.buf = kmem_alloc(SCKM_SCKD_MAXDATA, KM_SLEEP);
-	req_data = (sckm_mbox_req_hdr_t *)kmem_alloc(SCKM_SCKD_MAXDATA,
-	    KM_SLEEP);
-	rep_data = (sckm_mbox_rep_hdr_t *)kmem_alloc(SCKM_KDSC_MAXDATA,
-	    KM_SLEEP);
-
-	if ((sckm_udata.buf == NULL) || (req_data == NULL) ||
-	    (rep_data == NULL)) {
-		cmn_err(CE_WARN, "not enough memory during _init");
-
-		/* free what was successfully allocated */
-		if (sckm_udata.buf != NULL)
-			kmem_free(sckm_udata.buf, SCKM_SCKD_MAXDATA);
-		if (req_data != NULL)
-			kmem_free(req_data, SCKM_SCKD_MAXDATA);
-		if (rep_data != NULL)
-			kmem_free(rep_data, SCKM_KDSC_MAXDATA);
-		sckm_udata.buf = NULL;
-		req_data = NULL;
-		rep_data = NULL;
-
-		/* uninitialize mailboxes, remove module, and return error */
-		(void) mboxsc_fini(KEY_KDSC);
-		(void) mboxsc_fini(KEY_SCKD);
-		(void) mod_remove(&modlinkage);
-		return (-1);
-	}
-
-	cv_init(&sckm_udata_cv, NULL, CV_DRIVER, NULL);
-	cv_init(&sckm_cons_cv, NULL, CV_DRIVER, NULL);
-	mutex_init(&sckm_umutex, NULL, MUTEX_DRIVER, NULL);
-
-	/*
-	 * Create mutex for task processing, protection of taskq
-	 * pointer, and create taskq.
-	 */
-	mutex_init(&sckm_task_mutex, NULL, MUTEX_DRIVER, NULL);
-	mutex_init(&sckm_taskq_ptr_mutex, NULL, MUTEX_DRIVER, NULL);
-	sckm_taskq = taskq_create("sckm_taskq", 1, minclsyspri,
-	    SCKM_NUM_TASKQ, SCKM_NUM_TASKQ, TASKQ_PREPOPULATE);
-
-	SCKM_DEBUG1(D_INIT, "out _init ret=%d\n", ret);
-	return (ret);
-}
-
-int
-_fini(void)
-{
-	int ret;
-
-	SCKM_DEBUG0(D_INIT, "in _fini");
-
-	if ((ret = mod_remove(&modlinkage)) != 0) {
-		return (ret);
-	}
-
-	/*
-	 * Wait for scheduled tasks to complete, then destroy task queue.
-	 */
-	mutex_enter(&sckm_taskq_ptr_mutex);
-	if (sckm_taskq != NULL) {
-		taskq_destroy(sckm_taskq);
-		sckm_taskq = NULL;
-	}
-	mutex_exit(&sckm_taskq_ptr_mutex);
-
-	/*
-	 * Terminate incoming and outgoing IOSRAM mailboxes
-	 */
-	(void) mboxsc_fini(KEY_KDSC);
-	(void) mboxsc_fini(KEY_SCKD);
-
-	/*
-	 * Destroy module synchronization objects and free memory
-	 */
-	mutex_destroy(&sckm_task_mutex);
-	mutex_destroy(&sckm_taskq_ptr_mutex);
-	mutex_destroy(&sckm_umutex);
-	cv_destroy(&sckm_cons_cv);
-
-	if (sckm_udata.buf != NULL) {
-		kmem_free(sckm_udata.buf, SCKM_SCKD_MAXDATA);
-		sckm_udata.buf = NULL;
-	}
-	if (rep_data != NULL) {
-		kmem_free(rep_data, SCKM_KDSC_MAXDATA);
-		rep_data = NULL;
-	}
-	if (req_data != NULL) {
-		kmem_free(req_data, SCKM_SCKD_MAXDATA);
-		req_data = NULL;
-	}
-
-	return (ret);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	SCKM_DEBUG0(D_INIT, "in _info");
-	return (mod_info(&modlinkage, modinfop));
-}
-
-static int
-sckm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-	SCKM_DEBUG1(D_ATTACH, "in sckm_attach, cmd=%d", cmd);
-
-	switch (cmd) {
-	case DDI_ATTACH:
-		SCKM_DEBUG0(D_ATTACH, "sckm_attach: DDI_ATTACH");
-		if (ddi_create_minor_node(devi, "sckmdrv", S_IFCHR,
-		    0, NULL, NULL) == DDI_FAILURE) {
-			cmn_err(CE_WARN, "ddi_create_minor_node failed");
-			ddi_remove_minor_node(devi, NULL);
-			return (DDI_FAILURE);
-		}
-		sckm_devi = devi;
-		break;
-	case DDI_SUSPEND:
-		SCKM_DEBUG0(D_ATTACH, "sckm_attach: DDI_SUSPEND");
-		break;
-	default:
-		cmn_err(CE_WARN, "sckm_attach: bad cmd %d\n", cmd);
-		return (DDI_FAILURE);
-	}
-
-	SCKM_DEBUG0(D_ATTACH, "out sckm_attach (DDI_SUCCESS)");
-	return (DDI_SUCCESS);
-}
-
-static int
-sckm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
-	SCKM_DEBUG1(D_ATTACH, "in sckm_detach, cmd=%d", cmd);
-
-	switch (cmd) {
-	case DDI_DETACH:
-		SCKM_DEBUG0(D_ATTACH, "sckm_detach: DDI_DETACH");
-		ddi_remove_minor_node(devi, NULL);
-		break;
-	case DDI_SUSPEND:
-		SCKM_DEBUG0(D_ATTACH, "sckm_detach: DDI_DETACH");
-		break;
-	default:
-		cmn_err(CE_WARN, "sckm_detach: bad cmd %d\n", cmd);
-		return (DDI_FAILURE);
-	}
-
-	SCKM_DEBUG0(D_ATTACH, "out sckm_detach (DDI_SUCCESS)");
-	return (DDI_SUCCESS);
-}
-
-/* ARGSUSED */
-static int
-sckm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
-    void **result)
-{
-	int rv;
-
-	SCKM_DEBUG1(D_ATTACH, "in sckm_info, infocmd=%d", infocmd);
-
-	switch (infocmd) {
-	case DDI_INFO_DEVT2DEVINFO:
-		*result = (void *)sckm_devi;
-		rv = DDI_SUCCESS;
-		break;
-	case DDI_INFO_DEVT2INSTANCE:
-		*result = (void *)0;
-		rv = DDI_SUCCESS;
-		break;
-	default:
-		rv = DDI_FAILURE;
-	}
-
-	SCKM_DEBUG1(D_ATTACH, "out sckm_info, rv=%d", rv);
-	return (rv);
-}
-
-/*ARGSUSED*/
-static int
-sckm_open(dev_t *devp, int flag, int otyp, struct cred *cred)
-{
-	SCKM_DEBUG0(D_OPEN, "in sckm_open");
-
-	/* check credentials of calling process */
-	if (drv_priv(cred)) {
-		SCKM_DEBUG0(D_OPEN, "sckm_open: attempt by non-root proc");
-		return (EPERM);
-	}
-
-	/* enforce exclusive access */
-	mutex_enter(&sckm_umutex);
-	if (sckm_oflag == B_TRUE) {
-		SCKM_DEBUG0(D_OPEN, "sckm_open: already open");
-		mutex_exit(&sckm_umutex);
-		return (EBUSY);
-	}
-	sckm_oflag = B_TRUE;
-	mutex_exit(&sckm_umutex);
-
-	SCKM_DEBUG0(D_OPEN, "sckm_open: succcess");
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-sckm_close(dev_t dev, int flag, int otyp, struct cred *cred)
-{
-	SCKM_DEBUG0(D_OPEN, "in sckm_close");
-
-	mutex_enter(&sckm_umutex);
-	sckm_oflag = B_FALSE;
-	mutex_exit(&sckm_umutex);
-
-	return (0);
-}
-
-
-static int
-sckm_copyin_ioctl_getreq(intptr_t userarg, sckm_ioctl_getreq_t *driverarg,
-    int flag)
-{
-#ifdef _MULTI_DATAMODEL
-	switch (ddi_model_convert_from(flag & FMODELS)) {
-	case DDI_MODEL_ILP32: {
-		sckm_ioctl_getreq32_t driverarg32;
-		if (ddi_copyin((caddr_t)userarg, &driverarg32,
-		    sizeof (sckm_ioctl_getreq32_t), flag)) {
-			return (EFAULT);
-		}
-		driverarg->transid = driverarg32.transid;
-		driverarg->type = driverarg32.type;
-		driverarg->buf = (caddr_t)(uintptr_t)driverarg32.buf;
-		driverarg->buf_len = driverarg32.buf_len;
-		break;
-	}
-	case DDI_MODEL_NONE: {
-		if (ddi_copyin((caddr_t)userarg, &driverarg,
-		    sizeof (sckm_ioctl_getreq_t), flag)) {
-			return (EFAULT);
-		}
-		break;
-	}
-	}
-#else /* ! _MULTI_DATAMODEL */
-	if (ddi_copyin((caddr_t)userarg, &driverarg,
-	    sizeof (sckm_ioctl_getreq_t), flag)) {
-		return (EFAULT);
-	}
-#endif /* _MULTI_DATAMODEL */
-	return (0);
-}
-
-
-static int
-sckm_copyout_ioctl_getreq(sckm_ioctl_getreq_t *driverarg, intptr_t userarg,
-    int flag)
-{
-#ifdef _MULTI_DATAMODEL
-	switch (ddi_model_convert_from(flag & FMODELS)) {
-	case DDI_MODEL_ILP32: {
-		sckm_ioctl_getreq32_t driverarg32;
-		driverarg32.transid = driverarg->transid;
-		driverarg32.type = driverarg->type;
-		driverarg32.buf = (caddr32_t)(uintptr_t)driverarg->buf;
-		driverarg32.buf_len = driverarg->buf_len;
-		if (ddi_copyout(&driverarg32, (caddr_t)userarg,
-		    sizeof (sckm_ioctl_getreq32_t), flag)) {
-			return (EFAULT);
-		}
-		break;
-	}
-	case DDI_MODEL_NONE:
-		if (ddi_copyout(driverarg, (caddr_t)userarg,
-		    sizeof (sckm_ioctl_getreq_t), flag)) {
-			return (EFAULT);
-		}
-		break;
-	}
-#else /* ! _MULTI_DATAMODEL */
-	if (ddi_copyout(driverarg, (caddr_t)userarg,
-	    sizeof (sckm_ioctl_getreq_t), flag)) {
-		return (EFAULT);
-	}
-#endif /* _MULTI_DATAMODEL */
-	return (0);
-}
-
-
-/*ARGSUSED*/
-static int
-sckm_ioctl(dev_t dev, int cmd, intptr_t data, int flag,
-    cred_t *cred, int *rvalp)
-{
-	int rval = 0;
-
-	SCKM_DEBUG0(D_IOCTL, "in sckm_ioctl");
-
-	switch (cmd) {
-	case SCKM_IOCTL_GETREQ: {
-		sckm_ioctl_getreq_t arg;
-
-		SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_GETREQ");
-		if (sckm_copyin_ioctl_getreq(data, &arg, flag)) {
-			return (EFAULT);
-		}
-
-		/* sanity check argument */
-		if (arg.buf_len < SCKM_SCKD_MAXDATA) {
-			SCKM_DEBUG2(D_IOCTL, "sckm_ioctl: usr buffer too "
-			    "small (%d < %d)", arg.buf_len, SCKM_SCKD_MAXDATA);
-			return (ENOSPC);
-		}
-
-		mutex_enter(&sckm_umutex);
-
-		/* wait for request from SC */
-		while (!sckm_udata_req) {
-			SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: waiting for msg");
-			if (cv_wait_sig(&sckm_udata_cv, &sckm_umutex) == 0) {
-				mutex_exit(&sckm_umutex);
-				return (EINTR);
-			}
-		}
-		SCKM_DEBUG1(D_IOCTL, "sckm_ioctl: msg available "
-		    "transid = 0x%lx", sckm_udata.transid);
-
-		arg.transid = sckm_udata.transid;
-		arg.type = sckm_udata.type;
-		if (ddi_copyout(sckm_udata.buf, arg.buf,
-		    sckm_udata.buf_len, flag)) {
-			mutex_exit(&sckm_umutex);
-			return (EFAULT);
-		}
-		arg.buf_len = sckm_udata.buf_len;
-
-		mutex_exit(&sckm_umutex);
-		if (sckm_copyout_ioctl_getreq(&arg, data, flag)) {
-			return (EFAULT);
-		}
-		break;
-	}
-	case SCKM_IOCTL_STATUS: {
-		sckm_ioctl_status_t arg;
-		SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: got SCKM_IOCTL_STATUS");
-		if (ddi_copyin((caddr_t)data, &arg,
-		    sizeof (sckm_ioctl_status_t), flag)) {
-			cmn_err(CE_WARN, "sckm_ioctl: ddi_copyin failed");
-			return (EFAULT);
-		}
-		SCKM_DEBUG3(D_IOCTL, "sckm_ioctl: arg transid=0x%lx, "
-		    "status=%d, sadb_msg_errno=%d", arg.transid, arg.status,
-		    arg.sadb_msg_errno);
-
-		mutex_enter(&sckm_umutex);
-
-		/* fail if no status is expected, or if it does not match */
-		if (!sckm_udata_req || sckm_udata.transid != arg.transid) {
-			mutex_exit(&sckm_umutex);
-			return (EINVAL);
-		}
-
-		/* update status information for event handler */
-		bcopy(&arg, &sckm_udata_status, sizeof (sckm_ioctl_status_t));
-
-		/* signal event handler that request has been processed */
-		SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: signaling event handler"
-		    " that data has been processed");
-		cv_signal(&sckm_cons_cv);
-		sckm_udata_req = B_FALSE;
-
-		mutex_exit(&sckm_umutex);
-		break;
-	}
-	default:
-		SCKM_DEBUG0(D_IOCTL, "sckm_ioctl: unknown command");
-		rval = EINVAL;
-	}
-
-	SCKM_DEBUG1(D_IOCTL, "out sckm_ioctl, rval=%d", rval);
-	return (rval);
-}
-
-
-/*
- * sckm_mbox_callback
- *
- * Callback routine registered with the IOSRAM mailbox protocol driver.
- * Invoked when a message is received on the mailbox.
- */
-static void
-sckm_mbox_callback(void)
-{
-	SCKM_DEBUG0(D_CALLBACK, "in sckm_mbox_callback()");
-
-	mutex_enter(&sckm_taskq_ptr_mutex);
-
-	if (sckm_taskq == NULL) {
-		mutex_exit(&sckm_taskq_ptr_mutex);
-		return;
-	}
-
-	if (taskq_dispatch(sckm_taskq, sckm_mbox_task, NULL, KM_NOSLEEP) ==
-	    TASKQID_INVALID) {
-		/*
-		 * Too many tasks already pending. Do not queue a new
-		 * request.
-		 */
-		SCKM_DEBUG0(D_CALLBACK, "failed dispatching task");
-	}
-
-	mutex_exit(&sckm_taskq_ptr_mutex);
-
-	SCKM_DEBUG0(D_CALLBACK, "out sckm_mbox_callback()");
-}
-
-
-/*
- * sckm_mbox_task
- *
- * Dispatched on taskq from the IOSRAM mailbox callback
- * sckm_mbox_callback when a message is received on the incoming
- * mailbox.
- */
-static void
-sckm_mbox_task(void *ignored)
-{
-        _NOTE(ARGUNUSED(ignored))
-	uint32_t type, cmd, length;
-	uint64_t transid;
-	int rval;
-
-	SCKM_DEBUG0(D_TASK, "in sckm_mbox_task\n");
-
-	mutex_enter(&sckm_task_mutex);
-
-	if (req_data == NULL || rep_data == NULL) {
-		SCKM_DEBUG0(D_TASK, "sckm_mbox_task: no buffers");
-		mutex_exit(&sckm_task_mutex);
-		return;
-	}
-
-	/*
-	 * Get mailbox message.
-	 */
-
-	type = MBOXSC_MSG_REQUEST;
-	length = SCKM_SCKD_MAXDATA;
-	cmd = 0;
-	transid = 0;
-
-	SCKM_DEBUG0(D_TASK, "sckm_mbox_task: "
-	    "calling mboxsc_getmsg()\n");
-	rval = mboxsc_getmsg(KEY_SCKD, &type, &cmd, &transid,
-	    &length, req_data, sckm_getmsg_timeout);
-
-	if (rval != 0) {
-		SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
-		    "mboxsc_getmsg() failed (%d)\n", rval);
-		mutex_exit(&sckm_task_mutex);
-		return;
-	}
-
-	SCKM_DEBUG4(D_TASK, "sckm_mbox_task: "
-	    "type=0x%x cmd=0x%x length=%d transid=0x%lx\n",
-	    type, cmd, length, transid);
-
-	/* check message length */
-	if (length < sizeof (sckm_mbox_req_hdr_t)) {
-		/* protocol error, drop message */
-		SCKM_DEBUG2(D_TASK, "received short "
-		    "message of length %d, min %lu",
-		    length, sizeof (sckm_mbox_req_hdr_t));
-		mutex_exit(&sckm_task_mutex);
-		return;
-	}
-
-	/* check version of message received */
-	if (req_data->sckm_version != SCKM_PROTOCOL_VERSION) {
-		SCKM_DEBUG2(D_TASK, "received protocol "
-		    "version %d, expected %d",
-		    req_data->sckm_version, SCKM_PROTOCOL_VERSION);
-		/*
-		 * Send reply with SCKM_SADB_ERR_VERSION error
-		 * so that SC can adopt correct protocol version
-		 * for this domain.
-		 */
-		rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
-		rep_data->status = SCKM_ERR_VERSION;
-
-		rval = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
-		    cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
-		    rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT);
-
-		if (rval != 0) {
-			SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
-			    "mboxsc_putmsg() failed (%d)\n", rval);
-			mutex_exit(&sckm_task_mutex);
-			return;
-		}
-	}
-
-	/* process message */
-	sckm_process_msg(cmd, transid, length,
-	    req_data, rep_data);
-
-	mutex_exit(&sckm_task_mutex);
-}
-
-/*
- * sckm_process_msg
- *
- * Process a message received from the SC. Invoked by sckm_event_task().
- */
-static void
-sckm_process_msg(uint32_t cmd, uint64_t transid,
-    uint32_t len, sckm_mbox_req_hdr_t *req_data,
-    sckm_mbox_rep_hdr_t *rep_data)
-{
-	int rv;
-
-	mutex_enter(&sckm_umutex);
-
-	switch (cmd) {
-	case SCKM_MSG_SADB: {
-		int sadb_msglen;
-
-		sadb_msglen = len-sizeof (sckm_mbox_req_hdr_t);
-		SCKM_DEBUG1(D_TASK, "received SCKM_MSG_SADB len=%d",
-		    sadb_msglen);
-
-		/* sanity check request */
-		if (len-sizeof (sckm_mbox_req_hdr_t) <= 0) {
-			SCKM_DEBUG0(D_TASK, "bad SADB message, "
-			    "zero length");
-			/*
-			 * SADB message is too short, send corresponding
-			 * error message to SC.
-			 */
-			rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
-			rep_data->status = SCKM_ERR_SADB_MSG;
-
-			if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
-			    cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
-			    rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
-				SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
-				    "mboxsc_putmsg() failed (%d)\n", rv);
-			}
-			mutex_exit(&sckm_umutex);
-			return;
-		}
-
-		/* initialize request for daemon */
-		sckm_udata.transid = transid;
-		sckm_udata.type = SCKM_IOCTL_REQ_SADB;
-		sckm_udata.buf_len = len-sizeof (sckm_mbox_req_hdr_t);
-		bcopy(req_data+1, sckm_udata.buf, sckm_udata.buf_len);
-
-		break;
-	}
-	default:
-		cmn_err(CE_WARN, "unknown cmd %x received from SC", cmd);
-		/*
-		 * Received unknown command from SC. Send corresponding
-		 * error message to SC.
-		 */
-		rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
-		rep_data->status = SCKM_ERR_BAD_CMD;
-
-		if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
-		    cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
-		    rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
-			SCKM_DEBUG1(D_TASK, "sckm_mbox_task: "
-			    "mboxsc_putmsg() failed (%d)\n", rv);
-		}
-		mutex_exit(&sckm_umutex);
-		return;
-	}
-
-	/*
-	 * At this point, we know that the request is valid, so pass
-	 * the request to the daemon.
-	 */
-	SCKM_DEBUG0(D_TASK, "waking up daemon");
-	sckm_udata_req = B_TRUE;
-	cv_signal(&sckm_udata_cv);
-
-	/* wait for daemon to process request */
-	if (cv_reltimedwait(&sckm_cons_cv, &sckm_umutex,
-	    drv_usectohz(SCKM_DAEMON_TIMEOUT), TR_CLOCK_TICK) == -1) {
-		/*
-		 * Daemon did not process the data, report this
-		 * error to the SC.
-		 */
-		SCKM_DEBUG0(D_TASK, "daemon timeout!!");
-		rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
-		rep_data->status = SCKM_ERR_DAEMON;
-	} else {
-		/* Daemon processed data, return status to SC */
-		SCKM_DEBUG0(D_TASK, "daemon processed data");
-		rep_data->sckm_version = SCKM_PROTOCOL_VERSION;
-		switch (sckm_udata_status.status) {
-		case SCKM_IOCTL_STAT_SUCCESS:
-			SCKM_DEBUG0(D_TASK, "daemon returned success");
-			rep_data->status = SCKM_SUCCESS;
-			break;
-		case SCKM_IOCTL_STAT_ERR_PFKEY:
-			SCKM_DEBUG1(D_TASK, "daemon returned PF_KEY "
-			    "error, errno=%d",
-			    sckm_udata_status.sadb_msg_errno);
-			rep_data->status = SCKM_ERR_SADB_PFKEY;
-			rep_data->sadb_msg_errno =
-			    sckm_udata_status.sadb_msg_errno;
-			break;
-		case SCKM_IOCTL_STAT_ERR_REQ:
-			SCKM_DEBUG0(D_TASK, "daemon returned "
-			    "bad request");
-			rep_data->status = SCKM_ERR_DAEMON;
-			break;
-		case SCKM_IOCTL_STAT_ERR_VERSION:
-			SCKM_DEBUG0(D_TASK, "PF_KEY version not "
-			    "supported");
-			rep_data->status = SCKM_ERR_SADB_VERSION;
-			rep_data->sadb_msg_version =
-			    sckm_udata_status.sadb_msg_version;
-			break;
-		case SCKM_IOCTL_STAT_ERR_TIMEOUT:
-			SCKM_DEBUG0(D_TASK, "no response received "
-			    "from key engine");
-			rep_data->status = SCKM_ERR_SADB_TIMEOUT;
-			break;
-		case SCKM_IOCTL_STAT_ERR_OTHER:
-			SCKM_DEBUG0(D_TASK, "daemon encountered "
-			    "an error");
-			rep_data->status = SCKM_ERR_DAEMON;
-			break;
-		case SCKM_IOCTL_STAT_ERR_SADB_TYPE:
-			SCKM_DEBUG0(D_TASK, "daemon returned bad "
-			    "SADB message type");
-			rep_data->status = SCKM_ERR_SADB_BAD_TYPE;
-			break;
-		default:
-			cmn_err(CE_WARN, "SCKM daemon returned "
-			    "invalid status %d", sckm_udata_status.status);
-			rep_data->status = SCKM_ERR_DAEMON;
-		}
-	}
-
-	/* send reply back to SC */
-	if ((rv = mboxsc_putmsg(KEY_KDSC, MBOXSC_MSG_REPLY,
-	    cmd, &transid, sizeof (sckm_mbox_rep_hdr_t),
-	    rep_data, MBOXSC_PUTMSG_DEF_TIMEOUT)) != 0) {
-		SCKM_DEBUG1(D_TASK, "failed sending reply to SC (%d)", rv);
-	} else {
-		SCKM_DEBUG0(D_TASK, "reply sent to SC");
-	}
-
-	sckm_udata_req = B_FALSE;
-	mutex_exit(&sckm_umutex);
-}
--- a/usr/src/uts/sun4u/starcat/io/sckmdrv.conf	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-name="sckmdrv" parent="pseudo" instance=0;
--- a/usr/src/uts/sun4u/starcat/io/scosmb.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1258 +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 file contains the Starcat Solaris Mailbox Client module.  This module
- * handles mailbox messages from the SC to the OS (as opposed to messages sent
- * to specific drivers) and vice versa.  Two task queues are created upon
- * startup; one handles reading and processing of all incoming messages, while
- * the other handles transmission of all outgoing messages.
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysmacros.h>
-#include <sys/sunddi.h>
-#include <sys/errno.h>
-#include <sys/cmn_err.h>
-#include <sys/condvar.h>
-#include <sys/mutex.h>
-#include <sys/disp.h>
-#include <sys/thread.h>
-#include <sys/debug.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/machsystm.h>
-#include <sys/modctl.h>
-#include <sys/iosramio.h>
-#include <sys/mboxsc.h>
-#include <sys/promif.h>
-#include <sys/uadmin.h>
-#include <sys/cred.h>
-#include <sys/taskq.h>
-#include <sys/utsname.h>
-#include <sys/plat_ecc_unum.h>
-#include <sys/fm/protocol.h>
-#include <sys/fm/util.h>
-#include <sys/starcat.h>
-#include <sys/plat_ecc_dimm.h>
-#include <sys/plat_datapath.h>
-
-/* mailbox keys */
-#define	SCDM_KEY	0x5343444d	/* 'S', 'C', 'D', 'M' */
-#define	DMSC_KEY	0x444d5343	/* 'D', 'M', 'S', 'C' */
-
-/* mailbox commands */
-#define	SCDM_CMD		('S' << 8)	/* generic SSP */
-#define	SCDM_CMD_SUCCESS	(SCDM_CMD | 0x1)
-#define	SCDM_GOTO_OBP		(SCDM_CMD | 0x2)
-#define	SCDM_GOTO_PANIC		(SCDM_CMD | 0x3)
-#define	SCDM_ENVIRON		(SCDM_CMD | 0x4) /* environmental intr */
-#define	SCDM_SHUTDOWN		(SCDM_CMD | 0x5) /* setkeyswitch STANDBY */
-#define	SCDM_GET_NODENAME	(SCDM_CMD | 0x6) /* get domain nodename */
-#define	SCDM_LOG_ECC_ERROR	(SCDM_CMD | 0x7) /* ECC error logging */
-#define	SCDM_LOG_ECC_INDICTMENT	(SCDM_CMD | 0x8) /* ECC indictment logging */
-#define	SCDM_LOG_ECC		(SCDM_CMD | 0x9) /* ECC info */
-#define	SCDM_LOG_ECC_CAP_INIT	(SCDM_CMD | 0xa) /* ECC Capability Init */
-#define	SCDM_LOG_ECC_CAP_RESP	(SCDM_CMD | 0xb) /* ECC Capability Response */
-#define	SCDM_DIMM_SERIAL_ID	(SCDM_CMD | 0xc) /* DIMM ser# req/resp */
-#define	SCDM_DP_ERROR_MSG	(SCDM_CMD | 0xd) /* datapath error */
-#define	SCDM_DP_FAULT_MSG	(SCDM_CMD | 0xe) /* datapath fault */
-
-/* general constants */
-#define	GETMSG_TIMEOUT_MS	500
-#define	PUTMSG_TIMEOUT_MS	6000
-#define	MIN_INPUTQ_TASKS	2
-#define	MAX_INPUTQ_TASKS	4
-#define	MIN_OUTPUTQ_TASKS	2
-#define	MAX_OUTPUTQ_TASKS	512
-#ifndef TRUE
-#define	TRUE	1
-#endif
-#ifndef FALSE
-#define	FALSE	0
-#endif
-
-clock_t ecc_message_timeout_ms = PUTMSG_TIMEOUT_MS;
-
-/*
- * When a message needs to be sent to the SC, an scosmb_msgdata_t should be
- * populated with the data to be used for the message, and a call to
- * scosmb_process_output should be dispatched on the scosmb_output_taskq, with
- * the address of the scosmb_msgdata_t structure as its arg.  The "length" and
- * "data" fields can be used if the message needs to include data beyond the
- * header fields (type, cmd, and transid) and that information must be recorded
- * when the message is placed on the taskq.  If appropriate for the message type
- * (e.g. nodename info that should always be the most recent available), the
- * "data" field can be set to NULL and the additional data can be assembled
- * immediately prior to sending the message in scosmb_process_output().
- *
- * If log_error is set, any errors in delivering the message cause a
- * cmn_err() message to be issued.  If it is zero, the error is expressed
- * only through return values.
- */
-typedef struct {
-	uint32_t	type;
-	uint32_t	cmd;
-	uint64_t	transid;
-	uint32_t	length;
-	int		log_error;
-	void		*data;
-} scosmb_msgdata_t;
-
-/*
- * Datapath error and fault messages arrive unsolicited.  The message data
- * is contained in a plat_datapath_info_t structure.
- */
-typedef struct {
-	uint8_t		type;		/* CDS, DX, EX, CP */
-	uint8_t		pad;		/* for alignment */
-	uint16_t	cpuid;		/* Safari ID of base CPU */
-	uint32_t	t_value;	/* SERD timeout threshold (seconds) */
-} plat_datapath_info_t;
-
-/* externally visible routines */
-void scosmb_update_nodename(uint64_t transid);
-
-/* local routines */
-static void scosmb_inbox_handler();
-static void scosmb_process_input(void *unused);
-static int scosmb_process_output(scosmb_msgdata_t *arg);
-
-/* local variables */
-static uint8_t	scosmb_mboxsc_failed = FALSE;
-static uint8_t	scosmb_mboxsc_timedout = FALSE;
-static uint8_t	scosmb_nodename_event_pending = FALSE;
-static char	scosmb_hdr[] = "SCOSMB:";
-static kmutex_t scosmb_mutex;
-static taskq_t	*scosmb_input_taskq = NULL;
-static taskq_t	*scosmb_output_taskq = NULL;
-
-static char *dperrtype[] = {
-	DP_ERROR_CDS,
-	DP_ERROR_DX,
-	DP_ERROR_EX,
-	DP_ERROR_CP
-};
-
-/*
- * Structures from modctl.h used for loadable module support.
- * SCOSMB is a "miscellaneous" module.
- */
-extern struct mod_ops mod_miscops;
-
-static struct modlmisc modlmisc = {
-	&mod_miscops,
-	"Sun Fire 15000 OS Mbox Client v1.10",
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modlmisc,
-	NULL
-};
-
-
-/*
- * _init
- *
- * Loadable module support routine.  Initializes mutex and condition variables
- * and starts thread.
- */
-int
-_init(void)
-{
-	int error;
-
-	/*
-	 * Initialize the mailboxes
-	 */
-	if ((error = mboxsc_init(SCDM_KEY, MBOXSC_MBOX_IN,
-	    scosmb_inbox_handler)) != 0) {
-		cmn_err(CE_WARN, "%s mboxsc_init failed (0x%x)\n", scosmb_hdr,
-		    error);
-		return (error);
-	}
-
-	if ((error = mboxsc_init(DMSC_KEY, MBOXSC_MBOX_OUT, NULL)) != 0) {
-		cmn_err(CE_WARN, "%s mboxsc_init failed (0x%x)\n", scosmb_hdr,
-		    error);
-		(void) mboxsc_fini(SCDM_KEY);
-		return (error);
-	}
-
-	/*
-	 * Initialize the global lock
-	 */
-	mutex_init(&scosmb_mutex, NULL, MUTEX_DEFAULT, NULL);
-
-	/*
-	 * Create the task queues used for processing input and output messages
-	 */
-	scosmb_input_taskq = taskq_create("scosmb_input_taskq", 1,
-	    minclsyspri, MIN_INPUTQ_TASKS, MAX_INPUTQ_TASKS, TASKQ_PREPOPULATE);
-	scosmb_output_taskq = taskq_create("scosmb_output_taskq", 1,
-	    minclsyspri, MIN_OUTPUTQ_TASKS, MAX_OUTPUTQ_TASKS,
-	    TASKQ_PREPOPULATE);
-
-	/*
-	 * Attempt to install the module.  If unsuccessful, uninitialize
-	 * everything.
-	 */
-	error = mod_install(&modlinkage);
-	if (error != 0) {
-		taskq_destroy(scosmb_output_taskq);
-		taskq_destroy(scosmb_input_taskq);
-		mutex_destroy(&scosmb_mutex);
-		(void) mboxsc_fini(DMSC_KEY);
-		(void) mboxsc_fini(SCDM_KEY);
-	}
-
-	return (error);
-}
-
-/*
- * _fini
- *
- * Loadable module support routine. Since this routine shouldn't be unloaded (it
- * provides a critical service, and its symbols may be referenced externally),
- * EBUSY is returned to prevent unloading.
- */
-int
-_fini(void)
-{
-	return (EBUSY);
-}
-
-/*
- * _info
- *
- * Loadable module support routine.
- */
-int
-_info(struct modinfo *modinfop)
-{
-	int		error = 0;
-
-	error = mod_info(&modlinkage, modinfop);
-	return (error);
-}
-
-/*
- * scosmb_inbox_handler() - mbox API event handler.
- *
- * This routine adds an entry to the scosmb_input_taskq that will cause the
- * scosmb_process_input() routine to be called to service the SCDM mailbox.  The
- * possibility that taskq_dispatch may fail when given KM_NOSLEEP is safely
- * ignored because there can only be one message waiting in the mailbox at any
- * given time, so the current message will end up being handled by one of the
- * previously queued jobs (and a previous message presumably timed out before we
- * got around to reading it).
- */
-static void
-scosmb_inbox_handler()
-{
-	(void) taskq_dispatch(scosmb_input_taskq, scosmb_process_input, NULL,
-	    KM_NOSLEEP);
-}
-
-/*
- * dp_get_cores()
- *
- * Checks cpu implementation for the input cpuid and returns
- * the number of cores.
- * If implementation cannot be determined, returns 1
- */
-static int
-dp_get_cores(uint16_t cpuid)
-{
-	int	exp, ii, impl = 0, nc, slot;
-
-	exp = STARCAT_CPUID_TO_EXPANDER(cpuid);
-	slot = STARCAT_CPUID_TO_BOARDSLOT(cpuid);
-	if (slot == 1)
-		nc = STARCAT_SLOT1_CPU_MAX;
-	else
-		nc = plat_max_cpu_units_per_board();
-
-	/* find first with valid implementation */
-	for (ii = 0; ii < nc; ii++)
-		if (cpu[MAKE_CPUID(exp, slot, ii)]) {
-			impl = cpunodes[MAKE_CPUID(exp, slot, ii)].
-			    implementation;
-			break;
-		}
-
-	if (IS_JAGUAR(impl) || IS_PANTHER(impl))
-		return (2);
-	else
-		return (1);
-
-}
-
-/*
- * dp_payload_add_cpus()
- *
- * From datapath mailbox message, determines the number of and safari IDs
- * for affected cpus, then adds this info to the datapath ereport.
- *
- * Input maxcat (if set) is a count of maxcat cpus actually present - it is
- * a count of cpuids, which takes into account multi-core architecture.
- */
-static int
-dp_payload_add_cpus(plat_datapath_info_t *dpmsg, nvlist_t *erp, int maxcat)
-{
-	int		jj = 0, numcpus = 0, nummaxcpus = 0;
-	int		count, exp, ii, num, ncores, ret, slot, port;
-	uint16_t	*dparray, cpuid;
-	uint64_t	*snarray;
-
-	/* check for multiple core architectures */
-	ncores = dp_get_cores(dpmsg->cpuid);
-
-	/*
-	 * Determine the number of cpu cores impacted
-	 */
-	switch (dpmsg->type) {
-		case DP_CDS_TYPE:
-			if (maxcat)
-				nummaxcpus = ncores;
-			else
-				numcpus = ncores;
-			break;
-
-		case DP_DX_TYPE:
-			if (maxcat)
-				nummaxcpus = 2 * ncores;
-			else
-				numcpus = 2 * ncores;
-			break;
-
-		case DP_EX_TYPE:
-			if (maxcat)
-				nummaxcpus = STARCAT_SLOT1_CPU_MAX;
-			else
-				numcpus = plat_max_cpu_units_per_board();
-			break;
-
-		case DP_CP_TYPE:
-			/*
-			 * SC-DE supplies the base cpuid affected, if
-			 * maxcat id was given, there's no slot 0 board
-			 * present.
-			 */
-
-			if (!maxcat) {
-				/* Slot 0 id was given - set numcpus */
-				numcpus = plat_max_cpu_units_per_board();
-			}
-
-			/* there may/may not be maxcats. set a count anyway */
-			nummaxcpus = STARCAT_SLOT1_CPU_MAX;
-
-			break;
-
-		default:
-			ASSERT(0);
-			return (-1);
-	}
-
-	/* Allocate space for cores */
-	num = numcpus + nummaxcpus;
-	dparray = kmem_zalloc(num * sizeof (uint16_t *), KM_SLEEP);
-
-	/*
-	 * populate dparray with impacted cores (only those present)
-	 */
-	exp = STARCAT_CPUID_TO_EXPANDER(dpmsg->cpuid);
-	slot = STARCAT_CPUID_TO_BOARDSLOT(dpmsg->cpuid);
-	port = STARCAT_CPUID_TO_LPORT(dpmsg->cpuid);
-
-	mutex_enter(&cpu_lock);
-
-	switch (dpmsg->type) {
-		case DP_CDS_TYPE:
-			/*
-			 * For a CDS error, it's the reporting cpuid
-			 * and it's other core (if present)
-			 */
-			cpuid = dpmsg->cpuid & 0xFFFB; 	/* core 0 */
-			if (cpu[cpuid])
-				dparray[jj++] = cpuid;
-
-			cpuid = dpmsg->cpuid | 0x4; 	/* core 1 */
-			if (cpu[cpuid])
-				dparray[jj++] = cpuid;
-			break;
-
-		case DP_DX_TYPE:
-			/*
-			 * For a DX error, it's the reporting cpuid (all
-			 * cores), and the other CPU sharing the same
-			 * DX<-->DCDS interface (all cores)
-			 */
-
-			/* reporting cpuid */
-			cpuid = dpmsg->cpuid & 0xFFFB; 	/* core 0 */
-
-			if (cpu[cpuid])
-				dparray[jj++] = cpuid;
-
-			cpuid = dpmsg->cpuid | 0x4; 	/* core 1 */
-			if (cpu[cpuid])
-				dparray[jj++] = cpuid;
-
-			/* find partner cpuid */
-			if (port == 0 || port == 2)
-				cpuid = dpmsg->cpuid | 0x1;
-			else
-				cpuid = dpmsg->cpuid & 0xFFFE;
-
-			/* add partner cpuid */
-			cpuid &= 0xFFFB; 	/* core 0 */
-			if (cpu[cpuid])
-				dparray[jj++] = cpuid;
-
-			cpuid |= 0x4; 	/* core 1 */
-			if (cpu[cpuid])
-				dparray[jj++] = cpuid;
-			break;
-
-		case DP_EX_TYPE:
-			/*
-			 * For an EX error, it is all cpuids (all cores)
-			 * on the reporting board
-			 */
-
-			if (slot == 1) 			/* maxcat */
-				count = nummaxcpus;
-			else
-				count = numcpus;
-
-			for (ii = 0; ii < count; ii++) {
-				cpuid = MAKE_CPUID(exp, slot, ii);
-				if (cpu[cpuid])
-					dparray[jj++] = cpuid;
-			}
-			break;
-
-		case DP_CP_TYPE:
-			/*
-			 * For a CP error, it is all cpuids (all cores)
-			 * on both boards (SB & IO) in the boardset
-			 */
-
-			/* Do slot 0 */
-			for (ii = 0; ii < numcpus; ii++) {
-				cpuid = MAKE_CPUID(exp, 0, ii);
-				if (cpu[cpuid])
-					dparray[jj++] = cpuid;
-			}
-
-			/* Do slot 1 */
-			for (ii = 0; ii < nummaxcpus; ii++) {
-				cpuid = MAKE_CPUID(exp, 1, ii);
-				if (cpu[cpuid])
-					dparray[jj++] = cpuid;
-			}
-			break;
-	}
-
-	mutex_exit(&cpu_lock);
-
-	/*
-	 * The datapath message could not be associated with any
-	 * configured CPU.
-	 */
-	if (!jj) {
-		kmem_free(dparray, num * sizeof (uint16_t *));
-		ret = nvlist_add_uint32(erp, DP_LIST_SIZE, jj);
-		ASSERT(ret == 0);
-		return (-1);
-	}
-
-	snarray = kmem_zalloc(jj * sizeof (uint64_t *), KM_SLEEP);
-	for (ii = 0; ii < jj; ii++)
-		snarray[ii] = cpunodes[dparray[ii]].device_id;
-
-	ret = nvlist_add_uint32(erp, DP_LIST_SIZE, jj);
-	ret |= nvlist_add_uint16_array(erp, DP_LIST, dparray, jj);
-	ret |= nvlist_add_uint64_array(erp, SN_LIST, snarray, jj);
-	ASSERT(ret == 0);
-
-	kmem_free(dparray, num * sizeof (uint16_t *));
-	kmem_free(snarray, jj * sizeof (uint64_t *));
-
-	return (0);
-}
-
-/*
- * dp_trans_event() - datapath message handler.
- *
- * Process datapath error and fault messages received from the SC.  Checks
- * for, and disregards, messages associated with I/O boards.  Otherwise,
- * extracts message info to produce a datapath ereport.
- */
-static void
-dp_trans_event(plat_datapath_info_t *dpmsg, int msgtype)
-{
-	nvlist_t	*erp, *detector, *hcelem;
-	char		buf[FM_MAX_CLASS];
-	int		exp, slot, i, maxcat = 0;
-
-	/* check for I/O board message */
-	exp = STARCAT_CPUID_TO_EXPANDER(dpmsg->cpuid);
-	slot = STARCAT_CPUID_TO_BOARDSLOT(dpmsg->cpuid);
-
-	if (slot) {
-		mutex_enter(&cpu_lock);
-		for (i = 0; i < STARCAT_SLOT1_CPU_MAX; i++) {
-			if (cpu[MAKE_CPUID(exp, slot, i)]) {
-				/* maxcat cpu present */
-				maxcat++;
-			}
-		}
-		mutex_exit(&cpu_lock);
-
-		/*
-		 * Ignore I/O board msg
-		 */
-		if (maxcat == 0)
-			return;
-	}
-
-	/* allocate space for ereport */
-	erp = fm_nvlist_create(NULL);
-
-	/*
-	 *
-	 * Member Name	Data Type	   Comments
-	 * -----------	---------	   -----------
-	 * version	uint8		   0
-	 * class	string		   "asic"
-	 * ENA		uint64		   ENA Format 1
-	 * detector	fmri		   aggregated ID data for SC-DE
-	 *
-	 * Datapath ereport subclasses and data payloads:
-	 * There will be two types of ereports (error and fault) which will be
-	 * identified by the "type" member.
-	 *
-	 * ereport.asic.starcat.cds.cds-dp
-	 * ereport.asic.starcat.dx.dx-dp
-	 * ereport.asic.starcat.sdi.sdi-dp
-	 * ereport.asic.starcat.cp.cp-dp
-	 *
-	 * Member Name	Data Type	Comments
-	 * -----------	---------	-----------
-	 * erptype	uint16		derived from message type: error or
-	 *				fault
-	 * t-value	uint32		SC's datapath SERD timeout threshold
-	 * dp-list-sz	uint8		number of dp-list array elements
-	 * dp-list	array of uint16	Safari IDs of affected cpus
-	 * sn-list	array of uint64	Serial numbers of affected cpus
-	 *
-	 */
-
-	/* compose common ereport elements */
-	detector = fm_nvlist_create(NULL);
-
-	/*
-	 * Create legacy FMRI for the detector
-	 */
-	switch (dpmsg->type) {
-		case DP_CDS_TYPE:
-		case DP_DX_TYPE:
-			if (slot == 1)
-				(void) snprintf(buf, FM_MAX_CLASS, "IO%d", exp);
-			else
-				(void) snprintf(buf, FM_MAX_CLASS, "SB%d", exp);
-			break;
-
-		case DP_EX_TYPE:
-			(void) snprintf(buf, FM_MAX_CLASS, "EX%d", exp);
-			break;
-
-		case DP_CP_TYPE:
-			(void) snprintf(buf, FM_MAX_CLASS, "CP");
-			break;
-
-		default:
-			(void) snprintf(buf, FM_MAX_CLASS, "UNKNOWN");
-			break;
-	}
-
-	hcelem = fm_nvlist_create(NULL);
-
-	(void) nvlist_add_string(hcelem, FM_FMRI_HC_NAME, FM_FMRI_LEGACY_HC);
-	(void) nvlist_add_string(hcelem, FM_FMRI_HC_ID, buf);
-
-	(void) nvlist_add_uint8(detector, FM_VERSION, FM_HC_SCHEME_VERSION);
-	(void) nvlist_add_string(detector, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC);
-	(void) nvlist_add_string(detector, FM_FMRI_HC_ROOT, "");
-	(void) nvlist_add_uint32(detector, FM_FMRI_HC_LIST_SZ, 1);
-	(void) nvlist_add_nvlist_array(detector, FM_FMRI_HC_LIST, &hcelem, 1);
-
-	/* build ereport class name */
-	(void) snprintf(buf, FM_MAX_CLASS, "asic.starcat.%s.%s-%s",
-	    dperrtype[dpmsg->type], dperrtype[dpmsg->type],
-	    FM_ERROR_DATAPATH);
-
-	fm_ereport_set(erp, FM_EREPORT_VERSION, buf,
-	    fm_ena_generate(0, FM_ENA_FMT1), detector, NULL);
-
-	/* add payload elements */
-	if (msgtype == SCDM_DP_ERROR_MSG) {
-		fm_payload_set(erp,
-		    DP_EREPORT_TYPE, DATA_TYPE_UINT16, DP_ERROR, NULL);
-	} else {
-		fm_payload_set(erp,
-		    DP_EREPORT_TYPE, DATA_TYPE_UINT16, DP_FAULT, NULL);
-	}
-
-	fm_payload_set(erp, DP_TVALUE, DATA_TYPE_UINT32, dpmsg->t_value, NULL);
-
-	if (dp_payload_add_cpus(dpmsg, erp, maxcat) == 0) {
-		/* post ereport */
-		fm_ereport_post(erp, EVCH_SLEEP);
-	}
-
-	/* free ereport memory */
-	fm_nvlist_destroy(erp, FM_NVA_FREE);
-	fm_nvlist_destroy(detector, FM_NVA_FREE);
-
-}
-
-/*
- * scosmb_process_input() - incoming message processing routine
- *
- * this routine attempts to read a message from the SCDM mailbox and, if
- * successful, processes the command.  if an unrecoverable error is encountered,
- * the scosmb_task thread will be terminated.
- */
-/* ARGSUSED0 */
-static void
-scosmb_process_input(void *unused)
-{
-	int 			error;
-	scosmb_msgdata_t	 msg;
-	proc_t			*initpp;
-	plat_capability_data_t	*cap;	/* capability msg contents ptr */
-	int			cap_size;
-	int			cap_ver_len;
-	scosmb_msgdata_t	*cap_msgdatap; /* capability msg response */
-	int			max_size;
-
-	/*
-	 * Attempt to read a message from the SCDM mailbox.
-	 *
-	 * Setup a local buffer to read incoming messages from the SC.
-	 */
-	cap_ver_len = strlen(utsname.release) + strlen(utsname.version) + 2;
-	cap_size = sizeof (plat_capability_data_t) + cap_ver_len;
-	max_size = MAX(cap_size, sizeof (plat_dimm_sid_board_data_t));
-
-	msg.type = 0;
-	msg.cmd = 0;
-	msg.transid = 0;
-	msg.length = max_size;
-	msg.log_error = 0;
-	msg.data = kmem_zalloc(max_size, KM_SLEEP);
-
-	error = mboxsc_getmsg(SCDM_KEY, &msg.type, &msg.cmd, &msg.transid,
-	    &msg.length, msg.data, GETMSG_TIMEOUT_MS);
-
-	/*
-	 * If EAGAIN or ETIMEDOUT was received, give up.  The SC can just try
-	 * again if it was important.  If any other non-zero error was
-	 * encountered, the mailbox service is broken, and there's nothing more
-	 * we can do.
-	 */
-	mutex_enter(&scosmb_mutex);
-	if ((error == EAGAIN) || (error == ETIMEDOUT)) {
-		mutex_exit(&scosmb_mutex);
-		return;
-	} else if (error != 0) {
-		/*
-		 * The mailbox service appears to be badly broken.  If it was
-		 * working previously, generate a warning and set a flag to
-		 * avoid repeating the warning on subsequent failures.
-		 */
-		if (!scosmb_mboxsc_failed) {
-			scosmb_mboxsc_failed = TRUE;
-			cmn_err(CE_WARN, "%s mboxsc error (0x%x)\n", scosmb_hdr,
-			    error);
-		}
-		mutex_exit(&scosmb_mutex);
-		return;
-	} else {
-		/*
-		 * If the mailbox module failed previously, it appears to have
-		 * recovered, so we'll want to generate a warning if it fails
-		 * again.
-		 */
-		scosmb_mboxsc_failed = FALSE;
-	}
-	mutex_exit(&scosmb_mutex);
-
-	/*
-	 * A message was successfully received, so go ahead and process it.
-	 */
-	switch (msg.cmd) {
-
-	case SCDM_GOTO_OBP:	/* jump to OBP */
-		debug_enter("SC requested jump to OBP");
-		break;
-
-	case SCDM_GOTO_PANIC:	/* Panic the domain */
-		cmn_err(CE_PANIC, "%s SC requested PANIC\n", scosmb_hdr);
-		break;
-
-	case SCDM_SHUTDOWN:	/* graceful shutdown */
-		cmn_err(CE_WARN, "%s SC requested a shutdown ", scosmb_hdr);
-		(void) kadmin(A_SHUTDOWN, AD_HALT, NULL, kcred);
-		/*
-		 * In the event kadmin does not bring down the
-		 * domain, environmental shutdown is forced
-		 */
-		/*FALLTHROUGH*/
-	case SCDM_ENVIRON:	/* environmental shutdown */
-		/*
-		 * Send SIGPWR to init(1) it will run rc0,
-		 * which will uadmin to power down.
-		 */
-		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, "%s Environmental Interrupt",
-			    scosmb_hdr);
-			power_down((char *)NULL);
-			halt("Power off the System!\n");
-		}
-
-		/*
-		 * else, graceful shutdown with inittab and all
-		 * getting involved
-		 */
-		psignal(initpp, SIGPWR);
-		break;
-
-	case SCDM_GET_NODENAME:
-		scosmb_update_nodename(msg.transid);
-		break;
-
-	case SCDM_LOG_ECC_CAP_RESP:
-		/*
-		 * The SC has responded to our initiator capability message
-		 * issued during the boot flow via scosmb_update_nodename().
-		 *
-		 * Parse the incoming data, and appropriately set SC
-		 * capabilities...
-		 */
-		cap = (plat_capability_data_t *)msg.data;
-		plat_ecc_capability_sc_set(cap->capd_capability);
-		break;
-
-	case SCDM_LOG_ECC_CAP_INIT:
-		/*
-		 * The SC has initiated a capability messaging exchange with
-		 * the OS.
-		 *
-		 * We start out just as we do for an SC response capability
-		 * message, a parse of incoming data to appropriately set SC
-		 * described capabilities...
-		 */
-		cap = (plat_capability_data_t *)msg.data;
-		plat_ecc_capability_sc_set(cap->capd_capability);
-		/*
-		 * The next step is setting up our Response to the SC.
-		 *
-		 * Allocate memory for message data, initialize appropriately,
-		 * and place a new job on the scosmb_output_taskq for
-		 * SCDM_LOG_ECC_CAP_RESP, our OS capability messaging response
-		 * to the SC initiated sequence detected here.
-		 */
-		cap_msgdatap = kmem_zalloc(sizeof (scosmb_msgdata_t), KM_SLEEP);
-		cap_msgdatap->type = MBOXSC_MSG_EVENT;
-		cap_msgdatap->cmd = SCDM_LOG_ECC_CAP_RESP;
-		cap_msgdatap->transid = 0;
-		(void) taskq_dispatch(scosmb_output_taskq,
-		    (task_func_t *)scosmb_process_output, cap_msgdatap,
-		    KM_SLEEP);
-		break;
-
-	case SCDM_DP_ERROR_MSG:
-	case SCDM_DP_FAULT_MSG:
-		dp_trans_event(msg.data, msg.cmd);
-		break;
-
-	case SCDM_DIMM_SERIAL_ID:
-		(void) plat_store_mem_sids(msg.data);
-		break;
-
-	default:
-		cmn_err(CE_WARN, "%s invalid command (0x%x)\n", scosmb_hdr,
-		    msg.cmd);
-		break;
-	}
-
-	/*
-	 * Free up buffer for incoming messasge data that we allocated earlier
-	 */
-	kmem_free(msg.data, max_size);
-}
-
-/*
- * scosmb_process_output() - outgoing message processing routine
- *
- * This routine handles jobs that are queued on the scosmb_output_taskq, or
- * sent directly from scosmb_log_ecc_error.  Each job corresponds to a single
- * mailbox message that needs to be sent to the SC via the DMSC mailbox.  Some
- * processing of the message may be performed before it is sent to the SC,
- * depending on the value of the command field.
- */
-static int
-scosmb_process_output(scosmb_msgdata_t *msgdatap)
-{
-	int 			error;
-	int			length;
-	char			nodename[_SYS_NMLN];
-	void			*free_data;
-	int			free_data_len;
-	int			cap_size;
-	int			cap_ver_len;
-	plat_capability_data_t	*cap = NULL;
-
-	/*
-	 * This shouldn't ever happen, but it can't hurt to check anyway.
-	 */
-	if (msgdatap == NULL) {
-		return (EINVAL);
-	}
-
-	/*
-	 * If data was passed in, we'll need to free it before returning.
-	 */
-	free_data = msgdatap->data;
-	free_data_len = msgdatap->length;
-
-	/*
-	 * Some commands may need additional processing prior to transmission.
-	 */
-	switch (msgdatap->cmd) {
-		/*
-		 * Since the SC is only interested in the most recent value of
-		 * utsname.nodename, we wait until now to collect that data.  We
-		 * also use a global flag to prevent multiple event-type
-		 * nodename messages from being queued at the same time for the
-		 * same reason.
-		 */
-		case SCDM_GET_NODENAME:
-			mutex_enter(&scosmb_mutex);
-			length = strlen(utsname.nodename);
-			ASSERT(length < _SYS_NMLN);
-			if (length == 0) {
-				msgdatap->length = 0;
-				msgdatap->data = NULL;
-			} else {
-				bcopy(utsname.nodename, nodename, length);
-				nodename[length++] = '\0';
-				msgdatap->data = nodename;
-				msgdatap->length = length;
-			}
-			if (msgdatap->transid == 0) {
-				scosmb_nodename_event_pending = FALSE;
-			}
-			mutex_exit(&scosmb_mutex);
-			break;
-
-		/*
-		 * SCDM_LOG_ECC_CAP_INIT
-		 * Initiator Capability message from OS to SC
-		 *
-		 * We construct and send an initiator capability message
-		 * every time we go through scosmb_update_nodename(), which
-		 * works out to getting an "initiator" capability message
-		 * sent from the OS to the SC during the OS boot flow.
-		 *
-		 * The SC also issues a request to scosmb_update_nodename()
-		 * during an SC reboot.  Which results in an additional
-		 * capability message exchange during SC reboot scenarios.
-		 *
-		 * SCDM_LOG_ECC_CAP_RESP
-		 * Response Capability message from SC to OS
-		 *
-		 * In certain scenarios, the SC could initiate a capability
-		 * messaging exchange with the OS.  Processing starts in
-		 * scosmb_process_input(), where we detect an incoming
-		 * initiator capability message from the SC.  We finish
-		 * processing here, by sending a response capability message
-		 * back to the SC that reflects OS capabilities.
-		 */
-		case SCDM_LOG_ECC_CAP_INIT:
-			/*FALLTHROUGH*/
-		case SCDM_LOG_ECC_CAP_RESP:
-			mutex_enter(&scosmb_mutex);
-
-			cap_ver_len = strlen(utsname.release) +
-			    strlen(utsname.version) + 2;
-
-			cap_size = sizeof (plat_capability_data_t) +
-			    cap_ver_len;
-
-			cap =  kmem_zalloc(cap_size, KM_SLEEP);
-
-			cap->capd_major_version = PLAT_ECC_CAP_VERSION_MAJOR;
-			cap->capd_minor_version = PLAT_ECC_CAP_VERSION_MINOR;
-			cap->capd_msg_type = PLAT_ECC_CAPABILITY_MESSAGE;
-			cap->capd_msg_length =  cap_size;
-
-			cap->capd_capability =
-			    PLAT_ECC_CAPABILITY_DOMAIN_DEFAULT;
-
-			/*
-			 * Build the capability solaris_version string:
-			 * utsname.release + " " + utsname.version
-			 */
-			(void) snprintf(cap->capd_solaris_version,
-			    cap_ver_len, "%s %s", utsname.release,
-			    utsname.version);
-
-			/*
-			 * The capability message is constructed, now plug it
-			 * into the starcat msgdatap:
-			 */
-			msgdatap->data   = (plat_capability_data_t *)cap;
-			msgdatap->length = cap_size;
-
-			/*
-			 * Finished with initiator/response capability
-			 * message set up.
-			 *
-			 * Note that after sending an "initiator" capability
-			 * message, we can expect a subsequent "response"
-			 * capability message from the SC, which we will
-			 * pick up and minimally handle later,
-			 * in scosmb_process_input().
-			 *
-			 * If we're sending a "response" capability message
-			 * to the SC, then we're done once the message is sent.
-			 */
-
-			if (msgdatap->transid == 0) {
-				scosmb_nodename_event_pending = FALSE;
-			}
-			mutex_exit(&scosmb_mutex);
-			break;
-
-		default:
-			break;
-	}
-
-	/*
-	 * Attempt to send the message.
-	 */
-	error = mboxsc_putmsg(DMSC_KEY, msgdatap->type, msgdatap->cmd,
-	    &msgdatap->transid, msgdatap->length, msgdatap->data,
-	    ecc_message_timeout_ms);
-
-	/*
-	 * Free any allocated memory that was passed in.
-	 */
-	if (free_data != NULL) {
-		kmem_free(free_data, free_data_len);
-	}
-
-	if (cap != NULL) {
-		kmem_free(cap, cap_size);
-	}
-
-	kmem_free(msgdatap, sizeof (scosmb_msgdata_t));
-
-	/*
-	 * If EAGAIN or ETIMEDOUT was received, give up.  The sender can try
-	 * again if it was important.  If any other non-zero error was
-	 * encountered, the mailbox service is broken, and there's nothing more
-	 * we can do.
-	 */
-	mutex_enter(&scosmb_mutex);
-	if ((error == EAGAIN) || (error == ETIMEDOUT)) {
-		if (msgdatap->log_error && !scosmb_mboxsc_timedout) {
-			/*
-			 * Indictment mailbox messages use the return value to
-			 * indicate a problem in the mailbox.  For Error
-			 * mailbox messages, we'll have to use a syslog message.
-			 */
-			scosmb_mboxsc_timedout = TRUE;
-			cmn_err(CE_NOTE, "!Solaris failed to send a message "
-			    "(0x%x/0x%x) to the System Controller. Error: %d",
-			    msgdatap->type, msgdatap->cmd, error);
-		}
-	} else if (error != 0) {
-		/*
-		 * The mailbox service appears to be badly broken.  If it was
-		 * working previously, generate a warning and set a flag to
-		 * avoid repeating the warning on subsequent failures.
-		 */
-		if (msgdatap->log_error && !scosmb_mboxsc_failed) {
-			scosmb_mboxsc_failed = TRUE;
-			cmn_err(CE_NOTE, "!An internal error (%d) occurred "
-			    "while processing this message (0x%x/0x%x)",
-			    error, msgdatap->type, msgdatap->cmd);
-		}
-	} else {
-		/*
-		 * If the mailbox module failed previously, it appears to have
-		 * recovered, so we'll want to generate a warning if it fails
-		 * again.
-		 */
-		scosmb_mboxsc_failed = scosmb_mboxsc_timedout = FALSE;
-	}
-	mutex_exit(&scosmb_mutex);
-	return (error);
-}
-
-/*
- * scosmb_update_nodename() - nodename update routine
- *
- * this routine, which may be invoked from outside of the scosmb module, will
- * cause the current nodename to be sent to the SC.  The mailbox message sent to
- * the SC will use the indicated transaction ID, and will either be a reply
- * message if the ID is non-zero or an event message if it is 0.
- *
- * Capability messaging enhancements:
- *    Every time we move through this code flow, we put an "initiator
- *    capability message" on the message output taskq.  This action will
- *    get a capability message sent to the SC from the OS during boot
- *    scenarios.  A capability message exchange will also happen for
- *    SC reboot scenarios, as the SC will initiate a nodename update
- *    as a matter of course while coming back up.
- *
- *    We'll also get an extraneous capability message sent
- *    to the SC from time to time, but that won't hurt anything.
- */
-void
-scosmb_update_nodename(uint64_t transid)
-{
-	scosmb_msgdata_t	*msgdatap, *cap_msgdatap;
-
-	/*
-	 * If we're generating an unsolicited nodename update (presumably having
-	 * been called from platmod:plat_nodename_set()), there's no need to add
-	 * a new job to the queue if there is already one on it that will be
-	 * sending the latest nodename data.
-	 */
-	mutex_enter(&scosmb_mutex);
-	if (transid == 0) {
-		if (scosmb_nodename_event_pending) {
-			mutex_exit(&scosmb_mutex);
-			return;
-		} else {
-			scosmb_nodename_event_pending = TRUE;
-		}
-	}
-	mutex_exit(&scosmb_mutex);
-
-	/*
-	 * Allocate memory for the message data, initialize it, and place a new
-	 * job on the scosmb_output_taskq for SCDM_GET_NODENAME.
-	 */
-	msgdatap = (scosmb_msgdata_t *)kmem_zalloc(sizeof (scosmb_msgdata_t),
-	    KM_SLEEP);
-
-	msgdatap->type = (transid == 0) ? MBOXSC_MSG_EVENT : MBOXSC_MSG_REPLY;
-	msgdatap->cmd = SCDM_GET_NODENAME;
-	msgdatap->transid = transid;
-	msgdatap->log_error = 1;
-
-	(void) taskq_dispatch(scosmb_output_taskq,
-	    (task_func_t *)scosmb_process_output, msgdatap, KM_SLEEP);
-
-	/*
-	 * Next, allocate memory, initialize, and place a new job on the
-	 * scosmb_output_taskq for SCDM_LOG_ECC_CAP_INIT.  That's a
-	 * capability message, where we're the initiator.
-	 */
-	cap_msgdatap = kmem_zalloc(sizeof (scosmb_msgdata_t), KM_SLEEP);
-
-	cap_msgdatap->type = (transid == 0) ?
-	    MBOXSC_MSG_EVENT : MBOXSC_MSG_REPLY;
-	cap_msgdatap->cmd = SCDM_LOG_ECC_CAP_INIT;
-	cap_msgdatap->transid = transid;
-	cap_msgdatap->log_error = 1;
-
-	(void) taskq_dispatch(scosmb_output_taskq,
-	    (task_func_t *)scosmb_process_output, cap_msgdatap, KM_SLEEP);
-}
-
-/*
- * scosmb_log_ecc_error() - Record ECC error information to SC
- * For ECC error messages, send the messages through a taskq mechanism
- * to prevent impaired system performance during ECC floods.  Indictment
- * messages have already passed through a taskq, so directly call the
- * output function.
- */
-int
-scosmb_log_ecc_error(plat_ecc_message_type_t msg_type, void *datap)
-{
-	scosmb_msgdata_t	*msg_header_ptr;
-	uint32_t		msg_cmd, msg_length;
-	int			sleep_flag, log_error;
-	int			do_queue;	/* Set to 1 if taskq needed */
-
-	/*
-	 * Set header type and length for message
-	 */
-	switch (msg_type) {
-	case PLAT_ECC_ERROR_MESSAGE:
-		/*
-		 * We do not want to sleep in an error logging thread.  So,
-		 * we set the NOSLEEP flag and go through a taskq before we
-		 * send the message.
-		 */
-		msg_cmd = SCDM_LOG_ECC_ERROR;
-		msg_length = sizeof (plat_ecc_error_data_t);
-		sleep_flag = KM_NOSLEEP;
-		log_error = 1;
-		do_queue = 1;
-		break;
-	case PLAT_ECC_ERROR2_MESSAGE:
-		msg_cmd = SCDM_LOG_ECC;
-		msg_length = sizeof (plat_ecc_error2_data_t);
-		sleep_flag = KM_NOSLEEP;
-		log_error = 1;
-		do_queue = 1;
-		break;
-	case PLAT_ECC_INDICTMENT_MESSAGE:
-		/*
-		 * For indictment messages, we're allowed to sleep, and we
-		 * can directly call the output function, since we've already
-		 * gone through a taskq
-		 */
-		msg_cmd = SCDM_LOG_ECC_INDICTMENT;
-		msg_length = sizeof (plat_ecc_indictment_data_t);
-		sleep_flag = KM_SLEEP;
-		log_error = 0;
-		do_queue = 0;
-		break;
-	case PLAT_ECC_INDICTMENT2_MESSAGE:
-		/*
-		 * For indictment2 messages, we're allowed to sleep, and we
-		 * can directly call the output function, since we've already
-		 * gone through a taskq
-		 */
-		msg_cmd = SCDM_LOG_ECC;
-		msg_length = sizeof (plat_ecc_indictment2_data_t);
-		sleep_flag = KM_SLEEP;
-		log_error = 0;
-		do_queue = 0;
-		break;
-
-	case PLAT_ECC_DIMM_SID_MESSAGE:
-		/*
-		 * For DIMM sid request messages, we're allowed to sleep, and we
-		 * can directly call the output function, since we've already
-		 * gone through a taskq
-		 */
-		msg_cmd = SCDM_DIMM_SERIAL_ID;
-		msg_length = sizeof (plat_dimm_sid_request_data_t);
-		sleep_flag = KM_SLEEP;
-		log_error = 0;
-		do_queue = 0;
-		break;
-
-	default:
-		return (EINVAL);
-	}
-
-	/*
-	 * Allocate memory for the mailbox message header.
-	 */
-	msg_header_ptr =
-	    (scosmb_msgdata_t *)kmem_zalloc(sizeof (scosmb_msgdata_t),
-	    sleep_flag);
-
-	if (msg_header_ptr == NULL) {
-#ifdef DEBUG
-		cmn_err(CE_WARN, "failed to allocate space for scosmb "
-		    "message header.");
-#endif	/* DEBUG */
-		return (ENOMEM);
-	}
-
-	msg_header_ptr->type = MBOXSC_MSG_EVENT;
-	msg_header_ptr->cmd = msg_cmd;
-	msg_header_ptr->transid = 0;
-	msg_header_ptr->log_error = log_error;
-
-	/*
-	 * Allocate memory for the mailbox message payload.
-	 */
-	msg_header_ptr->length = msg_length;
-	msg_header_ptr->data = kmem_zalloc((size_t)msg_length, sleep_flag);
-
-	if (msg_header_ptr->data == NULL) {
-#ifdef DEBUG
-		cmn_err(CE_WARN, "failed to allocate space for scosmb "
-		    "message data.");
-#endif	/* DEBUG */
-		kmem_free(msg_header_ptr, sizeof (scosmb_msgdata_t));
-		return (ENOMEM);
-	}
-
-	bcopy(datap, msg_header_ptr->data, (size_t)msg_length);
-
-	/*
-	 * Based on our earlier look at the message type, we either go through
-	 * a taskq or directly call the output function.
-	 */
-	if (do_queue != 0) {
-		/*
-		 * Place a new job on the scosmb_output_taskq.
-		 */
-		if (taskq_dispatch(scosmb_output_taskq,
-		    (task_func_t *)scosmb_process_output,
-		    (void *)msg_header_ptr, TQ_NOSLEEP) == TASKQID_INVALID) {
-#ifdef DEBUG
-			cmn_err(CE_WARN, "failed to dispatch a task to send "
-			    "ECC mailbox message.");
-#endif	/* DEBUG */
-			kmem_free(msg_header_ptr->data, msg_header_ptr->length);
-			kmem_free(msg_header_ptr, sizeof (scosmb_msgdata_t));
-			return (ENOMEM);
-		}
-		return (0);
-	} else {
-		return (scosmb_process_output(msg_header_ptr));
-	}
-}
--- a/usr/src/uts/sun4u/starcat/iosram/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the production of the iosram driver module.
-#
-#	sun4u starcat 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		= iosram
-OBJECTS		= $(IOSRAM_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(IOSRAM_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_DRV_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Ndrv/axq
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/mboxsc/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#	This makefile drives the production of the mboxsc miscellaneous module.
-#
-#	sun4u starcat 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		= mboxsc
-OBJECTS		= $(MBOXSC_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(MBOXSC_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Ndrv/iosram
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/ml/drmach.il.cpp	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This 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 */
-
-#include <sys/sun4asi.h>
-#include <sys/privregs.h>
-#include <sys/cheetahregs.h>
-#include <sys/machparam.h>
-#include <sys/machthread.h>
-#include <sys/mmu.h>
-#include <sys/cheetahasm.h>
-
-#if defined(lint)
-
-/*ARGSUSED*/
-void
-bcopy32_il(uint64_t paddr1, uint64_t paddr2)
-{}
-
-void
-flush_dcache_il(void)
-{}
-
-void
-flush_icache_il(void)
-{}
-
-void
-flush_pcache_il(void)
-{}
-
-/*ARGSUSED*/
-void
-flush_ecache_il(uint64_t physaddr, uint_t size, uint_t linesz)
-{}
-
-#else /* lint */
-
-	!
-	! bcopy32_il
-	!
-	! input:
-	!	%o0	source PA
-	!	%o1	destination PA
-	!
-	! returns:
-	!	nothing
-	!
-	! A simple copy routine that copies 32 bytes using physical
-	! addresses. Used by drmach_copy_rename() to copy permanent
-	! memory. Assumes domain is quiesced and addresses are
-	! aligned appropriately.
-	!
-	! Derived from Starfire DR 2.6 version of bcopy32_il.
-	!
-	! NOTE: The rdpr instruction executes as a noop. It has no
-	! runtime value or purpose. It exists here solely for its
-	! magical property that protects bcopy32_il from the
-	! actions of Sun Pro's code generator. The ldxa instructions
-	! used in this inline are not supported by the inline feature
-	! of the Sun Pro 5.0 product. See inline(1) for details.
-	! Without the rdpr, the code generator improperly rewrites
-	! the instructions and emits a misrepresentation of the logic.
-	!
-	.inline bcopy32_il, 0
-	rdpr	%pstate, %g0		! See note.
-        ldxa    [%o0]ASI_MEM, %o2
-	add	%o0, 8, %o0
-        ldxa    [%o0]ASI_MEM, %o3
-	add	%o0, 8, %o0
-        ldxa    [%o0]ASI_MEM, %o4
-	add	%o0, 8, %o0
-        ldxa    [%o0]ASI_MEM, %o5
-	stxa    %o2, [%o1]ASI_MEM
-	add	%o1, 8, %o1
-	stxa    %o3, [%o1]ASI_MEM
-	add	%o1, 8, %o1
-	stxa    %o4, [%o1]ASI_MEM
-	add	%o1, 8, %o1
-	stxa    %o5, [%o1]ASI_MEM
-	.end
-
-	!
-	! flush_dcache_il
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	nothing
-	!
-	! Flushes data cache. Used by drmach_copy_rename() after
-	! the rename step to ensure the data cache tags and mtags
-	! are properly synchronized. Assumes domain is quiesced.
-	!
-	.inline	flush_dcache_il, 0
-	set	dcache_size, %o0
-	ld	[%o0], %o0
-	set	dcache_linesize, %o1
-	ld	[%o1], %o1
-	CH_DCACHE_FLUSHALL(%o0, %o1, %o2)
-	.end
-
-	!
-	! flush_icache_il
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	nothing
-	!
-	! Flushes instruction cache. Used by drmach_copy_rename()
-	! after the rename step to ensure the instruction cache tags
-	! and mtags are properly synchronized. Assumes domain is
-	! quiesced.
-	!
-	! Panther has a larger Icache compared to Cheetahplus or Jaguar.
-	!
-	.inline flush_icache_il, 0
-	GET_CPU_IMPL(%o0)
-	cmp	%o0, PANTHER_IMPL
-	bne	%xcc, 1f
-	  nop
-	set	PN_ICACHE_SIZE, %o0
-	set	PN_ICACHE_LSIZE, %o1
-	ba	2f
-	  nop
-1:
-	set	CH_ICACHE_SIZE, %o0
-	set	CH_ICACHE_LSIZE, %o1
-2:
-	CH_ICACHE_FLUSHALL(%o0, %o1, %o2, %o3)
-	.end
-
-	!
-	! flush_pcache_il
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	nothing
-	!
-	! Flushes prefetch cache. Used by drmach_copy_rename() after
-	! the rename step to ensure the prefetch cache tags and mtags
-	! are properly synchronized. Assumes domain is quiesced.
-	!
-	.inline	flush_pcache_il, 0
-	PCACHE_FLUSHALL(%o1, %o2, %o3)
-	.end
-
-	!
-	! flush_ecache_il
-	!
-	! input:
-	!	%o0	PA of flush span
-	!	%o1	size of this processor's E$
-	!	%o2	line size of this processor's E$
-	!
-	! output:
-	!	nothing
-	!
-	! Flushes external cache. Used by drmach_copy_rename() after
-	! the rename step to ensure the external cache tags and mtags
-	! are properly synchronized. Assumes domain is quiesced.
-	!
-	! Panther needs to flush L2 cache before L3 cache.
-	!
-	.inline flush_ecache_il, 0
-        PN_L2_FLUSHALL(%o3, %o4, %o5)
-	ECACHE_FLUSHALL(%o1, %o2, %o0, %o3)
-	.end
-
-#endif /* lint */
-
--- a/usr/src/uts/sun4u/starcat/ml/drmach_asm.s	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,975 +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 file is through cpp before being used as
- * an inline.  It contains support routines used
- * only by DR.
- */
-
-#if defined(lint)
-#include <sys/types.h>
-#else
-#include "assym.h"
-#endif /* lint */
-
-#include <sys/asm_linkage.h>
-#include <sys/clock.h>
-#include <sys/param.h>
-#include <sys/privregs.h>
-#include <sys/machasi.h>
-#include <sys/mmu.h>
-#include <sys/machthread.h>
-#include <sys/pte.h>
-#include <sys/stack.h>
-#include <sys/vis.h>
-#include <sys/cheetahregs.h>
-#include <sys/cmpregs.h>
-#include <sys/intreg.h>
-#include <sys/cheetahasm.h>
-
-#if defined(lint)
-
-/*ARGSUSED*/
-void
-drmach_shutdown_asm(uint64_t estack, uint64_t flushaddr,
-    int size, int lsz, uint64_t physmem)
-{}
-
-/*ARGSUSED*/
-void
-drmach_rename(uint64_t *script, uint_t *err, uint64_t *id)
-{}
-
-void
-drmach_rename_end(void)
-{}
-
-/*ARGSUSED*/
-void
-drmach_rename_wait(uint64_t not_used_0, uint64_t not_used_1)
-{
-}
-
-/*ARGSUSED*/
-void
-drmach_rename_done(uint64_t not_used_0, uint64_t not_used_1)
-{
-}
-
-/*ARGSUSED*/
-void
-drmach_rename_abort(uint64_t not_used_0, uint64_t not_used_1)
-{
-}
-
-/*ARGSUSED*/
-uint64_t
-lddsafconfig(void)
-{
-	return (0x0ull);
-}
-
-/* ARGSUSED */
-uint32_t
-drmach_bc_bzero(void *addr, size_t size)
-{
-	return (0x0);
-}
-
-#else /* lint */
-
-#define BUS_SYNC(reg1, reg2)					\
-1:								;\
-	ldx	[reg1], reg2					;\
-	brz,pn	reg2, 2f					;\
-	add	reg1, 8, reg1					;\
-	ldxa	[reg2]ASI_MEM, %g0				;\
-	ba,a	1b						;\
-	nop							;\
-2:
-
-#define LOAD_MB(cpuid, mb_data, reg1)				\
-	set	drmach_xt_mb, reg1				;\
-	ldx	[reg1], reg1					;\
-	add	reg1, cpuid, reg1				;\
-	ldub	[reg1], mb_data					;\
-	stub	%g0, [reg1]
-
-#define LPA_MASK 0x7ff8
-
-#define SET_LPA(cmd, reg1, reg2)				\
-	btst	0x80, cmd					;\
-	bz	2f						;\
-	nop							;\
-	btst	0x40, cmd					;\
-	bnz,a	1f						;\
-	mov	%g0, cmd					;\
-	and	cmd, 0x1f, cmd					;\
-	sllx	cmd, 3, reg1					;\
-	add	cmd, 1, cmd					;\
-	sllx	cmd, 9, cmd					;\
-	or	cmd, reg1, cmd					;\
-1:								;\
-	set	LPA_MASK, reg2					;\
-	ldxa	[%g0]ASI_SAFARI_CONFIG, reg1			;\
-	and	cmd, reg2, cmd					;\
-	andn	reg1, reg2, reg1				;\
-	or	reg1, cmd, reg1					;\
-	stxa	reg1, [%g0]ASI_SAFARI_CONFIG			;\
-	membar	#Sync						;\
-2:								;\
-
-#define SET_NULL_LPA(reg1, reg2)				\
-	set	LPA_MASK, reg2					;\
-	ldxa	[%g0]ASI_SAFARI_CONFIG, reg1			;\
-	andn	reg1, reg2, reg1				;\
-	stxa	reg1, [%g0]ASI_SAFARI_CONFIG			;\
-	membar	#Sync						;\
-
-	! ATOMIC_ADD_LONG
-	! This code is run at TL > 0, being exec'd via a cross trap.
-	! While running at trap level > 0, all memory accesses are
-	! performed using NUCLEUS context, which is always 0.
-	! Since the cross trap handler does not force PRIMARY context
-	! to be zero, the following casxa instruction must specify
-	! NUCLEUS ASI.
-	! This ASI must be specified explicitly (via casxa), rather
-	! than using casx. This is because of the fact that the
-	! default casx specifies ASI_PRIMARY, which if non-zero, can
-	! prevent the cpu from translating the address, leading to panic
-	! on bad trap following repetitive dtlb misses.  This behavior
-	! was encountered on MCPUs when using casx instruction.
-#define ATOMIC_ADD_LONG(label, simm, reg1, reg2, reg3)		\
-	set	label, reg1					;\
-	ldx	[reg1], reg2					;\
-1:								;\
-	add	reg2, simm, reg3				;\
-	casxa	[reg1]ASI_N, reg2, reg3				;\
-	cmp	reg2, reg3					;\
-	bne,a,pn %xcc, 1b					;\
-	ldx	[reg1], reg2
-
-#define HERE(reg1, simm, reg2)					\
-	rdpr	%tick, reg2					;\
-	stx	reg2, [reg1 + simm]
-
-	!
-	! Returns processor icache size and linesize in reg1 and
-	! reg2, respectively.
-	!
-	! Panther has a larger icache compared to Cheetahplus and
-	! Jaguar.
-	!
-#define	GET_ICACHE_PARAMS(reg1, reg2)				\
-	GET_CPU_IMPL(reg1)					;\
-	cmp	reg1, PANTHER_IMPL				;\
-	bne	%xcc, 1f					;\
-	  nop							;\
-	set	PN_ICACHE_SIZE, reg1				;\
-	set	PN_ICACHE_LSIZE, reg2				;\
-	ba	2f						;\
-	  nop							;\
-1:								;\
-	set	CH_ICACHE_SIZE, reg1				;\
-	set	CH_ICACHE_LSIZE, reg2				;\
-2:
-
-#define	DRMACH_MCU_IDLE_READS	3
-
-	! Macro to check if a Panther MC is idle.  The EMU Activity
-	! Status register is first read to clear the MCU status bit.
-	! The MCU status is then checked DRMACH_MCU_IDLE_READS times
-	! to verify the MCU is indeed idle.  A single non-idle status
-	! will fail the idle check.  This could be made more lenient
-	! by adding a retry loop.
-	!	addr:	Panther EMU Activity Status register read address.
-	!		Assumed to be 0x18 for local ASI access or else
-	!		FIREPLANE_ADDRESS_REG + 0x400050 for PIO access.
-	!		0 is returned in this register if MCU is idle and
-	!		queues are empty.  Otherwise, -1 is returned in this
-	!		register.
-	!	asi:	Immediate asi value.  Assumed to be ASI_SAFARI_CONFIG
-	!		for local ASI or ASI_IO for PIO access.
-	!	scr1:	Scratch 
-	!	scr2:	Scratch 
-	!
-#define	CHECK_MCU_IDLE(addr, asi, scr1, scr2)			\
-	ldxa	[addr]asi, %g0					;\
-	ba	1f						;\
-	  clr	scr2						;\
-0:								;\
-	btst	MCU_ACT_STATUS, scr1				;\
-	bne,a	2f						;\
-	  sub	%g0, 1, addr					;\
-	inc	scr2						;\
-1:								;\
-	cmp	scr2, DRMACH_MCU_IDLE_READS			;\
-	ble,a	0b						;\
-	  ldxa    [addr]asi, scr1				;\
-	clr	addr						;\
-2:
-
-	! drmach_shutdown_asm
-	!
-	! inputs:
-	!	%o0 = stack pointer
-	!	%o1 = ecache flush address (ignored if cheetah+ processor)
-	!	%o2 = ecache size
-	!	%o3 = ecache line size
-	!	%o4 = phys addr of byte to clear when finished
-	!
-	! output:
-	!	Stores a zero at [%o4]ASI_MEM when the processor
-	!	is ready to be removed from domain coherency.
-	!
-	ENTRY_NP(drmach_shutdown_asm)
-	membar	#LoadStore		! parsley.
-
-	! Calculate pointer to data area. Determine size of
-	! drmach_shutdown_asm, add to base address and align
-	! to next 16 byte boundary. Leave result in %g6.
-	set	drmach_shutdown_asm_end, %g6
-	set	drmach_shutdown_asm, %g1
-	set	drmach_cpu_sram_va, %g2
-	ldx	[%g2], %g2
-	sub	%g6, %g1, %g6
-	add	%g6, %g2, %g6
-	add	%g6, 15, %g6
-	andn	%g6, 15, %g6
-	
-	! Save parameters
-	stx	%o0, [%g6 + 0]		! save stack pointer
-	stx	%o1, [%g6 + 24]		! save E$ flush PA
-	st	%o2, [%g6 + 32]		! save E$ size
-	st	%o3, [%g6 + 36]		! save E$ linesize
-	stx	%o4, [%g6 + 40]		! save phys addr of signal byte
-
-	set	dcache_size, %g1
-	ld	[%g1], %g1
-	st	%g1, [%g6 + 8]		! save dcache_size
-	set	dcache_linesize, %g1
-	ld	[%g1], %g1
-	st	%g1, [%g6 + 12]		! save dcache_linesize
-
-	GET_ICACHE_PARAMS(%g1, %g2)
-	st	%g1, [%g6 + 16]		! save icache_size
-	st	%g2, [%g6 + 20]		! save icache_linesize
-
-	! Flushes all active windows except the current one.
-	! Can cause spill traps to occur.
-	flushw
-
-	! Make sure all asynchronous processing is complete.
-	! Note: has no implications on pending bus transactions.
-	membar	#Sync
-
-	! Move stack. Algorithm copied from t0stacktop setup of
-	! %sp in sun4u/ml/locore.s
-	! Replaces SWITCH_STACK() macro used in Starfire DR.
-	ldx	[%g6 + 0], %g1
-	sub	%g1, SA(KFPUSIZE+GSR_SIZE), %g2
- 	and	%g2, 0x3f, %g3
- 	sub	%g2, %g3, %o2
- 	sub	%o2, SA(MPCBSIZE) + STACK_BIAS, %sp
-	stx	%sp, [%g6 + 48]		! for debug
-
-	HERE(%g6, 128, %g1)		! initialization complete (for debug)
-
-	! Panther needs to flush the L2 cache before the L3
-	! cache is flushed by the ecache flushall macro.
-	PN_L2_FLUSHALL(%g1, %g2, %g3)
-	
-	! Flush E$. The purpose of this flush is to rid the E$ of
-	! lines in states O or Os. Implicitly flushes W$.
-	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
-	ld	[%g6 + 32], %g2		! ecache_size
-	ld	[%g6 + 36], %g3		! ecache_linesize
-	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
-
-	! Since the bus sync list read below does not guarantee
-	! transaction completion on Panther domains, as an
-	! optimization Panther skips the read and subsequent
-	! E$ flush.
-	GET_CPU_IMPL(%g1)
-	cmp	%g1, PANTHER_IMPL
-	be	%xcc, drmach_shutdown_ecache_flushed
-	  nop
-
-	!
-	! Ensure all outstanding writebacks have retired.  Following this
-	! sync, all writes must be strictly managed.
-	! 
-	set	drmach_bus_sync_list, %g1
-	BUS_SYNC(%g1, %g2)
-
-	! Flush E$ again to victimize references to drmach_bus_sync_list.
-	ldx     [%g6 + 24], %g1         ! *ecache_flushaddr
-	ld	[%g6 + 32], %g2		! ecache_size
-	ld	[%g6 + 36], %g3		! ecache_linesize
-	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
-
-drmach_shutdown_ecache_flushed:
-
-	ld	[%g6 + 8], %g1		! flush dcache
-	ld	[%g6 + 12], %g2
-	CH_DCACHE_FLUSHALL(%g1, %g2, %g3)
-
-	ld	[%g6 + 16], %g1		! flush icache
-	ld	[%g6 + 20], %g2
-	CH_ICACHE_FLUSHALL(%g1, %g2, %g3, %g4)
-
-	PCACHE_FLUSHALL(%g1, %g2, %g3) ! flush pcache (no parameters)
-
-	!
-	! Flush all unlocked dtlb and itlb entries.
-	! Replaces TLB_FLUSH_UNLOCKED macro used in Starfire DR.
-	!
-	sethi	%hi(FLUSH_ADDR), %g1
-	set	DEMAP_ALL_TYPE, %g2
-	stxa	%g0, [%g2]ASI_DTLB_DEMAP
-	stxa	%g0, [%g2]ASI_ITLB_DEMAP
-	flush	%g1
-
-	!
-	! Zero LPA by clearing CBASE and CBND. Following
-	! this, all transactions to cachable address space
-	! will be of the remote flavor.
-	!
-	SET_NULL_LPA(%g1, %g2)
-
-	HERE(%g6, 136, %g1)		! preparation complete (for debug)
-
-	!
-	! Clear byte to signal finished.
-	! NOTE: This store will allocate in the E$. It is
-	! vitally important that this line is demoted to
-	! state I before removing this processor from the
-	! coherency.  The demotion is ensured by a synchronous
-	! "steal back" that takes place in drmach_cpu_poweroff.
-	ldx	[%g6 + 40], %g1
-	stba	%g0, [%g1]ASI_MEM
-5:
-	HERE(%g6, 144, %g1)		! spin indicator (for debug)
-	ba	5b
-	  nop
-
-	.asciz	"drmach_shutdown_asm"		! for debug
-	.align	4
-	.global	drmach_shutdown_asm_end
-drmach_shutdown_asm_end:
-	SET_SIZE(drmach_shutdown_asm)
-
-
-	! lddsafconfig
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	%o0	content of this processor's SCR
-	!
-	!	Returns current value of this processor's Safari
-	!	Configuration Register.
-	!
-	ENTRY(lddsafconfig)
-        retl
-        ldxa    [%g0]ASI_SAFARI_CONFIG, %o0
-        SET_SIZE(lddsafconfig)
-
-	! drmach_rename
-	!
-	! input:
-	!	%o0	pointer to register address/value compound list
-	!	%o1	address for setting error code if rename did not
-	!		complete.  Unmodified if no error.
-	!	%o2	address for returning opaque memory controller id
-	!		in case of error.  Unmodified if no error.
-	!	Global	drmach_xt_mb[cpuid] is expected to be the new LPA.
-	!
-	! output:
-	!	[%o1] =	1 if failed to idle memory controller, otherwise unmodified.
-	!	[%o2] = id of failed memory controller, otherwise unmodified.
-	!
-	! Perform HW register reprogramming. This is the "rename" step for
-	! the copy-rename process.  drmach_rename is copied to a cpu's sram
-	! followed by register address/value pairs -- the text and data are
-	! sourced from the sram while drmach_rename is executed.
-	!
-	! The parameter is assumed to point to a concatenation of six
-	! zero-terminated lists located in non-cachable storage. The assumed
-	! format (and purpose) of each list is as follows:
-	!
-	!	1) a copy of drmach_bus_sync_list. A list of PA for each
-	!	   active memory bank in the domain. Used to infer the
-	!	   the completion of all pending coherent transactions
-	!	   initiated by this processor. Assumes MC work queue
-	!	   does not implement read bypass. This is true of Cheetah,
-	!	   Cheetah+, and Jaguar processors.  Panther does support
-	!	   read bypass, so for Panther MCs with read-bypass-write
-	!	   enabled, the read is issued but it does not guarantee
-	!	   completion of outstanding writes in the MC queue.  
-	!	2) address/id pair for the local Panther EMU Activity Status
-	!	   Register of this processor.  The register address is assumed
-	!	   to be a VA which is polled via ASI_SAFARI_CONFIG until the
-	!	   MC queues are empty.  The id is an opaque identifier which
-	!	   must be returned along with an error code if the MCU status
-	!	   does not go idle.  See the parameter description above.
-	!	   This section will be empty if this processor is not a Panther.
-	!	   Both the address and id are assumed to be 64 bit values.
-	!	3) address/id pairs for non-local Panther EMU Activity Status
-	!	   Registers on other source and target processors.  The register
-	!	   address is assumed to be a PIO address which is polled via
-	!	   ASI_IO to drain/idle the MCs on other Panther procs.  The
-	!	   id is an opaque identifier which must be returned along with
-	!	   an error code if a MC fails to go idle.  This section will
-	!	   empty if there are no non-local Panther processors on the
-	!	   source and target expanders.  Both the address and id are
-	!	   assumed to be 64 bit values.
-	!	4) address/value pairs for the Memory Address Decoder
-	!	   register of this processor. The register address is
-	!	   assumed to be a VA within ASM_MC_DECODE space. The
-	!	   address and value elements are assumed to 64 bit values.
-	!	5) address/value pairs for any 64 bit register accessible
-	!	   via ASI_IO. The address and value fields are assumed to
-	!	   be 64 bit values.
-	!	   This list is typically used for reprogramming the Memory
-	!	   Address Decoder Register of other cpus and for reprogram-
-	!	   ming the Safari Configuration Register of I/O controllers.
-	!	6) address/value pairs for any 32 bit register accessible
-	!	   via ASI_IO. The address element is assumed to be a 64 bit
-	!	   value. The value element is assumed to be a 64 bit word
-	!	   containing a 32 bit value in the lower half.
-	!	   This list typically contains address/value pairs for
-	!	   AXQ CASM tables.
-	!
-	ENTRY_NP(drmach_rename)
-
-	mov	%o1, %o4		! save error code address
-	mov	%o2, %o5		! save error id address
-
-	BUS_SYNC(%o0, %o1)		! run section 1
-
-	SET_NULL_LPA(%o1, %o2)		! prep for cachable transactions
-					! after rename completes.
-					! e.g.: the load_mb that occurs below
-3:
-	ldx	[%o0], %o1		! run section 2
-	brz,a,pn %o1, 4f
-	add	%o0, 8, %o0		! skip section 2 terminator
-	CHECK_MCU_IDLE(%o1, ASI_SAFARI_CONFIG, %o2, %o3)
-	cmp	%o1, 0			! idled?
-	be,a	3b			! ok, advance
-	  add	%o0, 16, %o0
-	mov	1, %o1			! not idle, bailout
-	stw	%o1, [%o4]		! set MC idle error code
-	ldx	[%o0 + 8], %o1
-	stx	%o1, [%o5]		! set MC idle error id
-	retl
-	  nop
-4:
-	ldx	[%o0], %o1		! run section 3
-	brz,a,pn %o1, 5f
-	add	%o0, 8, %o0		! skip section 3 terminator
-	CHECK_MCU_IDLE(%o1, ASI_IO, %o2, %o3)
-	cmp	%o1, 0			! idled?
-	be,a	4b			! ok, advance
-	  add	%o0, 16, %o0
-	mov	1, %o1			! not idle, bailout
-	stw	%o1, [%o4]		! set MC idle error code
-	ldx	[%o0 + 8], %o1
-	stx	%o1, [%o5]		! set MC idle error id
-	retl
-	  nop
-5:
-	ldx	[%o0], %o1		! run section 4
-	brz,a,pn %o1, 6f
-	add	%o0, 8, %o0		! skip section 4 terminator
-	ldx	[%o0 + 8], %o2
-	stxa	%o2, [%o1]ASI_MC_DECODE
-	membar	#Sync
-	ldxa	[%o1]ASI_MC_DECODE, %g0	! read back to insure written
-	b	5b
-	add	%o0, 16, %o0
-6:
-	ldx	[%o0], %o1		! run section 5
-	brz,a,pn %o1, 7f
-	add	%o0, 8, %o0		! skip section 5 terminator
-	ldx	[%o0 + 8], %o2
-	stxa	%o2, [%o1]ASI_IO
-	ldxa	[%o1]ASI_IO, %g0	! read back to insure written
-	b	6b
-	add	%o0, 16, %o0
-7:
-	ldx	[%o0], %o1		! run section 6
-	brz,a,pn %o1, 8f
-	nop
-	ldx	[%o0 + 8], %o2
-	stwa	%o2, [%o1]ASI_IO
-	lduwa	[%o1]ASI_IO, %g0	! read back to insure written
-	b	7b
-	add	%o0, 16, %o0
-8:
-	CPU_INDEX(%o0, %o1)
-	LOAD_MB(%o0, %o1, %o2)
-	SET_LPA(%o1, %o0, %o2)
-
-	retl
-	nop
-
-	.asciz	"drmach_rename"		! for debug
-	.align	4
-	SET_SIZE(drmach_rename)
-
-	.global drmach_rename_end
-drmach_rename_end:
-
-
-	! drmach_rename_wait
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	nothing
-	!
-	! drmach_rename_wait is a cross-trap function used to move a
-	! cpu's execution out of coherent space while a copy-rename
-	! operation is in progress.
-	!
-	! In each CPU SRAM exists an area (16KB on Cheetah+ boards,
-	! 32KB on Jaguar/Panther boards) reserved for DR. This area is
-	! logically divided by DR into 8KB pages, one page per CPU (or
-	! core) in a port pair. (Two Safari ports share HW resources on
-	! a CPU/MEM board. These are referred to as a port pair.) 
-	!
-	! This routine begins by mapping the appropriate SRAM page,
-	! transferring the machine code (between the labels
-	! drmach_rename_wait_asm and drmach_rename_wait_asm_end), then
-	! jumping to SRAM.  After returning from SRAM, the page is
-	! demapped before the cross-call is exited (sic).
-	!
-	! The machine code flushes all caches, waits for a special
-	! interrupt vector, then updates the processor's LPA and
-	! resynchronizes caches with the new home memory.
-	!
-	! The special interrupt vector is assumed to be a cross-call to
-	! drmach_rename_done sent by the master processor upon completing
-	! the copy-rename operation. The interrupt is received and discarded;
-	! The cross-call to drmach_rename_done is never executed.  Instead
-	! the Interrupt Receive Status Register is employed, temporarily,
-	! as a semaphore. This avoids unwanted bus traffic during the critical
-	! rename operation.
-	!
-	ENTRY_NP(drmach_rename_wait)
-
-	CPU_INDEX(%g5, %g1)		! put cpuid in %g5
-
-	!
-	! sfmmu_dtlb_ld(drmach_cpu_sram_va,
-	!	KCONTEXT, drmach_cpu_sram_tte[cpuid]);
-	! sfmmu_itlb_ld(drmach_cpu_sram_va,
-	!	KCONTEXT, drmach_cpu_sram_tte[cpuid]);
-	!
-	set	drmach_cpu_sram_tte, %g1
-	sllx	%g5, 3, %g2
-	ldx	[%g1 + %g2], %g3
-	set	drmach_cpu_sram_va, %g1
-	ldx	[%g1], %g1
-	or	%g1, KCONTEXT, %g2	! preserve %g1
-	set	MMU_TAG_ACCESS, %g4
-	set	cpu_impl_dual_pgsz, %g6 
-	ld      [%g6], %g6 
-	brz	%g6, 1f
-	  nop
-	
-	sethi	%hi(ksfmmup), %g6
-	ldx	[%g6 + %lo(ksfmmup)], %g6
-	ldub    [%g6 + SFMMU_CEXT], %g6
-        sll     %g6, TAGACCEXT_SHIFT, %g6
-
-	set	MMU_TAG_ACCESS_EXT, %g7
-	stxa	%g6, [%g7]ASI_DMMU
-1:
-	stxa	%g2, [%g4]ASI_DMMU
-	stxa    %g3, [%g0]ASI_DTLB_IN
-	membar	#Sync
-	sethi	%hi(FLUSH_ADDR), %g6
-	stxa	%g2, [%g4]ASI_IMMU
-	stxa    %g3, [%g0]ASI_ITLB_IN
-	flush	%g6
-
-	!
-	! copy drmach_rename_wait_asm block to SRAM. Preserve entry
-	! point in %g1. After the code has been copied, align %g6
-	! (the destination pointer) to the next highest 16 byte
-	! boundary. This will define the start of the data area.
-	!
-	mov	%g1, %g6
-	set	drmach_rename_wait_asm, %g2
-	set	drmach_rename_wait_asm_end, %g3
-0:
-	lduw	[%g2], %g4		! do copy
-	stw	%g4, [%g6]
-	add	%g2, 4, %g2
-	cmp	%g2, %g3
-	bne	0b
-	add	%g6, 4, %g6
-	
-	add	%g6, 15, %g6		! locate data area on next 16 byte
-	andn	%g6, 15, %g6		! boundary following text
-					! WARNING: no bounds checking
-
-	jmpl	%g1, %g7		! jump to code in cpu sram
-	nop
-
-	set	drmach_cpu_sram_va, %g1	! vtab_flushpage_tl1(drmach_cpu_sram_va,
-	ldx	[%g1], %g1		! 	KCONTEXT);
-	set	KCONTEXT, %g2
-	set	MMU_PCONTEXT, %g4
-	or	%g1, DEMAP_PRIMARY | DEMAP_PAGE_TYPE, %g1
-	ldxa	[%g4]ASI_DMMU, %g5	/* rd old ctxnum */
-	stxa	%g2, [%g4]ASI_DMMU	/* wr new ctxum */
-	stxa	%g0, [%g1]ASI_DTLB_DEMAP
-	stxa	%g0, [%g1]ASI_ITLB_DEMAP
-	stxa	%g5, [%g4]ASI_DMMU	/* restore old ctxnum */
-
-	retry
-
-drmach_rename_wait_asm:
-	! the following code is copied to a cpu's sram and executed
-	! from there.
-	! Input:
-	!	%g5 is cpuid
-	!	%g6 is data area (follows text)
-	!	%g7 is link address back to caller
-	!
-	st	%g5, [%g6 + 4]		! save cpuid (for debug)
-
-	set	dcache_size, %g1
-	ld	[%g1], %g1
-	st	%g1, [%g6 + 8]		! save dcache_size
-	set	dcache_linesize, %g1
-	ld	[%g1], %g1
-	st	%g1, [%g6 + 12]		! save dcache_linesize
-
-	GET_ICACHE_PARAMS(%g1, %g2)
-	st	%g1, [%g6 + 16]		! save icache_size
-	st	%g2, [%g6 + 20]		! save icache_linesize
-
-	set	drmach_iocage_paddr, %g1
-	ldx	[%g1], %g1
-	stx	%g1, [%g6 + 24]		! save *ecache_flushadr
-
-	mulx	%g5, CPU_NODE_SIZE, %g1	! %g4 = &cpunodes[cpuid]
-	set	cpunodes, %g4
-	add	%g4, %g1, %g4
-	ld	[%g4 + ECACHE_SIZE], %g1
-	st	%g1, [%g6 + 32]		! save ecache_size
-	ld	[%g4 + ECACHE_LINESIZE], %g1
-	st	%g1, [%g6 + 36]		! save ecache_linesize
-
-	LOAD_MB(%g5, %g1, %g2)		! save mailbox data
-	stb	%g1, [%g6 + 40]
-
-	membar	#Sync			! Complete any pending processing.
-
-	! Flush E$. The purpose of this flush is to rid the E$ of
-	! lines in states O or Os. Implicitly flushes W$.
-	! NOTE: Reading the bus sync list and r/w ops on drmach_xt_ready
-	! will disturb the E$. The lines of the bus sync list will be
-	! in state S. The line containing drmach_xt_ready will be in
-	! state O. Before proceeding with the copy-rename, the master
-	! processor will "steal back" the drmach_xt_ready (sic) line.
-	! This will demote the state of the line in E$ to I.
-	! However, the lines containing the bus sync list must be
-	! victimized before returning to the OS. This is vital because
-	! following copy-rename the corresponding lines in the new home
-	! memory will be in state gM. The resulting S,gM state pair is
-	! invalid and does represent a loss of coherency. Flushing the
-	! E$ after the bus sync list is read will be sufficient to
-	! avoid the invalid condition.
-	!
-	! For Panther, there is redundancy as both cores flush the shared
-	! L2 and L3 caches.  As an optimization, only one core could do the
-	! flush of the shared caches, however care must be taken that the
-	! sibling core does not install owned lines once the flush begins.
-	PN_L2_FLUSHALL(%g1, %g2, %g3)
-	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
-	ld	[%g6 + 32], %g2		! ecache_size
-	ld	[%g6 + 36], %g3		! ecache_linesize
-	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
-
-	! Make sure all outstanding transactions for this processor
-	! have retired. See E$ note above.
-	set	drmach_bus_sync_list, %g1
-	BUS_SYNC(%g1, %g2)
-
-	HERE(%g6, 128, %g4)		! preparation complete (for debug)
-
-	! Signal this processor is ready for rename operation to begin.
-	! See E$ note above.
-	ATOMIC_ADD_LONG(drmach_xt_ready, 1, %g2, %g3, %g4)
-
-	! Loop on IRSR waiting for interrupt. The expected interrupt
-	! is a cross-trap to drmach_wait_done. It is sent by the master
-	! processor when the copy-rename operation is complete. The
-	! received cross-trap is used only as a signal. It is not executed.
-2:
-	HERE(%g6, 136, %g4)		! last poll tick (for debug)
-
-	ldxa	[%g0]ASI_INTR_RECEIVE_STATUS, %g4	! wait for xt
-	btst	IRSR_BUSY, %g4
-	bz	2b
-	nop
-	stx	%g4, [%g6 + 64]		! save status and payload
-	set	IRDR_0, %g2
-	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
-	stx	%g2, [%g6 + 72]
-	set	IRDR_1, %g2
-	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
-	stx	%g2, [%g6 + 80]
-	set	IRDR_2, %g2
-	ldxa	[%g2]ASI_INTR_RECEIVE, %g2
-	stx	%g2, [%g6 + 88]
-
-					! clear rcv status
-	stxa	%g0, [%g0]ASI_INTR_RECEIVE_STATUS
-	membar	#Sync
-
-	HERE(%g6, 144, %g4)		! signal rcvd tick (for debug)
-
-	! Check for copy-rename abort signal. If this signal is received,
-	! the LPA change is skipped since the rename step was not done.
-	! The cache flushes are still done as paranoia.
-	set	drmach_rename_abort, %g1
-	ldx	[%g6 + 72], %g2
-	cmp 	%g1, %g2
-	be	3f
-	nop
-
-	! Resume waiting if this is not drmach_rename_done.
-	set	drmach_rename_done, %g1
-	cmp 	%g1, %g2
-	bne	2b
-	nop
-
-	ldub	[%g6 + 40], %g1		! get saved mailbox data
-	SET_LPA(%g1, %g2, %g3)		! set LPA as indicated by the mb data
-
-3:
-	! Flush all caches (E, D, I and P) to ensure each is resynchronized
-	! with the corresponding states in the new home memory. (W$ is
-	! implicitly flushed when the E$ is flushed.)
-	!
-	! Panther needs to flush the L2 cache before the L3
-	! cache is flushed by the ecache flushall macro.
-	PN_L2_FLUSHALL(%g1, %g2, %g3)
-
-	ldx	[%g6 + 24], %g1		! *ecache_flushaddr
-	ld	[%g6 + 32], %g2		! ecache_size
-	ld	[%g6 + 36], %g3		! ecache_linesize
-	ECACHE_FLUSHALL(%g2, %g3, %g1, %g4)
-
-	ld	[%g6 + 8], %g1		! flush dcache
-	ld	[%g6 + 12], %g2
-	CH_DCACHE_FLUSHALL(%g1, %g2, %g3)
-
-	ld	[%g6 + 16], %g1		! flush icache
-	ld	[%g6 + 20], %g2
-	CH_ICACHE_FLUSHALL(%g1, %g2, %g3, %g4)
-
-	PCACHE_FLUSHALL(%g1, %g2, %g3)	! flush pcache (no parameters)
-
-	HERE(%g6, 152, %g4)		! done tick (for debug)
-
-	jmpl	%g7+8, %g0
-	nop
-
-	.asciz	"drmach_rename_wait"	! for debug
-	.align	4
-drmach_rename_wait_asm_end:
-	SET_SIZE(drmach_rename_wait)
-
-
-	! drmach_rename_done
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	nothing
-	!
-	! Used as signal data. See drmach_rename_wait.
-	!
-	ENTRY_NP(drmach_rename_done)
-	retry
-	SET_SIZE(drmach_rename_done)
-
-	! drmach_rename_abort
-	!
-	! input:
-	!	nothing
-	!
-	! output:
-	!	nothing
-	!
-	! Used as signal data. See drmach_rename_wait.
-	!
-	ENTRY_NP(drmach_rename_abort)
-	retry
-	SET_SIZE(drmach_rename_abort)
-
-
-	! drmach_set_lpa
-	!
-	! input:
-	!	Globals: drmach_xt_mb[cpuid] contains new LPA data
-	!
-	! output:
-	!	nothing
-	!
-	! Sets the executing processor's LPA as indicated by the command
-	! stored in drmach_xt_mb, a byte array indexed by cpuid. Assumes
-	! the caller is preventing illegal LPA settings and transistions.
-	!
-	ENTRY_NP(drmach_set_lpa)
-
-	!
-	! Set %g1 to this processor's cpuid.
-	!
-	CPU_INDEX(%g1, %g2)
-
-	!
-	! Get LPA message from mailbox, leave in %g5.
-	!
-	LOAD_MB(%g1, %g5, %g2)
-
-	!
-	! Set LPA, mailbox data in %g5.
-	!
-	SET_LPA(%g5, %g1, %g2)
-
-	!
-	! Signal work is done.
-	!
-	ATOMIC_ADD_LONG(drmach_xt_ready, 1, %g1, %g2, %g3)
-
-	retry
-	SET_SIZE(drmach_set_lpa)
-
-!
-! drmach_bc_bzero
-!
-! inputs:
-! 	%o0 = base vaddr of area to clear (must be 64-byte aligned)
-!	%o1 = size of area to clear (must be multiple of 256 bytes)
-!
-! outputs:
-!	%o0 =
-!		0 (success)
-!		1 (size too small or not modulo 256)
-!		2 (vaddr not 64-byte aligned)
-!
-! Zero a block of storage using block commit stores.
-! Nonzero return if caller's address or size are not
-! block aligned.
-!
-
-
-	ENTRY(drmach_bc_bzero)
-
-	! verify size is >= 256 bytes
-	cmp	%o1, 256
-	blu,a	.bz_done
-	mov	1, %o0			! error code 1 for invalid size
-
-	! verify size is a multiple of 256
-	btst	(256-1), %o1
-	bnz,a	.bz_done
-	mov	1, %o0			! error code 1 for invalid size
-
-	! verify that vaddr is aligned for block stores
-	btst	(64-1), %o0
-	bnz,a	.bz_done
-	mov	2, %o0			! error code 2 for invalid alignment
-
-	! save fprs for restore when finished
-	rd	%fprs, %g1
-
-	! make sure FPU is enabled
-	rdpr	%pstate, %g3
-	btst	PSTATE_PEF, %g3
-	bnz	.bz_block
-	nop
-	andn	%g3, PSTATE_PEF, %g4
-	wrpr	%g4, PSTATE_PEF, %pstate
-	
-.bz_block:
-	membar	#StoreStore|#StoreLoad|#LoadStore
-	wr	%g0, FPRS_FEF, %fprs
-
-	! Clear block
-	fzero	%d0
-	fzero	%d2
-	fzero	%d4
-	fzero	%d6
-	fzero	%d8
-	fzero	%d10
-	fzero	%d12
-	fzero	%d14
-	wr	%g0, ASI_BLK_COMMIT_P, %asi
-	mov	256, %o3
-	ba	.bz_doblock
-	nop
-
-.bz_blkstart:	
-      ! stda	%d0, [%o0+192]%asi  ! in dly slot of branch that got us here
-	stda	%d0, [%o0+128]%asi
-	stda	%d0, [%o0+64]%asi
-	stda	%d0, [%o0]%asi
-	add	%o0, %o3, %o0
-	sub	%o1, %o3, %o1
-.bz_doblock:
-	cmp	%o1, 256
-	bgeu,a	%ncc, .bz_blkstart
-	stda	%d0, [%o0+192]%asi
-
-.bz_finish:
-	membar	#StoreLoad|#StoreStore
-	clr	%o0
-	wr	%g1, %fprs		! restore fprs
-	btst	PSTATE_PEF, %g3		! restore pstate if necessary
-	bnz	.bz_done
-	nop
-	wrpr	%g3, %g0, %pstate
-.bz_done:
-	membar	#Sync
-	retl
-	nop
-
-	SET_SIZE(drmach_bc_bzero)
-
-#endif /* lint */
--- a/usr/src/uts/sun4u/starcat/ml/starcat_asm.s	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +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"
-
-#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/mmu.h>
-#include <sys/machthread.h>
-#include <sys/pte.h>
-#include <sys/stack.h>
-#include <sys/vis.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/vtrace.h>
-#include <sys/clock.h>
-#include <sys/asi.h>
-#include <sys/fsr.h>
-#include <sys/cmpregs.h>
-#include <sys/cheetahregs.h>
-
-#if defined(lint)
-
-/* ARGSUSED */
-uint64_t
-lddmcdecode(uint64_t physaddr)
-{
-	return (0x0ull);
-}
-
-#else /* !lint */
-
-!
-! Load the mc_decode reg for this CPU.
-!
-
-	ENTRY(lddmcdecode)
-	rdpr    %pstate, %o4
-	andn    %o4, PSTATE_IE | PSTATE_AM, %o5
-	wrpr    %o5, 0, %pstate			! clear IE, AM bits
-	ldxa    [%o0]ASI_MC_DECODE, %o0
-	retl
-	wrpr    %g0, %o4, %pstate		! restore pstate value
-	SET_SIZE(lddmcdecode)
-
-#endif /* lint */
-
--- a/usr/src/uts/sun4u/starcat/os/starcat.c	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1329 +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 2011 Nexenta Systems, Inc.  All rights reserved.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysmacros.h>
-#include <sys/sunddi.h>
-#include <sys/esunddi.h>
-#include <sys/sunndi.h>
-#include <sys/modctl.h>
-#include <sys/promif.h>
-#include <sys/machparam.h>
-#include <sys/kobj.h>
-#include <sys/cpuvar.h>
-#include <sys/mem_cage.h>
-#include <sys/promif.h>
-#include <sys/promimpl.h>
-#include <sys/platform_module.h>
-#include <sys/errno.h>
-#include <sys/cpu_sgnblk_defs.h>
-#include <sys/iosramio.h>
-#include <sys/domaind.h>
-#include <sys/starcat.h>
-#include <sys/machsystm.h>
-#include <sys/bootconf.h>
-#include <sys/memnode.h>
-#include <vm/vm_dep.h>
-#include <vm/page.h>
-#include <sys/cheetahregs.h>
-#include <sys/plat_ecc_unum.h>
-#include <sys/plat_ecc_dimm.h>
-#include <sys/lgrp.h>
-#include <sys/dr.h>
-#include <sys/post/scat_dcd.h>
-#include <sys/kdi_impl.h>
-#include <sys/iosramreg.h>
-#include <sys/iosramvar.h>
-#include <sys/mc-us3.h>
-#include <sys/clock_impl.h>
-
-/* Preallocation of spare tsb's for DR */
-int starcat_tsb_spares = STARCAT_SPARE_TSB_MAX;
-
-/* Set the maximum number of slot0 + slot1 boards. .. for DR */
-int starcat_boards = STARCAT_BDSET_MAX * STARCAT_BDSET_SLOT_MAX;
-
-/* Maximum number of cpus per board... for DR */
-int starcat_cpu_per_board = MAX(STARCAT_SLOT0_CPU_MAX, STARCAT_SLOT1_CPU_MAX);
-
-/* Maximum number of mem-units per board... for DR */
-int starcat_mem_per_board = MAX(STARCAT_SLOT0_MEM_MAX, STARCAT_SLOT1_MEM_MAX);
-
-/* Maximum number of io-units (buses) per board... for DR */
-int starcat_io_per_board = 2 * MAX(STARCAT_SLOT0_IO_MAX, STARCAT_SLOT1_IO_MAX);
-
-/* Preferred minimum cage size (expressed in pages)... for DR */
-pgcnt_t starcat_startup_cage_size = 0;
-
-/* Platform specific function to get unum information */
-int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
-
-/* Memory for fcode claims.  16k times # maximum possible schizos */
-#define	EFCODE_SIZE	(STARCAT_BDSET_MAX * 4 * 0x4000)
-int efcode_size = EFCODE_SIZE;
-
-void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t);
-
-/*
- * The IOSRAM driver is loaded in load_platform_drivers() any cpu signature
- * usage prior to that time will have not have a function to call.
- */
-static int (*iosram_rdp)(uint32_t key, uint32_t off, uint32_t len,
-	    caddr_t dptr) = prom_starcat_iosram_read;
-static int (*iosram_wrp)(uint32_t key, uint32_t off, uint32_t len,
-	    caddr_t dptr) = prom_starcat_iosram_write;
-
-plat_dimm_sid_board_t	domain_dimm_sids[STARCAT_BDSET_MAX];
-
-/*
- * set_platform_max_ncpus should return the maximum number of CPUs that the
- * platform supports.  This function is called from check_cpus() to set the
- * value of max_ncpus [see PSARC 1997/165 CPU Dynamic Reconfiguration].
- * Data elements which are allocated based upon max_ncpus are all accessed
- * via cpu_seqid and not physical IDs.  Previously, the value of max_ncpus
- * was being set to the largest physical ID, which led to boot problems on
- * systems with less than 1.25GB of memory.
- */
-
-int
-set_platform_max_ncpus(void)
-{
-	int n;
-
-	/*
-	 * Convert number of slot0 + slot1 boards to number of expander brds
-	 * and constrain the value to an architecturally plausible range
-	 */
-	n = MAX(starcat_boards, STARCAT_BDSET_MIN * STARCAT_BDSET_SLOT_MAX);
-	n = MIN(n, STARCAT_BDSET_MAX * STARCAT_BDSET_SLOT_MAX);
-	n = (n + STARCAT_BDSET_SLOT_MAX - 1) / STARCAT_BDSET_SLOT_MAX;
-
-	/* return maximum number of cpus possible on N expander boards */
-	return (n * STARCAT_BDSET_CPU_MAX - STARCAT_SLOT1_CPU_MAX);
-}
-
-int
-set_platform_tsb_spares()
-{
-	return (MIN(starcat_tsb_spares, MAX_UPA));
-}
-
-#pragma weak mmu_init_large_pages
-
-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);
-	extern int tsb_lgrp_affinity;
-	extern int segkmem_reloc;
-	extern void mmu_init_large_pages(size_t);
-	extern int ncpunode;	/* number of CPUs detected by OBP */
-
-#ifdef DEBUG
-	ce_verbose_memory = 2;
-	ce_verbose_other = 2;
-#endif
-
-	/* Set the CPU signature function pointer */
-	cpu_sgn_func = cpu_sgn_update;
-
-	/* Set appropriate tod module for starcat */
-	ASSERT(tod_module_name == NULL);
-	tod_module_name = "todstarcat";
-
-	/*
-	 * Use the alternate TS dispatch table, which is better
-	 * tuned for large servers.
-	 */
-	if (ts_dispatch_extended == -1)
-		ts_dispatch_extended = 1;
-
-	/*
-	 * Use lgroup-aware TSB allocations on this platform,
-	 * since they are a considerable performance win.
-	 */
-	tsb_lgrp_affinity = 1;
-
-	if ((mmu_page_sizes == max_mmu_page_sizes) &&
-	    (mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) {
-		if (&mmu_init_large_pages)
-			mmu_init_large_pages(mmu_ism_pagesize);
-	}
-
-	/*
-	 * KPR (kernel page relocation) is supported on this platform.
-	 */
-	if (kernel_cage_enable && ncpunode >= 32) {
-		segkmem_reloc = 1;
-		cmn_err(CE_NOTE, "!Kernel Page Relocation is ENABLED");
-	} else {
-		cmn_err(CE_NOTE, "!Kernel Page Relocation is DISABLED");
-	}
-}
-
-#ifdef DEBUG
-pgcnt_t starcat_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(starcat_startup_cage_size, total_pages / 256);
-
-#ifdef DEBUG
-		if (starcat_cage_size_limit)
-			preferred_cage_size = starcat_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_modules(void)
-{
-	if (modload("misc", "pcihp") < 0) {
-		cmn_err(CE_NOTE, "pcihp driver failed to load");
-	}
-}
-
-/*
- * Starcat does not support power control of CPUs from the OS.
- */
-/*ARGSUSED*/
-int
-plat_cpu_poweron(struct cpu *cp)
-{
-	int (*starcat_cpu_poweron)(struct cpu *) = NULL;
-
-	starcat_cpu_poweron =
-	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0);
-
-	if (starcat_cpu_poweron == NULL)
-		return (ENOTSUP);
-	else
-		return ((starcat_cpu_poweron)(cp));
-}
-
-/*ARGSUSED*/
-int
-plat_cpu_poweroff(struct cpu *cp)
-{
-	int (*starcat_cpu_poweroff)(struct cpu *) = NULL;
-
-	starcat_cpu_poweroff =
-	    (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0);
-
-	if (starcat_cpu_poweroff == NULL)
-		return (ENOTSUP);
-	else
-		return ((starcat_cpu_poweroff)(cp));
-}
-
-/*
- * The following are currently private to Starcat DR
- */
-int
-plat_max_boards()
-{
-	return (starcat_boards);
-}
-
-int
-plat_max_cpu_units_per_board()
-{
-	return (starcat_cpu_per_board);
-}
-
-int
-plat_max_mc_units_per_board()
-{
-	return (starcat_mem_per_board); /* each CPU has a memory controller */
-}
-
-int
-plat_max_mem_units_per_board()
-{
-	return (starcat_mem_per_board);
-}
-
-int
-plat_max_io_units_per_board()
-{
-	return (starcat_io_per_board);
-}
-
-int
-plat_max_cpumem_boards(void)
-{
-	return (STARCAT_BDSET_MAX);
-}
-
-int
-plat_pfn_to_mem_node(pfn_t pfn)
-{
-	return (pfn >> mem_node_pfn_shift);
-}
-
-#define	STARCAT_MC_MEMBOARD_SHIFT 37	/* Boards on 128BG boundary */
-
-/* ARGSUSED */
-void
-plat_build_mem_nodes(prom_memlist_t *list, size_t nelems)
-{
-	size_t	elem;
-	pfn_t	basepfn;
-	pgcnt_t	npgs;
-
-	/*
-	 * Starcat mem slices are always aligned on a 128GB boundary,
-	 * fixed, and limited to one slice per expander due to design
-	 * of the centerplane ASICs.
-	 */
-	mem_node_pfn_shift = STARCAT_MC_MEMBOARD_SHIFT - MMU_PAGESHIFT;
-	mem_node_physalign = 0;
-
-	/*
-	 * Boot install lists are arranged <addr, len>, <addr, len>, ...
-	 */
-	for (elem = 0; elem < nelems; list++, elem++) {
-		basepfn = btop(list->addr);
-		npgs = btop(list->size);
-		mem_node_add_slice(basepfn, basepfn + npgs - 1);
-	}
-}
-
-/*
- * Find the CPU associated with a slice at boot-time.
- */
-void
-plat_fill_mc(pnode_t nodeid)
-{
-	int		len;
-	uint64_t	mc_addr, mask;
-	uint64_t	mc_decode[MAX_BANKS_PER_MC];
-	uint32_t	regs[4];
-	int		local_mc;
-	int		portid;
-	int		expnum;
-	int		i;
-
-	/*
-	 * Memory address decoding registers
-	 * (see Chap 9 of SPARCV9 JSP-1 US-III implementation)
-	 */
-	const uint64_t	mc_decode_addr[MAX_BANKS_PER_MC] = {
-		0x400028, 0x400010, 0x400018, 0x400020
-	};
-
-	/*
-	 * Starcat memory controller portid == global CPU id
-	 */
-	if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) ||
-	    (portid == -1))
-		return;
-
-	expnum = STARCAT_CPUID_TO_EXPANDER(portid);
-
-	/*
-	 * The "reg" property returns 4 32-bit values. The first two are
-	 * combined to form a 64-bit address.  The second two are for a
-	 * 64-bit size, but we don't actually need to look at that value.
-	 */
-	len = prom_getproplen(nodeid, "reg");
-	if (len != (sizeof (uint32_t) * 4)) {
-		prom_printf("Warning: malformed 'reg' property\n");
-		return;
-	}
-	if (prom_getprop(nodeid, "reg", (caddr_t)regs) < 0)
-		return;
-	mc_addr = ((uint64_t)regs[0]) << 32;
-	mc_addr |= (uint64_t)regs[1];
-
-	/*
-	 * Figure out whether the memory controller we are examining
-	 * belongs to this CPU/CMP or a different one.
-	 */
-	if (portid == cpunodes[CPU->cpu_id].portid)
-		local_mc = 1;
-	else
-		local_mc = 0;
-
-	for (i = 0; i < MAX_BANKS_PER_MC; i++) {
-
-		mask = mc_decode_addr[i];
-
-		/*
-		 * If the memory controller is local to this CPU, we use
-		 * the special ASI to read the decode registers.
-		 * Otherwise, we load the values from a magic address in
-		 * I/O space.
-		 */
-		if (local_mc)
-			mc_decode[i] = lddmcdecode(mask & MC_OFFSET_MASK);
-		else
-			mc_decode[i] = lddphysio((mc_addr | mask));
-
-		if (mc_decode[i] >> MC_VALID_SHIFT) {
-			uint64_t base = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT;
-			int sliceid = (base >> STARCAT_MC_MEMBOARD_SHIFT);
-
-			if (sliceid < max_mem_nodes) {
-				/*
-				 * Establish start-of-day mappings of
-				 * lgroup platform handles to memnodes.
-				 * Handle == Expander Number
-				 * Memnode == Fixed 128GB Slice
-				 */
-				plat_assign_lgrphand_to_mem_node(expnum,
-				    sliceid);
-			}
-		}
-	}
-}
-
-/*
- * Starcat support for lgroups.
- *
- * On Starcat, an lgroup platform handle == expander number.
- * For split-slot configurations (e.g. slot 0 and slot 1 boards
- * in different domains) an MCPU board has only remote memory.
- *
- * The centerplane logic provides fixed 128GB memory slices
- * each of which map to a memnode.  The initial mapping of
- * memnodes to lgroup handles is determined at boot time.
- * A DR addition of memory adds a new mapping. A DR copy-rename
- * swaps mappings.
- */
-
-/*
- * Convert board number to expander number.
- */
-#define	BOARDNUM_2_EXPANDER(b)	(b >> 1)
-
-/*
- * Return the number of boards configured with NULL LPA.
- */
-static int
-check_for_null_lpa(void)
-{
-	gdcd_t	*gdcd;
-	uint_t	exp, nlpa;
-
-	/*
-	 * Read GDCD from IOSRAM.
-	 * If this fails indicate a NULL LPA condition.
-	 */
-	if ((gdcd = kmem_zalloc(sizeof (gdcd_t), KM_NOSLEEP)) == NULL)
-		return (EXP_COUNT+1);
-
-	if ((*iosram_rdp)(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd) ||
-	    (gdcd->h.dcd_magic != GDCD_MAGIC) ||
-	    (gdcd->h.dcd_version != DCD_VERSION)) {
-		kmem_free(gdcd, sizeof (gdcd_t));
-		cmn_err(CE_WARN, "check_for_null_lpa: failed to access GDCD\n");
-		return (EXP_COUNT+2);
-	}
-
-	/*
-	 * Check for NULL LPAs on all slot 0 boards in domain
-	 * (i.e. in all expanders marked good for this domain).
-	 */
-	nlpa = 0;
-	for (exp = 0; exp < EXP_COUNT; exp++) {
-		if (RSV_GOOD(gdcd->dcd_slot[exp][0].l1ss_rsv) &&
-		    (gdcd->dcd_slot[exp][0].l1ss_flags &
-		    L1SSFLG_THIS_L1_NULL_PROC_LPA))
-			nlpa++;
-	}
-
-	kmem_free(gdcd, sizeof (gdcd_t));
-	return (nlpa);
-}
-
-/*
- * Return the platform handle for the lgroup containing the given CPU
- *
- * For Starcat, lgroup platform handle == expander.
- */
-
-extern int mpo_disabled;
-extern lgrp_handle_t lgrp_default_handle;
-int null_lpa_boards = -1;
-
-lgrp_handle_t
-plat_lgrp_cpu_to_hand(processorid_t id)
-{
-	lgrp_handle_t		plathand;
-
-	plathand = STARCAT_CPUID_TO_EXPANDER(id);
-
-	/*
-	 * Return the real platform handle for the CPU until
-	 * such time as we know that MPO should be disabled.
-	 * At that point, we set the "mpo_disabled" flag to true,
-	 * and from that point on, return the default handle.
-	 *
-	 * By the time we know that MPO should be disabled, the
-	 * first CPU will have already been added to a leaf
-	 * lgroup, but that's ok. The common lgroup code will
-	 * double check that the boot CPU is in the correct place,
-	 * and in the case where mpo should be disabled, will move
-	 * it to the root if necessary.
-	 */
-	if (mpo_disabled) {
-		/* If MPO is disabled, return the default (UMA) handle */
-		plathand = lgrp_default_handle;
-	} else {
-		if (null_lpa_boards > 0) {
-			/* Determine if MPO should be disabled */
-			mpo_disabled = 1;
-			plathand = lgrp_default_handle;
-		}
-	}
-	return (plathand);
-}
-
-/*
- * Platform specific lgroup initialization
- */
-void
-plat_lgrp_init(void)
-{
-	extern uint32_t lgrp_expand_proc_thresh;
-	extern uint32_t lgrp_expand_proc_diff;
-
-	/*
-	 * Set tuneables for Starcat architecture
-	 *
-	 * lgrp_expand_proc_thresh is the minimum load on the lgroups
-	 * this process is currently running on before considering
-	 * expanding threads to another lgroup.
-	 *
-	 * lgrp_expand_proc_diff determines how much less the remote lgroup
-	 * must be loaded before expanding to it.
-	 *
-	 * Since remote latencies can be costly, attempt to keep 3 threads
-	 * within the same lgroup before expanding to the next lgroup.
-	 */
-	lgrp_expand_proc_thresh = LGRP_LOADAVG_THREAD_MAX * 3;
-	lgrp_expand_proc_diff = LGRP_LOADAVG_THREAD_MAX;
-}
-
-/*
- * Platform notification of lgroup (re)configuration changes
- */
-/*ARGSUSED*/
-void
-plat_lgrp_config(lgrp_config_flag_t evt, uintptr_t arg)
-{
-	update_membounds_t	*umb;
-	lgrp_config_mem_rename_t lmr;
-	int			sbd, tbd;
-	lgrp_handle_t		hand, shand, thand;
-	int			mnode, snode, tnode;
-
-	if (mpo_disabled)
-		return;
-
-	switch (evt) {
-
-	case LGRP_CONFIG_MEM_ADD:
-		/*
-		 * Establish the lgroup handle to memnode translation.
-		 */
-		umb = (update_membounds_t *)arg;
-
-		hand = BOARDNUM_2_EXPANDER(umb->u_board);
-		mnode = plat_pfn_to_mem_node(umb->u_base >> MMU_PAGESHIFT);
-		plat_assign_lgrphand_to_mem_node(hand, mnode);
-
-		break;
-
-	case LGRP_CONFIG_MEM_DEL:
-		/* We don't have to do anything */
-
-		break;
-
-	case LGRP_CONFIG_MEM_RENAME:
-		/*
-		 * During a DR copy-rename operation, all of the memory
-		 * on one board is moved to another board -- but the
-		 * addresses/pfns and memnodes don't change. This means
-		 * the memory has changed locations without changing identity.
-		 *
-		 * Source is where we are copying from and target is where we
-		 * are copying to.  After source memnode is copied to target
-		 * memnode, the physical addresses of the target memnode are
-		 * renamed to match what the source memnode had.  Then target
-		 * memnode can be removed and source memnode can take its
-		 * place.
-		 *
-		 * To do this, swap the lgroup handle to memnode mappings for
-		 * the boards, so target lgroup will have source memnode and
-		 * source lgroup will have empty target memnode which is where
-		 * its memory will go (if any is added to it later).
-		 *
-		 * Then source memnode needs to be removed from its lgroup
-		 * and added to the target lgroup where the memory was living
-		 * but under a different name/memnode.  The memory was in the
-		 * target memnode and now lives in the source memnode with
-		 * different physical addresses even though it is the same
-		 * memory.
-		 */
-		sbd = arg & 0xffff;
-		tbd = (arg & 0xffff0000) >> 16;
-		shand = BOARDNUM_2_EXPANDER(sbd);
-		thand = BOARDNUM_2_EXPANDER(tbd);
-		snode = plat_lgrphand_to_mem_node(shand);
-		tnode = plat_lgrphand_to_mem_node(thand);
-
-		plat_assign_lgrphand_to_mem_node(thand, snode);
-		plat_assign_lgrphand_to_mem_node(shand, tnode);
-
-		lmr.lmem_rename_from = shand;
-		lmr.lmem_rename_to = thand;
-
-		/*
-		 * Remove source memnode of copy rename from its lgroup
-		 * and add it to its new target lgroup
-		 */
-		lgrp_config(LGRP_CONFIG_MEM_RENAME, (uintptr_t)snode,
-		    (uintptr_t)&lmr);
-
-		break;
-
-	default:
-		break;
-	}
-}
-
-/*
- * Return latency between "from" and "to" lgroups
- *
- * This latency number can only be used for relative comparison
- * between lgroups on the running system, cannot be used across platforms,
- * and may not reflect the actual latency.  It is platform and implementation
- * specific, so platform gets to decide its value.  It would be nice if the
- * number was at least proportional to make comparisons more meaningful though.
- * NOTE: The numbers below are supposed to be load latencies for uncached
- * memory divided by 10.
- */
-int
-plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to)
-{
-	/*
-	 * Return min remote latency when there are more than two lgroups
-	 * (root and child) and getting latency between two different lgroups
-	 * or root is involved
-	 */
-	if (lgrp_optimizations() && (from != to ||
-	    from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE))
-		return (48);
-	else
-		return (28);
-}
-
-/*
- * Return platform handle for root lgroup
- */
-lgrp_handle_t
-plat_lgrp_root_hand(void)
-{
-	if (mpo_disabled)
-		return (lgrp_default_handle);
-
-	return (LGRP_DEFAULT_HANDLE);
-}
-
-/* ARGSUSED */
-void
-plat_freelist_process(int mnode)
-{
-}
-
-void
-load_platform_drivers(void)
-{
-	uint_t		tunnel;
-	pnode_t		nodeid;
-	dev_info_t	*chosen_devi;
-	char		chosen_iosram[MAXNAMELEN];
-
-	/*
-	 * Get /chosen node - that's where the tunnel property is
-	 */
-	nodeid = prom_chosennode();
-
-	/*
-	 * Get the iosram property from the chosen node.
-	 */
-	if (prom_getprop(nodeid, IOSRAM_CHOSEN_PROP, (caddr_t)&tunnel) <= 0) {
-		prom_printf("Unable to get iosram property\n");
-		cmn_err(CE_PANIC, "Unable to get iosram property\n");
-	}
-
-	if (prom_phandle_to_path((phandle_t)tunnel, chosen_iosram,
-	    sizeof (chosen_iosram)) < 0) {
-		(void) prom_printf("prom_phandle_to_path(0x%x) failed\n",
-		    tunnel);
-		cmn_err(CE_PANIC, "prom_phandle_to_path(0x%x) failed\n",
-		    tunnel);
-	}
-
-	/*
-	 * Attach all driver instances along the iosram's device path
-	 */
-	if (i_ddi_attach_hw_nodes("iosram") != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "IOSRAM failed to load\n");
-	}
-
-	if ((chosen_devi = e_ddi_hold_devi_by_path(chosen_iosram, 0)) == NULL) {
-		(void) prom_printf("e_ddi_hold_devi_by_path(%s) failed\n",
-		    chosen_iosram);
-		cmn_err(CE_PANIC, "e_ddi_hold_devi_by_path(%s) failed\n",
-		    chosen_iosram);
-	}
-	ndi_rele_devi(chosen_devi);
-
-	/*
-	 * iosram driver is now loaded so we need to set our read and
-	 * write pointers.
-	 */
-	iosram_rdp = (int (*)(uint32_t, uint32_t, uint32_t, caddr_t))
-	    modgetsymvalue("iosram_rd", 0);
-	iosram_wrp = (int (*)(uint32_t, uint32_t, uint32_t, caddr_t))
-	    modgetsymvalue("iosram_wr", 0);
-
-	/*
-	 * Need to check for null proc LPA after IOSRAM driver is loaded
-	 * and before multiple lgroups created (when start_other_cpus() called)
-	 */
-	null_lpa_boards = check_for_null_lpa();
-
-	/* load and attach the axq driver */
-	if (i_ddi_attach_hw_nodes("axq") != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "AXQ failed to load\n");
-	}
-
-	/* load Starcat Solaris Mailbox Client driver */
-	if (modload("misc", "scosmb") < 0) {
-		cmn_err(CE_WARN, "SCOSMB failed to load\n");
-	}
-
-	/* load the DR driver */
-	if (i_ddi_attach_hw_nodes("dr") != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "dr failed to load");
-	}
-
-	/*
-	 * Load the mc-us3 memory driver.
-	 */
-	if (i_ddi_attach_hw_nodes("mc-us3") != DDI_SUCCESS)
-		cmn_err(CE_WARN, "mc-us3 failed to load");
-	else
-		(void) ddi_hold_driver(ddi_name_to_major("mc-us3"));
-
-	/* Load the schizo pci bus nexus driver. */
-	if (i_ddi_attach_hw_nodes("pcisch") != DDI_SUCCESS)
-		cmn_err(CE_WARN, "pcisch failed to load");
-
-	plat_ecc_init();
-}
-
-
-/*
- * No platform drivers on this platform
- */
-char *platform_module_list[] = {
-	(char *)0
-};
-
-
-/*ARGSUSED*/
-void
-plat_tod_fault(enum tod_fault_type tod_bad)
-{
-}
-
-/*
- * Update the signature(s) in the IOSRAM's domain data section.
- */
-void
-cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid)
-{
-	sig_state_t new_sgn;
-	sig_state_t current_sgn;
-
-	/*
-	 * If the substate is REBOOT, then check for panic flow
-	 */
-	if (sub_state == SIGSUBST_REBOOT) {
-		(*iosram_rdp)(DOMD_MAGIC, DOMD_DSTATE_OFFSET,
-		    sizeof (sig_state_t), (caddr_t)&current_sgn);
-		if (current_sgn.state_t.state == SIGST_EXIT)
-			sub_state = SIGSUBST_PANIC_REBOOT;
-	}
-
-	/*
-	 * cpuid == -1 indicates that the operation applies to all cpus.
-	 */
-	if (cpuid < 0) {
-		sgn_update_all_cpus(sgn, state, sub_state);
-		return;
-	}
-
-	new_sgn.signature = CPU_SIG_BLD(sgn, state, sub_state);
-	(*iosram_wrp)(DOMD_MAGIC,
-	    DOMD_CPUSIGS_OFFSET + cpuid * sizeof (sig_state_t),
-	    sizeof (sig_state_t), (caddr_t)&new_sgn);
-
-	/*
-	 * Under certain conditions we don't update the signature
-	 * of the domain_state.
-	 */
-	if ((sgn == OS_SIG) &&
-	    ((state == SIGST_OFFLINE) || (state == SIGST_DETACHED)))
-		return;
-	(*iosram_wrp)(DOMD_MAGIC, DOMD_DSTATE_OFFSET, sizeof (sig_state_t),
-	    (caddr_t)&new_sgn);
-}
-
-/*
- * Update the signature(s) in the IOSRAM's domain data section for all CPUs.
- */
-void
-sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state)
-{
-	sig_state_t new_sgn;
-	int i = 0;
-
-	new_sgn.signature = CPU_SIG_BLD(sgn, state, sub_state);
-
-	/*
-	 * First update the domain_state signature
-	 */
-	(*iosram_wrp)(DOMD_MAGIC, DOMD_DSTATE_OFFSET, sizeof (sig_state_t),
-	    (caddr_t)&new_sgn);
-
-	for (i = 0; i < NCPU; i++) {
-		if (cpu[i] != NULL && (cpu[i]->cpu_flags &
-		    (CPU_EXISTS|CPU_QUIESCED))) {
-			(*iosram_wrp)(DOMD_MAGIC,
-			    DOMD_CPUSIGS_OFFSET + i * sizeof (sig_state_t),
-			    sizeof (sig_state_t), (caddr_t)&new_sgn);
-		}
-	}
-}
-
-ushort_t
-get_cpu_sgn(int cpuid)
-{
-	sig_state_t cpu_sgn;
-
-	(*iosram_rdp)(DOMD_MAGIC,
-	    DOMD_CPUSIGS_OFFSET + cpuid * sizeof (sig_state_t),
-	    sizeof (sig_state_t), (caddr_t)&cpu_sgn);
-
-	return (cpu_sgn.state_t.sig);
-}
-
-uchar_t
-get_cpu_sgn_state(int cpuid)
-{
-	sig_state_t cpu_sgn;
-
-	(*iosram_rdp)(DOMD_MAGIC,
-	    DOMD_CPUSIGS_OFFSET + cpuid * sizeof (sig_state_t),
-	    sizeof (sig_state_t), (caddr_t)&cpu_sgn);
-
-	return (cpu_sgn.state_t.state);
-}
-
-
-/*
- * Type of argument passed into plat_get_ecache_cpu via ddi_walk_devs
- * for matching on specific CPU node in device tree
- */
-
-typedef struct {
-	char		*jnum;	/* output, kmem_alloc'd	if successful */
-	int		cpuid;	/* input, to match cpuid/portid/upa-portid */
-	uint_t		dimm;	/* input, index into ecache-dimm-label */
-} plat_ecache_cpu_arg_t;
-
-
-/*
- * plat_get_ecache_cpu is called repeatedly by ddi_walk_devs with pointers
- * to device tree nodes (dip) and to a plat_ecache_cpu_arg_t structure (arg).
- * Returning DDI_WALK_CONTINUE tells ddi_walk_devs to keep going, returning
- * DDI_WALK_TERMINATE ends the walk.  When the node for the specific CPU
- * being searched for is found, the walk is done.  But before returning to
- * ddi_walk_devs and plat_get_ecacheunum, we grab this CPU's ecache-dimm-label
- * property and set the jnum member of the plat_ecache_cpu_arg_t structure to
- * point to the label corresponding to this specific ecache DIMM.  It is up
- * to plat_get_ecacheunum to kmem_free this string.
- */
-
-static int
-plat_get_ecache_cpu(dev_info_t *dip, void *arg)
-{
-	char			*devtype;
-	plat_ecache_cpu_arg_t	*cpuarg;
-	char			**dimm_labels;
-	uint_t			numlabels;
-	int			portid;
-
-	/*
-	 * Check device_type, must be "cpu"
-	 */
-
-	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "device_type", &devtype) != DDI_PROP_SUCCESS)
-		return (DDI_WALK_CONTINUE);
-
-	if (strcmp(devtype, "cpu")) {
-		ddi_prop_free((void *)devtype);
-		return (DDI_WALK_CONTINUE);
-	}
-
-	ddi_prop_free((void *)devtype);
-
-	/*
-	 * Check cpuid, portid, upa-portid (in that order), must
-	 * match the cpuid being sought
-	 */
-
-	portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
-	    DDI_PROP_DONTPASS, "cpuid", -1);
-
-	if (portid == -1)
-		portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
-		    DDI_PROP_DONTPASS, "portid", -1);
-
-	if (portid == -1)
-		portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
-		    DDI_PROP_DONTPASS, "upa-portid", -1);
-
-	cpuarg = (plat_ecache_cpu_arg_t *)arg;
-
-	if (portid != cpuarg->cpuid)
-		return (DDI_WALK_CONTINUE);
-
-	/*
-	 * Found the right CPU, fetch ecache-dimm-label property
-	 */
-
-	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
-	    "ecache-dimm-label", &dimm_labels, &numlabels)
-	    != DDI_PROP_SUCCESS) {
-#ifdef	DEBUG
-		cmn_err(CE_NOTE, "cpuid=%d missing ecache-dimm-label property",
-		    portid);
-#endif	/* DEBUG */
-		return (DDI_WALK_TERMINATE);
-	}
-
-	if (cpuarg->dimm < numlabels) {
-		cpuarg->jnum = kmem_alloc(strlen(dimm_labels[cpuarg->dimm]) + 1,
-		    KM_SLEEP);
-		if (cpuarg->jnum != (char *)NULL)
-			(void) strcpy(cpuarg->jnum, dimm_labels[cpuarg->dimm]);
-#ifdef	DEBUG
-		else
-			cmn_err(CE_WARN,
-			    "cannot kmem_alloc for ecache dimm label");
-#endif	/* DEBUG */
-	}
-
-	ddi_prop_free((void *)dimm_labels);
-	return (DDI_WALK_TERMINATE);
-}
-
-
-/*
- * Bit 4 of physical address indicates ecache 0 or 1
- */
-
-#define	ECACHE_DIMM_MASK	0x10
-
-/*
- * plat_get_ecacheunum is called to generate the unum for an ecache error.
- * After some initialization, nearly all of the work is done by ddi_walk_devs
- * and plat_get_ecache_cpu.
- */
-
-int
-plat_get_ecacheunum(int cpuid, unsigned long long physaddr, char *buf,
-		    int buflen, int *ustrlen)
-{
-	plat_ecache_cpu_arg_t	findcpu;
-	uint_t	expander, slot, proc;
-
-	findcpu.jnum = (char *)NULL;
-	findcpu.cpuid = cpuid;
-
-	/*
-	 * Bit 4 of physaddr equal 0 maps to E0 and 1 maps to E1
-	 * except for Panther and Jaguar where it indicates the reverse
-	 */
-	if (IS_PANTHER(cpunodes[CPU->cpu_id].implementation) ||
-	    IS_JAGUAR(cpunodes[CPU->cpu_id].implementation))
-		findcpu.dimm =  (physaddr & ECACHE_DIMM_MASK) ? 0 : 1;
-	else
-		findcpu.dimm =  (physaddr & ECACHE_DIMM_MASK) ? 1 : 0;
-
-	/*
-	 * Walk the device tree, find this specific CPU, and get the label
-	 * for this ecache, returned here in findcpu.jnum
-	 */
-
-	ddi_walk_devs(ddi_root_node(), plat_get_ecache_cpu, (void *)&findcpu);
-
-	if (findcpu.jnum == (char *)NULL)
-		return (-1);
-
-	expander = STARCAT_CPUID_TO_EXPANDER(cpuid);
-	slot = STARCAT_CPUID_TO_BOARDSLOT(cpuid);
-
-	/*
-	 * STARCAT_CPUID_TO_PORTID clears the CoreID bit so that
-	 * STARCAT_CPUID_TO_AGENT will return a physical proc (0 - 3).
-	 */
-	proc = STARCAT_CPUID_TO_AGENT(STARCAT_CPUID_TO_PORTID(cpuid));
-
-	/*
-	 * NOTE: Any modifications to the snprintf() call below will require
-	 * changing plat_log_fruid_error() as well!
-	 */
-	(void) snprintf(buf, buflen, "%s%u/P%u/E%u J%s", (slot ? "IO" : "SB"),
-	    expander, proc, findcpu.dimm, findcpu.jnum);
-
-	*ustrlen = strlen(buf);
-
-	kmem_free(findcpu.jnum, strlen(findcpu.jnum) + 1);
-
-	return (0);
-}
-
-/*ARGSUSED*/
-int
-plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id,
-    int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp)
-{
-	int ret;
-
-	/*
-	 * check if it's a Memory or an Ecache error.
-	 */
-	if (flt_in_memory) {
-		if (p2get_mem_unum != NULL) {
-			return (p2get_mem_unum(synd_code, P2ALIGN(flt_addr, 8),
-			    buf, buflen, lenp));
-		} else {
-			return (ENOTSUP);
-		}
-	} else if (flt_status & ECC_ECACHE) {
-		if ((ret = plat_get_ecacheunum(flt_bus_id,
-		    P2ALIGN(flt_addr, 8), buf, buflen, lenp)) != 0)
-			return (EIO);
-	} else {
-		return (ENOTSUP);
-	}
-
-	return (ret);
-}
-
-static int (*ecc_mailbox_msg_func)(plat_ecc_message_type_t, void *) = NULL;
-
-/*
- * To keep OS mailbox handling localized, all we do is forward the call to the
- * scosmb module (if it is available).
- */
-int
-plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap)
-{
-	/*
-	 * find the symbol for the mailbox sender routine in the scosmb module
-	 */
-	if (ecc_mailbox_msg_func == NULL)
-		ecc_mailbox_msg_func = (int (*)(plat_ecc_message_type_t,
-		    void *))modgetsymvalue("scosmb_log_ecc_error", 0);
-
-	/*
-	 * If the symbol was found, call it.  Otherwise, there is not much
-	 * else we can do and console messages will have to suffice.
-	 */
-	if (ecc_mailbox_msg_func)
-		return ((*ecc_mailbox_msg_func)(msg_type, datap));
-	else
-		return (ENODEV);
-}
-
-int
-plat_make_fru_cpuid(int sb, int m, int proc)
-{
-	return (MAKE_CPUID(sb, m, proc));
-}
-
-/*
- * board number for a given proc
- */
-int
-plat_make_fru_boardnum(int proc)
-{
-	return (STARCAT_CPUID_TO_EXPANDER(proc));
-}
-
-/*
- * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3
- * driver giving each platform the opportunity to add platform
- * specific label information to the unum for ECC error logging purposes.
- */
-void
-plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm)
-{
-	char	new_unum[UNUM_NAMLEN];
-	uint_t	expander = STARCAT_CPUID_TO_EXPANDER(mcid);
-	uint_t	slot = STARCAT_CPUID_TO_BOARDSLOT(mcid);
-
-	/*
-	 * STARCAT_CPUID_TO_PORTID clears the CoreID bit so that
-	 * STARCAT_CPUID_TO_AGENT will return a physical proc (0 - 3).
-	 */
-	uint_t	proc = STARCAT_CPUID_TO_AGENT(STARCAT_CPUID_TO_PORTID(mcid));
-
-	/*
-	 * NOTE: Any modifications to the two sprintf() calls below will
-	 * require changing plat_log_fruid_error() as well!
-	 */
-	if (dimm == -1)
-		(void) snprintf(new_unum, UNUM_NAMLEN, "%s%u/P%u/B%d %s",
-		    (slot ? "IO" : "SB"), expander, proc, (bank & 0x1), unum);
-	else
-		(void) snprintf(new_unum, UNUM_NAMLEN, "%s%u/P%u/B%d/D%d %s",
-		    (slot ? "IO" : "SB"), expander,
-		    proc, (bank & 0x1), (dimm & 0x3), unum);
-
-	(void) strcpy(unum, new_unum);
-}
-
-int
-plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp)
-{
-	int	expander = STARCAT_CPUID_TO_EXPANDER(cpuid);
-	int	slot = STARCAT_CPUID_TO_BOARDSLOT(cpuid);
-
-	if (snprintf(buf, buflen, "%s%d", (slot ? "IO" : "SB"), expander)
-	    >= buflen) {
-		return (ENOSPC);
-	} else {
-		*lenp = strlen(buf);
-		return (0);
-	}
-}
-
-/*
- * This routine is used by the data bearing mondo (DMV) initialization
- * routine to determine the number of hardware and software DMV interrupts
- * that a platform supports.
- */
-void
-plat_dmv_params(uint_t *hwint, uint_t *swint)
-{
-	*hwint = STARCAT_DMV_HWINT;
-	*swint = 0;
-}
-
-/*
- * If provided, this function will be called whenever the nodename is updated.
- * To keep OS mailbox handling localized, all we do is forward the call to the
- * scosmb module (if it is available).
- */
-void
-plat_nodename_set(void)
-{
-	void (*nodename_update_func)(uint64_t) = NULL;
-
-	/*
-	 * find the symbol for the nodename update routine in the scosmb module
-	 */
-	nodename_update_func = (void (*)(uint64_t))
-	    modgetsymvalue("scosmb_update_nodename", 0);
-
-	/*
-	 * If the symbol was found, call it.  Otherwise, log a note (but not to
-	 * the console).
-	 */
-	if (nodename_update_func != NULL) {
-		nodename_update_func(0);
-	} else {
-		cmn_err(CE_NOTE,
-		    "!plat_nodename_set: scosmb_update_nodename not found\n");
-	}
-}
-
-caddr_t	efcode_vaddr = NULL;
-caddr_t efcode_paddr = NULL;
-/*
- * Preallocate enough memory for fcode claims.
- */
-
-caddr_t
-efcode_alloc(caddr_t alloc_base)
-{
-	caddr_t efcode_alloc_base = (caddr_t)roundup((uintptr_t)alloc_base,
-	    MMU_PAGESIZE);
-	caddr_t vaddr;
-
-	/*
-	 * allocate the physical memory schizo fcode.
-	 */
-	if ((vaddr = (caddr_t)BOP_ALLOC(bootops, efcode_alloc_base,
-	    efcode_size, MMU_PAGESIZE)) == NULL)
-		cmn_err(CE_PANIC, "Cannot allocate Efcode Memory");
-
-	efcode_vaddr = vaddr;
-
-	return (efcode_alloc_base + efcode_size);
-}
-
-caddr_t
-plat_startup_memlist(caddr_t alloc_base)
-{
-	caddr_t tmp_alloc_base;
-
-	tmp_alloc_base = efcode_alloc(alloc_base);
-	tmp_alloc_base = (caddr_t)roundup((uintptr_t)tmp_alloc_base,
-	    ecache_alignsize);
-	return (tmp_alloc_base);
-}
-
-/*
- * This is a helper function to determine if a given
- * node should be considered for a dr operation according
- * to predefined dr names. This is accomplished using
- * a function defined in drmach module. The drmach module
- * owns the definition of dr allowable names.
- * Formal Parameter: The name of a device node.
- * Expected Return Value: -1, device node name does not map to a valid dr name.
- *               A value greater or equal to 0, name is valid.
- */
-int
-starcat_dr_name(char *name)
-{
-	int (*drmach_name2type)(char *) = NULL;
-
-	/* Get a pointer to helper function in the dramch module. */
-	drmach_name2type =
-	    (int (*)(char *))kobj_getsymvalue("drmach_name2type_idx", 0);
-
-	if (drmach_name2type == NULL)
-		return (-1);
-
-	return ((*drmach_name2type)(name));
-}
-
-void
-startup_platform(void)
-{
-	/* set per platform constants for mutex backoff */
-	mutex_backoff_base = 2;
-	mutex_cap_factor = 64;
-}
-
-/*
- * 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
-starcat_system_claim(void)
-{
-	lbolt_debug_entry();
-
-	prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0);
-}
-
-static void
-starcat_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 = starcat_system_claim;
-	kdi->pkdi_system_release = starcat_system_release;
-}
-
-/*
- * This function returns 1 if large pages for kernel heap are supported
- * and 0 otherwise.
- *
- * Currently we disable lp kmem support if kpr is going to be enabled
- * because in the case of large pages hat_add_callback()/hat_delete_callback()
- * cause network performance degradation
- */
-int
-plat_lpkmem_is_supported(void)
-{
-	extern int segkmem_reloc;
-
-	if (kernel_cage_enable && (ncpunode >= 32 || segkmem_reloc == 1))
-		return (0);
-
-	return (1);
-}
--- a/usr/src/uts/sun4u/starcat/platmod/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the production of the sun4u starcat platform
-#	module.
-#
-#	sun4u starcat 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		= $(STARCAT_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(STARCAT_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-PLAT_DIR	= .
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Override defaults
-#
-CLEANFILES	+= $(PLATLIB)
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(PLATLIB)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-unused-variable
-
-#
-#	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):	$(OBJECTS)
-	$(BUILD.SO) $(OBJECTS)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/sc_gptwocfg/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the production of the sc_gptwocfg
-#	miscellaneous module.
-#
-#	sun4u starcat 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		= sc_gptwocfg
-OBJECTS		= $(SC_GPTWO_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(SC_GPTWO_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE) -I../sys -I$(UTSBASE)/sun4u/starcat/sys
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/gptwocfg -Nmisc/gptwo_cpu -Nmisc/gptwo_pci -Ndrv/iosram
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/schpc/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +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 makefile drives the production of the Starcat domain
-#	side Hot Plug Controller Driver.
-#
-#	Starcat 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		= schpc
-OBJECTS		= $(SCHPC_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(SCHPC_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/sun4u/starcat/io
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/mboxsc -Nmisc/hpcsvc -Ndrv/iosram
-
-#
-# Turn on doubleword alignment for 64 bit registers
-#
-CFLAGS += -dalign
-
-.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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/sckmdrv/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#	This makefile drives the production of the Starcat IPsec
-#	Key Management driver.
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= sckmdrv
-OBJECTS		= $(SCKMDRV_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(SCKMDRV_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/sun4u/starcat/io
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)  $(SRC_CONFFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/mboxsc
-
-#
-# 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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/scosmb/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-#	This makefile drives the production of the scosmb miscellaneous module.
-#
-#	sun4u starcat 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		= scosmb
-OBJECTS		= $(SCOSMB_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(SCOSMB_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_STARCAT_MISC_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# lint pass one enforcement
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-unused-variable
-CERRWARN += -_gcc=-Wno-uninitialized
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Nmisc/mboxsc
-
-#
-#	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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/starcat/sys/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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.starcat
-
-#
-# Override defaults.
-#
-FILEMODE	 = 644
-
-HDRS=
-
-
-CHKHDRS=	axq.h dman.h domaind.h drmach.h \
-		iosramio.h iosramreg.h iosramvar.h \
-		sc_cvc.h sc_cvcio.h \
-		sckm_msg.h sckm_io.h
-
-STARHDRS=	$(UTSBASE)/sun4u/ngdr/sys/dr.h \
-		$(UTSBASE)/sun4u/ngdr/sys/dr_util.h
-
-ROOTHDRS=	$(HDRS:%=$(USR_STARCAT_ISYS_DIR)/%)
-
-ROOTDIR=	$(ROOT)/usr/share/src
-ROOTDIRS=	$(ROOTDIR)/uts $(ROOTDIR)/uts/$(PLATFORM)
-
-CHECKHDRS=	$(HDRS:%.h=%.check) \
-		$(CHKHDRS:%.h=%.check) \
-		$(STARHDRS:%.h=%.check)
-
-.KEEP_STATE:
-
-.PARALLEL: $(CHECKHDRS) $(ROOTHDRS)
-
-install_h: $(ROOTDIRS) .WAIT $(ROOTHDRS) $(ROOTLINK)
-
-check:	$(CHECKHDRS)
-
-#
-# install rules
-#
-$(USR_STARCAT_ISYS_DIR)/%:	% $(USR_STARCAT_ISYS_DIR)
-	$(INS.file)
-
-FRC:
-
-include ../Makefile.targ
--- a/usr/src/uts/sun4u/starcat/sys/axq.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,368 +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 2002 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_AXQ_H
-#define	_SYS_AXQ_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/* AXQ register offset constant */
-#define	AXQ_REG_OFFSET		0x20
-#define	AXQ_REGOFF(idx)		((idx) * AXQ_REG_OFFSET)
-
-/*
- * AXQ system register offsets
- * Each Starcat AXQ asic instance is logically
- * associated with each slot in the expander board.
- * Slot 0 is the full slot (or full bandwidth slot)
- * and Slot1 is the half slot (or half bandwidth slot).
- * Some system registers are only accessible in certain
- * slot type.
- */
-
-/* domain control register (slot0 & slot1) */
-#define	AXQ_SLOT0_DOMCTRL	AXQ_REGOFF(0x1)
-#define	AXQ_SLOT1_DOMCTRL	AXQ_REGOFF(0x2)
-
-/* cpu2ssc intr register */
-#define	AXQ_SLOT_CPU2SSC_INTR	AXQ_REGOFF(0x3)
-
-/* performance counters (one set per slot) */
-#define	AXQ_SLOT0_PERFCNT_SEL	AXQ_REGOFF(0x9)
-#define	AXQ_SLOT0_PERFCNT0	AXQ_REGOFF(0xA)
-#define	AXQ_SLOT0_PERFCNT1	AXQ_REGOFF(0xB)
-#define	AXQ_SLOT0_PERFCNT2	AXQ_REGOFF(0xC)
-#define	AXQ_SLOT1_PERFCNT_SEL	AXQ_REGOFF(0x8)
-#define	AXQ_SLOT1_PERFCNT0	AXQ_REGOFF(0xD)
-#define	AXQ_SLOT1_PERFCNT1	AXQ_REGOFF(0xE)
-#define	AXQ_SLOT1_PERFCNT2	AXQ_REGOFF(0xF)
-
-/* CASM slots (for both slot0 & slot1) */
-#define	AXQ_CASM_SLOT_START	AXQ_REGOFF(0x10)
-#define	AXQ_CASM_SLOT_END	AXQ_REGOFF(0x21)
-
-/* CDC registers (only available in slot0) */
-#define	AXQ_SLOT0_CDC_ADR_TEST	AXQ_REGOFF(0x2C)
-#define	AXQ_SLOT0_CDC_CTL_TEST	AXQ_REGOFF(0x2D)
-#define	AXQ_SLOT0_CDC_DATA_WR3	AXQ_REGOFF(0x2E)
-#define	AXQ_SLOT0_CDC_DATA_WR2	AXQ_REGOFF(0x2F)
-#define	AXQ_SLOT0_CDC_DATA_WR1	AXQ_REGOFF(0x30)
-#define	AXQ_SLOT0_CDC_DATA_WR0	AXQ_REGOFF(0x31)
-#define	AXQ_SLOT0_CDC_CNT_TEST	AXQ_REGOFF(0x32)
-#define	AXQ_SLOT0_CDC_RD_DATA3	AXQ_REGOFF(0x33)
-#define	AXQ_SLOT0_CDC_RD_DATA2	AXQ_REGOFF(0x34)
-#define	AXQ_SLOT0_CDC_RD_DATA1	AXQ_REGOFF(0x35)
-#define	AXQ_SLOT0_CDC_RD_DATA0	AXQ_REGOFF(0x36)
-
-/* NASM registers */
-#define	AXQ_SLOT0_NASM		AXQ_REGOFF(0x37)
-#define	AXQ_SLOT1_NASM		AXQ_REGOFF(0x38)
-
-#define	AXQ_NASM_TYPE_IO		0
-#define	AXQ_NASM_TYPE_SLOT0_CMMU	1
-#define	AXQ_NASM_TYPE_WIB		2
-#define	AXQ_NASM_TYPE_WIB_STRIPED	3
-#define	AXQ_NASM_TYPE_SHIFT		5
-
-/* SDI Timeout register */
-#define	AXQ_SLOT_SDI_TIMEOUT_RD		AXQ_REGOFF(0x2A)
-#define	AXQ_SLOT_SDI_TIMEOUT_RDCLR	AXQ_REGOFF(0x2B)
-
-/*
- * Bits for domain control register
- */
-#define	AXQ_DOMCTRL_BUSY	0x1
-#define	AXQ_DOMCTRL_PAUSE	0x10
-#define	AXQ_DOMCTRL_PIOFIX	0x40
-
-/*
- * Bits for CDC registers
- */
-/* CDC control test register */
-#define	AXQ_CDC_TMODE_WR		0x20000
-#define	AXQ_CDC_TMODE_RDCMP		0x40000
-#define	AXQ_CDC_TMODE_WR_RDCMP0		0x60000
-#define	AXQ_CDC_TMODE_WR_RDCMP1		0x80000
-#define	AXQ_CDC_DATA_ECC_CHK_EN		0x10000
-#define	AXQ_CDC_ADR_PAR_CHK_EN		0x08000
-#define	AXQ_CDC_DATA_ECC_GEN_EN		0x04000
-#define	AXQ_CDC_ADR_PAR_GEN_EN		0x02000
-#define	AXQ_CDC_DATA2PAR_MUX_SEL_DATA	0x00800
-#define	AXQ_CDC_ADR2SRAM_MUX_SEL_TEST	0x00080
-#define	AXQ_CDC_ADR_INCR_XOR_CTRL	0x00010
-#define	AXQ_CDC_DIS			0x00001
-
-/* CDC Address Test register */
-#define	AXQ_CDC_ADR_TEST_EN		0x80000
-
-/* CDC counter test register */
-#define	AXQ_CDC_CNT_TEST_DONE		0x80000000
-
-/*
- * Bits for CPU to SSC interrupt register
- */
-#define	AXQ_CPU2SSC_INTR_PEND		0x80000000
-
-/*
- * Each AXQ instance has one pcr (performance control
- * register) controlling 3 pics (performance instru-
- * mentation counter).  pic0 and pic1 are similar
- * and have identical inputs to their muxes. pic2
- * only counts the clock.
- */
-
-/* Bit masks for selecting pic mux input */
-#define	FREEZE_CNT	0x0
-#define	COUNT_CLK	0x1
-#define	HA_INPUT_FIFO	0x2
-#define	HA_INTR_INFO	0x3
-#define	HA_PIO_FIFO	0x4
-#define	HA_ADR_FIFO_LK3	0x5
-#define	HA_ADR_FIFO_LK2	0x6
-#define	HA_ADR_FIFO_LK1	0x7
-#define	HA_ADR_FIFO_LK0	0x8
-#define	HA_DUMP_Q	0x9
-#define	HA_RD_F_STB_Q	0xA
-#define	HA_DP_WR_Q	0xB
-#define	HA_INT_Q	0xC
-#define	HA_WRB_Q	0xD
-#define	HA_WR_MP_Q	0xE
-#define	HA_WRTAG_Q	0xF
-#define	HA_WT_WAIT_FIFO	0x10
-#define	HA_WRB_STB_FIFO	0x11
-#define	HA_AP0_Q	0x12
-#define	HA_AP1_Q	0x13
-#define	HA_NEW_WR_Q	0x14
-#define	HA_DP_RD_Q	0x15
-#define	HA_UNLOCK_Q	0x16
-#define	HA_CDC_UPD_Q	0x17
-#define	HA_DS_Q		0x18
-#define	HA_UNLK_WAIT_Q	0x19
-#define	HA_RD_MP_Q	0x1A
-#define	L2_IO_Q		0x1B
-#define	L2_SB_Q		0x1C
-#define	L2_RA_Q		0x1D
-#define	L2_HA_Q		0x1E
-#define	L2_SA_Q		0x1F
-#define	RA_WAIT_FIFO	0x20
-#define	RA_WRB_INV_FIFO	0x21
-#define	RA_WRB_FIFO	0x22
-#define	RA_CC_PTR_FIFO	0x23
-#define	RA_IO_PTR_FIFO	0x24
-#define	RA_INT_PTR_FIFO	0x25
-#define	RA_RP_Q		0x26
-#define	RA_WRB_RP_Q	0x27
-#define	RA_DP_Q		0x28
-#define	RA_DP_STB_Q	0x29
-#define	RA_GTARG_Q	0x2A
-#define	SDC_RECV_Q	0x2B
-#define	SDC_REDIR_IO_Q	0x2C
-#define	SDC_REDIR_SB_Q	0x2D
-#define	SDC_OUTB_IO_Q	0x2E
-#define	SDC_OUTB_SB_Q	0x2F
-#define	SA_ADD1_INPUT_Q	0x30
-#define	SA_ADD2_INPUT_Q	0x31
-#define	SA_INV_Q	0x32
-#define	SA_NO_INV_Q	0x33
-#define	SA_INT_DP_Q	0x34
-#define	SA_DP_Q		0x35
-#define	SL_WRTAG_Q	0x36
-#define	SL_RTO_DP_Q	0x37
-#define	SYSREG_INPUT_Q	0x38
-#define	SDI_SYS_STATUS1	0x39
-#define	SDI_SYS_STATUS0	0x3A
-#define	CDC_HITS	0x3B
-#define	TOTAL_CDC_READ	0x3C
-#define	HA_WATRANID_SD	0x3D
-#define	HA_STB_SD	0x3E
-#define	HA_L2_IRQ_SD	0x3F
-#define	HA_SL_WRTAG_SD	0x40
-#define	AA_HOME_CC_FULL	0x41
-#define	AA_HOME_IO_FULL	0x42
-#define	AA_SLAVE_FULL	0x43
-#define	AA_RP_FULL	0x44
-
-/* Shift definitions into pcr for programming pics */
-#define	AXQ_PIC_SHIFT	7
-
-/* event constants */
-#define	AXQ_NUM_EVENTS		0x45
-#define	AXQ_PIC0_1_NUM_EVENTS	0x45
-#define	AXQ_PIC2_NUM_EVENTS	0x2
-#define	AXQ_NUM_PICS	3
-#define	AXQ_PIC_CLEAR_MASK	0x7F
-
-/* AXQ constants */
-#define	SLOT0_AXQ		0
-#define	SLOT1_AXQ		1
-#define	AXQ_MAX_EXP		18
-#define	AXQ_MAX_SLOT_PER_EXP	2
-#define	AXQ_CDC_SRAM_SIZE	0x40000
-#define	AXQ_CDC_FLUSH_WAIT	4
-#define	AXQ_INTR_PEND_WAIT	10
-#define	AXQ_NASM_SIZE		256
-
-/*
- * Struct element describing a eventname and
- * its pcr-mask.
- */
-typedef struct axq_event_mask {
-	char	*event_name;
-	uint64_t pcr_mask;
-} axq_event_mask_t;
-
-/*
- * NASM RAM system register for reading
- */
-typedef union {
-	struct axq_nasm_read {
-		uint32_t pad	: 16;
-		uint32_t valid	: 1;
-		uint32_t addr	: 8;
-		uint32_t data	: 7;
-	} bit;
-	uint32_t val;
-} axq_nasm_read_u;
-
-/*
- * NASM RAM system register for reading
- */
-typedef union {
-	struct axq_nasm_write {
-		uint32_t pad	: 16;
-		uint32_t addr	: 8;
-		uint32_t rw	: 1;
-		uint32_t data	: 7;
-	} bit;
-	uint32_t val;
-} axq_nasm_write_u;
-
-
-/*
- * Global data structure that is used to
- * export certain axq registers in
- * local space. Right now, the only
- * register we want to access in local space
- * is the cheetah2ssc interrupt reg. There
- * could be more in future.
- */
-struct axq_local_regs {
-	kmutex_t axq_local_lock;
-	int initflag;
-	caddr_t laddress;
-	ddi_acc_handle_t ac;
-	volatile uint32_t *axq_cpu2ssc_intr;
-};
-
-/*
- * axq soft state data structure.
- */
-struct axq_soft_state {
-	dev_info_t *dip;		/* devinfo of myself */
-	uint32_t portid;		/* port id */
-	uint32_t expid;			/* expander id */
-	uchar_t slotnum;		/* slot 0 or 1 */
-	caddr_t address;		/* mapped devnode addr property */
-	ddi_acc_handle_t ac0;		/* access handle for reg0 mapping */
-	uint64_t axq_phyaddr;		/* physical address of conf space */
-	kmutex_t axq_lock;		/* mutex protecting this softstate */
-
-	volatile uint32_t *axq_domain_ctrl;
-
-	/* CASM register slots */
-	volatile uint32_t *axq_casm_slot[18];
-
-	/* NASM register */
-	volatile uint32_t *axq_nasm;
-
-	/* CDC registers (only in slot0) */
-	volatile uint32_t *axq_cdc_addrtest;
-	volatile uint32_t *axq_cdc_ctrltest;
-	volatile uint32_t *axq_cdc_datawrite0;
-	volatile uint32_t *axq_cdc_datawrite1;
-	volatile uint32_t *axq_cdc_datawrite2;
-	volatile uint32_t *axq_cdc_datawrite3;
-	volatile uint32_t *axq_cdc_counter;
-	volatile uint32_t *axq_cdc_readdata0;
-	volatile uint32_t *axq_cdc_readdata1;
-	volatile uint32_t *axq_cdc_readdata2;
-	volatile uint32_t *axq_cdc_readdata3;
-
-	/* performance counters */
-	volatile uint32_t *axq_pcr;
-	volatile uint32_t *axq_pic0;
-	volatile uint32_t *axq_pic1;
-	volatile uint32_t *axq_pic2;
-	kstat_t *axq_counters_ksp;	/* perf counter kstat */
-
-	/* SDI timeout register */
-	volatile uint32_t *axq_sdi_timeout_rd;
-	volatile uint32_t *axq_sdi_timeout_rdclr;
-
-	uint32_t axq_cdc_state;		/* CDC state - enabled/disabled */
-	int paused;			/* AXQ_DOMCTRL_PAUSE asserted */
-
-#ifndef _AXQ_LOCAL_ACCESS_SUPPORTED
-	/*
-	 * No local access for cpu2ssc intr
-	 * Need to provide per instance explicit expander addressing
-	 */
-	volatile uint32_t *axq_cpu2ssc_intr;
-#endif /* _AXQ_LOCAL_ACCESS_SUPPORTED */
-};
-
-/*
- * Public interface
- */
-extern int axq_cdc_flush(uint32_t, int, int);
-extern int axq_cdc_flush_all();
-extern int axq_cdc_disable_flush_all();
-extern void axq_cdc_enable_all();
-extern int axq_iopause_enable_all(uint32_t *);
-extern void axq_iopause_disable_all();
-extern uint32_t axq_casm_read(uint32_t, uint32_t, int);
-extern int axq_casm_write(uint32_t, uint32_t, int, uint32_t);
-extern int axq_casm_write_all(int, uint32_t);
-extern int axq_do_casm_rename_script(uint64_t **, int, int);
-extern int axq_cpu2ssc_intr(uint8_t);
-extern uint32_t axq_read_sdi_timeout_reg(uint32_t, uint32_t, int);
-extern int axq_nasm_read(uint32_t expid, uint32_t slot, uint32_t nasm_entry,
-    uint32_t *data);
-extern int axq_nasm_write(uint32_t expid, uint32_t slot, uint32_t nasm_entry,
-    uint32_t data);
-extern int axq_nasm_write_all(uint32_t nasm_entry, uint32_t data);
-extern void axq_array_rw_enter(void);
-extern void axq_array_rw_exit(void);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_AXQ_H */
--- a/usr/src/uts/sun4u/starcat/sys/dman.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,552 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * ****** NOTICE **** This header file is maintained in the SMS gate,
- * ****** NOTICE **** the ON gate, and the ssc driver gate. Any changes
- * ****** NOTICE **** to it must also be made to in all gates.
- */
-
-#ifndef	_DMAN_H
-#define	_DMAN_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Ethernet stuff
- */
-
-#define	ETHERHEADER_SIZE (sizeof (struct ether_header))
-typedef struct ether_header ehdr_t;
-typedef struct ether_addr eaddr_t;
-#define	IS_BROADCAST(eap) \
-		(ether_cmp(eap, &etherbroadcast) == 0)
-#define	IS_MULTICAST(eap) \
-		((eap->ether_addr_octet[0] & 01) == 1)
-#define	IS_UNICAST(eap) \
-		(!IS_BROADCAST(eap) && !IS_MULTICAST(eap))
-
-#define	MAN_IS_DATA(mp)		((DB_TYPE(mp) == M_DATA) ||		\
-				    ((DB_TYPE(mp) == M_PROTO) &&	\
-				    (DL_PRIM(mp) == DL_UNITDATA_IND)))
-
-#define	MAN_ADDRL (sizeof (uint16_t) + ETHERADDRL)
-
-/*
- * Private	DLPI full dlsap address format - stolen from eri.h
- */
-typedef struct  man_dladdr_s {
-	struct  ether_addr	dl_phys;
-	uint16_t		dl_sap;
-} man_dladdr_t;
-
-#define	put_ether_type(ptr, value) {\
-	((uint8_t *)(&((ehdr_t *)ptr)->ether_type))[0] = \
-	    ((uint16_t)value & 0xff00) >> 8; \
-	((uint8_t *)(&((ehdr_t *)ptr)->ether_type))[1] = (value & 0xff); }
-#define	ether_bcopy(a, b) (bcopy((caddr_t)a, (caddr_t)b, 6))
-
-#define	MAN_MAX_EXPANDERS		18
-#define	MAN_MAX_DESTS			38 /* (MAN_NUM_EXPANDERS * 2) + 2 */
-#define	MAN_DEST_ARRAY_SIZE		(MAN_MAX_DESTS * sizeof (man_dest_t))
-#define	TRUE		1
-#define	FALSE		0
-
-/*
- * Caller IDs for man_sendit processing decision on canput failure.
- */
-#define	MAN_UPPER	0x1
-#define	MAN_LOWER	0x2
-
-/*
- * MAN device information structure, one per man instance
- *
- * global list pointed to by MAN_XX_head
- */
-typedef struct man_s {
-	struct man_s	*man_next;		/* next in list of devices */
-	dev_info_t	*man_dip;		/* devinfo for this device */
-	int		man_meta_ppa;		/* mxx device minor */
-	major_t		man_meta_major;		/* mxx device major # */
-	struct man_pg_s	*man_pg;		/* Pathgroups for this inst */
-	int		man_refcnt;		/* DL_ATTACHes to us */
-	int		man_suspended;		/* DDI_SUSPEND on device */
-	kstat_t		*man_ksp;		/* meta interface statistics */
-	int		man_eaddr_v;		/* ether addr valid */
-	eaddr_t		man_eaddr;		/* active ether addr */
-	/*
-	 * Failover timers, used by man_dest_t.
-	 */
-	int32_t		man_init_time;		/* init time in usecs */
-	int32_t		man_linkcheck_time;	/* linkcheck time in usecs */
-	int32_t		man_linkstale_time;	/* linkstale time in usecs */
-	int32_t		man_linkstale_retries;	/* linkstale retries/probes */
-	int32_t		man_dr_delay;		/* DR retry delay in usecs */
-	int32_t		man_dr_retries;		/* DR retries on EAGAIN errs */
-	int32_t		man_kstat_waittime;	/* kstat_wait time in usecs */
-	int32_t		man_dlpireset_time;	/* dlpireset time in usecs */
-} man_t;
-
-/*
- * MAN link state definitions
- */
-#define	MAN_LINKUNKNOWN		0x0
-#define	MAN_LINKINIT		0x1
-#define	MAN_LINKGOOD		0x2
-#define	MAN_LINKSTALE		0x3
-#define	MAN_LINKFAIL		0x4
-
-/*
- * MAN timer types and times.
- */
-#define	MAN_TIMER_INIT		0x1
-#define	MAN_TIMER_LINKCHECK	0x2
-#define	MAN_TIMER_DLPIRESET	0x4
-#define	MAN_INIT_TIME		1000000		/* 1 sec in usecs */
-#define	MAN_LINKCHECK_TIME	30000000	/* 30 secs in usecs */
-#define	MAN_LINKSTALE_TIME	1000000		/* 1 secs in usecs */
-#define	MAN_LINKSTALE_RETRIES	10		/* send 10 probes */
-#define	MAN_KSTAT_WAITTIME	300000		/* 0.3 secs in usecs */
-#define	MAN_DLPIRESET_TIME	5000000		/* 5 secs in usecs */
-#define	MAN_MAX_DLPIERRORS	10		/* 10 dlpi errors */
-
-/*
- * MAN DR variables
- */
-#define	MAN_DR_DELAY		200000		/* 1/5th sec in usecs */
-#define	MAN_DR_RETRIES		150		/* DR retries on EAGAIN errs */
-
-/*
- * Device info - this must stay 64 bit aligned.
- */
-typedef struct md_s {
-	major_t		mdev_major;	/* Driver major */
-	uint32_t	mdev_ppa;	/* Driver instance */
-	uint32_t	mdev_exp_id;	/* Containing expander in domain */
-	uint32_t	mdev_state;	/* Device state */
-} man_dev_t;
-
-/*
- * mdev_state definitions
- */
-#define	MDEV_UNASSIGNED		0x0	/* Path assigned to a destination */
-#define	MDEV_ASSIGNED		0x1	/* Path assigned to a destination */
-#define	MDEV_ACTIVE		0x2	/* Path actively in use for dest */
-#define	MDEV_FAILED		0x4	/* Failure detected in past. */
-
-/*
- * MAN lower multiplexor data structure
- */
-typedef struct man_dest_s {
-	uint_t		md_state;	/* state of this destination */
-	struct manstr_s	*md_msp;	/* containing upper STREAM structure */
-	queue_t		*md_rq;		/* upper read queue */
-	queue_t		*md_wq;		/* lower write queue  for active path */
-	man_dev_t	md_device;	/* Device from active path. */
-	int		md_pg_id;	/* pathgroup for destination */
-	eaddr_t		md_dst_eaddr;	/* Destinations ether address */
-	eaddr_t		md_src_eaddr;	/* Our ether address */
-	int		md_dlpistate;	/* DLPI State of netdev below us */
-	int		md_muxid;	/* muxid of netdev linked below us */
-	void *		md_switch_id;	/* ID of switch request */
-	kmutex_t	md_lock;	/* Lock for md_dmp_* */
-	mblk_t		*md_dmp_head;	/* deferred mblk list head */
-	mblk_t		*md_dmp_tail;	/* deferred mblk list tail */
-	size_t		 md_dmp_count;	/* bytes in deferred mblk list */
-	ulong_t		md_switches;	/* # of failover switches */
-	time_t		md_lastswitch;	/* time of last switch */
-	timeout_id_t	md_bc_id;	/* qbufcall timeout id */
-	/*
-	 * Failover variables, only valid for active path.
-	 */
-	timeout_id_t	md_lc_timer_id;		/* qtimeout ID */
-	int		md_linkstate;		/* link state */
-	ulong_t		md_lastrcvcnt;		/* snapshot of packet count */
-	ulong_t		md_rcvcnt;		/* current packet count */
-	ulong_t		md_linkfails;		/* # of AP link failures */
-	ulong_t		md_linkstales;		/* # of AP link stales */
-	int32_t		md_linkstale_retries;	/* # of probes to send */
-	ulong_t		md_icmpv4probes;	/* # of ICMPv4 probes sent */
-	ulong_t		md_icmpv6probes;	/* # of ICMPv6 probes sent */
-	int		md_link_updown_msg;	/* Last up/down message */
-	int		md_dlpierrors;		/* # of DLPI errors */
-} man_dest_t;
-
-/*
- * md_state values
- */
-#define	MAN_DSTATE_NOTPRESENT	0x0	/* Destination doesnt exist */
-#define	MAN_DSTATE_INITIALIZING	0x1	/* Initialize lower stream for dest */
-#define	MAN_DSTATE_READY	0x2	/* Destination lower stream exists */
-#define	MAN_DSTATE_PLUMBING	0x4	/* lower stream being switched */
-#define	MAN_DSTATE_CLOSING	0x8	/* lower stream closing */
-#define	MAN_DSTATE_BUSY		(MAN_DSTATE_PLUMBING|MAN_DSTATE_CLOSING)
-
-/*
- * md_link_updwon_msg states.
- */
-#define	MAN_LINK_UP_MSG		0x0	/* Last msg emitted was "Link up" */
-#define	MAN_LINK_DOWN_MSG	0x1	/* Last msg emitted was "Link down" */
-
-/*
- * Upper per-stream instance state information.
- *
- * Each instance is dynamically allocated at open() and free'd at close().
- * Each per-stream instance points to at most one per-device structure
- * using the ms_manp field.  All instances are threaded together into one
- * list of active instances ordered on sequence of opens.
- */
-typedef struct manstr_s {
-	struct manstr_s	*ms_next;	/* next in list of streams */
-	man_t		*ms_manp;	/* MAN device info pointer */
-	man_dest_t	*ms_destp;	/* Optimization if only one ms_dests */
-	man_dest_t	*ms_dests;	/* lower streams */
-	int		ms_flags;	/* State for this MAN upper stream */
-	queue_t		*ms_rq;		/* MAN upper read queue */
-	int		ms_minor;	/* minor number of this stream */
-	t_uscalar_t	ms_sap;		/* SAP bound to (if DL_BOUND) */
-	int		ms_dlpistate;	/* DLPI State of this MAN instance */
-	major_t		ms_meta_maj;	/* mxx device major # */
-	int		ms_meta_ppa;	/* mxx device minor # */
-	mblk_t		*ms_dl_mp;	/* list of DLPI ATTACH/BIND rqsts */
-	mblk_t		*ms_dlioc_mp;	/* list of DL_IOC rqsts */
-	uint_t		ms_dp;		/* # of pending DL_DETACH_REQs */
-	ulong_t		ms_switches;	/* number of switches so far	*/
-} manstr_t;
-
-/*
- * ms_flags values.
- */
-#define	MAN_SFLAG_FAST		0x1	/* M_DATA fastpath mode */
-#define	MAN_SFLAG_RAW		0x2	/* M_DATA plain raw mode */
-#define	MAN_SFLAG_ALLPHYS	0x4	/* promiscuous mode */
-#define	MAN_SFLAG_ALLMULTI	0x8	/* enable all multicast addresses */
-#define	MAN_SFLAG_ALLSAP	0x10	/* enable all ether type values */
-#define	MAN_SFLAG_CKSUM		0x20	/* enable hardware tcp checksumming */
-#define	MAN_SFLAG_MULTI		0x40	/* enable multicast addresses */
-#define	MAN_SFLAG_SERLPBK	0x80	/* enable SERDES looopback (DIAG) */
-#define	MAN_SFLAG_MACLPBK	0x100	/* enable MAC int loopback (DIAG) */
-
-#define	MAN_SFLAG_PROMISC	(MAN_SFLAG_ALLPHYS|MAN_SFLAG_ALLMULTI| \
-					MAN_SFLAG_ALLSAP)
-#define	MAN_SFLAG_CLOSING	0x200	/* Stream in process of closing */
-#define	MAN_SFLAG_CLOSE_DONE	0x400	/* Stream in process of closing */
-#define	MAN_SFLAG_CONTROL	0x800	/* Stream is control stream */
-
-/*
- * Paths in pathgroup lists.
- */
-typedef struct mpa_s {
-	struct mpa_s	*mp_next;	/* Next in linked list */
-	man_dev_t	mp_device;	/* Device for this path */
-	kstat_named_t	*mp_last_knp;	/* last named kstats from mp_phys_ksp */
-	time_t		mp_lru;		/* Last time used */
-} man_path_t;
-
-/*
- * Pathgroup list, one per destination ID. Each pathgroup connects
- * to one destination. Hence we put that destination ethernet address
- * here. It is read from here and stored in man_dest_t.md_dst_eaddr
- * each time a new path is switched to.
- */
-typedef struct man_pg_s {
-	struct man_pg_s		*mpg_next;
-	int			mpg_flags;
-	uint_t			mpg_pg_id;
-	uint_t			mpg_man_ppa;	/* MAN instance for pathgroup */
-	eaddr_t			mpg_dst_eaddr;
-	man_path_t		*mpg_pathp;
-} man_pg_t;
-/*
- *  mpg_pg_flags fields.
- */
-#define	MAN_PG_IDLE		0x0
-#define	MAN_PG_SWITCHING	0x1
-
-/*
- * MAN IOCTL Definitions.
- */
-#define	MIOC			('M'<< 16)
-#define	MAN_SETPATH		(MIOC|0x1)
-#define	MAN_GETEADDR		(MIOC|0x2)
-#define	MAN_SET_LINKCHECK_TIME	(MIOC|0x3)
-#define	MAN_SET_SC_IPADDRS	(MIOC|0x4)
-#define	MAN_SET_SC_IP6ADDRS	(MIOC|0x8)
-
-/*
- * Pathgroup assignment data structure - this must stay 64 bit aligned.
- */
-typedef struct mi_path_t {
-	uchar_t		mip_cmd;	/* Cmd for this pathgroup */
-	uchar_t		pad1[3];
-	uint32_t	mip_man_ppa;	/* Man instance to apply cmd to */
-	uint32_t	mip_pg_id;	/* pathgroup ID this path is for */
-	eaddr_t		mip_eaddr;	/* Eaddr for this destination */
-	uchar_t		pad2[2];
-	man_dev_t	mip_devs[MAN_MAX_DESTS]; /* Array of devices */
-	uint32_t	mip_ndevs;	/* #devs at mip_devs */
-} mi_path_t;
-
-#define	MI_PATH_READ		0x0	/* Fill in devs for destID */
-#define	MI_PATH_ASSIGN		0x1	/* Assign devs for destID */
-#define	MI_PATH_ACTIVATE	0x2	/* Mark a dev as active for destID */
-#define	MI_PATH_DEACTIVATE	0x3	/* Deactivate active dev for destID */
-#define	MI_PATH_UNASSIGN	0x4	/* Unassign assigned dev for destID */
-#define	MI_PATH_ADD		0x5	/* Just Add devs for destID */
-
-/*
- * Linkcheck time assignment data structure - this must stay 64 bit aligned.
- */
-typedef struct mi_time_t {
-	int32_t		mtp_man_ppa;	/* Man instance to apply cmd to */
-	int32_t		mtp_time;	/* Time in usecs to */
-} mi_time_t;
-
-/*
- * SC IP address assignment data structure. See man_pinger().
- */
-typedef struct man_sc_ipaddrs_s {
-	in_addr_t	ip_other_sc_ipaddr;
-	in_addr_t	ip_my_sc_ipaddr;
-} man_sc_ipaddrs_t;
-
-/*
- * SC IPv6 address assignment data structure. See man_pinger().
- */
-typedef struct man_sc_ip6addrs_s {
-	in6_addr_t	ip6_other_sc_ipaddr;
-	in6_addr_t	ip6_my_sc_ipaddr;
-} man_sc_ip6addrs_t;
-
-/*
- * Array of dests to apply operation to.
- */
-typedef struct man_adest_s {
-	int		a_man_ppa;	/* man instance */
-	int		a_pg_id;	/* pg_id of dests */
-	uint32_t	a_exp_id;	/* Used for DR requests */
-	man_dev_t	a_sf_dev;	/* Switch from device */
-	man_dev_t	a_st_dev;	/* Switch to device */
-	man_dest_t	*a_mdp;		/* array of dests for mw_type */
-	uint_t		a_ndests;	/* size of array */
-} man_adest_t;
-
-/*
- * work structure for MAN background thread.
- */
-typedef struct man_work_s {
-	struct	man_work_s	*mw_next;	/* next request on q */
-	queue_t			*mw_q;		/* For qwait-ers */
-	int			mw_type;	/* work request type */
-	int			mw_flags;	/* asycn/sync flags */
-	int			mw_status;	/* Status of work request */
-	man_adest_t		mw_arg;		/* work argument */
-	kcondvar_t		mw_cv;		/* sender sleeps here */
-} man_work_t;
-
-/*
- * Values for mw_flags
- */
-#define	MAN_WFLAGS_NOWAITER	0x0
-#define	MAN_WFLAGS_CVWAITER	0x1
-#define	MAN_WFLAGS_QWAITER	0x2
-#define	MAN_WFLAGS_DONE		0x4
-
-/*
- * Values for mw_type.
- */
-#define	MAN_WORK_OPEN_CTL	0x0	/* Open the control stream */
-#define	MAN_WORK_CLOSE_CTL	0x1	/* Open the control stream */
-#define	MAN_WORK_SWITCH		0x2	/* Dest requests switch to new path */
-#define	MAN_WORK_PATH_UPDATE	0x3	/* pathgrp info changed, update dests */
-#define	MAN_WORK_CLOSE		0x4	/* Close destinations */
-#define	MAN_WORK_CLOSE_STREAM	0x5	/* man_close()-ing upper stream */
-#define	MAN_WORK_DRATTACH	0x6	/* DR attached new IO board */
-#define	MAN_WORK_DRDETACH	0x7	/* DR detached an IO board */
-#define	MAN_WORK_STOP		0x8	/* Stop and exit */
-#define	MAN_WORK_DRSWITCH	0x9	/* Switch path prior to DRDETACH */
-#define	MAN_WORK_KSTAT_UPDATE	0xA	/* Take kstat snapshot */
-
-#define	MAN_IDNUM	(13138)		/* module ID number */
-#define	MAN_MINPSZ	(0)		/* min packet size */
-#define	MAN_MAXPSZ	(INFPSZ)	/* max packet size */
-#define	MAN_HIWAT	(64 * 1024)	/* hi-water mark */
-#define	MAN_LOWAT	(1)		/* lo-water mark */
-#define	MAN_MEDIA	"Ethernet"	/* media type */
-
-/*
- * State definitions for man_config_state
- */
-#define	MAN_UNCONFIGURED	0x0		/* Attached but never opened */
-#define	MAN_CONFIGURING		0x1		/* First open */
-#define	MAN_CONFIGURED		0x2		/* Done configuring */
-#define	MAN_FINI		0x3		/* cv_waiting in _fini() */
-
-/*
- * IOSRAM definitions
- */
-#define	MANC_VERSION		0x1
-#define	IOSRAM_KEY_MANC		(('M'<<24)|('A'<<16)|('N'<<8)|'C')
-#define	IOSRAM_KEY_SCMD		(('S'<<24)|('C'<<16)|('M'<<8)|'D')
-#define	IOSRAM_KEY_MDSC		(('M'<<24)|('D'<<16)|('S'<<8)|'C')
-#define	MAN_IOSRAM_TIMEOUT	10000		/* 10 secs in ms */
-
-typedef struct manc_s {
-	uint32_t	manc_magic;		/* MANC_MAGIC */
-	uint32_t	manc_version;		/* MANC_VERSION */
-	uint32_t	manc_csum;		/* TBD */
-	int		manc_ip_type;		/* AF_INET or AF_INET6 */
-	in_addr_t	manc_dom_ipaddr;	/* Domains IP address */
-	in_addr_t	manc_dom_ip_netmask;	/* Domains IP netmask */
-	in_addr_t	manc_sc_ipaddr;		/* SC's IP address */
-	in6_addr_t	manc_dom_ipv6addr;	/* Domain's IPv6 address */
-	in6_addr_t	manc_dom_ipv6_netmask;	/* Domain's IPv6 netmask */
-	in6_addr_t	manc_sc_ipv6addr;	/* SC's IPv6 address */
-	eaddr_t		manc_dom_eaddr;		/* 48 bit ethernet address */
-	eaddr_t		manc_sc_eaddr;		/* 48 bit ethernet address */
-	uint32_t	manc_iob_bitmap;	/* initial ioboard list */
-	uchar_t		manc_golden_iob;	/* post selected ioboard */
-} manc_t;
-
-
-typedef struct man_mb_s {
-	uint32_t		mb_status;
-	uint32_t		mb_exp_id;
-} man_mbox_msg_t;
-
-typedef struct ml_s {
-	struct ml_s	*l_next;
-	int		l_muxid;
-	queue_t		*l_rq;
-	queue_t		*l_wq;
-} man_linkrec_t;
-
-typedef struct man_workq_s {
-	man_work_t	*q_work;
-	kcondvar_t	q_cv;
-	bufcall_id_t	*q_id;
-} man_workq_t;
-
-/*
- * PCI stuff.
- */
-
-/*
- * Misc defines
- */
-#define	MAN_DDI_BUFLEN		128
-#define	MAN_DEVTYPE_PROP	"device_type"
-#define	MAN_REG_PROP		"reg"
-#define	MAN_PORTID_PROP		"portid"
-#define	MAN_DEVTYPE_PCI		"pci"
-#define	MAN_PCI_B_CSR_BASE	0x00700000
-#define	MAN_SCHIZO_MASK		0xF
-#define	MAN_SCHIZO_0_ID		0xC
-
-/* ------------------------------------------------------------------------- */
-/*
- * Patchable debug flag.
- * Set this to nonzero to enable error messages.
- */
-
-/*
- * The following parameters may be configured by the user. If they are not
- * configured by the user, the values will be based on the capabilities of
- * the transceiver.
- * The value "MAN_NOTUSR" is ORed with the parameter value to indicate values
- * which are NOT configured by the user.
- */
-
-/* command */
-
-#define	MAN_ND_GET	ND_GET
-#define	MAN_ND_SET	ND_SET
-#define	MAN_NOTUSR	0x0f000000
-#define	MAN_MASK_1BIT	0x1
-#define	MAN_MASK_2BIT	0x3
-#define	MAN_MASK_8BIT	0xff
-
-typedef struct param_s {
-	uint32_t param_min;
-	uint32_t param_max;
-	uint32_t param_val;
-	char   *param_name;
-} param_t;
-
-#if defined(DEBUG)
-#define	MAN_DBG(flag, msg)	{ if (man_debug&flag) (void) printf msg; }
-#define	MAN_DBGCALL(flag, func)	{ if (man_debug&flag) (void) func; }
-
-#define	MAN_INIT	0x00000001
-#define	MAN_OCLOSE	0x00000002
-#define	MAN_CONFIG	0x00000004
-#define	MAN_SWITCH	0x00000008
-#define	MAN_IOSRAM	0x00000010
-#define	MAN_LINK	0x00000020
-#define	MAN_PATH	0x00000040
-#define	MAN_DEST	0x00000080
-#define	MAN_KSTAT	0x00000100
-#define	MAN_KSTAT2	0x00000200
-#define	MAN_DDI		0x000001FF
-
-#define	MAN_UWPUT	0x00000400
-#define	MAN_LWPUT	0x00000800
-#define	MAN_LRPUT	0x00001000
-#define	MAN_LRPUT2	0x00002000
-#define	MAN_PUT		(MAN_UWPUT | MAN_LWPUT | MAN_LRPUT)
-#define	MAN_UWSRV	0x00004000
-#define	MAN_LWSRV	0x00008000
-#define	MAN_LRSRV	0x00010000
-#define	MAN_DATA	0x00020000
-#define	MAN_DLPI	0x00040000
-#define	MAN_SRV		(MAN_UWSRV | MAN_LWSRV | MAN_LRSRV)
-#define	MAN_STREAMS	(MAN_PUT | MAN_SRV | MAN_OCLOSE)
-
-#define	MAN_CALLS	(MAN_DDI | MAN_STREAMS)
-
-#define	MAN_STATE	0x00080000
-#define	MAN_WARN	0x00100000
-#define	MAN_DEBUG	(MAN_CALLS | MAN_WARN | MAN_STATE)
-#define	MAN_KMEM	0x00200000
-#define	MAN_DR		0x00400000
-#define	MAN_ALL		0xFFFFFFFF
-
-#else
-
-#define	MAN_DBG(flag, msg)
-#define	MAN_DBGCALL(flag, func)
-
-#endif  /* DEBUG */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _DMAN_H */
--- a/usr/src/uts/sun4u/starcat/sys/domaind.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +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 _SYS_DOMAIND_H
-#define	_SYS_DOMAIND_H
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#include <sys/sysmacros.h>
-#include <sys/cpu_sgnblk_defs.h>
-
-typedef struct domain_data {
-	uint32_t	magic;		/* magic number */
-	uint8_t		version;	/* version number */
-	uint8_t		keyswitch;	/* virtual SC keyswitch */
-	uint32_t	master_sc_ip;	/* IP address of master SC */
-	uint32_t	leds;		/* software LEDs */
-	sig_state_t	domain_state;	/* domain state */
-	uint32_t	heartbeat;	/* domain heartbeat */
-	cpuset_t	cpus_present;	/* CPU's present in this domain */
-	sig_state_t	cpu_sigs[NCPU];	/* state for present CPUs */
-	uint32_t	resetinfo_off[NCPU];	/* resetinfo offsets */
-	uint8_t		_reserved[16];	/* word aligned */
-} domain_data_t;
-
-/*
- * Unique ID for domain data IOSRAM chunk
- */
-#define	DOMD_MAGIC	0x444F4D44	/* 'D' 'O' 'M' 'D' */
-
-/*
- * offsets
- */
-#define	DOMD_MAGIC_OFFSET	offsetof(domain_data_t, magic)
-#define	DOMD_VERSION_OFFSET	offsetof(domain_data_t, version)
-#define	DOMD_KEYSWITCH_OFFSET	offsetof(domain_data_t, keyswitch)
-#define	DOMD_SCIP_OFFSET	offsetof(domain_data_t, master_sc_ip)
-#define	DOMD_LEDS_OFFSET	offsetof(domain_data_t, leds)
-#define	DOMD_DSTATE_OFFSET	offsetof(domain_data_t, domain_state)
-#define	DOMD_HEARTBEAT_OFFSET	offsetof(domain_data_t, heartbeat)
-#define	DOMD_CPUSPRESENT_OFFSET	offsetof(domain_data_t, cpus_present)
-#define	DOMD_CPUSIGS_OFFSET	offsetof(domain_data_t, cpu_sigs)
-#define	DOMD_RESETINFO_OFFSET	offsetof(domain_data_t, resetinfo_off)
-
-/*
- * tod
- */
-#define	TODSC_SET_THRESHOLD	30		/* in seconds */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_DOMAIND_H */
--- a/usr/src/uts/sun4u/starcat/sys/dr_mbx.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2000-2002 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_DR_MBX_H
-#define	_SYS_DR_MBX_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#ifdef _KERNEL
-#include <sys/mboxsc.h>
-#endif /* _KERNEL */
-#include <post/scat_const.h>
-
-/* this version of the DR - SC mailbox interface */
-#define	DRMBX_VERSION				0x0016
-
-#define	DR_KEY(a, b, c, d)	\
-	(((uint_t)(a) << 24) | ((uint_t)(b) << 16) \
-	| ((uint_t)(c) <<  8) | ((uint_t)(d)))
-#define	KEY_DRSC		DR_KEY('D', 'R', 'S', 'C')
-#define	KEY_SCDR		DR_KEY('S', 'C', 'D', 'R')
-
-#define	DRSC_TIMEOUT		30
-#define	BD_TYPELEN		16
-#define	DR_HPOPTLEN		512	/* maximum length of hpost options */
-
-/* Commands */
-#define	DRMSG_BOARDEVENT	0x1	/* must be 0x1 in every vesion */
-#define	DRMSG_MBOX_INIT		0x2	/* must be 0x2 in every version */
-#define	DRMSG_ASSIGN		0x3
-#define	DRMSG_UNASSIGN		0x4
-#define	DRMSG_CLAIM		0x5
-#define	DRMSG_UNCLAIM		0x6
-#define	DRMSG_POWERON		0x7
-#define	DRMSG_POWEROFF		0x8
-#define	DRMSG_TESTBOARD		0x9
-#define	DRMSG_ABORT_TEST	0xa
-#define	DRMSG_SHOWBOARD		0xb
-#define	DRMSG_UNCONFIG		0xc
-
-
-/* Test status definitions */
-#define	DR_TEST_STATUS_UNKNOWN	0x1
-#define	DR_TEST_STATUS_IPOST	0x2
-#define	DR_TEST_STATUS_PASSED	0x3
-#define	DR_TEST_STATUS_FAILED	0x4
-#define	DR_TEST_STATUS_ABORTED	0x5
-
-/* Message reply status definitions */
-#define	DRMSG_REPLY_OK		0x0
-#define	DRMSG_REPLY_FAIL	0x1
-
-/* Error Code definitions */
-#define	DRERR_NOACL		0x1	/* Board is not in domain's ACL */
-#define	DRERR_NOT_ASSIGNED	0x2	/* Board isn't assigned to domain */
-#define	DRERR_NOT_ACTIVE	0x3	/* Board is not active */
-#define	DRERR_EMPTY_SLOT	0x4	/* The board (slot) is empty */
-#define	DRERR_POWER_OFF		0x5	/* The specified board is powered off */
-#define	DRERR_TEST_IN_PROGRESS	0x6	/* The board is being tested */
-#define	DRERR_TESTING_BUSY	0x7	/* All SC test resources are in use */
-#define	DRERR_TEST_REQUIRED	0x8	/* Board requires test prior to use */
-#define	DRERR_UNAVAILABLE	0x9	/* Slot is not available to domain */
-#define	DRERR_RECOVERABLE	0xa	/* Failed, may safely retry */
-#define	DRERR_UNRECOVERABLE	0xb	/* Failed, resource unusable */
-
-/*
- *	Protocol Header and message structure definitions
- */
-
-/* DR-SC Protocol Header */
-typedef struct {
-	uint32_t	message_id;
-	uint16_t	drproto_version;
-	uint8_t		command;
-	uint8_t		expbrd;
-	uint8_t		slot;
-	uint8_t		reply_status;
-	uint8_t		error_code;
-	uint8_t		pad[1];		/* explicit pad to 4 byte alignment */
-} dr_proto_hdr_t;
-
-/* Showboard reply structure (from SC) */
-typedef struct {
-	uint8_t		slot_empty	:1,
-			power_on	:1,
-			bd_assigned	:1,
-			bd_active	:1,
-			test_status	:4;
-	uint8_t		test_level;
-	char		board_type[BD_TYPELEN];
-} dr_showboard_t;
-
-/* CPU Memory Controller constants and macros */
-#define	DRMACH_MC_VALID_MASK		(0x1ull		<< 63)
-#define	DRMACH_MC_UK_MASK		(0xFFFull	<< 41)
-#define	DRMACH_MC_UM_MASK		(0x1FFFFFull	<< 20)
-#define	DRMACH_MC_LK_MASK		(0xFull		<< 14)
-#define	DRMACH_MC_LM_MASK		(0xFull		<< 8)
-
-#define	DRMACH_MC_UK(madr)		(((madr) & DRMACH_MC_UK_MASK) >> 41)
-#define	DRMACH_MC_UM_TO_PA(madr)	(((madr) & DRMACH_MC_UM_MASK) << 6)
-#define	DRMACH_MC_LM_TO_PA(madr)	(((madr) & DRMACH_MC_LM_MASK) >> 2)
-#define	DRMACH_MC_PA_TO_UM(pa)		(((pa) >> 6) & DRMACH_MC_UM_MASK)
-#define	DRMACH_MC_PA_TO_LM(pa)		(((pa) << 2) & DRMACH_MC_LM_MASK)
-
-/* Claim/Unclaim/Unconfig request structures */
-typedef struct {
-	uint8_t	valid	:1,
-		unused	:2,
-		slice	:5;
-} dr_memslice_t;
-
-/*
- * Since uint64_t can't be used in DR mailbox messages due to alignment and
- * backwards compatibility issues, the 64 bit MADR and MACR register values must
- * be broken into high and low uint32_t values.
- */
-#define	DRMACH_MCREG_TO_U64(mcreg)	(((uint64_t)mcreg.hi) << 32 | \
-						((uint64_t)mcreg.lo))
-#define	DRMACH_U64_TO_MCREGHI(u64)	((uint32_t)((u64) >> 32))
-#define	DRMACH_U64_TO_MCREGLO(u64)	((uint32_t)(u64))
-typedef struct {
-	uint32_t	hi;
-	uint32_t	lo;
-} dr_mcreg_t;
-
-/*
- * Each expander can contain S0_LPORT_COUNT memory controllers (each CPU has one
- * memory controller, and slot 1 doesn't support memory), and each controller
- * contains PMBANKS_PER_PORT * LMBANKS_PER_PMBANK (the total number of memory
- * banks supported by each controller) MADR registers
- */
-typedef struct {
-	dr_mcreg_t	madr[S0_LPORT_COUNT][PMBANKS_PER_PORT *
-				LMBANKS_PER_PMBANK];
-} dr_memregs_t;
-
-typedef struct {
-	dr_memslice_t	mem_slice[18];
-	uint8_t		mem_clear;
-	uint8_t		pad[1];		/* explicit pad to 4 byte alignment */
-	dr_memregs_t	mem_regs[18];
-} dr_unclaim_t;
-
-typedef struct {
-	dr_memslice_t	mem_slice[18];
-	uint8_t		pad[2];		/* explicit pad to 4 byte alignment */
-	dr_memregs_t	mem_regs[18];
-} dr_claim_t;
-
-typedef struct {
-	dr_memslice_t	mem_slice[18];
-	uint8_t		pad[2];		/* explicit pad to 4 byte alignment */
-	dr_memregs_t	mem_regs[18];
-} dr_unconfig_t;
-
-/* CPU Portid macros */
-#define	DRMBX_PORTID2EXP(cpu_portid) \
-	(((cpu_portid) >> 5) & 0x1F)
-#define	DRMBX_PORTID2SLOT(cpu_portid) \
-	(((((cpu_portid) >> 4) & 0x7E) | (((cpu_portid) >> 3) & 0x01)) & 1)
-#define	DRMBX_PORTID2AGID(cpu_portid)	((cpu_portid) & 0x1F)
-
-/* Test board request structure */
-typedef struct {
-	uint32_t	memaddrhi;
-	uint32_t	memaddrlo;
-	uint32_t	memlen;
-	uint16_t	cpu_portid;
-	uint8_t		force		:1,
-			immediate 	:1,
-			reserved 	:6;
-	char		hpost_opts[DR_HPOPTLEN];
-} dr_testboard_req_t;
-
-/* Test board reply structure (from SC) */
-typedef struct {
-	uint32_t	memaddrhi;
-	uint32_t	memaddrlo;
-	uint32_t	memlen;
-	uint16_t	cpu_portid;
-	uint8_t		cpu_recovered	:1,
-			test_status 	:4,
-			reserved 	:3;
-} dr_testboard_reply_t;
-
-/* Test Abort structure (bi-directional) */
-typedef struct {
-	uint32_t	memaddrhi;
-	uint32_t	memaddrlo;
-	uint32_t	memlen;
-	uint16_t	cpu_portid;
-} dr_abort_test_t;
-
-
-/* Board event structure (from SC) */
-typedef struct {
-	uint16_t	initialized	:1,
-			board_insertion	:1,
-			board_removal	:1,
-			slot_assign	:1,
-			slot_unassign	:1,
-			slot_avail	:1,
-			slot_unavail	:1,
-			power_on	:1,
-			power_off	:1,
-			reserved	:7;
-} dr_boardevent_t;
-
-/*
- * NOTE: The structures in this union all require 4 byte alignment or less.  It
- * is forbidden to add any structure that requires 8 byte alignment, as doing so
- * will alter the dr_mbox_msg_t structure, thereby breaking compatibility with
- * older software.  (Since the dr_proto_hdr_t structure is 12 bytes long, it
- * can't be followed immediately by an 8 byte aligned structure, and the
- * compiler will implicitly insert 4 padding bytes.)
- */
-typedef union {
-	dr_showboard_t		dm_sb;
-	dr_unclaim_t		dm_ur;
-	dr_claim_t		dm_cr;
-	dr_unconfig_t		dm_uc;
-	dr_testboard_req_t	dm_tb;
-	dr_testboard_reply_t	dm_tr;
-	dr_abort_test_t		dm_ta;
-	dr_boardevent_t		dm_be;
-} dr_msg_t;
-
-typedef struct {
-	dr_proto_hdr_t		p_hdr;
-	dr_msg_t		msgdata;
-} dr_mbox_msg_t;
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _SYS_DR_MBX_H */
--- a/usr/src/uts/sun4u/starcat/sys/drmach.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +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/sbd_ioctl.h>
-#include <sys/sysevent.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Starcat platform specific routines currently only defined
- * in starcat.c and referenced by DR.
- */
-extern int	plat_max_boards();
-extern int	plat_max_cpu_units_per_board();
-extern int	plat_max_io_units_per_board();
-
-#define	MAX_BOARDS		plat_max_boards()
-#define	MAX_CPU_UNITS_PER_BOARD	plat_max_cpu_units_per_board()
-#define	MAX_MEM_UNITS_PER_BOARD	1
-#define	MAX_IO_UNITS_PER_BOARD	plat_max_io_units_per_board()
-#define	MAX_CMP_UNITS_PER_BOARD	4
-#define	MAX_CORES_PER_CMP	2
-
-/* 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_CMP	"cmp"
-#define	DRMACH_DEVTYPE_CPU	"cpu"
-#define	DRMACH_DEVTYPE_MEM	"memory"
-#define	DRMACH_DEVTYPE_PCI	"pci"
-#define	DRMACH_DEVTYPE_SBUS	"sbus"
-#define	DRMACH_DEVTYPE_WCI	"wci"
-
-/* 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_ */
--- a/usr/src/uts/sun4u/starcat/sys/gptwo_pci.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_GPTWO_PCI_H
-#define	_SYS_GPTWO_PCI_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Header file for the PCI/Schizo component to the
- * Safari Configurator (gptwo_cpu).
- */
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#include <sys/safari_pcd.h>
-
-gptwocfg_ops_cookie_t gptwocfg_alloc_pci_ops(int, int);
-gptwo_new_nodes_t *gptwo_configure_pci(dev_info_t *, spcd_t *, uint_t);
-dev_info_t *gptwo_prepare_pci(dev_info_t *);
-dev_info_t *gptwo_unconfigure_pci(dev_info_t *);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_GPTWO_PCI_H */
--- a/usr/src/uts/sun4u/starcat/sys/iosramio.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_IOSRAMIO_H
-#define	_SYS_IOSRAMIO_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-
-/*
- * data_valid flag values
- */
-#define	IOSRAM_DATA_INVALID	0
-#define	IOSRAM_DATA_VALID	1
-
-/*
- * int_pending flag values
- */
-#define	IOSRAM_INT_NONE		0
-#define	IOSRAM_INT_TO_SSC	1
-#define	IOSRAM_INT_TO_DOM	2
-
-/*
- * IOSRAM control commands, for use in iosram_ctrl().
- */
-#define	IOSRAM_CMD_CHUNKLEN			1
-
-/*
- * IOSRAM header control commands, for use in iosram_hdr_ctrl _only_ by the
- * Mailbox Protocol implementation
- */
-#define	IOSRAM_HDRCMD_GET_SMS_MBOX_VER		1
-#define	IOSRAM_HDRCMD_SET_OS_MBOX_VER		2
-#define	IOSRAM_HDRCMD_REG_CALLBACK		3
-
-/*
- * Extern prototypes for kernel drivers/modules
- */
-extern int iosram_rd(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr);
-extern int iosram_wr(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr);
-extern int iosram_force_write(uint32_t key, uint32_t off, uint32_t len,
-	caddr_t dptr);
-extern int iosram_get_flag(uint32_t key, uint8_t *data_valid,
-	uint8_t *int_pending);
-extern int iosram_set_flag(uint32_t key, uint8_t data_valid,
-	uint8_t int_pending);
-extern int iosram_send_intr();
-extern int iosram_register(uint32_t key, void (*handler)(), void *arg);
-extern int iosram_unregister(uint32_t key);
-extern int iosram_ctrl(uint32_t key, uint32_t cmd, void *arg);
-
-/*
- * This function is only intended to be called by DR.
- */
-extern int iosram_switchfrom(int instance);
-
-/*
- * The following functions are only to be used by the Mailbox Protocol
- * implementation.
- */
-extern int iosram_sema_acquire(uint32_t *);
-extern int iosram_sema_release(void);
-extern int iosram_hdr_ctrl(uint32_t cmd, void *arg);
-
-
-#if defined(DEBUG)
-
-/*
- * ioctls for testing purposes only
- */
-
-#define	IOSRAM_IOC			('i' << 8)
-
-#define	IOSRAM_RD		(int)(IOSRAM_IOC|1)
-#define	IOSRAM_WR		(int)(IOSRAM_IOC|2)
-#define	IOSRAM_GET_FLAG		(int)(IOSRAM_IOC|3)
-#define	IOSRAM_SET_FLAG		(int)(IOSRAM_IOC|4)
-#define	IOSRAM_TOC		(int)(IOSRAM_IOC|5)
-#define	IOSRAM_SEND_INTR	(int)(IOSRAM_IOC|6)
-#define	IOSRAM_REG_CBACK	(int)(IOSRAM_IOC|7)
-#define	IOSRAM_UNREG_CBACK	(int)(IOSRAM_IOC|8)
-#define	IOSRAM_PRINT_CBACK	(int)(IOSRAM_IOC|9)
-#define	IOSRAM_PRINT_STATE	(int)(IOSRAM_IOC|10)
-#define	IOSRAM_PRINT_LOG	(int)(IOSRAM_IOC|11)
-#define	IOSRAM_PRINT_FLAGS	(int)(IOSRAM_IOC|12)
-#define	IOSRAM_TUNNEL_SWITCH	(int)(IOSRAM_IOC|13)
-#define	IOSRAM_PRINT_STATS	(int)(IOSRAM_IOC|14)
-#define	IOSRAM_SEMA_ACQUIRE	(int)(IOSRAM_IOC|15)
-#define	IOSRAM_SEMA_RELEASE	(int)(IOSRAM_IOC|16)
-
-
-/*
- * struct iosram_io:
- *	Used for testing purposes to invoke IOSRAM internal
- *	interface from user level via ioctl() interface.
- */
-typedef struct iosram_io {
-	uint32_t cmd;		/* read or write */
-	uint32_t key;		/* IOSRAM chunk key */
-	uint32_t off;		/* offset within IOSRAM chunk */
-	uint32_t len;		/* size of read or write */
-	uint32_t bufp;		/* buffer pointer */
-	uint32_t retval;	/* provided by driver */
-	uint32_t data_valid;	/* flag being get/set */
-	uint32_t int_pending;	/* flag being get/set */
-} iosram_io_t;
-
-#endif /* DEBUG */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_IOSRAMIO_H */
--- a/usr/src/uts/sun4u/starcat/sys/iosramreg.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_IOSRAMREG_H
-#define	_SYS_IOSRAMREG_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-
-
-/*
- * iosram_reg_t property  (an array of following tuple/data)
- *	address format
- *	  hi  npt000ss  bbbbbbbb  dddddfff  rrrrrrrr
- *	 mid  hhhhhhhh  hhhhhhhh  hhhhhhhh  hhhhhhhh
- *	 low  llllllll  llllllll  llllllll  llllllll
- *
- *	size format
- *	  hi  hhhhhhhh  hhhhhhhh  hhhhhhhh  hhhhhhhh
- *	 low  llllllll  llllllll  llllllll  llllllll
- *	 n=0 if relocatable
- *	 p=1 if addressable region is prefetchable
- *	 t=1 if address region is aliased
- *	 ss=00 Config. space also n,p,t must be 0
- *	   =01 I/O space p must be 0
- *	   =10 32 bit address memory space
- *	   =11 64 bit address memory space
- *	 bbbbbbbb 8 bit bus number
- *	 ddddd 5 bit device number
- *	 fff 3 bit function number
- *	 rrrrrrrr 8 bit register number
- *	 hhhhhhhh 32 bit unsigned number
- *	 llllllll 32 bit unsigned number
- *
- *	 address: 64 bits memory space
- *	  hi 00000011  00000000  00000000  00000000
- *	     0x03000000
- *	 mid 00000000  00000000  00000000  00000000
- *	     0x00000000
- *	 low 00000000  00010000  00000000  00000000
- *	     0x00100000
- *	 size
- *	  hi 00000000  00000000  00000000  00000000
- *	 low 00000000  00000011  11111111  11111111
- */
-
-typedef struct {
-	uint32_t	addr_hi;
-	uint32_t	addr_lo;
-	uint32_t	size;
-} iosram_reg_t;
-
-
-/*
- * SBBC access structures.  Each SBBC register is 32 bits aligned on a 16
- * byte boundary.  The iosram_sbbc_region structure should be mapped onto
- * the SBBC register space starting at 0x1000 to achieve correct alignment
- * between structure fields and SBBC registers.
- */
-typedef struct iosram_sbbcr {
-	uint32_t	reg;		/* 32-bit register */
-	uint32_t	pad[3];		/* padding to fill out 16 bytes */
-} iosram_sbbcr_t;
-
-typedef struct iosram_sbbc_region {
-	iosram_sbbcr_t	synch[16];	/* 0x1000 - 10ff - semaphore region */
-	iosram_sbbcr_t	pad0[240];	/* 0x1100 - 1fff - padding */
-	iosram_sbbcr_t	p0_int_gen;	/* 0x2000 - 200f - PCI port 0 */
-					/*    interrupt generation */
-	iosram_sbbcr_t	p1_int_gen;	/* 0x2010 - 201f - PCI port 1 */
-					/*    interrupt generation */
-	iosram_sbbcr_t	pad1[48];	/* 0x2020 - 231f - padding */
-	iosram_sbbcr_t	int_status;	/* 0x2320 - 232f - interrupt status */
-	iosram_sbbcr_t	int_enable;	/* 0x2330 - 233f - interrupt enables */
-} iosram_sbbc_region_t;
-
-#define	IOSRAM_SBBC_MAP_OFFSET	0x1000	/* offset of SBBC regs to be mapped */
-#define	IOSRAM_SBBC_MAP_INDEX   0x1	/* address space set # for SBBC regs */
-#define	IOSRAM_SBBC_INT0	0x01
-#define	IOSRAM_SBBC_INT1	0x10
-
-/*
- * SBBC hardware semaphore access
- */
-
-/* indices into sbbc_region->synch array */
-#define	IOSRAM_SEMA_SMS_IDX	0x1	/* when accessed by SMS */
-#define	IOSRAM_SEMA_DOM_IDX	0x8	/* when accessed by domain */
-#define	IOSRAM_SEMA_OBP_IDX	0xf	/* when accessed by OBP */
-
-/* mask for bits used to encode how semaphore was acquired (bits 1-4) */
-#define	IOSRAM_SEMA_MASK	0x1e
-
-/* read an write semaphore values using domain assigned register */
-#define	IOSRAM_SEMA_RD(softp)	ddi_get32((softp)->sbbc_handle, \
-	&(softp->sbbc_region->synch[IOSRAM_SEMA_DOM_IDX].reg));
-#define	IOSRAM_SEMA_WR(softp, v) ddi_put32((softp)->sbbc_handle, \
-	&(softp->sbbc_region->synch[IOSRAM_SEMA_DOM_IDX].reg), v);
-
-#define	IOSRAM_SEMA_IS_HELD(v)	((v) & 0x1)
-#define	IOSRAM_SEMA_GET_IDX(v)	(((v) & IOSRAM_SEMA_MASK) >> 1)
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_IOSRAMREG_H */
--- a/usr/src/uts/sun4u/starcat/sys/iosramvar.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_IOSRAMVAR_H
-#define	_SYS_IOSRAMVAR_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Data sizes used by the original author
- */
-#ifndef UINT32SZ
-#define	UINT32SZ	sizeof (uint32_t)
-#define	UINT64SZ	sizeof (uint64_t)
-#endif
-
-/*
- * Values used for tunnel switching
- */
-#define	OBP_TSWITCH_REQREPLY	0		/* request reply from SSC */
-#define	OBP_TSWITCH_NOREPLY	1		/* don't wait for reply */
-#define	IOSRAM_TSWITCH_RETRY	20		/* # of times to wait for */
-						/*   current tunnel switch to */
-						/*   end when starting a new */
-						/*   one */
-/*
- * When performing back-to-back tunnel switches, we have to make sure that
- * HWAD (the SC-side implementation) has time to find the new tunnel from
- * one switch before we invalidate it for the next switch.  To ensure that,
- * we make sure that the time between consecutive tunnel switches is at
- * least twice the polling rate HWAD uses to detect the new tunnel.
- */
-#define	IOSRAM_TSWITCH_DELAY_US	100000
-
-/*
- * Values used for hash table maintenance
- */
-#define	IOSRAM_HASHSZ	0x20		/* # hash entries */
-#define	IOSRAM_HASH(key)	((((key) >> 24) ^ ((key) >> 16) ^\
-				((key) >> 9) ^ (key)) & (IOSRAM_HASHSZ - 1))
-
-/*
- * A pair of flags is associated with each IOSRAM chunk in the IOSRAM TOC.
- * These flags are stored sequentially in the "SC Domain Communication Data"
- * ('SDCD') IOSRAM chunk.  The data-valid/int-pending flags are one byte each
- * and stored sequentially with data-valid flag being the first.  The following
- * macros define the offset of the flags for each IOSRAM chunk based upon its
- * location (index) in the IOSRAM TOC.
- */
-#define	IOSRAM_DATAVALID_FLAGOFF(index)		(2 * (index))
-#define	IOSRAM_INTPENDING_FLAGOFF(index)	(2 * (index) + 1)
-
-/*
- * IOSRAM node properties (per IOSRAM node)
- */
-#define	IOSRAM_REG_PROP		"reg"
-#define	IOSRAM_TUNNELOK_PROP	"tunnel-capable"
-
-/*
- * Other IOSRAM properties (on chosen node and parent hierarchy)
- */
-#define	IOSRAM_CHOSEN_PROP	"iosram"
-#define	IOSRAM_PORTID_PROP	"portid"
-
-/*
- * Interrupt priority (PIL) used for IOSRAM interrupts.  The value 5 was
- * chosen somewhat arbitrarily based on the fact that it is higher than
- * disks and lower than networks.
- */
-#define	IOSRAM_PIL	5
-
-/*
- * IOSRAM header structure, located at the beginning of IOSRAM.
- *
- * NOTE - New fields may be appended to this structure, but no existing fields
- *        may be altered in any way!!!
- */
-typedef struct {
-	uint32_t	status;
-	uint32_t	version;
-	uint32_t	toc_offset;
-	uint32_t	sms_mbox_version;
-	uint32_t	os_mbox_version;
-	uint32_t	obp_mbox_version;
-	uint32_t	sms_change_mask;
-	uint32_t	os_change_mask;
-} iosram_hdr_t;
-
-/*
- * Values for the status field
- */
-#define	IOSRAM_INVALID		0x494e5644	/* 'INVD' */
-#define	IOSRAM_VALID		0x56414c44	/* 'VALD' */
-#define	IOSRAM_INTRANSIT	0x494e5452	/* 'INTR' */
-
-/*
- * Maximum IOSRAM Protocol version understood by this implementation
- */
-#define	IOSRAM_MAX_PROTOCOL_VERSION		1
-
-/*
- * Bit definitions for *_change_mask fields
- */
-#define	IOSRAM_HDRFIELD_SMS_MBOX_VER	0x00000001
-#define	IOSRAM_HDRFIELD_OS_MBOX_VER	0x00000002
-#define	IOSRAM_HDRFIELD_TOC_INDEX	0x00000004
-
-/*
- * Macros used to access fields in the header
- */
-#define	IOSRAM_GET_HDRFIELD32(softp, field)	\
-	(ddi_get32((softp)->handle, &((iosram_hdr_t *)(softp)->iosramp)->field))
-#define	IOSRAM_SET_HDRFIELD32(softp, field, val)	\
-	(ddi_put32((softp)->handle, &((iosram_hdr_t *)(softp)->iosramp)->field,\
-	(val)))
-
-/*
- * IOSRAM contains various data chunks and the key, location and size of
- * each IOSRAM chunk is communicated to the IOSRAM driver in the form of a
- * Table of Contents.  This structre contains one entry for each IOSRAM
- * chunk, as well as an initial index entry.  Each entry has the following
- * structure.
- *
- * NOTE - Although the unused field may be renamed for some use in the future,
- *        no other modification to this structure is allowed!!!
- */
-
-typedef struct {
-	uint32_t	key;		/* IOSRAM chunk key */
-	uint32_t	off;		/* IOSRAM chunk starting offset */
-	uint32_t	len;		/* IOSRAM chunk length */
-	uint32_t	unused;		/* currently unused */
-} iosram_toc_entry_t;
-
-/*
- * Special values used in some TOC entries
- */
-#define	IOSRAM_FLAGS_KEY	0x53444344	/* 'SDCD' - flags chunk key */
-#define	IOSRAM_INDEX_KEY	0x494e4458	/* 'INDX' - index entry key */
-#define	IOSRAM_INDEX_OFF	0xFFFFFFFF	/* index entry offset */
-
-
-/*
- * IOSRAM flags structure.  An array of these - one for every IOSRAM chunk - is
- * stored in the SDCD chunk.
- */
-typedef struct {
-	uint8_t	data_valid;
-	uint8_t	int_pending;
-} iosram_flags_t;
-
-/*
- * IOSRAM callback data structure
- */
-typedef struct {
-	uchar_t		busy;		/* cback handler is active/busy */
-	uchar_t		unregister;	/* delayed callback unregistration */
-	void		(*handler)();	/* cback handler */
-	void		*arg;		/* cback handler arg */
-} iosram_cback_t;
-
-
-/*
- * IOSRAM per chunk state
- */
-typedef struct iosram_chunk {
-	iosram_toc_entry_t toc_data;	/* Data from TOC entry */
-	iosram_cback_t	cback;		/* callback info */
-	uint8_t		*basep;		/* kvaddr for this IOSRAM chunk */
-	iosram_flags_t	*flagsp;
-	struct iosram_chunk *hash;	/* next entry in the hash list */
-} iosram_chunk_t;
-
-
-/*
- * IOSRAM per instance state
- */
-
-typedef struct iosramsoft {
-	struct iosramsoft *prev;	/* ptr for linked list */
-	struct iosramsoft *next;	/* ptr for linked list */
-
-	boolean_t	suspended;	/* TRUE if driver suspended */
-	int		instance;	/* driver instance number */
-	dev_info_t	*dip;		/* device information */
-
-	uchar_t		*iosramp;	/* IOSRAM mapped vaddr */
-	int		iosramlen; 	/* IOSRAM length */
-	int		nchunks;	/* # IOSRAM chunks */
-	iosram_chunk_t	*chunks;	/* ptr to iosram_chunk array */
-	iosram_chunk_t	*flags_chunk;	/* ptr to flags chunk */
-	ddi_acc_handle_t handle;	/* IOSRAM map handle */
-
-	ddi_iblock_cookie_t real_iblk;	/* real intr iblock cookie */
-	ddi_iblock_cookie_t soft_iblk;	/* soft intr iblock cookie */
-	ddi_softintr_t	softintr_id;	/* soft interrupt ID */
-	ushort_t	intr_busy;	/* softintr handler busy */
-	ushort_t	intr_pending;	/* interrupt pending */
-
-	int		state;		/* IOSRAM state (see below) */
-	int		portid;		/* Card port ID for tswitch */
-	uint32_t	tswitch_ok;	/* # successful tunnel switch */
-	uint32_t	tswitch_fail;	/* # failed tunnel switch */
-
-	ddi_acc_handle_t sbbc_handle;	/* SBBC regs map handle */
-	iosram_sbbc_region_t *sbbc_region; /* region of SBBC registers */
-	uint32_t	int_enable_sav;	/* save int enable reg. on suspend */
-	kmutex_t	intr_mutex;	/* real interrupt handler mutex */
-} iosramsoft_t;
-
-
-/* IOSRAM state value */
-#define	IOSRAM_STATE_INIT	0x0001	/* initialization */
-#define	IOSRAM_STATE_SLAVE	0x0002	/* SLAVE IOSRAM */
-#define	IOSRAM_STATE_MASTER	0x0004	/* MASTER IOSRAM */
-#define	IOSRAM_STATE_MAPPED	0x0008	/* IOSRAM mapped */
-
-#define	IOSRAM_STATE_TSWITCH	0x0010	/* tunnel switch source/target */
-#define	IOSRAM_STATE_DETACH	0x0020	/* IOSRAM instance being detached */
-
-
-#if DEBUG
-#define	IOSRAM_STATS	1		/* enable IOSRAM statistics */
-#define	IOSRAM_LOG	1		/* enable IOSRAM logging */
-#endif
-
-#if IOSRAM_STATS
-
-/*
- * IOSRAM statistics
- */
-struct iosram_stat {
-	uint32_t	read;		/* calls to iosram_read */
-	uint32_t	write;		/* calls to iosram_{force_}write */
-	uint32_t	getflag;	/* calls to iosram_getflag */
-	uint32_t	setflag;	/* calls to iosram_getflag */
-	uint32_t	tswitch;	/* # tunnel switch */
-	uint32_t	callbacks;	/* # callbacks invoked */
-	uint32_t	intr_recv;	/* # interrupts received */
-	uint32_t	sintr_recv;	/* # softintr received */
-	uint32_t	intr_send;	/* # interrupts sent */
-	uint64_t	bread;		/* # bytes read */
-	uint64_t	bwrite;		/* # bytes written */
-};
-
-#define	IOSRAM_STAT(field)		iosram_stats.field++
-#define	IOSRAM_STAT_ADD(field, amount)	iosram_stats.field += (uint64_t)amount
-#define	IOSRAM_STAT_SET(field, count)	iosram_stats.field = (uint64_t)count
-
-#else /* !IOSRAM_STATS */
-
-#define	IOSRAM_STAT(field)
-#define	IOSRAM_STAT_ADD(field, amount)
-#define	IOSRAM_STAT_SET(field, count)
-
-#endif /* !IOSRAM_STATS */
-
-
-#if IOSRAM_LOG
-
-/*
- * IOSRAM log related structures and extern declarations
- */
-
-#define	IOSRAM_MAXLOG	64
-
-typedef struct {
-	uint32_t	seq;		/* logseg# */
-	clock_t		tstamp;		/* time stamp */
-	caddr_t		fmt;		/* format ptr */
-	intptr_t 	arg1;		/* first arg */
-	intptr_t 	arg2;		/* second arg */
-	intptr_t 	arg3;		/* third arg */
-	intptr_t 	arg4;		/* fourth arg */
-} iosram_log_t;
-
-#define	IOSRAMLOG(level, fmt, a1, a2, a3, a4)			\
-	if (iosram_log_level >= level) {			\
-		iosram_log(fmt, (intptr_t)a1, (intptr_t)a2, 	\
-			(intptr_t)a3, (intptr_t)a4);		\
-	}
-
-extern int	iosram_log_level;
-extern uint32_t	iosram_logseq;
-extern iosram_log_t iosram_logbuf[IOSRAM_MAXLOG];
-extern void iosram_log(caddr_t, intptr_t, intptr_t, intptr_t, intptr_t);
-
-#else	/* !IOSRAM_LOG */
-
-#define	IOSRAMLOG(level, fmt, a1, a2, a3, a4)
-
-#endif	/* !IOSRAM_LOG */
-
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_IOSRAMVAR_H */
--- a/usr/src/uts/sun4u/starcat/sys/mboxsc.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_MBOXSC_H
-#define	_MBOXSC_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This file defines the Starcat Domain Mailbox Interface, as implemented in
- * the mboxsc module.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-
-/*
- * Mailbox message types, for use in mboxsc_putmsg() and mboxsc_getmsg() calls.
- * NOTE: Clients should not use the MBOXSC_NUM_MSG_TYPES value, which
- *       is used internally to simplify future code maintenance.
- */
-
-#define	MBOXSC_MSG_REQUEST	0x01
-#define	MBOXSC_MSG_REPLY	0x02
-#define	MBOXSC_MSG_EVENT	0x04
-#define	MBOXSC_NUM_MSG_TYPES	3
-
-/*
- * Mailbox directions, for use in mboxsc_init().
- */
-#define	MBOXSC_MBOX_IN		0
-#define	MBOXSC_MBOX_OUT		1
-
-
-#ifdef _KERNEL
-/*
- * Mailbox control commands, for use in mboxsc_ctrl().
- */
-#define	MBOXSC_CMD_VERSION			1
-#define	MBOXSC_CMD_MAXVERSION			2
-#define	MBOXSC_CMD_MAXDATALEN			3
-#define	MBOXSC_CMD_PUTMSG_TIMEOUT_RANGE		4
-#define	MBOXSC_CMD_GETMSG_TIMEOUT_RANGE		5
-
-/*
- * The argument for the TIMEOUT_RANGE control commands is a pointer to one of
- * these.
- */
-typedef struct mboxsc_timeout_range {
-	clock_t min_timeout;
-	clock_t max_timeout;
-} mboxsc_timeout_range_t;
-
-/*
- * Mailbox interface functions available to in-kernel clients on Starcat
- * Domains.
- * NOTE: The timeout arguments to mboxsc_putmsg() and mboxsc_getmsg() are
- *       interpreted as milliseconds.
- */
-extern int mboxsc_init(uint32_t key, int direction, void
-	(*event_handler)(void));
-extern int mboxsc_fini(uint32_t key);
-extern int mboxsc_putmsg(uint32_t key, uint32_t type, uint32_t cmd,
-	uint64_t *transid, uint32_t length, void *datap, clock_t timeout);
-extern int mboxsc_getmsg(uint32_t key, uint32_t *type, uint32_t *cmd,
-	uint64_t *transid, uint32_t *length, void *datap, clock_t timeout);
-extern int mboxsc_ctrl(uint32_t key, uint32_t cmd, void *arg);
-extern clock_t mboxsc_putmsg_def_timeout(void);
-#define	MBOXSC_PUTMSG_DEF_TIMEOUT	mboxsc_putmsg_def_timeout()
-
-#ifdef DEBUG
-/*
- * The following commands may be passed in to the mboxsc_debug() function to
- * dump data to the console that wouldn't be available through normal
- * (non-debug) functions.
- */
-#define	MBOXSC_PRNMBOX		1	/* display a particular mailbox */
-#define	MBOXSC_PRNHASHTBL	2	/* display the whole hash table */
-#define	MBOXSC_SETDBGMASK	3	/* set the debug mask */
-
-/*
- * Debugging interface routine.
- */
-extern int mboxsc_debug(int cmd, void *arg);
-
-#endif /* DEBUG */
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MBOXSC_H */
--- a/usr/src/uts/sun4u/starcat/sys/mboxsc_impl.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_MBOXSC_IMPL_H
-#define	_MBOXSC_IMPL_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This file contains implementation details for the mboxsc API that need to
- * be shared amongst all implementations, but should be hidden from clients.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Version number of the current Mailbox Protocol implementation.  This must
- * be updated whenever a new version of the Protocol is implemented.
- */
-#define	MBOXSC_PROTOCOL_VERSION	1
-
-/*
- * Mailbox message header and checksum.
- */
-typedef struct {
-	uint32_t	msg_version;
-	uint32_t	msg_type;
-	uint32_t	msg_cmd;
-	uint32_t	msg_length;
-	uint64_t	msg_transid;
-} mboxsc_msghdr_t;
-
-typedef uint32_t	mboxsc_chksum_t;
-
-/*
- * Constants for various aspects of the protocol.
- */
-#define	MBOXSC_MSGHDR_SIZE	(sizeof (mboxsc_msghdr_t))
-#define	MBOXSC_CHKSUM_SIZE	(sizeof (mboxsc_chksum_t))
-#define	MBOXSC_PROTOCOL_SIZE	(MBOXSC_MSGHDR_SIZE + MBOXSC_CHKSUM_SIZE)
-#define	MBOXSC_MSGHDR_OFFSET	(0)
-#define	MBOXSC_DATA_OFFSET	MBOXSC_MSGHDR_SIZE
-
-/*
- * Timeouts used for various mboxsc operations.  All timeouts are provided
- * in microseconds.
- * XXX - Aside from the conversion factors, these values are currently
- *       somewhat arbitrary, and may need significant modification.
- */
-#define	MBOXSC_USECS_PER_SECOND		(1000000L)
-#define	MBOXSC_USECS_PER_MSEC		(1000L)
-
-/*
- * The amount of time to sleep before retrying an IOSRAM operation that failed
- * because a tunnel switch was in progress.
- * Current value: 0.125 seconds
- */
-#define	MBOXSC_EAGAIN_POLL_USECS	(MBOXSC_USECS_PER_SECOND / 8)
-
-/*
- * The interval at which the data_valid flag should be polled for a change in
- * status after sending a message.
- * Current value: 0.010 seconds
- */
-#define	MBOXSC_PUTMSG_POLL_USECS	(MBOXSC_USECS_PER_SECOND / 100)
-
-/*
- * The polling rates for acquisition of the hardware lock used to synchronize
- * data_valid flag access.
- * Current values: 0.025 seconds
- */
-#define	MBOXSC_HWLOCK_POLL_USECS 	(MBOXSC_USECS_PER_SECOND / 40)
-
-/*
- * Minimum, default, and maximum times for mboxsc_putmsg to spend trying to send
- * a message before giving up.
- * Current value: 0.050, 10, and 1800 seconds, respectively
- *                1800 seconds (30 minutes) is a few minutes shy of the maximum
- *                value of a clock_t in units of microseconds.
- */
-#define	MBOXSC_PUTMSG_MIN_TIMEOUT_USECS	(MBOXSC_USECS_PER_SECOND / 20)
-#define	MBOXSC_PUTMSG_DEF_TIMEOUT_USECS	(MBOXSC_USECS_PER_SECOND * 10)
-#define	MBOXSC_PUTMSG_MAX_TIMEOUT_USECS	(MBOXSC_USECS_PER_SECOND * 60 * 30)
-
-#define	MBOXSC_PUTMSG_MIN_TIMEOUT_MSECS \
-	(MBOXSC_PUTMSG_MIN_TIMEOUT_USECS / MBOXSC_USECS_PER_MSEC)
-#define	MBOXSC_PUTMSG_DEF_TIMEOUT_MSECS \
-	(MBOXSC_PUTMSG_DEF_TIMEOUT_USECS / MBOXSC_USECS_PER_MSEC)
-#define	MBOXSC_PUTMSG_MAX_TIMEOUT_MSECS \
-	(MBOXSC_PUTMSG_MAX_TIMEOUT_USECS / MBOXSC_USECS_PER_MSEC)
-
-/*
- * Minimum and maximum times for mboxsc_getmsg to spend trying to receive a
- * message before giving up.
- * Current value: 0 and 1800 seconds, respectively
- *                1800 seconds (30 minutes) is a few minutes shy of the maximum
- *                value of a clock_t in units of microseconds.
- */
-#define	MBOXSC_GETMSG_MIN_TIMEOUT_USECS (MBOXSC_USECS_PER_SECOND * 0)
-#define	MBOXSC_GETMSG_MAX_TIMEOUT_USECS (MBOXSC_USECS_PER_SECOND * 60 * 30)
-
-#define	MBOXSC_GETMSG_MIN_TIMEOUT_MSECS \
-	(MBOXSC_GETMSG_MIN_TIMEOUT_USECS / MBOXSC_USECS_PER_MSEC)
-#define	MBOXSC_GETMSG_MAX_TIMEOUT_MSECS \
-	(MBOXSC_GETMSG_MAX_TIMEOUT_USECS / MBOXSC_USECS_PER_MSEC)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MBOXSC_IMPL_H */
--- a/usr/src/uts/sun4u/starcat/sys/post/scat_asicbrd_types.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +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-2000 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef	_SCAT_ASICBRD_TYPES_H
-#define	_SCAT_ASICBRD_TYPES_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This file contains enumerations of the board and asic types used
- * in Starcat.
- */
-
-/*
- * POST DEVELOPERS:
- * This file is copied to the OS workspace, and thus must abide by the OS
- * coding standards.  This file must always pass cstyle and hdrchk.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-	/* Enumeration of Starcat positional board types: */
-typedef enum {
-	XCBT_SYS0 = 0,		/* Full-slot system board, e.g., CPU */
-	XCBT_SYS1 = 1,		/* Half-slot system board, e,g., I/O */
-	XCBT_EXB = 2,		/* Expander board */
-	XCBT_CSB = 3,		/* Centerplane support board */
-	XCBT_CP = 4,		/* Half-centerplane */
-	XCBT_SC = 5,		/* System controller */
-
-	XCBT_COUNT		/* Size of array */
-} xcbrdtype_t;
-#define	IS_VALID_XCBT(xcbt) \
-	((((int)(xcbt)) >= 0) && (((int)(xcbt)) < (int)XCBT_COUNT))
-
-	/* Enumeration of Starcat L1 system board types */
-typedef enum {
-	XCL1BT_CPU,		/* Slot 0. Four CPUs, memory */
-	XCL1BT_WIB,		/* Slot 0. Two CPUs & mem, two WCIs */
-	XCL1BT_hPCI,		/* Slot 1. Two Schizos. "Hotplug PCI" */
-	XCL1BT_cPCI,		/* Slot 1. Two Schizos. */
-	XCL1BT_MAXCAT,		/* Slot 1. Two CPUs, no memory */
-	XCL1BT_WIBPCI,		/* Slot 1, hybrid hPCI / WCI */
-	XCL1BT_sPCI,		/* Slot 1. Two Schizos. "Standard PCI" */
-
-	XCL1BT_COUNT
-} xcl1bt_t;
-#define	IS_VALID_XCL1BT(l1bt) \
-	((((int)(l1bt)) >= 0) && (((int)(l1bt)) < (int)XCL1BT_COUNT))
-
-
-	/*
-	 * Arbitrarily chosen enumeration for the Starcat asics, so we
-	 * can build some tables & bitmasks. Make sure any changes are
-	 * reflected in the initialization of xc_asic_name[] in libxcpost.
-	 */
-typedef enum {
-	XCASICT_AXQ,
-	XCASICT_SDI,
-	XCASICT_AMX,
-	XCASICT_RMX,
-	XCASICT_DARB,
-	XCASICT_DMX,
-	XCASICT_CSBCBR,		/* Mode of SDI CSB Console Bus Repeater */
-	XCASICT_EXBCBR,		/* Mode of SDI EXB Console Bus Repeater */
-
-	XCASICT_AR,
-	XCASICT_DX,
-	XCASICT_SDC,
-	XCASICT_DCDS,
-	XCASICT_L1EPLD,
-
-	XCASICT_L1BBC,
-	XCASICT_EXBBBC,
-	XCASICT_CSBBBC,
-
-	XCASICT_CPU,
-	XCASICT_RIO,
-	XCASICT_SCHIZO,
-	XCASICT_WCI,
-
-	XCASICT_CBH,
-	XCASICT_SCM,
-
-	XCASICT_COUNT	/* Size of array */
-} xcasictype_t;
-#define	IS_VALID_XCASICT(asict) \
-	((((int)(asict)) >= 0) && (((int)(asict)) < (int)XCASICT_COUNT))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* !_SCAT_ASICBRD_TYPES_H */
--- a/usr/src/uts/sun4u/starcat/sys/post/scat_const.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +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	_SCAT_CONST_H
-#define	_SCAT_CONST_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This file contains definitions fundamental to the Starcat architecture;
- * how many exps, how many of each asic type, etc.
- */
-
-/*
- * POST DEVELOPERS:
- * This file is copied to the OS workspace, and thus must abide by the OS
- * coding standards.  This file must always pass cstyle and hdrchk.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define	SSC_COUNT		(2)
-#define	SSC_MAX			(SSC_COUNT - 1)
-#define	IS_VALID_SSC(ssc)	((ssc) >= 0 && (ssc) < SSC_COUNT)
-
-#define	EXP_COUNT		(18)
-#define	EXP_MAX			(EXP_COUNT - 1)
-#define	IS_VALID_EXP(exp)	((exp) >= 0 && (exp) < EXP_COUNT)
-
-#define	EXB_COUNT		EXP_COUNT
-#define	EXB_MAX			EXP_MAX
-#define	IS_VALID_EXB(exb)	IS_VALID_EXP(exb)
-
-#ifdef No_More_No_More
-	/* Support this for awhile until we purge everywhere: */
-#define	NODE_COUNT		EXP_COUNT
-#define	NODE_MAX		EXP_MAX
-#define	IS_VALID_NODE(node)	IS_VALID_EXP(node)
-#endif	/* No_More_No_More */
-
-	/* Slots are L1 boards within an expander */
-#define	SLOT_COUNT		(2)
-#define	SLOT_MAX		(SLOT_COUNT - 1)
-#define	IS_VALID_SLOT(slot)	((slot) >= 0 && (slot) < SLOT_COUNT)
-
-
-#ifdef REFERENCE
-	/* XXX: temporary definitions till Dan decides what he wants */
-#define	L1_COUNT		(SLOT_COUNT * EXP_COUNT)
-#define	L1_MAX			(L1_COUNT - 1)
-#define	IS_VALID_L1_BOARD(brd)	((brd) >= 0 && (brd) < L1_COUNT)
-
-#define	S0_PROC_COUNT		(4)	/* max procs on slot 0 L1 board */
-#define	S1_PROC_COUNT		(2)	/* max procs on slot 1 L1 board */
-
-#define	SPM_COUNT		(S0_PROC_COUNT + S1_PROC_COUNT)
-
-#define	PROC_COUNT		((S0_PROC_COUNT * EXP_COUNT) + \
-				    (S1_PROC_COUNT * EXP_COUNT))
-#define	PROC_MAX		(PROC_COUNT - 1)
-#define	IS_VALID_PROC(proc)	((proc) >= 0 && (proc) < PROC_COUNT)
-
-#define	EXP2PROC(exp, spm)		((exp) * (spm))
-#define	EXPSLTBBC2SRAM(exp, slt, bbc)	((exp * 3) + (slt * 2) + (bbc))
-
-#define	PROC2EXP(proc)	((proc) / 6)
-#define	PROC2SPM(proc)	((proc) % 6)
-#define	PROC2CPU(proc)	(PROC2SPM(proc) & 0x3)
-#define	PROC2SLT(proc)	(PROC2SPM(proc) >> 2)
-#define	PROC2BBC(proc)	(((PROC2CPU(proc)) & 0x2) >> 1)
-#define	PROC2PRT(proc)	((proc) & 0x1)
-#define	EXPSLT(proc)	PROC2EXP(proc), PROC2SLT(proc)
-#define	EXPSLTCPU(proc)	PROC2EXP(proc), PROC2SLT(proc), PROC2CPU(proc)
-#endif /* REFERENCE */
-
-
-	/*
-	 * PFP = Packed flat port.
-	 * For cases where one might need to maintain information
-	 * (pcd arrays), or write loops, over all 18 X 6 = 108 ports.
-	 * It is expected that this flat view of the ports is not made
-	 * visible to the user, they should see only the ordered triple
-	 * <exp>.<slot>.<lport> or the 10-bit Safari PortId.
-	 * PWE = Port Within Expander. [0-5]. Comes along with the
-	 * PFP model, should also not be externally visible.
-	 */
-#define	PORT_PER_EXP		6
-#define	PWE_COUNT		PORT_PER_EXP
-#define	PWE_MAX			(PWE_COUNT - 1)
-#define	IS_VALID_PWE(pwe)	((pwe) >= 0 && (pwe) < PWE_COUNT)
-
-#define	PFP_COUNT		(EXP_COUNT * PORT_PER_EXP)
-#define	PFP_MAX			(PFP_COUNT - 1)
-#define	IS_VALID_PFP(pfp)	((pfp) >= 0 && (pfp) < PFP_COUNT)
-
-#define	PFP2EXP(pfp)		((pfp) / 6)
-#define	PFP2PWE(pfp)		((pfp) % 6)
-#define	PWE2SLOT(pwe)		((pwe) >> 2)
-#define	PWE2LPORT(pwe)		((pwe) & 0x3)
-#define	PFP2SLOT(pfp)		(PWE2SLOT(PFP2PWE(pfp)))
-#define	PFP2LPORT(pfp)		(PWE2LPORT(PFP2PWE(pfp)))
-#define	PFP2BBC(pfp)		(((PFP2PWE(pfp)) >> 1) & 1)
-#define	PFP2BBCPORT(pfp)	((pfp) & 1)
-
-#define	SL2PWE(slot, lport)	(((slot) << 2) + (lport))
-#define	EPWE2PFP(exp, pwe)	(((exp) * 6) + (pwe))
-#define	ESL2PFP(exp, slot, lport) (EPWE2PFP((exp), SL2PWE((slot), (lport))))
-
-#define	S0_LPORT_COUNT		4	/* Ports on slot 0 L1 board */
-#define	S0_LPORT_MAX		(S0_LPORT_COUNT - 1)
-#define	IS_VALID_S0LPORT(lport)	((lport) >= 0 && (lport) < S0_LPORT_COUNT)
-#define	S1_LPORT_COUNT		2	/* Ports on slot 1 L1 board */
-#define	S1_LPORT_MAX		(S1_LPORT_COUNT - 1)
-#define	IS_VALID_S1LPORT(lport)	((lport) >= 0 && (lport) < S1_LPORT_COUNT)
-#define	LPORT_COUNT(slot)	((slot) ? S1_LPORT_COUNT : S0_LPORT_COUNT)
-#define	LPORT_MAX(slot)		(LPORT_COUNT(slot) - 1)
-#define	IS_VALID_LPORT(slot, lport) \
-	((lport) >= 0 && (lport) < LPORT_COUNT(slot))
-#define	XC_IOBUS_PER_PORT	2
-#define	XC_IOCARD_PER_PORT	1
-#define	IS_VALID_IOBUS(bus)	((bus) >= 0 && (bus) < XC_IOBUS_PER_PORT)
-#define	IS_VALID_IOCARD(card)	((card) >= 0 && (card) < XC_IOCARD_PER_PORT)
-
-	/* BBC in these macros is local to a slot, either 0 or 1: */
-#define	S0_BBC_COUNT		2	/* BBCs on slot 0 L1 board */
-#define	S0_BBC_MAX		(S0_BBC_COUNT - 1)
-#define	IS_VALID_S0BBC(bbc)	((bbc) >= 0 && (bbc) < S0_BBC_COUNT)
-#define	S1_BBC_COUNT		1	/* BBCs on slot 1 L1 board */
-#define	S1_BBC_MAX		(S1_BBC_COUNT - 1)
-#define	IS_VALID_S1BBC(bbc)	((bbc) >= 0 && (bbc) < S1_BBC_COUNT)
-#define	BBC_COUNT(slot)	((slot) ? S1_BBC_COUNT : S0_BBC_COUNT)
-#define	BBC_MAX(slot)		(BBC_COUNT(slot) - 1)
-#define	IS_VALID_BBC(slot, bbc) \
-	((bbc) >= 0 && (bbc) < BBC_COUNT(slot))
-
-#define	LPORT2BBC(lport)	((lport) >> 1)
-#define	PWE2BBC(pwe)		(((pwe) >> 1) & 1)
-
-
-	/* These are for use as printf() arguments for "%2d.%d", etc.: */
-#define	EXPSLOT(pfp)		PFP2EXP(pfp), PFP2SLOT(pfp)
-#define	EXPSLOTLPORT(pfp)	PFP2EXP(pfp), PFP2SLOT(pfp), PFP2LPORT(pfp)
-
-
-	/* Build a 5-bit Safari Agent ID: */
-#define	SAFAGENT(slot, lport, is_ioport) \
-	(((slot) ? ((is_ioport) ? 0x1C : 8) : 0) + (lport))
-
-	/* Build a 10-bit Safari ID: */
-#define	SAFARI_ID(exp, slot, lport, is_ioport) \
-	(SAFAGENT(slot, lport, is_ioport) | ((exp) << 5))
-
-	/* Given a Safari Agent ID, extract the expander number */
-#define	GET_EXP(aid)		((aid & 0x3E0ull) >> 5)
-
-	/* Cacheable memory per (CPU) port */
-#define	DIMMS_PER_PORT		8
-#define	IS_VALID_DIMM(dimm)	\
-	(((dimm) >= 0) && (dimm < (DIMMS_PER_PORT)))
-#define	PMBANKS_PER_PORT	2
-#define	LMBANKS_PER_PMBANK	2
-#define	IS_VALID_PMBANK(pmbank)	\
-	(((pmbank) >= 0) && (pmbank < PMBANKS_PER_PORT))
-#define	IS_VALID_LMBANK(lmbank)	\
-	(((lmbank) >= 0) && (lmbank < PMBANKS_PER_PORT))
-
-	/* Ecache per (CPU) port */
-#define	ECDIMMS_PER_PORT	2
-#define	IS_VALID_ECACHE(ecache)	\
-	(((ecache) >= 0) && (ecache < ECDIMMS_PER_PORT))
-
-	/* SCM asics per CSB: */
-#define	SCM_COUNT		(2)
-#define	SCM_MAX			(SCM_COUNT - 1)
-#define	IS_VALID_SCM(scm)	((scm) >= 0 && (scm) < SCM_COUNT)
-
-	/* Master ports in an SCM: */
-#define	SCM_MPORT_COUNT			10
-
-	/* SDI asics per EXB: */
-#define	SDI_COUNT		(6)
-#define	SDI_MAX			(SDI_COUNT - 1)
-#define	IS_VALID_SDI(sdi)	((sdi) >= 0 && (sdi) < SDI_COUNT)
-
-	/* Half-centerplanes, CSBs, etc. */
-#define	CP_COUNT		(2)
-#define	CP_MAX			(CP_COUNT - 1)
-#define	IS_VALID_CP(cp)		((cp) >= 0 && (cp) < CP_COUNT)
-
-	/* DMX asics on the half-centerplane: */
-#define	DMX_COUNT		(6)
-#define	DMX_MAX			(DMX_COUNT - 1)
-#define	IS_VALID_DMX(dmx)	((dmx) >= 0 && (dmx) < DMX_COUNT)
-
-	/* AMX asics on the half-centerplane: */
-#define	AMX_COUNT		(2)
-#define	AMX_MAX			(AMX_COUNT - 1)
-#define	IS_VALID_AMX(amx)	((amx) >= 0 && (amx) < AMX_COUNT)
-
-	/* Number of CPUs per SBBC on the various boards: */
-#define	CPU_COUNT		(2)
-
-	/* Number of WCI per WIB: */
-#define	S0_WCI_COUNT		(2)
-#define	S0_WCI_MIN		(2)
-#define	S0_WCI_MAX		(S0_WCI_MIN + S0_WCI_COUNT - 1)
-#define	S0_IS_VALID_WCI(wci)	((wci) >= S0_WCI_MIN && (wci) <= S0_WCI_MAX)
-#define	S1_WCI_COUNT		(1)
-#define	S1_WCI_MIN		(1)
-#define	S1_WCI_MAX		(S1_WCI_MIN + S1_WCI_COUNT - 1)
-#define	WCI_COUNT(slot)		((slot) ? S1_WCI_COUNT : S0_WCI_COUNT)
-#define	WCI_MIN(slot)		((slot) ? S1_WCI_MIN : S0_WCI_MIN)
-#define	WCI_MAX(slot)		((slot) ? S1_WCI_MAX : S0_WCI_MAX)
-#define	S1_IS_VALID_WCI(wci)	((wci) >= S1_WCI_MIN && (wci) <= S1_WCI_MAX)
-#define	IS_VALID_WCI(slot, wci)	((slot) ? S1_IS_VALID_WCI((wci)) : \
-				    S0_IS_VALID_WCI((wci)))
-
-	/* Safari reset number (within sbbc) given slot & lport */
-#define	WCI_RST_NUM(slot, lport) \
-	((slot) ? 1 : ((lport) & 1 ? 1 : 0))
-
-	/* Number of non WCI safari devices per WIB */
-#define	S0_WIB_PROC_COUNT	(2)	/* max procs on slot 0 WIB */
-#define	S1_WIB_SCHIZO_COUNT	(1)	/* max schizos on slot 1 WIB */
-
-	/* Number of Schizo per PCI I/O board: */
-#define	SCHIZO_COUNT		(2)
-
-	/*
-	 * CPU and Maxcat L1 boards have 4 DXs, I/O boards have 2.
-	 * But it's useful to have this for array dimensions, etc.
-	 */
-#define	DX_COUNT_MAX		(4)
-#define	IS_VALID_CPU_DX(dx)	((dx) >= 0 && (dx) < DX_COUNT_MAX)
-
-	/*
-	 * DCDS asics for half of a CPU board. The DCDS is a data slice,
-	 * 8 are required for a full Safari data path.
-	 */
-#define	DCDS_COUNT		(8)
-#define	DCDS_MAX		(DCDS_COUNT - 1)
-#define	IS_VALID_DCDS(dcds)	((dcds) >= 0 && (dcds) < DCDS_COUNT)
-
-
-	/*
-	 * Address, Data, or Response Bus.
-	 * For all three, 0 or 1 is a valid value.
-	 */
-#define	BUS_COUNT		(CP_COUNT)
-#define	BUS_MAX			(BUS_COUNT - 1)
-#define	IS_VALID_BUS(bus)	((bus) >= 0 && (bus) < BUS_COUNT)
-
-	/*
-	 * Address, Data, or Response Bus configuration.
-	 * For all three, 1. 2. or 3 is a valid value.
-	 */
-#define	BCONF_MIN		0x1
-#define	BCONF_MAX		0x3
-#define	BCONF_COUNT		3
-#define	IS_VALID_BCONF(bconf)	((bconf) >= BCONF_MIN && (bconf) <= BCONF_MAX)
-
-	/*
-	 * This might seem a little obscure to be here, but it's needed
-	 * for some array sizes and function prototypes:
-	 */
-#define	AXQ_NASM_SIZE				256
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* !_SCAT_CONST_H */
--- a/usr/src/uts/sun4u/starcat/sys/post/scat_dcd.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,509 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SCAT_DCD_H
-#define	_SCAT_DCD_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This file contains definitions of the structures gdcd_t and ldcd_t,
- * Global and Local Domain Configuration Descriptors and the various
- * substructures they contain.
- * The gdcd is the information handed off to OBP and the OS by POST
- * in the "golden" I/O SRAM of a domain in Sun Fire 15000 systems.
- * The ldcd contains information about the two ports local to each
- * sram, kept in that local sram, to support DR operations.
- */
-
-#include <sys/types.h>
-
-#include <post/scat_const.h>
-#include <post/scat_asicbrd_types.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define	DCD_VERSION 4
-
-
-#define	GDCD_MAGIC (('G'<< 24) | ('D'<< 16) | ('C'<< 8) | 'D')
-#define	LDCD_MAGIC (('L'<< 24) | ('D'<< 16) | ('C'<< 8) | 'D')
-
-
-#define	PMBANKS_PER_PORT	2
-#define	LMBANKS_PER_PMBANK	2
-#define	IOBUS_PER_PORT		2
-#define	IOCARD_PER_BUS		4	/* 1 currently, but could change */
-#define	LINKS_PER_PORT		5	/* 3 in current hardware */
-#define	DIMMS_PER_PORT		8
-#define	DIMMS_PER_PMBANK	4
-#define	ECDIMMS_PER_PORT	2
-
-	/*
-	 * This is intended to handle Jubatus8X - up to 8 CPU cores
-	 * within one Safari port.
-	 */
-#define	SAF_AGENT_PER_PORT	8
-
-	/*
-	 * The most significant element of the otherwise unused
-	 * prd_t.prd_wic_links[LINKS_PER_PORT] in processor ports is
-	 * reserved for use by DR to save the prd_prsv of the port
-	 * while that is temporarily marked RSV_UNCONFIG when the
-	 * processor is borrowed for I/O cage testing for DR.
-	 * It is expected that .prd_wic_links[PRD_LINK_IX_HOLD_CPUPORT_PRSV]
-	 * will be restored to RSV_UNDEFINED when the prd_prsv is
-	 * restored to its original value. It would be a Good Thing to
-	 * check that prd_prsv is not ever being set to RSV_UNDEFINED;
-	 * it's probably wrong to restore it to other than RSV_GOOD().
-	 */
-#define	PRD_LINK_IX_HOLD_CPUPORT_PRSV	(LINKS_PER_PORT - 1)
-
-	/*
-	 * There are four Address Decode Registers, 0 - 3, one for each
-	 * logical bank. ADR 0 and 2 control the logical banks in
-	 * physical bank 0; ADR 1 and 3 control the logical banks in
-	 * physical bank 1.
-	 */
-#define	ADR2PBANK(adr)			((adr) & 1)
-#define	ADR2LBANK(adr)			(((adr) >> 1) & 1)
-#define	PLBANK2ADR(pbank, lbank)	((((lbank) & 1) << 1) | ((pbank) & 1))
-
-
-	/* ======================================================== */
-	/*
-	 * RSV stands for Resource Status Value.
-	 * These are the values used in all cases where the status of
-	 * a resource is maintained in a byte element of a structure.
-	 * 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".
-	 * This is not an enum because they need to fit in a byte.
-	 */
-
-typedef uint8_t	prdrsv_t;
-
-#define	RSV_UNKNOWN	0x0		/* No status yet */
-#define	RSV_PRESENT	0x1		/* Presence detected */
-#define	RSV_CRUNCH	0x2		/* Unusable by implication */
-#define	RSV_UNDEFINED	0x3		/* Architecturally Missing */
-#define	RSV_MISS	0x4		/* Missing */
-#define	RSV_MISCONFIG	0x5		/* Misconfigured, e.g., mixed dimms */
-#define	RSV_FAIL_OBP	0x6		/* Failed by OBP */
-#define	RSV_FAIL	0x7		/* Tested and failed */
-#define	RSV_BLACK	0x8		/* Blacklisted */
-#define	RSV_RED		0x9		/* Redlisted */
-#define	RSV_EXCLUDED	0xA		/* Not in this domain */
-#define	RSV_UNCONFIG	0xB		/* Good, but not in config. */
-#define	RSV_PASS	0xC		/* Passed some sort of test; */
-					/* Always subject to more... */
-	/*
-	 * Odd proc of a good Lockstep pair. Valid only for prd_prsv for
-	 * processor ports.
-	 */
-#define	RSV_LOCKSTEP	0xD
-
-	/*
-	 * This will be used instead of RSV_MISS when an hsPCI
-	 * cassette is present but it contains no PCI adapter.
-	 * Intended to be used only for prd_t.prd_iocard_rsv[][]
-	 */
-#define	RSV_EMPTY_CASSETTE	0xF	/* An hsPCI cassette, no adapter */
-
-	/*
-	 * This definition of Good depends on context.
-	 * Some customers of this status may want to use only PASS.
-	 */
-#define	RSV_GOOD(rsv) \
-	(RSV_PASS == (rsv) || RSV_UNKNOWN == (rsv) || RSV_PRESENT == (rsv))
-
-#define	RSV_NOTOUCH(rsv) (RSV_EXCLUDED == (rsv) || RSV_RED == (rsv))
-
-	/* ============================================================ */
-	/*		Port Resource Descriptor - PRD			*/
-
-typedef struct {
-	uint64_t	prd_ver_reg;	/* port version register */
-		/*
-		 * For ports with memory, the address decode register
-		 * for each bank, and the address control register.
-		 */
-	uint64_t	prd_madr[PMBANKS_PER_PORT][LMBANKS_PER_PMBANK];
-	uint64_t	prd_macr;
-	/* DOUBLEWORD */
-
-	uint16_t	prd_rfreq;		/* rated frequency Mhz */
-	uint16_t	prd_afreq_ratio;	/* ratio of actual frequency */
-						/* to interconnect speed */
-
-	prdrsv_t	prd_prsv;	/* status of entire port. */
-	uint8_t		prd_ptype;	/* port type. See SAFPTYPE_ below */
-
-		/* memory configuration state */
-	uint8_t		prd_mem_config_state;
-
-	uint8_t		prd_fill1;
-	/* DOUBLEWORD */
-
-		/*
-		 * This is intended to handle Jubatus2X - 8X.
-		 * For all other cases, expect that prd_agent[0] = prd_prsv,
-		 * and prd_agent[7:1] = RSV_UNDEFINED.
-		 * For JubatusnX, it conveys the status of the
-		 * n core processors.
-		 */
-	prdrsv_t	prd_agent[SAF_AGENT_PER_PORT];
-	/* DOUBLEWORD */
-
-		/* for ports that have memory */
-	prdrsv_t	prd_bank_rsv[PMBANKS_PER_PORT][LMBANKS_PER_PMBANK];
-								/* bank rsv */
-	uint16_t	prd_log_bank_size[PMBANKS_PER_PORT];	/* bank size */
-				/*
-				 * If a physical bank has two logical
-				 * banks, they are always the same size.
-				 */
-	/* DOUBLEWORD */
-
-		/* for ports with IO buses */
-	prdrsv_t	prd_iocard_rsv[IOBUS_PER_PORT][IOCARD_PER_BUS];
-		/*
-		 * Currently, only 1 adapter is on each bus and index
-		 * zero is used for that. Index 1 is reserved.
-		 * The remaining 2 are used to support in-kernel-probing,
-		 * to avoid board specific hooks.
-		 * They only exist on bus 1 of Schizo 0 on the board.
-		 */
-#define	IOBOARD_BBCRIO_PORT		0
-#define	IOBOARD_BBCRIO_BUS		1
-#define	IOCARD_RSV_SBBC_INDEX		2
-#define	IOCARD_RSV_RIO_INDEX		3
-
-	/* DOUBLEWORD */
-
-	prdrsv_t	prd_iobus_rsv[IOBUS_PER_PORT];
-
-		/* For ports with WCI links, status of each link */
-	prdrsv_t	prd_wic_links[LINKS_PER_PORT];
-
-	uint8_t		fill2;
-	/* DOUBLEWORD */
-
-
-	prdrsv_t	prd_dimm[PMBANKS_PER_PORT][DIMMS_PER_PMBANK];
-			/*
-			 * Status for dimms [1:0][3:0].
-			 * This contains at most only probing information.
-			 * Testing is done on logical banks, so results are
-			 * not representable at the dimm level, since each
-			 * dimm contains part of two logical banks.
-			 *
-			 * Also, probing is expensive in time, so it is
-			 * skipped if the results would not affect available
-			 * resources.
-			 * Example: if dimm 0 of a pbank is missing, the other
-			 * three dimms are ignored and will be RSV_UNKNOWN.
-			 */
-
-	/* DOUBLEWORD */
-	uint8_t		prd_cache;	/* external cache size (MByte) */
-	prdrsv_t	prd_ecdimm[ECDIMMS_PER_PORT];
-		/* status for ecache dimms 0..1 */
-
-
-	uint8_t		prd_sparebyte[5];
-	/* DOUBLEWORD */
-	uint32_t	prd_spare[4];
-	/* DOUBLEWORD */
-
-} prd_t;
-
-	/* prd_mem_config_state manifest constants */
-#define	PRD_MCS_BANKS			((uint8_t)1 << 0)
-#define	PRD_MCS_SLICE			((uint8_t)1 << 1)
-#define	PRD_MCS_IMODE(mode)		(((uint8_t)(mode) & 0x3) << 2)
-#define	PRD_MCS_GET_IMODE(mcs)		(((uint8_t)(mcs) & 0xC) >> 2)
-#define	PRD_MCS_FAILD			((uint8_t)1 << 6)
-#define	PRD_MCS_VALID			((uint8_t)1 << 7)
-
-
-	/* Types of Safari ports. Not an enum so it fits in a byte. */
-#define	SAFPTYPE_NULL	0
-#define	SAFPTYPE_CPU	1
-#define	SAFPTYPE_sPCI	2
-#define	SAFPTYPE_cPCI	3
-#define	SAFPTYPE_WCI	4
-#define	SAFPTYPE_PCIX	5
-#define	SAFPTYPE_MAX	SAFPTYPE_PCIX
-
-#define	SAFTYPE_PCI(type) \
-	((SAFPTYPE_sPCI == (type)) || (SAFPTYPE_cPCI == (type)))
-
-
-	/* ======================================================== */
-	/* Local and Global Domain Configuration Descriptors LDCD & GDCD */
-
-	/* Enumeration of process types for xdcd.h.dcd_lmod_type */
-typedef enum {
-	DCDLMT_OTHER,		/* Something not otherwise in this enum */
-	DCDLMT_POST_BOOT,	/* POST at initial domain creation */
-	DCDLMT_POST_DR,		/* POST for some sort of DR case */
-	DCDLMT_OBP,		/* Domain Open Boot */
-	DCDLMT_OS,		/* Domain Solaris */
-	DCDLMT_DR_SMS,		/* DR process running on SSC */
-	DCDLMT_DR_DOMAIN,	/* DR process running on domain */
-	DCDLMT_OTHER_SMS,	/* Non-DR process running on SSC */
-	DCDLMT_COUNT		/* Array size for strings, etc. */
-} dcd_lmod_type_t;
-
-
-	/* dcd substructure for status of L1 boards in each slot */
-typedef struct {
-	xcl1bt_t	l1ss_type;	/* enum in scat_asicbrd_types.h */
-	prdrsv_t	l1ss_rsv;	/* Status. */
-					/*
-					 * The cdc information is rightfully
-					 * only relevant to the EXB and the
-					 * slot 0 board of that EXB. But it
-					 * needs to stay with that slot 0
-					 * board over DR operations, so
-					 * it goes here.
-					 * It should be ignored for slot 1
-					 * boards.
-					 */
-	prdrsv_t	l1ss_cdc_rsv;
-	uint8_t		l1ss_cdc_dimm_size;	/* MBytes */
-	uint8_t		l1ss_fill1;		/* Explicit alignment */
-	/* DOUBLEWORD */
-					/*
-					 * So Starcat software that doesn't
-					 * have knowledge of the CPU sram
-					 * TOC format can find the LDCD in
-					 * CPU srams.
-					 */
-	uint16_t	l1ss_cpu_ldcd_xwd_offset;	/* Byte offset >> 3 */
-	uint16_t	l1ss_cpu_drblock_xwd_offset;	/* Byte offset >> 3 */
-	uint8_t		l1ss_flags;			/* See below */
-	uint8_t		l1ss_sparebyte[3];
-	uint32_t	l1ss_spare[2];
-	/* DOUBLEWORD */
-} l1_slot_stat_t;
-
-	/*
-	 * When this flag is set, all CPUs on this L1 board should be
-	 * configured with a NULL Local Physical Address (LPA) range in
-	 * their Safari Config Registers.
-	 * This flag can be ignored for boards with no processors.
-	 */
-#define	L1SSFLG_THIS_L1_NULL_PROC_LPA		(1 << 0)
-
-
-	/* dcd substructure for memory chunk list. */
-typedef struct {
-	uint64_t	mc_base_pa;	/* Base Physical Address */
-	uint64_t	mc_mbytes;	/* Size of Chunk in MBytes */
-} mem_chunk_t;
-
-#define	MAX_DOM_MEM_CHUNKS (EXP_COUNT * S0_LPORT_COUNT * \
-			    PMBANKS_PER_PORT * LMBANKS_PER_PMBANK)
-typedef struct {
-	uint64_t	dcl_chunks;	/* number of chunks */
-	mem_chunk_t	dcl_chunk[MAX_DOM_MEM_CHUNKS];
-} domain_chunk_list_t;
-
-#define	MAX_EXP_MEM_CHUNKS (S0_LPORT_COUNT * \
-			    PMBANKS_PER_PORT * LMBANKS_PER_PMBANK)
-typedef struct {
-	uint64_t	ecl_chunks;	/* number of chunks */
-	mem_chunk_t	ecl_chunk[MAX_EXP_MEM_CHUNKS];
-} exp_chunk_list_t;
-
-typedef struct {
-	uint32_t	dcd_magic;	/* GDCD_MAGIC or LDCD_MAGIC */
-	uint32_t	dcd_version;	/* structure version: DCD_VERSION */
-	uint32_t	dcd_csum;	/* So sum((uint[]) xdcd) == 0. */
-	uint32_t	dcd_post_pid;	/* Process ID of the SSC hpost that */
-					/* originally created this domain */
-					/* or POSTed this board. */
-	/* DOUBLEWORD */
-
-	uint64_t	dcd_boot_time;	/* Time of creation of the domain */
-					/* by POST. To be backward compatible */
-					/* in ILD32, uint64_t is used instead */
-					/* of time_t. */
-
-	uint64_t	dcd_lmod_time;	/* Time of last modification of */
-					/* this structure. */
-
-	uint32_t	dcd_lmod_pid;	/* Process ID of the last modifier */
-					/* of this structure. If the last */
-					/* modifier has no PID, set to 0. */
-
-	dcd_lmod_type_t dcd_lmod_type;	/* Type of process that last modified */
-					/* this structure. See above. */
-	/* DOUBLEWORD */
-
-	uint32_t	dcd_mod_count;	/* Count of the number of times */
-					/* this structure has been modified. */
-					/* Set to 0 by original POST. */
-
-	uint32_t	dcd_post_level;	/* Level at which POST executed */
-					/* for most recent boot or test. */
-	/* DOUBLEWORD */
-
-	uint32_t	dcd_post_private;	/* Private word for POST */
-	uint32_t	dcd_flags;		/* See DCDFLAG_xxx */
-	uint32_t	dcd_spare[8];		/* Minimize future problems */
-	/* DOUBLEWORD */
-} dcd_header_t;
-
-
-	/*
-	 * This flag is only for use in LDCDs. It is set when this
-	 * board is part of a domain and the local DCD is considered
-	 * only a secondary copy of the information in the GDCD.
-	 * We do not keep the GDCD location here, since that would
-	 * impose extra work on DR when the golden IOSRAM board detaches.
-	 * POST will set this in all LDCDs in a newly booted domain.
-	 */
-#define	DCDFLAG_IN_DOMAIN		(1u << 0)
-
-	/*
-	 * This flag is only for use in LDCDs. It is set when this
-	 * board was called for hpost -H (h.dcd_lmod_type is DCDLMT_POST_DR)
-	 * and no testing was required. All that was done was clearing.
-	 */
-#define	DCDFLAG_CLEARED_ONLY		(1u << 1)
-
-	/* POST inititalizes dcd_testcage_mbyte_PA to this value */
-#define	DCD_TESTCAGE_MBYTE_PA_INIT	((uint32_t)-1)
-	/*
-	 * zero (0) in dcd_testcage_log2_mbytes has the special meaning
-	 * that no testcage memory is to be allocated.
-	 * zero (0) in dcd_testcage_log2_mbytes_align is a real
-	 * alignment of 1MB.
-	 */
-#define	DCD_DR_TESTCAGE_DISABLED	(0)	/* zero size cage */
-#define	DCD_DR_TESTCAGE_LOG2_1MB_ALIGN	(0)	/* 2^0 = 1 for */
-	/*
-	 * The remainder of these constants can be used for
-	 * either dcd_testcage_* variable and indicate the
-	 * value shown.
-	 */
-#define	DCD_DR_TESTCAGE_LOG2_2MB	(1)	/* 2^1 =  2 */
-#define	DCD_DR_TESTCAGE_LOG2_4MB	(2)	/* 2^2 =  4 */
-#define	DCD_DR_TESTCAGE_LOG2_8MB	(3)	/* 2^3 =  8 */
-#define	DCD_DR_TESTCAGE_LOG2_16MB	(4)	/* 2^4 =  16 */
-#define	DCD_DR_TESTCAGE_LOG2_32MB	(5)	/* 2^5 =  32 */
-#define	DCD_DR_TESTCAGE_LOG2_64MB	(6)	/* 2^6 =  64 */
-#define	DCD_DR_TESTCAGE_LOG2_128MB	(7)	/* 2^7 =  128 */
-#define	DCD_DR_TESTCAGE_LOG2_256MB	(8)	/* 2^8 =  256 */
-#define	DCD_DR_TESTCAGE_LOG2_512MB	(9)	/* 2^9 =  512 */
-#define	DCD_DR_TESTCAGE_LOG2_1024MB	(10)	/* 2^10 = 1024 */
-
-	/* Global DCD - exists only in golden I/O sram */
-typedef struct {
-	dcd_header_t	h;
-	/* DOUBLEWORD */
-
-	uint32_t	dcd_intercon_freq;	/* In Hertz */
-	uint8_t		dcd_abus_mask;		/* Address bus config [1:0] */
-	uint8_t		dcd_dbus_mask;		/* Data bus config [1:0] */
-	uint8_t		dcd_rbus_mask;		/* Response bus config [1:0] */
-	uint8_t		dcd_stick_ratio;	/* Ratio of intercon:STICK */
-	/* DOUBLEWORD */
-
-	uint8_t		dcd_domain;		/* 0-17 or other if unknown */
-		/*
-		 * Specification of the required size and alignment of
-		 * the DR testcage memory used during POST -H testcage runs.
-		 * The formula is bytes = (1 << (log2_value + 20)).
-		 */
-	uint8_t		dcd_testcage_log2_mbytes_size;
-	uint8_t 	dcd_testcage_log2_mbytes_align;
-	uint8_t		dcd_fill[5];
-	/* DOUBLEWORD */
-		/*
-		 * Specification of the DR testcage memory base physical addr.
-		 * This is initialized to DCD_TESTCAGE_PA_INIT by POST
-		 * and set by setkeyswitch when it determines the location of
-		 * the testcage.  The formula is PA = (mbyte_PA << 20).
-		 */
-	uint32_t	dcd_testcage_mbyte_PA;
-	uint32_t	dcd_spare[3];		/* Avoid future problems */
-	/* DOUBLEWORD */
-
-		/* Information on the L1 boards in each slot: */
-	l1_slot_stat_t	dcd_slot[EXP_COUNT][SLOT_COUNT];
-	/* DOUBLEWORD */
-
-		/*
-		 * Information on 108 Safari ports.
-		 * See scat_const.h for macros that will help in computing
-		 * indexes into this array, particularly "PWE" and "PFP".
-		 */
-	prd_t		dcd_prd[EXP_COUNT][PORT_PER_EXP];
-	/* DOUBLEWORD */
-
-		/*
-		 * memory chunk list for the domain; max 288 chunks.
-		 * This is the worst case scenario where there is no
-		 * interleaving and no re-configuration of the memory address
-		 * decode registers to make board memory contiguous.
-		 * This uses 288 * 16bytes = 4608KB.
-		 */
-	domain_chunk_list_t dcd_chunk_list;
-} gdcd_t;
-
-	/* Local DCD - exists in every I/O, CPU, and WCI sram */
-typedef struct {
-	dcd_header_t	h;
-	/* DOUBLEWORD */
-
-		/* Information on the L1 board in this slot: */
-	l1_slot_stat_t	dcd_slot;
-	/* DOUBLEWORD */
-
-		/* Information on 2 Safari ports: */
-	prd_t		dcd_prd[2];
-	/* DOUBLEWORD */
-
-		/* memory chunk list for this exp; max 16 chunks */
-	exp_chunk_list_t dcd_chunk_list;
-} ldcd_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* !_SCAT_DCD_H */
--- a/usr/src/uts/sun4u/starcat/sys/post/scat_pa_space.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef	_SCAT_PA_SPACE_H
-#define	_SCAT_PA_SPACE_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * This file contains definitions related to the Starcat
- * physical address space.
- */
-
-/*
- * POST DEVELOPERS:
- * This file is copied to the OS workspace, and thus must abide by the OS
- * coding standards.  This file must always pass cstyle and hdrchk.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define	STARCAT_DEVICE_CONFIG	(0x40000000000ull)
-
-#define	EXP_PA_ADDR(exp)	(exp << 28)
-
-	/*
-	 * Useful to translate an sram or fprom offset to an address
-	 * that a host processor would use to reach it.
-	 */
-#define	BOOTBUS_PA_BASE		0x7FFF0000000ull
-
-	/* See bbc.h for sizes */
-#define	BOOTBUS_FPROM_PA_BASE	(BOOTBUS_PA_BASE + 0)
-#define	BOOTBUS_SRAM_PA_BASE	(BOOTBUS_PA_BASE + 0x900000u)
-
-	/*
-	 * Cacheable Physical Memory Addresses in Starcat are assigned
-	 * to expanders in 128 GByte slices, based on PA[41:37].
-	 * The slice to exp mapping is not always 1-1, swaps may occur
-	 * as a result of some DR or POST operations.
-	 * The map is maintained in the PCD.
-	 * The slice number will always be a valid expander board
-	 * number in [0,17], but it may not reside on that expander.
-	 * The PA in these macros is 64-bit, the slice is 8 bit, unsigned.
-	 */
-#define	PA_2_SLICE128G(pa)		(((uint8_t)((pa) >> 37)) & 0x1Fu)
-#define	SLICE128G_2_PA_BASE(slice)	(((uint64_t)((slice) & 0x1F)) << 37)
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* !_SCAT_PA_SPACE_H */
--- a/usr/src/uts/sun4u/starcat/sys/sc_cvc.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_SC_CVC_H
-#define	_SYS_SC_CVC_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define	CVC_IOSRAM_POLL_USECS	100000
-
-#if defined(DEBUG)
-
-#define	CVC_DBG_ATTACH		0x0001
-#define	CVC_DBG_DETACH		0x0002
-#define	CVC_DBG_OPEN		0x0004
-#define	CVC_DBG_CLOSE		0x0008
-#define	CVC_DBG_IOCTL		0x0010
-#define	CVC_DBG_REDIR		0x0020
-#define	CVC_DBG_WPUT		0x0040
-#define	CVC_DBG_WSRV		0x0080
-#define	CVC_DBG_IOSRAM_WR	0x0100
-#define	CVC_DBG_IOSRAM_RD	0x0200
-#define	CVC_DBG_NETWORK_WR	0x0400
-#define	CVC_DBG_NETWORK_RD	0x0800
-#define	CVC_DBG_IOSRAM_CNTL	0x1000
-
-
-#define	CVC_DBG0(flag, fmt) \
-	cvc_dbg(flag, fmt, 0, 0, 0, 0, 0);
-#define	CVC_DBG1(flag, fmt, a1) \
-	cvc_dbg(flag, fmt, (uintptr_t)(a1), 0, 0, 0, 0);
-#define	CVC_DBG2(flag, fmt, a1, a2) \
-	cvc_dbg(flag, fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
-#define	CVC_DBG3(flag, fmt, a1, a2, a3) \
-	cvc_dbg(flag, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \
-		(uintptr_t)(a3), 0, 0);
-#define	CVC_DBG4(flag, fmt, a1, a2, a3, a4) \
-	cvc_dbg(flag, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \
-		(uintptr_t)(a3), (uintptr_t)(a4), 0);
-#define	CVC_DBG5(flag, fmt, a1, a2, a3, a4, a5) \
-	cvc_dbg(flag, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \
-		(uintptr_t)(a3), (uintptr_t)(a4), (uintptr_t)(a5));
-
-#else /* DEBUG */
-
-#define	CVC_DBG0(flag, fmt)
-#define	CVC_DBG1(flag, fmt, a1)
-#define	CVC_DBG2(flag, fmt, a1, a2)
-#define	CVC_DBG3(flag, fmt, a1, a2, a3)
-#define	CVC_DBG4(flag, fmt, a1, a2, a3, a4)
-#define	CVC_DBG5(flag, fmt, a1, a2, a3, a4, a5)
-
-#endif /* DEBUG */
-
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_SC_CVC_H */
--- a/usr/src/uts/sun4u/starcat/sys/sc_cvcio.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +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_SC_CVCIO_H
-#define	_SYS_SC_CVCIO_H
-
-#include <sys/sysmacros.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Layout of console IOSRAM chunks
- *         |---------------|
- *  CONC   |  cvc_ctl_t    |
- *         |  128 bytes    |
- *         |---------------|
- *
- *         |---------------|
- *  CONI   | input count   |
- *         |  2 bytes      |
- *         |---------------|
- *         | receive buffer|
- *         |  1022 bytes   |
- *         |---------------|
- *
- *         |---------------|
- *  CONO   | output count  |
- *         |  2 bytes      |
- *         |---------------|
- *         | send buffer   |
- *         | 1022 bytes    |
- *         |---------------|
- */
-
-#define	IOSRAM_KEY_CONC 0x434F4E43
-#define	IOSRAM_KEY_CONI 0x434F4E49
-#define	IOSRAM_KEY_CONO 0x434F4E4F
-
-#define	CONSBUF_IN_SIZE		1024
-#define	CONSBUF_OUT_SIZE	1024
-#define	CONSBUF_COUNT_SIZE	(sizeof (short))
-
-#define	MAX_XFER_CINPUT		(CONSBUF_IN_SIZE - CONSBUF_COUNT_SIZE)
-#define	MAX_XFER_COUTPUT	(CONSBUF_OUT_SIZE - CONSBUF_COUNT_SIZE)
-#define	COUNT_OFFSET		0
-#define	DATA_OFFSET		(CONSBUF_COUNT_SIZE)
-
-#define	cvc_username		"sms"
-#define	CVCD_SERVICE		"cvc_hostd"
-#define	MAX_CONS_CONN		100
-#define	MAXPKTSZ		4096
-
-#define	TCP_DEV			"/dev/tcp"
-#define	CVCREDIR_DEV		"/devices/pseudo/cvcredir@0:cvcredir"
-
-
-/*
- * ioctl commands passed to cvcredir (and possibly on to cvc from there) by cvcd
- */
-#define	CVC			'N'
-#define	CVC_BREAK		((CVC<<8) | 0x00)
-#define	CVC_DISCONNECT		((CVC<<8) | 0x01)
-
-/*
- * DXS (the SC-side console traffic application) may send a few of these codes
- * to cvcd as expedited TLI traffic.  The rest are not used in domain-side
- * software, but SC-side software may use them.
- */
-#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 */
-
-/*
- * This structure represents the layout of control data in the CONC chunk.
- * It should NOT grow beyond 128 bytes, as that is the max size that was
- * identified for the CONC chunk.
- */
-typedef struct cvc_ctl {
-	uint8_t		command;	/* CVC_IOSRAM_BREAK, etc */
-	uint8_t		version;	/* currently unused */
-	uint8_t		unused1[2];	/* currently unused */
-	uint16_t	winsize_rows;
-	uint16_t	winsize_cols;
-	uint16_t	winsize_xpixels;
-	uint16_t	winsize_ypixels;
-	uint8_t		unused2[116];	/* currently unused */
-} cvc_ctl_t;
-
-/*
- * These macros can be used to determine the offset or size of any field in the
- * CONC chunk.
- */
-#define	CVC_CTL_OFFSET(field)  offsetof(cvc_ctl_t, field)
-#define	CVC_CTL_SIZE(field)    (sizeof (((cvc_ctl_t *)0)->field))
-
-/*
- * Commands sent across IOSRAM from domain_server to cvc driver
- */
-#define	CVC_IOSRAM_BREAK	1
-#define	CVC_IOSRAM_DISCONNECT	2
-#define	CVC_IOSRAM_VIA_NET	3
-#define	CVC_IOSRAM_VIA_IOSRAM	4
-#define	CVC_IOSRAM_WIN_RESIZE	5
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_SC_CVCIO_H */
--- a/usr/src/uts/sun4u/starcat/sys/sc_gptwocfg.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_SC_GPTWOCFG_H
-#define	_SYS_SC_GPTWOCFG_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Interfaces exported by Starcat Interface, kernel/misc/sc_gptwocfg
- */
-
-typedef void *sc_gptwocfg_cookie_t;
-
-sc_gptwocfg_cookie_t sc_probe_board(uint_t);
-sc_gptwocfg_cookie_t sc_unprobe_board(uint_t);
-int sc_next_node(sc_gptwocfg_cookie_t, dev_info_t *, dev_info_t **);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_SC_GPTWOCFG_H */
--- a/usr/src/uts/sun4u/starcat/sys/schpc.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_SCHPC_H
-#define	_SYS_SCHPC_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#define	STARCAT_MAX_SLOTS	(18 * 4)
-
-/*
- * Slot LED Descriptor
- *
- * Each hot pluggable PCI/cPCI slot has three leds.  Each LED can
- * be on, off, or flashing.
- */
-typedef struct slot_led {
-	char		led_power;
-	char		led_service;
-	char		led_fault;
-	char		reserved;
-} slot_led_t;
-
-#define	LED_OFF		0x00
-#define	LED_ON		0x01
-#define	LED_FLASH	0x02
-
-/*
- * LED Commands
- */
-#define	POWER_LED_ON		0x00000001
-#define	POWER_LED_OFF		0x00000002
-#define	POWER_LED_FLASH		0x00000004
-#define	SERVICE_LED_ON		0x00000010
-#define	SERVICE_LED_OFF		0x00000020
-#define	SERVICE_LED_FLASH	0x00000040
-#define	FAULT_LED_ON		0x00000100
-#define	FAULT_LED_OFF		0x00000200
-#define	FAULT_LED_FLASH		0x00000400
-
-
-/*
- * Hot Plug Slot Descriptor.  Each hot pluggable slot will have
- * a schpc_slot_t structure allocated for it.
- */
-typedef struct {
-	dev_info_t	*devi;			/* Ptr to PCI dev_info */
-	uint32_t	state;			/* Slot's Hot Plug State */
-	uint16_t	pci_id;			/* PCI ID for slot */
-	uint8_t		expander;		/* Centerplane Expander */
-	uint8_t		board;			/* Number of IO Board 0/1 */
-	uint8_t		schizo;			/* Number of Schizo 0/1 */
-	uint8_t		leaf;			/* A or B (0 or 1) */
-	uint8_t		slot;			/* Slot Number */
-	slot_led_t	led;			/* Current LED state */
-	hpc_slot_ops_t	*slot_ops;		/* Ptr HPC entry points */
-	hpc_slot_info_t	slot_info;		/* Bus Specific SlotInfo */
-	hpc_slot_t	slot_handle;		/* Handle used by HPS */
-	char		nexus_path[MAXNAMELEN];	/* Pathname of Nexus */
-	char		ap_id[MAXNAMELEN];	/* Attachment point name */
-	caddr_t		saved_regs_va[3];	/* Reg set virtual addresses */
-	ddi_acc_handle_t saved_handle[3];	/* Handle from map in */
-	uint64_t	*saved_regs;		/* Ptr to saved off regs */
-	int		saved_size;		/* Size of saved off regs */
-} schpc_slot_t;
-
-/*
- * PCI/cPCI Hot Plug states for an attachment point
- */
-#define	SCHPC_SLOTSTATE_REC_GOOD	0x01	/* Receptacle is Good */
-#define	SCHPC_SLOTSTATE_OCC_GOOD	0x02	/* Occupant is Good */
-#define	SCHPC_SLOTSTATE_BAD_NEXUS	0x04	/* Invalid PCI Nexus */
-#define	SCHPC_SLOTSTATE_PRESENT		0x10	/* Occupant Present */
-#define	SCHPC_SLOTSTATE_CONNECTED	0x100	/* Receptacle Connected */
-#define	SCHPC_SLOTSTATE_CONFIGURED	0x1000	/* Occupant Configured */
-#define	SCHPC_SLOTSTATE_AUTOCFG_ENABLE	0x10000	/* Auto Configuration Enabled */
-#define	SCHPC_SLOTSTATE_ENUM		0x100000 /* ENUM Handling in progress */
-#define	SCHPC_SLOTSTATE_EXECUTING	0x200000 /* Executing a mailbox cmd */
-#define	SCHPC_SLOTSTATE_HPCINITED	0x400000 /* Ready to accept commands */
-
-/*
- * Soft state structure definition for each schpc instance.
- * There will be a single soft state stucture for each IO Board.
- */
-typedef struct schpc {
-	uint32_t	schpc_instance;		/* Instance # */
-	dev_info_t	*schpc_devi;		/* Ptr to dev_info */
-	kmutex_t	schpc_mutex;		/* Mutex to protect struct */
-	kcondvar_t	schpc_cv;		/* Conditional Variable */
-	char		*schpc_property;	/* Ptr to slot-table */
-	uint32_t	schpc_property_size;	/* Size of slot-table */
-	uint32_t	schpc_hotplugmodel;	/* Type of Hot Plug */
-	uint16_t	schpc_transid;		/* Current transaction ID */
-	uint16_t	schpc_number_of_slots;	/* Slot on IO Board */
-	struct schpc	*schpc_next;		/* Ptr to next schpc */
-	schpc_slot_t	*schpc_slot;		/* Slot Specific stuff */
-} schpc_t;
-
-/*
- * Types of Hot Plug/Hot Swap Models
- */
-#define	SCHPC_HOTPLUGTYPE_NOTHOTPLUGGABLE	0
-#define	SCHPC_HOTPLUGTYPE_CPCIHOTPLUG		1
-#define	SCHPC_HOTPLUGTYPE_CPCIHOTSWAPBASIC	2
-#define	SCHPC_HOTPLUGTYPE_CPCIHOTSWAPFULL	3
-#define	SCHPC_HOTPLUGTYPE_PCIHOTPLUG		4
-
-/*
- * schpc_t's slot table, schpc_slot[], is indexed by
- * a value in the range [0,STARCAT_MAX_SLOTS).
- *
- * That index is composed of these bit-fields:
- *
- *                   <-- slot num  -->
- *      |----------------------------|
- *      |  expander  | schizo | leaf |
- *      |------------|--------|------|
- *       7          2     1       0
- *
- */
-/* Extract various bit-fields from a slot table index: */
-#define	SCHPC_SLOT_EXPANDER(idx)	(((idx) & 0xfc) >> 2)
-#define	SCHPC_SLOT_SCHIZO(idx)		(((idx) & 0x2) >> 1)
-#define	SCHPC_SLOT_LEAF(idx)		((idx) & 0x1)
-#define	SCHPC_SLOT_NUM(idx)		((idx) & (0x1 | 0x2))
-
-/* Build a slot index from component bit-fields: */
-#define	SCHPC_MAKE_SLOT_INDEX2(expander, slot_num)\
-	(((expander) << 2) | (slot_num))
-#define	SCHPC_MAKE_SLOT_INDEX3(expander, schizo, leaf)\
-	(((expander) << 2) | ((schizo) << 1) | (leaf))
-
-/*
- * Integer values for the clock-frequency property.
- */
-#define	SCHPC_33MHZ	(33 * 1000 * 1000)
-#define	SCHPC_66MHZ	(66 * 1000 * 1000)
-#define	SCHPC_90MHZ	(90 * 1000 * 1000)
-#define	SCHPC_133MHZ	(133 * 1000 * 1000)
-
-/*
- * module-revision# for the XMITS versions
- */
-#define	XMITS_10	1
-#define	XMITS_20	2
-#define	XMITS_21	3
-#define	XMITS_30	4
-#define	XMITS_31	5
-
-extern int schpc_add_pci(dev_info_t *);
-extern int schpc_remove_pci(dev_info_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SCHPC_H */
--- a/usr/src/uts/sun4u/starcat/sys/schpc_msg.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_SCHPC_MSG_H
-#define	_SYS_SCHPC_MSG_H
-
-/*
- * This header file describes the messages that are sent between the
- * schpc Hot Plug Controller Driver running on the domain and the System
- * Controller.
- */
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Format of the Get Slot Status specific part of
- * PCI Hot Plug message.
- */
-typedef struct {
-	uint16_t	slot_power_on 		:1, /* Slot Power is on */
-			slot_powergood		:1, /* Slot Power is good */
-			slot_powerfault		:1, /* Slot Power has faulted */
-			slot_empty		:1, /* No occupant in slot */
-			slot_freq_cap		:2, /* Slot's Freq Capability */
-			slot_freq_setting	:2, /* Slot Freq setting */
-			slot_condition		:2, /* Condition of slot */
-			slot_HEALTHY		:1, /* Value of HEALTHY# sig */
-			slot_ENUM		:1, /* Value of ENUM# sig */
-			slot_mode_cap		:1, /* Conven or PCI-X */
-			slot_mode_setting	:1, /* Conven or PCI-X */
-			reserved		:2;
-	uint8_t		slot_replystatus;
-} pci_getslot_t;
-
-/*
- * Format of the Set Slot Status specific part of
- * PCI Hot Plug message.
- */
-typedef struct {
-	uint16_t	slot_power_on		:1, /* Connect Slot to bus */
-			slot_power_off		:1, /* Disconnect from bus */
-			slot_led_power		:2, /* Slot Power LED */
-			slot_led_service	:2, /* OK To Remove LED */
-			slot_led_fault		:2, /* Fault LED */
-			slot_disable_ENUM	:1, /* Disable ENUM Event */
-			slot_enable_ENUM	:1, /* Enable ENUM Event */
-			slot_disable_HEALTHY	:1, /* Disable HEALTHY EVENT */
-			slot_enable_HEALTHY	:1, /* Enable HEALTHY EVENT */
-			reserved		:4;
-	uint8_t		slot_replystatus;
-} pci_setslot_t;
-
-/*
- * Format of the Slot Event specific part of
- * the PCI Hot Plug message.
- */
-typedef struct {
-	uint16_t	slot_power		:1, /* Slot Power has changed */
-			slot_presence		:1, /* occupant has been    */
-						    /* inserted or removed  */
-			slot_ENUM		:1, /* ENUM# has changed */
-			slot_HEALTHY		:1, /* HEALTHY# has changed */
-			slot_powergood		:1, /* Power is good */
-			slot_powerfault		:1, /* Power has faulted */
-			reserved		:10;
-} pci_slotevent_t;
-
-/*
- * PCI Hot Plug message
- */
-typedef struct {
-	uint8_t		pcimsg_node;
-	uint8_t		pcimsg_board;
-	uint8_t		pcimsg_slot;
-	uint8_t		pcimsg_revision;
-	uint8_t		pcimsg_command;
-	union {
-		pci_setslot_t	pcimsg_setslot;
-		pci_getslot_t	pcimsg_getslot;
-		pci_slotevent_t	pcimsg_slotevent;
-	} pcimsg_type;
-} pcimsg_t;
-
-/*
- * Keys for the outgoing and incoming mailboxes
- */
-#define	KEY_PCSC	0x50435343	/* Outgoing Mailbox 'PCSC' */
-#define	KEY_SCPC	0x53435043	/* Incoming Mailbox 'SCPC' */
-
-/*
- * default timeout in seconds for mboxsc_getmsg calls
- */
-#define	PCSC_TIMEOUT	30
-
-/* Commands */
-#define	PCIMSG_GETSLOTSTATUS	0x1
-#define	PCIMSG_SETSLOTSTATUS	0x2
-#define	PCIMSG_SLOTEVENT	0x3
-
-/* Message Revisions */
-#define	PCIMSG_REVISION		0x10
-#define	PCIMSG_REVISION_1_0	0x10
-
-/*
- * Values for the slot_condition field of the get slot status command.
- */
-#define	PCIMSG_SLOTCOND_UNKNOWN		0x0
-#define	PCIMSG_SLOTCOND_GOOD		0x1
-#define	PCIMSG_SLOTCOND_REC_FAIL	0x2
-#define	PCIMSG_SLOTCOND_OCC_FAIL	0x3
-
-/*
- * Values for the slot_freq_cap and slot_freq_setting fields of the get
- * slot status command.
- */
-#define	PCIMSG_FREQ_33MHZ	0x0
-#define	PCIMSG_FREQ_66MHZ	0x1
-#define	PCIMSG_FREQ_90MHZ	0x2
-#define	PCIMSG_FREQ_133MHZ	0x3
-
-/*
- * Values for the slot_mode_cap and slot_mode_setting of the get
- * slot status command.
- */
-#define	PCIMSG_MODE_CONVEN	0x0
-#define	PCIMSG_MODE_PCIX	0x1
-
-/*
- * Values for the PRSNT signals.
- */
-#define	PCIMSG_PRSNT_NOADAPTER	0x0
-#define	PCIMSG_PRSNT_25W	0x1
-#define	PCIMSG_PRSNT_15W	0x2
-#define	PCIMSG_PRSNT_7_5W	0x3
-
-/*
- * Values to turn on and off slot characteristics.
- */
-#define	PCIMSG_ON		0x1
-#define	PCIMSG_OFF		0x0
-
-/*
- * Values to set the power, service and fault LEDs
- */
-#define	PCIMSG_LED_OFF		0x00
-#define	PCIMSG_LED_ON		0x01
-#define	PCIMSG_LED_FLASH	0x02
-
-/*
- * Return values for the slot_replystatus field for the get/set slot status
- * commands.
- */
-#define	PCIMSG_REPLY_GOOD	0x0
-#define	PCIMSG_REPLY_FAIL	0x1
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_SCHPC_MSG_H */
--- a/usr/src/uts/sun4u/starcat/sys/sckm_io.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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	_SYS_SCKM_IO_H
-#define	_SYS_SCKM_IO_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * This header file defines the interface between the sckmd daemon and
- * the sckmdrv driver.
- */
-
-#include <sys/types.h>
-
-#define	SCKM_IOC	('s' << 8)
-
-enum sckm_ioctl {
-	SCKM_IOCTL_GETREQ = SCKM_IOC,
-	SCKM_IOCTL_STATUS
-};
-
-/*
- * Structure passed by sckmd daemon to the sckmdrv driver during
- * a SCKM_IOCTL_GETREQ ioctl call.
- */
-typedef struct sckm_ioctl_getreq {
-	uint64_t transid;	/* returned by driver */
-	uint32_t type;		/* message type */
-	caddr_t buf;		/* user buffer to store msg */
-	uint32_t buf_len;	/* size of buf */
-} sckm_ioctl_getreq_t;
-
-#if defined(_SYSCALL32)
-typedef struct sckm_ioctl_getreq_32 {
-	uint64_t transid;	/* returned by driver */
-	uint32_t type;		/* message type */
-	caddr32_t buf;		/* user buffer to store msg */
-	uint32_t buf_len;	/* size of buf */
-} sckm_ioctl_getreq32_t;
-#endif /* defined(_SYSCALL32) */
-
-/*
- * Structure passed by sckmd daemon to the sckmdrv driver during
- * a SCKM_IOCTL_STATUS ioctl call.
- */
-typedef struct sckm_ioctl_status {
-	uint64_t transid;		/* set by daemon */
-	uint32_t status;		/* execution status */
-	uint32_t sadb_msg_errno;	/* PF_KEY errno, if applicable */
-	uint32_t sadb_msg_version;	/* PF_KEY version, if applicable */
-} sckm_ioctl_status_t;
-
-/*
- * Valid request types returned by the SCKM_IOCTL_GETREQ ioctl.
- */
-#define	SCKM_IOCTL_REQ_SADB		0x0	/* SADB message */
-
-/*
- * Valid values for the status field of the sckm_ioctl_status structure.
- */
-#define	SCKM_IOCTL_STAT_SUCCESS		0x0	/* operation success */
-#define	SCKM_IOCTL_STAT_ERR_PFKEY	0x1	/* PF_KEY error */
-#define	SCKM_IOCTL_STAT_ERR_REQ		0x2	/* invalid request */
-#define	SCKM_IOCTL_STAT_ERR_VERSION	0x3	/* not supp. PF_KEY version */
-#define	SCKM_IOCTL_STAT_ERR_TIMEOUT	0x4	/* no response from PF_KEY */
-#define	SCKM_IOCTL_STAT_ERR_OTHER	0x5	/* other daemon error */
-#define	SCKM_IOCTL_STAT_ERR_SADB_TYPE	0x6	/* bad SADB msg type */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _SYS_SCKM_IO_H */
--- a/usr/src/uts/sun4u/starcat/sys/sckm_msg.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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_SCKM_MSG_H
-#define	_SYS_SCKM_MSG_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * This header file describes the format of the IOSRAM mailbox messages
- * exchanged between the sckmr driver on a Starcat Domain and the
- * Starcat System Controller.
- */
-
-#include <sys/types.h>
-
-/*
- * MBOXSC_MSG_EVENT or MBOXSC_MSG_REQUEST message header.
- */
-typedef struct sckm_mbox_req_hdr {
-	uint32_t sckm_version;		/* protocol version */
-	uint32_t reserved;
-} sckm_mbox_req_hdr_t;
-
-/*
- * MBOXSC_MSG_REPLY message header
- */
-typedef struct sckm_mbox_rep_hdr {
-	uint32_t sckm_version;		/* protocol version */
-	uint32_t status;		/* error code */
-	uint32_t sadb_msg_errno;	/* PF_KEY errno, if applicable */
-	uint32_t sadb_msg_version;	/* PF_KEY version, if applicable */
-} sckm_mbox_rep_hdr_t;
-
-/*
- * Version of this current protocol.
- */
-#define	SCKM_PROTOCOL_VERSION	1
-
-/*
- * Keys for SC to Domain and Domain to SC mailboxes
- */
-#define	KEY_SCKD	0x53434b44	/* SC to Domain mailbox */
-#define	KEY_KDSC	0x4b445343	/* Domain to SC mailbox */
-
-/*
- * Max data size, in bytes, for IOSRAM mailboxes
- */
-#define	SCKM_SCKD_MAXDATA	1024
-#define	SCKM_KDSC_MAXDATA	1024
-
-/*
- * Message types.
- */
-#define	SCKM_MSG_SADB		0x1	/* SADB message		SC<->D */
-
-/*
- * Values for sckm_msg_rep_hdr status field.
- */
-#define	SCKM_SUCCESS		0x0	/* Operation succeeded */
-#define	SCKM_ERR_VERSION	0x1	/* Unexpected version */
-#define	SCKM_ERR_SADB_PFKEY	0x2	/* PF_KEY returned an error */
-#define	SCKM_ERR_SADB_MSG	0x3	/* bad SADB msg detect by driver */
-#define	SCKM_ERR_DAEMON		0x4	/* Error communicating with daemon */
-#define	SCKM_ERR_BAD_CMD	0x5	/* unknown command */
-#define	SCKM_ERR_SADB_VERSION	0x6	/* bad SADB version */
-#define	SCKM_ERR_SADB_TIMEOUT	0x7	/* no response from key engine */
-#define	SCKM_ERR_SADB_BAD_TYPE	0x8	/* bad SADB msg type */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif /* _SYS_SCKM_MSG_H */
--- a/usr/src/uts/sun4u/starcat/sys/starcat.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +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.
- */
-
-#ifndef _SYS_STARCAT_H
-#define	_SYS_STARCAT_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-/*
- * Manifest constants of Starcat configuration
- */
-
-#define	STARCAT_BDSET_MAX	18	/* maximum number of boardsets	*/
-
-#define	STARCAT_BDSET_MIN	1	/* minimum number of boardsets	*/
-
-#define	STARCAT_BDSET_SLOT_MAX	2	/* maximum slots per boardset	*/
-
-#define	STARCAT_SLOT0_CPU_MAX	8	/* max CPUs per slot 0 board	*/
-
-#define	STARCAT_SLOT1_CPU_MAX	4	/* max CPUs per slot 1 board	*/
-
-#define	STARCAT_BDSET_CPU_MAX	12	/* maximum CPUs per boardset	*/
-
-#define	STARCAT_SLOT0_MEM_MAX	4	/* max mem units per slot 0 bd	*/
-
-#define	STARCAT_SLOT1_MEM_MAX	0	/* max mem units per slot 1 bd	*/
-
-#define	STARCAT_BDSET_MEM_MAX	4	/* max mem units per boardset	*/
-
-#define	STARCAT_SLOT0_IO_MAX	0	/* max I/O ctrlrs per slot 0 bd	*/
-
-#define	STARCAT_SLOT1_IO_MAX	2	/* max I/O ctrlrs per slot 1 bd	*/
-
-#define	STARCAT_BDSET_IO_MAX	2	/* max I/O ctrlrs per boardset	*/
-
-#define	STARCAT_TSB_PER_IO	2	/* each IO has two leaves */
-
-					/* max prealloc spare tsb's	*/
-#define	STARCAT_SPARE_TSB_MAX	\
-	(STARCAT_BDSET_MAX * STARCAT_BDSET_IO_MAX * STARCAT_TSB_PER_IO)
-
-/*
- * Data bearing mondo vector (DMV) support
- *
- * For Starcat, we need to add a few extra "hardware" dmv interrupts.
- * These actually do not correspond to physical hardware but are used
- * by Starcat IDN.
- */
-#define	STARCAT_DMV_EXTRA	4
-#define	STARCAT_DMV_HWINT	(MAX_UPA + STARCAT_DMV_EXTRA)
-#define	STARCAT_DMV_IDN_BASE	(MAX_UPA)
-
-/*
- * The CPU ID on starcat looks like this:
- *
- *     9        5  4     3     2    1    0
- *    --------------------------------------
- *    | Expander |   | Slot | Core | LPORT |
- *    --------------------------------------
- *
- * Expander   Starcat has STARCAT_BDSET_MAX (18) expanders.
- * Slot       Starcat has STARCAT_BDSET_SLOT_MAX (2) slots per expander.
- *            Slot 0 carries a CPU-MEM board which has 4 processor chips.
- *            Slot 1 carries an I/O board typically. But it can be
- *            configured to carry a MAXCAT board which has 2 processor
- *            chips on board.
- * LPORT      Port number within the slot for a chip. This is also the
- *            chip number within the slot. Note that Slot 1 can have only
- *            2 chips, but this representation allows for 4. This is just
- *            the theoretical max.
- * Core       Core number within the chip.
- *
- * Currently, the maximum number of cores supported is 2 per chip (on
- * Panther and Jaguar).
- *
- */
-/*
- * Macros for manipulating CPU IDs
- */
-#define	STARCAT_CPUID_TO_EXPANDER(p)	(((p) >> 5) & 0x1f)
-#define	STARCAT_CPUID_TO_BOARDSLOT(p)	(((p) >> 3) & 0x1)
-#define	STARCAT_CPUID_TO_PORTID(p)	((p) & ~0x4)
-#define	STARCAT_CPUID_TO_COREID(p)	(((p) >> 2) & 0x1)
-#define	STARCAT_CPUID_TO_CORE_BIT(p)	((p) & (0x1 << 2))
-#define	STARCAT_CPUID_TO_AGENT(p)	((p) & 0x7)
-#define	STARCAT_CPUID_TO_LPORT(p)	((p) & 0x3)
-
-#define	MAKE_CPUID(e, s, a)	\
-		((((e) & 0x1f) << 5) | (((s) & 0x1) << 3) | ((a) & 0x7))
-
-/*
- * Definitions for decoding memory controller registers.  These values
- * are taken from Chapter 9 of the SPARCV9 JSP-1 US-III implementation
- * supplement.
- */
-
-/* Starcat has four banks of memory per MC */
-#define	MAX_BANKS_PER_MC	(4)
-
-/* Use only low bits for local CPU MC ASI */
-#define	MC_OFFSET_MASK		(0xffu)
-
-/* Shifts to access specific fields of the memdecode register */
-#define	MC_VALID_SHIFT		(63)	/* Shift for valid bit */
-#define	MC_UK_SHIFT		(41)	/* Shift for upper mask field */
-#define	MC_UM_SHIFT		(20)	/* Shift for upper match field */
-#define	PHYS2UM_SHIFT		(26)	/* UM field matches bits 42-26 of PA */
-
-/* Extract upper mask field from the decode register */
-#define	MC_UK(memdec)		(((memdec) >> MC_UK_SHIFT) & 0xfffu)
-
-/* Extract upper match field from memdecode register */
-#define	MC_UM(memdec)		(((memdec) >> MC_UM_SHIFT) & 0x1fffffu)
-
-/* Size of the range covered by the address mask field */
-#define	MC_UK2SPAN(memdec)	((MC_UK(memdec) + 1) << PHYS2UM_SHIFT)
-
-/* The base PA the memdecode register will respond to */
-#define	MC_BASE(memdec)		(MC_UM(memdec) & ~(MC_UK(memdec)))
-
-
-/*
- * Prototypes for functions
- */
-
-extern int set_platform_max_ncpus(void);
-extern int plat_max_boards(void);
-extern int plat_max_cpu_units_per_board(void);
-extern int plat_max_mem_units_per_board(void);
-extern int plat_max_io_units_per_board(void);
-extern uint64_t lddmcdecode(uint64_t);
-
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_STARCAT_H */
--- a/usr/src/uts/sun4u/starcat/unix/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +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 starcat 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_STARCAT_KERN_DIR)/$(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/starcat/Makefile.starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(UNIX_BIN)
-LINT_TARGET	= $(LINT_LIB)
-INSTALL_TARGET	= $(UNIX_BIN) $(ROOTMODULE)
-
-#
-#       Overrides
-#
-ALL_BUILDS      = $(ALL_BUILDSONLY64)
-DEF_BUILDS      = $(DEF_BUILDSONLY64)
-SYM_BUILDS      = $(DEF_BUILDSONLY64)
-CLEANLINTFILES  += $(LINT32_FILES)
-
-#
-#	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)
-
-symcheck:       $(SYM_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)
-
-symcheck.targ:	$(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) $(DTRACESTUBS) 
-	$(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_DIR 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/starcat/Makefile.targ
--- a/usr/src/uts/sun4u/sys/pci/pci_axq.h	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2001 by Sun Microsystems, Inc.
- * All rights reserved.
- */
-
-#ifndef	_SYS_PCI_AXQ_H
-#define	_SYS_PCI_AXQ_H
-
-#include <sys/types.h>
-#include <sys/atomic.h>
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#define	PIO_LIMIT_ENTER(p)	{ \
-				int n;\
-				for (;;) {\
-					do {\
-						n = p->pbm_pio_counter;\
-					} while (n <= 0);\
-					if (atomic_dec_32_nv(\
-					    (uint_t *)&p->pbm_pio_counter)\
-					    == (n - 1))\
-						break;\
-					atomic_inc_32(\
-					    (uint_t *)&p->pbm_pio_counter);\
-				}\
-				}
-
-
-
-#define	PIO_LIMIT_EXIT(p)	atomic_inc_32((uint_t *)&p->pbm_pio_counter);
-
-extern void pci_axq_setup(ddi_map_req_t *mp, pbm_t *pbm_p);
-extern void pci_axq_pio_limit(pbm_t *pbm_p);
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_PCI_AXQ_H */
--- a/usr/src/uts/sun4u/sys/pci/pci_obj.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/sys/pci/pci_obj.h	Fri May 31 14:32:40 2019 +0200
@@ -23,6 +23,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright 2019 Peter Tribble.
+ */
+
 #ifndef	_SYS_PCI_OBJ_H
 #define	_SYS_PCI_OBJ_H
 
@@ -56,7 +60,6 @@
 #ifdef PCI_DMA_TEST
 #include <sys/pci/pci_test.h>
 #endif
-#include <sys/pci/pci_axq.h>
 
 #ifdef	__cplusplus
 }
--- a/usr/src/uts/sun4u/sys/prom_plat.h	Wed May 29 18:07:38 2019 +0200
+++ b/usr/src/uts/sun4u/sys/prom_plat.h	Fri May 31 14:32:40 2019 +0200
@@ -253,16 +253,6 @@
 extern	int		prom_serengeti_tunnel_switch(uint_t node, uint_t board);
 
 /*
- * Starcat-specific routines
- */
-extern	int		prom_starcat_switch_tunnel(uint_t portid,
-			    uint_t msgtype);
-extern	int		prom_starcat_iosram_read(uint32_t key, uint32_t offset,
-			    uint32_t len, caddr_t buf);
-extern	int		prom_starcat_iosram_write(uint32_t key, uint32_t offset,
-			    uint32_t len, caddr_t buf);
-
-/*
  * OPL-specific routines
  */
 extern	void		prom_opl_get_tod(time_t *time, int64_t *stickval);
--- a/usr/src/uts/sun4u/todstarcat/Makefile	Wed May 29 18:07:38 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# uts/sun4u/todstarcat/Makefile
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-#
-#	This makefile drives the production of the todstarcat
-#	kernel module.
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= todstarcat
-OBJECTS		= $(TODSTARCAT_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(TODSTARCAT_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_PSM_TOD_DIR)/$(MODULE)
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/sun4u/Makefile.sun4u
-
-INC_PATH += -I$(UTSBASE)/sun4u/starcat
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
-
-#
-# module dependencies
-#
-LDFLAGS += -dy -Ndrv/sbbc -Ndrv/iosram
-
-#
-#	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