diff options
author | Peter Tribble <peter.tribble@gmail.com> | 2019-01-28 12:15:59 +0000 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2019-02-07 21:46:57 -0500 |
commit | 2a1fd0ffe121888d44fdec321c25b53dcfaa9118 (patch) | |
tree | 6b545d7ee224e6bc3f0fe80f3b231fa325f06368 /usr | |
parent | 84a8796cdac4378079f720e0ca4d2ff15eb1b8b7 (diff) | |
download | illumos-joyent-2a1fd0ffe121888d44fdec321c25b53dcfaa9118.tar.gz |
10318 Remove starfire support
Reviewed by: Andy Stormont <astormont@racktopsystems.com>
Reviewed by: Andy Fiddaman <af@citrus-it.net>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr')
115 files changed, 151 insertions, 44331 deletions
diff --git a/usr/src/cmd/cvcd/Makefile b/usr/src/cmd/cvcd/Makefile index 8fcf5909b8..b2b85d4613 100644 --- a/usr/src/cmd/cvcd/Makefile +++ b/usr/src/cmd/cvcd/Makefile @@ -19,16 +19,15 @@ # CDDL HEADER END # # -# ident "%Z%%M% %I% %E% SMI" -# # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # -# Makefile definitions for Starfire Network Console related items. +# Makefile definitions for Starcat Network Console related items. # # cmd/cvcd/Makefile # -# These utilities are specific to the Ultra-Enterprise-10000 platform at this +# These utilities are specific to the Sun-Fire-15000 platform at this # time. # diff --git a/usr/src/cmd/cvcd/cvc.xml b/usr/src/cmd/cvcd/cvc.xml index 346a4d3e79..4b88288850 100644 --- a/usr/src/cmd/cvcd/cvc.xml +++ b/usr/src/cmd/cvcd/cvc.xml @@ -3,6 +3,7 @@ <!-- Copyright 2007 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. + Copyright 2019 Peter Tribble. CDDL HEADER START @@ -23,8 +24,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 Starfire --> + <!-- sckmd is required on OPL and Starcat --> <dependency name='sckmd' grouping='optional_all' diff --git a/usr/src/cmd/cvcd/sparc/Makefile b/usr/src/cmd/cvcd/sparc/Makefile index 1be28bcac0..e5c629cfc3 100644 --- a/usr/src/cmd/cvcd/sparc/Makefile +++ b/usr/src/cmd/cvcd/sparc/Makefile @@ -20,12 +20,11 @@ # CDDL HEADER END # # -# ident "%Z%%M% %I% %E% SMI" -# # Copyright (c) 1997 by Sun Microsystems, Inc. # All rights reserved. +# Copyright 2019 Peter Tribble. # -# Makefile definitions for Starfire's Network Console related items. +# Makefile definitions for Starcat's Network Console related items. # # cmd/cvcd/sparc/Makefile # diff --git a/usr/src/cmd/cvcd/sparc/sun4u/Makefile b/usr/src/cmd/cvcd/sparc/sun4u/Makefile index ca4dcf086f..e9bbcd1148 100644 --- a/usr/src/cmd/cvcd/sparc/sun4u/Makefile +++ b/usr/src/cmd/cvcd/sparc/sun4u/Makefile @@ -20,17 +20,16 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# # Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # -# Makefile definitions for Starfire and Starcat Network Console related items. +# Makefile definitions for Starcat Network Console related items. # # cmd/cvcd/sparc/sun4u/Makefile # -SUBDIRS = starfire starcat +SUBDIRS = starcat all := TARGET= all install := TARGET= install diff --git a/usr/src/cmd/cvcd/sparc/sun4u/starfire/Makefile b/usr/src/cmd/cvcd/sparc/sun4u/starfire/Makefile deleted file mode 100644 index 1ec26f96d7..0000000000 --- a/usr/src/cmd/cvcd/sparc/sun4u/starfire/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# cmd/cvcd/sparc/sun4u/starfire/cvcd -# -PROG= cvcd -ROOTFS_PROG= $(PROG) -PLATFORM= SUNW,Ultra-Enterprise-10000 - -# Create default so empty rules don't confuse make -CLASS= 32 - -SRCS= $(PROG:%=%.c) -OBJS= $(PROG:%=%.o) - -include ../../../../Makefile.cmd -include ../../../../../Makefile.psm - -FILEMODE= 0700 - -ROOTPSMPROG = $(ROOT_PSM_LIB_DIR)/$(PROG) - -CPPFLAGS = -I$(USR_PSM_INCL_DIR) $(CPPFLAGS.master) -CERRWARN += -_gcc=-Wno-unused-variable - -LDLIBS += -lsocket -lnsl - -.KEEP_STATE: - -all: $(ROOTFS_PROG) - -install: all .WAIT $(ROOTPSMPROG) - -clean: - $(RM) $(PROG) $(OBJS) - -lint: lint_PROG - -include ../../../../Makefile.targ -include ../../../../../Makefile.psm.targ diff --git a/usr/src/cmd/cvcd/sparc/sun4u/starfire/cvcd.c b/usr/src/cmd/cvcd/sparc/sun4u/starfire/cvcd.c deleted file mode 100644 index 008d33af99..0000000000 --- a/usr/src/cmd/cvcd/sparc/sun4u/starfire/cvcd.c +++ /dev/null @@ -1,930 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, 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. - */ - - -/* - * This code implements the Starfire Virtual Console host daemon - * (see cvcd(1M)). It accepts a connection from netcon_server - * and transfers console I/O to/from the SSP across the - * network via TLI. The I/O is sent to the cvcredir device - * on the host (see cvc(7) and cvcredir(7)). It also sends - * disconnect and break ioctl's to the kernel CVC drivers. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - - -#include <stdio.h> -#include <stdarg.h> -#include <syslog.h> -#include <stdlib.h> -#include <tiuser.h> -#include <sys/timod.h> -#include <fcntl.h> -#include <sys/param.h> -#include <sys/utsname.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stropts.h> -#include <sys/conf.h> -#include <pwd.h> -#include <errno.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <locale.h> -#include <termio.h> -#include <signal.h> -#include <sys/cvc.h> - -#include <string.h> - -#include <sys/ioctl.h> -#include <sys/file.h> -#include <sys/sockio.h> - -#include <sys/tihdr.h> - -#include <netdb.h> -#include <net/if.h> -#include <netinet/if_ether.h> - -#include <inet/common.h> -#include <sys/systeminfo.h> - -/* Process priority control */ -#include <sys/priocntl.h> -#include <sys/tspriocntl.h> -#include <sys/rtpriocntl.h> - -/* - * Misc. defines. - */ -#define CONREF "connection request from illegal host" -#define SSPHOSTNAMEFILE "/etc/ssphostname" -#define NODENAME "/etc/nodename" -#define MAXIFS 256 - -/* - * Function prototypes - */ -static void cvcd_connect(int fd, struct pollfd *); -static void cvcd_reject(int fd); -static void cvcd_read(struct pollfd *); -static void cvcd_write(char *data, int size); -static void cvcd_status(int fd); -static void cvcd_winch(int, char *, int); -static void cvcd_ioctl(int fd, int cmd); -static void cvcd_err(int code, char *format, ...); -static void usage(void); -static id_t schedinfo(char *name, short *maxpri); -static void cvcd_setopt(int fd, int name); - -/* - * Globals - */ -static int rconsfd; /* Console redirection driver */ -static char progname[MAXPATHLEN]; -static char ssphostname[MAXPATHLEN]; -static int debug = 0; -static int connected = 0; -static int peercheck = 1; -static char nic_name[32]; - -int -main(int argc, char **argv) -{ - int opt; - int tport = 0; - char *hostname; - struct utsname utsname; - struct t_info tinfo; - int cvcd_ssp; - int nfd; - struct pollfd *cvcd_pfd; - int i; - int j; - struct servent *se; - struct sockaddr_in *sin; - struct t_bind *reqb; - struct t_bind *retb; - struct t_optmgmt *topt, *tropt; - struct opthdr *sockopt; - int on = 1; - int tmperr = 0; - int event; - char prefix[256]; - pcparms_t pcparms; - tsparms_t *tsparmsp; - id_t pid, tsID; - short tsmaxpri; - static int netcon_fail = 0; - - (void) setlocale(LC_ALL, ""); - (void) strcpy(progname, argv[0]); - (void) memset(ssphostname, 0, MAXPATHLEN); - - if ((cvcd_ssp = open(SSPHOSTNAMEFILE, O_RDONLY)) < 0) { - /* - * If there is no /etc/ssphostname disable peer check after - * issuing warning. - */ - tmperr = errno; - peercheck = 0; - } else { - if ((i = read(cvcd_ssp, ssphostname, MAXPATHLEN)) < 0) { - cvcd_err(LOG_ERR, "failed to read ssphostname"); - } - /* - * The ssp-config(1M) command newline terminates the - * ssphostname in the /etc/ssphostname file - */ - ssphostname[i-1] = '\0'; - (void) close(cvcd_ssp); - - (void) memset(nic_name, 0, sizeof (nic_name)); - } - -#if defined(DEBUG) - while ((opt = getopt(argc, argv, "dp:r:")) != EOF) { -#else - while ((opt = getopt(argc, argv, "r:")) != EOF) { -#endif /* DEBUG */ - switch (opt) { - -#if defined(DEBUG) - case 'd' : debug = 1; - break; - - case 'p' : tport = atoi(optarg); - break; -#endif /* DEBUG */ - - case 'r' : (void) strcpy(ssphostname, optarg); - break; - - default : 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 ((nfd = open(NODENAME, O_RDONLY)) > 0) { - if ((i = read(nfd, utsname.nodename, SYS_NMLN)) <= 0) { - cvcd_err(LOG_WARNING, - "failed to acquire hostname"); - } - utsname.nodename[i-1] = '\0'; - (void) close(nfd); - } - } - - /* - * Must be root. - */ - if (debug == 0 && geteuid() != 0) { - fprintf(stderr, "cvcd: Must be root"); - exit(1); - } - - /* - * Daemonize... - */ - if (debug == 0) { - for (i = 0; i < NOFILE; i++) { - (void) close(i); - } - (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); - } - if (peercheck == 0) { - cvcd_err(LOG_ERR, "open(SSPHOSTNAMEFILE):%s", - strerror(tmperr)); - } - - cvcd_pfd = (struct pollfd *)malloc(3*sizeof (struct pollfd)); - if (cvcd_pfd == (struct pollfd *)NULL) { - cvcd_err(LOG_ERR, "malloc:", strerror(errno)); - exit(1); - } - (void) memset((void *)cvcd_pfd, 0, 3*sizeof (struct pollfd)); - cvcd_pfd[0].fd = -1; - cvcd_pfd[1].fd = -1; - cvcd_pfd[2].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. - */ - 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, - "cvcd: GETPARMS failed. Warning: can't get ", - "TS priorities."); - } else { - /* Get class IDs and maximum priorities for a TS process */ - if ((tsID = schedinfo("TS", &tsmaxpri)) == -1) { - cvcd_err(LOG_ERR, "cvcd: Warning, can't get ", - "TS scheduler info."); - } else { - if (debug) { /* Print priority info */ - if (pcparms.pc_cid == tsID) { - cvcd_err(LOG_DEBUG, "%s%d%s%d%s%d\n", - "cvcd:: PID:", pid, - ", TS priority:", - tsparmsp->ts_upri, - ", TS max_pri:", tsmaxpri); - } - } - /* Change proc's priority to maxtspri */ - pcparms.pc_cid = tsID; - tsparmsp = (struct tsparms *)pcparms.pc_clparms; - tsparmsp->ts_upri = tsmaxpri; - tsparmsp->ts_uprilim = tsmaxpri; - - if (priocntl(P_PID, pid, PC_SETPARMS, - (caddr_t)&pcparms) == -1L) { - cvcd_err(LOG_ERR, "cvcd: Warning, ", - "can't set TS maximum priority."); - } - /* Done */ - if (debug) { /* Get new scheduler properties for PID */ - if (priocntl(P_PID, pid, PC_GETPARMS, - (caddr_t)&pcparms) == -1L) { - cvcd_err(LOG_DEBUG, "GETPARMS failed"); - exit(1); - } else { - cvcd_err(LOG_DEBUG, "%s%d%s%d%s%d\n", - "cvcd:: PID:", pid, - ", New TS priority:", - tsparmsp->ts_upri, - ", TS max_pri:", tsmaxpri); - } - } - } - } - - if (debug == 1) { - cvcd_err(LOG_DEBUG, "tport = %d, debug = %d", tport, debug); - } - - 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; - } - - cvcd_ssp = t_open(TCP_DEV, O_RDWR, &tinfo); - if (cvcd_ssp == -1) { - cvcd_err(LOG_ERR, "t_open: %s", t_errlist[t_errno]); - exit(1); - } - - /* - * Set the SO_REUSEADDR option for this TLI endpoint. - */ - cvcd_setopt(cvcd_ssp, SO_REUSEADDR); - - /* - * Set the SO_DONTROUTE option for this TLI endpoint, if - * /etc/ssphostname exists. - */ - if (peercheck == 1) - cvcd_setopt(cvcd_ssp, SO_DONTROUTE); - - /* - * Bind it. - */ - if (((reqb = (struct t_bind *)t_alloc(cvcd_ssp, T_BIND, T_ALL)) - == (struct t_bind *)NULL)) { - cvcd_err(LOG_ERR, "%s", t_errlist[t_errno]); - exit(1); - } - if (((retb = (struct t_bind *)t_alloc(cvcd_ssp, T_BIND, T_ALL)) - == (struct t_bind *)NULL)) { - cvcd_err(LOG_ERR, "%s", t_errlist[t_errno]); - exit(1); - } - reqb->qlen = 1; - reqb->addr.len = sizeof (struct sockaddr_in); - sin = (struct sockaddr_in *)reqb->addr.buf; - (void) memset((void *)sin, 0, sizeof (struct sockaddr_in)); - sin->sin_family = AF_INET; - - - sin->sin_addr.s_addr = htonl(INADDR_ANY); - sin->sin_port = htons(tport); - if (t_bind(cvcd_ssp, reqb, retb) == -1) { - cvcd_err(LOG_ERR, "t_bind: %s", t_errlist[t_errno]); - exit(1); - } - sin = (struct sockaddr_in *)retb->addr.buf; - if (sin->sin_port != htons(tport)) { - cvcd_err(LOG_ERR, "t_bind: bound to wrong port"); - cvcd_err(LOG_ERR, "Wanted %d, got %d", tport, - ntohs(sin->sin_port)); - exit(1); - } - - t_free((char *)reqb, T_BIND); - t_free((char *)retb, T_BIND); - - - /* - * Wait for connect from OBP. - */ - cvcd_pfd[2].fd = cvcd_ssp; - cvcd_pfd[2].events = POLLIN|POLLPRI; - if ((event = poll(&cvcd_pfd[2], 1, -1)) == -1) { - cvcd_err(LOG_ERR, "poll: %s", strerror(errno)); - exit(1); - } - /* - * cvcd_connect sets global - * connected = 1 if successful. - */ - cvcd_connect(cvcd_ssp, cvcd_pfd); - - /* - * Now set up the Network Console redirection driver. - */ - rconsfd = open(CVCREDIR_DEV, O_RDWR|O_NDELAY); - if (rconsfd < 0) { - cvcd_err(LOG_ERR, "open: %s", strerror(errno)); - exit(1); - } - - /* - * cvcd_pfd holds three file descriptors we need to poll from: - * 0 will be connected to in_cvcd; 1 is the CVC Redirection driver; - * and 2 is the listen endpoint for new connections. - */ - cvcd_pfd[1].fd = rconsfd; - cvcd_pfd[1].events = POLLIN; - /* - * Loop through main service routine. We check for inbound in.cvcd - * connection and data xfer between host and in.cvcd. - */ - for (;;) { - - char buf[MAXPKTSZ]; - - /* - * Check for in_cvcd connect requests. - */ - switch ((event = t_look(cvcd_ssp))) { - case -1 : - cvcd_err(LOG_ERR, "%s", t_errlist[t_errno]); - exit(1); - /* NOTREACHED */ - break; - case 0 : /* Nothing to do */ - break; - case T_LISTEN : - if (connected == 1) { - /* - * Someone already connected. - */ - cvcd_reject(cvcd_ssp); - } else { - /* - * cvcd_connect sets global - * connected = 1 if successful. - */ - cvcd_connect(cvcd_ssp, cvcd_pfd); - - /* - * Re-open the cvcredir driver if - * the netcon_fail is true. This - * indicates there was a previous - * network connection that got closed. - */ - if (netcon_fail) { - rconsfd = open(CVCREDIR_DEV, - O_RDWR|O_NDELAY); - if (rconsfd < 0) { - cvcd_err(LOG_ERR, - "open: %s", - strerror(errno)); - exit(1); - } - cvcd_pfd[1].fd = rconsfd; - cvcd_pfd[1].events = POLLIN; - netcon_fail = 0; - } - } - break; - default : - cvcd_err(LOG_ERR, - "Illegal event %d for cvcd_ssp", event); - exit(1); - } - /* - * Take a look for console I/O or connect request. - */ - if ((event = poll(cvcd_pfd, 3, -1)) == -1) { - cvcd_err(LOG_ERR, "poll: %s", strerror(errno)); - exit(1); - } - - /* - * The following for loop is to detect any bad - * things(ie hangup,errors,invalid fd) have happened - * to the file descriptors we're interested in. - * If so, disconnect current network console connection. - */ - for (j = 0; j < 3; j++) { - if (cvcd_pfd[j].revents & (POLLERR|POLLHUP|POLLNVAL)) { - cvcd_err(LOG_WARNING, - "poll: status on %s fd:%s%s%s", - ((j == 2) ? "listen" : - ((j == 0) ? "network" : "redir")), - (cvcd_pfd[j].revents & POLLERR) ? - " error" : "", - (cvcd_pfd[j].revents & POLLHUP) ? - " hangup" : "", - (cvcd_pfd[j].revents & POLLNVAL) ? - " bad fd" : ""); - - (void) t_close(cvcd_pfd[0].fd); - cvcd_pfd[0].fd = -1; - - (void) close(cvcd_pfd[1].fd); - cvcd_pfd[1].fd = -1; - connected = 0; - netcon_fail = 1; - break; - } - } - - /* - * Check if dummy netcon_fail flag is set, if set returns - * to the beginning of the main service routine. - */ - if (netcon_fail) - continue; - - if (event != 0) { - if (cvcd_pfd[0].revents == POLLIN) { - /* - * Process cvcd_ssp data and commands. - */ - cvcd_read(cvcd_pfd); - } - if (cvcd_pfd[1].revents == POLLIN) { - int s; - - if ((s = read(rconsfd, buf, MAXPKTSZ)) == -1) { - cvcd_err(LOG_ERR, "read: %s", - strerror(errno)); - exit(1); - } - if ((s > 0) && (connected == 1)) { - if (write(cvcd_pfd[0].fd, buf, s) != - s) { - cvcd_err(LOG_ERR, - "lost data output"); - } - } - } - } - } /* End forever loop */ - -#ifdef lint - /* NOTREACHED */ - return (1); -#endif /* lint */ -} - -static void -cvcd_reject(int fd) -{ - struct t_call *tcall; - - tcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL); - if (tcall == (struct t_call *)NULL) { - cvcd_err(LOG_ERR, "cvcd_reject: t_alloc: %s", - t_errlist[t_errno]); - return; - } - if (t_listen(fd, tcall) == -1) { - if (t_errno == TNODATA) { - cvcd_err(LOG_ERR, "cvcd_reject: No client data!"); - } - cvcd_err(LOG_ERR, "cvcd_reject: t_listen: %s", - t_errlist[t_errno]); - t_free((char *)tcall, T_CALL); - return; - } - if (t_snddis(fd, tcall) < 0) { - cvcd_err(LOG_ERR, "cvcd_reject: t_snddis: %s", - t_errlist[t_errno]); - } - t_free((char *)tcall, T_CALL); -} - -static void -cvcd_connect(int fd, struct pollfd *pfd) -{ - struct t_call *tcall; - int newfd; - struct sockaddr_in *peer; - int badpeer = 1; - struct hostent *he; - struct netbuf netbuf; - char addr[100]; - ulong_t tmpaddr; /* network byte order */ - char **pp; - - tcall = (struct t_call *)t_alloc(fd, T_CALL, T_ALL); - if (tcall == (struct t_call *)NULL) { - cvcd_err(LOG_ERR, "cvcd_connect: t_alloc: %s", - t_errlist[t_errno]); - return; - } - if (t_listen(fd, tcall) == -1) { - if (t_errno == TNODATA) { - cvcd_err(LOG_ERR, "cvcd_connect: No client data!"); - } - cvcd_err(LOG_ERR, "cnctip_connect: t_listen: %s", - t_errlist[t_errno]); - t_free((char *)tcall, T_CALL); - return; - } - if (pfd[0].fd != -1) { - cvcd_err(LOG_ERR, "cvcd_connect: no free file descriptors!"); - t_free((char *)tcall, T_CALL); - return; - } - newfd = t_open(TCP_DEV, O_RDWR|O_NDELAY, NULL); - if (newfd == -1) { - cvcd_err(LOG_ERR, "cvcd_connect: t_open: %s", - t_errlist[t_errno]); - t_free((char *)tcall, T_CALL); - return; - } - if (t_accept(fd, newfd, tcall) < 0) { - cvcd_err(LOG_ERR, "cvcd_connect: t_accept: %s", - t_errlist[t_errno]); - t_close(newfd); - t_free((char *)tcall, T_CALL); - return; - } - t_free((char *)tcall, T_CALL); - - /* - * If /etc/ssphostname doesnt exists, dont bother verifying - * peer since we cant do gethostbyname. - */ - if (peercheck == 1) { - he = gethostbyname(ssphostname); - if (he == NULL) { - cvcd_err(LOG_ERR, "gethostbyname: %s", - strerror(h_errno)); - cvcd_err(LOG_ERR, "unable to get SSP name %s!", - ssphostname); - exit(1); - } - /* - * Verify peer is from specified host by comparing the - * address (in network byte order) of the TLI endpoint - * and the address (in network byte order) of the ssp - * (using the hostname found in /etc/ssphostname). - */ - (void) memset(addr, 0, 100); - netbuf.buf = addr; - netbuf.len = 0; - netbuf.maxlen = 100; - if (ioctl(newfd, TI_GETPEERNAME, &netbuf) < 0) { - cvcd_err(LOG_ERR, "ioctl(TI_GETPEERNAME): %s", - strerror(errno)); - t_close(newfd); - return; - } - - /* - * cvcd doesn't check multi-homed ssphostname - * properly (only checks 1st address) - */ - peer = (struct sockaddr_in *)addr; - for (pp = he->h_addr_list; *pp != 0; pp++) { - tmpaddr = htonl(*(ulong_t *)*pp); - if (memcmp(&peer->sin_addr.s_addr, &tmpaddr, - he->h_length) == 0) { - badpeer = 0; - break; - } - } - - if (badpeer) { - cvcd_err(LOG_ERR, CONREF); - cvcd_err(LOG_ERR, "remote host = %s.", - inet_ntoa(peer->sin_addr)); - t_close(newfd); - return; - } - } - pfd[0].fd = newfd; - pfd[0].events = POLLIN; - connected = 1; -} - -/* - * Read in data from client. - */ -static void -cvcd_read(struct pollfd *pd) -{ - register char *data; - register int fd = pd[0].fd; - char buf[MAXPKTSZ]; - int flags = 0; - - data = buf; - - if (pd[0].revents & POLLIN) { - int n; - - if ((n = t_rcv(fd, data, MAXPKTSZ, &flags)) == -1) { - cvcd_err(LOG_ERR, "cvcd_read: t_rcv: %s", - t_errlist[t_errno]); - (void) t_close(pd[0].fd); - pd[0].fd = -1; - connected = 0; - return; - } - if (flags & T_EXPEDITED) { - if (n != 1) { - cvcd_err(LOG_ERR, - "cvcd_read: %d bytes EXD!!", - n); - } - /* - * Deal with cvcd_ssp_commands. - */ - switch (data[n-1]) { - case CVC_CONN_BREAK : - cvcd_ioctl(rconsfd, CVC_BREAK); - break; - - case CVC_CONN_DIS : - (void) t_close(pd[0].fd); - pd[0].fd = -1; - cvcd_ioctl(rconsfd, CVC_DISCONNECT); - connected = 0; - break; - - case CVC_CONN_STAT : - cvcd_status(fd); - break; - - default : - cvcd_err(LOG_ERR, - "Illegal cmd 0x%x", buf[n-1]); - break; - } - } else { - if (((data[0] & 0377) == 0377) && - ((data[1] & 0377) == 0377)) { - /* - * Pass on window size changes (TIOCSWINSZ). - */ - cvcd_winch(rconsfd, data, n); - (void) memset(data, 0, n); - } else { - cvcd_write(buf, n); - } - } - } - -} - -static void -cvcd_ioctl(int fd, int flags) -{ - struct strioctl cmd; - - cmd.ic_cmd = flags; - cmd.ic_timout = 0; - cmd.ic_len = 0; - cmd.ic_dp = NULL; - - if (ioctl(fd, I_STR, &cmd) == -1) { - cvcd_err(LOG_ERR, "cvcd_ioctl: %s", strerror(errno)); - exit(1); - } -} - - -/* ARGSUSED */ -static void -cvcd_status(int fd) -{ -} - - -/* - * Write input to console - called from cvcd_read. - */ -static void -cvcd_write(char *data, int size) -{ - int n; - - if ((n = write(rconsfd, data, size)) == -1) { - cvcd_err(LOG_ERR, "cvcd_write: write: %s", strerror(errno)); - exit(1); - } - if (n != size) { - cvcd_err(LOG_ERR, "cvcd_write: wrote %d of %d bytes", n, size); - } -} - -static void -usage() -{ -#if defined(DEBUG) - (void) printf("%s [-d] [-p port]\n", progname); -#else - (void) printf("%s -r [ssp host]\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) vsprintf(buf, format, varg_ptr); - va_end(varg_ptr); - - if (debug == 0) - syslog(code, buf); - else - (void) fprintf(stderr, "%s: %s\n", progname, buf); -} - -/* - * Handle a "control" request (signaled by magic being present) - * in the data stream. For now, we are only willing to handle - * window size changes. - */ -void -cvcd_winch(int pty, char *cp, int n) -{ - struct winsize w; - - if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') - return; - (void) memcpy(&w, cp + 4, sizeof (w)); - w.ws_row = ntohs(w.ws_row); - w.ws_col = ntohs(w.ws_col); - w.ws_xpixel = ntohs(w.ws_xpixel); - w.ws_ypixel = ntohs(w.ws_ypixel); - (void) ioctl(pty, TIOCSWINSZ, &w); -} - - -/* - * Return class ID and maximum priority of it. - * Input: - * name: is class name (either TS or RT). - * maxpri: maximum priority for the class, returned in *maxpri. - * Output: - * pc_cid: class ID - */ -static id_t -schedinfo(char *name, short *maxpri) -{ - pcinfo_t info; - tsinfo_t *tsinfop; - rtinfo_t *rtinfop; - - (void) strcpy(info.pc_clname, name); - if (priocntl(0L, 0L, PC_GETCID, (caddr_t)&info) == -1L) { - return (-1); - } - if (strcmp(name, "TS") == 0) { /* Time Shared */ - tsinfop = (struct tsinfo *)info.pc_clinfo; - *maxpri = tsinfop->ts_maxupri; - } else if (strcmp(name, "RT") == 0) { /* Real Time */ - rtinfop = (struct rtinfo *)info.pc_clinfo; - *maxpri = rtinfop->rt_maxpri; - } else { - return (-1); - } - return (info.pc_cid); -} - - -/* - * set the tli options for the given endpoint represented by fd - */ -static void -cvcd_setopt(int fd, int name) -{ - struct t_optmgmt *topt, *tropt; - struct opthdr *sockopt; - int on = 1; - - topt = (struct t_optmgmt *)t_alloc(fd, T_OPTMGMT, 0); - if (topt == NULL) { - cvcd_err(LOG_ERR, "t_alloc: %s", t_errlist[t_errno]); - exit(1); - } - tropt = (struct t_optmgmt *)t_alloc(fd, T_OPTMGMT, 0); - if (tropt == NULL) { - cvcd_err(LOG_ERR, "t_alloc: %s", t_errlist[t_errno]); - exit(1); - } - topt->opt.buf = (char *)malloc(sizeof (struct opthdr) + sizeof (int)); - topt->opt.maxlen = 0; - topt->opt.len = sizeof (struct opthdr) + sizeof (int); - topt->flags = T_NEGOTIATE; - sockopt = (struct opthdr *)topt->opt.buf; - sockopt->level = SOL_SOCKET; - sockopt->name = name; - sockopt->len = sizeof (int); - (void) memcpy((char *)(topt->opt.buf + sizeof (struct opthdr)), - (char *)&on, sizeof (on)); - tropt->opt.buf = (char *)malloc(sizeof (struct opthdr) + sizeof (int)); - tropt->opt.maxlen = sizeof (struct opthdr) + sizeof (int); - - if (t_optmgmt(fd, topt, tropt) == -1) { - t_error("t_optmgmt"); - exit(1); - } - - t_free((char *)topt, T_OPTMGMT); - t_free((char *)tropt, T_OPTMGMT); -} diff --git a/usr/src/cmd/cvcd/svc-cvcd b/usr/src/cmd/cvcd/svc-cvcd index 6b4748bd8c..caeeb9b54c 100644 --- a/usr/src/cmd/cvcd/svc-cvcd +++ b/usr/src/cmd/cvcd/svc-cvcd @@ -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. # # Start script for cvcd # @@ -45,17 +44,13 @@ getproparg() { } platform=`/sbin/uname -i` -starfire="SUNW,Ultra-Enterprise-10000" starcat="SUNW,Sun-Fire-15000" -args="" 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`" -fi - -if [ $platform = "$starfire" -o $platform = "$starcat" ]; then /platform/$platform/lib/cvcd $args # Fail if can't execute exit # Use cvcd's exit status else diff --git a/usr/src/cmd/dcs/sparc/sun4u/svc-dcs b/usr/src/cmd/dcs/sparc/sun4u/svc-dcs index 9f5c7bc0fd..4054ca111a 100644 --- a/usr/src/cmd/dcs/sparc/sun4u/svc-dcs +++ b/usr/src/cmd/dcs/sparc/sun4u/svc-dcs @@ -23,8 +23,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. # # Start script for dcs # @@ -47,7 +46,6 @@ getproparg() { DCS=/usr/lib/dcs platform=`/sbin/uname -i` -e10k="SUNW,Ultra-Enterprise-10000" sf15k="SUNW,Sun-Fire-15000" opl="SUNW,SPARC-Enterprise" @@ -60,8 +58,7 @@ elif [ $platform = "$opl" ]; then args="-l" fi -if [ $platform = "$e10k" -o $platform = "$sf15k" -o \ - $platform = "$opl" ]; then +if [ $platform = "$sf15k" -o $platform = "$opl" ]; then $DCS $args # Fail if can't execute exit # Use dcs's exit status else diff --git a/usr/src/cmd/svc/profile/Makefile b/usr/src/cmd/svc/profile/Makefile index 767d2c6247..43ee2779bd 100644 --- a/usr/src/cmd/svc/profile/Makefile +++ b/usr/src/cmd/svc/profile/Makefile @@ -22,6 +22,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # include ../../Makefile.cmd @@ -44,7 +45,6 @@ PROFILESRCS = \ platform_SUNW,Sun-Fire-15000.xml \ platform_SUNW,Sun-Fire-880.xml \ platform_SUNW,Sun-Fire.xml \ - platform_SUNW,Ultra-Enterprise-10000.xml \ platform_SUNW,UltraSPARC-IIi-Netract.xml \ platform_none.xml \ platform_sun4v.xml diff --git a/usr/src/cmd/svc/profile/platform_SUNW,Ultra-Enterprise-10000.xml b/usr/src/cmd/svc/profile/platform_SUNW,Ultra-Enterprise-10000.xml deleted file mode 100644 index fbb6c3d3a8..0000000000 --- a/usr/src/cmd/svc/profile/platform_SUNW,Ultra-Enterprise-10000.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version='1.0'?> -<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'> -<!-- - Copyright 2005 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - CDDL HEADER START - - The contents of this file are subject to the terms of the - Common Development and Distribution License, Version 1.0 only - (the "License"). You may not use this file except in compliance - with the License. - - You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - or http://www.opensolaris.org/os/licensing. - See the License for the specific language governing permissions - and limitations under the License. - - When distributing Covered Code, include this CDDL HEADER in each - file and include the License file at usr/src/OPENSOLARIS.LICENSE. - If applicable, add the following below this CDDL HEADER, with the - fields enclosed by brackets "[]" replaced with your own identifying - information: Portions Copyright [yyyy] [name of copyright owner] - - CDDL HEADER END - - ident "%Z%%M% %I% %E% SMI" - - NOTE: This service profile is not editable; its contents will be - overwritten by package or patch operations, including operating - system upgrade. - - Ultra Enterprise 10000 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_bundle> diff --git a/usr/src/lib/cfgadm_plugins/Makefile.com b/usr/src/lib/cfgadm_plugins/Makefile.com index d6f4bf6782..5fcc3e50e6 100644 --- a/usr/src/lib/cfgadm_plugins/Makefile.com +++ b/usr/src/lib/cfgadm_plugins/Makefile.com @@ -21,6 +21,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # lib/cfgadm_plugins/Makefile.com @@ -37,7 +38,6 @@ LINKED_PLATFORMS = SUNW,Ultra-2 LINKED_PLATFORMS += SUNW,Ultra-4 LINKED_PLATFORMS += SUNW,Ultra-250 LINKED_PLATFORMS += SUNW,Ultra-Enterprise -LINKED_PLATFORMS += SUNW,Ultra-Enterprise-10000 LINKED_PLATFORMS += SUNW,UltraSPARC-IIi-Netract LINKED_PLATFORMS += SUNW,UltraSPARC-IIe-NetraCT-40 LINKED_PLATFORMS += SUNW,UltraSPARC-IIe-NetraCT-60 diff --git a/usr/src/lib/efcode/engine/package.c b/usr/src/lib/efcode/engine/package.c index be241d01ac..54a75dfe88 100644 --- a/usr/src/lib/efcode/engine/package.c +++ b/usr/src/lib/efcode/engine/package.c @@ -22,8 +22,9 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2019 Peter Tribble. + */ #include <stdio.h> #include <stdlib.h> @@ -165,28 +166,11 @@ deactivate_device(fcode_env_t *env, device_t *d) do_definitions(env); } -/* - * Starfire hack to set '/' device_type to 'upa' - */ -#include <sys/systeminfo.h> -static void -starfire_hack(fcode_env_t *env) -{ - char platform[100]; - - sysinfo(SI_PLATFORM, platform, sizeof (platform)); - if (strcmp(platform, "SUNW,Ultra-Enterprise-10000") == 0 && - find_property(env->root_node, "device_type") == NULL) { - create_string_prop(env, "device_type", "upa"); - } -} - void root_node(fcode_env_t *env) { do_also(env); activate_device(env, env->root_node); - starfire_hack(env); } void diff --git a/usr/src/lib/libprtdiag_psr/sparc/Makefile b/usr/src/lib/libprtdiag_psr/sparc/Makefile index 529d0e17f7..2649e036df 100644 --- a/usr/src/lib/libprtdiag_psr/sparc/Makefile +++ b/usr/src/lib/libprtdiag_psr/sparc/Makefile @@ -21,12 +21,11 @@ # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" +# Copyright 2019 Peter Tribble. # # lib/libprtdiag_psr/sparc/Makefile -PRTDIAG_PLATFORMS= desktop tazmo javelin sunfire starfire serengeti \ +PRTDIAG_PLATFORMS= desktop tazmo javelin sunfire serengeti \ montecarlo littleneck starcat daktari cherrystone \ lw8 snowbird ontario schumacher opl montoya monza diff --git a/usr/src/lib/libprtdiag_psr/sparc/Makefile.com b/usr/src/lib/libprtdiag_psr/sparc/Makefile.com index 3c58df4d3b..cc52a6ef2c 100644 --- a/usr/src/lib/libprtdiag_psr/sparc/Makefile.com +++ b/usr/src/lib/libprtdiag_psr/sparc/Makefile.com @@ -21,6 +21,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # LIBRARY= libprtdiag_psr.a @@ -33,7 +34,7 @@ VERS= .1 # PSR_MACH= sun4u # -# PLATFORM_OBJECTS is defined in ./desktop ./wgs ./sunfire ./starfire Makefiles +# PLATFORM_OBJECTS is defined in ./desktop ./wgs ./sunfire Makefiles # OBJECTS= $(PLATFORM_OBJECTS) diff --git a/usr/src/lib/libprtdiag_psr/sparc/starfire/Makefile b/usr/src/lib/libprtdiag_psr/sparc/starfire/Makefile deleted file mode 100644 index c3f4e22812..0000000000 --- a/usr/src/lib/libprtdiag_psr/sparc/starfire/Makefile +++ /dev/null @@ -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 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# lib/libprtdiag_psr/sparc/starfire/Makefile - -UTSBASE = ../../../../uts - -PLATFORM_OBJECTS= starfire.o - -include ../Makefile.com - -IFLAGS += -I$(USR_PLAT_DIR)/sun4u/include -I ../../../libprtdiag/inc -LINTFLAGS += $(IFLAGS) - -PLATFORM=SUNW,Ultra-Enterprise-10000 - -$(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/starfire; $(MAKE) $(USR_PSM_LIB_DIR) - -# -# install rule -# -$(USR_PSM_LIB_DIR)/%: % $(USR_PSM_LIB_DIR) - $(INS.file) - -POFILE= libprtdiag_psr_starfire.po -POFILES= starfire.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/starfire.c` - $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ - $(RM) messages.po diff --git a/usr/src/lib/libprtdiag_psr/sparc/starfire/common/starfire.c b/usr/src/lib/libprtdiag_psr/sparc/starfire/common/starfire.c deleted file mode 100644 index 6620ebbb89..0000000000 --- a/usr/src/lib/libprtdiag_psr/sparc/starfire/common/starfire.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999-2001 by Sun Microsystems, Inc. - * All rights reserved. - * - * Starfire Platform specific functions. - * - * called when : - * machine_type == MTYPE_STARFIRE - * - */ - -#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 <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" - -/* - * these functions will overlay the symbol table of libprtdiag - * at runtime (starfire systems only) - */ -int error_check(Sys_tree *tree, struct system_kstat_data *kstats); -void display_memoryconf(Sys_tree *tree, struct grp_info *grps); -void display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats); -void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, - struct system_kstat_data *kstats); -void display_mid(int mid); -void display_pci(Board_node *); -Prom_node *find_device(Board_node *, int, char *); - -#if !defined(TEXT_DOMAIN) -#define TEXT_DOMAIN "SYS_TEST" -#endif - - -int -error_check(Sys_tree *tree, struct system_kstat_data *kstats) -{ -#ifdef lint - tree = tree; - kstats = kstats; -#endif - return (0); -} - -void -display_memoryconf(Sys_tree *tree, struct grp_info *grps) -{ - Board_node *bnode; - char indent_str[] = " "; - -#ifdef lint - grps = grps; -#endif - - /* Print the header for the memory section. */ - log_printf("\n", 0); - log_printf("=========================", 0); - log_printf(dgettext(TEXT_DOMAIN, " Memory "), 0); - log_printf("=========================", 0); - log_printf("\n\n", 0); - - /* Print the header for the memory section. */ - log_printf(indent_str, 0); - log_printf("Memory Units: Size \n", 0); - log_printf(indent_str, 0); - log_printf("0: MB 1: MB 2: MB 3: MB\n", 0); - log_printf(indent_str, 0); - log_printf("----- ----- ----- ----- \n", 0); - - /* Run thru the board and display its memory if any */ - bnode = tree->bd_list; - while (bnode != NULL) { - Prom_node *pnode; - unsigned int *memsize; - unsigned int mbyte = 1024*1024; - - /* - * Find the mem-unit of the board. - * If the board has memory, a mem-unit pnode should - * be there. - */ - pnode = dev_find_node(bnode->nodes, "mem-unit"); - - if (pnode != NULL) { - /* there is a mem-unit in the board */ - - /* Print the board header */ - log_printf("Board%2d ", bnode->board_num, 0); - - memsize = get_prop_val(find_prop(pnode, "size")); - - log_printf(" %4d %4d %4d %4d \n", - memsize[0]/mbyte, memsize[1]/mbyte, - memsize[2]/mbyte, memsize[3]/mbyte, 0); - } - bnode = bnode->next; - } - log_printf("\n", 0); -} - -void -display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats) -{ -#ifdef lint - tree = tree; - kstats = kstats; -#endif -} - -void -display_diaginfo(int flag, Prom_node *root, Sys_tree *tree, - struct system_kstat_data *kstats) -{ - - char hostname[128]; /* used for starfire output */ - struct utsname uts_buf; - -#ifdef lint - flag = flag; - root = root; - tree = tree; - kstats = kstats; -#endif - - /* - * Get hostname from system Banner - */ - (void) uname(&uts_buf); - strcpy(hostname, uts_buf.nodename); - - /* - * We can't display diagnostic/env information for starfire. - * The diagnostic information may be displayed through - * commands in ssp. - */ - log_printf(dgettext(TEXT_DOMAIN, - "\nFor diagnostic information,"), 0); - log_printf("\n", 0); - log_printf(dgettext(TEXT_DOMAIN, "see /var/opt/SUNWssp/adm/%s/messages " - "on the SSP."), hostname, 0); - log_printf("\n", 0); -} - -void -display_mid(int mid) -{ - log_printf(" %2d ", mid % 4, 0); -} - -/* - * display_pci - * Call the generic psycho version of this function. - */ -void -display_pci(Board_node *board) -{ - display_psycho_pci(board); -} - -/* - * Find the device on the current board with the requested device ID - * and name. If this rountine is passed a NULL pointer, it simply returns - * NULL. - */ -Prom_node * -find_device(Board_node *board, int id, char *name) -{ - Prom_node *pnode; - int mask; - - /* find the first cpu node */ - pnode = dev_find_node(board->nodes, name); - - mask = 0x7F; - while (pnode != NULL) { - if ((get_id(pnode) & mask) == id) - return (pnode); - - pnode = dev_next_node(pnode, name); - } - return (NULL); -} diff --git a/usr/src/man/man7d/Makefile b/usr/src/man/man7d/Makefile index a76d09cf03..fb99fb55e5 100644 --- a/usr/src/man/man7d/Makefile +++ b/usr/src/man/man7d/Makefile @@ -160,7 +160,6 @@ sparc_MANFILES= audiocs.7d \ fas.7d \ gpio_87317.7d \ grbeep.7d \ - idn.7d \ mc-opl.7d \ n2rng.7d \ ncp.7d \ diff --git a/usr/src/man/man7d/idn.7d b/usr/src/man/man7d/idn.7d deleted file mode 100644 index 42cd479ee5..0000000000 --- a/usr/src/man/man7d/idn.7d +++ /dev/null @@ -1,241 +0,0 @@ -'\" te -.\" Copyright (c) 1999, 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 IDN 7D "Jun 3, 1999" -.SH NAME -idn \- inter-domain network device driver -.SH SYNOPSIS -.LP -.nf -\fB/dev/idn\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBidn\fR driver is a multi-thread, loadable, clonable, STREAMS-based -pseudo driver that supports the connectionless Data Link Provider Interface -\fBdlpi\fR(7P) over the Sun Enterprise 10000 Gigplane-XB Interconnect. This -connection is permitted only between domains within the same Sun Enterprise -10000 server. -.sp -.LP -The \fBidn\fR driver supports 1 to 32 logical network interfaces that can be -connected to domains linked to the local domain through the -\fBdomain_link\fR(1M) command. (See \fBdomain_link\fR(1M) in the \fISun -Enterprise 10000 SSP 3.5 Reference Manual\fR for more information.) The -\fBidn\fR driver works in conjunction with the System Service Processor (SSP) -to perform domain linking/unlinking and automated linking upon host bootup. -.sp -.LP -The \fB/dev/idn\fR device is used to access all IDN services provided by the -system. -.SS "IDN and DLPI" -.sp -.LP -The \fBidn\fR driver is a style-2 Data Link Service provider. All \fBM_PROTO\fR -and \fBM_PCPROTO\fR-type messages are interpreted as \fBDLPI \fRprimitives. -For the \fBidn\fR driver to associate the opened stream with a particular -device (ppa), you must send an explicit \fBDL_ATTACH_REQ\fR message. The ppa ID -is interpreted as an unsigned long and indicates the corresponding device -instance (unit) number. The \fBDL_ERROR_ACK\fR error is returned by the driver -if the ppa field value does not correspond to a valid device-instance number -for the system. The device is initialized on first attach and de-initialized -(stopped) on the last detach. -.RS +4 -.TP -.ie t \(bu -.el o -The maximum SDU is configurable by using the \fBidn.conf\fR file and has a -range of 512 bytes to 512 Kbytes. The default value is 16384 bytes. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The minimum SDU is 0. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The Service Access Pointer (SAP) address length is 8. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The MAC type is \fBDL_ETHER\fR. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The \fBSAP\fR length value is \fI-2\fR, meaning the physical address component -is followed immediately by a 2-byte \fBSAP \fRcomponent within the \fBDLSAP\fR -address. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The service mode is \fBDL_CLDLS\fR. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -Optional quality of service (\fBQOS\fR) is not presently supported; -accordingly, the \fBQOS \fRfields are 0. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The provider style is \fBDL_STYLE2\fR. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The version is \fBDL_VERSION_2\fR. -.RE -.RS +4 -.TP -.ie t \(bu -.el o -The broadcast address value is Ethernet/IEEE broadcast address (0xFFFFFF). The -\fBidn\fR driver supports broadcast by issuing messages to each target -individually. The \fBidn\fR driver is inherently a point-to-point network -between domains. When the \fBidn\fR driver is in the \fBDL_ATTACHED\fR state, -the user must send a \fBDL_BIND_REQ\fR request to associate a particular \fBSAP -\fRwith the stream. The \fBidn\fR driver interprets the \fBSAP \fRfield within -the \fBDL_BIND_REQ\fR message as an Ethernet type and valid values for the -\fBSAP \fRfield are in the range of \fI0\fR to \fI0xFFFF\fR. Only one Ethernet -type can be bound to the stream at any time. -.RE -.sp -.LP -If a \fBSAP \fRwith a value of 0 is selected, the receiver will be in 802.3 -mode. All frames received from the media having a type field in the range of 0 -to 1500 are assumed to be 802.3 frames and are routed up all open streams which -are bound to \fBSAP \fR value 0. If more than one stream is in 802.3 mode, then -the frame will be duplicated and routed up as multiple stream -\fBDL_UNITDATA_IND\fR messages. -.sp -.LP -In transmission, the driver checks the \fBSAP\fR field of the \fBDL_BIND_REQ\fR -to determine if the SAP value is 0, and if the destination type field is in the -range of \fI 0\fR to \fI1500\fR. If either is true, the driver computes the -length of the message, (excluding the initial message block \fBM_PROTO mblk)\fR -of all subsequent \fBDL_UNITDATA_REQ\fR messages and transmits 802.3 frames -that have this value in the MAC frame header length field. -.sp -.LP -The driver also supports raw \fBM_DATA\fR mode. When the user sends a -\fBDLIOCRAW\fR ioctl, the particular stream is put in raw mode. A complete -frame and a proper ether header is expected as part of the data. -.sp -.LP -The \fBDLSAP\fR address format consists of the 6-byte, physical address -component (Ethernet) followed immediately by the 2-byte \fBSAP \fRcomponent -(type), producing an 8-byte \fBDLSAP\fR address. Applications should \fBnot\fR -hardcode to this particular implementation-specific \fBDLSAP\fR address format, -but instead should use information returned in the \fBDL_INFO_ACK\fR primitive -to compose and decompose \fBDLSAP\fR addresses. The \fBSAP \fRlength, full -\fBDLSAP \fR length, and \fBSAP \fRphysical ordering are included within the -\fBDL_INFO_ACK\fR primitive. The physical address length can be computed by -subtracting the \fBSAP \fRlength from the full \fBDLSAP\fR address length or by -issuing the \fBDL_PHYS_ADDR_REQ\fR message to obtain the current physical -address associated with the stream. -.sp -.LP -When the \fBidn\fR driver is in the \fBDL_BOUND\fR state, you can transmit -frames on the IDN by sending \fBDL_UNITDATA_REQ\fR messages to the driver. The -driver then routes received IDN frames up the open and bound streams having a -\fBSAP \fRwhich matches the Ethernet type as \fBDL_UNITDATA_IND\fR messages. -If necessary, received IDN frames are duplicated and routed up multiple open -streams. The \fBDLSAP\fR address contained within the \fBDL_UNITDATA_REQ\fR and -\fBDL_UNITDATA_IND\fR messages consists of both the \fBSAP \fR(type) and -physical (Ethernet) components. -.SS "IDN Primitives" -.sp -.LP -In addition to the mandatory connectionless DLPI message set, the \fBidn\fR -driver supports the following primitives: -.sp -.LP -The \fBDL_ENABMULTI_REQ\fR and \fBDL_DISABMULTI_REQ\fR primitives which enable -or disable, respectively, the reception of individual multicast group -addresses. A set of multicast addresses may be iteratively created and modified -on a per-stream basis using these primitives. These primitives are accepted by -the driver in any state following the \fBDL_ATTACHED\fR state. -.sp -.LP -The \fBDL_PROMISCON_REQ\fR and \fBDL_PROMISCOFF_REQ\fR primitives, which with -the \fBDL_PROMISC_PHYS\fR flag set in the \fBdl_level\fR field, enable or -disable, respectively, the reception of all promiscuous frames on the media, -including frames generated by the local domain. When used with the -\fBDL_PROMISC_SAP\fR flag set in the \fBdl_level\fR field, these primitives -enable or disable, respectively, the reception of all \fBSAP \fR (Ethernet -type) values. When used with the \fBDL_PROMISC_MULTI\fR flag set in the -\fBdl_level\fR field, these primitives enable or disable, respectively, the -reception of all multicast group addresses. The effect of each is always on a -per-stream basis and independent of the other \fBSAP \fRand physical level -configurations on this stream or other streams. -.sp -.LP -The \fBDL_PHYS_ADDR_REQ\fR primitive which returns the 6-octet, Ethernet -address associated with (or attached to) the stream in the -\fBDL_PHYS_ADDR_ACK\fR primitive. This primitive is valid only in states -following a successful \fBDL_ATTACH_REQ\fR request. -.sp -.LP -Because the driver maintains domain address information in the address to -direct packets to the correct destination, the \fBDL_SET_PHYS_ADDR_REQ\fR -primitive is not allowed. -.SH FILES -.sp -.LP -The following files are supported: -.sp -.ne 2 -.na -\fB\fB/dev/idn \fR\fR -.ad -.sp .6 -.RS 4n -IDN special character device -.RE - -.sp -.ne 2 -.na -\fB\fB/platform/SUNW,Ultra-Enterprise-10000/kernel/drv/idn.conf \fR\fR -.ad -.sp .6 -.RS 4n -System-wide and per-interface default device driver properties -.RE - -.SH SEE ALSO -.sp -.LP -\fBnetstat\fR(1M), \fBndd\fR(1M), \fBdlpi\fR(7P) -.sp -.LP -\fBdomain_link\fR(1M) in the \fISun Enterprise 10000 SSP 3.5 Reference -Manual\fR. -.sp -.LP -\fISun Enterprise 10000 InterDomain Networks User Guide\fR -.SH NOTES -.sp -.LP -The \fBidn\fR driver supports a set of properties that can be set by using the -\fBdriver.conf\fR file for the IDN. See the \fISun Enterprise 10000 InterDomain -Networks User Guide\fR for more information about the properties in the -\fBdriver.conf\fR(4), (\fBidn.conf\fR, for IDNs). diff --git a/usr/src/man/man7d/pcipsy.7d b/usr/src/man/man7d/pcipsy.7d index 0085d674cd..327c700827 100644 --- a/usr/src/man/man7d/pcipsy.7d +++ b/usr/src/man/man7d/pcipsy.7d @@ -1,31 +1,20 @@ '\" 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 PCIPSY 7D "May 26, 2005" +.TH PCIPSY 7D "Jan 28, 2019" .SH NAME pcipsy \- PCI bus to Safari bus nexus driver .SH DESCRIPTION -.sp .LP -The \fBpcipsy\fR nexus driver is used for certain IO assemblies for sun4u and -high-end Enterprise E10000 servers.. +The \fBpcipsy\fR nexus driver is used for certain IO assemblies for sun4u +servers. .SH FILES -.sp .ne 2 .na -\fB/platform/SUNW,Ultra-Enterprise-10000/kernel/drv/sparcv9/pcipsy\fR -.ad -.sp .6 -.RS 4n -32-bit ELF kernel module. -.RE - -.sp -.ne 2 -.na -\fB\fB/platform/sun4u/kernel/drv/sparcv9/pcipsy\fR\fR +\fB/platform/sun4u/kernel/drv/sparcv9/pcipsy\fR .ad .sp .6 .RS 4n @@ -33,6 +22,5 @@ high-end Enterprise E10000 servers.. .RE .SH SEE ALSO -.sp .LP \fBpcisch\fR(7D) diff --git a/usr/src/pkg/manifests/SUNWcs.mf b/usr/src/pkg/manifests/SUNWcs.mf index 1a146fd573..e186427aa0 100644 --- a/usr/src/pkg/manifests/SUNWcs.mf +++ b/usr/src/pkg/manifests/SUNWcs.mf @@ -25,6 +25,7 @@ # Copyright 2014 Garrett D'Amore <garrett@damore.org> # Copyright 2015 Nexenta Systems, Inc. All rights reserved. # Copyright 2017 Toomas Soome <tsoome@me.com> +# Copyright 2019 Peter Tribble. # <include SUNWcs.man1.inc> @@ -454,9 +455,6 @@ $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire-880.xml \ $(sparc_ONLY)file path=etc/svc/profile/platform_SUNW,Sun-Fire.xml group=sys \ mode=0444 $(sparc_ONLY)file \ - path=etc/svc/profile/platform_SUNW,Ultra-Enterprise-10000.xml group=sys \ - mode=0444 -$(sparc_ONLY)file \ path=etc/svc/profile/platform_SUNW,UltraSPARC-IIi-Netract.xml group=sys \ mode=0444 file path=etc/svc/profile/platform_none.xml group=sys mode=0444 diff --git a/usr/src/pkg/manifests/developer-apptrace-platform.mf b/usr/src/pkg/manifests/developer-apptrace-platform.mf index b7a3727b0e..1552f3a7a7 100644 --- a/usr/src/pkg/manifests/developer-apptrace-platform.mf +++ b/usr/src/pkg/manifests/developer-apptrace-platform.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2019 Peter Tribble. # set name=pkg.fmri value=pkg:/developer/apptrace/platform@$(PKGVERS) @@ -82,8 +83,6 @@ dir path=usr/platform/SUNW,Ultra-250/lib dir path=usr/platform/SUNW,Ultra-4 group=sys dir path=usr/platform/SUNW,Ultra-4/lib dir path=usr/platform/SUNW,Ultra-Enterprise group=sys -dir path=usr/platform/SUNW,Ultra-Enterprise-10000 group=sys -dir path=usr/platform/SUNW,Ultra-Enterprise-10000/lib dir path=usr/platform/SUNW,Ultra-Enterprise/lib dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib diff --git a/usr/src/pkg/manifests/system-header.mf b/usr/src/pkg/manifests/system-header.mf index f655696ac6..d979630ac0 100644 --- a/usr/src/pkg/manifests/system-header.mf +++ b/usr/src/pkg/manifests/system-header.mf @@ -26,6 +26,7 @@ # Copyright 2014 Garrett D'Amore <garrett@damore.org> # Copyright 2018 Nexenta Systems, Inc. # Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> +# Copyright 2019 Peter Tribble. # set name=pkg.fmri value=pkg:/system/header@$(PKGVERS) @@ -153,7 +154,6 @@ $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-2 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-250 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-4 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise-10000 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-60 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIi-Netract group=sys @@ -1719,7 +1719,6 @@ $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/cpc_ultra.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/cpr_impl.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/cpu_impl.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/cpu_sgnblk_defs.h -$(sparc_ONLY)file path=usr/platform/sun4u/include/sys/cvc.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/daktari.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/ddi_subrdefs.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/dvma.h @@ -1770,7 +1769,6 @@ $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/scsb_led.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/simmstat.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/spitregs.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/sram.h -$(sparc_ONLY)file path=usr/platform/sun4u/include/sys/starfire.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/sun4asi.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/sysctrl.h $(sparc_ONLY)file path=usr/platform/sun4u/include/sys/sysioerr.h @@ -2008,8 +2006,6 @@ $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-250/include \ target=../sun4u/include $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-4/include \ target=../sun4u/include -$(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise-10000/include \ - target=../sun4u/include $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise/include \ target=../sun4u/include $(sparc_ONLY)link path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/include \ diff --git a/usr/src/pkg/manifests/system-kernel-dynamic-reconfiguration-ultra-enterprise-10000.mf b/usr/src/pkg/manifests/system-kernel-dynamic-reconfiguration-ultra-enterprise-10000.mf index 41a5c074a3..0477a8a1fa 100644 --- a/usr/src/pkg/manifests/system-kernel-dynamic-reconfiguration-ultra-enterprise-10000.mf +++ b/usr/src/pkg/manifests/system-kernel-dynamic-reconfiguration-ultra-enterprise-10000.mf @@ -24,6 +24,10 @@ # # +# Copyright 2019 Peter Tribble. +# + +# # The default for payload-bearing actions in this package is to appear in the # global zone only. See the include file for greater detail, as well as # information about overriding the defaults. @@ -31,30 +35,6 @@ <include global_zone_only_component> set name=pkg.fmri \ value=pkg:/system/kernel/dynamic-reconfiguration/ultra-enterprise-10000@$(PKGVERS) -set name=pkg.description \ - value="Dynamic Reconfiguration Modules for Sun Enterprise 10000" -set name=pkg.summary \ - value="Dynamic Reconfiguration Modules for Sun Enterprise 10000" -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,Ultra-Enterprise-10000 group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64) group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/misc group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/misc/$(ARCH64) group=sys -driver name=ngdr perms="* 0600 root sys" -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/ngdr \ - group=sys -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/ngdr.conf group=sys \ - original_name=SUNWdrr:platform/SUNW,Ultra-Enterprise-10000/kernel/drv/ngdr.conf \ - preserve=true -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/misc/$(ARCH64)/ngdrmach \ - group=sys mode=0755 -legacy pkg=SUNWdrr.u arch=$(ARCH).sun4u \ - desc="Dynamic Reconfiguration Modules for Sun Enterprise 10000" \ - name="Dynamic Reconfiguration Modules for Sun Enterprise 10000" -license cr_Sun license=cr_Sun -license lic_CDDL license=lic_CDDL diff --git a/usr/src/pkg/manifests/system-kernel-inter-domain-ultra-enterprise-10000.mf b/usr/src/pkg/manifests/system-kernel-inter-domain-ultra-enterprise-10000.mf index a56eed0ae2..40b1ad61fb 100644 --- a/usr/src/pkg/manifests/system-kernel-inter-domain-ultra-enterprise-10000.mf +++ b/usr/src/pkg/manifests/system-kernel-inter-domain-ultra-enterprise-10000.mf @@ -24,6 +24,10 @@ # # +# Copyright 2019 Peter Tribble. +# + +# # The default for payload-bearing actions in this package is to appear in the # global zone only. See the include file for greater detail, as well as # information about overriding the defaults. @@ -31,29 +35,6 @@ <include global_zone_only_component> set name=pkg.fmri \ value=pkg:/system/kernel/inter-domain/ultra-enterprise-10000@$(PKGVERS) -set name=pkg.description \ - value="Inter-Domain Network Modules for Sun Enterprise 10000" -set name=pkg.summary \ - value="Inter-Domain Network Modules for Sun Enterprise 10000" -set name=info.classification \ - value="org.opensolaris.category.2008:System/Administration and Configuration" +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,Ultra-Enterprise-10000 group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64) group=sys -dir path=usr/share/man -dir path=usr/share/man/man7d -driver name=idn alias=SUNW,idn -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/idn \ - group=sys -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/idn.conf group=sys \ - original_name=SUNWidn:platform/SUNW,Ultra-Enterprise-10000/kernel/drv/idn.conf \ - preserve=true -file path=usr/share/man/man7d/idn.7d -legacy pkg=SUNWidn.u arch=$(ARCH).sun4u \ - desc="Inter-Domain Network Modules for Sun Enterprise 10000" \ - name="Inter-Domain Network Modules for Sun Enterprise 10000" -license cr_Sun license=cr_Sun -license lic_CDDL license=lic_CDDL diff --git a/usr/src/pkg/manifests/system-kernel-platform.mf b/usr/src/pkg/manifests/system-kernel-platform.mf index 5b21578e0b..ade33deeb3 100644 --- a/usr/src/pkg/manifests/system-kernel-platform.mf +++ b/usr/src/pkg/manifests/system-kernel-platform.mf @@ -23,6 +23,7 @@ # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2012 Nexenta Systems, Inc. All rights reserved. # Copyright 2014 Gary Mills +# Copyright 2019 Peter Tribble. # # @@ -268,22 +269,6 @@ $(sparc_ONLY)dir path=platform/SUNW,Ultra-80/kernel group=sys $(sparc_ONLY)dir path=platform/SUNW,Ultra-80/kernel/misc group=sys $(sparc_ONLY)dir path=platform/SUNW,Ultra-80/kernel/misc/$(ARCH64) group=sys $(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise group=sys -$(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise-10000 group=sys -$(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise-10000/kernel group=sys -$(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/$(ARCH64) \ - group=sys -$(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/cpu \ - group=sys -$(sparc_ONLY)dir \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/cpu/$(ARCH64) group=sys -$(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv \ - group=sys -$(sparc_ONLY)dir \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64) group=sys -$(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/misc \ - group=sys -$(sparc_ONLY)dir \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/misc/$(ARCH64) group=sys $(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise/kernel group=sys $(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise/kernel/drv group=sys $(sparc_ONLY)dir path=platform/SUNW,Ultra-Enterprise/kernel/drv/$(ARCH64) \ @@ -764,24 +749,6 @@ $(sparc_ONLY)file path=platform/SUNW,Ultra-4/kernel/misc/$(ARCH64)/platmod \ group=sys mode=0755 $(sparc_ONLY)file path=platform/SUNW,Ultra-5_10/kernel/misc/$(ARCH64)/platmod \ group=sys mode=0755 -$(sparc_ONLY)file \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/$(ARCH64)/unix group=sys \ - mode=0755 -$(sparc_ONLY)file \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-II \ - group=sys mode=0755 -$(sparc_ONLY)file \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/pcipsy \ - group=sys -$(sparc_ONLY)file \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/rootnex \ - group=sys -$(sparc_ONLY)file \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/sbus \ - group=sys -$(sparc_ONLY)file \ - path=platform/SUNW,Ultra-Enterprise-10000/kernel/misc/$(ARCH64)/platmod \ - group=sys mode=0755 $(sparc_ONLY)file path=platform/SUNW,Ultra-Enterprise/kernel/drv/$(ARCH64)/ac \ group=sys $(sparc_ONLY)file \ @@ -1038,8 +1005,6 @@ $(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/sun4u/kernel/tod/$(ARCH64)/todstarfire \ - 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 @@ -1229,8 +1194,6 @@ $(sparc_ONLY)link path=platform/SUNW,Sun-Fire/kernel/crypto/$(ARCH64)/aes \ target=../../../../sun4u-us3/kernel/crypto/$(ARCH64)/aes $(sparc_ONLY)link path=platform/SUNW,Ultra-80/kernel/misc/$(ARCH64)/platmod \ target=../../../../SUNW,Ultra-5_10/kernel/misc/$(ARCH64)/platmod -$(sparc_ONLY)link path=platform/SUNW,Ultra-Enterprise-10000/kernel/unix \ - target=$(ARCH64)/unix $(sparc_ONLY)link path=platform/sun4u/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-IIi \ target=SUNW,UltraSPARC-II $(sparc_ONLY)link path=platform/sun4u/kernel/cpu/$(ARCH64)/SUNW,UltraSPARC-IV \ diff --git a/usr/src/pkg/manifests/system-library-platform.mf b/usr/src/pkg/manifests/system-library-platform.mf index b65bd3279c..4ce4012eb5 100644 --- a/usr/src/pkg/manifests/system-library-platform.mf +++ b/usr/src/pkg/manifests/system-library-platform.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2019 Peter Tribble. # set name=pkg.fmri value=pkg:/system/library/platform@$(PKGVERS) @@ -116,8 +117,6 @@ $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-250/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-4 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-4/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise-10000 group=sys -$(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise-10000/lib $(sparc_ONLY)dir path=usr/platform/SUNW,Ultra-Enterprise/lib $(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40 group=sys $(sparc_ONLY)dir path=usr/platform/SUNW,UltraSPARC-IIe-NetraCT-40/lib @@ -175,8 +174,6 @@ $(sparc_ONLY)file path=usr/platform/SUNW,Ultra-2/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file path=usr/platform/SUNW,Ultra-250/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file path=usr/platform/SUNW,Ultra-4/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file \ - path=usr/platform/SUNW,Ultra-Enterprise-10000/lib/libprtdiag_psr.so.1 -$(sparc_ONLY)file \ path=usr/platform/SUNW,Ultra-Enterprise/lib/libprtdiag_psr.so.1 $(sparc_ONLY)file \ path=usr/platform/SUNW,UltraSPARC-IIi-Netract/lib/libprtdiag_psr.so.1 @@ -515,12 +512,6 @@ $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-4/sbin target=../sun4u/sbin $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-5_10 target=SUNW,Ultra-2 $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-60 target=SUNW,Ultra-2 $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-80 target=SUNW,Ultra-2 -$(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise-10000/lib/cfgadm \ - target=../../sun4u/lib/cfgadm -$(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise-10000/lib/fs \ - target=../../sun4u/lib/fs -$(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise-10000/sbin \ - target=../sun4u/sbin $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise/lib/cfgadm \ target=../../sun4u/lib/cfgadm $(sparc_ONLY)link path=usr/platform/SUNW,Ultra-Enterprise/lib/fs \ diff --git a/usr/src/pkg/manifests/system-network-console.mf b/usr/src/pkg/manifests/system-network-console.mf index a4ce2c6bee..ae675b5ffb 100644 --- a/usr/src/pkg/manifests/system-network-console.mf +++ b/usr/src/pkg/manifests/system-network-console.mf @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2019 Peter Tribble. # # @@ -45,11 +46,6 @@ 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=platform/SUNW,Ultra-Enterprise-10000 group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64) group=sys -dir path=platform/SUNW,Ultra-Enterprise-10000/lib dir path=usr/share/man dir path=usr/share/man/man1m dir path=usr/share/man/man7d @@ -62,14 +58,6 @@ 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=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/cvc \ - group=sys -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/$(ARCH64)/cvcredir \ - group=sys -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/cvc.conf group=sys -file path=platform/SUNW,Ultra-Enterprise-10000/kernel/drv/cvcredir.conf \ - group=sys -file path=platform/SUNW,Ultra-Enterprise-10000/lib/cvcd group=sys mode=0700 file path=usr/share/man/man1m/cvcd.1m file path=usr/share/man/man7d/cvc.7d file path=usr/share/man/man7d/cvcredir.7d diff --git a/usr/src/psm/promif/ieee1275/sun4u/Makefile.files b/usr/src/psm/promif/ieee1275/sun4u/Makefile.files index 381c6300ec..ff9ac4f72f 100644 --- a/usr/src/psm/promif/ieee1275/sun4u/Makefile.files +++ b/usr/src/psm/promif/ieee1275/sun4u/Makefile.files @@ -21,6 +21,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # psm/promif/ieee1275/sun4u/Makefile.files # @@ -53,7 +54,6 @@ CORE_OBJS += \ prom_set_traptable.o \ prom_sparc.o \ prom_starcat.o \ - prom_starfire.o \ prom_sunfire.o \ prom_tlb.o \ prom_vercheck.o \ diff --git a/usr/src/psm/promif/ieee1275/sun4u/prom_starfire.c b/usr/src/psm/promif/ieee1275/sun4u/prom_starfire.c deleted file mode 100644 index 3ef8dd983d..0000000000 --- a/usr/src/psm/promif/ieee1275/sun4u/prom_starfire.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/promif.h> -#include <sys/promimpl.h> - -/* - * This file contains the implementations of all Starfire-specific - * promif routines. - */ - -/* - * Probe all of the devices on a board. The board number is - * computed from cpuid. All of the cpus on the board are - * brought into OBP's slave idle loop but are not started. - * Returns zero for success and non-zero for failure. - */ -int -prom_starfire_add_brd(uint_t cpuid) -{ - cell_t ci[5]; - int rv; - - ci[0] = p1275_ptr2cell("SUNW,UE10000,add-brd"); /* name */ - ci[1] = (cell_t)1; /* #argument cells */ - ci[2] = (cell_t)1; /* #result cells */ - ci[3] = p1275_uint2cell(cpuid); - - promif_preprom(); - rv = p1275_cif_handler(&ci); - promif_postprom(); - - return ((rv) ? -1 : p1275_cell2int(ci[4])); -} - -/* - * Prune the device tree nodes for all devices on the board - * represented by brdnum. Returns zero for success and non-zero - * for failure. - */ -int -prom_starfire_rm_brd(uint_t brdnum) -{ - cell_t ci[5]; - int rv; - - ci[0] = p1275_ptr2cell("SUNW,UE10000,rm-brd"); /* name */ - ci[1] = (cell_t)1; /* #argument cells */ - ci[2] = (cell_t)1; /* #result cells */ - ci[3] = p1275_uint2cell(brdnum); - - promif_preprom(); - rv = p1275_cif_handler(&ci); - promif_postprom(); - - return ((rv) ? -1 : p1275_cell2int(ci[4])); -} - -/* - * Prepare firmware internal state for the inclusion of the - * cpu represented by cpuid. This operation has no effect on - * the cpu hardware or behavior in the client. - */ -void -prom_starfire_add_cpu(uint_t cpuid) -{ - cell_t ci[4]; - - ci[0] = p1275_ptr2cell("SUNW,UE10000,add-cpu"); /* name */ - ci[1] = (cell_t)1; /* #argument cells */ - ci[2] = (cell_t)0; /* #result cells */ - ci[3] = p1275_uint2cell(cpuid); - - promif_preprom(); - (void) p1275_cif_handler(&ci); - promif_postprom(); -} - -/* - * Prepare firmware internal state for the departure of the cpu - * represented by cpuid. - */ -void -prom_starfire_rm_cpu(uint_t cpuid) -{ - cell_t ci[4]; - - ci[0] = p1275_ptr2cell("SUNW,UE10000,rm-cpu"); /* name */ - ci[1] = (cell_t)1; /* #argument cells */ - ci[2] = (cell_t)0; /* #result cells */ - ci[3] = p1275_uint2cell(cpuid); - - promif_preprom(); - (void) p1275_cif_handler(&ci); - promif_postprom(); -} - -/* - * Mark the cpu represented by cpuid as cpu0. Returns zero for - * success and non-zero for failure. - */ -int -prom_starfire_move_cpu0(uint_t cpuid) -{ - cell_t ci[5]; - int rv; - - ci[0] = p1275_ptr2cell("SUNW,UE10000,move-cpu0"); /* name */ - ci[1] = (cell_t)1; /* #argument cells */ - ci[2] = (cell_t)1; /* #result cells */ - ci[3] = p1275_uint2cell(cpuid); - - promif_preprom(); - rv = p1275_cif_handler(&ci); - promif_postprom(); - - return ((rv) ? -1 : p1275_cell2int(ci[4])); -} - -/* - * Perform initialization steps required for the console before - * moving cpu0. The console uses the bootbus SRAM of cpu0 for both - * input and output. The offsets of the console buffers are initialized - * for the bootbus SRAM of the new cpu0 represented by cpuid. - */ -void -prom_starfire_init_console(uint_t cpuid) -{ - cell_t ci[4]; - - ci[0] = p1275_ptr2cell("SUNW,UE10000,init-console"); /* name */ - ci[1] = (cell_t)1; /* #argument cells */ - ci[2] = (cell_t)0; /* #result cells */ - ci[3] = p1275_uint2cell(cpuid); - - promif_preprom(); - (void) p1275_cif_handler(&ci); - promif_postprom(); -} diff --git a/usr/src/psm/stand/boot/sparc/common/machdep.c b/usr/src/psm/stand/boot/sparc/common/machdep.c index 5f4c71bc81..3fd6cc36db 100644 --- a/usr/src/psm/stand/boot/sparc/common/machdep.c +++ b/usr/src/psm/stand/boot/sparc/common/machdep.c @@ -22,6 +22,9 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #include <sys/types.h> #include <sys/param.h> @@ -146,7 +149,6 @@ retain_nvram_page(void) char name[32]; static char create_prop[] = "0 to my-self dev / 0 0 \" boot-retained-page\" property"; - static char ue10000[] = "SUNW,Ultra-Enterprise-10000"; static char ue[] = "SUNW,Ultra-Enterprise"; extern int verbosemode; @@ -157,8 +159,7 @@ retain_nvram_page(void) len = prom_getproplen(prom_rootnode(), "name"); if ((len != -1) && (len <= sizeof (name))) { (void) prom_getprop(prom_rootnode(), "name", name); - if ((strcmp(name, ue) == 0) || - (strcmp(name, ue10000) == 0)) + if (strcmp(name, ue) == 0) return; } } diff --git a/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile index d83ad955c1..cdd5a93b4b 100644 --- a/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile +++ b/usr/src/psm/stand/boot/sparcv9/sun4u/Makefile @@ -21,6 +21,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # TOPDIR = ../../../../.. @@ -33,7 +34,6 @@ PLATLINKS = SUNW,Ultra-2 PLATLINKS += SUNW,Ultra-250 PLATLINKS += SUNW,Ultra-4 PLATLINKS += SUNW,Ultra-Enterprise -PLATLINKS += SUNW,Ultra-Enterprise-10000 PLATLINKS += SUNW,UltraSPARC-IIi-Netract PLATLINKS += SUNW,UltraSPARC-IIe-NetraCT-40 PLATLINKS += SUNW,UltraSPARC-IIe-NetraCT-60 diff --git a/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile b/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile index 1fd1691c38..7fb47eeffc 100644 --- a/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile +++ b/usr/src/psm/stand/bootblks/ufs/sparc/sun4u/Makefile @@ -21,6 +21,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # psm/stand/bootblks/ufs/sparc/sun4u/Makefile # @@ -40,7 +41,6 @@ PLATLINKS = SUNW,Ultra-2 PLATLINKS += SUNW,Ultra-250 PLATLINKS += SUNW,Ultra-4 PLATLINKS += SUNW,Ultra-Enterprise -PLATLINKS += SUNW,Ultra-Enterprise-10000 PLATLINKS += SUNW,Sun-Blade-100 PLATLINKS += SUNW,Sun-Blade-1000 PLATLINKS += SUNW,Sun-Blade-1500 diff --git a/usr/src/tools/chk4ubin/chk4ubin.c b/usr/src/tools/chk4ubin/chk4ubin.c index 752e2013f0..aa2e38d6bc 100644 --- a/usr/src/tools/chk4ubin/chk4ubin.c +++ b/usr/src/tools/chk4ubin/chk4ubin.c @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ + #include <stdio.h> #include <sys/types.h> #include <sys/param.h> @@ -95,7 +99,6 @@ static uint_t pagemask = 0x1fff; static char *sun4u_bootables[] = { "platform/sun4u/kernel/sparcv9/unix", - "platform/SUNW,Ultra-Enterprise-10000/kernel/sparcv9/unix", "platform/SUNW,Sun-Fire-15000/kernel/sparcv9/unix", "platform/sun4u/cprboot", "platform/sun4u/bootlst" diff --git a/usr/src/uts/common/io/consconfig_dacf.c b/usr/src/uts/common/io/consconfig_dacf.c index edeb0f93d2..444cb9ce33 100644 --- a/usr/src/uts/common/io/consconfig_dacf.c +++ b/usr/src/uts/common/io/consconfig_dacf.c @@ -25,6 +25,10 @@ */ /* + * Copyright 2019 Peter Tribble. + */ + +/* * This module performs two functions. First, it kicks off the driver loading * of the console devices during boot in dynamic_console_config(). * The loading of the drivers for the console devices triggers the @@ -1533,29 +1537,6 @@ dynamic_console_config(void) consconfig_load_drivers(consconfig_sp); consconfig_sp->cons_input_type = cons_get_input_type(consconfig_sp); - /* - * This is legacy special case code for the "cool" virtual console - * for the Starfire project. Starfire has a dummy "ssp-serial" - * node in the OBP device tree and cvc is a pseudo driver. - */ - if (consconfig_sp->cons_stdout_path != NULL && stdindev == NODEV && - strstr(consconfig_sp->cons_stdout_path, "ssp-serial")) { - /* - * Setup the virtual console driver for Starfire - * Note that console I/O will still go through prom for now - * (notice we don't open the driver here). The cvc driver - * will be activated when /dev/console is opened by init. - * During that time, a cvcd daemon will be started that - * will open the cvcredirection driver to facilitate - * the redirection of console I/O from cvc to cvcd. - */ - rconsvp = i_consconfig_createvp(CVC_PATH); - if (rconsvp == NULL) - goto done; - rconsdev = rconsvp->v_rdev; - goto done; - } - rwsconsvp = consconfig_sp->cons_wc_vp; rwsconsdev = consconfig_sp->cons_wc_vp->v_rdev; @@ -1574,7 +1555,6 @@ dynamic_console_config(void) mousedev, kbddev, fbdev, rconsdev); flush_deferred_console_buf(); -done: consconfig_sp->cons_initialized = B_TRUE; } diff --git a/usr/src/uts/i86pc/sys/sbd_ioctl.h b/usr/src/uts/i86pc/sys/sbd_ioctl.h index 1eab543aa3..1ca9473dc2 100644 --- a/usr/src/uts/i86pc/sys/sbd_ioctl.h +++ b/usr/src/uts/i86pc/sys/sbd_ioctl.h @@ -26,6 +26,9 @@ * Copyright (c) 2010, Intel Corporation. * All rights reserved. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SBD_IOCTL_H #define _SBD_IOCTL_H @@ -508,34 +511,6 @@ typedef struct { #define ESTC_NWSWITCH 1037 /* Cannot unconfigure I/O board: network switch failed */ -/* Starfire error codes */ - -#define ESTF_NONE 2000 /* No error */ -#define ESTF_GETPROP 2001 /* Cannot read property value */ -#define ESTF_GETPROPLEN 2002 /* Cannot determine property length */ -#define ESTF_BNUM 2003 /* Invalid board number */ -#define ESTF_CONFIGBUSY 2004 - /* Cannot proceed; Board is configured or busy */ -#define ESTF_NOCPUID 2005 /* No CPU specified for connect */ -#define ESTF_PROBE 2006 /* Firmware probe failed */ -#define ESTF_DEPROBE 2007 /* Firmware deprobe failed */ -#define ESTF_MOVESIGB 2008 /* Firmware move-cpu0 failed */ -#define ESTF_JUGGLE 2009 /* Cannot move SIGB assignment */ -#define ESTF_HASSIGB 2010 - /* Cannot disconnect CPU; SIGB is currently assigned */ -#define ESTF_SUPPORT 2011 /* Operation not supported */ -#define ESTF_DRVFAIL 2012 /* Device driver failure */ -#define ESTF_SETCPUVAL 2013 - /* Must specify a CPU on the given board */ -#define ESTF_NODEV 2014 /* No such device */ -#define ESTF_INTERBOARD 2015 - /* Memory configured with inter-board interleaving */ -#define ESTF_UNKPTCMD 2016 /* Unrecognized platform command */ -#define ESTF_NOTID 2017 /* drmach parameter is not a valid ID */ -#define ESTF_INAPPROP 2018 - /* drmach parameter is inappropriate for operation */ -#define ESTF_INTERNAL 2019 /* Unexpected internal condition */ - /* Daktari error codes */ #define EDAK_NONE 3000 /* no error */ diff --git a/usr/src/uts/sun4/os/intr.c b/usr/src/uts/sun4/os/intr.c index 8036ca5bcb..3a7143115d 100644 --- a/usr/src/uts/sun4/os/intr.c +++ b/usr/src/uts/sun4/os/intr.c @@ -25,6 +25,9 @@ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ +/* + * Copyright 2019 Peter Tribble. + */ #include <sys/sysmacros.h> #include <sys/stack.h> @@ -115,7 +118,6 @@ intr_init(cpu_t *cp) extern uint_t softlevel1(); init_ivintr(); - REGISTER_BBUS_INTR(); /* * Register these software interrupts for ddi timer. diff --git a/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h b/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h index 0b18ca88f3..9e1a125308 100644 --- a/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h +++ b/usr/src/uts/sun4/sys/cpu_sgnblk_defs.h @@ -23,12 +23,13 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _CPU_SGNBLK_DEFS_H #define _CPU_SGNBLK_DEFS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -124,38 +125,6 @@ typedef union { extern void (*cpu_sgn_func)(ushort_t, uchar_t, uchar_t, int); - - -#ifdef _STARFIRE - -extern void register_bbus_intr(); -extern void cpu_sgn_mapin(int); -extern void cpu_sgn_mapout(int); -extern int cpu_sgn_exists(int); -extern ushort_t get_cpu_sgn(int); -extern uchar_t get_cpu_sgn_state(int); - -#define REGISTER_BBUS_INTR() register_bbus_intr() -#define CPU_SGN_MAPIN(cpuid) cpu_sgn_mapin(cpuid) -#define CPU_SGN_MAPOUT(cpuid) cpu_sgn_mapout(cpuid) -#define CPU_SGN_EXISTS(cpuid) cpu_sgn_exists(cpuid) -#define SGN_CPU_IS_OS(cpuid) (get_cpu_sgn(cpuid) == OS_SIG) -#define SGN_CPU_IS_OBP(cpuid) (get_cpu_sgn(cpuid) == OBP_SIG) -#define SGN_CPU_STATE_IS_DETACHED(cpuid) \ - (get_cpu_sgn_state(cpuid) == SIGST_DETACHED) - -#else - -#define REGISTER_BBUS_INTR() -#define CPU_SGN_MAPIN(cpuid) -#define CPU_SGN_MAPOUT(cpuid) -#define CPU_SGN_EXISTS(cpuid) (0) -#define SGN_CPU_IS_OS(cpuid) (0) -#define SGN_CPU_IS_OBP(cpuid) (0) -#define SGN_CPU_STATE_IS_DETACHED(cpuid) (0) - -#endif /* _STARFIRE */ - #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/sun4u/Makefile.files b/usr/src/uts/sun4u/Makefile.files index 5cfcd6025f..a2b45242cb 100644 --- a/usr/src/uts/sun4u/Makefile.files +++ b/usr/src/uts/sun4u/Makefile.files @@ -22,6 +22,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # This Makefile defines all file modules for the directory uts/sun4u # and it's children. These are the source files which are sun4u @@ -160,7 +161,6 @@ SHA1_OBJS += sha1_asm.o TODMOSTEK_OBJS += todmostek.o TODDS1287_OBJS += todds1287.o TODDS1337_OBJS += todds1337.o -TODSTARFIRE_OBJS += todstarfire.o TODSTARCAT_OBJS += todstarcat.o TODBLADE_OBJS += todblade.o TODM5819_OBJS += todm5819.o diff --git a/usr/src/uts/sun4u/Makefile.sun4u b/usr/src/uts/sun4u/Makefile.sun4u index d2b2b5cba7..f5e29d2a13 100644 --- a/usr/src/uts/sun4u/Makefile.sun4u +++ b/usr/src/uts/sun4u/Makefile.sun4u @@ -23,6 +23,7 @@ # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # Copyright (c) 2013 Andrew Stormont. All rights reserved. +# Copyright 2019 Peter Tribble. # # This makefile contains the common definitions for the sun4u unix # and all sun4u implementation architecture dependent modules. @@ -158,7 +159,6 @@ include $(UTSBASE)/Makefile.uts # These come after Makefile.uts. IMPLEMENTATIONS = tazmo -IMPLEMENTATIONS += starfire IMPLEMENTATIONS += javelin IMPLEMENTATIONS += darwin IMPLEMENTATIONS += quasar @@ -459,7 +459,7 @@ CPU_KMODS += cheetah cheetahplus jalapeno serrano spitfire hummingbird # # sun4u 'TOD' Modules (/platform/.../kernel/tod): # -TOD_KMODS += todds1287 todds1337 todmostek todstarfire +TOD_KMODS += todds1287 todds1337 todmostek TOD_KMODS += todm5819 todblade todbq4802 todsg todopl TOD_KMODS += todm5819p_rmc todstarcat diff --git a/usr/src/uts/sun4u/io/mach_rootnex.c b/usr/src/uts/sun4u/io/mach_rootnex.c index 8c0653d84a..b2a7ca8f1d 100644 --- a/usr/src/uts/sun4u/io/mach_rootnex.c +++ b/usr/src/uts/sun4u/io/mach_rootnex.c @@ -22,8 +22,9 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2019 Peter Tribble. + */ /* * sun4u root nexus driver @@ -329,13 +330,7 @@ rootnex_name_child_impl(dev_info_t *child, char *name, int namelen) if ((strcmp(node_name, "fhc") == 0) || (strcmp(node_name, "mem-unit") == 0) || (strcmp(node_name, "central") == 0)) { -#ifdef _STARFIRE - portid = ((((rp->regspec_bustype) & 0x6) >> 1) | - (((rp->regspec_bustype) & 0xF0) >> 2) | - (((rp->regspec_bustype) & 0x8) << 3)); -#else portid = (rp->regspec_bustype >> 1) & 0x1f; -#endif /* * The port-id must go on the hardware property list, diff --git a/usr/src/uts/sun4u/io/pci/pci_cb.c b/usr/src/uts/sun4u/io/pci/pci_cb.c index be0c9cf208..a22f1ca219 100644 --- a/usr/src/uts/sun4u/io/pci/pci_cb.c +++ b/usr/src/uts/sun4u/io/pci/pci_cb.c @@ -23,8 +23,9 @@ * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2019 Peter Tribble. + */ /* * PCI Control Block object @@ -38,10 +39,6 @@ #include <sys/pci/pci_obj.h> #include <sys/machsystm.h> -#ifdef _STARFIRE -#include <sys/starfire.h> -#endif /* _STARFIRE */ - /*LINTLIBRARY*/ void @@ -101,11 +98,6 @@ cb_enable_nintr(pci_t *pci_p, enum cb_nintr_index idx) mutex_enter(&cb_p->cb_intr_lock); cpu_id = intr_dist_cpuid(); -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(cb_p->cb_ittrans_cookie, cpu_id, - IB_GET_MAPREG_INO(ino)); -#endif /* _STARFIRE */ - reg = ib_get_map_reg(mondo, cpu_id); stdphysio(pa, reg); @@ -167,10 +159,6 @@ cb_disable_nintr(cb_t *cb_p, enum cb_nintr_index idx, int wait) cb_set_nintr_reg(cb_p, ino, COMMON_CLEAR_INTR_REG_PENDING); cb_p->cb_inos[idx] = 0; mutex_exit(&cb_p->cb_intr_lock); -#ifdef _STARFIRE - pc_ittrans_cleanup(cb_p->cb_ittrans_cookie, - (volatile uint64_t *)(uintptr_t)ino); -#endif /* _STARFIRE */ } void @@ -206,13 +194,8 @@ cb_intr_dist(void *arg) mondo = CB_INO_TO_MONDO(cb_p, ino); cpu_id = intr_dist_cpuid(); -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(cb_p->cb_ittrans_cookie, cpu_id, - IB_GET_MAPREG_INO(ino)); -#else if (ib_map_reg_get_cpu(imr) == cpu_id) continue; /* same cpu target, no re-program */ -#endif cb_disable_nintr_reg(cb_p, ino, IB_INTR_WAIT); stdphysio(mr_pa, ib_get_map_reg(mondo, cpu_id)); (void) lddphysio(mr_pa); /* flush previous write */ diff --git a/usr/src/uts/sun4u/io/pci/pci_ib.c b/usr/src/uts/sun4u/io/pci/pci_ib.c index cedfc35e05..65d3a5c571 100644 --- a/usr/src/uts/sun4u/io/pci/pci_ib.c +++ b/usr/src/uts/sun4u/io/pci/pci_ib.c @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ /* * PCI Interrupt Block (RISCx) implementation @@ -41,10 +44,6 @@ #include <sys/cpuvar.h> #include <sys/pci/pci_obj.h> -#ifdef _STARFIRE -#include <sys/starfire.h> -#endif /* _STARFIRE */ - /*LINTLIBRARY*/ static uint_t ib_intr_reset(void *arg); @@ -156,10 +155,6 @@ ib_intr_enable(pci_t *pci_p, ib_ino_t ino) */ mutex_enter(&ib_p->ib_intr_lock); cpu_id = intr_dist_cpuid(); -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(IB2CB(ib_p)->cb_ittrans_cookie, cpu_id, - IB_GET_MAPREG_INO(ino)); -#endif /* _STARFIRE */ DEBUG2(DBG_IB, pci_p->pci_dip, "ib_intr_enable: ino=%x cpu_id=%x\n", ino, cpu_id); @@ -202,10 +197,6 @@ ib_intr_disable(ib_t *ib_p, ib_ino_t ino, int wait) } wait_done: IB_INO_INTR_PEND(ib_clear_intr_reg_addr(ib_p, ino)); -#ifdef _STARFIRE - pc_ittrans_cleanup(IB2CB(ib_p)->cb_ittrans_cookie, - (volatile uint64_t *)(uintptr_t)ino); -#endif /* _STARFIRE */ } /* can only used for psycho internal interrupts thermal, power, ue, ce, pbm */ @@ -231,15 +222,8 @@ ib_intr_dist_nintr(ib_t *ib_p, ib_ino_t ino, volatile uint64_t *imr_p) cpu_id = intr_dist_cpuid(); -#ifdef _STARFIRE - if (ino) { - cpu_id = pc_translate_tgtid(IB2CB(ib_p)->cb_ittrans_cookie, - cpu_id, IB_GET_MAPREG_INO(ino)); - } -#else /* _STARFIRE */ if (ib_map_reg_get_cpu(*imr_p) == cpu_id) return; -#endif /* _STARFIRE */ *imr_p = ib_get_map_reg(IB_IMR2MONDO(imr), cpu_id); imr = *imr_p; /* flush previous write */ @@ -286,20 +270,8 @@ ib_intr_dist(ib_t *ib_p, ib_ino_info_t *ino_p) imr_p = ib_intr_map_reg_addr(ib_p, ino); state_reg = IB_INO_INTR_STATE_REG(ib_p, ino); -#ifdef _STARFIRE - /* - * For Starfire it is a pain to check the current target for - * the mondo since we have to read the PC asics ITTR slot - * assigned to this mondo. It will be much easier to assume - * the current target is always different and do the target - * reprogram all the time. - */ - cpu_id = pc_translate_tgtid(IB2CB(ib_p)->cb_ittrans_cookie, cpu_id, - IB_GET_MAPREG_INO(ino)); -#else if (ib_map_reg_get_cpu(*imr_p) == cpu_id) /* same cpu, no reprog */ return; -#endif /* _STARFIRE */ /* disable interrupt, this could disrupt devices sharing our slot */ IB_INO_INTR_OFF(imr_p); diff --git a/usr/src/uts/sun4u/io/pci/pci_intr.c b/usr/src/uts/sun4u/io/pci/pci_intr.c index 7d8760474b..493cc08f59 100644 --- a/usr/src/uts/sun4u/io/pci/pci_intr.c +++ b/usr/src/uts/sun4u/io/pci/pci_intr.c @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ /* * PCI nexus interrupt handling: @@ -41,10 +44,6 @@ #include <sys/sdt.h> #include <sys/clock.h> -#ifdef _STARFIRE -#include <sys/starfire.h> -#endif /* _STARFIRE */ - /* * interrupt jabber: * @@ -579,10 +578,6 @@ pci_add_intr(dev_info_t *dip, dev_info_t *rdip, ddi_intr_handle_impl_t *hdlp) weight = pci_class_to_intr_weight(rdip); intr_dist_cpuid_add_device_weight(cpu_id, rdip, weight); -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(cb_p->cb_ittrans_cookie, cpu_id, - IB_GET_MAPREG_INO(ino)); -#endif /* _STARFIRE */ if (!ipil_list) { *ino_p->ino_map_reg = ib_get_map_reg(mondo, cpu_id); *ino_p->ino_map_reg; diff --git a/usr/src/uts/sun4u/io/pci/pcipsy.c b/usr/src/uts/sun4u/io/pci/pcipsy.c index 93e93d1008..06a4a71e06 100644 --- a/usr/src/uts/sun4u/io/pci/pcipsy.c +++ b/usr/src/uts/sun4u/io/pci/pcipsy.c @@ -22,8 +22,9 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2019 Peter Tribble. + */ /* * Psycho+ specifics implementation: @@ -55,10 +56,6 @@ #include <sys/pci/pci_obj.h> #include <sys/pci/pcipsy.h> -#ifdef _STARFIRE -#include <sys/starfire.h> -#endif /* _STARFIRE */ - static uint32_t pci_identity_init(pci_t *pci_p); static int pci_intr_setup(pci_t *pci_p); static void pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p); @@ -706,9 +703,6 @@ pci_cb_teardown(pci_t *pci_p) cb_disable_nintr(cb_p, CBNINTR_THERMAL, IB_INTR_WAIT); VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_THERMAL]) == 0); } -#ifdef _STARFIRE - pc_ittrans_uninit(cb_p->cb_ittrans_cookie); -#endif /* _STARFIRE */ } int @@ -961,27 +955,6 @@ pbm_configure(pbm_t *pbm_p) */ l &= ~PSYCHO_PCI_CTRL_WAKEUP_EN; -#ifdef _STARFIRE - /* - * Hack to determine whether we do Starfire special handling - * For starfire, we simply program a constant odd-value - * (0x1D) in the MID field. - * - * Zero out the MID field before ORing. We leave the LSB of - * the MID field intact since we cannot have a zero (even) - * MID value. - */ - l &= 0xFF0FFFFFFFFFFFFFULL; - l |= 0x1DULL << 51; - - /* - * Program in the Interrupt Group Number. Here we have to - * convert the starfire 7bit upaid into a 5bit value. - */ - l |= (uint64_t)STARFIRE_UPAID2HWIGN(pbm_p->pbm_pci_p->pci_id) - << COMMON_CB_CONTROL_STATUS_IGN_SHIFT; -#endif /* _STARFIRE */ - /* * Now finally write the control register with the appropriate value. */ @@ -1160,11 +1133,6 @@ pci_cb_setup(pci_t *pci_p) csr &= ~COMMON_CB_CONTROL_STATUS_IAP; stdphysio(csr_pa, csr); -#ifdef _STARFIRE - /* Setup Starfire interrupt target translation */ - pc_ittrans_init(pci_p->pci_id, &cb_p->cb_ittrans_cookie); -#endif /* _STARFIRE */ - } void diff --git a/usr/src/uts/sun4u/io/sbd_cpu.c b/usr/src/uts/sun4u/io/sbd_cpu.c index efee104249..5db48f7572 100644 --- a/usr/src/uts/sun4u/io/sbd_cpu.c +++ b/usr/src/uts/sun4u/io/sbd_cpu.c @@ -23,8 +23,9 @@ * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2019 Peter Tribble. + */ /* * CPU support routines for DR @@ -514,9 +515,6 @@ sbd_pre_attach_cpu(sbd_handle_t *hp, sbd_devlist_t *devlist, int devnum) */ PR_CPU("%s: unmapping sigblk for cpu %d\n", f, cpuid); - - /* platform specific release of sigblk */ - CPU_SGN_MAPOUT(cpuid); } } diff --git a/usr/src/uts/sun4u/io/sysioerr.c b/usr/src/uts/sun4u/io/sysioerr.c index 75a5f3d59c..4242915e23 100644 --- a/usr/src/uts/sun4u/io/sysioerr.c +++ b/usr/src/uts/sun4u/io/sysioerr.c @@ -23,8 +23,9 @@ * Copyright 1990-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2019 Peter Tribble. + */ #include <sys/types.h> #include <sys/conf.h> @@ -53,16 +54,6 @@ int oven_test = 0; */ static int thermal_interrupt_enabled = 0; -#ifdef _STARFIRE -#include <sys/starfire.h> - -int -pc_translate_tgtid(caddr_t, int, volatile uint64_t *); - -void -pc_ittrans_cleanup(caddr_t, volatile uint64_t *); -#endif /* _STARFIRE */ - /* * adb debug_sysio_errs to 1 if you don't want your system to panic on * sbus ue errors. adb sysio_err_flag to 0 if you don't want your system @@ -235,29 +226,17 @@ sysio_init_err(struct sbus_soft_state *softsp) */ mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + UE_ECC_MAPREG); cpu_id = acpu_id; -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id, - mondo_vec_reg); -#endif /* _STARFIRE */ tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID; *mondo_vec_reg = tmp_mondo_vec; mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + CE_ECC_MAPREG); cpu_id = acpu_id; -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id, - mondo_vec_reg); -#endif /* _STARFIRE */ tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID; *mondo_vec_reg = tmp_mondo_vec; mondo_vec_reg = (uint64_t *)(softsp->intr_mapping_reg + SBUS_ERR_MAPREG); cpu_id = acpu_id; -#ifdef _STARFIRE - cpu_id = pc_translate_tgtid(softsp->ittrans_cookie, cpu_id, - mondo_vec_reg); -#endif /* _STARFIRE */ tmp_mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID; *mondo_vec_reg = tmp_mondo_vec; @@ -312,11 +291,6 @@ sysio_dis_err(struct sbus_soft_state *softsp) *mondo_vec_reg = 0; -#ifdef _STARFIRE - /* do cleanup for starfire interrupt target translation */ - pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg); -#endif /* _STARFIRE */ - *clear_vec_reg = 0; mondo_vec_reg = (softsp->intr_mapping_reg + CE_ECC_MAPREG); @@ -324,11 +298,6 @@ sysio_dis_err(struct sbus_soft_state *softsp) *mondo_vec_reg = 0; -#ifdef _STARFIRE - /* Do cleanup for starfire interrupt target translation */ - pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg); -#endif /* _STARFIRE */ - *clear_vec_reg = 0; mondo_vec_reg = (softsp->intr_mapping_reg + SBUS_ERR_MAPREG); @@ -336,11 +305,6 @@ sysio_dis_err(struct sbus_soft_state *softsp) *mondo_vec_reg = 0; -#ifdef _STARFIRE - /* Do cleanup for starfire interrupt target translation */ - pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg); -#endif /* _STARFIRE */ - *clear_vec_reg = 0; /* Flush store buffers */ diff --git a/usr/src/uts/sun4u/io/sysiosbus.c b/usr/src/uts/sun4u/io/sysiosbus.c index 71ec224b19..20b75c8a0b 100644 --- a/usr/src/uts/sun4u/io/sysiosbus.c +++ b/usr/src/uts/sun4u/io/sysiosbus.c @@ -27,6 +27,10 @@ * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. */ +/* + * Copyright 2019 Peter Tribble. + */ + #include <sys/types.h> #include <sys/conf.h> #include <sys/ddi.h> @@ -50,9 +54,6 @@ #include <sys/machsystm.h> #include <sys/intreg.h> #include <sys/ddi_subrdefs.h> -#ifdef _STARFIRE -#include <sys/starfire.h> -#endif /* _STARFIRE */ #include <sys/sdt.h> /* Useful debugging Stuff */ @@ -287,20 +288,6 @@ static int sbus_update_intr_state(dev_info_t *dip, dev_info_t *rdip, ddi_intr_handle_impl_t *hdlp, uint_t new_intr_state); -#ifdef _STARFIRE -void -pc_ittrans_init(int, caddr_t *); - -void -pc_ittrans_uninit(caddr_t); - -int -pc_translate_tgtid(caddr_t, int, volatile uint64_t *); - -void -pc_ittrans_cleanup(caddr_t, volatile uint64_t *); -#endif /* _STARFIRE */ - /* * Configuration data structures */ @@ -693,11 +680,6 @@ sbus_do_detach(dev_info_t *devi) } mutex_exit(&sbus_attachcnt_mutex); -#ifdef _STARFIRE - /* free starfire specific soft intr mapping structure */ - pc_ittrans_uninit(softsp->ittrans_cookie); -#endif /* _STARFIRE */ - /* free the soft state structure */ ddi_soft_state_free(sbusp, instance); @@ -740,11 +722,6 @@ sbus_init(struct sbus_soft_state *softsp, caddr_t address) "SBUS Control reg: 0x%p", (void *)softsp->sysio_ctrl_reg, (void *)softsp->sbus_ctrl_reg)); -#ifdef _STARFIRE - /* Setup interrupt target translation for starfire */ - pc_ittrans_init(softsp->upa_id, &softsp->ittrans_cookie); -#endif /* _STARFIRE */ - softsp->intr_mapping_ign = UPAID_TO_IGN(softsp->upa_id) << IMR_IGN_SHIFT; @@ -815,27 +792,6 @@ sbus_resume_init(struct sbus_soft_state *softsp, int resume) * (RAZ) Get rid of this later!!! */ -#ifdef _STARFIRE - /* - * For Starfire, we need to program a - * constant odd value. - * Zero out the MID field before ORing - * We leave the LSB of the MID field intact since - * we cannot have a zero(even) MID value - */ - uint64_t tmpconst = 0x1DULL; - *softsp->sysio_ctrl_reg &= 0xFF0FFFFFFFFFFFFFULL; - *softsp->sysio_ctrl_reg |= tmpconst << 51; - - /* - * Program in the interrupt group number - * Here we have to convert the starfire - * 7 bit upaid into a 5bit value. - */ - *softsp->sysio_ctrl_reg |= - (uint64_t)STARFIRE_UPAID2HWIGN(softsp->upa_id) - << SYSIO_IGN; -#else /* for the rest of sun4u's */ *softsp->sysio_ctrl_reg |= (uint64_t)softsp->upa_id << 51; @@ -843,7 +799,6 @@ sbus_resume_init(struct sbus_soft_state *softsp, int resume) /* Program in the interrupt group number */ *softsp->sysio_ctrl_reg |= (uint64_t)softsp->upa_id << SYSIO_IGN; -#endif /* _STARFIRE */ /* * Set appropriate fields of sbus control register. @@ -1821,16 +1776,10 @@ sbus_add_intr_impl(dev_info_t *dip, dev_info_t *rdip, (softsp->intr_hndlr_cnt[slot] == 0)) { cpu_id = intr_dist_cpuid(); -#ifdef _STARFIRE - tmp_mondo_vec = pc_translate_tgtid( - softsp->ittrans_cookie, cpu_id, - mondo_vec_reg) << IMR_TID_SHIFT; -#else tmp_mondo_vec = cpu_id << IMR_TID_SHIFT; DPRINTF(SBUS_INTERRUPT_DEBUG, ("Add intr: initial " "mapping reg 0x%lx\n", tmp_mondo_vec)); -#endif /* _STARFIRE */ } else { /* * There is already a different @@ -2004,10 +1953,6 @@ sbus_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip, if ((softsp->intr_hndlr_cnt[slot] == 0) || (slot >= EXT_SBUS_SLOTS)) { ASSERT(sbus_arg->handler_list == NULL); -#ifdef _STARFIRE - /* Do cleanup for interrupt target translation */ - pc_ittrans_cleanup(softsp->ittrans_cookie, mondo_vec_reg); -#endif /* _STARFIRE */ } @@ -2245,20 +2190,10 @@ sbus_intrdist(void *arg) last_mondo_vec_reg = (uint64_t *)mondo_vec_reg; cpu_id = intr_dist_cpuid(); -#ifdef _STARFIRE - /* - * For Starfire it is a pain to check the current target for - * the mondo since we have to read the PC asics ITTR slot - * assigned to this mondo. It will be much easier to assume - * the current target is always different and do the target - * reprogram all the time. - */ -#else if (((*mondo_vec_reg & IMR_TID) >> IMR_TID_SHIFT) == cpu_id) { /* It is the same, don't reprogram */ return; } -#endif /* _STARFIRE */ /* So it's OK to reprogram the CPU target */ @@ -2315,14 +2250,7 @@ sbus_intrdist(void *arg) } /* re-target the mondo and turn it on */ -#ifdef _STARFIRE - mondo_vec = (pc_translate_tgtid(softsp->ittrans_cookie, - cpu_id, mondo_vec_reg) << - INTERRUPT_CPU_FIELD) | - INTERRUPT_VALID; -#else mondo_vec = (cpu_id << INTERRUPT_CPU_FIELD) | INTERRUPT_VALID; -#endif /* _STARFIRE */ /* write it back to the hardware. */ *mondo_vec_reg = mondo_vec; diff --git a/usr/src/uts/sun4u/io/todstarfire.c b/usr/src/uts/sun4u/io/todstarfire.c deleted file mode 100644 index b8571c49f8..0000000000 --- a/usr/src/uts/sun4u/io/todstarfire.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * tod driver module for Starfire - * This module implements a soft tod since - * starfire has no tod part. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/sysmacros.h> -#include <sys/systm.h> -#include <sys/errno.h> -#include <sys/modctl.h> -#include <sys/autoconf.h> -#include <sys/debug.h> -#include <sys/clock.h> -#include <sys/cmn_err.h> -#include <sys/promif.h> -#include <sys/cpuvar.h> -#include <sys/cpu_sgnblk_defs.h> -#include <starfire/sys/cpu_sgn.h> - -static timestruc_t todsf_get(void); -static void todsf_set(timestruc_t); -static uint_t todsf_set_watchdog_timer(uint_t); -static uint_t todsf_clear_watchdog_timer(void); -static void todsf_set_power_alarm(timestruc_t); -static void todsf_clear_power_alarm(void); -static uint64_t todsf_get_cpufrequency(void); - -/* - * Module linkage information for the kernel. - */ -static struct modlmisc modlmisc = { - &mod_miscops, "Soft tod module for Starfire" -}; - -static struct modlinkage modlinkage = { - MODREV_1, (void *)&modlmisc, NULL -}; - -int -_init(void) -{ - if (strcmp(tod_module_name, "todstarfire") == 0) { - int ssp_time32; - char obp_string[40]; - - /* Set the string to pass to OBP */ - (void) sprintf(obp_string, "h# %p unix-gettod", - (void *)&ssp_time32); - - /* Get OBP to get TOD from ssp */ - prom_interpret(obp_string, 0, 0, 0, 0, 0); - - hrestime.tv_sec = (time_t)ssp_time32; - - tod_ops.tod_get = todsf_get; - tod_ops.tod_set = todsf_set; - tod_ops.tod_set_watchdog_timer = todsf_set_watchdog_timer; - tod_ops.tod_clear_watchdog_timer = todsf_clear_watchdog_timer; - tod_ops.tod_set_power_alarm = todsf_set_power_alarm; - tod_ops.tod_clear_power_alarm = todsf_clear_power_alarm; - tod_ops.tod_get_cpufrequency = todsf_get_cpufrequency; - - /* - * Flag warning if user tried to use hardware watchdog - */ - if (watchdog_enable) { - cmn_err(CE_WARN, "Hardware watchdog unavailable"); - } - } - - return (mod_install(&modlinkage)); -} - -int -_fini(void) -{ - if (strcmp(tod_module_name, "todstarfire") == 0) - return (EBUSY); - else - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - - -/* - * Simply return hrestime value - * Must be called with tod_lock held. - */ -static timestruc_t -todsf_get(void) -{ - timestruc_t ts; - extern cpu_sgnblk_t *cpu_sgnblkp[]; - - ASSERT(MUTEX_HELD(&tod_lock)); - - ts = hrestime; - - /* Update the heartbeat */ - if (cpu_sgnblkp[CPU->cpu_id] != NULL) - cpu_sgnblkp[CPU->cpu_id]->sigb_heartbeat++; - return (ts); -} - -/* - * Null function for now. - * Must be called with tod_lock held. - */ -/* ARGSUSED */ -static void -todsf_set(timestruc_t ts) -{ - ASSERT(MUTEX_HELD(&tod_lock)); -} - - -/* - * No watchdog function. - */ -/* ARGSUSED */ -static uint_t -todsf_set_watchdog_timer(uint_t timeoutval) -{ - ASSERT(MUTEX_HELD(&tod_lock)); - return (0); -} - -/* - * No watchdog function - */ -static uint_t -todsf_clear_watchdog_timer(void) -{ - ASSERT(MUTEX_HELD(&tod_lock)); - return (0); -} - -/* - * Null function. - */ -/* ARGSUSED */ -static void -todsf_set_power_alarm(timestruc_t ts) -{ - ASSERT(MUTEX_HELD(&tod_lock)); -} - -/* - * Null function - */ -static void -todsf_clear_power_alarm() -{ - ASSERT(MUTEX_HELD(&tod_lock)); -} - -/* - * Get clock freq from the cpunode - */ -uint64_t -todsf_get_cpufrequency(void) -{ - return (cpunodes[CPU->cpu_id].clock_freq); -} diff --git a/usr/src/uts/sun4u/ngdr/Makefile.files b/usr/src/uts/sun4u/ngdr/Makefile.files index 32e9af4eed..f03fb7a323 100644 --- a/usr/src/uts/sun4u/ngdr/Makefile.files +++ b/usr/src/uts/sun4u/ngdr/Makefile.files @@ -20,15 +20,14 @@ # CDDL HEADER END # # -#pragma ident "%Z%%M% %I% %E% SMI" -# # Copyright (c) 2001 by Sun Microsystems, Inc. # All rights reserved. +# Copyright 2019 Peter Tribble. # # # This Makefile defines the shared dr module that is used by -# directories uts/sun4u/starfire and uts/sun4u/starcat. +# directory uts/sun4u/starcat. # # diff --git a/usr/src/uts/sun4u/ngdr/Makefile.rules b/usr/src/uts/sun4u/ngdr/Makefile.rules index f72c79102f..3cbdbbbeed 100644 --- a/usr/src/uts/sun4u/ngdr/Makefile.rules +++ b/usr/src/uts/sun4u/ngdr/Makefile.rules @@ -19,15 +19,14 @@ # CDDL HEADER END # # -#pragma ident "%Z%%M% %I% %E% SMI" -# # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # # This Makefile defines the build rules for the shared dr -# module used by uts/sun4u/starfire and uts/sun4u/starcat. +# module used by uts/sun4u/starcat. # # diff --git a/usr/src/uts/sun4u/ngdr/io/dr_cpu.c b/usr/src/uts/sun4u/ngdr/io/dr_cpu.c index 17a96f378c..87b5cc7fef 100644 --- a/usr/src/uts/sun4u/ngdr/io/dr_cpu.c +++ b/usr/src/uts/sun4u/ngdr/io/dr_cpu.c @@ -25,6 +25,10 @@ */ /* + * Copyright 2019 Peter Tribble. + */ + +/* * CPU support routines for DR */ @@ -70,13 +74,8 @@ #include <sys/dr.h> #include <sys/dr_util.h> -#ifdef _STARFIRE -#include <sys/starfire.h> -extern struct cpu *SIGBCPU; -#else /* for the DR*INTERNAL_ERROR macros. see sys/dr.h. */ static char *dr_ie_fmt = "dr_cpu.c %d"; -#endif /* _STARFIRE */ int dr_cpu_unit_is_sane(dr_board_t *bp, dr_cpu_unit_t *cp) @@ -145,14 +144,7 @@ dr_cpu_set_prop(dr_cpu_unit_t *cp) } if (dip == NULL) { -#ifndef _STARFIRE - /* - * Do not report an error on Starfire since - * the dip will not be created until after - * the CPU has been configured. - */ DR_DEV_INTERNAL_ERROR(&cp->sbc_cm); -#endif /* !_STARFIRE */ return; } @@ -309,8 +301,6 @@ dr_pre_attach_cpu(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum) */ PR_CPU("%s: unmapping sigblk for cpu %d\n", f, up->sbc_cpu_id); - - CPU_SGN_MAPOUT(up->sbc_cpu_id); } } @@ -671,10 +661,6 @@ dr_fill_cpu_stat(dr_cpu_unit_t *cp, drmach_status_t *pstat, sbd_cpu_stat_t *csp) /* CPU specific status data */ csp->cs_cpuid = cp->sbc_cpu_id; -#ifdef _STARFIRE - csp->cs_isbootproc = (SIGBCPU->cpu_id == cp->sbc_cpu_id) ? 1 : 0; -#endif /* _STARFIRE */ - /* * If the speed and ecache properties have not been * cached yet, read them in from the device tree. diff --git a/usr/src/uts/sun4u/ngdr/io/dr_mem.c b/usr/src/uts/sun4u/ngdr/io/dr_mem.c index ccb70b83cb..436d899ef7 100644 --- a/usr/src/uts/sun4u/ngdr/io/dr_mem.c +++ b/usr/src/uts/sun4u/ngdr/io/dr_mem.c @@ -25,6 +25,10 @@ */ /* + * Copyright 2019 Peter Tribble. + */ + +/* * DR memory support routines. */ @@ -628,7 +632,6 @@ dr_detach_mem(dr_handle_t *hp, dr_common_unit_t *cp) } } -#ifndef _STARFIRE /* * XXX workaround for certain lab configurations (see also starcat drmach.c) * Temporary code to get around observed incorrect results from @@ -698,7 +701,6 @@ again: } #define kphysm_del_span_query dr_del_span_query -#endif /* _STARFIRE */ /* * NOTE: This routine is only partially smart about multiple diff --git a/usr/src/uts/sun4u/os/mach_mp_startup.c b/usr/src/uts/sun4u/os/mach_mp_startup.c index e513f902c4..279aafcd36 100644 --- a/usr/src/uts/sun4u/os/mach_mp_startup.c +++ b/usr/src/uts/sun4u/os/mach_mp_startup.c @@ -22,6 +22,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #include <sys/machsystm.h> #include <sys/cpu_module.h> @@ -64,10 +67,6 @@ init_cpu_info(struct cpu *cp) (void) strcpy(pi->pi_processor_type, "sparcv9"); (void) strcpy(pi->pi_fputypes, "sparcv9"); - /* - * StarFire requires the signature block stuff setup here - */ - CPU_SGN_MAPIN(cpuid); if (cpuid == cpu0.cpu_id) { /* * cpu0 starts out running. Other cpus are diff --git a/usr/src/uts/sun4u/starfire/Makefile b/usr/src/uts/sun4u/starfire/Makefile deleted file mode 100644 index 7a08af878a..0000000000 --- a/usr/src/uts/sun4u/starfire/Makefile +++ /dev/null @@ -1,122 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the sun4u starfire platform -# module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# The following are SPARC specific (rather than sun4u) specific modules -# which are required for the sun4u kernel to completely lint. They are -# not involved in the build in any other way. In order to minimize -# build time, it is assumed that they are up to date. But since sun4u -# is really a separate architecture we cannot use the v7 sparc modules. -# -SPARC_LIB_DIR = $(UTSBASE)/sparc/lint-libs/$(OBJS_DIR) - -SPARC_LINTS = - -SUN4U_LIB_DIR = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR) - -# -# -# -LINT_LIBS = $(LINT_LIB) \ - $(SPARC_LINTS:%=$(SPARC_LIB_DIR)/llib-l%.ln) \ - $(LINT_KMODS:%=$(SUN4U_LIB_DIR)/llib-l%.ln) \ - $(CLOSED_LINT_KMODS:%=$(SUN4U_LIB_DIR)/llib-l%.ln) - -def := TARGET= def -all := TARGET= all -install := TARGET= install -install_h := TARGET= install_h -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint -lintlib := TARGET= lintlib -modlintlib := TARGET= modlintlib -modlist := TARGET= modlist -modlist := NO_STATE= -K $$MODSTATE$$$$ -clean.lint := TARGET= clean.lint -check := TARGET= check - -IMPLEMENTED_PLATFORM = SUNW,Ultra-Enterprise-10000 - -# -# Default build targets. -# -.KEEP_STATE: - -.PARALLEL: $(STARFIRE_KMODS) - -.NO_PARALLEL: $(STARFIRE_CPU_KMODS) - -def all clean clobber clean.lint: genassym unix .WAIT \ - $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS) - -modlist: unix $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS) - -install: $(ROOT_STARFIRE_DIR) $(USR_STARFIRE_DIR) \ - $(USR_STARFIRE_INC_DIR) \ - $(USR_STARFIRE_SBIN_DIR) \ - $(USR_STARFIRE_LIB_DIR) \ - genassym unix .WAIT $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS) - -lintlib: unix - -modlintlib: $(STARFIRE_KMODS) $(STARFIRE_CPU_KMODS) - -genassym unix $(STARFIRE_CPU_KMODS) $(STARFIRE_KMODS): FRC - @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET) - -install_h check: FRC - @cd sys; pwd; $(MAKE) $(TARGET) - -# -# Full kernel lint target. -# -LINT_TARGET = globallint - -globallint: - @-$(ECHO) "\nStarfire KERNEL: global crosschecks:" - @-$(LINT) $(LINTFLAGS) $(LINT_LIBS) 2>&1 | $(LGREP.2) - -lint: lintlib .WAIT modlintlib .WAIT $(LINT_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/Makefile.files b/usr/src/uts/sun4u/starfire/Makefile.files deleted file mode 100644 index 96c4d9a102..0000000000 --- a/usr/src/uts/sun4u/starfire/Makefile.files +++ /dev/null @@ -1,67 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright 1997-2001, 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This Makefile defines all file modules for the directory -# uts/sun4u/starfire and its children. These are the source files which -# are starfire "implementation architecture" dependent. -# - -# -# Object lists -# -# Starfire specific kernel modules - -CORE_OBJS += cpu_sgnblk.o bbus_intr.o portctrl.o - -# -# Starfire specific driver related modules -# -CVC_OBJS += cvc.o - -CVCREDIR_OBJS += cvcredir.o - -NGDRMACH_OBJS += drmach.o drmach_asm.o pda.o memctrl.o \ - dr_util.o drmach_err.o - -IDN_OBJS += idn.o idn_proto.o idn_dlpi.o idn_xf.o idn_smr.o idn_asm.o \ - mi.o nd.o inet_common.o \ - memctrl.o pda.o -IDN_DEPS += idn_asm.o - -# -# Miscellaneous -# -INC_PATH += -I$(UTSBASE)/sun4u/starfire - -# -# Since assym.h is a derived file, the dependency must be explicit for -# all files including this file. (This is only actually required in the -# instance when the .nse_depinfo file does not exist.) It may seem that -# the lint targets should also have a similar dependency, but they don't -# since only C headers are included when #defined(lint) is true. -# -ASSYM_DEPS += drmach_asm.o idn_asm.o diff --git a/usr/src/uts/sun4u/starfire/Makefile.rules b/usr/src/uts/sun4u/starfire/Makefile.rules deleted file mode 100644 index 5da6c4cce3..0000000000 --- a/usr/src/uts/sun4u/starfire/Makefile.rules +++ /dev/null @@ -1,106 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This Makefile defines the build rules for the directory -# uts/sun4u/starfire and its children. -# -# The following two-level ordering must be maintained in this file. -# Lines are sorted first in order of decreasing specificity based on -# the first directory component. That is, sun4u rules come before -# sparc rules come before common rules. -# -# Lines whose initial directory components are equal are sorted -# alphabetically by the remaining components. - -# -# inline support for DR. -# - -IL_CPP=$(CPP) -P -DINLINE -D_ASM $(AS_INC_PATH) \ - $(CPP_DEFS) $(ALWAYS_DEFS) $(ALL_DEFS) $(CONFIG_DEFS) - -# -# Section 1a: C object build rules -# - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/cvc/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/cvcredir/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -DRMACH_IL= $(OBJS_DIR)/drmach.il -$(OBJS_DIR)/drmach.o := CC_XARCH_32 = -xarch=v8plusa -$(OBJS_DIR)/drmach.o: $(UTSBASE)/sun4u/starfire/io/drmach.c $(DRMACH_IL) - $(COMPILE.c) $(DRMACH_IL) -o $@ $(UTSBASE)/sun4u/starfire/io/drmach.c - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/io/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/ml/%.s - $(COMPILE.s) -o $@ $< - -$(OBJS_DIR)/%.o: $(UTSBASE)/sun4u/starfire/os/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -STARFIRE_IO= $(UTSBASE)/sun4u/starfire/io - -CLEANFILES += $(STARFIRE_IO)/drmach_err.c - -$(STARFIRE_IO)/drmach_err.c: $(SBDGENERR) $(SBD_IOCTL) - $(RM) $@ - $(SBDGENERRCMD) ESTF < $(SBD_IOCTL) > $@ - -# inline stuff - -CLEANFILES += $(DRMACH_IL) - -$(DRMACH_IL): $(UTSBASE)/sun4u/starfire/ml/drmach.il.cpp - $(IL_CPP) $(UTSBASE)/sun4u/starfire/ml/drmach.il.cpp > $@ - -# -# Section 1b: Lint object build rules -# - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/cvc/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/cvcredir/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/io/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/ml/%.s - @($(LHEAD) $(LINT.s) $< $(LTAIL)) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/sun4u/starfire/os/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/sun4u/starfire/Makefile.starfire b/usr/src/uts/sun4u/starfire/Makefile.starfire deleted file mode 100644 index ce706f8681..0000000000 --- a/usr/src/uts/sun4u/starfire/Makefile.starfire +++ /dev/null @@ -1,132 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Global definitions for sun4u starfire implementation specific modules. -# - -# -# Define directories. -# -ROOT_STARFIRE_DIR = $(ROOT_PLAT_DIR)/SUNW,Ultra-Enterprise-10000 -ROOT_STARFIRE_MOD_DIR = $(ROOT_STARFIRE_DIR)/kernel -ROOT_STARFIRE_KERN_DIR_32 = $(ROOT_STARFIRE_MOD_DIR) -ROOT_STARFIRE_KERN_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/$(SUBDIR64) -ROOT_STARFIRE_MISC_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)/misc -ROOT_STARFIRE_MISC_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/misc/$(SUBDIR64) -ROOT_STARFIRE_DRV_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)/drv -ROOT_STARFIRE_DRV_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/drv/$(SUBDIR64) -ROOT_STARFIRE_CPU_DIR_32 = $(ROOT_STARFIRE_MOD_DIR)/cpu -ROOT_STARFIRE_CPU_DIR_64 = $(ROOT_STARFIRE_MOD_DIR)/cpu/$(SUBDIR64) - -ROOT_STARFIRE_KERN_DIR = $(ROOT_STARFIRE_KERN_DIR_$(CLASS)) -ROOT_STARFIRE_MISC_DIR = $(ROOT_STARFIRE_MISC_DIR_$(CLASS)) -ROOT_STARFIRE_DRV_DIR = $(ROOT_STARFIRE_DRV_DIR_$(CLASS)) -ROOT_STARFIRE_CPU_DIR = $(ROOT_STARFIRE_CPU_DIR_$(CLASS)) - -ROOT_PLAT_MOD_DIRS += $(ROOT_STARFIRE_MOD_DIR) -ROOT_PLAT_MISC_DIRS_32 += $(ROOT_STARFIRE_MISC_DIR_32) - -USR_STARFIRE_DIR = $(USR_PLAT_DIR)/SUNW,Ultra-Enterprise-10000 -USR_STARFIRE_INC_DIR = $(USR_STARFIRE_DIR)/include -USR_STARFIRE_ISYS_DIR = $(USR_STARFIRE_INC_DIR)/sys -USR_STARFIRE_SBIN_DIR = $(USR_STARFIRE_DIR)/sbin -USR_STARFIRE_LIB_DIR = $(USR_STARFIRE_DIR)/lib - -# -# Define objects. -# -STARFIRE_OBJS = starfire.o - -# -# Define modules. -# -STARFIRE_KMODS = platmod -STARFIRE_KMODS += rootnex sbus pcipsy -STARFIRE_KMODS += cvc cvcredir -STARFIRE_KMODS += ngdr ngdrmach -STARFIRE_KMODS += idn - -# -# CPU modules. -# -STARFIRE_CPU_KMODS += spitfire - -# -# Include the makefiles which define build rule templates, the -# collection of files per module, and a few specific flags. Note -# that order is significant, just as with an include path. The -# first build rule template which matches the files name will be -# used. By including these in order from most machine dependent -# to most machine independent, we allow a machine dependent file -# to be used in preference over a machine independent version -# (Such as a machine specific optimization, which preserves the -# interfaces.) -# -include $(UTSBASE)/sun4u/ngdr/Makefile.files -include $(UTSBASE)/sun4u/starfire/Makefile.files - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/Makefile.sun4u - -# -# Everybody needs to know how to build modstubs.o and to locate unix.o -# -UNIX_DIR = $(UTSBASE)/$(PLATFORM)/starfire/unix -MODSTUBS_DIR = $(UNIX_DIR) -DSF_DIR = $(UTSBASE)/$(PLATFORM)/starfire/genassym -LINTS_DIR = $(OBJS_DIR) -LINT_LIB_DIR = $(UTSBASE)/$(PLATFORM)/starfire/lint-libs/$(OBJS_DIR) - -UNIX_O = $(UNIX_DIR)/$(OBJS_DIR)/unix.o - -LINT_LIB = $(LINT_LIB_DIR)/llib-lunix.ln - -# -# Define the actual specific platforms -# -MACHINE_DEFS = -D$(PLATFORM) -D_MACHDEP -DSFMMU -MACHINE_DEFS += -D_STARFIRE -D_CPU_SIGNATURE - -# -# Define for inline pre-processing since -# cpp not smart about v9 yet. -# -CPP_DEFS_32 = -CPP_DEFS_64 = -D__sparcv9 -CPP_DEFS = $(CPP_DEFS_$(CLASS)) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED -LINTTAGS += -erroff=E_STATIC_UNUSED -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV -LINTTAGS += -erroff=E_BAD_FORMAT_STR2 diff --git a/usr/src/uts/sun4u/starfire/Makefile.targ b/usr/src/uts/sun4u/starfire/Makefile.targ deleted file mode 100644 index e746704e81..0000000000 --- a/usr/src/uts/sun4u/starfire/Makefile.targ +++ /dev/null @@ -1,93 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Common targets for sun4u starfire implementation specific modules. -# - -.KEEP_STATE: - -# -# Rules for implementation subdirectories. -# -$(ROOT_STARFIRE_DIR): $(ROOT_PLAT_DIR) - -$(INS.dir) - -$(ROOT_STARFIRE_MOD_DIR): $(ROOT_STARFIRE_DIR) - -$(INS.dir) - -$(ROOT_STARFIRE_KERN_DIR): $(ROOT_STARFIRE_MOD_DIR) - -$(INS.dir) - -$(ROOT_STARFIRE_DRV_DIR_32): $(ROOT_STARFIRE_MOD_DIR) - -$(INS.dir) - -$(ROOT_STARFIRE_DRV_DIR_64): $(ROOT_STARFIRE_DRV_DIR_32) - -$(INS.dir) - -$(ROOT_STARFIRE_CPU_DIR_32): $(ROOT_STARFIRE_MOD_DIR) - -$(INS.dir) - -$(ROOT_STARFIRE_CPU_DIR_64): $(ROOT_STARFIRE_CPU_DIR_32) - -$(INS.dir) - -$(ROOT_STARFIRE_MISC_DIR_32): $(ROOT_STARFIRE_MOD_DIR) - -$(INS.dir) - -$(ROOT_STARFIRE_MISC_DIR_64): $(ROOT_STARFIRE_MISC_DIR_32) - -$(INS.dir) - -$(USR_STARFIRE_DIR): $(USR_PLAT_DIR) - -$(INS.dir) - -$(USR_STARFIRE_INC_DIR): $(USR_STARFIRE_DIR) $(USR_PSM_INCL_DIR) - $(INS.slink4) - -$(USR_STARFIRE_SBIN_DIR): $(USR_STARFIRE_DIR) $(USR_PSM_SBIN_DIR) - -$(INS.slink5) - -$(USR_STARFIRE_LIB_DIR): $(USR_STARFIRE_DIR) $(USR_PSM_LIB_DIR) - -$(INS.dir) - -$(USR_STARFIRE_ISYS_DIR): $(USR_STARFIRE_INC_DIR) - $(INS.dir) - -$(ROOT_STARFIRE_KERN_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_KERN_DIR) FRC - $(INS.file) - -$(ROOT_STARFIRE_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_DRV_DIR) FRC - $(INS.file) - -$(ROOT_STARFIRE_CPU_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_CPU_DIR) FRC - $(INS.file) - -$(ROOT_STARFIRE_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_STARFIRE_MISC_DIR) FRC - $(INS.file) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/ngdr/Makefile.rules -include $(UTSBASE)/sun4u/starfire/Makefile.rules -include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/cvc/Makefile b/usr/src/uts/sun4u/starfire/cvc/Makefile deleted file mode 100644 index f450a72f3b..0000000000 --- a/usr/src/uts/sun4u/starfire/cvc/Makefile +++ /dev/null @@ -1,88 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the cvc driver module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = cvc -OBJECTS = $(CVC_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(CVC_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/cvc - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-unused-function -CERRWARN += -_gcc=-Wno-uninitialized - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/cvc/cvc.c b/usr/src/uts/sun4u/starfire/cvc/cvc.c deleted file mode 100644 index 1538db559c..0000000000 --- a/usr/src/uts/sun4u/starfire/cvc/cvc.c +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -/* - * MT STREAMS Virtual Console Device Driver - */ - -#include <sys/types.h> -#include <sys/sysmacros.h> -#include <sys/processor.h> -#include <sys/cpuvar.h> -#include <sys/open.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/signal.h> -#include <sys/cred.h> -#include <sys/user.h> -#include <sys/proc.h> -#include <sys/vnode.h> -#include <sys/uio.h> -#include <sys/buf.h> -#include <sys/file.h> -#include <sys/kmem.h> -#include <sys/vmem.h> -#include <sys/stat.h> -#include <sys/stream.h> -#include <sys/stropts.h> -#include <sys/strsubr.h> -#include <sys/strsun.h> -#include <sys/tty.h> -#include <sys/ptyvar.h> -#include <sys/poll.h> -#include <sys/debug.h> -#include <sys/conf.h> - -#include <sys/starfire.h> -#include <sys/mman.h> -#include <vm/seg_kmem.h> - -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/errno.h> -#include <sys/modctl.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/cvc.h> -#include <sys/cpu_sgn.h> - -extern void prom_printf(char *fmt, ...); - -static int cvc_info(dev_info_t *, ddi_info_cmd_t, void *, void **); -static int cvc_attach(dev_info_t *, ddi_attach_cmd_t); -static int cvc_detach(dev_info_t *, ddi_detach_cmd_t); -static int cvc_open(register queue_t *, dev_t *, int, int, cred_t *); -static int cvc_close(queue_t *, int, cred_t *); -static int cvc_wput(queue_t *, mblk_t *); -static int cvc_wsrv(queue_t *); -static void cvc_ioctl(queue_t *, mblk_t *); -static void cvc_ack(mblk_t *, mblk_t *, uint_t); -static void cvc_reioctl(void *); -static void cvc_input_daemon(void); -static void cvc_putc(register int); -static void cvc_flush_buf(void *); -static void cvc_bbsram_ops(volatile uchar_t *); - -static caddr_t cvc_iobuf_mapin(processorid_t); -static void cvc_iobuf_mapout(processorid_t); - void cvc_assign_iocpu(processorid_t); - -/* - * Private copy of devinfo pointer; cvc_info uses it. - */ -static dev_info_t *cvcdip; - -/* - * This buffer is used to manage mapping in the I/O buffer that CVC - * uses when communicating with the SSP Client (netcon_server) via bbsram. - */ -static caddr_t cvc_iobufp[NCPU]; - -typedef struct cvc_s { - bufcall_id_t cvc_wbufcid; - tty_common_t cvc_tty; -} cvc_t; - -cvc_t cvc_common_tty; - -static struct module_info cvcm_info = { - 1313, /* mi_idnum Bad luck number ;-) */ - "cvc", /* mi_idname */ - 0, /* mi_minpsz */ - INFPSZ, /* mi_maxpsz */ - 2048, /* mi_hiwat */ - 2048 /* mi_lowat */ -}; - -static struct qinit cvcrinit = { - NULL, /* qi_putp */ - NULL, /* qi_srvp */ - cvc_open, /* qi_qopen */ - cvc_close, /* qi_qclose */ - NULL, /* qi_qadmin */ - &cvcm_info, /* qi_minfo */ - NULL /* qi_mstat */ -}; - -static struct qinit cvcwinit = { - cvc_wput, /* qi_putp */ - cvc_wsrv, /* qi_srvp */ - cvc_open, /* qi_qopen */ - cvc_close, /* qi_qclose */ - NULL, /* qi_qadmin */ - &cvcm_info, /* qi_minfo */ - NULL /* qi_mstat */ -}; - -struct streamtab cvcinfo = { - &cvcrinit, /* st_rdinit */ - &cvcwinit, /* st_wrinit */ - NULL, /* st_muxrinit */ - NULL /* st_muxwrinit */ -}; - -#define TIMEOUT_DELAY 100000 - -#define BBSRAM_INPUT_BUF ((volatile char *)(cvc_iobufp[cvc_iocpu] \ - + BBSRAM_INPUT_COUNT_OFF)) - -#define BBSRAM_OUTPUT_BUF ((volatile char *)(cvc_iobufp[cvc_iocpu] \ - + BBSRAM_OUTPUT_COUNT_OFF)) - -#define BBSRAM_INPUT_COUNT (*((volatile short *)BBSRAM_INPUT_BUF)) - -#define BBSRAM_OUTPUT_COUNT (*((volatile short *)BBSRAM_OUTPUT_BUF)) - -#define CVC_OUT_MAXSPIN 1024 - -/* The bbsram control reg is located at the end of the I/O buffers */ -#define BBSRAM_CONTROL_REG ((volatile uchar_t *)(cvc_iobufp[cvc_iocpu] \ - + CVC_IN_SIZE + CVC_OUT_SIZE)) - -static krwlock_t cvclock; /* lock protecting everything here */ -static queue_t *cvcinput_q; /* queue for console input */ -static queue_t *cvcoutput_q; /* queue for console output */ -static int cvc_instance = -1; -static int cvc_stopped = 0; -static int cvc_suspended = 0; -static int cvc_hangup_ok = 0; - -static kthread_id_t cvc_input_daemon_thread; -static kmutex_t cvcmutex; /* protects input */ -static kmutex_t cvc_buf_mutex; /* protects internal output buffer */ -static kmutex_t cvc_bbsram_input_mutex; /* protects BBSRAM inp buff */ -static int input_ok = 0; /* true when stream is valid */ -static int stop_bbsram = 1; /* true when BBSRAM is not usable */ -static int stop_timeout = 0; -static uchar_t cvc_output_buffer[MAX_XFER_OUTPUT]; /* output buffer */ -static ushort_t cvc_output_count = 0; -static int via_bbsram = 0; /* toggle switch */ -static timeout_id_t cvc_timeout_id = (timeout_id_t)-1; -static processorid_t cvc_iocpu = -1; /* cpu id of cpu zero */ - -/* - * Module linkage information for the kernel. - */ - -DDI_DEFINE_STREAM_OPS(cvcops, nulldev, nulldev, cvc_attach, cvc_detach, - nodev, cvc_info, (D_MTPERQ | D_MP), &cvcinfo, - ddi_quiesce_not_supported); - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a pseudo driver */ - "CVC driver 'cvc'", - &cvcops, /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -int -_init(void) -{ - int status; - - status = mod_install(&modlinkage); - if (status == 0) { - mutex_init(&cvcmutex, NULL, MUTEX_DEFAULT, NULL); - } - return (status); -} - -int -_fini(void) -{ - return (EBUSY); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* - * DDI glue routines. - */ - -/* ARGSUSED */ -static int -cvc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - static char been_here = 0; - - if (cmd == DDI_RESUME) { - cvc_suspended = 0; - return (DDI_SUCCESS); - } - - mutex_enter(&cvcmutex); - if (!been_here) { - been_here = 1; - mutex_init(&cvc_buf_mutex, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&cvc_bbsram_input_mutex, NULL, MUTEX_DEFAULT, NULL); - rw_init(&cvclock, NULL, RW_DRIVER, NULL); - rw_enter(&cvclock, RW_WRITER); - cvc_timeout_id = timeout(cvc_flush_buf, NULL, - drv_usectohz(TIMEOUT_DELAY)); - rw_exit(&cvclock); - cvc_instance = ddi_get_instance(devi); - } else { -#if defined(DEBUG) - cmn_err(CE_NOTE, - "cvc_attach: called multiple times!! (instance = %d)", - ddi_get_instance(devi)); -#endif /* DEBUG */ - return (DDI_SUCCESS); - } - mutex_exit(&cvcmutex); - - if (ddi_create_minor_node(devi, "cvc", S_IFCHR, - 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { - ddi_remove_minor_node(devi, NULL); - return (-1); - } - cvcdip = devi; - cvcinput_q = NULL; - cvcoutput_q = NULL; - return (DDI_SUCCESS); -} - -static int -cvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - if (cmd == DDI_SUSPEND) { - cvc_suspended = 1; - } else { - if (cmd != DDI_DETACH) { - return (DDI_FAILURE); - } - /* - * XXX this doesn't even begin to address the detach - * issues - it doesn't terminate the outstanding thread, - * it doesn't clean up mutexes, kill the timeout routine - * etc. - */ - if (cvc_instance == ddi_get_instance(dip)) { - ddi_remove_minor_node(dip, NULL); - } - } - return (DDI_SUCCESS); -} - -/* ARGSUSED */ -static int -cvc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - register int error; - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if (cvcdip == NULL) { - error = DDI_FAILURE; - } else { - *result = (void *)cvcdip; - error = DDI_SUCCESS; - } - break; - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)0; - error = DDI_SUCCESS; - break; - default: - error = DDI_FAILURE; - } - return (error); -} - -/* ARGSUSED */ -static int -cvc_open(register queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp) -{ - register int unit = getminor(*devp); - register int err = 0; - tty_common_t *tty; - cvc_t *cp; - static int input_daemon_started; - - if (unit != 0) - return (ENXIO); - - if (q->q_ptr) - return (0); - - cp = (cvc_t *)&cvc_common_tty; - bzero((caddr_t)cp, sizeof (cvc_t)); - cp->cvc_wbufcid = 0; - tty = &cp->cvc_tty; - tty->t_readq = q; - tty->t_writeq = WR(q); - WR(q)->q_ptr = q->q_ptr = (caddr_t)cp; - cvcinput_q = RD(q); /* save for cvc_redir */ - qprocson(q); - mutex_enter(&cvcmutex); - input_ok = 1; - if (!input_daemon_started) { - extern struct cpu *SIGBCPU; /* bugid4141050 */ - extern cpu_sgnblk_t *cpu_sgnblkp[]; - - input_daemon_started = 1; - mutex_exit(&cvcmutex); - - ASSERT(cpu_sgnblkp[SIGBCPU->cpu_id] != NULL); - cvc_assign_iocpu(SIGBCPU->cpu_id); - - cvc_input_daemon_thread = thread_create(NULL, 0, - cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri); - } else { - mutex_exit(&cvcmutex); - } -#ifdef lint - cvc_input_daemon_thread = cvc_input_daemon_thread; -#endif - return (err); -} - -/* ARGSUSED */ -static int -cvc_close(queue_t *q, int flag, cred_t *crp) -{ - register int err = 0; - register cvc_t *cp; - - mutex_enter(&cvcmutex); - input_ok = 0; - mutex_exit(&cvcmutex); - - cp = q->q_ptr; - if (cp->cvc_wbufcid != 0) { - unbufcall(cp->cvc_wbufcid); - } - ttycommon_close(&cp->cvc_tty); - WR(q)->q_ptr = q->q_ptr = NULL; - cvcinput_q = NULL; - bzero((caddr_t)cp, sizeof (cvc_t)); - qprocsoff(q); - return (err); -} - - -/* - * cvc_wput() - * cn driver does a strwrite of console output data to rconsvp which - * has been set by consconfig. The data enters the cvc stream at the - * streamhead and flows thru ttycompat and ldterm which have been - * pushed on the stream. Console output data gets sent out either - * by cvcredir (if there is a cvcd running) or bbsram (if there - * isn't). - * Data is sent to the cvcredir via it's read q which is cvcoutput_q - * and was set in cvc_register(). - */ -static int -cvc_wput(register queue_t *q, register mblk_t *mp) -{ - int error = 0; - - rw_enter(&cvclock, RW_READER); - switch (mp->b_datap->db_type) { - - case M_IOCTL: - case M_CTL: - cvc_ioctl(q, mp); - break; - - case M_FLUSH: - if (*mp->b_rptr & FLUSHW) { - /* - * Flush our write queue. - */ - flushq(q, FLUSHDATA); - *mp->b_rptr &= ~FLUSHW; - } - if (*mp->b_rptr & FLUSHR) { - flushq(RD(q), FLUSHDATA); - qreply(q, mp); - } else - freemsg(mp); - break; - - case M_STOP: - cvc_stopped = 1; - freemsg(mp); - break; - - case M_START: - cvc_stopped = 0; - freemsg(mp); - qenable(q); /* Start up delayed messages */ - break; - - case M_READ: - /* - * ldterm handles this (VMIN/VTIME processing). - */ - freemsg(mp); - break; - default: - cmn_err(CE_WARN, "cvc_wput: illegal mblk = 0x%p", - (void *)mp); - cmn_err(CE_WARN, "cvc_wput: type = 0x%x", - mp->b_datap->db_type); - /* FALLTHROUGH */ -#ifdef lint - break; -#endif - - case M_DATA: - if (cvc_stopped == 1 || cvc_suspended == 1) { - (void) putq(q, mp); - break; - } - if (cvcoutput_q != NULL && !via_bbsram) { - /* - * Send it up past cvcredir module. - */ - putnext(cvcoutput_q, mp); - } else { - char *msgp, c; - mblk_t *mp2 = mp; - int count; - - while (mp2 != NULL) { - count = mp2->b_wptr - mp2->b_rptr; - msgp = (char *)mp2->b_rptr; - while (count > 0) { - count--; - if ((c = *msgp++) != '\0') { - /* don't print NULs */ - cvc_putc(c); - } - } - mp2 = mp2->b_cont; - } - freemsg(mp); - } - break; - - } - rw_exit(&cvclock); - return (error); -} - -static int cvc_wsrv_count = 0; - -static int -cvc_wsrv(queue_t *q) -{ - register mblk_t *mp; - - cvc_wsrv_count++; - - if (cvc_stopped == 1 || cvc_suspended == 1) { - return (0); - } - - rw_enter(&cvclock, RW_READER); - while ((mp = getq(q)) != NULL) { - if (cvcoutput_q != NULL && !via_bbsram) { - /* - * Send it up past cvcredir module. - */ - putnext(cvcoutput_q, mp); - } else { - char *msgp, c; - mblk_t *mp2 = mp; - int count; - - while (mp2 != NULL) { - count = mp2->b_wptr - mp2->b_rptr; - msgp = (char *)mp2->b_rptr; - while (count > 0) { - count--; - if ((c = *msgp++) != '\0') { - /* don't print NULs */ - cvc_putc(c); - } - } - mp2 = mp2->b_cont; - } - freemsg(mp); - } - } - rw_exit(&cvclock); - return (0); -} - - -/* - * cvc_ioctl() - * handle normal console ioctls. - */ -static void -cvc_ioctl(register queue_t *q, register mblk_t *mp) -{ - register struct iocblk *iocp; - register tty_common_t *tty; - register cvc_t *cp; - int datasize; - int error = 0; - mblk_t *tmp; - - cp = q->q_ptr; - tty = &cp->cvc_tty; - if (tty->t_iocpending != NULL) { - freemsg(tty->t_iocpending); - tty->t_iocpending = NULL; - } - datasize = ttycommon_ioctl(tty, q, mp, &error); - if (datasize != 0) { - if (cp->cvc_wbufcid) - unbufcall(cp->cvc_wbufcid); - cp->cvc_wbufcid = bufcall(datasize, BPRI_HI, cvc_reioctl, cp); - return; - } - if (error < 0) { - iocp = (struct iocblk *)mp->b_rptr; - /* - * "ttycommon_ioctl" didn't do anything; we process it here. - */ - error = 0; - switch (iocp->ioc_cmd) { - - /* - * Set modem bit ioctls. These are NOPs for us, since we - * dont control any hardware. - */ - case TCSBRK: - case TIOCSBRK: - case TIOCCBRK: - case TIOCMSET: - case TIOCMBIS: - case TIOCMBIC: - if (iocp->ioc_count != TRANSPARENT) { - mioc2ack(mp, NULL, 0, 0); - } else { - mcopyin(mp, NULL, sizeof (int), NULL); - } - /* qreply done below */ - break; - - /* - * Get modem bits, we return 0 in mblk. - */ - case TIOCMGET: - tmp = allocb(sizeof (int), BPRI_MED); - if (tmp == NULL) { - miocnak(q, mp, 0, EAGAIN); - return; - } - *(int *)tmp->b_rptr = 0; - - if (iocp->ioc_count != TRANSPARENT) - mioc2ack(mp, tmp, sizeof (int), 0); - else - mcopyout(mp, NULL, sizeof (int), NULL, tmp); - /* qreply done below */ - break; - - default: - /* - * If we don't understand it, it's an error. NAK it. - */ - error = EINVAL; - break; - } - } - if (error != 0) { - iocp->ioc_error = error; - mp->b_datap->db_type = M_IOCNAK; - } - qreply(q, mp); - -} - - -/* - * cvc_redir() - * called from cvcredir:cvcr_wput() to handle console input - * data. This routine puts the cvcredir write (downstream) data - * onto the cvc read (upstream) queues. Note that if `mp' is - * an M_IOCTL, then it may be reused by the caller to send back - * an M_IOCACK or M_IOCNAK. - */ -int -cvc_redir(mblk_t *mp) -{ - register struct iocblk *iocp; - register tty_common_t *tty; - register cvc_t *cp; - struct winsize *ws; - int error; - - if (cvcinput_q == NULL) { - cmn_err(CE_WARN, "cvc_redir: cvcinput_q NULL!"); - return (EINVAL); - } - - if (DB_TYPE(mp) != M_IOCTL) { - putnext(cvcinput_q, mp); - return (0); - } - - iocp = (struct iocblk *)mp->b_rptr; - if (iocp->ioc_cmd == TIOCSWINSZ) { - error = miocpullup(mp, sizeof (struct winsize)); - if (error != 0) - return (error); - - ws = (struct winsize *)mp->b_cont->b_rptr; - cp = cvcinput_q->q_ptr; - tty = &cp->cvc_tty; - mutex_enter(&tty->t_excl); - if (bcmp(&tty->t_size, ws, sizeof (struct winsize)) != 0) { - tty->t_size = *ws; - mutex_exit(&tty->t_excl); - (void) putnextctl1(cvcinput_q, M_PCSIG, SIGWINCH); - } else - mutex_exit(&tty->t_excl); - } else { - /* - * It must be a CVC_DISCONNECT, send hangup. - */ - ASSERT(iocp->ioc_cmd == CVC_DISCONNECT); - if (cvc_hangup_ok) - (void) putnextctl(cvcinput_q, M_HANGUP); - } - - return (0); -} - - -/* - * cvc_register() - * called from cvcredir to register it's queues. cvc - * receives data from cn via the streamhead and sends it to cvcredir - * via pointers to cvcredir's queues. - */ -int -cvc_register(queue_t *q) -{ - int error = -1; - - if (cvcinput_q == NULL) - cmn_err(CE_WARN, "cvc_register: register w/ no console open!"); - rw_enter(&cvclock, RW_WRITER); - if (cvcoutput_q == NULL) { - cvcoutput_q = RD(q); /* Make sure its the upstream q */ - qprocson(cvcoutput_q); /* must be done within cvclock */ - error = 0; - } else { - /* - * cmn_err will call us, so release lock. - */ - rw_exit(&cvclock); - if (cvcoutput_q == q) - cmn_err(CE_WARN, "cvc_register: duplicate q!"); - else - cmn_err(CE_WARN, "cvc_register: nondup q = 0x%p", - (void *)q); - return (error); - } - - /* - * Unless "via_bbsram" is set, i/o will be going through cvcd, so - * stop flushing output to BBSRAM. - */ - if ((cvc_timeout_id != (timeout_id_t)-1) && (!via_bbsram)) { - stop_timeout = 1; - (void) untimeout(cvc_timeout_id); - cvc_timeout_id = (timeout_id_t)-1; - cvc_hangup_ok = 1; - } - rw_exit(&cvclock); - return (error); -} - - -/* - * cvc_unregister() - * called from cvcredir to clear pointers to its queues. - * cvcredir no longer wants to send or receive data. - */ -void -cvc_unregister(queue_t *q) -{ - rw_enter(&cvclock, RW_WRITER); - if (q == cvcoutput_q) { - qprocsoff(cvcoutput_q); /* must be done within cvclock */ - cvcoutput_q = NULL; - } else { - rw_exit(&cvclock); - cmn_err(CE_WARN, "cvc_unregister: q = 0x%p not registered", - (void *)q); - return; - } - - /* - * i/o will not be going through cvcd, start flushing output to - * BBSRAM - */ - if (cvc_timeout_id == (timeout_id_t)-1) { - stop_timeout = 0; - cvc_timeout_id = timeout(cvc_flush_buf, NULL, - drv_usectohz(TIMEOUT_DELAY)); - } - rw_exit(&cvclock); -} - -/* - * cvc_reioctl() - * Retry an "ioctl", now that "bufcall" claims we may be able - * to allocate the buffer we need. - */ -static void -cvc_reioctl(void *unit) -{ - register queue_t *q; - register mblk_t *mp; - register cvc_t *cp = (cvc_t *)unit; - - /* - * The bufcall is no longer pending. - */ - if (!cp->cvc_wbufcid) { - return; - } - cp->cvc_wbufcid = 0; - if ((q = cp->cvc_tty.t_writeq) == NULL) { - return; - } - if ((mp = cp->cvc_tty.t_iocpending) != NULL) { - /* not pending any more */ - cp->cvc_tty.t_iocpending = NULL; - cvc_ioctl(q, mp); - } -} - - -/* - * cvc_bbsram_ops() - * Process commands sent to cvc from netcon_server via BBSRAM - */ -static void -cvc_bbsram_ops(volatile unsigned char *op_reg) -{ - uchar_t op; - - if ((op = *op_reg) == 0) - return; - - ASSERT(MUTEX_HELD(&cvc_bbsram_input_mutex)); - - switch (op) { - case CVC_BBSRAM_BREAK: /* A console break (L1-A) */ - abort_sequence_enter((char *)NULL); - break; - case CVC_BBSRAM_DISCONNECT: /* Break connection, hang up */ - if (cvcinput_q && cvc_hangup_ok) - (void) putnextctl(cvcinput_q, M_HANGUP); - break; - case CVC_BBSRAM_VIA_NET: /* console via network */ - via_bbsram = 0; - /* - * stop periodic flushing of output to BBSRAM - * only if cvcredir/cvcd are present - */ - rw_enter(&cvclock, RW_WRITER); - if (cvcoutput_q != NULL) { - stop_timeout = 1; - if (cvc_timeout_id != (timeout_id_t)-1) { - (void) untimeout(cvc_timeout_id); - cvc_timeout_id = (timeout_id_t)-1; - } - } - rw_exit(&cvclock); - break; - case CVC_BBSRAM_VIA_BBSRAM: /* console via bbsram */ - via_bbsram = 1; - /* start periodic flushing of ouput to BBSRAM */ - rw_enter(&cvclock, RW_WRITER); - if (cvc_timeout_id == (timeout_id_t)-1) { - stop_timeout = 0; - cvc_timeout_id = timeout(cvc_flush_buf, - NULL, drv_usectohz(TIMEOUT_DELAY)); - } - rw_exit(&cvclock); - break; - case CVC_BBSRAM_CLOSE_NET: - /* - * Send a hangup control message upstream to cvcd - * thru cvcredir. This is an attempt to close - * out any existing network connection(if any). - * cvcoutput_q should point to the cvcredir's read - * queue. - */ - rw_enter(&cvclock, RW_READER); - if (cvcoutput_q != NULL) { - (void) putnextctl(cvcoutput_q, M_HANGUP); - } - rw_exit(&cvclock); - break; - default: - cmn_err(CE_WARN, "cvc: unknown BBSRAM opcode %d\n", - (unsigned int)op); - break; - } - *op_reg = 0; -} - - -/* - * cvc_putc() - * Put a single character out to BBSRAM if space available. - */ -static void -cvc_putc(register int c) -{ - static int output_lost = 0; - - if (c == '\n') - cvc_putc('\r'); - - mutex_enter(&cvc_buf_mutex); - /* - * Just exit if the buffer is already full. - * It will be up to cvc_flush_buf() to flush the buffer. - */ - if (cvc_output_count == MAX_XFER_OUTPUT) { - output_lost = 1; - mutex_exit(&cvc_buf_mutex); - return; - } - if (output_lost) - prom_printf("WARNING: overflow of cvc output buffer, " - "output lost!"); - output_lost = 0; - cvc_output_buffer[cvc_output_count] = (unsigned char)c; - cvc_output_count++; - if ((cvc_output_count == MAX_XFER_OUTPUT) || (c == '\n')) { - /* flush cvc's internal output buffer to BBSRAM */ - - /* - * Wait for the BBSRAM output buffer to be emptied. - * This may hang if netcon_server isn't running on the SSP - */ - int maxspin = CVC_OUT_MAXSPIN; - while ((BBSRAM_OUTPUT_COUNT != 0) && --maxspin) { - if (stop_bbsram) { - mutex_exit(&cvc_buf_mutex); - return; - } - DELAY(1000); - } - bcopy((caddr_t)cvc_output_buffer, - (caddr_t)(BBSRAM_OUTPUT_BUF - cvc_output_count), - cvc_output_count); - - BBSRAM_OUTPUT_COUNT = cvc_output_count; - cvc_output_count = 0; - } - mutex_exit(&cvc_buf_mutex); -} - - -/* - * cvc_flush_buf() - * Flush cvc's internal output buffer to BBSRAM at regular intervals. - * This should only be done if cvcd is not running or the user (via the cvc - * application on the SSP) has requested that i/o go through BBSRAM. - */ -/* ARGSUSED */ -static void -cvc_flush_buf(void *notused) -{ - if (stop_timeout) - return; - - mutex_enter(&cvc_buf_mutex); - if (cvc_output_count != 0) { - /* - * Wait for the BBSRAM output buffer to be emptied. - * This may hang if netcon_server isn't running on the SSP. - */ - int maxspin = CVC_OUT_MAXSPIN; - while ((BBSRAM_OUTPUT_COUNT != 0) && --maxspin) { - if (stop_bbsram) - goto exit; - DELAY(1000); - } - - bcopy((caddr_t)cvc_output_buffer, - (caddr_t)BBSRAM_OUTPUT_BUF - cvc_output_count, - cvc_output_count); - - BBSRAM_OUTPUT_COUNT = cvc_output_count; - cvc_output_count = 0; - } -exit: - mutex_exit(&cvc_buf_mutex); - /* rw_enter(&cvclock, RW_WRITER); */ - cvc_timeout_id = timeout(cvc_flush_buf, NULL, - drv_usectohz(TIMEOUT_DELAY)); - /* rw_exit(&cvclock); */ -} - - -/* - * cvc_getstr() - * Poll BBSRAM for console input while available. - */ -static void -cvc_getstr(char *cp) -{ - short count; - volatile char *lp; - - mutex_enter(&cvc_bbsram_input_mutex); - /* Poll BBSRAM for input */ - do { - if (stop_bbsram) { - *cp = '\0'; /* set string to zero-length */ - mutex_exit(&cvc_bbsram_input_mutex); - return; - } - /* - * Use a smaller delay between checks of BBSRAM for input - * when cvcd/cvcredir are not running or "via_bbsram" has - * been set. - * We don't go away completely when i/o is going through the - * network via cvcd since a command may be sent via BBSRAM - * to switch if the network is down or hung. - */ - if ((cvcoutput_q == NULL) || (via_bbsram)) - delay(drv_usectohz(100000)); - else - delay(drv_usectohz(1000000)); - cvc_bbsram_ops(BBSRAM_CONTROL_REG); - count = BBSRAM_INPUT_COUNT; - } while (count == 0); - - lp = BBSRAM_INPUT_BUF - count; - - while (count--) { - *cp++ = *lp++; - } - *cp = '\0'; - - BBSRAM_INPUT_COUNT = 0; - mutex_exit(&cvc_bbsram_input_mutex); -} - - -/* - * cvc_input_daemon() - * this function runs as a separate kernel thread and polls BBSRAM for - * input, and possibly put it on read stream for the console. - * There are two poll rates (implemented in cvc_getstr): - * 100 000 uS (10 Hz) - no cvcd communications || via_bbsram - * 1000 000 uS ( 1 Hz) - cvcd communications - * This continues to run even if there are network console communications - * in order to handle out-of-band signaling. - */ -static void -cvc_input_daemon(void) -{ - char linebuf[MAX_XFER_INPUT]; - char *cp; - mblk_t *mbp; - int c; - int dropped_read = 0; - - for (;;) { - cvc_getstr(linebuf); - - mbp = allocb(strlen(linebuf), BPRI_MED); - if (mbp == NULL) { /* drop it & go on if no buffer */ - if (!dropped_read) { - cmn_err(CE_WARN, - "cvc_input_daemon: " - "dropping BBSRAM reads\n"); - } - dropped_read++; - continue; - } - if (dropped_read) { - cmn_err(CE_WARN, - "cvc_input_daemon: dropped %d BBSRAM reads\n", - dropped_read); - dropped_read = 0; - } - - for (cp = linebuf; *cp != '\0'; cp++) { - c = (int)*cp; - if (c == '\r') - c = '\n'; - c &= 0177; - *mbp->b_wptr = (char)c; - mbp->b_wptr++; - } - mutex_enter(&cvcmutex); - if (input_ok) { - if (cvcinput_q == NULL) { - cmn_err(CE_WARN, - "cvc_input_daemon: cvcinput_q is NULL!"); - } else { - putnext(cvcinput_q, mbp); - } - } else { - freemsg(mbp); - } - mutex_exit(&cvcmutex); - } - - /* NOTREACHED */ -} - - -/* - * cvc_bbsram_stop() - * Prevents accesses to BBSRAM. used by cvc_assign_iocpu() when - * mapping in BBSRAM to a virtual address. - */ -static void -cvc_bbsram_stop(void) -{ - stop_bbsram = 1; - mutex_enter(&cvc_bbsram_input_mutex); - mutex_enter(&cvc_buf_mutex); -} - - -/* - * cvc_bbsram_start() - * Allow accesses to BBSRAM, used by cvc_assign_iocpu() after - * BBSRAM has been mapped to a virtual address. - */ -static void -cvc_bbsram_start(void) -{ - stop_bbsram = 0; - mutex_exit(&cvc_buf_mutex); - mutex_exit(&cvc_bbsram_input_mutex); -} - - -/* - * cvc_assign_iocpu() - * Map in BBSRAM to a virtual address - * This called by the kernel with the cpu id of cpu zero. - */ -void -cvc_assign_iocpu(processorid_t newcpu) -{ - processorid_t oldcpu = cvc_iocpu; - - if (newcpu == oldcpu) - return; - - cvc_iobufp[newcpu] = cvc_iobuf_mapin(newcpu); - - cvc_bbsram_stop(); - - cvc_iocpu = newcpu; - - cvc_bbsram_start(); - - if (oldcpu != -1) - cvc_iobuf_mapout(oldcpu); -} - - -/* - * cvc_iobuf_mapin() - * Map in the cvc bbsram i/o buffer into kernel space. - */ -static caddr_t -cvc_iobuf_mapin(processorid_t cpu_id) -{ - caddr_t cvaddr; - uint64_t cvc_iobuf_physaddr; - pfn_t pfn; - uint_t num_pages; - extern cpu_sgnblk_t *cpu_sgnblkp[]; - - ASSERT(cpu_sgnblkp[cpu_id] != NULL); - - /* - * First construct the physical base address of the bbsram - * in Starfire PSI space associated with this cpu in question. - */ - cvc_iobuf_physaddr = STARFIRE_UPAID2UPS(cpu_id) | STARFIRE_PSI_BASE; - - /* - * Next add the cvc i/o buffer offset obtained from the - * sigblock to get cvc iobuf physical address - */ - cvc_iobuf_physaddr += cpu_sgnblkp[cpu_id]->sigb_cvc_off; - - /* Get the page frame number */ - pfn = (cvc_iobuf_physaddr >> MMU_PAGESHIFT); - - /* Calculate how many pages we need to map in */ - num_pages = mmu_btopr(((uint_t)(cvc_iobuf_physaddr - & MMU_PAGEOFFSET) + sizeof (sigb_cvc_t))); - - /* - * Map in the cvc iobuf - */ - cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP); - - hat_devload(kas.a_hat, cvaddr, mmu_ptob(num_pages), pfn, - PROT_READ | PROT_WRITE, HAT_LOAD_LOCK); - - return ((caddr_t)(cvaddr + (uint_t)(cvc_iobuf_physaddr - & MMU_PAGEOFFSET))); -} - - -/* - * cvc_iobuf_mapout() - * Map out the cvc iobuf from kernel space - */ -static void -cvc_iobuf_mapout(processorid_t cpu_id) -{ - caddr_t cvaddr; - size_t num_pages; - - if ((cvaddr = cvc_iobufp[cpu_id]) == 0) { - /* already unmapped - return */ - return; - } - - /* Calculate how many pages we need to map out */ - num_pages = mmu_btopr(((size_t)((uint64_t)cvaddr & MMU_PAGEOFFSET) + - sizeof (sigb_cvc_t))); - - /* Get cvaddr to the start of the page boundary */ - cvaddr = (caddr_t)(((uint64_t)cvaddr & MMU_PAGEMASK)); - - hat_unload(kas.a_hat, cvaddr, mmu_ptob(num_pages), HAT_UNLOAD_UNLOCK); - vmem_free(heap_arena, cvaddr, ptob(num_pages)); - - cvc_iobufp[cpu_id] = NULL; -} diff --git a/usr/src/uts/sun4u/starfire/cvc/cvc.conf b/usr/src/uts/sun4u/starfire/cvc/cvc.conf deleted file mode 100644 index 50abb823fe..0000000000 --- a/usr/src/uts/sun4u/starfire/cvc/cvc.conf +++ /dev/null @@ -1,28 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1996 by Sun Microsystems, Inc. -# All rights reserved. -# -name="cvc" parent="pseudo" instance=0; diff --git a/usr/src/uts/sun4u/starfire/cvcredir/Makefile b/usr/src/uts/sun4u/starfire/cvcredir/Makefile deleted file mode 100644 index 6725d33bef..0000000000 --- a/usr/src/uts/sun4u/starfire/cvcredir/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# Copyright (c) 2011 Bayard G. Bell. All rights reserved. -# -# This makefile drives the production of the cvcredir driver module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = cvcredir -OBJECTS = $(CVCREDIR_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(CVCREDIR_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/cvcredir - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# Define dependency on cvc -# -LDFLAGS += -dy -N drv/cvc - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c b/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c deleted file mode 100644 index 05e9784933..0000000000 --- a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2011 Bayard G. Bell. All rights reserved. - */ - - -/* - * MT STREAMS Virtual Console Redirection Device Driver - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/errno.h> -#include <sys/kmem.h> -#include <sys/stat.h> -#include <sys/stream.h> -#include <sys/stropts.h> -#include <sys/strsun.h> -#include <sys/debug.h> -#include <sys/thread.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/tty.h> -#include <sys/cvc.h> -#include <sys/conf.h> -#include <sys/modctl.h> - - -/* - * Routine to to register/unregister our queue for console output and pass - * redirected data to the console. The cvc driver will do a putnext using - * our queue, so we will not see the redirected console data. - */ -extern int cvc_redir(mblk_t *); -extern int cvc_register(queue_t *); -extern int cvc_unregister(queue_t *); - -static int cvcr_info(dev_info_t *, ddi_info_cmd_t, void *, void **); -static int cvcr_attach(dev_info_t *, ddi_attach_cmd_t); -static int cvcr_detach(dev_info_t *, ddi_detach_cmd_t); -static int cvcr_wput(queue_t *, mblk_t *); -static int cvcr_open(queue_t *, dev_t *, int, int, cred_t *); -static int cvcr_close(queue_t *, int, cred_t *); -static void cvcr_ioctl(queue_t *, mblk_t *); - -static dev_info_t *cvcr_dip; -static int cvcr_suspend = 0; - -static struct module_info minfo = { - 1314, /* mi_idnum Bad luck number +1 ;-) */ - "cvcredir", /* mi_idname */ - 0, /* mi_minpsz */ - INFPSZ, /* mi_maxpsz */ - 2048, /* mi_hiwat */ - 2048 /* mi_lowat */ -}; - -static struct qinit cvcr_rinit = { - NULL, /* qi_putp */ - NULL, /* qi_srvp */ - cvcr_open, /* qi_qopen */ - cvcr_close, /* qi_qclose */ - NULL, /* qi_qadmin */ - &minfo, /* qi_minfo */ - NULL /* qi_mstat */ -}; - -static struct qinit cvcr_winit = { - cvcr_wput, /* qi_putp */ - NULL, /* qi_srvp */ - cvcr_open, /* qi_qopen */ - cvcr_close, /* qi_qclose */ - NULL, /* qi_qadmin */ - &minfo, /* qi_minfo */ - NULL /* qi_mstat */ -}; - -struct streamtab cvcrinfo = { - &cvcr_rinit, /* st_rdinit */ - &cvcr_winit, /* st_wrinit */ - NULL, /* st_muxrinit */ - NULL /* st_muxwrinit */ -}; - -DDI_DEFINE_STREAM_OPS(cvcrops, nulldev, nulldev, cvcr_attach, - cvcr_detach, nodev, cvcr_info, (D_MTPERQ | D_MP), &cvcrinfo, - ddi_quiesce_not_supported); - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a pseudo driver */ - "CVC redirect driver 'cvcredir'", - &cvcrops, /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -static int -cvcr_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ -#ifdef lint - cvcr_suspend = cvcr_suspend; -#endif - if (cmd == DDI_RESUME) { - cvcr_suspend = 0; - } else { - if (ddi_create_minor_node(devi, "cvcredir", S_IFCHR, - 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { - ddi_remove_minor_node(devi, NULL); - return (-1); - } - cvcr_dip = devi; - } - return (DDI_SUCCESS); -} - -static int -cvcr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - if (cmd == DDI_SUSPEND) { - cvcr_suspend = 1; - } else { - if (cmd != DDI_DETACH) { - return (DDI_FAILURE); - } - ddi_remove_minor_node(dip, NULL); - } - return (DDI_SUCCESS); -} - -/* ARGSUSED */ -static int -cvcr_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - register int error; - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if (cvcr_dip == NULL) { - error = DDI_FAILURE; - } else { - *result = (void *)cvcr_dip; - error = DDI_SUCCESS; - } - break; - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)0; - error = DDI_SUCCESS; - break; - default: - error = DDI_FAILURE; - } - return (error); -} - -/* ARGSUSED */ -static int -cvcr_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred) -{ - WR(q)->q_ptr = q->q_ptr = (char *)2; - /* - * call into the cvc driver to register our queue. cvc will use - * our queue to send console output data upstream (our stream)to - * cvcd which has us open and is reading console data. - */ - if (cvc_register(RD(q)) == -1) { - cmn_err(CE_WARN, "cvcr_open: cvc_register failed for q = 0x%p", - (void *)q); - } - return (0); -} - -/* ARGSUSED */ -static int -cvcr_close(queue_t *q, int flag, cred_t *cred) -{ - /* - * call into the cvc driver to un-register our queue. cvc will - * no longer use our queue to send console output data upstream. - */ - (void) cvc_unregister(RD(q)); - WR(q)->q_ptr = q->q_ptr = NULL; - return (0); -} - -static int -cvcr_wput(queue_t *q, mblk_t *mp) -{ - /* - * Handle BREAK key for debugger and TIOCSWINSZ. - */ - if (mp->b_datap->db_type == M_IOCTL) { - cvcr_ioctl(q, mp); - return (0); - } - /* - * Call into the cvc driver to put console input data on - * its upstream queue to be picked up by the console driver. - */ - if (cvc_redir(mp) != 0) - freemsg(mp); - return (0); -} - -static void -cvcr_ioctl(queue_t *q, mblk_t *mp) -{ - struct iocblk *iocp = (struct iocblk *)mp->b_rptr; - int error; - - switch (iocp->ioc_cmd) { - case CVC_BREAK: - abort_sequence_enter(NULL); - miocack(q, mp, 0, 0); - break; - - case CVC_DISCONNECT: - case TIOCSWINSZ: - /* - * Generate a SIGHUP or SIGWINCH to the console. Note in this - * case cvc_redir does not free up mp, so we can reuse it for - * the ACK/NAK. - */ - error = cvc_redir(mp); - if (error != 0) - miocnak(q, mp, 0, error); - else - miocack(q, mp, 0, 0); - break; - - default: - miocnak(q, mp, 0, EINVAL); - break; - } -} diff --git a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf b/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf deleted file mode 100644 index 64ed7ee2a3..0000000000 --- a/usr/src/uts/sun4u/starfire/cvcredir/cvcredir.conf +++ /dev/null @@ -1,28 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1996 by Sun Microsystems, Inc. -# All rights reserved. -# -name="cvcredir" parent="pseudo" instance=0; diff --git a/usr/src/uts/sun4u/starfire/genassym/Makefile b/usr/src/uts/sun4u/starfire/genassym/Makefile deleted file mode 100644 index 1d2dd04248..0000000000 --- a/usr/src/uts/sun4u/starfire/genassym/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of assym.h through genconst/stabs. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -ASSYM_H = $(DSF_DIR)/$(OBJS_DIR)/assym.h -GENCONST = $(DSF_DIR)/$(OBJS_DIR)/genconst - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(ASSYM_H) - -# -# This is DSF_DIR. Use a short path. -# -DSF_DIR = . - -# -# Overrides -# -CLEANFILES = $(GENCONST) Nothing_to_remove -CLOBBERFILES = $(ASSYM_H) $(CLEANFILES) Nothing_to_remove - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -clean.lint: - -install: def - -# -# create assym.h -# -$(GENCONST): $(GENCONST_SRC) - $(NATIVECC) -w $(ALWAYS_DEFS) $(GENCONST_DEFS) $(NATIVE_INC_PATH) \ - -o $(GENCONST) $(GENCONST_SRC) - -$(ASSYM_H): $(GENCONST) $(OFFSETS) $(PLATFORM_OFFSETS) - $(OFFSETS_CREATE) <$(OFFSETS) >$@ - $(OFFSETS_CREATE) <$(PLATFORM_OFFSETS) >>$@ - $(GENCONST) >>$@ - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/idn/Makefile b/usr/src/uts/sun4u/starfire/idn/Makefile deleted file mode 100644 index 3d7de4962e..0000000000 --- a/usr/src/uts/sun4u/starfire/idn/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the idn driver module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = idn -OBJECTS = $(IDN_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(IDN_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/io - -IDN_OFFSETS = $(UTSBASE)/sun4u/starfire/ml/idn_offsets.in -IDN_OFFSETS_H = $(OBJS_DIR)/idn_offsets.h - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -DIPV6 -CERRWARN += -_gcc=-Wno-unused-function -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized -CERRWARN += -_gcc=-Wno-type-limits - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -AS_INC_PATH += -I$(OBJS_DIR) - -$(IDN_DEPS:%=$(OBJS_DIR)/%): $(IDN_OFFSETS_H) - -$(IDN_OFFSETS_H): $(GENCONST) $(IDN_OFFSETS) - $(OFFSETS_CREATE) <$(IDN_OFFSETS) >$@ - $(GENCONST) >>$@ - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/io/drmach.c b/usr/src/uts/sun4u/starfire/io/drmach.c deleted file mode 100644 index dc51df3d6f..0000000000 --- a/usr/src/uts/sun4u/starfire/io/drmach.c +++ /dev/null @@ -1,3857 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2011 Bayard G. Bell. All rights reserved. - * Copyright (c) 2016 by Delphix. All rights reserved. - */ - -#include <sys/debug.h> -#include <sys/types.h> -#include <sys/varargs.h> -#include <sys/errno.h> -#include <sys/cred.h> -#include <sys/dditypes.h> -#include <sys/devops.h> -#include <sys/modctl.h> -#include <sys/poll.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/sunndi.h> -#include <sys/ndi_impldefs.h> -#include <sys/stat.h> -#include <sys/kmem.h> -#include <sys/vmem.h> -#include <sys/processor.h> -#include <sys/spitregs.h> -#include <sys/cpuvar.h> -#include <sys/cpupart.h> -#include <sys/mem_config.h> -#include <sys/ddi_impldefs.h> -#include <sys/systm.h> -#include <sys/machsystm.h> -#include <sys/autoconf.h> -#include <sys/cmn_err.h> -#include <sys/sysmacros.h> -#include <sys/x_call.h> -#include <sys/promif.h> -#include <sys/prom_plat.h> -#include <sys/membar.h> -#include <vm/seg_kmem.h> -#include <sys/mem_cage.h> -#include <sys/stack.h> -#include <sys/archsystm.h> -#include <vm/hat_sfmmu.h> -#include <sys/pte.h> -#include <sys/mmu.h> -#include <sys/cpu_module.h> -#include <sys/obpdefs.h> -#include <sys/note.h> - -#include <sys/starfire.h> /* plat_max_... decls */ -#include <sys/cvc.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/drmach.h> -#include <sys/dr_util.h> -#include <sys/pda.h> - -#include <sys/sysevent.h> -#include <sys/sysevent/dr.h> -#include <sys/sysevent/eventdefs.h> - - -extern void bcopy32_il(uint64_t, uint64_t); -extern void flush_ecache_il( - uint64_t physaddr, int size, int linesz); -extern uint_t ldphysio_il(uint64_t physaddr); -extern void stphysio_il(uint64_t physaddr, uint_t value); - -extern uint64_t mc_get_mem_alignment(void); -extern uint64_t mc_get_asr_addr(pnode_t); -extern uint64_t mc_get_idle_addr(pnode_t); -extern uint64_t mc_get_alignment_mask(pnode_t); -extern int mc_read_asr(pnode_t, uint_t *); -extern int mc_write_asr(pnode_t, uint_t); -extern uint64_t mc_asr_to_pa(uint_t); -extern uint_t mc_pa_to_asr(uint_t, uint64_t); - -extern int pc_madr_add(int, int, int, int); - -typedef struct { - struct drmach_node *node; - void *data; -} drmach_node_walk_args_t; - -typedef struct drmach_node { - void *here; - - pnode_t (*get_dnode)(struct drmach_node *node); - int (*walk)(struct drmach_node *node, void *data, - int (*cb)(drmach_node_walk_args_t *args)); -} drmach_node_t; - -typedef struct { - int min_index; - int max_index; - int arr_sz; - drmachid_t *arr; -} drmach_array_t; - -typedef struct { - void *isa; - - sbd_error_t *(*release)(drmachid_t); - sbd_error_t *(*status)(drmachid_t, drmach_status_t *); - - char name[MAXNAMELEN]; -} drmach_common_t; - -typedef struct { - drmach_common_t cm; - int bnum; - int assigned; - int powered; - int connect_cpuid; - int cond; - drmach_node_t *tree; - drmach_array_t *devices; -} drmach_board_t; - -typedef struct { - drmach_common_t cm; - drmach_board_t *bp; - int unum; - int busy; - int powered; - const char *type; - drmach_node_t *node; -} drmach_device_t; - -typedef struct { - int flags; - drmach_device_t *dp; - sbd_error_t *err; - dev_info_t *dip; -} drmach_config_args_t; - -typedef struct { - uint64_t idle_addr; - drmach_device_t *mem; -} drmach_mc_idle_script_t; - -typedef struct { - uint64_t masr_addr; - uint_t masr; - uint_t _filler; -} drmach_rename_script_t; - -typedef struct { - void (*run)(void *arg); - caddr_t data; - pda_handle_t *ph; - struct memlist *c_ml; - uint64_t s_copybasepa; - uint64_t t_copybasepa; - drmach_device_t *restless_mc; /* diagnostic output */ -} drmach_copy_rename_program_t; - -typedef enum { - DO_IDLE, - DO_UNIDLE, - DO_PAUSE, - DO_UNPAUSE -} drmach_iopc_op_t; - -typedef struct { - drmach_board_t *obj; - int ndevs; - void *a; - sbd_error_t *(*found)(void *a, const char *, int, drmachid_t); - sbd_error_t *err; -} drmach_board_cb_data_t; - -static caddr_t drmach_shutdown_va; - -static int drmach_initialized; -static drmach_array_t *drmach_boards; - -static int drmach_cpu_delay = 100; -static int drmach_cpu_ntries = 50000; - -volatile uchar_t *drmach_xt_mb; - -/* - * Do not change the drmach_shutdown_mbox structure without - * considering the drmach_shutdown_asm assembly language code. - */ -struct drmach_shutdown_mbox { - uint64_t estack; - uint64_t flushaddr; - int size; - int linesize; - uint64_t physaddr; -}; -struct drmach_shutdown_mbox *drmach_shutdown_asm_mbox; - -static int drmach_fini(void); -static sbd_error_t *drmach_device_new(drmach_node_t *, - drmach_board_t *, drmach_device_t **); -static sbd_error_t *drmach_cpu_new(drmach_device_t *); -static sbd_error_t *drmach_mem_new(drmach_device_t *); -static sbd_error_t *drmach_io_new(drmach_device_t *); -static sbd_error_t *drmach_board_release(drmachid_t); -static sbd_error_t *drmach_board_status(drmachid_t, drmach_status_t *); -static sbd_error_t *drmach_cpu_release(drmachid_t); -static sbd_error_t *drmach_cpu_status(drmachid_t, drmach_status_t *); -static sbd_error_t *drmach_io_release(drmachid_t); -static sbd_error_t *drmach_io_status(drmachid_t, drmach_status_t *); -static sbd_error_t *drmach_mem_release(drmachid_t); -static sbd_error_t *drmach_mem_status(drmachid_t, drmach_status_t *); - -extern struct cpu *SIGBCPU; - -#ifdef DEBUG - -#define DRMACH_PR if (drmach_debug) printf -int drmach_debug = 0; /* set to non-zero to enable debug messages */ -#else - -#define DRMACH_PR _NOTE(CONSTANTCONDITION) if (0) printf -#endif /* DEBUG */ - -#define DRMACH_OBJ(id) ((drmach_common_t *)id) - -#define DRMACH_IS_BOARD_ID(id) \ - ((id != 0) && \ - (DRMACH_OBJ(id)->isa == (void *)drmach_board_new)) - -#define DRMACH_IS_CPU_ID(id) \ - ((id != 0) && \ - (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new)) - -#define DRMACH_IS_MEM_ID(id) \ - ((id != 0) && \ - (DRMACH_OBJ(id)->isa == (void *)drmach_mem_new)) - -#define DRMACH_IS_IO_ID(id) \ - ((id != 0) && \ - (DRMACH_OBJ(id)->isa == (void *)drmach_io_new)) - -#define DRMACH_IS_DEVICE_ID(id) \ - ((id != 0) && \ - (DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \ - DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \ - DRMACH_OBJ(id)->isa == (void *)drmach_io_new)) - -#define DRMACH_IS_ID(id) \ - ((id != 0) && \ - (DRMACH_OBJ(id)->isa == (void *)drmach_board_new || \ - DRMACH_OBJ(id)->isa == (void *)drmach_cpu_new || \ - DRMACH_OBJ(id)->isa == (void *)drmach_mem_new || \ - DRMACH_OBJ(id)->isa == (void *)drmach_io_new)) - -#define DRMACH_CPUID2BNUM(cpuid) \ - ((cpuid) / MAX_CPU_UNITS_PER_BOARD) - -#define DRMACH_INTERNAL_ERROR() \ - drerr_new(1, ESTF_INTERNAL, drmach_ie_fmt, __LINE__) -static char *drmach_ie_fmt = "drmach.c %d"; - -static struct { - const char *name; - const char *type; - sbd_error_t *(*new)(drmach_device_t *); -} name2type[] = { - { "SUNW,UltraSPARC", DRMACH_DEVTYPE_CPU, drmach_cpu_new }, - { "mem-unit", DRMACH_DEVTYPE_MEM, drmach_mem_new }, - { "pci", DRMACH_DEVTYPE_PCI, drmach_io_new }, - { "sbus", DRMACH_DEVTYPE_SBUS, drmach_io_new }, -}; - -/* node types to cleanup when a board is unconfigured */ -#define MISC_COUNTER_TIMER_DEVNAME "counter-timer" -#define MISC_PERF_COUNTER_DEVNAME "perf-counter" - -/* utility */ -#define MBYTE (1048576ull) - -/* - * drmach autoconfiguration data structures and interfaces - */ - -extern struct mod_ops mod_miscops; - -static struct modlmisc modlmisc = { - &mod_miscops, - "Sun Enterprise 10000 DR" -}; - -static struct modlinkage modlinkage = { - MODREV_1, - (void *)&modlmisc, - NULL -}; - -static kmutex_t drmach_i_lock; - -int -_init(void) -{ - int err; - - /* check that we have the correct version of obp */ - if (prom_test("SUNW,UE10000,add-brd") != 0) { - - cmn_err(CE_WARN, "!OBP/SSP upgrade is required to enable " - "DR Functionality"); - - return (-1); - } - - mutex_init(&drmach_i_lock, NULL, MUTEX_DRIVER, NULL); - - drmach_xt_mb = (uchar_t *)vmem_alloc(static_alloc_arena, - NCPU * sizeof (uchar_t), VM_SLEEP); - drmach_shutdown_asm_mbox = (struct drmach_shutdown_mbox *) - vmem_alloc(static_alloc_arena, sizeof (struct drmach_shutdown_mbox), - VM_SLEEP); - - if ((err = mod_install(&modlinkage)) != 0) { - mutex_destroy(&drmach_i_lock); - vmem_free(static_alloc_arena, (void *)drmach_xt_mb, - NCPU * sizeof (uchar_t)); - vmem_free(static_alloc_arena, (void *)drmach_shutdown_asm_mbox, - sizeof (struct drmach_shutdown_mbox)); - } - - return (err); -} - -int -_fini(void) -{ - if (drmach_fini()) - return (DDI_FAILURE); - else - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -static pnode_t -drmach_node_obp_get_dnode(drmach_node_t *np) -{ - return ((pnode_t)(uintptr_t)np->here); -} - -static int -drmach_node_obp_walk(drmach_node_t *np, void *data, - int (*cb)(drmach_node_walk_args_t *args)) -{ - pnode_t nodeid; - int rv; - drmach_node_walk_args_t args; - - /* initialized args structure for callback */ - args.node = np; - args.data = data; - - nodeid = prom_childnode(prom_rootnode()); - - /* save our new position with in the tree */ - np->here = (void *)(uintptr_t)nodeid; - - rv = 0; - while (nodeid != OBP_NONODE) { - rv = (*cb)(&args); - if (rv) - break; - - nodeid = prom_nextnode(nodeid); - - /* save our new position with in the tree */ - np->here = (void *)(uintptr_t)nodeid; - } - - return (rv); -} - -static drmach_node_t * -drmach_node_new(void) -{ - drmach_node_t *np; - - np = kmem_zalloc(sizeof (drmach_node_t), KM_SLEEP); - - np->get_dnode = drmach_node_obp_get_dnode; - np->walk = drmach_node_obp_walk; - - return (np); -} - -static void -drmach_node_dispose(drmach_node_t *np) -{ - kmem_free(np, sizeof (*np)); -} - -static dev_info_t * -drmach_node_get_dip(drmach_node_t *np) -{ - pnode_t nodeid; - - nodeid = np->get_dnode(np); - if (nodeid == OBP_NONODE) - return (NULL); - else { - dev_info_t *dip; - - /* The root node doesn't have to be held */ - dip = e_ddi_nodeid_to_dip(nodeid); - if (dip) { - /* - * Branch rooted at dip is already held, so release - * hold acquired in e_ddi_nodeid_to_dip() - */ - ddi_release_devi(dip); - ASSERT(e_ddi_branch_held(dip)); - } - - return (dip); - } - /*NOTREACHED*/ -} - -static pnode_t -drmach_node_get_dnode(drmach_node_t *np) -{ - return (np->get_dnode(np)); -} - -static int -drmach_node_walk(drmach_node_t *np, void *param, - int (*cb)(drmach_node_walk_args_t *args)) -{ - return (np->walk(np, param, cb)); -} - -static int -drmach_node_get_prop(drmach_node_t *np, char *name, void *buf) -{ - pnode_t nodeid; - int rv; - - nodeid = np->get_dnode(np); - if (nodeid == OBP_NONODE) - rv = -1; - else if (prom_getproplen(nodeid, (caddr_t)name) < 0) - rv = -1; - else { - (void) prom_getprop(nodeid, (caddr_t)name, (caddr_t)buf); - rv = 0; - } - - return (rv); -} - -static int -drmach_node_get_proplen(drmach_node_t *np, char *name, int *len) -{ - pnode_t nodeid; - int rv; - - nodeid = np->get_dnode(np); - if (nodeid == OBP_NONODE) - rv = -1; - else { - *len = prom_getproplen(nodeid, (caddr_t)name); - rv = (*len < 0 ? -1 : 0); - } - - return (rv); -} - -static drmachid_t -drmach_node_dup(drmach_node_t *np) -{ - drmach_node_t *dup; - - dup = drmach_node_new(); - dup->here = np->here; - - return (dup); -} - -/* - * drmach_array provides convenient array construction, access, - * bounds checking and array destruction logic. - */ - -static drmach_array_t * -drmach_array_new(int min_index, int max_index) -{ - drmach_array_t *arr; - - arr = kmem_zalloc(sizeof (drmach_array_t), KM_SLEEP); - - arr->arr_sz = (max_index - min_index + 1) * sizeof (void *); - if (arr->arr_sz > 0) { - arr->min_index = min_index; - arr->max_index = max_index; - - arr->arr = kmem_zalloc(arr->arr_sz, KM_SLEEP); - return (arr); - } else { - kmem_free(arr, sizeof (*arr)); - return (0); - } -} - -static int -drmach_array_set(drmach_array_t *arr, int idx, drmachid_t val) -{ - if (idx < arr->min_index || idx > arr->max_index) - return (-1); - else { - arr->arr[idx - arr->min_index] = val; - return (0); - } - /*NOTREACHED*/ -} - -static int -drmach_array_get(drmach_array_t *arr, int idx, drmachid_t *val) -{ - if (idx < arr->min_index || idx > arr->max_index) - return (-1); - else { - *val = arr->arr[idx - arr->min_index]; - return (0); - } - /*NOTREACHED*/ -} - -static int -drmach_array_first(drmach_array_t *arr, int *idx, drmachid_t *val) -{ - int rv; - - *idx = arr->min_index; - while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL) - *idx += 1; - - return (rv); -} - -static int -drmach_array_next(drmach_array_t *arr, int *idx, drmachid_t *val) -{ - int rv; - - *idx += 1; - while ((rv = drmach_array_get(arr, *idx, val)) == 0 && *val == NULL) - *idx += 1; - - return (rv); -} - -static void -drmach_array_dispose(drmach_array_t *arr, void (*disposer)(drmachid_t)) -{ - drmachid_t val; - int idx; - int rv; - - rv = drmach_array_first(arr, &idx, &val); - while (rv == 0) { - (*disposer)(val); - rv = drmach_array_next(arr, &idx, &val); - } - - kmem_free(arr->arr, arr->arr_sz); - kmem_free(arr, sizeof (*arr)); -} - -/*ARGSUSED*/ -static int -drmach_prom_select(pnode_t nodeid, void *arg, uint_t flags) -{ - int rprop[64]; - pnode_t saved; - drmach_config_args_t *ap = (drmach_config_args_t *)arg; - drmach_device_t *dp = ap->dp; - sbd_error_t *err; - - saved = drmach_node_get_dnode(dp->node); - - if (nodeid != saved) - return (DDI_FAILURE); - - if (saved == OBP_NONODE) { - err = DRMACH_INTERNAL_ERROR(); - DRERR_SET_C(&ap->err, &err); - return (DDI_FAILURE); - } - - if (prom_getprop(nodeid, OBP_REG, (caddr_t)rprop) <= 0) { - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -static void -drmach_branch_callback(dev_info_t *rdip, void *arg, uint_t flags) -{ - drmach_config_args_t *ap = (drmach_config_args_t *)arg; - - ASSERT(ap->dip == NULL); - - ap->dip = rdip; -} - -sbd_error_t * -drmach_configure(drmachid_t id, int flags) -{ - drmach_device_t *dp; - sbd_error_t *err; - drmach_config_args_t ca; - devi_branch_t b = {0}; - dev_info_t *fdip = NULL; - - if (!DRMACH_IS_DEVICE_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - ca.dp = dp; - ca.flags = flags; - ca.err = NULL; /* will be set if error detected */ - ca.dip = NULL; - - b.arg = &ca; - b.type = DEVI_BRANCH_PROM; - b.create.prom_branch_select = drmach_prom_select; - b.devi_branch_callback = drmach_branch_callback; - - if (e_ddi_branch_create(ddi_root_node(), &b, &fdip, - DEVI_BRANCH_CHILD | DEVI_BRANCH_CONFIGURE) != 0) { - char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP); - - /* - * If non-NULL, fdip is returned held and must be released. - */ - if (fdip != NULL) { - (void) ddi_pathname(fdip, path); - ddi_release_devi(fdip); - } else if (ca.dip != NULL) { - /* safe to call ddi_pathname as dip already held */ - (void) ddi_pathname(ca.dip, path); - } else { - (void) strcpy(path, "<none>"); - } - - err = drerr_new(1, ESTF_DRVFAIL, path); - DRERR_SET_C(&ca.err, &err); - kmem_free(path, MAXPATHLEN); - } - - return (ca.err); -} - -static sbd_error_t * -drmach_device_new(drmach_node_t *node, - drmach_board_t *bp, drmach_device_t **dpp) -{ - int i; - int rv; - drmach_device_t *dp; - sbd_error_t *err; - char name[OBP_MAXDRVNAME]; - - rv = drmach_node_get_prop(node, OBP_NAME, name); - if (rv) { - /* every node is expected to have a name */ - err = drerr_new(1, ESTF_GETPROP, - "PROM Node 0x%x: property %s", - (uint_t)node->get_dnode(node), OBP_NAME); - - return (err); - } - - /* - * The node currently being examined is not listed in the name2type[] - * array. In this case, the node is no interest to drmach. Both - * dp and err are initialized here to yield nothing (no device or - * error structure) for this case. - */ - for (i = 0; i < sizeof (name2type) / sizeof (name2type[0]); i++) - if (strcmp(name2type[i].name, name) == 0) - break; - - if (i < sizeof (name2type) / sizeof (name2type[0])) { - dp = kmem_zalloc(sizeof (drmach_device_t), KM_SLEEP); - - dp->bp = bp; - dp->unum = -1; - dp->node = drmach_node_dup(node); - dp->type = name2type[i].type; - - err = (name2type[i].new)(dp); - if (err) { - drmach_node_dispose(node); - kmem_free(dp, sizeof (*dp)); - dp = NULL; - } - - *dpp = dp; - return (err); - } - - /* - * The node currently being examined is not listed in the name2type[] - * array. In this case, the node is no interest to drmach. Both - * dp and err are initialized here to yield nothing (no device or - * error structure) for this case. - */ - *dpp = NULL; - return (NULL); -} - -static void -drmach_device_dispose(drmachid_t id) -{ - drmach_device_t *self = id; - - if (self->node) - drmach_node_dispose(self->node); - - kmem_free(self, sizeof (*self)); -} - -static sbd_error_t * -drmach_device_get_prop(drmach_device_t *dp, char *name, void *buf) -{ - sbd_error_t *err = NULL; - int rv; - - rv = drmach_node_get_prop(dp->node, name, buf); - if (rv) { - err = drerr_new(1, ESTF_GETPROP, - "%s::%s: property %s", - dp->bp->cm.name, dp->cm.name, name); - } - - return (err); -} - -static sbd_error_t * -drmach_device_get_proplen(drmach_device_t *dp, char *name, int *len) -{ - sbd_error_t *err = NULL; - int rv; - - rv = drmach_node_get_proplen(dp->node, name, len); - if (rv) { - err = drerr_new(1, ESTF_GETPROPLEN, - "%s::%s: property %s", - dp->bp->cm.name, dp->cm.name, name); - } - - return (err); -} - -static drmach_board_t * -drmach_board_new(int bnum) -{ - drmach_board_t *bp; - - bp = kmem_zalloc(sizeof (drmach_board_t), KM_SLEEP); - - bp->cm.isa = (void *)drmach_board_new; - bp->cm.release = drmach_board_release; - bp->cm.status = drmach_board_status; - - (void) drmach_board_name(bnum, bp->cm.name, sizeof (bp->cm.name)); - - bp->bnum = bnum; - bp->devices = NULL; - bp->connect_cpuid = -1; - bp->tree = drmach_node_new(); - bp->assigned = !drmach_initialized; - bp->powered = !drmach_initialized; - - (void) drmach_array_set(drmach_boards, bnum, bp); - return (bp); -} - -static void -drmach_board_dispose(drmachid_t id) -{ - drmach_board_t *bp; - - ASSERT(DRMACH_IS_BOARD_ID(id)); - bp = id; - - if (bp->tree) - drmach_node_dispose(bp->tree); - - if (bp->devices) - drmach_array_dispose(bp->devices, drmach_device_dispose); - - kmem_free(bp, sizeof (*bp)); -} - -static sbd_error_t * -drmach_board_status(drmachid_t id, drmach_status_t *stat) -{ - sbd_error_t *err = NULL; - drmach_board_t *bp; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - bp = id; - - stat->assigned = bp->assigned; - stat->powered = bp->powered; - stat->busy = 0; /* assume not busy */ - stat->configured = 0; /* assume not configured */ - stat->empty = 0; - stat->cond = bp->cond = SBD_COND_OK; - (void) strncpy(stat->type, "System Brd", sizeof (stat->type)); - stat->info[0] = '\0'; - - if (bp->devices) { - int rv; - int d_idx; - drmachid_t d_id; - - rv = drmach_array_first(bp->devices, &d_idx, &d_id); - while (rv == 0) { - drmach_status_t d_stat; - - err = drmach_status(d_id, &d_stat); - if (err) - break; - - stat->busy |= d_stat.busy; - stat->configured |= d_stat.configured; - - rv = drmach_array_next(bp->devices, &d_idx, &d_id); - } - } - - return (err); -} - -/* a simple routine to reduce redundancy of this common logic */ -static pda_handle_t -drmach_pda_open(void) -{ - pda_handle_t ph; - - ph = pda_open(); - if (ph == NULL) { - /* catch in debug kernels */ - ASSERT(0); - cmn_err(CE_WARN, "pda_open failed"); - } - - return (ph); -} - -#ifdef DEBUG -int drmach_init_break = 0; -#endif - -static int -hold_rele_branch(dev_info_t *rdip, void *arg) -{ - int i; - int *holdp = (int *)arg; - char *name = ddi_node_name(rdip); - - /* - * For Starfire, we must be children of the root devinfo node - */ - ASSERT(ddi_get_parent(rdip) == ddi_root_node()); - - for (i = 0; i < sizeof (name2type) / sizeof (name2type[0]); i++) - if (strcmp(name2type[i].name, name) == 0) - break; - - if (i == sizeof (name2type) / sizeof (name2type[0])) { - /* Not of interest to us */ - return (DDI_WALK_PRUNECHILD); - } - - if (*holdp) { - ASSERT(!e_ddi_branch_held(rdip)); - e_ddi_branch_hold(rdip); - } else { - ASSERT(e_ddi_branch_held(rdip)); - e_ddi_branch_rele(rdip); - } - - return (DDI_WALK_PRUNECHILD); -} - -static int -drmach_init(void) -{ - pnode_t nodeid; - dev_info_t *rdip; - int hold, circ; - -#ifdef DEBUG - if (drmach_init_break) - debug_enter("drmach_init: drmach_init_break set\n"); -#endif - mutex_enter(&drmach_i_lock); - if (drmach_initialized) { - mutex_exit(&drmach_i_lock); - return (0); - } - - drmach_boards = drmach_array_new(0, MAX_BOARDS - 1); - - nodeid = prom_childnode(prom_rootnode()); - do { - int bnum; - drmachid_t id; - - bnum = -1; - (void) prom_getprop(nodeid, OBP_BOARDNUM, (caddr_t)&bnum); - if (bnum == -1) - continue; - - if (drmach_array_get(drmach_boards, bnum, &id) == -1) { - cmn_err(CE_WARN, "OBP node 0x%x has" - " invalid property value, %s=%d", - nodeid, OBP_BOARDNUM, bnum); - - /* clean up */ - drmach_array_dispose( - drmach_boards, drmach_board_dispose); - - mutex_exit(&drmach_i_lock); - return (-1); - } else if (id == NULL) - (void) drmach_board_new(bnum); - } while ((nodeid = prom_nextnode(nodeid)) != OBP_NONODE); - - drmach_shutdown_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); - - /* - * Walk immediate children of devinfo root node and hold - * all devinfo branches of interest. - */ - hold = 1; - rdip = ddi_root_node(); - - ndi_devi_enter(rdip, &circ); - ddi_walk_devs(ddi_get_child(rdip), hold_rele_branch, &hold); - ndi_devi_exit(rdip, circ); - - drmach_initialized = 1; - - mutex_exit(&drmach_i_lock); - - return (0); -} - -static int -drmach_fini(void) -{ - dev_info_t *rdip; - int hold, circ; - - if (drmach_initialized) { - int busy = 0; - int rv; - int idx; - drmachid_t id; - - ASSERT(drmach_boards != NULL); - - rv = drmach_array_first(drmach_boards, &idx, &id); - while (rv == 0) { - sbd_error_t *err; - drmach_status_t stat; - - err = drmach_board_status(id, &stat); - if (err) { - /* catch in debug kernels */ - ASSERT(0); - sbd_err_clear(&err); - busy = 1; - } else - busy |= stat.busy; - - rv = drmach_array_next(drmach_boards, &idx, &id); - } - - if (busy) - return (-1); - - drmach_array_dispose(drmach_boards, drmach_board_dispose); - drmach_boards = NULL; - - vmem_free(heap_arena, drmach_shutdown_va, PAGESIZE); - - /* - * Walk immediate children of the root devinfo node - * releasing holds acquired on branches in drmach_init() - */ - hold = 0; - rdip = ddi_root_node(); - - ndi_devi_enter(rdip, &circ); - ddi_walk_devs(ddi_get_child(rdip), hold_rele_branch, &hold); - ndi_devi_exit(rdip, circ); - - mutex_destroy(&drmach_i_lock); - - drmach_initialized = 0; - } - if (drmach_xt_mb != NULL) { - vmem_free(static_alloc_arena, (void *)drmach_xt_mb, - NCPU * sizeof (uchar_t)); - } - if (drmach_shutdown_asm_mbox != NULL) { - vmem_free(static_alloc_arena, (void *)drmach_shutdown_asm_mbox, - sizeof (struct drmach_shutdown_mbox)); - } - return (0); -} - -static sbd_error_t * -drmach_get_mc_asr_addr(drmachid_t id, uint64_t *pa) -{ - drmach_device_t *dp; - pnode_t nodeid; - uint64_t addr; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - nodeid = drmach_node_get_dnode(dp->node); - if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) - return (DRMACH_INTERNAL_ERROR()); - - addr = mc_get_asr_addr(nodeid); - if (addr == (uint64_t)-1) - return (DRMACH_INTERNAL_ERROR()); - - *pa = addr; - return (NULL); -} - -static sbd_error_t * -drmach_get_mc_idle_addr(drmachid_t id, uint64_t *pa) -{ - drmach_device_t *dp; - pnode_t nodeid; - uint64_t addr; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - nodeid = drmach_node_get_dnode(dp->node); - if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) - return (DRMACH_INTERNAL_ERROR()); - - addr = mc_get_idle_addr(nodeid); - if (addr == (uint64_t)-1) - return (DRMACH_INTERNAL_ERROR()); - - *pa = addr; - return (NULL); -} - -static sbd_error_t * -drmach_read_mc_asr(drmachid_t id, uint_t *mcregp) -{ - drmach_device_t *dp; - pnode_t nodeid; - sbd_error_t *err; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - nodeid = drmach_node_get_dnode(dp->node); - if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) - err = DRMACH_INTERNAL_ERROR(); - else if (mc_read_asr(nodeid, mcregp) == -1) - err = DRMACH_INTERNAL_ERROR(); - else - err = NULL; - - return (err); -} - -static sbd_error_t * -drmach_write_mc_asr(drmachid_t id, uint_t mcreg) -{ - drmach_device_t *dp; - pnode_t nodeid; - sbd_error_t *err; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - nodeid = drmach_node_get_dnode(dp->node); - if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) - err = DRMACH_INTERNAL_ERROR(); - else if (mc_write_asr(nodeid, mcreg) == -1) - err = DRMACH_INTERNAL_ERROR(); - else - err = NULL; - - return (err); -} - -static sbd_error_t * -drmach_prep_rename_script(drmach_device_t *s_mem, drmach_device_t *t_mem, - uint64_t t_slice_offset, caddr_t buf, int buflen) -{ - int i, b, m; - drmach_mc_idle_script_t *isp; - drmach_rename_script_t *rsp; - int s_bd, t_bd; - uint_t s_masr, t_masr; - uint64_t s_new_basepa, t_new_basepa; - int b_idx, rv; - sbd_error_t *err; - drmachid_t b_id; - drmach_board_t *brd; - -#ifdef DEBUG - /* - * Starfire CPU/MEM/IO boards have only one MC per board. - * This function has been coded with that fact in mind. - */ - ASSERT(MAX_MEM_UNITS_PER_BOARD == 1); - - /* - * calculate the maximum space that could be consumed, - * then verify the available buffer space is adequate. - */ - m = sizeof (drmach_mc_idle_script_t *) * 2; /* two MCs */ - b = sizeof (drmach_rename_script_t *) * 3 * MAX_CPU_UNITS_PER_BOARD; - b += sizeof (drmach_rename_script_t *) * 3 * MAX_IO_UNITS_PER_BOARD; - b *= MAX_BOARDS; - b += sizeof (drmach_rename_script_t *) * 3; - b += sizeof (drmach_rename_script_t *) * 1; - ASSERT(m + b < buflen); -#endif - - /* - * construct an array of MC idle register addresses of - * both MCs. The array is zero terminated -- as expected - * by drmach_copy_rename_prog__relocatable(). - */ - isp = (drmach_mc_idle_script_t *)buf; - - /* source mc */ - err = drmach_get_mc_idle_addr(s_mem, &isp->idle_addr); - if (err) - return (err); - isp->mem = s_mem; - isp += 1; - - /* target mc */ - err = drmach_get_mc_idle_addr(t_mem, &isp->idle_addr); - if (err) - return (err); - isp->mem = t_mem; - isp += 1; - - /* terminator */ - isp->idle_addr = 0; - isp->mem = NULL; - isp += 1; - - /* fetch source mc asr register value */ - err = drmach_read_mc_asr(s_mem, &s_masr); - if (err) - return (err); - else if (s_masr & STARFIRE_MC_INTERLEAVE_MASK) { - return (drerr_new(1, ESTF_INTERBOARD, "%s::%s", - s_mem->bp->cm.name, s_mem->cm.name)); - } - - /* fetch target mc asr register value */ - err = drmach_read_mc_asr(t_mem, &t_masr); - if (err) - return (err); - else if (t_masr & STARFIRE_MC_INTERLEAVE_MASK) { - return (drerr_new(1, ESTF_INTERBOARD, "%s::%s", - t_mem->bp->cm.name, t_mem->cm.name)); - } - - /* get new source base pa from target's masr */ - s_new_basepa = mc_asr_to_pa(t_masr); - - /* - * remove any existing slice offset to realign - * memory with board's slice boundary - */ - s_new_basepa &= ~ (mc_get_mem_alignment() - 1); - - /* get new target base pa from source's masr */ - t_new_basepa = mc_asr_to_pa(s_masr); - - /* remove any existing slice offset, then apply new offset */ - t_new_basepa &= ~ (mc_get_mem_alignment() - 1); - t_new_basepa += t_slice_offset; - - /* encode new base pa into s_masr. turn off mem present bit */ - s_masr = mc_pa_to_asr(s_masr, s_new_basepa); - s_masr &= ~STARFIRE_MC_MEM_PRESENT_MASK; - - /* encode new base pa into t_masr. turn on mem present bit */ - t_masr = mc_pa_to_asr(t_masr, t_new_basepa); - t_masr |= STARFIRE_MC_MEM_PRESENT_MASK; - - /* - * Step 0: Mark source memory as not present. - */ - m = 0; - rsp = (drmach_rename_script_t *)isp; - err = drmach_get_mc_asr_addr(s_mem, &rsp[m].masr_addr); - if (err) - return (err); - rsp[m].masr = s_masr; - m++; - - /* - * Step 1: Write source base address to target MC - * with present bit off. - */ - err = drmach_get_mc_asr_addr(t_mem, &rsp[m].masr_addr); - if (err) - return (err); - rsp[m].masr = t_masr & ~STARFIRE_MC_MEM_PRESENT_MASK; - m++; - - /* - * Step 2: Now rewrite target reg with present bit on. - */ - rsp[m].masr_addr = rsp[m-1].masr_addr; - rsp[m].masr = t_masr; - m++; - - s_bd = s_mem->bp->bnum; - t_bd = t_mem->bp->bnum; - - DRMACH_PR("preparing script for CPU and IO units:\n"); - - rv = drmach_array_first(drmach_boards, &b_idx, &b_id); - if (rv) { - /* catch this in debug kernels */ - ASSERT(0); - return (DRMACH_INTERNAL_ERROR()); - } - - do { - int d_idx; - drmachid_t d_id; - drmach_device_t *device; - - ASSERT(DRMACH_IS_BOARD_ID(b_id)); - brd = b_id; - b = brd->bnum; - - /* - * Step 3: Update PC MADR tables for CPUs. - */ - if (brd->devices == NULL) { - /* devices not initialized */ - continue; - } - - rv = drmach_array_first(brd->devices, &d_idx, &d_id); - if (rv) { - /* must mean no devices on this board */ - break; - } - - DRMACH_PR("\t%s\n", brd->cm.name); - - do { - ASSERT(DRMACH_IS_DEVICE_ID(d_id)); - - if (!DRMACH_IS_CPU_ID(d_id)) - continue; - - device = d_id; - i = device->unum; - - DRMACH_PR("\t\t%s\n", device->cm.name); - - /* - * Disabled detaching mem node. - */ - rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, s_bd, i); - rsp[m].masr = s_masr; - m++; - /* - * Always write masr with present bit - * off and then again with it on. - */ - rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, t_bd, i); - rsp[m].masr = t_masr & ~STARFIRE_MC_MEM_PRESENT_MASK; - m++; - rsp[m].masr_addr = rsp[m-1].masr_addr; - rsp[m].masr = t_masr; - m++; - - } while (drmach_array_next(brd->devices, &d_idx, &d_id) == 0); - - /* - * Step 4: Update PC MADR tables for IOs. - */ - rv = drmach_array_first(brd->devices, &d_idx, &d_id); - /* this worked for previous loop, must work here too */ - ASSERT(rv == 0); - - do { - ASSERT(DRMACH_IS_DEVICE_ID(d_id)); - - if (!DRMACH_IS_IO_ID(d_id)) - continue; - - device = d_id; - i = device->unum; - - DRMACH_PR("\t\t%s\n", device->cm.name); - - /* - * Disabled detaching mem node. - */ - rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, s_bd, i+4); - rsp[m].masr = s_masr; - m++; - /* - * Always write masr with present bit - * off and then again with it on. - */ - rsp[m].masr_addr = STARFIRE_PC_MADR_ADDR(b, t_bd, i+4); - rsp[m].masr = t_masr & ~STARFIRE_MC_MEM_PRESENT_MASK; - m++; - rsp[m].masr_addr = rsp[m-1].masr_addr; - rsp[m].masr = t_masr; - m++; - - } while (drmach_array_next(brd->devices, &d_idx, &d_id) == 0); - } while (drmach_array_next(drmach_boards, &b_idx, &b_id) == 0); - - /* - * Zero masr_addr value indicates the END. - */ - rsp[m].masr_addr = 0ull; - rsp[m].masr = 0; - DRMACH_PR("number of steps in rename script = %d\n", m); - m++; - - /* paranoia */ - ASSERT((caddr_t)&rsp[m] <= buf + buflen); - -#ifdef DEBUG - { - int j; - - DRMACH_PR("mc idle register address list:"); - isp = (drmach_mc_idle_script_t *)buf; - DRMACH_PR("source mc idle addr 0x%lx, mem id %p", - isp[0].idle_addr, (void *)isp[0].mem); - DRMACH_PR("target mc idle addr 0x%lx, mem id %p", - isp[1].idle_addr, (void *)isp[1].mem); - ASSERT(isp[2].idle_addr == 0); - - DRMACH_PR("copy-rename script:"); - for (j = 0; j < m; j++) { - DRMACH_PR("0x%lx = 0x%08x", - rsp[j].masr_addr, rsp[j].masr); - } - - DELAY(1000000); - } -#endif - - /* return number of bytes consumed */ - b = (caddr_t)&rsp[m] - buf; - DRMACH_PR("total number of bytes consumed is %d\n", b); - ASSERT(b <= buflen); - -#ifdef lint - buflen = buflen; -#endif - - return (NULL); -} - -/* - * The routine performs the necessary memory COPY and MC adr SWITCH. - * Both operations MUST be at the same "level" so that the stack is - * maintained correctly between the copy and switch. The switch - * portion implements a caching mechanism to guarantee the code text - * is cached prior to execution. This is to guard against possible - * memory access while the MC adr's are being modified. - * - * IMPORTANT: The _drmach_copy_rename_end() function must immediately - * follow drmach_copy_rename_prog__relocatable() so that the correct - * "length" of the drmach_copy_rename_prog__relocatable can be - * calculated. This routine MUST be a LEAF function, i.e. it can - * make NO function calls, primarily for two reasons: - * - * 1. We must keep the stack consistent across the "switch". - * 2. Function calls are compiled to relative offsets, and - * we execute this function we'll be executing it from - * a copied version in a different area of memory, thus - * the relative offsets will be bogus. - * - * Moreover, it must have the "__relocatable" suffix to inform DTrace - * providers (and anything else, for that matter) that this - * function's text is manually relocated elsewhere before it is - * executed. That is, it cannot be safely instrumented with any - * methodology that is PC-relative. - */ -static void -drmach_copy_rename_prog__relocatable(drmach_copy_rename_program_t *prog) -{ - extern void drmach_exec_script_il(drmach_rename_script_t *rsp); - - drmach_mc_idle_script_t *isp; - struct memlist *ml; - int csize; - int lnsize; - uint64_t caddr; - - isp = (drmach_mc_idle_script_t *)prog->data; - - caddr = ecache_flushaddr; - csize = (cpunodes[CPU->cpu_id].ecache_size << 1); - lnsize = cpunodes[CPU->cpu_id].ecache_linesize; - - /* - * DO COPY. - */ - for (ml = prog->c_ml; ml; ml = ml->ml_next) { - uint64_t s_pa, t_pa; - uint64_t nbytes; - - s_pa = prog->s_copybasepa + ml->ml_address; - t_pa = prog->t_copybasepa + ml->ml_address; - nbytes = ml->ml_size; - - while (nbytes != 0ull) { - /* - * This copy does NOT use an ASI - * that avoids the Ecache, therefore - * the dst_pa addresses may remain - * in our Ecache after the dst_pa - * has been removed from the system. - * A subsequent write-back to memory - * will cause an ARB-stop because the - * physical address no longer exists - * in the system. Therefore we must - * flush out local Ecache after we - * finish the copy. - */ - - /* copy 32 bytes at src_pa to dst_pa */ - bcopy32_il(s_pa, t_pa); - - /* increment by 32 bytes */ - s_pa += (4 * sizeof (uint64_t)); - t_pa += (4 * sizeof (uint64_t)); - - /* decrement by 32 bytes */ - nbytes -= (4 * sizeof (uint64_t)); - } - } - - /* - * Since bcopy32_il() does NOT use an ASI to bypass - * the Ecache, we need to flush our Ecache after - * the copy is complete. - */ - flush_ecache_il(caddr, csize, lnsize); /* inline version */ - - /* - * Wait for MCs to go idle. - */ - do { - register int t = 10; - register uint_t v; - - /* loop t cycles waiting for each mc to indicate it's idle */ - do { - v = ldphysio_il(isp->idle_addr) - & STARFIRE_MC_IDLE_MASK; - - } while (v != STARFIRE_MC_IDLE_MASK && t-- > 0); - - /* bailout if timedout */ - if (t <= 0) { - prog->restless_mc = isp->mem; - return; - } - - isp += 1; - - /* stop if terminating zero has been reached */ - } while (isp->idle_addr != 0); - - /* advance passed terminating zero */ - isp += 1; - - /* - * The following inline assembly routine caches - * the rename script and then caches the code that - * will do the rename. This is necessary - * so that we don't have any memory references during - * the reprogramming. We accomplish this by first - * jumping through the code to guarantee it's cached - * before we actually execute it. - */ - drmach_exec_script_il((drmach_rename_script_t *)isp); -} - -static void -drmach_copy_rename_end(void) -{ - /* - * IMPORTANT: This function's location MUST be located immediately - * following drmach_copy_rename_prog__relocatable to - * accurately estimate its size. Note that this assumes - * the compiler keeps these functions in the order in - * which they appear :-o - */ -} - -sbd_error_t * -drmach_copy_rename_init(drmachid_t t_id, uint64_t t_slice_offset, - drmachid_t s_id, struct memlist *c_ml, drmachid_t *pgm_id) -{ - drmach_device_t *s_mem; - drmach_device_t *t_mem; - struct memlist *x_ml; - uint64_t off_mask, s_copybasepa, t_copybasepa, t_basepa; - int len; - caddr_t bp, wp; - pda_handle_t ph; - sbd_error_t *err; - drmach_copy_rename_program_t *prog; - - if (!DRMACH_IS_MEM_ID(s_id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - if (!DRMACH_IS_MEM_ID(t_id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - s_mem = s_id; - t_mem = t_id; - - /* get starting physical address of target memory */ - err = drmach_mem_get_base_physaddr(t_id, &t_basepa); - if (err) - return (err); - - /* calculate slice offset mask from slice size */ - off_mask = mc_get_mem_alignment() - 1; - - /* calculate source and target base pa */ - s_copybasepa = c_ml->ml_address; - t_copybasepa = - t_basepa + ((c_ml->ml_address & off_mask) - t_slice_offset); - - /* paranoia */ - ASSERT((c_ml->ml_address & off_mask) >= t_slice_offset); - - /* adjust copy memlist addresses to be relative to copy base pa */ - x_ml = c_ml; - while (x_ml != NULL) { - x_ml->ml_address -= s_copybasepa; - x_ml = x_ml->ml_next; - } - -#ifdef DEBUG - { - uint64_t s_basepa, s_size, t_size; - - x_ml = c_ml; - while (x_ml->ml_next != NULL) - x_ml = x_ml->ml_next; - - DRMACH_PR("source copy span: base pa 0x%lx, end pa 0x%lx\n", - s_copybasepa, - s_copybasepa + x_ml->ml_address + x_ml->ml_size); - - DRMACH_PR("target copy span: base pa 0x%lx, end pa 0x%lx\n", - t_copybasepa, - t_copybasepa + x_ml->ml_address + x_ml->ml_size); - - DRMACH_PR("copy memlist (relative to copy base pa):\n"); - MEMLIST_DUMP(c_ml); - - err = drmach_mem_get_base_physaddr(s_id, &s_basepa); - ASSERT(err == NULL); - - err = drmach_mem_get_size(s_id, &s_size); - ASSERT(err == NULL); - - err = drmach_mem_get_size(t_id, &t_size); - ASSERT(err == NULL); - - DRMACH_PR("current source base pa 0x%lx, size 0x%lx\n", - s_basepa, s_size); - DRMACH_PR("current target base pa 0x%lx, size 0x%lx\n", - t_basepa, t_size); - - ASSERT(s_copybasepa + x_ml->ml_address + x_ml->ml_size <= - s_basepa + s_size); - ASSERT(t_copybasepa + x_ml->ml_address + x_ml->ml_size <= - t_basepa + t_size); - } -#endif - - ph = drmach_pda_open(); - if (ph == NULL) - return (DRMACH_INTERNAL_ERROR()); - - /* - * bp will be page aligned, since we're calling - * kmem_zalloc() with an exact multiple of PAGESIZE. - */ - wp = bp = kmem_zalloc(PAGESIZE, KM_SLEEP); - - /* allocate space for copy rename struct */ - len = sizeof (drmach_copy_rename_program_t); - DRMACH_PR("prog = 0x%p, header len %d\n", (void *)wp, len); - prog = (drmach_copy_rename_program_t *)wp; - wp += (len + ecache_alignsize - 1) & ~ (ecache_alignsize - 1); - - /* - * Copy the code for the copy-rename routine into - * a page aligned piece of memory. We do this to guarantee - * that we're executing within the same page and thus reduce - * the possibility of cache collisions between different - * pages. - */ - len = (int)((ulong_t)drmach_copy_rename_end - - (ulong_t)drmach_copy_rename_prog__relocatable); - ASSERT(wp + len < bp + PAGESIZE); - bcopy((caddr_t)drmach_copy_rename_prog__relocatable, wp, len); - - DRMACH_PR("copy-rename function 0x%p, len %d\n", (void *)wp, len); - prog->run = (void (*)())wp; - wp += (len + ecache_alignsize - 1) & ~ (ecache_alignsize - 1); - - /* - * Prepare data page that will contain script of - * operations to perform during copy-rename. - * Allocate temporary buffer to hold script. - */ - err = drmach_prep_rename_script(s_mem, t_mem, t_slice_offset, - wp, PAGESIZE - (wp - bp)); - if (err) { - (void) drmach_copy_rename_fini(prog); - return (err); - } - - DRMACH_PR("copy-rename script 0x%p, len %d\n", (void *)wp, len); - prog->data = wp; - wp += (len + ecache_alignsize - 1) & ~ (ecache_alignsize - 1); - - prog->ph = ph; - prog->s_copybasepa = s_copybasepa; - prog->t_copybasepa = t_copybasepa; - prog->c_ml = c_ml; - *pgm_id = prog; - - return (NULL); -} - -sbd_error_t * -drmach_copy_rename_fini(drmachid_t id) -{ - drmach_copy_rename_program_t *prog = id; - sbd_error_t *err = NULL; - - if (prog->c_ml != NULL) - memlist_delete(prog->c_ml); - - if (prog->ph != NULL) - pda_close(prog->ph); - - if (prog->restless_mc != 0) { - cmn_err(CE_WARN, "MC did not idle; OBP Node 0x%x", - (uint_t)drmach_node_get_dnode(prog->restless_mc->node)); - - err = DRMACH_INTERNAL_ERROR(); - } - - kmem_free(prog, PAGESIZE); - - return (err); -} - -static sbd_error_t * -drmach_io_new(drmach_device_t *dp) -{ - sbd_error_t *err; - int portid; - - err = drmach_device_get_prop(dp, "upa-portid", &portid); - if (err == NULL) { - ASSERT(portid & 0x40); - dp->unum = portid & 1; - } - - dp->cm.isa = (void *)drmach_io_new; - dp->cm.release = drmach_io_release; - dp->cm.status = drmach_io_status; - - (void) snprintf(dp->cm.name, sizeof (dp->cm.name), "%s%d", dp->type, - dp->unum); - - return (err); -} - -static void -drmach_iopc_op(pda_handle_t ph, drmach_iopc_op_t op) -{ - register int b; - - for (b = 0; b < MAX_BOARDS; b++) { - int p; - ushort_t bda_ioc; - board_desc_t *bdesc; - - if (pda_board_present(ph, b) == 0) - continue; - - bdesc = (board_desc_t *)pda_get_board_info(ph, b); - /* - * Update PCs for IOCs. - */ - bda_ioc = bdesc->bda_ioc; - for (p = 0; p < MAX_IOCS; p++) { - u_longlong_t idle_addr; - uchar_t value; - - if (BDA_NBL(bda_ioc, p) != BDAN_GOOD) - continue; - - idle_addr = STARFIRE_BB_PC_ADDR(b, p, 1); - - switch (op) { - case DO_PAUSE: - value = STARFIRE_BB_PC_PAUSE(p); - break; - - case DO_IDLE: - value = STARFIRE_BB_PC_IDLE(p); - break; - - case DO_UNPAUSE: - value = ldbphysio(idle_addr); - value &= ~STARFIRE_BB_PC_PAUSE(p); - break; - - case DO_UNIDLE: - value = ldbphysio(idle_addr); - value &= ~STARFIRE_BB_PC_IDLE(p); - break; - - default: - cmn_err(CE_PANIC, - "drmach_iopc_op: unknown op (%d)", - (int)op); - /*NOTREACHED*/ - } - stbphysio(idle_addr, value); - } - } -} - -void -drmach_copy_rename(drmachid_t id) -{ - drmach_copy_rename_program_t *prog = id; - uint64_t neer; - - /* - * UPA IDLE - * Protocol = PAUSE -> IDLE -> UNPAUSE - * In reality since we only "idle" the IOPCs it's sufficient - * to just issue the IDLE operation since (in theory) all IOPCs - * in the field are PC6. However, we'll be robust and do the - * proper workaround protocol so that we never have to worry! - */ - drmach_iopc_op(prog->ph, DO_PAUSE); - drmach_iopc_op(prog->ph, DO_IDLE); - DELAY(100); - drmach_iopc_op(prog->ph, DO_UNPAUSE); - DELAY(100); - - /* disable CE reporting */ - neer = get_error_enable(); - set_error_enable(neer & ~EER_CEEN); - - /* run the copy/rename program */ - prog->run(prog); - - /* enable CE reporting */ - set_error_enable(neer); - - /* - * UPA UNIDLE - * Protocol = UNIDLE - */ - drmach_iopc_op(prog->ph, DO_UNIDLE); - DELAY(100); -} - -/* - * The counter-timer and perf-counter nodes are not being cleaned - * up after a board that was present at start of day is detached. - * If the board has become unconfigured with this operation, walk - * the prom tree and find all counter-timer and perf-counter nodes - * that have the same board number as the board that was just - * unconfigured and remove them. - */ -static sbd_error_t * -drmach_remove_counter_nodes(drmachid_t id) -{ - int num; - char name[OBP_MAXDRVNAME]; - pnode_t child; - dev_info_t *dip; - sbd_error_t *err; - drmach_status_t stat; - drmach_board_t *bp; - - if (!DRMACH_IS_BOARD_ID(id)) { - return (drerr_new(0, ESTF_INAPPROP, NULL)); - } - - if ((err = drmach_board_status(id, &stat)) != NULL) { - return (err); - } - - /* - * Only clean up the counter-timer and perf-counter - * nodes when the entire board is unconfigured. - */ - if (stat.configured) { - return (NULL); - } - - bp = (drmach_board_t *)id; - - err = NULL; - - for (child = prom_childnode(prom_rootnode()); child != OBP_NONODE; - child = prom_nextnode(child)) { - - if (prom_getprop(child, OBP_BOARDNUM, (caddr_t)&num) == -1) { - continue; - } - - if (bp->bnum != num) { - continue; - } - - if (prom_getprop(child, OBP_NAME, (caddr_t)name) == -1) { - continue; - } - - if (strncmp(name, MISC_COUNTER_TIMER_DEVNAME, OBP_MAXDRVNAME) && - strncmp(name, MISC_PERF_COUNTER_DEVNAME, OBP_MAXDRVNAME)) { - continue; - } - - /* Root node doesn't have to be held */ - dip = e_ddi_nodeid_to_dip(child); - - /* - * If the node is only in the OBP tree, then - * we don't have to remove it. - */ - if (dip) { - dev_info_t *fdip = NULL; - - DRMACH_PR("removing %s devinfo node\n", name); - - e_ddi_branch_hold(dip); - ddi_release_devi(dip); /* held in e_ddi_nodeid_to_dip */ - - if (e_ddi_branch_destroy(dip, &fdip, 0)) { - char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP); - - /* - * If non-NULL, fdip is held and must be - * released. - */ - if (fdip != NULL) { - (void) ddi_pathname(fdip, path); - ddi_release_devi(fdip); - } else { - (void) ddi_pathname(dip, path); - } - - err = drerr_new(1, ESTF_DRVFAIL, path); - kmem_free(path, MAXPATHLEN); - e_ddi_branch_rele(dip); - break; - } - } - } - - return (err); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_pre_op(int cmd, drmachid_t id, drmach_opts_t *opts) -{ - /* allow status and ncm operations to always succeed */ - if ((cmd == SBD_CMD_STATUS) || (cmd == SBD_CMD_GETNCM)) { - return (NULL); - } - - /* check all other commands for the required option string */ - if ((opts->size > 0) && (opts->copts != NULL)) { - - DRMACH_PR("platform options: %s\n", opts->copts); - - if (strstr(opts->copts, "xfdr") != NULL) { - return (NULL); - } - } - - return (drerr_new(0, ESTF_SUPPORT, NULL)); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_post_op(int cmd, drmachid_t id, drmach_opts_t *opts) -{ - sbd_error_t *err = NULL; - - switch (cmd) { - case SBD_CMD_UNCONFIGURE: - - err = drmach_remove_counter_nodes(id); - break; - - case SBD_CMD_CONFIGURE: - case SBD_CMD_DISCONNECT: - case SBD_CMD_CONNECT: - case SBD_CMD_GETNCM: - case SBD_CMD_STATUS: - break; - - default: - break; - } - - return (err); -} - -sbd_error_t * -drmach_board_assign(int bnum, drmachid_t *id) -{ - sbd_error_t *err; - - if (!drmach_initialized && drmach_init() == -1) { - err = DRMACH_INTERNAL_ERROR(); - } else if (drmach_array_get(drmach_boards, bnum, id) == -1) { - err = drerr_new(1, ESTF_BNUM, "%d", bnum); - } else if (*id != NULL) { - err = NULL; - } else { - drmach_board_t *bp; - - *id = (drmachid_t)drmach_board_new(bnum); - bp = *id; - bp->assigned = 1; - err = NULL; - } - - return (err); -} - -static int -drmach_attach_board(void *arg) -{ - drmach_board_t *obj = (drmach_board_t *)arg; - cpuset_t cset; - int retval; - - /* - * OBP disables traps during the board probe. - * So, in order to prevent cross-call/cross-trap timeouts, - * and thus panics, we effectively block anybody from - * issuing xc's/xt's by doing a promsafe_xc_attention. - * In the previous version of Starfire DR (2.6), a timeout - * suspension mechanism was implemented in the send-mondo - * assembly. That mechanism is unnecessary with the - * existence of xc_attention/xc_dismissed. - */ - cset = cpu_ready_set; - promsafe_xc_attention(cset); - - retval = prom_starfire_add_brd(obj->connect_cpuid); - - xc_dismissed(cset); - - return (retval); -} - -sbd_error_t * -drmach_board_connect(drmachid_t id, drmach_opts_t *opts) -{ - drmach_board_t *obj = (drmach_board_t *)id; - int retval; - sbd_error_t *err; - char *cptr, *copts; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - - if (opts->size > 0) - copts = opts->copts; - - if ((cptr = strstr(copts, "cpuid=")) != NULL) { - int cpuid; - - cptr += strlen("cpuid="); - cpuid = stoi(&cptr); - - if (DRMACH_CPUID2BNUM(cpuid) == obj->bnum) { - obj->connect_cpuid = cpuid; - obj->assigned = 1; - } else - return (drerr_new(1, ESTF_SETCPUVAL, "%d", cpuid)); - } else { - /* cpuid was not specified */ - obj->connect_cpuid = -1; - } - - if (obj->connect_cpuid == -1) { - err = drerr_new(1, ESTF_NOCPUID, obj->cm.name); - return (err); - } - - cmn_err(CE_CONT, "DRMACH: PROM attach %s CPU %d\n", - obj->cm.name, obj->connect_cpuid); - - retval = prom_tree_update(drmach_attach_board, obj); - - if (retval == 0) - err = NULL; - else { - cmn_err(CE_WARN, "prom error: prom_starfire_add_brd(%d) " - "returned %d", obj->connect_cpuid, retval); - - err = drerr_new(1, ESTF_PROBE, obj->cm.name); - } - - obj->connect_cpuid = -1; - - return (err); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_board_disconnect(drmachid_t id, drmach_opts_t *opts) -{ - drmach_board_t *bp; - int rv; - int d_idx; /* device index */ - drmachid_t d_id; /* device ID */ - sbd_error_t *err; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - - bp = id; - - /* - * We need to make sure all of the board's device nodes - * have been removed from the Solaris device tree before - * continuing with the disconnect. Otherwise, we could - * disconnect the board and remove the OBP device tree - * nodes with Solaris device tree nodes remaining. - * - * On Starfire, Solaris device tree nodes are deleted - * during unconfigure by drmach_unconfigure(). It's - * necessary to do this here because drmach_unconfigure() - * failures are not handled during unconfigure. - */ - if (bp->devices) { - rv = drmach_array_first(bp->devices, &d_idx, &d_id); - while (rv == 0) { - err = drmach_unconfigure(d_id, DRMACH_DEVI_REMOVE); - if (err) - return (err); - - rv = drmach_array_next(bp->devices, &d_idx, &d_id); - } - } - - /* - * Starfire board Solaris device tree counter nodes, - * which are only present on start-of-day boards, are - * removed in the dr_post_op() code flow after the - * board is unconfigured. We call the counter node - * removal function here because unconfigure errors - * can cause the dr_post_op() function to be skipped - * after an unconfigure operation even though all of - * the board's devices have been transitioned to the - * unconfigured state. - */ - err = drmach_remove_counter_nodes(id); - if (err) - return (err); - - return (NULL); -} - -static int -drmach_board_find_devices_cb(drmach_node_walk_args_t *args) -{ - drmach_node_t *node = args->node; - drmach_board_cb_data_t *data = args->data; - drmach_board_t *obj = data->obj; - - int rv; - int bnum; - drmach_device_t *device; - - rv = drmach_node_get_prop(node, OBP_BOARDNUM, &bnum); - if (rv) { - /* - * if the node does not have a board# property, then - * by that information alone it is known that drmach - * is not interested in it. - */ - return (0); - } else if (bnum != obj->bnum) - return (0); - - /* - * Create a device data structure from this node data. - * The call may yield nothing if the node is not of interest - * to drmach. - */ - data->err = drmach_device_new(node, obj, &device); - if (data->err) - return (-1); - else if (device == NULL) { - /* - * drmach_device_new examined the node we passed in - * and determined that it was one not of interest to - * drmach. So, it is skipped. - */ - return (0); - } - - rv = drmach_array_set(obj->devices, data->ndevs++, device); - if (rv) { - drmach_device_dispose(device); - data->err = DRMACH_INTERNAL_ERROR(); - return (-1); - } - - data->err = (*data->found)(data->a, device->type, device->unum, device); - return (data->err == NULL ? 0 : -1); -} - -sbd_error_t * -drmach_board_find_devices(drmachid_t id, void *a, - sbd_error_t *(*found)(void *a, const char *, int, drmachid_t)) -{ - extern int plat_max_cpu_units_per_board(); - extern int plat_max_mem_units_per_board(); - extern int plat_max_io_units_per_board(); - - drmach_board_t *obj = (drmach_board_t *)id; - sbd_error_t *err; - int max_devices; - int rv; - drmach_board_cb_data_t data; - - max_devices = plat_max_cpu_units_per_board(); - max_devices += plat_max_mem_units_per_board(); - max_devices += plat_max_io_units_per_board(); - - obj->devices = drmach_array_new(0, max_devices); - - data.obj = obj; - data.ndevs = 0; - data.found = found; - data.a = a; - data.err = NULL; - - rv = drmach_node_walk(obj->tree, &data, drmach_board_find_devices_cb); - if (rv == 0) - err = NULL; - else { - drmach_array_dispose(obj->devices, drmach_device_dispose); - obj->devices = NULL; - - if (data.err) - err = data.err; - else - err = DRMACH_INTERNAL_ERROR(); - } - - return (err); -} - -int -drmach_board_lookup(int bnum, drmachid_t *id) -{ - int rv = 0; - - if (!drmach_initialized && drmach_init() == -1) { - *id = 0; - rv = -1; - } else if (drmach_array_get(drmach_boards, bnum, id)) { - *id = 0; - rv = -1; - } - return (rv); -} - -sbd_error_t * -drmach_board_name(int bnum, char *buf, int buflen) -{ - (void) snprintf(buf, buflen, "SB%d", bnum); - return (NULL); -} - -sbd_error_t * -drmach_board_poweroff(drmachid_t id) -{ - drmach_board_t *bp; - sbd_error_t *err; - drmach_status_t stat; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - bp = id; - - err = drmach_board_status(id, &stat); - if (err) - return (err); - else if (stat.configured || stat.busy) - return (drerr_new(0, ESTF_CONFIGBUSY, bp->cm.name)); - else { - /* board power off is essentially a noop for Starfire */ - bp->powered = 0; - return (NULL); - } - /*NOTREACHED*/ -} - -sbd_error_t * -drmach_board_poweron(drmachid_t id) -{ - drmach_board_t *bp; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - bp = id; - - /* board power on is essentially a noop for Starfire */ - bp->powered = 1; - - return (NULL); -} - -static sbd_error_t * -drmach_board_release(drmachid_t id) -{ - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - return (NULL); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_board_test(drmachid_t id, drmach_opts_t *opts, int force) -{ - return (NULL); -} - -sbd_error_t * -drmach_board_unassign(drmachid_t id) -{ - drmach_board_t *bp; - sbd_error_t *err; - drmach_status_t stat; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - bp = id; - - err = drmach_board_status(id, &stat); - if (err) - return (err); - else if (stat.configured || stat.busy) - return (drerr_new(0, ESTF_CONFIGBUSY, bp->cm.name)); - else if (drmach_array_set(drmach_boards, bp->bnum, 0) != 0) - return (DRMACH_INTERNAL_ERROR()); - else { - drmach_board_dispose(bp); - return (NULL); - } - /*NOTREACHED*/ -} - -static sbd_error_t * -drmach_cpu_new(drmach_device_t *dp) -{ - sbd_error_t *err; - int portid; - - err = drmach_device_get_prop(dp, "upa-portid", &portid); - if (err == NULL) - dp->unum = portid & 3; - - dp->cm.isa = (void *)drmach_cpu_new; - dp->cm.release = drmach_cpu_release; - dp->cm.status = drmach_cpu_status; - - (void) snprintf(dp->cm.name, sizeof (dp->cm.name), "%s%d", dp->type, - dp->unum); - - return (err); -} - -/* - * drmach_cpu_obp_detach() - * This requires two steps, first, we must put the cpuid into the OBP - * idle loop (Idle in Program) state. Then we call OBP to place the CPU - * into the "Detached" state, which does any special processing to - * actually detach the cpu, such as flushing ecache, and also ensures - * that a subsequent breakpoint won't restart the cpu (if it was just in - * Idle in Program state). - */ -static void -drmach_cpu_obp_detach(int cpuid) -{ - /* - * Cpu may not be under OBP's control. Eg, if cpu exited to download - * helper on a prior attach. - */ - if (CPU_SGN_EXISTS(cpuid) && - !SGN_CPU_IS_OS(cpuid) && - !SGN_CPU_IS_OBP(cpuid)) { - cmn_err(CE_WARN, - "unexpected signature (0x%x) for cpu %d", - get_cpu_sgn(cpuid), cpuid); - } - - /* - * Now we place the CPU into the "Detached" idle loop in OBP. - * This is so that the CPU won't be restarted if we break into - * OBP with a breakpoint or BREAK key from the console, and also - * if we need to do any special processing, such as flushing the - * cpu's ecache, disabling interrupts (by turning of the ET bit in - * the PSR) and/or spinning in BBSRAM rather than global memory. - */ - DRMACH_PR("prom_starfire_rm_cpu(%d)\n", cpuid); - prom_starfire_rm_cpu(cpuid); -} - -/* - * drmach_cpu_obp_is_detached() returns TRUE if the cpu sigblock signature state - * is SIGBST_DETACHED; otherwise it returns FALSE. This routine should only - * be called after we have asked OBP to detach the CPU. It should NOT be - * called as a check during any other flow. - */ -static int -drmach_cpu_obp_is_detached(int cpuid) -{ - if (!CPU_SGN_EXISTS(cpuid) || - (SGN_CPU_IS_OS(cpuid) && SGN_CPU_STATE_IS_DETACHED(cpuid))) - return (1); - else - return (0); -} - -static int -drmach_cpu_start(struct cpu *cp) -{ - int cpuid = cp->cpu_id; - int ntries = drmach_cpu_ntries; - extern void restart_other_cpu(int); - - ASSERT(MUTEX_HELD(&cpu_lock)); - ASSERT(cpunodes[cpuid].nodeid != (pnode_t)0); - - cp->cpu_flags &= ~CPU_POWEROFF; - - /* - * NOTE: restart_other_cpu pauses cpus during the - * slave cpu start. This helps to quiesce the - * bus traffic a bit which makes the tick sync - * routine in the prom more robust. - */ - DRMACH_PR("COLD START for cpu (%d)\n", cpuid); - - prom_starfire_add_cpu(cpuid); - - restart_other_cpu(cpuid); - - /* - * Wait for the cpu to reach its idle thread before - * we zap it with a request to blow away the mappings - * it (might) have for the drmach_shutdown_asm code - * it may have executed on unconfigure. - */ - while ((cp->cpu_thread != cp->cpu_idle_thread) && (ntries > 0)) { - DELAY(drmach_cpu_delay); - ntries--; - } - - DRMACH_PR("waited %d out of %d loops for cpu %d\n", - drmach_cpu_ntries - ntries, drmach_cpu_ntries, cpuid); - - xt_one(cpuid, vtag_flushpage_tl1, - (uint64_t)drmach_shutdown_va, (uint64_t)ksfmmup); - - return (0); -} - -/* - * A detaching CPU is xcalled with an xtrap to drmach_cpu_stop_self() after - * it has been offlined. The function of this routine is to get the cpu - * spinning in a safe place. The requirement is that the system will not - * reference anything on the detaching board (memory and i/o is detached - * elsewhere) and that the CPU not reference anything on any other board - * in the system. This isolation is required during and after the writes - * to the domain masks to remove the board from the domain. - * - * To accomplish this isolation the following is done: - * 1) Create a locked mapping to a location in BBSRAM where - * the cpu will execute. - * 2) Copy the target function (drmach_shutdown_asm) in which - * the cpu will execute into BBSRAM. - * 3) Jump into function with BBSRAM. - * Function will: - * 3.1) Flush its Ecache (displacement). - * 3.2) Flush its Dcache with HW mechanism. - * 3.3) Flush its Icache with HW mechanism. - * 3.4) Flush all valid and _unlocked_ D-TLB entries. - * 3.5) Flush all valid and _unlocked_ I-TLB entries. - * 3.6) Clear xt_mb to signal completion. Note: cache line is - * recovered by drmach_cpu_poweroff(). - * 4) Jump into a tight loop. - */ -#define DRMACH_BBSRAM_OFFSET 0x1000 - -static void -drmach_cpu_stop_self(void) -{ - int cpuid = (int)CPU->cpu_id; - tte_t tte; - volatile uint_t *src, *dst; - size_t funclen; - uint64_t bbsram_pa, bbsram_offset; - uint_t bbsram_pfn; - uint64_t bbsram_addr; - void (*bbsram_func)(uint64_t); - extern void drmach_shutdown_asm(uint64_t); - extern void drmach_shutdown_asm_end(void); - - funclen = (uintptr_t)drmach_shutdown_asm_end - - (uintptr_t)drmach_shutdown_asm; - ASSERT(funclen <= MMU_PAGESIZE); - /* - * We'll start from the 0th's base. - */ - bbsram_pa = STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE; - bbsram_offset = bbsram_pa | 0xfe0ULL; - bbsram_pa += ldphysio(bbsram_offset) + DRMACH_BBSRAM_OFFSET; - - bbsram_pfn = (uint_t)(bbsram_pa >> MMU_PAGESHIFT); - - bbsram_addr = (uint64_t)drmach_shutdown_va; - drmach_shutdown_asm_mbox->estack = bbsram_addr + funclen; - - tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) | - TTE_PFN_INTHI(bbsram_pfn); - tte.tte_intlo = TTE_PFN_INTLO(bbsram_pfn) | - TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT; - sfmmu_dtlb_ld_kva(drmach_shutdown_va, &tte); /* load dtlb */ - sfmmu_itlb_ld_kva(drmach_shutdown_va, &tte); /* load itlb */ - - for (src = (uint_t *)drmach_shutdown_asm, dst = (uint_t *)bbsram_addr; - src < (uint_t *)drmach_shutdown_asm_end; src++, dst++) - *dst = *src; - - bbsram_func = (void (*)())bbsram_addr; - drmach_shutdown_asm_mbox->flushaddr = ecache_flushaddr; - drmach_shutdown_asm_mbox->size = (cpunodes[cpuid].ecache_size << 1); - drmach_shutdown_asm_mbox->linesize = cpunodes[cpuid].ecache_linesize; - drmach_shutdown_asm_mbox->physaddr = - va_to_pa((void *)&drmach_xt_mb[cpuid]); - - /* - * Signal to drmach_cpu_poweroff() is via drmach_xt_mb cleared - * by asm code - */ - - (*bbsram_func)(va_to_pa((void *)drmach_shutdown_asm_mbox)); -} - -static void -drmach_cpu_shutdown_self(void) -{ - cpu_t *cp = CPU; - int cpuid = cp->cpu_id; - extern void flush_windows(void); - - flush_windows(); - - (void) spl8(); - - ASSERT(cp->cpu_intr_actv == 0); - ASSERT(cp->cpu_thread == cp->cpu_idle_thread || - cp->cpu_thread == cp->cpu_startup_thread); - - cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF; - - drmach_cpu_stop_self(); - - cmn_err(CE_PANIC, "CPU %d FAILED TO SHUTDOWN", cpuid); -} - -/* a helper routine to keep the math in one place */ -static processorid_t -drmach_cpu_calc_id(drmach_device_t *dp) -{ - return (dp->bp->bnum * MAX_CPU_UNITS_PER_BOARD + dp->unum); -} - -/* - * Move bootproc (SIGBCPU) to another cpu. If dst_cpu is NULL, a - * destination cpu is chosen from the set of cpus not located on the - * same board as the current bootproc cpu. - */ -static sbd_error_t * -drmach_cpu_juggle_bootproc(drmach_device_t *dst_cpu) -{ - processorid_t cpuid; - struct cpu *cp; - sbd_error_t *err; - int rv; - - ASSERT(MUTEX_HELD(&cpu_lock)); - - /* dst_cpu is NULL when target cpu is unspecified. So, pick one. */ - if (dst_cpu == NULL) { - int avoid_board = DRMACH_CPUID2BNUM(SIGBCPU->cpu_id); - int max_cpuid = MAX_BOARDS * MAX_CPU_UNITS_PER_BOARD; - - for (cpuid = 0; cpuid < max_cpuid; cpuid++) - if (DRMACH_CPUID2BNUM(cpuid) != avoid_board) { - cp = cpu_get(cpuid); - if (cp != NULL && cpu_is_online(cp)) - break; - } - - if (cpuid == max_cpuid) { - err = drerr_new(1, ESTF_JUGGLE, NULL); - return (err); - } - - /* else, cp points to the selected target cpu */ - } else { - cpuid = drmach_cpu_calc_id(dst_cpu); - - if ((cp = cpu_get(cpuid)) == NULL) { - err = drerr_new(1, ESTF_NODEV, "%s::%s", - dst_cpu->bp->cm.name, dst_cpu->cm.name); - return (err); - } - - if (cpuid == SIGBCPU->cpu_id) { - cmn_err(CE_WARN, - "SIGBCPU(%d) same as new selection(%d)", - SIGBCPU->cpu_id, cpuid); - - /* technically not an error, but a no-op */ - return (NULL); - } - } - - cmn_err(CE_NOTE, "?relocating SIGBCPU from %d to %d", - SIGBCPU->cpu_id, cpuid); - - DRMACH_PR("moving SIGBCPU to CPU %d\n", cpuid); - - /* - * Tell OBP to initialize cvc-offset field of new CPU0 - * so that it's in sync with OBP and cvc_server - */ - prom_starfire_init_console(cpuid); - - /* - * Assign cvc to new cpu0's bbsram for I/O. This has to be - * done BEFORE cpu0 is moved via obp, since this logic - * will cause obp_helper to switch to a different bbsram for - * cvc I/O. We don't want cvc writing to a buffer from which - * nobody will pick up the data! - */ - cvc_assign_iocpu(cpuid); - - rv = prom_starfire_move_cpu0(cpuid); - - if (rv == 0) { - SIGBCPU = cp; - - DRMACH_PR("successfully juggled to CPU %d\n", cpuid); - return (NULL); - } else { - DRMACH_PR("prom error: prom_starfire_move_cpu0(%d) " - "returned %d\n", cpuid, rv); - - /* - * The move failed, hopefully obp_helper is still back - * at the old bootproc. Move cvc back there. - */ - cvc_assign_iocpu(SIGBCPU->cpu_id); - - - err = drerr_new(1, ESTF_MOVESIGB, "CPU %d", cpuid); - return (err); - } - /*NOTREACHED*/ -} - -static sbd_error_t * -drmach_cpu_release(drmachid_t id) -{ - drmach_device_t *dp; - processorid_t cpuid; - struct cpu *cp; - sbd_error_t *err; - - if (!DRMACH_IS_CPU_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - cpuid = drmach_cpu_calc_id(dp); - - ASSERT(MUTEX_HELD(&cpu_lock)); - - cp = cpu_get(cpuid); - if (cp == NULL) - err = DRMACH_INTERNAL_ERROR(); - else if (SIGBCPU->cpu_id == cp->cpu_id) - err = drmach_cpu_juggle_bootproc(NULL); - else - err = NULL; - - return (err); -} - -static sbd_error_t * -drmach_cpu_status(drmachid_t id, drmach_status_t *stat) -{ - drmach_device_t *dp; - - ASSERT(DRMACH_IS_CPU_ID(id)); - dp = id; - - stat->assigned = dp->bp->assigned; - stat->powered = dp->bp->powered; - mutex_enter(&cpu_lock); - stat->configured = (cpu_get(drmach_cpu_calc_id(dp)) != NULL); - mutex_exit(&cpu_lock); - stat->busy = dp->busy; - (void) strncpy(stat->type, dp->type, sizeof (stat->type)); - stat->info[0] = '\0'; - - return (NULL); -} - -sbd_error_t * -drmach_cpu_disconnect(drmachid_t id) -{ - drmach_device_t *cpu; - int cpuid; - int ntries; - int p; - u_longlong_t pc_addr; - uchar_t rvalue; - - if (!DRMACH_IS_CPU_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - cpu = id; - - cpuid = drmach_cpu_calc_id(cpu); - if (SIGBCPU->cpu_id == cpuid) { - /* this cpu is SIGBCPU, can't disconnect */ - return (drerr_new(1, ESTF_HASSIGB, "%s::%s", - cpu->bp->cm.name, cpu->cm.name)); - } - - /* - * Make sure SIGBST_DETACHED is set before - * mapping out the sig block. - */ - ntries = drmach_cpu_ntries; - while (!drmach_cpu_obp_is_detached(cpuid) && ntries) { - DELAY(drmach_cpu_delay); - ntries--; - } - if (!drmach_cpu_obp_is_detached(cpuid)) { - cmn_err(CE_WARN, "failed to mark cpu %d detached in sigblock", - cpuid); - } - - /* map out signature block */ - if (CPU_SGN_EXISTS(cpuid)) { - CPU_SGN_MAPOUT(cpuid); - } - - /* - * We now PC IDLE the processor to guarantee we - * stop any transactions from coming from it. - */ - p = cpu->unum & 1; - pc_addr = STARFIRE_BB_PC_ADDR(cpu->bp->bnum, cpu->unum, 0); - - DRMACH_PR("PC idle cpu %d (addr = 0x%llx, port = %d, p = %d)", - drmach_cpu_calc_id(cpu), pc_addr, cpu->unum, p); - - rvalue = ldbphysio(pc_addr); - rvalue |= STARFIRE_BB_PC_IDLE(p); - stbphysio(pc_addr, rvalue); - DELAY(50000); - - return (NULL); -} - -sbd_error_t * -drmach_cpu_get_id(drmachid_t id, processorid_t *cpuid) -{ - drmach_device_t *cpu; - - if (!DRMACH_IS_CPU_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - cpu = id; - - *cpuid = drmach_cpu_calc_id(cpu); - return (NULL); -} - -sbd_error_t * -drmach_cpu_get_impl(drmachid_t id, int *ip) -{ - drmach_device_t *cpu; - int impl; - - if (!DRMACH_IS_CPU_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - - cpu = id; - - if (drmach_node_get_prop(cpu->node, "implementation#", &impl) == -1) { - return (DRMACH_INTERNAL_ERROR()); - } - - *ip = impl; - - return (NULL); -} - -void -drmach_cpu_flush_ecache_sync(void) -{ - ASSERT(curthread->t_bound_cpu == CPU); - - /* - * Now let's flush our ecache thereby removing all references - * to the target (detaching) memory from all ecache's in - * system. - */ - cpu_flush_ecache(); - - /* - * Delay 100 usec out of paranoia to insure everything - * (hardware queues) has drained before we start reprogramming - * the hardware. - */ - DELAY(100); -} - -sbd_error_t * -drmach_get_dip(drmachid_t id, dev_info_t **dip) -{ - drmach_device_t *dp; - - if (!DRMACH_IS_DEVICE_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - *dip = drmach_node_get_dip(dp->node); - return (NULL); -} - -sbd_error_t * -drmach_io_is_attached(drmachid_t id, int *yes) -{ - drmach_device_t *dp; - dev_info_t *dip; - int state; - - if (!DRMACH_IS_IO_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - dip = drmach_node_get_dip(dp->node); - if (dip == NULL) { - *yes = 0; - return (NULL); - } - - state = ddi_get_devstate(dip); - *yes = (i_ddi_devi_attached(dip) || (state == DDI_DEVSTATE_UP)); - - return (NULL); -} - -sbd_error_t * -drmach_io_pre_release(drmachid_t id) -{ - if (!DRMACH_IS_IO_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - return (NULL); -} - -static sbd_error_t * -drmach_io_release(drmachid_t id) -{ - if (!DRMACH_IS_IO_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - return (NULL); -} - -sbd_error_t * -drmach_io_unrelease(drmachid_t id) -{ - if (!DRMACH_IS_IO_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - return (NULL); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_io_post_release(drmachid_t id) -{ - return (NULL); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_io_post_attach(drmachid_t id) -{ - return (NULL); -} - -static sbd_error_t * -drmach_io_status(drmachid_t id, drmach_status_t *stat) -{ - drmach_device_t *dp; - sbd_error_t *err; - int configured; - - ASSERT(DRMACH_IS_IO_ID(id)); - dp = id; - - err = drmach_io_is_attached(id, &configured); - if (err) - return (err); - - stat->assigned = dp->bp->assigned; - stat->powered = dp->bp->powered; - stat->configured = (configured != 0); - stat->busy = dp->busy; - (void) strncpy(stat->type, dp->type, sizeof (stat->type)); - stat->info[0] = '\0'; - - return (NULL); -} - -static sbd_error_t * -drmach_mem_new(drmach_device_t *dp) -{ - dp->unum = 0; - dp->cm.isa = (void *)drmach_mem_new; - dp->cm.release = drmach_mem_release; - dp->cm.status = drmach_mem_status; - - (void) snprintf(dp->cm.name, sizeof (dp->cm.name), "%s", dp->type); - - return (NULL); -} - -sbd_error_t * -drmach_mem_add_span(drmachid_t id, uint64_t basepa, uint64_t size) -{ - pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT); - pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT); - pda_handle_t ph; - int rv; - - ASSERT(size != 0); - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - - rv = kcage_range_add(basepfn, npages, KCAGE_DOWN); - if (rv == ENOMEM) { - cmn_err(CE_WARN, "%lu megabytes not available to kernel cage", - (ulong_t)(size == 0 ? 0 : size / MBYTE)); - } else if (rv != 0) { - /* catch this in debug kernels */ - ASSERT(0); - - cmn_err(CE_WARN, "unexpected kcage_range_add" - " return value %d", rv); - } - - /* - * Update the PDA (post2obp) structure with the - * range of the newly added memory. - */ - ph = drmach_pda_open(); - if (ph != NULL) { - pda_mem_add_span(ph, basepa, size); - pda_close(ph); - } - - return (NULL); -} - -sbd_error_t * -drmach_mem_del_span(drmachid_t id, uint64_t basepa, uint64_t size) -{ - drmach_device_t *mem = id; - pfn_t basepfn = (pfn_t)(basepa >> PAGESHIFT); - pgcnt_t npages = (pgcnt_t)(size >> PAGESHIFT); - uint_t mcreg; - sbd_error_t *err; - pda_handle_t ph; - int rv; - - err = drmach_read_mc_asr(id, &mcreg); - if (err) - return (err); - else if (mcreg & STARFIRE_MC_INTERLEAVE_MASK) { - return (drerr_new(1, ESTF_INTERBOARD, "%s::%s", - mem->bp->cm.name, mem->cm.name)); - } - - if (size > 0) { - rv = kcage_range_delete_post_mem_del(basepfn, npages); - if (rv != 0) { - cmn_err(CE_WARN, - "unexpected kcage_range_delete_post_mem_del" - " return value %d", rv); - return (DRMACH_INTERNAL_ERROR()); - } - } - - /* - * Update the PDA (post2obp) structure with the - * range of removed memory. - */ - ph = drmach_pda_open(); - if (ph != NULL) { - if (size > 0) - pda_mem_del_span(ph, basepa, size); - - /* update PDA to board's new mc register settings */ - pda_mem_sync(ph, mem->bp->bnum, 0); - - pda_close(ph); - } - - return (NULL); -} - -/* support routine for enable and disable */ -static sbd_error_t * -drmach_mem_update_interconnect(drmachid_t id, uint_t mcreg) -{ - drmach_device_t *dp; - pda_handle_t ph; - int b; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - dp = id; - - ph = drmach_pda_open(); - if (ph == NULL) - return (DRMACH_INTERNAL_ERROR()); - - for (b = 0; b < MAX_BOARDS; b++) { - int p; - int rv; - ushort_t bda_proc, bda_ioc; - board_desc_t *bdesc; - - if (pda_board_present(ph, b) == 0) - continue; - - bdesc = (board_desc_t *)pda_get_board_info(ph, b); - - /* - * Update PCs for CPUs. - */ - - /* make sure definition in platmod is in sync with pda */ - ASSERT(MAX_PROCMODS == MAX_CPU_UNITS_PER_BOARD); - - bda_proc = bdesc->bda_proc; - for (p = 0; p < MAX_PROCMODS; p++) { - if (BDA_NBL(bda_proc, p) != BDAN_GOOD) - continue; - - rv = pc_madr_add(b, dp->bp->bnum, p, mcreg); - if (rv) { - pda_close(ph); - return (DRMACH_INTERNAL_ERROR()); - } - } - - /* - * Update PCs for IOCs. - */ - - /* make sure definition in platmod is in sync with pda */ - ASSERT(MAX_IOCS == MAX_IO_UNITS_PER_BOARD); - - bda_ioc = bdesc->bda_ioc; - for (p = 0; p < MAX_IOCS; p++) { - if (BDA_NBL(bda_ioc, p) != BDAN_GOOD) - continue; - - rv = pc_madr_add(b, dp->bp->bnum, p + 4, mcreg); - if (rv) { - pda_close(ph); - return (DRMACH_INTERNAL_ERROR()); - } - } - } - - pda_close(ph); - return (NULL); -} - -sbd_error_t * -drmach_mem_disable(drmachid_t id) -{ - sbd_error_t *err; - uint_t mcreg; - - err = drmach_read_mc_asr(id, &mcreg); - if (err == NULL) { - ASSERT(mcreg & STARFIRE_MC_MEM_PRESENT_MASK); - - /* Turn off presence bit. */ - mcreg &= ~STARFIRE_MC_MEM_PRESENT_MASK; - - err = drmach_mem_update_interconnect(id, mcreg); - if (err == NULL) - err = drmach_write_mc_asr(id, mcreg); - } - - return (err); -} - -sbd_error_t * -drmach_mem_enable(drmachid_t id) -{ - sbd_error_t *err; - uint_t mcreg; - - err = drmach_read_mc_asr(id, &mcreg); - if (err == NULL) { - mcreg |= STARFIRE_MC_MEM_PRESENT_MASK; - - err = drmach_write_mc_asr(id, mcreg); - if (err == NULL) - err = drmach_mem_update_interconnect(id, mcreg); - } - - return (err); -} - -sbd_error_t * -drmach_mem_get_alignment(drmachid_t id, uint64_t *mask) -{ - drmach_device_t *mem; - sbd_error_t *err; - pnode_t nodeid; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - mem = id; - - nodeid = drmach_node_get_dnode(mem->node); - if (nodeid == OBP_NONODE || nodeid == OBP_BADNODE) - err = DRMACH_INTERNAL_ERROR(); - else { - uint64_t size; - - size = mc_get_alignment_mask(nodeid); - if (size == (uint64_t)-1) - err = DRMACH_INTERNAL_ERROR(); - else { - *mask = size - 1; - err = NULL; - } - } - - return (err); -} - -sbd_error_t * -drmach_mem_get_base_physaddr(drmachid_t id, uint64_t *pa) -{ - sbd_error_t *err; - uint_t mcreg; - - err = drmach_read_mc_asr(id, &mcreg); - if (err == NULL) - *pa = mc_asr_to_pa(mcreg); - - return (err); -} - -/* - * Use of this routine after copy/rename will yield incorrect results, - * because the OBP MEMAVAIL property will not correctly reflect the - * programming of the MCs. - */ -sbd_error_t * -drmach_mem_get_memlist(drmachid_t id, struct memlist **ml) -{ - drmach_device_t *mem; - int rv, i, rlen, rblks; - sbd_error_t *err; - struct memlist *mlist; - struct sf_memunit_regspec *rlist; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - mem = id; - - err = drmach_device_get_proplen(mem, "dr-available", &rlen); - if (err) - return (err); - - rlist = kmem_zalloc(rlen, KM_SLEEP); - - err = drmach_device_get_prop(mem, "dr-available", rlist); - if (err) { - kmem_free(rlist, rlen); - return (err); - } - - mlist = NULL; - rblks = rlen / sizeof (struct sf_memunit_regspec); - for (i = 0; i < rblks; i++) { - uint64_t addr, size; - - addr = (uint64_t)rlist[i].regspec_addr_hi << 32; - addr |= (uint64_t)rlist[i].regspec_addr_lo; - size = (uint64_t)rlist[i].regspec_size_hi << 32; - size |= (uint64_t)rlist[i].regspec_size_lo; - - mlist = memlist_add_span(mlist, addr, size); - } - - kmem_free(rlist, rlen); - - /* - * Make sure the incoming memlist doesn't already - * intersect with what's present in the system (phys_install). - */ - memlist_read_lock(); - rv = memlist_intersect(phys_install, mlist); - memlist_read_unlock(); - if (rv) { -#ifdef DEBUG - DRMACH_PR("OBP derived memlist intersects" - " with phys_install\n"); - memlist_dump(mlist); - - DRMACH_PR("phys_install memlist:\n"); - memlist_dump(phys_install); -#endif - - memlist_delete(mlist); - return (DRMACH_INTERNAL_ERROR()); - } - -#ifdef DEBUG - DRMACH_PR("OBP derived memlist:"); - memlist_dump(mlist); -#endif - - *ml = mlist; - return (NULL); -} - -sbd_error_t * -drmach_mem_get_size(drmachid_t id, uint64_t *bytes) -{ - drmach_device_t *mem; - pda_handle_t ph; - pgcnt_t npages; - - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - mem = id; - - ph = drmach_pda_open(); - if (ph == NULL) - return (DRMACH_INTERNAL_ERROR()); - - npages = pda_get_mem_size(ph, mem->bp->bnum); - *bytes = (uint64_t)npages << PAGESHIFT; - - pda_close(ph); - return (NULL); -} - -sbd_error_t * -drmach_mem_get_slice_size(drmachid_t id, uint64_t *bytes) -{ - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - - *bytes = mc_get_mem_alignment(); - return (NULL); -} - -/* field debugging tool */ -processorid_t drmach_mem_cpu_affinity_nail = 0; - -processorid_t -drmach_mem_cpu_affinity(drmachid_t id) -{ - drmach_device_t *mp; - drmach_board_t *bp; - processorid_t cpuid; - - if (!DRMACH_IS_MEM_ID(id)) - return (CPU_CURRENT); - - if (drmach_mem_cpu_affinity_nail) { - cpuid = drmach_mem_cpu_affinity_nail; - - if (cpuid < 0 || cpuid > NCPU) - return (CPU_CURRENT); - - mutex_enter(&cpu_lock); - if (cpu[cpuid] == NULL || !CPU_ACTIVE(cpu[cpuid])) - cpuid = CPU_CURRENT; - mutex_exit(&cpu_lock); - - return (cpuid); - } - - /* try to choose a proc on the target board */ - mp = id; - bp = mp->bp; - if (bp->devices) { - int rv; - int d_idx; - drmachid_t d_id; - - rv = drmach_array_first(bp->devices, &d_idx, &d_id); - while (rv == 0) { - if (DRMACH_IS_CPU_ID(d_id)) { - cpuid = drmach_cpu_calc_id(d_id); - - mutex_enter(&cpu_lock); - if (cpu[cpuid] && CPU_ACTIVE(cpu[cpuid])) { - mutex_exit(&cpu_lock); - DRMACH_PR("drmach_mem_cpu_affinity: " - "selected cpuid=%d\n", cpuid); - return (cpuid); - } else { - mutex_exit(&cpu_lock); - } - } - - rv = drmach_array_next(bp->devices, &d_idx, &d_id); - } - } - - /* otherwise, this proc, wherever it is */ - DRMACH_PR("drmach_mem_cpu_affinity: using default CPU_CURRENT\n"); - - return (CPU_CURRENT); -} - -static sbd_error_t * -drmach_mem_release(drmachid_t id) -{ - if (!DRMACH_IS_MEM_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - return (NULL); -} - -static sbd_error_t * -drmach_mem_status(drmachid_t id, drmach_status_t *stat) -{ - drmach_device_t *dp; - sbd_error_t *err; - uint64_t pa, slice_size; - struct memlist *ml; - - ASSERT(DRMACH_IS_MEM_ID(id)); - dp = id; - - /* get starting physical address of target memory */ - err = drmach_mem_get_base_physaddr(id, &pa); - if (err) - return (err); - - /* round down to slice boundary */ - slice_size = mc_get_mem_alignment(); - pa &= ~ (slice_size - 1); - - /* stop at first span that is in slice */ - memlist_read_lock(); - for (ml = phys_install; ml; ml = ml->ml_next) - if (ml->ml_address >= pa && ml->ml_address < pa + slice_size) - break; - memlist_read_unlock(); - - stat->assigned = dp->bp->assigned; - stat->powered = dp->bp->powered; - stat->configured = (ml != NULL); - stat->busy = dp->busy; - (void) strncpy(stat->type, dp->type, sizeof (stat->type)); - stat->info[0] = '\0'; - - return (NULL); -} - -static int -drmach_detach_board(void *arg) -{ - cpuset_t cset; - int retval; - drmach_board_t *bp = (drmach_board_t *)arg; - - cset = cpu_ready_set; - promsafe_xc_attention(cset); - - retval = prom_starfire_rm_brd(bp->bnum); - - xc_dismissed(cset); - - return (retval); -} - -sbd_error_t * -drmach_board_deprobe(drmachid_t id) -{ - drmach_board_t *bp; - int retval; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - bp = id; - - cmn_err(CE_CONT, "DR: PROM detach board %d\n", bp->bnum); - - retval = prom_tree_update(drmach_detach_board, bp); - - if (retval == 0) - return (NULL); - else { - cmn_err(CE_WARN, "prom error: prom_starfire_rm_brd(%d) " - "returned %d", bp->bnum, retval); - return (drerr_new(1, ESTF_DEPROBE, "%s", bp->cm.name)); - } -} - -/*ARGSUSED*/ -static sbd_error_t * -drmach_pt_juggle_bootproc(drmachid_t id, drmach_opts_t *opts) -{ - drmach_device_t *cpu; - sbd_error_t *err; - - if (!DRMACH_IS_CPU_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - cpu = id; - - mutex_enter(&cpu_lock); - - err = drmach_cpu_juggle_bootproc(cpu); - - mutex_exit(&cpu_lock); - - return (err); -} - -/*ARGSUSED*/ -static sbd_error_t * -drmach_pt_dump_pdainfo(drmachid_t id, drmach_opts_t *opts) -{ - drmach_board_t *bp; - int board; - int i; - pda_handle_t ph; - board_desc_t *bdesc; - - if (!DRMACH_IS_BOARD_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - bp = id; - board = bp->bnum; - - ph = drmach_pda_open(); - if (ph == NULL) - return (DRMACH_INTERNAL_ERROR()); - - if (pda_board_present(ph, board) == 0) { - cmn_err(CE_CONT, "board %d is MISSING\n", board); - pda_close(ph); - return (DRMACH_INTERNAL_ERROR()); - } - - cmn_err(CE_CONT, "board %d is PRESENT\n", board); - - bdesc = (board_desc_t *)pda_get_board_info(ph, board); - if (bdesc == NULL) { - cmn_err(CE_CONT, - "no board descriptor found for board %d\n", - board); - pda_close(ph); - return (DRMACH_INTERNAL_ERROR()); - } - - /* make sure definition in platmod is in sync with pda */ - ASSERT(MAX_PROCMODS == MAX_CPU_UNITS_PER_BOARD); - - for (i = 0; i < MAX_PROCMODS; i++) { - if (BDA_NBL(bdesc->bda_proc, i) == BDAN_GOOD) - cmn_err(CE_CONT, - "proc %d.%d PRESENT\n", board, i); - else - cmn_err(CE_CONT, - "proc %d.%d MISSING\n", board, i); - } - - for (i = 0; i < MAX_MGROUPS; i++) { - if (BDA_NBL(bdesc->bda_mgroup, i) == BDAN_GOOD) - cmn_err(CE_CONT, - "mgroup %d.%d PRESENT\n", board, i); - else - cmn_err(CE_CONT, - "mgroup %d.%d MISSING\n", board, i); - } - - /* make sure definition in platmod is in sync with pda */ - ASSERT(MAX_IOCS == MAX_IO_UNITS_PER_BOARD); - - for (i = 0; i < MAX_IOCS; i++) { - int s; - - if (BDA_NBL(bdesc->bda_ioc, i) == BDAN_GOOD) { - cmn_err(CE_CONT, - "ioc %d.%d PRESENT\n", board, i); - for (s = 0; s < MAX_SLOTS_PER_IOC; s++) { - if (BDA_NBL(bdesc->bda_ios[i], s) != BDAN_GOOD) - continue; - cmn_err(CE_CONT, - "..scard %d.%d.%d PRESENT\n", - board, i, s); - } - } else { - cmn_err(CE_CONT, - "ioc %d.%d MISSING\n", - board, i); - } - } - - cmn_err(CE_CONT, - "board %d memsize = %d pages\n", - board, pda_get_mem_size(ph, board)); - - pda_close(ph); - - return (NULL); -} - -/*ARGSUSED*/ -sbd_error_t * -drmach_pt_readmem(drmachid_t id, drmach_opts_t *opts) -{ - struct memlist *ml; - uint64_t src_pa; - uint64_t dst_pa; - uint64_t dst; - - dst_pa = va_to_pa(&dst); - - memlist_read_lock(); - for (ml = phys_install; ml; ml = ml->ml_next) { - uint64_t nbytes; - - src_pa = ml->ml_address; - nbytes = ml->ml_size; - - while (nbytes != 0ull) { - - /* copy 32 bytes at arc_pa to dst_pa */ - bcopy32_il(src_pa, dst_pa); - - /* increment by 32 bytes */ - src_pa += (4 * sizeof (uint64_t)); - - /* decrement by 32 bytes */ - nbytes -= (4 * sizeof (uint64_t)); - } - } - memlist_read_unlock(); - - return (NULL); -} - -static struct { - const char *name; - sbd_error_t *(*handler)(drmachid_t id, drmach_opts_t *opts); -} drmach_pt_arr[] = { - { "juggle", drmach_pt_juggle_bootproc }, - { "pda", drmach_pt_dump_pdainfo }, - { "readmem", drmach_pt_readmem }, - - /* the following line must always be last */ - { NULL, NULL } -}; - -/*ARGSUSED*/ -sbd_error_t * -drmach_passthru(drmachid_t id, drmach_opts_t *opts) -{ - int i; - sbd_error_t *err; - - i = 0; - while (drmach_pt_arr[i].name != NULL) { - int len = strlen(drmach_pt_arr[i].name); - - if (strncmp(drmach_pt_arr[i].name, opts->copts, len) == 0) - break; - - i += 1; - } - - if (drmach_pt_arr[i].name == NULL) - err = drerr_new(0, ESTF_UNKPTCMD, opts->copts); - else - err = (*drmach_pt_arr[i].handler)(id, opts); - - return (err); -} - -sbd_error_t * -drmach_release(drmachid_t id) -{ - drmach_common_t *cp; - if (!DRMACH_IS_DEVICE_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - cp = id; - - return (cp->release(id)); -} - -sbd_error_t * -drmach_status(drmachid_t id, drmach_status_t *stat) -{ - drmach_common_t *cp; - - if (!DRMACH_IS_ID(id)) - return (drerr_new(0, ESTF_NOTID, NULL)); - cp = id; - - return (cp->status(id, stat)); -} - -sbd_error_t * -drmach_unconfigure(drmachid_t id, int flags) -{ - drmach_device_t *dp; - pnode_t nodeid; - dev_info_t *dip, *fdip = NULL; - - if (!DRMACH_IS_DEVICE_ID(id)) - return (drerr_new(0, ESTF_INAPPROP, NULL)); - - dp = id; - - nodeid = drmach_node_get_dnode(dp->node); - if (nodeid == OBP_NONODE) - return (DRMACH_INTERNAL_ERROR()); - - dip = e_ddi_nodeid_to_dip(nodeid); - if (dip == NULL) - return (NULL); - - /* - * Branch already held, so hold acquired in - * e_ddi_nodeid_to_dip() can be released - */ - ddi_release_devi(dip); - - if (flags & DEVI_BRANCH_DESTROY) - flags |= DEVI_BRANCH_EVENT; - - /* - * Force flag is no longer necessary. See starcat/io/drmach.c - * for details. - */ - ASSERT(e_ddi_branch_held(dip)); - if (e_ddi_branch_unconfigure(dip, &fdip, flags)) { - sbd_error_t *err; - char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP); - - /* - * If non-NULL, fdip is returned held and must be released. - */ - if (fdip != NULL) { - (void) ddi_pathname(fdip, path); - ndi_rele_devi(fdip); - } else { - (void) ddi_pathname(dip, path); - } - - err = drerr_new(1, ESTF_DRVFAIL, path); - - kmem_free(path, MAXPATHLEN); - - return (err); - } - - return (NULL); -} - -/* - * drmach interfaces to legacy Starfire platmod logic - * linkage via runtime symbol look up, called from plat_cpu_power* - */ - -/* - * Start up a cpu. It is possible that we're attempting to restart - * the cpu after an UNCONFIGURE in which case the cpu will be - * spinning in its cache. So, all we have to do is wake it up. - * Under normal circumstances the cpu will be coming from a previous - * CONNECT and thus will be spinning in OBP. In both cases, the - * startup sequence is the same. - */ -int -drmach_cpu_poweron(struct cpu *cp) -{ - DRMACH_PR("drmach_cpu_poweron: starting cpuid %d\n", cp->cpu_id); - - ASSERT(MUTEX_HELD(&cpu_lock)); - - if (drmach_cpu_start(cp) != 0) - return (EBUSY); - else - return (0); -} - -int -drmach_cpu_poweroff(struct cpu *cp) -{ - int ntries, cnt; - processorid_t cpuid = cp->cpu_id; - void drmach_cpu_shutdown_self(void); - - DRMACH_PR("drmach_cpu_poweroff: stopping cpuid %d\n", cp->cpu_id); - - ASSERT(MUTEX_HELD(&cpu_lock)); - - /* - * Capture all CPUs (except for detaching proc) to prevent - * crosscalls to the detaching proc until it has cleared its - * bit in cpu_ready_set. - * - * The CPU's remain paused and the prom_mutex is known to be free. - * This prevents the x-trap victim from blocking when doing prom - * IEEE-1275 calls at a high PIL level. - */ - promsafe_pause_cpus(); - - /* - * Quiesce interrupts on the target CPU. We do this by setting - * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to - * prevent it from receiving cross calls and cross traps. - * This prevents the processor from receiving any new soft interrupts. - */ - mp_cpu_quiesce(cp); - - /* setup xt_mb, will be cleared by drmach_shutdown_asm when ready */ - drmach_xt_mb[cpuid] = 0x80; - - xt_one_unchecked(cpuid, (xcfunc_t *)idle_stop_xcall, - (uint64_t)drmach_cpu_shutdown_self, NULL); - - ntries = drmach_cpu_ntries; - cnt = 0; - while (drmach_xt_mb[cpuid] && ntries) { - DELAY(drmach_cpu_delay); - ntries--; - cnt++; - } - - drmach_xt_mb[cpuid] = 0; /* steal the cache line back */ - - start_cpus(); - - DRMACH_PR("waited %d out of %d tries for " - "drmach_cpu_shutdown_self on cpu%d", - drmach_cpu_ntries - ntries, drmach_cpu_ntries, cp->cpu_id); - - drmach_cpu_obp_detach(cpuid); - - CPU_SIGNATURE(OS_SIG, SIGST_DETACHED, SIGSUBST_NULL, cpuid); - - return (0); -} - -/*ARGSUSED*/ -int -drmach_verify_sr(dev_info_t *dip, int sflag) -{ - return (0); -} - -void -drmach_suspend_last(void) -{ -} - -void -drmach_resume_first(void) -{ -} - -/* - * Log a DR sysevent. - * Return value: 0 success, non-zero failure. - */ -int -drmach_log_sysevent(int board, char *hint, int flag, int verbose) -{ - sysevent_t *ev; - sysevent_id_t eid; - int rv, km_flag; - sysevent_value_t evnt_val; - sysevent_attr_list_t *evnt_attr_list = NULL; - char attach_pnt[MAXNAMELEN]; - - km_flag = (flag == SE_SLEEP) ? KM_SLEEP : KM_NOSLEEP; - attach_pnt[0] = '\0'; - if (drmach_board_name(board, attach_pnt, MAXNAMELEN)) { - rv = -1; - goto logexit; - } - if (verbose) - DRMACH_PR("drmach_log_sysevent: %s %s, flag: %d, verbose: %d\n", - attach_pnt, hint, flag, verbose); - - if ((ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE, - SUNW_KERN_PUB"dr", km_flag)) == NULL) { - rv = -2; - goto logexit; - } - evnt_val.value_type = SE_DATA_TYPE_STRING; - evnt_val.value.sv_string = attach_pnt; - if ((rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID, - &evnt_val, km_flag)) != 0) - goto logexit; - - evnt_val.value_type = SE_DATA_TYPE_STRING; - evnt_val.value.sv_string = hint; - if ((rv = sysevent_add_attr(&evnt_attr_list, DR_HINT, - &evnt_val, km_flag)) != 0) { - sysevent_free_attr(evnt_attr_list); - goto logexit; - } - - (void) sysevent_attach_attributes(ev, evnt_attr_list); - - /* - * Log the event but do not sleep waiting for its - * delivery. This provides insulation from syseventd. - */ - rv = log_sysevent(ev, SE_NOSLEEP, &eid); - -logexit: - if (ev) - sysevent_free(ev); - if ((rv != 0) && verbose) - cmn_err(CE_WARN, - "drmach_log_sysevent failed (rv %d) for %s %s\n", - rv, attach_pnt, hint); - - return (rv); -} - -/*ARGSUSED*/ -int -drmach_allow_memrange_modify(drmachid_t id) -{ - return (1); /* TRUE */ -} diff --git a/usr/src/uts/sun4u/starfire/io/idn.c b/usr/src/uts/sun4u/starfire/io/idn.c deleted file mode 100644 index 79eb65f819..0000000000 --- a/usr/src/uts/sun4u/starfire/io/idn.c +++ /dev/null @@ -1,5787 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - */ - -#include <sys/types.h> -#include <sys/sysmacros.h> -#include <sys/open.h> -#include <sys/param.h> -#include <sys/machparam.h> -#include <sys/systm.h> -#include <sys/signal.h> -#include <sys/cred.h> -#include <sys/user.h> -#include <sys/proc.h> -#include <sys/vnode.h> -#include <sys/uio.h> -#include <sys/buf.h> -#include <sys/file.h> -#include <sys/kmem.h> -#include <sys/stat.h> -#include <sys/stream.h> -#include <sys/stropts.h> -#include <sys/strsubr.h> -#include <sys/strsun.h> -#include <inet/common.h> -#include <inet/mi.h> -#include <inet/nd.h> -#include <sys/poll.h> -#include <sys/utsname.h> -#include <sys/debug.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/errno.h> -#include <sys/modctl.h> -#include <sys/machsystm.h> -#include <sys/promif.h> -#include <sys/prom_plat.h> -#include <sys/obpdefs.h> -#include <vm/seg_kmem.h> -#include <vm/seg_kp.h> -#include <sys/kstat.h> -#include <sys/membar.h> -#include <sys/ivintr.h> -#include <sys/vm_machparam.h> -#include <sys/x_call.h> -#include <sys/cpuvar.h> -#include <sys/archsystm.h> -#include <sys/dmv.h> - -#include <sys/idn.h> -#include <sys/idn_xf.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/cpu_sgn.h> - -struct idn_gkstat sg_kstat; - -#define MBXTBL_PART_REPORT ((caddr_t)1) -#define MBXTBL_FULL_REPORT ((caddr_t)2) - -idn_domain_t idn_domain[MAX_DOMAINS]; -idn_global_t idn; -int idn_debug; -int idn_snoop; -int idn_history; - -typedef enum { - IDN_GPROPS_OKAY, - IDN_GPROPS_UNCHECKED, - IDN_GPROPS_ERROR -} idn_gprops_t; - -struct idn_history idnhlog; - -/* - * IDN "tunables". - */ -int idn_smr_size; -int idn_nwr_size; -int idn_lowat; -int idn_hiwat; -int idn_protocol_nservers; -int idn_awolmsg_interval; -int idn_smr_bufsize; -int idn_slab_bufcount; -int idn_slab_prealloc; -int idn_slab_maxperdomain; -int idn_slab_mintotal; -int idn_window_max; -int idn_window_incr; -int idn_window_emax; -int idn_reclaim_min; -int idn_reclaim_max; -int idn_mbox_per_net; -int idn_max_nets; - -int idn_netsvr_spin_count; -int idn_netsvr_wait_min; -int idn_netsvr_wait_max; -int idn_netsvr_wait_shift; - -int idn_checksum; - -int idn_msgwait_nego; -int idn_msgwait_cfg; -int idn_msgwait_con; -int idn_msgwait_fin; -int idn_msgwait_cmd; -int idn_msgwait_data; - -int idn_retryfreq_nego; -int idn_retryfreq_con; -int idn_retryfreq_fin; - -int idn_window_emax; /* calculated */ -int idn_slab_maxperdomain; /* calculated */ - -/* - * DMV interrupt support. - */ -int idn_pil; -int idn_dmv_pending_max; -idn_dmv_msg_t *idn_iv_queue[NCPU]; -int idn_intr_index[NCPU]; /* idn_handler ONLY */ -static idn_dmv_data_t *idn_dmv_data; - -int idn_sigbpil; - -idnparam_t idn_param_arr[] = { -{ 0, 1, 0, /* 0 */ "idn_modunloadable" }, -}; - -/* - * Parameters that are only accessible in a DEBUG driver. - */ -static char *idn_param_debug_only[] = { -#if 0 - "idn_checksum", -#endif /* 0 */ - 0 -}; - -/* - * Parameters that are READ-ONLY. - */ -static char *idn_param_read_only[] = { -#if 0 - "idn_window_emax", - "idn_slab_maxperdomain", -#endif /* 0 */ - 0 -}; - -static struct idn_global_props { - int p_min, p_max, p_def; - char *p_string; - int *p_var; -} idn_global_props[] = { -{ 0, 0, 0, "idn_debug", &idn_debug }, -{ 0, 1, 0, "idn_history", &idn_history }, -{ 0, IDN_SMR_MAXSIZE, - 0, "idn_smr_size", &idn_smr_size }, -{ 0, IDN_SMR_MAXSIZE, - 0, "idn_nwr_size", &idn_nwr_size }, -{ 1, 512*1024, - 1, "idn_lowat", &idn_lowat }, -{ 1*1024, - 1*1024*1024, - 256*1024, - "idn_hiwat", &idn_hiwat }, -{ IDN_SMR_BUFSIZE_MIN, - IDN_SMR_BUFSIZE_MAX, - IDN_SMR_BUFSIZE_DEF, - "idn_smr_bufsize", &idn_smr_bufsize }, -{ 4, 1024, 32, "idn_slab_bufcount", &idn_slab_bufcount }, -{ 0, 10, 0, "idn_slab_prealloc", &idn_slab_prealloc }, -{ 2, MAX_DOMAINS, - 8, "idn_slab_mintotal", &idn_slab_mintotal }, -{ 8, 256, 64, "idn_window_max", &idn_window_max }, -{ 0, 32, 8, "idn_window_incr", &idn_window_incr }, -{ 1, 128, 5, "idn_reclaim_min", &idn_reclaim_min }, -{ 0, 128, 0, "idn_reclaim_max", &idn_reclaim_max }, -{ 1, IDN_MAXMAX_NETS, - 8, "idn_max_nets", &idn_max_nets }, -{ 31, 511, 127, "idn_mbox_per_net", &idn_mbox_per_net }, -{ 0, 1, 1, "idn_checksum", &idn_checksum }, -{ 0, 10000, 500, "idn_netsvr_spin_count", - &idn_netsvr_spin_count }, -{ 0, 30*100, 40, "idn_netsvr_wait_min", &idn_netsvr_wait_min }, -{ 0, 60*100, 16*100, "idn_netsvr_wait_max", &idn_netsvr_wait_max }, -{ 1, 5, 1, "idn_netsvr_wait_shift", - &idn_netsvr_wait_shift }, -{ 1, MAX_DOMAINS, - IDN_PROTOCOL_NSERVERS, - "idn_protocol_nservers", - &idn_protocol_nservers }, -{ 0, 3600, IDN_AWOLMSG_INTERVAL, - "idn_awolmsg_interval", &idn_awolmsg_interval }, -{ 10, 300, IDN_MSGWAIT_NEGO, - "idn_msgwait_nego", &idn_msgwait_nego }, -{ 10, 300, IDN_MSGWAIT_CFG, - "idn_msgwait_cfg", &idn_msgwait_cfg }, -{ 10, 300, IDN_MSGWAIT_CON, - "idn_msgwait_con", &idn_msgwait_con }, -{ 10, 300, IDN_MSGWAIT_FIN, - "idn_msgwait_fin", &idn_msgwait_fin }, -{ 10, 300, IDN_MSGWAIT_CMD, - "idn_msgwait_cmd", &idn_msgwait_cmd }, -{ 10, 300, IDN_MSGWAIT_DATA, - "idn_msgwait_data", &idn_msgwait_data }, -{ 1, 60, IDN_RETRYFREQ_NEGO, - "idn_retryfreq_nego", &idn_retryfreq_nego }, -{ 1, 60, IDN_RETRYFREQ_CON, - "idn_retryfreq_con", &idn_retryfreq_con }, -{ 1, 60, IDN_RETRYFREQ_FIN, - "idn_retryfreq_fin", &idn_retryfreq_fin }, -{ 1, 9, IDN_PIL, - "idn_pil", &idn_pil }, -{ 1, 9, IDN_SIGBPIL, - "idn_sigbpil", &idn_sigbpil }, -{ 8, 512, IDN_DMV_PENDING_MAX, - "idn_dmv_pending_max", &idn_dmv_pending_max }, -{ 0, 0, 0, NULL, NULL } -}; - -struct idn *idn_i2s_table[IDN_MAXMAX_NETS << 1]; -clock_t idn_msg_waittime[IDN_NUM_MSGTYPES]; -clock_t idn_msg_retrytime[(int)IDN_NUM_RETRYTYPES]; - -static caddr_t idn_ndlist; /* head of 'named dispatch' var list */ - -static int idnattach(dev_info_t *, ddi_attach_cmd_t); -static int idndetach(dev_info_t *, ddi_detach_cmd_t); -static int idnopen(register queue_t *, dev_t *, int, int, cred_t *); -static int idnclose(queue_t *, int, cred_t *); -static int idnwput(queue_t *, mblk_t *); -static int idnwsrv(queue_t *); -static int idnrput(queue_t *, mblk_t *); -static void idnioctl(queue_t *, mblk_t *); -static idn_gprops_t idn_check_conf(dev_info_t *dip, processorid_t *cpuid); -static int idn_size_check(); -static void idn_xmit_monitor_init(); -static void idn_xmit_monitor_deinit(); -static void idn_init_msg_waittime(); -static void idn_init_msg_retrytime(); -static void idn_sigb_setup(cpu_sgnblk_t *sigbp, void *arg); -static int idn_init(dev_info_t *dip); -static int idn_deinit(); -static void idn_sigbhandler_create(); -static void idn_sigbhandler_kill(); -static uint_t idn_sigbhandler_wakeup(caddr_t arg1, caddr_t arg2); -static void idn_sigbhandler_thread(struct sigbintr **sbpp); -static void idn_sigbhandler(processorid_t cpuid, cpu_sgnblk_t *sgnblkp); -static int idn_info(idnsb_info_t *sfp); -static int idn_init_smr(); -static void idn_deinit_smr(); -static int idn_prom_getsmr(uint_t *smrsz, uint64_t *paddrp, - uint64_t *sizep); -static int idn_init_handler(); -static void idn_deinit_handler(); -static uint_t idn_handler(caddr_t unused, caddr_t unused2); -/* - * ioctl services - */ -static int idnioc_link(idnop_t *idnop); -static int idnioc_unlink(idnop_t *idnop); -static int idn_rw_mem(idnop_t *idnop); -static int idn_send_ping(idnop_t *idnop); - -static void idn_domains_init(struct hwconfig *local_hw); -static void idn_domains_deinit(); -static void idn_retrytask_init(); -static void idn_retrytask_deinit(); -static void idn_gkstat_init(); -static void idn_gkstat_deinit(); -static int idn_gkstat_update(); -static void idn_timercache_init(); -static void idn_timercache_deinit(); -static void idn_dopers_init(); -static void idn_dopers_deinit(); - -static void idn_param_cleanup(); -static int idn_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr); -static int idn_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, - cred_t *cr); -static int idn_param_register(register idnparam_t *idnpa, int count); -static int idn_slabpool_report(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static int idn_buffer_report(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static int idn_mboxtbl_report(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static int idn_mainmbox_report(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static void idn_mainmbox_domain_report(queue_t *wq, mblk_t *mp, int domid, - idn_mainmbox_t *mmp, char *mbxtype); -static int idn_global_report(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static int idn_domain_report(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static int idn_get_net_binding(queue_t *wq, mblk_t *mp, caddr_t cp, - cred_t *cr); -static int idn_set_net_binding(queue_t *wq, mblk_t *mp, char *value, - caddr_t cp, cred_t *cr); - -/* - * String definitions used for DEBUG and non-DEBUG. - */ -const char *idnm_str[] = { -/* 0 */ "null", -/* 1 */ "nego", -/* 2 */ "con", -/* 3 */ "cfg", -/* 4 */ "fin", -/* 5 */ "cmd", -/* 6 */ "data", -}; - -const char *idnds_str[] = { -/* 0 */ "CLOSED", -/* 1 */ "NEGO_PEND", -/* 2 */ "NEGO_SENT", -/* 3 */ "NEGO_RCVD", -/* 4 */ "CONFIG", -/* 5 */ "CON_PEND", -/* 6 */ "CON_SENT", -/* 7 */ "CON_RCVD", -/* 8 */ "CON_READY", -/* 9 */ "CONNECTED", -/* 10 */ "FIN_PEND", -/* 11 */ "FIN_SENT", -/* 12 */ "FIN_RCVD", -/* 13 */ "DMAP" -}; - -const char *idnxs_str[] = { -/* 0 */ "PEND", -/* 1 */ "SENT", -/* 2 */ "RCVD", -/* 3 */ "FINAL", -/* 4 */ "NIL" -}; - -const char *idngs_str[] = { -/* 0 */ "OFFLINE", -/* 1 */ "CONNECT", -/* 2 */ "ONLINE", -/* 3 */ "DISCONNECT", -/* 4 */ "RECONFIG", -/* 5 */ "unknown", -/* 6 */ "unknown", -/* 7 */ "unknown", -/* 8 */ "unknown", -/* 9 */ "unknown", -/* 10 */ "IGNORE" -}; - -const char *idncmd_str[] = { -/* 0 */ "unknown", -/* 1 */ "SLABALLOC", -/* 2 */ "SLABFREE", -/* 3 */ "SLABREAP", -/* 4 */ "NODENAME" -}; - -const char *idncon_str[] = { -/* 0 */ "OFF", -/* 1 */ "NORMAL", -/* 2 */ "QUERY" -}; - -const char *idnfin_str[] = { -/* 0 */ "OFF", -/* 1 */ "NORMAL", -/* 2 */ "FORCE_SOFT", -/* 3 */ "FORCE_HARD", -/* 4 */ "QUERY" -}; - -const char *idnfinopt_str[] = { -/* 0 */ "NONE", -/* 1 */ "UNLINK", -/* 2 */ "RELINK" -}; - -const char *idnfinarg_str[] = { -/* 0 */ "NONE", -/* 1 */ "SMRBAD", -/* 2 */ "CPUCFG", -/* 3 */ "HWERR", -/* 4 */ "CFGERR_FATAL", -/* 5 */ "CFGERR_MTU", -/* 6 */ "CFGERR_BUF", -/* 7 */ "CFGERR_SLAB", -/* 8 */ "CFGERR_NWR", -/* 9 */ "CFGERR_NETS", -/* 10 */ "CFGERR_MBOX", -/* 11 */ "CFGERR_NMCADR", -/* 12 */ "CFGERR_MCADR", -/* 13 */ "CFGERR_CKSUM", -/* 14 */ "CFGERR_SMR", -}; - -const char *idnsync_str[] = { -/* 0 */ "NIL", -/* 1 */ "CONNECT", -/* 2 */ "DISCONNECT" -}; - -const char *idnreg_str[] = { -/* 0 */ "REG", -/* 1 */ "NEW", -/* 2 */ "QUERY" -}; - -const char *idnnack_str[] = { -/* 0 */ "unknown", -/* 1 */ "NOCONN", -/* 2 */ "BADCHAN", -/* 3 */ "BADCFG", -/* 4 */ "BADCMD", -/* 5 */ "RETRY", -/* 6 */ "DUP", -/* 7 */ "EXIT", -/* 8 */ "--reserved1", -/* 9 */ "--reserved2", -/* 10 */ "--reserved3" -}; - -const char *idnop_str[] = { -/* 0 */ "DISCONNECTED", -/* 1 */ "CONNECTED", -/* 2 */ "ERROR" -}; - -const char *chanop_str[] = { -/* 0 */ "OPEN", -/* 1 */ "SOFT_CLOSE", -/* 2 */ "HARD_CLOSE", -/* 3 */ "OFFLINE", -/* 4 */ "ONLINE" -}; - -const char *chanaction_str[] = { -/* 0 */ "DETACH", -/* 1 */ "STOP", -/* 2 */ "SUSPEND", -/* 3 */ "RESUME", -/* 4 */ "RESTART", -/* 5 */ "ATTACH" -}; - -const char *timer_str[] = { -/* 0 */ "NIL", -/* 1 */ "MSG" -}; - -static struct module_info idnrinfo = { - IDNIDNUM, /* mi_idnum */ - IDNNAME, /* mi_idname */ - IDNMINPSZ, /* mi_minpsz */ - IDNMAXPSZ, /* mi_maxpsz */ - 0, /* mi_hiwat - see IDN_HIWAT */ - 0 /* mi_lowat - see IDN_LOWAT */ -}; - -static struct module_info idnwinfo = { - IDNIDNUM, /* mi_idnum */ - IDNNAME, /* mi_idname */ - IDNMINPSZ, /* mi_minpsz */ - IDNMAXPSZ, /* mi_maxpsz */ - 0, /* mi_hiwat - see IDN_HIWAT */ - 0 /* mi_lowat - see IDN_LOWAT */ -}; - -static struct qinit idnrinit = { - idnrput, /* qi_putp */ - NULL, /* qi_srvp */ - idnopen, /* qi_qopen */ - idnclose, /* qi_qclose */ - NULL, /* qi_qadmin */ - &idnrinfo, /* qi_minfo */ - NULL, /* qi_mstat */ - NULL, /* qi_rwp */ - NULL, /* qi_infop */ - STRUIOT_DONTCARE /* qi_struiot */ -}; - -static struct qinit idnwinit = { - idnwput, /* qi_putp */ - idnwsrv, /* qi_srvp */ - NULL, /* qi_qopen */ - NULL, /* qi_qclose */ - NULL, /* qi_qadmin */ - &idnwinfo, /* qi_minfo */ - NULL, /* qi_mstat */ - NULL, /* qi_rwp */ - NULL, /* qi_infop */ - STRUIOT_DONTCARE /* qi_struiot */ -}; - -struct streamtab idninfo = { - &idnrinit, /* st_rdinit */ - &idnwinit, /* st_wrinit */ - NULL, /* st_muxrinit */ - NULL, /* st_muxwinit */ -}; - -/* - * Module linkage information (cb_ops & dev_ops) for the kernel. - */ - -static struct cb_ops cb_idnops = { - nulldev, /* cb_open */ - nulldev, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - nodev, /* cb_read */ - nodev, /* cb_write */ - nodev, /* cb_ioctl */ - nodev, /* cb_devmap */ - nodev, /* cb_mmap */ - nodev, /* cb_segmap */ - nochpoll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - &idninfo, /* cb_stream */ - D_MP, /* cb_flag */ - CB_REV, /* cb_rev */ - nodev, /* cb_aread */ - nodev, /* cb_awrite */ -}; - -static struct dev_ops idnops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - ddi_no_info, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - idnattach, /* devo_attach */ - idndetach, /* devo_detach */ - nodev, /* devo_reset */ - &cb_idnops, /* devo_cb_ops */ - (struct bus_ops *)NULL, /* devo_bus_ops */ - NULL, /* devo_power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -extern cpuset_t cpu_ready_set; - -static struct modldrv modldrv = { - &mod_driverops, /* This module is a pseudo driver */ - IDNDESC " 1.58", - &idnops -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -/* - * -------------------------------------------------- - */ -int -_init(void) -{ - idn.version = IDN_VERSION; - - return (mod_install(&modlinkage)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* - * ---------------------------------------------- - */ -static int -idnattach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int instance; - int doinit = 0; - processorid_t bcpuid; - struct idn *sip; - struct idnstr *stp; - procname_t proc = "idnattach"; - - -#ifndef lint - ASSERT(sizeof (idnsb_t) == IDNSB_SIZE); - ASSERT(offsetof(struct idnsb, id_hwchkpt[0]) == 0x40); -#endif /* lint */ - - switch (cmd) { - case DDI_RESUME: - sip = ddi_get_driver_private(dip); - /* - * sip may have not yet been set if the - * OBP environment variable (idn-smr-size) - * was not set. - */ - if (sip == NULL) - return (DDI_FAILURE); - /* - * RESUME IDN services. - */ - IDN_GLOCK_SHARED(); - if (idn.state != IDNGS_OFFLINE) { - cmn_err(CE_WARN, - "IDN: 101: not in expected OFFLINE state " - "for DDI_RESUME"); - ASSERT(0); - } - IDN_GUNLOCK(); - - /* - * RESUME DLPI services. - */ - sip->si_flags &= ~IDNSUSPENDED; - - rw_enter(&idn.struprwlock, RW_READER); - for (stp = idn.strup; stp; stp = stp->ss_nextp) - if (stp->ss_sip == sip) { - doinit = 1; - break; - } - rw_exit(&idn.struprwlock); - if (doinit) - (void) idndl_init(sip); - - return (DDI_SUCCESS); - - case DDI_ATTACH: - break; - - default: - return (DDI_FAILURE); - } - - instance = ddi_get_instance(dip); - - PR_DRV("%s: instance = %d\n", proc, instance); - - if (idn_check_conf(dip, &bcpuid) == IDN_GPROPS_ERROR) - return (DDI_FAILURE); - - mutex_enter(&idn.siplock); - - if (ddi_create_minor_node(dip, IDNNAME, S_IFCHR, instance, - DDI_NT_NET, CLONE_DEV) == DDI_FAILURE) { - mutex_exit(&idn.siplock); - return (DDI_FAILURE); - } - - if (idn.smr.ready == 0) { - if (idn_init_smr() == 0) { - idn.enabled = 1; -#ifdef DEBUG - cmn_err(CE_NOTE, "!IDN: Driver enabled"); -#endif /* DEBUG */ - } else { - cmn_err(CE_NOTE, - "!IDN: 102: driver disabled " - "- check OBP environment " - "(idn-smr-size)"); - mutex_exit(&idn.siplock); - return (DDI_SUCCESS); - } - } - - ASSERT(idn.smr.ready || idn.enabled); - - if (idn.dip == NULL) { - doinit = 1; - - if (idn_size_check()) { - idn_deinit_smr(); - ddi_remove_minor_node(dip, NULL); - mutex_exit(&idn.siplock); - return (DDI_FAILURE); - } - - if (idn_init(dip)) { - idn_deinit_smr(); - ddi_remove_minor_node(dip, NULL); - mutex_exit(&idn.siplock); - return (DDI_FAILURE); - } - } - - ASSERT(idn.dip); - - /* - * This must occur _after_ idn_init() since - * it assumes idn_chanservers_init() has been - * called. - */ - idn_chanserver_bind(ddi_get_instance(dip), bcpuid); - - /* - * DLPI supporting stuff. - */ - sip = GETSTRUCT(struct idn, 1); - sip->si_dip = dip; - ddi_set_driver_private(dip, sip); - sip->si_nextp = idn.sip; - idn.sip = sip; - IDN_SET_INST2SIP(instance, sip); - mutex_exit(&idn.siplock); - - if (doinit) - idndl_dlpi_init(); /* initializes idninfoack */ - /* - * Get our local IDN ethernet address. - */ - idndl_localetheraddr(sip, &sip->si_ouraddr); - idndl_statinit(sip); - - if (doinit) { - idn_gkstat_init(); - /* - * Add our sigblock SSP interrupt handler. - */ - mutex_enter(&idn.sigbintr.sb_mutex); - idn_sigbhandler_create(); - mutex_exit(&idn.sigbintr.sb_mutex); - - if (sgnblk_poll_register(idn_sigbhandler) == 0) { - mutex_enter(&idn.sigbintr.sb_mutex); - idn_sigbhandler_kill(); - idn.sigbintr.sb_cpuid = (uchar_t)-1; - idn.sigbintr.sb_busy = IDNSIGB_INACTIVE; - mutex_exit(&idn.sigbintr.sb_mutex); - - idn_gkstat_deinit(); - - mutex_enter(&idn.siplock); - (void) idn_deinit(); - IDN_SET_INST2SIP(instance, NULL); - idn.sip = sip->si_nextp; - mutex_exit(&idn.siplock); - - ddi_remove_minor_node(dip, NULL); - - return (DDI_FAILURE); - } - /* - * We require sigblkp[cpu0] to be mapped for hardware - * configuration determination and also auto-linking - * on bootup. - */ - if (sgnblk_poll_reference(idn_sigb_setup, NULL) != 0) { - (void) sgnblk_poll_unregister(idn_sigbhandler); - mutex_enter(&idn.sigbintr.sb_mutex); - idn_sigbhandler_kill(); - idn.sigbintr.sb_cpuid = (uchar_t)-1; - idn.sigbintr.sb_busy = IDNSIGB_INACTIVE; - mutex_exit(&idn.sigbintr.sb_mutex); - - idn_gkstat_deinit(); - - mutex_enter(&idn.siplock); - (void) idn_deinit(); - IDN_SET_INST2SIP(instance, NULL); - idn.sip = sip->si_nextp; - mutex_exit(&idn.siplock); - - ddi_remove_minor_node(dip, NULL); - - cmn_err(CE_WARN, - "IDN: 103: unable to reference sigblock area"); - - return (DDI_FAILURE); - } - - idn_init_autolink(); - } - - ddi_report_dev(dip); - - return (DDI_SUCCESS); -} - -/* - * ---------------------------------------------- - */ -static int -idndetach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - int err = 0; - int instance; - struct idn *sip, *hsip, *tsip; - procname_t proc = "idndetach"; - - sip = ddi_get_driver_private(dip); - instance = ddi_get_instance(dip); - - switch (cmd) { - case DDI_SUSPEND: - if (sip == NULL) - return (DDI_FAILURE); - /* - * SUSPEND IDN services. - * - Actually don't suspend anything, we just - * make sure we're not connected per DR protocol. - * If we really wanted to suspend it should - * be done _after_ DLPI is suspended so that - * we're not competing with that traffic. - */ - IDN_GLOCK_SHARED(); - - if (idn.state != IDNGS_OFFLINE) { - int d; - - cmn_err(CE_WARN, - "IDN: 104: cannot suspend while active " - "(state = %s)", - idngs_str[idn.state]); - - for (d = 0; d < MAX_DOMAINS; d++) { - idn_domain_t *dp; - - dp = &idn_domain[d]; - if (dp->dcpu < 0) - continue; - - cmn_err(CE_CONT, - "IDN: 121: domain %d (CPU %d, name " - "\"%s\", state %s)\n", - d, dp->dcpu, dp->dname, - idnds_str[dp->dstate]); - } - err = 1; - } - - IDN_GUNLOCK(); - - if (err) - return (DDI_FAILURE); - /* - * SUSPEND DLPI services. - */ - sip->si_flags |= IDNSUSPENDED; - - idndl_uninit(sip); - - return (DDI_FAILURE); - - case DDI_DETACH: - if (idn.enabled == 0) { - ddi_remove_minor_node(dip, NULL); - ASSERT(idn.dip == NULL); - return (DDI_SUCCESS); - } - if (!IDN_MODUNLOADABLE) - return (DDI_FAILURE); - break; - - default: - return (DDI_FAILURE); - } - - PR_DRV("%s: instance = %d\n", proc, instance); - - if (sip == NULL) { - /* - * No resources allocated. - */ - return (DDI_SUCCESS); - } - - mutex_enter(&idn.siplock); - if (idn.sip && (idn.sip->si_nextp == NULL)) { - /* - * This is our last stream connection - * going away. Time to deinit and flag - * the SSP we're (IDN) DOWN. - */ - if (idn_deinit()) { - /* - * Must still be active. - */ - mutex_exit(&idn.siplock); - return (DDI_FAILURE); - } - idn_deinit_autolink(); - /* - * Remove our sigblock SSP interrupt handler. - */ - (void) sgnblk_poll_unregister(idn_sigbhandler); - mutex_enter(&idn.sigbintr.sb_mutex); - idn_sigbhandler_kill(); - idn.sigbintr.sb_cpuid = (uchar_t)-1; - idn.sigbintr.sb_busy = IDNSIGB_NOTREADY; - mutex_exit(&idn.sigbintr.sb_mutex); - /* - * Remove our reference to the sigblock area. - */ - sgnblk_poll_unreference(idn_sigb_setup); - idn_gkstat_deinit(); - } - - ddi_remove_minor_node(dip, NULL); - - /* - * Remove this instance from our linked list. - */ - IDN_SET_INST2SIP(instance, NULL); - if ((hsip = tsip = idn.sip) == sip) { - idn.sip = sip->si_nextp; - } else { - for (; hsip && (sip != hsip); tsip = hsip, - hsip = hsip->si_nextp) - ; - if (hsip) - tsip->si_nextp = hsip->si_nextp; - } - mutex_exit(&idn.siplock); - if (sip->si_ksp) - kstat_delete(sip->si_ksp); - - ddi_set_driver_private(dip, NULL); - - FREESTRUCT(sip, struct idn, 1); - - return (DDI_SUCCESS); -} - -/* - * ---------------------------------------------- - */ -static idn_gprops_t -idn_check_conf(dev_info_t *dip, processorid_t *cpuid) -{ - static idn_gprops_t global_props = IDN_GPROPS_UNCHECKED; - - if (global_props == IDN_GPROPS_UNCHECKED) { - int p; - - global_props = IDN_GPROPS_OKAY; - - for (p = 0; idn_global_props[p].p_string; p++) { - char *str; - int *var; - int val, v_min, v_max, v_def; - - str = idn_global_props[p].p_string; - var = (int *)idn_global_props[p].p_var; - v_min = idn_global_props[p].p_min; - v_max = idn_global_props[p].p_max; - v_def = idn_global_props[p].p_def; - ASSERT(str && var); - - val = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS | - DDI_PROP_NOTPROM, - str, v_def); - if ((v_min != v_max) && - ((val < v_min) || (val > v_max))) { - cmn_err(CE_WARN, - "IDN: 105: driver parameter " - "(%s) specified (%d) out of " - "range [%d - %d]", - str, val, v_min, v_max); - global_props = IDN_GPROPS_ERROR; - } else { - *var = val; - } - } - } - - *cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - "bind_cpu", -1); - - return (global_props); -} - -static int -idn_size_check() -{ - int i, cnt; - int rv = 0; - ulong_t mboxareasize; - int max_num_slabs; - procname_t proc = "idn_size_check"; - - if (IDN_NWR_SIZE == 0) - IDN_NWR_SIZE = IDN_SMR_SIZE; - - if (IDN_NWR_SIZE > IDN_SMR_SIZE) { - cmn_err(CE_WARN, - "IDN: 106: idn_nwr_size(%d) > idn_smr_size(%d)" - " - Limiting to %d MB", - IDN_NWR_SIZE, IDN_SMR_SIZE, IDN_SMR_SIZE); - IDN_NWR_SIZE = IDN_SMR_SIZE; - } - - if (MB2B(IDN_NWR_SIZE) < IDN_SLAB_SIZE) { - cmn_err(CE_WARN, - "IDN: 107: memory region(%lu) < slab size(%u)", - MB2B(IDN_NWR_SIZE), IDN_SLAB_SIZE); - rv = -1; - } - - if (IDN_LOWAT >= IDN_HIWAT) { - cmn_err(CE_WARN, - "IDN: 108: idn_lowat(%d) >= idn_hiwat(%d)", - IDN_LOWAT, IDN_HIWAT); - rv = -1; - } - - mboxareasize = (ulong_t)(IDN_MBOXAREA_SIZE + (IDN_SMR_BUFSIZE - 1)); - mboxareasize &= ~((ulong_t)IDN_SMR_BUFSIZE - 1); -#ifdef DEBUG - if ((ulong_t)IDN_SLAB_SIZE < mboxareasize) { - PR_DRV("%s: slab size(%d) < mailbox area(%ld)", - proc, IDN_SLAB_SIZE, mboxareasize); - /* not fatal */ - } -#endif /* DEBUG */ - - if ((mboxareasize + (ulong_t)IDN_SLAB_SIZE) > MB2B(IDN_NWR_SIZE)) { - cmn_err(CE_WARN, - "IDN: 109: mailbox area(%lu) + slab size(%u) " - "> nwr region(%lu)", - mboxareasize, IDN_SLAB_SIZE, - MB2B(IDN_NWR_SIZE)); - rv = -1; - } - - max_num_slabs = (int)((MB2B(IDN_NWR_SIZE) - mboxareasize) / - (ulong_t)IDN_SLAB_SIZE); - if (max_num_slabs < IDN_SLAB_MINTOTAL) { - cmn_err(CE_WARN, - "IDN: 110: maximum number of slabs(%d) < " - "minimum required(%d)", - max_num_slabs, IDN_SLAB_MINTOTAL); - rv = -1; - } else { - IDN_SLAB_MAXPERDOMAIN = max_num_slabs / IDN_SLAB_MINTOTAL; - } - -#if 0 - if ((IDN_MTU + sizeof (struct ether_header)) > IDN_DATA_SIZE) { - cmn_err(CE_WARN, - "IDN: (IDN_MTU(%d) + ether_header(%d)) " - "> IDN_DATA_SIZE(%lu)", - IDN_MTU, sizeof (struct ether_header), - IDN_DATA_SIZE); - rv = -1; - } -#endif /* 0 */ - - if (IDN_SMR_BUFSIZE & (IDN_ALIGNSIZE - 1)) { - cmn_err(CE_WARN, - "IDN: 111: idn_smr_bufsize(%d) not on a " - "64 byte boundary", IDN_SMR_BUFSIZE); - rv = -1; - } - - for (i = cnt = 0; - (cnt <= 1) && (((ulong_t)1 << i) < MB2B(IDN_NWR_SIZE)); - i++) - if ((1 << i) & IDN_SMR_BUFSIZE) - cnt++; - if ((i > 0) && (!cnt || (cnt > 1))) { - cmn_err(CE_WARN, - "IDN: 112: idn_smr_bufsize(%d) not a power of 2", - IDN_SMR_BUFSIZE); - rv = -1; - } - - if ((IDN_MBOX_PER_NET & 1) == 0) { - cmn_err(CE_WARN, - "IDN: 113: idn_mbox_per_net(%d) must be an " - "odd number", IDN_MBOX_PER_NET); - rv = -1; - } - - if (idn.nchannels > 0) - IDN_WINDOW_EMAX = IDN_WINDOW_MAX + - ((idn.nchannels - 1) * IDN_WINDOW_INCR); - - if (IDN_NETSVR_WAIT_MIN > IDN_NETSVR_WAIT_MAX) { - cmn_err(CE_WARN, - "IDN: 115: idn_netsvr_wait_min(%d) cannot be " - "greater than idn_netsvr_wait_max(%d)", - IDN_NETSVR_WAIT_MIN, - IDN_NETSVR_WAIT_MAX); - rv = -1; - } - - return (rv); -} - -static int -idn_init_smr() -{ - uint64_t obp_paddr; - uint64_t obp_size; /* in Bytes */ - uint_t smr_size; /* in MBytes */ - pgcnt_t npages; - procname_t proc = "idn_init_smr"; - - if (idn.smr.ready) - return (0); - - if (idn_prom_getsmr(&smr_size, &obp_paddr, &obp_size) < 0) - return (-1); - - PR_PROTO("%s: smr_size = %d, obp_paddr = 0x%lx, obp_size = 0x%lx\n", - proc, smr_size, obp_paddr, obp_size); - - if (IDN_SMR_SIZE) - smr_size = MIN(smr_size, IDN_SMR_SIZE); - - npages = btopr(MB2B(smr_size)); - - idn.smr.prom_paddr = obp_paddr; - idn.smr.prom_size = obp_size; - idn.smr.vaddr = vmem_alloc(heap_arena, ptob(npages), VM_SLEEP); - ASSERT(((ulong_t)idn.smr.vaddr & MMU_PAGEOFFSET) == 0); - idn.smr.locpfn = (pfn_t)(obp_paddr >> MMU_PAGESHIFT); - idn.smr.rempfn = idn.smr.rempfnlim = PFN_INVALID; - IDN_SMR_SIZE = smr_size; - - PR_PROTO("%s: smr vaddr = %p\n", proc, (void *)idn.smr.vaddr); - - smr_remap(&kas, idn.smr.vaddr, idn.smr.locpfn, IDN_SMR_SIZE); - - idn.localid = PADDR_TO_DOMAINID(obp_paddr); - - idn.smr.ready = 1; - - return (0); -} - -static void -idn_deinit_smr() -{ - pgcnt_t npages; - - if (idn.smr.ready == 0) - return; - - smr_remap(&kas, idn.smr.vaddr, PFN_INVALID, IDN_SMR_SIZE); - - npages = btopr(MB2B(IDN_SMR_SIZE)); - - vmem_free(heap_arena, idn.smr.vaddr, ptob(npages)); - - idn.localid = IDN_NIL_DOMID; - - IDN_SMR_SIZE = 0; - - idn.smr.ready = 0; -} - -/*ARGSUSED1*/ -static void -idn_sigb_setup(cpu_sgnblk_t *sigbp, void *arg) -{ - procname_t proc = "idn_sigb_setup"; - - PR_PROTO("%s: Setting sigb to %p\n", proc, (void *)sigbp); - - mutex_enter(&idn.idnsb_mutex); - if (sigbp == NULL) { - idn.idnsb = NULL; - idn.idnsb_eventp = NULL; - mutex_exit(&idn.idnsb_mutex); - return; - } - idn.idnsb_eventp = (idnsb_event_t *)sigbp->sigb_idn; - idn.idnsb = (idnsb_t *)&idn.idnsb_eventp->idn_reserved1; - mutex_exit(&idn.idnsb_mutex); -} - -static int -idn_init(dev_info_t *dip) -{ - struct hwconfig local_hw; - procname_t proc = "idn_init"; - - - ASSERT(MUTEX_HELD(&idn.siplock)); - - if (!idn.enabled) { - cmn_err(CE_WARN, - "IDN: 117: IDN not enabled"); - return (-1); - } - - if (idn.dip != NULL) { - PR_DRV("%s: already initialized (dip = 0x%p)\n", - proc, (void *)idn.dip); - return (0); - } - - /* - * Determine our local domain's hardware configuration. - */ - if (get_hw_config(&local_hw)) { - cmn_err(CE_WARN, - "IDN: 118: hardware config not appropriate"); - return (-1); - } - - PR_DRV("%s: locpfn = 0x%lx\n", proc, idn.smr.locpfn); - PR_DRV("%s: rempfn = 0x%lx\n", proc, idn.smr.rempfn); - PR_DRV("%s: smrsize = %d MB\n", proc, IDN_SMR_SIZE); - - rw_init(&idn.grwlock, NULL, RW_DEFAULT, NULL); - rw_init(&idn.struprwlock, NULL, RW_DEFAULT, NULL); - mutex_init(&idn.sync.sz_mutex, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&idn.sipwenlock, NULL, MUTEX_DEFAULT, NULL); - - /* - * Calculate proper value for idn.bframe_shift. - * Kind of hokey as it assume knowledge of the format - * of the idnparam_t structure. - */ - { - int s; - - for (s = 0; (1 << s) < IDN_SMR_BUFSIZE_MIN; s++) - ; - idn.bframe_shift = s; - PR_DRV("%s: idn.bframe_shift = %d, minbuf = %d\n", - proc, idn.bframe_shift, IDN_SMR_BUFSIZE_MIN); - - ASSERT((uint_t)IDN_OFFSET2BFRAME(MB2B(idn_smr_size)) < - (1 << 24)); - } - - idn_xmit_monitor_init(); - - /* - * Initialize the domain op (dopers) stuff. - */ - idn_dopers_init(); - - /* - * Initialize the timer (kmem) cache used for timeout - * structures. - */ - idn_timercache_init(); - - /* - * Initialize the slab waiting areas. - */ - (void) smr_slabwaiter_init(); - - /* - * Initialize retryjob kmem cache. - */ - idn_retrytask_init(); - - idn_init_msg_waittime(); - idn_init_msg_retrytime(); - - /* - * Initialize idn_domains[] and local domains information - * include idn_global information. - */ - idn_domains_init(&local_hw); - - /* - * Start up IDN protocol servers. - */ - if (idn_protocol_init(idn_protocol_nservers) <= 0) { - cmn_err(CE_WARN, - "IDN: 119: failed to initialize %d protocol servers", - idn_protocol_nservers); - idn_domains_deinit(); - idn_retrytask_deinit(); - smr_slabwaiter_deinit(); - idn_timercache_deinit(); - idn_dopers_deinit(); - idn_xmit_monitor_deinit(); - mutex_destroy(&idn.sipwenlock); - mutex_destroy(&idn.sync.sz_mutex); - rw_destroy(&idn.grwlock); - rw_destroy(&idn.struprwlock); - return (-1); - } - - /* - * Initialize chan_servers array. - */ - (void) idn_chanservers_init(); - - /* - * Need to register the IDN handler with the DMV subsystem. - * - * Need to prevent the IDN driver from being unloaded - * once loaded since DMV's may come in at any time. - * If the driver is not loaded and the idn_dmv_handler - * has been registered with the DMV, system will crash. - */ - (void) idn_init_handler(); - - idn.dip = dip; - IDN_GLOCK_EXCL(); - IDN_GSTATE_TRANSITION(IDNGS_OFFLINE); - IDN_GUNLOCK(); - - return (0); -} - -static int -idn_deinit() -{ - procname_t proc = "idn_deinit"; - - ASSERT(MUTEX_HELD(&idn.siplock)); - - IDN_GLOCK_EXCL(); - - if (idn.state != IDNGS_OFFLINE) { - int d; - - cmn_err(CE_WARN, - "IDN: 120: cannot deinit while active " - "(state = %s)", idngs_str[idn.state]); - - for (d = 0; d < MAX_DOMAINS; d++) { - idn_domain_t *dp; - - dp = &idn_domain[d]; - if (dp->dcpu < 0) - continue; - - cmn_err(CE_CONT, - "IDN: 121: domain %d (CPU %d, " - "name \"%s\", state %s)\n", - d, dp->dcpu, dp->dname, - idnds_str[dp->dstate]); - } - IDN_GUNLOCK(); - return (-1); - } - - if (idn.dip == NULL) { - PR_DRV("%s: already deinitialized\n", proc); - IDN_GUNLOCK(); - return (0); - } - - IDN_GSTATE_TRANSITION(IDNGS_IGNORE); - - IDN_GUNLOCK(); - - idn_xmit_monitor_deinit(); - - idn_deinit_handler(); - - idn_chanservers_deinit(); - - idn.nchannels = 0; - ASSERT(idn.chan_servers == NULL); - - smr_slabpool_deinit(); - - idn_protocol_deinit(); - - idn_domains_deinit(); - - smr_slabwaiter_deinit(); - - idn_retrytask_deinit(); - - idn_timercache_deinit(); - - idn_dopers_deinit(); - - ASSERT(idn.localid == IDN_NIL_DOMID); - - IDN_SET_MASTERID(IDN_NIL_DOMID); - - idn_deinit_smr(); - - mutex_destroy(&idn.sipwenlock); - mutex_destroy(&idn.sync.sz_mutex); - rw_destroy(&idn.grwlock); - rw_destroy(&idn.struprwlock); - - idn.dip = NULL; - - return (0); -} - -static void -idn_xmit_monitor_init() -{ - mutex_init(&idn.xmit_lock, NULL, MUTEX_DEFAULT, NULL); - idn.xmit_tid = (timeout_id_t)NULL; - CHANSET_ZERO(idn.xmit_chanset_wanted); -} - -static void -idn_xmit_monitor_deinit() -{ - timeout_id_t tid; - - mutex_enter(&idn.xmit_lock); - CHANSET_ZERO(idn.xmit_chanset_wanted); - if ((tid = idn.xmit_tid) != (timeout_id_t)NULL) { - idn.xmit_tid = (timeout_id_t)NULL; - mutex_exit(&idn.xmit_lock); - (void) untimeout(tid); - } else { - mutex_exit(&idn.xmit_lock); - } - mutex_destroy(&idn.xmit_lock); -} - -static void -idn_init_msg_waittime() -{ - idn_msg_waittime[IDNP_NULL] = -1; - idn_msg_waittime[IDNP_NEGO] = idn_msgwait_nego * hz; - idn_msg_waittime[IDNP_CFG] = idn_msgwait_cfg * hz; - idn_msg_waittime[IDNP_CON] = idn_msgwait_con * hz; - idn_msg_waittime[IDNP_FIN] = idn_msgwait_fin * hz; - idn_msg_waittime[IDNP_CMD] = idn_msgwait_cmd * hz; - idn_msg_waittime[IDNP_DATA] = idn_msgwait_data * hz; -} - -static void -idn_init_msg_retrytime() -{ - idn_msg_retrytime[(int)IDNRETRY_NIL] = -1; - idn_msg_retrytime[(int)IDNRETRY_NEGO] = idn_retryfreq_nego * hz; - idn_msg_retrytime[(int)IDNRETRY_CON] = idn_retryfreq_con * hz; - idn_msg_retrytime[(int)IDNRETRY_CONQ] = idn_retryfreq_con * hz; - idn_msg_retrytime[(int)IDNRETRY_FIN] = idn_retryfreq_fin * hz; - idn_msg_retrytime[(int)IDNRETRY_FINQ] = idn_retryfreq_fin * hz; -} - -/* - * ---------------------------------------------- - */ -/*ARGSUSED*/ -static int -idnopen(register queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *crp) -{ - register int err = 0; - int minordev; - struct idnstr *stp, **pstp; - procname_t proc = "idnopen"; - - ASSERT(sflag != MODOPEN); - - IDN_GLOCK_EXCL(); - - rw_enter(&idn.struprwlock, RW_WRITER); - mutex_enter(&idn.sipwenlock); - pstp = &idn.strup; - - if (idn.enabled == 0) { - PR_DRV("%s: Driver disabled (check OBP:idn-smr-size)\n", - proc); - mutex_exit(&idn.sipwenlock); - rw_exit(&idn.struprwlock); - IDN_GUNLOCK(); - return (EACCES); - } - - if (!idn_ndlist && - idn_param_register(idn_param_arr, A_CNT(idn_param_arr))) { - PR_DRV("%s: failed to register ndd parameters\n", proc); - mutex_exit(&idn.sipwenlock); - rw_exit(&idn.struprwlock); - IDN_GUNLOCK(); - return (ENOMEM); - } - IDN_GUNLOCK(); - - if (sflag == CLONEOPEN) { - minordev = 0; - for (stp = *pstp; stp; pstp = &stp->ss_nextp, stp = *pstp) { - if (minordev < stp->ss_minor) - break; - minordev++; - } - *devp = makedevice(getmajor(*devp), minordev); - } else { - minordev = getminor(*devp); - } - if (rq->q_ptr) - goto done; - - stp = GETSTRUCT(struct idnstr, 1); - stp->ss_rq = rq; - stp->ss_minor = minordev; - rw_init(&stp->ss_rwlock, NULL, RW_DEFAULT, NULL); - /* - * DLPI stuff - */ - stp->ss_sip = NULL; - stp->ss_state = DL_UNATTACHED; - stp->ss_sap = 0; - stp->ss_flags = 0; - stp->ss_mccount = 0; - stp->ss_mctab = NULL; - - /* - * Link new entry into list of actives. - */ - stp->ss_nextp = *pstp; - *pstp = stp; - - WR(rq)->q_ptr = rq->q_ptr = (void *)stp; - /* - * Disable automatic enabling of our write service - * procedure. We control this explicitly. - */ - noenable(WR(rq)); - - /* - * Set our STREAMs queue maximum packet size that - * we'll accept and our high/low water marks. - */ - (void) strqset(WR(rq), QMAXPSZ, 0, IDN_DATA_SIZE); - (void) strqset(WR(rq), QLOWAT, 0, IDN_LOWAT); - (void) strqset(WR(rq), QHIWAT, 0, IDN_HIWAT); - (void) strqset(rq, QMAXPSZ, 0, IDN_DATA_SIZE); - (void) strqset(rq, QLOWAT, 0, IDN_LOWAT); - (void) strqset(rq, QHIWAT, 0, IDN_HIWAT); - -done: - mutex_exit(&idn.sipwenlock); - rw_exit(&idn.struprwlock); - - (void) qassociate(rq, -1); - qprocson(rq); - - return (err); -} - -/* - * ---------------------------------------------- - */ -/*ARGSUSED1*/ -static int -idnclose(queue_t *rq, int flag, cred_t *crp) -{ - struct idnstr *stp, **pstp; - - ASSERT(rq->q_ptr); - - qprocsoff(rq); - /* - * Guaranteed to be single threaded with respect - * to this stream at this point. - */ - - stp = (struct idnstr *)rq->q_ptr; - - if (stp->ss_sip) - idndl_dodetach(stp); - - rw_enter(&idn.struprwlock, RW_WRITER); - mutex_enter(&idn.sipwenlock); - pstp = &idn.strup; - for (stp = *pstp; stp; pstp = &stp->ss_nextp, stp = *pstp) - if (stp == (struct idnstr *)rq->q_ptr) - break; - ASSERT(stp); - ASSERT(stp->ss_rq == rq); - *pstp = stp->ss_nextp; - - rw_destroy(&stp->ss_rwlock); - FREESTRUCT(stp, struct idnstr, 1); - - WR(rq)->q_ptr = rq->q_ptr = NULL; - mutex_exit(&idn.sipwenlock); - rw_exit(&idn.struprwlock); - - idn_param_cleanup(); - (void) qassociate(rq, -1); - - return (0); -} - -/* - * ---------------------------------------------- - */ -static int -idnwput(register queue_t *wq, register mblk_t *mp) -{ - register struct idnstr *stp; - struct idn *sip; - procname_t proc = "idnwput"; - - stp = (struct idnstr *)wq->q_ptr; - sip = stp->ss_sip; - - switch (DB_TYPE(mp)) { - case M_IOCTL: - idnioctl(wq, mp); - break; - - case M_DATA: - if (((stp->ss_flags & (IDNSFAST|IDNSRAW)) == 0) || - (stp->ss_state != DL_IDLE) || - (sip == NULL)) { - PR_DLPI("%s: fl=0x%x, st=0x%x, ret(EPROTO)\n", - proc, stp->ss_flags, stp->ss_state); - merror(wq, mp, EPROTO); - - } else if (wq->q_first) { - if (putq(wq, mp) == 0) - freemsg(mp); - /* - * We're only holding the reader lock, - * but that's okay since this field - * is just a soft-flag. - */ - sip->si_wantw = 1; - qenable(wq); - - } else if (sip->si_flags & IDNPROMISC) { - if (putq(wq, mp) == 0) { - PR_DLPI("%s: putq failed\n", proc); - freemsg(mp); - } else { - PR_DLPI("%s: putq succeeded\n", proc); - } - qenable(wq); - - } else { - PR_DLPI("%s: idndl_start(sip=0x%p)\n", - proc, (void *)sip); - rw_enter(&stp->ss_rwlock, RW_READER); - (void) idndl_start(wq, mp, sip); - rw_exit(&stp->ss_rwlock); - } - break; - - case M_PROTO: - case M_PCPROTO: - /* - * Break the association between the current thread - * and the thread that calls idndl_proto() to resolve - * the problem of idn_chan_server() threads which - * loop back around to call idndl_proto and try to - * recursively acquire internal locks. - */ - if (putq(wq, mp) == 0) - freemsg(mp); - qenable(wq); - break; - - case M_FLUSH: - PR_STR("%s: M_FLUSH request (flush = %d)\n", - proc, (int)*mp->b_rptr); - if (*mp->b_rptr & FLUSHW) { - flushq(wq, FLUSHALL); - *mp->b_rptr &= ~FLUSHW; - } - if (*mp->b_rptr & FLUSHR) - qreply(wq, mp); - else - freemsg(mp); - break; - - default: - PR_STR("%s: unexpected DB_TYPE 0x%x\n", - proc, DB_TYPE(mp)); - freemsg(mp); - break; - } - - return (0); -} - -/* - * ---------------------------------------------- - */ -static int -idnwsrv(queue_t *wq) -{ - mblk_t *mp; - int err = 0; - struct idnstr *stp; - struct idn *sip; - procname_t proc = "idnwsrv"; - - stp = (struct idnstr *)wq->q_ptr; - sip = stp->ss_sip; - - while (mp = getq(wq)) { - switch (DB_TYPE(mp)) { - case M_DATA: - if (sip) { - PR_DLPI("%s: idndl_start(sip=0x%p)\n", - proc, (void *)sip); - rw_enter(&stp->ss_rwlock, RW_READER); - err = idndl_start(wq, mp, sip); - rw_exit(&stp->ss_rwlock); - if (err) - goto done; - } else { - PR_DLPI("%s: NO sip to start msg\n", proc); - freemsg(mp); - } - break; - - case M_PROTO: - case M_PCPROTO: - idndl_proto(wq, mp); - break; - - default: - ASSERT(0); - PR_STR("%s: unexpected db_type (%d)\n", - proc, DB_TYPE(mp)); - freemsg(mp); - break; - } - } -done: - return (0); -} - -/* - * ---------------------------------------------- - */ -static int -idnrput(register queue_t *rq, register mblk_t *mp) -{ - register int err = 0; - procname_t proc = "idnrput"; - - switch (DB_TYPE(mp)) { - case M_DATA: - /* - * Should not reach here with data packets - * if running DLPI. - */ - cmn_err(CE_WARN, - "IDN: 123: unexpected M_DATA packets for " - "q_stream 0x%p", (void *)rq->q_stream); - freemsg(mp); - err = ENXIO; - break; - - case M_FLUSH: - PR_STR("%s: M_FLUSH request (flush = %d)\n", - proc, (int)*mp->b_rptr); - if (*mp->b_rptr & FLUSHR) - flushq(rq, FLUSHALL); - (void) putnext(rq, mp); - break; - - case M_ERROR: - PR_STR("%s: M_ERROR (error = %d) coming through\n", - proc, (int)*mp->b_rptr); - (void) putnext(rq, mp); - break; - default: - PR_STR("%s: unexpected DB_TYPE 0x%x\n", - proc, DB_TYPE(mp)); - freemsg(mp); - err = ENXIO; - break; - } - - return (err); -} - -/* - * ---------------------------------------------- - * Not allowed to enqueue messages! Only M_DATA messages - * can be enqueued on the write stream. - * ---------------------------------------------- - */ -static void -idnioctl(register queue_t *wq, register mblk_t *mp) -{ - register struct iocblk *iocp; - register int cmd; - idnop_t *idnop = NULL; - int error = 0; - int argsize; - procname_t proc = "idnioctl"; - - iocp = (struct iocblk *)mp->b_rptr; - cmd = iocp->ioc_cmd; - - /* - * Intercept DLPI ioctl's. - */ - if (VALID_DLPIOP(cmd)) { - PR_STR("%s: DLPI ioctl(%d)\n", proc, cmd); - error = idnioc_dlpi(wq, mp, &argsize); - goto done; - } - - /* - * Validate expected arguments. - */ - if (!VALID_IDNIOCTL(cmd)) { - PR_STR("%s: invalid cmd (0x%x)\n", proc, cmd); - error = EINVAL; - goto done; - - } else if (!VALID_NDOP(cmd)) { - error = miocpullup(mp, sizeof (idnop_t)); - if (error != 0) { - PR_STR("%s: idnioc(cmd = 0x%x) miocpullup " - "failed (%d)\n", proc, cmd, error); - goto done; - } - } - - argsize = mp->b_cont->b_wptr - mp->b_cont->b_rptr; - idnop = (idnop_t *)mp->b_cont->b_rptr; - - switch (cmd) { - case IDNIOC_LINK: - error = idnioc_link(idnop); - break; - - case IDNIOC_UNLINK: - error = idnioc_unlink(idnop); - break; - - case IDNIOC_MEM_RW: - error = idn_rw_mem(idnop); - break; - - case IDNIOC_PING: - error = idn_send_ping(idnop); - break; - - case ND_SET: - IDN_GLOCK_EXCL(); - if (!nd_getset(wq, idn_ndlist, mp)) { - IDN_GUNLOCK(); - error = ENOENT; - break; - } - IDN_GUNLOCK(); - qreply(wq, mp); - return; - - case ND_GET: - IDN_GLOCK_SHARED(); - if (!nd_getset(wq, idn_ndlist, mp)) { - IDN_GUNLOCK(); - error = ENOENT; - break; - } - IDN_GUNLOCK(); - qreply(wq, mp); - return; - - default: - PR_STR("%s: invalid cmd 0x%x\n", proc, cmd); - error = EINVAL; - break; - } - -done: - if (error == 0) - miocack(wq, mp, argsize, 0); - else - miocnak(wq, mp, 0, error); -} - -/* - * This thread actually services the SSI_LINK/UNLINK calls - * asynchronously that come via BBSRAM. This is necessary - * since we can't process them from within the context of - * the interrupt handler in which idn_sigbhandler() is - * called. - */ -static void -idn_sigbhandler_thread(struct sigbintr **sbpp) -{ - int d, pri, rv; - struct sigbintr *sbp; - sigbmbox_t *mbp; - idn_fin_t fintype; - idnsb_data_t *sdp; - idnsb_info_t *sfp; - idnsb_error_t *sep; - idn_domain_t *dp; - procname_t proc = "idn_sigbhandler_thread"; - - - sbp = *sbpp; - - PR_PROTO("%s: KICKED OFF (sigbintr pointer = 0x%p)\n", - proc, (void *)sbp); - - ASSERT(sbp == &idn.sigbintr); - - mutex_enter(&idn.sigbintr.sb_mutex); - - while (sbp->sb_busy != IDNSIGB_DIE) { - cpu_sgnblk_t *sigbp; - - while ((sbp->sb_busy != IDNSIGB_ACTIVE) && - (sbp->sb_busy != IDNSIGB_DIE)) { - cv_wait(&sbp->sb_cv, &idn.sigbintr.sb_mutex); - PR_PROTO("%s: AWAKENED (busy = %d)\n", - proc, (int)sbp->sb_busy); - } - if (sbp->sb_busy == IDNSIGB_DIE) { - PR_PROTO("%s: DIE REQUESTED\n", proc); - break; - } - - if ((sigbp = cpu_sgnblkp[sbp->sb_cpuid]) == NULL) { - cmn_err(CE_WARN, - "IDN: 124: sigblk for CPU ID %d " - "is NULL", sbp->sb_cpuid); - sbp->sb_busy = IDNSIGB_INACTIVE; - continue; - } - - mbp = &sigbp->sigb_host_mbox; - - if (mbp->flag != SIGB_MBOX_BUSY) { - PR_PROTO("%s: sigblk mbox flag (%d) != BUSY (%d)\n", - proc, mbp->flag, SIGB_MBOX_BUSY); - sbp->sb_busy = IDNSIGB_INACTIVE; - continue; - } - /* - * The sb_busy bit is set and the mailbox flag - * indicates BUSY also, so we effectively have things locked. - * So, we can drop the critical sb_mutex which we want to - * do since it pushes us to PIL 14 while we hold it and we - * don't want to run at PIL 14 across IDN code. - */ - mutex_exit(&idn.sigbintr.sb_mutex); - - sdp = (idnsb_data_t *)mbp->data; - sep = (idnsb_error_t *)&sdp->ssb_error; - INIT_IDNKERR(sep); - - if (mbp->len != sizeof (idnsb_data_t)) { - PR_PROTO("%s: sigblk mbox length (%d) != " - "expected (%lu)\n", proc, mbp->len, - sizeof (idnsb_data_t)); - SET_IDNKERR_ERRNO(sep, EINVAL); - SET_IDNKERR_IDNERR(sep, IDNKERR_DATA_LEN); - SET_IDNKERR_PARAM0(sep, sizeof (idnsb_data_t)); - - goto sberr; - - } - if (idn.enabled == 0) { -#ifdef DEBUG - cmn_err(CE_NOTE, - "IDN: 102: driver disabled " - "- check OBP environment " - "(idn-smr-size)"); -#else /* DEBUG */ - cmn_err(CE_NOTE, - "!IDN: 102: driver disabled " - "- check OBP environment " - "(idn-smr-size)"); -#endif /* DEBUG */ - SET_IDNKERR_ERRNO(sep, EACCES); - SET_IDNKERR_IDNERR(sep, IDNKERR_DRV_DISABLED); - - goto sberr; - - } - - switch (mbp->cmd) { - - case SSI_LINK: - { - idnsb_link_t slp; - - bcopy(&sdp->ssb_link, &slp, sizeof (slp)); - - if (slp.master_pri < 0) { - pri = IDNVOTE_MINPRI; - } else if (slp.master_pri > 0) { - /* - * If I'm already in a IDN network, - * then my vote priority is set to - * the max, otherwise it's one-less. - */ - pri = IDNVOTE_MAXPRI; - IDN_GLOCK_SHARED(); - if (idn.ndomains <= 1) - pri--; - IDN_GUNLOCK(); - } else { - pri = IDNVOTE_DEFPRI; - } - - PR_PROTO("%s: SSI_LINK(cpuid = %d, domid = %d, " - "pri = %d (req = %d), t/o = %d)\n", - proc, slp.cpuid, slp.domid, pri, - slp.master_pri, slp.timeout); - - rv = idn_link(slp.domid, slp.cpuid, pri, - slp.timeout, sep); - SET_IDNKERR_ERRNO(sep, rv); - (void) idn_info(&sdp->ssb_info); - break; - } - - case SSI_UNLINK: - { - idnsb_unlink_t sup; - idn_domain_t *xdp; - domainset_t domset; - - bcopy(&sdp->ssb_unlink, &sup, sizeof (sup)); - - PR_PROTO("%s: SSI_UNLINK(c = %d, d = %d, bs = 0x%x, " - "f = %d, is = 0x%x, t/o = %d)\n", - proc, sup.cpuid, sup.domid, sup.boardset, - sup.force, sup.idnset, sup.timeout); - - domset = idn.domset.ds_trans_on | - idn.domset.ds_connected | - idn.domset.ds_trans_off | - idn.domset.ds_awol | - idn.domset.ds_relink; - - if (VALID_DOMAINID(sup.domid)) { - dp = &idn_domain[sup.domid]; - } else if (VALID_CPUID(sup.cpuid)) { - for (d = 0; d < MAX_DOMAINS; d++) { - xdp = &idn_domain[d]; - - if ((xdp->dcpu == IDN_NIL_DCPU) && - !DOMAIN_IN_SET(domset, d)) - continue; - - if (CPU_IN_SET(xdp->dcpuset, - sup.cpuid)) - break; - } - dp = (d == MAX_DOMAINS) ? NULL : xdp; - } - if ((dp == NULL) && sup.boardset) { - for (d = 0; d < MAX_DOMAINS; d++) { - xdp = &idn_domain[d]; - - if ((xdp->dcpu == IDN_NIL_DCPU) && - !DOMAIN_IN_SET(domset, d)) - continue; - - if (xdp->dhw.dh_boardset & - sup.boardset) - break; - } - dp = (d == MAX_DOMAINS) ? NULL : xdp; - } - if (dp == NULL) { - SET_IDNKERR_ERRNO(sep, EINVAL); - SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_DOMAIN); - SET_IDNKERR_PARAM0(sep, sup.domid); - SET_IDNKERR_PARAM1(sep, sup.cpuid); - (void) idn_info(&sdp->ssb_info); - goto sberr; - } else { - sup.domid = dp->domid; - } - - switch (sup.force) { - case SSIFORCE_OFF: - fintype = IDNFIN_NORMAL; - break; - - case SSIFORCE_SOFT: - fintype = IDNFIN_FORCE_SOFT; - break; - - case SSIFORCE_HARD: - fintype = IDNFIN_FORCE_HARD; - break; - default: - SET_IDNKERR_ERRNO(sep, EINVAL); - SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_FORCE); - SET_IDNKERR_PARAM0(sep, sup.force); - (void) idn_info(&sdp->ssb_info); - goto sberr; - } - - rv = idn_unlink(sup.domid, sup.idnset, fintype, - IDNFIN_OPT_UNLINK, sup.timeout, sep); - SET_IDNKERR_ERRNO(sep, rv); - (void) idn_info(&sdp->ssb_info); - break; - } - - case SSI_INFO: - sfp = &sdp->ssb_info; - - PR_PROTO("%s: SSI_INFO\n", proc); - - rv = idn_info(sfp); - SET_IDNKERR_ERRNO(sep, rv); - if (rv != 0) { - SET_IDNKERR_IDNERR(sep, IDNKERR_INFO_FAILED); - } - break; - - default: - ASSERT(0); - SET_IDNKERR_ERRNO(sep, EINVAL); - SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_CMD); - SET_IDNKERR_PARAM0(sep, mbp->cmd); - break; - } - -sberr: - - if (GET_IDNKERR_ERRNO(sep) != 0) { - cmn_err(CE_WARN, -#ifdef DEBUG - "IDN: 125: op (%s) failed, returning " - "(%d/0x%x [%d, %d, %d])", -#else /* DEBUG */ - "!IDN: 125: op (%s) failed, returning " - "(%d/0x%x [%d, %d, %d])", -#endif /* DEBUG */ - (mbp->cmd == SSI_LINK) ? "LINK" : - (mbp->cmd == SSI_UNLINK) ? "UNLINK" : - (mbp->cmd == SSI_INFO) ? - "INFO" : "UNKNOWN", - GET_IDNKERR_ERRNO(sep), - GET_IDNKERR_IDNERR(sep), - GET_IDNKERR_PARAM0(sep), - GET_IDNKERR_PARAM1(sep), - GET_IDNKERR_PARAM2(sep)); - } - - PR_PROTO("%s: returning errno = %d, idnerr = %d, " - "params = [%d, %d, %d]\n", - proc, GET_IDNKERR_ERRNO(sep), GET_IDNKERR_IDNERR(sep), - GET_IDNKERR_PARAM0(sep), GET_IDNKERR_PARAM1(sep), - GET_IDNKERR_PARAM2(sep)); - - mutex_enter(&idn.sigbintr.sb_mutex); - ASSERT((sbp->sb_busy == IDNSIGB_ACTIVE) || - (sbp->sb_busy == IDNSIGB_DIE)); - mbp->cmd |= SSI_ACK; - if (sbp->sb_busy == IDNSIGB_ACTIVE) - sbp->sb_busy = IDNSIGB_INACTIVE; - /* - * Set flag which kicks off response to SSP. - */ - membar_stst_ldst(); - mbp->flag = HOST_TO_CBS; - } - - /* - * Wake up the dude that killed us! - */ - idn.sigb_threadp = NULL; - cv_signal(&sbp->sb_cv); - mutex_exit(&idn.sigbintr.sb_mutex); - thread_exit(); -} - -/* - * Create the thread that will service sigb interrupts. - */ -static void -idn_sigbhandler_create() -{ - struct sigbintr *sbp; - - if (idn.sigb_threadp) { - cmn_err(CE_WARN, - "IDN: 126: sigbhandler thread already " - "exists (0x%p)", (void *)idn.sigb_threadp); - return; - } - cv_init(&idn.sigbintr.sb_cv, NULL, CV_DEFAULT, NULL); - sbp = &idn.sigbintr; - sbp->sb_busy = IDNSIGB_INACTIVE; - idn.sigb_threadp = thread_create(NULL, 0, - idn_sigbhandler_thread, &sbp, sizeof (sbp), &p0, - TS_RUN, minclsyspri); - sbp->sb_inum = add_softintr((uint_t)idn_sigbpil, - idn_sigbhandler_wakeup, 0, SOFTINT_ST); -} - -static void -idn_sigbhandler_kill() -{ - if (idn.sigb_threadp) { - struct sigbintr *sbp; - - sbp = &idn.sigbintr; - if (sbp->sb_inum != 0) - (void) rem_softintr(sbp->sb_inum); - sbp->sb_inum = 0; - sbp->sb_busy = IDNSIGB_DIE; - cv_signal(&sbp->sb_cv); - while (idn.sigb_threadp != NULL) - cv_wait(&sbp->sb_cv, &idn.sigbintr.sb_mutex); - sbp->sb_busy = IDNSIGB_INACTIVE; - cv_destroy(&sbp->sb_cv); - } -} - -/*ARGSUSED0*/ -static uint_t -idn_sigbhandler_wakeup(caddr_t arg1, caddr_t arg2) -{ - mutex_enter(&idn.sigbintr.sb_mutex); - if (idn.sigbintr.sb_busy == IDNSIGB_STARTED) { - idn.sigbintr.sb_busy = IDNSIGB_ACTIVE; - cv_signal(&idn.sigbintr.sb_cv); - } - mutex_exit(&idn.sigbintr.sb_mutex); - - return (DDI_INTR_CLAIMED); -} - -static void -idn_sigbhandler(processorid_t cpuid, cpu_sgnblk_t *sgnblkp) -{ - struct sigbintr *sbp = &idn.sigbintr; - sigbmbox_t *mbp; - idnsb_data_t *sdp; - idnsb_error_t *sep; - uint32_t cmd; - int sigb_lock = 0; - - ASSERT(sgnblkp); - - mbp = &sgnblkp->sigb_host_mbox; - sdp = (idnsb_data_t *)mbp->data; - sep = &sdp->ssb_error; - cmd = mbp->cmd; - - if ((mbp->flag != CBS_TO_HOST) || !VALID_IDNSIGBCMD(cmd)) { - /* - * Not a valid IDN command. Just bail out. - */ - return; - } - - mbp->flag = SIGB_MBOX_BUSY; - SET_IDNKERR_ERRNO(sep, 0); - - if (cmd & SSI_ACK) { - /* - * Hmmm...weird, the ACK bit is set. - */ - SET_IDNKERR_ERRNO(sep, EPROTO); - SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_CMD); - SET_IDNKERR_PARAM0(sep, cmd); - goto sigb_done; - } - - if (!mutex_tryenter(&idn.sigbintr.sb_mutex)) { - /* - * Couldn't get the lock. Driver is either - * not quite all the way up or is shutting down - * for some reason. Caller should spin again. - */ - cmd |= SSI_ACK; - SET_IDNKERR_ERRNO(sep, EBUSY); - SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_LOCKED); - goto sigb_done; - } - sigb_lock = 1; - - if ((idn.sigb_threadp == NULL) || - (sbp->sb_busy == IDNSIGB_NOTREADY)) { - cmd |= SSI_ACK; - SET_IDNKERR_ERRNO(sep, EAGAIN); - SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_NOTRDY); - goto sigb_done; - } - - if (sbp->sb_busy != IDNSIGB_INACTIVE) { - cmd |= SSI_ACK; - SET_IDNKERR_ERRNO(sep, EBUSY); - SET_IDNKERR_IDNERR(sep, IDNKERR_SIGBINTR_BUSY); - goto sigb_done; - } - - sbp->sb_cpuid = (uchar_t)cpuid & 0xff; - membar_stst_ldst(); - sbp->sb_busy = IDNSIGB_STARTED; - /* - * The sb_busy bit is set and the mailbox flag - * indicates BUSY also, so we effectively have things locked. - * So, we can drop the critical sb_mutex which we want to - * do since it pushes us to PIL 14 while we hold it and we - * don't want to run at PIL 14 across IDN code. - * - * Send interrupt to cause idn_sigbhandler_thread to wakeup. - * We cannot do wakeup (cv_signal) directly from here since - * we're executing from a high-level (14) interrupt. - */ - setsoftint(sbp->sb_inum); - -sigb_done: - - if (GET_IDNKERR_ERRNO(sep) != 0) { - mbp->len = sizeof (idnsb_data_t); - mbp->cmd = cmd; - membar_stst_ldst(); - mbp->flag = HOST_TO_CBS; - } - - if (sigb_lock) - mutex_exit(&idn.sigbintr.sb_mutex); -} - -static int -idn_info(idnsb_info_t *sfp) -{ - int count, d; - idn_domain_t *dp; - idnsb_info_t sinfo; - int local_id, master_id; - procname_t proc = "idn_info"; - - bzero(&sinfo, sizeof (sinfo)); - sinfo.master_index = (uchar_t)-1; - sinfo.master_cpuid = (uchar_t)-1; - sinfo.local_index = (uchar_t)-1; - sinfo.local_cpuid = (uchar_t)-1; - - IDN_GLOCK_SHARED(); - - sinfo.idn_state = (uchar_t)idn.state; - - switch (idn.state) { - case IDNGS_OFFLINE: - sinfo.idn_active = SSISTATE_INACTIVE; - PR_PROTO("%s: idn_state (%s) = INACTIVE\n", - proc, idngs_str[idn.state]); - break; - - case IDNGS_IGNORE: - PR_PROTO("%s: IGNORING IDN_INFO call...\n", proc); - IDN_GUNLOCK(); - return (EIO); - - default: - sinfo.idn_active = SSISTATE_ACTIVE; - PR_PROTO("%s: idn_state (%s) = ACTIVE\n", - proc, idngs_str[idn.state]); - break; - } - master_id = IDN_GET_MASTERID(); - local_id = idn.localid; - - /* - * Need to drop idn.grwlock before acquiring domain locks. - */ - IDN_GUNLOCK(); - - IDN_SYNC_LOCK(); - - sinfo.awol_domset = (ushort_t)idn.domset.ds_awol; - sinfo.conn_domset = (ushort_t)(idn.domset.ds_connected & - ~idn.domset.ds_trans_on); - DOMAINSET_ADD(sinfo.conn_domset, idn.localid); - - count = 0; - for (d = 0; d < MAX_DOMAINS; d++) { - dp = &idn_domain[d]; - - if (dp->dcpu == IDN_NIL_DCPU) - continue; - - IDN_DLOCK_SHARED(d); - if ((dp->dcpu == IDN_NIL_DCPU) || - (dp->dstate == IDNDS_CLOSED)) { - IDN_DUNLOCK(d); - continue; - } - - count++; - if (d == local_id) { - sinfo.local_index = (uchar_t)d; - sinfo.local_cpuid = (uchar_t)dp->dcpu; - PR_PROTO("%s: domid %d is LOCAL (cpuid = %d)\n", - proc, d, dp->dcpu); - } - if (d == master_id) { - sinfo.master_index = (uchar_t)d; - sinfo.master_cpuid = (uchar_t)dp->dcpu; - PR_PROTO("%s: domid %d is MASTER (cpuid = %d)\n", - proc, d, dp->dcpu); - } - - sinfo.domain_boardset[d] = (ushort_t)dp->dhw.dh_boardset; - - IDN_DUNLOCK(d); - } - - IDN_SYNC_UNLOCK(); - - bcopy(&sinfo, sfp, sizeof (*sfp)); - - PR_PROTO("%s: Found %d domains within IDNnet\n", proc, count); - - return (0); -} - -/* - * ---------------------------------------------- - * ndd param support routines. - * - Borrowed from tcp. - * ---------------------------------------------- - */ -static void -idn_param_cleanup() -{ - IDN_GLOCK_EXCL(); - if (!idn.strup && idn_ndlist) - nd_free(&idn_ndlist); - IDN_GUNLOCK(); -} - -/*ARGSUSED*/ -static int -idn_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - idnparam_t *idnpa = (idnparam_t *)cp; - - /* - * lock grabbed before calling nd_getset. - */ - ASSERT(IDN_GLOCK_IS_HELD()); - - (void) mi_mpprintf(mp, "%ld", idnpa->sp_val); - - return (0); -} - -/*ARGSUSED*/ -static int -idn_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr) -{ - char *end; - ulong_t new_value; - idnparam_t *idnpa = (idnparam_t *)cp; - - /* - * lock grabbed before calling nd_getset. - */ - ASSERT(IDN_GLOCK_IS_EXCL()); - - new_value = (ulong_t)mi_strtol(value, &end, 10); - - if ((end == value) || - (new_value < idnpa->sp_min) || - (new_value > idnpa->sp_max)) - return (EINVAL); - - if (idn.enabled == 0) { -#ifdef DEBUG - cmn_err(CE_NOTE, - "IDN: 102: driver disabled " - "- check OBP environment " - "(idn-smr-size)"); -#else /* DEBUG */ - cmn_err(CE_NOTE, - "!IDN: 102: driver disabled " - "- check OBP environment " - "(idn-smr-size)"); -#endif /* DEBUG */ - return (EACCES); - } - - idnpa->sp_val = new_value; - - return (0); -} - -static int -idn_param_register(register idnparam_t *idnpa, int count) -{ - ASSERT(IDN_GLOCK_IS_EXCL()); - - for (; count > 0; count--, idnpa++) { - if (idnpa->sp_name && idnpa->sp_name[0]) { - register int i; - ndsetf_t set_func; - char *p; - /* - * Don't advertise in non-DEBUG parameters. - */ - for (i = 0; idn_param_debug_only[i]; i++) { - p = idn_param_debug_only[i]; - if (strcmp(idnpa->sp_name, p) == 0) - break; - } - if (idn_param_debug_only[i]) - continue; - - /* - * Do not register a "set" function for - * read-only parameters. - */ - for (i = 0; idn_param_read_only[i]; i++) { - p = idn_param_read_only[i]; - if (strcmp(idnpa->sp_name, p) == 0) - break; - } - if (idn_param_read_only[i]) - set_func = NULL; - else - set_func = idn_param_set; - - if (!nd_load(&idn_ndlist, idnpa->sp_name, - idn_param_get, set_func, - (caddr_t)idnpa)) { - nd_free(&idn_ndlist); - return (-1); - } - } - } - if (!nd_load(&idn_ndlist, "idn_slabpool", idn_slabpool_report, - NULL, NULL)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_buffers", idn_buffer_report, - NULL, NULL)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_mboxtbl", idn_mboxtbl_report, - NULL, MBXTBL_PART_REPORT)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_mboxtbl_all", idn_mboxtbl_report, - NULL, MBXTBL_FULL_REPORT)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_mainmbox", idn_mainmbox_report, - NULL, NULL)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_global", idn_global_report, - NULL, NULL)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_domain", idn_domain_report, - NULL, (caddr_t)0)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_domain_all", idn_domain_report, - NULL, (caddr_t)1)) { - nd_free(&idn_ndlist); - return (-1); - } - if (!nd_load(&idn_ndlist, "idn_bind_net", idn_get_net_binding, - idn_set_net_binding, NULL)) { - nd_free(&idn_ndlist); - return (-1); - } - - return (0); -} - -/*ARGSUSED*/ -static int -idn_set_net_binding(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr) -{ - char *end, *cpup; - long net; - processorid_t cpuid; - - /* - * lock grabbed before calling nd_getset. - */ - ASSERT(IDN_GLOCK_IS_EXCL()); - - if ((cpup = strchr(value, '=')) == NULL) - return (EINVAL); - - *cpup++ = '\0'; - - net = mi_strtol(value, &end, 10); - if ((end == value) || (net < 0) || (net >= IDN_MAX_NETS) || - !CHAN_IN_SET(idn.chanset, net)) - return (EINVAL); - - cpuid = (processorid_t)mi_strtol(cpup, &end, 10); - if ((end == cpup) || ((cpuid != -1) && - (!VALID_CPUID(cpuid) || - !CPU_IN_SET(cpu_ready_set, cpuid)))) - return (EINVAL); - - idn_chanserver_bind(net, cpuid); - - return (0); -} - -/*ARGSUSED*/ -static int -idn_get_net_binding(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - int c; - - /* - * lock grabbed before calling nd_getset. - */ - ASSERT(IDN_GLOCK_IS_HELD()); - - (void) mi_mpprintf(mp, - "IDN network interfaces/channels active = %d", - idn.nchannels); - - if (idn.nchannels == 0) - return (0); - - (void) mi_mpprintf(mp, "Net Cpu"); - - for (c = 0; c < IDN_MAX_NETS; c++) { - int bc; - idn_chansvr_t *csp; - - if (!CHAN_IN_SET(idn.chanset, c)) - continue; - - csp = &idn.chan_servers[c]; - - if ((bc = csp->ch_bound_cpuid) == -1) - bc = csp->ch_bound_cpuid_pending; - - if (c < 10) - (void) mi_mpprintf(mp, " %d %d", c, bc); - else - (void) mi_mpprintf(mp, " %d %d", c, bc); - } - - return (0); -} - -static int -idnioc_link(idnop_t *idnop) -{ - int rv; - int pri; - idnsb_error_t err; - procname_t proc = "idnioc_link"; - - if (idnop->link.master < 0) - pri = IDNVOTE_MINPRI; - else if (idnop->link.master > 0) - pri = IDNVOTE_MAXPRI; - else - pri = IDNVOTE_DEFPRI; - - PR_DRV("%s: domid = %d, cpuid = %d, pri = %d\n", - proc, idnop->link.domid, idnop->link.cpuid, pri); - - rv = idn_link(idnop->link.domid, idnop->link.cpuid, - pri, idnop->link.wait, &err); - - return (rv); -} - -static int -idnioc_unlink(idnop_t *idnop) -{ - int d, cpuid, domid, rv; - boardset_t idnset; - idn_fin_t fintype; - idn_domain_t *dp, *xdp; - idnsb_error_t err; - procname_t proc = "idnioc_unlink"; - - PR_DRV("%s: domid = %d, cpuid = %d, force = %d\n", - proc, idnop->unlink.domid, idnop->unlink.cpuid, - idnop->unlink.force); - - idnset = BOARDSET_ALL; - domid = idnop->unlink.domid; - cpuid = idnop->unlink.cpuid; - dp = NULL; - - if (domid == IDN_NIL_DOMID) - domid = idn.localid; - - if (VALID_DOMAINID(domid)) { - dp = &idn_domain[domid]; - if (VALID_CPUID(cpuid) && (dp->dcpu != IDN_NIL_DCPU) && - !CPU_IN_SET(dp->dcpuset, cpuid)) { - dp = NULL; - PR_PROTO("%s: ERROR: invalid cpuid " - "(%d) for domain (%d) [cset = 0x%x.x%x]\n", - proc, cpuid, domid, - UPPER32_CPUMASK(dp->dcpuset), - LOWER32_CPUMASK(dp->dcpuset)); - } - } else if (VALID_CPUID(cpuid)) { - for (d = 0; d < MAX_DOMAINS; d++) { - xdp = &idn_domain[d]; - - if (xdp->dcpu == IDN_NIL_DCPU) - continue; - - if (CPU_IN_SET(xdp->dcpuset, cpuid)) - break; - } - dp = (d == MAX_DOMAINS) ? NULL : xdp; - } - - if ((dp == NULL) || (dp->dcpu == IDN_NIL_DCPU)) - return (0); - - domid = dp->domid; - - switch (idnop->unlink.force) { - case SSIFORCE_OFF: - fintype = IDNFIN_NORMAL; - break; - - case SSIFORCE_SOFT: - fintype = IDNFIN_FORCE_SOFT; - break; - - case SSIFORCE_HARD: - fintype = IDNFIN_FORCE_HARD; - break; - default: - PR_PROTO("%s: invalid force parameter \"%d\"", - proc, idnop->unlink.force); - return (EINVAL); - } - - rv = idn_unlink(domid, idnset, fintype, IDNFIN_OPT_UNLINK, - idnop->unlink.wait, &err); - - return (rv); -} - -static int -idn_send_ping(idnop_t *idnop) -{ - int domid = idnop->ping.domid; - int cpuid = idnop->ping.cpuid; - int ocpuid; - idn_domain_t *dp; - idn_msgtype_t mt; - procname_t proc = "idn_send_ping"; - - if ((domid == IDN_NIL_DOMID) && (cpuid == IDN_NIL_DCPU)) { - cmn_err(CE_WARN, - "IDN: %s: no valid domain ID or CPU ID given", - proc); - return (EINVAL); - } - if (domid == IDN_NIL_DOMID) - domid = MAX_DOMAINS - 1; - - dp = &idn_domain[domid]; - IDN_DLOCK_EXCL(domid); - if ((dp->dcpu == IDN_NIL_DCPU) && (cpuid == IDN_NIL_DCPU)) { - cmn_err(CE_WARN, - "IDN: %s: no valid target CPU specified", - proc); - IDN_DUNLOCK(domid); - return (EINVAL); - } - if (cpuid == IDN_NIL_DCPU) - cpuid = dp->dcpu; - - ocpuid = dp->dcpu; - dp->dcpu = cpuid; - - /* - * XXX - Need a special PING IDN command. - */ - mt.mt_mtype = IDNP_DATA | IDNP_ACK; - mt.mt_atype = 0; - - (void) IDNXDC(domid, &mt, 0x100, 0x200, 0x300, 0x400); - - dp->dcpu = ocpuid; - IDN_DUNLOCK(domid); - - return (0); -} - -/* - * ---------------------------------------------- - */ -static void -idn_dopers_init() -{ - int i; - dop_waitlist_t *dwl; - - if (idn.dopers) - return; - - idn.dopers = GETSTRUCT(struct dopers, 1); - - bzero(idn.dopers, sizeof (struct dopers)); - - dwl = &idn.dopers->_dop_wcache[0]; - for (i = 0; i < (IDNOP_CACHE_SIZE-1); i++) - dwl[i].dw_next = &dwl[i+1]; - dwl[i].dw_next = NULL; - - idn.dopers->dop_freelist = &idn.dopers->_dop_wcache[0]; - idn.dopers->dop_waitcount = 0; - idn.dopers->dop_domset = 0; - idn.dopers->dop_waitlist = NULL; - - cv_init(&idn.dopers->dop_cv, NULL, CV_DEFAULT, NULL); - mutex_init(&idn.dopers->dop_mutex, NULL, MUTEX_DEFAULT, NULL); -} - -static void -idn_dopers_deinit() -{ - dop_waitlist_t *dwl, *next_dwl; - - - if (idn.dopers == NULL) - return; - - for (dwl = idn.dopers->dop_waitlist; dwl; dwl = next_dwl) { - next_dwl = dwl->dw_next; - if (!IDNOP_IN_CACHE(dwl)) - FREESTRUCT(dwl, dop_waitlist_t, 1); - } - - cv_destroy(&idn.dopers->dop_cv); - mutex_destroy(&idn.dopers->dop_mutex); - - FREESTRUCT(idn.dopers, struct dopers, 1); - idn.dopers = NULL; -} - -/* - * Reset the dop_errset field in preparation for an - * IDN operation attempt. This is only called from - * idn_link() and idn_unlink(). - */ -void * -idn_init_op(idn_opflag_t opflag, domainset_t domset, idnsb_error_t *sep) -{ - dop_waitlist_t *dwl; - /* - * Clear any outstanding error ops in preparation - * for an IDN (link/unlink) operation. - */ - mutex_enter(&idn.dopers->dop_mutex); - if ((dwl = idn.dopers->dop_freelist) == NULL) { - dwl = GETSTRUCT(dop_waitlist_t, 1); - } else { - idn.dopers->dop_freelist = dwl->dw_next; - bzero(dwl, sizeof (*dwl)); - } - dwl->dw_op = opflag; - dwl->dw_reqset = domset; - dwl->dw_idnerr = sep; - dwl->dw_next = idn.dopers->dop_waitlist; - - idn.dopers->dop_waitlist = dwl; - idn.dopers->dop_waitcount++; - idn.dopers->dop_domset |= domset; - mutex_exit(&idn.dopers->dop_mutex); - - return (dwl); -} - -/* - * Anybody waiting on a opflag operation for any one - * of the domains in domset, needs to be updated to - * additionally wait for new domains in domset. - * This is used, for example, when needing to connect - * to more domains than known at the time of the - * original request. - */ -void -idn_add_op(idn_opflag_t opflag, domainset_t domset) -{ - dop_waitlist_t *dwl; - - mutex_enter(&idn.dopers->dop_mutex); - if ((idn.dopers->dop_waitcount == 0) || - ((idn.dopers->dop_domset & domset) == 0)) { - mutex_exit(&idn.dopers->dop_mutex); - return; - } - for (dwl = idn.dopers->dop_waitlist; dwl; dwl = dwl->dw_next) - if ((dwl->dw_op == opflag) && (dwl->dw_reqset & domset)) - dwl->dw_reqset |= domset; - mutex_exit(&idn.dopers->dop_mutex); -} - -/* - * Mechanism to wakeup any potential users which may be waiting - * for a link/unlink operation to complete. If an error occurred - * don't update dop_errset unless there was no previous error. - */ -void -idn_update_op(idn_opflag_t opflag, domainset_t domset, idnsb_error_t *sep) -{ - int do_wakeup = 0; - dop_waitlist_t *dw; - procname_t proc = "idn_update_op"; - - mutex_enter(&idn.dopers->dop_mutex); - /* - * If there are no waiters, or nobody is waiting for - * the particular domainset in question, then - * just bail. - */ - if ((idn.dopers->dop_waitcount == 0) || - ((idn.dopers->dop_domset & domset) == 0)) { - mutex_exit(&idn.dopers->dop_mutex); - PR_PROTO("%s: NO waiters exist (domset=0x%x)\n", - proc, domset); - return; - } - - for (dw = idn.dopers->dop_waitlist; dw; dw = dw->dw_next) { - int d; - domainset_t dset, rset; - - if ((dset = dw->dw_reqset & domset) == 0) - continue; - - if (opflag == IDNOP_ERROR) { - dw->dw_errset |= dset; - if (sep) { - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(dset, d)) - continue; - - dw->dw_errors[d] = - (short)GET_IDNKERR_ERRNO(sep); - } - bcopy(sep, dw->dw_idnerr, sizeof (*sep)); - } - } else if (opflag == dw->dw_op) { - dw->dw_domset |= dset; - } - - /* - * Check if all the domains are spoken for that - * a particular waiter may have been waiting for. - * If there's at least one, we'll need to broadcast. - */ - rset = (dw->dw_errset | dw->dw_domset) & dw->dw_reqset; - if (rset == dw->dw_reqset) - do_wakeup++; - } - - PR_PROTO("%s: found %d waiters ready for wakeup\n", proc, do_wakeup); - - if (do_wakeup > 0) - cv_broadcast(&idn.dopers->dop_cv); - - mutex_exit(&idn.dopers->dop_mutex); -} - -void -idn_deinit_op(void *cookie) -{ - domainset_t domset; - dop_waitlist_t *hw, *tw; - dop_waitlist_t *dwl = (dop_waitlist_t *)cookie; - - mutex_enter(&idn.dopers->dop_mutex); - - ASSERT(idn.dopers->dop_waitlist); - - if (dwl == idn.dopers->dop_waitlist) { - idn.dopers->dop_waitlist = dwl->dw_next; - if (IDNOP_IN_CACHE(dwl)) { - dwl->dw_next = idn.dopers->dop_freelist; - idn.dopers->dop_freelist = dwl; - } else { - FREESTRUCT(dwl, dop_waitlist_t, 1); - } - } else { - for (tw = idn.dopers->dop_waitlist, hw = tw->dw_next; - hw; - tw = hw, hw = hw->dw_next) { - if (dwl == hw) - break; - } - ASSERT(hw); - - tw->dw_next = hw->dw_next; - } - - /* - * Recompute domainset for which waiters might be waiting. - * It's possible there may be other waiters waiting for - * the same domainset that the current waiter that's leaving - * may have been waiting for, so we can't simply delete - * the leaving waiter's domainset from dop_domset. - */ - for (hw = idn.dopers->dop_waitlist, domset = 0; hw; hw = hw->dw_next) - domset |= hw->dw_reqset; - - idn.dopers->dop_waitcount--; - idn.dopers->dop_domset = domset; - - mutex_exit(&idn.dopers->dop_mutex); -} - -/* - * Wait until the specified operation succeeds or fails with - * respect to the given domains. Note the function terminates - * if at least one error occurs. - * This process is necessary since link/unlink operations occur - * asynchronously and we need some way of waiting to find out - * if it indeed completed. - * Timeout value is received indirectly from the SSP and - * represents seconds. - */ -int -idn_wait_op(void *cookie, domainset_t *domsetp, int wait_timeout) -{ - int d, rv, err = 0; - dop_waitlist_t *dwl; - - - dwl = (dop_waitlist_t *)cookie; - - ASSERT(wait_timeout > 0); - ASSERT((dwl->dw_op == IDNOP_CONNECTED) || - (dwl->dw_op == IDNOP_DISCONNECTED)); - - mutex_enter(&idn.dopers->dop_mutex); - - while (((dwl->dw_domset | dwl->dw_errset) != dwl->dw_reqset) && !err) { - rv = cv_reltimedwait_sig(&idn.dopers->dop_cv, - &idn.dopers->dop_mutex, (wait_timeout * hz), TR_CLOCK_TICK); - - if ((dwl->dw_domset | dwl->dw_errset) == dwl->dw_reqset) - break; - - switch (rv) { - case -1: - /* - * timed out - */ - cmn_err(CE_WARN, - "!IDN: 129: %s operation timed out", - (dwl->dw_op == IDNOP_CONNECTED) ? "LINK" : - (dwl->dw_op == IDNOP_DISCONNECTED) ? "UNLINK" : - "UNKNOWN"); - /*FALLTHROUGH*/ - case 0: - /* - * signal, e.g. kill(2) - */ - err = 1; - break; - - default: - break; - } - } - - if (dwl->dw_domset == dwl->dw_reqset) { - rv = 0; - } else { - /* - * Op failed for some domains or we were awakened. - */ - for (d = rv = 0; (d < MAX_DOMAINS) && !rv; d++) - rv = dwl->dw_errors[d]; - } - *domsetp = dwl->dw_domset; - - mutex_exit(&idn.dopers->dop_mutex); - - idn_deinit_op(cookie); - - return (rv); -} - -/* - * -------------------------------------------------- - * Return any valid (& ready) cpuid for the given board based on - * the given cpuset. - * -------------------------------------------------- - */ -int -board_to_ready_cpu(int board, cpuset_t cpuset) -{ - int base_cpuid; - int ncpu_board = MAX_CPU_PER_BRD; - - board *= ncpu_board; - for (base_cpuid = board; - base_cpuid < (board + ncpu_board); - base_cpuid++) - if (CPU_IN_SET(cpuset, base_cpuid)) - return (base_cpuid); - - return (-1); -} - -void -idn_domain_resetentry(idn_domain_t *dp) -{ - register int i; - procname_t proc = "idn_domain_resetentry"; - - ASSERT(dp); - ASSERT(dp->dstate == IDNDS_CLOSED); - ASSERT(IDN_DLOCK_IS_EXCL(dp->domid)); - ASSERT(IDN_GLOCK_IS_EXCL()); - - ASSERT(dp->domid == (dp - &idn_domain[0])); - - IDN_FSTATE_TRANSITION(dp, IDNFIN_OFF); - dp->dname[0] = '\0'; - dp->dnetid = (ushort_t)-1; - dp->dmtu = 0; - dp->dbufsize = 0; - dp->dslabsize = 0; - dp->dnwrsize = 0; - dp->dncpus = 0; - dp->dcpuindex = 0; - CPUSET_ZERO(dp->dcpuset); - dp->dcpu = dp->dcpu_last = dp->dcpu_save = IDN_NIL_DCPU; - dp->dvote.ticket = 0; - dp->dslab = NULL; - dp->dslab_state = DSLAB_STATE_UNKNOWN; - dp->dnslabs = 0; - dp->dio = 0; - dp->dioerr = 0; - lock_clear(&dp->diowanted); - bzero(&dp->dhw, sizeof (dp->dhw)); - dp->dxp = NULL; - IDN_XSTATE_TRANSITION(dp, IDNXS_NIL); - dp->dsync.s_cmd = IDNSYNC_NIL; - dp->dfin_sync = IDNFIN_SYNC_OFF; - IDN_RESET_COOKIES(dp->domid); - dp->dcookie_err = 0; - bzero(&dp->dawol, sizeof (dp->dawol)); - dp->dtmp = -1; - - if (dp->dtimerq.tq_queue != NULL) { - PR_PROTO("%s: WARNING: MSG timerq not empty (count = %d)\n", - proc, dp->dtimerq.tq_count); - IDN_MSGTIMER_STOP(dp->domid, 0, 0); - } - - for (i = 0; i < NCPU; i++) - dp->dcpumap[i] = (uchar_t)-1; -} - -int -idn_open_domain(int domid, int cpuid, uint_t ticket) -{ - int c, new_cpuid; - idn_domain_t *dp, *ldp; - procname_t proc = "idn_open_domain"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (!VALID_DOMAINID(domid)) { - PR_PROTO("%s: INVALID domainid (%d) " - "[cpuid = %d, ticket = 0x%x]\n", - proc, domid, cpuid, ticket); - return (-1); - } - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - if (dp->dcpu >= 0) { - PR_PROTO("%s:%d: domain already OPEN (state = %s)\n", - proc, domid, idnds_str[dp->dstate]); - return (1); - } - - if (DOMAIN_IN_SET(idn.domset.ds_relink, domid)) { - if (dp->dcpu_save == IDN_NIL_DCPU) - new_cpuid = cpuid; - else - new_cpuid = dp->dcpu_save; - } else { - new_cpuid = cpuid; - } - - if (new_cpuid == IDN_NIL_DCPU) { - PR_PROTO("%s:%d: WARNING: invalid cpuid (%d) specified\n", - proc, domid, new_cpuid); - return (-1); - } - - IDN_GLOCK_EXCL(); - - idn_domain_resetentry(dp); - - PR_STATE("%s:%d: requested cpuid %d, assigning cpuid %d\n", - proc, domid, cpuid, new_cpuid); - - idn_assign_cookie(domid); - - dp->dcpu = dp->dcpu_save = new_cpuid; - dp->dvote.ticket = ticket; - CPUSET_ADD(dp->dcpuset, new_cpuid); - dp->dncpus = 1; - for (c = 0; c < NCPU; c++) - dp->dcpumap[c] = (uchar_t)new_cpuid; - dp->dhw.dh_nboards = 1; - dp->dhw.dh_boardset = BOARDSET(CPUID_TO_BOARDID(new_cpuid)); - - if (domid != idn.localid) - IDN_DLOCK_EXCL(idn.localid); - - if (idn.ndomains == 1) { - struct hwconfig local_hw; - - /* - * We're attempting to connect to our first domain. - * Recheck our local hardware configuration before - * we go any further in case it changed due to a DR, - * and update any structs dependent on this. - * ASSUMPTION: - * IDN is unlinked before performing any DRs. - */ - PR_PROTO("%s: RECHECKING local HW config.\n", proc); - if (get_hw_config(&local_hw)) { - dp->dcpu = IDN_NIL_DCPU; - cmn_err(CE_WARN, - "IDN: 118: hardware config not appropriate"); - if (domid != idn.localid) - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - return (-1); - } - (void) update_local_hw_config(ldp, &local_hw); - } - - idn.ndomains++; - - if (domid != idn.localid) - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - - IDN_MBOX_LOCK(domid); - dp->dmbox.m_tbl = NULL; - - if (domid != idn.localid) { - dp->dmbox.m_send = idn_mainmbox_init(domid, - IDNMMBOX_TYPE_SEND); - dp->dmbox.m_recv = idn_mainmbox_init(domid, - IDNMMBOX_TYPE_RECV); - } else { - /* - * The local domain does not need send/recv - * mailboxes in its idn_domain[] entry. - */ - dp->dmbox.m_send = NULL; - dp->dmbox.m_recv = NULL; - } - IDN_MBOX_UNLOCK(domid); - - PR_PROTO("%s:%d: new domain (cpu = %d, vote = 0x%x)\n", - proc, domid, dp->dcpu, dp->dvote.ticket); - - return (0); -} - -/* - * The local domain never "closes" itself unless the driver - * is doing a idndetach. It will be reopened during idnattach - * when idn_domains_init is called. - */ -void -idn_close_domain(int domid) -{ - uint_t token; - idn_domain_t *dp; - procname_t proc = "idn_close_domain"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - - ASSERT(dp->dstate == IDNDS_CLOSED); - - if (dp->dcpu == IDN_NIL_DCPU) { - PR_PROTO("%s:%d: DOMAIN ALREADY CLOSED!\n", - proc, domid); - return; - } - - token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL); - - (void) idn_retry_terminate(token); - - DOMAINSET_DEL(idn.domset.ds_trans_on, domid); - DOMAINSET_DEL(idn.domset.ds_ready_on, domid); - DOMAINSET_DEL(idn.domset.ds_connected, domid); - DOMAINSET_DEL(idn.domset.ds_trans_off, domid); - DOMAINSET_DEL(idn.domset.ds_ready_off, domid); - DOMAINSET_DEL(idn.domset.ds_hwlinked, domid); - DOMAINSET_DEL(idn.domset.ds_flush, domid); - - idn_sync_exit(domid, IDNSYNC_CONNECT); - idn_sync_exit(domid, IDNSYNC_DISCONNECT); - - IDN_GLOCK_EXCL(); - - if (DOMAIN_IN_SET(idn.domset.ds_awol, domid)) - idn_clear_awol(domid); - - idn.ndomains--; - - IDN_GUNLOCK(); - - IDN_MBOX_LOCK(domid); - dp->dmbox.m_tbl = NULL; - - if (dp->dmbox.m_send) { - idn_mainmbox_deinit(domid, dp->dmbox.m_send); - dp->dmbox.m_send = NULL; - } - - if (dp->dmbox.m_recv) { - idn_mainmbox_deinit(domid, dp->dmbox.m_recv); - dp->dmbox.m_recv = NULL; - } - - IDN_MBOX_UNLOCK(domid); - - cmn_err(CE_NOTE, - "!IDN: 142: link (domain %d, CPU %d) disconnected", - dp->domid, dp->dcpu); - - dp->dcpu = IDN_NIL_DCPU; /* ultimate demise */ - - IDN_RESET_COOKIES(domid); - - ASSERT(dp->dio <= 0); - ASSERT(dp->dioerr == 0); - ASSERT(dp->dslab == NULL); - ASSERT(dp->dnslabs == 0); - - IDN_GKSTAT_GLOBAL_EVENT(gk_unlinks, gk_unlink_last); -} - - -/* - * ----------------------------------------------------------------------- - */ -static void -idn_domains_init(struct hwconfig *local_hw) -{ - register int i, d; - idn_domain_t *ldp; - uchar_t *cpumap; - - ASSERT(local_hw != NULL); - - cpumap = GETSTRUCT(uchar_t, NCPU * MAX_DOMAINS); - - for (d = 0; d < MAX_DOMAINS; d++) { - register idn_domain_t *dp; - - dp = &idn_domain[d]; - - dp->domid = d; - - rw_init(&dp->drwlock, NULL, RW_DEFAULT, NULL); - - IDN_TIMERQ_INIT(&dp->dtimerq); - - dp->dstate = IDNDS_CLOSED; - - mutex_init(&dp->dmbox.m_mutex, NULL, MUTEX_DEFAULT, NULL); - - dp->dcpumap = cpumap; - - rw_init(&dp->dslab_rwlock, NULL, RW_DEFAULT, NULL); - - IDN_DLOCK_EXCL(d); - IDN_GLOCK_EXCL(); - - idn_domain_resetentry(dp); - - IDN_GUNLOCK(); - - IDNSB_DOMAIN_UPDATE(dp); - - IDN_DUNLOCK(d); - - cpumap += NCPU; - } - - IDN_SYNC_LOCK(); - - /* - * Update local domain information. - */ - ASSERT(idn.smr.locpfn); - ASSERT(local_hw->dh_nboards && local_hw->dh_boardset); - - idn.ndomains = 0; /* note that open_domain will get us to 1 */ - - IDN_DLOCK_EXCL(idn.localid); - d = idn_open_domain(idn.localid, (int)CPU->cpu_id, 0); - ASSERT(d == 0); - IDN_GLOCK_EXCL(); - IDN_SET_MASTERID(IDN_NIL_DOMID); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - - ldp = &idn_domain[idn.localid]; - - (void) strncpy(ldp->dname, utsname.nodename, MAXDNAME - 1); - ldp->dname[MAXDNAME-1] = '\0'; - bcopy(local_hw, &ldp->dhw, sizeof (ldp->dhw)); - ASSERT(idn.ndomains == 1); - ASSERT((ldp->dhw.dh_nboards > 0) && - (ldp->dhw.dh_nboards <= MAX_BOARDS)); - ldp->dnetid = IDN_DOMID2NETID(ldp->domid); - ldp->dmtu = IDN_MTU; - ldp->dbufsize = IDN_SMR_BUFSIZE; - ldp->dslabsize = (short)IDN_SLAB_BUFCOUNT; - ldp->dnwrsize = (short)IDN_NWR_SIZE; - ldp->dcpuset = cpu_ready_set; - ldp->dncpus = (short)ncpus; - ldp->dvote.ticket = IDNVOTE_INITIAL_TICKET; - ldp->dvote.v.master = 0; - ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1; - ldp->dvote.v.ncpus = (int)ldp->dncpus - 1; - ldp->dvote.v.board = CPUID_TO_BOARDID(ldp->dcpu); - i = -1; - for (d = 0; d < NCPU; d++) { - BUMP_INDEX(ldp->dcpuset, i); - ldp->dcpumap[d] = (uchar_t)i; - } - - CPUSET_ZERO(idn.dc_cpuset); - CPUSET_OR(idn.dc_cpuset, ldp->dcpuset); - idn.dc_boardset = ldp->dhw.dh_boardset; - - /* - * Setting the state for ourselves is only relevant - * for loopback performance testing. Anyway, it - * makes sense that we always have an established - * connection with ourself regardless of IDN :-o - */ - IDN_DSTATE_TRANSITION(ldp, IDNDS_CONNECTED); - - IDN_GUNLOCK(); - IDN_DUNLOCK(idn.localid); - IDN_SYNC_UNLOCK(); -} - -static void -idn_domains_deinit() -{ - register int d; - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(idn.localid); - IDN_DSTATE_TRANSITION(&idn_domain[idn.localid], IDNDS_CLOSED); - idn_close_domain(idn.localid); - IDN_DUNLOCK(idn.localid); - IDN_SYNC_UNLOCK(); - idn.localid = IDN_NIL_DOMID; - - FREESTRUCT(idn_domain[0].dcpumap, uchar_t, NCPU * MAX_DOMAINS); - - for (d = 0; d < MAX_DOMAINS; d++) { - idn_domain_t *dp; - - dp = &idn_domain[d]; - - rw_destroy(&dp->dslab_rwlock); - mutex_destroy(&dp->dmbox.m_mutex); - rw_destroy(&dp->drwlock); - IDN_TIMERQ_DEINIT(&dp->dtimerq); - dp->dcpumap = NULL; - } -} - -/* - * ----------------------------------------------------------------------- - */ -static void -idn_retrytask_init() -{ - ASSERT(idn.retryqueue.rq_cache == NULL); - - mutex_init(&idn.retryqueue.rq_mutex, NULL, MUTEX_DEFAULT, NULL); - idn.retryqueue.rq_cache = kmem_cache_create("idn_retryjob_cache", - sizeof (idn_retry_job_t), - 0, NULL, NULL, NULL, - NULL, NULL, 0); -} - -static void -idn_retrytask_deinit() -{ - if (idn.retryqueue.rq_cache == NULL) - return; - - kmem_cache_destroy(idn.retryqueue.rq_cache); - mutex_destroy(&idn.retryqueue.rq_mutex); - - bzero(&idn.retryqueue, sizeof (idn.retryqueue)); -} - -/* - * ----------------------------------------------------------------------- - */ -static void -idn_timercache_init() -{ - ASSERT(idn.timer_cache == NULL); - - idn.timer_cache = kmem_cache_create("idn_timer_cache", - sizeof (idn_timer_t), - 0, NULL, NULL, NULL, - NULL, NULL, 0); -} - -static void -idn_timercache_deinit() -{ - if (idn.timer_cache == NULL) - return; - - kmem_cache_destroy(idn.timer_cache); - idn.timer_cache = NULL; -} - -idn_timer_t * -idn_timer_alloc() -{ - idn_timer_t *tp; - - tp = kmem_cache_alloc(idn.timer_cache, KM_SLEEP); - bzero(tp, sizeof (*tp)); - tp->t_forw = tp->t_back = tp; - - return (tp); -} - -void -idn_timer_free(idn_timer_t *tp) -{ - if (tp == NULL) - return; - kmem_cache_free(idn.timer_cache, tp); -} - -void -idn_timerq_init(idn_timerq_t *tq) -{ - mutex_init(&tq->tq_mutex, NULL, MUTEX_DEFAULT, NULL); - tq->tq_count = 0; - tq->tq_queue = NULL; -} - -void -idn_timerq_deinit(idn_timerq_t *tq) -{ - ASSERT(tq->tq_queue == NULL); - mutex_destroy(&tq->tq_mutex); -} - -/* - * Dequeue all the timers of the given subtype from the - * given timerQ. If subtype is 0, then dequeue all the - * timers. - */ -idn_timer_t * -idn_timer_get(idn_timerq_t *tq, int type, ushort_t tcookie) -{ - register idn_timer_t *tp, *tphead; - - ASSERT(IDN_TIMERQ_IS_LOCKED(tq)); - - if ((tp = tq->tq_queue) == NULL) - return (NULL); - - if (!type) { - tq->tq_queue = NULL; - tq->tq_count = 0; - tphead = tp; - } else { - int count; - idn_timer_t *tpnext; - - tphead = NULL; - count = tq->tq_count; - do { - tpnext = tp->t_forw; - if ((tp->t_type == type) && - (!tcookie || (tp->t_cookie == tcookie))) { - tp->t_forw->t_back = tp->t_back; - tp->t_back->t_forw = tp->t_forw; - if (tphead == NULL) { - tp->t_forw = tp->t_back = tp; - } else { - tp->t_forw = tphead; - tp->t_back = tphead->t_back; - tp->t_back->t_forw = tp; - tphead->t_back = tp; - } - tphead = tp; - if (--(tq->tq_count) == 0) - tq->tq_queue = NULL; - else if (tq->tq_queue == tp) - tq->tq_queue = tpnext; - } - tp = tpnext; - } while (--count > 0); - } - - if (tphead) { - tphead->t_back->t_forw = NULL; - - for (tp = tphead; tp; tp = tp->t_forw) - tp->t_onq = 0; - } - - return (tphead); -} - -ushort_t -idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp, clock_t tval) -{ - idn_timer_t *otp; - ushort_t tcookie; - procname_t proc = "idn_timer_start"; - STRING(str); - - ASSERT(tq && tp && (tval > 0)); - ASSERT((tp->t_forw == tp) && (tp->t_back == tp)); - ASSERT(tp->t_type != 0); - - IDN_TIMERQ_LOCK(tq); - /* - * Assign a unique non-zero 8-bit cookie to this timer - * if the caller hasn't already preassigned one. - */ - while ((tcookie = tp->t_cookie) == 0) { - tp->t_cookie = (tp->t_type & 0xf) | - ((++tq->tq_cookie & 0xf) << 4); - /* - * Calculated cookie must never conflict - * with the public timer cookie. - */ - ASSERT(tp->t_cookie != IDN_TIMER_PUBLIC_COOKIE); - } - - /* - * First have to remove old timers of the - * same type and cookie, and get rid of them. - */ - otp = idn_timer_get(tq, tp->t_type, tcookie); - - tq->tq_count++; - - if (tq->tq_queue == NULL) { - tq->tq_queue = tp; - ASSERT((tp->t_forw == tp) && (tp->t_back == tp)); - } else { - /* - * Put me at the end of the list. - */ - tp->t_forw = tq->tq_queue; - tp->t_back = tq->tq_queue->t_back; - tp->t_back->t_forw = tp; - tp->t_forw->t_back = tp; - } - - tp->t_onq = 1; - tp->t_q = tq; - tp->t_id = timeout(idn_timer_expired, (caddr_t)tp, tval); - - - INUM2STR(tp->t_type, str); - PR_TIMER("%s: started %s timer (domain = %d, cookie = 0x%x)\n", - proc, str, tp->t_domid, tcookie); - - IDN_TIMERQ_UNLOCK(tq); - - if (otp) - (void) idn_timer_stopall(otp); - - return (tcookie); -} - -/* - * Stop all timers of the given subtype. - * If subtype is 0, then stop all timers - * in this timerQ. - */ -void -idn_timer_stop(idn_timerq_t *tq, int type, ushort_t tcookie) -{ - idn_timer_t *tphead; - procname_t proc = "idn_timer_stop"; - STRING(str); - - ASSERT(tq); - - INUM2STR(type, str); - - IDN_TIMERQ_LOCK(tq); - - if (tq->tq_count == 0) { - PR_TIMER("%s: found no %s timers (count=0)\n", proc, str); - IDN_TIMERQ_UNLOCK(tq); - return; - } - tphead = idn_timer_get(tq, type, tcookie); -#ifdef DEBUG - if (tphead == NULL) - PR_TIMER("%s: found no %s (cookie = 0x%x) " - "timers (count=%d)!!\n", - proc, str, tcookie, tq->tq_count); -#endif /* DEBUG */ - IDN_TIMERQ_UNLOCK(tq); - - if (tphead) - (void) idn_timer_stopall(tphead); -} - -int -idn_timer_stopall(idn_timer_t *tp) -{ - int count = 0; - int nonactive; - uint_t type; - idn_timer_t *ntp; - procname_t proc = "idn_timer_stopall"; - STRING(str); - - nonactive = 0; - - if (tp) { - /* - * Circle should have been broken. - */ - ASSERT(tp->t_back->t_forw == NULL); - type = tp->t_type; - INUM2STR(type, str); - } - - for (; tp; tp = ntp) { - ntp = tp->t_forw; - count++; - ASSERT(tp->t_id != (timeout_id_t)0); - if (untimeout(tp->t_id) < 0) { - nonactive++; - PR_TIMER("%s: bad %s untimeout (domain=%d)\n", - proc, str, tp->t_domid); - } else { - PR_TIMER("%s: good %s untimeout (domain=%d)\n", - proc, str, tp->t_domid); - } - /* - * There are two possible outcomes from - * the untimeout(). Each ultimately result - * in us having to free the timeout structure. - * - * 1. We successfully aborted a timeout call. - * - * 2. We failed to find the given timer. It - * probably just fired off. - */ - idn_timer_free(tp); - } - PR_TIMER("%s: stopped %d of %d %s timers\n", - proc, count - nonactive, count, str); - - return (count); -} - -void -idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp) -{ - ASSERT(tq && tp); - ASSERT(IDN_TIMERQ_IS_LOCKED(tq)); - - ASSERT(tp->t_q == tq); - - if (tp->t_onq == 0) { - /* - * We've already been dequeued. - */ - ASSERT(tp == tp->t_forw); - ASSERT(tp == tp->t_back); - } else { - /* - * We're still in the queue, get out. - */ - if (tq->tq_queue == tp) - tq->tq_queue = tp->t_forw; - tp->t_forw->t_back = tp->t_back; - tp->t_back->t_forw = tp->t_forw; - tp->t_onq = 0; - if (--(tq->tq_count) == 0) { - ASSERT(tq->tq_queue == tp); - tq->tq_queue = NULL; - } - tp->t_forw = tp->t_back = tp; - } -} - -/* - * ----------------------------------------------------------------------- - */ -/*ARGSUSED*/ -static int -idn_slabpool_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - register int p, nfree; - char dsetstr[128]; - - ASSERT(IDN_GLOCK_IS_HELD()); - - if (idn.slabpool == NULL) { - (void) mi_mpprintf(mp, - "IDN slabpool not initialized (masterid = %d)", - IDN_GET_MASTERID()); - return (0); - } - - for (p = nfree = 0; p < idn.slabpool->npools; p++) - nfree += idn.slabpool->pool[p].nfree; - - (void) mi_mpprintf(mp, - "IDN slabpool (ntotal_slabs = %d, nalloc = %d, " - "npools = %d)", - idn.slabpool->ntotslabs, - idn.slabpool->ntotslabs - nfree, - idn.slabpool->npools); - - (void) mi_mpprintf(mp, "pool nslabs nfree domains"); - - for (p = 0; p < idn.slabpool->npools; p++) { - register int d, s; - uint_t domset; - - domset = 0; - for (s = 0; s < idn.slabpool->pool[p].nslabs; s++) { - short dd; - - dd = idn.slabpool->pool[p].sarray[s].sl_domid; - if (dd != (short)IDN_NIL_DOMID) - DOMAINSET_ADD(domset, dd); - } - dsetstr[0] = '\0'; - if (domset) { - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(domset, d)) - continue; - - if (dsetstr[0] == '\0') - (void) sprintf(dsetstr, "%d", d); - else - (void) sprintf(dsetstr, "%s %d", - dsetstr, d); - } - } - - if (p < 10) - (void) mi_mpprintf(mp, " %d %d %d %s", - p, idn.slabpool->pool[p].nslabs, - idn.slabpool->pool[p].nfree, - dsetstr); - else - (void) mi_mpprintf(mp, " %d %d %d %s", - p, idn.slabpool->pool[p].nslabs, - idn.slabpool->pool[p].nfree, - dsetstr); - } - return (0); -} - -/*ARGSUSED*/ -static int -idn_buffer_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - smr_slab_t *sp; - register int d, cnt; - int bufcount[MAX_DOMAINS]; - int spl; - - ASSERT(IDN_GLOCK_IS_HELD()); - - if (idn.localid == IDN_NIL_DOMID) { - (void) mi_mpprintf(mp, "IDN not initialized (localid = %d)", - idn.localid); - return (0); - } - - (void) mi_mpprintf(mp, "Local domain has %d slabs allocated.", - idn_domain[idn.localid].dnslabs); - - DSLAB_LOCK_SHARED(idn.localid); - if ((sp = idn_domain[idn.localid].dslab) == NULL) { - DSLAB_UNLOCK(idn.localid); - return (0); - } - - bzero(bufcount, sizeof (bufcount)); - cnt = 0; - - spl = splhi(); - for (; sp; sp = sp->sl_next) { - smr_slabbuf_t *bp; - - while (!lock_try(&sp->sl_lock)) - ; - for (bp = sp->sl_inuse; bp; bp = bp->sb_next) { - bufcount[bp->sb_domid]++; - cnt++; - } - lock_clear(&sp->sl_lock); - } - splx(spl); - - DSLAB_UNLOCK(idn.localid); - - (void) mi_mpprintf(mp, "Local domain has %d buffers outstanding.", cnt); - if (cnt == 0) - return (0); - - (void) mi_mpprintf(mp, "Domain nbufs"); - for (d = 0; d < MAX_DOMAINS; d++) - if (bufcount[d]) { - if (d < 10) - (void) mi_mpprintf(mp, " %d %d", - d, bufcount[d]); - else - (void) mi_mpprintf(mp, " %d %d", - d, bufcount[d]); - } - - return (0); -} - -static const char * -_get_spaces(int w, int s, int W) -{ - static const char *const _spaces[] = { - "", /* 0 */ - " ", /* 1 */ - " ", /* 2 */ - " ", /* 3 */ - " ", /* 4 */ - " ", /* 5 */ - " ", /* 6 */ - " ", /* 7 */ - " ", /* 8 */ - " ", /* 9 */ - " ", /* 10 */ - " ", /* 11 */ - " ", /* 12 */ - " ", /* 13 */ - " ", /* 14 */ - " ", /* 15 */ - " ", /* 16 */ - " ", /* 17 */ - " ", /* 18 */ - " ", /* 19 */ - }; - return (_spaces[w+s-W]); -} - -#define _SSS(X, W, w, s) \ - (((w) >= (W)) && (X)) ? _get_spaces((w), (s), (W)) - -static const char * -_hexspace(uint64_t v, int sz, int width, int padding) -{ - int maxnbl = 16; - int diff; - uchar_t *np; - - diff = sizeof (uint64_t) - sz; - np = (uchar_t *)&v + diff; - maxnbl -= diff << 1; - while (sz-- > 0) { - if ((*np & 0xf0) && (width >= maxnbl)) - return (_get_spaces(width, padding, maxnbl)); - maxnbl--; - if ((*np & 0x0f) && (width >= maxnbl)) - return (_get_spaces(width, padding, maxnbl)); - maxnbl--; - np++; - } - return (_get_spaces(width, padding, 1)); -} - -#define HEXSPACE(v, t, w, s) _hexspace((uint64_t)(v), sizeof (t), (w), (s)) - -#define DECSPACE(n, w, s) \ - (_SSS((uint_t)(n) >= 10000000, 8, (w), (s)) : \ - _SSS((uint_t)(n) >= 1000000, 7, (w), (s)) : \ - _SSS((uint_t)(n) >= 100000, 6, (w), (s)) : \ - _SSS((uint_t)(n) >= 10000, 5, (w), (s)) : \ - _SSS((uint_t)(n) >= 1000, 4, (w), (s)) : \ - _SSS((uint_t)(n) >= 100, 3, (w), (s)) : \ - _SSS((uint_t)(n) >= 10, 2, (w), (s)) : \ - _get_spaces((w), (s), 1)) - -#define DECSPACE16(n, w, s) \ - (_SSS((n) >= 10000, 5, (w), (s)) : \ - _SSS((n) >= 1000, 4, (w), (s)) : \ - _SSS((n) >= 100, 3, (w), (s)) : \ - _SSS((n) >= 10, 2, (w), (s)) : \ - _get_spaces((w), (s), 1)) - -#define MBXINFO(mtp) \ - (void *)&mtp->mt_header, \ - HEXSPACE(&mtp->mt_header, &mtp->mt_header, 16, 2), \ - mtp->mt_header.mh_svr_ready_ptr, \ - HEXSPACE(mtp->mt_header.mh_svr_ready_ptr, \ - mtp->mt_header.mh_svr_ready_ptr, 8, 1), \ - mtp->mt_header.mh_svr_active_ptr, \ - HEXSPACE(mtp->mt_header.mh_svr_active_ptr, \ - mtp->mt_header.mh_svr_active_ptr, 8, 2), \ - *(ushort_t *)(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_ready_ptr)), \ - DECSPACE16(*(ushort_t *) \ - (IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_ready_ptr)), \ - 1, 1), \ - *(ushort_t *)(IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_active_ptr)), \ - DECSPACE16(*(ushort_t *) \ - (IDN_OFFSET2ADDR(mtp->mt_header.mh_svr_active_ptr)), \ - 1, 5), \ - mtp->mt_header.mh_cookie, \ - HEXSPACE(mtp->mt_header.mh_cookie, \ - mtp->mt_header.mh_cookie, 8, 2), \ - (void *)&mtp->mt_queue[0], \ - HEXSPACE(&mtp->mt_queue[0], &mtp->mt_queue[0], 16, 2) - -/*ARGSUSED*/ -static int -idn_mboxtbl_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - register int c, n, domid, subdomid; - register idn_mboxtbl_t *mtp; - register idn_mboxmsg_t *msp; - idn_mboxtbl_t *map, *mtbasep; - - - ASSERT((cp == MBXTBL_PART_REPORT) || (cp == MBXTBL_FULL_REPORT)); - - if (IDN_GLOCK_TRY_SHARED() == 0) { - (void) mi_mpprintf(mp, "Local domain busy, try again."); - return (0); - } - - if ((map = idn.mboxarea) == NULL) { - (void) mi_mpprintf(mp, - "WARNING: Local domain is not master, " - "ASSUMING idn.smr.vaddr."); - map = (idn_mboxtbl_t *)idn.smr.vaddr; - } - - if (map) { - (void) mi_mpprintf(mp, "Mailbox Area starts @ 0x%p", - (void *)map); - } else { - (void) mi_mpprintf(mp, "Mailbox Area not found."); - goto repdone; - } - - if (!idn.nchannels) { - (void) mi_mpprintf(mp, "No OPEN channels found"); - goto repdone; - } - - for (c = 0; c < IDN_MAX_NETS; c++) { - - IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]); - if (!IDN_CHANNEL_IS_ATTACHED(&idn.chan_servers[c])) { - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]); - continue; - } - - (void) mi_mpprintf(mp, - "Channel %d ---------------------------" - "--------------------------" - "-----------------------------", c); - (void) mi_mpprintf(mp, - " Domain Header " - "Ready/Active Ptrs " - "rdy/actv cookie Queue " - "busy"); - - for (domid = 0; domid < MAX_DOMAINS; domid++) { - register int busy_count; - - if ((cp == MBXTBL_PART_REPORT) && - (idn_domain[domid].dcpu == IDN_NIL_DCPU)) - continue; - - mtbasep = IDN_MBOXAREA_BASE(map, domid); - - for (subdomid = 0; subdomid < MAX_DOMAINS; - subdomid++) { - mtp = IDN_MBOXTBL_PTR(mtbasep, subdomid); - mtp = IDN_MBOXTBL_PTR_CHAN(mtp, c); - - if (subdomid == domid) { - if (subdomid == 0) - (void) mi_mpprintf(mp, - " %x.%x-%d%s%s", - domid, subdomid, c, - /*CONSTCOND*/ - DECSPACE(c, 2, 2), - "-- unused --"); - else - (void) mi_mpprintf(mp, - " .%x-%d%s%s", - subdomid, c, - /*CONSTCOND*/ - DECSPACE(c, 2, 2), - "-- unused --"); - continue; - } - busy_count = 0; - msp = &mtp->mt_queue[0]; - for (n = 0; n < IDN_MMBOX_NUMENTRIES; n++) { - if (msp[n].ms_owner) - busy_count++; - } - if (subdomid == 0) { - (void) mi_mpprintf(mp, - " %x.%x-%d%s%p%s%x%s/ %x%s" - "%d%s/ %d%s%x%s%p%s%d%s", - domid, subdomid, c, - /*CONSTCOND*/ - DECSPACE(c, 2, 2), - MBXINFO(mtp), busy_count, - busy_count ? " <<<<<":""); - } else { - (void) mi_mpprintf(mp, - " .%x-%d%s%p%s%x%s/ %x%s" - "%d%s/ %d%s%x%s%p%s%d%s", - subdomid, c, - /*CONSTCOND*/ - DECSPACE(c, 2, 2), - MBXINFO(mtp), busy_count, - busy_count ? " <<<<<":""); - } - } - } - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]); - } - -repdone: - IDN_GUNLOCK(); - - return (0); -} - -/*ARGSUSED*/ -static void -idn_mainmbox_domain_report(queue_t *wq, mblk_t *mp, int domid, - idn_mainmbox_t *mmp, char *mbxtype) -{ - register int c; - - if (mmp == NULL) { - (void) mi_mpprintf(mp, " %x.%s -- none --", domid, mbxtype); - return; - } - - for (c = 0; c < IDN_MAX_NETS; mmp++, c++) { - int mm_count; - - IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]); - if (IDN_CHANNEL_IS_DETACHED(&idn.chan_servers[c])) { - (void) mi_mpprintf(mp, " %x.%s %u -- not open --", - domid, mbxtype, (int)mmp->mm_channel); - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]); - continue; - } - - mm_count = ((mmp->mm_count < 0) ? 0 : mmp->mm_count) / 1000; - - (void) mi_mpprintf(mp, " %x.%s %d%s%d%s%d%s%p%s%p%s%p%s%d/%d", - domid, mbxtype, - (int)mmp->mm_channel, - /*CONSTCOND*/ - DECSPACE((int)mmp->mm_channel, 5, 2), - mm_count, DECSPACE(mm_count, 8, 2), - mmp->mm_dropped, - DECSPACE(mmp->mm_dropped, 8, 2), - (void *)mmp->mm_smr_mboxp, - HEXSPACE(mmp->mm_smr_mboxp, - mmp->mm_smr_mboxp, 16, 2), - (void *)mmp->mm_smr_readyp, - HEXSPACE(mmp->mm_smr_readyp, - mmp->mm_smr_readyp, 16, 2), - (void *)mmp->mm_smr_activep, - HEXSPACE(mmp->mm_smr_activep, - mmp->mm_smr_activep, 16, 2), - mmp->mm_qiget, mmp->mm_qiput); - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]); - } -} - -/*ARGSUSED2*/ -static int -idn_mainmbox_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - int domid; - int header = 0; - - /* - * Domain 0 never has a send/recv mainmbox so - * don't bother printing it. - */ - for (domid = 1; domid < MAX_DOMAINS; domid++) { - idn_domain_t *dp; - - dp = &idn_domain[domid]; - - if (dp->dcpu == IDN_NIL_DCPU) - continue; - IDN_DLOCK_SHARED(domid); - if (dp->dcpu == IDN_NIL_DCPU) { - IDN_DUNLOCK(domid); - continue; - } - if (!header) { - (void) mi_mpprintf(mp, - "Domain Chan PktCntK " - "PktDrop SMRMbox " - "ReadyPtr " - "ActvPtr Miget/Miput"); - header = 1; - } - - mutex_enter(&dp->dmbox.m_mutex); - idn_mainmbox_domain_report(wq, mp, domid, - idn_domain[domid].dmbox.m_send, - "snd"); - idn_mainmbox_domain_report(wq, mp, domid, - idn_domain[domid].dmbox.m_recv, - "rcv"); - mutex_exit(&dp->dmbox.m_mutex); - - IDN_DUNLOCK(domid); - - (void) mi_mpprintf(mp, - " ---------------------------------------" - "------------------------" - "----------------------------"); - } - - if (!header) - (void) mi_mpprintf(mp, "No ACTIVE domain connections exist"); - - return (0); -} - -/*ARGSUSED*/ -static int -idn_global_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - int i, nactive, masterid, nretry; - uint_t locpfn_upper, locpfn_lower, - rempfn_upper, rempfn_lower; - uint_t marea_upper, marea_lower, - iarea_upper, iarea_lower; - char alt_dbuffer[64]; - idn_retry_job_t *rp; - domainset_t retryset; - domainset_t connected; - idn_synczone_t *zp; - idn_syncop_t *sp; - idn_domain_t *dp; - char *dbp, *dbuffer; - - if (IDN_SYNC_TRYLOCK() == 0) { - (void) mi_mpprintf(mp, "Sync lock busy, try again."); - return (0); - } - - if (IDN_GLOCK_TRY_SHARED() == 0) { - (void) mi_mpprintf(mp, "Local domain busy, try again."); - IDN_SYNC_UNLOCK(); - return (0); - } - if ((dbp = dbuffer = ALLOC_DISPSTRING()) == NULL) - dbp = alt_dbuffer; - - (void) mi_mpprintf(mp, "IDN\n Global State = %s (%d)", - idngs_str[idn.state], idn.state); - - (void) mi_mpprintf(mp, "SMR"); - (void) mi_mpprintf(mp, " vaddr "); - (void) mi_mpprintf(mp, " 0x%p", (void *)idn.smr.vaddr); - - (void) mi_mpprintf(mp, " paddr-local paddr-remote"); - masterid = IDN_GET_MASTERID(); - locpfn_upper = (uint_t)(idn.smr.locpfn >> (32 - PAGESHIFT)); - locpfn_lower = (uint_t)(idn.smr.locpfn << PAGESHIFT); - if (idn.smr.rempfn == PFN_INVALID) { - rempfn_upper = rempfn_lower = 0; - } else { - rempfn_upper = (uint_t)(idn.smr.rempfn >> (32 - PAGESHIFT)); - rempfn_lower = (uint_t)(idn.smr.rempfn << PAGESHIFT); - } - (void) mi_mpprintf(mp, " 0x%x.%x%s0x%x.%x", - locpfn_upper, locpfn_lower, - HEXSPACE(locpfn_lower, locpfn_lower, 8, - (locpfn_upper < 0x10) ? 4 : 3), - rempfn_upper, rempfn_lower); - - (void) mi_mpprintf(mp, " SMR length = %d MBytes", IDN_SMR_SIZE); - (void) mi_mpprintf(mp, " SMR bufsize = %d Bytes", IDN_SMR_BUFSIZE); - (void) mi_mpprintf(mp, " NWR length = %d MBytes", IDN_NWR_SIZE); - marea_upper = (uint_t)((uint64_t)IDN_MBOXAREA_SIZE >> 32); - marea_lower = (uint_t)((uint64_t)IDN_MBOXAREA_SIZE & 0xffffffff); - iarea_upper = (uint_t)((uint64_t)(MB2B(IDN_NWR_SIZE) - - (size_t)IDN_MBOXAREA_SIZE) >> 32); - iarea_lower = (uint_t)((MB2B(IDN_NWR_SIZE) - - (size_t)IDN_MBOXAREA_SIZE) & 0xffffffff); - (void) mi_mpprintf(mp, - " [ mbox area = 0x%x.%x Bytes, " - "iobuf area = 0x%x.%x Bytes ]", - marea_upper, marea_lower, iarea_upper, iarea_lower); - - (void) mi_mpprintf(mp, - "\nIDNnet (local domain [id:%d] [name:%s] is %s)", - idn.localid, - idn_domain[idn.localid].dname, - (masterid == IDN_NIL_DOMID) ? "IDLE" : - (idn.localid == masterid) ? "MASTER" : - "SLAVE"); - nactive = 0; - for (i = 0; i < IDN_MAX_NETS; i++) { - IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[i]); - if (IDN_CHANNEL_IS_ACTIVE(&idn.chan_servers[i])) - nactive++; - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[i]); - } - (void) mi_mpprintf(mp, " I/O Networks: (Open = %d, " - "Active = %d, Max = %d)", - idn.nchannels, nactive, IDN_MAX_NETS); - (void) mi_mpprintf(mp, " Number of Domains = %d", idn.ndomains); - (void) mi_mpprintf(mp, " Number of AWOLs = %d", idn.nawols); - /* - * During connect domains can possibly be in ds_connected - * while still in ds_trans_on. Only once they leave ds_trans_on - * are they really connected. - */ - connected = idn.domset.ds_connected & ~idn.domset.ds_trans_on; - DOMAINSET_ADD(connected, idn.localid); - boardset2str(connected, dbp); - (void) mi_mpprintf(mp, " Connected Domains = %s", dbp); - domainset2str(idn.domset.ds_trans_on, dbp); - (void) mi_mpprintf(mp, " Pending Domain Links = %s", - idn.domset.ds_trans_on ? dbp : "<>"); - domainset2str(idn.domset.ds_trans_off, dbp); - (void) mi_mpprintf(mp, " Pending Domain Unlinks = %s", - idn.domset.ds_trans_off ? dbp : "<>"); - mutex_enter(&idn.retryqueue.rq_mutex); - nretry = idn.retryqueue.rq_count; - retryset = 0; - for (i = 0, rp = idn.retryqueue.rq_jobs; i < nretry; i++, - rp = rp->rj_next) { - int domid; - - domid = IDN_RETRY_TOKEN2DOMID(rp->rj_token); - if (VALID_DOMAINID(domid)) { - DOMAINSET_ADD(retryset, domid); - } - } - mutex_exit(&idn.retryqueue.rq_mutex); - domainset2str(retryset, dbp); - (void) mi_mpprintf(mp, " Retry Jobs:Domains = %d:%s", - nretry, retryset ? dbp : "<>"); - domainset2str(idn.domset.ds_hitlist, dbp); - (void) mi_mpprintf(mp, " Hitlist Domains = %s", - idn.domset.ds_hitlist ? dbp : "<>"); - domainset2str(idn.domset.ds_relink, dbp); - (void) mi_mpprintf(mp, " Reconfig Domains = %s", - idn.domset.ds_relink ? dbp : "<>"); - if (idn.domset.ds_relink) - (void) mi_mpprintf(mp, " new master id = %d", - IDN_GET_NEW_MASTERID()); - if (masterid == IDN_NIL_DOMID) { - (void) mi_mpprintf(mp, " Master Domain: no master"); - } else { - idn_domain_t *mdp; - - mdp = &idn_domain[masterid]; - - (void) mi_mpprintf(mp, - " Master Domain (id:name/brds - state):"); - - if (strlen(mdp->dname) > 0) - (void) strcpy(dbp, mdp->dname); - else - boardset2str(mdp->dhw.dh_boardset, dbp); - if (masterid < 10) - (void) mi_mpprintf(mp, " %d: %s - %s", - masterid, dbp, - idnds_str[mdp->dstate]); - else - (void) mi_mpprintf(mp, " %d: %s - %s", - masterid, dbp, - idnds_str[mdp->dstate]); - } - if (idn.ndomains <= 1) { - (void) mi_mpprintf(mp, " Slave Domains: none"); - } else { - int d; - - (void) mi_mpprintf(mp, - " Slave Domains (id:name/brds - state):"); - for (d = 0; d < MAX_DOMAINS; d++) { - dp = &idn_domain[d]; - - if ((dp->dcpu == IDN_NIL_DCPU) || (d == masterid)) - continue; - - if (strlen(dp->dname) > 0) - (void) strcpy(dbp, dp->dname); - else - boardset2str(dp->dhw.dh_boardset, dbp); - if (d < 10) - (void) mi_mpprintf(mp, " %d: %s - %s", - d, dbp, - idnds_str[dp->dstate]); - else - (void) mi_mpprintf(mp, " %d: %s - %s", - d, dbp, - idnds_str[dp->dstate]); - } - } - - if (idn.nawols == 0) { - (void) mi_mpprintf(mp, " AWOL Domains: none"); - } else { - int d; - - (void) mi_mpprintf(mp, " AWOL Domains (id:name/brds):"); - for (d = 0; d < MAX_DOMAINS; d++) { - dp = &idn_domain[d]; - - if (!DOMAIN_IN_SET(idn.domset.ds_awol, d) || - (dp->dcpu == IDN_NIL_DCPU)) - continue; - - if (strlen(dp->dname) > 0) - (void) strcpy(dbp, dp->dname); - else - boardset2str(dp->dhw.dh_boardset, dbp); - if (d < 10) - (void) mi_mpprintf(mp, " %d: %s", - d, dbp); - else - (void) mi_mpprintf(mp, " %d: %s", - d, dbp); - } - } - - /*CONSTCOND*/ - i = IDN_SYNC_GETZONE(IDNSYNC_CONNECT); - zp = &idn.sync.sz_zone[i]; - if (zp->sc_cnt == 0) { - (void) mi_mpprintf(mp, " Sync Zone (con): [empty]"); - } else { - (void) mi_mpprintf(mp, " Sync Zone (con): [%d domains]", - zp->sc_cnt); - sp = zp->sc_op; - for (i = 0; (i < zp->sc_cnt) && sp; i++) { - (void) mi_mpprintf(mp, - " " - "%x: x_set =%s0x%x, r_set =%s0x%x", - sp->s_domid, - HEXSPACE(sp->s_set_exp, - sp->s_set_exp, 4, 1), - sp->s_set_exp, - HEXSPACE(sp->s_set_rdy, - sp->s_set_rdy, 4, 1), - sp->s_set_rdy); - sp = sp->s_next; - } - } - /*CONSTCOND*/ - i = IDN_SYNC_GETZONE(IDNSYNC_DISCONNECT); - zp = &idn.sync.sz_zone[i]; - if (zp->sc_cnt == 0) { - (void) mi_mpprintf(mp, " Sync Zone (dis): [empty]"); - } else { - (void) mi_mpprintf(mp, " Sync Zone (dis): [%d domains]", - zp->sc_cnt); - sp = zp->sc_op; - for (i = 0; (i < zp->sc_cnt) && sp; i++) { - (void) mi_mpprintf(mp, - " " - "%x: x_set =%s0x%x, r_set =%s0x%x", - sp->s_domid, - HEXSPACE(sp->s_set_exp, - sp->s_set_exp, 4, 1), - sp->s_set_exp, - HEXSPACE(sp->s_set_rdy, - sp->s_set_rdy, 4, 1), - sp->s_set_rdy); - sp = sp->s_next; - } - } - - IDN_GUNLOCK(); - IDN_SYNC_UNLOCK(); - - if (dbuffer) { - FREE_DISPSTRING(dbuffer); - } - - return (0); -} - -/*ARGSUSED*/ -static int -idn_domain_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr) -{ - int d, nchan; - uint_t domset; - idn_chanset_t chanset; - idn_domain_t *dp; - uint_t pset_upper, pset_lower; - char *dbuffer, *dbp; - char alt_dbuffer[64]; - - - if (IDN_SYNC_TRYLOCK() == 0) { - (void) mi_mpprintf(mp, "Sync lock busy, try again."); - return (0); - } - - if (IDN_GLOCK_TRY_SHARED() == 0) { - (void) mi_mpprintf(mp, "Local domain busy, try again."); - IDN_SYNC_UNLOCK(); - return (0); - } - - if ((dbp = dbuffer = ALLOC_DISPSTRING()) == NULL) - dbp = alt_dbuffer; - - if (cp == NULL) - domset = DOMAINSET(idn.localid); - else - domset = DOMAINSET_ALL; - - for (d = 0; d < MAX_DOMAINS; d++) { - - if (DOMAIN_IN_SET(domset, d) == 0) - continue; - - dp = &idn_domain[d]; - - if (dp->dcpu == IDN_NIL_DCPU) - continue; - - if (IDN_DLOCK_TRY_SHARED(d) == 0) { - if (d < 10) - (void) mi_mpprintf(mp, - "Domain %d (0x%p) busy...", - d, (void *)dp); - else - (void) mi_mpprintf(mp, - "Domain %d (0x%p) busy...", - d, (void *)dp); - continue; - } - if (dp->dcpu == IDN_NIL_DCPU) { - IDN_DUNLOCK(d); - continue; - } - if (d < 10) - (void) mi_mpprintf(mp, "%sDomain %d (0x%p)", - (d && (idn.ndomains > 1)) ? "\n" : "", - d, (void *)dp); - else - (void) mi_mpprintf(mp, "%sDomain %d (0x%p)", - (d && (idn.ndomains > 1)) ? "\n" : "", - d, (void *)dp); - - if (d == idn.localid) - (void) mi_mpprintf(mp, " (local) State = %s (%d)", - idnds_str[dp->dstate], dp->dstate); - else - (void) mi_mpprintf(mp, " State = %s (%d)", - idnds_str[dp->dstate], dp->dstate); - (void) mi_mpprintf(mp, " Name = %s, Netid = %d", - (strlen(dp->dname) > 0) ? dp->dname : "<>", - (int)dp->dnetid); - - CHANSET_ZERO(chanset); - nchan = idn_domain_is_registered(d, -1, &chanset); - if (dbuffer) - mask2str(chanset, dbp, 32); - else - (void) sprintf(dbp, "0x%x", chanset); - (void) mi_mpprintf(mp, " Nchans = %d, Chanset = %s", - nchan, nchan ? dbp : "<>"); - pset_upper = UPPER32_CPUMASK(dp->dcpuset); - pset_lower = LOWER32_CPUMASK(dp->dcpuset); - if (dbuffer) - boardset2str(dp->dhw.dh_boardset, dbp); - else - (void) sprintf(dbp, "0x%x", dp->dhw.dh_boardset); - - (void) mi_mpprintf(mp, " Nboards = %d, Brdset = %s", - dp->dhw.dh_nboards, - dp->dhw.dh_nboards ? dbp : "<>"); - (void) sprintf(dbp, "0x%x.%x", pset_upper, pset_lower); - (void) mi_mpprintf(mp, " Ncpus = %d, Cpuset = %s", - dp->dncpus, dp->dncpus ? dbp : "<>"); - (void) mi_mpprintf(mp, " Nmcadr = %d", - dp->dhw.dh_nmcadr); - (void) mi_mpprintf(mp, - " MsgTimer = %s (cnt = %d)", - (dp->dtimerq.tq_count > 0) - ? "active" : "idle", - dp->dtimerq.tq_count); - (void) mi_mpprintf(mp, " Dcpu = %d " - "(lastcpu = %d, cpuindex = %d)", - dp->dcpu, dp->dcpu_last, dp->dcpuindex); - (void) mi_mpprintf(mp, " Dio = %d " - "(ioerr = %d, iochk = %d, iowanted = %d)", - dp->dio, dp->dioerr, dp->diocheck ? 1 : 0, - dp->diowanted ? 1 : 0); - if (dp->dsync.s_cmd == IDNSYNC_NIL) { - (void) mi_mpprintf(mp, " Dsync = %s", - idnsync_str[IDNSYNC_NIL]); - } else { - (void) mi_mpprintf(mp, - " Dsync = %s " - "(x_set = 0x%x, r_set = 0x%x)", - idnsync_str[dp->dsync.s_cmd], - (uint_t)dp->dsync.s_set_exp, - (uint_t)dp->dsync.s_set_rdy); - } - (void) mi_mpprintf(mp, " Dvote = 0x%x", - dp->dvote.ticket); - (void) mi_mpprintf(mp, " Dfin = %s (Sync = %s)", - idnfin_str[dp->dfin], - (dp->dfin_sync == IDNFIN_SYNC_OFF) ? "OFF" : - (dp->dfin_sync == IDNFIN_SYNC_YES) ? "YES" : - "NO"); - (void) mi_mpprintf(mp, " Dcookie_err = %s (cnt = %d)", - dp->dcookie_err ? "YES" : "NO", - dp->dcookie_errcnt); - IDN_DUNLOCK(d); - } - - IDN_GUNLOCK(); - - if (dbuffer) { - FREE_DISPSTRING(dbuffer); - } - - IDN_SYNC_UNLOCK(); - - return (0); -} - -#define SNOOP_ENTRIES 2048 /* power of 2 */ - -struct snoop_buffer { -/* 0 */ char io; -/* 1 */ char board; -/* 2 */ char trans[14]; - -/* 10 */ uint_t xargs[4]; -} *snoop_data, snoop_buffer[SNOOP_ENTRIES+1]; - - -int snoop_index; -kmutex_t snoop_mutex; -static char _bd2hexascii[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -#define SNOOP_IDN(in, tr, bd, arg1, arg2, arg3, arg4) \ -{ \ - if (idn_snoop) { \ - mutex_enter(&snoop_mutex); \ - if (snoop_data == NULL) { \ - snoop_data = (struct snoop_buffer *) \ - (((uint_t)(uintptr_t)snoop_buffer + 0xf) & \ - ~0xf); \ - } \ - snoop_data[snoop_index].io = ((in) == 0) ? 'o' : 'i'; \ - snoop_data[snoop_index].board = \ - ((bd) == -1) ? 'X' : _bd2hexascii[bd]; \ - (void) strncpy(snoop_data[snoop_index].trans, (tr), 14); \ - snoop_data[snoop_index].xargs[0] = (arg1); \ - snoop_data[snoop_index].xargs[1] = (arg2); \ - snoop_data[snoop_index].xargs[2] = (arg3); \ - snoop_data[snoop_index].xargs[3] = (arg4); \ - snoop_index++; \ - snoop_index &= SNOOP_ENTRIES - 1; \ - mutex_exit(&snoop_mutex); \ - } \ -} - -/* - * Allocate the circular buffers to be used for - * DMV interrupt processing. - */ -static int -idn_init_handler() -{ - int i, c; - size_t len; - idn_dmv_msg_t *basep, *ivp; - uint32_t ivp_offset; - procname_t proc = "idn_init_handler"; - - if (idn.intr.dmv_data != NULL) { - cmn_err(CE_WARN, - "IDN: 130: IDN DMV handler already initialized"); - return (-1); - } - - /* - * This memory will be touched by the low-level - * DMV trap handler for IDN. - */ - len = sizeof (idn_dmv_data_t); - len = roundup(len, sizeof (uint64_t)); - len += NCPU * idn_dmv_pending_max * sizeof (idn_dmv_msg_t); - len = roundup(len, PAGESIZE); - - PR_PROTO("%s: sizeof (idn_dmv_data_t) = %lu\n", - proc, sizeof (idn_dmv_data_t)); - PR_PROTO("%s: allocating %lu bytes for dmv data area\n", proc, len); - - idn.intr.dmv_data_len = len; - idn.intr.dmv_data = kmem_zalloc(len, KM_SLEEP); - - PR_PROTO("%s: DMV data area = %p\n", proc, (void *)idn.intr.dmv_data); - - idn_dmv_data = (idn_dmv_data_t *)idn.intr.dmv_data; - basep = (idn_dmv_msg_t *)roundup((size_t)idn.intr.dmv_data + - sizeof (idn_dmv_data_t), - sizeof (uint64_t)); - idn_dmv_data->idn_dmv_qbase = (uint64_t)basep; - - ivp = basep; - ivp_offset = 0; - /* - * The buffer queues are allocated per-cpu. - */ - for (c = 0, ivp = basep; c < NCPU; ivp++, c++) { - idn_dmv_data->idn_dmv_cpu[c].idn_dmv_current = ivp_offset; - idn_iv_queue[c] = ivp; - ivp_offset += sizeof (idn_dmv_msg_t); - for (i = 1; i < idn_dmv_pending_max; ivp++, i++) { - ivp->iv_next = ivp_offset; - ivp->iv_ready = 0; - lock_set(&ivp->iv_ready); - ivp_offset += sizeof (idn_dmv_msg_t); - } - ivp->iv_next = idn_dmv_data->idn_dmv_cpu[c].idn_dmv_current; - ivp->iv_ready = 0; - lock_set(&ivp->iv_ready); - } - - idn.intr.dmv_inum = STARFIRE_DMV_IDN_BASE; - idn.intr.soft_inum = add_softintr((uint_t)idn_pil, idn_handler, 0, - SOFTINT_ST); - idn_dmv_data->idn_soft_inum = idn.intr.soft_inum; - /* - * Make sure everything is out there before - * we effectively set it free for use. - */ - membar_stld_stst(); - - if (dmv_add_intr(idn.intr.dmv_inum, idn_dmv_handler, - (caddr_t)idn_dmv_data)) { - idn_deinit_handler(); - cmn_err(CE_WARN, "IDN: 132: failed to add IDN DMV handler"); - return (-1); - } - - return (0); -} - -static void -idn_deinit_handler() -{ - if (idn.intr.dmv_data == NULL) - return; - - (void) dmv_rem_intr(idn.intr.dmv_inum); - (void) rem_softintr(idn.intr.soft_inum); - kmem_free(idn.intr.dmv_data, idn.intr.dmv_data_len); - idn.intr.dmv_data = NULL; -} - -/* - * High-level (soft interrupt) handler for DMV interrupts - */ -/*ARGSUSED0*/ -static uint_t -idn_handler(caddr_t unused, caddr_t unused2) -{ -#ifdef DEBUG - int count = 0; -#endif /* DEBUG */ - int cpuid = (int)CPU->cpu_id; - ushort_t mtype, atype; - idn_dmv_msg_t *xp, *xplimit; - procname_t proc = "idn_handler"; - - ASSERT(getpil() >= idn_pil); - flush_windows(); - - /* - * Clear the synchronization flag to indicate that - * processing has started. As long as idn_dmv_active - * is non-zero, idn_dmv_handler will queue work without - * initiating a soft interrupt. Since we clear it - * first thing at most one pil-interrupt for IDN will - * queue up behind the currently active one. We don't - * want to clear this flag at the end because it leaves - * a window where an interrupt could get lost (unless it's - * pushed by a subsequent interrupt). The objective in - * doing this is to prevent exhausting a cpu's intr_vec - * structures with interrupts of the same pil level. - */ - lock_clear(&idn_dmv_data->idn_dmv_cpu[cpuid].idn_dmv_active); - - xp = idn_iv_queue[cpuid]; - xplimit = xp + idn_dmv_pending_max; - xp += idn_intr_index[cpuid]; - /* - * As long as there's stuff that's READY in the - * queue, keep processing. - */ - while (lock_try(&xp->iv_ready)) { - - ASSERT(lock_try(&xp->iv_inuse) == 0); - - mtype = (ushort_t)xp->iv_mtype; - mtype &= IDNP_MSGTYPE_MASK | IDNP_ACKNACK_MASK; - atype = (ushort_t)xp->iv_atype; - - if (((int)xp->iv_ver == idn.version) && mtype) { - idn_protojob_t *jp; -#ifdef DEBUG - STRING(mstr); - STRING(astr); - - INUM2STR(mtype, mstr); - if ((mtype & IDNP_MSGTYPE_MASK) == 0) { - INUM2STR(atype, astr); - (void) strcat(mstr, "/"); - (void) strcat(mstr, astr); - } - - count++; - - PR_XDC("%s:%d:%d RECV: scpu = %d, msg = 0x%x(%s)\n", - proc, (int)xp->iv_domid, count, - (int)xp->iv_cpuid, mtype, mstr); - PR_XDC("%s:%d:%d R-DATA: a0 = 0x%x, a1 = 0x%x\n", - proc, (int)xp->iv_domid, count, - xp->iv_xargs0, xp->iv_xargs1); - PR_XDC("%s:%d:%d R-DATA: a2 = 0x%x, a3 = 0x%x\n", - proc, (int)xp->iv_domid, count, - xp->iv_xargs2, xp->iv_xargs3); -#endif /* DEBUG */ - - if (mtype == IDNP_DATA) { - jp = NULL; - /* - * The only time we receive pure - * data messages at this level is - * to wake up the channel server. - * Since this is often an urgent - * request we'll do it from here - * instead of waiting for a proto - * server to do it. - */ - idn_signal_data_server((int)xp->iv_domid, - (ushort_t)xp->iv_xargs0); - } else { - jp = idn_protojob_alloc(KM_NOSLEEP); - /* - * If the allocation fails, just drop - * the message and get on with life. - * If memory pressure is this great then - * dropping this message is probably - * the least of our worries! - */ - if (jp) { - jp->j_msg.m_domid = (int)xp->iv_domid; - jp->j_msg.m_cpuid = (int)xp->iv_cpuid; - jp->j_msg.m_msgtype = mtype; - jp->j_msg.m_acktype = atype; - jp->j_msg.m_cookie = xp->iv_cookie; - SET_XARGS(jp->j_msg.m_xargs, - xp->iv_xargs0, xp->iv_xargs1, - xp->iv_xargs2, xp->iv_xargs3); - } - - } - membar_ldst_stst(); - - lock_clear(&xp->iv_inuse); - - if (jp) - idn_protojob_submit(jp->j_msg.m_domid, jp); - } else { - membar_ldst_stst(); - IDN_GKSTAT_INC(gk_dropped_intrs); - lock_clear(&xp->iv_inuse); - } - - if (++xp == xplimit) - xp = idn_iv_queue[cpuid]; - } - - idn_intr_index[cpuid] = xp - idn_iv_queue[cpuid]; - - return (DDI_INTR_CLAIMED); -} - -void -idn_awol_event_set(boardset_t boardset) -{ - idnsb_event_t *sbp; - procname_t proc = "idn_awol_event_set"; - - ASSERT(IDN_GLOCK_IS_EXCL()); - - mutex_enter(&idn.idnsb_mutex); - sbp = idn.idnsb_eventp; - if (sbp == NULL) { - cmn_err(CE_WARN, "IDN: 133: sigblock event area missing"); - cmn_err(CE_CONT, - "IDN: 134: unable to mark boardset (0x%x) AWOL\n", - boardset); - mutex_exit(&idn.idnsb_mutex); - return; - } - - if (boardset == 0) { - PR_PROTO("%s: AWOL BOARDSET is 0, NO EVENT <<<<<<<<<<<<<<<\n", - proc); - mutex_exit(&idn.idnsb_mutex); - return; - } else { - PR_PROTO("%s: MARKING BOARDSET (0x%x) AWOL\n", proc, boardset); - } - SSIEVENT_ADD(sbp, SSIEVENT_AWOL, boardset); - mutex_exit(&idn.idnsb_mutex); -} - -void -idn_awol_event_clear(boardset_t boardset) -{ - idnsb_event_t *sbp; - procname_t proc = "idn_awol_event_clear"; - - ASSERT(IDN_GLOCK_IS_EXCL()); - - mutex_enter(&idn.idnsb_mutex); - sbp = idn.idnsb_eventp; - if (sbp == NULL) { - cmn_err(CE_WARN, "IDN: 133: sigblock event area missing"); - cmn_err(CE_CONT, - "IDN: 134: unable to mark boardset (0x%x) AWOL\n", - boardset); - mutex_exit(&idn.idnsb_mutex); - return; - } - - if (boardset == 0) { - PR_PROTO("%s: AWOL BOARDSET is 0, NO EVENT <<<<<<<<<<<<<<<\n", - proc); - mutex_exit(&idn.idnsb_mutex); - return; - } else { - PR_PROTO("%s: CLEARING BOARDSET (0x%x) AWOL\n", proc, boardset); - } - SSIEVENT_DEL(sbp, SSIEVENT_AWOL, boardset); - mutex_exit(&idn.idnsb_mutex); -} - -static void -idn_gkstat_init() -{ - struct kstat *ksp; - struct idn_gkstat_named *sgkp; - -#ifdef kstat - if ((ksp = kstat_create(IDNNAME, ddi_get_instance(idn.dip), - IDNNAME, "net", KSTAT_TYPE_NAMED, - sizeof (struct idn_gkstat_named) / sizeof (kstat_named_t), - KSTAT_FLAG_PERSISTENT)) == NULL) { -#else - if ((ksp = kstat_create(IDNNAME, ddi_get_instance(idn.dip), - IDNNAME, "net", KSTAT_TYPE_NAMED, - sizeof (struct idn_gkstat_named) / - sizeof (kstat_named_t), 0)) == NULL) { -#endif /* kstat */ - cmn_err(CE_CONT, "IDN: 135: %s: %s\n", - IDNNAME, "kstat_create failed"); - return; - } - - idn.ksp = ksp; - sgkp = (struct idn_gkstat_named *)(ksp->ks_data); - kstat_named_init(&sgkp->sk_curtime, "curtime", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_reconfigs, "reconfigs", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_reconfig_last, "reconfig_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_reaps, "reaps", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_reap_last, "reap_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_links, "links", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_link_last, "link_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_unlinks, "unlinks", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_unlink_last, "unlink_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_buffail, "buf_fail", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_buffail_last, "buf_fail_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_slabfail, "slab_fail", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_slabfail_last, "slab_fail_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_slabfail_last, "slab_fail_last", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_reap_count, "reap_count", - KSTAT_DATA_ULONG); - kstat_named_init(&sgkp->sk_dropped_intrs, "dropped_intrs", - KSTAT_DATA_ULONG); - ksp->ks_update = idn_gkstat_update; - ksp->ks_private = (void *)NULL; - kstat_install(ksp); -} - -static void -idn_gkstat_deinit() -{ - if (idn.ksp) - kstat_delete(idn.ksp); - idn.ksp = NULL; -} - -static int -idn_gkstat_update(kstat_t *ksp, int rw) -{ - struct idn_gkstat_named *sgkp; - - sgkp = (struct idn_gkstat_named *)ksp->ks_data; - - if (rw == KSTAT_WRITE) { - sg_kstat.gk_reconfigs = sgkp->sk_reconfigs.value.ul; - sg_kstat.gk_reconfig_last = sgkp->sk_reconfig_last.value.ul; - sg_kstat.gk_reaps = sgkp->sk_reaps.value.ul; - sg_kstat.gk_reap_last = sgkp->sk_reap_last.value.ul; - sg_kstat.gk_links = sgkp->sk_links.value.ul; - sg_kstat.gk_link_last = sgkp->sk_link_last.value.ul; - sg_kstat.gk_unlinks = sgkp->sk_unlinks.value.ul; - sg_kstat.gk_unlink_last = sgkp->sk_unlink_last.value.ul; - sg_kstat.gk_buffail = sgkp->sk_buffail.value.ul; - sg_kstat.gk_buffail_last = sgkp->sk_buffail_last.value.ul; - sg_kstat.gk_slabfail = sgkp->sk_slabfail.value.ul; - sg_kstat.gk_slabfail_last = sgkp->sk_slabfail_last.value.ul; - sg_kstat.gk_reap_count = sgkp->sk_reap_count.value.ul; - sg_kstat.gk_dropped_intrs = sgkp->sk_dropped_intrs.value.ul; - } else { - sgkp->sk_curtime.value.ul = ddi_get_lbolt(); - sgkp->sk_reconfigs.value.ul = sg_kstat.gk_reconfigs; - sgkp->sk_reconfig_last.value.ul = sg_kstat.gk_reconfig_last; - sgkp->sk_reaps.value.ul = sg_kstat.gk_reaps; - sgkp->sk_reap_last.value.ul = sg_kstat.gk_reap_last; - sgkp->sk_links.value.ul = sg_kstat.gk_links; - sgkp->sk_link_last.value.ul = sg_kstat.gk_link_last; - sgkp->sk_unlinks.value.ul = sg_kstat.gk_unlinks; - sgkp->sk_unlink_last.value.ul = sg_kstat.gk_unlink_last; - sgkp->sk_buffail.value.ul = sg_kstat.gk_buffail; - sgkp->sk_buffail_last.value.ul = sg_kstat.gk_buffail_last; - sgkp->sk_slabfail.value.ul = sg_kstat.gk_slabfail; - sgkp->sk_slabfail_last.value.ul = sg_kstat.gk_slabfail_last; - sgkp->sk_reap_count.value.ul = sg_kstat.gk_reap_count; - sgkp->sk_dropped_intrs.value.ul = sg_kstat.gk_dropped_intrs; - } - - return (0); -} - -#ifdef DEBUG -#define RW_HISTORY 100 -static uint_t rw_history[NCPU][RW_HISTORY]; -static int rw_index[NCPU]; -#endif /* DEBUG */ - -static int -idn_rw_mem(idnop_t *idnop) -{ - uint_t lo_off, hi_off; - int rw, blksize, num; - int cpuid; - register int n, idx; - char *ibuf, *obuf; - char *smraddr; - struct seg *segp; - ulong_t randx; - kmutex_t slock; - kcondvar_t scv; - static int orig_gstate = IDNGS_IGNORE; - extern struct seg ktextseg; - -#define RANDOM_INIT() (randx = ddi_get_lbolt()) -#define RANDOM(a, b) \ - (((a) >= (b)) ? \ - (a) : (((randx = randx * 1103515245L + 12345) % ((b)-(a))) + (a))) - - RANDOM_INIT(); - - lo_off = idnop->rwmem.lo_off; - hi_off = idnop->rwmem.hi_off; - blksize = idnop->rwmem.blksize; - num = idnop->rwmem.num; - rw = idnop->rwmem.rw; /* 0 = rd, 1 = wr, 2 = rd/wr */ - - if (((hi_off > (uint_t)MB2B(IDN_SMR_SIZE)) || (lo_off >= hi_off) || - (blksize <= 0) || (blksize > (hi_off - lo_off)) || (num <= 0)) && - (idnop->rwmem.goawol == -1)) { - return (EINVAL); - } - - if (idnop->rwmem.goawol && (orig_gstate == IDNGS_IGNORE)) { - IDN_GLOCK_EXCL(); - cmn_err(CE_WARN, "IDN: Local domain going into IGNORE MODE!!"); - orig_gstate = idn.state; - IDN_GSTATE_TRANSITION(IDNGS_IGNORE); - IDN_GUNLOCK(); - - } else if (!idnop->rwmem.goawol && (orig_gstate != IDNGS_IGNORE)) { - IDN_GLOCK_EXCL(); - cmn_err(CE_WARN, - "IDN: Local domain restoring original state %s(%d)", - idngs_str[orig_gstate], (int)orig_gstate); - IDN_GSTATE_TRANSITION(orig_gstate); - orig_gstate = IDNGS_IGNORE; - IDN_GUNLOCK(); - } - /* - * Just requested AWOL. - */ - if (num == 0) - return (0); - /* - * Default READ only. - */ - ibuf = (char *)kmem_alloc(blksize, KM_SLEEP); - if (rw == 1) { - /* - * WRITE only. - */ - obuf = ibuf; - ibuf = NULL; - } else if (rw == 2) { - /* - * READ/WRITE. - */ - obuf = (char *)kmem_alloc(blksize, KM_SLEEP); - for (segp = &ktextseg; segp; segp = AS_SEGNEXT(&kas, segp)) { - if (segp->s_size >= blksize) - break; - } - if (segp == NULL) { - cmn_err(CE_WARN, - "IDN: blksize (%d) too large", blksize); - return (EINVAL); - } - bcopy(segp->s_base, obuf, blksize); - } - - mutex_init(&slock, NULL, MUTEX_DEFAULT, NULL); - cv_init(&scv, NULL, CV_DEFAULT, NULL); - - cmn_err(CE_NOTE, - "IDN: starting %s of %d blocks of %d bytes each...", - (rw == 1) ? "W-ONLY" : (rw == 2) ? "RW" : "R-ONLY", - num, blksize); - - for (n = 0; n < num; n++) { - uint_t rpos; - - if ((hi_off - lo_off) > blksize) - rpos = RANDOM(lo_off, (hi_off - blksize)); - else - rpos = lo_off; - smraddr = IDN_OFFSET2ADDR(rpos); - - cpuid = (int)CPU->cpu_id; -#ifdef DEBUG - idx = rw_index[cpuid]++ % RW_HISTORY; - rw_history[cpuid][idx] = rpos; -#endif /* DEBUG */ - - switch (rw) { - case 0: - bcopy(smraddr, ibuf, blksize); - break; - case 1: - bcopy(obuf, smraddr, blksize); - break; - case 2: - if (n & 1) - bcopy(obuf, smraddr, blksize); - else - bcopy(smraddr, ibuf, blksize); - break; - default: - break; - } - if (!(n % 1000)) { - int rv; - - mutex_enter(&slock); - rv = cv_reltimedwait_sig(&scv, &slock, hz, - TR_CLOCK_TICK); - mutex_exit(&slock); - if (rv == 0) - break; - } - } - - cv_destroy(&scv); - mutex_destroy(&slock); - - if (ibuf) - kmem_free(ibuf, blksize); - if (obuf) - kmem_free(obuf, blksize); - - return (0); -} - -void -inum2str(uint_t inum, char str[]) -{ - uint_t acknack; - - str[0] = '\0'; - - acknack = (inum & IDNP_ACKNACK_MASK); - inum &= ~IDNP_ACKNACK_MASK; - - if (!inum && !acknack) { - (void) strcpy(str, idnm_str[0]); - return; - } - - if (inum == 0) { - (void) strcpy(str, (acknack & IDNP_ACK) ? "ack" : "nack"); - } else { - if (inum < IDN_NUM_MSGTYPES) - (void) strcpy(str, idnm_str[inum]); - else - (void) sprintf(str, "0x%x?", inum); - if (acknack) { - if (acknack & IDNP_ACK) - (void) strcat(str, "+ack"); - else - (void) strcat(str, "+nack"); - } - } -} - -boardset_t -cpuset2boardset(cpuset_t portset) -{ - register int c; - register boardset_t bset; - - bset = 0; - for (c = 0; c < NCPU; ) - if (CPU_IN_SET(portset, c)) { - BOARDSET_ADD(bset, CPUID_TO_BOARDID(c)); - c = (c + 4) & ~3; - } else { - c++; - } - - return (bset); -} - -void -cpuset2str(cpuset_t cset, char buffer[]) -{ - register int c, n; - - buffer[0] = '\0'; - for (c = n = 0; c < NCPU; c++) { - if (!CPU_IN_SET(cset, c)) - continue; -#ifdef DEBUG - if (strlen(buffer) >= _DSTRLEN) { - PR_PROTO("************* WARNING WARNING WARNING\n"); - PR_PROTO("cpuset2str(cpu = %d) buffer " - "OVERFLOW <<<<<<\n", c); - PR_PROTO("*******************************\n"); - (void) sprintf(&buffer[_DSTRLEN-6], "*OVER"); - return; - } -#endif /* DEBUG */ - if (n == 0) - (void) sprintf(buffer, "%d", c); - else - (void) sprintf(buffer, "%s, %d", buffer, c); - n++; - } -} - -void -domainset2str(domainset_t dset, char buffer[]) -{ - /* - * Since domainset_t and boardset_t are the - * same (max = MAX_DOMAINS = MAX_BOARDS) we - * can just overload boardset2str(). - */ - mask2str((uint_t)dset, buffer, MAX_DOMAINS); -} - -void -boardset2str(boardset_t bset, char buffer[]) -{ - mask2str((uint_t)bset, buffer, MAX_BOARDS); -} - -void -mask2str(uint_t mask, char buffer[], int maxnum) -{ - int n, i; - - buffer[0] = '\0'; - for (i = n = 0; i < maxnum; i++) { - if ((mask & (1 << i)) == 0) - continue; - if (n == 0) - (void) sprintf(buffer, "%d", i); - else - (void) sprintf(buffer, "%s, %d", buffer, i); - n++; - } -} - -int -idnxdc(int domid, idn_msgtype_t *mtp, - uint_t arg1, uint_t arg2, - uint_t arg3, uint_t arg4) -{ - int rv, cpuid, tcpuid; - uint_t cookie; - uint64_t pdata; - uint64_t dmv_word0, dmv_word1, dmv_word2; - idn_domain_t *dp = &idn_domain[domid]; - extern kmutex_t xc_sys_mutex; - extern int xc_spl_enter[]; - procname_t proc = "idnxdc"; - - - if (idn_snoop) { - int bd; - STRING(str); - STRING(mstr); - STRING(astr); - - INUM2STR(mtp->mt_mtype, mstr); - if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == 0) { - INUM2STR(arg1, astr); - (void) sprintf(str, "%s/%s", mstr, astr); - } else { - (void) strcpy(str, mstr); - } - if (dp->dcpu == IDN_NIL_DCPU) - bd = -1; - else - bd = CPUID_TO_BOARDID(dp->dcpu); - SNOOP_IDN(0, str, bd, arg1, arg2, arg3, arg4); - } - - /* - * For NEGO messages we send the remote domain the cookie we - * expect it to use in subsequent messages that it sends - * to us (dcookie_recv). - * For other messages, we must use the cookie that the - * remote domain assigned to us for sending (dcookie_send). - */ - if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == IDNP_NEGO) - cookie = IDN_MAKE_COOKIE(dp->dcookie_recv, mtp->mt_cookie); - else - cookie = IDN_MAKE_COOKIE(dp->dcookie_send, mtp->mt_cookie); - - pdata = IDN_MAKE_PDATA(mtp->mt_mtype, mtp->mt_atype, cookie); - - dmv_word0 = DMV_MAKE_DMV(idn.intr.dmv_inum, pdata); - dmv_word1 = ((uint64_t)arg1 << 32) | (uint64_t)arg2; - dmv_word2 = ((uint64_t)arg3 << 32) | (uint64_t)arg4; - - ASSERT((dp->dcpu != IDN_NIL_DCPU) || - (dp->dcpu_last != IDN_NIL_DCPU)); - - tcpuid = (dp->dcpu == IDN_NIL_DCPU) ? - dp->dcpu_last : dp->dcpu; - - if (tcpuid == IDN_NIL_DCPU) { - PR_PROTO("%s:%d: cpu/cpu_last == NIL_DCPU\n", - proc, domid); - return (-1); - } - - mutex_enter(&xc_sys_mutex); - cpuid = (int)CPU->cpu_id; - xc_spl_enter[cpuid] = 1; - - idnxf_init_mondo(dmv_word0, dmv_word1, dmv_word2); - - rv = idnxf_send_mondo(STARFIRE_UPAID2HWMID(tcpuid)); - - xc_spl_enter[cpuid] = 0; - mutex_exit(&xc_sys_mutex); - - return (rv); -} - -void -idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp, - uint_t arg1, uint_t arg2, - uint_t arg3, uint_t arg4) -{ - int d; - - for (d = 0; d < MAX_DOMAINS; d++) { - idn_domain_t *dp; - - if (!DOMAIN_IN_SET(domset, d)) - continue; - - dp = &idn_domain[d]; - if (dp->dcpu == IDN_NIL_DCPU) - continue; - - (void) IDNXDC(d, mtp, arg1, arg2, arg3, arg4); - } -} - -#define PROM_SMRSIZE 0x1 -#define PROM_SMRADDR 0x2 -#define PROM_SMRPROPS (PROM_SMRSIZE | PROM_SMRADDR) -/* - * Locate the idn-smr-size property to determine the size of the SMR - * region for the SSI. Value inherently enables/disables SSI capability. - */ -static int -idn_prom_getsmr(uint_t *smrsz, uint64_t *paddrp, uint64_t *sizep) -{ - pnode_t nodeid; - int found = 0; - int len; - uint_t smrsize = 0; - uint64_t obpaddr, obpsize; - struct smraddr { - uint32_t hi_addr; - uint32_t lo_addr; - uint32_t hi_size; - uint32_t lo_size; - } smraddr; - procname_t proc = "idn_prom_getsmr"; - - bzero(&smraddr, sizeof (smraddr)); - /* - * idn-smr-size is a property of the "memory" node and - * is defined in megabytes. - */ - nodeid = prom_finddevice("/memory"); - - if (nodeid != OBP_NONODE) { - len = prom_getproplen(nodeid, IDN_PROP_SMRSIZE); - if (len == sizeof (smrsize)) { - (void) prom_getprop(nodeid, IDN_PROP_SMRSIZE, - (caddr_t)&smrsize); - found |= PROM_SMRSIZE; - } - len = prom_getproplen(nodeid, IDN_PROP_SMRADDR); - if (len == sizeof (smraddr)) { - (void) prom_getprop(nodeid, IDN_PROP_SMRADDR, - (caddr_t)&smraddr); - found |= PROM_SMRADDR; - } - } - - if (found != PROM_SMRPROPS) { - if ((found & PROM_SMRSIZE) == 0) - cmn_err(CE_WARN, - "IDN: 136: \"%s\" property not found, " - "disabling IDN", - IDN_PROP_SMRSIZE); - if (smrsize && ((found & PROM_SMRADDR) == 0)) - cmn_err(CE_WARN, - "IDN: 136: \"%s\" property not found, " - "disabling IDN", - IDN_PROP_SMRADDR); - return (-1); - } - - if (smrsize == 0) { - PR_SMR("%s: IDN DISABLED (idn_smr_size = 0)\n", proc); - cmn_err(CE_NOTE, "!IDN: 137: SMR size is 0, disabling IDN"); - - } else if (smrsize > IDN_SMR_MAXSIZE) { - PR_SMR("%s: IDN DISABLED (idn_smr_size too big %d > %d MB)\n", - proc, smrsize, IDN_SMR_MAXSIZE); - cmn_err(CE_WARN, - "!IDN: 138: SMR size (%dMB) is too big (max = %dMB), " - "disabling IDN", - smrsize, IDN_SMR_MAXSIZE); - smrsize = 0; - } else { - *smrsz = smrsize; - found &= ~PROM_SMRSIZE; - } - - obpaddr = ((uint64_t)smraddr.hi_addr << 32) | - (uint64_t)smraddr.lo_addr; - obpsize = ((uint64_t)smraddr.hi_size << 32) | - (uint64_t)smraddr.lo_size; - - if (obpsize == 0) { - if (smrsize > 0) { - cmn_err(CE_WARN, "!IDN: 139: OBP region for " - "SMR is 0 length"); - } - } else if (obpsize < (uint64_t)MB2B(smrsize)) { - cmn_err(CE_WARN, - "!IDN: 140: OBP region (%ld B) smaller " - "than requested size (%ld B)", - obpsize, MB2B(smrsize)); - } else if ((obpaddr & ((uint64_t)IDN_SMR_ALIGN - 1)) != 0) { - cmn_err(CE_WARN, - "!IDN: 141: OBP region (0x%lx) not on (0x%x) " - "boundary", obpaddr, IDN_SMR_ALIGN); - } else { - *sizep = obpsize; - *paddrp = obpaddr; - found &= ~PROM_SMRADDR; - } - - return (found ? -1 : 0); -} - -void -idn_init_autolink() -{ - idnsb_event_t *sbp; - procname_t proc = "idn_init_autolink"; - - mutex_enter(&idn.idnsb_mutex); - if ((sbp = idn.idnsb_eventp) == NULL) { - PR_PROTO("%s: IDN private sigb (event) area is NULL\n", proc); - mutex_exit(&idn.idnsb_mutex); - return; - } - - PR_PROTO("%s: marking domain IDN ready.\n", proc); - - bzero(sbp, sizeof (*sbp)); - - sbp->idn_version = (uchar_t)idn.version; - SSIEVENT_SET(sbp, SSIEVENT_BOOT, 0); - (void) strncpy(sbp->idn_cookie_str, SSIEVENT_COOKIE, - SSIEVENT_COOKIE_LEN); - mutex_exit(&idn.idnsb_mutex); -} - -void -idn_deinit_autolink() -{ - idnsb_event_t *sbp; - procname_t proc = "idn_deinit_autolink"; - - mutex_enter(&idn.idnsb_mutex); - if ((sbp = idn.idnsb_eventp) == NULL) { - PR_PROTO("%s: IDN private sigb (event) area is NULL\n", proc); - mutex_exit(&idn.idnsb_mutex); - return; - } - - PR_PROTO("%s: marking domain IDN unavailable.\n", proc); - - sbp->idn_version = (uchar_t)idn.version; - SSIEVENT_CLEAR(sbp, SSIEVENT_BOOT, 0); - (void) strncpy(sbp->idn_cookie_str, SSIEVENT_COOKIE, - SSIEVENT_COOKIE_LEN); - mutex_exit(&idn.idnsb_mutex); -} - -void -_make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower) -{ - int c; - - CPUSET_ZERO(*csetp); - - for (c = 0; c < 32; c++) { - if (lower & (1 << c)) { - CPUSET_ADD(*csetp, c); - } - if (upper & (1 << (c + 32))) { - CPUSET_ADD(*csetp, c + 32); - } - } -} - -uint_t -_lower32cpumask(cpuset_t cset) -{ - int c; - uint_t set = 0; - - for (c = 0; c < 32; c++) - if (CPU_IN_SET(cset, c)) - set |= 1 << c; - - return (set); -} - -uint_t -_upper32cpumask(cpuset_t cset) -{ - int c; - uint_t set = 0; - - for (c = 32; c < NCPU; c++) - if (CPU_IN_SET(cset, c)) - set |= 1 << (c - 32); - - return (set); -} - -#ifdef DEBUG -int -debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp, - uint_t a1, uint_t a2, uint_t a3, uint_t a4) -{ - idn_domain_t *dp = &idn_domain[domid]; - int rv, cpuid, bd; - static int xx = 0; - STRING(str); - STRING(mstr); - STRING(astr); - - xx++; - INUM2STR(mtp->mt_mtype, mstr); - if ((mtp->mt_mtype & IDNP_MSGTYPE_MASK) == 0) { - INUM2STR(a1, astr); - (void) sprintf(str, "%s/%s", mstr, astr); - } else { - (void) strcpy(str, mstr); - } - - if ((cpuid = dp->dcpu) == IDN_NIL_DCPU) - bd = -1; - else - bd = CPUID_TO_BOARDID(cpuid); - - SNOOP_IDN(0, str, bd, a1, a2, a3, a4); - - PR_XDC("%s:%d:%d SENT: scpu = %d, msg = 0x%x(%s)\n", - f, domid, xx, cpuid, mtp->mt_mtype, str); - PR_XDC("%s:%d:%d S-DATA: a1 = 0x%x, a2 = 0x%x\n", - f, domid, xx, a1, a2); - PR_XDC("%s:%d:%d S-DATA: a3 = 0x%x, a4 = 0x%x\n", - f, domid, xx, a3, a4); - - rv = idnxdc(domid, mtp, a1, a2, a3, a4); - if (rv != 0) { - PR_XDC("%s:%d:%d: WARNING: idnxdc(cpu %d) FAILED\n", - f, domid, xx, cpuid); - } - - return (rv); -} - -caddr_t -_idn_getstruct(char *structname, int size) -{ - caddr_t ptr; - procname_t proc = "GETSTRUCT"; - - ptr = kmem_zalloc(size, KM_SLEEP); - - PR_ALLOC("%s: ptr 0x%p, struct(%s), size = %d\n", - proc, (void *)ptr, structname, size); - - return (ptr); -} - -void -_idn_freestruct(caddr_t ptr, char *structname, int size) -{ - procname_t proc = "FREESTRUCT"; - - PR_ALLOC("%s: ptr 0x%p, struct(%s), size = %d\n", - proc, (void *)ptr, structname, size); - - ASSERT(ptr != NULL); - kmem_free(ptr, size); -} -#endif /* DEBUG */ diff --git a/usr/src/uts/sun4u/starfire/io/idn.conf b/usr/src/uts/sun4u/starfire/io/idn.conf deleted file mode 100644 index 7bd23982b1..0000000000 --- a/usr/src/uts/sun4u/starfire/io/idn.conf +++ /dev/null @@ -1,35 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 1998 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" - -name="idn" parent="pseudo" instance=0; -name="idn" parent="pseudo" instance=1; -name="idn" parent="pseudo" instance=2; -name="idn" parent="pseudo" instance=3; -name="idn" parent="pseudo" instance=4; -name="idn" parent="pseudo" instance=5; -name="idn" parent="pseudo" instance=6; -name="idn" parent="pseudo" instance=7; diff --git a/usr/src/uts/sun4u/starfire/io/idn_dlpi.c b/usr/src/uts/sun4u/starfire/io/idn_dlpi.c deleted file mode 100644 index 693499c041..0000000000 --- a/usr/src/uts/sun4u/starfire/io/idn_dlpi.c +++ /dev/null @@ -1,2295 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * IDN DLPI support (based on QE implementation). - */ -#include <sys/types.h> -#include <sys/debug.h> -#include <sys/stropts.h> -#include <sys/stream.h> -#include <sys/systm.h> -#include <sys/cmn_err.h> -#include <sys/errno.h> -#ifdef xxx_trace -#include <sys/vtrace.h> -#endif /* xxx_trace */ -#include <sys/kmem.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/strsun.h> -#include <sys/stat.h> -#include <sys/kstat.h> -#include <sys/dlpi.h> -#include <sys/time.h> -#include <sys/cpuvar.h> - -#include <sys/idn.h> - -#ifdef IPV6 -#define IS_ETHERTYPE_IPV4(x) ((x) == ETHERTYPE_IP) -#define IS_ETHERTYPE_IPV6(x) ((x) == ETHERTYPE_IPV6) -#define IS_ETHERTYPE_IP(x) (IS_ETHERTYPE_IPV4(x) || IS_ETHERTYPE_IPV6(x)) -#else -#define IS_ETHERTYPE_IPV4(x) ((x) == ETHERTYPE_IP) -#define IS_ETHERTYPE_IPV6(x) (0) -#define IS_ETHERTYPE_IP IS_ETHERTYPE_IPV4 -#endif /* IPV6 */ - -#ifdef IDN_TRACE -/* - * This stuff should go into <sys/vtrace.h> - */ -#define TR_FAC_IDN 100 -/* - * TR_FAC_IDN tags - */ -#define TR_IDN_OPEN 0 -#define TR_IDN_CLOSE 1 -#define TR_IDN_WPUT_START 2 -#define TR_IDN_WPUT_END 3 -#define TR_IDN_WSRV_START 4 -#define TR_IDN_WSRV_END 5 -#define TR_IDN_START_START 6 -#define TR_IDN_START_END 7 -#define TR_IDN_INTR_START 8 -#define TR_IDN_INTR_END 9 -#define TR_IDN_READ_START 10 -#define TR_IDN_READ_END 11 -#define TR_IDN_SENDUP_START 12 -#define TR_IDN_SENDUP_END 13 -#define TR_IDN_ADDUDIND_START 14 -#define TR_IDN_ADDUDIND_END 15 -#define TR_IDN_GETBUF_START 16 -#define TR_IDN_GETBUF_END 17 -#define TR_IDN_FREEBUF_START 18 -#define TR_IDN_FREEBUF_END 19 -#define TR_IDN_PROTO_START 20 -#define TR_IDN_PROTO_END 21 -#define TR_IDN_INIT_START 22 -#define TR_IDN_INIT_END 23 -#define TR_IDN_PROTO_IN 24 -#define TR_IDN_PROTO_OUT 25 - -#define IDNTRACE(fac, tag) (printf("idn.TRACE: ")) - -#define TRACE_0(fac, tag, name) \ - IDNTRACE((fac), (tag)); \ - printf(name); printf("\n"); - -#define TRACE_1(fac, tag, name, d1) \ - IDNTRACE((fac), (tag)); \ - printf(name, (d1)); printf("\n"); - -#define TRACE_2(fac, tag, name, d1, d2) \ - IDNTRACE((fac), (tag)); \ - printf(name, (d1), (d2)); printf("\n"); - -#define TRACE_3(fac, tag, name, d1, d2, d3) \ - IDNTRACE((fac), (tag)); \ - printf(name, (d1), (d2), (d3)); printf("\n"); - -#define TRACE_4(fac, tag, name, d1, d2, d3, d4) \ - IDNTRACE((fac), (tag)); \ - printf(name, (d1), (d2), (d3), (d4)); printf("\n"); - -#define TRACE_5(fac, tag, name, d1, d2, d3, d4, d5) \ - IDNTRACE((fac), (tag)); \ - printf(name, (d1), (d2), (d3), (d4), (d5)); printf("\n"); - -#else /* IDN_TRACE */ - -#define TRACE_0(fac, tag, name) {} -#define TRACE_1(fac, tag, name, d1) {} -#define TRACE_2(fac, tag, name, d1, d2) {} -#define TRACE_3(fac, tag, name, d1, d2, d3) {} -#define TRACE_4(fac, tag, name, d1, d2, d3, d4) {} -#define TRACE_5(fac, tag, name, d1, d2, d3, d4, d5) {} - -#endif /* IDN_TRACE */ - -#ifdef DEBUG -#define DLERRORACK(qq, mm, cc, ee, xx) \ -{ \ - PR_DLPI("dlpi: ERRORACK: 0x%x(%s), err = 0x%x(%s)\n", \ - (uint_t)(cc), dlprim2str(cc), \ - (uint_t)(ee), dlerr2str((int)(ee))); \ - dlerrorack((qq), (mm), (cc), (ee), (xx)); \ -} -#define DLOKACK(qq, mm, cc) \ -{ \ - PR_DLPI("dlpi: OKACK: 0x%x(%s)\n", (cc), dlprim2str(cc)); \ - dlokack((qq), (mm), (cc)); \ -} -#define DLBINDACK(qq, mm, ss, aa, ll, xx, yy) \ -{ \ - PR_DLPI("dlpi: BINDACK: eth=%x:%x:%x:%x:%x:%x, sap=0x%x, l=%d\n", \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[0], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[1], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[2], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[3], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[4], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[5], \ - (uint_t)(ss), (int)(ll)); \ - dlbindack((qq), (mm), (ss), (aa), (ll), (xx), (yy)); \ -} -#define DLPHYSADDRACK(qq, mm, aa, ll) \ -{ \ - PR_DLPI("dlpi: PHYSACK: eth=%x:%x:%x:%x:%x:%x, l=%d\n", \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[0], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[1], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[2], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[3], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[4], \ - ((struct idndladdr *)(aa))->dl_phys.ether_addr_octet[5], \ - (ll)); \ - dlphysaddrack((qq), (mm), (aa), (ll)); \ -} - -static char *dlerrstr[] = { - "DL_BADSAP", - "DL_BADADDR", - "DL_ACCESS", - "DL_OUTSTATE", - "DL_SYSERR", - "DL_BADCORR", - "DL_BADDATA", - "DL_UNSUPPORTED", - "DL_BADPPA", - "DL_BADPRIM", - "DL_BADQOSPARAM", - "DL_BADQOSTYPE", - "DL_BADTOKEN", - "DL_BOUND", - "DL_INITFAILED", - "DL_NOADDR", - "DL_NOTINIT", - "DL_UNDELIVERABLE", - "DL_NOTSUPPORTED", - "DL_TOOMANY", - "DL_NOTENAB", - "DL_BUSY", - "DL_NOAUTO", - "DL_NOXIDAUTO", - "DL_NOTESTAUTO", - "DL_XIDAUTO", - "DL_TESTAUTO", - "DL_PENDING" -}; -static int dlerrnum = (sizeof (dlerrstr) / sizeof (char *)); - -static char * -dlerr2str(int err) -{ - if ((err < 0) || (err >= dlerrnum)) - return ("unknown"); - else - return (dlerrstr[err]); -} - -static char * -dlprim2str(int prim) -{ - char *pstr; - - switch (prim) { - case DL_UNITDATA_REQ: pstr = "UNITDATA_REQ"; break; - case DL_ATTACH_REQ: pstr = "ATTACH_REQ"; break; - case DL_DETACH_REQ: pstr = "DETACH_REQ"; break; - case DL_BIND_REQ: pstr = "BIND_REQ"; break; - case DL_UNBIND_REQ: pstr = "UNBIND_REQ"; break; - case DL_INFO_REQ: pstr = "INFO_REQ"; break; - case DL_PROMISCON_REQ: pstr = "PROMISCON_REQ"; break; - case DL_PROMISCOFF_REQ: pstr = "PROMISCOFF_REQ"; break; - case DL_ENABMULTI_REQ: pstr = "ENABMULTI_REQ"; break; - case DL_DISABMULTI_REQ: pstr = "DISABMULTI_REQ"; break; - case DL_PHYS_ADDR_REQ: pstr = "PHYS_ADDR_REQ"; break; - case DL_SET_PHYS_ADDR_REQ: - pstr = "SET_PHYS_ADDR_REQ"; break; - default: pstr = "unsupported"; break; - } - return (pstr); -} -#else /* DEBUG */ -#define DLERRORACK(qq, mm, cc, ee, xx) \ - (dlerrorack((qq), (mm), (cc), (ee), (xx))) -#define DLOKACK(qq, mm, cc) \ - (dlokack((qq), (mm), (cc))) -#define DLBINDACK(qq, mm, ss, aa, ll, xx, yy) \ - (dlbindack((qq), (mm), (ss), (aa), (ll), (xx), (yy))) -#define DLPHYSADDRACK(qq, mm, aa, ll) \ - (dlphysaddrack((qq), (mm), (aa), (ll))) -#endif /* DEBUG */ - -#define IDNDL_ADDR_IS_MULTICAST(ap) (((ap)->ether_addr_octet[0] & 01) == 1) -/* - * MIB II broadcast/multicast packets - */ -#define IS_BROADCAST(ehp) \ - (ether_cmp(&(ehp)->ether_dhost, ðerbroadcastaddr) == 0) -#define IS_MULTICAST(ehp) \ - IDNDL_ADDR_IS_MULTICAST(&(ehp)->ether_dhost) -#define BUMP_InNUcast(sip, ehp) \ - if (IS_BROADCAST(ehp)) { \ - (sip)->si_kstat.si_brdcstrcv++; \ - } else if (IS_MULTICAST(ehp)) { \ - (sip)->si_kstat.si_multircv++; \ - } -#define BUMP_OutNUcast(sip, ehp) \ - if (IS_BROADCAST(ehp)) { \ - (sip)->si_kstat.si_brdcstxmt++; \ - } else if (IS_MULTICAST(ehp)) { \ - (sip)->si_kstat.si_multixmt++; \ - } - -/* - * Function prototypes. - */ -static int idndl_ioc_hdr_info(queue_t *, mblk_t *, int *); -static void idndl_areq(queue_t *, mblk_t *); -static void idndl_dreq(queue_t *, mblk_t *); -static void idndl_breq(queue_t *, mblk_t *); -static void idndl_ubreq(queue_t *, mblk_t *); -static void idndl_ireq(queue_t *, mblk_t *); -static void idndl_ponreq(queue_t *, mblk_t *); -static void idndl_poffreq(queue_t *, mblk_t *); -static void idndl_emreq(queue_t *, mblk_t *); -static void idndl_dmreq(queue_t *, mblk_t *); -static void idndl_pareq(queue_t *, mblk_t *); -#ifdef notdef -static void idndl_spareq(queue_t *, mblk_t *); -#endif /* notdef */ -static void idndl_udreq(queue_t *, mblk_t *); -static void serror(dev_info_t *dip, int idnerr, char *fmt, ...); -static mblk_t *idndl_addudind(struct idn *, mblk_t *, struct ether_addr *, - struct ether_addr *, int, ulong_t); -static void idndl_setipq(struct idn *); -static int idndl_mcmatch(struct idnstr *, struct ether_addr *); -static int idndl_stat_kstat_update(kstat_t *ksp, int rw); - -static int _idndl_ether2domain(struct ether_addr *eap); -static struct idn *_idndl_ether2sip(struct ether_addr *eap); - - -#define IDNSAPMATCH(sap, type, flags) ((sap == type)? 1 : \ - ((flags & IDNSALLSAP)? 1 : \ - ((sap <= ETHERMTU) && sap && (type <= ETHERMTU))? 1 : 0)) - -/* - * Our DL_INFO_ACK template. - */ -static dl_info_ack_t idninfoack = { - DL_INFO_ACK, /* dl_primitive */ - 0, /* dl_max_sdu (see idndl_dlpi_init()) */ - 0, /* dl_min_sdu */ - IDNADDRL, /* dl_addr_length */ - DL_ETHER, /* DL_OTHER, */ /* dl_mac_type */ - 0, /* dl_reserved */ - 0, /* dl_current_state */ - -2, /* dl_sap_length */ - DL_CLDLS, /* DL_CODLS? */ /* dl_service_mode */ - 0, /* dl_qos_length */ - 0, /* dl_qos_offset */ - 0, /* dl_range_length */ - 0, /* dl_range_offset */ - DL_STYLE2, /* dl_provider_style */ - sizeof (dl_info_ack_t), /* dl_addr_offset */ - DL_VERSION_2, /* dl_version */ - ETHERADDRL, /* dl_brdcst_addr_length */ - sizeof (dl_info_ack_t) + IDNADDRL, /* dl_brdcst_addr_offset */ - 0 /* dl_growth */ -}; - -/* - * Ethernet broadcast address definition. - */ -static struct ether_addr etherbroadcastaddr = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -/* - * -------------------------------------------------- - */ -void -idndl_localetheraddr(struct idn *sip, struct ether_addr *eap) -{ - int rv; - int instance; - procname_t proc = "idndl_localetheraddr"; - - ASSERT(sip && sip->si_dip && eap); - - instance = ddi_get_instance(sip->si_dip); - - PR_DLPI("%s: getting local etheraddr...\n", proc); - - rv = idndl_domain_etheraddr(idn.localid, instance, eap); - ASSERT(rv == 0); -} - -int -idndl_domain_etheraddr(int domid, int channel, struct ether_addr *eap) -{ - uchar_t netid; - procname_t proc = "idndl_domain_etheraddr"; - - if (idn_domain[domid].dcpu == IDN_NIL_DCPU) - return (-1); - - netid = (uchar_t)idn_domain[domid].dnetid; - - PR_DLPI("%s: dnetid = 0x%x, channel = 0x%x\n", - proc, (uint_t)netid, channel); - -#ifdef notdef - localetheraddr(NULL, eap); - - PR_DLPI("%s: localetheraddr = %x:%x:%x:%x:%x:%x\n", - proc, eap->ether_addr_octet[0], eap->ether_addr_octet[1], - eap->ether_addr_octet[2], eap->ether_addr_octet[3], - eap->ether_addr_octet[4], eap->ether_addr_octet[5]): -#endif /* notdef */ - - eap->ether_addr_octet[IDNETHER_ZERO] = 0; - eap->ether_addr_octet[IDNETHER_COOKIE1] = IDNETHER_COOKIE1_VAL; - eap->ether_addr_octet[IDNETHER_COOKIE2] = IDNETHER_COOKIE2_VAL; - eap->ether_addr_octet[IDNETHER_NETID] = netid; - eap->ether_addr_octet[IDNETHER_CHANNEL] = (uchar_t)channel; - eap->ether_addr_octet[IDNETHER_RESERVED] = IDNETHER_RESERVED_VAL; - - PR_DLPI("%s: domain %d: etheraddr = %x:%x:%x:%x:%x:%x\n", - proc, domid, - eap->ether_addr_octet[0], eap->ether_addr_octet[1], - eap->ether_addr_octet[2], eap->ether_addr_octet[3], - eap->ether_addr_octet[4], eap->ether_addr_octet[5]); - - return (0); -} - -#ifdef DEBUG -/* - */ -static int -_idndl_ether2domain(struct ether_addr *eap) -{ - uchar_t *eaop; - - eaop = eap->ether_addr_octet; - - ASSERT(IDNDL_ADDR_IS_MULTICAST(eap) || - ((eaop[IDNETHER_COOKIE1] == IDNETHER_COOKIE1_VAL) && - (eaop[IDNETHER_COOKIE2] == IDNETHER_COOKIE2_VAL)) || - ((eaop[IDNETHER_COOKIE1] == 0xff) && - (eaop[IDNETHER_COOKIE2] == 0xff))); - /* - * Note that (IDN_NIL_DOMID) will be returned if ether address is - * a broadcast 0xff. - */ - return (IDN_NETID2DOMID(eaop[IDNETHER_NETID])); -} - -/* - */ -static struct idn * -_idndl_ether2sip(struct ether_addr *eap) -{ - int instance; - struct idn *sip; - uchar_t *eaop; - procname_t proc = "_idndl_ether2sip"; - - eaop = eap->ether_addr_octet; - - if (!IDNDL_ADDR_IS_MULTICAST(eap) && - (((eaop[IDNETHER_COOKIE1] != IDNETHER_COOKIE1_VAL) || - (eaop[IDNETHER_COOKIE2] != IDNETHER_COOKIE2_VAL)) && - ((eaop[IDNETHER_COOKIE1] != 0xff) || - (eaop[IDNETHER_COOKIE2] != 0xff)))) { - - cmn_err(CE_WARN, - "IDN: 400: corrupted MAC header " - "(exp %x or 0xffff, act 0x%x)", - (IDNETHER_COOKIE1_VAL << 8) | - IDNETHER_COOKIE2_VAL, - (eaop[IDNETHER_COOKIE1] << 8) | - eaop[IDNETHER_COOKIE2]); - - return (NULL); - } - - if (IDNDL_ADDR_IS_MULTICAST(eap)) { - PR_DLPI("%s: MULTICAST ADDR *** ERROR ***\n", proc); - sip = NULL; - } else if (eaop[IDNETHER_CHANNEL] == 0xff) { - /* - * Received a broadcast. Need to manually - * find anybody the first running sip and use it. - * XXX - kind of kludgy - single threads broadcasts. - */ - PR_DLPI("%s: BROADCAST CHANNEL *** ERROR ***\n", proc); - sip = NULL; - } else { - instance = (int)eaop[IDNETHER_CHANNEL]; - - sip = IDN_INST2SIP(instance); - } - - return (sip); -} -#endif /* DEBUG */ - -void -idndl_dlpi_init() -{ - procname_t proc = "idndl_dlpi_init"; - - PR_DLPI("%s: setting dl_max_sdu to %ld (0x%lx) bytes\n", - proc, IDN_MTU, IDN_MTU); - /* - * This field is dynamic because the user may - * want to dynamically set it _before_ an IDNnet - * has been established via ndd(1M). - */ - idninfoack.dl_max_sdu = IDN_MTU; -} - -static int -idndl_stat_kstat_update(kstat_t *ksp, int rw) -{ - struct idn *sip; - struct idn_kstat_named *skp; - - sip = (struct idn *)ksp->ks_private; - skp = (struct idn_kstat_named *)ksp->ks_data; - - if (rw == KSTAT_WRITE) { -#if 0 - bzero(&sg_kstat.gk_kstat, sizeof (sg_kstat.gk_kstat)); -#endif /* 0 */ - bzero(&sip->si_kstat, sizeof (sip->si_kstat)); - - sip->si_kstat.si_ipackets = skp->sk_ipackets.value.ul; - sip->si_kstat.si_ierrors = skp->sk_ierrors.value.ul; - sip->si_kstat.si_opackets = skp->sk_opackets.value.ul; - sip->si_kstat.si_oerrors = skp->sk_oerrors.value.ul; - sip->si_kstat.si_txcoll = skp->sk_txcoll.value.ul; - sip->si_kstat.si_rxcoll = skp->sk_rxcoll.value.ul; - sip->si_kstat.si_crc = skp->sk_crc.value.ul; - sip->si_kstat.si_buff = skp->sk_buff.value.ul; - sip->si_kstat.si_nolink = skp->sk_nolink.value.ul; - sip->si_kstat.si_linkdown = skp->sk_linkdown.value.ul; - sip->si_kstat.si_inits = skp->sk_inits.value.ul; - sip->si_kstat.si_nocanput = skp->sk_nocanput.value.ul; - sip->si_kstat.si_allocbfail = skp->sk_allocbfail.value.ul; - sip->si_kstat.si_notbufs = skp->sk_notbufs.value.ul; - sip->si_kstat.si_reclaim = skp->sk_reclaim.value.ul; - sip->si_kstat.si_smraddr = skp->sk_smraddr.value.ul; - sip->si_kstat.si_txmax = skp->sk_txmax.value.ul; - sip->si_kstat.si_txfull = skp->sk_txfull.value.ul; - sip->si_kstat.si_xdcall = skp->sk_xdcall.value.ul; - sip->si_kstat.si_sigsvr = skp->sk_sigsvr.value.ul; - sip->si_kstat.si_mboxcrc = skp->sk_mboxcrc.value.ul; - /* - * MIB II kstat variables - */ - sip->si_kstat.si_rcvbytes = skp->sk_rcvbytes.value.ul; - sip->si_kstat.si_xmtbytes = skp->sk_xmtbytes.value.ul; - sip->si_kstat.si_multircv = skp->sk_multircv.value.ul; - sip->si_kstat.si_multixmt = skp->sk_multixmt.value.ul; - sip->si_kstat.si_brdcstrcv = skp->sk_brdcstrcv.value.ul; - sip->si_kstat.si_brdcstxmt = skp->sk_brdcstxmt.value.ul; - sip->si_kstat.si_norcvbuf = skp->sk_norcvbuf.value.ul; - sip->si_kstat.si_noxmtbuf = skp->sk_noxmtbuf.value.ul; - /* - * PSARC 1997/198 : 64bit kstats - */ - sip->si_kstat.si_ipackets64 = skp->sk_ipackets64.value.ull; - sip->si_kstat.si_opackets64 = skp->sk_opackets64.value.ull; - sip->si_kstat.si_rbytes64 = skp->sk_rbytes64.value.ull; - sip->si_kstat.si_obytes64 = skp->sk_obytes64.value.ull; - /* - * PSARC 1997/247 : RFC 1643 - */ - sip->si_kstat.si_fcs_errors = skp->sk_fcs_errors.value.ul; - sip->si_kstat.si_macxmt_errors = - skp->sk_macxmt_errors.value.ul; - sip->si_kstat.si_toolong_errors = - skp->sk_toolong_errors.value.ul; - sip->si_kstat.si_macrcv_errors = - skp->sk_macrcv_errors.value.ul; - - return (0); - } - - skp->sk_ipackets.value.ul = sip->si_kstat.si_ipackets; - skp->sk_ierrors.value.ul = sip->si_kstat.si_ierrors; - skp->sk_opackets.value.ul = sip->si_kstat.si_opackets; - skp->sk_oerrors.value.ul = sip->si_kstat.si_oerrors; - skp->sk_txcoll.value.ul = sip->si_kstat.si_txcoll; - skp->sk_rxcoll.value.ul = sip->si_kstat.si_rxcoll; - skp->sk_crc.value.ul = sip->si_kstat.si_crc; - skp->sk_buff.value.ul = sip->si_kstat.si_buff; - skp->sk_nolink.value.ul = sip->si_kstat.si_nolink; - skp->sk_linkdown.value.ul = sip->si_kstat.si_linkdown; - skp->sk_inits.value.ul = sip->si_kstat.si_inits; - skp->sk_nocanput.value.ul = sip->si_kstat.si_nocanput; - skp->sk_allocbfail.value.ul = sip->si_kstat.si_allocbfail; - skp->sk_notbufs.value.ul = sip->si_kstat.si_notbufs; - skp->sk_reclaim.value.ul = sip->si_kstat.si_reclaim; - skp->sk_smraddr.value.ul = sip->si_kstat.si_smraddr; - skp->sk_txfull.value.ul = sip->si_kstat.si_txfull; - skp->sk_txmax.value.ul = sip->si_kstat.si_txmax; - skp->sk_xdcall.value.ul = sip->si_kstat.si_xdcall; - skp->sk_sigsvr.value.ul = sip->si_kstat.si_sigsvr; - skp->sk_mboxcrc.value.ul = sip->si_kstat.si_mboxcrc; - /* - * MIB II kstat variables - */ - skp->sk_rcvbytes.value.ul = sip->si_kstat.si_rcvbytes; - skp->sk_xmtbytes.value.ul = sip->si_kstat.si_xmtbytes; - skp->sk_multircv.value.ul = sip->si_kstat.si_multircv; - skp->sk_multixmt.value.ul = sip->si_kstat.si_multixmt; - skp->sk_brdcstrcv.value.ul = sip->si_kstat.si_brdcstrcv; - skp->sk_brdcstxmt.value.ul = sip->si_kstat.si_brdcstxmt; - skp->sk_norcvbuf.value.ul = sip->si_kstat.si_norcvbuf; - skp->sk_noxmtbuf.value.ul = sip->si_kstat.si_noxmtbuf; - /* - * PSARC 1997/198 : 64bit kstats - */ - skp->sk_ipackets64.value.ull = sip->si_kstat.si_ipackets64; - skp->sk_opackets64.value.ull = sip->si_kstat.si_opackets64; - skp->sk_rbytes64.value.ull = sip->si_kstat.si_rbytes64; - skp->sk_obytes64.value.ull = sip->si_kstat.si_obytes64; - /* - * PSARC 1997/247 : RFC 1643 - */ - skp->sk_fcs_errors.value.ul = sip->si_kstat.si_fcs_errors; - skp->sk_macxmt_errors.value.ul = sip->si_kstat.si_macxmt_errors; - skp->sk_toolong_errors.value.ul = sip->si_kstat.si_toolong_errors; - skp->sk_macrcv_errors.value.ul = sip->si_kstat.si_macrcv_errors; - - return (0); -} - -void -idndl_statinit(struct idn *sip) -{ - struct kstat *ksp; - struct idn_kstat_named *skp; - -#ifdef kstat - if ((ksp = kstat_create(IDNNAME, ddi_get_instance(sip->si_dip), - NULL, "net", KSTAT_TYPE_NAMED, - sizeof (struct idn_kstat_named) / sizeof (kstat_named_t), - KSTAT_FLAG_PERSISTENT)) == NULL) { -#else - if ((ksp = kstat_create(IDNNAME, ddi_get_instance(sip->si_dip), - NULL, "net", KSTAT_TYPE_NAMED, - sizeof (struct idn_kstat_named) / - sizeof (kstat_named_t), 0)) == NULL) { -#endif /* kstat */ - serror(sip->si_dip, 450, "kstat_create failed"); - return; - } - - sip->si_ksp = ksp; - skp = (struct idn_kstat_named *)(ksp->ks_data); - kstat_named_init(&skp->sk_ipackets, "ipackets", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_ierrors, "ierrors", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_opackets, "opackets", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_oerrors, "oerrors", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_txcoll, "collisions", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_rxcoll, "rx_collisions", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_crc, "crc", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_buff, "buff", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_nolink, "nolink", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_linkdown, "linkdown", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_inits, "inits", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_nocanput, "nocanput", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_allocbfail, "allocbfail", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_notbufs, "notbufs", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_reclaim, "reclaim", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_smraddr, "smraddr", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_txmax, "txmax", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_txfull, "txfull", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_xdcall, "xdcall", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_sigsvr, "sigsvr", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_mboxcrc, "mboxcrc", - KSTAT_DATA_ULONG); - /* - * MIB II kstat variables - */ - kstat_named_init(&skp->sk_rcvbytes, "rbytes", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_xmtbytes, "obytes", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_multircv, "multircv", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_multixmt, "multixmt", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_brdcstrcv, "brdcstrcv", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_brdcstxmt, "brdcstxmt", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_norcvbuf, "norcvbuf", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_noxmtbuf, "noxmtbuf", - KSTAT_DATA_ULONG); - /* - * PSARC 1997/198 : 64bit kstats - */ - kstat_named_init(&skp->sk_ipackets64, "ipackets64", - KSTAT_DATA_ULONGLONG); - kstat_named_init(&skp->sk_opackets64, "opackets64", - KSTAT_DATA_ULONGLONG); - kstat_named_init(&skp->sk_rbytes64, "rbytes64", - KSTAT_DATA_ULONGLONG); - kstat_named_init(&skp->sk_obytes64, "obytes64", - KSTAT_DATA_ULONGLONG); - /* - * PSARC 1997/247 : RFC 1643 - */ - kstat_named_init(&skp->sk_fcs_errors, "fcs_errors", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_macxmt_errors, "macxmt_errors", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_toolong_errors, "toolong_errors", - KSTAT_DATA_ULONG); - kstat_named_init(&skp->sk_macrcv_errors, "macrcv_errors", - KSTAT_DATA_ULONG); - - ksp->ks_update = idndl_stat_kstat_update; - ksp->ks_private = (void *)sip; - kstat_install(ksp); -} - -void -idndl_proto(queue_t *wq, mblk_t *mp) -{ - union DL_primitives *dlp; - struct idnstr *stp; - t_uscalar_t prim; - procname_t proc = "idndl_proto"; - - stp = (struct idnstr *)wq->q_ptr; - if (MBLKL(mp) < sizeof (t_uscalar_t)) { - /* - * Gotta at least have enough room to hold - * the primitive! - */ - DLERRORACK(wq, mp, -1, DL_BADPRIM, 0); - return; - } - dlp = (union DL_primitives *)mp->b_rptr; - prim = dlp->dl_primitive; - - TRACE_2(TR_FAC_IDN, TR_IDN_PROTO_START, - "idndl_proto start: wq %p dlprim %X", wq, prim); - -#ifdef DEBUG - PR_DLPI("%s: stp = 0x%p, wq = 0x%p, dlprim = 0x%x(%s)\n", - proc, (void *)stp, (void *)wq, prim, dlprim2str(prim)); -#endif /* DEBUG */ - - rw_enter(&stp->ss_rwlock, RW_WRITER); - - switch (prim) { - case DL_UNITDATA_REQ: - idndl_udreq(wq, mp); - break; - - case DL_ATTACH_REQ: - idndl_areq(wq, mp); - break; - - case DL_DETACH_REQ: - idndl_dreq(wq, mp); - break; - - case DL_BIND_REQ: - idndl_breq(wq, mp); - break; - - case DL_UNBIND_REQ: - idndl_ubreq(wq, mp); - break; - - case DL_INFO_REQ: - idndl_ireq(wq, mp); - break; - - case DL_PROMISCON_REQ: - idndl_ponreq(wq, mp); - break; - - case DL_PROMISCOFF_REQ: - idndl_poffreq(wq, mp); - break; - - case DL_ENABMULTI_REQ: - idndl_emreq(wq, mp); - break; - - case DL_DISABMULTI_REQ: - idndl_dmreq(wq, mp); - break; - - case DL_PHYS_ADDR_REQ: - idndl_pareq(wq, mp); - break; - -#ifdef notdef - /* - * We cannot allow this in IDN-land because we - * rely on the ethernet (physical) address to determine - * where to target the message. Recall that unlike - * ethernet we simply cannot dump junk on the wire and - * expect it to automatically find its destination. - * In the IDN we need to target the destination. - * Note that if we used POINT-TO-POINT then we wouldn't - * have to worry about the physical address since each - * domain connection would have a separate queue. - * However, ptp then requires multiple interfaces at - * the appl level as opposed to a single one for all - * of idn. We opt for the simpler single interface (idn0). - */ - case DL_SET_PHYS_ADDR_REQ: - idndl_spareq(wq, mp); - break; -#endif /* notdef */ - - default: - DLERRORACK(wq, mp, prim, DL_UNSUPPORTED, 0); - break; - } - - TRACE_2(TR_FAC_IDN, TR_IDN_PROTO_END, - "idnproto end: wq %p dlprim %X", wq, prim); - - rw_exit(&stp->ss_rwlock); -} - -int -idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsizep) -{ - int rv = 0; - struct iocblk *iocp = (struct iocblk *)mp->b_rptr; - struct idnstr *stp = (struct idnstr *)wq->q_ptr; - procname_t proc = "idnioc_dlpi"; - - *argsizep = 0; - - switch (iocp->ioc_cmd) { - case DLIOCRAW: /* raw M_DATA mode */ - PR_DLPI("%s: cmd = DLIOCRAW\n", proc); - stp->ss_flags |= IDNSRAW; - break; - - case DL_IOC_HDR_INFO: /* M_DATA "fastpath" info request */ - PR_DLPI("%s: cmd = DL_IOC_HDR_INFO\n", proc); - rv = idndl_ioc_hdr_info(wq, mp, argsizep); - break; - - default: - PR_DLPI("%s: invalid cmd 0x%x\n", proc, iocp->ioc_cmd); - rv = EINVAL; - break; - } - return (rv); -} - -/* - * M_DATA "fastpath" info request. - * Following the M_IOCTL mblk should come a DL_UNITDATA_REQ mblk. - * We ack with an M_IOCACK pointing to the original DL_UNITDATA_REQ mblk - * followed by an mblk containing the raw ethernet header corresponding - * to the destination address. Subsequently, we may receive M_DATA - * msgs which start with this header and may send up - * up M_DATA msgs with b_rptr pointing to a (ulong) group address - * indicator followed by the network-layer data (IP packet header). - * This is all selectable on a per-Stream basis. - */ -static int -idndl_ioc_hdr_info(queue_t *wq, mblk_t *mp, int *argsizep) -{ - mblk_t *nmp; - struct idnstr *stp; - struct idndladdr *dlap; - dl_unitdata_req_t *dludp; - struct ether_header *headerp; - struct idn *sip; - int off, len; - int padding = 0; - int error; - procname_t proc = "idndl_ioc_hdr_info"; - - stp = (struct idnstr *)wq->q_ptr; - sip = stp->ss_sip; - if (sip == NULL) { - PR_DLPI("%s: NULL sip (ret EINVAL)\n", proc); - return (EINVAL); - } - - error = miocpullup(mp, sizeof (dl_unitdata_req_t) + IDNADDRL); - if (error != 0) { - PR_DLPI("%s: sanity error (ret %d)\n", proc, error); - return (error); - } - - /* - * Sanity check the DL_UNITDATA_REQ destination address - * offset and length values. - */ - dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr; - off = dludp->dl_dest_addr_offset; - len = dludp->dl_dest_addr_length; - if (dludp->dl_primitive != DL_UNITDATA_REQ || - !MBLKIN(mp->b_cont, off, len) || len != IDNADDRL) { - PR_DLPI("%s: off(0x%x)/len(%d) error (ret EINVAL)\n", - proc, off, len); - return (EINVAL); - } - - dlap = (struct idndladdr *)(mp->b_cont->b_rptr + off); - - /* - * Allocate a new mblk to hold the ether header. - */ - nmp = allocb(sizeof (struct ether_header) + padding, BPRI_MED); - if (nmp == NULL) { - IDN_KSTAT_INC(sip, si_allocbfail); - return (ENOMEM); - } - nmp->b_rptr += padding; - nmp->b_wptr = nmp->b_rptr + sizeof (struct ether_header); - - /* - * Fill in the ether header. - */ - headerp = (struct ether_header *)nmp->b_rptr; - ether_copy(&dlap->dl_phys, &headerp->ether_dhost); - ether_copy(&sip->si_ouraddr, &headerp->ether_shost); - headerp->ether_type = dlap->dl_sap; - - /* - * Link new mblk in after the "request" mblks. - */ - linkb(mp, nmp); - - stp->ss_flags |= IDNSFAST; - - /* - * XXX Don't bother calling idndl_setipq() here. - */ - - if (argsizep) - *argsizep = msgsize(mp->b_cont); - - return (0); -} - -static void -idndl_areq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - union DL_primitives *dlp; - struct idn *sip; - int ppa; - procname_t proc = "idndl_areq"; - - stp = (struct idnstr *)wq->q_ptr; - dlp = (union DL_primitives *)mp->b_rptr; - - if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) { - DLERRORACK(wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0); - return; - } - - if (stp->ss_state != DL_UNATTACHED) { - DLERRORACK(wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0); - return; - } - - ppa = dlp->attach_req.dl_ppa; - - /* - * Valid ppa? - */ - if (ppa == -1 || qassociate(wq, ppa) != 0) { - PR_DLPI("%s: bad ppa %d\n", proc, ppa); - DLERRORACK(wq, mp, dlp->dl_primitive, DL_BADPPA, 0); - return; - } - mutex_enter(&idn.siplock); - for (sip = idn.sip; sip; sip = sip->si_nextp) { - if (ppa == ddi_get_instance(sip->si_dip)) - break; - } - mutex_exit(&idn.siplock); - ASSERT(sip != NULL); /* qassociate() succeeded */ - - /* - * Has device been initialized? Do so if necessary. - */ - if ((sip->si_flags & IDNRUNNING) == 0) { - if (idndl_init(sip)) { - DLERRORACK(wq, mp, dlp->dl_primitive, - DL_INITFAILED, 0); - (void) qassociate(wq, -1); - return; - } - } - - /* - * Set link to device and update our state. - */ - stp->ss_sip = sip; - stp->ss_state = DL_UNBOUND; - - DLOKACK(wq, mp, DL_ATTACH_REQ); -} - -static void -idndl_dreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_DETACH_REQ_SIZE) { - DLERRORACK(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0); - return; - } - - if (stp->ss_state != DL_UNBOUND) { - DLERRORACK(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0); - return; - } - - idndl_dodetach(stp); - (void) qassociate(wq, -1); - DLOKACK(wq, mp, DL_DETACH_REQ); -} - -/* - * Detach a Stream from an interface. - */ -void -idndl_dodetach(struct idnstr *stp) -{ - struct idnstr *tstp; - struct idn *sip; - int reinit = 0; - - ASSERT(stp->ss_sip); - - sip = stp->ss_sip; - stp->ss_sip = NULL; - - /* - * Disable promiscuous mode if on. - */ - if (stp->ss_flags & IDNSALLPHYS) { - stp->ss_flags &= ~IDNSALLPHYS; - reinit = 1; - } - - /* - * Disable ALLMULTI mode if on. - */ - if (stp->ss_flags & IDNSALLMULTI) { - stp->ss_flags &= ~IDNSALLMULTI; - reinit = 1; - } - - /* - * Disable any Multicast Addresses. - */ - stp->ss_mccount = 0; - if (stp->ss_mctab) { - kmem_free(stp->ss_mctab, IDNMCALLOC); - stp->ss_mctab = NULL; - reinit = 1; - } - - /* - * Detach from device structure. - * Uninit the device when no other streams are attached to it. - */ - rw_enter(&idn.struprwlock, RW_READER); - for (tstp = idn.strup; tstp; tstp = tstp->ss_nextp) - if (tstp->ss_sip == sip) - break; - rw_exit(&idn.struprwlock); - - if (tstp == NULL) - idndl_uninit(sip); - else if (reinit) - (void) idndl_init(sip); - - stp->ss_state = DL_UNATTACHED; - - idndl_setipq(sip); -} - -static void -idndl_breq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - union DL_primitives *dlp; - struct idn *sip; - struct idndladdr idnaddr; - t_uscalar_t sap; - int xidtest; - procname_t proc = "idndl_breq"; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_BIND_REQ_SIZE) { - DLERRORACK(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0); - return; - } - - if (stp->ss_state != DL_UNBOUND) { - DLERRORACK(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0); - return; - } - - dlp = (union DL_primitives *)mp->b_rptr; - - if (dlp->bind_req.dl_service_mode != idninfoack.dl_service_mode) { - DLERRORACK(wq, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0); - return; - } - - sip = stp->ss_sip; - sap = dlp->bind_req.dl_sap; - xidtest = dlp->bind_req.dl_xidtest_flg; - - ASSERT(sip); - - if (xidtest) { - DLERRORACK(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0); - return; - } - - if (sap > ETHERTYPE_MAX) { - DLERRORACK(wq, mp, dlp->dl_primitive, DL_BADSAP, 0); - return; - } - - /* - * Save SAP value for this Stream and change state. - */ - stp->ss_sap = sap; - stp->ss_state = DL_IDLE; - - idnaddr.dl_sap = sap; - ether_copy(&sip->si_ouraddr, &idnaddr.dl_phys); - - if (IS_ETHERTYPE_IP(sap)) { - int channel; - - channel = - (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL]; - PR_DLPI("%s: IP SAP, opening channel %d\n", proc, channel); - if (idn_open_channel(channel)) { - PR_DLPI("%s: FAILED TO OPEN CHANNEL %d\n", - proc, channel); - DLERRORACK(wq, mp, dlp->dl_primitive, DL_NOADDR, 0); - return; - } - } - DLBINDACK(wq, mp, sap, &idnaddr, IDNADDRL, 0, 0); - - idndl_setipq(sip); -} - -static void -idndl_ubreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - procname_t proc = "idndl_ubreq"; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) { - DLERRORACK(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0); - return; - } - - if (stp->ss_state != DL_IDLE) { - DLERRORACK(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0); - return; - } - - stp->ss_state = DL_UNBOUND; - - if (IS_ETHERTYPE_IP(stp->ss_sap)) { - struct idn *sip; - int channel; - - sip = stp->ss_sip; - channel = - (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL]; - PR_DLPI("%s: IP SAP, unbinding channel %d\n", proc, channel); - /* - * We need to do an "soft" close since there's a - * potential that we've been called by one of the - * IDN data server/dispatcher threads! We'll deadlock - * if we attempt a "hard" close of the channel from here. - */ - idn_close_channel(channel, IDNCHAN_SOFT_CLOSE); - } - - stp->ss_sap = 0; - - DLOKACK(wq, mp, DL_UNBIND_REQ); - - idndl_setipq(stp->ss_sip); -} - -static void -idndl_ireq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - dl_info_ack_t *dlip; - struct idndladdr *dlap; - struct ether_addr *ep; - int size; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_INFO_REQ_SIZE) { - DLERRORACK(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0); - return; - } - - /* - * Exchange current msg for a DL_INFO_ACK. - */ - size = sizeof (dl_info_ack_t) + IDNADDRL + ETHERADDRL; - if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) - return; - - /* - * Fill in the DL_INFO_ACK fields and reply. - */ - dlip = (dl_info_ack_t *)mp->b_rptr; - ASSERT(idninfoack.dl_max_sdu); - *dlip = idninfoack; - dlip->dl_current_state = stp->ss_state; - dlap = (struct idndladdr *)(mp->b_rptr + dlip->dl_addr_offset); - dlap->dl_sap = stp->ss_sap; - if (stp->ss_sip) { - ether_copy(&stp->ss_sip->si_ouraddr, &dlap->dl_phys); - } else { - bzero(&dlap->dl_phys, ETHERADDRL); - } - ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset); - ether_copy(ðerbroadcastaddr, ep); - - qreply(wq, mp); -} - -static void -idndl_ponreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) { - DLERRORACK(wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0); - return; - } - - switch (((dl_promiscon_req_t *)mp->b_rptr)->dl_level) { - case DL_PROMISC_PHYS: - stp->ss_flags |= IDNSALLPHYS; - break; - - case DL_PROMISC_SAP: - stp->ss_flags |= IDNSALLSAP; - break; - - case DL_PROMISC_MULTI: - stp->ss_flags |= IDNSALLMULTI; - break; - - default: - DLERRORACK(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0); - return; - } - - if (stp->ss_sip) - (void) idndl_init(stp->ss_sip); - - if (stp->ss_sip) - idndl_setipq(stp->ss_sip); - - DLOKACK(wq, mp, DL_PROMISCON_REQ); -} - -static void -idndl_poffreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - int flag; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) { - DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0); - return; - } - - switch (((dl_promiscoff_req_t *)mp->b_rptr)->dl_level) { - case DL_PROMISC_PHYS: - flag = IDNSALLPHYS; - break; - - case DL_PROMISC_SAP: - flag = IDNSALLSAP; - break; - - case DL_PROMISC_MULTI: - flag = IDNSALLMULTI; - break; - - default: - DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0); - return; - } - - if ((stp->ss_flags & flag) == 0) { - DLERRORACK(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0); - return; - } - - stp->ss_flags &= ~flag; - - if (stp->ss_sip) - (void) idndl_init(stp->ss_sip); - - if (stp->ss_sip) - idndl_setipq(stp->ss_sip); - - DLOKACK(wq, mp, DL_PROMISCOFF_REQ); -} - -static void -idndl_emreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - union DL_primitives *dlp; - struct ether_addr *addrp; - int off; - int len; - int i; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_ENABMULTI_REQ_SIZE) { - DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0); - return; - } - - if (stp->ss_state == DL_UNATTACHED) { - DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0); - return; - } - - dlp = (union DL_primitives *)mp->b_rptr; - len = dlp->enabmulti_req.dl_addr_length; - off = dlp->enabmulti_req.dl_addr_offset; - addrp = (struct ether_addr *)(mp->b_rptr + off); - - if ((len != ETHERADDRL) || - !MBLKIN(mp, off, len) || - !IDNDL_ADDR_IS_MULTICAST(addrp)) { - DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0); - return; - } - - if ((stp->ss_mccount + 1) >= IDNMAXMC) { - DLERRORACK(wq, mp, DL_ENABMULTI_REQ, DL_TOOMANY, 0); - return; - } - - /* - * Allocate table on first request. - */ - if (stp->ss_mctab == NULL) - stp->ss_mctab = kmem_alloc(IDNMCALLOC, KM_SLEEP); - - /* - * Check to see if the address is already in the table. - * Bug 1209733: - * If present in the table, add the entry to the end of the table - * and return without initializing the hardware. - */ - for (i = 0; i < stp->ss_mccount; i++) { - if (ether_cmp(&stp->ss_mctab[i], addrp) == 0) { - stp->ss_mctab[stp->ss_mccount++] = *addrp; - DLOKACK(wq, mp, DL_ENABMULTI_REQ); - return; - } - } - - stp->ss_mctab[stp->ss_mccount++] = *addrp; - - (void) idndl_init(stp->ss_sip); - - DLOKACK(wq, mp, DL_ENABMULTI_REQ); -} - -static void -idndl_dmreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - union DL_primitives *dlp; - struct ether_addr *addrp; - int off; - int len; - int i; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_DISABMULTI_REQ_SIZE) { - DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0); - return; - } - - if (stp->ss_state == DL_UNATTACHED) { - DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_OUTSTATE, 0); - return; - } - - dlp = (union DL_primitives *)mp->b_rptr; - len = dlp->disabmulti_req.dl_addr_length; - off = dlp->disabmulti_req.dl_addr_offset; - addrp = (struct ether_addr *)(mp->b_rptr + off); - - if ((len != ETHERADDRL) || !MBLKIN(mp, off, len)) { - DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0); - return; - } - - /* - * Find the address in the multicast table for this Stream - * and delete it by shifting all subsequent multicast - * table entries over one. - */ - for (i = 0; i < stp->ss_mccount; i++) - if (ether_cmp(addrp, &stp->ss_mctab[i]) == 0) { - bcopy(&stp->ss_mctab[i+1], - &stp->ss_mctab[i], - ((stp->ss_mccount - i) * - sizeof (struct ether_addr))); - stp->ss_mccount--; - (void) idndl_init(stp->ss_sip); - DLOKACK(wq, mp, DL_DISABMULTI_REQ); - return; - } - DLERRORACK(wq, mp, DL_DISABMULTI_REQ, DL_NOTENAB, 0); -} - -static void -idndl_pareq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - union DL_primitives *dlp; - int type; - struct idn *sip; - struct ether_addr addr; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) { - DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0); - return; - } - - dlp = (union DL_primitives *)mp->b_rptr; - type = dlp->physaddr_req.dl_addr_type; - sip = stp->ss_sip; - - if (sip == NULL) { - DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0); - return; - } - - switch (type) { - case DL_FACT_PHYS_ADDR: - idndl_localetheraddr(sip, &addr); - break; - - case DL_CURR_PHYS_ADDR: - ether_copy(&sip->si_ouraddr, &addr); - break; - - default: - DLERRORACK(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0); - return; - } - - DLPHYSADDRACK(wq, mp, &addr, ETHERADDRL); -} - -#ifdef notdef -static void -idndl_spareq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - union DL_primitives *dlp; - int off; - int len; - struct ether_addr *addrp; - struct idn *sip; - - stp = (struct idnstr *)wq->q_ptr; - - if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) { - DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0); - return; - } - - dlp = (union DL_primitives *)mp->b_rptr; - len = dlp->set_physaddr_req.dl_addr_length; - off = dlp->set_physaddr_req.dl_addr_offset; - - if (!MBLKIN(mp, off, len)) { - DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0); - return; - } - - addrp = (struct ether_addr *)(mp->b_rptr + off); - - /* - * Error if length of address isn't right or the address - * specified is a multicast or broadcast address. - */ - if ((len != ETHERADDRL) || - IDNDL_ADDR_IS_MULTICAST(addrp) || - (ether_cmp(addrp, ðerbroadcastaddr) == 0)) { - DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0); - return; - } - - /* - * Error if this stream is not attached to a device. - */ - if ((sip = stp->ss_sip) == NULL) { - DLERRORACK(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0); - return; - } - - /* - * Set new interface local address and re-init device. - * This is destructive to any other streams attached - * to this device. - */ - ether_copy(addrp, &sip->si_ouraddr); - (void) idndl_init(stp->ss_sip); - - DLOKACK(wq, mp, DL_SET_PHYS_ADDR_REQ); -} -#endif /* notdef */ - -static void -idndl_udreq(queue_t *wq, mblk_t *mp) -{ - struct idnstr *stp; - register struct idn *sip; - register dl_unitdata_req_t *dludp; - mblk_t *nmp; - struct idndladdr *dlap; - struct ether_header *headerp; - t_uscalar_t off, len; - t_uscalar_t sap; - - stp = (struct idnstr *)wq->q_ptr; - sip = stp->ss_sip; - - if (stp->ss_state != DL_IDLE) { - DLERRORACK(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0); - return; - } - - dludp = (dl_unitdata_req_t *)mp->b_rptr; - - off = dludp->dl_dest_addr_offset; - len = dludp->dl_dest_addr_length; - - /* - * Validate destination address format. - */ - if (!MBLKIN(mp, off, len) || (len != IDNADDRL)) { - dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0); - return; - } - - /* - * Error if no M_DATA follows. - */ - nmp = mp->b_cont; - if (nmp == NULL) { - dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADDATA, 0); - return; - } - - dlap = (struct idndladdr *)(mp->b_rptr + off); - - /* - * Create ethernet header by either prepending it onto the - * next mblk if potential, or reusing the M_PROTO block if not. - */ - if ((DB_REF(nmp) == 1) && - (MBLKHEAD(nmp) >= sizeof (struct ether_header)) && - (((ulong_t)nmp->b_rptr & 0x1) == 0)) { - nmp->b_rptr -= sizeof (struct ether_header); - headerp = (struct ether_header *)nmp->b_rptr; - ether_copy(&dlap->dl_phys, &headerp->ether_dhost); - ether_copy(&sip->si_ouraddr, &headerp->ether_shost); - sap = dlap->dl_sap; - freeb(mp); - mp = nmp; - } else { - DB_TYPE(mp) = M_DATA; - headerp = (struct ether_header *)mp->b_rptr; - mp->b_wptr = mp->b_rptr + sizeof (struct ether_header); - ether_copy(&dlap->dl_phys, &headerp->ether_dhost); - ether_copy(&sip->si_ouraddr, &headerp->ether_shost); - sap = dlap->dl_sap; - } - - /* - * For transmitting, the driver looks at the - * sap field of the DL_BIND_REQ being 0 in addition to the type - * field in the range [0-1500]. If either is true, then the driver - * computes the length of the message, not including initial M_PROTO - * mblk (message block), of all subsequent DL_UNITDATA_REQ messages and - * transmits 802.3 frames that have this value in the MAC frame header - * length field. - */ - if ((sap <= ETHERMTU) || (stp->ss_sap == 0)) - headerp->ether_type = (msgsize(mp) - - sizeof (struct ether_header)); - else - headerp->ether_type = sap; - - /* - * The data transfer code requires only READ access (idn_wput_data). - */ - rw_downgrade(&stp->ss_rwlock); - (void) idndl_start(wq, mp, sip); -} - -int -idndl_start(queue_t *wq, register mblk_t *mp, register struct idn *sip) -{ - int rv = 0; - int flags; - int broadcast = 0; - int goagain = 0; - int goqueue = 0; - int msgcount; - char channel; - mblk_t *nmp = NULL; - int domid; - domainset_t domset; - idn_netaddr_t netaddr; - struct idnstr *stp; - struct ether_header *ehp; - procname_t proc = "idndl_start"; - - ASSERT(DB_TYPE(mp) == M_DATA); - - stp = (struct idnstr *)wq->q_ptr; - ASSERT(sip == stp->ss_sip); - flags = sip->si_flags; - channel = (char)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL]; - - ASSERT(RW_READ_HELD(&stp->ss_rwlock)); - - if ((flags & (IDNRUNNING|IDNPROMISC)) != IDNRUNNING) { - if (!(flags & IDNRUNNING)) - goto requeue; - } - - /* - * Translate an IDN ethernet address into a domainid - * and idnaddr. - */ - ehp = (struct ether_header *)mp->b_rptr; - domid = IDNDL_ETHER2DOMAIN(&ehp->ether_dhost); - - /* - * update MIB II statistics - */ - BUMP_OutNUcast(sip, ehp); - - PR_DLPI("%s: ether %x:%x:%x:%x:%x:%x (domid = %d)\n", - proc, ehp->ether_dhost.ether_addr_octet[0], - ehp->ether_dhost.ether_addr_octet[1], - ehp->ether_dhost.ether_addr_octet[2], - ehp->ether_dhost.ether_addr_octet[3], - ehp->ether_dhost.ether_addr_octet[4], - ehp->ether_dhost.ether_addr_octet[5], - domid); - - netaddr.net.chan = channel; - PR_DLPI("%s: source channel = %d\n", proc, (int)channel); - - if ((ether_cmp(&ehp->ether_dhost, ðerbroadcastaddr) == 0) || - IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost)) { - /* - * Caller wants to broadcast! - * XXX - Send to everybody but ourself??? - */ - PR_DLPI("%s: broadcast/multicast requested!!!\n", proc); - domset = ~DOMAINSET(idn.localid); - broadcast = 1; - netaddr.net.netid = IDN_BROADCAST_ALLNETID; - if ((flags & IDNPROMISC) && - ((nmp = copymsg(mp)) == NULL)) { - IDN_KSTAT_INC(sip, si_allocbfail); - } - - } else if (domid != IDN_NIL_DOMID) { - domset = DOMAINSET(domid); - netaddr.net.netid = idn_domain[domid].dnetid; - if ((flags & IDNPROMISC) && - ((nmp = copymsg(mp)) == NULL)) { - IDN_KSTAT_INC(sip, si_allocbfail); - } - } else { -#ifdef DEBUG - int netid; - - netid = (int) - ehp->ether_dhost.ether_addr_octet[IDNETHER_NETID]; - PR_DLPI("%s: no domain found for netid 0x%x\n", - proc, netid); -#endif /* DEBUG */ - goto bad; - } - - PR_DLPI("%s: target domainset = 0x%x\n", proc, domset); - - if ((domset == 0) && (domid == IDN_NIL_DOMID)) { - PR_DLPI("%s: not connected to any domains!! Bailing\n", - proc); - goto bad; - } - /* - * XXX - Need to find a better way to handle broadcasting. - * Should be able to take advantage of the fact that - * we can broadcast XDC's (xdc_some). Need to use - * atomic counter (semaphore) instead of binary - * "owner" flag, or perhaps domain specific owner bytes. - * - * Transfer the data. - */ - msgcount = 0; - if (!broadcast) - goto noloop; - - for (domid = 0; domid < MAX_DOMAINS; domid++) { - if (!DOMAIN_IN_SET(domset, domid)) - continue; - -noloop: - - if (idn_domain[domid].dcpu == IDN_NIL_DCPU) { - if (broadcast) - continue; - else - break; - } - - rv = idn_send_data(domid, netaddr, wq, mp); - - switch (rv) { - case IDNXMIT_LOOP: /* handled in loopback */ - msgcount++; - break; - - case IDNXMIT_OKAY: /* handled, okay to free */ - msgcount++; - break; - - case IDNXMIT_RETRY: - if (!broadcast) - goto tryagain; - goagain++; - break; - - case IDNXMIT_REQUEUE: - if (!broadcast) - goto requeue; - goqueue++; - break; - - default: - if (!broadcast) - goto bad; - break; - } - if (!broadcast) - break; - } - - if (msgcount == 0) - if (goqueue) - goto requeue; - else if (goagain) - goto tryagain; - else - goto bad; - - if ((flags & IDNPROMISC) && nmp) - idndl_sendup(sip, nmp, idndl_paccept); - - freemsg(mp); - - PR_DLPI("%s: successful transmit to domainset 0x%x.\n", - proc, domset); - - return (0); - -bad: - PR_DLPI("%s: bad transmission to domainset 0x%x, dropping msg.\n", - proc, domset); - if (nmp) - freemsg(nmp); - freemsg(mp); - qenable(wq); - return (1); - -requeue: - PR_DLPI("%s: requeue for domainset 0x%x, no qenable\n", - proc, domset); - if (nmp) - freemsg(nmp); - if (putbq(wq, mp) == 0) - freemsg(mp); - return (1); - -tryagain: - PR_DLPI("%s: try again to domainset 0x%x, putbq.\n", - proc, domset); - if (nmp) - freemsg(nmp); - if (putbq(wq, mp) == 0) - freemsg(mp); - qenable(wq); - return (1); -} - -/* - * Called by: idnh_recv_data, idn_recv_mboxdata. - */ -void -idndl_read(struct idn *sip, mblk_t *mp) -{ - struct ether_header *ehp; - queue_t *ip4q; - queue_t *ip6q; - int pktlen; - procname_t proc = "idndl_read"; - - PR_DLPI("%s: incoming msgsize = %lu, msgdsize = %lu\n", - proc, msgsize(mp), msgdsize(mp)); - - ehp = (struct ether_header *)mp->b_rptr; - if (sip == NULL) - sip = IDNDL_ETHER2SIP(&ehp->ether_dhost); - if (sip == NULL) { - /* - * If the sip is NULL, then I don't have a connection - * for this network. No point in sending the message - * up. - */ - PR_DLPI("%s: no plumbing to send message through.\n", - proc); - freemsg(mp); - return; - } - IDN_KSTAT_INC(sip, si_ipackets); - IDN_KSTAT_INC(sip, si_ipackets64); - /* - * update MIB II statistics - */ - pktlen = mp->b_wptr - mp->b_rptr; - BUMP_InNUcast(sip, ehp); - IDN_KSTAT_ADD(sip, si_rcvbytes, pktlen); - IDN_KSTAT_ADD(sip, si_rbytes64, (uint64_t)pktlen); - - ip4q = sip->si_ip4q; - ip6q = sip->si_ip6q; - - if (IS_ETHERTYPE_IPV4(ehp->ether_type) && - !IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost) && - ip4q && - canputnext(ip4q)) { - mp->b_rptr += sizeof (struct ether_header); - (void) putnext(ip4q, mp); - /*LINTED*/ - } else if (IS_ETHERTYPE_IPV6(ehp->ether_type) && - !IDNDL_ADDR_IS_MULTICAST(&ehp->ether_dhost) && - ip6q && - canputnext(ip6q)) { - mp->b_rptr += sizeof (struct ether_header); - (void) putnext(ip6q, mp); - } else { - /* - * Strip the PADs for 802.3 - */ - pktlen = ehp->ether_type + sizeof (struct ether_header); - PR_DLPI("%s: stripping PADs for 802.3 (pktlen=%d)\n", - proc, pktlen); - if (pktlen < ETHERMIN) - mp->b_wptr = mp->b_rptr + pktlen; - idndl_sendup(sip, mp, idndl_accept); - } -} - -int -idndl_init(struct idn *sip) -{ - struct idnstr *stp; - - if (sip->si_flags & IDNSUSPENDED) - (void) ddi_dev_is_needed(sip->si_dip, 0, 1); - - sip->si_flags = 0; - sip->si_wantw = 0; - - IDN_KSTAT_INC(sip, si_inits); - - rw_enter(&idn.struprwlock, RW_WRITER); - - for (stp = idn.strup; stp; stp = stp->ss_nextp) { - if ((stp->ss_sip == sip) && (stp->ss_flags & IDNSALLPHYS)) { - sip->si_flags |= IDNPROMISC; - break; - } - } - - sip->si_flags |= IDNRUNNING; - - mutex_enter(&idn.sipwenlock); - idndl_wenable(sip); - mutex_exit(&idn.sipwenlock); - - rw_exit(&idn.struprwlock); - - return (!(sip->si_flags & IDNRUNNING)); -} - -void -idndl_uninit(struct idn *sip) -{ - int channel; - procname_t proc = "idndl_uninit"; - - sip->si_flags &= ~IDNRUNNING; - - channel = (int)sip->si_ouraddr.ether_addr_octet[IDNETHER_CHANNEL]; - PR_DLPI("%s: IP SAP, uninit channel %d\n", proc, channel); - /* - * A uninit is a hard close of an interface. - */ - idn_close_channel(channel, IDNCHAN_HARD_CLOSE); -} - -/* - * Send packet upstream. - * Assume mp->b_rptr points to ether_header. - */ -void -idndl_sendup(struct idn *sip, mblk_t *mp, struct idnstr *(*acceptfunc)()) -{ - int type; - struct ether_addr *dhostp, *shostp; - struct idnstr *stp, *nstp; - mblk_t *nmp; - ulong_t isgroupaddr; - - TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_START, "idnsendup start"); - - dhostp = &((struct ether_header *)mp->b_rptr)->ether_dhost; - shostp = &((struct ether_header *)mp->b_rptr)->ether_shost; - type = ((struct ether_header *)mp->b_rptr)->ether_type; - - isgroupaddr = IDNDL_ADDR_IS_MULTICAST(dhostp); - - /* - * While holding a reader lock on the linked list of streams structures, - * attempt to match the address criteria for each stream - * and pass up the raw M_DATA ("fastpath") or a DL_UNITDATA_IND. - */ - - rw_enter(&idn.struprwlock, RW_READER); - - if ((stp = (*acceptfunc)(idn.strup, sip, type, dhostp)) == NULL) { - rw_exit(&idn.struprwlock); - freemsg(mp); - TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_END, "idnsendup end"); - return; - } - - /* - * Loop on matching open streams until (*acceptfunc)() returns NULL. - */ - for (; nstp = (*acceptfunc)(stp->ss_nextp, sip, type, dhostp); - stp = nstp) { - - if (canputnext(stp->ss_rq) == 0) { - IDN_KSTAT_INC(sip, si_nocanput); - continue; - } - if ((nmp = dupmsg(mp)) == NULL) - nmp = copymsg(mp); - if (nmp) { - if ((stp->ss_flags & IDNSFAST) && !isgroupaddr) { - nmp->b_rptr += sizeof (struct ether_header); - (void) putnext(stp->ss_rq, nmp); - } else if (stp->ss_flags & IDNSRAW) { - (void) putnext(stp->ss_rq, nmp); - } else if ((nmp = idndl_addudind(sip, nmp, shostp, - dhostp, type, isgroupaddr))) { - (void) putnext(stp->ss_rq, nmp); - } - } else { - IDN_KSTAT_INC(sip, si_allocbfail); - } - } - - - /* - * Do the last one. - */ - if (canputnext(stp->ss_rq)) { - if ((stp->ss_flags & IDNSFAST) && !isgroupaddr) { - mp->b_rptr += sizeof (struct ether_header); - (void) putnext(stp->ss_rq, mp); - } else if (stp->ss_flags & IDNSRAW) { - (void) putnext(stp->ss_rq, mp); - } else if ((mp = idndl_addudind(sip, mp, shostp, dhostp, - type, isgroupaddr))) { - (void) putnext(stp->ss_rq, mp); - } - } else { - freemsg(mp); - IDN_KSTAT_INC(sip, si_nocanput); - IDN_KSTAT_INC(sip, si_norcvbuf); /* MIB II */ - } - - rw_exit(&idn.struprwlock); - TRACE_0(TR_FAC_IDN, TR_IDN_SENDUP_END, "idnsendup end"); -} - -/* - * Test upstream destination sap and address match. - */ -struct idnstr * -idndl_accept(register struct idnstr *stp, register struct idn *sip, - int type, struct ether_addr *addrp) -{ - t_uscalar_t sap; - uint_t flags; - - for (; stp; stp = stp->ss_nextp) { - sap = stp->ss_sap; - flags = stp->ss_flags; - - if ((stp->ss_sip == sip) && IDNSAPMATCH(sap, type, flags)) - if ((ether_cmp(addrp, &sip->si_ouraddr) == 0) || - (ether_cmp(addrp, ðerbroadcastaddr) == 0) || - (flags & IDNSALLPHYS) || - idndl_mcmatch(stp, addrp)) - return (stp); - } - - return (NULL); -} - -/* - * Test upstream destination sap and address match for IDNSALLPHYS only. - */ -/* ARGSUSED3 */ -struct idnstr * -idndl_paccept(register struct idnstr *stp, register struct idn *sip, - int type, struct ether_addr *addrp) -{ - t_uscalar_t sap; - uint_t flags; - - for (; stp; stp = stp->ss_nextp) { - sap = stp->ss_sap; - flags = stp->ss_flags; - - if ((stp->ss_sip == sip) && - IDNSAPMATCH(sap, type, flags) && - (flags & IDNSALLPHYS)) - return (stp); - } - - return (NULL); -} - -/* - * Set or clear the device ipq pointer. - * Assumes IPv4 and IPv6 are IDNSFAST. - */ -static void -idndl_setipq(struct idn *sip) -{ - struct idnstr *stp; - int ok4 = 1; - int ok6 = 1; - queue_t *ip4q = NULL; - queue_t *ip6q = NULL; - - rw_enter(&idn.struprwlock, RW_READER); - - for (stp = idn.strup; stp; stp = stp->ss_nextp) { - if (stp->ss_sip == sip) { - if (stp->ss_flags & (IDNSALLPHYS|IDNSALLSAP)) { - ok4 = 0; - ok6 = 0; - break; - } - if (IS_ETHERTYPE_IPV4(stp->ss_sap)) { - if (ip4q == NULL) - ip4q = stp->ss_rq; - else - ok4 = 0; - /*LINTED*/ - } else if (IS_ETHERTYPE_IPV6(stp->ss_sap)) { - if (ip6q == NULL) - ip6q = stp->ss_rq; - else - ok6 = 0; - } - } - } - - rw_exit(&idn.struprwlock); - - if (ok4) - sip->si_ip4q = ip4q; - else - sip->si_ip4q = NULL; - if (ok6) - sip->si_ip6q = ip6q; - else - sip->si_ip6q = NULL; -} - -/* - * Prefix msg with a DL_UNITDATA_IND mblk and return the new msg. - */ -static mblk_t * -idndl_addudind(struct idn *sip, mblk_t *mp, - struct ether_addr *shostp, struct ether_addr *dhostp, - int type, ulong_t isgroupaddr) -{ - dl_unitdata_ind_t *dludindp; - struct idndladdr *dlap; - mblk_t *nmp; - int size; - - TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_START, "idndl_addudind start"); - - mp->b_rptr += sizeof (struct ether_header); - - /* - * Allocate an M_PROTO mblk for the DL_UNITDATA_IND. - */ - size = sizeof (dl_unitdata_ind_t) + IDNADDRL + IDNADDRL; - nmp = allocb(IDNROUNDUP(IDNHEADROOM + size, sizeof (double)), BPRI_LO); - if (nmp == NULL) { - IDN_KSTAT_INC(sip, si_allocbfail); - IDN_KSTAT_INC(sip, si_ierrors); - if (idn_debug) - serror(sip->si_dip, 451, "allocb failed"); - freemsg(mp); - TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_END, "idndl_addudind end"); - return (NULL); - } - DB_TYPE(nmp) = M_PROTO; - nmp->b_wptr = nmp->b_datap->db_lim; - nmp->b_rptr = nmp->b_wptr - size; - - /* - * Construct a DL_UNITDATA_IND primitive. - */ - dludindp = (dl_unitdata_ind_t *)nmp->b_rptr; - dludindp->dl_primitive = DL_UNITDATA_IND; - dludindp->dl_dest_addr_length = IDNADDRL; - dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t); - dludindp->dl_src_addr_length = IDNADDRL; - dludindp->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + IDNADDRL; - dludindp->dl_group_address = isgroupaddr; - - dlap = (struct idndladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t)); - ether_copy(dhostp, &dlap->dl_phys); - dlap->dl_sap = (ushort_t)type; - - dlap = (struct idndladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t) - + IDNADDRL); - ether_copy(shostp, &dlap->dl_phys); - dlap->dl_sap = (ushort_t)type; - - /* - * Link the M_PROTO and M_DATA together. - */ - nmp->b_cont = mp; - TRACE_0(TR_FAC_IDN, TR_IDN_ADDUDIND_END, "idndl_addudind end"); - return (nmp); -} - -/* - * Return TRUE if the given multicast address is one - * of those that this particular Stream is interested in. - */ -static int -idndl_mcmatch(register struct idnstr *stp, register struct ether_addr *addrp) -{ - register struct ether_addr *mctab; - register int mccount; - register int i; - - /* - * Return FALSE if not a multicast address. - */ - if (!IDNDL_ADDR_IS_MULTICAST(addrp)) - return (0); - - /* - * Check if all multicasts have been enabled for this Stream - */ - if (stp->ss_flags & IDNSALLMULTI) - return (1); - - /* - * Return FALSE if no multicast addresses enabled for this Stream. - */ - if (stp->ss_mccount == 0) - return (0); - - /* - * Otherwise, find it in the table. - */ - - mccount = stp->ss_mccount; - mctab = stp->ss_mctab; - - for (i = 0; i < mccount; i++) - if (!ether_cmp(addrp, &mctab[i])) - return (1); - - return (0); -} - -/* - * Start xmit on any msgs previously enqueued on any write queues. - * If the caller passes NULL, then we need to check all - * our interfaces. - */ -void -idndl_wenable(struct idn *sip) -{ - struct idnstr *stp; - queue_t *wq; - - /* - * Order of wantw accesses is important. - */ - ASSERT((sip == NULL) ? RW_LOCK_HELD(&idn.struprwlock) : 1); - ASSERT(MUTEX_HELD(&idn.sipwenlock)); - - do { - if (sip) - sip->si_wantw = 0; - for (stp = idn.strup; stp; stp = stp->ss_nextp) { - if ((!sip || (stp->ss_sip == sip)) && - stp->ss_rq && ((wq = WR(stp->ss_rq))->q_first)) - qenable(wq); - } - } while (sip && sip->si_wantw); -} - -/*VARARGS*/ -static void -serror(dev_info_t *dip, int idnerr, char *fmt, ...) -{ - static long last; - static char *lastfmt; - char msg_buffer[255]; - va_list ap; - time_t now; - - /* - * Don't print same error message too often. - */ - now = gethrestime_sec(); - if ((last == (now & ~1)) && (lastfmt == fmt)) - return; - - last = now & ~1; - lastfmt = fmt; - - va_start(ap, fmt); - (void) vsprintf(msg_buffer, fmt, ap); - cmn_err(CE_CONT, "IDN: %d: %s%d: %s\n", - idnerr, ddi_get_name(dip), - ddi_get_instance(dip), msg_buffer); - va_end(ap); -} diff --git a/usr/src/uts/sun4u/starfire/io/idn_proto.c b/usr/src/uts/sun4u/starfire/io/idn_proto.c deleted file mode 100644 index cebcdb89f7..0000000000 --- a/usr/src/uts/sun4u/starfire/io/idn_proto.c +++ /dev/null @@ -1,12971 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - */ - -/* - * Inter-Domain Network - * - * IDN Protocol functions to support domain link/unlink/reconfig. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/machparam.h> -#include <sys/debug.h> -#include <sys/cpuvar.h> -#include <sys/kmem.h> -#include <sys/mutex.h> -#include <sys/rwlock.h> -#include <sys/systm.h> -#include <sys/stream.h> -#include <sys/strsun.h> -#include <sys/stropts.h> -#include <sys/sema_impl.h> -#include <sys/membar.h> -#include <sys/utsname.h> -#include <inet/common.h> -#include <inet/mi.h> -#include <netinet/ip6.h> -#include <inet/ip.h> -#include <netinet/in.h> -#include <sys/vm_machparam.h> -#include <sys/x_call.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/atomic.h> -#include <vm/as.h> /* kas decl */ - -#include <sys/idn.h> -#include <sys/idn_xf.h> - -#define IDNBUG_CPUPERBOARD - -extern pri_t maxclsyspri; -extern u_longlong_t gettick(); - -clock_t idn_xmit_monitor_freq = 50; - -static int idn_connect(int domid); -static int idn_disconnect(int domid, idn_fin_t fintype, - idn_finarg_t finarg, idn_finsync_t finsync); -static void idn_deconfig(int domid); -static void idn_unlink_domainset(domainset_t domset, idn_fin_t fintype, - idn_finarg_t finarg, idn_finopt_t finopt, - boardset_t idnset); -static void idn_retry_execute(void *arg); -static void idn_retry_submit(void (*func)(uint_t token, void *arg), - void *arg, uint_t token, clock_t ticks); -static void idn_shutdown_datapath(domainset_t domset, int force); -static mblk_t *idn_fill_buffer(caddr_t bufp, int size, mblk_t *mp, - uchar_t **data_rptrp); -static ushort_t idn_cksum(register ushort_t *hdrp, register int count); -static int idn_mark_awol(int domid, clock_t *atime); - -static void idn_recv_proto(idn_protomsg_t *hp); -static void idn_send_config(int domid, int phase); -static void idn_recv_config(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static int idn_send_master_config(int domid, int phase); -static int idn_send_slave_config(int domid, int phase); -static uint_t idn_check_master_config(int domid, uint_t *exp, uint_t *act); -static uint_t idn_check_slave_config(int domid, uint_t *exp, uint_t *act); -static int idn_recv_config_done(int domid); -static void idn_nego_cleanup_check(int domid, int new_masterid, - int new_cpuid); -static void idn_recv_cmd(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static int idn_recv_data(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static int idn_send_data_loopback(idn_netaddr_t dst_netaddr, - queue_t *wq, mblk_t *mp); -static void idn_send_dataresp(int domid, idn_nack_t nacktype); -static int idn_send_mboxdata(int domid, struct idn *sip, int channel, - caddr_t bufp); -static int idn_recv_mboxdata(int channel, caddr_t bufp); -static int idn_program_hardware(int domid); -static int idn_deprogram_hardware(int domid); - -static void idn_send_cmd_nackresp(int domid, idn_msgtype_t *mtp, - idn_cmd_t cmdtype, idn_nack_t nacktype); -static void idn_local_cmd(idn_cmd_t cmdtype, uint_t arg1, - uint_t arg2, uint_t arg3); -static void idn_terminate_cmd(int domid, int serrno); -static void idn_mboxarea_init(idn_mboxtbl_t *mtp, register int ntbls); -static void idn_mainmbox_activate(int domid); -static void idn_mainmbox_deactivate(ushort_t domset); -static void idn_mainmbox_chan_register(int domid, - idn_mainmbox_t *send_mmp, - idn_mainmbox_t *recv_mmp, int channel); -static int idn_mainmbox_chan_unregister(ushort_t domset, int channel); -static int idn_mainmbox_flush(int domid, idn_mainmbox_t *mmp); -static void idn_mainmbox_reset(int domid, idn_mainmbox_t *cmp); -static int idn_activate_channel(idn_chanset_t chanset, - idn_chanop_t chanop); -static void idn_deactivate_channel(idn_chanset_t chanset, - idn_chanop_t chanop); -static int idn_deactivate_channel_services(int channel, - idn_chanop_t chanop); -static int idn_activate_channel_services(int channel); -static void idn_chan_server(idn_chansvr_t **cspp); -#if 0 -static void idn_chan_flush(idn_chansvr_t *csp); -#endif /* 0 */ -static void idn_chan_action(int channel, idn_chanaction_t chanaction, - int wait); -static void idn_chan_addmbox(int channel, ushort_t domset); -static void idn_chan_delmbox(int channel, ushort_t domset); -static void idn_submit_chanactivate_job(int channel); -static void idn_exec_chanactivate(void *chn); - -static void idn_link_established(void *arg); -static void idn_prealloc_slab(int nslabs); -static void idn_recv_slaballoc_req(int domid, idn_msgtype_t *mtp, - uint_t slab_size); -static void idn_send_slaballoc_resp(int domid, idn_msgtype_t *mtp, - uint_t slab_offset, uint_t slab_size, - int serrno); -static void idn_recv_slaballoc_resp(int domid, smr_offset_t slab_offset, - uint_t slab_size, int serrno); -static void idn_recv_slabreap_req(int domid, idn_msgtype_t *mtp, - int nslabs); -static void idn_recv_slabreap_resp(int domid, int nslabs, int serrno); -static void idn_send_slabreap_resp(int domid, idn_msgtype_t *mtp, - int nslabs, int serrno); -static void idn_recv_slabfree_req(int domid, idn_msgtype_t *mtp, - smr_offset_t slab_offset, uint_t slab_size); -static void idn_recv_slabfree_resp(int domid, uint_t slab_offset, - uint_t slab_size, int serrno); -static void idn_send_slabfree_resp(int domid, idn_msgtype_t *mtp, - uint_t slab_offset, uint_t slab_size, - int serrno); -static void idn_retry_nodename_req(void *arg); -static void idn_send_nodename_req(int domid); -static void idn_send_nodename_resp(int domid, idn_msgtype_t *mtp, - uint_t bufoffset, int serrno); -static void idn_recv_nodename_req(int domid, idn_msgtype_t *mtp, - uint_t bufoffset); -static void idn_recv_nodename_resp(int domid, uint_t bufoffset, - int serrno); - -static void idn_protocol_server(int *id); -static void idn_protocol_server_killall(); -static void idn_protojob_free(idn_protojob_t *jp); - -static int idn_xstate_transfunc(int domid, void *transarg); -static int idn_xphase_transition(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_sync_enter(int domid, idn_synccmd_t cmd, - domainset_t xset, domainset_t rset, - int (*transfunc)(), void *transarg); -static domainset_t - idn_sync_register(int domid, idn_synccmd_t cmd, - domainset_t ready_set, idn_syncreg_t regtype); -static void idn_sync_register_awol(int domid); -static int idn_verify_config_mbox(int domid); -static int idn_select_master(int domid, int rmasterid, int rcpuid); - -static int valid_mtu(uint_t mtu); -static int valid_bufsize(uint_t bufsize); -static int valid_slabsize(int slabsize); -static int valid_nwrsize(int nwrsize); - -static int idn_master_init(); -static void idn_master_deinit(); - -static void idn_send_acknack(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); - -static int idn_send_nego(int domid, idn_msgtype_t *mtp, - domainset_t conset); -static void idn_retry_nego(uint_t token, void *arg); -static int idn_check_nego(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_nego_pend(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_error_nego(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_nego_sent(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_nego_rcvd(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_final_nego(int domid); -static void idn_exit_nego(int domid, uint_t msgtype); - -static int idn_send_con(int domid, idn_msgtype_t *mtp, - idn_con_t contype, domainset_t conset); -static void idn_retry_con(uint_t token, void *arg); -static int idn_check_con(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_con_pend(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_error_con(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_con_sent(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_con_rcvd(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_final_con(int domid); -static void idn_exit_con(int domid, uint_t msgtype); - -static int idn_send_fin(int domid, idn_msgtype_t *mtp, idn_fin_t fintype, - idn_finarg_t finarg, idn_finopt_t finopt, - domainset_t finset, uint_t finmaster); -static void idn_retry_fin(uint_t token, void *arg); -static int idn_check_fin_pend(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_fin_pend(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_error_fin_pend(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static int idn_check_fin_sent(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_fin_sent(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_error_fin_sent(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_action_fin_rcvd(int domid, idn_msgtype_t *mtp, - idn_xdcargs_t xargs); -static void idn_final_fin(int domid); -static void idn_exit_fin(int domid, uint_t msgtype); - -/* - * We keep a small cache of protojob structures just - * in case allocation within idn_handler comes back - * with nothing from the land of kmem. - */ -idn_protojob_t idn_protojob_cache[IDN_DMV_PENDING_MAX]; -idn_protojob_t *idn_protojob_cache_list; -kmutex_t idn_protojob_cache_lock; - -/* - * - receive message. - * - call check-function for current state. - * - if (check-function == ok) then - * call action-function for current state. - * else - * call error-function for current state. - * - transition state based on check results. - * - if (next state == final state) then - * call final-function. - */ -static idn_xphase_t xphase_nego = { - IDNP_NEGO, - { - { IDNDS_NEGO_PEND, - idn_check_nego, - idn_action_nego_pend, - idn_error_nego}, - { IDNDS_NEGO_SENT, - idn_check_nego, - idn_action_nego_sent, - idn_error_nego}, - { IDNDS_NEGO_RCVD, - NULL, - idn_action_nego_rcvd, - NULL }, - { IDNDS_CONFIG, NULL, NULL, NULL }, - }, - idn_final_nego, - idn_exit_nego -}; - -static idn_xphase_t xphase_con = { - IDNP_CON, - { - { IDNDS_CON_PEND, - idn_check_con, - idn_action_con_pend, - idn_error_con}, - { IDNDS_CON_SENT, - idn_check_con, - idn_action_con_sent, - idn_error_con}, - { IDNDS_CON_RCVD, - NULL, - idn_action_con_rcvd, - NULL }, - { IDNDS_CON_READY, NULL, NULL, NULL }, - }, - idn_final_con, - idn_exit_con -}; - -static idn_xphase_t xphase_fin = { - IDNP_FIN, - { - { IDNDS_FIN_PEND, - idn_check_fin_pend, - idn_action_fin_pend, - idn_error_fin_pend }, - { IDNDS_FIN_SENT, - idn_check_fin_sent, - idn_action_fin_sent, - idn_error_fin_sent }, - { IDNDS_FIN_RCVD, - NULL, - idn_action_fin_rcvd, - NULL }, - { IDNDS_DMAP, NULL, NULL, NULL }, - }, - idn_final_fin, - idn_exit_fin -}; - -static int idnxs_state_table[4][5][2] = { - { /* IDNXS_PEND */ - { IDNXS_SENT, IDNXS_PEND }, /* 0 */ - { IDNXS_RCVD, IDNXS_PEND }, /* msg */ - { IDNXS_NIL, IDNXS_PEND }, /* msg+ack */ - { IDNXS_PEND, IDNXS_NIL }, /* ack */ - { IDNXS_PEND, IDNXS_NIL }, /* nack */ - }, - { /* IDNXS_SENT */ - { IDNXS_NIL, IDNXS_NIL }, /* 0 */ - { IDNXS_RCVD, IDNXS_PEND }, /* msg */ - { IDNXS_FINAL, IDNXS_PEND }, /* msg+ack */ - { IDNXS_NIL, IDNXS_NIL }, /* ack */ - { IDNXS_PEND, IDNXS_NIL }, /* nack */ - }, - { /* IDNXS_RCVD */ - { IDNXS_NIL, IDNXS_NIL }, /* 0 */ - { IDNXS_NIL, IDNXS_NIL }, /* msg */ - { IDNXS_FINAL, IDNXS_NIL }, /* msg+ack */ - { IDNXS_FINAL, IDNXS_NIL }, /* ack */ - { IDNXS_PEND, IDNXS_NIL }, /* nack */ - }, - { /* IDNXS_FINAL */ - { IDNXS_NIL, IDNXS_NIL }, /* 0 */ - { IDNXS_NIL, IDNXS_NIL }, /* msg */ - { IDNXS_NIL, IDNXS_NIL }, /* msg+ack */ - { IDNXS_NIL, IDNXS_NIL }, /* ack */ - { IDNXS_NIL, IDNXS_NIL }, /* nack */ - } -}; - -/* - * NONE Respective domain does not have a master. - * OTHER Respective domain has a master different - * than either local or remote. - * LOCAL Respective domain has chosen local as master. - * REMOTE Respective domain has chosen remote as master. - * - * Actions: - * VOTE Compare votes and select one. - * VOTE_RCFG Compare votes and Reconfigure - * if necessary, i.e. remote won. - * CONNECT Connect to remote's OTHER if different - * than our local master. - * LOCAL Local domain is winner. - * REMOTE Remote domain is winner. - * WAIT Wait for remote to connect to our - * master if theirs is different. - * ERROR An impossible condition. - * - * Index: - * 0 = Local - * 1 = Remote - */ -static idn_master_select_t master_select_table[4][4] = { - { /* local remote */ - MASTER_SELECT_VOTE, /* NONE NONE */ - MASTER_SELECT_CONNECT, /* NONE OTHER */ - MASTER_SELECT_LOCAL, /* NONE LOCAL */ - MASTER_SELECT_REMOTE /* NONE REMOTE */ - }, - { - MASTER_SELECT_WAIT, /* OTHER NONE */ - MASTER_SELECT_CONNECT, /* OTHER OTHER */ - MASTER_SELECT_WAIT, /* OTHER LOCAL */ - MASTER_SELECT_WAIT /* OTHER REMOTE */ - }, - { - MASTER_SELECT_LOCAL, /* LOCAL NONE */ - MASTER_SELECT_CONNECT, /* LOCAL OTHER */ - MASTER_SELECT_LOCAL, /* LOCAL LOCAL */ - MASTER_SELECT_VOTE_RCFG /* LOCAL REMOTE */ - }, - { - MASTER_SELECT_REMOTE, /* REMOTE NONE */ - MASTER_SELECT_CONNECT, /* REMOTE OTHER */ - MASTER_SELECT_ERROR, /* REMOTE LOCAL */ - MASTER_SELECT_REMOTE /* REMOTE REMOTE */ - } -}; - -void -idn_assign_cookie(int domid) -{ - static ushort_t num = 0; - ushort_t cookie; - procname_t proc = "idn_assign_cookie"; - - if ((cookie = idn_domain[domid].dcookie_recv) != 0) - return; - - cookie = (ushort_t)(((uint64_t)&idn_domain[domid] >> 8) & 0xff); - while ((cookie ^= num++ & 0xff) == 0) - ; - - PR_PROTO("%s:%d: assigned RECV cookie 0x%x\n", proc, domid, cookie); - - idn_domain[domid].dcookie_recv = cookie; -} - -void -idn_update_priority(int domid, int pri) -{ - idn_domain_t *dp; - procname_t proc = "idn_update_priority"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - - if (pri >= IDNVOTE_MINPRI) { - dp->dvote.v.priority = pri & IDNVOTE_PRI_MASK; - - PR_PROTO("%s:%d: SETTING PRIORITY to req(%d) " - "(localpri = 0x%x)\n", - proc, domid, pri, IDNVOTE_PRIVALUE(dp->dvote)); - } else { - PR_PROTO("%s:%d: PRIORITIES UNCHANGED (pri = 0x%x)\n", - proc, domid, IDNVOTE_PRIVALUE(dp->dvote)); - } -} - -/* - * Initiate a link between the local domain and the remote domain - * containing the given cpuid. - */ -int -idn_link(int domid, int cpuid, int pri, int waittime, idnsb_error_t *sep) -{ - int rv; - idn_domain_t *dp; - void *opcookie; - procname_t proc = "idn_link"; - - if ((cpuid < 0) || (cpuid >= NCPU)) { - cmn_err(CE_WARN, - "IDN: 201: (LINK) invalid CPU ID (%d)", cpuid); - return (EINVAL); - } - if (waittime < 0) { - cmn_err(CE_WARN, - "IDN: 202: (LINK) invalid time-out value (%d)", - waittime); - return (EINVAL); - } - if (!VALID_DOMAINID(domid)) { - cmn_err(CE_WARN, - "IDN: 203: (LINK) invalid domain ID (%d)", - domid); - return (EINVAL); - } - if (domid == idn.localid) - return (0); - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - - dp = &idn_domain[domid]; - - switch (dp->dstate) { - case IDNDS_CLOSED: - break; - - case IDNDS_CONNECTED: -#ifdef DEBUG - cmn_err(CE_NOTE, - "!IDN: domain %d (CPU ID %d) already connected", - domid, cpuid); -#endif /* DEBUG */ - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return (0); - - default: - cmn_err(CE_WARN, - "IDN: 204: domain %d state (%s) inappropriate", - domid, idnds_str[dp->dstate]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return (EINVAL); - } - - rv = idn_open_domain(domid, cpuid, 0); - if (rv != 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s) failed to open-domain(%d,%d)", - proc, domid, cpuid); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return (EIO); - } - - - IDN_DLOCK_EXCL(idn.localid); - idn_update_priority(idn.localid, pri); - IDN_DUNLOCK(idn.localid); - - if (waittime > 0) - opcookie = idn_init_op(IDNOP_CONNECTED, DOMAINSET(domid), sep); - - (void) idn_connect(domid); - - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - - PR_PROTO("%s:%d: ALLOCATED idn_link(%d)\n", proc, domid, cpuid); - - if (waittime > 0) { - boardset_t domset = 0; - /* - * Well we've successfully allocated a domain id, - * but the link may not be fully established yet. - * Need to wait since it happens asynchronously. - */ - PR_PROTO("%s:%d: WAITING for op(%s) for (domset 0%x)...\n", - proc, domid, idnop_str[IDNOP_CONNECTED], - DOMAINSET(domid)); - - rv = idn_wait_op(opcookie, &domset, waittime); - } - -#ifdef DEBUG - if (rv == 0) { - if (waittime > 0) { - PR_PROTO("%s:%d: connect SUCCEEDED (cpu %d)\n", - proc, domid, cpuid); - } else { - PR_PROTO("%s:%d: connect KICKED OFF (cpu %d)\n", - proc, domid, cpuid); - } - } else { - PR_PROTO("%s:%d: connect FAILED (cpu %d)\n", - proc, domid, cpuid); - } -#endif /* DEBUG */ - - return (rv); -} - -/* - * Unlink the given domain from any domain cluster of - * which it might be a member. Force indicates that domain - * should not go AWOL and if it's currently AWOL to close - * and remove it. - * IMPORTANT: If the (hard) force flag is set, the caller is - * assumed to GUARANTEE that the given domain will - * not attempt to communicate with the local domain - * in any manner. - */ -int -idn_unlink(int domid, boardset_t idnset, idn_fin_t fintype, - idn_finopt_t finopt, int waittime, idnsb_error_t *sep) -{ - int rv = 0; - domainset_t domset; - void *opcookie; - procname_t proc = "idn_unlink"; - - - if (waittime < 0) { - cmn_err(CE_WARN, - "IDN: 202: (UNLINK) invalid time-out value (%d)", - waittime); - SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_WTIME); - SET_IDNKERR_PARAM0(sep, waittime); - return (EINVAL); - } - if (!VALID_DOMAINID(domid)) { - cmn_err(CE_WARN, - "IDN: 203: (UNLINK) invalid domain ID (%d)", - domid); - SET_IDNKERR_IDNERR(sep, IDNKERR_INVALID_DOMAIN); - SET_IDNKERR_PARAM0(sep, domid); - SET_IDNKERR_PARAM1(sep, -1); - return (EINVAL); - } - if (idn.localid == IDN_NIL_DOMID) { -#ifdef DEBUG - cmn_err(CE_NOTE, - "!IDN: %s: local domain not connected to an IDNnet", - proc); -#endif /* DEBUG */ - return (0); - } - - /* - * Lock ordering protocols requires that we grab the - * global lock _before_ the local domain's lock. - * However, non-local domains must have their lock - * grabbed _before_ the global lock. - */ - IDN_SYNC_LOCK(); - IDN_GLOCK_EXCL(); - domset = idn.domset.ds_trans_on | idn.domset.ds_trans_off; - if ((idn.state == IDNGS_OFFLINE) && !domset) { -#ifdef DEBUG - cmn_err(CE_WARN, - "!IDN: %s: local domain not connected to an IDNnet", - proc); -#endif /* DEBUG */ - IDN_GUNLOCK(); - IDN_SYNC_UNLOCK(); - return (0); - } - - if ((domid == IDN_NIL_DOMID) || (domid == idn.localid)) { - domid = idn.localid; - IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - domset = DOMAINSET_ALL; - DOMAINSET_DEL(domset, idn.localid); - } else { - domset = DOMAINSET(domid); - } - IDN_GUNLOCK(); - - if (waittime > 0) - opcookie = idn_init_op(IDNOP_DISCONNECTED, domset, sep); - - idn_unlink_domainset(domset, fintype, IDNFIN_ARG_NONE, finopt, idnset); - - IDN_SYNC_UNLOCK(); - - if (waittime > 0) { - /* - * Well the unlink has successfully kicked off. - * Since process is asynchronous we need to wait - * for it to complete. - */ - PR_PROTO("%s:%d: WAITING for op(%s) for (domset 0%x)...\n", - proc, domid, idnop_str[IDNOP_DISCONNECTED], - domset); - - rv = idn_wait_op(opcookie, &domset, waittime); - } - - if (rv == 0) { - if (waittime > 0) { - PR_PROTO("%s:%d: disconnect SUCCEEDED\n", - proc, domid); - } else { - PR_PROTO("%s:%d: disconnect KICKED OFF\n", - proc, domid); - } - } else { - PR_PROTO("%s:%d: disconnect FAILED\n", proc, domid); - } - - return (rv); -} - -static void -idn_unlink_domainset(domainset_t domset, idn_fin_t fintype, - idn_finarg_t finarg, idn_finopt_t finopt, - boardset_t idnset) -{ - int d; - domainset_t offset; - procname_t proc = "idn_unlink_domainset"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - - /* - * Determine subset for which we have - * no active connections. - */ - offset = domset & ~(idn.domset.ds_trans_on | - idn.domset.ds_connected | - idn.domset.ds_trans_off | - idn.domset.ds_relink); - /* - * Determine subset that are really candidates. - * Note that we include those already down the path - * since it's possible a request came in to upgrade - * their fintype (e.g. NORMAL->FORCE_SOFT). - */ - domset &= ~offset; - - if (offset) - idn_update_op(IDNOP_DISCONNECTED, offset, NULL); - - IDN_GLOCK_EXCL(); - if ((finopt == IDNFIN_OPT_RELINK) && (idn.state != IDNGS_DISCONNECT)) { - /* - * Don't add domains already transitioning off. - * If they caught on an earlier Reconfig wave then - * they'll already be in ds_relink anyway. Otherwise, - * once a domain is transition off we can't upgrade - * him to a RELINK. - */ -#ifdef DEBUG - if (idn.domset.ds_hitlist & domset) { - PR_HITLIST("%s: domset=%x, hitlist=%x, trans_off=%x " - "-> relink = %x -> %x\n", - proc, domset, idn.domset.ds_hitlist, - idn.domset.ds_relink, idn.domset.ds_trans_off, - idn.domset.ds_relink | - (domset & ~idn.domset.ds_trans_off)); - } -#endif /* DEBUG */ - - domset &= ~idn.domset.ds_trans_off; - idn.domset.ds_relink |= domset; - } else { - idn.domset.ds_relink &= ~domset; - } - /* - * Update the ds_trans_on/off so we don't waste - * time talking to these folks. - */ - idn.domset.ds_trans_on &= ~domset; - idn.domset.ds_trans_off |= domset; - - if (domset == 0) { - if ((idn.domset.ds_trans_on | - idn.domset.ds_connected | - idn.domset.ds_trans_off | - idn.domset.ds_relink) == 0) { - PR_HITLIST("%s:%x: HITLIST %x -> 0\n", - proc, domset, idn.domset.ds_hitlist); - idn.domset.ds_hitlist = 0; - IDN_GSTATE_TRANSITION(IDNGS_OFFLINE); - } - IDN_GUNLOCK(); - return; - } - IDN_GUNLOCK(); - - for (d = 0; d < MAX_DOMAINS; d++) { - idn_domain_t *dp; - idn_fin_t ftype; - - if (!DOMAIN_IN_SET(domset, d)) - continue; - - dp = &idn_domain[d]; - IDN_DLOCK_EXCL(d); - IDN_HISTORY_LOG(IDNH_RELINK, d, dp->dstate, - idn.domset.ds_relink); - ftype = fintype; - if ((dp->dcpu != IDN_NIL_DCPU) && dp->dhw.dh_boardset) { - /* - * If domain is not in the IDNSET passed - * down then we need to upgrade this to - * hard-force in order to prevent possible - * system failures (arbstop). This is simply - * extra protection beyond that checked by - * the SSP. IDNSET contains the set of boards - * that have a "link" to the local domain, - * including the SMD regs. - */ - if ((idnset & dp->dhw.dh_boardset) == 0) { - PR_PROTO("%s:%d: boardset 0x%x " - "NOT in IDNSET 0x%x\n", - proc, d, dp->dhw.dh_boardset, - idnset); - if (ftype != IDNFIN_FORCE_HARD) - cmn_err(CE_NOTE, - "!IDN: 222: no IDN linkage " - "found (b=0x%x, i=0x%x) " - "upgrading unlink %s to %s", - dp->dhw.dh_boardset, - idnset, idnfin_str[ftype], - idnfin_str[IDNFIN_FORCE_HARD]); - - ftype = IDNFIN_FORCE_HARD; - } else { - PR_PROTO("%s:%d: boardset 0x%x " - "FOUND in IDNSET 0x%x\n", - proc, d, dp->dhw.dh_boardset, - idnset); - } - } - (void) idn_disconnect(d, ftype, finarg, IDNDS_SYNC_TYPE(dp)); - IDN_DUNLOCK(d); - } -} - -/* - * Return w/locks held. - */ -static int -idn_connect(int domid) -{ - idn_xdcargs_t xargs; - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_connect"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - ASSERT(dp->dcpu != IDN_NIL_DCPU); - - if (dp->dstate != IDNDS_CLOSED) { - if (DOMAIN_IN_SET(idn.domset.ds_trans_on | - idn.domset.ds_connected, domid)) { - PR_PROTO("%s:%d: already connected or " - "in-progress\n", proc, domid); - } else { - PR_PROTO("%s:%d: current state (%s) != " - "CLOSED\n", proc, domid, - idnds_str[dp->dstate]); - } - return (-1); - } - - ASSERT(!DOMAIN_IN_SET(idn.domset.ds_connected, domid)); - ASSERT(!DOMAIN_IN_SET(idn.domset.ds_trans_off, domid)); - - dp->dxp = &xphase_nego; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - - (void) idn_xphase_transition(domid, NULL, xargs); - - return (0); -} - -/* - * Return w/locks held. - */ -static int -idn_disconnect(int domid, idn_fin_t fintype, idn_finarg_t finarg, - idn_finsync_t finsync) -{ - int new_masterid, new_cpuid = IDN_NIL_DCPU; - uint_t token; - uint_t finmaster; - idn_xdcargs_t xargs; - idn_finopt_t finopt; - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_disconnect"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (dp->dstate == IDNDS_CLOSED) { - PR_PROTO("%s:%d: already CLOSED\n", proc, domid); - idn_update_op(IDNOP_DISCONNECTED, DOMAINSET(domid), NULL); - return (-1); - } - - /* - * Terminate any outstanding commands that were - * targeted towards this domain. - */ - idn_terminate_cmd(domid, ECANCELED); - - /* - * Terminate any and all retries that may have - * outstanding for this domain. - */ - token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL); - (void) idn_retry_terminate(token); - - /* - * Stop all outstanding message timers for - * this guy. - */ - IDN_MSGTIMER_STOP(domid, 0, 0); - - dp->dxp = &xphase_fin; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - if ((int)dp->dfin < (int)fintype) { - /* - * You can only upgrade a fin type. - * We don't allow it to be downgraded - * as it's too dangerous since some - * state may have been blown away while - * we were fin'ing at a higher level. - */ - IDN_FSTATE_TRANSITION(dp, fintype); - } - - dp->dfin_sync = finsync; - PR_PROTO("%s:%d: disconnect synchronously = %s\n", - proc, domid, (finsync == IDNFIN_SYNC_OFF) ? "OFF" : - (finsync == IDNFIN_SYNC_NO) ? "NO" : "YES"); - - IDN_GLOCK_SHARED(); - if (DOMAIN_IN_SET(idn.domset.ds_relink, domid) && - (idn.state != IDNGS_DISCONNECT)) { - finopt = IDNFIN_OPT_RELINK; - } else { - finopt = IDNFIN_OPT_UNLINK; - PR_HITLIST("%s:%d: HITLIST %x -> %x\n", - proc, domid, idn.domset.ds_hitlist, - idn.domset.ds_hitlist | DOMAINSET(domid)); - DOMAINSET_ADD(idn.domset.ds_hitlist, domid); - } - - CLR_XARGS(xargs); - SET_XARGS_FIN_TYPE(xargs, dp->dfin); - SET_XARGS_FIN_ARG(xargs, finarg); - SET_XARGS_FIN_OPT(xargs, finopt); - SET_XARGS_FIN_DOMSET(xargs, 0); /* unused when msg = 0 */ - new_masterid = IDN_GET_NEW_MASTERID(); - IDN_GUNLOCK(); - if (new_masterid != IDN_NIL_DOMID) - new_cpuid = idn_domain[new_masterid].dcpu; - finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid); - SET_XARGS_FIN_MASTER(xargs, finmaster); - - (void) idn_xphase_transition(domid, NULL, xargs); - - return (0); -} - -static int -idn_next_xstate(idn_xstate_t o_xstate, int err, uint_t msg) -{ - int index; - procname_t proc = "idn_next_xstate"; - - ASSERT(((int)o_xstate >= 0) && ((int)o_xstate <= 4)); - - if (!msg) - index = 0; - else if ((msg & IDNP_MSGTYPE_MASK) == 0) - index = (msg & IDNP_ACK) ? 3 : (msg & IDNP_NACK) ? 4 : -1; - else - index = (msg & IDNP_ACK) ? 2 : - !(msg & IDNP_ACKNACK_MASK) ? 1 : -1; - - if (index == -1) { - STRING(str); - - INUM2STR(msg, str); - PR_PROTO("%s: (msg = 0x%x(%s))\n", proc, msg, str); - return (IDNXS_NIL); - } - - if (err == -1) { - int n_xstate; - /* - * Caller is just interested in querying is this - * is a valid message to receive in the current - * xstate. A return value of IDNXS_NIL indicates - * that it's not. A return value of non-IDNXS_NIL - * indicates it's cool. An invalid message is - * determined by both err & !err states being IDNXS_NIL. - */ - n_xstate = idnxs_state_table[(int)o_xstate][index][0]; - if (n_xstate != IDNXS_NIL) - return (n_xstate); - else - return (idnxs_state_table[(int)o_xstate][index][1]); - } else { - return (idnxs_state_table[(int)o_xstate][index][err ? 1 : 0]); - } -} - -static int -idn_select_candidate(domainset_t master_set) -{ - int d, best_id = IDN_NIL_DOMID; - uint_t best_vote = 0; - idn_domain_t *dp; - procname_t proc = "idn_select_candidate"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - - if (master_set == 0) { - PR_PROTO("%s: %x -> %d\n", proc, master_set, IDN_NIL_DOMID); - return (IDN_NIL_DOMID); - } - - for (d = 0; d < MAX_DOMAINS; d++) { - uint_t vote; - idn_vote_t v; - - if (!DOMAIN_IN_SET(master_set, d)) - continue; - - dp = &idn_domain[d]; - - if ((dp->domid == IDN_NIL_DOMID) || - (dp->dcpu == IDN_NIL_DCPU) || - ((v.ticket = dp->dvote.ticket) == 0)) - continue; - - vote = IDNVOTE_ELECT(v); - - if (vote > best_vote) { - best_vote = vote; - best_id = d; - } - } - - PR_PROTO("%s: %x -> %d\n", proc, master_set, best_id); - - return (best_id); -} - -/* - * If a non-zero value is returned then GLOCK will have been dropped. - * Otherwise, routine returns with all incoming locks still held. - */ -static int -idn_select_master(int domid, int rmasterid, int rcpuid) -{ - char *sel; - int lmasterid, masterid; - int do_reconfig = 0; - int lindex, rindex; - idn_domain_t *ldp, *rdp; - uint_t rvote, lvote; - idn_master_select_t select; - procname_t proc = "idn_select_master"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_GLOCK_IS_EXCL()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - PR_PROTO("%s:%d: lmasterid = %d, rmasterid = %d, rcpuid = %d\n", - proc, domid, IDN_GET_MASTERID(), rmasterid, rcpuid); - - IDN_DLOCK_EXCL(idn.localid); - - ldp = &idn_domain[idn.localid]; - rdp = &idn_domain[domid]; - - /* - * Clear master bits since mastership is derived from - * other information (local/remote idn.masterid/idn.new_masterid) - * and we don't want the vote master bit to confuse matters. - */ - lvote = IDNVOTE_ELECT(ldp->dvote); - rvote = IDNVOTE_ELECT(rdp->dvote); - - lmasterid = IDN_GET_MASTERID(); - - lindex = (lmasterid == IDN_NIL_DOMID) ? MASTER_IS_NONE : - (lmasterid == idn.localid) ? MASTER_IS_LOCAL : - (lmasterid == domid) ? MASTER_IS_REMOTE : - MASTER_IS_OTHER; - - rindex = (rmasterid == IDN_NIL_DOMID) ? MASTER_IS_NONE : - (rmasterid == domid) ? MASTER_IS_REMOTE : - (rmasterid == idn.localid) ? MASTER_IS_LOCAL : - MASTER_IS_OTHER; - - select = master_select_table[lindex][rindex]; - - masterid = IDN_NIL_DOMID; - - /* - * Each case is responsible for dropping DLOCK(localid) - * and GLOCK if it doesn't select a master, unless a - * reconfig is necessary. - */ - switch (select) { - case MASTER_SELECT_VOTE_RCFG: - sel = "VOTE_RECONFIG"; - if (lvote > rvote) { - /* - * If the local domain is the winner then remote - * domain will have to Reconfig. We'll continue - * through the connection process anyway. The - * remote domains will tell us to back-off while - * Reconfigs, but that's okay as we'll keep retrying. - */ - masterid = idn.localid; - } else if (lvote < rvote) { - do_reconfig = 1; - /* - * GLOCK will get dropped once reconfig - * is kicked off. - */ - } else { - cmn_err(CE_WARN, - "IDN: 206: cannot link domains " - "with equal votes (L(%d),R(%d),0x%x)", - idn.localid, domid, rvote); - IDN_GUNLOCK(); - } - IDN_DUNLOCK(idn.localid); - break; - - case MASTER_SELECT_VOTE: - sel = "VOTE"; - if (lvote > rvote) { - masterid = idn.localid; - ldp->dvote.v.master = 1; - rdp->dvote.v.master = 0; - } else if (lvote < rvote) { - masterid = domid; - ldp->dvote.v.master = 0; - rdp->dvote.v.master = 1; - } else { - cmn_err(CE_WARN, - "IDN: 206: cannot link domains " - "with equal votes (L(%d),R(%d),0x%x)", - idn.localid, domid, rvote); - } - ASSERT(IDN_GET_MASTERID() == IDN_NIL_DOMID); - if (masterid != IDN_NIL_DOMID) { - IDN_SET_MASTERID(masterid); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - } else { - IDN_GUNLOCK(); - } - IDN_DUNLOCK(idn.localid); - break; - - case MASTER_SELECT_REMOTE: - sel = "REMOTE"; - masterid = domid; - if (IDN_GET_MASTERID() == IDN_NIL_DOMID) { - IDN_SET_MASTERID(masterid); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - ldp->dvote.v.master = 0; - rdp->dvote.v.master = 1; - } - ASSERT(IDN_GET_MASTERID() == domid); - IDN_DUNLOCK(idn.localid); - break; - - case MASTER_SELECT_LOCAL: - sel = "LOCAL"; - masterid = idn.localid; - if (IDN_GET_MASTERID() == IDN_NIL_DOMID) { - IDN_SET_MASTERID(masterid); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - ldp->dvote.v.master = 1; - rdp->dvote.v.master = 0; - } - ASSERT(IDN_GET_MASTERID() == idn.localid); - IDN_DUNLOCK(idn.localid); - break; - - case MASTER_SELECT_CONNECT: - sel = "CONNECT"; - if (rmasterid == lmasterid) { - /* - * Local and remote have same master, - * let him come onboard. - */ - masterid = lmasterid; - IDN_DUNLOCK(idn.localid); - - } else { - int rv; - - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - IDN_DLOCK_EXCL(rmasterid); - PR_PROTO("%s:%d: attempting connect w/remote " - "master %d\n", - proc, domid, rmasterid); - rv = idn_open_domain(rmasterid, rcpuid, 0); - if (rv == 0) { - (void) idn_connect(rmasterid); - } else if (rv < 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s) failed to " - "open-domain(%d,%d)", - proc, rmasterid, rcpuid); - } else { - /* - * Must already have a connection going. - */ - PR_PROTO("%s:%d: failed " - "idn_open_domain(%d,%d,0) " - "(rv = %d)\n", - proc, domid, rmasterid, - rcpuid, rv); - } - IDN_DUNLOCK(rmasterid); - } - break; - - case MASTER_SELECT_WAIT: - sel = "WAIT"; - /* - * If the remote domain has the same master as the local - * domain then there's no need to wait. - */ - if (rmasterid == lmasterid) { - masterid = lmasterid; - } else { - IDN_GUNLOCK(); - } - IDN_DUNLOCK(idn.localid); - break; - - case MASTER_SELECT_ERROR: - sel = "ERROR"; - /* - * Hit impossible condition. - */ - cmn_err(CE_WARN, - "IDN: 207: local/remote master-id conflict " - "(%d.lmasterid = %d, %d.rmasterid = %d)", - idn.localid, lmasterid, domid, rmasterid); - IDN_GUNLOCK(); - IDN_DUNLOCK(idn.localid); - break; - - default: - cmn_err(CE_WARN, - "IDN: 208: %s: unknown case (%d)", - proc, (int)select); - IDN_GUNLOCK(); - IDN_DUNLOCK(idn.localid); - ASSERT(0); - break; - } - - if (masterid == IDN_NIL_DOMID) { - PR_PROTO("%s:%d: NO MASTER SELECTED (rmstr=%d) sel=%s\n", - proc, domid, rmasterid, sel); - } else { - PR_PROTO("%s:%d: MASTER SELECTED = %d (%s)\n", - proc, domid, masterid, - (masterid == idn.localid) ? "LOCAL" : - (masterid == domid) ? "REMOTE" : "OTHER"); - } - - if (do_reconfig) { - domainset_t dis_set; - - /* - * Local domain already has a master. - * Need to dismantle all connections - * and reestablish one with new master. - */ - IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs, gk_reconfig_last); - - PR_PROTO("%s:%d: RECONFIG new masterid = %d\n", - proc, domid, domid); - - IDN_GSTATE_TRANSITION(IDNGS_RECONFIG); - IDN_SET_NEW_MASTERID(domid); - IDN_GUNLOCK(); - - dis_set = idn.domset.ds_trans_on | idn.domset.ds_connected; - DOMAINSET_DEL(dis_set, domid); - - idn_unlink_domainset(dis_set, IDNFIN_NORMAL, IDNFIN_ARG_NONE, - IDNFIN_OPT_RELINK, BOARDSET_ALL); - } - - return ((masterid == IDN_NIL_DOMID) ? -1 : 0); -} - -/*ARGSUSED1*/ -static void -idn_retry_query(uint_t token, void *arg) -{ - idn_retry_t rtype = IDN_RETRY_TOKEN2TYPE(token); - int d, domid = IDN_RETRY_TOKEN2DOMID(token); - idn_domain_t *dp = &idn_domain[domid]; - idn_synccmd_t sync_cmd; - domainset_t query_set, my_ready_set; - procname_t proc = "idn_retry_query"; - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - - switch (rtype) { - case IDNRETRY_CONQ: - sync_cmd = IDNSYNC_CONNECT; - my_ready_set = idn.domset.ds_ready_on | idn.domset.ds_connected; - my_ready_set &= ~idn.domset.ds_trans_off; - DOMAINSET_ADD(my_ready_set, idn.localid); - break; - - case IDNRETRY_FINQ: - sync_cmd = IDNSYNC_DISCONNECT; - my_ready_set = idn.domset.ds_ready_off | - ~idn.domset.ds_connected; - break; - - default: - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - if (dp->dsync.s_cmd == sync_cmd) - my_ready_set |= dp->dsync.s_set_rdy; - - query_set = idn_sync_register(domid, sync_cmd, 0, IDNSYNC_REG_QUERY); - - PR_PROTO("%s:%d: query_set = 0x%x\n", proc, domid, query_set); - - if (query_set == 0) { - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(query_set, d)) - continue; - - dp = &idn_domain[d]; - if (d != domid) - IDN_DLOCK_EXCL(d); - - if ((dp->dsync.s_cmd == sync_cmd) || - (!dp->dcookie_send && - (rtype == IDNRETRY_CONQ))) { - if (d != domid) - IDN_DUNLOCK(d); - continue; - } - - IDN_SYNC_QUERY_UPDATE(domid, d); - - if (rtype == IDNRETRY_CONQ) - (void) idn_send_con(d, NULL, IDNCON_QUERY, - my_ready_set); - else - (void) idn_send_fin(d, NULL, IDNFIN_QUERY, - IDNFIN_ARG_NONE, IDNFIN_OPT_NONE, my_ready_set, - NIL_FIN_MASTER); - if (d != domid) - IDN_DUNLOCK(d); - } - - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); -} - -static int -idn_send_nego(int domid, idn_msgtype_t *mtp, domainset_t conset) -{ - idn_domain_t *ldp, *dp; - int d, masterid; - uint_t dmask; - uint_t acknack; - uint_t ticket; - idnneg_dset_t dset; - idn_msgtype_t mt; - procname_t proc = "idn_send_nego"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (mtp) { - acknack = mtp->mt_mtype & IDNP_ACKNACK_MASK; - mt.mt_mtype = mtp->mt_mtype; - mt.mt_atype = mtp->mt_atype; - mt.mt_cookie = mtp->mt_cookie; - } else { - acknack = 0; - mt.mt_mtype = IDNP_NEGO; - mt.mt_atype = 0; - mt.mt_cookie = IDN_TIMER_PUBLIC_COOKIE; - } - - IDN_GLOCK_SHARED(); - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - if ((idn.state == IDNGS_RECONFIG) || - ((masterid = IDN_GET_MASTERID()) == IDN_NIL_DOMID)) { - masterid = IDN_GET_NEW_MASTERID(); - if ((masterid == idn.localid) || (masterid == domid)) { - /* - * We only send the new-master "hint" to - * "other" domains. If the new-master is - * ourself or we're talking to the new-master - * then we need to be accurate about our - * real master so that the correct master - * is selected. - */ - masterid = IDN_NIL_DOMID; - } - } - - DOMAINSET_DEL(conset, idn.localid); - DOMAINSET_DEL(conset, domid); - /* - * Exclude domains from conset that are on - * remote domain's hitlist. He's not interested - * in hearing about them. SSP is probably requesting - * such domains be unlinked - will eventually get to - * local domain. - */ - conset &= ~idn.domset.ds_hitlist; - if ((masterid != IDN_NIL_DOMID) && - DOMAIN_IN_SET(idn.domset.ds_hitlist, masterid)) { - PR_PROTO("%s:%d: masterid(%d) on hitlist(0x%x) -> -1\n", - proc, domid, masterid, idn.domset.ds_hitlist); - /* - * Yikes, our chosen master is on the hitlist! - */ - masterid = IDN_NIL_DOMID; - } - - dmask = IDNNEG_DSET_MYMASK(); - IDNNEG_DSET_INIT(dset, dmask); - for (d = 0; d < MAX_DOMAINS; d++) { - int cpuid; - - if (!DOMAIN_IN_SET(conset, d)) - continue; - - if ((cpuid = idn_domain[d].dcpu) == IDN_NIL_DCPU) { - ASSERT(d != masterid); - continue; - } - - IDNNEG_DSET_SET(dset, d, cpuid, dmask); - } - IDNNEG_DSET_SET_MASTER(dset, domid, masterid); - ASSERT((masterid != IDN_NIL_DOMID) ? - (idn_domain[masterid].dcpu != IDN_NIL_DCPU) : 1); - IDN_GUNLOCK(); - - IDN_DLOCK_SHARED(idn.localid); - ticket = IDNVOTE_BASICS(ldp->dvote); - /* - * We just want to send basic vote components without an - * indication of mastership (master bit) since that's primarily - * for local domain's usage. There is more correct master - * indications in the DSET. Recall that if we were in a - * Reconfig we would have transmitted the "new_masterid" - * which might conflict with the local domain's vote.v.master - * bit if he was originally the master prior to the Reconfig. - */ - - PR_PROTO("%s:%d: sending nego%sto (cpu %d) " - "[v=0x%x, cs=0x%x, mstr=%d]\n", - proc, domid, - (acknack & IDNP_ACK) ? "+ack " : - (acknack & IDNP_NACK) ? "+nack " : " ", - dp->dcpu, ticket, conset, masterid); - - IDN_MSGTIMER_START(domid, IDNP_NEGO, 0, - idn_msg_waittime[IDNP_NEGO], &mt.mt_cookie); - - IDNXDC(domid, &mt, ticket, dset[0], dset[1], dset[2]); - - IDN_DUNLOCK(idn.localid); - - return (0); -} - -static int -idn_recv_nego(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs, - ushort_t dcookie) -{ - uint_t msg = mtp->mt_mtype; - idn_msgtype_t mt; - idn_domain_t *dp = &idn_domain[domid]; - idn_xdcargs_t nargs; - procname_t proc = "idn_recv_nego"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - mt.mt_cookie = mtp->mt_cookie; - -#ifdef DEBUG - if (DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) { - PR_HITLIST("%s:%d: dcpu=%d, dstate=%s, msg=%x, " - "hitlist=%x\n", - proc, domid, dp->dcpu, idnds_str[dp->dstate], - msg, idn.domset.ds_hitlist); - } -#endif /* DEBUG */ - - if (dp->dcpu == IDN_NIL_DCPU) { - int cpuid; - uint_t ticket; - /* - * Brandnew link. Need to open a new domain entry. - */ - ticket = GET_XARGS_NEGO_TICKET(xargs); - cpuid = dp->dcpu_last; - ASSERT(VALID_CPUID(cpuid)); - - if (idn_open_domain(domid, cpuid, ticket) != 0) { - PR_PROTO("%s:%d: FAILED to open doamin " - "(ticket = 0x%x)\n", - proc, domid, ticket); - return (-1); - } - } - - if ((msg & IDNP_MSGTYPE_MASK) == IDNP_NEGO) { - PR_PROTO("%s:%d: assigned SEND cookie 0x%x\n", - proc, domid, dcookie); - dp->dcookie_send = dcookie; - } - - if ((dp->dxp == NULL) && IDNDS_IS_CLOSED(dp)) { - dp->dxp = &xphase_nego; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - } else if (dp->dxp != &xphase_nego) { - if (msg & IDNP_MSGTYPE_MASK) { - /* - * If we already have a connection to somebody - * trying to initiate a connection to us, then - * possibly we've awaken from a coma or he did. - * In any case, dismantle current connection - * and attempt to establish a new one. - */ - if (dp->dstate == IDNDS_CONNECTED) { - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, - dp->dstate, idn.domset.ds_relink); - (void) idn_disconnect(domid, IDNFIN_NORMAL, - IDNFIN_ARG_NONE, IDNFIN_SYNC_YES); - } else { - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - - CLR_XARGS(nargs); - - if (DOMAIN_IN_SET(idn.domset.ds_hitlist, - domid)) { - SET_XARGS_NACK_TYPE(nargs, - IDNNACK_EXIT); - } else { - int new_masterid; - int new_cpuid = IDN_NIL_DCPU; - - SET_XARGS_NACK_TYPE(nargs, - IDNNACK_RETRY); - IDN_GLOCK_SHARED(); - new_masterid = IDN_GET_NEW_MASTERID(); - if (new_masterid == IDN_NIL_DOMID) - new_masterid = - IDN_GET_MASTERID(); - if (new_masterid != IDN_NIL_DOMID) { - idn_domain_t *mdp; - - mdp = &idn_domain[new_masterid]; - new_cpuid = mdp->dcpu; - } - SET_XARGS_NACK_ARG1(nargs, - new_masterid); - SET_XARGS_NACK_ARG2(nargs, new_cpuid); - IDN_GUNLOCK(); - } - idn_send_acknack(domid, &mt, nargs); - } - } - return (0); - } - - (void) idn_xphase_transition(domid, mtp, xargs); - - return (0); -} - -/*ARGSUSED1*/ -static void -idn_retry_nego(uint_t token, void *arg) -{ - int domid = IDN_RETRY_TOKEN2DOMID(token); - int new_masterid; - idn_domain_t *dp = &idn_domain[domid]; - idn_xdcargs_t xargs; - procname_t proc = "idn_retry_nego"; - - ASSERT(IDN_RETRY_TOKEN2TYPE(token) == IDNRETRY_NEGO); - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - - if (dp->dxp != &xphase_nego) { - STRING(str); - -#ifdef DEBUG - if (dp->dxp) { - INUM2STR(dp->dxp->xt_msgtype, str); - } -#endif /* DEBUG */ - - PR_PROTO("%s:%d: dxp(%s) != NEGO...bailing...\n", - proc, domid, dp->dxp ? str : "NULL"); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - if (dp->dxstate != IDNXS_PEND) { - PR_PROTO("%s:%d: xstate(%s) != %s...bailing\n", - proc, domid, idnxs_str[dp->dxstate], - idnxs_str[IDNXS_PEND]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - IDN_GLOCK_SHARED(); - if (idn.state == IDNGS_RECONFIG) { - /* - * Have to try again later after - * reconfig has completed. - */ - PR_PROTO("%s:%d: reconfig in-progress...try later\n", - proc, domid); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[IDNP_NEGO]); - IDN_GUNLOCK(); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - new_masterid = IDN_GET_NEW_MASTERID(); - if ((idn.state == IDNGS_CONNECT) && - (new_masterid != IDN_NIL_DOMID) && - (domid != new_masterid) && - (idn.localid != new_masterid)) { - /* - * We have a new master pending and this - * guy isn't it. Wait until the local domain - * has a chance to connect with the new - * master before going forward with this - * guy. - */ - PR_PROTO("%s:%d: waiting for connect to new master %d\n", - proc, domid, IDN_GET_NEW_MASTERID()); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[IDNP_NEGO]); - IDN_GUNLOCK(); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - IDN_GUNLOCK(); - - (void) idn_xphase_transition(domid, NULL, xargs); - - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); -} - -static int -idn_check_nego(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - int d, new_masterid, masterid; - int cpuid, m_cpuid = -1; - uint_t dmask; - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_domain_t *dp, *ldp; - domainset_t con_set, pending_set; - idnneg_dset_t dset; - procname_t proc = "idn_check_nego"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - if (msg & IDNP_NACK) { - if (GET_XARGS_NACK_TYPE(xargs) == IDNNACK_EXIT) { - PR_HITLIST("%s:%d(%s): (msg=%x) EXIT received, " - "adding to hitlist %x -> %x\n", - proc, domid, idnds_str[dp->dstate], msg, - idn.domset.ds_hitlist, - idn.domset.ds_hitlist | DOMAINSET(domid)); - - DOMAINSET_ADD(idn.domset.ds_hitlist, domid); - return (-1); - } else { - return (0); - } - } - - if (DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) { - PR_HITLIST("%s:%d(%s): (msg=%x) domain in hitlist (%x) - " - "exiting phase\n", - proc, domid, idnds_str[dp->dstate], msg, - idn.domset.ds_hitlist); - return (-1); - } - - if ((dp->dstate == IDNDS_NEGO_PEND) && (msg & IDNP_MSGTYPE_MASK) && - (msg & IDNP_ACK)) /* nego+ack */ - return (1); - - dmask = (uint_t)-1; - - IDN_GLOCK_EXCL(); - if (idn.state == IDNGS_DISCONNECT) { - PR_PROTO("%s:%d: DISCONNECT in-progress >>> EXIT\n", - proc, domid); - IDN_GUNLOCK(); - return (-1); - } else if (idn.state == IDNGS_OFFLINE) { - IDN_GSTATE_TRANSITION(IDNGS_CONNECT); - IDN_PREP_HWINIT(); - IDN_DLOCK_EXCL(idn.localid); - ldp->dvote.v.connected = 0; - IDN_DUNLOCK(idn.localid); - } - - if (!DOMAIN_IN_SET(idn.domset.ds_trans_on, domid)) { - DOMAINSET_ADD(idn.domset.ds_trans_on, domid); - IDN_HISTORY_LOG(IDNH_NEGO, domid, - idn.domset.ds_trans_on, - idn.domset.ds_connected); - } - - switch (idn.state) { - case IDNGS_RECONFIG: - PR_PROTO("%s:%d: RECONFIG in-progress >>> RETRY\n", - proc, domid); - IDN_GUNLOCK(); - return (1); - - case IDNGS_CONNECT: - new_masterid = IDN_GET_NEW_MASTERID(); - if ((new_masterid != IDN_NIL_DOMID) && - (domid != new_masterid) && - (idn.localid != new_masterid)) { - PR_PROTO("%s:%d: waiting for connect to " - "new master %d\n", - proc, domid, IDN_GET_NEW_MASTERID()); - IDN_GUNLOCK(); - return (1); - } - break; - - default: - break; - } - - ASSERT((idn.state == IDNGS_CONNECT) || (idn.state == IDNGS_ONLINE)); - - con_set = 0; - - if (msg) { - idn_domain_t *mdp; - idn_vote_t vote; - - vote.ticket = GET_XARGS_NEGO_TICKET(xargs); - /* - * Sender should note have set master bit, - * but just in case clear it so local domain - * doesn't get confused. - */ - vote.v.master = 0; - dp->dvote.ticket = vote.ticket; - GET_XARGS_NEGO_DSET(xargs, dset); - /*LINTED*/ - IDNNEG_DSET_GET_MASK(dset, domid, dmask); - IDNNEG_DSET_GET_MASTER(dset, new_masterid); - if (new_masterid == IDNNEG_NO_MASTER) { - new_masterid = IDN_NIL_DOMID; - } else { - /* - * Remote domain has a master. Find - * his cpuid in the dset. We may need - * it to initiate a connection. - */ - if (new_masterid == domid) { - m_cpuid = dp->dcpu; - } else { - IDNNEG_DSET_GET(dset, new_masterid, m_cpuid, - dmask); - if (m_cpuid == -1) { - /* - * Something is bogus if remote domain - * is reporting a valid masterid, but - * doesn't have the cpuid for it. - */ - cmn_err(CE_WARN, - "IDN: 209: remote domain (ID " - "%d, CPU %d) reporting master " - "(ID %d) without CPU ID", - domid, dp->dcpu, new_masterid); - DOMAINSET_ADD(idn.domset.ds_hitlist, - domid); - IDN_GUNLOCK(); - return (-1); - } - } - } - - for (d = 0; d < MAX_DOMAINS; d++) { - if ((d == idn.localid) || (d == domid)) - continue; - IDNNEG_DSET_GET(dset, d, cpuid, dmask); - if (cpuid != -1) { - DOMAINSET_ADD(con_set, d); - } - } - -#ifdef DEBUG - if (idn.domset.ds_hitlist) { - PR_HITLIST("%s:%d: con_set %x -> %x (hitlist = %x)\n", - proc, domid, con_set, - con_set & ~idn.domset.ds_hitlist, - idn.domset.ds_hitlist); - } -#endif /* DEBUG */ - - con_set &= ~idn.domset.ds_hitlist; - - ASSERT(!DOMAIN_IN_SET(con_set, idn.localid)); - ASSERT(!DOMAIN_IN_SET(con_set, domid)); - - if ((new_masterid != IDN_NIL_DOMID) && - DOMAIN_IN_SET(idn.domset.ds_hitlist, new_masterid)) { - PR_HITLIST("%s:%d: new_mstr %d -> -1 (hitlist = %x)\n", - proc, domid, new_masterid, - idn.domset.ds_hitlist); - IDN_GUNLOCK(); - return (1); - } - - if (idn_select_master(domid, new_masterid, m_cpuid) < 0) { - /* - * Returns w/GLOCK dropped if error. - */ - return (1); - } - - masterid = IDN_GET_MASTERID(); - ASSERT(masterid != IDN_NIL_DOMID); - - if (idn.state == IDNGS_CONNECT) { - /* - * This is the initial connection for - * the local domain. - */ - IDN_DLOCK_EXCL(idn.localid); - - if (masterid == idn.localid) { - if (idn_master_init() < 0) { - cmn_err(CE_WARN, - "IDN: 210: failed to init " - "MASTER context"); - ldp->dvote.v.master = 0; - IDN_DUNLOCK(idn.localid); - IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT); - IDN_SET_MASTERID(IDN_NIL_DOMID); - IDN_GUNLOCK(); - return (-1); - } - DSLAB_LOCK_EXCL(idn.localid); - ldp->dslab_state = DSLAB_STATE_LOCAL; - DSLAB_UNLOCK(idn.localid); - ldp->dvote.v.connected = 1; - } else { - /* - * Either the remote domain is the - * master or its a new slave trying - * to connect to us. We can't allow - * further progress until we've - * sync'd up with the master. - */ - if (masterid != domid) { - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - return (1); - } - DSLAB_LOCK_EXCL(idn.localid); - ldp->dslab_state = DSLAB_STATE_REMOTE; - DSLAB_UNLOCK(idn.localid); - } - IDN_DUNLOCK(idn.localid); - /* - * We've sync'd up with the new master. - */ - IDN_GSTATE_TRANSITION(IDNGS_ONLINE); - } - - mdp = &idn_domain[masterid]; - - if ((masterid != domid) && !IDNDS_CONFIG_DONE(mdp)) { - /* - * We can't progress any further with - * other domains until we've exchanged all - * the necessary CFG info with the master, - * i.e. until we have a mailbox area from - * which we can allocate mailboxes to - * other domains. - */ - PR_PROTO("%s:%d: still exchanging CFG " - "w/master(%d)\n", proc, domid, masterid); - IDN_GUNLOCK(); - return (1); - } - - DSLAB_LOCK_EXCL(domid); - dp->dslab_state = ldp->dslab_state; - DSLAB_UNLOCK(domid); - if (idn.state != IDNGS_ONLINE) { - IDN_GSTATE_TRANSITION(IDNGS_ONLINE); - } - } - - IDN_GUNLOCK(); - - pending_set = con_set; - pending_set &= ~(idn.domset.ds_trans_on | idn.domset.ds_connected); - idn.domset.ds_trans_on |= pending_set; - - con_set |= idn.domset.ds_trans_on | idn.domset.ds_connected; - con_set &= ~idn.domset.ds_trans_off; - DOMAINSET_ADD(con_set, idn.localid); - - if (dp->dsync.s_cmd != IDNSYNC_CONNECT) { - idn_sync_exit(domid, IDNSYNC_DISCONNECT); - idn_sync_enter(domid, IDNSYNC_CONNECT, - con_set, DOMAINSET(idn.localid), idn_xstate_transfunc, - (void *)IDNP_CON); - } - - /* - * Get this domain registered as an expected domain on - * the remaining domains in the CONNECT synchronization. - */ - (void) idn_sync_register(domid, IDNSYNC_CONNECT, 0, IDNSYNC_REG_NEW); - - /* - * Note that if (msg == 0), i.e. then there will be - * no dset and also pending_set will be 0. - * So, the following loop will never attempt to - * look at the dset unless (msg != 0), implying - * that we've been through the initial code above - * and have initialized dmask. - */ - ASSERT(pending_set ? (dmask != (uint_t)-1) : 1); - - for (d = 0; d < MAX_DOMAINS; d++) { - int rv; - - if (!DOMAIN_IN_SET(pending_set, d)) - continue; - - ASSERT((d != idn.localid) && (d != domid)); - - dp = &idn_domain[d]; - - IDNNEG_DSET_GET(dset, d, cpuid, dmask); - if (cpuid == -1) { - PR_PROTO("%s:%d: failed to get cpuid from dset " - "for domain %d (pset = 0x%x)\n", - proc, domid, d, pending_set); - DOMAINSET_DEL(idn.domset.ds_trans_on, d); - continue; - } - - IDN_DLOCK_EXCL(d); - if ((rv = idn_open_domain(d, cpuid, 0)) != 0) { - PR_PROTO("%s:%d: failed " - "idn_open_domain(%d,%d,0) (rv = %d)\n", - proc, domid, d, cpuid, rv); - if (rv < 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s) failed to " - "open-domain(%d,%d)", - proc, d, cpuid); - DOMAINSET_DEL(idn.domset.ds_trans_on, d); - } else if (DOMAIN_IN_SET(idn.domset.ds_trans_off, d)) { - /* - * We've requested to connect to a domain - * from which we're disconnecting. We - * better mark this guy for relinking. - */ - DOMAINSET_ADD(idn.domset.ds_relink, d); - IDN_HISTORY_LOG(IDNH_RELINK, d, dp->dstate, - idn.domset.ds_relink); - } - IDN_DUNLOCK(d); - continue; - } - - (void) idn_connect(d); - - IDN_DUNLOCK(d); - } - - return (0); -} - -/*ARGSUSED*/ -static void -idn_action_nego_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_msgtype_t mt; - domainset_t con_set; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - con_set = idn.domset.ds_trans_on | idn.domset.ds_connected; - con_set &= ~idn.domset.ds_trans_off; - - if (!msg) { - (void) idn_send_nego(domid, NULL, con_set); - } else { - mt.mt_mtype = IDNP_NEGO | IDNP_ACK; - mt.mt_atype = 0; - mt.mt_cookie = mtp->mt_cookie; - (void) idn_send_nego(domid, &mt, con_set); - } -} - -/*ARGSUSED*/ -static void -idn_error_nego(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - int new_masterid, new_cpuid; - int retry = 1; - uint_t msg = mtp ? mtp->mt_mtype : 0; - uint_t token; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) { - idn_nack_t nack; - - nack = GET_XARGS_NACK_TYPE(xargs); - switch (nack) { - case IDNNACK_RETRY: - new_masterid = (int)GET_XARGS_NACK_ARG1(xargs); - new_cpuid = (int)GET_XARGS_NACK_ARG2(xargs); - break; - - case IDNNACK_EXIT: - retry = 0; - /*FALLTHROUGH*/ - - default: - new_masterid = IDN_NIL_DOMID; - new_cpuid = IDN_NIL_DCPU; - break; - } - idn_nego_cleanup_check(domid, new_masterid, new_cpuid); - } - - if (msg & IDNP_MSGTYPE_MASK) { - idn_msgtype_t mt; - idn_xdcargs_t nargs; - - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - mt.mt_cookie = mtp->mt_cookie; - CLR_XARGS(nargs); - SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY); - IDN_GLOCK_SHARED(); - new_masterid = IDN_GET_NEW_MASTERID(); - if (new_masterid == IDN_NIL_DOMID) - new_masterid = IDN_GET_MASTERID(); - if (new_masterid != IDN_NIL_DOMID) - new_cpuid = idn_domain[new_masterid].dcpu; - else - new_cpuid = IDN_NIL_DCPU; - SET_XARGS_NACK_ARG1(nargs, new_masterid); - SET_XARGS_NACK_ARG2(nargs, new_cpuid); - IDN_GUNLOCK(); - idn_send_acknack(domid, &mt, nargs); - } - - if (retry) { - token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_NEGO]); - } else { - DOMAINSET_DEL(idn.domset.ds_relink, domid); - IDN_RESET_COOKIES(domid); - (void) idn_disconnect(domid, IDNFIN_NORMAL, IDNFIN_ARG_NONE, - IDNDS_SYNC_TYPE(&idn_domain[domid])); - } -} - -/*ARGSUSED*/ -static void -idn_action_nego_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - domainset_t conset; - idn_msgtype_t mt; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - mt.mt_cookie = mtp ? mtp->mt_cookie : 0; - - conset = idn.domset.ds_trans_on | idn.domset.ds_connected; - conset &= ~idn.domset.ds_trans_off; - - if ((msg & IDNP_ACKNACK_MASK) == 0) { - /* - * nego - */ - mt.mt_mtype = IDNP_NEGO | IDNP_ACK; - mt.mt_atype = 0; - (void) idn_send_nego(domid, &mt, conset); - } else if (msg & IDNP_MSGTYPE_MASK) { - int d; - idn_xdcargs_t nargs; - idnneg_dset_t dset; - uint_t dmask; - idn_vote_t vote; - - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = msg; - DOMAINSET_DEL(conset, idn.localid); - DOMAINSET_DEL(conset, domid); - - dmask = IDNNEG_DSET_MYMASK(); - IDNNEG_DSET_INIT(dset, dmask); - for (d = 0; d < MAX_DOMAINS; d++) { - int cpuid; - - if (!DOMAIN_IN_SET(conset, d)) - continue; - - if ((cpuid = idn_domain[d].dcpu) == IDN_NIL_DCPU) - continue; - - IDNNEG_DSET_SET(dset, d, cpuid, dmask); - } - IDNNEG_DSET_SET_MASTER(dset, domid, IDN_GET_MASTERID()); - ASSERT((IDN_GET_MASTERID() != IDN_NIL_DOMID) ? - (idn_domain[IDN_GET_MASTERID()].dcpu != IDN_NIL_DCPU) : 1); - vote.ticket = idn_domain[idn.localid].dvote.ticket; - vote.v.master = 0; - CLR_XARGS(nargs); - SET_XARGS_NEGO_TICKET(nargs, vote.ticket); - SET_XARGS_NEGO_DSET(nargs, dset); - /* - * nego+ack - */ - idn_send_acknack(domid, &mt, nargs); - } else { - uint_t token; - int new_masterid, new_cpuid; - int retry = 1; - idn_nack_t nack; - /* - * nack - retry - * - * It's possible if we've made it this far that - * we may have already chosen a master and this - * dude might be it! If it is we need to clean up. - */ - nack = GET_XARGS_NACK_TYPE(xargs); - switch (nack) { - case IDNNACK_RETRY: - new_masterid = (int)GET_XARGS_NACK_ARG1(xargs); - new_cpuid = (int)GET_XARGS_NACK_ARG2(xargs); - break; - - case IDNNACK_EXIT: - retry = 0; - /*FALLTHROUGH*/ - - default: - new_masterid = IDN_NIL_DOMID; - new_cpuid = IDN_NIL_DCPU; - break; - } - - idn_nego_cleanup_check(domid, new_masterid, new_cpuid); - - if (retry) { - token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_NEGO]); - } else { - DOMAINSET_DEL(idn.domset.ds_relink, domid); - IDN_RESET_COOKIES(domid); - (void) idn_disconnect(domid, IDNFIN_NORMAL, - IDNFIN_ARG_NONE, - IDNDS_SYNC_TYPE(&idn_domain[domid])); - } - } -} - -/*ARGSUSED*/ -static void -idn_action_nego_rcvd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) { - uint_t token; - int new_masterid, new_cpuid; - int retry = 1; - idn_nack_t nack; - /* - * nack - retry. - * - * At this stage of receiving a nack we need to - * check whether we need to start over again with - * selecting a new master. - */ - nack = GET_XARGS_NACK_TYPE(xargs); - switch (nack) { - case IDNNACK_RETRY: - new_masterid = (int)GET_XARGS_NACK_ARG1(xargs); - new_cpuid = (int)GET_XARGS_NACK_ARG2(xargs); - break; - - case IDNNACK_EXIT: - retry = 0; - /*FALLTHROUGH*/ - - default: - new_masterid = IDN_NIL_DOMID; - new_cpuid = IDN_NIL_DCPU; - break; - } - - idn_nego_cleanup_check(domid, new_masterid, new_cpuid); - - if (retry) { - token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_NEGO]); - } else { - DOMAINSET_DEL(idn.domset.ds_relink, domid); - IDN_RESET_COOKIES(domid); - (void) idn_disconnect(domid, IDNFIN_NORMAL, - IDNFIN_ARG_NONE, - IDNDS_SYNC_TYPE(&idn_domain[domid])); - } - } -} - -static void -idn_final_nego(int domid) -{ - idn_domain_t *dp = &idn_domain[domid]; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - (void) idn_retry_terminate(IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO)); - - ASSERT(dp->dstate == IDNDS_CONFIG); - - dp->dxp = NULL; - IDN_XSTATE_TRANSITION(dp, IDNXS_NIL); - - idn_send_config(domid, 1); -} - -/* - */ -/*ARGSUSED1*/ -static void -idn_exit_nego(int domid, uint_t msgtype) -{ - idn_domain_t *dp; - idn_fin_t fintype; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - - fintype = msgtype ? IDNFIN_NORMAL : IDNFIN_FORCE_HARD; - - (void) idn_retry_terminate(IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO)); - - ASSERT(!DOMAIN_IN_SET(idn.domset.ds_connected, domid)); - ASSERT(!DOMAIN_IN_SET(idn.domset.ds_ready_on, domid)); - ASSERT(dp->dxp == &xphase_nego); - - idn_nego_cleanup_check(domid, IDN_NIL_DOMID, IDN_NIL_DCPU); - - IDN_GLOCK_SHARED(); - if ((idn.state != IDNGS_DISCONNECT) && - !DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) { - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate, - idn.domset.ds_relink); - } else { - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), NULL); - DOMAINSET_DEL(idn.domset.ds_relink, domid); - } - IDN_GUNLOCK(); - /* - * Reset send cookie to 0 so that receiver does not validate - * cookie. This is necessary since at this early stage it's - * possible we may not have exchanged appropriate cookies. - */ - IDN_RESET_COOKIES(domid); - (void) idn_disconnect(domid, fintype, IDNFIN_ARG_NONE, - IDNDS_SYNC_TYPE(dp)); -} - -static void -idn_nego_cleanup_check(int domid, int new_masterid, int new_cpuid) -{ - idn_domain_t *ldp, *dp; - procname_t proc = "idn_nego_cleanup_check"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - IDN_GLOCK_EXCL(); - - if (((idn.state == IDNGS_ONLINE) && !idn.domset.ds_connected) || - (idn.state == IDNGS_CONNECT)) { - domainset_t trans_on; - int masterid; - int retry_domid = IDN_NIL_DOMID; - int rv; - - IDN_DLOCK_EXCL(idn.localid); - masterid = (idn.state == IDNGS_ONLINE) ? - IDN_GET_MASTERID() : IDN_GET_NEW_MASTERID(); - trans_on = idn.domset.ds_trans_on; - DOMAINSET_DEL(trans_on, domid); - if (trans_on == 0) { - int d; - domainset_t relink = idn.domset.ds_relink; - /* - * This was the only guy we were trying - * to connect with. - */ - ASSERT((idn.state == IDNGS_ONLINE) ? - ((idn.localid == masterid) || - (domid == masterid)) : 1); - if (idn.localid == masterid) - idn_master_deinit(); - ldp->dvote.v.connected = 0; - ldp->dvote.v.master = 0; - dp->dvote.v.master = 0; - IDN_SET_MASTERID(IDN_NIL_DOMID); - IDN_SET_NEW_MASTERID(new_masterid); - IDN_GSTATE_TRANSITION(IDNGS_CONNECT); - IDN_PREP_HWINIT(); - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - /* - * If there's a new master available then - * just try and relink with him unless - * it's ourself. - */ - if ((new_masterid != IDN_NIL_DOMID) && - (new_masterid != idn.localid) && - (new_masterid != domid)) { - IDN_DLOCK_EXCL(new_masterid); - rv = idn_open_domain(new_masterid, - new_cpuid, 0); - if (rv < 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s) failed to " - "open-domain(%d,%d)", - proc, new_masterid, new_cpuid); - IDN_GLOCK_EXCL(); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - IDN_GUNLOCK(); - } else { - relink = DOMAINSET(new_masterid); - } - IDN_DUNLOCK(new_masterid); - } - DOMAINSET_DEL(relink, domid); - if (relink) - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(relink, d)) - continue; - retry_domid = d; - break; - } - } else if (domid == masterid) { - /* - * There are other domains we were trying - * to connect to. As long as the chosen - * master was somebody other then this - * domain that nack'd us, life is cool, but - * if it was this remote domain we'll need - * to start over. - */ - IDN_DUNLOCK(idn.localid); - dp->dvote.v.master = 0; - IDN_SET_MASTERID(IDN_NIL_DOMID); - IDN_SET_NEW_MASTERID(new_masterid); - - if (idn.state == IDNGS_ONLINE) { - IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs, - gk_reconfig_last); - IDN_GSTATE_TRANSITION(IDNGS_RECONFIG); - IDN_GUNLOCK(); - idn_unlink_domainset(trans_on, IDNFIN_NORMAL, - IDNFIN_ARG_NONE, - IDNFIN_OPT_RELINK, - BOARDSET_ALL); - } else if ((new_masterid != IDN_NIL_DOMID) && - (new_masterid != idn.localid) && - (new_masterid != domid) && - !DOMAIN_IN_SET(trans_on, new_masterid)) { - IDN_GUNLOCK(); - IDN_DLOCK_EXCL(new_masterid); - rv = idn_open_domain(new_masterid, - new_cpuid, 0); - IDN_GLOCK_EXCL(); - IDN_DUNLOCK(new_masterid); - if (rv < 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s) failed to " - "open-domain(%d,%d)", - proc, new_masterid, - new_cpuid); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - new_masterid = IDN_NIL_DOMID; - } else { - retry_domid = new_masterid; - } - IDN_GUNLOCK(); - } else { - IDN_GUNLOCK(); - } - } else { - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - } - if (retry_domid != IDN_NIL_DOMID) { - uint_t token; - idn_domain_t *rdp = &idn_domain[retry_domid]; - - IDN_DLOCK_EXCL(retry_domid); - rdp->dxp = &xphase_nego; - IDN_XSTATE_TRANSITION(rdp, IDNXS_PEND); - IDN_DUNLOCK(retry_domid); - token = IDN_RETRY_TOKEN(retry_domid, IDNRETRY_NEGO); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_NEGO]); - } - } else { - IDN_GUNLOCK(); - } -} - -static int -idn_send_con(int domid, idn_msgtype_t *mtp, idn_con_t contype, domainset_t - conset) -{ - idn_msgtype_t mt; - uint_t acknack; - procname_t proc = "idn_send_con"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (mtp) { - acknack = mtp->mt_mtype & IDNP_ACKNACK_MASK; - mt.mt_mtype = mtp->mt_mtype; - mt.mt_atype = mtp->mt_atype; - mt.mt_cookie = mtp->mt_cookie; - } else { - acknack = 0; - mt.mt_mtype = IDNP_CON; - mt.mt_atype = 0; - /* - * For simple CON queries we want a unique - * timer assigned. For others, they - * effectively share one. - */ - if (contype == IDNCON_QUERY) - mt.mt_cookie = 0; - else - mt.mt_cookie = IDN_TIMER_PUBLIC_COOKIE; - } - - ASSERT((contype == IDNCON_QUERY) ? idn_domain[domid].dcookie_send : 1); - - PR_PROTO("%s:%d: sending con%sto (cpu %d) [ct=%s, cs=0x%x]\n", - proc, domid, - (acknack & IDNP_ACK) ? "+ack " : - (acknack & IDNP_NACK) ? "+nack " : " ", - idn_domain[domid].dcpu, - idncon_str[contype], conset); - - IDN_MSGTIMER_START(domid, IDNP_CON, (ushort_t)contype, - idn_msg_waittime[IDNP_CON], &mt.mt_cookie); - - IDNXDC(domid, &mt, (uint_t)contype, (uint_t)conset, 0, 0); - - return (0); -} - -/* - * Must leave w/DLOCK dropped and SYNC_LOCK held. - */ -static int -idn_recv_con(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - uint_t msgarg = mtp ? mtp->mt_atype : 0; - idn_con_t contype; - domainset_t my_ready_set, ready_set; - idn_msgtype_t mt; - idn_domain_t *dp = &idn_domain[domid]; - idn_xdcargs_t aargs; - procname_t proc = "idn_recv_con"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - mt.mt_cookie = mtp ? mtp->mt_cookie : 0; - - contype = GET_XARGS_CON_TYPE(xargs); - ready_set = GET_XARGS_CON_DOMSET(xargs); - - CLR_XARGS(aargs); - - if (!(msg & IDNP_NACK) && (contype == IDNCON_QUERY)) { - domainset_t query_set; - - query_set = idn_sync_register(domid, IDNSYNC_CONNECT, - ready_set, IDNSYNC_REG_REG); - - my_ready_set = idn.domset.ds_connected | idn.domset.ds_ready_on; - my_ready_set &= ~idn.domset.ds_trans_off; - DOMAINSET_ADD(my_ready_set, idn.localid); - - if (msg & IDNP_MSGTYPE_MASK) { - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = IDNP_CON; - SET_XARGS_CON_TYPE(aargs, contype); - SET_XARGS_CON_DOMSET(aargs, my_ready_set); - idn_send_acknack(domid, &mt, aargs); - } - - if (query_set) { - uint_t token; - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_CONQ); - idn_retry_submit(idn_retry_query, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_CONQ]); - } - - return (0); - } - - if (dp->dxp == NULL) { - STRING(mstr); - STRING(lstr); - /* - * Must have received an inappropriate error - * message as we should already be registered - * by the time we reach here. - */ - INUM2STR(msg, mstr); - INUM2STR(msgarg, lstr); - - PR_PROTO("%s:%d: ERROR: NOT YET REGISTERED (%s/%s)\n", - proc, domid, mstr, lstr); - - if (msg & IDNP_MSGTYPE_MASK) { - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - SET_XARGS_NACK_TYPE(aargs, IDNNACK_RETRY); - idn_send_acknack(domid, &mt, aargs); - } - - return (-1); - } - - (void) idn_xphase_transition(domid, mtp, xargs); - - return (0); -} - -/*ARGSUSED1*/ -static void -idn_retry_con(uint_t token, void *arg) -{ - int domid = IDN_RETRY_TOKEN2DOMID(token); - idn_domain_t *dp = &idn_domain[domid]; - idn_xdcargs_t xargs; - procname_t proc = "idn_retry_con"; - - ASSERT(IDN_RETRY_TOKEN2TYPE(token) == IDNRETRY_CON); - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - - if (dp->dxp != &xphase_con) { - STRING(str); - -#ifdef DEBUG - if (dp->dxp) { - INUM2STR(dp->dxp->xt_msgtype, str); - } -#endif /* DEBUG */ - - PR_PROTO("%s:%d: dxp(%s) != CON...bailing...\n", - proc, domid, dp->dxp ? str : "NULL"); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - if ((dp->dsync.s_cmd != IDNSYNC_CONNECT) || - (dp->dxstate != IDNXS_PEND)) { - PR_PROTO("%s:%d: cmd (%s) and/or xstate (%s) not " - "expected (%s/%s)\n", - proc, domid, idnsync_str[dp->dsync.s_cmd], - idnxs_str[dp->dxstate], idnsync_str[IDNSYNC_CONNECT], - idnxs_str[IDNXS_PEND]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - (void) idn_xphase_transition(domid, NULL, xargs); - - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); -} - -static int -idn_check_con(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - int ready; - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_domain_t *dp = &idn_domain[domid]; - domainset_t ready_set, my_ready_set, query_set; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) - return (0); - - if ((dp->dstate == IDNDS_CON_PEND) && - (msg & IDNP_MSGTYPE_MASK) && (msg & IDNP_ACK)) /* con+ack */ - return (1); - - if (msg == 0) { - ready_set = idn.domset.ds_connected & - ~idn.domset.ds_trans_off; - } else { - ready_set = GET_XARGS_CON_DOMSET(xargs); - DOMAINSET_ADD(idn.domset.ds_ready_on, domid); - } - - DOMAINSET_ADD(ready_set, idn.localid); - - query_set = idn_sync_register(domid, IDNSYNC_CONNECT, - ready_set, IDNSYNC_REG_REG); - /* - * No need to query this domain as he's already - * in the CON sequence. - */ - DOMAINSET_DEL(query_set, domid); - - ready = (dp->dsync.s_set_exp == dp->dsync.s_set_rdy) ? 1 : 0; - if (ready) { - DOMAINSET_DEL(idn.domset.ds_ready_on, domid); - DOMAINSET_ADD(idn.domset.ds_connected, domid); - } - - if (query_set) { - int d; - - my_ready_set = idn.domset.ds_ready_on | - idn.domset.ds_connected; - my_ready_set &= ~idn.domset.ds_trans_off; - DOMAINSET_ADD(my_ready_set, idn.localid); - - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(query_set, d)) - continue; - - dp = &idn_domain[d]; - - IDN_DLOCK_EXCL(d); - if ((dp->dsync.s_cmd == IDNSYNC_CONNECT) || - !dp->dcookie_send) { - IDN_DUNLOCK(d); - continue; - } - - IDN_SYNC_QUERY_UPDATE(domid, d); - - (void) idn_send_con(d, NULL, IDNCON_QUERY, - my_ready_set); - IDN_DUNLOCK(d); - } - } - - return (!msg ? 0 : (ready ? 0 : 1)); -} - -/*ARGSUSED2*/ -static void -idn_error_con(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t token; - uint_t msg = mtp ? mtp->mt_mtype : 0; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_MSGTYPE_MASK) { - idn_msgtype_t mt; - idn_xdcargs_t nargs; - - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - mt.mt_cookie = mtp->mt_cookie; - CLR_XARGS(nargs); - SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY); - idn_send_acknack(domid, &mt, nargs); - } - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON); - idn_retry_submit(idn_retry_con, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_CON]); -} - -/*ARGSUSED*/ -static void -idn_action_con_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_domain_t *dp = &idn_domain[domid]; - idn_msgtype_t mt; - domainset_t my_ready_set; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_on | - idn.domset.ds_connected; - my_ready_set &= ~idn.domset.ds_trans_off; - DOMAINSET_ADD(my_ready_set, idn.localid); - - if (!msg) { - (void) idn_send_con(domid, NULL, IDNCON_NORMAL, my_ready_set); - } else { - mt.mt_mtype = IDNP_CON | IDNP_ACK; - mt.mt_atype = 0; - mt.mt_cookie = mtp->mt_cookie; - (void) idn_send_con(domid, &mt, IDNCON_NORMAL, my_ready_set); - } -} - -static void -idn_action_con_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_domain_t *dp = &idn_domain[domid]; - idn_con_t contype; - domainset_t my_ready_set; - idn_msgtype_t mt; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - mt.mt_cookie = mtp ? mtp->mt_cookie : 0; - - my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_on | - idn.domset.ds_connected; - my_ready_set &= ~idn.domset.ds_trans_off; - DOMAINSET_ADD(my_ready_set, idn.localid); - - contype = GET_XARGS_CON_TYPE(xargs); - - if ((msg & IDNP_ACKNACK_MASK) == 0) { - /* - * con - */ - mt.mt_mtype = IDNP_CON | IDNP_ACK; - mt.mt_atype = 0; - (void) idn_send_con(domid, &mt, contype, my_ready_set); - } else if (msg & IDNP_MSGTYPE_MASK) { - idn_xdcargs_t cargs; - - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = msg; - CLR_XARGS(cargs); - SET_XARGS_CON_TYPE(cargs, contype); - SET_XARGS_CON_DOMSET(cargs, my_ready_set); - /* - * con+ack - */ - idn_send_acknack(domid, &mt, cargs); - } else { - uint_t token; - /* - * nack - retry - */ - token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON); - idn_retry_submit(idn_retry_con, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_CON]); - } -} - -/*ARGSUSED*/ -static void -idn_action_con_rcvd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) { - uint_t token; - /* - * nack - retry - */ - token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON); - idn_retry_submit(idn_retry_con, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_CON]); - } -} - -static void -idn_final_con(int domid) -{ - uint_t targ; - uint_t token = IDN_RETRY_TOKEN(domid, IDNRETRY_CON); - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_final_con"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - (void) idn_retry_terminate(token); - - dp->dxp = NULL; - IDN_XSTATE_TRANSITION(dp, IDNXS_NIL); - - idn_sync_exit(domid, IDNSYNC_CONNECT); - - CHECKPOINT_OPENED(IDNSB_CHKPT_LINK, dp->dhw.dh_boardset, 1); - - DOMAINSET_DEL(idn.domset.ds_trans_on, domid); - DOMAINSET_DEL(idn.domset.ds_relink, domid); - IDN_FSTATE_TRANSITION(dp, IDNFIN_OFF); - - PR_PROTO("%s:%d: CONNECTED\n", proc, domid); - - if (idn.domset.ds_trans_on == 0) { - if ((idn.domset.ds_trans_off | idn.domset.ds_relink) == 0) { - PR_HITLIST("%s:%d: HITLIST %x -> 0\n", - proc, domid, idn.domset.ds_hitlist); - idn.domset.ds_hitlist = 0; - } - PR_PROTO("%s:%d: ALL CONNECTED ************ " - "(0x%x + 0x%x) = 0x%x\n", proc, domid, - DOMAINSET(idn.localid), idn.domset.ds_connected, - DOMAINSET(idn.localid) | idn.domset.ds_connected); - } else { - PR_PROTO("%s:%d: >>> ds_trans_on = 0x%x, ds_ready_on = 0x%x\n", - proc, domid, - idn.domset.ds_trans_on, idn.domset.ds_ready_on); - } - - if (idn_verify_config_mbox(domid)) { - idnsb_error_t idnerr; - /* - * Mailbox is not cool. Need to disconnect. - */ - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EPROTO); - SET_IDNKERR_IDNERR(&idnerr, IDNKERR_SMR_CORRUPTED); - SET_IDNKERR_PARAM0(&idnerr, domid); - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr); - /* - * We cannot disconnect from an individual domain - * unless all domains are attempting to disconnect - * from him also, especially now since we touched - * the SMR and now we have a potential cache conflicts - * with the other domains with respect to this - * domain. Disconnect attempt will effectively - * shutdown connection with respective domain - * which is the effect we really want anyway. - */ - (void) idn_disconnect(domid, IDNFIN_NORMAL, IDNFIN_ARG_SMRBAD, - IDNFIN_SYNC_YES); - - return; - } - - if (lock_try(&idn.first_swlink)) { - /* - * This is our first connection. Need to - * kick some stuff into gear. - */ - idndl_dlpi_init(); - (void) idn_activate_channel(CHANSET_ALL, IDNCHAN_ONLINE); - - targ = 0xf0; - } else { - targ = 0; - } - - idn_mainmbox_activate(domid); - - idn_update_op(IDNOP_CONNECTED, DOMAINSET(domid), NULL); - - IDN_GKSTAT_GLOBAL_EVENT(gk_links, gk_link_last); - - membar_stst_ldst(); - - IDN_DSTATE_TRANSITION(dp, IDNDS_CONNECTED); - /* - * Need to kick off initial commands in background. - * We do not want to do them within the context of - * a protocol server because they may sleep and thus - * cause the protocol server to incur a soft-deadlock, - * i.e. he's sleeping waiting in the slab-waiting area - * for a response that will arrive on his protojob - * queue, but which he obviously can't process since - * he's not waiting on his protojob queue. - */ - targ |= domid & 0x0f; - (void) timeout(idn_link_established, (void *)(uintptr_t)targ, 50); - - cmn_err(CE_NOTE, - "!IDN: 200: link (domain %d, CPU %d) connected", - dp->domid, dp->dcpu); -} - -static void -idn_exit_con(int domid, uint_t msgtype) -{ - idn_domain_t *dp = &idn_domain[domid]; - idn_fin_t fintype; - procname_t proc = "idn_exit_con"; - STRING(str); - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - INUM2STR(msgtype, str); - PR_PROTO("%s:%d: msgtype = 0x%x(%s)\n", proc, domid, msgtype, str); - - fintype = msgtype ? IDNFIN_NORMAL : IDNFIN_FORCE_HARD; - - IDN_GLOCK_SHARED(); - if (idn.state != IDNGS_DISCONNECT) { - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate, - idn.domset.ds_relink); - } else { - DOMAINSET_DEL(idn.domset.ds_relink, domid); - } - IDN_GUNLOCK(); - - (void) idn_disconnect(domid, fintype, IDNFIN_ARG_NONE, - IDNDS_SYNC_TYPE(dp)); -} - -static int -idn_send_fin(int domid, idn_msgtype_t *mtp, idn_fin_t fintype, idn_finarg_t - finarg, idn_finopt_t finopt, domainset_t finset, uint_t finmaster) -{ - int need_timer = 1; - uint_t acknack; - uint_t fintypearg = 0; - idn_msgtype_t mt; - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_send_fin"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - ASSERT((fintype != IDNFIN_QUERY) ? (finopt != IDNFIN_OPT_NONE) : 1); - - if (mtp) { - acknack = mtp->mt_mtype & IDNP_ACKNACK_MASK; - mt.mt_mtype = mtp->mt_mtype; - mt.mt_atype = mtp->mt_atype; - mt.mt_cookie = mtp->mt_cookie; - } else { - acknack = 0; - mt.mt_mtype = IDNP_FIN; - mt.mt_atype = 0; - /* - * For simple FIN queries we want a unique - * timer assigned. For others, they - * effectively share one. - */ - if (fintype == IDNFIN_QUERY) - mt.mt_cookie = 0; - else - mt.mt_cookie = IDN_TIMER_PUBLIC_COOKIE; - } - - PR_PROTO("%s:%d: sending fin%sto (cpu %d) " - "[ft=%s, fa=%s, fs=0x%x, fo=%s, fm=(%d,%d)]\n", - proc, domid, - (acknack & IDNP_ACK) ? "+ack " : - (acknack & IDNP_NACK) ? "+nack " : " ", - dp->dcpu, idnfin_str[fintype], idnfinarg_str[finarg], - (int)finset, idnfinopt_str[finopt], - FIN_MASTER_DOMID(finmaster), FIN_MASTER_CPUID(finmaster)); - - if (need_timer) { - IDN_MSGTIMER_START(domid, IDNP_FIN, (ushort_t)fintype, - idn_msg_waittime[IDNP_FIN], &mt.mt_cookie); - } - - SET_FIN_TYPE(fintypearg, fintype); - SET_FIN_ARG(fintypearg, finarg); - - IDNXDC(domid, &mt, fintypearg, (uint_t)finset, (uint_t)finopt, - finmaster); - - return (0); -} - -/* - * Must leave w/DLOCK dropped and SYNC_LOCK held. - */ -static int -idn_recv_fin(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_fin_t fintype; - idn_finarg_t finarg; - idn_finopt_t finopt; - domainset_t my_ready_set, ready_set; - idn_msgtype_t mt; - idn_domain_t *dp = &idn_domain[domid]; - idn_xdcargs_t aargs; - procname_t proc = "idn_recv_fin"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - mt.mt_cookie = mtp ? mtp->mt_cookie : 0; - - fintype = GET_XARGS_FIN_TYPE(xargs); - finarg = GET_XARGS_FIN_ARG(xargs); - ready_set = GET_XARGS_FIN_DOMSET(xargs); - finopt = GET_XARGS_FIN_OPT(xargs); - - CLR_XARGS(aargs); - - if (msg & IDNP_NACK) { - PR_PROTO("%s:%d: received NACK (type = %s)\n", - proc, domid, idnnack_str[xargs[0]]); - } else { - PR_PROTO("%s:%d: fintype = %s, finopt = %s, " - "finarg = %s, ready_set = 0x%x\n", - proc, domid, idnfin_str[fintype], - idnfinopt_str[finopt], - idnfinarg_str[finarg], ready_set); - } - - if (!(msg & IDNP_NACK) && (fintype == IDNFIN_QUERY)) { - domainset_t query_set; - - query_set = idn_sync_register(domid, IDNSYNC_DISCONNECT, - ready_set, IDNSYNC_REG_REG); - - my_ready_set = ~idn.domset.ds_connected | - idn.domset.ds_ready_off; - - if (msg & IDNP_MSGTYPE_MASK) { - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = IDNP_FIN; - SET_XARGS_FIN_TYPE(aargs, fintype); - SET_XARGS_FIN_ARG(aargs, finarg); - SET_XARGS_FIN_DOMSET(aargs, my_ready_set); - SET_XARGS_FIN_OPT(aargs, IDNFIN_OPT_NONE); - SET_XARGS_FIN_MASTER(aargs, NIL_FIN_MASTER); - idn_send_acknack(domid, &mt, aargs); - } - - if (query_set) { - uint_t token; - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FINQ); - idn_retry_submit(idn_retry_query, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FINQ]); - } - - return (0); - } - - if (dp->dxp != &xphase_fin) { - uint_t token; - - if (IDNDS_IS_CLOSED(dp)) { - PR_PROTO("%s:%d: domain already closed (%s)\n", - proc, domid, idnds_str[dp->dstate]); - if (msg & IDNP_MSGTYPE_MASK) { - /* - * fin or fin+ack. - */ - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - SET_XARGS_NACK_TYPE(aargs, IDNNACK_NOCONN); - idn_send_acknack(domid, &mt, aargs); - } - return (0); - } - dp->dfin_sync = IDNDS_SYNC_TYPE(dp); - - /* - * Need to do some clean-up ala idn_disconnect(). - * - * Terminate any outstanding commands that were - * targeted towards this domain. - */ - idn_terminate_cmd(domid, ECANCELED); - - /* - * Terminate any and all retries that may have - * outstanding for this domain. - */ - token = IDN_RETRY_TOKEN(domid, IDN_RETRY_TYPEALL); - (void) idn_retry_terminate(token); - - /* - * Stop all outstanding message timers for - * this guy. - */ - IDN_MSGTIMER_STOP(domid, 0, 0); - - dp->dxp = &xphase_fin; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - } - - if (msg & IDNP_NACK) { - idn_nack_t nack; - - nack = GET_XARGS_NACK_TYPE(xargs); - if (nack == IDNNACK_NOCONN) { - /* - * We're trying to FIN with somebody we're - * already disconnected from. Need to - * speed this guy through. - */ - DOMAINSET_ADD(idn.domset.ds_ready_off, domid); - (void) idn_sync_register(domid, IDNSYNC_DISCONNECT, - DOMAINSET_ALL, IDNSYNC_REG_REG); - ready_set = (uint_t)DOMAINSET_ALL; - /* - * Need to transform message to allow us to - * pass this guy right through and not waste time - * talking to him. - */ - IDN_FSTATE_TRANSITION(dp, IDNFIN_FORCE_HARD); - - switch (dp->dstate) { - case IDNDS_FIN_PEND: - mtp->mt_mtype = 0; - mtp->mt_atype = 0; - break; - - case IDNDS_FIN_SENT: - mtp->mt_mtype = IDNP_FIN | IDNP_ACK; - mtp->mt_atype = 0; - break; - - case IDNDS_FIN_RCVD: - mtp->mt_mtype = IDNP_ACK; - mtp->mt_atype = IDNP_FIN | IDNP_ACK; - break; - - default: -#ifdef DEBUG - cmn_err(CE_PANIC, - "%s:%d: UNEXPECTED state = %s", - proc, domid, - idnds_str[dp->dstate]); -#endif /* DEBUG */ - break; - } - } - fintype = (uint_t)dp->dfin; - finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ? - IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK; - - CLR_XARGS(xargs); - SET_XARGS_FIN_TYPE(xargs, fintype); - SET_XARGS_FIN_ARG(xargs, finarg); - SET_XARGS_FIN_DOMSET(xargs, ready_set); - SET_XARGS_FIN_OPT(xargs, finopt); - SET_XARGS_FIN_MASTER(xargs, NIL_FIN_MASTER); - } - - (void) idn_xphase_transition(domid, mtp, xargs); - - return (0); -} - -/*ARGSUSED1*/ -static void -idn_retry_fin(uint_t token, void *arg) -{ - int domid = IDN_RETRY_TOKEN2DOMID(token); - int new_masterid, new_cpuid = IDN_NIL_DCPU; - uint_t finmaster; - idn_domain_t *dp = &idn_domain[domid]; - idn_xdcargs_t xargs; - idn_finopt_t finopt; - procname_t proc = "idn_retry_fin"; - - ASSERT(IDN_RETRY_TOKEN2TYPE(token) == IDNRETRY_FIN); - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - - if (dp->dxp != &xphase_fin) { - PR_PROTO("%s:%d: dxp(0x%p) != xstate_fin(0x%p)...bailing\n", - proc, domid, (void *)dp->dxp, (void *)&xphase_fin); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - if (dp->dxstate != IDNXS_PEND) { - PR_PROTO("%s:%d: xstate(%s) != %s...bailing\n", - proc, domid, idnxs_str[dp->dxstate], - idnxs_str[IDNXS_PEND]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - - finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ? - IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK; - - CLR_XARGS(xargs); - SET_XARGS_FIN_TYPE(xargs, dp->dfin); - /*LINTED*/ - SET_XARGS_FIN_ARG(xargs, IDNFIN_ARG_NONE); - SET_XARGS_FIN_OPT(xargs, finopt); - SET_XARGS_FIN_DOMSET(xargs, 0); /* unused when msg == 0 */ - IDN_GLOCK_SHARED(); - new_masterid = IDN_GET_NEW_MASTERID(); - IDN_GUNLOCK(); - if (new_masterid != IDN_NIL_DOMID) - new_cpuid = idn_domain[new_masterid].dcpu; - finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid); - SET_XARGS_FIN_MASTER(xargs, finmaster); - - (void) idn_xphase_transition(domid, NULL, xargs); - - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); -} - -static int -idn_check_fin_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - idn_domain_t *dp = &idn_domain[domid]; - idn_fin_t fintype; - idn_finopt_t finopt; - idn_finarg_t finarg; - int ready; - int finmasterid; - int fincpuid; - uint_t finmaster; - uint_t msg = mtp ? mtp->mt_mtype : 0; - domainset_t query_set, ready_set, conn_set; - domainset_t my_ready_set, shutdown_set; - procname_t proc = "idn_check_fin_pend"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) - return (0); - - if ((dp->dstate == IDNDS_FIN_PEND) && (msg & IDNP_MSGTYPE_MASK) && - (msg & IDNP_ACK)) /* fin+ack */ - return (1); - - query_set = 0; - - if (!DOMAIN_IN_SET(idn.domset.ds_trans_off, domid)) { - /* - * Can't remove domain from ds_connected yet, - * since he's still officially connected until - * we get an ACK from him. - */ - DOMAINSET_DEL(idn.domset.ds_trans_on, domid); - DOMAINSET_ADD(idn.domset.ds_trans_off, domid); - } - - IDN_GLOCK_SHARED(); - conn_set = (idn.domset.ds_connected | idn.domset.ds_trans_on) & - ~idn.domset.ds_trans_off; - if ((idn.state == IDNGS_DISCONNECT) || - (idn.state == IDNGS_RECONFIG) || - (domid == IDN_GET_MASTERID()) || !conn_set) { - /* - * If we're disconnecting, reconfiguring, - * unlinking from the master, or unlinking - * the last of our connections, then we need - * to shutdown all the channels. - */ - shutdown_set = DOMAINSET_ALL; - } else { - shutdown_set = DOMAINSET(domid); - } - IDN_GUNLOCK(); - - idn_shutdown_datapath(shutdown_set, (dp->dfin == IDNFIN_FORCE_HARD)); - - IDN_GLOCK_EXCL(); - /* - * Remap the SMR back to our local space if the remote - * domain going down is the master. We do this now before - * flushing caches. This will help guarantee that any - * accidental accesses to the SMR after the cache flush - * will only go to local memory. - */ - if ((domid == IDN_GET_MASTERID()) && (idn.smr.rempfn != PFN_INVALID)) { - PR_PROTO("%s:%d: deconfiging CURRENT MASTER - SMR remap\n", - proc, domid); - IDN_DLOCK_EXCL(idn.localid); - /* - * We're going to remap the SMR, - * so gotta blow away our local - * pointer to the mbox table. - */ - idn_domain[idn.localid].dmbox.m_tbl = NULL; - IDN_DUNLOCK(idn.localid); - - idn.smr.rempfn = PFN_INVALID; - idn.smr.rempfnlim = PFN_INVALID; - - smr_remap(&kas, idn.smr.vaddr, idn.smr.locpfn, IDN_SMR_SIZE); - } - IDN_GUNLOCK(); - - if (DOMAIN_IN_SET(idn.domset.ds_flush, domid)) { - idnxf_flushall_ecache(); - CHECKPOINT_CLOSED(IDNSB_CHKPT_CACHE, dp->dhw.dh_boardset, 2); - DOMAINSET_DEL(idn.domset.ds_flush, domid); - } - - fintype = GET_XARGS_FIN_TYPE(xargs); - finarg = GET_XARGS_FIN_ARG(xargs); - ready_set = GET_XARGS_FIN_DOMSET(xargs); - finopt = GET_XARGS_FIN_OPT(xargs); - - ASSERT(fintype != IDNFIN_QUERY); - if (!VALID_FIN(fintype)) { - /* - * If for some reason remote domain - * sent us an invalid FIN type, - * override it to a NORMAL fin. - */ - PR_PROTO("%s:%d: WARNING invalid fintype (%d) -> %s(%d)\n", - proc, domid, (int)fintype, - idnfin_str[IDNFIN_NORMAL], (int)IDNFIN_NORMAL); - fintype = IDNFIN_NORMAL; - } - - if (!VALID_FINOPT(finopt)) { - PR_PROTO("%s:%d: WARNING invalid finopt (%d) -> %s(%d)\n", - proc, domid, (int)finopt, - idnfinopt_str[IDNFIN_OPT_UNLINK], - (int)IDNFIN_OPT_UNLINK); - finopt = IDNFIN_OPT_UNLINK; - } - - finmaster = GET_XARGS_FIN_MASTER(xargs); - finmasterid = FIN_MASTER_DOMID(finmaster); - fincpuid = FIN_MASTER_CPUID(finmaster); - - if ((finarg != IDNFIN_ARG_NONE) && - !DOMAIN_IN_SET(idn.domset.ds_hitlist, domid)) { - idnsb_error_t idnerr; - - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EPROTO); - SET_IDNKERR_IDNERR(&idnerr, FINARG2IDNKERR(finarg)); - SET_IDNKERR_PARAM0(&idnerr, domid); - - if (IDNFIN_ARG_IS_FATAL(finarg)) { - finopt = IDNFIN_OPT_UNLINK; - DOMAINSET_DEL(idn.domset.ds_relink, domid); - DOMAINSET_ADD(idn.domset.ds_hitlist, domid); - - if (idn.domset.ds_connected == 0) { - domainset_t domset; - - IDN_GLOCK_EXCL(); - domset = ~idn.domset.ds_relink; - if (idn.domset.ds_relink == 0) { - IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT); - } - domset &= ~idn.domset.ds_hitlist; - /* - * The primary domain we were trying to - * connect to fin'd us with a fatal argument. - * Something isn't cool in our IDN environment, - * e.g. corrupted SMR or non-compatible CONFIG - * parameters. In any case we need to dismantle - * ourselves completely. - */ - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - IDN_GUNLOCK(); - IDN_DUNLOCK(domid); - - DOMAINSET_DEL(domset, idn.localid); - DOMAINSET_DEL(domset, domid); - - idn_update_op(IDNOP_ERROR, DOMAINSET_ALL, - &idnerr); - - PR_HITLIST("%s:%d: unlink_domainset(%x) " - "due to CFG error (relink=%x, " - "hitlist=%x)\n", proc, domid, domset, - idn.domset.ds_relink, - idn.domset.ds_hitlist); - - idn_unlink_domainset(domset, IDNFIN_NORMAL, - finarg, IDNFIN_OPT_UNLINK, BOARDSET_ALL); - IDN_DLOCK_EXCL(domid); - } - PR_HITLIST("%s:%d: CFG error, (conn=%x, relink=%x, " - "hitlist=%x)\n", - proc, domid, idn.domset.ds_connected, - idn.domset.ds_relink, idn.domset.ds_hitlist); - } - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr); - } - - if ((finmasterid != IDN_NIL_DOMID) && (!VALID_DOMAINID(finmasterid) || - DOMAIN_IN_SET(idn.domset.ds_hitlist, domid))) { - PR_HITLIST("%s:%d: finmasterid = %d -> -1, relink=%x, " - "hitlist=%x\n", - proc, domid, finmasterid, idn.domset.ds_relink, - idn.domset.ds_hitlist); - PR_PROTO("%s:%d: WARNING invalid finmasterid (%d) -> -1\n", - proc, domid, finmasterid); - finmasterid = IDN_NIL_DOMID; - } - - IDN_GLOCK_EXCL(); - - if ((finopt == IDNFIN_OPT_RELINK) && (idn.state != IDNGS_DISCONNECT)) { - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate, - idn.domset.ds_relink); - } else { - DOMAINSET_DEL(idn.domset.ds_relink, domid); - DOMAINSET_ADD(idn.domset.ds_hitlist, domid); - } - - if ((domid == IDN_GET_NEW_MASTERID()) && - !DOMAIN_IN_SET(idn.domset.ds_relink, domid)) { - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - } - - if ((idn.state != IDNGS_DISCONNECT) && (idn.state != IDNGS_RECONFIG) && - (domid == IDN_GET_MASTERID())) { - domainset_t dis_set, master_candidates; - - IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs, gk_reconfig_last); - - IDN_GSTATE_TRANSITION(IDNGS_RECONFIG); - IDN_GUNLOCK(); - - if ((finmasterid != IDN_NIL_DOMID) && - (finmasterid != idn.localid)) { - if (finmasterid != domid) - IDN_DLOCK_EXCL(finmasterid); - if (idn_open_domain(finmasterid, fincpuid, 0) < 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s) failed to " - "open-domain(%d,%d)", - proc, finmasterid, fincpuid); - if (finmasterid != domid) - IDN_DUNLOCK(finmasterid); - finmasterid = IDN_NIL_DOMID; - } - if (finmasterid != domid) - IDN_DUNLOCK(finmasterid); - } - - IDN_GLOCK_EXCL(); - if (finmasterid == IDN_NIL_DOMID) { - int m; - - master_candidates = idn.domset.ds_trans_on | - idn.domset.ds_connected | - idn.domset.ds_relink; - master_candidates &= ~(idn.domset.ds_trans_off & - ~idn.domset.ds_relink); - DOMAINSET_DEL(master_candidates, domid); - /* - * Local domain gets to participate also. - */ - DOMAINSET_ADD(master_candidates, idn.localid); - - m = idn_select_candidate(master_candidates); - IDN_SET_NEW_MASTERID(m); - } else { - IDN_SET_NEW_MASTERID(finmasterid); - } - IDN_GUNLOCK(); - - dis_set = idn.domset.ds_trans_on | idn.domset.ds_connected; - DOMAINSET_DEL(dis_set, domid); - - idn_unlink_domainset(dis_set, IDNFIN_NORMAL, IDNFIN_ARG_NONE, - IDNFIN_OPT_RELINK, BOARDSET_ALL); - } else { - IDN_GUNLOCK(); - } - - /* - * My local ready-set are those domains from which I - * have confirmed no datapaths exist. - */ - my_ready_set = ~idn.domset.ds_connected; - - switch (dp->dfin) { - case IDNFIN_NORMAL: - case IDNFIN_FORCE_SOFT: - case IDNFIN_FORCE_HARD: - if (fintype < dp->dfin) { - /* - * Remote domain has requested a - * FIN of lower priority than what - * we're currently running. Just - * leave the priority where it is. - */ - break; - } - /*FALLTHROUGH*/ - - default: - IDN_FSTATE_TRANSITION(dp, fintype); - break; - } - - ASSERT(dp->dfin_sync != IDNFIN_SYNC_OFF); - - if (msg == 0) { - /* - * Local domain is initiating a FIN sequence - * to remote domid. Note that remote domain - * remains in ds_connected even though he's - * in thet ready-set from the local domain's - * perspective. We can't remove him from - * ds_connected until we get a confirmed message - * from him indicating he has ceased communication. - */ - ready_set = my_ready_set; - } else { - /* - * Remote domain initiated a FIN sequence - * to local domain. This implies that he - * has shutdown his datapath to us. Since - * we shutdown our datapath to him, we're - * effectively now in his ready-set. - */ - DOMAINSET_ADD(ready_set, idn.localid); - /* - * Since we know both sides of the connection - * have ceased, this remote domain is effectively - * considered disconnected. - */ - DOMAINSET_ADD(idn.domset.ds_ready_off, domid); - } - - if (dp->dfin == IDNFIN_FORCE_HARD) { - /* - * If we're doing a hard disconnect - * of this domain then we want to - * blow straight through and not - * waste time trying to talk to the - * remote domain nor to domains we - * believe are AWOL. Although we will - * try and do it cleanly with - * everybody else. - */ - DOMAINSET_ADD(my_ready_set, domid); - my_ready_set |= idn.domset.ds_awol; - ready_set = DOMAINSET_ALL; - - } else if (dp->dfin_sync == IDNFIN_SYNC_NO) { - /* - * If we're not fin'ing this domain - * synchronously then the only - * expected domain set is himself. - */ - ready_set |= ~DOMAINSET(domid); - my_ready_set |= ~DOMAINSET(domid); - } - - if (dp->dsync.s_cmd != IDNSYNC_DISCONNECT) { - idn_sync_exit(domid, IDNSYNC_CONNECT); - idn_sync_enter(domid, IDNSYNC_DISCONNECT, DOMAINSET_ALL, - my_ready_set, idn_xstate_transfunc, (void *)IDNP_FIN); - } - - query_set = idn_sync_register(domid, IDNSYNC_DISCONNECT, ready_set, - IDNSYNC_REG_REG); - - /* - * No need to query this domain as he's already - * in the FIN sequence. - */ - DOMAINSET_DEL(query_set, domid); - - ready = (dp->dsync.s_set_exp == dp->dsync.s_set_rdy) ? 1 : 0; - if (ready) { - DOMAINSET_DEL(idn.domset.ds_ready_off, domid); - DOMAINSET_DEL(idn.domset.ds_connected, domid); - } - - if (query_set) { - int d; - - my_ready_set = idn.domset.ds_ready_off | - ~idn.domset.ds_connected; - - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(query_set, d)) - continue; - - dp = &idn_domain[d]; - - IDN_DLOCK_EXCL(d); - - if (dp->dsync.s_cmd == IDNSYNC_DISCONNECT) { - IDN_DUNLOCK(d); - continue; - } - - IDN_SYNC_QUERY_UPDATE(domid, d); - - (void) idn_send_fin(d, NULL, IDNFIN_QUERY, - IDNFIN_ARG_NONE, IDNFIN_OPT_NONE, my_ready_set, - NIL_FIN_MASTER); - IDN_DUNLOCK(d); - } - } - - return (!msg ? 0 : (ready ? 0 : 1)); -} - -/*ARGSUSED*/ -static void -idn_error_fin_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - uint_t token; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - /* - * Don't communicate with domains that - * we're forcing a hard disconnect. - */ - if ((idn_domain[domid].dfin != IDNFIN_FORCE_HARD) && - (msg & IDNP_MSGTYPE_MASK)) { - idn_msgtype_t mt; - idn_xdcargs_t nargs; - - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - mt.mt_cookie = mtp->mt_cookie; - CLR_XARGS(nargs); - SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY); - idn_send_acknack(domid, &mt, nargs); - } - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); -} - -static void -idn_action_fin_pend(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - idn_domain_t *dp = &idn_domain[domid]; - domainset_t my_ready_set; - idn_finopt_t finopt; - idn_finarg_t finarg; - uint_t finmaster; - int new_masterid, new_cpuid = IDN_NIL_DCPU; - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_msgtype_t mt; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_off | - ~idn.domset.ds_connected; - - ASSERT(xargs[0] != (uint_t)IDNFIN_QUERY); - - finarg = GET_XARGS_FIN_ARG(xargs); - finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ? - IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK; - - mt.mt_cookie = mtp ? mtp->mt_cookie : 0; - - IDN_GLOCK_SHARED(); - new_masterid = IDN_GET_NEW_MASTERID(); - IDN_GUNLOCK(); - if (new_masterid != IDN_NIL_DOMID) - new_cpuid = idn_domain[new_masterid].dcpu; - finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid); - - if (dp->dfin == IDNFIN_FORCE_HARD) { - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (!msg) { - mt.mt_mtype = IDNP_FIN | IDNP_ACK; - mt.mt_atype = 0; - } else { - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = IDNP_FIN | IDNP_ACK; - } - (void) idn_xphase_transition(domid, &mt, xargs); - } else if (!msg) { - (void) idn_send_fin(domid, NULL, dp->dfin, finarg, - finopt, my_ready_set, finmaster); - } else if ((msg & IDNP_ACKNACK_MASK) == 0) { - /* - * fin - */ - mt.mt_mtype = IDNP_FIN | IDNP_ACK; - mt.mt_atype = 0; - (void) idn_send_fin(domid, &mt, dp->dfin, finarg, - finopt, my_ready_set, finmaster); - } else { - uint_t token; - /* - * nack - retry - */ - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); - } -} - -static int -idn_check_fin_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - int ready; - uint_t msg = mtp ? mtp->mt_mtype : 0; - idn_fin_t fintype; - idn_finopt_t finopt; - idn_domain_t *dp = &idn_domain[domid]; - domainset_t query_set, ready_set; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) - return (0); - - fintype = GET_XARGS_FIN_TYPE(xargs); - ready_set = GET_XARGS_FIN_DOMSET(xargs); - finopt = GET_XARGS_FIN_OPT(xargs); - - ASSERT(fintype != IDNFIN_QUERY); - if (!VALID_FIN(fintype)) { - /* - * If for some reason remote domain - * sent us an invalid FIN type, - * override it to a NORMAL fin. - */ - fintype = IDNFIN_NORMAL; - } - - if (!VALID_FINOPT(finopt)) { - finopt = IDNFIN_OPT_UNLINK; - } - IDN_GLOCK_SHARED(); - if ((finopt == IDNFIN_OPT_RELINK) && (idn.state != IDNGS_DISCONNECT)) { - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate, - idn.domset.ds_relink); - } else { - DOMAINSET_DEL(idn.domset.ds_relink, domid); - } - IDN_GUNLOCK(); - - switch (dp->dfin) { - case IDNFIN_NORMAL: - case IDNFIN_FORCE_SOFT: - case IDNFIN_FORCE_HARD: - if (fintype < dp->dfin) { - /* - * Remote domain has requested a - * FIN of lower priority than what - * we're current running. Just - * leave the priority where it is. - */ - break; - } - /*FALLTHROUGH*/ - - default: - IDN_FSTATE_TRANSITION(dp, fintype); - break; - } - - if (dp->dfin == IDNFIN_FORCE_HARD) { - /* - * If we're doing a hard disconnect - * of this domain then we want to - * blow straight through and not - * waste time trying to talk to the - * remote domain. By registering him - * as ready with respect to all - * possible domains he'll transition - * immediately. Note that we'll still - * try and do it coherently with - * other domains to which we're connected. - */ - ready_set = DOMAINSET_ALL; - } else { - DOMAINSET_ADD(ready_set, idn.localid); - } - - DOMAINSET_ADD(idn.domset.ds_ready_off, domid); - - query_set = idn_sync_register(domid, IDNSYNC_DISCONNECT, - ready_set, IDNSYNC_REG_REG); - /* - * No need to query this domain as he's already - * in the FIN sequence. - */ - DOMAINSET_DEL(query_set, domid); - - ready = (dp->dsync.s_set_exp == dp->dsync.s_set_rdy) ? 1 : 0; - if (ready) { - DOMAINSET_DEL(idn.domset.ds_ready_off, domid); - DOMAINSET_DEL(idn.domset.ds_connected, domid); - } - - if (query_set) { - int d; - domainset_t my_ready_set; - - my_ready_set = idn.domset.ds_ready_off | - ~idn.domset.ds_connected; - - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(query_set, d)) - continue; - - dp = &idn_domain[d]; - - IDN_DLOCK_EXCL(d); - - if (dp->dsync.s_cmd == IDNSYNC_DISCONNECT) { - IDN_DUNLOCK(d); - continue; - } - - IDN_SYNC_QUERY_UPDATE(domid, d); - - (void) idn_send_fin(d, NULL, IDNFIN_QUERY, - IDNFIN_ARG_NONE, IDNFIN_OPT_NONE, my_ready_set, - NIL_FIN_MASTER); - IDN_DUNLOCK(d); - } - } - - return ((ready > 0) ? 0 : 1); -} - -/*ARGSUSED*/ -static void -idn_error_fin_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - uint_t token; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - /* - * Don't communicate with domains that - * we're forcing a hard disconnect. - */ - if ((idn_domain[domid].dfin != IDNFIN_FORCE_HARD) && - (msg & IDNP_MSGTYPE_MASK)) { - idn_msgtype_t mt; - idn_xdcargs_t nargs; - - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = msg; - mt.mt_cookie = mtp->mt_cookie; - CLR_XARGS(nargs); - SET_XARGS_NACK_TYPE(nargs, IDNNACK_RETRY); - idn_send_acknack(domid, &mt, nargs); - } - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); -} - -static void -idn_action_fin_sent(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - int new_masterid, new_cpuid = IDN_NIL_DCPU; - uint_t finmaster; - idn_msgtype_t mt; - idn_finopt_t finopt; - idn_finarg_t finarg; - domainset_t my_ready_set; - idn_domain_t *dp = &idn_domain[domid]; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - mt.mt_cookie = mtp ? mtp->mt_cookie : 0; - - finopt = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ? - IDNFIN_OPT_RELINK : IDNFIN_OPT_UNLINK; - - finarg = GET_XARGS_FIN_ARG(xargs); - - my_ready_set = dp->dsync.s_set_rdy | idn.domset.ds_ready_off | - ~idn.domset.ds_connected; - - IDN_GLOCK_SHARED(); - new_masterid = IDN_GET_NEW_MASTERID(); - IDN_GUNLOCK(); - if (new_masterid != IDN_NIL_DOMID) - new_cpuid = idn_domain[new_masterid].dcpu; - finmaster = MAKE_FIN_MASTER(new_masterid, new_cpuid); - - if ((msg & IDNP_ACKNACK_MASK) == 0) { - /* - * fin - */ - if (dp->dfin == IDNFIN_FORCE_HARD) { - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = IDNP_FIN | IDNP_ACK; - (void) idn_xphase_transition(domid, &mt, xargs); - } else { - mt.mt_mtype = IDNP_FIN | IDNP_ACK; - mt.mt_atype = 0; - (void) idn_send_fin(domid, &mt, dp->dfin, finarg, - finopt, my_ready_set, finmaster); - } - } else if (msg & IDNP_MSGTYPE_MASK) { - /* - * fin+ack - */ - if (dp->dfin != IDNFIN_FORCE_HARD) { - idn_xdcargs_t fargs; - - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = msg; - CLR_XARGS(fargs); - SET_XARGS_FIN_TYPE(fargs, dp->dfin); - SET_XARGS_FIN_ARG(fargs, finarg); - SET_XARGS_FIN_DOMSET(fargs, my_ready_set); - SET_XARGS_FIN_OPT(fargs, finopt); - SET_XARGS_FIN_MASTER(fargs, finmaster); - idn_send_acknack(domid, &mt, fargs); - } - } else { - uint_t token; - /* - * nack - retry - */ - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); - } -} - -/*ARGSUSED*/ -static void -idn_action_fin_rcvd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (msg & IDNP_NACK) { - uint_t token; - /* - * nack - retry. - */ - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); - } -} - -static void -idn_final_fin(int domid) -{ - int do_relink; - int rv, d, new_masterid = IDN_NIL_DOMID; - idn_gstate_t next_gstate; - domainset_t relinkset; - uint_t token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_domain_t *ldp, *dp = &idn_domain[domid]; - procname_t proc = "idn_final_fin"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(dp->dstate == IDNDS_DMAP); - - (void) idn_retry_terminate(token); - - dp->dxp = NULL; - IDN_XSTATE_TRANSITION(dp, IDNXS_NIL); - - idn_sync_exit(domid, IDNSYNC_DISCONNECT); - - DOMAINSET_DEL(idn.domset.ds_trans_off, domid); - - do_relink = DOMAIN_IN_SET(idn.domset.ds_relink, domid) ? 1 : 0; - - /* - * idn_deconfig will idn_close_domain. - */ - idn_deconfig(domid); - - PR_PROTO("%s:%d: DISCONNECTED\n", proc, domid); - - IDN_GLOCK_EXCL(); - /* - * It's important that this update-op occur within - * the context of holding the glock(EXCL). There is - * still some additional state stuff to cleanup which - * will be completed once the glock is dropped in - * this flow. Which means anybody that's doing a - * SSI_INFO and waiting on glock will not actually - * run until the clean-up is completed, which is what - * we want. Recall that a separate thread processes - * the SSI_LINK/UNLINK calls and when they complete - * (i.e. are awakened) they will immediately SSI_INFO - * and we don't want them to prematurely pick up stale - * information. - */ - idn_update_op(IDNOP_DISCONNECTED, DOMAINSET(domid), NULL); - - ASSERT(idn.state != IDNGS_OFFLINE); - ASSERT(!DOMAIN_IN_SET(idn.domset.ds_trans_on, domid)); - - if (domid == IDN_GET_MASTERID()) { - IDN_SET_MASTERID(IDN_NIL_DOMID); - dp->dvote.v.master = 0; - } - - if ((domid == IDN_GET_NEW_MASTERID()) && !do_relink) { - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - } - - if (idn.state == IDNGS_RECONFIG) - new_masterid = IDN_GET_NEW_MASTERID(); - - if ((idn.domset.ds_trans_on | idn.domset.ds_trans_off | - idn.domset.ds_relink) == 0) { - PR_HITLIST("%s:%d: HITLIST %x -> 0\n", - proc, domid, idn.domset.ds_hitlist); - idn.domset.ds_hitlist = 0; - } - - if (idn.domset.ds_connected || idn.domset.ds_trans_off) { - PR_PROTO("%s:%d: ds_connected = 0x%x, ds_trans_off = 0x%x\n", - proc, domid, idn.domset.ds_connected, - idn.domset.ds_trans_off); - IDN_GUNLOCK(); - goto fin_done; - } - - IDN_DLOCK_EXCL(idn.localid); - ldp = &idn_domain[idn.localid]; - - if (idn.domset.ds_trans_on != 0) { - ASSERT((idn.state != IDNGS_DISCONNECT) && - (idn.state != IDNGS_OFFLINE)); - - switch (idn.state) { - case IDNGS_CONNECT: - if (idn.localid == IDN_GET_MASTERID()) { - idn_master_deinit(); - IDN_SET_MASTERID(IDN_NIL_DOMID); - ldp->dvote.v.master = 0; - } - /*FALLTHROUGH*/ - case IDNGS_ONLINE: - next_gstate = idn.state; - break; - - case IDNGS_RECONFIG: - if (idn.localid == IDN_GET_MASTERID()) { - idn_master_deinit(); - IDN_SET_MASTERID(IDN_NIL_DOMID); - ldp->dvote.v.master = 0; - } - ASSERT(IDN_GET_MASTERID() == IDN_NIL_DOMID); - next_gstate = IDNGS_CONNECT; - ldp->dvote.v.connected = 0; - /* - * Need to do HWINIT since we won't - * be transitioning through OFFLINE - * which would normally be caught in - * idn_check_nego() when we - * initially go to CONNECT. - */ - IDN_PREP_HWINIT(); - break; - - case IDNGS_DISCONNECT: - case IDNGS_OFFLINE: - cmn_err(CE_WARN, - "IDN: 211: disconnect domain %d, " - "unexpected Gstate (%s)", - domid, idngs_str[idn.state]); - IDN_DUNLOCK(idn.localid); - IDN_GUNLOCK(); - goto fin_done; - - default: - /* - * XXX - * Go into FATAL state? - */ - cmn_err(CE_PANIC, - "IDN: 212: disconnect domain %d, " - "bad Gstate (%d)", - domid, idn.state); - /* not reached */ - break; - } - } else { - if (idn.localid == IDN_GET_MASTERID()) { - idn_master_deinit(); - IDN_SET_MASTERID(IDN_NIL_DOMID); - ldp->dvote.v.master = 0; - } - next_gstate = IDNGS_OFFLINE; - if (idn.domset.ds_relink == 0) { - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - } - } - IDN_DUNLOCK(idn.localid); - - /* - * If we reach here we've effectively disconnected all - * existing links, however new ones may be pending. - */ - PR_PROTO("%s:%d: ALL DISCONNECTED *****************\n", proc, domid); - - IDN_GSTATE_TRANSITION(next_gstate); - - ASSERT((idn.state == IDNGS_OFFLINE) ? - (IDN_GET_MASTERID() == IDN_NIL_DOMID) : 1); - - IDN_GUNLOCK(); - - /* - * If we have no new masterid and yet there are relinkers - * out there, then force us to attempt to link with one - * of them. - */ - if ((new_masterid == IDN_NIL_DOMID) && idn.domset.ds_relink) - new_masterid = idn.localid; - - if (new_masterid != IDN_NIL_DOMID) { - /* - * If the local domain is the selected - * master then we'll want to initiate - * a link with one of the other candidates. - * If not, then we want to initiate a link - * with the master only. - */ - relinkset = (new_masterid == idn.localid) ? - idn.domset.ds_relink : DOMAINSET(new_masterid); - - DOMAINSET_DEL(relinkset, idn.localid); - - for (d = 0; d < MAX_DOMAINS; d++) { - int lock_held; - - if (!DOMAIN_IN_SET(relinkset, d)) - continue; - - if (d == domid) { - do_relink = 0; - lock_held = 0; - } else { - IDN_DLOCK_EXCL(d); - lock_held = 1; - } - - rv = idn_open_domain(d, -1, 0); - if (rv == 0) { - rv = idn_connect(d); - if (lock_held) - IDN_DUNLOCK(d); - /* - * If we're able to kick off at - * least one connect then that's - * good enough for now. The others - * will fall into place normally. - */ - if (rv == 0) - break; - } else if (rv < 0) { - if (lock_held) - IDN_DUNLOCK(d); - cmn_err(CE_WARN, - "IDN: 205: (%s.1) failed to " - "open-domain(%d,%d)", - proc, domid, -1); - DOMAINSET_DEL(idn.domset.ds_relink, d); - } else { - if (lock_held) - IDN_DUNLOCK(d); - PR_PROTO("%s:%d: failed to " - "re-open domain %d " - "(cpu %d) [rv = %d]\n", - proc, domid, d, idn_domain[d].dcpu, - rv); - } - } - } - -fin_done: - if (do_relink) { - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - rv = idn_open_domain(domid, -1, 0); - if (rv == 0) { - (void) idn_connect(domid); - } else if (rv < 0) { - cmn_err(CE_WARN, - "IDN: 205: (%s.2) failed to " - "open-domain(%d,%d)", - proc, domid, -1); - DOMAINSET_DEL(idn.domset.ds_relink, domid); - } - } -} - -static void -idn_exit_fin(int domid, uint_t msgtype) -{ - idn_domain_t *dp = &idn_domain[domid]; - uint_t token; - procname_t proc = "idn_exit_fin"; - STRING(str); - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - INUM2STR(msgtype, str); - PR_PROTO("%s:%d: msgtype = 0x%x(%s)\n", proc, domid, msgtype, str); - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - (void) idn_retry_terminate(token); - - DOMAINSET_DEL(idn.domset.ds_ready_off, domid); - - dp->dxp = &xphase_fin; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); -} - -/* - * Must return w/locks held. - */ -static int -idn_xphase_transition(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp ? mtp->mt_mtype : 0; - uint_t msgarg = mtp ? mtp->mt_atype : 0; - idn_xphase_t *xp; - idn_domain_t *dp; - int (*cfunc)(int, idn_msgtype_t *, idn_xdcargs_t); - void (*ffunc)(int); - void (*afunc)(int, idn_msgtype_t *, idn_xdcargs_t); - void (*efunc)(int, idn_msgtype_t *, idn_xdcargs_t); - void (*xfunc)(int, uint_t); - int err = 0; - uint_t msgtype; - idn_xstate_t o_xstate, n_xstate; - procname_t proc = "idn_xphase_transition"; - STRING(mstr); - STRING(astr); - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - INUM2STR(msg, mstr); - INUM2STR(msgarg, astr); - - dp = &idn_domain[domid]; - if ((xp = dp->dxp) == NULL) { - PR_PROTO("%s:%d: WARNING: domain xsp is NULL (msg = %s, " - "msgarg = %s) <<<<<<<<<<<<\n", - proc, domid, mstr, astr); - return (-1); - } - o_xstate = dp->dxstate; - - xfunc = xp->xt_exit; - - if ((msgtype = (msg & IDNP_MSGTYPE_MASK)) == 0) - msgtype = msgarg & IDNP_MSGTYPE_MASK; - - if ((o_xstate == IDNXS_PEND) && msg && - ((msg & IDNP_ACKNACK_MASK) == msg)) { - PR_PROTO("%s:%d: unwanted acknack received (o_xstate = %s, " - "msg = %s/%s - dropping message\n", - proc, domid, idnxs_str[(int)o_xstate], mstr, astr); - return (0); - } - - /* - * Validate that message received is following - * the expected protocol for the current state. - */ - if (idn_next_xstate(o_xstate, -1, msg) == IDNXS_NIL) { - PR_PROTO("%s:%d: WARNING: o_xstate = %s, msg = %s -> NIL " - "<<<<<<<<<\n", - proc, domid, idnxs_str[(int)o_xstate], mstr); - if (xfunc) - (*xfunc)(domid, msgtype); - return (-1); - } - - if (msg || msgarg) { - /* - * Verify that message type is correct for - * the given xstate. - */ - if (msgtype != xp->xt_msgtype) { - STRING(xstr); - STRING(tstr); - - INUM2STR(xp->xt_msgtype, xstr); - INUM2STR(msgtype, tstr); - PR_PROTO("%s:%d: WARNING: msg expected %s(0x%x), " - "actual %s(0x%x) [msg=%s(0x%x), " - "msgarg=%s(0x%x)]\n", - proc, domid, xstr, xp->xt_msgtype, - tstr, msgtype, mstr, msg, astr, msgarg); - if (xfunc) - (*xfunc)(domid, msgtype); - return (-1); - } - } - - cfunc = xp->xt_trans[(int)o_xstate].t_check; - - if (cfunc && ((err = (*cfunc)(domid, mtp, xargs)) < 0)) { - if (o_xstate != IDNXS_PEND) { - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - } - if (xfunc) - (*xfunc)(domid, msgtype); - return (-1); - } - - n_xstate = idn_next_xstate(o_xstate, err, msg); - - if (n_xstate == IDNXS_NIL) { - PR_PROTO("%s:%d: WARNING: n_xstate = %s, msg = %s -> NIL " - "<<<<<<<<<\n", - proc, domid, idnxs_str[(int)n_xstate], mstr); - if (xfunc) - (*xfunc)(domid, msgtype); - return (-1); - } - - if (n_xstate != o_xstate) { - IDN_XSTATE_TRANSITION(dp, n_xstate); - } - - if (err) { - if ((efunc = xp->xt_trans[(int)o_xstate].t_error) != NULL) - (*efunc)(domid, mtp, xargs); - } else if ((afunc = xp->xt_trans[(int)o_xstate].t_action) != NULL) { - (*afunc)(domid, mtp, xargs); - } - - if ((n_xstate == IDNXS_FINAL) && ((ffunc = xp->xt_final) != NULL)) - (*ffunc)(domid); - - return (0); -} - -/* - * Entered and returns w/DLOCK & SYNC_LOCK held. - */ -static int -idn_xstate_transfunc(int domid, void *transarg) -{ - uint_t msg = (uint_t)(uintptr_t)transarg; - uint_t token; - procname_t proc = "idn_xstate_transfunc"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - - switch (msg) { - case IDNP_CON: - DOMAINSET_ADD(idn.domset.ds_connected, domid); - break; - - case IDNP_FIN: - DOMAINSET_DEL(idn.domset.ds_connected, domid); - break; - - default: - PR_PROTO("%s:%d: ERROR: unknown msg (0x%x) <<<<<<<<\n", - proc, domid, msg); - return (0); - } - - token = IDN_RETRY_TOKEN(domid, (msg == IDNP_CON) ? - IDNRETRY_CON : IDNRETRY_FIN); - if (msg == IDNP_CON) - idn_retry_submit(idn_retry_con, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_CON]); - else - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); - - return (1); -} - -/* - * Entered and returns w/DLOCK & SYNC_LOCK held. - */ -static void -idn_sync_enter(int domid, idn_synccmd_t cmd, domainset_t xset, - domainset_t rset, int (*transfunc)(), void *transarg) -{ - int z; - idn_syncop_t *sp; - idn_synczone_t *zp; - procname_t proc = "idn_sync_enter"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - z = IDN_SYNC_GETZONE(cmd); - ASSERT(z >= 0); - zp = &idn.sync.sz_zone[z]; - - PR_SYNC("%s:%d: cmd=%s(%d), z=%d, xs=0x%x, rx=0x%x, cnt=%d\n", - proc, domid, idnsync_str[cmd], cmd, z, xset, rset, zp->sc_cnt); - - sp = &idn_domain[domid].dsync; - - sp->s_domid = domid; - sp->s_cmd = cmd; - sp->s_msg = 0; - sp->s_set_exp = xset; - sp->s_set_rdy = rset; - sp->s_transfunc = transfunc; - sp->s_transarg = transarg; - IDN_SYNC_QUERY_INIT(domid); - - sp->s_next = zp->sc_op; - zp->sc_op = sp; - zp->sc_cnt++; -} - -/* - * Entered and returns w/DLOCK & SYNC_LOCK held. - */ -void -idn_sync_exit(int domid, idn_synccmd_t cmd) -{ - int d, z, zone, tot_queries, tot_domains; - idn_syncop_t *sp; - idn_synczone_t *zp = NULL; - procname_t proc = "idn_sync_exit"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - sp = &idn_domain[domid].dsync; - - z = IDN_SYNC_GETZONE(sp->s_cmd); - - zone = IDN_SYNC_GETZONE(cmd); - - PR_SYNC("%s:%d: cmd=%s(%d) (z=%d, zone=%d)\n", - proc, domid, idnsync_str[cmd], cmd, z, zone); - -#ifdef DEBUG - if (z != -1) { - tot_queries = tot_domains = 0; - - for (d = 0; d < MAX_DOMAINS; d++) { - int qv; - - if ((qv = sp->s_query[d]) > 0) { - tot_queries += qv; - tot_domains++; - PR_SYNC("%s:%d: query_count = %d\n", - proc, domid, qv); - } - } - PR_SYNC("%s:%d: tot_queries = %d, tot_domaines = %d\n", - proc, domid, tot_queries, tot_domains); - } -#endif /* DEBUG */ - - zp = (z != -1) ? &idn.sync.sz_zone[z] : NULL; - - if (zp) { - idn_syncop_t **spp; - - for (spp = &zp->sc_op; *spp; spp = &((*spp)->s_next)) { - if (*spp == sp) { - *spp = sp->s_next; - sp->s_next = NULL; - zp->sc_cnt--; - break; - } - } - } - - sp->s_cmd = IDNSYNC_NIL; - - for (z = 0; z < IDN_SYNC_NUMZONE; z++) { - idn_syncop_t **spp, **nspp; - - if ((zone != -1) && (z != zone)) - continue; - - zp = &idn.sync.sz_zone[z]; - - for (spp = &zp->sc_op; *spp; spp = nspp) { - sp = *spp; - nspp = &sp->s_next; - - if (!DOMAIN_IN_SET(sp->s_set_exp, domid)) - continue; - - DOMAINSET_DEL(sp->s_set_exp, domid); - DOMAINSET_DEL(sp->s_set_rdy, domid); - - if ((sp->s_set_exp == sp->s_set_rdy) && - sp->s_transfunc) { - int delok; - - ASSERT(sp->s_domid != domid); - - PR_SYNC("%s:%d invoking transfunc " - "for domain %d\n", - proc, domid, sp->s_domid); - delok = (*sp->s_transfunc)(sp->s_domid, - sp->s_transarg); - if (delok) { - *spp = sp->s_next; - sp->s_next = NULL; - zp->sc_cnt--; - nspp = spp; - } - } - } - } -} - -/* - * Entered and returns w/DLOCK & SYNC_LOCK held. - */ -static domainset_t -idn_sync_register(int domid, idn_synccmd_t cmd, domainset_t ready_set, - idn_syncreg_t regtype) -{ - int z; - idn_synczone_t *zp; - idn_syncop_t *sp, **spp, **nspp; - domainset_t query_set = 0, trans_set; - procname_t proc = "idn_sync_register"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if ((z = IDN_SYNC_GETZONE(cmd)) == -1) { - PR_SYNC("%s:%d: ERROR: unexpected sync cmd(%d)\n", - proc, domid, cmd); - return (0); - } - - /* - * Find out what domains are in transition with respect - * to given command. There will be no need to query - * these folks. - */ - trans_set = IDN_SYNC_GETTRANS(cmd); - - zp = &idn.sync.sz_zone[z]; - - PR_SYNC("%s:%d: cmd=%s(%d), z=%d, rset=0x%x, " - "regtype=%s(%d), sc_op=%s\n", - proc, domid, idnsync_str[cmd], cmd, z, ready_set, - idnreg_str[regtype], regtype, - zp->sc_op ? idnsync_str[zp->sc_op->s_cmd] : "NULL"); - - for (spp = &zp->sc_op; *spp; spp = nspp) { - sp = *spp; - nspp = &sp->s_next; - - if (regtype == IDNSYNC_REG_NEW) { - DOMAINSET_ADD(sp->s_set_exp, domid); - PR_SYNC("%s:%d: adding new to %d (exp=0x%x)\n", - proc, domid, sp->s_domid, sp->s_set_exp); - } else if (regtype == IDNSYNC_REG_QUERY) { - query_set |= ~sp->s_set_rdy & sp->s_set_exp; - continue; - } - - if (!DOMAIN_IN_SET(sp->s_set_exp, domid)) - continue; - - if (!DOMAIN_IN_SET(ready_set, sp->s_domid)) { - /* - * Given domid doesn't have a desired - * domain in his ready-set. We'll need - * to query him again. - */ - DOMAINSET_ADD(query_set, domid); - continue; - } - - /* - * If we reach here, then an expected domain - * has marked its respective datapath to - * sp->s_domid as down (i.e. in his ready_set). - */ - DOMAINSET_ADD(sp->s_set_rdy, domid); - - PR_SYNC("%s:%d: mark READY for domain %d " - "(r=0x%x, x=0x%x)\n", - proc, domid, sp->s_domid, - sp->s_set_rdy, sp->s_set_exp); - - query_set |= ~sp->s_set_rdy & sp->s_set_exp; - - if (sp->s_set_exp == sp->s_set_rdy) { -#ifdef DEBUG - if (sp->s_msg == 0) { - sp->s_msg = 1; - PR_SYNC("%s:%d: >>>>>>>>>>> DOMAIN %d " - "ALL CHECKED IN (0x%x)\n", - proc, domid, sp->s_domid, - sp->s_set_exp); - } -#endif /* DEBUG */ - - if ((sp->s_domid != domid) && sp->s_transfunc) { - int delok; - - PR_SYNC("%s:%d invoking transfunc " - "for domain %d\n", - proc, domid, sp->s_domid); - delok = (*sp->s_transfunc)(sp->s_domid, - sp->s_transarg); - if (delok) { - *spp = sp->s_next; - sp->s_next = NULL; - zp->sc_cnt--; - nspp = spp; - } - } - } - } - - PR_SYNC("%s:%d: trans_set = 0x%x, query_set = 0x%x -> 0x%x\n", - proc, domid, trans_set, query_set, query_set & ~trans_set); - - query_set &= ~trans_set; - - return (query_set); -} - -static void -idn_sync_register_awol(int domid) -{ - int z; - idn_synccmd_t cmd = IDNSYNC_DISCONNECT; - idn_synczone_t *zp; - idn_syncop_t *sp; - procname_t proc = "idn_sync_register_awol"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - - if ((z = IDN_SYNC_GETZONE(cmd)) == -1) { - PR_SYNC("%s:%d: ERROR: unexpected sync cmd(%d)\n", - proc, domid, cmd); - return; - } - - zp = &idn.sync.sz_zone[z]; - - PR_SYNC("%s:%d: cmd=%s(%d), z=%d (domain %d = AWOL)\n", - proc, domid, idnsync_str[cmd], cmd, z, domid); - - for (sp = zp->sc_op; sp; sp = sp->s_next) { - idn_domain_t *dp; - - dp = &idn_domain[sp->s_domid]; - if (dp->dfin == IDNFIN_FORCE_HARD) { - DOMAINSET_ADD(sp->s_set_rdy, domid); - PR_SYNC("%s:%d: adding new to %d (rdy=0x%x)\n", - proc, domid, sp->s_domid, sp->s_set_rdy); - } - } -} - -static void -idn_link_established(void *arg) -{ - int first_link; - int domid, masterid; - uint_t info = (uint_t)(uintptr_t)arg; - - first_link = (int)(info & 0xf0); - domid = (int)(info & 0x0f); - - IDN_GLOCK_SHARED(); - masterid = IDN_GET_MASTERID(); - if ((masterid == IDN_NIL_DOMID) || - (idn_domain[masterid].dstate != IDNDS_CONNECTED)) { - /* - * No point in doing this unless we're connected - * to the master. - */ - if ((masterid != IDN_NIL_DOMID) && - (idn.state == IDNGS_ONLINE)) { - /* - * As long as we're still online keep - * trying. - */ - (void) timeout(idn_link_established, arg, 50); - } - IDN_GUNLOCK(); - return; - } - IDN_GUNLOCK(); - - if (first_link && IDN_SLAB_PREALLOC) - idn_prealloc_slab(IDN_SLAB_PREALLOC); - - /* - * No guarantee, but it might save a little - * time. - */ - if (idn_domain[domid].dstate == IDNDS_CONNECTED) { - /* - * Get the remote domain's dname. - */ - idn_send_nodename_req(domid); - } - - /* - * May have had some streams backed up waiting for - * this connection. Prod them. - */ - rw_enter(&idn.struprwlock, RW_READER); - mutex_enter(&idn.sipwenlock); - idndl_wenable(NULL); - mutex_exit(&idn.sipwenlock); - rw_exit(&idn.struprwlock); -} - -/* - * Send the following chunk of data received from above onto - * the IDN wire. This is raw data as far as the IDN driver - * is concerned. - * Returns: - * IDNXMIT_LOOP - Msg handled in loopback and thus - * still active (i.e. don't free). - * IDNXMIT_OKAY - Data handled (freemsg). - * IDNXMIT_DROP - Packet should be dropped. - * IDNXMIT_RETRY - Packet should be requeued and retried. - * IDNXMIT_REQUEUE - Packet should be requeued, but not - * immediatetly retried. - */ -int -idn_send_data(int dst_domid, idn_netaddr_t dst_netaddr, queue_t *wq, mblk_t *mp) -{ - int pktcnt = 0; - int msglen; - int rv = IDNXMIT_OKAY; - int xfersize = 0; - caddr_t iobufp, iodatap; - uchar_t *data_rptr; - int cpuindex; - int serrno; - int channel; - int retry_reclaim; - idn_chansvr_t *csp = NULL; - uint_t netports = 0; - struct idnstr *stp; - struct idn *sip; - idn_domain_t *dp; - struct ether_header *ehp; - smr_pkthdr_t *hdrp; - idn_msgtype_t mt; - procname_t proc = "idn_send_data"; -#ifdef DEBUG - size_t orig_msglen = msgsize(mp); -#endif /* DEBUG */ - - ASSERT(DB_TYPE(mp) == M_DATA); - - mt.mt_mtype = IDNP_DATA; - mt.mt_atype = 0; - mt.mt_cookie = 0; - - channel = (int)dst_netaddr.net.chan; - - msglen = msgdsize(mp); - PR_DATA("%s:%d: (netaddr 0x%x) msgsize=%ld, msgdsize=%d\n", - proc, dst_domid, dst_netaddr.netaddr, msgsize(mp), msglen); - - ASSERT(wq->q_ptr); - - stp = (struct idnstr *)wq->q_ptr; - sip = stp->ss_sip; - ASSERT(sip); - - if (msglen < 0) { - /* - * No data to send. That was easy! - */ - PR_DATA("%s:%d: BAD msg length (%d) (netaddr 0x%x)\n", - proc, dst_domid, msglen, dst_netaddr.netaddr); - return (IDNXMIT_DROP); - } - - ASSERT(RW_READ_HELD(&stp->ss_rwlock)); - - if (dst_domid == IDN_NIL_DOMID) { - cmn_err(CE_WARN, - "IDN: 213: no destination specified " - "(d=%d, c=%d, n=0x%x)", - dst_domid, dst_netaddr.net.chan, - dst_netaddr.net.netid); - IDN_KSTAT_INC(sip, si_nolink); - IDN_KSTAT_INC(sip, si_macxmt_errors); - rv = IDNXMIT_DROP; - goto nocando; - } - - ehp = (struct ether_header *)mp->b_rptr; - PR_DATA("%s:%d: destination channel = %d\n", proc, dst_domid, channel); - -#ifdef DEBUG - { - uchar_t echn; - - echn = (uchar_t) - ehp->ether_shost.ether_addr_octet[IDNETHER_CHANNEL]; - ASSERT((uchar_t)channel == echn); - } -#endif /* DEBUG */ - ASSERT(msglen <= IDN_DATA_SIZE); - - dp = &idn_domain[dst_domid]; - /* - * Get reader lock. We hold for the duration - * of the transfer so that our state doesn't - * change during this activity. Note that since - * we grab the reader lock, we can still permit - * simultaneous tranfers from different threads - * to the same domain. - * Before we waste a bunch of time gathering locks, etc. - * do a an unprotected check to make sure things are - * semi-copesetic. If these values are in flux, - * that's okay. - */ - if ((dp->dstate != IDNDS_CONNECTED) || (idn.state != IDNGS_ONLINE)) { - IDN_KSTAT_INC(sip, si_linkdown); - if (idn.state != IDNGS_ONLINE) { - rv = IDNXMIT_REQUEUE; - } else { - IDN_KSTAT_INC(sip, si_macxmt_errors); - rv = IDNXMIT_DROP; - } - goto nocando; - } - - if (idn.chan_servers[channel].ch_send.c_checkin) { - /* - * Gotta bail, somethin' s'up. - */ - rv = IDNXMIT_REQUEUE; - goto nocando; - } - - csp = &idn.chan_servers[channel]; - IDN_CHAN_LOCK_SEND(csp); - - if (dst_netaddr.net.netid == IDN_BROADCAST_ALLNETID) { - /* - * We're doing a broadcast. Need to set - * up IDN netaddr's one at a time. - * We set the ethernet destination to the same - * instance as the sending address. The instance - * numbers effectively represent subnets. - */ - dst_netaddr.net.netid = dp->dnetid; - - (void) idndl_domain_etheraddr(dst_domid, channel, - &ehp->ether_dhost); - - if (dst_domid == idn.localid) { - mblk_t *nmp; - /* - * If this is a broadcast and going to - * the local domain, then we need to make - * a private copy of the message since - * the current one will be reused when - * transmitting to other domains. - */ - PR_DATA("%s:%d: dup broadcast msg for local domain\n", - proc, dst_domid); - if ((nmp = copymsg(mp)) == NULL) { - /* - * Couldn't get a duplicate copy. - */ - IDN_CHAN_UNLOCK_SEND(csp); - csp = NULL; - IDN_KSTAT_INC(sip, si_allocbfail); - IDN_KSTAT_INC(sip, si_noxmtbuf); - rv = IDNXMIT_DROP; - goto nocando; - } - mp = nmp; - } - } - - if (dp->dnetid != dst_netaddr.net.netid) { - PR_DATA("%s:%d: dest netid (0x%x) != expected (0x%x)\n", - proc, dst_domid, (uint_t)dst_netaddr.net.netid, - (uint_t)dp->dnetid); - IDN_CHAN_UNLOCK_SEND(csp); - csp = NULL; - IDN_KSTAT_INC(sip, si_nolink); - IDN_KSTAT_INC(sip, si_macxmt_errors); - rv = IDNXMIT_DROP; - goto nocando; - } - - if (dst_domid == idn.localid) { - int lbrv; - /* - * Sending to our local domain! Loopback. - * Note that idn_send_data_loop returning 0 - * does not mean the message can now be freed. - * We need to return (-1) so that caller doesn't - * try to free mblk. - */ - IDN_CHAN_UNLOCK_SEND(csp); - rw_exit(&stp->ss_rwlock); - lbrv = idn_send_data_loopback(dst_netaddr, wq, mp); - rw_enter(&stp->ss_rwlock, RW_READER); - if (lbrv == 0) { - return (IDNXMIT_LOOP); - } else { - IDN_KSTAT_INC(sip, si_macxmt_errors); - return (IDNXMIT_DROP); - } - } - - if (dp->dstate != IDNDS_CONNECTED) { - /* - * Can't send data unless a link has already been - * established with the target domain. Normally, - * a user cannot set the remote netaddr unless a - * link has already been established, however it - * is possible the connection may have become - * disconnected since that time. - */ - IDN_CHAN_UNLOCK_SEND(csp); - csp = NULL; - IDN_KSTAT_INC(sip, si_linkdown); - IDN_KSTAT_INC(sip, si_macxmt_errors); - rv = IDNXMIT_DROP; - goto nocando; - } - - /* - * Need to make sure the channel is active and that the - * domain to which we're sending is allowed to receive stuff. - */ - if (!IDN_CHANNEL_IS_SEND_ACTIVE(csp)) { - int not_active; - /* - * See if we can activate channel. - */ - IDN_CHAN_UNLOCK_SEND(csp); - not_active = idn_activate_channel(CHANSET(channel), - IDNCHAN_OPEN); - if (!not_active) { - /* - * Only grab the lock for a recheck if we were - * able to activate the channel. - */ - IDN_CHAN_LOCK_SEND(csp); - } - /* - * Verify channel still active now that we have the lock. - */ - if (not_active || !IDN_CHANNEL_IS_SEND_ACTIVE(csp)) { - if (!not_active) { - /* - * Only need to drop the lock if it was - * acquired while we thought we had - * activated the channel. - */ - IDN_CHAN_UNLOCK_SEND(csp); - } - ASSERT(!IDN_CHAN_SEND_IS_LOCKED(csp)); - /* - * Damn! Must have went inactive during the window - * before we regrabbed the send lock. Oh well, can't - * spend all day doing this, bail out. Set csp to - * NULL to prevent inprogress update at bottom. - */ - csp = NULL; - /* - * Channel is not active, should not be used. - */ - PR_DATA("%s:%d: dest channel %d NOT ACTIVE\n", - proc, dst_domid, channel); - IDN_KSTAT_INC(sip, si_linkdown); - rv = IDNXMIT_REQUEUE; - goto nocando; - } - ASSERT(IDN_CHAN_SEND_IS_LOCKED(csp)); - } - /* - * If we made it here then the channel is active - * Make sure the target domain is registered to receive stuff, - * i.e. we're still linked. - */ - if (!IDN_CHAN_DOMAIN_IS_REGISTERED(csp, dst_domid)) { - /* - * If domain is not even registered with this channel - * then we have no business being here. Doesn't matter - * whether it's active or not. - */ - PR_DATA("%s:%d: domain not registered with channel %d\n", - proc, dst_domid, channel); - /* - * Set csp to NULL to prevent in-progress update below. - */ - IDN_CHAN_UNLOCK_SEND(csp); - csp = NULL; - IDN_KSTAT_INC(sip, si_linkdown); - IDN_KSTAT_INC(sip, si_macxmt_errors); - rv = IDNXMIT_DROP; - goto nocando; - } - - IDN_CHAN_SEND_INPROGRESS(csp); - IDN_CHAN_UNLOCK_SEND(csp); - - /* - * Find a target cpu to send interrupt to if - * it becomes necessary (i.e. remote channel - * server is idle). - */ - cpuindex = dp->dcpuindex; - - /* - * dcpuindex is atomically incremented, but other than - * that is not well protected and that's okay. The - * intention is to simply spread around the interrupts - * at the destination domain, however we don't have to - * anal about it. If we hit the same cpu multiple times - * in a row that's okay, it will only be for a very short - * period anyway before the cpuindex is incremented - * to the next cpu. - */ - if (cpuindex < NCPU) { - ATOMIC_INC(dp->dcpuindex); - } - if (dp->dcpuindex >= NCPU) - dp->dcpuindex = 0; - - IDN_ASSIGN_DCPU(dp, cpuindex); - -#ifdef XXX_DLPI_UNFRIENDLY - { - ushort_t dstport = (ushort_t)dp->dcpu; - - /* - * XXX - * This is not DLPI friendly, but we need some way - * of distributing our XDC interrupts to the cpus - * on the remote domain in a relatively random fashion - * while trying to remain constant for an individual - * network connection. Don't want the target network - * appl pinging around cpus thrashing the caches. - * So, we'll pick target cpus based on the destination - * TCP/IP port (socket). The (simple) alternative to - * this is to simply send all messages destined for - * particular domain to the same cpu (dcpu), but - * will lower our bandwidth and introduce a lot of - * contention on that target cpu. - */ - if (ehp->ether_type == ETHERTYPE_IP) { - ipha_t *ipha; - uchar_t *dstporta; - int hdr_length; - mblk_t *nmp = mp; - uchar_t *rptr = mp->b_rptr + - sizeof (struct ether_header); - if (nmp->b_wptr <= rptr) { - /* - * Only the ethernet header was contained - * in the first block. Check for the - * next packet. - */ - if ((nmp = mp->b_cont) != NULL) - rptr = nmp->b_rptr; - } - /* - * If we still haven't found the IP header packet - * then don't bother. Can't search forever. - */ - if (nmp && - ((nmp->b_wptr - rptr) >= IP_SIMPLE_HDR_LENGTH)) { - ipha = (ipha_t *)ALIGN32(rptr); - - ASSERT(DB_TYPE(mp) == M_DATA); - hdr_length = IPH_HDR_LENGTH(ipha); - - switch (ipha->ipha_protocol) { - case IPPROTO_UDP: - case IPPROTO_TCP: - /* - * TCP/UDP Protocol Header (1st word) - * 0 15,16 31 - * ----------------------- - * | src port | dst port | - * ----------------------- - */ - dstporta = (uchar_t *)ipha + hdr_length; - netports = *(uint_t *)dstporta; - dstporta += 2; - dstport = *(ushort_t *)dstporta; - break; - default: - break; - } - } - - } - IDN_ASSIGN_DCPU(dp, dstport); - - PR_DATA("%s:%d: (dstport %d) assigned %d\n", - proc, dst_domid, (int)dstport, dp->dcpu); - } -#endif /* XXX_DLPI_UNFRIENDLY */ - - data_rptr = mp->b_rptr; - - ASSERT(dp->dcpu != IDN_NIL_DCPU); - - ASSERT(idn_domain[dst_domid].dmbox.m_send); - - retry_reclaim = 1; -retry: - if ((dp->dio >= IDN_RECLAIM_MIN) || dp->diowanted) { - int reclaim_req; - /* - * Reclaim however many outstanding buffers - * there are up to IDN_RECLAIM_MAX if it's set. - */ - reclaim_req = dp->diowanted ? -1 : IDN_RECLAIM_MAX ? - MIN(dp->dio, IDN_RECLAIM_MAX) : dp->dio; - (void) idn_reclaim_mboxdata(dst_domid, channel, - reclaim_req); - } - - if (dp->dio >= IDN_WINDOW_EMAX) { - - if (lock_try(&dp->diocheck)) { - IDN_MSGTIMER_START(dst_domid, IDNP_DATA, 0, - idn_msg_waittime[IDNP_DATA], - &mt.mt_cookie); - /* - * We have exceeded the minimum window for - * outstanding I/O buffers to this domain. - * Need to start the MSG timer to check for - * possible response from remote domain. - * The remote domain may be hung. Send a - * wakeup! Specify all channels for given - * domain since we don't know precisely which - * is backed up (dio is global). - */ - IDNXDC(dst_domid, &mt, - (uint_t)dst_netaddr.net.chan, 0, 0, 0); - } - - /* - * Yikes! We have exceeded the maximum window - * which means no more packets going to remote - * domain until he frees some up. - */ - IDN_KSTAT_INC(sip, si_txmax); - IDN_KSTAT_INC(sip, si_macxmt_errors); - rv = IDNXMIT_DROP; - goto nocando; - } - - /* - * Allocate a SMR I/O buffer and send it. - */ - if (msglen == 0) { - /* - * A zero length messages is effectively a signal - * to just send an interrupt to the remote domain. - */ - IDN_MSGTIMER_START(dst_domid, IDNP_DATA, 0, - idn_msg_waittime[IDNP_DATA], - &mt.mt_cookie); - IDNXDC(dst_domid, &mt, - (uint_t)dst_netaddr.net.chan, 0, 0, 0); - } - for (; (msglen > 0) && mp; msglen -= xfersize) { - int xrv; - smr_offset_t bufoffset; -#ifdef DEBUG - int n_xfersize; -#endif /* DEBUG */ - - ASSERT(msglen <= IDN_DATA_SIZE); - xfersize = msglen; - - serrno = smr_buf_alloc(dst_domid, xfersize, &iobufp); - if (serrno) { - PR_DATA("%s:%d: failed to alloc SMR I/O buffer " - "(serrno = %d)\n", - proc, dst_domid, serrno); - /* - * Failure is either due to a timeout waiting - * for the master to give us a slab, OR the - * local domain exhausted its slab quota! - * In either case we'll have to bail from - * here and let higher layers decide what - * to do. - * We also could have had locking problems. - * A negative serrno indicates we lost the lock - * on dst_domid, so no need in dropping lock. - */ - - if (lock_try(&dp->diowanted) && retry_reclaim) { - /* - * We were the first to acquire the - * lock indicating that it wasn't - * set on entry to idn_send_data. - * So, let's go back and see if we - * can't reclaim some buffers and - * try again. - * It's very likely diowanted will be - * enough to prevent us from looping - * on retrying here, however to protect - * against the small window where a - * race condition might exist, we use - * the retry_reclaim flag so that we - * don't retry more than once. - */ - retry_reclaim = 0; - goto retry; - } - - rv = (serrno > 0) ? serrno : -serrno; - IDN_KSTAT_INC(sip, si_notbufs); - IDN_KSTAT_INC(sip, si_noxmtbuf); /* MIB II */ - switch (rv) { - case ENOMEM: - case EBUSY: - case ENOLCK: - case ETIMEDOUT: - case EDQUOT: - /* - * These are all transient conditions - * which should be recoverable over - * time. - */ - rv = IDNXMIT_REQUEUE; - break; - - default: - rv = IDNXMIT_DROP; - break; - } - goto nocando; - } - - lock_clear(&dp->diowanted); - - hdrp = IDN_BUF2HDR(iobufp); - bufoffset = (smr_offset_t)IDN_ALIGNPTR(sizeof (smr_pkthdr_t), - data_rptr); - /* - * If the alignment of bufoffset took us pass the - * length of a smr_pkthdr_t then we need to possibly - * lower xfersize since it was calulated based on - * a perfect alignment. However, if we're in DLPI - * mode then shouldn't be necessary since the length - * of the incoming packet (mblk) should have already - * taken into consideration this possible adjustment. - */ -#ifdef DEBUG - if (bufoffset != sizeof (smr_pkthdr_t)) - PR_DATA("%s:%d: offset ALIGNMENT (%lu -> %u) " - "(data_rptr = %p)\n", - proc, dst_domid, sizeof (smr_pkthdr_t), - bufoffset, (void *)data_rptr); - - n_xfersize = MIN(xfersize, (IDN_SMR_BUFSIZE - bufoffset)); - if (xfersize != n_xfersize) { - PR_DATA("%s:%d: xfersize ADJUST (%d -> %d)\n", - proc, dst_domid, xfersize, n_xfersize); - cmn_err(CE_WARN, "%s: ERROR (xfersize = %d, > " - "bufsize(%d)-bufoffset(%d) = %d)", - proc, xfersize, IDN_SMR_BUFSIZE, - bufoffset, - IDN_SMR_BUFSIZE - bufoffset); - } -#endif /* DEBUG */ - xfersize = MIN(xfersize, (int)(IDN_SMR_BUFSIZE - bufoffset)); - - iodatap = IDN_BUF2DATA(iobufp, bufoffset); - mp = idn_fill_buffer(iodatap, xfersize, mp, &data_rptr); - - hdrp->b_netaddr = dst_netaddr.netaddr; - hdrp->b_netports = netports; - hdrp->b_offset = bufoffset; - hdrp->b_length = xfersize; - hdrp->b_next = IDN_NIL_SMROFFSET; - hdrp->b_rawio = 0; - hdrp->b_cksum = IDN_CKSUM_PKT(hdrp); - - xrv = idn_send_mboxdata(dst_domid, sip, channel, iobufp); - if (xrv) { - /* - * Reclaim packet. - * Return error on this packet so it can be retried - * (putbq). Note that it should be safe to assume - * that this for-loop is only executed once when in - * DLPI mode and so no need to worry about fractured - * mblk packet. - */ - PR_DATA("%s:%d: DATA XFER to chan %d FAILED " - "(ret=%d)\n", - proc, dst_domid, channel, xrv); - (void) smr_buf_free(dst_domid, iobufp, xfersize); - - PR_DATA("%s:%d: (line %d) dec(dio) -> %d\n", - proc, dst_domid, __LINE__, dp->dio); - - rv = IDNXMIT_DROP; - IDN_KSTAT_INC(sip, si_macxmt_errors); - goto nocando; - } else { - pktcnt++; - /* - * Packet will get freed on a subsequent send - * when we reclaim buffers that the receivers - * has finished consuming. - */ - } - } - -#ifdef DEBUG - if (pktcnt > 1) - cmn_err(CE_WARN, - "%s: ERROR: sent multi-pkts (%d), len = %ld", - proc, pktcnt, orig_msglen); -#endif /* DEBUG */ - - PR_DATA("%s:%d: SENT %d packets (%d @ 0x%x)\n", - proc, dst_domid, pktcnt, dst_netaddr.net.chan, - dst_netaddr.net.netid); - - IDN_CHAN_LOCK_SEND(csp); - IDN_CHAN_SEND_DONE(csp); - IDN_CHAN_UNLOCK_SEND(csp); - - return (IDNXMIT_OKAY); - -nocando: - - if (csp) { - IDN_CHAN_LOCK_SEND(csp); - IDN_CHAN_SEND_DONE(csp); - IDN_CHAN_UNLOCK_SEND(csp); - } - - if (rv == IDNXMIT_REQUEUE) { - /* - * Better kick off monitor to check when - * it's ready to reenable the queues for - * this channel. - */ - idn_xmit_monitor_kickoff(channel); - } - - return (rv); -} - -/* - * Function to support local loopback testing of IDN driver. - * Primarily geared towards measuring stream-head and IDN driver - * overhead with respect to data messages. Setting idn_strhead_only - * allows routine to focus on stream-head overhead by simply putting - * the message straight to the 'next' queue of the destination - * read-queue. Current implementation puts the message directly to - * the read-queue thus sending the message right back to the IDN driver - * as though the data came in off the wire. No need to worry about - * any IDN layers attempting to ack data as that's normally handled - * by idnh_recv_data. - * - * dst_netaddr = destination port-n-addr on local domain. - * wq = write queue from whence message came. - * mp = the (data-only) message. - * - * Returns 0 Indicates data handled. - * errno EAGAIN indicates data can be retried. - * Other errno's indicate failure to handle. - */ -static int -idn_send_data_loopback(idn_netaddr_t dst_netaddr, queue_t *wq, mblk_t *mp) -{ - register struct idnstr *stp; - struct idn *sip; - int rv = 0; - procname_t proc = "idn_send_data_loopback"; - - if (dst_netaddr.net.netid != idn_domain[idn.localid].dnetid) { - PR_DATA("%s: dst_netaddr.net.netid 0x%x != local 0x%x\n", - proc, dst_netaddr.net.netid, - idn_domain[idn.localid].dnetid); - rv = EADDRNOTAVAIL; - goto done; - } - stp = (struct idnstr *)wq->q_ptr; - if (!stp || !stp->ss_rq) { - rv = EDESTADDRREQ; - goto done; - } - sip = stp->ss_sip; - - idndl_read(sip, mp); - rv = 0; - -done: - return (rv); -} - -/* - * Fill bufp with as much data as possible from the message pointed - * to by mp up to size bytes. - * Save our current read pointer in the variable parameter (data_rptrp) - * so we know where to start on the next go around. Don't want to - * bump the actual b_rptr in the mblk because the mblk may need to - * be reused, e.g. broadcast. - * Return the mblk pointer to the position we had to stop. - */ -static mblk_t * -idn_fill_buffer(caddr_t bufp, int size, mblk_t *mp, uchar_t **data_rptrp) -{ - int copysize; - - ASSERT(bufp && size); - - if (mp == NULL) - return (NULL); - - while ((size > 0) && mp) { - - copysize = MIN(mp->b_wptr - (*data_rptrp), size); - - if (copysize > 0) { - /* - * If there's data to copy, do it. - */ - bcopy((*data_rptrp), bufp, copysize); - (*data_rptrp) += copysize; - bufp += copysize; - size -= copysize; - } - if (mp->b_wptr <= (*data_rptrp)) { - /* - * If we emptied the mblk, then - * move on to the next one. - */ - for (mp = mp->b_cont; - mp && (mp->b_datap->db_type != M_DATA); - mp = mp->b_cont) - ; - if (mp) - *data_rptrp = mp->b_rptr; - } - } - return (mp); -} - -/* - * Messages received here do NOT arrive on a stream, but are - * instead handled via the idn_protocol_servers. This routine - * is effectively the job processor for the protocol servers. - */ -static void -idn_recv_proto(idn_protomsg_t *hp) -{ - int domid, cpuid; - int sync_lock = 0; - idn_domain_t *dp; - register uint_t mtype; - register uint_t msgtype, acktype; - idn_msgtype_t mt; - ushort_t dcookie, tcookie; - procname_t proc = "idn_recv_proto"; - - - if (idn.state == IDNGS_IGNORE) { - /* - * Fault injection to simulate non-responsive domain. - */ - return; - } - - domid = hp->m_domid; - cpuid = hp->m_cpuid; - msgtype = hp->m_msgtype; - acktype = hp->m_acktype; - dcookie = IDN_DCOOKIE(hp->m_cookie); - tcookie = IDN_TCOOKIE(hp->m_cookie); - /* - * msgtype = Is the type of message we received, - * e.g. nego, ack, nego+ack, etc. - * - * acktype = If we received a pure ack or nack - * then this variable is set to the - * type of message that was ack/nack'd. - */ - if ((mtype = msgtype & IDNP_MSGTYPE_MASK) == 0) { - /* - * Received a pure ack/nack. - */ - mtype = acktype & IDNP_MSGTYPE_MASK; - } - - if (!VALID_MSGTYPE(mtype)) { - PR_PROTO("%s:%d: ERROR: invalid message type (0x%x)\n", - proc, domid, mtype); - return; - } - if (!VALID_CPUID(cpuid)) { - PR_PROTO("%s:%d: ERROR: invalid cpuid (%d)\n", - proc, domid, cpuid); - return; - } - - /* - * No pure data packets should reach this level. - * Data+ack messages will reach here, but only - * for the purpose of stopping the timer which - * happens by default when this routine is called. - */ - ASSERT(msgtype != IDNP_DATA); - - /* - * We should never receive a request from ourself, - * except for commands in the case of broadcasts! - */ - if ((domid == idn.localid) && (mtype != IDNP_CMD)) { - char str[15]; - - inum2str(hp->m_msgtype, str); - - cmn_err(CE_WARN, - "IDN: 214: received message (%s[0x%x]) from self " - "(domid %d)", - str, hp->m_msgtype, domid); - return; - } - - IDN_SYNC_LOCK(); - /* - * Set a flag indicating whether we really need - * SYNC-LOCK. We'll drop it in a little bit if - * we really don't need it. - */ - switch (mtype) { - case IDNP_CON: - case IDNP_FIN: - case IDNP_NEGO: - sync_lock = 1; - break; - - default: - break; - } - - dp = &idn_domain[domid]; - IDN_DLOCK_EXCL(domid); - - /* - * The only messages we do _not_ check the cookie are: - * nego - * nego+ack - * fin - if received cookie is 0. - * fin+ack - if received cookie is 0. - * ack/fin - if received cookie is 0. - * nack/fin - if received cookie is 0. - */ - if (((msgtype & IDNP_MSGTYPE_MASK) != IDNP_NEGO) && - ((mtype != IDNP_FIN) || (dcookie && dp->dcookie_recv))) { - if (dp->dcookie_recv != dcookie) { - dp->dcookie_errcnt++; - if (dp->dcookie_err == 0) { - /* - * Set cookie error to prevent a - * possible flood of bogus cookies - * and thus error messages. - */ - dp->dcookie_err = 1; - cmn_err(CE_WARN, - "IDN: 215: invalid cookie (0x%x) " - "for message (0x%x) from domain %d", - dcookie, hp->m_msgtype, domid); - - PR_PROTO("%s:%d: received cookie (0x%x), " - "expected (0x%x) [errcnt = %d]\n", - proc, domid, dcookie, - dp->dcookie_recv, dp->dcookie_errcnt); - } - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - return; - } - } - dp->dcookie_err = 0; - IDN_GLOCK_EXCL(); - - idn_clear_awol(domid); - - IDN_GUNLOCK(); - if (!sync_lock) /* really don't need SYNC-LOCK past here */ - IDN_SYNC_UNLOCK(); - - /* - * Stop any timers that may have been outstanding for - * this domain, for this particular message type. - * Note that CFG timers are directly managed by - * config recv/send code. - */ - if ((mtype != IDNP_CFG) && (msgtype & IDNP_ACKNACK_MASK) && tcookie) { - IDN_MSGTIMER_STOP(domid, mtype, tcookie); - } - - /* - * Keep track of the last cpu to send us a message. - * If the domain has not yet been assigned, we'll need - * this cpuid in order to send back a respond. - */ - dp->dcpu_last = cpuid; - - mt.mt_mtype = (ushort_t)msgtype; - mt.mt_atype = (ushort_t)acktype; - mt.mt_cookie = tcookie; - - switch (mtype) { - case IDNP_NEGO: - (void) idn_recv_nego(domid, &mt, hp->m_xargs, dcookie); - break; - - case IDNP_CFG: - idn_recv_config(domid, &mt, hp->m_xargs); - break; - - case IDNP_CON: - (void) idn_recv_con(domid, &mt, hp->m_xargs); - break; - - case IDNP_FIN: - (void) idn_recv_fin(domid, &mt, hp->m_xargs); - break; - - case IDNP_CMD: - idn_recv_cmd(domid, &mt, hp->m_xargs); - break; - - case IDNP_DATA: - ASSERT(msgtype & IDNP_ACKNACK_MASK); - /* - * When doing the fast track we simply process - * possible nack error conditions. The actual - * processing of the SMR data buffer is taken - * care of in idnh_recv_dataack. When NOT doing - * the fast track, we do all the processing here - * in the protocol server. - */ - (void) idn_recv_data(domid, &mt, hp->m_xargs); - break; - - default: - /* - * Should be receiving 0 inum and 0 acknack. - */ -#ifdef DEBUG - cmn_err(CE_PANIC, -#else /* DEBUG */ - cmn_err(CE_WARN, -#endif /* DEBUG */ - /* CSTYLED */ - "IDN: 216: (0x%x)msgtype/(0x%x)acktype rcvd from " - /* CSTYLED */ - "domain %d", msgtype, acktype, domid); - break; - } - - IDN_DUNLOCK(domid); - /* - * All receiving routines are responsible for dropping drwlock. - */ - - if (sync_lock) - IDN_SYNC_UNLOCK(); -} - -/* - * Once the CONFIG state is hit we immediately blast out all - * of our config info. This guarantees that the CONFIG state - * effectively signifies that the sender has sent _all_ of - * their config info. - */ -static void -idn_send_config(int domid, int phase) -{ - idn_domain_t *dp; - int rv; - clock_t cfg_waittime = idn_msg_waittime[IDNP_CFG]; - procname_t proc = "idn_send_config"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - - ASSERT(dp->dstate == IDNDS_CONFIG); - - if (phase == 1) { - /* - * Reset stuff in dtmp to 0: - * dcfgphase - * dcksum - * dncfgitems - * dmaxnets - * dmboxpernet - */ - dp->dtmp = 0; - } - - if (dp->dcfgsnddone) { - if (!dp->dcfgrcvdone) { - IDN_MSGTIMER_START(domid, IDNP_CFG, 0, - cfg_waittime, NULL); - } - return; - } - - IDN_DLOCK_SHARED(idn.localid); - - PR_PROTO("%s:%d: sending %s config (phase %d)\n", - proc, domid, - idn_domain[idn.localid].dvote.v.master ? "MASTER" : "SLAVE", - phase); - - if (idn_domain[idn.localid].dvote.v.master) - rv = idn_send_master_config(domid, phase); - else - rv = idn_send_slave_config(domid, phase); - - IDN_DUNLOCK(idn.localid); - - if (rv >= 0) { - - if (rv == 1) { - dp->dcfgsnddone = 1; - PR_PROTO("%s:%d: SEND config DONE\n", proc, domid); - if (!dp->dcfgrcvdone) { - IDN_MSGTIMER_START(domid, IDNP_CFG, 0, - cfg_waittime, NULL); - } - } else { - IDN_MSGTIMER_START(domid, IDNP_CFG, 0, - cfg_waittime, NULL); - } - } -} - -/* - * Clear out the mailbox table. - * NOTE: This routine touches the SMR. - */ -static void -idn_reset_mboxtbl(idn_mboxtbl_t *mtp) -{ - int qi; - idn_mboxmsg_t *mp = &mtp->mt_queue[0]; - - qi = 0; - do { - mp[qi].ms_bframe = 0; - mp[qi].ms_owner = 0; - mp[qi].ms_flag = 0; - IDN_MMBOXINDEX_INC(qi); - } while (qi); -} - -static int -idn_get_mbox_config(int domid, int *mindex, smr_offset_t *mtable, - smr_offset_t *mdomain) -{ - idn_domain_t *dp, *ldp; - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(IDN_DLOCK_IS_SHARED(idn.localid)); - ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); - - /* - * Get SMR offset of receive mailbox assigned - * to respective domain. If I'm a slave then - * my dmbox.m_tbl will not have been assigned yet. - * Instead of sending the actual offset I send - * the master his assigned index. Since the - * master knows what offset it will assign to - * me he can determine his assigned (recv) mailbox - * based on the offset and given index. The local - * domain can also use this information once the - * dmbox.m_tbl is received to properly assign the - * correct mbox offset to the master. - */ - if (ldp->dmbox.m_tbl == NULL) { - /* - * Local domain has not yet been assigned a - * (recv) mailbox table. This must be the - * initial connection of this domain. - */ - ASSERT(dp->dvote.v.master && !ldp->dvote.v.master); - ASSERT(mindex); - *mindex = domid; - } else { - idn_mboxtbl_t *mtp; - - mtp = IDN_MBOXTBL_PTR(ldp->dmbox.m_tbl, domid); - - ASSERT(mdomain); - *mdomain = IDN_ADDR2OFFSET(mtp); - - if (ldp->dvote.v.master) { - /* - * Need to calculate mailbox table to - * assign to the given domain. Since - * I'm the master his mailbox is in - * the (all-domains) mailbox table. - */ - mtp = IDN_MBOXAREA_BASE(idn.mboxarea, domid); - ASSERT(mtable); - *mtable = IDN_ADDR2OFFSET(mtp); - - dp->dmbox.m_tbl = mtp; - } - } - - return (0); -} - -/* - * RETURNS: - * 1 Unexpected/unnecessary phase. - * 0 Successfully handled, timer needed. - */ -static int -idn_send_master_config(int domid, int phase) -{ - idn_cfgsubtype_t cfg_subtype; - int rv = 0; - idn_domain_t *dp, *ldp; - idn_msgtype_t mt; - int nmcadr; - uint_t barpfn, larpfn; - uint_t cpus_u32, cpus_l32; - uint_t mcadr[3]; - smr_offset_t mbox_table, mbox_domain; - register int b, p, m; - procname_t proc = "idn_send_master_config"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(IDN_DLOCK_IS_SHARED(idn.localid)); - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - ASSERT(dp->dstate == IDNDS_CONFIG); - ASSERT(dp->dvote.v.master == 0); - ASSERT(ldp->dvote.v.master == 1); - - mt.mt_mtype = IDNP_CFG; - mt.mt_atype = 0; - mt.mt_cookie = 0; - m = 0; - mcadr[0] = mcadr[1] = mcadr[2] = 0; - cfg_subtype.val = 0; - - switch (phase) { - - case 1: - mbox_table = mbox_domain = IDN_NIL_SMROFFSET; - (void) idn_get_mbox_config(domid, NULL, &mbox_table, - &mbox_domain); - /* - * ---------------------------------------------------- - * Send: SLABSIZE, DATAMBOX.DOMAIN, DATAMBOX.TABLE - * ---------------------------------------------------- - */ - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_SLAB); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_DATAMBOX, - IDNCFGARG_DATAMBOX_DOMAIN); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_DATAMBOX, - IDNCFGARG_DATAMBOX_TABLE); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - ASSERT(mbox_domain != IDN_NIL_SMROFFSET); - ASSERT(mbox_table != IDN_NIL_SMROFFSET); - - PR_PROTO("%s:%d:%d: sending SLABSIZE (%d), " - "DATAMBOX.DOMAIN (0x%x), DATAMBOX.TABLE (0x%x)\n", - proc, domid, phase, IDN_SLAB_BUFCOUNT, mbox_domain, - mbox_table); - - IDNXDC(domid, &mt, cfg_subtype.val, IDN_SLAB_BUFCOUNT, - mbox_domain, mbox_table); - break; - - case 2: - barpfn = idn.smr.locpfn; - larpfn = barpfn + (uint_t)btop(MB2B(IDN_SMR_SIZE)); - /* - * ---------------------------------------------------- - * Send: NETID, BARLAR - * ---------------------------------------------------- - */ - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_NETID, 0); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_BARLAR, - IDNCFGARG_BARLAR_BAR); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_BARLAR, - IDNCFGARG_BARLAR_LAR); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending NETID (%d), " - "BARPFN/LARPFN (0x%x/0x%x)\n", - proc, domid, phase, ldp->dnetid, barpfn, larpfn); - - IDNXDC(domid, &mt, cfg_subtype.val, - (uint_t)ldp->dnetid, barpfn, larpfn); - break; - - case 3: - nmcadr = ldp->dhw.dh_nmcadr; - cpus_u32 = UPPER32_CPUMASK(ldp->dcpuset); - cpus_l32 = LOWER32_CPUMASK(ldp->dcpuset); - /* - * ---------------------------------------------------- - * Send: CPUSET, NMCADR - * ---------------------------------------------------- - */ - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_CPUSET, - IDNCFGARG_CPUSET_UPPER); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_CPUSET, - IDNCFGARG_CPUSET_LOWER); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_NMCADR, 0); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending CPUSET (0x%x.%x), NMCADR (%d)\n", - proc, domid, phase, cpus_u32, cpus_l32, nmcadr); - - IDNXDC(domid, &mt, cfg_subtype.val, - cpus_u32, cpus_l32, nmcadr); - break; - - case 4: - /* - * ---------------------------------------------------- - * Send: BOARDSET, MTU, BUFSIZE - * ---------------------------------------------------- - */ - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_BOARDSET, 0); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_MTU); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_BUF); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending BOARDSET (0x%x), MTU (0x%lx), " - "BUFSIZE (0x%x)\n", proc, domid, phase, - ldp->dhw.dh_boardset, IDN_MTU, IDN_SMR_BUFSIZE); - - IDNXDC(domid, &mt, cfg_subtype.val, - ldp->dhw.dh_boardset, IDN_MTU, IDN_SMR_BUFSIZE); - break; - - case 5: - /* - * ---------------------------------------------------- - * Send: MAXNETS, MBOXPERNET, CKSUM - * ---------------------------------------------------- - */ - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_DATASVR, - IDNCFGARG_DATASVR_MAXNETS); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_DATASVR, - IDNCFGARG_DATASVR_MBXPERNET); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_OPTIONS, - IDNCFGARG_CHECKSUM); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending MAXNETS (%d), " - "MBOXPERNET (%d), CKSUM (%d)\n", - proc, domid, phase, - IDN_MAX_NETS, IDN_MBOX_PER_NET, - IDN_CHECKSUM); - - IDNXDC(domid, &mt, cfg_subtype.val, - IDN_MAX_NETS, IDN_MBOX_PER_NET, IDN_CHECKSUM); - break; - - case 6: - /* - * ---------------------------------------------------- - * Send: NWRSIZE (piggyback on MCADRs) - * ---------------------------------------------------- - */ - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_NWR); - mcadr[0] = IDN_NWR_SIZE; - m = 1; - - /*FALLTHROUGH*/ - - default: /* case 7 and above */ - /* - * ---------------------------------------------------- - * Send: MCADR's - * ---------------------------------------------------- - * First need to figure how many we've already sent - * based on what phase of CONFIG we're in. - * ---------------------------------------------------- - */ - if (phase > 6) { - p = ((phase - 7) * 3) + 2; - for (b = 0; (b < MAX_BOARDS) && (p > 0); b++) - if (ldp->dhw.dh_mcadr[b]) - p--; - } else { - b = 0; - } - - for (; (b < MAX_BOARDS) && (m < 3); b++) { - if (ldp->dhw.dh_mcadr[b] == 0) - continue; - mcadr[m] = ldp->dhw.dh_mcadr[b]; - cfg_subtype.param.p[m] = IDN_CFGPARAM(IDNCFG_MCADR, b); - m++; - } - if (m > 0) { - if (phase == 6) { - PR_PROTO("%s:%d:%d: sending NWRSIZE (%d), " - "MCADRs (0x%x, 0x%x)\n", - proc, domid, phase, - mcadr[0], mcadr[1], mcadr[2]); - } else { - PR_PROTO("%s:%d:%d: sending MCADRs " - "(0x%x, 0x%x, 0x%x)\n", - proc, domid, phase, - mcadr[0], mcadr[1], mcadr[2]); - } - cfg_subtype.info.num = m; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - IDNXDC(domid, &mt, cfg_subtype.val, - mcadr[0], mcadr[1], mcadr[2]); - } else { - rv = 1; - } - break; - } - - return (rv); -} - -/* - * RETURNS: - * 1 Unexpected/unnecessary phase. - * 0 Successfully handled. - */ -static int -idn_send_slave_config(int domid, int phase) -{ - idn_cfgsubtype_t cfg_subtype; - int rv = 0; - idn_domain_t *dp, *ldp; - smr_offset_t mbox_domain; - idn_msgtype_t mt; - int mbox_index; - uint_t cpus_u32, cpus_l32; - procname_t proc = "idn_send_slave_config"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(IDN_DLOCK_IS_SHARED(idn.localid)); - - mt.mt_mtype = IDNP_CFG; - mt.mt_atype = 0; - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - ASSERT(dp->dstate == IDNDS_CONFIG); - ASSERT(ldp->dvote.v.master == 0); - - switch (phase) { - - case 1: - mbox_index = IDN_NIL_DOMID; - mbox_domain = IDN_NIL_SMROFFSET; - (void) idn_get_mbox_config(domid, &mbox_index, NULL, - &mbox_domain); - /* - * ---------------------------------------------------- - * Send: DATAMBOX.DOMAIN or DATAMBOX.INDEX, - * DATASVR.MAXNETS, DATASVR.MBXPERNET - * ---------------------------------------------------- - */ - cfg_subtype.val = 0; - if (mbox_index == IDN_NIL_DOMID) { - ASSERT(mbox_domain != IDN_NIL_SMROFFSET); - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_DATAMBOX, - IDNCFGARG_DATAMBOX_DOMAIN); - } else { - /* - * Should only be sending Index to - * the master and not another slave. - */ - ASSERT(dp->dvote.v.master); - ASSERT(mbox_domain == IDN_NIL_SMROFFSET); - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_DATAMBOX, - IDNCFGARG_DATAMBOX_INDEX); - } - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_DATASVR, - IDNCFGARG_DATASVR_MAXNETS); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_DATASVR, - IDNCFGARG_DATASVR_MBXPERNET); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending DATAMBOX.%s (0x%x), " - "MAXNETS (%d), MBXPERNET (%d)\n", - proc, domid, phase, - (IDN_CFGPARAM_ARG(cfg_subtype.param.p[0]) - == IDNCFGARG_DATAMBOX_INDEX) ? "INDEX" : "DOMAIN", - (mbox_index == IDN_NIL_DOMID) ? mbox_domain : mbox_index, - IDN_MAX_NETS, IDN_MBOX_PER_NET); - - IDNXDC(domid, &mt, cfg_subtype.val, - ((mbox_index == IDN_NIL_DOMID) ? mbox_domain : mbox_index), - IDN_MAX_NETS, IDN_MBOX_PER_NET); - break; - - case 2: - cpus_u32 = UPPER32_CPUMASK(ldp->dcpuset); - cpus_l32 = LOWER32_CPUMASK(ldp->dcpuset); - /* - * ---------------------------------------------------- - * Send: NETID, CPUSET - * ---------------------------------------------------- - */ - cfg_subtype.val = 0; - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_NETID, 0); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_CPUSET, - IDNCFGARG_CPUSET_UPPER); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_CPUSET, - IDNCFGARG_CPUSET_LOWER); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending NETID (%d), " - "CPUSET (0x%x.%x)\n", proc, domid, phase, - ldp->dnetid, cpus_u32, cpus_l32); - - IDNXDC(domid, &mt, cfg_subtype.val, - (uint_t)ldp->dnetid, cpus_u32, cpus_l32); - break; - - case 3: - /* - * ---------------------------------------------------- - * Send: BOARDSET, MTU, BUFSIZE - * ---------------------------------------------------- - */ - cfg_subtype.val = 0; - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_BOARDSET, 0); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_MTU); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_BUF); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending BOARDSET (0x%x), MTU (0x%lx), " - "BUFSIZE (0x%x)\n", - proc, domid, phase, ldp->dhw.dh_boardset, IDN_MTU, - IDN_SMR_BUFSIZE); - - IDNXDC(domid, &mt, cfg_subtype.val, - ldp->dhw.dh_boardset, IDN_MTU, IDN_SMR_BUFSIZE); - break; - - case 4: - /* - * ---------------------------------------------------- - * Send: SLABSIZE, OPTIONS.CHECKSUM, NWR_SIZE - * ---------------------------------------------------- - */ - cfg_subtype.val = 0; - cfg_subtype.param.p[0] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_SLAB); - cfg_subtype.param.p[1] = IDN_CFGPARAM(IDNCFG_OPTIONS, - IDNCFGARG_CHECKSUM); - cfg_subtype.param.p[2] = IDN_CFGPARAM(IDNCFG_SIZE, - IDNCFGARG_SIZE_NWR); - cfg_subtype.info.num = 3; - cfg_subtype.info.phase = phase; - dp->dcfgphase = phase; - - PR_PROTO("%s:%d:%d: sending SLABSIZE (%d), CKSUM (%d), " - "NWRSIZE (%d)\n", - proc, domid, phase, IDN_SLAB_BUFCOUNT, - IDN_CHECKSUM, IDN_NWR_SIZE); - - IDNXDC(domid, &mt, cfg_subtype.val, - IDN_SLAB_BUFCOUNT, IDN_CHECKSUM, IDN_NWR_SIZE); - break; - - default: - rv = 1; - break; - } - - return (rv); -} - -#define CFG_FATAL ((uint_t)-1) /* reset link */ -#define CFG_CONTINUE 0x0000 /* looking for more */ -#define CFG_DONE 0x0001 /* got everything expected */ -#define CFG_ERR_MTU 0x0002 -#define CFG_ERR_BUF 0x0004 -#define CFG_ERR_SLAB 0x0008 -#define CFG_ERR_NWR 0x0010 -#define CFG_ERR_NETS 0x0020 -#define CFG_ERR_MBOX 0x0040 -#define CFG_ERR_NMCADR 0x0080 -#define CFG_ERR_MCADR 0x0100 -#define CFG_ERR_CKSUM 0x0200 -#define CFG_ERR_SMR 0x0400 -#define CFG_MAX_ERRORS 16 - -#define CFGERR2IDNKERR(ce) \ - (((ce) & CFG_ERR_MTU) ? IDNKERR_CONFIG_MTU : \ - ((ce) & CFG_ERR_BUF) ? IDNKERR_CONFIG_BUF : \ - ((ce) & CFG_ERR_SLAB) ? IDNKERR_CONFIG_SLAB : \ - ((ce) & CFG_ERR_NWR) ? IDNKERR_CONFIG_NWR : \ - ((ce) & CFG_ERR_NETS) ? IDNKERR_CONFIG_NETS : \ - ((ce) & CFG_ERR_MBOX) ? IDNKERR_CONFIG_MBOX : \ - ((ce) & CFG_ERR_NMCADR) ? IDNKERR_CONFIG_NMCADR : \ - ((ce) & CFG_ERR_MCADR) ? IDNKERR_CONFIG_MCADR : \ - ((ce) & CFG_ERR_CKSUM) ? IDNKERR_CONFIG_CKSUM : \ - ((ce) & CFG_ERR_SMR) ? IDNKERR_CONFIG_SMR : 0) - -#define CFGERR2FINARG(ce) \ - (((ce) & CFG_ERR_MTU) ? IDNFIN_ARG_CFGERR_MTU : \ - ((ce) & CFG_ERR_BUF) ? IDNFIN_ARG_CFGERR_BUF : \ - ((ce) & CFG_ERR_SLAB) ? IDNFIN_ARG_CFGERR_SLAB : \ - ((ce) & CFG_ERR_NWR) ? IDNFIN_ARG_CFGERR_NWR : \ - ((ce) & CFG_ERR_NETS) ? IDNFIN_ARG_CFGERR_NETS : \ - ((ce) & CFG_ERR_MBOX) ? IDNFIN_ARG_CFGERR_MBOX : \ - ((ce) & CFG_ERR_NMCADR) ? IDNFIN_ARG_CFGERR_NMCADR : \ - ((ce) & CFG_ERR_MCADR) ? IDNFIN_ARG_CFGERR_MCADR : \ - ((ce) & CFG_ERR_CKSUM) ? IDNFIN_ARG_CFGERR_CKSUM : \ - ((ce) & CFG_ERR_SMR) ? IDNFIN_ARG_CFGERR_SMR : IDNFIN_ARG_NONE) - -/* - * Called when some CFG messages arrive. We use dncfgitems to count the - * total number of items received so far since we'll receive multiple CFG - * messages during the CONFIG phase. Note that dncfgitems is initialized - * in idn_send_config. - */ -static void -idn_recv_config(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp->mt_mtype; - uint_t rv, rv_expected, rv_actual; - int pnum; - int phase; - register int p; - register int c; - idn_mainmbox_t *mmp; - register uint_t subtype, subtype_arg; - idn_domain_t *dp; - int index; - idn_domain_t *ldp = &idn_domain[idn.localid]; - idn_mboxtbl_t *mbtp; - idn_cfgsubtype_t cfg_subtype; - idn_xdcargs_t cfg_arg; - idn_msgtype_t mt; - idnsb_error_t idnerr; - procname_t proc = "idn_recv_config"; - - ASSERT(domid != idn.localid); - - GET_XARGS(xargs, &cfg_subtype.val, &cfg_arg[0], &cfg_arg[1], - &cfg_arg[2]); - cfg_arg[3] = 0; - - dp = &idn_domain[domid]; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (dp->dstate != IDNDS_CONFIG) { - /* - * Not ready to receive config info. - * Drop whatever he sent us. Let the - * timer continue and timeout if needed. - */ - PR_PROTO("%s:%d: WARNING state(%s) != CONFIG\n", - proc, domid, idnds_str[dp->dstate]); - return; - } - - if ((msg & IDNP_ACKNACK_MASK) || dp->dcfgsnddone) { - IDN_MSGTIMER_STOP(domid, IDNP_CFG, 0); - } - - if (msg & IDNP_ACKNACK_MASK) { - /* - * ack/cfg - */ - phase = GET_XARGS_CFG_PHASE(xargs); - - PR_PROTO("%s:%d: received ACK for CFG phase %d\n", - proc, domid, phase); - if (phase != (int)dp->dcfgphase) { - /* - * Phase is not what we were - * expecting. Something got lost - * in the shuffle. Restart the - * timer and let it timeout if necessary - * and reestablish the connection. - */ - IDN_MSGTIMER_START(domid, IDNP_CFG, dp->dcfgphase, - idn_msg_waittime[IDNP_CFG], NULL); - } else { - idn_send_config(domid, phase + 1); - - if (dp->dcfgsnddone && dp->dcfgrcvdone) { - IDN_DUNLOCK(domid); - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - if (dp->dstate == IDNDS_CONFIG) { - dp->dxp = &xphase_con; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - bzero(xargs, sizeof (xargs)); - - (void) idn_xphase_transition(domid, - NULL, xargs); - } - IDN_SYNC_UNLOCK(); - } - } - return; - } - - pnum = (int)cfg_subtype.info.num; - phase = (int)cfg_subtype.info.phase; - - for (p = 0; p < pnum; p++) { - int board; -#ifdef DEBUG - uint_t val; - char *str; - - val = 0; - str = NULL; -#define RCVCFG(s, v) { str = (s); val = (v); } -#else -#define RCVCFG(s, v) {} -#endif /* DEBUG */ - - subtype = IDN_CFGPARAM_TYPE(cfg_subtype.param.p[p]); - subtype_arg = IDN_CFGPARAM_ARG(cfg_subtype.param.p[p]); - - switch (subtype) { - - case IDNCFG_BARLAR: - IDN_GLOCK_EXCL(); - switch (subtype_arg) { - - case IDNCFGARG_BARLAR_BAR: - if (idn.smr.rempfn == PFN_INVALID) { - idn.smr.rempfn = (pfn_t)cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("BARLAR_BAR", cfg_arg[p]); - } - break; - - case IDNCFGARG_BARLAR_LAR: - if (idn.smr.rempfnlim == PFN_INVALID) { - idn.smr.rempfnlim = (pfn_t)cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("BARLAR_LAR", cfg_arg[p]); - } - break; - - default: - cmn_err(CE_WARN, - "IDN 217: unknown CFGARG type (%d) " - "from domain %d", - subtype_arg, domid); - break; - } - IDN_GUNLOCK(); - break; - - case IDNCFG_MCADR: - board = subtype_arg; - if ((board >= 0) && (board < MAX_BOARDS) && - (dp->dhw.dh_mcadr[board] == 0)) { - dp->dhw.dh_mcadr[board] = cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("MCADR", cfg_arg[p]); - } - break; - - case IDNCFG_NMCADR: - if (dp->dhw.dh_nmcadr == 0) { - dp->dhw.dh_nmcadr = cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("NMCADR", cfg_arg[p]); - } - break; - - case IDNCFG_CPUSET: - switch (subtype_arg) { - - case IDNCFGARG_CPUSET_UPPER: - { - cpuset_t tmpset; - - MAKE64_CPUMASK(tmpset, cfg_arg[p], 0); - CPUSET_OR(dp->dcpuset, tmpset); - dp->dncfgitems++; - RCVCFG("CPUSET_UPPER", cfg_arg[p]); - break; - } - case IDNCFGARG_CPUSET_LOWER: - { - cpuset_t tmpset; - - MAKE64_CPUMASK(tmpset, 0, cfg_arg[p]); - CPUSET_OR(dp->dcpuset, tmpset); - dp->dncfgitems++; - RCVCFG("CPUSET_LOWER", cfg_arg[p]); - break; - } - default: - ASSERT(0); - break; - } - break; - - case IDNCFG_NETID: - if (dp->dnetid == (ushort_t)-1) { - dp->dnetid = (ushort_t)cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("NETID", cfg_arg[p]); - } - break; - - case IDNCFG_BOARDSET: - if ((dp->dhw.dh_boardset & cfg_arg[p]) - == dp->dhw.dh_boardset) { - /* - * Boardset better include what we - * already know about. - */ - dp->dhw.dh_boardset = cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("BOARDSET", cfg_arg[p]); - } - break; - - case IDNCFG_SIZE: - switch (subtype_arg) { - - case IDNCFGARG_SIZE_MTU: - if (dp->dmtu == 0) { - dp->dmtu = cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("MTU", cfg_arg[p]); - } - break; - - case IDNCFGARG_SIZE_BUF: - if (dp->dbufsize == 0) { - dp->dbufsize = cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("BUFSIZE", cfg_arg[p]); - } - break; - - case IDNCFGARG_SIZE_SLAB: - if (dp->dslabsize == 0) { - dp->dslabsize = (short)cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("SLABSIZE", cfg_arg[p]); - } - break; - - case IDNCFGARG_SIZE_NWR: - if (dp->dnwrsize == 0) { - dp->dnwrsize = (short)cfg_arg[p]; - dp->dncfgitems++; - RCVCFG("NWRSIZE", cfg_arg[p]); - } - break; - - default: - ASSERT(0); - break; - } - break; - - case IDNCFG_DATAMBOX: - switch (subtype_arg) { - - case IDNCFGARG_DATAMBOX_TABLE: - if (ldp->dmbox.m_tbl || - !dp->dvote.v.master || - !VALID_NWROFFSET(cfg_arg[p], 4)) { - /* - * Only a master should be - * sending us a datambox table. - */ - break; - } - IDN_DLOCK_EXCL(idn.localid); - ldp->dmbox.m_tbl = (idn_mboxtbl_t *) - IDN_OFFSET2ADDR(cfg_arg[p]); - IDN_DUNLOCK(idn.localid); - dp->dncfgitems++; - RCVCFG("DATAMBOX.TABLE", cfg_arg[p]); - break; - - case IDNCFGARG_DATAMBOX_DOMAIN: - if (dp->dmbox.m_send->mm_smr_mboxp || - !VALID_NWROFFSET(cfg_arg[p], 4)) - break; - mbtp = (idn_mboxtbl_t *) - IDN_OFFSET2ADDR(cfg_arg[p]); - mmp = dp->dmbox.m_send; - for (c = 0; c < IDN_MAX_NETS; c++) { - - mutex_enter(&mmp[c].mm_mutex); - mmp[c].mm_smr_mboxp = mbtp; - mutex_exit(&mmp[c].mm_mutex); - - IDN_MBOXTBL_PTR_INC(mbtp); - } - if (c <= 0) - break; - dp->dncfgitems++; - RCVCFG("DATAMBOX.DOMAIN", cfg_arg[p]); - break; - - case IDNCFGARG_DATAMBOX_INDEX: - if (!ldp->dvote.v.master || - dp->dmbox.m_send->mm_smr_mboxp) { - /* - * If I'm not the master then - * I can't handle processing a - * mailbox index. - * OR, if I already have the send - * mailbox, I'm done with this - * config item. - */ - break; - } - ASSERT(dp->dmbox.m_tbl); - index = (int)cfg_arg[p]; - /* - * The given index is the local domain's - * index into the remote domain's mailbox - * table that contains the mailbox that - * remote domain wants the local domain to - * use as the send mailbox for messages - * destined for the remote domain. - * I.e. from the remote domain's - * perspective, this is his receive - * mailbox. - */ - mbtp = IDN_MBOXTBL_PTR(dp->dmbox.m_tbl, index); - mmp = dp->dmbox.m_send; - for (c = 0; c < IDN_MAX_NETS; c++) { - - mutex_enter(&mmp[c].mm_mutex); - mmp[c].mm_smr_mboxp = mbtp; - mutex_exit(&mmp[c].mm_mutex); - - IDN_MBOXTBL_PTR_INC(mbtp); - } - if (c <= 0) - break; - dp->dncfgitems++; - RCVCFG("DATAMBOX.INDEX", cfg_arg[p]); - break; - - default: - ASSERT(0); - break; - } - break; - - case IDNCFG_DATASVR: - switch (subtype_arg) { - - case IDNCFGARG_DATASVR_MAXNETS: - if (dp->dmaxnets) - break; - dp->dmaxnets = (uint_t)(cfg_arg[p] & 0x3f); - dp->dncfgitems++; - RCVCFG("DATASVR.MAXNETS", cfg_arg[p]); - break; - - case IDNCFGARG_DATASVR_MBXPERNET: - if (dp->dmboxpernet) - break; - dp->dmboxpernet = (uint_t)(cfg_arg[p] & 0x1ff); - dp->dncfgitems++; - RCVCFG("DATASVR.MBXPERNET", cfg_arg[p]); - break; - - default: - ASSERT(0); - break; - } - break; - - case IDNCFG_OPTIONS: - switch (subtype_arg) { - - case IDNCFGARG_CHECKSUM: - if (dp->dcksum) - break; - if ((cfg_arg[p] & 0xff) == 0) - dp->dcksum = 1; /* off */ - else - dp->dcksum = 2; /* on */ - dp->dncfgitems++; - RCVCFG("OPTIONS.CHECKSUM", cfg_arg[p]); - break; - - default: - ASSERT(0); - break; - } - - default: - break; - } -#ifdef DEBUG - PR_PROTO("%s:%d: received %s (0x%x)\n", - proc, domid, str ? str : "<empty>", val); -#endif /* DEBUG */ - } - - mt.mt_mtype = IDNP_ACK; - mt.mt_atype = IDNP_CFG; - mt.mt_cookie = mtp->mt_cookie; - CLR_XARGS(cfg_arg); - SET_XARGS_CFG_PHASE(cfg_arg, phase); - idn_send_acknack(domid, &mt, cfg_arg); - - rv_expected = rv_actual = 0; - - if (dp->dvote.v.master == 0) { - /* - * Remote domain is a slave, check if we've received - * all that we were expecting, and if so transition to - * the next state. - */ - rv = idn_check_slave_config(domid, &rv_expected, &rv_actual); - } else { - /* - * Remote domain is a master, check if this slave has - * received all that it was expecting, and if so - * transition to the next state. - */ - rv = idn_check_master_config(domid, &rv_expected, &rv_actual); - } - - switch (rv) { - case CFG_DONE: - /* - * All config info received that was expected, wrap up. - */ - if (!idn_recv_config_done(domid) && dp->dvote.v.master) { - IDN_DLOCK_EXCL(idn.localid); - ldp->dvote.v.connected = 1; - IDN_DUNLOCK(idn.localid); - } - break; - - case CFG_CONTINUE: - /* - * If we're not done sending our own config, then - * there's no need to set a timer since one will - * automatically be set when we send a config - * message waiting for an acknowledgement. - */ - if (dp->dcfgsnddone) { - /* - * We haven't yet received all the config - * information we were expecting. Need to - * restart CFG timer if we've sent everything.. - */ - IDN_MSGTIMER_START(domid, IDNP_CFG, 0, - idn_msg_waittime[IDNP_CFG], NULL); - } - break; - - case CFG_FATAL: - /* - * Fatal error occurred during config exchange. - * We need to shutdown connection in this - * case, so initiate a (non-relink) FIN. - * so let's get the show on the road. - */ - IDN_DUNLOCK(domid); - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - /* - * If the state has changed from CONFIG - * then somebody else has taken over - * control of this domain so we can just - * bail out. - */ - if (dp->dstate == IDNDS_CONFIG) { - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EPROTO); - SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CONFIG_FATAL); - SET_IDNKERR_PARAM0(&idnerr, domid); - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr); - /* - * Keep this guy around so we can try again. - */ - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate, - idn.domset.ds_relink); - (void) idn_disconnect(domid, IDNFIN_NORMAL, - IDNFIN_ARG_CFGERR_FATAL, - IDNFIN_SYNC_NO); - } - IDN_SYNC_UNLOCK(); - break; - - default: /* parameter conflict */ - IDN_DUNLOCK(domid); - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - if (dp->dstate != IDNDS_CONFIG) { - /* - * Hmmm...changed in the short period - * we had dropped the lock, oh well. - */ - IDN_SYNC_UNLOCK(); - break; - } - c = 0; - for (p = 0; p < CFG_MAX_ERRORS; p++) - if (rv & (1 << p)) - c++; - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EINVAL); - SET_IDNKERR_PARAM0(&idnerr, domid); - if (c > 1) { - SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CONFIG_MULTIPLE); - SET_IDNKERR_PARAM1(&idnerr, c); - } else { - SET_IDNKERR_IDNERR(&idnerr, CFGERR2IDNKERR(rv)); - SET_IDNKERR_PARAM1(&idnerr, rv_expected); - SET_IDNKERR_PARAM2(&idnerr, rv_actual); - } - /* - * Any parameter conflicts are grounds for dismissal. - */ - if (idn.domset.ds_connected == 0) { - domainset_t domset; - /* - * We have no other connections yet. - * We must blow out of here completely - * unless we have relinkers left from - * a RECONFIG. - */ - IDN_GLOCK_EXCL(); - domset = ~idn.domset.ds_relink; - if (idn.domset.ds_relink == 0) { - IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT); - } - domset &= ~idn.domset.ds_hitlist; - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - IDN_GUNLOCK(); - IDN_DUNLOCK(domid); - - DOMAINSET_DEL(domset, idn.localid); - - idn_update_op(IDNOP_ERROR, DOMAINSET_ALL, &idnerr); - - PR_HITLIST("%s:%d: unlink_domainset(%x) due to " - "CFG error (relink=%x, hitlist=%x)\n", - proc, domid, domset, idn.domset.ds_relink, - idn.domset.ds_hitlist); - - idn_unlink_domainset(domset, IDNFIN_NORMAL, - CFGERR2FINARG(rv), - IDNFIN_OPT_UNLINK, - BOARDSET_ALL); - IDN_SYNC_UNLOCK(); - IDN_DLOCK_EXCL(domid); - } else { - PR_HITLIST("%s:%d: idn_disconnect(%d) due to CFG " - "error (conn=%x, relink=%x, hitlist=%x)\n", - proc, domid, domid, idn.domset.ds_connected, - idn.domset.ds_relink, idn.domset.ds_hitlist); - /* - * If we have other connections then - * we're only going to blow away this - * single connection. - */ - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr); - - DOMAINSET_DEL(idn.domset.ds_relink, domid); - (void) idn_disconnect(domid, IDNFIN_NORMAL, - CFGERR2FINARG(rv), IDNFIN_SYNC_NO); - IDN_SYNC_UNLOCK(); - } - break; - } -} - -/* - * Called by master or slave which expects exactly the following - * with respect to config info received from a SLAVE: - * IDNCFG_CPUSET - * IDNCFG_NETID - * IDNCFG_BOARDSET - * IDNCFG_SIZE (MTU, BUF, SLAB, NWR) - * IDNCFG_DATAMBOX (DOMAIN or INDEX if caller is master) - * IDNCFG_DATASVR (MAXNETS, MBXPERNET) - * IDNCFG_OPTIONS (CHECKSUM) - */ -static uint_t -idn_check_slave_config(int domid, uint_t *exp, uint_t *act) -{ - uint_t rv = 0; - idn_domain_t *ldp, *dp; - procname_t proc = "idn_check_slave_config"; - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - ASSERT(domid != idn.localid); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(dp->dstate == IDNDS_CONFIG); - - PR_PROTO("%s:%d: number received %d, number expected %d\n", - proc, domid, (int)dp->dncfgitems, IDN_SLAVE_NCFGITEMS); - - if ((int)dp->dncfgitems < IDN_SLAVE_NCFGITEMS) - return (CFG_CONTINUE); - - if ((dp->dnetid == (ushort_t)-1) || - CPUSET_ISNULL(dp->dcpuset) || - (dp->dhw.dh_boardset == 0) || - (dp->dmbox.m_send->mm_smr_mboxp == NULL) || - (dp->dmaxnets == 0) || - (dp->dmboxpernet == 0) || - (dp->dcksum == 0) || - (dp->dmtu == 0) || - (dp->dbufsize == 0) || - (dp->dslabsize == 0) || - (dp->dnwrsize == 0)) { - /* - * We received our IDN_SLAVE_NCFGITEMS config items, - * but not all what we were expecting! Gotta nack and - * close connection. - */ - cmn_err(CE_WARN, - "IDN: 218: missing some required config items from " - "domain %d", domid); - - rv = CFG_FATAL; - goto done; - } - - if (!valid_mtu(dp->dmtu)) { - cmn_err(CE_WARN, - "IDN: 219: remote domain %d MTU (%d) invalid " - "(local.mtu = %d)", dp->domid, dp->dmtu, ldp->dmtu); - - *exp = (uint_t)ldp->dmtu; - *act = (uint_t)dp->dmtu; - rv |= CFG_ERR_MTU; - } - if (!valid_bufsize(dp->dbufsize)) { - cmn_err(CE_WARN, - "IDN: 220: remote domain %d BUFSIZE (%d) invalid " - "(local.bufsize = %d)", dp->domid, dp->dbufsize, - ldp->dbufsize); - - *exp = (uint_t)ldp->dbufsize; - *act = (uint_t)dp->dbufsize; - rv |= CFG_ERR_BUF; - } - if (!valid_slabsize((int)dp->dslabsize)) { - cmn_err(CE_WARN, - "IDN: 221: remote domain %d SLABSIZE (%d) invalid " - "(local.slabsize = %d)", - dp->domid, dp->dslabsize, ldp->dslabsize); - - *exp = (uint_t)ldp->dslabsize; - *act = (uint_t)dp->dslabsize; - rv |= CFG_ERR_SLAB; - } - if (!valid_nwrsize((int)dp->dnwrsize)) { - cmn_err(CE_WARN, - "IDN: 223: remote domain %d NWRSIZE (%d) invalid " - "(local.nwrsize = %d)", - dp->domid, dp->dnwrsize, ldp->dnwrsize); - - *exp = (uint_t)ldp->dnwrsize; - *act = (uint_t)dp->dnwrsize; - rv |= CFG_ERR_NWR; - } - if ((int)dp->dmaxnets != IDN_MAX_NETS) { - cmn_err(CE_WARN, - "IDN: 224: remote domain %d MAX_NETS (%d) invalid " - "(local.maxnets = %d)", - dp->domid, (int)dp->dmaxnets, IDN_MAX_NETS); - - *exp = (uint_t)IDN_MAX_NETS; - *act = (uint_t)dp->dmaxnets; - rv |= CFG_ERR_NETS; - } - if ((int)dp->dmboxpernet != IDN_MBOX_PER_NET) { - cmn_err(CE_WARN, - "IDN: 225: remote domain %d MBOX_PER_NET (%d) " - "invalid (local.mboxpernet = %d)", - dp->domid, (int)dp->dmboxpernet, IDN_MBOX_PER_NET); - - *exp = (uint_t)IDN_MBOX_PER_NET; - *act = (uint_t)dp->dmboxpernet; - rv |= CFG_ERR_MBOX; - } - if ((dp->dcksum - 1) != (uchar_t)IDN_CHECKSUM) { - cmn_err(CE_WARN, - "IDN: 226: remote domain %d CHECKSUM flag (%d) " - "mismatches local domain's (%d)", - dp->domid, (int)dp->dcksum - 1, IDN_CHECKSUM); - - *exp = (uint_t)IDN_CHECKSUM; - *act = (uint_t)(dp->dcksum - 1); - rv |= CFG_ERR_CKSUM; - } - -done: - - return (rv ? rv : CFG_DONE); -} - -/* - * Called by slave ONLY which expects exactly the following - * config info from the MASTER: - * IDNCFG_BARLAR - * IDNCFG_MCADR - * IDNCFG_NMCADR - * IDNCFG_CPUSET - * IDNCFG_NETID - * IDNCFG_BOARDSET - * IDNCFG_SIZE (MTU, BUF, SLAB, NWR) - * IDNCFG_DATAMBOX (TABLE, DOMAIN) - * IDNCFG_DATASVR (MAXNETS, MBXPERNET) - * IDNCFG_OPTIONS (CHECKSUM) - */ -static uint_t -idn_check_master_config(int domid, uint_t *exp, uint_t *act) -{ - uint_t rv = 0; - int nmcadr; - int total_expitems; - int p, m, err; - idn_domain_t *dp; - idn_domain_t *ldp = &idn_domain[idn.localid]; - procname_t proc = "idn_check_master_config"; - - dp = &idn_domain[domid]; - - ASSERT(IDN_GET_MASTERID() != idn.localid); - ASSERT(domid != idn.localid); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(dp->dstate == IDNDS_CONFIG); - - PR_PROTO("%s:%d: number received %d, minimum number expected %d\n", - proc, domid, (int)dp->dncfgitems, IDN_MASTER_NCFGITEMS); - - if ((int)dp->dncfgitems < IDN_MASTER_NCFGITEMS) - return (CFG_CONTINUE); - - /* - * We have at least IDN_MASTER_NCFGITEMS items which - * means we have at least one MCADR. Need to make sure - * we have all that we're expecting, NMCADR. - */ - total_expitems = IDN_MASTER_NCFGITEMS + dp->dhw.dh_nmcadr - 1; - if ((dp->dhw.dh_nmcadr == 0) || - ((int)dp->dncfgitems < total_expitems)) { - /* - * We have not yet received all the MCADRs - * we're expecting. - */ - PR_PROTO("%s:%d: haven't received all MCADRs yet.\n", - proc, domid); - return (CFG_CONTINUE); - } - - nmcadr = 0; - for (p = 0; p < MAX_BOARDS; p++) - if (dp->dhw.dh_mcadr[p] != 0) - nmcadr++; - - IDN_GLOCK_SHARED(); - if ((idn.smr.rempfn == PFN_INVALID) || - (idn.smr.rempfnlim == PFN_INVALID) || - (dp->dnetid == (ushort_t)-1) || - CPUSET_ISNULL(dp->dcpuset) || - (dp->dhw.dh_boardset == 0) || - (nmcadr != dp->dhw.dh_nmcadr) || - (dp->dmbox.m_send->mm_smr_mboxp == NULL) || - (ldp->dmbox.m_tbl == NULL) || - (dp->dmaxnets == 0) || - (dp->dmboxpernet == 0) || - (dp->dcksum == 0) || - (dp->dmtu == 0) || - (dp->dbufsize == 0) || - (dp->dnwrsize == 0)) { - - IDN_GUNLOCK(); - /* - * We received all of our config items, but not - * all what we were expecting! Gotta reset and - * close connection. - */ - cmn_err(CE_WARN, - "IDN: 227: missing some required config items from " - "domain %d", domid); - - rv = CFG_FATAL; - goto done; - } - if ((idn.smr.rempfnlim - idn.smr.rempfn) > btop(MB2B(IDN_SMR_SIZE))) { - /* - * The master's SMR region is larger than - * mine! This means that this domain may - * receive I/O buffers which are out of the - * range of this local domain's SMR virtual - * address space. The master SMR has to be - * no larger than the local SMR in order to - * guarantee enough local virtual addresses - * to see all of the SMR space. - * XXX - Possibly add negotiating SMR size. - * Try to create a new virtual mapping. - * Could let domains negotiate SMR size. - * Winning size would have to be smallest - * in DC. If so, how to handle incoming - * domains with even smaller SMRs? - * - Could either disallow connection - * - Could reconfigure to use smaller SMR. - */ - cmn_err(CE_WARN, - "IDN: 228: master's SMR (%ld) larger than " - "local's SMR (%ld)", - idn.smr.rempfnlim - idn.smr.rempfn, - btop(MB2B(IDN_SMR_SIZE))); - - *exp = (uint_t)IDN_SMR_SIZE; - *act = (uint_t)B2MB(ptob(idn.smr.rempfnlim - idn.smr.rempfn)); - rv |= CFG_ERR_SMR; - } - IDN_GUNLOCK(); - - if (!valid_mtu(dp->dmtu)) { - cmn_err(CE_WARN, - "IDN: 219: remote domain %d MTU (%d) invalid " - "(local.mtu = %d)", dp->domid, dp->dmtu, ldp->dmtu); - - *exp = (uint_t)ldp->dmtu; - *act = (uint_t)dp->dmtu; - rv |= CFG_ERR_MTU; - } - if (!valid_bufsize(dp->dbufsize)) { - cmn_err(CE_WARN, - "IDN: 220: remote domain %d BUFSIZE (%d) invalid " - "(local.bufsize = %d)", dp->domid, dp->dbufsize, - ldp->dbufsize); - - *exp = (uint_t)ldp->dbufsize; - *act = (uint_t)dp->dbufsize; - rv |= CFG_ERR_BUF; - } - if (!valid_nwrsize((int)dp->dnwrsize)) { - cmn_err(CE_WARN, - "IDN: 223: remote domain %d NWRSIZE (%d) invalid " - "(local.nwrsize = %d)", - dp->domid, dp->dnwrsize, ldp->dnwrsize); - - *exp = (uint_t)ldp->dnwrsize; - *act = (uint_t)dp->dnwrsize; - rv |= CFG_ERR_NWR; - } - if ((int)dp->dmaxnets != IDN_MAX_NETS) { - cmn_err(CE_WARN, - "IDN: 224: remote domain %d MAX_NETS (%d) invalid " - "(local.maxnets = %d)", - dp->domid, (int)dp->dmaxnets, IDN_MAX_NETS); - - *exp = (uint_t)IDN_MAX_NETS; - *act = (uint_t)dp->dmaxnets; - rv |= CFG_ERR_NETS; - } - if ((int)dp->dmboxpernet != IDN_MBOX_PER_NET) { - cmn_err(CE_WARN, - "IDN: 225: remote domain %d MBOX_PER_NET (%d) " - "invalid (local.mboxpernet = %d)", - dp->domid, (int)dp->dmboxpernet, IDN_MBOX_PER_NET); - - *exp = (uint_t)IDN_MBOX_PER_NET; - *act = (uint_t)dp->dmboxpernet; - rv |= CFG_ERR_MBOX; - } - if ((dp->dcksum - 1) != (uchar_t)IDN_CHECKSUM) { - cmn_err(CE_WARN, - "IDN: 226: remote domain %d CHECKSUM flag (%d) " - "mismatches local domain's (%d)", - dp->domid, (int)dp->dcksum - 1, IDN_CHECKSUM); - - *exp = (uint_t)IDN_CHECKSUM; - *act = (uint_t)(dp->dcksum - 1); - rv |= CFG_ERR_CKSUM; - } - nmcadr = 0; - err = 0; - for (m = 0; m < MAX_BOARDS; m++) { - if (!BOARD_IN_SET(dp->dhw.dh_boardset, m) && - dp->dhw.dh_mcadr[m]) { - cmn_err(CE_WARN, - "IDN: 229: remote domain %d boardset (0x%x) " - "conflicts with MCADR(board %d) [0x%x]", - dp->domid, (uint_t)dp->dhw.dh_boardset, m, - dp->dhw.dh_mcadr[m]); - err++; - } - if (dp->dhw.dh_mcadr[m]) - nmcadr++; - } - if (err) { - *exp = 0; - *act = err; - rv |= CFG_ERR_MCADR; - } else if (nmcadr != dp->dhw.dh_nmcadr) { - cmn_err(CE_WARN, - "IDN: 230: remote domain %d reported number of " - "MCADRs (%d) mismatches received (%d)", - dp->domid, dp->dhw.dh_nmcadr, nmcadr); - *exp = (uint_t)dp->dhw.dh_nmcadr; - *act = (uint_t)nmcadr; - rv |= CFG_ERR_NMCADR; - } - -done: - - return (rv ? rv : CFG_DONE); -} - -static int -idn_recv_config_done(int domid) -{ - boardset_t b_conflicts; - cpuset_t p_conflicts; - register int p, i; - register idn_domain_t *dp; - idnsb_error_t idnerr; - procname_t proc = "idn_recv_config_done"; - - ASSERT(domid != IDN_NIL_DOMID); - dp = &idn_domain[domid]; - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - /* - * Well, we received all that we were expecting - * so stop any CFG timers we had going. - */ - IDN_MSGTIMER_STOP(domid, IDNP_CFG, 0); - - dp->dncpus = 0; - for (p = 0; p < NCPU; p++) - if (CPU_IN_SET(dp->dcpuset, p)) - dp->dncpus++; - dp->dhw.dh_nboards = 0; - for (p = 0; p < MAX_BOARDS; p++) - if (BOARD_IN_SET(dp->dhw.dh_boardset, p)) - dp->dhw.dh_nboards++; - - IDN_GLOCK_EXCL(); - /* - * Verify dcpuset and dhw.dh_boardset don't - * conflict with any existing DC member. - */ - b_conflicts = idn.dc_boardset & dp->dhw.dh_boardset; - CPUSET_ZERO(p_conflicts); - CPUSET_OR(p_conflicts, idn.dc_cpuset); - CPUSET_AND(p_conflicts, dp->dcpuset); - - if (b_conflicts || !CPUSET_ISNULL(p_conflicts)) { - if (b_conflicts) { - cmn_err(CE_WARN, - "IDN: 231: domain %d boardset " - "(0x%x) conflicts with existing " - "IDN boardset (0x%x)", - domid, dp->dhw.dh_boardset, - b_conflicts); - } - if (!CPUSET_ISNULL(p_conflicts)) { - cmn_err(CE_WARN, - "IDN: 232: domain %d cpuset " - "(0x%x.%0x) conflicts with existing " - "IDN cpuset (0x%x.%0x)", domid, - UPPER32_CPUMASK(dp->dcpuset), - LOWER32_CPUMASK(dp->dcpuset), - UPPER32_CPUMASK(p_conflicts), - LOWER32_CPUMASK(p_conflicts)); - } - IDN_GUNLOCK(); - /* - * Need to disconnect and not retry with this guy. - */ - IDN_DUNLOCK(domid); - IDN_SYNC_LOCK(); - DOMAINSET_DEL(idn.domset.ds_relink, domid); - IDN_DLOCK_EXCL(domid); - - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EPROTO); - SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CONFIG_FATAL); - SET_IDNKERR_PARAM0(&idnerr, domid); - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr); - - (void) idn_disconnect(domid, IDNFIN_FORCE_HARD, - IDNFIN_ARG_CFGERR_FATAL, IDNFIN_SYNC_NO); - IDN_SYNC_UNLOCK(); - - return (-1); - } - - idn_mainmbox_reset(domid, dp->dmbox.m_send); - idn_mainmbox_reset(domid, dp->dmbox.m_recv); - -#ifdef IDNBUG_CPUPERBOARD - /* - * We only allow connections to domains whose (mem) boards - * all have at least one cpu. This is necessary so that - * we can program the CICs of that respective board. This - * is primarily only a requirement if the remote domain - * is the master _and_ has the SMR in that particular board. - * To simplify the checking we simply restrict connections to - * domains that have at least one cpu on all boards that - * contain memory. - */ - if (!idn_cpu_per_board((void *)NULL, dp->dcpuset, &dp->dhw)) { - cmn_err(CE_WARN, - "IDN: 233: domain %d missing CPU per " - "memory boardset (0x%x), CPU boardset (0x%x)", - domid, dp->dhw.dh_boardset, - cpuset2boardset(dp->dcpuset)); - - IDN_GUNLOCK(); - /* - * Need to disconnect and not retry with this guy. - */ - IDN_DUNLOCK(domid); - IDN_SYNC_LOCK(); - DOMAINSET_DEL(idn.domset.ds_relink, domid); - IDN_DLOCK_EXCL(domid); - - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EINVAL); - SET_IDNKERR_IDNERR(&idnerr, IDNKERR_CPU_CONFIG); - SET_IDNKERR_PARAM0(&idnerr, domid); - idn_update_op(IDNOP_ERROR, DOMAINSET(domid), &idnerr); - - (void) idn_disconnect(domid, IDNFIN_FORCE_HARD, - IDNFIN_ARG_CPUCFG, IDNFIN_SYNC_NO); - IDN_SYNC_UNLOCK(); - - return (-1); - } -#endif /* IDNBUG_CPUPERBOARD */ - - CPUSET_OR(idn.dc_cpuset, dp->dcpuset); - idn.dc_boardset |= dp->dhw.dh_boardset; - - IDN_GUNLOCK(); - - /* - * Set up the portmap for this domain. - */ - i = -1; - for (p = 0; p < NCPU; p++) { - BUMP_INDEX(dp->dcpuset, i); - dp->dcpumap[p] = (uchar_t)i; - } - - /* - * Got everything we need from the remote - * domain, now we can program hardware as needed. - */ - if (idn_program_hardware(domid) != 0) { - domainset_t domset; - /* - * Yikes! Failed to program hardware. - * Gotta bail. - */ - cmn_err(CE_WARN, - "IDN: 234: failed to program hardware for domain %d " - "(boardset = 0x%x)", - domid, dp->dhw.dh_boardset); - - IDN_DUNLOCK(domid); - /* - * If we're having problems programming our - * hardware we better unlink completely from - * the IDN before things get really bad. - */ - IDN_SYNC_LOCK(); - IDN_GLOCK_EXCL(); - IDN_GSTATE_TRANSITION(IDNGS_DISCONNECT); - domset = DOMAINSET_ALL; - DOMAINSET_DEL(domset, idn.localid); - IDN_SET_NEW_MASTERID(IDN_NIL_DOMID); - IDN_GUNLOCK(); - - INIT_IDNKERR(&idnerr); - SET_IDNKERR_ERRNO(&idnerr, EINVAL); - SET_IDNKERR_IDNERR(&idnerr, IDNKERR_HW_ERROR); - SET_IDNKERR_PARAM0(&idnerr, domid); - idn_update_op(IDNOP_ERROR, DOMAINSET_ALL, &idnerr); - - idn_unlink_domainset(domset, IDNFIN_NORMAL, IDNFIN_ARG_HWERR, - IDNFIN_OPT_UNLINK, BOARDSET_ALL); - - IDN_SYNC_UNLOCK(); - IDN_DLOCK_EXCL(domid); - - return (-1); - } - - /* - * Now that hardware has been programmed we can - * remap the SMR into our local space, if necessary. - */ - IDN_GLOCK_EXCL(); - if (domid == IDN_GET_MASTERID()) { - /* - * No need to worry about disabling the data - * server since at this stage there is only - * one and he doesn't go active until his - * mailbox (dmbox.m_recv->mm_smr_mboxp) is set up. - */ - smr_remap(&kas, idn.smr.vaddr, idn.smr.rempfn, IDN_SMR_SIZE); - } - IDN_GUNLOCK(); - - /* - * There is no need to ACK the CFG messages since remote - * domain would not progress to the next state (CON_SENT) - * unless he has received everything. - */ - - dp->dcfgrcvdone = 1; - PR_PROTO("%s:%d: RECV config DONE\n", proc, domid); - - if (dp->dcfgsnddone) { - idn_xdcargs_t xargs; - /* - * Well, we've received all that we were expecting, - * but we don't know if the remote domain has - * received all that it was expecting from us, - * although we know we transferred everything - * so let's get the show on the road. - */ - IDN_DUNLOCK(domid); - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(domid); - /* - * If the state has changed from CONFIG - * then somebody else has taken over - * control of this domain so we can just - * bail out. - */ - if (dp->dstate == IDNDS_CONFIG) { - dp->dxp = &xphase_con; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - bzero(xargs, sizeof (xargs)); - - (void) idn_xphase_transition(domid, NULL, xargs); - } - IDN_SYNC_UNLOCK(); - } - - return (0); -} - -static int -idn_verify_config_mbox(int domid) -{ - idn_domain_t *ldp, *dp; - idn_mainmbox_t *mmp; - idn_mboxtbl_t *mtp; - int c, rv = 0; - uint_t activeptr, readyptr; - ushort_t mbox_csum; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - dp = &idn_domain[domid]; - ldp = &idn_domain[idn.localid]; - - /* - * The master will have assigned us the dmbox.m_tbl - * from which we assign our receive mailboxes. - * The first (0) entry contains the cookie used - * for verification. - */ - IDN_DLOCK_SHARED(idn.localid); - /* - * Now that we have an assigned mboxtbl from the - * master, we can determine which receive mailbox - * we indirectly assigned to him at the time we - * sent him his MBOX_INDEX. Prep it, however note - * that the master will have not been able to - * validate it because of the chicken 'n egg - * problem between a master and slave. Thus we - * need to reset the cookie after the prep. - */ - mmp = dp->dmbox.m_recv; - mtp = IDN_MBOXTBL_PTR(ldp->dmbox.m_tbl, domid); - for (c = 0; c < IDN_MAX_NETS; c++) { - mutex_enter(&mmp[c].mm_mutex); - ASSERT(!mmp[c].mm_smr_mboxp); - - mmp[c].mm_smr_mboxp = mtp; - mbox_csum = IDN_CKSUM_MBOX(&mtp->mt_header); - if (!VALID_MBOXHDR(&mtp->mt_header, c, mbox_csum)) { - cmn_err(CE_WARN, - "IDN: 235: [recv] mailbox (domain %d, " - "channel %d) SMR CORRUPTED - RELINK", - domid, c); - cmn_err(CE_CONT, - "IDN: 235: [recv] expected (cookie 0x%x, " - "cksum 0x%x) actual (cookie 0x%x, " - "cksum 0x%x)\n", - IDN_GET_MBOXHDR_COOKIE(&mtp->mt_header), - (int)mtp->mt_header.mh_cksum, - IDN_MAKE_MBOXHDR_COOKIE(0, 0, c), - (int)mbox_csum); - mutex_exit(&mmp[c].mm_mutex); - rv = -1; - break; - } - activeptr = mtp->mt_header.mh_svr_active_ptr; - readyptr = mtp->mt_header.mh_svr_ready_ptr; - /* - * Verify pointers are valid. - */ - if (!activeptr || !VALID_NWROFFSET(activeptr, 2) || - !readyptr || !VALID_NWROFFSET(readyptr, 2)) { - cmn_err(CE_WARN, - "IDN: 235: [recv] mailbox (domain %d, " - "channel %d) SMR CORRUPTED - RELINK", - domid, c); - cmn_err(CE_CONT, - "IDN: 235: [recv] activeptr (0x%x), " - "readyptr (0x%x)\n", - activeptr, readyptr); - mutex_exit(&mmp[c].mm_mutex); - rv = -1; - break; - } - mmp[c].mm_smr_activep = (ushort_t *)IDN_OFFSET2ADDR(activeptr); - mmp[c].mm_smr_readyp = (ushort_t *)IDN_OFFSET2ADDR(readyptr); - mutex_exit(&mmp[c].mm_mutex); - IDN_MBOXTBL_PTR_INC(mtp); - } - - IDN_DUNLOCK(idn.localid); - - if (rv) - return (rv); - - /* - * Now we need to translate SMR offsets for send mailboxes - * to actual virtual addresses. - */ - mmp = dp->dmbox.m_send; - for (c = 0; c < IDN_MAX_NETS; mmp++, c++) { - mutex_enter(&mmp->mm_mutex); - if ((mtp = mmp->mm_smr_mboxp) == NULL) { - mutex_exit(&mmp->mm_mutex); - rv = -1; - break; - } - - mbox_csum = IDN_CKSUM_MBOX(&mtp->mt_header); - - if (!VALID_MBOXHDR(&mtp->mt_header, c, mbox_csum)) { - cmn_err(CE_WARN, - "IDN: 235: [send] mailbox (domain %d, " - "channel %d) SMR CORRUPTED - RELINK", - domid, c); - cmn_err(CE_CONT, - "IDN: 235: [send] expected (cookie 0x%x, " - "cksum 0x%x) actual (cookie 0x%x, " - "cksum 0x%x)\n", - IDN_GET_MBOXHDR_COOKIE(&mtp->mt_header), - (int)mtp->mt_header.mh_cksum, - IDN_MAKE_MBOXHDR_COOKIE(0, 0, c), - (int)mbox_csum); - mutex_exit(&mmp->mm_mutex); - rv = -1; - break; - } - activeptr = mtp->mt_header.mh_svr_active_ptr; - readyptr = mtp->mt_header.mh_svr_ready_ptr; - /* - * Paranoid check. - */ - if (!activeptr || !VALID_NWROFFSET(activeptr, 2) || - !readyptr || !VALID_NWROFFSET(readyptr, 2)) { - cmn_err(CE_WARN, - "IDN: 235: [send] mailbox (domain %d, " - "channel %d) SMR CORRUPTED - RELINK", - domid, c); - cmn_err(CE_CONT, - "IDN: 235: [send] activeptr (0x%x), " - "readyptr (0x%x)\n", - activeptr, readyptr); - mutex_exit(&mmp->mm_mutex); - rv = -1; - break; - } - mmp->mm_smr_activep = (ushort_t *)IDN_OFFSET2ADDR(activeptr); - mmp->mm_smr_readyp = (ushort_t *)IDN_OFFSET2ADDR(readyptr); - idn_reset_mboxtbl(mtp); - mutex_exit(&mmp->mm_mutex); - IDN_MBOXTBL_PTR_INC(mtp); - } - - return (rv); -} - -/* - * The BUFSIZEs between domains have to be equal so that slave buffers - * and the master's slabpool are consistent. - * The MTUs between domains have to be equal so they can transfer - * packets consistently without possible data truncation. - * - * ZZZ - Perhaps these could be negotiated? - */ -static int -valid_mtu(uint_t mtu) -{ - return ((mtu == idn_domain[idn.localid].dmtu) && mtu); -} - -static int -valid_bufsize(uint_t bufsize) -{ - return ((bufsize == idn_domain[idn.localid].dbufsize) && bufsize); -} - -static int -valid_slabsize(int slabsize) -{ - return ((slabsize == idn_domain[idn.localid].dslabsize) && slabsize); -} - -static int -valid_nwrsize(int nwrsize) -{ - return ((nwrsize == idn_domain[idn.localid].dnwrsize) && nwrsize); -} - -static int -idn_program_hardware(int domid) -{ - int rv, is_master; - idn_domain_t *dp; - uint_t *mcadrp; - pfn_t rem_pfn, rem_pfnlimit; - procname_t proc = "idn_program_hardware"; - - PR_PROTO("%s:%d: program hw in domain %d w.r.t remote domain %d\n", - proc, domid, idn.localid, domid); - - dp = &idn_domain[domid]; - - ASSERT(domid != idn.localid); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(dp->dstate == IDNDS_CONFIG); - - IDN_GLOCK_EXCL(); - - if (DOMAIN_IN_SET(idn.domset.ds_hwlinked, domid)) { - IDN_GUNLOCK(); - return (0); - } - - DOMAINSET_ADD(idn.domset.ds_flush, domid); - CHECKPOINT_OPENED(IDNSB_CHKPT_CACHE, dp->dhw.dh_boardset, 1); - - if (domid != IDN_GET_MASTERID()) { - /* - * If the remote domain is a slave, then - * all we have to program is the CIC sm_mask. - */ - is_master = 0; - if ((idn.localid == IDN_GET_MASTERID()) && - lock_try(&idn.first_hwlink)) { - /* - * This is our first HW link and I'm the - * master, which means we need to program - * our local bar/lar. - */ - ASSERT(idn.first_hwmasterid == (short)IDN_NIL_DOMID); - idn.first_hwmasterid = (short)idn.localid; - rem_pfn = idn.smr.locpfn; - rem_pfnlimit = idn.smr.locpfn + - btop(MB2B(IDN_SMR_SIZE)); - } else { - /* - * Otherwise, just a slave linking to - * another slave. No bar/lar updating - * necessary. - */ - rem_pfn = rem_pfnlimit = PFN_INVALID; - } - mcadrp = NULL; - } else { - /* - * If the remote domain is a master, then - * we need to program the CIC sm_mask/sm_bar/sm_lar, - * and PC's. - */ - is_master = 1; - rem_pfn = idn.smr.rempfn; - rem_pfnlimit = idn.smr.rempfnlim; - mcadrp = dp->dhw.dh_mcadr; - ASSERT(idn.first_hwmasterid == (short)IDN_NIL_DOMID); - idn.first_hwmasterid = (short)domid; - } - - PR_PROTO("%s:%d: ADD bset (0x%x)\n", proc, domid, dp->dhw.dh_boardset); - - rv = idnxf_shmem_add(is_master, dp->dhw.dh_boardset, - rem_pfn, rem_pfnlimit, mcadrp); - - if (rv == 0) { - DOMAINSET_ADD(idn.domset.ds_hwlinked, domid); - } else { - if (rem_pfn == idn.smr.locpfn) - lock_clear(&idn.first_hwlink); - - if (idn.first_hwmasterid == (short)domid) - idn.first_hwmasterid = (short)IDN_NIL_DOMID; - - (void) idnxf_shmem_sub(is_master, dp->dhw.dh_boardset); - } - - IDN_GUNLOCK(); - - return (rv); -} - -static int -idn_deprogram_hardware(int domid) -{ - int rv, is_master; - idn_domain_t *dp; - procname_t proc = "idn_deprogram_hardware"; - - - dp = &idn_domain[domid]; - - ASSERT(domid != idn.localid); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - /* - * Need to take into consideration what boards remote - * domain was connected to. If we don't have a connection to - * them ourself, then we better remove them now , otherwise - * they'll never be removed (unless we link to them at some point). - */ -#if 0 - DEBUG_USECDELAY(500000); -#endif /* 0 */ - - IDN_GLOCK_EXCL(); - - if (!DOMAIN_IN_SET(idn.domset.ds_hwlinked, domid)) { - IDN_GUNLOCK(); - return (0); - } - - PR_PROTO("%s:%d: DEprogram hw in domain %d w.r.t remote domain %d\n", - proc, domid, idn.localid, domid); - - /* - * It's possible to come through this flow for domains that - * have not been programmed, i.e. not in idn.hwlinked_domset, - * so don't bother asserting that they might be in there. - * This can occur if we lose a domain during the config/syn - * sequence. If this occurs we won't know whether the remote - * domain has programmed its hardware or not. If it has then - * it will have to go through the DMAP sequence and thus we - * have to go through it also. So, if we reach at least the - * CONFIG state, we need to go through the DMAP handshake. - */ - - PR_PROTO("%s:%d: SUB bset (0x%x)\n", proc, domid, dp->dhw.dh_boardset); - - if (idn.first_hwmasterid == (short)domid) { - is_master = 1; - idn.first_hwmasterid = (short)IDN_NIL_DOMID; - } else { - is_master = 0; - } - rv = idnxf_shmem_sub(is_master, dp->dhw.dh_boardset); - - if (rv == 0) - DOMAINSET_DEL(idn.domset.ds_hwlinked, domid); - - IDN_GUNLOCK(); - - return (rv); -} - -/* - * Remember can't send slabs back to master at this point. - * Entered with write-drwlock held. - * Returns with drwlock dropped. - */ -static void -idn_deconfig(int domid) -{ - idn_domain_t *dp, *ldp; - smr_slab_t *sp; - int c, masterid; - procname_t proc = "idn_deconfig"; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - ASSERT(domid != idn.localid); - - ldp = &idn_domain[idn.localid]; - dp = &idn_domain[domid]; - - ASSERT(dp->dstate == IDNDS_DMAP); - - PR_PROTO("%s:%d: (dio=%d, dioerr=%d, dnslabs=%d)\n", - proc, domid, dp->dio, dp->dioerr, dp->dnslabs); - - IDN_GLOCK_EXCL(); - masterid = IDN_GET_MASTERID(); - - idn.dc_boardset &= ~dp->dhw.dh_boardset; - for (c = 0; c < NCPU; c++) { - if (CPU_IN_SET(dp->dcpuset, c)) { - CPUSET_DEL(idn.dc_cpuset, c); - } - } - - IDN_GUNLOCK(); - - (void) smr_buf_free_all(domid); - - if (idn.localid == masterid) { - /* - * Since I'm the master there may - * have been slabs in this domain's - * idn_domain[] entry. - */ - DSLAB_LOCK_EXCL(domid); - if ((sp = dp->dslab) != NULL) { - PR_PROTO("%s:%d: freeing up %d dead slabs\n", - proc, domid, dp->dnslabs); - smr_slab_free(domid, sp); - dp->dslab = NULL; - dp->dnslabs = 0; - dp->dslab_state = DSLAB_STATE_UNKNOWN; - } - DSLAB_UNLOCK(domid); - } else if (domid == masterid) { - /* - * We're shutting down the master! - * We need to blow away our local slab - * data structures. - * Since I'm not the master, there should - * be no slab structures in the given - * domain's idn_domain[] entry. They should - * only exist in the local domain's entry. - */ - DSLAB_LOCK_EXCL(idn.localid); - ASSERT(dp->dslab == NULL); -#ifdef DEBUG - { - int nbusy = 0; - uint_t dommask = 0; - for (sp = ldp->dslab; sp; sp = sp->sl_next) { - smr_slabbuf_t *bp; - - if (!smr_slab_busy(sp)) - continue; - nbusy++; - for (bp = sp->sl_inuse; bp; bp = bp->sb_next) - if (bp->sb_domid != IDN_NIL_DOMID) - DOMAINSET_ADD(dommask, - bp->sb_domid); - } - if (nbusy) - PR_PROTO("%s:%d: found %d busy slabs " - "(dommask = 0x%x)\n", - proc, domid, nbusy, dommask); - } -#endif /* DEBUG */ - if ((sp = ldp->dslab) != NULL) { - PR_PROTO("%s:%d: freeing up %d local slab " - "structs\n", proc, domid, ldp->dnslabs); - smr_slab_garbage_collection(sp); - ldp->dslab = NULL; - ldp->dnslabs = 0; - ldp->dslab_state = DSLAB_STATE_UNKNOWN; - } - DSLAB_UNLOCK(idn.localid); - } - if (dp->dio) { - PR_PROTO("%s:%d: reset dio (%d) to 0\n", proc, domid, dp->dio); - dp->dio = 0; - } - dp->dioerr = 0; - - PR_PROTO("%s:%d: reset diocheck (%x) to 0\n", - proc, domid, dp->diocheck); - lock_clear(&dp->diocheck); - - CHECKPOINT_CLOSED(IDNSB_CHKPT_LINK, dp->dhw.dh_boardset, 2); - - /* - * Should have already flush our memory before - * reaching this stage. The issue is that by the - * time we reach here the remote domains may have - * already reprogrammed their hardware and so flushing - * out caches now could result in a arbstop/hang - * if we have data that needs to go back to one - * of the remote domains that has already reprogrammed - * its hardware. - */ - ASSERT(!DOMAIN_IN_SET(idn.domset.ds_flush, domid)); - - (void) idn_deprogram_hardware(domid); - /* - * XXX - what to do if we - * fail to program hardware - * probably should panic since - * demise of system may be near? - * Sufficient to just shutdown network? - */ - - IDN_DSTATE_TRANSITION(dp, IDNDS_CLOSED); - - idn_close_domain(domid); -} - -/* - * If we're sending a Reset we better make sure we don't have any - * references or traffic headed in the direction of this guy, since - * when he receives the reset, he'll start shutting down which means - * we effectively have to shutdown _before_ sending the reset. - * DO NOT HOLD ANY DOMAIN RWLOCKS ON ENTRY. Could result in deadlock - * due to channel server looping back through STREAMs and attempting - * to acquire domain lock, i.e. channel server will never "stop". - */ -static void -idn_shutdown_datapath(domainset_t domset, int force) -{ - int do_allchan; - idn_domain_t *dp; - register int d; - procname_t proc = "idn_shutdown_datapath"; - - - PR_CHAN("%s: domset = 0x%x\n", proc, (uint_t)domset); - - do_allchan = (domset == DOMAINSET_ALL) ? 1 : 0; - - DOMAINSET_DEL(domset, idn.localid); - - if (do_allchan) { - /* - * Need to stop all outgoing and - * incoming SMR references. - */ - idn_deactivate_channel(CHANSET_ALL, IDNCHAN_OFFLINE); - } - - /* - * If force is set then we don't want to reference - * the SMR at all, so deactivate the domains from - * channels first. This will result in the mainmbox-flush - * routines to just clean up without referencing the - * SMR space. - */ - if (force) - idn_mainmbox_deactivate(domset); - - /* - * Flush out mailboxes (clear smr reference). - */ - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(domset, d)) - continue; - - dp = &idn_domain[d]; - if ((dp->dmbox.m_send == NULL) && (dp->dmbox.m_recv == NULL)) - continue; - - IDN_MBOX_LOCK(d); - if (dp->dmbox.m_send) - (void) idn_mainmbox_flush(d, dp->dmbox.m_send); - if (dp->dmbox.m_recv) - (void) idn_mainmbox_flush(d, dp->dmbox.m_recv); - IDN_MBOX_UNLOCK(d); - } - /* - * Deactivate all domain references also. - * Only necessary if it wasn't already done above. - */ - if (!force) - idn_mainmbox_deactivate(domset); -} - -void -idn_send_cmd(int domid, idn_cmd_t cmdtype, uint_t arg1, uint_t arg2, uint_t - arg3) -{ - idn_msgtype_t mt; - procname_t proc = "idn_send_cmd"; - - mt.mt_mtype = IDNP_CMD; - mt.mt_atype = 0; - mt.mt_cookie = 0; - - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - PR_PROTO("%s:%d: sending command %s\n", proc, domid, - VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown"); - - IDN_MSGTIMER_START(domid, IDNP_CMD, (ushort_t)cmdtype, - idn_msg_waittime[IDNP_CMD], &mt.mt_cookie); - - IDNXDC(domid, &mt, (uint_t)cmdtype, arg1, arg2, arg3); -} - -void -idn_send_cmdresp(int domid, idn_msgtype_t *mtp, idn_cmd_t cmdtype, uint_t arg1, - uint_t arg2, uint_t cerrno) -{ - idn_msgtype_t mt; - - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - if (domid == idn.localid) { - /* - * It's possible local domain received a command - * from itself. However, we cannot send a normal - * "ack" response (XDC) to ourself. - */ - return; - } - - mt.mt_mtype = IDNP_CMD | IDNP_ACK; - mt.mt_atype = 0; - mt.mt_cookie = mtp->mt_cookie; - - IDNXDC(domid, &mt, (uint_t)cmdtype, arg1, arg2, cerrno); -} - -static void -idn_send_cmd_nackresp(int domid, idn_msgtype_t *mtp, idn_cmd_t cmdtype, - idn_nack_t nacktype) -{ - idn_msgtype_t mt; - - if (domid == idn.localid) - return; - - mt.mt_mtype = IDNP_CMD | IDNP_NACK; - mt.mt_atype = 0; - mt.mt_cookie = mtp->mt_cookie; - - (void) IDNXDC(domid, &mt, (uint_t)cmdtype, (uint_t)nacktype, 0, 0); -} - -void -idn_broadcast_cmd(idn_cmd_t cmdtype, uint_t arg1, uint_t arg2, uint_t arg3) -{ - idn_msgtype_t mt; - domainset_t domset; - procname_t proc = "idn_broadcast_cmd"; - - IDN_GLOCK_SHARED(); - - domset = idn.domset.ds_connected; - DOMAINSET_DEL(domset, idn.localid); - - PR_PROTO("%s: broadcasting command (%s) to domainset 0x%x\n", - proc, VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown", - domset); - - mt.mt_mtype = IDNP_CMD; - mt.mt_atype = 0; - mt.mt_cookie = 0; - - IDNXDC_BROADCAST(domset, &mt, (uint_t)cmdtype, arg1, arg2, arg3); - - IDN_GUNLOCK(); - /* - * This is a broadcast which means local domain needs - * to process it also. Since we can't XDC to ourselves - * we simply call a local function. - */ - idn_local_cmd(cmdtype, arg1, arg2, arg3); -} - -/* - * Since xargs[0] contains the cmdtype, only xargs[1], xargs[2], xargs[3] - * are valid possible response arguments. - */ -static void -idn_recv_cmd(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - uint_t msg = mtp->mt_mtype; - register idn_domain_t *dp; - idn_cmd_t cmdtype; - uint_t acknack; - uint_t cmdarg1, cmdarg2, cmdarg3; - int islocal; - int unsup_cmd_sent, unsup_cmd_recvd; - procname_t proc = "idn_recv_cmd"; - - acknack = msg & IDNP_ACKNACK_MASK; - GET_XARGS(xargs, &cmdtype, &cmdarg1, &cmdarg2, &cmdarg3); - - dp = &idn_domain[domid]; - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - IDN_GLOCK_SHARED(); - - islocal = (domid == idn.localid); - - ASSERT(!acknack || (acknack & IDNP_ACKNACK_MASK)); - - PR_PROTO("%s:%d: (local=%d) acknack=0x%x, cmdtype=%s(%d), " - "a1=0x%x, a2=0x%x, a3=0x%x\n", - proc, domid, islocal, acknack, - VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown", - cmdtype, cmdarg1, cmdarg2, cmdarg3); - - unsup_cmd_sent = unsup_cmd_recvd = 0; - - if ((IDN_GET_MASTERID() == IDN_NIL_DOMID) || - (dp->dstate != IDNDS_CONNECTED)) { - /* - * Commands cannot be handled without a valid - * master. If this is a request then nack him. - */ - PR_PROTO("%s:%d: cannot process CMD w/o master (%d, %s)\n", - proc, domid, IDN_GET_MASTERID(), - idnds_str[dp->dstate]); - - if (!islocal && !(acknack & IDNP_ACKNACK_MASK)) - idn_send_cmd_nackresp(domid, mtp, cmdtype, - IDNNACK_NOCONN); - IDN_GUNLOCK(); - return; - } - IDN_GUNLOCK(); - - if (acknack & IDNP_ACKNACK_MASK) { - idn_nack_t nack; - /* - * Receiving a cmd+ack or cmd+nack in response to some - * earlier command we must have issued. - * If the response is a nack, there are two possibilites: - * - * 1. Remote domain failed to allocate due - * to limited resources. - * - * 2. Remote domain does not support this - * particular command. - * - * In the case of #2, the argument immediately after - * the cmdtype (xargs[1]) will be (-1). - */ - nack = (idn_nack_t)cmdarg1; - if ((acknack & IDNP_NACK) && (nack == IDNNACK_BADCMD)) - unsup_cmd_sent++; - - if (islocal) { - /* - * Shouldn't be receiving local commands w/acks. - */ - cmdtype = (idn_cmd_t)0; - } - - switch (cmdtype) { - case IDNCMD_SLABALLOC: - idn_recv_slaballoc_resp(domid, cmdarg1, cmdarg2, - cmdarg3); - break; - - case IDNCMD_SLABFREE: - idn_recv_slabfree_resp(domid, cmdarg1, cmdarg2, - cmdarg3); - break; - - case IDNCMD_SLABREAP: - /* - * We only care if successful. - */ - if (acknack & IDNP_ACK) - idn_recv_slabreap_resp(domid, cmdarg1, cmdarg3); - break; - - case IDNCMD_NODENAME: - if ((acknack & IDNP_NACK) == 0) { - idn_recv_nodename_resp(domid, cmdarg1, cmdarg3); - break; - } - switch (nack) { - case IDNNACK_NOCONN: - case IDNNACK_RETRY: - /* - * Remote domain was not quite - * ready, try again. - */ - PR_PROTO("%s:%d: remote not ready " - "for %s - retrying " - "[dstate=%s]\n", - proc, domid, - idncmd_str[IDNCMD_NODENAME], - idnds_str[dp->dstate]); - - if (dp->dstate == IDNDS_CONNECTED) - (void) timeout(idn_retry_nodename_req, - (void *)(uintptr_t)domid, hz); - default: - break; - } - break; - - default: - /* - * Unsupported command. - */ - unsup_cmd_recvd++; - break; - } - if (unsup_cmd_sent) { - PR_PROTO("%s:%d: unsupported command " - "requested (0x%x)\n", - proc, domid, cmdtype); - } - if (unsup_cmd_recvd) { - PR_PROTO("%s:%d: unsupported command " - "response (0x%x)\n", - proc, domid, cmdtype); - } - } else { - /* - * Receiving a regular cmd from a remote domain. - */ - switch (cmdtype) { - case IDNCMD_SLABALLOC: - idn_recv_slaballoc_req(domid, mtp, cmdarg1); - break; - - case IDNCMD_SLABFREE: - idn_recv_slabfree_req(domid, mtp, cmdarg1, cmdarg2); - break; - - case IDNCMD_SLABREAP: - idn_recv_slabreap_req(domid, mtp, cmdarg1); - break; - - case IDNCMD_NODENAME: - idn_recv_nodename_req(domid, mtp, cmdarg1); - break; - - default: - /* - * Unsupported command. - */ - unsup_cmd_recvd++; - break; - } - if (!islocal && unsup_cmd_recvd) { - /* - * Received an unsupported IDN command. - */ - idn_send_cmd_nackresp(domid, mtp, cmdtype, - IDNNACK_BADCMD); - } - } -} - -/* - * This is a supporting routine for idn_broadcast_cmd() to - * handle processing of the requested command for the local - * domain. Currently the only support broadcast command - * supported is reaping. - */ -/*ARGSUSED2*/ -static void -idn_local_cmd(idn_cmd_t cmdtype, uint_t arg1, uint_t arg2, uint_t arg3) -{ - idn_protojob_t *jp; - idn_domain_t *ldp = &idn_domain[idn.localid]; - procname_t proc = "idn_local_cmd"; - - PR_PROTO("%s: submitting local command %s on domain %d\n", - proc, VALID_IDNCMD(cmdtype) ? idncmd_str[cmdtype] : "unknown", - idn.localid); - - - jp = idn_protojob_alloc(KM_SLEEP); - - jp->j_msg.m_domid = ldp->domid; - jp->j_msg.m_msgtype = IDNP_CMD; - jp->j_msg.m_cookie = ldp->dcookie_recv; - SET_XARGS(jp->j_msg.m_xargs, cmdtype, arg1, arg2, arg3); - - idn_protojob_submit(ldp->domid, jp); -} - -/* - * Terminate any outstanding commands that may have - * been targeted for the given domain. A command is - * designated as outstanding if it has an active timer. - * - * serrno = ECANCELED. - */ -static void -idn_terminate_cmd(int domid, int serrno) -{ - idn_domain_t *dp; - idn_timer_t *tplist = NULL, *tp; - procname_t proc = "idn_terminate_cmd"; - - dp = &idn_domain[domid]; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - IDN_MSGTIMER_GET(dp, IDNP_CMD, tplist, 0); - /* - * At this point the timers are effectively terminated - * since when they're t_onq indication is set false. - */ - if (tplist == NULL) { - PR_PROTO("%s:%d: no outstanding cmds found\n", - proc, domid); - /* - * There is a window where we may have caught a - * request just prior to issuing the actual - * command (SLABALLOC). We're guaranteed if there - * was, then he will have at least registered. - * So, if we abort the command now, he'll catch - * it before going to sleep. - * Drop through. - */ - } - ASSERT(tplist ? (tplist->t_back->t_forw == NULL) : 1); - - for (tp = tplist; tp; tp = tp->t_forw) { - ASSERT(tp->t_type == IDNP_CMD); - - PR_PROTO("%s:%d: found outstanding cmd: %s\n", - proc, domid, idncmd_str[tp->t_subtype]); - - switch (tp->t_subtype) { - case IDNCMD_SLABALLOC: - /* - * Outstanding slaballoc request may have - * slab waiters hanging around. Need to - * tell them to bail out. The given domain - * must be the master if we have an outstanding - * command to him. This also presumes that - * if there are any waiters they're only in - * the local domain's waiting area (i.e. we're - * a slave). - */ -#ifdef DEBUG - IDN_GLOCK_SHARED(); - ASSERT(domid == IDN_GET_MASTERID()); - ASSERT(idn.localid != IDN_GET_MASTERID()); - IDN_GUNLOCK(); -#endif /* DEBUG */ - (void) smr_slabwaiter_abort(idn.localid, serrno); - break; - - case IDNCMD_SLABFREE: - case IDNCMD_SLABREAP: - case IDNCMD_NODENAME: - /* - * Nothing really waiting for these operations - * so no biggy if we just drop. - * Note that NODENAME may have an outstanding - * buffer, however that will be reclaimed - * when we actually unlink from domain. - */ - break; - - default: - ASSERT(0); - break; - } - } - /* - * As mentioned before the timers are effectively no-op'd - * once they're dequeued, however let's cleanup house and - * get rid of the useless entries in the timeout queue. - */ - if (tplist) { - IDN_TIMER_STOPALL(tplist); - } - - if (idn_domain[idn.localid].dvote.v.master) { - /* - * I'm the master so it's possible I had - * outstanding commands (SLABALLOC) waiting - * to be satisfied for the given domain. - * Since we're forcing an error it's okay - * to continue holding onto the drwlock. - */ - PR_PROTO("%s:%d: abort slaballoc waiters\n", proc, domid); - (void) smr_slabwaiter_abort(domid, serrno); - - } else if (dp->dvote.v.master) { - PR_PROTO("%s:%d: abort (local domain) slaballoc waiters\n", - proc, domid); - (void) smr_slabwaiter_abort(idn.localid, serrno); - } -} - -static void -idn_send_acknack(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_send_acknack"; - - ASSERT(mtp ? (mtp->mt_mtype & IDNP_ACKNACK_MASK) : 1); - ASSERT(domid != IDN_NIL_DOMID); - -#ifdef DEBUG - { - STRING(mstr); - STRING(astr); - - INUM2STR(mtp->mt_mtype, mstr); - INUM2STR(mtp->mt_atype, astr); - - if (mtp->mt_mtype & IDNP_ACK) { - PR_PROTO("%s:%d: dstate=%s, msg=(%s/%s), " - "a1=0x%x, a2=0x%x, a3=0x%x, a4 = 0x%x\n", - proc, domid, idnds_str[dp->dstate], - astr, mstr, xargs[0], xargs[1], - xargs[2], xargs[3]); - } else { - idn_nack_t nack; - - nack = GET_XARGS_NACK_TYPE(xargs); - PR_PROTO("%s:%d: dstate=%s, msg=(%s/%s), " - "nack=%s(0x%x)\n", - proc, domid, idnds_str[dp->dstate], - astr, mstr, idnnack_str[nack], - (uint_t)nack); - } - } -#endif /* DEBUG */ - - (void) IDNXDC(domid, mtp, xargs[0], xargs[1], xargs[2], xargs[3]); -} - -/*ARGSUSED0*/ -static void -idn_prealloc_slab(int nslabs) -{ - register int s, serrno; - smr_slab_t *sp; - idn_domain_t *ldp = &idn_domain[idn.localid]; - procname_t proc = "idn_prealloc_slab"; - - IDN_GLOCK_SHARED(); - DSLAB_LOCK_SHARED(idn.localid); - if ((idn.state != IDNGS_ONLINE) || (ldp->dnslabs > 0)) { - /* - * Not in the proper state or slab already allocated. - */ - DSLAB_UNLOCK(idn.localid); - IDN_GUNLOCK(); - return; - } - IDN_GUNLOCK(); - ASSERT(!ldp->dslab); - - serrno = 0; - for (s = 0; (s < nslabs) && ((int)ldp->dnslabs < nslabs); s++) { - /* - * Returns with ldp->drwlock dropped. - */ - serrno = smr_slab_alloc(idn.localid, &sp); - if (serrno != 0) { - PR_PROTO("%s: FAILED to pre-alloc'd " - "slab (serrno = %d)\n", proc, serrno); - break; - } - /* - * State may have changed since smr_slab_alloc - * temporarily drops drwlock. Make sure we're - * still connected. - */ - PR_PROTO("%s: SUCCESSFULLY pre-alloc'd slab\n", proc); - - if (idn.state != IDNGS_ONLINE) { - PR_PROTO("%s: Lost connection..leaving\n", proc); - break; - } - } - - DSLAB_UNLOCK(idn.localid); -} - -/* - * Received a request from a remote domain to - * allocate a slab from the master SMR for him. - * Allocate slab and return the response. - */ -static void -idn_recv_slaballoc_req(int domid, idn_msgtype_t *mtp, uint_t slab_size) -{ - register idn_domain_t *dp; - procname_t proc = "idn_recv_slaballoc_req"; - - PR_PROTO("%s: slaballoc req from domain %d (size=0x%x)\n", - proc, domid, slab_size); - - dp = &idn_domain[domid]; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - IDN_GLOCK_SHARED(); - - if (idn.localid != IDN_GET_MASTERID()) { - IDN_GUNLOCK(); - /* - * It's a fatal error if the remote domain thinks - * we're the master. - */ - idn_send_slaballoc_resp(domid, mtp, 0, 0, EACCES); - - } else if (dp->dstate != IDNDS_CONNECTED) { - - IDN_GUNLOCK(); - /* - * It's a fatal error if we don't yet have a - * connection established with the requestor. - */ - idn_send_slaballoc_resp(domid, mtp, 0, 0, ENOLINK); - } else { - int serrno; - smr_slab_t *sp; - smr_offset_t slab_offset; - - IDN_GUNLOCK(); - DSLAB_LOCK_SHARED(domid); - IDN_DUNLOCK(domid); - /* - * We're connected and we're the master. - * smr_slab_alloc() returns with dp->drwlock dropped. - */ - if ((serrno = smr_slab_alloc(domid, &sp)) == 0) { - /* - * Successfully allocated slab for remote slave. - */ - slab_offset = IDN_ADDR2OFFSET(sp->sl_start); - slab_size = sp->sl_end - sp->sl_start; - ASSERT((slab_offset != 0) && (slab_size != 0)); - } else { - slab_offset = slab_size = 0; - } - DSLAB_UNLOCK(domid); - /* - * The drwlock is dropped during smr_slab_alloc. - * During that time our connection with the given - * domain may have changed. Better check again. - */ - IDN_DLOCK_SHARED(domid); - if ((dp->dstate != IDNDS_CONNECTED) && !serrno) { - /* - * Connection broke. Keep the slab here. - */ - DSLAB_LOCK_EXCL(domid); - IDN_DUNLOCK(domid); - smr_slab_free(domid, sp); - DSLAB_UNLOCK(domid); - slab_offset = slab_size = 0; - serrno = ECANCELED; - IDN_DLOCK_SHARED(domid); - } - /* - * Send response. - * Note that smr_slab_alloc automatically installs - * slab into domains respective idn_domain entry - * to be associated with that domain. - */ - idn_send_slaballoc_resp(domid, mtp, slab_offset, slab_size, - serrno); - } -} - -static void -idn_send_slaballoc_resp(int domid, idn_msgtype_t *mtp, smr_offset_t slab_offset, - uint_t slab_size, int serrno) -{ - procname_t proc = "idn_send_slaballoc_resp"; - - PR_PROTO("%s: slaballoc resp to domain %d (off=0x%x, size=0x%x) " - "[serrno = %d]\n", - proc, domid, slab_offset, slab_size, serrno); - - idn_send_cmdresp(domid, mtp, IDNCMD_SLABALLOC, slab_offset, slab_size, - serrno); -} - -/* - * Received the ack or nack to a previous allocation request - * made by the local domain to the master for a slab. Need - * to "put" the response into the waiting area for any - * waiters. - */ -static void -idn_recv_slaballoc_resp(int domid, smr_offset_t slab_offset, uint_t slab_size, - int serrno) -{ - smr_slab_t *sp = NULL; - int rv; - procname_t proc = "idn_recv_slaballoc_resp"; - - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - PR_PROTO("%s: slaballoc resp from domain %d (off=0x%x, size=0x%x) " - "[serrno = %d]\n", - proc, domid, slab_offset, slab_size, serrno); - - if (!serrno) { - IDN_GLOCK_SHARED(); - if (domid != IDN_GET_MASTERID()) { - /* - * We should only be receiving responses from - * our master. This is either a bogus message - * or an old response. In either case dump it. - */ - PR_PROTO("%s: BOGUS slaballoc resp from domid %d " - "(master = %d)\n", - proc, domid, IDN_GET_MASTERID()); - serrno = EPROTO; - } - IDN_GUNLOCK(); - - if (!serrno && - !VALID_NWROFFSET(slab_offset, IDN_SMR_BUFSIZE)) { - PR_PROTO("%s: slab offset (0x%x) out of range " - "(0-0x%lx)\n", - proc, slab_offset, MB2B(IDN_NWR_SIZE)); - serrno = EPROTO; - } else if (!serrno) { - sp = GETSTRUCT(smr_slab_t, 1); - sp->sl_start = IDN_OFFSET2ADDR(slab_offset); - sp->sl_end = sp->sl_start + slab_size; - smr_alloc_buflist(sp); - } - } - - /* - * Always "put" slabs back to yourself since you're a slave. - * Note that we set the forceflag so that even if there are - * no waiters we still install the slab for the domain. - */ - if (!serrno) { - DSLAB_LOCK_EXCL(idn.localid); - } - rv = smr_slaballoc_put(idn.localid, sp, 1, serrno); - if (!serrno) { - DSLAB_UNLOCK(idn.localid); - } - - if (rv < 0) { - /* - * Some kind of error trying to install response. - * If there was a valid slab sent to us, we'll - * just have to send it back. - */ - PR_PROTO("%s: failed to install response in waiting area\n", - proc); - if (slab_size != 0) { - PR_PROTO("%s: sending slab back to domain %d " - "(master = %d)\n", - proc, domid, IDN_GET_MASTERID()); - idn_send_cmd(domid, IDNCMD_SLABFREE, slab_offset, - slab_size, 0); - } - if (sp) { - smr_free_buflist(sp); - FREESTRUCT(sp, smr_slab_t, 1); - } - } -} - -/* - * Note that slab reaping is effectively performed asynchronously - * since the request will be received a protocol server. - */ -static void -idn_recv_slabreap_req(int domid, idn_msgtype_t *mtp, int nslabs) -{ - procname_t proc = "idn_recv_slabreap_req"; - - PR_PROTO("%s: slab reap request (nslabs = %d)\n", proc, nslabs); - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - IDN_GLOCK_SHARED(); - if (domid != IDN_GET_MASTERID()) { - /* - * Only the master can request that slabs be reaped. - */ - IDN_GUNLOCK(); - PR_PROTO("%s: only master can request slab reaping\n", proc); - - idn_send_cmdresp(domid, mtp, IDNCMD_SLABREAP, 0, 0, EACCES); - - return; - } - IDN_GUNLOCK(); - - if (nslabs != 0) { - IDN_DUNLOCK(domid); - smr_slab_reap(idn.localid, &nslabs); - IDN_DLOCK_SHARED(domid); - } - - PR_PROTO("%s: slab reap result (nslabs = %d)\n", proc, nslabs); - - /* - * Go ahead and send the reap response back before we start - * free'ing off the individual slabs. - */ - idn_send_slabreap_resp(domid, mtp, nslabs, 0); -} - -static void -idn_recv_slabreap_resp(int domid, int nslabs, int serrno) -{ - procname_t proc = "idn_recv_slabreap_resp"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if ((idn.localid != IDN_GET_MASTERID()) || (idn.localid == domid)) { - PR_PROTO("%s: unexpected slabreap resp received " - "(domid = %d)\n", proc, domid); - ASSERT(0); - return; - } - PR_PROTO("%s: recvd reap response from domain %d for %d slabs " - "[serrno = %d]\n", proc, domid, nslabs, serrno); -} - -/* - * Not really necessary to send slabreap response. - * XXX - perhaps useful to master for accounting or - * throttling of further reaping? - */ -static void -idn_send_slabreap_resp(int domid, idn_msgtype_t *mtp, int nslabs, int serrno) -{ - idn_send_cmdresp(domid, mtp, IDNCMD_SLABREAP, nslabs, 0, serrno); -} - -/* - * Slave -> Master ONLY - * Master never sends slabfree request to itself. - */ -static void -idn_recv_slabfree_req(int domid, idn_msgtype_t *mtp, smr_offset_t slab_offset, - uint_t slab_size) -{ - smr_slab_t *sp; - int serrno; - caddr_t s_start, s_end; - procname_t proc = "idn_recv_slabfree_req"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (domid == IDN_GET_MASTERID()) { - PR_PROTO("%s: unexpected slabfree req received (domid = %d)\n", - proc, domid); - idn_send_slabfree_resp(domid, mtp, slab_offset, slab_size, - EACCES); - return; - } - if (slab_size > IDN_SLAB_SIZE) { - PR_PROTO("%s: unexpected slab size. exp %d, recvd %d\n", - proc, IDN_SLAB_SIZE, slab_size); - idn_send_slabfree_resp(domid, mtp, slab_offset, slab_size, - EINVAL); - return; - } - s_start = IDN_OFFSET2ADDR(slab_offset); - s_end = s_start + slab_size; - /* - * Master has received a SLABFREE request (effectively a response - * to some earlier SLABREAP request. - * Find the slab associated with this slab and free it up. - */ - DSLAB_LOCK_EXCL(domid); - if ((sp = smr_slaballoc_get(domid, s_start, s_end)) != NULL) { - smr_slab_free(domid, sp); - serrno = 0; - } else { - serrno = EINVAL; - } - DSLAB_UNLOCK(domid); - - idn_send_slabfree_resp(domid, mtp, slab_offset, slab_size, serrno); -} - -/* - * Master -> Slave ONLY - */ -static void -idn_recv_slabfree_resp(int domid, uint_t slab_offset, uint_t slab_size, int - serrno) -{ - procname_t proc = "idn_recv_slabfree_resp"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (domid != IDN_GET_MASTERID()) { - PR_PROTO("%s: unexpected slabfree resp received (domid = %d)\n", - proc, domid); - ASSERT(0); - return; - } - if (slab_size > IDN_SLAB_SIZE) { - PR_PROTO("%s: unexpected slab size. exp %d, recvd %d\n", - proc, IDN_SLAB_SIZE, slab_size); - ASSERT(0); - return; - } - PR_PROTO("%s: recvd free resp from dom %d " - "- slab (off/size) 0x%x/0x%x [serrno = %d]\n", - proc, domid, slab_offset, slab_size, serrno); -} - -static void -idn_send_slabfree_resp(int domid, idn_msgtype_t *mtp, uint_t slab_offset, - uint_t slab_size, int serrno) -{ - idn_send_cmdresp(domid, mtp, IDNCMD_SLABFREE, slab_offset, slab_size, - serrno); -} - -static void -idn_retry_nodename_req(void *arg) -{ - int domid = (int)(uintptr_t)arg; - - idn_send_nodename_req(domid); -} - -static void -idn_send_nodename_req(int domid) -{ - caddr_t b_bufp; - smr_offset_t bufoffset; - int serrno; - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_send_nodename_req"; - - /* - * Need to drop domain lock across - * SMR allocation. - */ - serrno = smr_buf_alloc(domid, MAXDNAME+1, &b_bufp); - - IDN_DLOCK_SHARED(domid); - if (dp->dstate != IDNDS_CONNECTED) { - /* - * Lost connection. - */ - PR_PROTO("%s:%d: connection lost [dstate = %s]\n", - proc, domid, idnds_str[dp->dstate]); - IDN_DUNLOCK(domid); - if (!serrno) - (void) smr_buf_free(domid, b_bufp, MAXDNAME+1); - return; - } - if (serrno) { - /* - * Failed to allocate buffer, but still have - * connection so keep trying. We may have queried - * the master a little too earlier. - */ - PR_PROTO("%s:%d: buffer alloc failed [dstate = %s]\n", - proc, domid, idnds_str[dp->dstate]); - (void) timeout(idn_retry_nodename_req, (void *)(uintptr_t)domid, - hz); - IDN_DUNLOCK(domid); - return; - } - - *b_bufp = (char)MAXDNAME; - bufoffset = IDN_ADDR2OFFSET(b_bufp); - - idn_send_cmd(domid, IDNCMD_NODENAME, bufoffset, 0, 0); - IDN_DUNLOCK(domid); -} - -static void -idn_send_nodename_resp(int domid, idn_msgtype_t *mtp, smr_offset_t bufoffset, - int serrno) -{ - idn_send_cmdresp(domid, mtp, IDNCMD_NODENAME, (uint_t)bufoffset, 0, - serrno); -} - -static void -idn_recv_nodename_req(int domid, idn_msgtype_t *mtp, smr_offset_t bufoffset) -{ - caddr_t b_bufp; - int length; - idn_domain_t *ldp = &idn_domain[idn.localid]; - procname_t proc = "idn_recv_nodename_req"; - - IDN_DLOCK_EXCL(idn.localid); - if (!strlen(ldp->dname)) { - if (!strlen(utsname.nodename)) { - /* - * Local domain's nodename hasn't been - * set yet. - */ - IDN_DUNLOCK(idn.localid); - idn_send_cmd_nackresp(domid, mtp, IDNCMD_NODENAME, - IDNNACK_RETRY); - return; - } - (void) strncpy(ldp->dname, utsname.nodename, MAXDNAME - 1); - } - IDN_DLOCK_DOWNGRADE(idn.localid); - - if (!VALID_NWROFFSET(bufoffset, IDN_SMR_BUFSIZE)) { - PR_PROTO("%s:%d: invalid SMR offset received (0x%x)\n", - proc, domid, bufoffset); - IDN_DUNLOCK(idn.localid); - idn_send_nodename_resp(domid, mtp, bufoffset, EINVAL); - return; - } - - b_bufp = IDN_OFFSET2ADDR(bufoffset); - length = (int)(*b_bufp++ & 0xff); - - if (length < strlen(ldp->dname)) { - PR_PROTO("%s:%d: buffer not big enough (req %lu, got %d)\n", - proc, domid, strlen(ldp->dname), length); - IDN_DUNLOCK(idn.localid); - idn_send_nodename_resp(domid, mtp, bufoffset, EINVAL); - return; - } - - (void) strncpy(b_bufp, ldp->dname, MAXDNAME); - b_bufp[MAXDNAME-1] = 0; - IDN_DUNLOCK(idn.localid); - - idn_send_nodename_resp(domid, mtp, bufoffset, 0); -} - -static void -idn_recv_nodename_resp(int domid, smr_offset_t bufoffset, int serrno) -{ - caddr_t b_bufp; - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_recv_nodename_resp"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - if (!VALID_NWROFFSET(bufoffset, IDN_SMR_BUFSIZE)) { - PR_PROTO("%s:%d: invalid SMR offset received (0x%x)\n", - proc, domid, bufoffset); - return; - } - - if (serrno == 0) { - b_bufp = IDN_OFFSET2ADDR(bufoffset) + 1; - b_bufp[MAXDNAME-1] = 0; - - if (strlen(b_bufp) > 0) { - (void) strncpy(dp->dname, b_bufp, MAXDNAME); - PR_PROTO("%s:%d: received nodename(%s)\n", - proc, domid, dp->dname); - } - } - - (void) smr_buf_free(domid, b_bufp - 1, MAXDNAME + 1); -} - -/* - * The master allocations the SMR management structures. - */ -static int -idn_master_init() -{ - idn_domain_t *ldp = &idn_domain[idn.localid]; - size_t reserved_size = 0; - caddr_t reserved_area = NULL; - procname_t proc = "idn_master_init"; - - ASSERT(IDN_GLOCK_IS_EXCL()); - ASSERT(IDN_DLOCK_IS_EXCL(idn.localid)); - - if (idn.mboxarea != NULL) { - PR_PROTO("%s: master data already initialized\n", proc); - return (0); - } - - PR_PROTO("%s: initializing master data (domid = %d)\n", - proc, idn.localid); - - /* - * Reserve an area of the SMR for mailbox usage. - * This area is allocated to other domains via - * the master. Round it up to IDN_SMR_BUFSIZE multiple. - */ - reserved_size = IDNROUNDUP(IDN_MBOXAREA_SIZE, IDN_SMR_BUFSIZE); - - PR_PROTO("%s: reserving %lu bytes for mailbox area\n", - proc, reserved_size); - -#ifdef DEBUG - if (reserved_size > (size_t)IDN_SLAB_SIZE) { - PR_PROTO("%s: WARNING mbox area (%ld) > slab size (%d)\n", - proc, reserved_size, IDN_SLAB_SIZE); - } -#endif /* DEBUG */ - /* - * Initialize the pool of slabs and SMR I/O buffers. - */ - if (smr_slabpool_init(reserved_size, &reserved_area) != 0) { - idn_master_deinit(); - return (-1); - } - - ASSERT(idn.mboxarea == NULL); - ASSERT(reserved_area); - - bzero(reserved_area, reserved_size); - - idn.mboxarea = (idn_mboxtbl_t *)reserved_area; - ldp->dmbox.m_tbl = IDN_MBOXAREA_BASE(idn.mboxarea, idn.localid); - /* - * Initialize the SMR pointers in the entire - * mailbox table. - */ - idn_mboxarea_init(idn.mboxarea, IDN_MBOXAREA_SIZE / IDN_MBOXTBL_SIZE); - - return (0); -} - -static void -idn_master_deinit() -{ - idn_domain_t *ldp; - smr_slab_t *sp; - procname_t proc = "idn_master_deinit"; - - ASSERT(IDN_GLOCK_IS_EXCL()); - ASSERT(IDN_DLOCK_IS_EXCL(idn.localid)); - - if (idn.mboxarea == NULL) { - PR_PROTO("%s: master data already deinitialized\n", proc); - return; - } - - ldp = &idn_domain[idn.localid]; - - PR_PROTO("%s: deinitializing master data (domid = %d)\n", - proc, idn.localid); - - ldp->dmbox.m_tbl = NULL; - idn.mboxarea = NULL; - /* - * Master may still be holding onto slabs of his own. - */ - DSLAB_LOCK_EXCL(idn.localid); - sp = ldp->dslab; - ldp->dslab = NULL; - ldp->dnslabs = 0; - if (sp) - smr_slab_free(idn.localid, sp); - ldp->dslab_state = DSLAB_STATE_UNKNOWN; - DSLAB_UNLOCK(idn.localid); - - smr_slabpool_deinit(); -} - -static int -idn_mark_awol(int domid, clock_t *atime) -{ - clock_t awol; - idn_domain_t *dp = &idn_domain[domid]; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_GLOCK_IS_EXCL()); - - if (!DOMAIN_IN_SET(idn.domset.ds_awol, domid)) { - DOMAINSET_ADD(idn.domset.ds_awol, domid); - idn.nawols++; - } - awol = ddi_get_lbolt(); - if (dp->dawol.a_count++ == 0) - dp->dawol.a_time = awol; - dp->dawol.a_last = awol; - if ((awol - dp->dawol.a_msg) >= (clock_t)(idn_awolmsg_interval * hz)) - dp->dawol.a_msg = awol; - else - awol = 0; - - *atime = awol; - - idn_awol_event_set(dp->dhw.dh_boardset); - - return (dp->dawol.a_count); -} - -void -idn_clear_awol(int domid) -{ - idn_domain_t *dp = &idn_domain[domid]; - - ASSERT(IDN_SYNC_IS_LOCKED()); - ASSERT(IDN_GLOCK_IS_EXCL()); - if (DOMAIN_IN_SET(idn.domset.ds_awol, domid)) { - DOMAINSET_DEL(idn.domset.ds_awol, domid); - idn.nawols--; - } - if (dp->dawol.a_count > 0) { - dp->dawol.a_count = 0; - dp->dawol.a_last = dp->dawol.a_time; - dp->dawol.a_time = 0; - dp->dawol.a_msg = 0; - - idn_awol_event_clear(dp->dhw.dh_boardset); - } -} - -/* - * A timer expired. - */ -void -idn_timer_expired(void *arg) -{ - idn_domain_t *dp; - char *op = "UNKNOWN"; - clock_t awol = 0; - int awolcount, dcpu, domid; - idn_timer_t *tp = (idn_timer_t *)arg; - idn_timerq_t *tq = NULL; - uint_t token; - char dname[MAXDNAME]; - procname_t proc = "idn_timer_expired"; - STRING(str); - - tq = tp->t_q; - - ASSERT(tp->t_domid != IDN_NIL_DOMID); - - IDN_TIMERQ_LOCK(tq); - - INUM2STR(tp->t_type, str); - - if (tp->t_onq == 0) { - PR_TIMER("%s: timer CAUGHT TERMINATION (type = %s)\n", - proc, str); - /* - * Timer was dequeued. Somebody is trying - * to shut it down. - */ - IDN_TIMERQ_UNLOCK(tq); - return; - } - - IDN_TIMER_DEQUEUE(tq, tp); - - IDN_TIMERQ_UNLOCK(tq); - - IDN_SYNC_LOCK(); - IDN_DLOCK_EXCL(tp->t_domid); - - domid = tp->t_domid; - - dp = &idn_domain[domid]; - (void) strcpy(dname, dp->dname); - dcpu = dp->dcpu; - - IDN_TIMER_EXEC(tp); - -#ifdef DEBUG - PR_TIMER("%s:%d: [%s] timer EXPIRED (C=0x%x, P=0x%llx, X=0x%llx)\n", - proc, tp->t_domid, str, tp->t_cookie, - tp->t_posttime, tp->t_exectime); -#endif /* DEBUG */ - - /* - * IMPORTANT: - * Each case is responsible for dropping SYNC_LOCK & DLOCK. - */ - switch (tp->t_type) { - case IDNP_DATA: - IDN_SYNC_UNLOCK(); - /* - * Timed out waiting for a data packet response. - * We can't close domain since he may just be - * temporarily AWOL. - * Note that dio and diocheck do not get cleared. - * This is taken care of when the domain restarts - * or is fatally closed. - * We only need a reader lock for this. - */ - IDN_DLOCK_DOWNGRADE(domid); - if (dp->diocheck && dp->dmbox.m_send) { - (void) idn_reclaim_mboxdata(domid, 0, -1); - if (dp->dio >= IDN_WINDOW_EMAX) { - idn_msgtype_t mt; - /* - * Restart timer for another - * go around. - */ - IDN_MSGTIMER_START(domid, IDNP_DATA, 0, - idn_msg_waittime[IDNP_DATA], - &mt.mt_cookie); - } else { - lock_clear(&dp->diocheck); - } - } - IDN_DUNLOCK(domid); - break; - - case IDNP_NEGO: - /* - * If we're not in a NEGO transition, then - * just ignore this timeout. - */ - if (dp->dxp == &xphase_nego) { - uint_t token; - - IDN_GLOCK_EXCL(); - op = "CONNECT"; - awolcount = idn_mark_awol(domid, &awol); - IDN_GUNLOCK(); - - idn_nego_cleanup_check(domid, IDN_NIL_DOMID, - IDN_NIL_DCPU); - - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - token = IDN_RETRY_TOKEN(domid, IDNRETRY_NEGO); - idn_retry_submit(idn_retry_nego, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_NEGO]); - } - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - - case IDNP_CMD: - /* - * Timeouts on commands typically mean that the - * the master is not responding. Furthermore, we - * can't FORCE a FIN disconnect since at this stage - * we are CONNECTED and thus other domains may - * have cache entries that we're sharing with them. - * Only choice is to completely disconnect from - * IDN and try to reestablish connection. - * - * However, timeouts attempting to get nodename - * are not fatal. Although we don't want to retry - * either since each timeout is a lost buffer to - * the remote domain. - */ - if (tp->t_subtype == (ushort_t)IDNCMD_NODENAME) { - PR_PROTO("%s:%d: timedout waiting for nodename\n", - proc, domid); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - } - - IDN_GLOCK_EXCL(); - if (idn.state == IDNGS_ONLINE) { - domainset_t domset; - int masterid = IDN_GET_MASTERID(); - - IDN_GKSTAT_GLOBAL_EVENT(gk_reconfigs, - gk_reconfig_last); - - PR_PROTO("%s:%d: RECONFIG trying old masterid = %d\n", - proc, domid, masterid); - - IDN_GSTATE_TRANSITION(IDNGS_RECONFIG); - IDN_SET_NEW_MASTERID(masterid); - IDN_GUNLOCK(); - IDN_DUNLOCK(domid); - - domset = idn.domset.ds_trans_on | - idn.domset.ds_connected; - - idn_unlink_domainset(domset, IDNFIN_NORMAL, - IDNFIN_ARG_NONE, IDNFIN_OPT_RELINK, BOARDSET_ALL); - } else { - IDN_GUNLOCK(); - IDN_DUNLOCK(domid); - } - IDN_SYNC_UNLOCK(); - break; - - case IDNP_CON: - if (tp->t_subtype == (ushort_t)IDNCON_QUERY) { - /* - * Timed out sending a CON-query. This is - * non-fatal. We simply need to retry. - */ - IDN_GLOCK_EXCL(); - op = "CONNECT"; - awolcount = idn_mark_awol(domid, &awol); - IDN_GUNLOCK(); - token = IDN_RETRY_TOKEN(domid, IDNRETRY_CONQ); - idn_retry_submit(idn_retry_query, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_CONQ]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - } - /*FALLTHROUGH*/ - case IDNP_CFG: - /* - * Any timeouts here we simply try to disconnect - * and reestablish the link. Since we haven't - * reached the connected state w.r.t. this domain - * we put his fin state to FORCE-HARD in order - * to shoot right through without involving other - * domains. Recall that other domains may have - * established connections with the given domain - * which means any FIN queries to them will always - * return connected to the given domain. Since - * neither the given domain nor the local domain - * plan on disconnecting from the IDN the connection - * to the other domains will remain thereby preventing - * the local FIN from ever completing. Recall that - * a FIN depends on all member domains FIN'ing also. - */ - IDN_GLOCK_EXCL(); - op = "CONNECT"; - awolcount = idn_mark_awol(domid, &awol); - IDN_GUNLOCK(); - DOMAINSET_ADD(idn.domset.ds_relink, domid); - IDN_HISTORY_LOG(IDNH_RELINK, domid, dp->dstate, - idn.domset.ds_relink); - (void) idn_disconnect(domid, IDNFIN_FORCE_SOFT, - IDNFIN_ARG_NONE, IDNFIN_SYNC_NO); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - - case IDNP_FIN: - /* - * Timeouts here simply try to retry. - */ - IDN_GLOCK_EXCL(); - op = "DISCONNECT"; - awolcount = idn_mark_awol(domid, &awol); - IDN_GUNLOCK(); - if (tp->t_subtype == (ushort_t)IDNFIN_QUERY) { - int d; - domainset_t rdyset; - /* - * Timed out sending a FIN-query. This is - * non-fatal. We simply need to retry. - * If we were doing a forced unlink of any - * domains, we don't want this awol guy - * to hold us up. Looks for any forced - * unlinks and make them "ready" with - * respect to this awol domain. - */ - rdyset = 0; - for (d = 0; d < MAX_DOMAINS; d++) { - if (FIN_IS_FORCE(idn_domain[d].dfin)) { - DOMAINSET_ADD(rdyset, d); - } - } - if (rdyset) - (void) idn_sync_register(domid, - IDNSYNC_DISCONNECT, - rdyset, IDNSYNC_REG_REG); - - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FINQ); - idn_retry_submit(idn_retry_query, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FINQ]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - } - - if (dp->dfin == IDNFIN_FORCE_SOFT) { - IDN_FSTATE_TRANSITION(dp, IDNFIN_FORCE_HARD); - } - /* - * Anybody that was waiting on this domain and - * had a hard-force in action gets this guy for - * free in their base ready-set. - */ - idn_sync_register_awol(domid); - - dp->dxp = &xphase_fin; - IDN_XSTATE_TRANSITION(dp, IDNXS_PEND); - token = IDN_RETRY_TOKEN(domid, IDNRETRY_FIN); - idn_retry_submit(idn_retry_fin, NULL, token, - idn_msg_retrytime[(int)IDNRETRY_FIN]); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - - default: - - ASSERT(0); - IDN_DUNLOCK(domid); - IDN_SYNC_UNLOCK(); - break; - } - - IDN_TIMER_FREE(tp); - - if (awol) { - if (strlen(dname) > 0) { - cmn_err(CE_WARN, - "IDN: 236: domain (%s) [ID %d] not " - "responding to %s [#%d]", - dname, domid, op, awolcount); - } else { - cmn_err(CE_WARN, - "IDN: 236: domain [ID %d, CPU %d] not " - "responding to %s [#%d]", - domid, dcpu, op, awolcount); - } - } -} - -#if 0 -static int -idn_retry_check(uint_t token) -{ - int i, count = 0; - int domid = IDN_RETRY_TOKEN2DOMID(token); - int key = IDN_RETRY_TOKEN2TYPE(token); - idn_retry_job_t *rp; - idn_retry_queue_t *qp; - - qp = &idn.retryqueue; - - mutex_enter(&qp->rq_mutex); - - for (i = 0, rp = qp->rq_jobs; i < qp->rq_count; i++, rp = rp->rj_next) - if ((domid == IDN_RETRY_TOKEN2DOMID(rp->rj_token)) && - ((key == IDN_RETRY_TYPEALL) || (rp->rj_token == token))) - count++; - - mutex_exit(&qp->rq_mutex); - - return (count); -} -#endif /* 0 */ - -static void -idn_retry_execute(void *arg) -{ - idn_retry_job_t *rp = (idn_retry_job_t *)arg; - idn_retry_queue_t *qp; - - qp = &idn.retryqueue; - - mutex_enter(&qp->rq_mutex); - if (rp->rj_onq == 0) { - /* - * Job has already been claimed by - * retry termination routine. - * Bail out. - */ - mutex_exit(&qp->rq_mutex); - return; - } - rp->rj_next->rj_prev = rp->rj_prev; - rp->rj_prev->rj_next = rp->rj_next; - if (--(qp->rq_count) == 0) - qp->rq_jobs = NULL; - else if (qp->rq_jobs == rp) - qp->rq_jobs = rp->rj_next; - mutex_exit(&qp->rq_mutex); - - (*rp->rj_func)(rp->rj_token, rp->rj_arg); - - IDNRETRY_FREEJOB(rp); -} - -/* - * - */ -static void -idn_retry_submit(void (*func)(uint_t token, void *arg), void *arg, uint_t token, - clock_t ticks) -{ - idn_retry_job_t *rp, *cp; - idn_retry_queue_t *qp; - int c; - procname_t proc = "idn_retry_submit"; - - if (ticks < 0) { - PR_PROTO("%s: (token = 0x%x) WARNING ticks = %ld\n", - proc, token, ticks); - return; - } - if (ticks == 0) /* At least one tick to get into background */ - ticks++; - - PR_PROTO("%s: token = 0x%x\n", proc, token); - - qp = &idn.retryqueue; - - mutex_enter(&qp->rq_mutex); - for (c = 0, cp = qp->rq_jobs; c < qp->rq_count; cp = cp->rj_next, c++) { - if (cp->rj_token == token) { - PR_PROTO("%s: token = (%d,0x%x) already present\n", - proc, IDN_RETRY_TOKEN2DOMID(token), - IDN_RETRY_TOKEN2TYPE(token)); - break; - } - } - - if (c < qp->rq_count) { - mutex_exit(&qp->rq_mutex); - return; - } - - rp = IDNRETRY_ALLOCJOB(); - rp->rj_func = func; - rp->rj_arg = arg; - rp->rj_token = token; - rp->rj_prev = rp->rj_next = rp; - - if (qp->rq_jobs == NULL) { - qp->rq_jobs = rp; - } else { - rp->rj_next = qp->rq_jobs; - rp->rj_prev = qp->rq_jobs->rj_prev; - rp->rj_next->rj_prev = rp; - rp->rj_prev->rj_next = rp; - } - rp->rj_onq = 1; - qp->rq_count++; - rp->rj_id = timeout(idn_retry_execute, (caddr_t)rp, ticks); - mutex_exit(&qp->rq_mutex); -} - -int -idn_retry_terminate(uint_t token) -{ - int i, domid; - uint_t key, count; - idn_retry_job_t *rp, *nrp, *fp; - idn_retry_queue_t *qp; - procname_t proc = "idn_retry_terminate"; - - key = IDN_RETRY_TOKEN2TYPE(token); - domid = IDN_RETRY_TOKEN2DOMID(token); - fp = NULL; - qp = &idn.retryqueue; - - mutex_enter(&qp->rq_mutex); - for (i = count = 0, rp = qp->rq_jobs; i < qp->rq_count; i++) { - nrp = rp->rj_next; - if ((domid == IDN_RETRY_TOKEN2DOMID(rp->rj_token)) && - ((key == IDN_RETRY_TYPEALL) || - (rp->rj_token == token))) { - /* - * Turn off onq field as a signal to - * the execution routine that this - * retry has been terminated. This - * is necessary since we can't untimeout - * while holding the rq_mutex otherwise - * we'll deadlock with the execution - * routine. We'll untimeout these guys - * _after_ we drop rq_mutex. - */ - rp->rj_onq = 0; - rp->rj_next->rj_prev = rp->rj_prev; - rp->rj_prev->rj_next = rp->rj_next; - if (qp->rq_jobs == rp) - qp->rq_jobs = rp->rj_next; - rp->rj_next = fp; - fp = rp; - count++; - } - rp = nrp; - } - - if ((qp->rq_count -= count) == 0) - qp->rq_jobs = NULL; - - mutex_exit(&qp->rq_mutex); - - PR_PROTO("%s: token = (%d,0x%x), dequeued = %d\n", - proc, domid, key, count); - - for (; fp; fp = nrp) { - (void) untimeout(fp->rj_id); - - nrp = fp->rj_next; - IDNRETRY_FREEJOB(fp); - } - - return (count); -} - -/* - * ----------------------------------------------------------------------- - * The sole purpose of the idn_protocol_server is to manage the IDN - * protocols between the various domains. These messages do _not_ go - * through the regular streams queues since they are not dependent on - * any user process or module necessarily having the IDN driver open. - * There may be multiple instances of these servers to enhance performance - * of domain management. Each server is assigned a idn_protoqueue_t - * from which to obtain the work they need to do. - * ----------------------------------------------------------------------- - */ -int -idn_protocol_init(int nservers) -{ - int i; - idn_protojob_t *jp; - register idn_protoqueue_t *protoq; - - if (nservers <= 0) { - cmn_err(CE_WARN, - "IDN: 237: invalid number (%d) of protocol servers", - nservers); - return (-1); - } - - idn.protocol.p_jobpool = kmem_cache_create("idn_protocol_jobcache", - sizeof (idn_protojob_t), 0, NULL, NULL, NULL, NULL, NULL, 0); - if (idn.protocol.p_jobpool == NULL) { - cmn_err(CE_WARN, - "IDN: 238: kmem_cache_create(jobcache) failed"); - return (-1); - } - - /* - * Initialize static cache for protojob. - */ - mutex_init(&idn_protojob_cache_lock, NULL, MUTEX_DRIVER, NULL); - jp = &idn_protojob_cache[0]; - for (i = 1; i < IDN_DMV_PENDING_MAX; jp = jp->j_next, i++) { - jp->j_cache = 1; - jp->j_next = &idn_protojob_cache[i]; - } - jp->j_cache = 1; - jp->j_next = NULL; - idn_protojob_cache_list = &idn_protojob_cache[0]; - - /* - * Init morgue semaphore. - */ - sema_init(&idn.protocol.p_morgue, 0, NULL, SEMA_DEFAULT, NULL); - /* - * Alloc server queues. - */ - idn.protocol.p_serverq = GETSTRUCT(idn_protoqueue_t, nservers); - - /* - * Init server queues. - */ - protoq = idn.protocol.p_serverq; - for (i = 0; i < nservers; protoq++, i++) { - mutex_init(&protoq->q_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&protoq->q_cv, NULL, CV_DEFAULT, NULL); - protoq->q_id = i; - protoq->q_joblist = NULL; - protoq->q_joblist_tail = NULL; - protoq->q_die = 0; - protoq->q_morgue = &idn.protocol.p_morgue; - /* - * Create protocol server thread. - */ - protoq->q_threadp = thread_create(NULL, 0, - idn_protocol_server, (caddr_t)&i, sizeof (i), &p0, - TS_RUN, maxclsyspri); - } - /* - * The servers are kept in the p_server[] array, however - * we'll build a linked list of them to facilitate debugging. - */ - protoq = idn.protocol.p_serverq; - for (i = 0; i < (nservers - 1); protoq++, i++) - protoq->q_next = (protoq + 1); - protoq->q_next = NULL; - - idn.nservers = nservers; - - return (idn.nservers); -} - -void -idn_protocol_deinit() -{ - register int i; - int nservers; - register idn_protoqueue_t *protoq; - - nservers = idn.nservers; - - if (nservers <= 0) - return; - - /* - * Make sure the servers are dead. - */ - idn_protocol_server_killall(); - ASSERT(idn.nservers == 0); - /* - * Destroy the mutexes. - */ - protoq = idn.protocol.p_serverq; - for (i = 0; i < nservers; protoq++, i++) { - mutex_destroy(&protoq->q_mutex); - cv_destroy(&protoq->q_cv); - } - /* - * Free up the protoqueue memory. - */ - FREESTRUCT(idn.protocol.p_serverq, idn_protoqueue_t, nservers); - idn.protocol.p_serverq = NULL; - /* - * Destroy the morgue semaphore. - */ - sema_destroy(&idn.protocol.p_morgue); - - if (idn.protocol.p_jobpool) { - kmem_cache_destroy(idn.protocol.p_jobpool); - idn.protocol.p_jobpool = NULL; - } -} - -static void -idn_protocol_server(int *id) -{ - idn_protoqueue_t *pq; - idn_protojob_t *jl; - register idn_protojob_t *jp; - procname_t proc = "idn_protocol_server"; - - if (id == NULL) { - PR_PROTO("%s: id == NULL, thread exiting\n", proc); - return; - } - ASSERT((*id >= 0) && (*id < idn_protocol_nservers)); - - pq = &idn.protocol.p_serverq[*id]; - - ASSERT(pq->q_id == *id); - - PR_PROTO("%s: id %d starting up (pq = 0x%p)\n", - proc, pq->q_id, (void *)pq); - - /*CONSTCOND*/ - while (1) { - mutex_enter(&pq->q_mutex); - - while (((jl = pq->q_joblist) == NULL) && !pq->q_die) - cv_wait(&pq->q_cv, &pq->q_mutex); - - pq->q_joblist = pq->q_joblist_tail = NULL; - - if (pq->q_die) { - /* - * We've been killed. Need to check-in - * at the morgue. - */ - pq->q_threadp = NULL; - mutex_exit(&pq->q_mutex); - PR_PROTO("%s: thread (%d) killed...bye bye\n", - proc, pq->q_id); - for (jp = jl; jp; jp = jl) { - jl = jp->j_next; - idn_protojob_free(jp); - } - sema_v(pq->q_morgue); - thread_exit(); - /*NOTREACHED*/ - } - mutex_exit(&pq->q_mutex); - - /* - * We can process the jobs asynchronously while more are - * put on. - */ - for (jp = jl; jp; jp = jl) { - jl = jp->j_next; - idn_recv_proto(&(jp->j_msg)); - idn_protojob_free(jp); - } - } -} - -/* - * Kill off all the protocol servers. - */ -static void -idn_protocol_server_killall() -{ - register idn_protoqueue_t *pq; - int i; - procname_t proc = "idn_protocol_server_killall"; - - PR_PROTO("%s: killing off %d protocol servers\n", - proc, idn.nservers); - - pq = idn.protocol.p_serverq; - for (i = 0; i < idn.nservers; pq++, i++) { - mutex_enter(&pq->q_mutex); - pq->q_die = 1; - cv_signal(&pq->q_cv); - mutex_exit(&pq->q_mutex); - } - - while (idn.nservers > 0) { - sema_p(&idn.protocol.p_morgue); - idn.nservers--; - } -} - -idn_protojob_t * -idn_protojob_alloc(int kmflag) -{ - idn_protojob_t *jp; - - jp = kmem_cache_alloc(idn.protocol.p_jobpool, kmflag); - if (jp == NULL) { - mutex_enter(&idn_protojob_cache_lock); - if ((jp = idn_protojob_cache_list) != NULL) - idn_protojob_cache_list = jp->j_next; - mutex_exit(&idn_protojob_cache_lock); - } else { - jp->j_cache = 0; - } - - return (jp); -} - -static void -idn_protojob_free(idn_protojob_t *jp) -{ - ASSERT(jp); - - if (jp->j_cache) { - mutex_enter(&idn_protojob_cache_lock); - jp->j_next = idn_protojob_cache_list; - idn_protojob_cache_list = jp; - mutex_exit(&idn_protojob_cache_lock); - } else { - kmem_cache_free(idn.protocol.p_jobpool, (void *)jp); - } -} - -void -idn_protojob_submit(int cookie, idn_protojob_t *jp) -{ - idn_protoqueue_t *pq; - int serverid; - procname_t proc = "idn_protojob_submit"; - STRING(str); - - if (jp == NULL) - return; - - serverid = IDN_PROTOCOL_SERVER_HASH(cookie); - - pq = &idn.protocol.p_serverq[serverid]; - - INUM2STR(jp->j_msg.m_msgtype, str); - PR_PROTO("%s: job (d=%d, m=0x%x, %s) submitted to " - "protocol server %d\n", proc, jp->j_msg.m_domid, - jp->j_msg.m_msgtype, str, serverid); - - mutex_enter(&pq->q_mutex); - /* - * Can't submit jobs to dying servers. - */ - if (!pq->q_die) { - if (pq->q_joblist_tail) { - pq->q_joblist_tail->j_next = jp; - pq->q_joblist_tail = jp; - } else { - pq->q_joblist = pq->q_joblist_tail = jp; - } - jp->j_next = NULL; - cv_signal(&pq->q_cv); - } else { - PR_PROTO("%s: protocol server dead. freeing protojob\n", - proc); - idn_protojob_free(jp); - } - mutex_exit(&pq->q_mutex); -} - -static void -idn_mboxarea_init(idn_mboxtbl_t *mtp, register int ntbls) -{ - register int d; - caddr_t state_ptr = NULL, mtbasep = (caddr_t)mtp; - idn_mboxtbl_t *amtp; - procname_t proc = "idn_mboxarea_init"; - - ASSERT(mtp && (ntbls > 0)); - - PR_PROTO("%s: init mboxtbl (0x%p) ntbls = %d\n", - proc, (void *)mtp, ntbls); - - for (d = 0; d < ntbls; d++) { - register int pd, sd; - register int ch; - - mtp->mt_header.mh_svr_active = 0; - mtp->mt_header.mh_svr_ready = 0; - /* - * Initialize the header of each mbox table - * with a cookie for identity. - */ - /* - * Format: 0xc0c0DSCC - * D = primary domain - * S = sub-domain of primary - * CC = channel of sub-domain. - */ - pd = (d / MAX_DOMAINS) / IDN_MAX_NETS; - sd = (d / IDN_MAX_NETS) % MAX_DOMAINS; - ch = d % IDN_MAX_NETS; - - /* - * We point all sub-domains in the same channel - * to the same active sync flag since a single server - * services all domains in the same channel. - */ - amtp = IDN_MBOXTBL_ABS_PTR(mtbasep, pd, 0, ch); - - state_ptr = (caddr_t)&amtp->mt_header.mh_svr_active; - mtp->mt_header.mh_svr_active_ptr = IDN_ADDR2OFFSET(state_ptr); - - state_ptr = (caddr_t)&amtp->mt_header.mh_svr_ready; - mtp->mt_header.mh_svr_ready_ptr = IDN_ADDR2OFFSET(state_ptr); - - mtp->mt_header.mh_cookie = IDN_MAKE_MBOXHDR_COOKIE(pd, sd, ch); - - mtp->mt_header.mh_cksum = IDN_CKSUM_MBOX(&mtp->mt_header); - - IDN_MBOXTBL_PTR_INC(mtp); - } - /* - * Now that the master has initialized the entire mailbox - * region the referenced memory may not necessarily be up-to-date - * with respect to the actual SMR memory due to caching. - * In order to make sure future connecting domains get a - * consistent picture of the mailbox region, it's necessary - * for the master to flush its caches. - */ - PR_PROTO("%s: flushing ecache's of local (master) domain\n", proc); - - idnxf_flushall_ecache(); -} - -idn_mainmbox_t * -idn_mainmbox_init(int domid, int mbx) -{ - idn_mainmbox_t *mmp; - int c; - idn_mainmbox_t *cmp; - procname_t proc = "idn_mainmbox_init"; - - ASSERT(idn_domain[domid].dcpu != IDN_NIL_DCPU); - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - PR_PROTO("%s: initializing main %s mailbox for domain %d\n", - proc, IDNMBOX_IS_RECV(mbx) ? "RECV" : "SEND", domid); - - cmp = GETSTRUCT(idn_mainmbox_t, IDN_MAX_NETS); - for (c = 0; c < IDN_MAX_NETS; c++) { - mmp = &cmp[c]; - mmp->mm_channel = (short)c; - mutex_init(&mmp->mm_mutex, NULL, MUTEX_DRIVER, NULL); - mmp->mm_domid = (short)domid; - mmp->mm_type = mbx; - } - mmp = cmp; - /* - * The actual SMR mailbox (mmp->mm_smr_mboxp) gets setup - * when the SMR is setup. - */ - - return (mmp); -} - -static void -idn_mainmbox_reset(int domid, idn_mainmbox_t *cmp) -{ - idn_mainmbox_t *mmp; - int c; - procname_t proc = "idn_mainmbox_reset"; - - ASSERT(IDN_DLOCK_IS_EXCL(domid)); - - PR_PROTO("%s: reseting main %s mailbox for domain %d\n", - proc, IDNMBOX_IS_RECV(cmp->mm_type) ? "RECV" : "SEND", domid); - - for (c = 0; c < IDN_MAX_NETS; c++) { - mmp = &cmp[c]; - - mmp->mm_channel = (short)c; - mmp->mm_domid = (short)domid; - mmp->mm_count = 0; - mmp->mm_flags = 0; - mmp->mm_qiget = mmp->mm_qiput = 0; - mmp->mm_csp = NULL; - ASSERT(mmp->mm_type == cmp->mm_type); - } -} - -void -idn_mainmbox_deinit(int domid, idn_mainmbox_t *mmp) -{ - procname_t proc = "idn_mainmbox_deinit"; - - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - PR_PROTO("%s: deinitializing main %s mailbox for domain %d\n", - proc, IDNMBOX_IS_RECV(mmp->mm_type) ? "RECV" : "SEND", domid); - - ASSERT(idn_domain_is_registered(domid, -1, NULL) == 0); - - FREESTRUCT(mmp, idn_mainmbox_t, IDN_MAX_NETS); -} - -static void -idn_mainmbox_activate(int domid) -{ - register int c; - idn_domain_t *dp = &idn_domain[domid]; - procname_t proc = "idn_mainmbox_activate"; - - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - PR_PROTO("%s:%d: activating main mailbox\n", proc, domid); - - for (c = 0; c < IDN_MAX_NETS; c++) - idn_mainmbox_chan_register(domid, &dp->dmbox.m_send[c], - &dp->dmbox.m_recv[c], c); -} - -/* - * Called upon disabling the SMR to deactivate all the mailboxes - * so that they no longer reference the SMR that's going away. - * - * stopall - Indicates to stop all channel services, across the board. - */ -static void -idn_mainmbox_deactivate(ushort_t domset) -{ - int svr_count; - procname_t proc = "idn_mainmbox_deactivate"; - - - if (domset == 0) - return; - - PR_PROTO("%s: %s deactivating main mailboxes for domset 0x%x\n", - proc, (domset == (ushort_t)-1) ? "STOP-ALL" : "NORMAL", domset); - - svr_count = idn_mainmbox_chan_unregister(domset, -1); - - PR_PROTO("%s: deactivated %d chansvrs (domset 0x%x)\n", - proc, svr_count, domset); -} - -static void -idn_mainmbox_chan_register(int domid, idn_mainmbox_t *send_mmp, - idn_mainmbox_t *recv_mmp, int channel) -{ - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - /* - * Obtain receive mailbox lock first. - */ - mutex_enter(&recv_mmp->mm_mutex); - mutex_enter(&send_mmp->mm_mutex); - - ASSERT(recv_mmp->mm_channel == (short)channel); - ASSERT(send_mmp->mm_channel == (short)channel); - - recv_mmp->mm_csp = &idn.chan_servers[channel]; - recv_mmp->mm_count = 0; - recv_mmp->mm_dropped = 0; - recv_mmp->mm_flags = 0; - - send_mmp->mm_csp = &idn.chan_servers[channel]; - send_mmp->mm_count = 0; - send_mmp->mm_dropped = 0; - send_mmp->mm_flags = 0; - - mutex_exit(&send_mmp->mm_mutex); - mutex_exit(&recv_mmp->mm_mutex); - - /* - * We have to add ourselves to the respective - * channel server's service table. - * Note that the channel may not necessarily be - * active at this time. - */ - ASSERT(idn.chan_servers); - /* - * Have to get the channel server under - * control so we can add ourselves. - * Returns w/c_mutex. - */ - IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[channel]); - /* - * Add the following domain (mailbox) for monitoring - * by the respective channel server. - */ - idn_chan_addmbox(channel, DOMAINSET(domid)); - - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[channel]); -} - -/* - * Unregister the given domain from the specified channel(s) for monitoring. - */ -static int -idn_mainmbox_chan_unregister(ushort_t domset, int channel) -{ - int c, dd_count; - int min_chan, max_chan; - procname_t proc = "idn_mainmbox_chan_unregister"; - - PR_CHAN("%s: deactivating main mailboxes (channel %d) " - "for domset 0x%x\n", proc, channel, domset); - - if (channel == -1) { - min_chan = 0; - max_chan = IDN_MAX_NETS - 1; - } else { - min_chan = max_chan = channel; - } - /* - * Point all the data dispatchers to the same morgue - * so we can kill them all at once. - */ - dd_count = 0; - for (c = min_chan; c <= max_chan; c++) { - - /* - * Have to get the channel server under - * control so we can remove ourselves. - * Returns w/c_mutex held. - */ - IDN_CHAN_LOCK_GLOBAL(&idn.chan_servers[c]); - /* - * Delete the following domain (mailbox) from - * monitoring by the respective channel server. - */ - idn_chan_delmbox(c, (ushort_t)domset); - - IDN_CHAN_UNLOCK_GLOBAL(&idn.chan_servers[c]); - dd_count++; - } - PR_CHAN("%s: deactivated %d channel mboxes for domset 0x%x, chan %d\n", - proc, dd_count, domset, channel); - return (dd_count); -} - -/* - * Check if the given domain is registered with the given channel(s). - */ -int -idn_domain_is_registered(int domid, int channel, idn_chanset_t *chansetp) -{ - int regcount; - int c, min_chan, max_chan; - idn_chanset_t chanset; - procname_t proc = "idn_domain_is_registered"; - - CHANSET_ZERO(chanset); - - if (idn.chan_servers == NULL) { - PR_CHAN("%s: idn.chan_servers == NULL!!\n", proc); - return (0); - } - - if (channel == -1) { - min_chan = 0; - max_chan = IDN_MAX_NETS - 1; - } else { - min_chan = max_chan = channel; - } - - regcount = 0; - - for (c = min_chan; c <= max_chan; c++) { - idn_chansvr_t *csp; - - csp = &idn.chan_servers[c]; - IDN_CHAN_LOCK_SEND(csp); - /* - * Don't really need recv side lock since registeration - * can't change while we're holding send side. - * No need to wait for send side to actually suspend - * since all we want to do is prevent the registered - * information from changing. - */ - if (IDN_CHAN_DOMAIN_IS_REGISTERED(csp, domid)) { - regcount++; - CHANSET_ADD(chanset, c); - } - - IDN_CHAN_UNLOCK_SEND(csp); - } - - PR_CHAN("%s: domid %d mbox reg'd with %d channels [0x%x] (req=%d)\n", - proc, domid, regcount, chanset, channel); - - if (chansetp) - *chansetp = chanset; - - return (regcount); -} - -static int -idn_mainmbox_flush(int domid, idn_mainmbox_t *mmp) -{ - register int qi; - register idn_mboxmsg_t *mqp; - int total_count = 0; - int c, count; - int mbox_type; - char *mbox_str; - int lost_io, total_lost_io = 0; - idn_chanset_t chanset; - procname_t proc = "idn_mainmbox_flush"; - - - if (mmp == NULL) - return (0); - - CHANSET_ZERO(chanset); - - mbox_type = mmp->mm_type; - ASSERT((mbox_type == IDNMMBOX_TYPE_SEND) || - (mbox_type == IDNMMBOX_TYPE_RECV)); - - mbox_str = (mbox_type == IDNMMBOX_TYPE_SEND) ? "SEND" : "RECV"; - - /* - * Determine which channels this domain is registered - * with. If he's not registered with any, then we - * can't touch the SMR. - */ - (void) idn_domain_is_registered(domid, -1, &chanset); - - for (c = 0; c < IDN_MAX_NETS; c++) { - ushort_t mbox_csum; - - if (mmp[c].mm_smr_mboxp == NULL) - continue; - mutex_enter(&mmp[c].mm_mutex); - ASSERT(mmp[c].mm_type == mbox_type); - if (CHAN_IN_SET(chanset, c) == 0) { - /* - * Domain is no longer registered. - * DON'T TOUCH THE SMR - IT'S POISON! - */ - if (mmp[c].mm_smr_mboxp) { - PR_CHAN("%s:%d:%s: domain unregistered " - "w/chan %d - DUMPING SMR reference\n", - proc, domid, mbox_str, c); - lost_io = IDN_MMBOXINDEX_DIFF(mmp[c].mm_qiput, - mmp[c].mm_qiget); -#ifdef DEBUG - if (mbox_type == IDNMMBOX_TYPE_RECV) { - PR_CHAN("%s:%d:%s: blowing away %d " - "incoming pkts\n", - proc, domid, mbox_str, lost_io); - } else { - PR_CHAN("%s:%d:%s: blowing away %d/%d " - "outstanding pkts\n", - proc, domid, mbox_str, lost_io, - idn_domain[domid].dio); - } -#endif /* DEBUG */ - } - mmp[c].mm_qiput = mmp[c].mm_qiget = 0; - mmp[c].mm_smr_mboxp = NULL; - total_lost_io += lost_io; - } - if (mmp[c].mm_smr_mboxp) { - mbox_csum = - IDN_CKSUM_MBOX(&mmp[c].mm_smr_mboxp->mt_header); - if (!VALID_NWRADDR(mmp[c].mm_smr_mboxp, 4) || - !VALID_MBOXHDR(&mmp[c].mm_smr_mboxp->mt_header, - c, mbox_csum)) { - lost_io = IDN_MMBOXINDEX_DIFF(mmp[c].mm_qiput, - mmp[c].mm_qiget); -#ifdef DEBUG - if (mbox_type == IDNMMBOX_TYPE_RECV) { - PR_CHAN("%s:%d:%s: bad mbox. blowing " - "away %d incoming pkts\n", - proc, domid, mbox_str, lost_io); - } else { - PR_CHAN("%s:%d:%s: bad mbox. blowing " - "away %d/%d outstanding pkts\n", - proc, domid, mbox_str, lost_io, - idn_domain[domid].dio); - } -#endif /* DEBUG */ - mmp[c].mm_smr_mboxp = NULL; - mmp[c].mm_qiput = mmp[c].mm_qiget = 0; - total_lost_io += lost_io; - } - } - if (mmp[c].mm_smr_mboxp == NULL) { - mutex_exit(&mmp[c].mm_mutex); - continue; - } - mqp = &mmp[c].mm_smr_mboxp->mt_queue[0]; - qi = 0; - count = 0; - /* - * It's quite possible the remote domain may be accessing - * these mailbox entries at the exact same time we're - * clearing the owner bit. That's okay. All we're trying - * to do at this point is to minimize the number of packets - * the remote domain might try to process unnecessarily. - */ - do { - if (mqp[qi].ms_owner) - count++; - mqp[qi].ms_owner = 0; - IDN_MMBOXINDEX_INC(qi); - } while (qi); - - lost_io = IDN_MMBOXINDEX_DIFF(mmp[c].mm_qiput, mmp[c].mm_qiget); - total_lost_io += lost_io; - - mmp[c].mm_qiput = mmp[c].mm_qiget = 0; - mmp[c].mm_smr_mboxp = NULL; - mutex_exit(&mmp[c].mm_mutex); - - total_count += count; - - PR_CHAN("%s:%d:%s: flushed out %d mbox entries for chan %d\n", - proc, domid, mbox_str, count, c); - } - - if (total_lost_io && (mbox_type == IDNMMBOX_TYPE_SEND)) { - int lost_bufs; - /* - * If we lost all our outstanding I/O. We could - * possible could have slabs now with mistakenly - * outstanding I/O buffers. Need to clean them up. - * Clean up of leftovers our self. - */ - lost_bufs = smr_buf_free_all(domid); - - PR_CHAN("%s:%d:%s: flushed %d/%d buffers from slabs\n", - proc, domid, mbox_str, lost_bufs, total_lost_io); - } - - PR_CHAN("%s:%d:%s: flushed total of %d mailbox entries (lost %d)\n", - proc, domid, mbox_str, total_count, total_lost_io); - - return (total_count); -} - -void -idn_chanserver_bind(int net, int cpuid) -{ - int ocpuid; - cpu_t *cp; - idn_chansvr_t *csp; - kthread_id_t tp; - procname_t proc = "idn_chanserver_bind"; - - csp = &idn.chan_servers[net]; - IDN_CHAN_LOCK_GLOBAL(csp); - - mutex_enter(&cpu_lock); /* protect checking cpu_ready_set */ - ocpuid = csp->ch_bound_cpuid; - cp = cpu_get(cpuid); - if ((cpuid != -1) && ((cp == NULL) || !cpu_is_online(cp))) { - mutex_exit(&cpu_lock); - cmn_err(CE_WARN, - "IDN: 239: invalid CPU ID (%d) specified for " - "IDN net %d", - cpuid, net); - IDN_CHAN_UNLOCK_GLOBAL(csp); - return; - } - if ((tp = csp->ch_recv_threadp) == NULL) { - /* - * Thread is not yet active. Set ch_bound_cpuid - * so when thread activates it will automatically - * bind itself. - */ - csp->ch_bound_cpuid = -1; - csp->ch_bound_cpuid_pending = cpuid; - } else { - if (ocpuid != -1) { - thread_affinity_clear(tp); - csp->ch_bound_cpuid = -1; - } - if (cpuid >= 0) { - thread_affinity_set(tp, cpuid); - csp->ch_bound_cpuid = cpuid; - } - csp->ch_bound_cpuid_pending = -1; - } - mutex_exit(&cpu_lock); - - PR_CHAN("%s: bound net/channel (%d) from cpuid %d to%scpuid %d\n", - proc, net, ocpuid, tp ? " " : " (pending) ", cpuid); - - IDN_CHAN_UNLOCK_GLOBAL(csp); -} - -#ifdef DEBUG -static idn_mboxhdr_t *prev_mhp[IDN_MAXMAX_NETS]; -#endif /* DEBUG */ -/* - * Get access to the respective channel server's synchronization - * header which resides in SMR space. - */ -static idn_mboxhdr_t * -idn_chan_server_syncheader(int channel) -{ - idn_domain_t *ldp = &idn_domain[idn.localid]; - idn_mboxtbl_t *mtp; - idn_mboxhdr_t *mhp; - ushort_t mbox_csum; - procname_t proc = "idn_chan_server_syncheader"; - - ASSERT(IDN_CHAN_RECV_IS_LOCKED(&idn.chan_servers[channel])); - - IDN_DLOCK_SHARED(idn.localid); - - if (ldp->dmbox.m_tbl == NULL) { - PR_CHAN("%s: local dmbox.m_tbl == NULL\n", proc); - IDN_DUNLOCK(idn.localid); - return (NULL); - } - - mtp = IDN_MBOXTBL_PTR_CHAN(ldp->dmbox.m_tbl, channel); - mhp = &mtp->mt_header; - mbox_csum = IDN_CKSUM_MBOX(&mtp->mt_header); - -#ifdef DEBUG - if (mhp != prev_mhp[channel]) { - prev_mhp[channel] = mhp; - PR_CHAN("%s: chan_server (%d) cookie = 0x%x (exp 0x%x)\n", - proc, channel, IDN_GET_MBOXHDR_COOKIE(mhp), - IDN_MAKE_MBOXHDR_COOKIE(0, 0, channel)); - PR_CHAN("%s: chan_server (%d) actv_ptr = 0x%x (exp 0x%x)\n", - proc, channel, mhp->mh_svr_active_ptr, - IDN_ADDR2OFFSET(&mhp->mh_svr_active)); - PR_CHAN("%s: chan_server (%d) ready_ptr = 0x%x (exp 0x%x)\n", - proc, channel, mhp->mh_svr_ready_ptr, - IDN_ADDR2OFFSET(&mhp->mh_svr_ready)); - PR_CHAN("%s: chan_server (%d) mbox_cksum = 0x%x (exp 0x%x)\n", - proc, channel, (int)mhp->mh_cksum, (int)mbox_csum); - } -#endif /* DEBUG */ - - if ((IDN_ADDR2OFFSET(&mhp->mh_svr_active) != - mhp->mh_svr_active_ptr) || - (IDN_ADDR2OFFSET(&mhp->mh_svr_ready) != mhp->mh_svr_ready_ptr) || - !VALID_MBOXHDR(mhp, channel, mbox_csum)) { - idn_chansvr_t *csp; - - csp = &idn.chan_servers[channel]; - if (IDN_CHANNEL_IS_RECV_CORRUPTED(csp) == 0) { - IDN_CHANSVC_MARK_RECV_CORRUPTED(csp); - - cmn_err(CE_WARN, - "IDN: 240: (channel %d) SMR CORRUPTED " - "- RELINK", channel); - cmn_err(CE_CONT, - "IDN: 240: (channel %d) cookie " - "(expected 0x%x, actual 0x%x)\n", - channel, - IDN_MAKE_MBOXHDR_COOKIE(0, 0, channel), - mhp->mh_cookie); - cmn_err(CE_CONT, - "IDN: 240: (channel %d) actv_flg " - "(expected 0x%x, actual 0x%x)\n", - channel, mhp->mh_svr_active_ptr, - IDN_ADDR2OFFSET(&mhp->mh_svr_active)); - cmn_err(CE_CONT, - "IDN: 240: (channel %d) ready_flg " - "(expected 0x%x, actual 0x%x)\n", - channel, mhp->mh_svr_ready_ptr, - IDN_ADDR2OFFSET(&mhp->mh_svr_ready)); - } - - mhp = NULL; - } - IDN_DUNLOCK(idn.localid); - - PR_CHAN("%s: channel(%d) mainhp = 0x%p\n", proc, channel, (void *)mhp); - - return (mhp); -} - -#define CHANSVR_SYNC_CACHE(csp, mmp, chan) \ -{ \ - ASSERT(IDN_CHAN_RECV_IS_LOCKED(csp)); \ - if ((csp)->ch_recv_changed) { \ - register int _d; \ - (csp)->ch_recv_scanset = (csp)->ch_recv_scanset_pending; \ - (csp)->ch_recv_domset = (csp)->ch_recv_domset_pending; \ - for (_d = 0; _d < MAX_DOMAINS; _d++) { \ - if (DOMAIN_IN_SET((csp)->ch_recv_domset, _d)) { \ - (mmp)[_d] = \ - &idn_domain[_d].dmbox.m_recv[chan]; \ - } else { \ - (mmp)[_d] = NULL; \ - } \ - } \ - (csp)->ch_recv_changed = 0; \ - } \ -} -#define CHANSVR_NEXT_DOMID(csp, i, d) \ -{ \ - (i) = ((i) + 1) & (MAX_DOMAINS - 1); \ - (d) = (int)(((csp)->ch_recv_scanset >> ((i) << 2)) & 0xf); \ -} -#define CHANSVR_RESET_INDEX(i) ((i) = -1) - -#ifdef DEBUG -static idn_mainmbox_t *Mmp[IDN_MAXMAX_NETS][MAX_DOMAINS]; -#endif /* DEBUG */ - -static void -idn_chan_server(idn_chansvr_t **cspp) -{ - idn_mboxhdr_t *mainhp; - register idn_chansvr_t *csp; - register idn_mboxmsg_t *mqp; -#ifdef DEBUG - idn_mainmbox_t **mmp; -#else - idn_mainmbox_t *mmp[MAX_DOMAINS]; -#endif /* DEBUG */ - register int qi; - struct idn *sip; - int channel; - int cpuid; - int empty; - int tot_pktcount, tot_dropcount; - register int index; - register int domid; - register int idleloops; - procname_t proc = "idn_chan_server"; - - -#ifdef DEBUG - mmp = &Mmp[(*cspp)->ch_id][0]; - bzero(mmp, MAX_DOMAINS * sizeof (idn_mainmbox_t *)); -#else /* DEBUG */ - bzero(mmp, sizeof (mmp)); -#endif /* DEBUG */ - - tot_pktcount = tot_dropcount = 0; - - ASSERT(cspp && *cspp); - - csp = *cspp; - channel = csp->ch_id; - sip = IDN_INST2SIP(channel); - ASSERT(sip); - - PR_CHAN("%s: CHANNEL SERVER (channel %d) GOING ACTIVE...\n", - proc, channel); - - IDN_CHAN_LOCK_RECV(csp); - IDN_CHAN_RECV_INPROGRESS(csp); - ASSERT(csp->ch_recv_threadp == curthread); - mutex_enter(&cpu_lock); - if ((cpuid = csp->ch_bound_cpuid_pending) != -1) { - cpu_t *cp = cpu_get(cpuid); - /* - * We've been requested to bind to - * a particular cpu. - */ - if ((cp == NULL) || !cpu_is_online(cp)) { - /* - * Cpu seems to have gone away or gone offline - * since originally requested. - */ - mutex_exit(&cpu_lock); - cmn_err(CE_WARN, - "IDN: 239: invalid CPU ID (%d) specified for " - "IDN net %d", - cpuid, channel); - } else { - csp->ch_bound_cpuid = cpuid; - affinity_set(csp->ch_bound_cpuid); - mutex_exit(&cpu_lock); - } - csp->ch_bound_cpuid_pending = -1; - } else { - mutex_exit(&cpu_lock); - } - if (csp->ch_bound_cpuid != -1) { - PR_CHAN("%s: thread bound to cpuid %d\n", - proc, csp->ch_bound_cpuid); - } - /* - * Only the first (main) mbox header is used for - * synchronization with data delivery since there is - * only data server for all mailboxes for this - * given channel. - */ - CHANSVR_SYNC_CACHE(csp, mmp, channel); - - mainhp = ((csp->ch_recv_domcount > 0) && - IDN_CHANNEL_IS_RECV_ACTIVE(csp)) - ? idn_chan_server_syncheader(channel) : NULL; - - if (mainhp && IDN_CHANNEL_IS_RECV_ACTIVE(csp)) - mainhp->mh_svr_active = 1; - - ASSERT(csp->ch_recv_domcount ? - (csp->ch_recv_scanset && csp->ch_recv_domset) : 1); - - IDN_CHAN_UNLOCK_RECV(csp); - - empty = 0; - idleloops = 0; - CHANSVR_RESET_INDEX(index); - - /* - * --------------------------------------------- - */ - /*CONSTCOND*/ - while (1) { - register int pktcount; - register int dropcount; - ushort_t mbox_csum; - idn_mboxtbl_t *smr_mboxp; /* points to SMR space */ - register smr_offset_t bufoffset; -#ifdef DEBUG - register smr_pkthdr_t *hdrp; - idn_netaddr_t netaddr; -#endif /* DEBUG */ - - /* - * Speed through and find the next available domid. - */ - CHANSVR_NEXT_DOMID(csp, index, domid); - - if (!index) { - /* - * We only check state changes when - * we wrap around. Done for performance. - */ - if (!IDN_CHANNEL_IS_RECV_ACTIVE(csp) || - csp->ch_recv.c_checkin || - (idn.state != IDNGS_ONLINE)) { - - PR_DATA("%s: (channel %d) %s\n", - proc, channel, - IDN_CHANNEL_IS_DETACHED(csp) - ? "DEAD" : - IDN_CHANNEL_IS_PENDING(csp) - ? "IDLED" : - IDN_CHANNEL_IS_ACTIVE(csp) - ? "ACTIVE" : "DISABLED"); - goto cc_sleep; - } - } - if (csp->ch_recv.c_checkin) - goto cc_sleep; - - if (empty == csp->ch_recv_domcount) { - empty = 0; - goto cc_slowdown; - } - - ASSERT(mmp[domid] != NULL); - - mutex_enter(&mmp[domid]->mm_mutex); - if ((smr_mboxp = mmp[domid]->mm_smr_mboxp) == NULL) { - /* - * Somebody is trying to shut things down. - */ - empty++; - mutex_exit(&mmp[domid]->mm_mutex); - continue; - } - ASSERT(mmp[domid]->mm_channel == (short)channel); - /* - * We don't care if the mm_smr_mboxp is nullified - * after this point. The thread attempting to shut - * us down has to formally pause this channel before - * anything is official anyway. So, we can continue - * with our local SMR reference until the thread - * shutting us down really stops us. - * - * Need to get the qiget index _before_ we drop the - * lock since it might get flushed (idn_mainmbox_flush) - * once we drop the mm_mutex. - * - * We prefer not to hold the mm_mutex across the - * idn_recv_mboxdata() call since that may be time- - * consuming. - */ - qi = mmp[domid]->mm_qiget; - - /* - * Check the mailbox header if checksum is turned on. - */ - mbox_csum = IDN_CKSUM_MBOX(&smr_mboxp->mt_header); - if (!VALID_MBOXHDR(&smr_mboxp->mt_header, channel, mbox_csum)) { - IDN_KSTAT_INC(sip, si_mboxcrc); - IDN_KSTAT_INC(sip, si_ierrors); - if (!(mmp[domid]->mm_flags & IDNMMBOX_FLAG_CORRUPTED)) { - cmn_err(CE_WARN, - "IDN: 241: [recv] (domain %d, " - "channel %d) SMR CORRUPTED - RELINK", - domid, channel); - mmp[domid]->mm_flags |= IDNMMBOX_FLAG_CORRUPTED; - } - empty = 0; - mutex_exit(&mmp[domid]->mm_mutex); - goto cc_sleep; - } - mutex_exit(&mmp[domid]->mm_mutex); - mqp = &smr_mboxp->mt_queue[0]; - - pktcount = dropcount = 0; - - if (mqp[qi].ms_owner == 0) - goto cc_next; - - bufoffset = IDN_BFRAME2OFFSET(mqp[qi].ms_bframe); - - if (!VALID_NWROFFSET(bufoffset, IDN_SMR_BUFSIZE)) { - /* ASSERT(0); */ - mqp[qi].ms_flag |= IDN_MBOXMSG_FLAG_ERR_BADOFFSET; - mqp[qi].ms_owner = 0; - IDN_MMBOXINDEX_INC(qi); - dropcount++; - - IDN_KSTAT_INC(sip, si_smraddr); - IDN_KSTAT_INC(sip, si_ierrors); - - } else { - PR_DATA("%s: (channel %d) pkt (off 0x%x, " - "qiget %d) from domain %d\n", - proc, channel, bufoffset, qi, domid); -#ifdef DEBUG - - hdrp = IDN_BUF2HDR(IDN_OFFSET2ADDR(bufoffset)); - netaddr.netaddr = hdrp->b_netaddr; - ASSERT(netaddr.net.chan == (ushort_t)channel); -#endif /* DEBUG */ - - if (idn_recv_mboxdata(channel, - IDN_OFFSET2ADDR(bufoffset)) < 0) { - mutex_enter(&mmp[domid]->mm_mutex); - if (!(mmp[domid]->mm_flags & - IDNMMBOX_FLAG_CORRUPTED)) { - cmn_err(CE_WARN, - "IDN: 241: [recv] (domain " - "%d, channel %d) SMR " - "CORRUPTED - RELINK", - domid, channel); - mmp[domid]->mm_flags |= - IDNMMBOX_FLAG_CORRUPTED; - } - mutex_exit(&mmp[domid]->mm_mutex); - } - - mqp[qi].ms_owner = 0; - IDN_MMBOXINDEX_INC(qi); - pktcount++; - } - -cc_next: - - mutex_enter(&mmp[domid]->mm_mutex); - if (mmp[domid]->mm_smr_mboxp) { - if (dropcount) - mmp[domid]->mm_dropped += dropcount; - mmp[domid]->mm_qiget = qi; - mmp[domid]->mm_count += pktcount; - } - mutex_exit(&mmp[domid]->mm_mutex); - - if (pktcount == 0) { - empty++; - } else { - csp->ch_recv_waittime = IDN_NETSVR_WAIT_MIN; - empty = 0; - idleloops = 0; - - PR_DATA("%s: (channel %d) dom=%d, pktcnt=%d\n", - proc, channel, domid, pktcount); - } - - continue; - -cc_slowdown: - -#ifdef DEBUG - if (idleloops == 0) { - PR_DATA("%s: (channel %d) going SOFT IDLE...\n", - proc, channel); - } -#endif /* DEBUG */ - if (idleloops++ < IDN_NETSVR_SPIN_COUNT) { - /* - * At this level we only busy-wait. - * Get back into action. - */ - continue; - } - idleloops = 0; - -cc_sleep: - - if (mainhp) - mainhp->mh_svr_active = 0; - - IDN_CHAN_LOCK_RECV(csp); - -cc_die: - - ASSERT(IDN_CHAN_RECV_IS_LOCKED(csp)); - - if (!IDN_CHANNEL_IS_RECV_ACTIVE(csp) && - IDN_CHANNEL_IS_DETACHED(csp)) { - /* - * Time to die... - */ - PR_CHAN("%s: (channel %d) serviced %d " - "packets, drop = %d\n", proc, channel, - tot_pktcount, tot_dropcount); - PR_CHAN("%s: (channel %d) TERMINATING\n", - proc, channel); - PR_CHAN("%s: (channel %d) ch_morguep = %p\n", - proc, channel, (void *)csp->ch_recv_morguep); - - csp->ch_recv_threadp = NULL; -#ifdef DEBUG - for (index = 0; index < csp->ch_recv_domcount; - index++) { - if ((int)((csp->ch_recv_scanset >> - (index*4)) & 0xf) == domid) { - PR_DATA("%s: WARNING (channel %d) " - "DROPPING domid %d...\n", - proc, channel, domid); - } - } -#endif /* DEBUG */ - IDN_CHAN_RECV_DONE(csp); - - sema_v(csp->ch_recv_morguep); - - IDN_CHAN_UNLOCK_RECV(csp); - - thread_exit(); - /* not reached */ - } - - do { - if (IDN_CHANNEL_IS_DETACHED(csp)) { - PR_CHAN("%s: (channel %d) going to DIE...\n", - proc, channel); - goto cc_die; - } -#ifdef DEBUG - if (IDN_CHANNEL_IS_RECV_ACTIVE(csp) && - (csp->ch_recv_waittime <= IDN_NETSVR_WAIT_MAX)) { - PR_CHAN("%s: (channel %d) going SOFT IDLE " - "(waittime = %d ticks)...\n", - proc, channel, - csp->ch_recv_waittime); - } else { - PR_CHAN("%s: (channel %d) going " - "HARD IDLE...\n", proc, channel); - } -#endif /* DEBUG */ - IDN_CHAN_RECV_DONE(csp); - - /* - * If we're being asked to check-in then - * go into a hard sleep. Want to give the - * thread requesting us to checkin a chance. - */ - while (csp->ch_recv.c_checkin) - cv_wait(&csp->ch_recv_cv, - &csp->ch_recv.c_mutex); - - if (csp->ch_recv_waittime > IDN_NETSVR_WAIT_MAX) - cv_wait(&csp->ch_recv_cv, - &csp->ch_recv.c_mutex); - else - (void) cv_reltimedwait(&csp->ch_recv_cv, - &csp->ch_recv.c_mutex, - csp->ch_recv_waittime, TR_CLOCK_TICK); - - IDN_CHAN_RECV_INPROGRESS(csp); - - IDN_KSTAT_INC(sip, si_sigsvr); - - if (csp->ch_recv_waittime <= IDN_NETSVR_WAIT_MAX) - csp->ch_recv_waittime <<= - IDN_NETSVR_WAIT_SHIFT; - - } while (!IDN_CHANNEL_IS_RECV_ACTIVE(csp)); - - /* - * Before we see the world (and touch SMR space), - * see if we've been told to die. - */ - mainhp = NULL; - /* - * The world may have changed since we were - * asleep. Need to resync cache and check for a - * new syncheader. - * - * Reset chansvr cache against any changes in - * mbox fields we need (mm_qiget). - */ - CHANSVR_SYNC_CACHE(csp, mmp, channel); - if (csp->ch_recv_domcount <= 0) { - /* - * Everybody disappeared on us. - * Go back to sleep. - */ - goto cc_die; - } - ASSERT(csp->ch_recv_scanset && csp->ch_recv_domset); - - mainhp = idn_chan_server_syncheader(channel); - if (mainhp == NULL) { - /* - * Bummer...we're idling... - */ - goto cc_die; - } - - mainhp->mh_svr_active = 1; - - IDN_CHAN_UNLOCK_RECV(csp); - /* - * Reset the domid index after sleeping. - */ - CHANSVR_RESET_INDEX(index); - - empty = 0; - idleloops = 0; - } -} - -#if 0 -/* - * We maintain a separate function for flushing the STREAMs - * queue of a channel because it must be done outside the - * context of the idn_chan_action routine. The streams flush - * cannot occur inline with the idn_chan_action because - * the act of flushing may cause IDN send functions to be called - * directly and thus locks to be obtained which could result - * in deadlocks. - */ -static void -idn_chan_flush(idn_chansvr_t *csp) -{ - queue_t *rq; - struct idn *sip; - int flush_type = 0; - idn_chaninfo_t *csend, *crecv; - procname_t proc = "idn_chan_flush"; - - csend = &csp->ch_send; - crecv = &csp->ch_recv; - - mutex_enter(&crecv->c_mutex); - mutex_enter(&csend->c_mutex); - - if (crecv->c_state & IDN_CHANSVC_STATE_FLUSH) - flush_type |= FLUSHR; - - if (csend->c_state & IDN_CHANSVC_STATE_FLUSH) - flush_type |= FLUSHW; - - if (flush_type) { - rq = NULL; - rw_enter(&idn.struprwlock, RW_READER); - if ((sip = IDN_INST2SIP(csp->ch_id)) != NULL) - rq = sip->si_ipq; - rw_exit(&idn.struprwlock); - if (rq) { - /* - * Flush the STREAM if possible - * to get the channel server coherent - * enough to respond to us. - */ - PR_CHAN("%s: sending FLUSH (%x) to channel %d\n", - proc, flush_type, csp->ch_id); - - (void) putnextctl1(rq, M_FLUSH, flush_type); - } - crecv->c_state &= ~IDN_CHANSVC_STATE_FLUSH; - csend->c_state &= ~IDN_CHANSVC_STATE_FLUSH; - - if (crecv->c_waiters) - cv_broadcast(&crecv->c_cv); - } - - mutex_exit(&csend->c_mutex); - mutex_exit(&crecv->c_mutex); -} -#endif /* 0 */ - -/* - * Locks are with respect to SEND/RECV locks (c_mutex). - * - * STOP/SUSPEND/DETACH - * - Entered with locks dropped, leave with locks held. - * DETACH - lock dropped manually. - * RESTART/RESUME - * - Entered with locks held, leave with locks dropped. - * ATTACH - * - both enter and leave with locks dropped. - */ -static void -idn_chan_action(int channel, idn_chanaction_t chanaction, int wait) -{ - uchar_t clr_state, set_state; - uint_t is_running; - domainset_t closed_slabwaiters = 0; - struct idn *sip; - idn_chansvr_t *csp; - idn_chaninfo_t *csend, *crecv; - procname_t proc = "idn_chan_action"; - - ASSERT((channel >= 0) && (channel < IDN_MAX_NETS)); - ASSERT(idn.chan_servers); - - csp = &idn.chan_servers[channel]; - - PR_CHAN("%s: requesting %s for channel %d\n", - proc, chanaction_str[(int)chanaction], channel); - - csend = &csp->ch_send; - crecv = &csp->ch_recv; - - ASSERT(IDN_CHAN_GLOBAL_IS_LOCKED(csp)); - - clr_state = set_state = 0; - - switch (chanaction) { - case IDNCHAN_ACTION_DETACH: - clr_state = IDN_CHANSVC_STATE_MASK; - /*FALLTHROUGH*/ - - case IDNCHAN_ACTION_STOP: - clr_state |= IDN_CHANSVC_STATE_ENABLED; - /*FALLTHROUGH*/ - - case IDNCHAN_ACTION_SUSPEND: - clr_state |= IDN_CHANSVC_STATE_ACTIVE; - - /* - * Must maintain this locking order. - * Set asynchronous check-in flags. - */ - crecv->c_checkin = 1; - csend->c_checkin = 1; - - is_running = 0; - if ((csend->c_inprogress || crecv->c_inprogress) && - wait && (csp->ch_recv_threadp != curthread)) { - - rw_enter(&idn.struprwlock, RW_READER); - if ((sip = IDN_INST2SIP(channel)) != NULL) { - /* - * Temporarily turn off the STREAM - * to give a chance to breath. - */ - is_running = sip->si_flags & IDNRUNNING; - if (is_running) - sip->si_flags &= ~IDNRUNNING; - } - rw_exit(&idn.struprwlock); - } - - mutex_enter(&crecv->c_mutex); - crecv->c_state &= ~clr_state; - - mutex_enter(&csend->c_mutex); - csend->c_state &= ~clr_state; - - /* - * It's possible the channel server could come - * through this flow itself due to putting data upstream - * that ultimately turned around and came back down for - * sending. If this is the case we certainly don't - * want to cv_wait, otherwise we'll obviously deadlock - * waiting for ourself. So, only block if somebody - * other than the channel server we're attempting to - * suspend/stop. - */ - if (wait && (csp->ch_recv_threadp != curthread)) { - int do_flush = 0; - - if (csend->c_inprogress || crecv->c_inprogress) - do_flush++; - - if (do_flush) { - rw_enter(&idn.struprwlock, RW_READER); - if ((sip = IDN_INST2SIP(channel)) != NULL) { - /* - * Temporarily turn off the STREAM - * to give a chance to breath. - */ - if (sip->si_flags & IDNRUNNING) { - is_running = 1; - sip->si_flags &= ~IDNRUNNING; - } - } - rw_exit(&idn.struprwlock); - } - - /* - * If we have any senders in-progress - * it's possible they're stuck waiting - * down in smr_buf_alloc which may never - * arrive if we're in an unlink process. - * Rather than wait for it to timeout - * let's be proactive so we can disconnect - * asap. - */ - closed_slabwaiters = csp->ch_reg_domset; - DOMAINSET_ADD(closed_slabwaiters, idn.localid); - if (closed_slabwaiters) - smr_slabwaiter_close(closed_slabwaiters); - - do { - /* - * It's possible due to a STREAMs - * loopback from read queue to write queue - * that receiver and sender may be same - * thread, i.e. receiver's inprogress - * flag will never clear until sender's - * inprogress flag clears. So, we wait - * for sender's inprogress first. - */ - while (csend->c_inprogress) { - mutex_exit(&crecv->c_mutex); - while (csend->c_inprogress) { - csend->c_waiters++; - cv_wait(&csend->c_cv, - &csend->c_mutex); - csend->c_waiters--; - } - /* - * Maintain lock ordering. - * Eventually we will catch - * him due to the flag settings. - */ - mutex_exit(&csend->c_mutex); - mutex_enter(&crecv->c_mutex); - mutex_enter(&csend->c_mutex); - } - if (crecv->c_inprogress) { - mutex_exit(&csend->c_mutex); - while (crecv->c_inprogress) { - crecv->c_waiters++; - cv_wait(&crecv->c_cv, - &crecv->c_mutex); - crecv->c_waiters--; - } - mutex_enter(&csend->c_mutex); - } - } while (csend->c_inprogress); - } - - if (is_running) { - /* - * Restore the IDNRUNNING bit in - * the flags to let them know the - * channel is still alive. - */ - rw_enter(&idn.struprwlock, RW_READER); - if ((sip = IDN_INST2SIP(channel)) != NULL) - sip->si_flags |= IDNRUNNING; - rw_exit(&idn.struprwlock); - } - - if (closed_slabwaiters) { - /* - * We can reopen now since at this point no new - * slabwaiters will attempt to come in and wait. - */ - smr_slabwaiter_open(csp->ch_reg_domset); - } - - crecv->c_checkin = 0; - csend->c_checkin = 0; - - /* - * ALL leave with locks held. - */ - PR_CHAN("%s: action (%s) for channel %d - COMPLETED\n", - proc, chanaction_str[(int)chanaction], channel); - break; - - case IDNCHAN_ACTION_ATTACH: - mutex_enter(&crecv->c_mutex); - mutex_enter(&csend->c_mutex); - set_state |= csp->ch_state & IDN_CHANSVC_STATE_ATTACHED; - /*FALLTHROUGH*/ - - case IDNCHAN_ACTION_RESTART: - set_state |= csp->ch_state & IDN_CHANSVC_STATE_ENABLED; - /*FALLTHROUGH*/ - - case IDNCHAN_ACTION_RESUME: - ASSERT(IDN_CHAN_LOCAL_IS_LOCKED(csp)); - set_state |= csp->ch_state & IDN_CHANSVC_STATE_ACTIVE; - - crecv->c_state |= set_state; - csend->c_state |= set_state; - - /* - * The channel server itself could come through this - * flow, so obviously no point in attempting to wake - * ourself up!. - */ - if (csp->ch_recv_threadp && (csp->ch_recv_threadp != curthread)) - cv_signal(&csp->ch_recv_cv); - - PR_CHAN("%s: action (%s) for channel %d - COMPLETED\n", - proc, chanaction_str[(int)chanaction], channel); - - /* - * Leaves with lock released. - */ - mutex_exit(&csend->c_mutex); - mutex_exit(&crecv->c_mutex); - break; - - default: - ASSERT(0); - break; - } -} - -static void -idn_chan_addmbox(int channel, ushort_t domset) -{ - idn_chansvr_t *csp; - register int d; - procname_t proc = "idn_chan_addmbox"; - - PR_CHAN("%s: adding domset 0x%x main mailboxes to channel %d\n", - proc, domset, channel); - - ASSERT(idn.chan_servers); - - csp = &idn.chan_servers[channel]; - - /* - * Adding domains to a channel can be - * asynchonous, so we don't bother waiting. - */ - IDN_CHANNEL_SUSPEND(channel, 0); - - /* - * Now we have the sending and receiving sides blocked - * for this channel. - */ - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(domset, d)) - continue; - if (IDN_CHAN_DOMAIN_IS_REGISTERED(csp, d)) { - DOMAINSET_DEL(domset, d); - continue; - } - IDN_CHANSVR_SCANSET_ADD_PENDING(csp, d); - DOMAINSET_ADD(csp->ch_recv_domset_pending, d); - IDN_CHAN_DOMAIN_REGISTER(csp, d); - - PR_CHAN("%s: domain %d (channel %d) RECV (pending) " - "scanset = 0x%lx\n", proc, d, channel, - csp->ch_recv_scanset_pending); - PR_CHAN("%s: domain %d (channel %d) domset = 0x%x\n", - proc, d, channel, (uint_t)csp->ch_reg_domset); - - CHECKPOINT_OPENED(IDNSB_CHKPT_CHAN, - idn_domain[d].dhw.dh_boardset, 1); - } - if (domset) - csp->ch_recv_changed = 1; - - IDN_CHANNEL_RESUME(channel); -} - -static void -idn_chan_delmbox(int channel, ushort_t domset) -{ - idn_chansvr_t *csp; - register int d; - procname_t proc = "idn_chan_delmbox"; - - PR_CHAN("%s: deleting domset 0x%x main mailboxes from channel %d\n", - proc, domset, channel); - - ASSERT(idn.chan_servers); - - csp = &idn.chan_servers[channel]; - - /* - * Here we have to wait for the channel server - * as it's vital that we don't return without guaranteeing - * that the given domset is no longer registered. - */ - IDN_CHANNEL_SUSPEND(channel, 1); - - /* - * Now we have the sending and receiving sides blocked - * for this channel. - */ - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(domset, d)) - continue; - if (!IDN_CHAN_DOMAIN_IS_REGISTERED(csp, d)) { - DOMAINSET_DEL(domset, d); - continue; - } - /* - * This domain has a mailbox hanging on this channel. - * Get him out. - * - * First remove him from the receive side. - */ - ASSERT(csp->ch_recv_domcount > 0); - IDN_CHANSVR_SCANSET_DEL_PENDING(csp, d); - DOMAINSET_DEL(csp->ch_recv_domset_pending, d); - IDN_CHAN_DOMAIN_UNREGISTER(csp, d); - - PR_CHAN("%s: domain %d (channel %d) RECV (pending) " - "scanset = 0x%lx\n", proc, d, channel, - csp->ch_recv_scanset_pending); - PR_CHAN("%s: domain %d (channel %d) domset = 0x%x\n", - proc, d, channel, (uint_t)csp->ch_reg_domset); - - CHECKPOINT_CLOSED(IDNSB_CHKPT_CHAN, - idn_domain[d].dhw.dh_boardset, 2); - - } - if (domset) - csp->ch_recv_changed = 1; - - IDN_CHANNEL_RESUME(channel); -} - -static int -idn_valid_etherheader(struct ether_header *ehp) -{ - uchar_t *eap; - - eap = &ehp->ether_dhost.ether_addr_octet[0]; - - if ((eap[IDNETHER_ZERO] != 0) && (eap[IDNETHER_ZERO] != 0xff)) - return (0); - - if ((eap[IDNETHER_COOKIE1] != IDNETHER_COOKIE1_VAL) && - (eap[IDNETHER_COOKIE1] != 0xff)) - return (0); - - if ((eap[IDNETHER_COOKIE2] != IDNETHER_COOKIE2_VAL) && - (eap[IDNETHER_COOKIE2] != 0xff)) - return (0); - - if ((eap[IDNETHER_RESERVED] != IDNETHER_RESERVED_VAL) && - (eap[IDNETHER_RESERVED] != 0xff)) - return (0); - - if (!VALID_UCHANNEL(eap[IDNETHER_CHANNEL]) && - (eap[IDNETHER_CHANNEL] != 0xff)) - return (0); - - if (!VALID_UDOMAINID(IDN_NETID2DOMID(eap[IDNETHER_NETID])) && - (eap[IDNETHER_NETID] != 0xff)) - return (0); - - return (1); -} - -/* - * Packet header has already been filled in. - * RETURNS: 0 - * ENOLINK - * EPROTO - * ENOSPC - */ -/*ARGSUSED*/ -static int -idn_send_mboxdata(int domid, struct idn *sip, int channel, caddr_t bufp) -{ - idn_mainmbox_t *mmp; - idn_mboxmsg_t *mqp; - smr_pkthdr_t *hdrp; - smr_offset_t bufoffset; - idn_netaddr_t dst; - ushort_t mbox_csum; - int rv = 0; - int pktlen, qi; - procname_t proc = "idn_send_mboxdata"; - - mmp = idn_domain[domid].dmbox.m_send; - if (mmp == NULL) { - PR_DATA("%s: dmbox.m_send == NULL\n", proc); - IDN_KSTAT_INC(sip, si_linkdown); - return (ENOLINK); - } - - mmp += channel; - mutex_enter(&mmp->mm_mutex); - - if (mmp->mm_smr_mboxp == NULL) { - PR_DATA("%s: (d %d, chn %d) mm_smr_mboxp == NULL\n", - proc, domid, channel); - IDN_KSTAT_INC(sip, si_linkdown); - rv = ENOLINK; - goto send_err; - } - mbox_csum = IDN_CKSUM_MBOX(&mmp->mm_smr_mboxp->mt_header); - if (mbox_csum != mmp->mm_smr_mboxp->mt_header.mh_cksum) { - PR_DATA("%s: (d %d, chn %d) mbox hdr cksum (%d) " - "!= actual (%d)\n", - proc, domid, channel, mbox_csum, - mmp->mm_smr_mboxp->mt_header.mh_cksum); - if ((mmp->mm_flags & IDNMMBOX_FLAG_CORRUPTED) == 0) { - cmn_err(CE_WARN, - "IDN: 241: [send] (domain %d, " - "channel %d) SMR CORRUPTED - RELINK", - domid, channel); - mmp->mm_flags |= IDNMMBOX_FLAG_CORRUPTED; - } - IDN_KSTAT_INC(sip, si_mboxcrc); - IDN_KSTAT_INC(sip, si_oerrors); - rv = EPROTO; - goto send_err; - } - - bufoffset = IDN_ADDR2OFFSET(bufp); - hdrp = IDN_BUF2HDR(bufp); - pktlen = hdrp->b_length; - dst.netaddr = hdrp->b_netaddr; - ASSERT(dst.net.chan == (ushort_t)channel); - - mqp = &mmp->mm_smr_mboxp->mt_queue[0]; - qi = mmp->mm_qiput; - - if (mqp[qi].ms_owner) { - PR_DATA("%s: mailbox FULL (qiput=%d, qiget=%d)\n", - proc, mmp->mm_qiput, mmp->mm_qiget); - IDN_KSTAT_INC(sip, si_txfull); - rv = ENOSPC; - goto send_err; - } - if (mqp[qi].ms_flag & IDN_MBOXMSG_FLAG_RECLAIM) { - smr_offset_t recl_bufoffset; - /* - * Remote domain finished with mailbox entry, - * however it has not been reclaimed yet. A reclaim - * was done before coming into this routine, however - * timing may have been such that the entry became - * free just after the reclamation, but before - * entry into here. Go ahead and reclaim this entry. - */ - recl_bufoffset = IDN_BFRAME2OFFSET(mqp[qi].ms_bframe); - - PR_DATA("%s: attempting reclaim (domain %d) " - "(qiput=%d, b_off=0x%x)\n", - proc, domid, qi, recl_bufoffset); - - if (VALID_NWROFFSET(recl_bufoffset, IDN_SMR_BUFSIZE)) { - int recl; - caddr_t b_bufp; - smr_pkthdr_t *b_hdrp; - - b_bufp = IDN_OFFSET2ADDR(recl_bufoffset); - b_hdrp = IDN_BUF2HDR(b_bufp); - - if (IDN_CKSUM_PKT(b_hdrp) != b_hdrp->b_cksum) { - IDN_KSTAT_INC(sip, si_crc); - IDN_KSTAT_INC(sip, si_fcs_errors); - IDN_KSTAT_INC(sip, si_reclaim); - IDN_KSTAT_INC(sip, si_oerrors); - } - - recl = smr_buf_free(domid, b_bufp, b_hdrp->b_length); -#ifdef DEBUG - if (recl == 0) { - PR_DATA("%s: SUCCESSFULLY reclaimed buf " - "(domain %d)\n", proc, domid); - } else { - PR_DATA("%s: WARNING: reclaim failed (FREE) " - "(domain %d)\n", proc, domid); - } -#endif /* DEBUG */ - } else { - IDN_KSTAT_INC(sip, si_smraddr); - IDN_KSTAT_INC(sip, si_reclaim); - PR_DATA("%s: WARNING: reclaim failed (BAD OFFSET) " - "(domain %d)\n", proc, domid); - } - } - - if (*mmp->mm_smr_readyp == 0) { - mmp->mm_qiput = qi; - IDN_KSTAT_INC(sip, si_linkdown); - rv = ENOLINK; - goto send_err; - } - - mqp[qi].ms_flag = IDN_MBOXMSG_FLAG_RECLAIM; - mqp[qi].ms_bframe = IDN_OFFSET2BFRAME(bufoffset); - /* membar_stst(); */ - mqp[qi].ms_owner = 1; - - IDN_MMBOXINDEX_INC(qi); - - mmp->mm_qiput = qi; - - mmp->mm_count++; - - if ((*mmp->mm_smr_readyp) && !(*mmp->mm_smr_activep)) { - idn_msgtype_t mt; - - mt.mt_mtype = IDNP_DATA; - mt.mt_atype = 0; - IDN_KSTAT_INC(sip, si_xdcall); - (void) IDNXDC(domid, &mt, (uint_t)dst.net.chan, 0, 0, 0); - } - mutex_exit(&mmp->mm_mutex); - IDN_KSTAT_INC(sip, si_opackets); - IDN_KSTAT_INC(sip, si_opackets64); - IDN_KSTAT_ADD(sip, si_xmtbytes, pktlen); - IDN_KSTAT_ADD(sip, si_obytes64, (uint64_t)pktlen); - - return (0); - -send_err: - mmp->mm_dropped++; - - mutex_exit(&mmp->mm_mutex); - - return (rv); -} - -static int -idn_recv_mboxdata(int channel, caddr_t bufp) -{ - smr_pkthdr_t *hdrp; - struct idn *sip; - mblk_t *mp = nilp(mblk_t); - int pktlen; - int apktlen; - int rv = 0; - smr_offset_t bufoffset; - ushort_t csum; - idn_netaddr_t dst, daddr; - procname_t proc = "idn_recv_mboxdata"; - - hdrp = IDN_BUF2HDR(bufp); - - csum = IDN_CKSUM_PKT(hdrp); - - sip = IDN_INST2SIP(channel); - if (sip == NULL) { - /*LINTED*/ - sip = IDN_INST2SIP(0); - } - ASSERT(sip); - - if (csum != hdrp->b_cksum) { - PR_DATA("%s: bad checksum(%x) != expected(%x)\n", - proc, (uint_t)csum, (uint_t)hdrp->b_cksum); - IDN_KSTAT_INC(sip, si_crc); - IDN_KSTAT_INC(sip, si_fcs_errors); - rv = -1; - goto recv_err; - } - - daddr.net.chan = (ushort_t)channel; - daddr.net.netid = (ushort_t)idn.localid; - - dst.netaddr = hdrp->b_netaddr; - bufoffset = hdrp->b_offset; - - if (dst.netaddr != daddr.netaddr) { - PR_DATA("%s: wrong dest netaddr (0x%x), expected (0x%x)\n", - proc, dst.netaddr, daddr.netaddr); - IDN_KSTAT_INC(sip, si_nolink); - IDN_KSTAT_INC(sip, si_macrcv_errors); - goto recv_err; - } - pktlen = hdrp->b_length; - apktlen = pktlen; - - if ((pktlen <= 0) || (pktlen > IDN_DATA_SIZE)) { - PR_DATA("%s: invalid packet length (%d) <= 0 || > %lu\n", - proc, pktlen, IDN_DATA_SIZE); - IDN_KSTAT_INC(sip, si_buff); - IDN_KSTAT_INC(sip, si_toolong_errors); - goto recv_err; - } - - mp = allocb(apktlen + IDN_ALIGNSIZE, BPRI_LO); - if (mp == nilp(mblk_t)) { - PR_DATA("%s: allocb(pkt) failed\n", proc); - IDN_KSTAT_INC(sip, si_allocbfail); - IDN_KSTAT_INC(sip, si_norcvbuf); /* MIB II */ - goto recv_err; - } - ASSERT(DB_TYPE(mp) == M_DATA); - /* - * Copy data packet into its streams buffer. - * Align pointers for maximum bcopy performance. - */ - mp->b_rptr = (uchar_t *)IDN_ALIGNPTR(mp->b_rptr, bufoffset); - bcopy(IDN_BUF2DATA(bufp, bufoffset), mp->b_rptr, apktlen); - mp->b_wptr = mp->b_rptr + pktlen; - - if (IDN_CHECKSUM && - !idn_valid_etherheader((struct ether_header *)mp->b_rptr)) { - freeb(mp); - mp = nilp(mblk_t); - PR_DATA("%s: etherheader CORRUPTED\n", proc); - IDN_KSTAT_INC(sip, si_crc); - IDN_KSTAT_INC(sip, si_fcs_errors); - rv = -1; - goto recv_err; - } - - idndl_read(NULL, mp); - -recv_err: - - if (mp == nilp(mblk_t)) { - IDN_KSTAT_INC(sip, si_ierrors); - } - - return (rv); -} - -/* - * When on shutdown path (idn_active_resources) must call - * idn_mainmbox_flush() _BEFORE_ calling idn_reclaim_mboxdata() - * for any final data. This is necessary incase the mailboxes - * have been unregistered. If they have then idn_mainmbox_flush() - * will set mm_smr_mboxp to NULL which prevents us from touching - * poison SMR space. - */ -int -idn_reclaim_mboxdata(int domid, int channel, int nbufs) -{ - idn_mainmbox_t *mmp; - idn_mboxmsg_t *mqp; - smr_pkthdr_t *hdrp; - idn_domain_t *dp; - int qi; - int mi; - int reclaim_cnt = 0; - int free_cnt; - ushort_t csum; - struct idn *sip; - smr_offset_t reclaim_list, curr, prev; - procname_t proc = "idn_reclaim_mboxdata"; - - - sip = IDN_INST2SIP(channel); - if (sip == NULL) { - /*LINTED*/ - sip = IDN_INST2SIP(0); - } - ASSERT(sip); - - dp = &idn_domain[domid]; - - PR_DATA("%s: requested %d buffers from domain %d\n", - proc, nbufs, domid); - - if (lock_try(&dp->dreclaim_inprogress) == 0) { - /* - * Reclaim is already in progress, don't - * bother. - */ - PR_DATA("%s: reclaim already in progress\n", proc); - return (0); - } - - if (dp->dmbox.m_send == NULL) - return (0); - - reclaim_list = curr = prev = IDN_NIL_SMROFFSET; - - mi = (int)dp->dreclaim_index; - do { - ushort_t mbox_csum; - - mmp = &dp->dmbox.m_send[mi]; - /* do-while continues down */ - ASSERT(mmp); - if (mutex_tryenter(&mmp->mm_mutex) == 0) { - /* - * This channel is busy, move on. - */ - IDN_MBOXCHAN_INC(mi); - continue; - } - - if (mmp->mm_smr_mboxp == NULL) { - PR_DATA("%s: no smr pointer for domid %d, chan %d\n", - proc, domid, (int)mmp->mm_channel); - ASSERT(mmp->mm_qiget == mmp->mm_qiput); - mutex_exit(&mmp->mm_mutex); - IDN_MBOXCHAN_INC(mi); - continue; - } - mbox_csum = IDN_CKSUM_MBOX(&mmp->mm_smr_mboxp->mt_header); - if (mbox_csum != mmp->mm_smr_mboxp->mt_header.mh_cksum) { - PR_DATA("%s: (d %d, chn %d) mbox hdr " - "cksum (%d) != actual (%d)\n", - proc, domid, (int)mmp->mm_channel, mbox_csum, - mmp->mm_smr_mboxp->mt_header.mh_cksum); - IDN_KSTAT_INC(sip, si_mboxcrc); - IDN_KSTAT_INC(sip, si_oerrors); - mutex_exit(&mmp->mm_mutex); - IDN_MBOXCHAN_INC(mi); - continue; - } - mqp = &mmp->mm_smr_mboxp->mt_queue[0]; - qi = mmp->mm_qiget; - - while (!mqp[qi].ms_owner && - (mqp[qi].ms_flag & IDN_MBOXMSG_FLAG_RECLAIM) && - nbufs) { - idn_mboxmsg_t *msp; - int badbuf; - - badbuf = 0; - msp = &mqp[qi]; - - if (msp->ms_flag & IDN_MBOXMSG_FLAG_ERRMASK) { - PR_DATA("%s: msg.flag ERROR(0x%x) (off=0x%x, " - "domid=%d, qiget=%d)\n", proc, - (uint_t)(msp->ms_flag & - IDN_MBOXMSG_FLAG_ERRMASK), - IDN_BFRAME2OFFSET(msp->ms_bframe), - domid, qi); - } - prev = curr; - curr = IDN_BFRAME2OFFSET(mqp[qi].ms_bframe); - - if (!VALID_NWROFFSET(curr, IDN_SMR_BUFSIZE)) { - badbuf = 1; - IDN_KSTAT_INC(sip, si_reclaim); - } else { - /* - * Put the buffers onto a list that will be - * formally reclaimed down below. This allows - * us to free up mboxq entries as fast as - * possible. - */ - hdrp = IDN_BUF2HDR(IDN_OFFSET2ADDR(curr)); - csum = IDN_CKSUM_PKT(hdrp); - - if (csum != hdrp->b_cksum) { - badbuf = 1; - IDN_KSTAT_INC(sip, si_crc); - IDN_KSTAT_INC(sip, si_fcs_errors); - IDN_KSTAT_INC(sip, si_reclaim); - if (!(mmp->mm_flags & - IDNMMBOX_FLAG_CORRUPTED)) { - cmn_err(CE_WARN, - "IDN: 241: [send] " - "(domain %d, channel " - "%d) SMR CORRUPTED - " - "RELINK", - domid, channel); - mmp->mm_flags |= - IDNMMBOX_FLAG_CORRUPTED; - } - - } else if (reclaim_list == IDN_NIL_SMROFFSET) { - reclaim_list = curr; - } else { - caddr_t bufp; - - bufp = IDN_OFFSET2ADDR(prev); - hdrp = IDN_BUF2HDR(bufp); - hdrp->b_next = curr; - } - } - - mqp[qi].ms_flag = 0; - - IDN_MMBOXINDEX_INC(qi); - - if (!badbuf) { - nbufs--; - reclaim_cnt++; - } - - if (qi == mmp->mm_qiget) - break; - } - mmp->mm_qiget = qi; - - mutex_exit(&mmp->mm_mutex); - - IDN_MBOXCHAN_INC(mi); - - } while ((mi != (int)dp->dreclaim_index) && nbufs); - - dp->dreclaim_index = (uchar_t)mi; - - if (reclaim_list != IDN_NIL_SMROFFSET) { - hdrp = IDN_BUF2HDR(IDN_OFFSET2ADDR(curr)); - hdrp->b_next = IDN_NIL_SMROFFSET; - } - - PR_DATA("%s: reclaimed %d buffers from domain %d\n", - proc, reclaim_cnt, domid); - - if (reclaim_cnt == 0) { - lock_clear(&dp->dreclaim_inprogress); - return (0); - } - - /* - * Now actually go and reclaim (free) the buffers. - */ - free_cnt = 0; - - for (curr = reclaim_list; curr != IDN_NIL_SMROFFSET; ) { - caddr_t bufp; - - bufp = IDN_OFFSET2ADDR(curr); - hdrp = IDN_BUF2HDR(bufp); - csum = IDN_CKSUM_PKT(hdrp); - if (csum != hdrp->b_cksum) { - /* - * Once corruption is detected we - * can't trust our list any further. - * These buffers are effectively lost. - */ - cmn_err(CE_WARN, - "IDN: 241: [send] (domain %d, channel %d) SMR " - "CORRUPTED - RELINK", domid, channel); - break; - } - - curr = hdrp->b_next; - - if (!smr_buf_free(domid, bufp, hdrp->b_length)) - free_cnt++; - } - - if ((dp->dio < IDN_WINDOW_EMAX) && dp->diocheck) { - lock_clear(&dp->diocheck); - IDN_MSGTIMER_STOP(domid, IDNP_DATA, 0); - } - -#ifdef DEBUG - if (free_cnt != reclaim_cnt) { - PR_DATA("%s: *** WARNING *** freecnt(%d) != reclaim_cnt (%d)\n", - proc, free_cnt, reclaim_cnt); - } -#endif /* DEBUG */ - - lock_clear(&dp->dreclaim_inprogress); - - return (reclaim_cnt); -} - -void -idn_signal_data_server(int domid, ushort_t channel) -{ - idn_nack_t nacktype = 0; - idn_domain_t *dp; - idn_chansvr_t *csp; - int c, min_chan, max_chan; - idn_mainmbox_t *mmp; - procname_t proc = "idn_signal_data_server"; - - - if (domid == IDN_NIL_DOMID) - return; - - dp = &idn_domain[domid]; - - if (dp->dawol.a_count > 0) { - /* - * Domain was previously AWOL, but no longer. - */ - IDN_SYNC_LOCK(); - IDN_GLOCK_EXCL(); - idn_clear_awol(domid); - IDN_GUNLOCK(); - IDN_SYNC_UNLOCK(); - } - /* - * Do a precheck before wasting time trying to acquire the lock. - */ - if ((dp->dstate != IDNDS_CONNECTED) || !IDN_DLOCK_TRY_SHARED(domid)) { - /* - * Either we're not connected or somebody is busy working - * on the domain. Bail on the signal for now, we'll catch - * it on the next go around. - */ - return; - } - /* - * We didn't have the drwlock on the first check of dstate, - * but now that we do, make sure the world hasn't changed! - */ - if (dp->dstate != IDNDS_CONNECTED) { - /* - * If we reach here, then no connection. - * Send no response if this is the case. - */ - nacktype = IDNNACK_NOCONN; - goto send_dresp; - } - - /* - * No need to worry about locking mainmbox - * because we're already holding reader - * lock on domain, plus we're just reading - * fields in the mainmbox which only change - * (or go away) when the writer lock is - * held on the domain. - */ - if ((mmp = dp->dmbox.m_recv) == NULL) { - /* - * No local mailbox. - */ - nacktype = IDNNACK_BADCFG; - goto send_dresp; - } - if ((channel != IDN_BROADCAST_ALLCHAN) && (channel >= IDN_MAX_NETS)) { - nacktype = IDNNACK_BADCHAN; - goto send_dresp; - } - if (channel == IDN_BROADCAST_ALLCHAN) { - PR_DATA("%s: requested signal to ALL channels on domain %d\n", - proc, domid); - min_chan = 0; - max_chan = IDN_MAX_NETS - 1; - } else { - PR_DATA("%s: requested signal to channel %d on domain %d\n", - proc, channel, domid); - min_chan = max_chan = (int)channel; - } - mmp += min_chan; - for (c = min_chan; c <= max_chan; mmp++, c++) { - - /* - * We do a quick check for a pending channel. - * If pending it will need activation and we rather - * do that through a separate (proto) thread. - */ - csp = &idn.chan_servers[c]; - - if (csp->ch_recv.c_checkin) { - PR_DATA("%s: chansvr (%d) for domid %d CHECK-IN\n", - proc, c, domid); - continue; - } - - if (IDN_CHAN_TRYLOCK_RECV(csp) == 0) { - /* - * Failed to grab lock, server must be active. - */ - PR_DATA("%s: chansvr (%d) for domid %d already actv\n", - proc, c, domid); - continue; - } - - if (IDN_CHANNEL_IS_PENDING(csp)) { - /* - * Lock is pending. Submit asynchronous - * job to activate and move-on. - */ - IDN_CHAN_UNLOCK_RECV(csp); - idn_submit_chanactivate_job(c); - continue; - } - - /* - * If he ain't active, we ain't talkin'. - */ - if (IDN_CHANNEL_IS_RECV_ACTIVE(csp) == 0) { - IDN_CHAN_UNLOCK_RECV(csp); - PR_DATA("%s: chansvr (%d) for domid %d inactive\n", - proc, c, domid); - continue; - } - - if (mutex_tryenter(&mmp->mm_mutex) == 0) { - IDN_CHAN_UNLOCK_RECV(csp); - continue; - } - - if (mmp->mm_csp != csp) { - /* - * Not registered. - */ - mutex_exit(&mmp->mm_mutex); - IDN_CHAN_UNLOCK_RECV(csp); - continue; - - } - if (mmp->mm_smr_mboxp == NULL) { - /* - * No SMR mailbox. - */ - mutex_exit(&mmp->mm_mutex); - IDN_CHAN_UNLOCK_RECV(csp); - continue; - } - mutex_exit(&mmp->mm_mutex); - - if (csp->ch_recv.c_inprogress) { - /* - * Data server is already active. - */ - IDN_CHAN_UNLOCK_RECV(csp); - PR_DATA("%s: chansvr (%d) for domid %d already actv\n", - proc, c, domid); - continue; - } - ASSERT(csp == &idn.chan_servers[c]); - - - PR_DATA("%s: signaling data dispatcher for chan %d dom %d\n", - proc, c, domid); - ASSERT(csp); - cv_signal(&csp->ch_recv_cv); - IDN_CHAN_UNLOCK_RECV(csp); - } - - if (!nacktype || (channel == IDN_BROADCAST_ALLCHAN)) { - /* - * If there were no real errors or we were - * handling multiple channels, then just - * return. - */ - IDN_DUNLOCK(domid); - return; - } - -send_dresp: - - PR_DATA("%s: sending NACK (%s) back to domain %d (cpu %d)\n", - proc, idnnack_str[nacktype], domid, idn_domain[domid].dcpu); - - idn_send_dataresp(domid, nacktype); - - IDN_DUNLOCK(domid); -} - -/*ARGSUSED*/ -static int -idn_recv_data(int domid, idn_msgtype_t *mtp, idn_xdcargs_t xargs) -{ -#ifdef DEBUG - uint_t msg = mtp ? mtp->mt_mtype : 0; - uint_t msgarg = mtp ? mtp->mt_atype : 0; - procname_t proc = "idn_recv_data"; - - PR_PROTO("%s:%d: DATA message received (msg = 0x%x, msgarg = 0x%x)\n", - proc, domid, msg, msgarg); - PR_PROTO("%s:%d: xargs = (0x%x, 0x%x, 0x%x, 0x%x)\n", - proc, domid, xargs[0], xargs[1], xargs[2], xargs[3]); -#endif /* DEBUG */ - - return (0); -} - -/* - * Only used when sending a negative response. - */ -static void -idn_send_dataresp(int domid, idn_nack_t nacktype) -{ - idn_msgtype_t mt; - - ASSERT(IDN_DLOCK_IS_HELD(domid)); - - if (idn_domain[domid].dcpu == IDN_NIL_DCPU) - return; - - mt.mt_mtype = IDNP_NACK; - mt.mt_atype = IDNP_DATA; - - (void) IDNXDC(domid, &mt, (uint_t)nacktype, 0, 0, 0); -} - -/* - * Checksum routine used in checksum smr_pkthdr_t and idn_mboxhdr_t. - */ -static ushort_t -idn_cksum(register ushort_t *hdrp, register int count) -{ - register int i; - register ushort_t sum = 0; - - for (i = 0; i < count; i++) - sum += hdrp[i]; - - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - - return (~sum); -} - -/* - * ------------------------------------------------ - */ - -int -idn_open_channel(int channel) -{ - int masterid; - idn_chansvr_t *csp; - struct idn *sip; - procname_t proc = "idn_open_channel"; - - if (channel >= IDN_MAX_NETS) { - cmn_err(CE_WARN, - "IDN: 242: maximum channels (%d) already open", - IDN_MAX_NETS); - return (-1); - } - IDN_GLOCK_EXCL(); - - ASSERT(idn.chan_servers != NULL); - - csp = &idn.chan_servers[channel]; - - IDN_CHAN_LOCK_GLOBAL(csp); - - if (IDN_CHANNEL_IS_ATTACHED(csp)) { - PR_CHAN("%s: channel %d already open\n", proc, channel); - IDN_CHAN_UNLOCK_GLOBAL(csp); - IDN_GUNLOCK(); - return (0); - } - - /* - * Need to zero out the kstats now that we're activating - * this channel. - */ - for (sip = idn.sip; sip; sip = sip->si_nextp) { - if (sip->si_dip && (ddi_get_instance(sip->si_dip) == channel)) { - bzero(&sip->si_kstat, sizeof (sip->si_kstat)); - break; - } - } - - IDN_CHANSVC_MARK_ATTACHED(csp); - idn.nchannels++; - CHANSET_ADD(idn.chanset, channel); - IDN_CHANNEL_ATTACH(channel); - - IDN_CHAN_UNLOCK_GLOBAL(csp); - - /* - * We increase our window threshold each time a channel - * is opened. - */ - ASSERT(idn.nchannels > 0); - IDN_WINDOW_EMAX = IDN_WINDOW_MAX + - ((idn.nchannels - 1) * IDN_WINDOW_INCR); - - PR_CHAN("%s: channel %d is OPEN (nchannels = %d)\n", - proc, channel, idn.nchannels); - - masterid = IDN_GET_MASTERID(); - IDN_GUNLOCK(); - - /* - * Check if there is an active master to which - * we're connected. If so, then activate channel. - */ - if (masterid != IDN_NIL_DOMID) { - idn_domain_t *dp; - - dp = &idn_domain[masterid]; - IDN_DLOCK_SHARED(masterid); - if (dp->dvote.v.master && (dp->dstate == IDNDS_CONNECTED)) - (void) idn_activate_channel(CHANSET(channel), - IDNCHAN_ONLINE); - IDN_DUNLOCK(masterid); - } - - return (0); -} - -void -idn_close_channel(int channel, idn_chanop_t chanop) -{ - idn_chansvr_t *csp; - procname_t proc = "idn_close_channel"; - - - ASSERT(idn.chan_servers != NULL); - - csp = &idn.chan_servers[channel]; - - IDN_GLOCK_EXCL(); - - IDN_CHAN_LOCK_GLOBAL(csp); - if (IDN_CHANNEL_IS_DETACHED(csp)) { - PR_CHAN("%s: channel %d already closed\n", proc, channel); - IDN_CHAN_UNLOCK_GLOBAL(csp); - IDN_GUNLOCK(); - return; - } - IDN_CHAN_UNLOCK_GLOBAL(csp); - - idn_deactivate_channel(CHANSET(channel), chanop); - - IDN_CHAN_LOCK_GLOBAL(csp); - - if (chanop == IDNCHAN_HARD_CLOSE) { - idn.nchannels--; - CHANSET_DEL(idn.chanset, channel); - /* - * We increase our window threshold each time a channel - * is opened. - */ - if (idn.nchannels <= 0) - IDN_WINDOW_EMAX = 0; - else - IDN_WINDOW_EMAX = IDN_WINDOW_MAX + - ((idn.nchannels - 1) * IDN_WINDOW_INCR); - } - - PR_CHAN("%s: channel %d is (%s) CLOSED (nchannels = %d)\n", - proc, channel, - (chanop == IDNCHAN_SOFT_CLOSE) ? "SOFT" - : (chanop == IDNCHAN_HARD_CLOSE) ? "HARD" : "OFFLINE", - idn.nchannels); - - IDN_CHAN_UNLOCK_GLOBAL(csp); - IDN_GUNLOCK(); -} - -static int -idn_activate_channel(idn_chanset_t chanset, idn_chanop_t chanop) -{ - int c, rv = 0; - procname_t proc = "idn_activate_channel"; - - PR_CHAN("%s: chanset = 0x%x, chanop = %s\n", - proc, chanset, chanop_str[chanop]); - - if (idn.state != IDNGS_ONLINE) { - /* - * Can't activate any channels unless local - * domain is connected and thus has a master. - */ - PR_CHAN("%s: local domain not connected. no data servers\n", - proc); - return (-1); - } - - for (c = 0; c < IDN_MAX_NETS; c++) { - idn_chansvr_t *csp; - idn_mboxhdr_t *mainhp; - struct idn *sip; - - if (!CHAN_IN_SET(chanset, c)) - continue; - csp = &idn.chan_servers[c]; - - if (chanop == IDNCHAN_ONLINE) { - IDN_CHAN_LOCK_GLOBAL(csp); - } else { - /* - * We don't wait to grab the global lock - * if IDNCHAN_OPEN since these occur along - * critical data paths and will be retried - * anyway if needed. - */ - if (IDN_CHAN_TRYLOCK_GLOBAL(csp) == 0) { - PR_CHAN("%s: failed to acquire global " - "lock for channel %d\n", - proc, c); - continue; - } - } - - if (!IDN_CHANNEL_IS_ATTACHED(csp)) { - PR_CHAN("%s: channel %d NOT open\n", proc, c); - IDN_CHAN_UNLOCK_GLOBAL(csp); - continue; - - } - - if (IDN_CHANNEL_IS_ACTIVE(csp)) { - - PR_CHAN("%s: channel %d already active\n", proc, c); - rv++; - IDN_CHAN_UNLOCK_GLOBAL(csp); - continue; - - } - /* - * Channel activation can happen asynchronously. - */ - IDN_CHANNEL_SUSPEND(c, 0); - - if (IDN_CHANNEL_IS_PENDING(csp) && (chanop == IDNCHAN_OPEN)) { - - PR_CHAN("%s: ACTIVATING channel %d\n", proc, c); - - if (idn_activate_channel_services(c) >= 0) { - PR_CHAN("%s: Setting channel %d ACTIVE\n", - proc, c); - IDN_CHANSVC_MARK_ACTIVE(csp); - rv++; - } - } else if (!IDN_CHANNEL_IS_PENDING(csp) && - (chanop == IDNCHAN_ONLINE)) { - PR_CHAN("%s: Setting channel %d PENDING\n", proc, c); - - IDN_CHANSVC_MARK_PENDING(csp); - } - /* - * Don't syncheader (i.e. touch SMR) unless - * channel is at least ENABLED. For a DISABLED - * channel, the SMR may be invalid so do NOT - * touch it. - */ - if (IDN_CHANNEL_IS_ENABLED(csp) && - ((mainhp = idn_chan_server_syncheader(c)) != NULL)) { - PR_CHAN("%s: marking chansvr (mhp=0x%p) %d READY\n", - proc, (void *)mainhp, c); - mainhp->mh_svr_ready = 1; - } - - IDN_CHANNEL_RESUME(c); - sip = IDN_INST2SIP(c); - ASSERT(sip); - if (sip->si_wantw) { - mutex_enter(&idn.sipwenlock); - idndl_wenable(sip); - mutex_exit(&idn.sipwenlock); - } - IDN_CHAN_UNLOCK_GLOBAL(csp); - - } - /* - * Returns "not active", i.e. value of 0 indicates - * no channels are activated. - */ - return (rv == 0); -} - -static void -idn_deactivate_channel(idn_chanset_t chanset, idn_chanop_t chanop) -{ - int c; - procname_t proc = "idn_deactivate_channel"; - - PR_CHAN("%s: chanset = 0x%x, chanop = %s\n", - proc, chanset, chanop_str[chanop]); - - for (c = 0; c < IDN_MAX_NETS; c++) { - idn_chansvr_t *csp; - idn_mboxhdr_t *mainhp; - - if (!CHAN_IN_SET(chanset, c)) - continue; - - csp = &idn.chan_servers[c]; - - IDN_CHAN_LOCK_GLOBAL(csp); - - if (((chanop == IDNCHAN_SOFT_CLOSE) && - !IDN_CHANNEL_IS_ACTIVE(csp)) || - ((chanop == IDNCHAN_HARD_CLOSE) && - IDN_CHANNEL_IS_DETACHED(csp)) || - ((chanop == IDNCHAN_OFFLINE) && - !IDN_CHANNEL_IS_ENABLED(csp))) { - - ASSERT(!IDN_CHANNEL_IS_RECV_ACTIVE(csp)); - ASSERT(!IDN_CHANNEL_IS_SEND_ACTIVE(csp)); - - PR_CHAN("%s: channel %d already deactivated\n", - proc, c); - IDN_CHAN_UNLOCK_GLOBAL(csp); - continue; - } - - switch (chanop) { - case IDNCHAN_OFFLINE: - IDN_CHANSVC_MARK_IDLE(csp); - IDN_CHANSVC_MARK_DISABLED(csp); - IDN_CHANNEL_STOP(c, 1); - mainhp = idn_chan_server_syncheader(c); - if (mainhp != NULL) - mainhp->mh_svr_ready = 0; - break; - - case IDNCHAN_HARD_CLOSE: - IDN_CHANSVC_MARK_DETACHED(csp); - IDN_CHANNEL_DETACH(c, 1); - mainhp = idn_chan_server_syncheader(c); - if (mainhp != NULL) - mainhp->mh_svr_ready = 0; - break; - - default: - IDN_CHANSVC_MARK_IDLE(csp); - IDN_CHANNEL_SUSPEND(c, 1); - ASSERT(IDN_CHANNEL_IS_ATTACHED(csp)); - break; - } - - lock_clear(&csp->ch_actvlck); - lock_clear(&csp->ch_initlck); - - PR_CHAN("%s: DEACTIVATING channel %d (%s)\n", proc, c, - chanop_str[chanop]); - PR_CHAN("%s: removing chanset 0x%x data svrs for " - "each domain link\n", proc, chanset); - - (void) idn_deactivate_channel_services(c, chanop); - } - /* - * Returns with channels unlocked. - */ -} - -/* - * The priority of the channel server must be less than that - * of the protocol server since the protocol server tasks - * are (can be) of more importance. - * - * Possible range: 60-99. - */ -static pri_t idn_chansvr_pri = (7 * MAXCLSYSPRI) / 8; - -static int -idn_activate_channel_services(int channel) -{ - idn_chansvr_t *csp; - procname_t proc = "idn_activate_channel_services"; - - - ASSERT((channel >= 0) && (channel < IDN_MAX_NETS)); - - csp = &idn.chan_servers[channel]; - - ASSERT(IDN_CHAN_GLOBAL_IS_LOCKED(csp)); - ASSERT(IDN_CHAN_LOCAL_IS_LOCKED(csp)); - - if (csp->ch_recv_threadp) { - /* - * There's an existing dispatcher! - * Must have been idle'd during an earlier - * stint. - */ - ASSERT(csp->ch_id == (uchar_t)channel); - PR_CHAN("%s: existing chansvr FOUND for (c=%d)\n", - proc, channel); - - if (IDN_CHANNEL_IS_PENDING(csp) == 0) - return (-1); - - PR_CHAN("%s: chansvr (c=%d) Rstate = 0x%x, Sstate = 0x%x\n", - proc, channel, csp->ch_recv.c_state, - csp->ch_send.c_state); - - cv_signal(&csp->ch_recv_cv); - - return (0); - } - - if (IDN_CHANNEL_IS_PENDING(csp) == 0) - return (-1); - - csp->ch_id = (uchar_t)channel; - - PR_CHAN("%s: init channel %d server\n", proc, channel); - - csp->ch_recv_morguep = GETSTRUCT(ksema_t, 1); - sema_init(csp->ch_recv_morguep, 0, NULL, SEMA_DRIVER, NULL); - - csp->ch_recv.c_inprogress = 0; - csp->ch_recv.c_waiters = 0; - csp->ch_recv.c_checkin = 0; - csp->ch_recv_changed = 1; - - csp->ch_recv_domset = csp->ch_reg_domset; - - csp->ch_recv_waittime = IDN_NETSVR_WAIT_MIN; - - csp->ch_recv_threadp = thread_create(NULL, 0, - idn_chan_server, &csp, sizeof (csp), &p0, TS_RUN, idn_chansvr_pri); - - csp->ch_send.c_inprogress = 0; - csp->ch_send.c_waiters = 0; - csp->ch_send.c_checkin = 0; - - return (0); -} - -/* - * This routine can handle terminating a set of channel - * servers all at once, however currently only used - * for serial killing, i.e. one-at-a-time. - * - * Entered with RECV locks held on chanset. - * Acquires SEND locks if needed. - * Leaves with all RECV and SEND locks dropped. - */ -static int -idn_deactivate_channel_services(int channel, idn_chanop_t chanop) -{ - idn_chansvr_t *csp; - int cs_count; - int c; - idn_chanset_t chanset; - ksema_t *central_morguep = NULL; - procname_t proc = "idn_deactivate_channel_services"; - - - ASSERT(idn.chan_servers); - - PR_CHAN("%s: deactivating channel %d services\n", proc, channel); - - /* - * XXX - * Old code allowed us to deactivate multiple channel - * servers at once. Keep for now just in case. - */ - chanset = CHANSET(channel); - - /* - * Point all the data dispatchers to the same morgue - * so we can kill them all at once. - */ - cs_count = 0; - for (c = 0; c < IDN_MAX_NETS; c++) { - if (!CHAN_IN_SET(chanset, c)) - continue; - - csp = &idn.chan_servers[c]; - ASSERT(IDN_CHAN_GLOBAL_IS_LOCKED(csp)); - ASSERT(IDN_CHAN_LOCAL_IS_LOCKED(csp)); - - if (csp->ch_recv_threadp == NULL) { - /* - * No channel server home. - * But we're still holding the c_mutex. - * At mark him idle incase we start him up. - */ - PR_CHAN("%s: no channel server found for chan %d\n", - proc, c); - IDN_CHAN_UNLOCK_LOCAL(csp); - IDN_CHAN_UNLOCK_GLOBAL(csp); - continue; - } - ASSERT(csp->ch_id == (uchar_t)c); - - /* - * Okay, now we've blocked the send and receive sides. - */ - - if ((chanop == IDNCHAN_SOFT_CLOSE) || - (chanop == IDNCHAN_OFFLINE)) { - /* - * We set turned off the ACTIVE flag, but there's - * no guarantee he stopped because of it. He may - * have already been sleeping. We need to be - * sure he recognizes the IDLE, so we need to - * signal him and give him a chance to see it. - */ - cv_signal(&csp->ch_recv_cv); - IDN_CHAN_UNLOCK_LOCAL(csp); - IDN_CHAN_UNLOCK_GLOBAL(csp); - cs_count++; - continue; - } - - PR_CHAN("%s: pointing chansvr %d to morgue (0x%p)\n", - proc, c, central_morguep ? (void *)central_morguep - : (void *)(csp->ch_recv_morguep)); - - if (central_morguep == NULL) { - central_morguep = csp->ch_recv_morguep; - } else { - sema_destroy(csp->ch_recv_morguep); - FREESTRUCT(csp->ch_recv_morguep, ksema_t, 1); - - csp->ch_recv_morguep = central_morguep; - } - cv_signal(&csp->ch_recv_cv); - if (csp->ch_recv.c_waiters > 0) - cv_broadcast(&csp->ch_recv.c_cv); - /* - * Save any existing binding for next reincarnation. - * Note that we're holding the local and global - * locks so we're protected against others touchers - * of the ch_bound_cpuid fields. - */ - csp->ch_bound_cpuid_pending = csp->ch_bound_cpuid; - csp->ch_bound_cpuid = -1; - IDN_CHAN_UNLOCK_LOCAL(csp); - IDN_CHAN_UNLOCK_GLOBAL(csp); - cs_count++; - } - PR_CHAN("%s: signaled %d chansvrs for chanset 0x%x\n", - proc, cs_count, chanset); - - if ((chanop == IDNCHAN_SOFT_CLOSE) || (chanop == IDNCHAN_OFFLINE)) - return (cs_count); - - PR_CHAN("%s: waiting for %d (chnset=0x%x) chan svrs to term\n", - proc, cs_count, chanset); - PR_CHAN("%s: morguep = 0x%p\n", proc, (void *)central_morguep); - - ASSERT((cs_count > 0) ? (central_morguep != NULL) : 1); - while (cs_count-- > 0) - sema_p(central_morguep); - - if (central_morguep) { - sema_destroy(central_morguep); - FREESTRUCT(central_morguep, ksema_t, 1); - } - - return (cs_count); -} - -int -idn_chanservers_init() -{ - int c; - idn_chansvr_t *csp; - - - if (idn.chan_servers) - return (0); - - idn.chan_servers = GETSTRUCT(idn_chansvr_t, IDN_MAXMAX_NETS); - - for (c = 0; c < IDN_MAXMAX_NETS; c++) { - csp = &idn.chan_servers[c]; - mutex_init(&csp->ch_send.c_mutex, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&csp->ch_recv.c_mutex, NULL, MUTEX_DEFAULT, NULL); - cv_init(&csp->ch_send.c_cv, NULL, CV_DRIVER, NULL); - cv_init(&csp->ch_recv.c_cv, NULL, CV_DRIVER, NULL); - cv_init(&csp->ch_recv_cv, NULL, CV_DRIVER, NULL); - csp->ch_bound_cpuid = -1; - csp->ch_bound_cpuid_pending = -1; - } - - return (c); -} - -void -idn_chanservers_deinit() -{ - int c; - idn_chansvr_t *csp; - - - if (idn.chan_servers == NULL) - return; - - for (c = 0; c < IDN_MAXMAX_NETS; c++) { - csp = &idn.chan_servers[c]; - - mutex_destroy(&csp->ch_send.c_mutex); - mutex_destroy(&csp->ch_recv.c_mutex); - cv_destroy(&csp->ch_send.c_cv); - cv_destroy(&csp->ch_recv.c_cv); - cv_destroy(&csp->ch_recv_cv); - } - - FREESTRUCT(idn.chan_servers, idn_chansvr_t, IDN_MAXMAX_NETS); - idn.chan_servers = NULL; -} - -static void -idn_exec_chanactivate(void *chn) -{ - int not_active, channel; - idn_chansvr_t *csp; - - channel = (int)(uintptr_t)chn; - - IDN_GLOCK_SHARED(); - if (idn.chan_servers == NULL) { - IDN_GUNLOCK(); - return; - } - csp = &idn.chan_servers[channel]; - - if (IDN_CHAN_TRYLOCK_GLOBAL(csp) == 0) { - /* - * If we can't grab the global lock, then - * something is up, skip out. - */ - IDN_GUNLOCK(); - return; - } - IDN_GUNLOCK(); - - if (IDN_CHANNEL_IS_PENDING(csp) && lock_try(&csp->ch_actvlck)) { - IDN_CHAN_UNLOCK_GLOBAL(csp); - not_active = idn_activate_channel(CHANSET(channel), - IDNCHAN_OPEN); - if (not_active) - lock_clear(&csp->ch_actvlck); - } else { - IDN_CHAN_UNLOCK_GLOBAL(csp); - } -} - -/* - * Delayed activation of channel. We don't want to do this within - * idn_signal_data_server() since that's called within the context - * of an XDC handler so we submit it as a timeout() call to be short - * as soon as possible. - * The ch_initlck & ch_actvlck are used to synchronize activation - * of the channel so that we don't have multiple idn_activate_channel's - * attempting to activate the same channel. - */ -static void -idn_submit_chanactivate_job(int channel) -{ - idn_chansvr_t *csp; - - if (idn.chan_servers == NULL) - return; - csp = &idn.chan_servers[channel]; - - if (lock_try(&csp->ch_initlck) == 0) - return; - - (void) timeout(idn_exec_chanactivate, (caddr_t)(uintptr_t)channel, 1); -} - -/*ARGSUSED0*/ -static void -idn_xmit_monitor(void *unused) -{ - int c, d; - idn_chansvr_t *csp; - idn_chanset_t wake_set; - domainset_t conset; - smr_slab_t *sp; - procname_t proc = "idn_xmit_monitor"; - - CHANSET_ZERO(wake_set); - - mutex_enter(&idn.xmit_lock); - if ((idn.xmit_tid == NULL) || !idn.xmit_chanset_wanted) { - idn.xmit_tid = NULL; - mutex_exit(&idn.xmit_lock); - PR_XMON("%s: bailing out\n", proc); - return; - } - - /* - * No point in transmitting unless state - * is ONLINE. - */ - if (idn.state != IDNGS_ONLINE) - goto retry; - - conset = idn.domset.ds_connected; - - /* - * Try and reclaim some buffers if possible. - */ - for (d = 0; d < MAX_DOMAINS; d++) { - if (!DOMAIN_IN_SET(conset, d)) - continue; - - if (!IDN_DLOCK_TRY_SHARED(d)) - continue; - - if (idn_domain[d].dcpu != IDN_NIL_DCPU) - (void) idn_reclaim_mboxdata(d, 0, -1); - - IDN_DUNLOCK(d); - } - - /* - * Now check if we were successful in getting - * any buffers. - */ - DSLAB_LOCK_SHARED(idn.localid); - sp = idn_domain[idn.localid].dslab; - for (; sp; sp = sp->sl_next) - if (sp->sl_free) - break; - DSLAB_UNLOCK(idn.localid); - - /* - * If there are no buffers available, - * no point in reenabling the queues. - */ - if (sp == NULL) - goto retry; - - CHANSET_ZERO(wake_set); - for (c = 0; c < IDN_MAX_NETS; c++) { - int pending_bits; - struct idn *sip; - - if (!CHAN_IN_SET(idn.xmit_chanset_wanted, c)) - continue; - - csp = &idn.chan_servers[c]; - if (!IDN_CHAN_TRYLOCK_GLOBAL(csp)) - continue; - - pending_bits = csp->ch_state & IDN_CHANSVC_PENDING_BITS; - - sip = IDN_INST2SIP(c); - - if (!csp->ch_send.c_checkin && - (pending_bits == IDN_CHANSVC_PENDING_BITS) && - sip && (sip->si_flags & IDNRUNNING)) { - - IDN_CHAN_UNLOCK_GLOBAL(csp); - CHANSET_ADD(wake_set, c); - - PR_XMON("%s: QENABLE for channel %d\n", proc, c); - - rw_enter(&idn.struprwlock, RW_READER); - mutex_enter(&idn.sipwenlock); - idndl_wenable(sip); - mutex_exit(&idn.sipwenlock); - rw_exit(&idn.struprwlock); - } else { - IDN_CHAN_UNLOCK_GLOBAL(csp); - } - } - - /* - * Clear the channels we enabled. - */ - idn.xmit_chanset_wanted &= ~wake_set; - -retry: - - if (idn.xmit_chanset_wanted == 0) - idn.xmit_tid = NULL; - else - idn.xmit_tid = timeout(idn_xmit_monitor, NULL, - idn_xmit_monitor_freq); - - mutex_exit(&idn.xmit_lock); -} - -void -idn_xmit_monitor_kickoff(int chan_wanted) -{ - procname_t proc = "idn_xmit_monitor_kickoff"; - - mutex_enter(&idn.xmit_lock); - - if (chan_wanted < 0) { - /* - * Wants all channels. - */ - idn.xmit_chanset_wanted = CHANSET_ALL; - } else { - CHANSET_ADD(idn.xmit_chanset_wanted, chan_wanted); - } - - if (idn.xmit_tid != (timeout_id_t)NULL) { - /* - * A monitor is already running, so - * he will catch the new "wants" when - * he comes around. - */ - mutex_exit(&idn.xmit_lock); - return; - } - - PR_XMON("%s: xmit_mon kicked OFF (chanset = 0x%x)\n", - proc, idn.xmit_chanset_wanted); - - idn.xmit_tid = timeout(idn_xmit_monitor, NULL, idn_xmit_monitor_freq); - - mutex_exit(&idn.xmit_lock); -} diff --git a/usr/src/uts/sun4u/starfire/io/idn_smr.c b/usr/src/uts/sun4u/starfire/io/idn_smr.c deleted file mode 100644 index be520d731c..0000000000 --- a/usr/src/uts/sun4u/starfire/io/idn_smr.c +++ /dev/null @@ -1,2178 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - * - * Inter-Domain Network - * - * Shared Memory Region (SMR) supporting code. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/machparam.h> -#include <sys/debug.h> -#include <sys/cpuvar.h> -#include <sys/kmem.h> -#include <sys/mutex.h> -#include <sys/rwlock.h> -#include <sys/systm.h> -#include <sys/machlock.h> -#include <sys/membar.h> -#include <sys/mman.h> -#include <vm/hat.h> -#include <vm/as.h> -#include <vm/hat_sfmmu.h> -#include <sys/vm_machparam.h> -#include <sys/x_call.h> - -#include <sys/idn.h> - -#ifdef DEBUG -#define DIOCHECK(domid) \ -{ \ - int _dio; \ - if ((_dio = idn_domain[domid].dio) < 0) { \ - cmn_err(CE_WARN, \ - ">>>>> file %s, line %d: domain %d, dio = %d", \ - __FILE__, __LINE__, (domid), _dio); \ - } \ -} -#else -#define DIOCHECK(domid) -#endif /* DEBUG */ - -static int smr_slab_alloc_local(int domid, smr_slab_t **spp); -static int smr_slab_alloc_remote(int domid, smr_slab_t **spp); -static void smr_slab_free_local(int domid, smr_slab_t *sp); -static void smr_slab_free_remote(int domid, smr_slab_t *sp); -static int smr_slabwaiter_register(int domid); -static int smr_slabwaiter_unregister(int domid, smr_slab_t **spp); -static int smr_slaballoc_wait(int domid, smr_slab_t **spp); -static smr_slab_t *smr_slab_reserve(int domid); -static void smr_slab_unreserve(int domid, smr_slab_t *sp); -static void smr_slab_reap_global(); - -/* - * Can only be called by the master. Allocate a slab from the - * local pool representing the SMR, on behalf of the given - * domain. Slab is either being requested for use by the - * local domain (i.e. domid == idn.localid), or it's being - * allocated to give to a remote domain which requested one. - * In the base of allocating on behalf of a remote domain, - * smr_slab_t structure is used simply to manage ownership. - * - * Returns: smr_slaballoc_wait - * (EINVAL, ETIMEDOUT) - * smr_slabwatier_unregister - * (0, EINVAL, EBUSY, ENOMEM) - * ENOLCK - */ -static int -smr_slab_alloc_local(int domid, smr_slab_t **spp) -{ - int serrno = 0; - int nwait; - smr_slab_t *sp; - idn_domain_t *dp; - - - /* - * Only the master can make local allocations. - */ - ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); - ASSERT(idn.localid == IDN_GET_MASTERID()); - - *spp = NULL; - - dp = &idn_domain[domid]; - ASSERT(DSLAB_READ_HELD(domid)); - ASSERT(dp->dslab_state == DSLAB_STATE_LOCAL); - - /* - * Register myself with the waiting list. - */ - nwait = smr_slabwaiter_register(domid); - - if (nwait > 1) { - /* - * XXX - old comment? - * Need to drop the read lock _after_ registering - * ourselves with the potential wait list for this allocation. - * Although this allocation is not a remote one, we could - * still have multiple threads on the master trying to - * satisfy (allocate) request on behalf of a remote domain. - */ - /* - * Somebody is already in the process of satisfying - * the allocation request for this respective - * domain. All we need to do is wait and let - * it happen. - */ - serrno = smr_slaballoc_wait(domid, spp); - return (serrno); - } - /* - * I'm the original slab requester for this domain. It's local - * so go ahead and do the job. - */ - - if ((sp = smr_slab_reserve(domid)) == NULL) - serrno = ENOMEM; - - /* - * Allocation may have failed. In either case we've - * got to do the put to at least wake potential waiters up. - */ - if (!serrno) { - if (DSLAB_LOCK_TRYUPGRADE(domid) == 0) { - DSLAB_UNLOCK(domid); - DSLAB_LOCK_EXCL(domid); - } - } - - (void) smr_slaballoc_put(domid, sp, 0, serrno); - - /* - * If serrno is ENOLCK here, then we must have failed - * on the upgrade above, so lock already dropped. - */ - if (serrno != ENOLCK) { - /* - * Need to drop since reaping may be recursive? - */ - DSLAB_UNLOCK(domid); - } - - /* - * Since we were the original requester but never went - * to sleep, we need to directly unregister ourselves - * from the waiting list. - */ - serrno = smr_slabwaiter_unregister(domid, spp); - - /* - * Now that we've satisfied the request, let's check if any - * reaping is necessary. Only the master does this and only - * when allocating slabs, an infrequent event :-o - */ - smr_slab_reap_global(); - - ASSERT((serrno == 0) ? (*spp != NULL) : (*spp == NULL)); - - DSLAB_LOCK_SHARED(domid); - - return (serrno); -} - -/* - * Can only be called by a slave on behalf of himself. Need to - * make a request to the master to allocate a slab of SMR buffers - * for the local domain. - * - * Returns: smr_slaballoc_wait - * (0, EINVAL, EBUSY, ENOMEM) - * ENOLCK - * ECANCELED - */ -static int -smr_slab_alloc_remote(int domid, smr_slab_t **spp) -{ - int nwait; - int serrno = 0; - int bailout = 0; - int masterid; - idn_domain_t *dp, *mdp = NULL; - procname_t proc = "smr_slab_alloc_remote"; - - /* - * Only slaves make remote allocations. - */ - ASSERT(idn.localid != IDN_GET_MASTERID()); - ASSERT(domid == idn.localid); - ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); - - *spp = NULL; - - dp = &idn_domain[domid]; - ASSERT(DSLAB_READ_HELD(domid)); - ASSERT(dp->dslab_state == DSLAB_STATE_REMOTE); - - /* - * Register myself with the slaballoc waiting list. - * Note that only allow one outstanding allocation - * request for the given domain. Other callers which - * detect a slab is needed simply get stuck on the - * waiting list waiting for the original caller to - * get the job done. - * The waiter_register routine will allocate the necessary - * slab structure which will ultimately be inserted in - * the domain's slab list via smr_slaballoc_put(). - */ - nwait = smr_slabwaiter_register(domid); - - /* - * Make sure we have a connection with the master - * before we wait around for nothing and send a - * command off to nowhere. - * First do a quick (no lock) check for global okayness. - */ - if ((idn.state != IDNGS_ONLINE) || - ((masterid = IDN_GET_MASTERID()) == IDN_NIL_DOMID)) { - bailout = 1; - serrno = ECANCELED; - } - /* - * We need to drop our read lock _before_ acquiring the - * slaballoc waiter lock. This is necessary because the - * thread that receives the slab alloc response and fills - * in the slab structure will need to grab the domain write - * lock while holding onto the slaballoc waiter lock. - * Potentially could deadlock if we didn't drop our domain - * lock before. Plus, we've registered. - * - * 4093209 - Note also that we do this _after_ the check for - * idn.masterid where we grab the READER global - * lock. This is to prevent somebody from - * changing our state after we drop the drwlock. - * A deadlock can occur when shutting down a - * domain we're holding the - */ - - if (!bailout) { - mdp = &idn_domain[masterid]; - /* - * Global state is okay. Let's double check the - * state of our actual target domain. - */ - if (mdp->dstate != IDNDS_CONNECTED) { - bailout = 1; - serrno = ECANCELED; - } else if (IDN_DLOCK_TRY_SHARED(masterid)) { - if (mdp->dstate != IDNDS_CONNECTED) { - bailout = 1; - serrno = ECANCELED; - IDN_DUNLOCK(masterid); - } else if (nwait != 1) { - IDN_DUNLOCK(masterid); - } - /* - * Note that keep the drwlock(read) for - * the target (master) domain if it appears - * we're the lucky one to send the command. - * We hold onto the lock until we've actually - * sent the command out. - * We don't reach this place unless it - * appears everything is kosher with - * the target (master) domain. - */ - } else { - bailout = 1; - serrno = ENOLCK; - } - } - - if (bailout) { - ASSERT(serrno); - /* - * Gotta bail. Abort operation. Error result - * will be picked up when we attempt to wait. - */ - PR_SMR("%s: BAILING OUT on behalf domain %d " - "(err=%d, gs=%s, ms=%s)\n", - proc, domid, serrno, idngs_str[idn.state], - (masterid == IDN_NIL_DOMID) - ? "unknown" : idnds_str[idn_domain[masterid].dstate]); - (void) smr_slabwaiter_abort(domid, serrno); - - } else if (nwait == 1) { - /* - * We are the original requester. Initiate the - * actual request to the master. - */ - idn_send_cmd(masterid, IDNCMD_SLABALLOC, IDN_SLAB_SIZE, 0, 0); - ASSERT(mdp); - IDN_DUNLOCK(masterid); - } - - /* - * Wait here for response. Once awakened func returns - * with slab structure possibly filled with gifts! - */ - serrno = smr_slaballoc_wait(domid, spp); - - return (serrno); -} - -/* - * Allocate a slab from the Master on behalf - * of the given domain. Note that master uses - * this function to allocate slabs on behalf of - * remote domains also. - * Entered with drwlock held. - * Leaves with drwlock dropped. - * Returns: EDQUOT - * EINVAL - * ENOLCK - * smr_slab_alloc_local - * smr_slab_alloc_remote - * (0, EINVAL, EBUSY, ENOMEM) - */ -int -smr_slab_alloc(int domid, smr_slab_t **spp) -{ - int serrno = 0; - idn_domain_t *dp; - procname_t proc = "smr_slab_alloc"; - - - dp = &idn_domain[domid]; - - ASSERT(DSLAB_READ_HELD(domid)); - ASSERT(dp->dslab_state != DSLAB_STATE_UNKNOWN); - - *spp = NULL; - - switch (dp->dslab_state) { - case DSLAB_STATE_UNKNOWN: - cmn_err(CE_WARN, - "IDN: 300: no slab allocations without a master"); - serrno = EINVAL; - break; - - case DSLAB_STATE_LOCAL: - /* - * If I'm the master, then get a slab - * from the local SMR pool, but only - * if the number of allocated slabs has - * not been exceeded. - */ - if (((int)dp->dnslabs < IDN_SLAB_MAXPERDOMAIN) || - !IDN_SLAB_MAXPERDOMAIN) - serrno = smr_slab_alloc_local(domid, spp); - else - serrno = EDQUOT; - break; - - case DSLAB_STATE_REMOTE: - /* - * Have to make a remote request. - * In order to prevent overwhelming the master - * with a bunch of requests that it won't be able - * to handle we do a check to see if we're still - * under quota. Note that the limit is known - * apriori based on the SMR/NWR size and - * IDN_SLAB_MINTOTAL. Domains must have the same - * size SMR/NWR, however they can have different - * IDN_SLAB_MINTOTAL. Thus a domain could throttle - * itself however it wishes. - */ - if (((int)dp->dnslabs < IDN_SLAB_MAXPERDOMAIN) || - !IDN_SLAB_MAXPERDOMAIN) - serrno = smr_slab_alloc_remote(domid, spp); - else - serrno = EDQUOT; - break; - - default: - cmn_err(CE_WARN, - "IDN: 301: (ALLOC) unknown slab state (%d) " - "for domain %d", dp->dslab_state, domid); - serrno = EINVAL; - break; - } - - if (*spp == NULL) { - PR_SMR("%s: failed to allocate %s slab [serrno = %d]\n", - proc, (idn.localid == IDN_GET_MASTERID()) ? - "local" : "remote", serrno); - } - - if (serrno) { - IDN_GKSTAT_GLOBAL_EVENT(gk_slabfail, gk_slabfail_last); - } - - return (serrno); -} - -static void -smr_slab_free_local(int domid, smr_slab_t *sp) -{ - int rv; - - /* - * Do a slaballoc_put just in case there may have - * been waiters for slabs for this respective domain - * before we unreserve this slab. - */ - rv = smr_slaballoc_put(domid, sp, 0, 0); - - if (rv == -1) { - /* - * Put failed. Must not have been any waiters. - * Go ahead and unreserve the space. - */ - smr_slab_unreserve(domid, sp); - } -} - -static void -smr_slab_free_remote(int domid, smr_slab_t *sp) -{ - smr_offset_t slab_offset; - int slab_size; - int rv; - int masterid; - - ASSERT(domid == idn.localid); - ASSERT(idn.localid != IDN_GET_MASTERID()); - ASSERT(DSLAB_WRITE_HELD(domid)); - ASSERT(idn_domain[domid].dslab_state == DSLAB_STATE_REMOTE); - - masterid = IDN_GET_MASTERID(); - - ASSERT(masterid != IDN_NIL_DOMID); - - slab_offset = IDN_ADDR2OFFSET(sp->sl_start); - slab_size = (int)(sp->sl_end - sp->sl_start); - - /* - * Do a slaballoc_put just in case there may have - * been waiters for slabs for this domain before - * returning back to the master. - */ - rv = smr_slaballoc_put(domid, sp, 0, 0); - - if ((rv == -1) && (masterid != IDN_NIL_DOMID)) { - /* - * Put failed. No waiters so free the local data - * structure ship the SMR range off to the master. - */ - smr_free_buflist(sp); - FREESTRUCT(sp, smr_slab_t, 1); - - IDN_DLOCK_SHARED(masterid); - idn_send_cmd(masterid, IDNCMD_SLABFREE, slab_offset, slab_size, - 0); - IDN_DUNLOCK(masterid); - } -} - -/* - * Free up the list of slabs passed - */ -void -smr_slab_free(int domid, smr_slab_t *sp) -{ - smr_slab_t *nsp = NULL; - - ASSERT(DSLAB_WRITE_HELD(domid)); - - if (sp == NULL) - return; - - ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); - - switch (idn_domain[domid].dslab_state) { - case DSLAB_STATE_UNKNOWN: - cmn_err(CE_WARN, "IDN: 302: no slab free without a master"); - break; - - case DSLAB_STATE_LOCAL: - /* - * If I'm the master then put the slabs - * back to the local SMR pool. - */ - for (; sp; sp = nsp) { - nsp = sp->sl_next; - smr_slab_free_local(domid, sp); - } - break; - - case DSLAB_STATE_REMOTE: - /* - * If the domid is my own then I'm freeing - * a slab back to the Master. - */ - for (; sp; sp = nsp) { - nsp = sp->sl_next; - smr_slab_free_remote(domid, sp); - } - break; - - default: - cmn_err(CE_WARN, - "IDN: 301: (FREE) unknown slab state (%d) for domain %d", - idn_domain[domid].dslab_state, domid); - break; - } -} - -/* - * Free up the list of slab data structures ONLY. - * This is called during a fatal shutdown of the master - * where we need to garbage collect the locally allocated - * data structures used to manage slabs allocated to the - * local domain. Should never be called by a master since - * the master can do a regular smr_slab_free. - */ -void -smr_slab_garbage_collection(smr_slab_t *sp) -{ - smr_slab_t *nsp; - - ASSERT(idn_domain[idn.localid].dvote.v.master == 0); - - if (sp == NULL) - return; - /* - * Since this is only ever called by a slave, - * the slab structure size always contains a buflist. - */ - for (; sp; sp = nsp) { - nsp = sp->sl_next; - smr_free_buflist(sp); - FREESTRUCT(sp, smr_slab_t, 1); - } -} - -/* - * Allocate a SMR buffer on behalf of the local domain - * which is ultimately targeted for the given domain. - * - * IMPORTANT: This routine is going to drop the domain rwlock (drwlock) - * for the domain on whose behalf the request is being - * made. This routine canNOT block on trying to - * reacquire the drwlock. If it does block then somebody - * must have the write lock on the domain which most likely - * means the domain is going south anyway, so just bail on - * this buffer. Higher levels will retry if needed. - * - * XXX - Support larger than IDN_SMR_BUFSIZE allocations? - * - * Returns: A negative return value indicates lock lost on domid. - * EINVAL, ENOLINK, ENOLCK(internal) - * smr_slaballoc_wait - * (EINVAL, ETIMEDOUT) - * smr_slabwatier_unregister - * (0, EINVAL, EBUSY, ENOMEM) - */ -int -smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp) -{ - register idn_domain_t *dp, *ldp; - smr_slab_t *sp; - caddr_t bufp = NULL; - int serrno; - procname_t proc = "smr_buf_alloc"; - - dp = &idn_domain[domid]; - /* - * Local domain can only allocate on behalf of - * itself if this is a priviledged call and the - * caller is the master. - */ - ASSERT((domid != idn.localid) && (domid != IDN_NIL_DOMID)); - - *bufpp = NULL; - - if (len > IDN_DATA_SIZE) { - cmn_err(CE_WARN, - "IDN: 303: buffer len %d > IDN_DATA_SIZE (%lu)", - len, IDN_DATA_SIZE); - IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, gk_buffail_last); - return (EINVAL); - } - - /* - * Need to go to my local slab list to find - * a buffer. - */ - ldp = &idn_domain[idn.localid]; - /* - * Now we loop trying to locate a buffer out of our - * slabs. We continue this until either we find a - * buffer or we're unable to allocate a slab. Note - * that new slabs are allocated to the front. - */ - DSLAB_LOCK_SHARED(idn.localid); - sp = ldp->dslab; - do { - int spl, all_empty; - - if (sp == NULL) { - if ((serrno = smr_slab_alloc(idn.localid, &sp)) != 0) { - PR_SMR("%s:%d: failed to allocate " - "slab [serrno = %d]", - proc, domid, serrno); - DSLAB_UNLOCK(idn.localid); - IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, - gk_buffail_last); - return (serrno); - } - /* - * Of course, the world may have changed while - * we dropped the lock. Better make sure we're - * still established. - */ - if (dp->dstate != IDNDS_CONNECTED) { - PR_SMR("%s:%d: state changed during slab " - "alloc (dstate = %s)\n", - proc, domid, idnds_str[dp->dstate]); - DSLAB_UNLOCK(idn.localid); - IDN_GKSTAT_GLOBAL_EVENT(gk_buffail, - gk_buffail_last); - return (ENOLINK); - } - /* - * We were able to allocate a slab. Should - * be at the front of the list, spin again. - */ - sp = ldp->dslab; - } - /* - * If we have reached here then we have a slab! - * Hopefully there are free bufs there :-o - */ - spl = splhi(); - all_empty = 1; - for (; sp && !bufp; sp = sp->sl_next) { - smr_slabbuf_t *bp; - - if (sp->sl_free == NULL) - continue; - - if (!lock_try(&sp->sl_lock)) { - all_empty = 0; - continue; - } - - if ((bp = sp->sl_free) == NULL) { - lock_clear(&sp->sl_lock); - continue; - } - - sp->sl_free = bp->sb_next; - bp->sb_next = sp->sl_inuse; - sp->sl_inuse = bp; - /* - * Found a free buffer. - */ - bp->sb_domid = domid; - bufp = bp->sb_bufp; - lock_clear(&sp->sl_lock); - } - splx(spl); - - if (!all_empty && !bufp) { - /* - * If we still haven't found a buffer, but - * there's still possibly a buffer available, - * then try again. Only if we're absolutely - * sure all slabs are empty do we attempt - * to allocate a new one. - */ - sp = ldp->dslab; - } - } while (bufp == NULL); - - *bufpp = bufp; - - ATOMIC_INC(dp->dio); - - DSLAB_UNLOCK(idn.localid); - - return (0); -} - -/* - * Free a buffer allocated to the local domain back to - * its respective slab. Slabs are freed via the slab-reap command. - * XXX - Support larger than IDN_SMR_BUFSIZE allocations? - */ -int -smr_buf_free(int domid, caddr_t bufp, uint_t len) -{ - register smr_slab_t *sp; - smr_slabbuf_t *bp, **bpp; - idn_domain_t *ldp; - int buffreed; - int lockheld = (len == (uint_t)-1); - - /* - * We should never be free'ing a buffer on - * behalf of ourselves as we are never the - * target for allocated SMR buffers. - */ - ASSERT(domid != idn.localid); - - sp = NULL; - buffreed = 0; - ldp = &idn_domain[idn.localid]; - - DSLAB_LOCK_SHARED(idn.localid); - - if (((uintptr_t)bufp & (IDN_SMR_BUFSIZE-1)) && - (IDN_ADDR2OFFSET(bufp) % IDN_SMR_BUFSIZE)) { - cmn_err(CE_WARN, - "IDN: 304: buffer (0x%p) from domain %d not on a " - "%d boundary", (void *)bufp, domid, IDN_SMR_BUFSIZE); - goto bfdone; - } - if (!lockheld && (len > IDN_DATA_SIZE)) { - cmn_err(CE_WARN, - "IDN: 305: buffer length (%d) from domain %d greater " - "than IDN_DATA_SIZE (%lu)", - len, domid, IDN_DATA_SIZE); - goto bfdone; - } - - for (sp = ldp->dslab; sp; sp = sp->sl_next) - if ((bufp >= sp->sl_start) && (bufp < sp->sl_end)) - break; - - if (sp) { - int spl; - - spl = splhi(); - while (!lock_try(&sp->sl_lock)) - ; - bpp = &sp->sl_inuse; - for (bp = *bpp; bp; bp = *bpp) { - if (bp->sb_bufp == bufp) - break; - bpp = &bp->sb_next; - } - if (bp) { - ASSERT(bp->sb_domid == domid); - buffreed++; - bp->sb_domid = IDN_NIL_DOMID; - *bpp = bp->sb_next; - bp->sb_next = sp->sl_free; - sp->sl_free = bp; - } - lock_clear(&sp->sl_lock); - splx(spl); - } -bfdone: - if (buffreed) { - ATOMIC_DEC(idn_domain[domid].dio); - DIOCHECK(domid); - } else { - cmn_err(CE_WARN, - "IDN: 306: unknown buffer (0x%p) from domain %d", - (void *)bufp, domid); - ATOMIC_INC(idn_domain[domid].dioerr); - } - - DSLAB_UNLOCK(idn.localid); - - return (sp ? 0 : -1); -} - -/* - * Alternative interface to smr_buf_free, but with local drwlock - * held. - */ -/* ARGSUSED2 */ -int -smr_buf_free_locked(int domid, caddr_t bufp, uint_t len) -{ - return (smr_buf_free(domid, bufp, (uint_t)-1)); -} - -/* - * Free any and all buffers associated with the given domain. - * Assumption is that domain is dead and buffers are not in use. - * Returns: Number of buffers freed. - * -1 if error. - */ -int -smr_buf_free_all(int domid) -{ - register smr_slab_t *sp; - register smr_slabbuf_t *bp, **bpp; - idn_domain_t *ldp; - int nbufsfreed = 0; - procname_t proc = "smr_buf_free_all"; - - /* - * We should never be free'ing buffers on - * behalf of ourself - */ - ASSERT(domid != idn.localid); - - if (!VALID_DOMAINID(domid)) { - cmn_err(CE_WARN, "IDN: 307: domain ID (%d) invalid", domid); - return (-1); - } - - ldp = &idn_domain[idn.localid]; - - /* - * We grab the writer lock so that we don't have any - * competition during a "free-all" call. - * No need to grab individual slab locks when holding - * dslab(writer). - */ - DSLAB_LOCK_EXCL(idn.localid); - - for (sp = ldp->dslab; sp; sp = sp->sl_next) { - bpp = &sp->sl_inuse; - for (bp = *bpp; bp; bp = *bpp) { - if (bp->sb_domid == domid) { - bp->sb_domid = IDN_NIL_DOMID; - *bpp = bp->sb_next; - bp->sb_next = sp->sl_free; - sp->sl_free = bp; - nbufsfreed++; - } else { - bpp = &bp->sb_next; - } - } - } - - if (nbufsfreed > 0) { - ATOMIC_SUB(idn_domain[domid].dio, nbufsfreed); - idn_domain[domid].dioerr = 0; - DIOCHECK(domid); - } - - DSLAB_UNLOCK(idn.localid); - - PR_SMR("%s: freed %d buffers for domain %d\n", proc, nbufsfreed, domid); - - return (nbufsfreed); -} - -int -smr_buf_reclaim(int domid, int nbufs) -{ - int num_reclaimed = 0; - idn_domain_t *ldp, *dp; - procname_t proc = "smr_buf_reclaim"; - - ldp = &idn_domain[idn.localid]; - dp = &idn_domain[domid]; - - ASSERT(domid != idn.localid); - - if (ATOMIC_CAS(&dp->dreclaim_inprogress, 0, 1)) { - /* - * Reclaim is already in progress, don't - * bother. - */ - PR_DATA("%s: reclaim already in progress\n", proc); - return (0); - } - - PR_SMR("%s: requested %d buffers from domain %d\n", proc, nbufs, domid); - - if (dp->dio && nbufs) { - register smr_slab_t *sp; - int spl; - - DSLAB_LOCK_SHARED(idn.localid); - spl = splhi(); - for (sp = ldp->dslab; sp && nbufs; sp = sp->sl_next) { - register smr_slabbuf_t *bp, **bpp; - - if (sp->sl_inuse == NULL) - continue; - - if (!lock_try(&sp->sl_lock)) - continue; - - if (sp->sl_inuse == NULL) { - lock_clear(&sp->sl_lock); - continue; - } - - bpp = &sp->sl_inuse; - for (bp = *bpp; bp && nbufs; bp = *bpp) { - if (bp->sb_domid == domid) { - /* - * Buffer no longer in use, - * reclaim it. - */ - bp->sb_domid = IDN_NIL_DOMID; - *bpp = bp->sb_next; - bp->sb_next = sp->sl_free; - sp->sl_free = bp; - num_reclaimed++; - nbufs--; - } else { - bpp = &bp->sb_next; - } - } - lock_clear(&sp->sl_lock); - } - splx(spl); - - if (num_reclaimed > 0) { - ATOMIC_SUB(dp->dio, num_reclaimed); - DIOCHECK(domid); - } - DSLAB_UNLOCK(idn.localid); - } - - PR_SMR("%s: reclaimed %d buffers from domain %d\n", - proc, num_reclaimed, domid); - - return (num_reclaimed); -} - -/* - * Returns 1 If any buffers are locked for the given slab. - * 0 If all buffers are free for the given slab. - * - * The caller is assumed to have the slab protected so that no - * new allocations are attempted from it. Also, this is only - * valid to be called with respect to slabs that were allocated - * on behalf of the local domain, i.e. the master is not expected - * to call this function with (slave) slab "representatives". - */ -int -smr_slab_busy(smr_slab_t *sp) -{ - return ((sp && sp->sl_inuse) ? 1 : 0); -} - -int -smr_slabwaiter_init() -{ - register int i; - struct slabwaiter *wp; - - if (idn.slabwaiter != NULL) - return (0); - - /* - * Initialize the slab waiting area for MAX_DOMAINS. - */ - idn.slabwaiter = GETSTRUCT(struct slabwaiter, MAX_DOMAINS); - wp = idn.slabwaiter; - for (i = 0; i < MAX_DOMAINS; wp++, i++) { - wp->w_closed = 0; - mutex_init(&wp->w_mutex, NULL, MUTEX_DEFAULT, NULL); - cv_init(&wp->w_cv, NULL, CV_DEFAULT, NULL); - } - - return (0); -} - -void -smr_slabwaiter_deinit() -{ - register int i; - struct slabwaiter *wp; - - if ((wp = idn.slabwaiter) == NULL) - return; - - for (i = 0; i < MAX_DOMAINS; wp++, i++) { - ASSERT(wp->w_nwaiters == 0); - ASSERT(wp->w_sp == NULL); - cv_destroy(&wp->w_cv); - mutex_destroy(&wp->w_mutex); - } - - FREESTRUCT(idn.slabwaiter, struct slabwaiter, MAX_DOMAINS); - idn.slabwaiter = NULL; -} - -void -smr_slabwaiter_open(domainset_t domset) -{ - int d; - struct slabwaiter *wp; - - if ((domset == 0) || !idn.slabwaiter) - return; - - wp = idn.slabwaiter; - - for (d = 0; d < MAX_DOMAINS; wp++, d++) { - if (!DOMAIN_IN_SET(domset, d)) - continue; - mutex_enter(&wp->w_mutex); - wp->w_closed = 0; - mutex_exit(&wp->w_mutex); - } -} - -void -smr_slabwaiter_close(domainset_t domset) -{ - int d; - struct slabwaiter *wp; - - if ((domset == 0) || !idn.slabwaiter) - return; - - wp = idn.slabwaiter; - - for (d = 0; d < MAX_DOMAINS; wp++, d++) { - if (!DOMAIN_IN_SET(domset, d)) - continue; - mutex_enter(&wp->w_mutex); - wp->w_closed = 1; - cv_broadcast(&wp->w_cv); - mutex_exit(&wp->w_mutex); - } -} - -/* - * Register the caller with the waiting list for the - * given domain. - * - * Protocol: - * 1st Local requester: register -> alloc -> - * put(wakeup|xdc) -> unregister - * Nth Local requester: register -> wait - * 1st Remote requester: register -> xdc -> wait - * Nth Remote requester: register -> wait - * - * Remote Responder: local alloc -> put(xdc) - * Local Handler: xdc -> put(wakeup) - * - * E.g. A standard slave allocation request: - * slave master - * ----- ------ - * idn_slab_alloc(remote) - * - register - * - xdc -> idn_handler - * - wait ... - * idn_slab_alloc(local) - * - register - * - alloc - * - put - * . wakeup [local] - * - unregister - * idn_handler <- - xdc - * - put DONE - * . wakeup [local] - * | - * V - * - wait - * . unregister - * DONE - */ -static int -smr_slabwaiter_register(int domid) -{ - struct slabwaiter *wp; - int nwait; - procname_t proc = "smr_slabwaiter_register"; - - - ASSERT(domid != IDN_NIL_DOMID); - - ASSERT(DSLAB_READ_HELD(domid)); - - wp = &idn.slabwaiter[domid]; - - ASSERT(MUTEX_NOT_HELD(&wp->w_mutex)); - - mutex_enter(&wp->w_mutex); - - nwait = ++(wp->w_nwaiters); - ASSERT(nwait > 0); - - PR_SMR("%s: domain = %d, (new)nwaiters = %d\n", proc, domid, nwait); - - if (nwait > 1) { - /* - * There are already waiters for slab allocations - * with respect to this domain. - */ - PR_SMR("%s: existing waiters for slabs for domain %d\n", - proc, domid); - mutex_exit(&wp->w_mutex); - - return (nwait); - } - PR_SMR("%s: initial waiter for slabs for domain %d\n", proc, domid); - /* - * We are the first requester of a slab allocation for this - * respective domain. Need to prep waiting area for - * subsequent arrival of a slab. - */ - wp->w_sp = NULL; - wp->w_done = 0; - wp->w_serrno = 0; - - mutex_exit(&wp->w_mutex); - - return (nwait); -} - -/* - * It is assumed that the caller had previously registered, - * but wakeup did not occur due to caller never waiting. - * Thus, slaballoc mutex is still held by caller. - * - * Returns: 0 - * EINVAL - * EBUSY - * w_serrno (smr_slaballoc_put) - * (0, ENOLCK, ENOMEM, EDQUOT, EBUSY, ECANCELED) - */ -static int -smr_slabwaiter_unregister(int domid, smr_slab_t **spp) -{ - struct slabwaiter *wp; - int serrno = 0; - procname_t proc = "smr_slabwaiter_unregister"; - - - ASSERT(domid != IDN_NIL_DOMID); - - wp = &idn.slabwaiter[domid]; - - mutex_enter(&wp->w_mutex); - - PR_SMR("%s: domain = %d, nwaiters = %d\n", proc, domid, wp->w_nwaiters); - - if (wp->w_nwaiters <= 0) { - /* - * Hmmm...nobody is registered! - */ - PR_SMR("%s: NO WAITERS (domid = %d)\n", proc, domid); - mutex_exit(&wp->w_mutex); - return (EINVAL); - } - (wp->w_nwaiters)--; - /* - * Is our present under the tree? - */ - if (!wp->w_done) { - /* - * Bummer...no presents. Let the caller know - * via a null slab pointer. - * Note that we don't clean up immediately since - * message might still come in for other waiters. - * Thus, late sleepers may still get a chance. - */ - PR_SMR("%s: bummer no slab allocated for domain %d\n", - proc, domid); - ASSERT(wp->w_sp == NULL); - (*spp) = NULL; - serrno = wp->w_closed ? ECANCELED : EBUSY; - - } else { - (*spp) = wp->w_sp; - serrno = wp->w_serrno; - -#ifdef DEBUG - if (serrno == 0) { - register smr_slab_t *sp; - - ASSERT(wp->w_sp); - PR_SMR("%s: allocation succeeded (domain %d)\n", - proc, domid); - - DSLAB_LOCK_SHARED(domid); - for (sp = idn_domain[domid].dslab; sp; sp = sp->sl_next) - if (sp == wp->w_sp) - break; - if (sp == NULL) - cmn_err(CE_WARN, - "%s:%d: slab ptr = NULL", - proc, domid); - DSLAB_UNLOCK(domid); - } else { - PR_SMR("%s: allocation failed (domain %d) " - "[serrno = %d]\n", proc, domid, serrno); - } -#endif /* DEBUG */ - } - if (wp->w_nwaiters == 0) { - /* - * Last one turns out the lights. - */ - PR_SMR("%s: domain %d last waiter, turning out lights\n", - proc, domid); - wp->w_sp = NULL; - wp->w_done = 0; - wp->w_serrno = 0; - } - mutex_exit(&wp->w_mutex); - - return (serrno); -} - -/* - * Called to abort any slaballoc requests on behalf of the - * given domain. - */ -int -smr_slabwaiter_abort(int domid, int serrno) -{ - ASSERT(serrno != 0); - - return (smr_slaballoc_put(domid, NULL, 0, serrno)); -} - -/* - * Put ourselves into a timedwait waiting for slab to be - * allocated. - * Returns with slaballoc mutex dropped. - * - * Returns: EINVAL - * ETIMEDOUT - * smr_slabwatier_unregister - * (0, EINVAL, EBUSY, ENOMEM) - */ -static int -smr_slaballoc_wait(int domid, smr_slab_t **spp) -{ - struct slabwaiter *wp; - int serrno = 0, serrno_unreg; - procname_t proc = "smr_slaballoc_wait"; - - - wp = &idn.slabwaiter[domid]; - - ASSERT(MUTEX_NOT_HELD(&wp->w_mutex)); - - mutex_enter(&wp->w_mutex); - - PR_SMR("%s: domain = %d, nwaiters = %d, wsp = 0x%p\n", - proc, domid, wp->w_nwaiters, (void *)wp->w_sp); - - if (wp->w_nwaiters <= 0) { - /* - * Hmmm...no waiters registered. - */ - PR_SMR("%s: domain %d, no waiters!\n", proc, domid); - mutex_exit(&wp->w_mutex); - return (EINVAL); - } - ASSERT(DSLAB_READ_HELD(domid)); - DSLAB_UNLOCK(domid); - - if (!wp->w_done && !wp->w_closed) { - int rv; - - /* - * Only wait if data hasn't arrived yet. - */ - PR_SMR("%s: domain %d, going to sleep...\n", proc, domid); - - rv = cv_reltimedwait_sig(&wp->w_cv, &wp->w_mutex, - IDN_SLABALLOC_WAITTIME, TR_CLOCK_TICK); - if (rv == -1) - serrno = ETIMEDOUT; - - PR_SMR("%s: domain %d, awakened (reason = %s)\n", - proc, domid, (rv == -1) ? "TIMEOUT" : "SIGNALED"); - } - /* - * We've awakened or request already filled! - * Unregister ourselves. - */ - mutex_exit(&wp->w_mutex); - - /* - * Any gifts will be entered into spp. - */ - serrno_unreg = smr_slabwaiter_unregister(domid, spp); - - /* - * Leave with reader lock on dslab_lock. - */ - DSLAB_LOCK_SHARED(domid); - - if ((serrno_unreg == EBUSY) && (serrno == ETIMEDOUT)) - return (serrno); - else - return (serrno_unreg); -} - -/* - * A SMR slab was allocated on behalf of the given domain. - * Wakeup anybody that may have been waiting for the allocation. - * Note that if the domain is a remote one, i.e. master is allocating - * on behalf of a slave, it's up to the caller to transmit the - * allocation response to that domain. - * The force flag indicates that we want to install the slab for - * the given user regardless of whether there are waiters or not. - * This is used primarily in situations where a slave may have timed - * out before the response actually arrived. In this situation we - * don't want to send slab back to the master after we went through - * the trouble of allocating one. Master is _not_ allowed to do this - * for remote domains. - * - * Returns: -1 Non-registered waiter or waiting area garbaged. - * 0 Successfully performed operation. - */ -int -smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag, int serrno) -{ - idn_domain_t *dp; - struct slabwaiter *wp; - procname_t proc = "smr_slaballoc_put"; - - - dp = &idn_domain[domid]; - - ASSERT(!serrno ? DSLAB_WRITE_HELD(domid) : 1); - - if (domid == IDN_NIL_DOMID) - return (-1); - - ASSERT(serrno ? (sp == NULL) : (sp != NULL)); - - wp = &idn.slabwaiter[domid]; - - mutex_enter(&wp->w_mutex); - - PR_SMR("%s: domain = %d, bufp = 0x%p, ebufp = 0x%p, " - "(f = %d, se = %d)\n", proc, domid, - (sp ? (void *)sp->sl_start : 0), - (sp ? (void *)sp->sl_end : 0), forceflag, serrno); - - if (wp->w_nwaiters <= 0) { - /* - * There are no waiters!! Must have timed out - * and left. Oh well... - */ - PR_SMR("%s: no slaballoc waiters found for domain %d\n", - proc, domid); - if (!forceflag || serrno || !sp) { - /* - * No waiters and caller doesn't want to force it. - */ - mutex_exit(&wp->w_mutex); - return (-1); - } - PR_SMR("%s: forcing slab onto domain %d\n", proc, domid); - ASSERT(domid == idn.localid); - ASSERT(wp->w_sp == NULL); - wp->w_done = 0; - /* - * Now we fall through and let it be added in the - * regular manor. - */ - } - if (wp->w_done) { - /* - * There's at least one waiter so there has - * to be a slab structure waiting for us. - * If everything is going smoothly, there should only - * be one guy coming through the path of inserting - * an error or good slab. However, if a disconnect was - * detected, you may get several guys coming through - * trying to let everybody know. - */ - ASSERT(wp->w_serrno ? - (wp->w_sp == NULL) : (wp->w_sp != NULL)); - - cv_broadcast(&wp->w_cv); - mutex_exit(&wp->w_mutex); - - return (-1); - } - if (serrno != 0) { - /* - * Bummer...allocation failed. This call is simply - * to wake up the sleepers and let them know. - */ - PR_SMR("%s: slaballoc failed for domain %d\n", proc, domid); - wp->w_serrno = serrno; - wp->w_done = 1; - cv_broadcast(&wp->w_cv); - mutex_exit(&wp->w_mutex); - - return (0); - } - PR_SMR("%s: putting slab into struct (domid=%d, localid=%d)\n", - proc, domid, idn.localid); - /* - * Prep the slab structure. - */ - - if (domid == idn.localid) { - /* - * Allocation was indeed for me. - * Slab may or may not be locked when - * we reach. Normally they will be locked - * if we're being called on behalf of a - * free, and not locked if on behalf of - * a new allocation request. - */ - lock_clear(&sp->sl_lock); - smr_alloc_buflist(sp); -#ifdef DEBUG - } else { - uint_t rv; - /* - * Slab was not allocated on my behalf. Must be - * a master request on behalf of some other domain. - * Prep appropriately. Slab should have been locked - * by smr_slab_reserve. - */ - rv = lock_try(&sp->sl_lock); - ASSERT(!rv); - ASSERT(sp->sl_domid == (short)domid); -#endif /* DEBUG */ - } - - /* - * Slab is ready to go. Insert it into the domain's - * slab list so once we wake everybody up they'll find it. - * You better have write lock if you're putting treasures - * there. - */ - ASSERT(DSLAB_WRITE_HELD(domid)); - - sp->sl_next = dp->dslab; - dp->dslab = sp; - dp->dnslabs++; - - /* - * It's possible to fall through here without waiters. - * This is a case where forceflag was set. - */ - if (wp->w_nwaiters > 0) { - wp->w_sp = sp; - wp->w_serrno = serrno; - wp->w_done = 1; - cv_broadcast(&wp->w_cv); - } else { - ASSERT(forceflag); - wp->w_sp = NULL; - wp->w_serrno = 0; - wp->w_done = 0; - } - mutex_exit(&wp->w_mutex); - - return (0); -} - -/* - * Get the slab representing [bufp,ebufp] from the respective - * domain's pool if all the buffers are free. Remove them from - * the domain's list and return it. - * If bufp == NULL, then return however many free ones you - * can find. - * List of slabs are returned locked (sl_lock). - * XXX - Need minimum limit to make sure we don't free up _all_ - * of our slabs! However, during a shutdown we will need - * method to free them all up regardless of locking. - */ -smr_slab_t * -smr_slaballoc_get(int domid, caddr_t bufp, caddr_t ebufp) -{ - idn_domain_t *dp; - smr_slab_t *retsp, *sp, **psp; - int foundit, islocal = 0; - int nslabs; - procname_t proc = "smr_slaballoc_get"; - - PR_SMR("%s: getting slab for domain %d [bufp=0x%p, ebufp=0x%p]\n", - proc, domid, (void *)bufp, (void *)ebufp); - - dp = &idn_domain[domid]; - - ASSERT(DSLAB_WRITE_HELD(domid)); - - if ((sp = dp->dslab) == NULL) { - PR_SMR("%s: oops, no slabs for domain %d\n", proc, domid); - return (NULL); - } - /* - * If domid is myself then I'm trying to get a slab out - * of my local pool. Otherwise, I'm the master and - * I'm trying to get the slab representative from the - * global pool. - */ - if (domid == idn.localid) - islocal = 1; - - if (bufp != NULL) { - nslabs = -1; - } else { - nslabs = *(int *)ebufp; - if (nslabs == 0) { - PR_SMR("%s: requested nslabs (%d) <= 0\n", - proc, nslabs); - return (NULL); - } else if (nslabs < 0) { - /* - * Caller wants them all! - */ - nslabs = (int)dp->dnslabs; - } - } - - retsp = NULL; - foundit = 0; - for (psp = &dp->dslab; sp; sp = *psp) { - int isbusy; - - if (bufp && (sp->sl_start != bufp)) { - psp = &sp->sl_next; - continue; - } - - if (bufp && (ebufp > sp->sl_end)) { - PR_SMR("%s: bufp/ebufp (0x%p/0x%p) " - "expected (0x%p/0x%p)\n", proc, (void *)bufp, - (void *)ebufp, (void *)sp->sl_start, - (void *)sp->sl_end); - ASSERT(0); - } - /* - * We found the desired slab. Make sure - * it's free. - */ - foundit++; - isbusy = 0; - if (islocal) { - int spl; - - /* - * Some of the buffers in the slab - * are still in use. Unlock the - * buffers we locked and bail out. - */ - spl = splhi(); - if (!lock_try(&sp->sl_lock)) { - isbusy = 1; - foundit--; - } else if (sp->sl_inuse) { - lock_clear(&sp->sl_lock); - isbusy = 1; - foundit--; - } - splx(spl); - } else { - /* - * If not local, then I'm the master getting - * a slab from one of the slaves. In this case, - * their slab structs will always be locked. - */ - ASSERT(!lock_try(&sp->sl_lock)); - } - if (!isbusy) { - /* - * Delete the entry from the list and slap - * it onto our return list. - */ - *psp = sp->sl_next; - sp->sl_next = retsp; - retsp = sp; - } else { - psp = &sp->sl_next; - } - /* - * If bufp == NULL (alternate interface) and we haven't - * found the desired number of slabs yet, keep looking. - */ - if (bufp || (foundit == nslabs)) - break; - } - dp->dnslabs -= (short)foundit; - - if (foundit) { - PR_SMR("%s: found %d free slabs (domid = %d)\n", proc, foundit, - domid); - } else { - PR_SMR("%s: no free slabs found (domid = %d)\n", proc, domid); - } - - /* - * If this is the alternate interface, need to return - * the number of slabs found in the ebufp parameter. - */ - if (bufp == NULL) - *(int *)ebufp = foundit; - - return (retsp); -} - -/* - * Wrapper to hide alternate interface to smr_slaballoc_get() - */ -smr_slab_t * -smr_slaballoc_get_n(int domid, int *nslabs) -{ - smr_slab_t *sp; - - ASSERT(DSLAB_WRITE_HELD(domid)); - - sp = smr_slaballoc_get(domid, NULL, (caddr_t)nslabs); - - return (sp); -} - -/* - * Only called by master. Initialize slab pool based on local SMR. - * Returns number of slabs initialized. - * reserved_size = Length of area at the front of the NWR portion - * of the SMR to reserve and not make available for - * slab allocations. Must be a IDN_SMR_BUFSIZE multiple. - * reserved_area = Pointer to reserved area, if any. - */ -int -smr_slabpool_init(size_t reserved_size, caddr_t *reserved_area) -{ - size_t nwr_available; - int minperpool, ntotslabs, nxslabs, nslabs; - register int p, pp; - register caddr_t bufp; - register smr_slab_t *sp; - - ASSERT(IDN_GLOCK_IS_EXCL()); - ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); - - *reserved_area = NULL; - - nwr_available = MB2B(IDN_NWR_SIZE) - reserved_size; - - if ((idn.localid != IDN_GET_MASTERID()) || - (nwr_available < IDN_SLAB_SIZE) || - (idn.slabpool != NULL) || - ((reserved_size != 0) && (reserved_size & (IDN_SMR_BUFSIZE-1)))) { - return (-1); - } - - idn.slabpool = GETSTRUCT(struct slabpool, 1); - idn.slabpool->ntotslabs = ntotslabs = nwr_available / IDN_SLAB_SIZE; - ASSERT(ntotslabs > 0); - minperpool = (ntotslabs < IDN_SLAB_MINPERPOOL) ? - 1 : IDN_SLAB_MINPERPOOL; - idn.slabpool->npools = (ntotslabs + (minperpool - 1)) / minperpool; - - if ((idn.slabpool->npools & 1) == 0) { - /* - * npools needs to be odd for hashing algorithm. - */ - idn.slabpool->npools++; - } - ASSERT(idn.slabpool->npools > 0); - minperpool = (ntotslabs < idn.slabpool->npools) ? - 1 : (ntotslabs / idn.slabpool->npools); - - /* - * Calculate the number of extra slabs that will need to - * be alloted to the pools. This number will be less than - * npools. Only one extra slab is allocated to each pool - * until we have assigned all the extra slabs. - */ - if (ntotslabs > (idn.slabpool->npools * minperpool)) - nxslabs = ntotslabs - (idn.slabpool->npools * minperpool); - else - nxslabs = 0; - ASSERT((nxslabs >= 0) && (nxslabs < idn.slabpool->npools)); - - idn.slabpool->pool = GETSTRUCT(struct smr_slabtbl, - idn.slabpool->npools); - sp = GETSTRUCT(smr_slab_t, idn.slabpool->ntotslabs); - - idn.slabpool->savep = sp; - bufp = idn.smr.vaddr + reserved_size; - - for (p = nslabs = 0; - (p < idn.slabpool->npools) && (ntotslabs > 0); - p++, ntotslabs -= nslabs) { - - nslabs = (ntotslabs < minperpool) ? ntotslabs : minperpool; - if (nxslabs > 0) { - nslabs++; - nxslabs--; - } - idn.slabpool->pool[p].sarray = sp; - for (pp = 0; pp < nslabs; pp++) { - - sp->sl_next = NULL; - sp->sl_start = bufp; - sp->sl_end = bufp = sp->sl_start + IDN_SLAB_SIZE; - sp->sl_lock = 0; - sp->sl_domid = (short)IDN_NIL_DOMID; - - sp++; - } - idn.slabpool->pool[p].nfree = nslabs; - idn.slabpool->pool[p].nslabs = nslabs; - } - ASSERT((ntotslabs == 0) && (nxslabs == 0)); - /* - * We should be at the end of the SMR at this point. - */ - ASSERT(bufp == (idn.smr.vaddr + reserved_size - + (idn.slabpool->ntotslabs * IDN_SLAB_SIZE))); - - if (reserved_size != 0) - *reserved_area = idn.smr.vaddr; - - return (0); -} - -void -smr_slabpool_deinit() -{ - if (idn.slabpool == NULL) - return; - - FREESTRUCT(idn.slabpool->savep, smr_slab_t, idn.slabpool->ntotslabs); - FREESTRUCT(idn.slabpool->pool, struct smr_slabtbl, - idn.slabpool->npools); - FREESTRUCT(idn.slabpool, struct slabpool, 1); - - idn.slabpool = NULL; -} - -void -smr_alloc_buflist(smr_slab_t *sp) -{ - int n, nbufs; - caddr_t sbufp; - smr_slabbuf_t *hp, *bp; - - if (sp->sl_head) - return; - - nbufs = (sp->sl_end - sp->sl_start) / IDN_SMR_BUFSIZE; - ASSERT(nbufs > 0); - if (nbufs <= 0) { - sp->sl_head = sp->sl_free = sp->sl_inuse = NULL; - return; - } - - hp = GETSTRUCT(smr_slabbuf_t, nbufs); - - sbufp = sp->sl_start; - for (n = 0, bp = hp; n < nbufs; bp++, n++) { - bp->sb_bufp = sbufp; - bp->sb_domid = IDN_NIL_DOMID; - bp->sb_next = bp + 1; - sbufp += IDN_SMR_BUFSIZE; - } - (--bp)->sb_next = NULL; - - sp->sl_head = sp->sl_free = hp; - sp->sl_inuse = NULL; -} - -void -smr_free_buflist(smr_slab_t *sp) -{ - int nbufs; - - if (sp->sl_head == NULL) - return; - - nbufs = (sp->sl_end - sp->sl_start) / IDN_SMR_BUFSIZE; - - FREESTRUCT(sp->sl_head, smr_slabbuf_t, nbufs); - - sp->sl_head = sp->sl_free = sp->sl_inuse = NULL; -} - -/* - * Returns: 0 Successfully located a slab. - * -1 Failure. - */ -static smr_slab_t * -smr_slab_reserve(int domid) -{ - register int p, nextp, s, nexts; - register smr_slab_t *spa; - int startp, starts; - int foundone = 0; - int spl; - procname_t proc = "smr_slab_reserve"; - - p = startp = SMR_SLABPOOL_HASH(domid); - nextp = -1; - - spl = splhi(); - while ((nextp != startp) && !foundone) { - - s = starts = SMR_SLAB_HASH(p, domid); - nexts = -1; - spa = &(idn.slabpool->pool[p].sarray[0]); - - while ((nexts != starts) && !foundone) { - if (lock_try(&spa[s].sl_lock)) { - foundone = 1; - break; - } - nexts = SMR_SLAB_HASHSTEP(p, s); - s = nexts; - } - if (foundone) - break; - nextp = SMR_SLABPOOL_HASHSTEP(p); - p = nextp; - } - splx(spl); - - if (foundone) { - ASSERT((&spa[s] >= idn.slabpool->savep) && - (&spa[s] < (idn.slabpool->savep + - idn.slabpool->ntotslabs))); - - spa[s].sl_domid = (short)domid; - - ATOMIC_DEC(idn.slabpool->pool[p].nfree); - - if (domid == idn.localid) { - smr_slab_t *nsp; - /* - * Caller is actually reserving a slab for - * themself which means they'll need the full - * slab structure to represent all of the I/O - * buffers. The "spa" is just a representative - * and doesn't contain the space to manage the - * individual buffers. Need to alloc a full-size - * struct. - * Note that this results in the returning - * smr_slab_t structure being unlocked. - */ - ASSERT(idn.localid == IDN_GET_MASTERID()); - nsp = GETSTRUCT(smr_slab_t, 1); - nsp->sl_start = spa[s].sl_start; - nsp->sl_end = spa[s].sl_end; - smr_alloc_buflist(nsp); - spa = nsp; - PR_SMR("%s: allocated full slab struct for domain %d\n", - proc, domid); - } else { - /* - * Slab structure gets returned locked. - */ - spa += s; - } - - PR_SMR("%s: allocated slab 0x%p (start=0x%p, size=%lu) for " - "domain %d\n", proc, (void *)spa, (void *)spa->sl_start, - spa->sl_end - spa->sl_start, domid); - } else { - PR_SMR("%s: FAILED to allocate for domain %d\n", - proc, domid); - spa = NULL; - } - - return (spa); -} - -static void -smr_slab_unreserve(int domid, smr_slab_t *sp) -{ - register int p, nextp, s, nexts; - register smr_slab_t *spa; - int foundit = 0; - int startp, starts; - caddr_t bufp; - procname_t proc = "smr_slab_unreserve"; - - bufp = sp->sl_start; - p = startp = SMR_SLABPOOL_HASH(domid); - nextp = -1; - - while ((nextp != startp) && !foundit) { - - s = starts = SMR_SLAB_HASH(p, domid); - nexts = -1; - spa = &(idn.slabpool->pool[p].sarray[0]); - - while ((nexts != starts) && !foundit) { - if (spa[s].sl_start == bufp) { - foundit = 1; - break; - } - nexts = SMR_SLAB_HASHSTEP(p, s); - s = nexts; - } - if (foundit) - break; - nextp = SMR_SLABPOOL_HASHSTEP(p); - p = nextp; - } - if (foundit) { - ASSERT((&spa[s] >= idn.slabpool->savep) && - (&spa[s] < (idn.slabpool->savep + - idn.slabpool->ntotslabs))); - ASSERT(!lock_try(&spa[s].sl_lock)); - ASSERT(spa[s].sl_domid == (short)domid); - - spa[s].sl_next = NULL; - spa[s].sl_domid = (short)IDN_NIL_DOMID; - lock_clear(&spa[s].sl_lock); - - ATOMIC_INC(idn.slabpool->pool[p].nfree); - - PR_SMR("%s: freed (bufp=0x%p) for domain %d\n", - proc, (void *)bufp, domid); - - if (domid == idn.localid) { - /* - * Caller is actually unreserving a slab of their - * own. Note that only the master calls this - * routine. Since the master's local slab - * structures do not get entered into the global - * "representative" pool, we need to free up the - * data structure that was passed in. - */ - ASSERT(idn.localid == IDN_GET_MASTERID()); - ASSERT(sp != &spa[s]); - - smr_free_buflist(sp); - FREESTRUCT(sp, smr_slab_t, 1); - } else { - ASSERT(sp == &spa[s]); - } - } else { - /* - * Couldn't find slab entry for given buf! - */ - PR_SMR("%s: FAILED to free (bufp=0x%p) for domain %d\n", - proc, (void *)bufp, domid); - } -} - -/* - * The Reap Protocol: - * master slave - * ------ ----- - * smr_slab_reap_global - * - idn_broadcast_cmd(SLABREAP) -> idn_recv_cmd(SLABREAP) - * . idn_local_cmd(SLABREAP) - idn_recv_slabreap_req - * - smr_slab_reap . smr_slab_reap - * . smr_slaballoc_get_n - smr_slaballoc_get_n - * . smr_slab_free - smr_slab_free - * - smr_slab_free_local . smr_slab_free_remote - * . smr_slab_unreserve - * <- - idn_send_cmd(SLABFREE) - * idn_recv_cmd(SLABFREE) - * - idn_recv_slabfree_req - * . smr_slaballoc_get - * . smr_slab_free - * - smr_slab_free_local - * . smr_slab_unreserve - * . idn_send_slabfree_resp -> idn_recv_cmd(SLABFREE | ack) - * - idn_recv_slabfree_resp - * - * idn_recv_cmd(SLABREAP | ack) <- . idn_send_slabreap_resp - * - idn_recv_slabreap_resp DONE - * DONE - * - * Check available slabs and if we're below the threshold, kick - * off reaping to all remote domains. There is no guarantee remote - * domains will be able to free up any. - */ -static void -smr_slab_reap_global() -{ - register int p, npools; - register int total_free = 0; - register struct smr_slabtbl *tblp; - static clock_t reap_last = 0; - procname_t proc = "smr_slab_reap_global"; - clock_t now; - - ASSERT(IDN_GET_MASTERID() != IDN_NIL_DOMID); - - DSLAB_LOCK_SHARED(idn.localid); - if (idn_domain[idn.localid].dslab_state != DSLAB_STATE_LOCAL) { - PR_SMR("%s: only allowed by master (%d)\n", - proc, IDN_GET_MASTERID()); - DSLAB_UNLOCK(idn.localid); - return; - } - DSLAB_UNLOCK(idn.localid); - - now = ddi_get_lbolt(); - if ((now > 0) && (now > reap_last) && - ((now - reap_last) < IDN_REAP_INTERVAL)) - return; - - reap_last = now; - - ASSERT(idn.slabpool); - - npools = idn.slabpool->npools; - tblp = idn.slabpool->pool; - - for (p = 0; p < npools; tblp++, p++) - total_free += tblp->nfree; - - if (total_free <= IDN_SLAB_THRESHOLD) { - int diff, reap_per_domain; - - PR_SMR("%s: kicking off reaping " - "(total_free = %d, min = %d)\n", - proc, total_free, IDN_SLAB_THRESHOLD); - - diff = IDN_SLAB_THRESHOLD - total_free; - reap_per_domain = (diff < idn.ndomains) ? - 1 : (diff / idn.ndomains); - - idn_broadcast_cmd(IDNCMD_SLABREAP, reap_per_domain, 0, 0); - } -} - -void -smr_slab_reap(int domid, int *nslabs) -{ - register int d; - int nreclaimed; - smr_slab_t *sp; - domainset_t reapset; - procname_t proc = "smr_slab_reap"; - - /* - * Should only be called on behalf of local - * domain. - */ - if (domid != idn.localid) { - PR_SMR("%s: called by domain %d, should only be local (%d)\n", - proc, domid, idn.localid); - ASSERT(0); - return; - } - /* - * Try and reclaim some buffers so we can possibly - * free up some slabs. - */ - reapset = idn.domset.ds_connected; - - IDN_GKSTAT_GLOBAL_EVENT(gk_reaps, gk_reap_last); - - nreclaimed = 0; - for (d = 0; d < MAX_DOMAINS; d++) { - int nr; - idn_domain_t *dp; - - if (!DOMAIN_IN_SET(reapset, d)) - continue; - - IDN_DLOCK_SHARED(d); - - dp = &idn_domain[d]; - if ((d == idn.localid) || (dp->dcpu < 0)) { - IDN_DUNLOCK(d); - continue; - } - /* - * Clean up any dead I/O errors if possible. - */ - if (dp->dioerr > 0) { - idn_domain_t *ldp; - register int cnt; - register smr_slabbuf_t *bp; - /* - * We need to grab the writer lock to prevent - * anybody from allocating buffers while we - * traverse the slabs outstanding. - */ - cnt = 0; - ldp = &idn_domain[idn.localid]; - IDN_DLOCK_EXCL(idn.localid); - DSLAB_LOCK_EXCL(idn.localid); - for (sp = ldp->dslab; sp; sp = sp->sl_next) - for (bp = sp->sl_inuse; bp; bp = bp->sb_next) - if (bp->sb_domid == d) - cnt++; - DSLAB_UNLOCK(idn.localid); - ASSERT((dp->dio + dp->dioerr) >= cnt); - dp->dio = cnt; - dp->dioerr = 0; - IDN_DUNLOCK(idn.localid); - } - if ((dp->dstate == IDNDS_CONNECTED) && - ((nr = idn_reclaim_mboxdata(d, 0, -1)) > 0)) - nreclaimed += nr; - - IDN_DUNLOCK(d); - } - - DSLAB_LOCK_EXCL(domid); - sp = smr_slaballoc_get_n(domid, nslabs); - if (sp) { - IDN_GKSTAT_ADD(gk_reap_count, (ulong_t)(*nslabs)); - smr_slab_free(domid, sp); - } - DSLAB_UNLOCK(domid); -} - -/* - * --------------------------------------------------------------------- - * Remap the (IDN) shared memory region to a new physical address. - * Caller is expected to have performed a ecache flush if needed. - * --------------------------------------------------------------------- - */ -void -smr_remap(struct as *as, register caddr_t vaddr, - register pfn_t new_pfn, uint_t mblen) -{ - tte_t tte; - size_t blen; - pgcnt_t p, npgs; - procname_t proc = "smr_remap"; - - if (va_to_pfn(vaddr) == new_pfn) { - PR_REMAP("%s: vaddr (0x%p) already mapped to pfn (0x%lx)\n", - proc, (void *)vaddr, new_pfn); - return; - } - - blen = MB2B(mblen); - npgs = btopr(blen); - ASSERT(npgs != 0); - - PR_REMAP("%s: va = 0x%p, pfn = 0x%lx, npgs = %ld, mb = %d MB (%ld)\n", - proc, (void *)vaddr, new_pfn, npgs, mblen, blen); - - /* - * Unmap the SMR virtual address from it's current - * mapping. - */ - hat_unload(as->a_hat, vaddr, blen, HAT_UNLOAD_UNLOCK); - - if (new_pfn == PFN_INVALID) - return; - - /* - * Map the SMR to the new physical address space, - * presumably a remote pfn. Cannot use hat_devload - * because it will think pfn represents non-memory, - * since it may extend beyond its physmax. - */ - for (p = 0; p < npgs; p++) { - sfmmu_memtte(&tte, new_pfn, PROT_READ | PROT_WRITE | HAT_NOSYNC, - TTE8K); - sfmmu_tteload(as->a_hat, &tte, vaddr, NULL, HAT_LOAD_LOCK); - - vaddr += MMU_PAGESIZE; - new_pfn++; - } - - PR_REMAP("%s: remapped %ld pages (expected %ld)\n", - proc, npgs, btopr(MB2B(mblen))); -} diff --git a/usr/src/uts/sun4u/starfire/io/idn_xf.c b/usr/src/uts/sun4u/starfire/io/idn_xf.c deleted file mode 100644 index 797f2479a8..0000000000 --- a/usr/src/uts/sun4u/starfire/io/idn_xf.c +++ /dev/null @@ -1,1694 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - */ - -#include <sys/types.h> -#include <sys/sysmacros.h> -#include <sys/open.h> -#include <sys/param.h> -#include <sys/vm_machparam.h> -#include <sys/machparam.h> -#include <sys/systm.h> -#include <sys/signal.h> -#include <sys/cred.h> -#include <sys/user.h> -#include <sys/proc.h> -#include <sys/vnode.h> -#include <sys/uio.h> -#include <sys/buf.h> -#include <sys/file.h> -#include <sys/kmem.h> -#include <sys/stat.h> -#include <sys/stream.h> -#include <sys/stropts.h> -#include <sys/strsubr.h> -#include <sys/poll.h> -#include <sys/debug.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/errno.h> -#include <sys/modctl.h> -#include <sys/x_call.h> -#include <sys/cpuvar.h> -#include <sys/machcpuvar.h> -#include <sys/machsystm.h> - -#include <sys/pda.h> -#include <sys/starfire.h> -#include <sys/idn.h> -#include <sys/idn_xf.h> - -kmutex_t idn_xf_mutex; /* to serialize hardware access */ -/* - * This data structure is referenced during the cross-call - * update of the CICs. The semaphore is used for synchronization - * when waiting for completion of the respective operation. - * We want IDNCIC_TIMEOUT ticks for all the cpus to check-in - * before we bail out and fail the operation. - */ -#define IDNCIC_TIMEOUT (30*hz) -#define IDNCIC_TIMECHK (hz/3) -#define IDNCIC_UNKNOWN 0 -#define IDNCIC_OK 1 /* values for xf_errcic */ -#define IDNCIC_ERR 2 -#define IDNCIC_BUSY 3 - -#ifdef DEBUG -#define NCICREGS 3 /* smmask, smbar, smlar */ -#define CICREG_SMMASK 0 -#define CICREG_SMBAR 1 -#define CICREG_SMLAR 2 - -#define RESET_CIC_HISTORY() \ - (xf_cicboards = xf_cicbuses = 0, \ - bzero(xf_cicregs, sizeof (xf_cicregs))) - -#define UPDATE_CIC_HISTORY(reg, brd, bus, val) \ - (BOARDSET_ADD(xf_cicboards, (brd)), \ - BOARDSET_ADD(xf_cicbuses, (bus)), \ - xf_cicregs[brd][bus][reg] = (val)) - -#define DUMP_CIC_HISTORY() \ -{ \ - if (idn_debug & IDNDBG_XF) { \ - int _bd, _bs; \ - procname_t _proc = "dump_cic_history"; \ - for (_bd = 0; _bd < MAX_BOARDS; _bd++) { \ - if (!BOARD_IN_SET(xf_cicboards, _bd)) \ - continue; \ - for (_bs = 0; _bs < MAX_ABUSES; _bs++) { \ - if (!BOARD_IN_SET(xf_cicbuses, _bs)) \ - continue; \ - printf("%s: (bd.bs = %d.%d) m/b/l = " \ - "%x/%x/%x\n", _proc, _bd, _bs, \ - xf_cicregs[_bd][_bs][CICREG_SMMASK], \ - xf_cicregs[_bd][_bs][CICREG_SMBAR], \ - xf_cicregs[_bd][_bs][CICREG_SMLAR]); \ - } \ - } \ - DEBUG_DELAY(); \ - } \ -} - -/* - * Globally updated during CIC reg updates. Everybody has - * a unique location, so no concern about updates stepping - * on each other. - */ -static ushort_t xf_cicboards, xf_cicbuses; -static uint_t xf_cicregs[MAX_BOARDS][MAX_ABUSES][NCICREGS]; -#else /* DEBUG */ -#define RESET_CIC_HISTORY() -#define UPDATE_CIC_HISTORY(reg, brd, bus, val) -#define DUMP_CIC_HISTORY() -#endif /* DEBUG */ - -struct idnxf_cic_info { /* protected by idn_xf_mutex */ -/* 0 */ short xf_abus_mask; -/* 2 */ boardset_t xf_boardset; -/* 4 */ uint_t xf_smbase; -/* 8 */ uint_t xf_smlimit; -/* c */ int xf_doadd; - -/* 10 */ int xf_count; /* atomically updated */ -/* 14 */ time_t xf_start_time; -/* 18 */ kcondvar_t xf_cv; -/* 1a */ short xf_errtimer; -/* 1c */ int xf_errcnt; /* atomically updated */ - -/* 20 */ uchar_t xf_errcic[MAX_BOARDS][MAX_ABUSES]; - -/* 60 */ kmutex_t xf_mutex; -}; /* sizeof = 0x68 = 104 (26X) */ - -static struct idnxf_cic_info idnxf_cic_info; -#ifdef DEBUG -static uint_t o_idn_debug; -#endif /* DEBUG */ - -int idn_check_cpu_per_board = 1; - -static int pc_prep_cic_buffer(int cpuid, uint_t cicdata); -static int cic_write_sm_mask(int board, int bus, boardset_t sm_mask); -static int cic_write_sm_bar(int board, int bus, uint_t sm_bar); -static int cic_write_sm_lar(int board, int bus, uint_t sm_lar); -static int cic_get_smmask_bit(void); -static int pc_write_madr(pda_handle_t ph, - int lboard, int rboard, uint_t madr); -static boardset_t get_boardset(pda_handle_t ph, int *nboards); -static int verify_smregs(int brd, int bus, boardset_t smmask, - uint_t smbase, uint_t smlimit); -static void idnxf_shmem_wakeup(void *arg); -static void idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2); -static int idnxf_shmem_update_all(pda_handle_t ph, - boardset_t boardset, uint_t smbase, - uint_t smlimit, int doadd); - -#define PHYSIO_ST(paddr, val) (stphysio((paddr), (val))) -#define PHYSIO_LD(paddr) (ldphysio(paddr)) -#define PHYSIO_STH(paddr, val) (sthphysio((paddr), (val))) -#define PHYSIO_LDH(paddr) (ldhphysio(paddr)) - -#ifdef DEBUG -#define DEBUG_DELAY() (drv_usecwait(5000)) /* 5 ms */ -#else /* DEBUG */ -#define DEBUG_DELAY() -#endif /* DEBUG */ - - -/* - * --------------------------------------------------------------------- - */ -boardset_t -cic_read_domain_mask(int board, int bus) -{ - u_longlong_t csr_addr; - boardset_t domain_mask; - procname_t proc = "cic_read_domain_mask"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_DOMAIN_MASK_ADDR, - bus); - PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - - domain_mask = (boardset_t)PHYSIO_LDH(csr_addr); - - return (domain_mask); -} - -boardset_t -cic_read_sm_mask(int board, int bus) -{ - u_longlong_t csr_addr; - boardset_t sm_mask; - procname_t proc = "cic_read_sm_mask"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR, - bus); - PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - - sm_mask = (boardset_t)PHYSIO_LDH(csr_addr); - - return (sm_mask); -} - -static int -cic_write_sm_mask(int board, int bus, boardset_t sm_mask) -{ - u_longlong_t csr_addr; - int cnt; - procname_t proc = "cic_write_sm_mask"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - sm_mask &= 0xffff; - /* - * Before we can write to the CIC, we need to set - * up the CIC write data buffer in the PC. - */ - if (pc_prep_cic_buffer(CPU->cpu_id, (uint_t)sm_mask) < 0) - return (-1); - - /* - * Now we can write to the CIC. - */ - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR, - bus); - PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - PR_XF("%s: writing sm_mask = 0x%x\n", - proc, (ushort_t)sm_mask); - - UPDATE_CIC_HISTORY(CICREG_SMMASK, board, bus, sm_mask); - - PHYSIO_STH(csr_addr, (ushort_t)sm_mask); - /* - * Read back for verification. - */ - for (cnt = 0; (PHYSIO_LDH(csr_addr) != sm_mask) && (cnt < 10); cnt++) - ; - - return ((cnt == 10) ? -1 : 0); -} - -uint_t -cic_read_sm_bar(int board, int bus) -{ - u_longlong_t csr_addr; - uint_t sm_bar; - procname_t proc = "cic_read_sm_bar"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR, - bus); - PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - - sm_bar = (uint_t)PHYSIO_LDH(csr_addr); - sm_bar <<= 16; - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR, - bus); - PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - - sm_bar |= (uint_t)PHYSIO_LDH(csr_addr); - - return (sm_bar); -} - -static int -cic_write_sm_bar(int board, int bus, uint_t sm_bar) -{ - int cnt; - u_longlong_t csr_addr; - uint_t sm_bar_lsb, sm_bar_msb; - procname_t proc = "cic_write_sm_bar"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - sm_bar_lsb = sm_bar & 0xffff; - sm_bar_msb = (sm_bar >> 16) & 0xffff; - - /* - * Before we can write to the CIC, we need to set - * up the CIC write data buffer in the PC. - */ - if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_msb) < 0) - return (-1); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR, - bus); - PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - PR_XF("%s:MSB: sm_bar[31:16] = 0x%x\n", - proc, (ushort_t)sm_bar_msb); - - UPDATE_CIC_HISTORY(CICREG_SMBAR, board, bus, sm_bar); - - PHYSIO_STH(csr_addr, (ushort_t)sm_bar_msb); - for (cnt = 0; - ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_msb) && (cnt < 10); - cnt++) - ; - if (cnt == 10) { - cmn_err(CE_WARN, - "IDN: 500: failed to write sm_bar (msb) (0x%x)", - (uint_t)sm_bar_msb); - return (-1); - } - - /* - * Now to LSB portion. - */ - if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_lsb) < 0) - return (-1); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR, - bus); - PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - PR_XF("%s:LSB: sm_bar[15:0] = 0x%x\n", - proc, (ushort_t)sm_bar_lsb); - - PHYSIO_STH(csr_addr, (ushort_t)sm_bar_lsb); - for (cnt = 0; - ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_lsb) && (cnt < 10); - cnt++) - ; - if (cnt == 10) { - cmn_err(CE_WARN, - "IDN: 500: failed to write sm_bar (lsb) (0x%x)", - (uint_t)sm_bar_lsb); - return (-1); - } - - return (0); -} - -uint_t -cic_read_sm_lar(int board, int bus) -{ - u_longlong_t csr_addr; - uint_t sm_lar; - procname_t proc = "cic_read_sm_lar"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR, - bus); - PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - - sm_lar = (uint_t)PHYSIO_LDH(csr_addr); - sm_lar <<= 16; - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR, - bus); - PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - - sm_lar |= (uint_t)PHYSIO_LDH(csr_addr); - - return (sm_lar); -} - -static int -cic_write_sm_lar(int board, int bus, uint_t sm_lar) -{ - int cnt; - u_longlong_t csr_addr; - uint_t sm_lar_lsb, sm_lar_msb; - procname_t proc = "cic_write_sm_lar"; - - ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); - - sm_lar_lsb = sm_lar & 0xffff; - sm_lar_msb = (sm_lar >> 16) & 0xffff; - - /* - * Before we can write to the CIC, we need to set - * up the CIC write data buffer in the PC. - */ - if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_msb) < 0) - return (-1); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR, - bus); - PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - PR_XF("%s:MSB: sm_lar[31:16] = 0x%x\n", - proc, (ushort_t)sm_lar_msb); - - UPDATE_CIC_HISTORY(CICREG_SMLAR, board, bus, sm_lar); - - PHYSIO_STH(csr_addr, (ushort_t)sm_lar_msb); - for (cnt = 0; - ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_msb) && (cnt < 10); - cnt++) - ; - if (cnt == 10) { - cmn_err(CE_WARN, - "IDN: 501: failed to write sm_lar (msb) (0x%x)", - (uint_t)sm_lar_msb); - return (-1); - } - - /* - * Now to LSB portion. - */ - if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_lsb) < 0) - return (-1); - - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR, - bus); - PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", - proc, board, bus, csr_addr); - PR_XF("%s:LSB: sm_lar[15:0] = 0x%x\n", - proc, (ushort_t)sm_lar_lsb); - - PHYSIO_STH(csr_addr, (ushort_t)sm_lar_lsb); - for (cnt = 0; - ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_lsb) && (cnt < 10); - cnt++) - ; - if (cnt == 10) { - cmn_err(CE_WARN, - "IDN: 501: failed to write sm_lar (lsb) (0x%x)", - (uint_t)sm_lar_lsb); - return (-1); - } - - return (0); -} - -static int -cic_get_smmask_bit(void) -{ - u_longlong_t csr_addr; - int board; - uint_t config1; - procname_t proc = "cic_get_smmask_bit"; - - affinity_set(CPU_CURRENT); - - board = CPUID_TO_BOARDID(CPU->cpu_id); - /* - * Now that I'm stuck on this cpu I can go look at this - * board's CIC registers. - */ - csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_CONFIG1_ADDR, 0); - PR_XF("%s: (bd=%d) csr_addr = 0x%llx (via cpu %d)\n", - proc, board, csr_addr, (int)CPU->cpu_id); - - config1 = (uint_t)PHYSIO_LDH(csr_addr); - - config1 = CIC_CONFIG1_SMMASK_BIT(config1); - - affinity_clear(); - - return (config1); -} - -static int -pc_prep_cic_buffer(int cpuid, uint_t cicdata) -{ - int rv; - int brd, port; - u_longlong_t csr_addr; - register int cnt; - procname_t proc = "pc_prep_cic_buffer"; - - - ASSERT(CPU->cpu_id == cpuid); - - port = cpuid % plat_max_cpu_units_per_board(); - brd = CPUID_TO_BOARDID(cpuid); - - csr_addr = STARFIRE_PC_CICBUF_ADDR(brd, port); - - /* - * csr_addr now points to CIC write buffer which resides - * in PC register space. - */ - PR_XF("%s: (cpu=%d) csr_addr = 0x%llx\n", proc, cpuid, csr_addr); - - PHYSIO_ST(csr_addr, cicdata); - - /* - * Now we need to read back the data to guarantee - * it got there. Part of the PC protocol. - */ - for (cnt = 0; (PHYSIO_LD(csr_addr) != cicdata) && (cnt < 10); - cnt++) - ; - - rv = 0; - if (cnt == 10) { - cmn_err(CE_WARN, - "IDN: 502: unable to store data (0x%x) to " - "CIC buffer (0x%llx)", - cicdata, csr_addr); - rv = -1; - } else if (cnt >= 1) { - PR_XF("%s: MULTIPLE READS (cpu=%d) cnt = %d\n", - proc, cpuid, cnt); - } - - return (rv); -} - -/* - * -------------------------------------------------- - * Write the given MC address decoding register contents (madr) of - * the respective remote board (rboard) into all the PCs located on - * the local board (lboard). - * -------------------------------------------------- - */ -static int -pc_write_madr(pda_handle_t ph, int lboard, int rboard, uint_t madr) -{ - u_longlong_t pc_madr_addr; - register int p, ioc; - register ushort_t procset, iocset; - int rv = 0; - uint_t rd_madr; - board_desc_t *lbp; - procname_t proc = "pc_write_madr"; - - lbp = pda_get_board_info(ph, lboard); - - ASSERT(lbp); - ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD); - - procset = lbp->bda_proc; - iocset = lbp->bda_ioc; - - /* - * Update the PCs for the cpus. - */ - for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) { - int i; - - if (!((procset & BDAN_MASK) == BDAN_GOOD)) - continue; - - pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, - rboard, p); - - /* - * On this first iteration of updating the PC - * we need to turn off the MADR VALID bit so that - * there's no accidental usage of the entry before - * all four bytes have been updated in the PC. - */ - if (madr != 0) { - /* - * Need to clear valid bit on first - * go around. - */ - madr &= ~STARFIRE_PC_MADR_VALIDBIT; - } - PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) " - "[lb=%d, rb=%d, cpu=%d]\n", - proc, madr, pc_madr_addr, lboard, rboard, p); - DEBUG_DELAY(); - - for (i = 0; i < 20; i++) { - PHYSIO_ST(pc_madr_addr, madr); - /* - * Read back for sanity check. - */ - rd_madr = PHYSIO_LD(pc_madr_addr); - if (madr == rd_madr) - break; - } - if (i > 0) { - PR_XF("%s: WARNING: (1) lb=%d, rb=%d, " - "madr=0x%x (i=%d)\n", - proc, lboard, rboard, madr, i); - } - if (rd_madr != madr) { - cmn_err(CE_WARN, - "IDN: 503: (invalidate) failed to update " - "PC madr (expected 0x%x, actual 0x%x)", - madr, rd_madr); - rv++; - continue; - } - if (madr == 0) { - continue; - } else { - /* - * Turn the valid bit back on. - */ - madr |= STARFIRE_PC_MADR_VALIDBIT; - } - PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) " - "[lb=%d, rb=%d, cpu=%d]\n", - proc, madr, pc_madr_addr, lboard, rboard, p); - DEBUG_DELAY(); - - for (i = 0; i < 20; i++) { - PHYSIO_ST(pc_madr_addr, madr); - /* - * Read back for sanity check. - */ - rd_madr = PHYSIO_LD(pc_madr_addr); - if (madr == rd_madr) - break; - } - if (i > 0) { - PR_XF("%s: WARNING: (2) lb=%d, rb=%d, " - "madr=0x%x (i=%d)\n", - proc, lboard, rboard, madr, i); - } - if (rd_madr != madr) { - cmn_err(CE_WARN, - "IDN: 503: (validate) failed to update " - "PC madr (expected 0x%x, actual 0x%x)", - madr, rd_madr); - rv++; - } - } - /* - * Update the PCs for the iocs. - */ - for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) { - int i; - - if (!((iocset & BDAN_MASK) == BDAN_GOOD)) - continue; - - pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, - rboard, ioc + 4); - - if (madr != 0) { - /* - * Need to clear valid bit on first - * go around. - */ - madr &= ~STARFIRE_PC_MADR_VALIDBIT; - } - PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) " - "[lb=%d, rb=%d, ioc=%d]\n", - proc, madr, pc_madr_addr, lboard, rboard, ioc); - DEBUG_DELAY(); - - for (i = 0; i < 20; i++) { - PHYSIO_ST(pc_madr_addr, madr); - /* - * Read back for sanity check. - */ - rd_madr = PHYSIO_LD(pc_madr_addr); - if (madr == rd_madr) - break; - } - if (i > 0) { - PR_XF("%s: WARNING: (3) lb=%d, rb=%d, " - "madr=0x%x (i=%d)\n", - proc, lboard, rboard, madr, i); - } - if (rd_madr != madr) { - cmn_err(CE_WARN, - "IDN: 504: (invalidate) failed to update " - "IOPC madr (expected 0x%x, actual 0x%x)", - madr, rd_madr); - rv++; - continue; - } - - if (madr == 0) { - continue; - } else { - /* - * Turn the valid bit back on. - */ - madr |= STARFIRE_PC_MADR_VALIDBIT; - } - - PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) " - "[lb=%d, rb=%d, ioc=%d]\n", - proc, madr, pc_madr_addr, lboard, rboard, ioc); - DEBUG_DELAY(); - - for (i = 0; i < 20; i++) { - PHYSIO_ST(pc_madr_addr, madr); - /* - * Read back for sanity check. - */ - rd_madr = PHYSIO_LD(pc_madr_addr); - if (madr == rd_madr) - break; - } - if (i > 0) { - PR_XF("%s: WARNING: (4) lb=%d, rb=%d, " - "madr=0x%x (i=%d)\n", - proc, lboard, rboard, madr, i); - } - if (rd_madr != madr) { - cmn_err(CE_WARN, - "IDN: 504: (validate) failed to update " - "IOPC madr (expected 0x%x, actual 0x%x)", - madr, rd_madr); - rv++; - } - } - - return (rv ? -1 : 0); -} - -/* - * -------------------------------------------------- - * Read the array of MC address decoding registers from one of the - * PCs on the local board (lboard) into the given in array (mc_adr). - * -------------------------------------------------- - */ -void -pc_read_madr(pda_handle_t ph, int lboard, uint_t mc_adr[], int local_only) -{ - u_longlong_t pc_madr_addr; - register int p, ioc; - register ushort_t procset, iocset; - int brd; - board_desc_t *lbp; - - lbp = pda_get_board_info(ph, lboard); - - ASSERT(lbp); - ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD); - - procset = lbp->bda_proc; - iocset = lbp->bda_ioc; - - for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) - if ((procset & BDAN_MASK) == BDAN_GOOD) - break; - - if (p == MAX_PROCMODS) { - /* - * Couldn't find a PC off a cpu, let's check the - * IOCs. - */ - for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) - if ((iocset & BDAN_MASK) == BDAN_GOOD) - break; - if (ioc == MAX_IOCS) { - cmn_err(CE_WARN, - "IDN: 505: board %d missing any valid PCs", - lboard); - return; - } - p = ioc + 4; - } - - pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 0, p); - /* - * pc_madr_addr = Starts at entry for board 0. - */ - for (brd = 0; brd < MAX_BOARDS; brd++) { - /* - * It's possible our local PC may have old entries to - * AWOL domains. Only want to pay attention to PC - * entries corresponding to our boards. - */ - lbp = pda_get_board_info(ph, brd); - if (!local_only || ((lbp->bda_board & BDAN_MASK) == BDAN_GOOD)) - mc_adr[brd] = PHYSIO_LD(pc_madr_addr); - else - mc_adr[brd] = 0; - - pc_madr_addr += ((u_longlong_t)1 << - STARFIRE_PC_MADR_BOARD_SHIFT); - } -} - -/* - * -------------------------------------------------- - * Read the MC address decoding register contents for all - * possible boards and store the results in their respective - * slot in mc_adr. Keep a count of non-zero MC ADRs and - * return that. - * -------------------------------------------------- - */ -void -mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], int *nmcadr) -{ - int brd; - uint_t madr[MAX_BOARDS]; - - /* - * Note that each PC has a complete copy of all MC contents - * and so all we have to do is read one PC rather than - * each of the MCs in the system. - */ - brd = CPUID_TO_BOARDID(CPU->cpu_id); - pc_read_madr(ph, brd, madr, 1); - - *nmcadr = 0; - for (brd = 0; brd < MAX_BOARDS; brd++) - if ((mc_adr[brd] = madr[brd]) != 0) - (*nmcadr)++; -} - -static boardset_t -get_boardset(pda_handle_t ph, int *nboards) -{ - int brd; - int nbrds = 0; - boardset_t bmask; - - if (nboards != NULL) - *nboards = 0; - - bmask = 0; - for (brd = 0; brd < MAX_BOARDS; brd++) { - if (pda_board_present(ph, brd)) { - bmask |= 1 << brd; - nbrds++; - } - } - if (nboards != NULL) - *nboards = (short)nbrds; - - return (bmask); -} - -int -update_local_hw_config(idn_domain_t *ldp, struct hwconfig *loc_hw) -{ - procname_t proc = "update_local_hw_config"; - - ASSERT(IDN_DLOCK_IS_EXCL(ldp->domid)); - ASSERT(IDN_GLOCK_IS_EXCL()); - ASSERT(ldp == &idn_domain[idn.localid]); - - if (ldp->dhw.dh_boardset != loc_hw->dh_boardset) { - int c; - - PR_PROTO("%s: NEW HW CONFIG (old_bset = 0x%x, " - "new_bset = 0x%x)\n", - proc, ldp->dhw.dh_boardset, loc_hw->dh_boardset); - - PR_PROTO("%s: clearing boardset 0x%x\n", proc, - ldp->dhw.dh_boardset & ~loc_hw->dh_boardset); - PR_PROTO("%s: setting boardset 0x%x\n", proc, - loc_hw->dh_boardset & ~ldp->dhw.dh_boardset); - - idn.dc_boardset &= ~ldp->dhw.dh_boardset; - idn.dc_boardset |= loc_hw->dh_boardset; - for (c = 0; c < NCPU; c++) { - if (CPU_IN_SET(ldp->dcpuset, c)) { - CPUSET_DEL(idn.dc_cpuset, c); - } - } - CPUSET_OR(idn.dc_cpuset, cpu_ready_set); - - bcopy(loc_hw, &ldp->dhw, sizeof (ldp->dhw)); - ldp->dcpuset = cpu_ready_set; - ldp->dcpu = cpu0.cpu_id; - ldp->dncpus = (int)ncpus; - ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1; - ldp->dvote.v.ncpus = (int)ldp->dncpus - 1; - ldp->dvote.v.board = CPUID_TO_BOARDID(CPU->cpu_id); - - return (1); - } else { - PR_PROTO("%s: NO change detected\n", proc); - return (0); - } -} - -int -get_hw_config(struct hwconfig *loc_hw) -{ - pda_handle_t ph; - boardset_t domainset; - int bd; - int nmcadr; - int nboards; - procname_t proc = "get_hw_config"; - - ASSERT(loc_hw != NULL); - - bzero(loc_hw, sizeof (*loc_hw)); - /* - * See if sm_mask is writable. - * XXX - Should be the same for all CIC's. Do we - * we need to verify? - */ - if (cic_get_smmask_bit() == 0) { - /* - * If smmask is not writable, we can not allow - * IDN operations. - */ - cmn_err(CE_WARN, - "IDN: 506: cic sm_mask is not writeable"); - return (-1); - } - /* - * Map in the post2obp structure so we can find - * valid boards and hardware asics. - */ - ph = pda_open(); - if (ph == (pda_handle_t)NULL) { - cmn_err(CE_WARN, - "IDN: 507: failed to map-in post2obp structure"); - return (-1); - } else if (!pda_is_valid(ph)) { - cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); - pda_close(ph); - return (-1); - } - /* - * Need to read the MC address decoding registers - * so that they can be given to other domains. - */ - loc_hw->dh_boardset = get_boardset(ph, &nboards); - loc_hw->dh_nboards = (short)nboards; - ASSERT(loc_hw->dh_boardset & (1 << CPUID_TO_BOARDID(CPU->cpu_id))); - - mc_get_adr_all(ph, loc_hw->dh_mcadr, &nmcadr); - loc_hw->dh_nmcadr = (short)nmcadr; - - affinity_set(CPU_CURRENT); - /* - * There will always be a bus 0 (logical). - */ - bd = CPUID_TO_BOARDID(CPU->cpu_id); - domainset = (boardset_t)cic_read_domain_mask(bd, 0); - affinity_clear(); - - if (!idn_cpu_per_board(ph, cpu_ready_set, loc_hw)) { - pda_close(ph); - return (-1); - } - - pda_close(ph); - - -#ifdef DEBUG - { - int brd; - - for (brd = 0; brd < MAX_BOARDS; brd++) - if (loc_hw->dh_mcadr[brd] != 0) { - PR_XF("%s: brd %d, mc = 0x%x\n", - proc, brd, loc_hw->dh_mcadr[brd]); - } - } -#endif /* DEBUG */ - - if ((loc_hw->dh_boardset != domainset) || (loc_hw->dh_nmcadr < 1)) - return (-1); - else - return (0); -} - -/* - * Function called via timeout() to wakeup a possibly stuck - * idnxf_shmem_update_all() should not all cpus check-in after a - * x-call to update their respective CICs. - */ -/*ARGSUSED0*/ -static void -idnxf_shmem_wakeup(void *arg) -{ - struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg; - int count; - int expired; - procname_t proc = "idnxf_shmem_wakeup"; - - expired = ((ddi_get_lbolt() - idnxfp->xf_start_time) >= - IDNCIC_TIMEOUT) ? 1 : 0; - - if ((count = idnxfp->xf_count) == 0) { - /* - * Everybody has finished. Wakeup the requester. - */ - mutex_enter(&idnxfp->xf_mutex); - cv_signal(&idnxfp->xf_cv); - mutex_exit(&idnxfp->xf_mutex); - - } else if ((count > 0) && expired) { - /* - * There are still active cic updaters and time - * has expired. Bail on them. - */ - idnxfp->xf_errtimer = 1; -#ifdef DEBUG - /* - * Special debug case since idn_debug - * may have been temporarily cleared - * during xc_some. - */ - if ((idn_debug | o_idn_debug) & IDNDBG_REGS) - printf("%s: TIMEOUT...bailing on %d lost CIC " - "updates...\n", proc, count); -#endif /* DEBUG */ - - ATOMIC_SUB(idnxfp->xf_count, count); - - mutex_enter(&idnxfp->xf_mutex); - cv_signal(&idnxfp->xf_cv); - mutex_exit(&idnxfp->xf_mutex); - - } else { - (void) timeout(idnxf_shmem_wakeup, (caddr_t)idnxfp, - (clock_t)IDNCIC_TIMECHK); - } -} - -/* - * Called indirectly from idnxf_shmem_update_all() via a xcall - * for the recepient cpu to update the CICs on its respective - * board. - * IMPORTANT: NO console output from this routine!! - */ -static void -idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2) -{ - struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg1; - time_t start_time = (time_t)arg2; - int rv, cpuid, brd, bus; - boardset_t smmask; - - - cpuid = CPU->cpu_id; - brd = CPUID_TO_BOARDID(cpuid); - - if (idnxfp->xf_start_time != start_time) { - /* - * Ooops! Not my place to intrude. - */ - idnxf_cic_info.xf_errcic[brd][0] = IDNCIC_BUSY; - ATOMIC_INC(idnxf_cic_info.xf_errcnt); - - goto done; - } - - /* - * We're executing out of the context of a cross-call - * so we're effectively bound! :) - */ - for (bus = 0; bus < MAX_ABUSES; bus++) { - /* - * XXX - need to worry about shuffle?? - */ - if (!(idnxfp->xf_abus_mask & (1 << bus))) - continue; - smmask = cic_read_sm_mask(brd, bus); - - if (idnxfp->xf_doadd) { - smmask |= idnxfp->xf_boardset; - (void) cic_write_sm_mask(brd, bus, smmask); - - if (idnxfp->xf_smbase != (uint_t)-1) { - (void) cic_write_sm_bar(brd, bus, - idnxfp->xf_smbase); - (void) cic_write_sm_lar(brd, bus, - idnxfp->xf_smlimit); - } - /* - * Verify data got there! - */ - rv = verify_smregs(brd, bus, smmask, idnxfp->xf_smbase, - idnxfp->xf_smlimit); - } else { - smmask &= ~idnxfp->xf_boardset; - (void) cic_write_sm_mask(brd, bus, smmask); - - if (!smmask) { - /* - * Update the LAR first so that we effectively - * disable the register without possibly - * opening the window to transaction we - * don't care about. Updating the LAR first - * will guarantee we effectively turn it - * off immediately. - */ - (void) cic_write_sm_lar(brd, bus, 0); - (void) cic_write_sm_bar(brd, bus, 1); - - rv = verify_smregs(brd, bus, smmask, 1, 0); - } else { - rv = verify_smregs(brd, bus, smmask, - (uint_t)-1, (uint_t)-1); - } - } - if (rv) { - idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_ERR; - ATOMIC_INC(idnxf_cic_info.xf_errcnt); - } else { - idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_OK; - } - } - -done: - ATOMIC_DEC(idnxf_cic_info.xf_count); -} - -static int -idnxf_shmem_update_all(pda_handle_t ph, boardset_t boardset, - uint_t smbase, uint_t smlimit, int doadd) -{ - cpuset_t target_cpuset; - int target_count; - int rv = 0; - int c, brd, bus; - short abus_mask; - time_t start_time; - procname_t proc = "idnxf_shmem_update_all"; - - - ASSERT(MUTEX_HELD(&idn_xf_mutex)); - - pda_get_busmask(ph, &abus_mask, NULL); - - CPUSET_ZERO(target_cpuset); - target_count = 0; - /* - * Build a cpuset of target cpus (one per board) to - * be used to send the CIC update xcall. - */ - for (brd = 0; brd < MAX_BOARDS; brd++) { - /* - * Need to target an available cpu on the target board - * so that we can look at the CICs on that board. - */ - c = board_to_ready_cpu(brd, cpu_ready_set); - - if (c == -1) { - /* - * If there's no cpu on this board, no - * need to update the CICs. - */ - continue; - } - CPUSET_ADD(target_cpuset, c); - target_count++; - } - - if (CPUSET_ISNULL(target_cpuset)) { - PR_REGS("%s: NO target cpus to update!!\n", proc); - return (0); - } - - RESET_CIC_HISTORY(); - - /* - * Broadcast out the CIC update request and then - * sit back and wait for dinner to arrive! - * Let's set up the global structure all the xcall - * recepients will read. - */ - start_time = ddi_get_lbolt(); - /* - * Set the start time. Make sure it's different - * then the previous run. - */ - if (start_time <= idnxf_cic_info.xf_start_time) - start_time++; - idnxf_cic_info.xf_start_time = start_time; - - idnxf_cic_info.xf_abus_mask = abus_mask; - idnxf_cic_info.xf_boardset = boardset; - idnxf_cic_info.xf_smbase = smbase; - idnxf_cic_info.xf_smlimit = smlimit; - idnxf_cic_info.xf_doadd = doadd; - idnxf_cic_info.xf_count = target_count; - idnxf_cic_info.xf_errcnt = 0; - idnxf_cic_info.xf_errtimer = 0; - bzero(&idnxf_cic_info.xf_errcic, sizeof (idnxf_cic_info.xf_errcic)); - - /* - * Broadcast out the xcall to do the task. - */ -#ifdef DEBUG - { - uint_t tu32, tl32; - - tu32 = UPPER32_CPUMASK(target_cpuset); - tl32 = LOWER32_CPUMASK(target_cpuset); - PR_REGS("%s: (start %ld) broadcasting CIC - " - "%s to cpus 0x%x.%0x\n", - proc, start_time, doadd ? "LINK" : "UNLINK", - tu32, tl32); - } - - /* - * Can't dump debug during cross-calls. - */ - o_idn_debug = idn_debug; - idn_debug = 0; -#endif /* DEBUG */ - - xc_attention(target_cpuset); - - xc_some(target_cpuset, idnxf_shmem_update_one, - (uint64_t)&idnxf_cic_info, (uint64_t)start_time); - - xc_dismissed(target_cpuset); - - ASSERT(idnxf_cic_info.xf_count == 0); - -#ifdef DEBUG - idn_debug = o_idn_debug; - o_idn_debug = 0; -#endif /* DEBUG */ - - PR_REGS("%s: waiting for completion of %d CIC - %s...\n", - proc, idnxf_cic_info.xf_count, doadd ? "LINKS" : "UNLINKS"); - PR_REGS("%s: CIC - %s have checked IN.\n", - proc, doadd ? "LINKS" : "UNLINKS"); - - /* - * Modifying xf_start_time effectively disables any - * possible outstanding xcall's since they don't touch - * idnxf_cic_info unless their given start_time matches - * that in the idnxf_cic_info structure. - */ - idnxf_cic_info.xf_start_time++; - - PR_REGS("%s: xf_errcnt = %d, xf_errtimer = %d\n", - proc, idnxf_cic_info.xf_errcnt, idnxf_cic_info.xf_errtimer); - DUMP_CIC_HISTORY(); - /* - * Should errors be fatal? (panic). - */ - rv = 0; - for (c = 0; c < NCPU; c++) { - if (!CPU_IN_SET(target_cpuset, c)) - continue; - brd = CPUID_TO_BOARDID(c); - - for (bus = 0; bus < MAX_ABUSES; bus++) { - - if (!(abus_mask & (1 << bus))) - continue; - - switch (idnxf_cic_info.xf_errcic[brd][bus]) { - case IDNCIC_UNKNOWN: - /* - * Unknown is only an error if the - * timer expired. - */ - if (!idnxf_cic_info.xf_errtimer) - break; - cmn_err(CE_WARN, - "IDN: 509: CPU %d never responded " - "to CIC update", c); - /*FALLTHROUGH*/ - - case IDNCIC_ERR: - cmn_err(CE_WARN, - "IDN: 510: failed write-smregs " - "(bd=%d, bs=%d, sm(bar=0x%x, " - "lar=0x%x))", - brd, bus, smbase, smlimit); - rv++; - break; - - case IDNCIC_BUSY: - cmn_err(CE_WARN, "IDN: 511: update-one " - "(cpu=%d, bd=%d) time conflict", - c, brd); - /* - * Should never occur. Not fatal, - * just continue. - */ - break; - - default: - PR_REGS("%s: board %d, bus %d " - "(bar=0x%x,lar=0x%x) - update OK\n", - proc, brd, bus, smbase, smlimit); - break; - } - } - } - - return (rv ? -1 : 0); -} - -/* - * Add the respective boardset/base/limit/mcadr's to the local - * domain's hardware configuration with respect to the SMR. - * - * is_master Indicates remote domain is a master. - */ -int -idnxf_shmem_add(int is_master, boardset_t boardset, pfn_t pfnbase, - pfn_t pfnlimit, uint_t *mcadr) -{ - int rv = 0; - register int brd, rbrd; - register boardset_t localboardset; - uint_t madr; - uint_t smbase, smlimit; - pda_handle_t ph; - procname_t proc = "idnxf_shmem_add"; - - - localboardset = idn_domain[idn.localid].dhw.dh_boardset; - - ASSERT(localboardset && boardset && ((localboardset & boardset) == 0)); - ASSERT(is_master ? (pfnbase && pfnlimit && mcadr) : 1); - - if (pfnbase != PFN_INVALID) { - smbase = (uint_t)PFN_TO_SMADDR(pfnbase); - smlimit = (uint_t)PFN_TO_SMADDR(pfnlimit); - } else { - smbase = smlimit = (uint_t)-1; - } - PR_REGS("%s: is_master=%d, boardset=0x%x, smbase=0x%x, smlimit=%x\n", - proc, is_master, boardset, smbase, smlimit); - - /* - * Need to serialize hardware access so we don't have multiple - * threads attempting to access hardware regs simulataneously. - * This should not be a significant performance penalty since - * the hardware is only touched when domains are linking or - * unlinking. - */ - mutex_enter(&idn_xf_mutex); - - /* - * Map in the post2obp structure so we can find - * bus config information. - */ - ph = pda_open(); - if (ph == (pda_handle_t)NULL) { - cmn_err(CE_WARN, - "IDN: 507: failed to map-in post2obp structure"); - rv = -1; - goto done; - - } else if (!pda_is_valid(ph)) { - cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); - rv = -1; - goto done; - } - /* - * Take a checkpoint in bbsram for diagnostic purposes. - */ - CHECKPOINT_OPENED(IDNSB_CHKPT_SMR, boardset, 1); - - rv = idnxf_shmem_update_all(ph, boardset, smbase, smlimit, 1); - - if (rv || (is_master == 0)) - goto done; - - /* - * If this is a slave (i.e. remote domain is_master), - * then we need to deprogram our PCs. - */ - PR_REGS("%s: updating PC regs (lboardset=0x%x, rboardset=0x%x)\n", - proc, localboardset, boardset); - - for (brd = 0; brd < MAX_BOARDS; brd++) { - - if (!BOARD_IN_SET(localboardset, brd)) - continue; - /* - * If this is a slave (i.e. remote domain is_master), - * then we need to program our PCs. - */ - for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) { - - if ((madr = mcadr[rbrd]) == 0) - continue; - - ASSERT(BOARD_IN_SET(boardset, rbrd)); - /* - * Write the MC adr for the respective - * remote board (rbrd) into the PCs of - * the given local board (brd). - */ - if (pc_write_madr(ph, brd, rbrd, madr) < 0) { - cmn_err(CE_WARN, - "IDN: 512: failed [add] write-madr " - "(bd=%d, rbd=%d, madr=0x%x)", - brd, rbrd, madr); - rv = -1; - goto done; - } - } - } - -done: - if (ph) - pda_close(ph); - - mutex_exit(&idn_xf_mutex); - /* - * XXX - * - * Failure here is fatal. Disable IDN? - * NOn-zero return value will at least prevent - * linkage with domain - probably sufficient. - */ - return (rv); -} - -/* - * Remove the respective boardset from the local domain's - * hardware configuration with respect to the SMR. - * - * is_master Indicates remote domain is a master. - */ -int -idnxf_shmem_sub(int is_master, boardset_t boardset) -{ - int rv = 0; - register int brd, rbrd; - register boardset_t localboardset; - pda_handle_t ph; - procname_t proc = "idnxf_shmem_sub"; - - localboardset = idn_domain[idn.localid].dhw.dh_boardset; - - ASSERT(localboardset && boardset && ((localboardset & boardset) == 0)); - - PR_REGS("%s: is_master=%d, boardset=0x%x\n", - proc, is_master, boardset); - - /* - * Need to serialize hardware access so we don't have multiple - * threads attempting to access hardware regs simulataneously. - * This should not be a significant performance penalty since - * the hardware is only touched when domains are linking or - * unlinking. - */ - mutex_enter(&idn_xf_mutex); - - /* - * Map in the post2obp structure so we can find - * bus config information. - */ - ph = pda_open(); - if (ph == (pda_handle_t)NULL) { - cmn_err(CE_WARN, - "IDN: 507: failed to map-in post2obp structure"); - rv = -1; - goto done; - - } else if (!pda_is_valid(ph)) { - cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); - rv = -1; - goto done; - } - /* - * Take a checkpoint in bbsram for diagnostic purposes. - */ - CHECKPOINT_CLOSED(IDNSB_CHKPT_SMR, boardset, 2); - - rv = idnxf_shmem_update_all(ph, boardset, (uint_t)-1, (uint_t)-1, 0); - - if (rv || (is_master == 0)) - goto done; - - /* - * If this is a slave (i.e. remote domain is_master), - * then we need to deprogram our PCs. - */ - PR_REGS("%s: reseting PC regs (lboardset=0x%x, rboardset=0x%x)\n", - proc, localboardset, boardset); - - for (brd = 0; brd < MAX_BOARDS; brd++) { - - if (!BOARD_IN_SET(localboardset, brd)) - continue; - - for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) { - - if (!BOARD_IN_SET(boardset, rbrd)) - continue; - /* - * Clear the MC adr for the respective - * remote board (rbrd) into the PCs of - * the given local board (brd). - */ - if (pc_write_madr(ph, brd, rbrd, 0) < 0) { - cmn_err(CE_WARN, - "IDN: 512: failed [del] write-madr " - "(bd=%d, rbd=%d, madr=0x%x)", - brd, rbrd, 0); - rv = -1; - goto done; - } - } - } - -done: - if (ph) - pda_close(ph); - mutex_exit(&idn_xf_mutex); - - return (rv); -} - -/* - * We cannot cross-trap cpu_flush_ecache since it references - * %g7 via CPU. It's possible that %g7 may not be set up - * when the trap comes in, and could thus cause a crash. - * Well...at least that's what has been happening when I - * tried x-calls within an xc_attention (KMISS) panic. - * Instead we use cross-calls. However, since we can't - * xc_attention around a cross-call, we have not guaranteed - * way of knowing the operation succeeded. To synchronize - * this flush operation across cpus, we use a semaphore - * which is V'd by the receiving cpus and P'd by the caller - * initiating the all-cpus flush. - */ -/*ARGSUSED0*/ -void -idn_flush_ecache(uint64_t arg1, uint64_t arg2) -{ - extern void cpu_flush_ecache(void); - - cpu_flush_ecache(); - /* - * Paranoia...Give things a chance to drain. - */ - drv_usecwait(500000); /* 500 msec */ -} -/* - * Flush the ecache's of all the cpus within this domain of - * any possible SMR references. - * This logic is borrowed from ecc.c:cpu_flush_ecache(). - */ -void -idnxf_flushall_ecache() -{ - cpuset_t local_cpuset; - procname_t proc = "idnxf_flushall_ecache"; - - - PR_XF("%s: flushing ecache (cpu_ready_set = 0x%x.%x)\n", proc, - UPPER32_CPUMASK(cpu_ready_set), LOWER32_CPUMASK(cpu_ready_set)); - - CHECKPOINT_CACHE_CLEAR_DEBUG(1); - CHECKPOINT_CACHE_STEP_DEBUG(0x1, 2); - - local_cpuset = cpu_ready_set; - - xc_attention(local_cpuset); - - /* - * We tell each cpu to do a flush and then we hit - * a semaphore to synchronize with all of them - * to guarantee they have completed the flush before - * we continue on. We have to do this type of - * sychronization since we can't xc_attention around - * a cross-call. - */ - CHECKPOINT_CACHE_STEP_DEBUG(0x2, 3); - - xc_all(idn_flush_ecache, 0, 0); - - CHECKPOINT_CACHE_STEP_DEBUG(0x4, 4); - - xc_dismissed(local_cpuset); - - CHECKPOINT_CACHE_STEP_DEBUG(0x8, 5); -} - -/* - * -------------------------------------------------- - */ -static int -verify_smregs(int brd, int bus, boardset_t smmask, uint_t smbase, uint_t - smlimit) -{ - int rv = 0; - uint_t smreg; - - if (smmask != (boardset_t)-1) { - smreg = (uint_t)cic_read_sm_mask(brd, bus); - if (smreg != (uint_t)smmask) { - cmn_err(CE_WARN, - "IDN: 513: sm-mask error " - "(expected = 0x%x, actual = 0x%x)", - (uint_t)smmask, smreg); - rv++; - } - } - - if (smbase != (uint_t)-1) { - smreg = cic_read_sm_bar(brd, bus); - if (smreg != smbase) { - cmn_err(CE_WARN, - "IDN: 514: sm-base error " - "(expected = 0x%x, actual = 0x%x)", - smbase, smreg); - rv++; - } - } - - if (smlimit != (uint_t)-1) { - smreg = cic_read_sm_lar(brd, bus); - if (smreg != smlimit) { - cmn_err(CE_WARN, - "IDN: 515: sm-limit error " - "(expected = 0x%x, actual = 0x%x)", - smlimit, smreg); - rv++; - } - } - - return (rv ? -1 : 0); -} - -/* - * ------------------------------------------------------------- - */ -int -idn_cpu_per_board(pda_handle_t ph, cpuset_t cset, struct hwconfig *hwp) -{ - int b, err = 0; - boardset_t bset, cpu_bset; - board_desc_t *lbp; - - if (!idn_check_cpu_per_board) - return (1); - - bset = hwp->dh_boardset; - CPUSET_TO_BOARDSET(cset, cpu_bset); - - /* - * Every board has at least one cpu, we're happy. - */ - if (cpu_bset == bset) - return (1); - - /* - * Well, not all boards had cpus. That's okay so - * long as they don't have memory also. - * Get rid of the boards that have a cpu. - */ - bset &= ~cpu_bset; - /* - * None of the remaining boards in the set shold have mem. - */ - err = 0; - - /* - * A NULL post2obp pointer indicates we're checking - * the config of a remote domain. Since we can't - * look at the post2obp of the remote domain, we'll - * have to trust what it passed us in its config. - */ - if (ph && !pda_is_valid(ph)) { - cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); - return (0); - } - - for (b = 0; b < MAX_BOARDS; b++) { - if (!BOARD_IN_SET(bset, b)) - continue; - - lbp = ph ? pda_get_board_info(ph, b) : NULL; - - if ((lbp && - (BDA_NBL(lbp->bda_board, BDA_MC_NBL) == BDAN_GOOD)) || - (!lbp && hwp->dh_mcadr[b])) { - err++; - cmn_err(CE_WARN, - "IDN: 516: (%s) board %d has memory, " - "but no CPUs - CPU per memory board REQUIRED", - ph ? "local" : "remote", b); - } - } - - return (err ? 0 : 1); -} diff --git a/usr/src/uts/sun4u/starfire/io/memctrl.c b/usr/src/uts/sun4u/starfire/io/memctrl.c deleted file mode 100644 index 953542f3cb..0000000000 --- a/usr/src/uts/sun4u/starfire/io/memctrl.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Starfire Memory Controller specific routines. - */ - -#include <sys/debug.h> -#include <sys/types.h> -#include <sys/errno.h> -#include <sys/dditypes.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/sunndi.h> -#include <sys/ddi_impldefs.h> -#include <sys/promif.h> -#include <sys/machsystm.h> - -#include <sys/starfire.h> - -struct mc_dimm_table { - int mc_type; - int mc_module_size; /* module size in MB */ -}; - -static struct mc_dimm_table dimmsize_table[] = { - { 4, 8 }, - { 6, 8 }, - { 11, 32 }, - { 15, 128 }, - { 0, 0 } -}; - -#define MC_MB(mb) ((mb) * 1048576ull) - -struct mc_seg_size { - uint_t seg_mask; - uint64_t seg_size; -}; - -struct mc_seg_size mc_seg_table[] = { - { 0x7f, MC_MB(64) }, - { 0x7e, MC_MB(128) }, - { 0x7c, MC_MB(256) }, - { 0x78, MC_MB(512) }, - { 0x70, MC_MB(1024) }, - { 0x60, MC_MB(2048) }, - { 0x40, MC_MB(4096) }, - { 0, 0 } -}; - -/* - * Alignment of memory between MC's. - */ -uint64_t -mc_get_mem_alignment() -{ - return (STARFIRE_MC_MEMBOARD_ALIGNMENT); -} - -uint64_t -mc_get_asr_addr(pnode_t nodeid) -{ - int rlen; - uint64_t psi_addr; - struct sf_memunit_regspec reg; - - rlen = prom_getproplen(nodeid, "reg"); - if (rlen != sizeof (struct sf_memunit_regspec)) - return ((uint64_t)-1); - - if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) - return ((uint64_t)-1); - - psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; - psi_addr |= (uint64_t)reg.regspec_addr_lo; - - return (STARFIRE_MC_ASR_ADDR(psi_addr)); -} - -uint64_t -mc_get_idle_addr(pnode_t nodeid) -{ - int rlen; - uint64_t psi_addr; - struct sf_memunit_regspec reg; - - rlen = prom_getproplen(nodeid, "reg"); - if (rlen != sizeof (struct sf_memunit_regspec)) - return ((uint64_t)-1); - - if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) - return ((uint64_t)-1); - - psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; - psi_addr |= (uint64_t)reg.regspec_addr_lo; - - return (STARFIRE_MC_IDLE_ADDR(psi_addr)); -} - -int -mc_get_dimm_size(pnode_t nodeid) -{ - uint64_t psi_addr; - uint_t dimmtype; - int i, rlen; - struct sf_memunit_regspec reg; - - rlen = prom_getproplen(nodeid, "reg"); - if (rlen != sizeof (struct sf_memunit_regspec)) - return (-1); - - if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) - return (-1); - - psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; - psi_addr |= (uint64_t)reg.regspec_addr_lo; - psi_addr = STARFIRE_MC_DIMMTYPE_ADDR(psi_addr); - - if (psi_addr == (uint64_t)-1) - return (-1); - - dimmtype = ldphysio(psi_addr); - dimmtype &= STARFIRE_MC_DIMMSIZE_MASK; - - for (i = 0; dimmsize_table[i].mc_type != 0; i++) - if (dimmsize_table[i].mc_type == dimmtype) - break; - - return (dimmsize_table[i].mc_module_size); -} - -uint64_t -mc_get_alignment_mask(pnode_t nodeid) -{ - uint64_t psi_addr, seg_sz; - uint_t mcreg, seg_sz_mask; - int i, rlen; - struct sf_memunit_regspec reg; - - rlen = prom_getproplen(nodeid, "reg"); - if (rlen != sizeof (struct sf_memunit_regspec)) - return (-1); - - if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) - return (-1); - - psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; - psi_addr |= (uint64_t)reg.regspec_addr_lo; - psi_addr = STARFIRE_MC_ASR_ADDR(psi_addr); - - if (psi_addr == (uint64_t)-1) - return (-1); - - mcreg = ldphysio(psi_addr); - seg_sz_mask = (mcreg & STARFIRE_MC_MASK_MASK) >> 8; - - for (i = 0; mc_seg_table[i].seg_size != 0; i++) - if (mc_seg_table[i].seg_mask == seg_sz_mask) - break; - - if (mc_seg_table[i].seg_size == 0) - seg_sz = mc_get_mem_alignment(); - else - seg_sz = mc_seg_table[i].seg_size; - -#ifdef DEBUG - printf("nodeid %x, mc asr addr %lx, val %x, seg_sz_mask %x, " - "seg_sz %lx\n", nodeid, psi_addr, mcreg, seg_sz_mask, seg_sz); -#endif /* DEBUG */ - - return (seg_sz - 1); -} - -int -mc_read_asr(pnode_t nodeid, uint_t *mcregp) -{ - uint64_t psi_addr; - - *mcregp = 0; - - psi_addr = mc_get_asr_addr(nodeid); - if (psi_addr == (uint64_t)-1) - return (-1); - - *mcregp = ldphysio(psi_addr); - - return (0); -} - -int -mc_write_asr(pnode_t nodeid, uint_t mcreg) -{ - uint_t mcreg_rd; - uint64_t psi_addr; - - psi_addr = mc_get_asr_addr(nodeid); - if (psi_addr == (uint64_t)-1) - return (-1); - - stphysio(psi_addr, mcreg); - - mcreg_rd = ldphysio(psi_addr); - ASSERT(mcreg_rd == mcreg); - - return ((mcreg_rd != mcreg) ? -1 : 0); -} - -uint64_t -mc_asr_to_pa(uint_t mcreg) -{ - uint64_t pa, masr, addrmask, lowbitmask; - - /* - * Remove memory present bit. - */ - masr = (uint64_t)(mcreg & ~STARFIRE_MC_MEM_PRESENT_MASK); - /* - * Get mask for bits 32-26. - */ - lowbitmask = masr & (uint64_t)STARFIRE_MC_MASK_MASK; - lowbitmask <<= STARFIRE_MC_MASK_SHIFT; - addrmask = STARFIRE_MC_ADDR_HIBITS | lowbitmask; - - pa = (masr << STARFIRE_MC_BASE_SHIFT) & addrmask; - - return (pa); -} - -uint_t -mc_pa_to_asr(uint_t masr, uint64_t pa) -{ - uint64_t addrmask, lowbitmask; - uint_t base; - - /* - * Get mask for bits 32-26. - */ - lowbitmask = masr & (uint64_t)STARFIRE_MC_MASK_MASK; - lowbitmask <<= STARFIRE_MC_MASK_SHIFT; - addrmask = STARFIRE_MC_ADDR_HIBITS | lowbitmask; - - base = (pa & addrmask) >> STARFIRE_MC_BASE_SHIFT; - masr &= ~ STARFIRE_MC_MEM_BASEADDR_MASK; - masr |= base & STARFIRE_MC_MEM_BASEADDR_MASK; - - ASSERT(mc_asr_to_pa(masr) == pa); - - return (masr); -} diff --git a/usr/src/uts/sun4u/starfire/io/ngdr.conf b/usr/src/uts/sun4u/starfire/io/ngdr.conf deleted file mode 100644 index 85b7a4e81f..0000000000 --- a/usr/src/uts/sun4u/starfire/io/ngdr.conf +++ /dev/null @@ -1,28 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" - -name="ngdr" parent="pseudo" instance=0; diff --git a/usr/src/uts/sun4u/starfire/io/portctrl.c b/usr/src/uts/sun4u/starfire/io/portctrl.c deleted file mode 100644 index adfe173833..0000000000 --- a/usr/src/uts/sun4u/starfire/io/portctrl.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 1990-2002 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/cmn_err.h> -#include <sys/kmem.h> -#include <sys/debug.h> -#include <sys/machsystm.h> -#include <sys/starfire.h> - -/* - * Interrupt target translation data for - * Starfire's Port controller asics - */ -struct pc_ittrans_data { - kmutex_t ittrans_lock; /* lock for ITTR array */ - volatile uint64_t *ittrans_mondovec[32]; /* mondovecreg addr array */ - uint64_t ittransreg_physaddr[32]; /* ITTREG physaddr array */ -}; - -/* - * Setup and initialize the soft table that - * represent the Starfire interrupt target translation - * registers in the Port controller asics. There is one - * for each sysio/pci instance. - */ -void -pc_ittrans_init(int upa_id, caddr_t *ittptr_cookie) -{ - int i; - uint64_t physaddr; - struct pc_ittrans_data *tmpptr; - - ASSERT(ittptr_cookie != NULL); - - /* - * Allocate the data structure to support starfire's - * interrupt target translations - */ - tmpptr = (struct pc_ittrans_data *) - kmem_zalloc(sizeof (struct pc_ittrans_data), - KM_SLEEP); - - /* Initialize the ittrans lock */ - mutex_init(&tmpptr->ittrans_lock, NULL, MUTEX_DEFAULT, NULL); - - /* - * Construct the base physical address of the - * ITTR registers associated with this PC asics - */ - physaddr = STARFIRE_UPAID2UPS(upa_id); - physaddr |= (STARFIRE_PSI_BASE | STARFIRE_PSI_PCREG_OFF | - STARFIRE_PC_INT_MAP); - - /* - * Initialize the ITTR table - * This soft table is used to represent the interrupt - * target translation hardware registers in the Starfire's - * PC asics. There are 32 slots and each slot consists of - * a mondovec regaddr entry and the physical address of - * the that ITT register. A empty slot is one whose - * mondovec entry is null. To reserve/use a slot for a - * particular intr mapping reg, we simply find - * a empty slot and write in the mondovec mapping - * regaddr into the mondovec field. - */ - for (i = 0; i < 32; i++) { - tmpptr->ittrans_mondovec[i] = NULL; - tmpptr->ittransreg_physaddr[i] = physaddr + i*16; - } - - *ittptr_cookie = (caddr_t)tmpptr; -} - -void -pc_ittrans_uninit(caddr_t ittr_cookie) -{ - struct pc_ittrans_data *tmpptr; - - ASSERT(ittr_cookie != NULL); - - tmpptr = (struct pc_ittrans_data *)ittr_cookie; - - mutex_destroy(&tmpptr->ittrans_lock); - kmem_free((int *)ittr_cookie, sizeof (struct pc_ittrans_data)); -} - -/* - * This routine searches for a slot in the soft ITTR table - * that was reserved earlier by matching the mondovec - * mapping regaddr argument with the corresponding field in - * the table. Note that the soft ITTR table mirrors the - * corresponding hw table in the starfire port controller(PC) - * asics. A new slot will be obtained if the slot cannot - * be found. (not reserved previously). The routine then programs - * in the target cpu id into the PC ITTR hardware, updates the - * soft table and return the index to this slot as the target - * id cookie. - */ -int -pc_translate_tgtid(caddr_t ittr_cookie, int cpu_id, - volatile uint64_t *mondovec_addr) -{ - struct pc_ittrans_data *ittptr; - int i; - int foundslot = -1; - - ASSERT(ittr_cookie != NULL); - - ittptr = (struct pc_ittrans_data *)ittr_cookie; - - mutex_enter(&ittptr->ittrans_lock); - - /* - * Search the mondovec addrlist to see if we - * already reserved/used a slot for this particular - * mondovec mapping regaddr. - */ - for (i = 0; i < 32; i++) { - if (mondovec_addr == ittptr->ittrans_mondovec[i]) { - /* - * found the slot that matches the - * mondo vec in question - */ - foundslot = i; - break; - } - if (foundslot == -1 && ittptr->ittrans_mondovec[i] == NULL) - /* keep track of a empty slot */ - foundslot = i; - } - - if (foundslot != -1) { - /* We found a slot for this mondo vec, let's use it */ - stphysio(ittptr->ittransreg_physaddr[foundslot], - STARFIRE_UPAID2HWMID(cpu_id)); - ittptr->ittrans_mondovec[foundslot] = mondovec_addr; - } else { - cmn_err(CE_PANIC, "No more ITTR slots!!"); - } - - mutex_exit(&ittptr->ittrans_lock); - return (foundslot); -} - -/* - * This routine searches the interrupt target translation table - * (if exists) for a slot that was reserved/used earlier by - * matching the mondovec_addr input argument with the mondovec - * field in the table. The routine then free the found slot by - * resetting it to zero. - */ -void -pc_ittrans_cleanup(caddr_t ittr_cookie, - volatile uint64_t *mondovec_addr) -{ - - struct pc_ittrans_data *ittptr; - int i; - int foundslot = -1; - - ASSERT(ittr_cookie != NULL); - - ittptr = (struct pc_ittrans_data *)ittr_cookie; - - mutex_enter(&ittptr->ittrans_lock); - - /* - * Search the mondovec addrlist for the reserved/used - * slot associated with this particular mondo vector. - */ - for (i = 0; i < 32; i++) { - if (mondovec_addr == ittptr->ittrans_mondovec[i]) { - /* - * found the slot that matches the - * mondo vec in question - */ - foundslot = i; - break; - } - } - - if (foundslot != -1) { - /* We found a slot for this mondo vec, clear it */ - ittptr->ittrans_mondovec[foundslot] = 0; - } - - mutex_exit(&ittptr->ittrans_lock); -} - -int -pc_madr_add(int lboard, int rboard, int proc, uint_t madr) -{ - register int i; - uint_t madr_rd, madr_off; - uint64_t pc_madr_addr; - - pc_madr_addr = STARFIRE_PC_MADR_ADDR(lboard, rboard, proc); - - /* - * First write with Presence bit disabled - * and then with it enabled. - */ - madr_off = madr & ~STARFIRE_MC_MEM_PRESENT_MASK; - stphysio(pc_madr_addr, madr_off); - - for (i = 0; i < 20; i++) { - madr_rd = ldphysio(pc_madr_addr); - if (madr_off == madr_rd) - break; - } - if (madr_off != madr_rd) { - cmn_err(CE_WARN, - "pc_madr_add: (1) failed to update " - "PC MADR (%d, %d, %d, 0x%x)\n", - lboard, rboard, proc, madr); - return (-1); - } - if (madr == madr_off) { - /* - * Caller wanted to write value out there - * with presence bit turned off, which is - * what we just completed. So, we're finished. - */ - return (0); - } - /* - * Now write with Presence bit enabled. - */ - stphysio(pc_madr_addr, madr); - - for (i = 0; i < 20; i++) { - madr_rd = ldphysio(pc_madr_addr); - if (madr == madr_rd) - break; - } - if (madr != madr_rd) { - cmn_err(CE_WARN, - "pc_madr_add: (2) failed to update " - "PC MADR (%d, %d, %d, 0x%x)\n", - lboard, rboard, proc, madr); - return (-1); - } - - return (0); -} diff --git a/usr/src/uts/sun4u/starfire/ml/drmach.il.cpp b/usr/src/uts/sun4u/starfire/ml/drmach.il.cpp deleted file mode 100644 index f948876aa4..0000000000 --- a/usr/src/uts/sun4u/starfire/ml/drmach.il.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2001,2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file is through cpp before being used as - * an inline. It contains support routines used - * only by DR for the copy-rename sequence. - */ - -#if defined(lint) -#include <sys/types.h> -#endif /* lint */ - -#ifndef INLINE - -#include <sys/asm_linkage.h> - -#else /* INLINE */ - -#define ENTRY_NP(x) .inline x,0 -#define retl /* nop */ -#define SET_SIZE(x) .end - -#endif /* INLINE */ - -#include <sys/privregs.h> -#include <sys/sun4asi.h> -#include <sys/machparam.h> - -/* - * Bcopy routine used by DR to copy - * between physical addresses. - * Borrowed from Starfire DR 2.6. - */ -#if defined(lint) - -/*ARGSUSED*/ -void -bcopy32_il(uint64_t paddr1, uint64_t paddr2) -{} - -#else /* lint */ - - ENTRY_NP(bcopy32_il) - .register %g2, #scratch - .register %g3, #scratch - rdpr %pstate, %o4 - andn %o4, PSTATE_IE | PSTATE_AM, %g3 ! clear IE, AM bits - wrpr %g0, %g3, %pstate - - ldxa [%o0]ASI_MEM, %o2 - add %o0, 8, %o0 - ldxa [%o0]ASI_MEM, %o3 - add %o0, 8, %o0 - ldxa [%o0]ASI_MEM, %g1 - add %o0, 8, %o0 - ldxa [%o0]ASI_MEM, %g2 - - stxa %o2, [%o1]ASI_MEM - add %o1, 8, %o1 - stxa %o3, [%o1]ASI_MEM - add %o1, 8, %o1 - stxa %g1, [%o1]ASI_MEM - add %o1, 8, %o1 - stxa %g2, [%o1]ASI_MEM - - retl - wrpr %g0, %o4, %pstate ! restore earlier pstate register value - SET_SIZE(bcopy32_il) - -#endif /* lint */ - -#if defined(lint) - -/*ARGSUSED*/ -void -flush_ecache_il(uint64_t physaddr, uint_t size, uint_t linesize) -{} - -#else /* lint */ - - ENTRY_NP(flush_ecache_il) - srl %o1, 0, %o1 ! clear upper 32 bits - srl %o2, 0, %o2 ! clear upper 32 bits - rdpr %pstate, %o3 - andn %o3, PSTATE_IE | PSTATE_AM, %o4 - wrpr %g0, %o4, %pstate ! clear AM to access 64 bit physaddr - b 2f - nop -1: - ldxa [%o0 + %o1]ASI_MEM, %g0 ! start reading from physaddr + size -2: - subcc %o1, %o2, %o1 - bgeu,a 1b - nop - - ! retl - wrpr %g0, %o3, %pstate ! restore earlier pstate - SET_SIZE(flush_ecache_il) - -#endif /* lint */ - -#if defined(lint) - -/*ARGUSED*/ -void -stphysio_il(uint64_t physaddr, u_int value) -{} - -/*ARGSUSED*/ -u_int -ldphysio_il(uint64_t physaddr) -{ return(0); } - -#else /* lint */ - - ENTRY_NP(stphysio_il) - rdpr %pstate, %o2 /* read PSTATE reg */ - andn %o2, PSTATE_IE | PSTATE_AM, %o3 - wrpr %g0, %o3, %pstate - stwa %o1, [%o0]ASI_IO /* store value via bypass ASI */ - retl - wrpr %g0, %o2, %pstate /* restore the PSTATE */ - SET_SIZE(stphysio_il) - - ! - ! load value at physical address in I/O space - ! - ! u_int ldphysio_il(uint64_t physaddr) - ! - ENTRY_NP(ldphysio_il) - rdpr %pstate, %o2 /* read PSTATE reg */ - andn %o2, PSTATE_IE | PSTATE_AM, %o3 - wrpr %g0, %o3, %pstate - lduwa [%o0]ASI_IO, %o0 /* load value via bypass ASI */ - retl - wrpr %g0, %o2, %pstate /* restore pstate */ - SET_SIZE(ldphysio_il) - -#endif /* lint */ - -#if defined(lint) - -/* - * Argument to drmach_exec_script_il is a pointer to: - * - * typedef struct { - * uint64_t masr_addr; - * uint_t masr; - * uint_t _filler; - * } drmach_rename_script_t; - */ - -/*ARGUSED*/ -void -drmach_exec_script_il(void *sp) -{} - -#else /* lint */ - - ENTRY_NP(drmach_exec_script_il) - mov %o0, %o2 -0: /* cache script */ - ldx [%o2], %o1 - cmp %g0, %o1 - bnz,pt %xcc, 0b - add %o2, 16, %o2 - - rdpr %pstate, %o4 /* read PSTATE reg */ - andn %o4, PSTATE_IE | PSTATE_AM, %o1 - wrpr %g0, %o1, %pstate - - b 2f /* cache it */ - nop -1: - ldx [%o0], %o1 - cmp %g0, %o1 - bz,pn %xcc, 5f - ld [%o0 + 8], %o2 - b 3f - stwa %o2, [%o1]ASI_IO -2: - b 4f /* cache it */ - nop -3: - add %o0, 16, %o0 - b 1b - lduwa [%o1]ASI_IO, %g0 /* read back to insure written */ -4: - b 1b /* caching done */ - nop -5: - retl - wrpr %g0, %o4, %pstate /* restore the PSTATE */ - SET_SIZE(drmach_exec_script_il) - -#endif /* lint */ diff --git a/usr/src/uts/sun4u/starfire/ml/drmach_asm.s b/usr/src/uts/sun4u/starfire/ml/drmach_asm.s deleted file mode 100644 index 3c825df992..0000000000 --- a/usr/src/uts/sun4u/starfire/ml/drmach_asm.s +++ /dev/null @@ -1,361 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file is through cpp before being used as - * an inline. It contains support routines used - * only by DR for the copy-rename sequence. - */ - -#if defined(lint) -#include <sys/types.h> -#else -#include "assym.h" -#endif /* lint */ - -#include <sys/asm_linkage.h> -#include <sys/param.h> -#include <sys/privregs.h> -#include <sys/machasi.h> -#include <sys/spitregs.h> -#include <sys/mmu.h> -#include <sys/machthread.h> -#include <sys/pte.h> -#include <sys/stack.h> -#include <sys/vis.h> - -#ifndef lint - -/* - * arg1 = icache_size - * arg2 = icache_linesize - */ -#define ICACHE_FLUSHALL(lbl, arg1, arg2, tmp1) \ - ldxa [%g0]ASI_LSU, tmp1 ;\ - btst LSU_IC, tmp1 ;\ - bz,pn %icc, lbl/**/1 ;\ - sub arg1, arg2, tmp1 ;\ -lbl/**/0: ;\ - stxa %g0, [tmp1]ASI_IC_TAG ;\ - membar #Sync ;\ - cmp %g0, tmp1 ;\ - bne,pt %icc, lbl/**/0 ;\ - sub tmp1, arg2, tmp1 ;\ -lbl/**/1: - -/* - * arg1 = dcache_size - * arg2 = dcache_linesize - */ -#define DCACHE_FLUSHALL(lbl, arg1, arg2, tmp1) \ - ldxa [%g0]ASI_LSU, tmp1 ;\ - btst LSU_DC, tmp1 ;\ - bz,pn %icc, lbl/**/1 ;\ - sub arg1, arg2, tmp1 ;\ -lbl/**/0: ;\ - stxa %g0, [tmp1]ASI_DC_TAG ;\ - membar #Sync ;\ - cmp %g0, tmp1 ;\ - bne,pt %icc, lbl/**/0 ;\ - sub tmp1, arg2, tmp1 ;\ -lbl/**/1: - -/* - * arg1 = ecache flush physaddr - * arg2 = size - * arg3 = ecache_linesize - */ -#define ECACHE_FLUSHALL(lbl, arg1, arg2, arg3, tmp1, tmp2) \ - rdpr %pstate, tmp1 ;\ - andn tmp1, PSTATE_IE | PSTATE_AM, tmp2 ;\ - wrpr %g0, tmp2, %pstate ;\ - b lbl/**/1 ;\ -lbl/**/0: ;\ - sub arg2, arg3, arg2 ;\ -lbl/**/1: ;\ - brgez,a arg2, lbl/**/0 ;\ - ldxa [arg1 + arg2]ASI_MEM, %g0 ;\ - wrpr %g0, tmp1, %pstate - -#ifdef SF_ERRATA_32 -#define SF_WORKAROUND(tmp1, tmp2) \ - sethi %hi(FLUSH_ADDR), tmp2 ;\ - set MMU_PCONTEXT, tmp1 ;\ - stxa %g0, [tmp1]ASI_DMMU ;\ - flush tmp2 ; -#else -#define SF_WORKAROUND(tmp1, tmp2) -#endif /* SF_ERRATA_32 */ - -/* - * arg1 = vaddr - * arg2 = ctxnum - * - disable interrupts and clear address mask - * to access 64 bit physaddr - * - Blow out the TLB. - * . If it's kernel context, then use primary context. - * . Otherwise, use secondary. - */ -#define VTAG_FLUSHPAGE(lbl, arg1, arg2, tmp1, tmp2, tmp3, tmp4) \ - rdpr %pstate, tmp1 ;\ - andn tmp1, PSTATE_IE | PSTATE_AM, tmp2 ;\ - wrpr tmp2, 0, %pstate ;\ - brnz,pt arg2, lbl/**/1 ;\ - sethi %hi(FLUSH_ADDR), tmp2 ;\ - stxa %g0, [arg1]ASI_DTLB_DEMAP ;\ - stxa %g0, [arg1]ASI_ITLB_DEMAP ;\ - b lbl/**/5 ;\ - flush tmp2 ;\ -lbl/**/1: ;\ - set MMU_SCONTEXT, tmp3 ;\ - ldxa [tmp3]ASI_DMMU, tmp4 ;\ - or DEMAP_SECOND | DEMAP_PAGE_TYPE, arg1, arg1 ;\ - cmp tmp4, arg2 ;\ - be,a,pt %icc, lbl/**/4 ;\ - nop ;\ - stxa arg2, [tmp3]ASI_DMMU ;\ -lbl/**/4: ;\ - stxa %g0, [arg1]ASI_DTLB_DEMAP ;\ - stxa %g0, [arg1]ASI_ITLB_DEMAP ;\ - flush tmp2 ;\ - be,a,pt %icc, lbl/**/5 ;\ - nop ;\ - stxa tmp4, [tmp3]ASI_DMMU ;\ - flush tmp2 ;\ -lbl/**/5: ;\ - wrpr %g0, tmp1, %pstate - -/* - * arg1 = dtlb entry - * - Before first compare: - * tmp4 = tte - * tmp5 = vaddr - * tmp6 = cntxnum - */ -#define DTLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \ - tmp4, tmp5, tmp6) \ -lbl/**/0: ;\ - sllx arg1, 3, tmp3 ;\ - SF_WORKAROUND(tmp1, tmp2) ;\ - ldxa [tmp3]ASI_DTLB_ACCESS, tmp4 ;\ - srlx tmp4, 6, tmp4 ;\ - andcc tmp4, 1, %g0 ;\ - bnz,pn %xcc, lbl/**/1 ;\ - srlx tmp4, 57, tmp4 ;\ - andcc tmp4, 1, %g0 ;\ - beq,pn %xcc, lbl/**/1 ;\ - nop ;\ - set TAGREAD_CTX_MASK, tmp1 ;\ - ldxa [tmp3]ASI_DTLB_TAGREAD, tmp2 ;\ - and tmp2, tmp1, tmp6 ;\ - andn tmp2, tmp1, tmp5 ;\ - VTAG_FLUSHPAGE(VD, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\ -lbl/**/1: ;\ - brgz,pt arg1, lbl/**/0 ;\ - sub arg1, 1, arg1 - -/* - * arg1 = itlb entry - * - Before first compare: - * tmp4 = tte - * tmp5 = vaddr - * tmp6 = cntxnum - */ -#define ITLB_FLUSH_UNLOCKED(lbl, arg1, tmp1, tmp2, tmp3, \ - tmp4, tmp5, tmp6) \ -lbl/**/0: ;\ - sllx arg1, 3, tmp3 ;\ - SF_WORKAROUND(tmp1, tmp2) ;\ - ldxa [tmp3]ASI_ITLB_ACCESS, tmp4 ;\ - srlx tmp4, 6, tmp4 ;\ - andcc tmp4, 1, %g0 ;\ - bnz,pn %xcc, lbl/**/1 ;\ - srlx tmp4, 57, tmp4 ;\ - andcc tmp4, 1, %g0 ;\ - beq,pn %xcc, lbl/**/1 ;\ - nop ;\ - set TAGREAD_CTX_MASK, tmp1 ;\ - ldxa [tmp3]ASI_ITLB_TAGREAD, tmp2 ;\ - and tmp2, tmp1, tmp6 ;\ - andn tmp2, tmp1, tmp5 ;\ - VTAG_FLUSHPAGE(VI, tmp5, tmp6, tmp1, tmp2, tmp3, tmp4) ;\ -lbl/**/1: ;\ - brgz,pt arg1, lbl/**/0 ;\ - sub arg1, 1, arg1 - -#define CLEARTL(lvl) \ - wrpr %g0, lvl, %tl ;\ - wrpr %g0, %g0, %tpc ;\ - wrpr %g0, %g0, %tnpc ;\ - wrpr %g0, %g0, %tt - -#define SWITCH_STACK(estk) \ - flushw ;\ - sub estk, SA(KFPUSIZE+GSR_SIZE), estk ;\ - andn estk, 0x3f, estk ;\ - sub estk, SA(MINFRAME) + STACK_BIAS, %sp ;\ - mov estk, %fp - -#endif /* !lint */ - -#if defined(lint) - -/*ARGSUSED*/ -void -drmach_shutdown_asm(uint64_t mbox_addr) -{} - -#else /* lint */ - - ENTRY_NP(drmach_shutdown_asm) - mov %o0, %o5 - - ldxa [%o5]ASI_MEM, %o0 ! get 8-byte estack in o0 - add %o5, 8, %o5 - ldxa [%o5]ASI_MEM, %o1 ! get 8-byte flushaddr in o1 - add %o5, 8, %o5 - lda [%o5]ASI_MEM, %o2 ! get 4-byte size in o2 - srl %o2, 0, %o2 - add %o5, 4, %o5 - lda [%o5]ASI_MEM, %o3 ! get 4-byte linesize in o3 - srl %o3, 0, %o3 - add %o5, 4, %o5 - ldxa [%o5]ASI_MEM, %o4 ! get 8-byte physaddr in o4 - - - ! %o0 = base (va mapping this code in bbsram) - ! %o1 = flushaddr for ecache - ! %o2 = size to use for ecache flush - ! %o3 = ecache linesize - ! %o4 = phys addr of byte to clear when finished - ! - ! output: Stores a zero at [%o4]ASI_MEM - - membar #LoadStore - - ! - ! Switch stack pointer to bbsram - ! - SWITCH_STACK(%o0) - - ! - ! Get some globals - ! - mov %o3, %g1 ! ecache_linesize - mov %o4, %o0 ! physaddr byte to clear - - sethi %hi(dcache_linesize), %g2 - ld [%g2 + %lo(dcache_linesize)], %g2 - - sethi %hi(dcache_size), %g3 - ld [%g3 + %lo(dcache_size)], %g3 - - sethi %hi(icache_linesize), %g4 - ld [%g4 + %lo(icache_linesize)], %g4 - - sethi %hi(icache_size), %g5 - ld [%g5 + %lo(icache_size)], %g5 - - sethi %hi(dtlb_entries), %o5 - ld [%o5 + %lo(dtlb_entries)], %o5 - sllx %o5, 32, %o5 - srlx %o5, 32, %o5 - - sethi %hi(itlb_entries), %o3 - ld [%o3 + %lo(itlb_entries)], %o3 - ! - ! cram Xtlb_entries into a single register (%o5) - ! %o5 upper 32 = itlb_entries - ! lower 32 = dtlb_entries - ! - sllx %o3, 32, %o3 - or %o5, %o3, %o5 - - ! - ! Flush E$ - ! - ECACHE_FLUSHALL(EC, %o1, %o2, %g1, %o3, %o4) - ! - ! %o1 & %o2 now available - ! - - membar #Sync - - ! - ! Flush D$ - ! - DCACHE_FLUSHALL(DC, %g3, %g2, %o3) - - ! - ! Flush I$ - ! - ICACHE_FLUSHALL(IC, %g5, %g4, %o3) - - membar #Sync - - ! - ! Flush dtlb's - ! - srlx %o5, 32, %g5 ! %g5 = itlb_entries - sllx %o5, 32, %o5 - srlx %o5, 32, %g1 - sub %g1, 1, %g1 ! %g1 = dtlb_entries - 1 - - DTLB_FLUSH_UNLOCKED(D, %g1, %g3, %g4, %o2, %o3, %o4, %o5) - - ! - ! Flush itlb's - ! - sub %g5, 1, %g1 ! %g1 = itlb_entries - 1 - - ITLB_FLUSH_UNLOCKED(I, %g1, %g3, %g4, %o2, %o3, %o4, %o5) - - membar #Sync - - ! - ! Clear byte to signal finished. - ! - stba %g0, [%o0]ASI_MEM - membar #Sync - - ! - ! read ensures that last write completed (has left queue in the PC chip) - ! - lduba [%o0]ASI_MEM, %g0 -5: - ba 5b - nop - SET_SIZE(drmach_shutdown_asm) - - .global drmach_shutdown_asm_end - - .skip 2048 - -drmach_shutdown_asm_end: - -#endif /* lint */ diff --git a/usr/src/uts/sun4u/starfire/ml/idn_asm.s b/usr/src/uts/sun4u/starfire/ml/idn_asm.s deleted file mode 100644 index 563fe67286..0000000000 --- a/usr/src/uts/sun4u/starfire/ml/idn_asm.s +++ /dev/null @@ -1,385 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file contains the low-level DMV interrupt - * handler for IDN cross-domain interrupts. - */ - -#if defined(lint) -#include <sys/types.h> -#endif /* lint */ - -#include <sys/asm_linkage.h> -#include <sys/machasi.h> -#include <sys/privregs.h> -#include <sys/intreg.h> -#include <sys/machthread.h> - -#include <sys/idn.h> - -#if !defined(lint) -#include "idn_offsets.h" -#endif /* !lint */ - -#define IDN_MONDO - -/* - * The IDN_DMV_CPU_SHIFT is based on the sizeof (idn_dmv_cpu_t) - * which must be a power of 2 to optimize calculating our - * entry into idn_dmv_cpu[]. - */ -#define IDN_DMV_CPU_SHIFT 4 - -/* - *-------------------------------------------------------- - */ -#if defined(lint) - -/* - * Would be nice to use init_mondo, but unforunately - * it assumes the first arg is 32-bits. - */ -/*ARGSUSED*/ -void -idnxf_init_mondo(uint64_t arg0, uint64_t arg1, uint64_t arg2) -{} - -#else /* lint */ - - .global _idn_dispatch_status_busy -_idn_dispatch_status_busy: - .asciz "ASI_INTR_DISPATCH_STATUS error: busy" - .align 4 - - ENTRY_NP(idnxf_init_mondo) -#ifdef DEBUG - ! - ! IDSR should not be busy at the moment - borrowed from init_mondo - ! - ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %g1 - btst IDSR_BUSY, %g1 - bz,pt %xcc, 1f - mov ASI_INTR_DISPATCH, %asi - sethi %hi(_idn_dispatch_status_busy), %o0 - call panic - or %o0, %lo(_idn_dispatch_status_busy), %o0 -#endif /* DEBUG */ - - mov ASI_INTR_DISPATCH, %asi -1: - stxa %o0, [IDDR_0]%asi ! dmv_word0 - stxa %o1, [IDDR_1]%asi ! dmv_word1 - stxa %o2, [IDDR_2]%asi ! dmv_word2 - - retl - membar #Sync - - SET_SIZE(idnxf_init_mondo) - -#endif /* lint */ -/* - *-------------------------------------------------------- - */ -#if defined(lint) - -/* - * Unfortunately, send_mondo is rather picky about getting - * a result from the cpu it sends an interrupt to. If it - * doesn't get a result within a specific timeframe it - * will panic! For IDN that's not cool since a cpu hungup - * in one could ultimately result in the demise of a cpu - * in another domain. Instead of getting our panties in - * a bind, we simply bail out. - */ -/*ARGSUSED*/ -int -idnxf_send_mondo(int upaid) -{ return (0); } - -#else /* lint */ - - .seg ".data" - - .global _idn_send_mondo_failure -_idn_send_mondo_failure: - .word 0 - - .seg ".text" - ENTRY(idnxf_send_mondo) - ! - ! NOTE: - ! This is stolen from send_mondo. The changes - ! are those ifdef'd with IDN_MONDO - ! - ! construct the interrupt dispatch command register in %g1 - ! also, get the dispatch out as SOON as possible - ! (initial analysis puts the minimum dispatch time at around - ! 30-60 cycles. hence, we try to get the dispatch out quickly - ! and then start the rapid check loop). - ! - rd %tick, %o4 ! baseline tick - sll %o0, IDCR_PID_SHIFT, %g1 ! IDCR<18:14> = upa port id - or %g1, IDCR_OFFSET, %g1 ! IDCR<13:0> = 0x70 - stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch -#if defined(SF_ERRATA_54) - membar #Sync ! store must occur before load - mov 0x20, %g3 ! UDBH Control Register Read - ldxa [%g3]ASI_SDB_INTR_R, %g0 -#endif - membar #Sync - clr %o2 ! clear NACK counter - clr %o3 ! clear BUSY counter - - ! - ! how long, in ticks, are we willing to wait completely - ! - sethi %hi(xc_tick_limit), %g2 - ldx [%g2 + %lo(xc_tick_limit)], %g2 - add %g2, %o4, %o5 ! compute the limit value - - ! - ! check the dispatch status - ! -.check_dispatch: - ldxa [%g0]ASI_INTR_DISPATCH_STATUS, %o1 - brz,pn %o1, .dispatch_complete - rd %tick, %g5 - - ! - ! see if we've gone beyond the limit - ! (can tick ever overflow?) - ! -.timeout_primed: - sub %o5, %g5, %g2 ! limit - tick < 0 if timeout - brgez,pt %g2, .check_busy - inc %o3 ! bump the BUSY counter - -#ifdef IDN_MONDO - ! - ! Within the context of IDN we don't want - ! to panic just because we can't send_mondo. - ! Clear the dispatch register and increment - ! our count of failures. - ! - stxa %g0, [%g1]ASI_INTR_DISPATCH - sethi %hi(_idn_send_mondo_failure), %o0 - ld [%o0 + %lo(_idn_send_mondo_failure)], %o1 - inc %o1 - st %o1, [%o0 + %lo(_idn_send_mondo_failure)] - retl - mov -1, %o0 ! return (-1) -#else /* IDN_MONDO */ - ! - ! time to die, see if we are already panicing - ! - mov %o0, %o1 ! save target - sethi %hi(_send_mondo_nack), %o0 - or %o0, %lo(_send_mondo_nack), %o0 - sethi %hi(panicstr), %g2 - ldn [%g2 + %lo(panicstr)], %g2 - brnz %g2, .dispatch_complete ! skip if already in panic - nop - call panic - nop -#endif /* IDN_MONDO */ - -.check_busy: - btst IDSR_BUSY, %o1 ! was it BUSY? - bnz,pt %xcc, .check_dispatch - nop - - ! - ! we weren't busy, we must have been NACK'd - ! wait a while and send again - ! (this might need jitter) - ! - sethi %hi(sys_clock_mhz), %g2 - lduw [%g2 + %lo(sys_clock_mhz)], %g2 - rd %tick, %g4 - add %g2, %g4, %g2 -.delay: - cmp %g2, %g4 - bgu,pt %xcc, .delay - rd %tick, %g4 - - stxa %g0, [%g1]ASI_INTR_DISPATCH ! interrupt vector dispatch -#if defined(SF_ERRATA_54) - membar #Sync ! store must occur before load - ldxa [%g3]ASI_SDB_INTR_R, %g0 -#endif - membar #Sync - clr %o3 ! reset BUSY counter - ba .check_dispatch - inc %o2 ! bump the NACK counter - -.dispatch_complete: -#ifndef IDN_MONDO -#ifdef SEND_MONDO_STATS - ! - ! Increment the appropriate entry in a send_mondo timeout array - ! x_entry[CPU][MSB]++; - sub %g5, %o4, %g5 ! how long did we wait? - clr %o1 ! o1 is now bit counter -1: orcc %g5, %g0, %g0 ! any bits left? - srlx %g5, 1, %g5 ! bits to the right - bne,a,pt %xcc, 1b - add %o1, 4, %o1 ! pointer increment - - ! - ! now compute the base of the x_early entry for our cpu - ! - CPU_INDEX(%o0, %g5) - sll %o0, 8, %o0 ! 64 * 4 - add %o0, %o1, %o1 ! %o0 = &[CPU][delay] - - ! - ! and increment the appropriate value - ! - sethi %hi(x_early), %o0 - or %o0, %lo(x_early), %o0 - ld [%o0 + %o1], %g5 - inc %g5 - st %g5, [%o0 + %o1] -#endif /* SEND_MONDO_STATS */ -#endif /* !IDN_MONDO */ - retl -#ifdef IDN_MONDO - mov %g0, %o0 ! return (0) -#else /* IDN_MONDO */ - nop -#endif /* IDN_MONDO */ - SET_SIZE(idnxf_send_mondo) - -#endif /* lint */ -/* - *-------------------------------------------------------- - */ -#if defined(lint) - -/*ARGSUSED*/ -void -idn_dmv_handler(void *arg) -{} - -#else /* lint */ - - ENTRY_NP(idn_dmv_handler) - ! - ! On entry: - ! g1 = idn_dmv_data - ! g2 = word 0 - ! - ldx [%g1 + IDN_DMV_QBASE], %g4 ! g4 = idn_dmv_qbase - add %g1, IDN_DMV_CPU, %g3 ! g3 = &idn_dmv_cpu[0] - - CPU_INDEX(%g6, %g5) ! g6 = cpuid - - ! - ! g5 = cur = idn_dmv_cpu[cpuid] - ! - sll %g6, IDN_DMV_CPU_SHIFT, %g6 ! g6 = cpuid * 8 - add %g3, IDN_DMV_CURRENT, %g3 - ld [%g6 + %g3], %g5 - ! - ! g5 = idn_dmv_cpu[cpuid].idn_dmv_current - ! offset from idn_dmv_qbase - ! - or %g5, %g0, %g5 ! get to 64-bits - add %g5, %g4, %g5 ! g5 = idn_dmv_current - ! actual address - ldstub [%g5 + IV_INUSE], %g7 ! cur->iv_inuse = 0xff - brz,pt %g7, 1f ! did we get it? - sub %g3, IDN_DMV_CURRENT, %g4 - - ! - ! Queue is FULL. Drop interrupt. - ! - add %g4, IDN_DMV_LOSTINTR, %g3 - ld [%g6 + %g3], %g2 - ! - ! g2 = idn_dmv_cpu[cpuid].idn_iv_lostintr++ - ! - inc %g2 - set dmv_finish_intr, %g4 - st %g2, [%g3 + %g6] - jmp %g4 - mov -1, %g1 - ! - ! not reached - ! - -1: - add %g4, IDN_DMV_ACTIVE, %g7 - ! - ! Move current pointer to next one. - ! idn_dmv_current[cpuid] = cur->iv_next - ! - ld [%g5 + IV_NEXT], %g4 - st %g4, [%g3 + %g6] - - ! - ! Start filling in structure with data. - ! - stx %g2, [%g5 + IV_HEAD] - - mov IRDR_1, %g2 - mov IRDR_2, %g4 - ldxa [%g2]ASI_INTR_RECEIVE, %g2 ! g2 = xargs[0,1] - ldxa [%g4]ASI_INTR_RECEIVE, %g4 ! g4 = xargs[2,3] - - stx %g2, [%g5 + IV_XARGS0] - stx %g4, [%g5 + IV_XARGS2] - - membar #StoreLoad|#StoreStore - - clrb [%g5 + IV_READY] ! cur->iv_ready = 0 (unlocked) - - ! - ! See if we're already active, i.e. have things - ! queued. If so, don't bother generating a soft - ! interrupt. IDN interrupts could exhaust the - ! intr_vec structs for the given cpu and that code - ! doesn't know how to survive with intr_vec structs! - ! - ldstub [%g6 + %g7], %g7 ! idn_dmv_active = 0xff - brz,a,pt %g7, 2f - ldx [%g1 + IDN_SOFT_INUM], %g7 ! g7 = idn_soft_inum - mov -1, %g7 -2: - - ! - ! Setup to cause an IDN soft interrupt to occur, - ! (if necessary). - ! - set dmv_finish_intr, %g3 - jmp %g3 - mov %g7, %g1 - - SET_SIZE(idn_dmv_handler) - -#endif /* lint */ diff --git a/usr/src/uts/sun4u/starfire/ml/idn_offsets.in b/usr/src/uts/sun4u/starfire/ml/idn_offsets.in deleted file mode 100644 index 2a5da76e4b..0000000000 --- a/usr/src/uts/sun4u/starfire/ml/idn_offsets.in +++ /dev/null @@ -1,60 +0,0 @@ -\ -\ CDDL HEADER START -\ -\ The contents of this file are subject to the terms of the -\ Common Development and Distribution License, Version 1.0 only -\ (the "License"). You may not use this file except in compliance -\ with the License. -\ -\ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -\ or http://www.opensolaris.org/os/licensing. -\ See the License for the specific language governing permissions -\ and limitations under the License. -\ -\ When distributing Covered Code, include this CDDL HEADER in each -\ file and include the License file at usr/src/OPENSOLARIS.LICENSE. -\ If applicable, add the following below this CDDL HEADER, with the -\ fields enclosed by brackets "[]" replaced with your own identifying -\ information: Portions Copyright [yyyy] [name of copyright owner] -\ -\ CDDL HEADER END -\ -\ Copyright (c) 1999 by Sun Microsystems, Inc. -\ All rights reserved. -\ -\ Based on sun4u/ml/offsets.in. -\ -\ Definitions needed by IDN send-mondo support. -\ -\ Offset definitions for low-level idn_dmv_handler() (assembly code) -\ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/sysmacros.h> -#include <sys/param.h> -#include <sys/machparam.h> -#include <sys/systm.h> -#include <sys/machsystm.h> -#include <sys/cpuvar.h> - -#include <sys/idn.h> - -idn_dmv_cpu_t IDN_DMV_CPU_SIZE - idn_dmv_current - idn_dmv_active - idn_dmv_lostintr - -idn_dmv_data_t IDN_DMV_DATA_SIZE - idn_soft_inum - idn_dmv_qbase - idn_dmv_cpu - -idn_dmv_msg_t IDN_DMV_MSG_SIZE - iv_next - iv_inuse - iv_ready - iv_head - iv_xargs0 - iv_xargs2 diff --git a/usr/src/uts/sun4u/starfire/ngdr/Makefile b/usr/src/uts/sun4u/starfire/ngdr/Makefile deleted file mode 100644 index 7d68bff634..0000000000 --- a/usr/src/uts/sun4u/starfire/ngdr/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the ngdr driver module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = ngdr -OBJECTS = $(DR_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(DR_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/sun4u/starfire/io - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized - -# -# module dependencies -# -LDFLAGS += -dy -Nmisc/ngdrmach - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/ngdrmach/Makefile b/usr/src/uts/sun4u/starfire/ngdrmach/Makefile deleted file mode 100644 index 181e6cf8a6..0000000000 --- a/usr/src/uts/sun4u/starfire/ngdrmach/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# Copyright (c) 2011 Bayard G. Bell. All rights reserved. -# -# This makefile drives the production of the ngdrmach loadable module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = ngdrmach -OBJECTS = $(NGDRMACH_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(NGDRMACH_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_MISC_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-uninitialized - -# -# Define dependency on cvc -# -LDFLAGS += -dy -N drv/cvc - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/os/bbus_intr.c b/usr/src/uts/sun4u/starfire/os/bbus_intr.c deleted file mode 100644 index f82d8afc50..0000000000 --- a/usr/src/uts/sun4u/starfire/os/bbus_intr.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/kmem.h> -#include <sys/cpu_sgnblk_defs.h> -#include <vm/seg.h> -#include <sys/iommu.h> -#include <sys/vtrace.h> -#include <sys/intreg.h> -#include <sys/ivintr.h> -#include <sys/cpuvar.h> -#include <sys/systm.h> -#include <sys/machsystm.h> -#include <sys/cyclic.h> -#include <sys/cpu_sgn.h> - -extern cpu_sgnblk_t *cpu_sgnblkp[NCPU]; -extern struct cpu *SIGBCPU; -extern void power_down(const char *); - -uint_t bbus_intr_inum; -uint64_t bbus_poll_inum; - -/* - * Support for sgnblk polling. - */ - -/* Internal function prototypes */ -static void sgnblk_poll_init(); -static uint_t bbus_poll(caddr_t arg1, caddr_t arg2); -static void sgnblk_poll_handler(void *unused); -#ifdef THROTTLE -static void sgnblk_poll_throttle(uint64_t interval); -#endif /* THROTTLE */ - -/* Default sgnblk polling interval is every 5 seconds. */ -#define ONE_SECOND (1000000) /* in usecs */ -#ifdef THROTTLE -#define SGNBLK_POLL_INTERVAL (5 * ONE_SECOND) -#define SGNBLK_POLL_FAST (ONE_SECOND >> 1) -#define SGNBLK_POLL_FAST_WIN ((60 * ONE_SECOND) / \ - SGNBLK_POLL_FAST) -#else /* THROTTLE */ -/* - * Until we can find a way to throttle back to 0.5 second intervals - * we're stuck fixed on 2.5 second intervals. - */ -#define SGNBLK_POLL_INTERVAL ((2 * ONE_SECOND) + (ONE_SECOND >> 1)) -#endif /* THROTTLE */ - -#define MAX_SGNBLK_POLL_CLNT 5 - -void (*pollclntfunc[MAX_SGNBLK_POLL_CLNT])(); -/* - * sgnblk_mutex Protects juggling & sgnblk_poll_refs[]. - * sgnblk_poll_mutex Protects pollclntfunc[]. - */ -kmutex_t sgnblk_mutex; -kmutex_t sgnblk_poll_mutex; -static uint64_t sgnblk_poll_interval = SGNBLK_POLL_INTERVAL; -#ifdef THROTTLE -static uint64_t sgnblk_poll_fast = SGNBLK_POLL_FAST; -static int64_t sgnblk_poll_fast_win = SGNBLK_POLL_FAST_WIN; -#endif /* THROTTLE */ -static processorid_t sgnblk_pollcpu = -1; -/* - * Note that the sigblock polling depends on CY_HIGH_LEVEL - * being higher than PIL_13 since we ultimately need to - * dispatch a PIL_13 soft handler. - * Also, we assume one sgnblk handler for the entire system. - * Once upon a time we had them per-cpu. With the Cyclic stuff - * we would have to bind our cyclic handler to a cpu and doing - * this prevents that cpu from being offlined. Since the Cyclic - * subsystem could indirectly juggle us without us knowing we - * have to assume we're running from any possible cpu and not - * always SIGBCPU. - */ -#ifdef THROTTLE -static cyclic_id_t sgnblk_poll_cycid = CYCLIC_NONE; -#endif /* THROTTLE */ -static cyc_handler_t sgnblk_poll_cychandler = { - sgnblk_poll_handler, - NULL, - CY_HIGH_LEVEL -}; -static cyc_time_t sgnblk_poll_time; - -/* - * Anybody that references the polling (SIGBCPU) can - * register a callback function that will be called if - * the polling cpu is juggled, e.g. during a DR operation. - */ -#define MAX_SGNBLK_POLL_REFS 10 - -struct sgnblk_poll_refs { - void (*callback)(cpu_sgnblk_t *sigbp, void *arg); - void *arg; -} sgnblk_poll_refs[MAX_SGNBLK_POLL_REFS]; - -/* - * Bootbus intr handler: Generic handler for all SSP/CBS - * interrupt requests initiated via the hw bootbus intr - * mechanism. This is similar to the level15 - * interrupt handling for sigb commands in the CS6400. - * Most of these code were stolen from the sigb stuff in - * in CS6400. - */ - -extern struct cpu cpu0; - -/*ARGSUSED*/ -static uint_t -bbus_intr(caddr_t arg) -{ - int cmd = 0; - processorid_t cpu_id = CPU->cpu_id; - int retflag; - int resp = 0; - proc_t *initpp; - - ASSERT(cpu_sgnblkp[cpu_id] != NULL); - - /* - * Check for unsolicited messages in the host's mailbox. - */ - retflag = cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag; - - switch (retflag) { - case CBS_TO_HOST: - retflag = HOST_TO_CBS; - break; - default: - retflag = SIGB_MBOX_EMPTY; - break; - } - if (retflag == SIGB_MBOX_EMPTY) - return (0); /* interrupt not claimed */ - - /* - * We only look for UNSOLICITED messages, i.e. commands. - * Responses to these commands are returned into the same - * mailbox from which the command was received, i.e. host's. - * - * If the host should solicit a message from the SSP, that - * message/command goes into the SSP's mailbox (sigb_ssp_mbox). - * The responses (from the SSP) to these messages will be - * read from the ssp mailbox by whomever solicited it, but - * will NOT be handled through this level 15 interrupt - * mechanism. - * - * Note that use of the flag field of the signature block mailbox - * structure and the mailbox protocol itself, serializes access - * to these mailboxes. - */ - - resp = 0; - - /* - * The first sizeof (uint_t) bytes of the data field - * is the command. - */ - cmd = cpu_sgnblkp[cpu_id]->sigb_host_mbox.cmd; - - switch (cmd) { - case SSP_GOTO_OBP: - /* - * Let's set the mailbox flag to BUSY while we are in OBP - */ - cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = SIGB_MBOX_BUSY; - - debug_enter("SSP requested (SSP_GOTO_OBP)"); - /* - * This command does NOT require a response. - */ - resp = 0; - break; - - case SSP_GOTO_PANIC: - /* - * Let's reset the mailbox flag before we bail. - */ - cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = SIGB_MBOX_EMPTY; - - cmn_err(CE_PANIC, "SSP requested (SSP_GOTO_PANIC)\n"); - /* should never reach this point */ - - resp = 0; - break; - case SSP_ENVIRON: - /* - * Environmental Interrupt. - */ - - /* - * Send SIGPWR to init(1) it will run rc0, which will uadmin to - * powerdown. - */ - - mutex_enter(&pidlock); - initpp = prfind(P_INITPID); - mutex_exit(&pidlock); - - /* - * If we're still booting and init(1) isn't set up yet, - * simply halt. - */ - if (initpp == NULL) { - extern void halt(char *); - cmn_err(CE_WARN, "?Environmental Interrupt"); - power_down((char *)NULL); - halt("Power off the System!\n"); /* just in case */ - } - - /* - * else, graceful shutdown with inittab and all getting involved - * - * XXX: Do we Need to modify the init process for the Cray 6400! - */ - psignal(initpp, SIGPWR); - - /* - * XXX: kick off a sanity timeout panic in case the /etc/inittab - * or /etc/rc0 files are hosed. The 6400 needs to hang here - * when we return from psignal. - * - * cmn_err(CE_PANIC, "SSP requested (SSP_ENVIRON)\n"); - * should never reach this point - */ - - resp = 0; - break; - /* - * Could handle more mailbox commands right here. - */ - - default: - resp = SIGB_BAD_MBOX_CMD; - break; - } - - /* - * If resp is non-zero then we'll automatically reset - * the handler_sigb lock once we've sent the response, - * however if no response is needed, then resetlck must - * be set so that the handler_sigb lock is reset. - */ - if (resp != 0) { - /* - * Had some kind of trouble handling the mailbox - * command. Need to send back an error response - * and back out of the cpu_sgnblk handling. - */ - cpu_sgnblkp[cpu_id]->sigb_host_mbox.cmd = resp; - bcopy((caddr_t)&cmd, - (caddr_t)&cpu_sgnblkp[cpu_id]->sigb_host_mbox.data[0], - sizeof (cmd)); - cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = retflag; - } else { - /* - * No response expected, but we still have to - * reset the flag to empty for the next person. - */ - cpu_sgnblkp[cpu_id]->sigb_host_mbox.flag = SIGB_MBOX_EMPTY; - } - return (1); /* interrupt claimed */ -} - -void -register_bbus_intr() -{ - /* - * Starfire's ASIC have the capability to generate a mondo - * vector. The SSP uses this capability via the Boot Bus to - * send an interrupt to a domain. - * - * The SSP generates a mondo with: - * ign = UPAID_TO_IGN(bootcpu_upaid) - * ino = 0 - * - * An interrupt handler is added for this inum. - */ - bbus_intr_inum = UPAID_TO_IGN(cpu0.cpu_id) * MAX_INO; - VERIFY(add_ivintr(bbus_intr_inum, PIL_13, (intrfunc)bbus_intr, - NULL, NULL, NULL) == 0); - - - /* - * Due to a HW flaw in starfire, liberal use - * of bootbus intrs under heavy system load - * may cause the machine to arbstop. The workaround - * is to provide a polling mechanism thru the signature - * block interface to allow another way for the SSP to - * interrupt the host. Applications like IDN which generate - * a high degree of SSP to host interruptions for - * synchronization will need to use the polling facility - * instead of the hw bootbus interrupt mechanism. - * The HW bootbus intr support is left intact as it - * will still be used by existing SSP applications for system - * recovery in the event of system hangs etc.. In such situations, - * HW bootbus intr is a better mechanism as it is HW generated - * level 15 interrupt that has a better chance of kicking - * a otherwise hung OS into recovery. - * - * Polling is done by scheduling a constant tick timer - * interrupt at a certain predefined interval. - * The handler will do a poll and if there is a - * "intr" request, scheduled a soft level 13 intr - * to handle it. Allocate the inum for the level - * 13 intr here. - */ - bbus_poll_inum = add_softintr(PIL_13, bbus_poll, 0, SOFTINT_ST); -} - -static void -sgnblk_poll_init() -{ - ASSERT(MUTEX_HELD(&sgnblk_mutex)); - - mutex_init(&sgnblk_poll_mutex, NULL, - MUTEX_SPIN, (void *)ipltospl(PIL_14)); - sgnblk_pollcpu = SIGBCPU->cpu_id; - mutex_enter(&cpu_lock); - sgnblk_poll_time.cyt_when = 0ull; - sgnblk_poll_time.cyt_interval = sgnblk_poll_interval * 1000ull; -#ifdef THROTTLE - sgnblk_poll_cycid = cyclic_add(&sgnblk_poll_cychandler, - &sgnblk_poll_time); -#else /* THROTTLE */ - (void) cyclic_add(&sgnblk_poll_cychandler, &sgnblk_poll_time); -#endif /* THROTTLE */ - mutex_exit(&cpu_lock); - ASSERT(sgnblk_pollcpu == SIGBCPU->cpu_id); -} - -int -sgnblk_poll_register(void(*func)(processorid_t cpu_id, - cpu_sgnblk_t *cpu_sgnblkp)) -{ - int i; - - /* - * See if we need to initialize - * sgnblk polling - */ - mutex_enter(&sgnblk_mutex); - if (sgnblk_pollcpu == -1) - sgnblk_poll_init(); - mutex_exit(&sgnblk_mutex); - - mutex_enter(&sgnblk_poll_mutex); - - /* - * Look for a empty slot - */ - for (i = 0; i < MAX_SGNBLK_POLL_CLNT; i++) { - if (pollclntfunc[i] == NULL) { - pollclntfunc[i] = func; - mutex_exit(&sgnblk_poll_mutex); - return (1); - } - } - mutex_exit(&sgnblk_poll_mutex); - return (0); /* failed */ -} - -int -sgnblk_poll_unregister(void(*func)(processorid_t cpu_id, - cpu_sgnblk_t *cpu_sgnblkp)) -{ - int i; - - mutex_enter(&sgnblk_poll_mutex); - - /* - * Look for the slot matching the function passed in. - */ - for (i = 0; i < MAX_SGNBLK_POLL_CLNT; i++) { - if (pollclntfunc[i] == func) { - pollclntfunc[i] = NULL; - mutex_exit(&sgnblk_poll_mutex); - return (1); - } - } - mutex_exit(&sgnblk_poll_mutex); - return (0); /* failed */ -} - - -/* - * For DR support. - * Juggle poll tick client to another cpu - * Assumed to be called single threaded. - */ -void -juggle_sgnblk_poll(struct cpu *cp) -{ - int i; - - mutex_enter(&sgnblk_mutex); - - if (sgnblk_pollcpu == -1 || - (cp != NULL && sgnblk_pollcpu == cp->cpu_id)) { - mutex_exit(&sgnblk_mutex); - return; - } - - /* - * Disable by simply returning here - * Passing a null cp is assumed to be - * sgnpoll disable request. - */ - if (cp == NULL) { - for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) { - void (*func)(), *arg; - - if ((func = sgnblk_poll_refs[i].callback) != NULL) { - arg = sgnblk_poll_refs[i].arg; - (*func)(NULL, arg); - } - } - mutex_exit(&sgnblk_mutex); - return; - } - - sgnblk_pollcpu = cp->cpu_id; - - for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) { - void (*func)(), *arg; - - if ((func = sgnblk_poll_refs[i].callback) != NULL) { - arg = sgnblk_poll_refs[i].arg; - (*func)(cpu_sgnblkp[sgnblk_pollcpu], arg); - } - } - - mutex_exit(&sgnblk_mutex); -} - -#ifdef THROTTLE -/*ARGSUSED0*/ -static void -_sgnblk_poll_throttle(void *unused) -{ - mutex_enter(&cpu_lock); - if (sgnblk_poll_cycid != CYCLIC_NONE) { - cyclic_remove(sgnblk_poll_cycid); - sgnblk_poll_cycid = CYCLIC_NONE; - } - - if (sgnblk_poll_time.cyt_interval > 0ull) - sgnblk_poll_cycid = cyclic_add(&sgnblk_poll_cychandler, - &sgnblk_poll_time); - mutex_exit(&cpu_lock); -} - -/* - * We don't want to remove the cyclic within the context of - * the handler so we kick off the throttle in background - * via a timeout call. - */ -static void -sgnblk_poll_throttle(uint64_t new_interval) -{ - mutex_enter(&cpu_lock); - sgnblk_poll_time.cyt_when = 0ull; - sgnblk_poll_time.cyt_interval = new_interval * 1000ull; - mutex_exit(&cpu_lock); - - (void) timeout(_sgnblk_poll_throttle, NULL, (clock_t)0); -} -#endif /* THROTTLE */ - -/* - * High priority interrupt handler (PIL_14) - * for signature block mbox polling. - */ -/*ARGSUSED0*/ -static void -sgnblk_poll_handler(void *unused) -{ - processorid_t cpuid = SIGBCPU->cpu_id; -#ifdef THROTTLE - static int64_t sb_window = -1; - static uint64_t sb_interval = 0; -#endif /* THROTTLE */ - - if (cpu_sgnblkp[cpuid] == NULL) - return; - - /* - * Poll for SSP requests - */ - if (cpu_sgnblkp[cpuid]->sigb_host_mbox.intr == SIGB_INTR_SEND) { - /* reset the flag - sure hope this is atomic */ - cpu_sgnblkp[cpuid]->sigb_host_mbox.intr = SIGB_INTR_OFF; - -#ifdef THROTTLE - /* - * Go into fast poll mode for a short duration - * (SGNBLK_POLL_FAST_WIN) in SGNBLK_POLL_FAST interval. - * The assumption here is that we just got activity - * on the mbox poll, the probability of more coming down - * the pipe is high - so let's look more often. - */ - if ((sb_window < 0) && (sb_interval > sgnblk_poll_fast)) { - sb_interval = sgnblk_poll_fast; - sgnblk_poll_throttle(sb_interval); - } - sb_window = sgnblk_poll_fast_win; -#endif /* THROTTLE */ - - /* schedule poll processing */ - setsoftint(bbus_poll_inum); - -#ifdef THROTTLE - } else if (sb_window >= 0) { - /* Revert to slow polling once fast window ends */ - if ((--sb_window < 0) && - (sb_interval < sgnblk_poll_interval)) { - sb_interval = sgnblk_poll_interval; - sgnblk_poll_throttle(sb_interval); - } -#endif /* THROTTLE */ - } -} - -/*ARGSUSED*/ -static uint_t -bbus_poll(caddr_t arg1, caddr_t arg2) -{ - int i; - processorid_t cpu_id = SIGBCPU->cpu_id; - cpu_sgnblk_t *sgnblkp = cpu_sgnblkp[cpu_id]; - - /* - * Go thru the poll client array and call the - * poll client functions one by one - */ - mutex_enter(&sgnblk_poll_mutex); - - for (i = 0; i < MAX_SGNBLK_POLL_CLNT; i++) { - void (*func)(processorid_t cpuid, cpu_sgnblk_t *sgnblkp); - - if ((func = pollclntfunc[i]) != NULL) { - mutex_exit(&sgnblk_poll_mutex); - (*func)(cpu_id, sgnblkp); - mutex_enter(&sgnblk_poll_mutex); - } - } - mutex_exit(&sgnblk_poll_mutex); - - return (1); -} - -int -sgnblk_poll_reference(void (*callback)(cpu_sgnblk_t *sigb, void *arg), - void *arg) -{ - int i, slot; - cpu_sgnblk_t *sigbp; - - if (callback == NULL) - return (-1); - - mutex_enter(&sgnblk_mutex); - /* - * First verify caller is not already registered. - */ - slot = -1; - for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) { - if ((slot == -1) && (sgnblk_poll_refs[i].callback == NULL)) { - slot = i; - continue; - } - if (sgnblk_poll_refs[i].callback == callback) { - mutex_exit(&sgnblk_mutex); - return (-1); - } - } - /* - * Now find an empty entry. - */ - if (slot == -1) { - mutex_exit(&sgnblk_mutex); - return (-1); - } - sgnblk_poll_refs[slot].callback = callback; - sgnblk_poll_refs[slot].arg = arg; - - sigbp = (sgnblk_pollcpu != -1) ? cpu_sgnblkp[sgnblk_pollcpu] : NULL; - - (*callback)(sigbp, arg); - - mutex_exit(&sgnblk_mutex); - - return (0); -} - -void -sgnblk_poll_unreference(void (*callback)(cpu_sgnblk_t *sigb, void *arg)) -{ - int i; - - mutex_enter(&sgnblk_mutex); - for (i = 0; i < MAX_SGNBLK_POLL_REFS; i++) { - if (sgnblk_poll_refs[i].callback == callback) { - void *arg; - - arg = sgnblk_poll_refs[i].arg; - (*callback)(NULL, arg); - sgnblk_poll_refs[i].callback = NULL; - sgnblk_poll_refs[i].arg = NULL; - break; - } - } - mutex_exit(&sgnblk_mutex); -} diff --git a/usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c b/usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c deleted file mode 100644 index be505da37b..0000000000 --- a/usr/src/uts/sun4u/starfire/os/cpu_sgnblk.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Following is STARFIRE specific code - */ - -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/archsystm.h> -#include <sys/machsystm.h> -#include <sys/vmem.h> -#include <sys/mman.h> -#include <sys/vm.h> - -#include <sys/cmn_err.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/starfire.h> - -#include <vm/seg.h> -#include <vm/seg_kmem.h> -#include <vm/seg_kp.h> -#include <sys/vtrace.h> -#include <sys/cpu_sgn.h> - -/* - * SIGBCPU represents the cpu maintaining the primary - * sigblock (bbsram). This bbsram is used for CVC - * and maintains the post2obp structure. It starts - * out as the bootproc (cpu0). - */ -struct cpu *SIGBCPU = &cpu0; - -cpu_sgnblk_t *cpu_sgnblkp[NCPU]; - -/* - * Mapin the the cpu's signature block. - */ -void -cpu_sgn_mapin(int cpuid) -{ - uint64_t bbsram_physaddr; - uint64_t cpu_sgnblk_physaddr; - uint32_t cpu_sgnblk_offset; - caddr_t cvaddr; - pgcnt_t num_pages; - pfn_t pfn; - - ASSERT(cpu_sgnblkp[cpuid] == NULL); - - /* - * Construct the physical base address of the bbsram - * in PSI space associated with this cpu in question. - */ - cpu_sgnblk_physaddr = bbsram_physaddr = - STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE; - - /* - * The cpu_sgnblk pointer offsets are stored in the - * undefined hardware trap slot 0x7f which is located - * at offset 0xfe0. There are 2 of them since the - * bbsram is shared among the 2 cpus residing on the - * a PC. We need to determine the CPU in question whether - * it is in port 0 or 1. CPU on port 0 has its - * signature blkptr stored in 0xfe0 while the cpu_sgnblk - * ptr of local port 1's CPU is in offset 0xfe8. - */ - if (cpuid & 0x1) { - /* CPU is in local port 1 */ - bbsram_physaddr |= 0xfe8ULL; - } else { - /* CPU is in local port 0 */ - bbsram_physaddr |= 0xfe0ULL; - } - - /* - * Read in the cpu_sgnblk pointer offset. Add it to the bbsram - * base address to get the base address of the cpu_sgnblk. - */ - cpu_sgnblk_offset = ldphysio(bbsram_physaddr); - cpu_sgnblk_physaddr += cpu_sgnblk_offset; - - pfn = (pfn_t)(cpu_sgnblk_physaddr >> MMU_PAGESHIFT); - - num_pages = mmu_btopr(((cpu_sgnblk_physaddr & - MMU_PAGEOFFSET) + sizeof (cpu_sgnblk_t))); - - /* - * Map in the cpu_sgnblk - */ - cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP); - - hat_devload(kas.a_hat, cvaddr, ptob(num_pages), - pfn, PROT_READ | PROT_WRITE, HAT_LOAD_LOCK); - - cpu_sgnblkp[cpuid] = ((cpu_sgnblk_t *)(cvaddr + - (uint32_t)(cpu_sgnblk_offset & MMU_PAGEOFFSET))); -} - -void -cpu_sgn_mapout(int cpuid) -{ - ulong_t cvaddr, num_pages; - uint32_t cpu_sgnblk_offset; - uint64_t cpu_sgnblk_physaddr; - uint64_t bbsram_physaddr; - - if ((cvaddr = (ulong_t)cpu_sgnblkp[cpuid]) == NULL) { - cmn_err(CE_WARN, "cpu_sgn_mapout: ERROR: " - "cpu_sgnblkp[%d] = NULL\n", cpuid); - } else { - cvaddr &= ~MMU_PAGEOFFSET; - - /* - * Construct the physical base address of the bbsram - * in PSI space associated with this cpu in question. - */ - bbsram_physaddr = STARFIRE_UPAID2UPS(cpuid) | - STARFIRE_PSI_BASE; - cpu_sgnblk_physaddr = bbsram_physaddr; - - /* - * The cpu_sgnblk pointer offsets are stored in the - * undefined hardware trap slot 0x7f which is located - * at offset 0xfe0. There are 2 of them since the - * bbsram is shared among the 2 cpus residing on the - * a PC. We need to determine the CPU in question whether - * it is in port 0 or 1. CPU on port 0 has its - * signature blkptr stored in 0xfe0 while the cpu_sgnblk - * ptr of local port 1's CPU is in offset 0xfe8. - */ - if (cpuid & 0x1) { - /* CPU is in local port 1 */ - bbsram_physaddr |= 0xfe8ULL; - } else { - /* CPU is in local port 0 */ - bbsram_physaddr |= 0xfe0ULL; - } - - /* - * Read in the cpu_sgnblk pointer offset. Add it to the bbsram - * base address to get the base address of the cpu_sgnblk. - */ - cpu_sgnblk_offset = ldphysio(bbsram_physaddr); - cpu_sgnblk_physaddr += cpu_sgnblk_offset; - - num_pages = mmu_btopr(((uint_t)(cpu_sgnblk_physaddr & - MMU_PAGEOFFSET) + sizeof (cpu_sgnblk_t))); - - hat_unload(kas.a_hat, (caddr_t)cvaddr, ptob(num_pages), - HAT_UNLOAD_UNLOCK); - vmem_free(heap_arena, (caddr_t)cvaddr, ptob(num_pages)); - - cpu_sgnblkp[cpuid] = NULL; - } -} diff --git a/usr/src/uts/sun4u/starfire/os/pda.c b/usr/src/uts/sun4u/starfire/os/pda.c deleted file mode 100644 index 5aee0cd542..0000000000 --- a/usr/src/uts/sun4u/starfire/os/pda.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Starfire Post Descriptor Array (post2obp) management. - */ - -#include <sys/debug.h> -#include <sys/types.h> -#include <sys/errno.h> -#include <sys/cpuvar.h> -#include <sys/dditypes.h> -#include <sys/conf.h> -#include <sys/ddi.h> -#include <sys/kmem.h> -#include <sys/sunddi.h> -#include <sys/sunndi.h> -#include <sys/vm.h> -#include <vm/seg.h> -#include <vm/seg_kmem.h> -#include <vm/seg_kp.h> -#include <sys/machsystm.h> -#include <sys/starfire.h> - -#include <sys/cpu_sgnblk_defs.h> -#include <sys/pda.h> -#include <sys/cpu_sgn.h> - -extern struct cpu *SIGBCPU; -extern cpu_sgnblk_t *cpu_sgnblkp[]; - -extern uint64_t mc_get_mem_alignment(); -extern uint64_t mc_asr_to_pa(uint_t mcreg); - -static post2obp_info_t *cpu_p2o_mapin(int cpuid); -static void cpu_p2o_mapout(int cpuid, post2obp_info_t *p2o); -static void p2o_update_checksum(post2obp_info_t *p2o); -static uint_t p2o_calc_checksum(post2obp_info_t *p2o); -static void p2o_mem_sort(post2obp_info_t *p2o); -static void p2o_mem_coalesce(post2obp_info_t *p2o); - -typedef struct { - post2obp_info_t *p2o_ptr; - int p2o_cpuid; -} p2o_info_t; - -/* - * PDA management routines. Should ultimately be made - * accessible to other Starfire subsystems, but for - * now we'll leave it here. - */ -pda_handle_t -pda_open() -{ - p2o_info_t *pip; - - if (SIGBCPU == NULL) { - cmn_err(CE_WARN, "pda_open: SIGBCPU is NULL"); - return (NULL); - } - - pip = (p2o_info_t *)kmem_alloc(sizeof (p2o_info_t), KM_SLEEP); - - pip->p2o_cpuid = (int)SIGBCPU->cpu_id; - pip->p2o_ptr = cpu_p2o_mapin(pip->p2o_cpuid); - - if (pip->p2o_ptr == NULL) { - kmem_free((caddr_t)pip, sizeof (p2o_info_t)); - return ((pda_handle_t)NULL); - } else { - return ((pda_handle_t)pip); - } -} - -void -pda_close(pda_handle_t ph) -{ - p2o_info_t *pip; - - if ((pip = (p2o_info_t *)ph) == NULL) - return; - - cpu_p2o_mapout(pip->p2o_cpuid, pip->p2o_ptr); - - kmem_free((caddr_t)pip, sizeof (p2o_info_t)); -} - -int -pda_board_present(pda_handle_t ph, int boardnum) -{ - ushort_t bda_board; - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - - bda_board = p2o->p2o_bdinfo[boardnum].bda_board; - - if ((bda_board & BDAN_MASK) != BDAN_GOOD) - return (0); - else - return (1); -} - -void * -pda_get_board_info(pda_handle_t ph, int boardnum) -{ - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - - return ((void *)&(p2o->p2o_bdinfo[boardnum])); -} - -uint_t -pda_get_mem_size(pda_handle_t ph, int boardnum) -{ - int c; - pgcnt_t npages; - uint_t asr; - pfn_t basepfn, endpfn; - uint64_t basepa, endpa; - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - - if (boardnum == -1) - return (p2o->p2o_memtotal.Memt_NumPages); - - asr = p2o->p2o_bdminfo[boardnum].bmda_adr; - - basepa = mc_asr_to_pa(asr); - /* - * Put on MC alignment. - */ - endpa = mc_get_mem_alignment(); - basepa &= ~(endpa - 1); - endpa += basepa; - basepfn = (pfn_t)(basepa >> PAGESHIFT); - endpfn = (pfn_t)(endpa >> PAGESHIFT); - - npages = 0; - - for (c = 0; c < p2o->p2o_memtotal.Memt_NumChunks; c++) { - pfn_t c_basepfn, c_endpfn; - - c_basepfn = (pfn_t)p2o->p2o_mchunks[c].Memc_StartAddress - >> (PAGESHIFT - BDA_PAGESHIFT); - c_endpfn = (pfn_t)p2o->p2o_mchunks[c].Memc_Size - >> (PAGESHIFT - BDA_PAGESHIFT); - c_endpfn += c_basepfn; - - if ((endpfn <= c_basepfn) || (basepfn >= c_endpfn)) - continue; - - c_basepfn = MAX(c_basepfn, basepfn); - c_endpfn = MIN(c_endpfn, endpfn); - ASSERT(c_basepfn <= c_endpfn); - - npages += c_endpfn - c_basepfn; - } - - return (npages); -} - -void -pda_mem_add_span(pda_handle_t ph, uint64_t basepa, uint64_t nbytes) -{ - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - int c, nchunks; - pfn_t a_pfn, a_npgs; - - ASSERT(p2o); - - nchunks = p2o->p2o_memtotal.Memt_NumChunks; - a_pfn = (pfn_t)(basepa >> BDA_PAGESHIFT); - a_npgs = (pfn_t)(nbytes >> BDA_PAGESHIFT); - - for (c = 0; c < nchunks; c++) { - int cend; - - if (a_pfn <= p2o->p2o_mchunks[c].Memc_StartAddress) { - for (cend = nchunks; cend > c; cend--) - p2o->p2o_mchunks[cend] = - p2o->p2o_mchunks[cend - 1]; - break; - } - } - p2o->p2o_mchunks[c].Memc_StartAddress = a_pfn; - p2o->p2o_mchunks[c].Memc_Size = a_npgs; - nchunks++; - - p2o->p2o_memtotal.Memt_NumChunks = nchunks; - p2o->p2o_memtotal.Memt_NumPages += a_npgs; - - p2o_mem_sort(p2o); - p2o_mem_coalesce(p2o); - p2o_update_checksum(p2o); -} - -void -pda_mem_del_span(pda_handle_t ph, uint64_t basepa, uint64_t nbytes) -{ - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - int c, o_nchunks, n_nchunks; - pfn_t d_pfn; - pgcnt_t d_npgs, npages; - MemChunk_t *mp, *endp; - - ASSERT(p2o); - - d_pfn = (pfn_t)(basepa >> BDA_PAGESHIFT); - d_npgs = (pgcnt_t)(nbytes >> BDA_PAGESHIFT); - n_nchunks = o_nchunks = p2o->p2o_memtotal.Memt_NumChunks; - endp = &(p2o->p2o_mchunks[o_nchunks]); - npages = 0; - - for (c = 0; c < o_nchunks; c++) { - uint_t p_pfn, p_npgs; - - p_pfn = p2o->p2o_mchunks[c].Memc_StartAddress; - p_npgs = p2o->p2o_mchunks[c].Memc_Size; - if (p_npgs == 0) - continue; - - if (((d_pfn + d_npgs) <= p_pfn) || - (d_pfn >= (p_pfn + p_npgs))) { - npages += p_npgs; - continue; - } - - if (d_pfn < p_pfn) { - if ((d_pfn + d_npgs) >= (p_pfn + p_npgs)) { - /* - * Entire chunk goes away. - */ - p_pfn = p_npgs = 0; - } else { - p_npgs -= d_pfn + d_npgs - p_pfn; - p_pfn = d_pfn + d_npgs; - } - } else if (d_pfn == p_pfn) { - if ((d_pfn + d_npgs) >= (p_pfn + p_npgs)) { - p_pfn = p_npgs = 0; - } else { - p_npgs -= d_npgs; - p_pfn += d_npgs; - } - } else { - if ((d_pfn + d_npgs) >= (p_pfn + p_npgs)) { - p_npgs = d_pfn - p_pfn; - npages += p_npgs; - } else { - /* - * Ugh, got to split a - * memchunk, we're going to - * need an extra one. It's - * gotten from the end. - */ - endp->Memc_StartAddress = d_pfn + d_npgs; - endp->Memc_Size = (p_pfn + p_npgs) - - (d_pfn + d_npgs); - npages += endp->Memc_Size; - endp++; - n_nchunks++; - p_npgs = d_pfn - p_pfn; - } - } - - p2o->p2o_mchunks[c].Memc_StartAddress = p_pfn; - p2o->p2o_mchunks[c].Memc_Size = p_npgs; - if (p_npgs == 0) - n_nchunks--; - npages += p_npgs; - } - p2o->p2o_memtotal.Memt_NumChunks = n_nchunks; - p2o->p2o_memtotal.Memt_NumPages = npages; - - /* - * There is a possibility we created holes in the memchunk list - * due to memchunks that went away. Before we can sort and - * coalesce we need to "pull up" the end of the memchunk list - * and get rid of any holes. - * endp = points to the last empty memchunk entry. - */ - for (mp = &(p2o->p2o_mchunks[0]); mp < endp; mp++) { - register MemChunk_t *mmp; - - if (mp->Memc_Size) - continue; - - for (mmp = mp; mmp < endp; mmp++) - *mmp = *(mmp + 1); - mp--; - endp--; - } - ASSERT(endp == &(p2o->p2o_mchunks[n_nchunks])); - - p2o_mem_sort(p2o); - p2o_mem_coalesce(p2o); - p2o_update_checksum(p2o); -} - -/* - * Synchonize all memory attributes (currently just MC ADRs [aka ASR]) - * with PDA representative values for the given board. A board value - * of (-1) indicates all boards. - */ -/*ARGSUSED*/ -void -pda_mem_sync(pda_handle_t ph, int board, int unit) -{ - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - register int b; - - for (b = 0; b < MAX_SYSBDS; b++) { - if ((board != -1) && (board != b)) - continue; - - if (pda_board_present(ph, b)) { - uint64_t masr; - uint_t masr_value; - - masr = STARFIRE_MC_ASR_ADDR_BOARD(b); - masr_value = ldphysio(masr); - - p2o->p2o_bdminfo[b].bmda_adr = masr_value; - } - - if (board == b) - break; - } - - p2o_update_checksum(p2o); -} - -void -pda_get_busmask(pda_handle_t ph, short *amask, short *dmask) -{ - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - - if (amask) - *amask = p2o ? p2o->p2o_abus_mask : 0; - - if (dmask) - *dmask = p2o ? p2o->p2o_dbus_mask : 0; -} - -int -pda_is_valid(pda_handle_t ph) -{ - post2obp_info_t *p2o = ((p2o_info_t *)ph)->p2o_ptr; - uint_t csum; - - if (p2o == NULL) - return (0); - - csum = p2o_calc_checksum(p2o); - - return (csum == p2o->p2o_csum); -} - -/* - * Post2obp support functions below here. Internal to PDA module. - * - * p2o_update_checksum - * - * Calculate checksum for post2obp structure and insert it so - * when POST reads it it'll be happy. - */ -static void -p2o_update_checksum(post2obp_info_t *p2o) -{ - uint_t new_csum; - - ASSERT(p2o); - - new_csum = p2o_calc_checksum(p2o); - p2o->p2o_csum = new_csum; -} - -static uint_t -p2o_calc_checksum(post2obp_info_t *p2o) -{ - int i, nchunks; - uint_t *csumptr; - uint_t p2o_size; - uint_t csum, o_csum; - - ASSERT(p2o != NULL); - - nchunks = p2o->p2o_memtotal.Memt_NumChunks; - p2o_size = sizeof (post2obp_info_t) - + ((nchunks - VAR_ARRAY_LEN) * sizeof (MemChunk_t)); - p2o_size /= sizeof (uint_t); - - o_csum = p2o->p2o_csum; - p2o->p2o_csum = 0; - csum = 0; - for (i = 0, csumptr = (uint_t *)p2o; i < p2o_size; i++) - csum += *csumptr++; - p2o->p2o_csum = o_csum; - - return (-csum); -} - -/* - * Sort the mchunk list in ascending order based on the - * Memc_StartAddress field. - * - * disclosure: This is based on the qsort() library routine. - */ -static void -p2o_mem_sort(post2obp_info_t *p2o) -{ - MemChunk_t *base; - int nchunks; - uint_t c1, c2; - char *min, *max; - register char c, *i, *j, *lo, *hi; - - ASSERT(p2o != NULL); - - nchunks = p2o->p2o_memtotal.Memt_NumChunks; - base = &p2o->p2o_mchunks[0]; - - /* ala qsort() */ - max = (char *)base + nchunks * sizeof (MemChunk_t); - hi = max; - for (j = lo = (char *)base; (lo += sizeof (MemChunk_t)) < hi; ) { - c1 = ((MemChunk_t *)j)->Memc_StartAddress; - c2 = ((MemChunk_t *)lo)->Memc_StartAddress; - if (c1 > c2) - j = lo; - } - if (j != (char *)base) { - for (i = (char *)base, - hi = (char *)base + sizeof (MemChunk_t); - /* CSTYLED */ - i < hi;) { - c = *j; - *j++ = *i; - *i++ = c; - } - } - for (min = (char *)base; - /* CSTYLED */ - (hi = min += sizeof (MemChunk_t)) < max;) { - do { - hi -= sizeof (MemChunk_t); - c1 = ((MemChunk_t *)hi)->Memc_StartAddress; - c2 = ((MemChunk_t *)min)->Memc_StartAddress; - } while (c1 > c2); - if ((hi += sizeof (MemChunk_t)) != min) { - for (lo = min + sizeof (MemChunk_t); - /* CSTYLED */ - --lo >= min;) { - c = *lo; - for (i = j = lo; - (j -= sizeof (MemChunk_t)) >= hi; - i = j) { - *i = *j; - } - *i = c; - } - } - } -} - -static void -p2o_mem_coalesce(post2obp_info_t *p2o) -{ - MemChunk_t *mc; - int nchunks, new_nchunks; - uint_t addr, size, naddr, nsize; - uint_t npages; - register int i, cp, ncp; - - ASSERT(p2o != NULL); - - nchunks = new_nchunks = p2o->p2o_memtotal.Memt_NumChunks; - mc = &p2o->p2o_mchunks[0]; - - for (cp = i = 0; i < (nchunks-1); i++, cp = ncp) { - ncp = cp + 1; - addr = mc[cp].Memc_StartAddress; - size = mc[cp].Memc_Size; - naddr = mc[ncp].Memc_StartAddress; - nsize = mc[ncp].Memc_Size; - - if ((addr + size) >= naddr) { - uint_t overlap; - - overlap = addr + size - naddr; - /* - * if (nsize < overlap) then - * next entry fits within the current - * entry so no need to update size. - */ - if (nsize >= overlap) { - size += nsize - overlap; - mc[cp].Memc_Size = size; - } - bcopy((char *)&mc[ncp+1], - (char *)&mc[ncp], - (nchunks - ncp - 1) * sizeof (MemChunk_t)); - ncp = cp; - new_nchunks--; - } - } - - npages = 0; - for (i = 0; i < new_nchunks; i++) - npages += p2o->p2o_mchunks[i].Memc_Size; - - p2o->p2o_memtotal.Memt_NumChunks = new_nchunks; - p2o->p2o_memtotal.Memt_NumPages = npages; -} - -/* - * Mapin the the cpu's post2obp structure. - */ -static post2obp_info_t * -cpu_p2o_mapin(int cpuid) -{ - uint64_t cpu_p2o_physaddr; - uint32_t cpu_p2o_offset; - caddr_t cvaddr; - uint_t num_pages; - pfn_t pfn; - - ASSERT(cpu_sgnblkp[cpuid] != NULL); - /* - * Construct the physical base address of the bbsram - * in PSI space associated with this cpu in question. - */ - cpu_p2o_offset = (uint32_t)cpu_sgnblkp[cpuid]->sigb_postconfig; - if (cpu_p2o_offset == 0) { - cmn_err(CE_WARN, - "cpu_p2o_mapin:%d: sigb_postconfig == NULL\n", - cpuid); - return (NULL); - } - cpu_p2o_physaddr = (STARFIRE_UPAID2UPS(cpuid) | STARFIRE_PSI_BASE) + - (uint64_t)cpu_p2o_offset; - cpu_p2o_offset = (uint32_t)(cpu_p2o_physaddr & MMU_PAGEOFFSET); - cpu_p2o_physaddr -= (uint64_t)cpu_p2o_offset; - - /* - * cpu_p2o_physaddr = Beginning of page containing p2o. - * cpu_p2o_offset = Offset within page where p2o starts. - */ - - pfn = (pfn_t)(cpu_p2o_physaddr >> MMU_PAGESHIFT); - - num_pages = mmu_btopr(cpu_p2o_offset + sizeof (post2obp_info_t)); - - /* - * Map in the post2obp structure. - */ - cvaddr = vmem_alloc(heap_arena, ptob(num_pages), VM_SLEEP); - - hat_devload(kas.a_hat, cvaddr, ptob(num_pages), - pfn, PROT_READ | PROT_WRITE, HAT_LOAD_LOCK); - - return ((post2obp_info_t *)(cvaddr + (ulong_t)cpu_p2o_offset)); -} - -static void -cpu_p2o_mapout(int cpuid, post2obp_info_t *p2o) -{ - ulong_t cvaddr, num_pages; - uint32_t cpu_p2o_offset; - - ASSERT(cpu_sgnblkp[cpuid] != NULL); - - cpu_p2o_offset = (uint32_t)cpu_sgnblkp[cpuid]->sigb_postconfig; - if (cpu_p2o_offset == 0) { - cmn_err(CE_WARN, - "cpu_p2o_mapout:%d: sigb_postconfig == NULL\n", - cpuid); - return; - } - - cpu_p2o_offset = (uint32_t)(((STARFIRE_UPAID2UPS(cpuid) | - STARFIRE_PSI_BASE) + - (uint64_t)cpu_p2o_offset) & - MMU_PAGEOFFSET); - - num_pages = mmu_btopr(cpu_p2o_offset + sizeof (post2obp_info_t)); - - cvaddr = (ulong_t)p2o - cpu_p2o_offset; - if (cvaddr & MMU_PAGEOFFSET) { - cmn_err(CE_WARN, - "cpu_p2o_mapout:%d: cvaddr (0x%x) not on page " - "boundary\n", - cpuid, (uint_t)cvaddr); - return; - } - - hat_unload(kas.a_hat, (caddr_t)cvaddr, ptob(num_pages), - HAT_UNLOAD_UNLOCK); - vmem_free(heap_arena, (caddr_t)cvaddr, ptob(num_pages)); -} diff --git a/usr/src/uts/sun4u/starfire/os/starfire.c b/usr/src/uts/sun4u/starfire/os/starfire.c deleted file mode 100644 index 2dd0688f4a..0000000000 --- a/usr/src/uts/sun4u/starfire/os/starfire.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sysmacros.h> -#include <sys/sunddi.h> -#include <sys/modctl.h> -#include <sys/promif.h> -#include <sys/machparam.h> -#include <sys/kobj.h> -#include <sys/mem_cage.h> -#include <sys/starfire.h> - -#include <sys/platform_module.h> -#include <sys/errno.h> -#include <vm/page.h> -#include <vm/hat_sfmmu.h> -#include <sys/memnode.h> -#include <vm/vm_dep.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/cpu_sgn.h> -#include <sys/kdi_impl.h> -#include <sys/clock_impl.h> - -extern cpu_sgnblk_t *cpu_sgnblkp[]; - -/* Preallocation of spare tsb's for DR - none for now */ -int starfire_tsb_spares = STARFIRE_MAX_BOARDS << 1; - -/* Set the maximum number of boards... for DR */ -int starfire_boards = STARFIRE_MAX_BOARDS; - -/* Maximum number of cpus per board... for DR */ -int starfire_cpu_per_board = 4; - -/* Maximum number of mem-units per board... for DR */ -int starfire_mem_per_board = 1; - -/* Maximum number of io-units (buses) per board... for DR */ -int starfire_io_per_board = 2; - -/* Preferred minimum cage size (expressed in pages)... for DR */ -pgcnt_t starfire_startup_cage_size = 0; - -void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t); - -int -set_platform_max_ncpus(void) -{ - starfire_boards = MIN(starfire_boards, STARFIRE_MAX_BOARDS); - - if (starfire_boards < 1) - starfire_boards = 1; - - return (starfire_boards * starfire_cpu_per_board); -} - -void -startup_platform(void) -{ -} - -int -set_platform_tsb_spares() -{ - return (MIN(starfire_tsb_spares, MAX_UPA)); -} - -void -set_platform_defaults(void) -{ - extern char *tod_module_name; - extern int ts_dispatch_extended; - extern void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int); - - uint32_t revlevel; - char buf[20]; - -#ifdef DEBUG - ce_verbose_memory = 2; - ce_verbose_other = 2; -#endif - - /* - * Check to see if we have the right firmware - * We simply do a prom_test to see if - * "SUNW,UE10000-prom-version" interface exist. - */ - if (prom_test("SUNW,UE10000-prom-version") != 0) { - halt("Firmware upgrade is required to boot this OS!"); - } else { - /* - * Versions 5 to 50 and 150 or above can support this OS - */ - (void) sprintf(buf, "cpu-prom-version swap l!"); - prom_interpret(buf, (uintptr_t)&revlevel, 0, 0, 0, 0); - if ((revlevel < 5) || ((revlevel > 50) && (revlevel < 150))) - halt("Firmware upgrade is required to boot this OS!"); - } - - /* Set the CPU signature function pointer */ - cpu_sgn_func = cpu_sgn_update; - - /* Set appropriate tod module for starfire */ - ASSERT(tod_module_name == NULL); - tod_module_name = "todstarfire"; - - /* - * Use the alternate TS dispatch table, which is better - * tuned for large servers. - */ - if (ts_dispatch_extended == -1) /* use platform default */ - ts_dispatch_extended = 1; -} - -#ifdef DEBUG -pgcnt_t starfire_cage_size_limit; -#endif - -void -set_platform_cage_params(void) -{ - extern pgcnt_t total_pages; - extern struct memlist *phys_avail; - - if (kernel_cage_enable) { - pgcnt_t preferred_cage_size; - - preferred_cage_size = - MAX(starfire_startup_cage_size, total_pages / 256); - -#ifdef DEBUG - if (starfire_cage_size_limit) - preferred_cage_size = starfire_cage_size_limit; -#endif - /* - * Note: we are assuming that post has load the - * whole show in to the high end of memory. Having - * taken this leap, we copy the whole of phys_avail - * the glist and arrange for the cage to grow - * downward (descending pfns). - */ - kcage_range_init(phys_avail, KCAGE_DOWN, preferred_cage_size); - } - - if (kcage_on) - cmn_err(CE_NOTE, "!DR Kernel Cage is ENABLED"); - else - cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED"); -} - -void -load_platform_drivers(void) -{ - /* load the NGDR driver */ - if (i_ddi_attach_pseudo_node("ngdr") == NULL) { - cmn_err(CE_WARN, "ngdr failed to load"); - } -} - -/* - * Starfire does not support power control of CPUs from the OS. - */ -/*ARGSUSED*/ -int -plat_cpu_poweron(struct cpu *cp) -{ - int (*starfire_cpu_poweron)(struct cpu *) = NULL; - - starfire_cpu_poweron = - (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0); - - if (starfire_cpu_poweron == NULL) - return (ENOTSUP); - else - return ((starfire_cpu_poweron)(cp)); -} - -/*ARGSUSED*/ -int -plat_cpu_poweroff(struct cpu *cp) -{ - int (*starfire_cpu_poweroff)(struct cpu *) = NULL; - - starfire_cpu_poweroff = - (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0); - - if (starfire_cpu_poweroff == NULL) - return (ENOTSUP); - else - return ((starfire_cpu_poweroff)(cp)); -} - -void -plat_dmv_params(uint_t *hwint, uint_t *swint) -{ - *hwint = STARFIRE_DMV_HWINT; - *swint = 0; -} - -/* - * The following our currently private to Starfire DR - */ -int -plat_max_boards() -{ - return (starfire_boards); -} - -int -plat_max_cpu_units_per_board() -{ - return (starfire_cpu_per_board); -} - -int -plat_max_mem_units_per_board() -{ - return (starfire_mem_per_board); -} - -int -plat_max_io_units_per_board() -{ - return (starfire_io_per_board); -} - - -/* - * This index is used to associate a given pfn to a place on the freelist. - * This results in dispersing pfn assignment over all the boards in the - * system. - * Choose the index randomly to prevent clustering pages of different - * colors on the same board. - */ -static uint_t random_idx(int ubound); - -#define PFN_2_LBN(pfn) (((pfn) >> (STARFIRE_MC_MEMBOARD_SHIFT - PAGESHIFT)) % \ - STARFIRE_MAX_BOARDS) - -void -plat_freelist_process(int mnode) -{ - page_t *page, **freelist; - page_t *bdlist[STARFIRE_MAX_BOARDS]; - page_t **sortlist[STARFIRE_MAX_BOARDS]; - uint32_t idx, idy, size, color, max_color, lbn; - uint32_t bd_flags, bd_cnt, result, bds; - kmutex_t *pcm; - int mtype; - - /* for each page size */ - for (mtype = 0; mtype < MAX_MEM_TYPES; mtype++) { - for (size = 0; size < mmu_page_sizes; size++) { - - /* - * Compute the maximum # of phys colors based on - * page size. - */ - max_color = page_get_pagecolors(size); - - /* for each color */ - for (color = 0; color < max_color; color++) { - - bd_cnt = 0; - bd_flags = 0; - for (idx = 0; idx < STARFIRE_MAX_BOARDS; - idx++) { - bdlist[idx] = NULL; - sortlist[idx] = NULL; - } - - /* find freelist */ - freelist = &PAGE_FREELISTS(mnode, size, - color, mtype); - - if (*freelist == NULL) - continue; - - /* acquire locks */ - pcm = PC_BIN_MUTEX(mnode, color, PG_FREE_LIST); - mutex_enter(pcm); - - /* - * read freelist & sort pages by logical - * board number - */ - /* grab pages till last one. */ - while (*freelist) { - page = *freelist; - result = page_trylock(page, SE_EXCL); - - ASSERT(result); - - /* Delete from freelist */ - if (size != 0) { - page_vpsub(freelist, page); - } else { - mach_page_sub(freelist, page); - } - - /* detect the lbn */ - lbn = PFN_2_LBN(page->p_pagenum); - - /* add to bdlist[lbn] */ - if (size != 0) { - page_vpadd(&bdlist[lbn], page); - } else { - mach_page_add(&bdlist[lbn], - page); - } - - /* if lbn new */ - if ((bd_flags & (1 << lbn)) == 0) { - bd_flags |= (1 << lbn); - bd_cnt++; - } - page_unlock(page); - } - - /* - * Make the sortlist so - * bd_cnt choices show up - */ - bds = 0; - for (idx = 0; idx < STARFIRE_MAX_BOARDS; - idx++) { - if (bdlist[idx]) - sortlist[bds++] = &bdlist[idx]; - } - - /* - * Set random start. - */ - (void) random_idx(-color); - - /* - * now rebuild the freelist by shuffling - * pages from bd lists - */ - while (bd_cnt) { - - /* - * get "random" index between 0 & - * bd_cnt - */ - - ASSERT(bd_cnt && - (bd_cnt < STARFIRE_MAX_BOARDS+1)); - - idx = random_idx(bd_cnt); - - page = *sortlist[idx]; - result = page_trylock(page, SE_EXCL); - - ASSERT(result); - - /* Delete from sort_list */ - /* & Append to freelist */ - /* Big pages use vp_add - 8k don't */ - if (size != 0) { - page_vpsub(sortlist[idx], page); - page_vpadd(freelist, page); - } else { - mach_page_sub(sortlist[idx], - page); - mach_page_add(freelist, page); - } - - /* needed for indexing tmp lists */ - lbn = PFN_2_LBN(page->p_pagenum); - - /* - * if this was the last page on this - * list? - */ - if (*sortlist[idx] == NULL) { - - /* have to find brd list */ - - /* idx is lbn? -- No! */ - /* sortlist, brdlist */ - /* have diff indexs */ - bd_flags &= ~(1 << lbn); - --bd_cnt; - - /* - * redo the sortlist so only - * bd_cnt choices show up - */ - bds = 0; - for (idy = 0; - idy < STARFIRE_MAX_BOARDS; - idy++) { - if (bdlist[idy]) { - sortlist[bds++] - /* CSTYLED */ - = &bdlist[idy]; - } - } - } - page_unlock(page); - } - mutex_exit(pcm); - } - } - } -} - -/* - * If ubound > 0, will return an int between 0 & ubound - * If ubound < 0, will set "random seed" - */ -static uint_t -random_idx(int ubound) -{ - static int idx = 0; - - if (ubound > 0) { - idx = (idx + 1) % ubound; - return (idx); - } - idx = -ubound; - return (0); -} - -/* - * No platform drivers on this platform - */ -char *platform_module_list[] = { - (char *)0 -}; - -/*ARGSUSED*/ -void -plat_tod_fault(enum tod_fault_type tod_bad) -{ -} - -/* - * Update signature block and the signature ring buffer of a given cpu_id. - */ -void -cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid) -{ - uchar_t idx; - cpu_sgnblk_t *cpu_sgnblkptr; - - /* - * cpuid == -1 indicates that the operation applies to all cpus. - */ - if (cpuid < 0) { - sgn_update_all_cpus(sgn, state, sub_state); - return; - } - - if (cpu_sgnblkp[cpuid] == NULL) - return; - - cpu_sgnblkptr = cpu_sgnblkp[cpuid]; - - /* - * Map new generic cpu states to older Starfire states. - */ - switch (state) { - case SIGST_OFFLINE: - state = SIGBST_OFFLINE; - break; - case SIGST_RESUME_INPROGRESS: - state = SIGBST_RESUME_INPROGRESS; - break; - case SIGST_QUIESCE_INPROGRESS: - state = SIGBST_QUIESCE_INPROGRESS; - break; - case SIGST_QUIESCED: - state = SIGBST_QUIESCED; - break; - case SIGST_EXIT: - switch (sub_state) { - case SIGSUBST_DEBUG: - state = SIGBST_RUN; - sub_state = EXIT_NULL; - break; - case SIGSUBST_PANIC_CONT: - state = SIGBST_RUN; - sub_state = EXIT_PANIC2; - break; - case SIGSUBST_DUMP: - state = SIGBST_EXIT; - sub_state = EXIT_PANIC2; - break; - default: - break; - } - break; - default: - break; - } - - cpu_sgnblkptr->sigb_signature.state_t.sig = sgn; - cpu_sgnblkptr->sigb_signature.state_t.state = state; - cpu_sgnblkptr->sigb_signature.state_t.sub_state = sub_state; - - /* Update the ring buffer */ - idx = cpu_sgnblkptr->sigb_ringbuf.wr_ptr; - cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sig = sgn; - cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.state = state; - cpu_sgnblkptr->sigb_ringbuf.ringbuf[idx].state_t.sub_state = sub_state; - cpu_sgnblkptr->sigb_ringbuf.wr_ptr += 1; - cpu_sgnblkptr->sigb_ringbuf.wr_ptr &= RB_IDX_MASK; -} - -/* - * Update signature block and the signature ring buffer of all CPUs. - */ -void -sgn_update_all_cpus(ushort_t sgn, uchar_t state, uchar_t sub_state) -{ - int i = 0; - uchar_t cpu_state; - uchar_t cpu_sub_state; - - for (i = 0; i < NCPU; i++) { - cpu_sgnblk_t *sblkp; - - sblkp = cpu_sgnblkp[i]; - cpu_sub_state = sub_state; - - if ((sblkp != NULL) && (cpu[i] != NULL && (cpu[i]->cpu_flags & - (CPU_EXISTS|CPU_QUIESCED)))) { - - if (sub_state == EXIT_REBOOT) { - cpu_sub_state = - sblkp->sigb_signature.state_t.sub_state; - - if ((cpu_sub_state == EXIT_PANIC1) || - (cpu_sub_state == EXIT_PANIC2)) - cpu_sub_state = EXIT_PANIC_REBOOT; - else - cpu_sub_state = EXIT_REBOOT; - } - - /* - * If we get here from an OBP sync after watchdog, - * we need to retain the watchdog sync state so that - * hostmon knows what's going on. So if we're in - * watchdog we don't update the state. - */ - - cpu_state = sblkp->sigb_signature.state_t.state; - if (cpu_state == SIGBST_WATCHDOG_SYNC) - cpu_sgn_update(sgn, SIGBST_WATCHDOG_SYNC, - cpu_sub_state, i); - else if (cpu_state == SIGBST_REDMODE_SYNC) - cpu_sgn_update(sgn, SIGBST_REDMODE_SYNC, - cpu_sub_state, i); - else - cpu_sgn_update(sgn, state, cpu_sub_state, i); - } - } -} - -int -cpu_sgn_exists(int cpuid) -{ - return (cpu_sgnblkp[cpuid] != NULL); -} - -ushort_t -get_cpu_sgn(int cpuid) -{ - if (cpu_sgnblkp[cpuid] == NULL) - return ((ushort_t)-1); - - return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.sig); -} - -uchar_t -get_cpu_sgn_state(int cpuid) -{ - if (cpu_sgnblkp[cpuid] == NULL) - return ((uchar_t)-1); - - return (cpu_sgnblkp[cpuid]->sigb_signature.state_t.state); -} - -/* - * KDI functions - used by the in-situ kernel debugger (kmdb) to perform - * platform-specific operations. These functions execute when the world is - * stopped, and as such cannot make any blocking calls, hold locks, etc. - * promif functions are a special case, and may be used. - */ - -static void -starfire_system_claim(void) -{ - lbolt_debug_entry(); - - prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0); -} - -static void -starfire_system_release(void) -{ - prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0); - - lbolt_debug_return(); -} - -void -plat_kdi_init(kdi_t *kdi) -{ - kdi->pkdi_system_claim = starfire_system_claim; - kdi->pkdi_system_release = starfire_system_release; -} diff --git a/usr/src/uts/sun4u/starfire/pcipsy/Makefile b/usr/src/uts/sun4u/starfire/pcipsy/Makefile deleted file mode 100644 index 97bb94d9a6..0000000000 --- a/usr/src/uts/sun4u/starfire/pcipsy/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# uts/sun4u/starfire/pcipsy/Makefile -# -# This makefile drives the production of the PCI driver kernel module. -# -# sun4u implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = pcipsy -OBJECTS = $(PSYCHO_PCI_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(PSYCHO_PCI_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-uninitialized -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-unused-function - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/platmod/Makefile b/usr/src/uts/sun4u/starfire/platmod/Makefile deleted file mode 100644 index 026493c4fb..0000000000 --- a/usr/src/uts/sun4u/starfire/platmod/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -# -# This makefile drives the production of the sun4u starfire platform -# module. -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. -# -# Define the module and object file sets. -# -MODULE = platmod -OBJECTS = $(STARFIRE_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(STARFIRE_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_MISC_DIR)/$(MODULE) -PLAT_DIR = . - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Override defaults -# -CLEANFILES += $(PLATLIB) - -# -# Define targets -# -ALL_TARGET = $(PLATLIB) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -$(PLATLIB): $(BINARY) - $(BUILD.SO) $(BINARY) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/rootnex/Makefile b/usr/src/uts/sun4u/starfire/rootnex/Makefile deleted file mode 100644 index 191a61016c..0000000000 --- a/usr/src/uts/sun4u/starfire/rootnex/Makefile +++ /dev/null @@ -1,97 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the rootnex driver -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = rootnex -OBJECTS = $(ROOTNEX_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(ROOTNEX_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Override defaults to build a unique, local modstubs.o. -# -MODSTUBS_DIR = . -$(MODSTUBS_O) := AS_CPPFLAGS += -DROOTNEX_MODULE - -CLEANFILES += $(MODSTUBS_O) - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-uninitialized -CERRWARN += -_gcc=-Wno-switch - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/sbus/Makefile b/usr/src/uts/sun4u/starfire/sbus/Makefile deleted file mode 100644 index 03c6d28bf4..0000000000 --- a/usr/src/uts/sun4u/starfire/sbus/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# uts/sun4u/starfire/sbus/Makefile -# -# This makefile drives the production of the SBus driver kernel module, -# the iommu nexus, and the obio nexus (which really is sbus on sun5). -# -# starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = sbus -OBJECTS = $(SYSIO_SBUS_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(SYSIO_SBUS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# Turn this on once compiler understands v9 in it's backend -#INLINES += $(UTSBASE)/sun4u/io/iommu.il - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-type-limits -CERRWARN += -_gcc=-Wno-uninitialized - -# -# Turn on doubleword alignment for 64 bit registers -# -CFLAGS += -dalign - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/spitfire/Makefile b/usr/src/uts/sun4u/starfire/spitfire/Makefile deleted file mode 100644 index 9db750b1cd..0000000000 --- a/usr/src/uts/sun4u/starfire/spitfire/Makefile +++ /dev/null @@ -1,109 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the sun4u UltraSPARC driver module. -# -# sun4u/starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -MODULE = SUNW,UltraSPARC-II -OBJECTS = $(SPITFIRE_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(SPITFIRE_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_STARFIRE_CPU_DIR)/$(MODULE) - -CPU_DIR = . -HERE = ../spitfire - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Override defaults -# -CLEANFILES += $(CPULIB) $(SYM_MOD) - -# -# Define targets -# -ALL_TARGET = $(SYM_MOD) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = def $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-uninitialized - -CPPFLAGS += -DCPU_MODULE -DSPITFIRE -AS_CPPFLAGS += -DCPU_MODULE -DSPITFIRE - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -$(CPULIB): $(BINARY) - $(BUILD.SO) $(BINARY) - -$(SYM_MOD): $(UNIX_O) $(CPULIB) - @echo "resolving symbols against unix.o" - @(cd $(UNIX_DIR); pwd; \ - CPU_DIR=$(HERE) SYM_MOD=$(HERE)/$(SYM_MOD) $(MAKE) symcheck) - -$(ROOTSOFTLINKS): $(ROOTMODULE) - $(RM) $@; $(SYMLINK) $(MODULE) $@ - -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/sys/Makefile b/usr/src/uts/sun4u/starfire/sys/Makefile deleted file mode 100644 index 00f306b5c3..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -UTSBASE = ../../.. - -# -# include global definitions -# -include ../Makefile.starfire - -# -# Override defaults. -# -FILEMODE = 644 - -HDRS= cvc.h - -STARHDRS= $(UTSBASE)/sun4u/ngdr/sys/dr.h \ - $(UTSBASE)/sun4u/ngdr/sys/dr_util.h - -ROOTHDRS= $(HDRS:%=$(USR_STARFIRE_ISYS_DIR)/%) - -ROOTDIR= $(ROOT)/usr/share/src -ROOTDIRS= $(ROOTDIR)/uts $(ROOTDIR)/uts/$(PLATFORM) - -CHECKHDRS= $(HDRS:%.h=%.check) \ - $(STARHDRS:%.h=%.check) - -.KEEP_STATE: - -.PARALLEL: $(CHECKHDRS) $(ROOTHDRS) - -install_h: $(ROOTDIRS) .WAIT $(ROOTHDRS) $(ROOTLINK) - -check: $(CHECKHDRS) - -# -# install rules -# -$(USR_STARFIRE_ISYS_DIR)/%: % $(USR_STARFIRE_ISYS_DIR) - $(INS.file) - -$(ROOTDIRS): - $(INS.dir) - -FRC: - -include ../Makefile.targ diff --git a/usr/src/uts/sun4u/starfire/sys/cpu_sgn.h b/usr/src/uts/sun4u/starfire/sys/cpu_sgn.h deleted file mode 100644 index 8c14d34f3b..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/cpu_sgn.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _CPU_SGN_H -#define _CPU_SGN_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ASM -#include <sys/types.h> -#include <sys/cpuvar.h> -#endif /* _ASM */ - -/* - * BBSRAM virtual address - 64 bits max. - */ -typedef uint64_t vaddr_t; - -/* - * Special type for BBSRAM offsets (rather than pointers). - * This must be a 32 bit value - */ -typedef uint32_t bboff_t; - -/* - * As long as each component of the revision is less than - * 256, this trick will work. So we check for that and generate a - * syntax error if the SID is out of range. - */ -#define SIGB_MBOX_SIZE 64 -/* reserved space - rounds size of sigblock_t to 512 */ -#define SIGB_RESV 16 - -#define BASE_ADDR_T_OFFSET 0xFE0 /* BBSRAM base_addr_t offset */ - -#define CVC_OUT_SIZ 1024 /* cvc output buffer size */ -#define CVC_IN_SIZ 256 /* cvc input buffer size */ - -/* make sure the assembler doesn't see the C code */ -#ifndef _ASM - -/* - * The reserved hardware interrupt 7F is used as a pointer structure - * to the two processors' signature blocks in bbsram. Each trap entry - * is 32 bytes, so this structure is always present at bbsram offset - * 0xFE0. - * Over time, we may discover other items that need pointers, that don't - * logically fit in the sigblocks themselves. This structure declares - * the global use of these 8 words. - * The spare_x words are reserved in case a design change calls for - * using 64-bit virtual addresses instead of offsets. This is - * considered unlikely. - * - * The offsets and this structure are normally created by POST when it - * initially creates the sigblocks. Subsequent programs may move the - * sigblocks in bbsram as they see fit, as long as this structure is changed - * to reflect the new location. - */ - -typedef struct { - bboff_t sigblk_offset_0; /* BBSRAM sig block 0 offset */ - uint32_t spare_0; /* spare word just in case */ - bboff_t sigblk_offset_1; /* BBSRAM sig block 1 offset */ - uint32_t spare_1; /* another just in case */ - uint32_t pad[4]; /* trap is 8 32-bit words long */ -} base_addr_t; - - -/* - * The following are used in the flag field of the mailbox structure. - * They are used to synchronize access with the mailbox between the - * SSP and Host, and indicate direction of the given message. - */ -#define SIGB_MBOX_EMPTY 0 -#define SIGB_MBOX_BUSY 1 -#define HOST_TO_CBS 2 -#define CBS_TO_HOST 3 - -/* for sigblk polling */ -#define SIGB_INTR_OFF 0x00 -#define SIGB_INTR_SEND 0xFF - -typedef short mboxflag_t; - -/* - * BE CAREFUL with modifications. To optimize transfers on the - * bootbus between the kernel and mailbox, try to make sure the data - * field falls on a 16 byte boundary. - */ -typedef struct { -/* 0 */ short intr; -/* 2 */ mboxflag_t flag; -/* 4 */ int32_t len; -/* 8 */ uint32_t cmd; -/* c */ char data[SIGB_MBOX_SIZE]; -} sigbmbox_t; /* sizeof = 76 (0x4c) = 19X */ - -typedef struct { - uchar_t cvc_output_buf[CVC_OUT_SIZ]; - uchar_t cvc_input_buf[CVC_IN_SIZ]; - uchar_t cvc_obp_input_flag; /* !=0 -> OBP wants CVC input */ -} sigb_cvc_t; - -/* - * Every CPU signature, state, or substate transition is captured - * in the ring buffer. OS or OBP will be the writer of the ring buffer - * and control board executive (via JTAG) will be the sole reader. Because of - * space limitation in the BBSRAM, the ring buffer can only be 64 entries big. - * A ring buffer is necessary because of the speed difference between the - * reader and writer, and to prevent race condition. - * - * The ring buffer structure contains two pointers, one for reading and - * one for writing, and the buffer itself. The last 6 bits in each of the - * pointer identify an entry in the buffer. The read pointer represents - * the next entry the reader should read. The write pointer represents the - * next entry the writer is going to write. For the reader, the ring buffer - * contains un-read entries if the read and write pointers are different. - * - * In most situations, the reader should be able to keep up with the - * writer. However, in the case where the writer is transitioning - * rapidly, the reader may not be able to keep up and causes an overflow. - * When an overflow happens, instead of suspending the writer, the - * writer continues to write. - * - * The first transition that causes an overflow has 2 consequences - * because of this continuous write action: - * 1. The ring buffer is flushed, all previous transitions history are lost. - * - * Flushing the ring buffer is acceptable since the reader is not - * able to keep up with rapid transitions, it is better off to start - * from the current transition than trying to catch up. - * - * 2. The new transition is recorded in the ring buffer. However, bcecause of - * the way the write pointer is updated, both the read and write pointers - * will be identical which makes the reader thinks there is no transition to - * read. - * - * Even though the reader does not see the most current signature/state in the - * ring buffer, it can be found in the signature block data structure. - * The reader can do a read in the signature block to obtain the current - * signature/block if the read/write pointers indicate the buffer is empty. - * The problem will go away once the writer starts writing again. - * - * Initial condition: - * rd_ptr = 0 - * wr_ptr = 0 - * - * To write a signature into the ring buffer, the steps are: - * 1. write signature into ringbuf[wr_ptr] - * 2. increment wr_ptr by 1 modulo SIGB_RB_SIZ using RB_IDX_MASK - * - * Note: the writer always writes to the ring buffer and the signature - * field in the signature block data structure. - * - * To read a signature from the ring buffer, the steps are: - * 1. compare rd_ptr and wr_ptr - * 2. if they are not equal then - * read signature ringbuf[rd_ptr] - * increment rd_ptr by 1 modulo SIGB_RB_SIZ using RB_IDX_MASK - * save a copy of the signature locally - * return the signature - * 3. else - * read signature from the signature block data structure - * if signature is not the same as the last signature then - * return the signature - * - */ - -#define SIGB_RB_SIZ 64 /* ring buffer size */ -#define RB_IDX_MASK 0x3f /* mask to determine read/write index */ - -typedef struct { -/* 0 */ uchar_t rd_ptr; /* entry to read */ -/* 1 */ uchar_t wr_ptr; /* next entry to write */ -/* 4 */ sig_state_t ringbuf[SIGB_RB_SIZ]; -} sigb_ringbuf_t; /* sizeof = 260 (0x104) = 65X */ - -typedef struct cpu_sgnblk { -/* 0 */ uint32_t sigb_magic; /* SIGBLOCK_MAGIC */ -/* 4 */ uint32_t sigb_version; /* changes with each SID */ -/* 8 */ uint32_t sigb_flags; /* struct sigblock status */ -/* c */ uint32_t sigb_heartbeat; /* prog's heartbeat */ - -/* 10 */ uint32_t sigb_leds; /* Software LED */ -/* 14 */ sig_state_t sigb_signature; /* Current signature & state */ - - /* - * sigb_ringbuf captures the last SIGB_RB_SIZ signature/state - * transitions. - */ -/* 18 */ sigb_ringbuf_t sigb_ringbuf; - - /* - * sigb_host_mbox is intended for msgs targeted for the Host and - * follows the protocol: - * SSP -> [cmd] -> Host -> [resp] -> SSP. - */ -/* 11c */ sigbmbox_t sigb_host_mbox; - -/* 168 */ char sigb_idn[sizeof (sigbmbox_t)]; - -/* 1b4 */ bboff_t sigb_obp_mbox; /* OBP/DHLP mailbox. */ - -/* 1b8 */ bboff_t sigb_postconfig; /* config info from POST */ - -/* 1bc */ uint32_t sigb_post; /* POST opaque */ - -/* 1c0 */ bboff_t sigb_slavep; /* Slave startup block offset */ - -/* 1c4 */ bboff_t sigb_resetinfo_off; /* Resetinfo offset */ - -/* 1c8 */ bboff_t sigb_cvc_off; /* CVC offset */ - -/* 1cc */ bboff_t sigb_eeprom_off; /* EEPROM offset */ - -/* 1d0 */ vaddr_t sigb_wdog_reset_vec; /* Watchdog Reset Vector */ - -/* 1d8 */ vaddr_t sigb_xir_reset_vec; /* XIR Reset vector */ - -/* 1e0 */ vaddr_t sigb_sir_reset_vec; /* SIR Reset Vector */ - -/* 1e8 */ vaddr_t sigb_red_state_reset_vec; /* RED State Reset Vector */ - -/* 1f0 */ uchar_t sigb_resv_array[SIGB_RESV]; /* reserved space */ -} cpu_sgnblk_t; /* sizeof = 512 (0x200) = 128X */ - -#endif /* _ASM */ - -/* - * Mailbox commands. - * - * The commands are listed here so that they are in a central place - * for all users of the signature block mailbox. Want to be careful - * that some subsystems don't accidently use the same value for a - * command. For this reason we introduce a cookie for each subsystem. - */ - -#define SIGB_HANDLER_BUSY (-2) -#define SIGB_BAD_MBOX_CMD (-1) -#define SSP_CMD ('S' << 8) /* generic SSP */ -#define SSP_CMD_SUCCESS (SSP_CMD | 0x1) -#define SSP_GOTO_OBP (SSP_CMD | 0x2) -#define SSP_GOTO_PANIC (SSP_CMD | 0x3) -#define SSP_ENVIRON (SSP_CMD | 0x4) /* environmental intr */ - -#ifdef _KERNEL - -#ifdef _STARFIRE - -extern void juggle_sgnblk_poll(struct cpu *); -extern int sgnblk_poll_register(void (*)(processorid_t, cpu_sgnblk_t *)); -extern int sgnblk_poll_unregister(void (*)(processorid_t, cpu_sgnblk_t *)); -extern int sgnblk_poll_reference(void (*)(cpu_sgnblk_t *, void *), void *); -extern void sgnblk_poll_unreference(void (*)(cpu_sgnblk_t *, void *)); - -extern cpu_sgnblk_t *cpu_sgnblkp[NCPU]; - -/* - * Starfire specific signatures - */ -#define POST_SIG SIG_BLD('P', 'O') -#define DHLP_SIG SIG_BLD('D', 'H') - -/* - * Starfire specific Sigblock states. - */ -#define SIGBST_NONE 0 /* no state */ -#define SIGBST_RUN 1 /* running */ -#define SIGBST_EXIT 2 /* finished */ -#define SIGBST_PRERUN 3 /* pre-exec */ -#define SIGBST_ARBSTOP 4 /* transient arbstop state */ -#define SIGBST_RESET 5 /* reset */ -#define SIGBST_POWEROFF 6 /* no power */ -#define SIGBST_DETACHED 7 /* spinning in OBP after DR DETACH */ -#define SIGBST_CALLBACK 8 /* kernel calling back into OBP */ -#define SIGBST_WATCHDOG 9 /* OBP running after watchdog */ -#define SIGBST_WATCHDOG_SYNC 10 /* OBP "sync" after watchdog reset */ -#define SIGBST_OFFLINE 11 /* cpu offline */ -#define SIGBST_BOOTING 12 /* booting */ -#define SIGBST_UNKNOWN 13 /* unknown */ -#define SIGBST_XIR 14 /* OBP running after XIR */ -#define SIGBST_XIR_SYNC 15 /* OBP trying "sync" in XIR */ -#define SIGBST_SIR 16 /* OBP running after SIR */ -#define SIGBST_SIR_SYNC 17 /* OBP trying "sync" in SIR */ -#define SIGBST_REDMODE 18 /* OBP running after REDMODE */ -#define SIGBST_REDMODE_SYNC 19 /* OBP trying "sync" in REDMODE */ -#define SIGBST_QUIESCED 20 /* system quiesced */ -#define SIGBST_QUIESCE_INPROGRESS 21 /* system quiesce in-progress */ -#define SIGBST_RESUME_INPROGRESS 22 /* system resume in-progress */ - -/* - * Starfire specific Sigblock sub-states - */ -#define EXIT_NULL 0 -#define EXIT_HALT 1 -#define EXIT_ENVIRON 2 -#define EXIT_REBOOT 3 -#define EXIT_PANIC1 4 -#define EXIT_PANIC2 5 -#define EXIT_HUNG 6 -#define EXIT_WATCH 7 -#define EXIT_PANIC_REBOOT 8 -#define EXIT_WATCHDOG_REBOOT 9 -#define EXIT_SOFT_INIT_RESET 10 /* SIR */ -#define EXIT_EXTERN_INIT_RESET 11 /* XIR */ -#define EXIT_REDMODE_REBOOT 12 /* REDMODE */ -#define EXIT_OBP_RESET 13 /* OBP RESET */ - -#else - -#define REGISTER_BBUS_INTR() -#define CPU_SGN_MAPIN(cpuid) -#define CPU_SGN_MAPOUT(cpuid) -#define CPU_SGN_EXISTS(cpuid) (0) -#define SGN_CPU_IS_OS(cpuid) (0) -#define SGN_CPU_IS_OBP(cpuid) (0) -#define SGN_CPU_STATE_IS_DETACHED(cpuid) (0) - -#endif /* _STARFIRE */ - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _CPU_SGN_H */ diff --git a/usr/src/uts/sun4u/starfire/sys/cvc.h b/usr/src/uts/sun4u/starfire/sys/cvc.h deleted file mode 100644 index 4f36155022..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/cvc.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _CVC_H -#define _CVC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define cvc_username "ssp" -#define CVCD_SERVICE "cvc_hostd" -#define CVC_CONN_SERVICE "cvc" -#define MAX_CVC_CONN 100 -#define MAXPKTSZ 4096 - -#define TRUE 1 -#define FALSE 0 - -/* - * Network Redirection driver ioctl to jump into debugger. - */ -#define CVC 'N' -#define CVC_BREAK (CVC<<8) -#define CVC_DISCONNECT ((CVC<<8)|0x1) - -#define CVC_CONN_BREAK 0x1 /* Break to OBP or kmdb */ -#define CVC_CONN_DIS 0x2 /* disconnect */ -#define CVC_CONN_STAT 0x4 /* status of CVC connects */ -#define CVC_CONN_WRITE 0x8 /* ask write permission */ -#define CVC_CONN_RELW 0x10 /* release write permission */ -#define CVC_CONN_WRLK 0x20 /* Lock the Write */ -#define CVC_CONN_PRIVATE 0x40 /* Only one session is allowed */ -#define CVC_CONN_SWITCH 0x41 /* Switch communication path */ - - -#define TCP_DEV "/dev/tcp" -#define CVCREDIR_DEV "/devices/pseudo/cvcredir@0:cvcredir" - -/* - * Layout of BBSRAM input and output buffers: - * - * - * |---------------| - * 0x1f400 | control msg | Receive buffer is reduced by two bytes to - * | 1 byte | accomodate a control msg area in which - * |---------------| information is sent from obp_helper to the - * | send buffer | cvc driver (e.g. break to obp) when - * | | communication is over BBSRAM. - * | 1020 bytes | - * |---------------| - * | send count | - * 0x1f7fe | 2 bytes | - * |---------------| - * | receive buffer| - * | | - * | 1022 bytes | - * |---------------| - * | output count | - * 0x1fbfe | 2 bytes | - * |---------------| - * - */ - -#define BBSRAM_COUNT_SIZE sizeof (short) -#define CVC_IN_SIZE 256 -#define CVC_OUT_SIZE 1024 -#define MAX_XFER_INPUT (CVC_IN_SIZE - BBSRAM_COUNT_SIZE) -#define MAX_XFER_OUTPUT (CVC_OUT_SIZE - BBSRAM_COUNT_SIZE) - -#define BBSRAM_OUTPUT_COUNT_OFF (CVC_OUT_SIZE - BBSRAM_COUNT_SIZE) -#define BBSRAM_INPUT_COUNT_OFF (CVC_OUT_SIZE + CVC_IN_SIZE - BBSRAM_COUNT_SIZE) - -/* - * Control msgs sent across BBSRAM from obp_helper to cvc driver - */ -#define CVC_BBSRAM_BREAK 1 -#define CVC_BBSRAM_DISCONNECT 2 -#define CVC_BBSRAM_VIA_NET 3 -#define CVC_BBSRAM_VIA_BBSRAM 4 -#define CVC_BBSRAM_CLOSE_NET 5 - -#ifdef _KERNEL -extern void cvc_assign_iocpu(int cpu_id); -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _CVC_H */ diff --git a/usr/src/uts/sun4u/starfire/sys/drmach.h b/usr/src/uts/sun4u/starfire/sys/drmach.h deleted file mode 100644 index 68b8fcc87e..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/drmach.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_DRMACH_H_ -#define _SYS_DRMACH_H_ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/memlist.h> -#include <sys/processor.h> -#include <sys/starfire.h> -#include <sys/sbd_ioctl.h> -#include <sys/sysevent.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAX_BOARDS plat_max_boards() -#define MAX_CPU_UNITS_PER_BOARD plat_max_cpu_units_per_board() -#define MAX_MEM_UNITS_PER_BOARD plat_max_mem_units_per_board() -#define MAX_IO_UNITS_PER_BOARD plat_max_io_units_per_board() -#define MAX_CMP_UNITS_PER_BOARD MAX_CPU_UNITS_PER_BOARD -#define MAX_CORES_PER_CMP 1 - -/* flags for drmach_configure() and drmach_unconfigure() */ -#define DRMACH_DEVI_FORCE 1 -#define DRMACH_DEVI_REMOVE 2 - -/* returned with drmach_board_find_devices callback */ -#define DRMACH_DEVTYPE_CPU "cpu" -#define DRMACH_DEVTYPE_MEM "memory" -#define DRMACH_DEVTYPE_PCI "pci" -#define DRMACH_DEVTYPE_SBUS "sbus" - -/* number of bytes in smallest coherency unit of this machine */ -#define DRMACH_COHERENCY_UNIT 64 - -typedef void *drmachid_t; - -typedef struct { - boolean_t assigned; - boolean_t powered; - boolean_t configured; - boolean_t busy; - boolean_t empty; - sbd_cond_t cond; - char type[MAXNAMELEN]; - char info[MAXPATHLEN]; /* TODO: what size? */ -} drmach_status_t; - -typedef struct { - int size; - char *copts; -} drmach_opts_t; - -extern sbd_error_t *drmach_copy_rename_init( - drmachid_t dst_id, uint64_t dst_slice_offset, - drmachid_t src_id, struct memlist *src_copy_ml, - drmachid_t *pgm_id); -extern sbd_error_t *drmach_copy_rename_fini(drmachid_t id); -extern void drmach_copy_rename(drmachid_t id); - -extern sbd_error_t *drmach_pre_op(int cmd, drmachid_t id, - drmach_opts_t *opts); -extern sbd_error_t *drmach_post_op(int cmd, drmachid_t id, - drmach_opts_t *opts); - -extern sbd_error_t *drmach_board_assign(int bnum, drmachid_t *id); -extern sbd_error_t *drmach_board_connect(drmachid_t id, - drmach_opts_t *opts); -extern sbd_error_t *drmach_board_deprobe(drmachid_t id); -extern sbd_error_t *drmach_board_disconnect(drmachid_t id, - drmach_opts_t *opts); -extern sbd_error_t *drmach_board_find_devices(drmachid_t id, void *a, - sbd_error_t *(*found)(void *a, const char *, int, drmachid_t)); -extern int drmach_board_lookup(int bnum, drmachid_t *id); -extern sbd_error_t *drmach_passthru(drmachid_t id, - drmach_opts_t *opts); - -extern sbd_error_t *drmach_board_name(int bnum, char *buf, int buflen); - -extern sbd_error_t *drmach_board_poweroff(drmachid_t id); -extern sbd_error_t *drmach_board_poweron(drmachid_t id); -extern sbd_error_t *drmach_board_test(drmachid_t id, drmach_opts_t *opts, - int force); - -extern sbd_error_t *drmach_board_unassign(drmachid_t id); - -extern sbd_error_t *drmach_configure(drmachid_t id, int flags); - -extern sbd_error_t *drmach_cpu_disconnect(drmachid_t id); -extern sbd_error_t *drmach_cpu_get_id(drmachid_t id, processorid_t *cpuid); -extern sbd_error_t *drmach_cpu_get_impl(drmachid_t id, int *ip); -extern void drmach_cpu_flush_ecache_sync(void); - -extern sbd_error_t *drmach_get_dip(drmachid_t id, dev_info_t **dip); - -extern sbd_error_t *drmach_io_is_attached(drmachid_t id, int *yes); -extern sbd_error_t *drmach_io_post_attach(drmachid_t id); -extern sbd_error_t *drmach_io_post_release(drmachid_t id); -extern sbd_error_t *drmach_io_pre_release(drmachid_t id); -extern sbd_error_t *drmach_io_unrelease(drmachid_t id); - -extern sbd_error_t *drmach_mem_add_span(drmachid_t id, - uint64_t basepa, uint64_t size); -extern sbd_error_t *drmach_mem_del_span(drmachid_t id, - uint64_t basepa, uint64_t size); -extern sbd_error_t *drmach_mem_disable(drmachid_t id); -extern sbd_error_t *drmach_mem_enable(drmachid_t id); -extern sbd_error_t *drmach_mem_get_alignment(drmachid_t id, uint64_t *pa); -extern sbd_error_t *drmach_mem_get_base_physaddr(drmachid_t id, - uint64_t *pa); -extern sbd_error_t *drmach_mem_get_memlist(drmachid_t id, - struct memlist **ml); -extern sbd_error_t *drmach_mem_get_size(drmachid_t id, uint64_t *bytes); -extern sbd_error_t *drmach_mem_get_slice_size(drmachid_t id, - uint64_t *bytes); -extern processorid_t drmach_mem_cpu_affinity(drmachid_t id); -extern int drmach_allow_memrange_modify(drmachid_t id); - -extern sbd_error_t *drmach_release(drmachid_t id); -extern sbd_error_t *drmach_status(drmachid_t id, drmach_status_t *stat); -extern sbd_error_t *drmach_unconfigure(drmachid_t id, int flags); -extern int drmach_log_sysevent(int board, char *hint, int flag, - int verbose); - -extern int drmach_verify_sr(dev_info_t *dip, int sflag); -extern void drmach_suspend_last(); -extern void drmach_resume_first(); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_DRMACH_H_ */ diff --git a/usr/src/uts/sun4u/starfire/sys/idn.h b/usr/src/uts/sun4u/starfire/sys/idn.h deleted file mode 100644 index a8ee2ce9b8..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/idn.h +++ /dev/null @@ -1,3886 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright (c) 2016 by Delphix. All rights reserved. - * - * Inter-Domain Network - */ - -#ifndef _SYS_IDN_H -#define _SYS_IDN_H - -#ifndef _ASM - -#ifdef _KERNEL - -#include <sys/note.h> - -#include <sys/cmn_err.h> -#include <sys/dditypes.h> -#include <sys/stream.h> -#include <sys/machsystm.h> -#include <sys/ethernet.h> -#include <sys/dlpi.h> -#include <sys/time.h> -#include <sys/kmem.h> -#include <sys/atomic.h> -#include <sys/cpuvar.h> - -#include <sys/idn_sigb.h> -#include <sys/idn_smr.h> -#endif /* _KERNEL */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef const char * const procname_t; - -#define MB2B(m) ((size_t)(m) << 20) /* MBytes to Bytes */ -#define B2MB(b) ((uint_t)((b) >> 20)) /* Bytes to MBytes */ - -#ifdef _KERNEL - -/* - * IDN_PROP_SMRSIZE - User specified size in MBytes. - * IDN_PROP_SMRADDR - OBP's internal physical address of the region. - * - * OBP properties of "memory" node that define the SMR space. - */ -#define IDN_PROP_SMRSIZE "idn-smr-size" -#define IDN_PROP_SMRADDR "idn-smr-addr" - -/* - * IDN_AWOLMSG_INTERVAL (driver.conf) - * - * Number of seconds between AWOL messages on a per-domain basis. - * The purpose is to throttle the frequency at which these - * messages appear. - * - * IDN_MSGWAIT_NEGO (driver.conf) - * IDN_MSGWAIT_CFG - * IDN_MSGWAIT_CON - * IDN_MSGWAIT_FIN - * IDN_MSGWAIT_CMD - * IDN_MSGWAIT_DATA - * - * Number of seconds to wait for response to respective - * message type. - * - * IDN_RETRYFREQ_NEGO (driver.conf) - * IDN_RETRYFREQ_CON - * IDN_RETRYFREQ_FIN - * - * Number of seconds to wait between retries of the respective - * message type. - * - * IDN_SMR_ALIGN (not tunable) - * - * The hardware registers that describe the SMR are based on a 64K - * aligned physical address. - * - * IDN_SMR_SIZE (OBP [only]) - * - * Total size of the SMR (Shared Memory Region) in bytes. - * - * IDN_NWR_SIZE (driver.conf) - * - * Total size of the NWR (NetWork Region) portion of the SMR which - * is actually used to support network activity. The NWR is managed - * as simply a pool of I/O buffers which are distributed by the - * Master domain to the Slaves for the purpose of communicating - * between each other. If not set then the entire SMR is used - * as the NWR. - * Req: IDN_NWR_SIZE <= IDN_SMR_SIZE - * - * IDN_SMR_BUFSIZE (driver.conf) - * - * Size of individual SMR buffers. The SMR is divided into chunks - * of IDN_SMR_BUFSIZE bytes. The IDN_MTU is based on this size - * and thus the IDN_SMR_BUFSIZE should be chosen based on performance. - * - * IDN_DATA_SIZE (NOT tunable) - * - * Portion of IDN_SMR_BUFSIZE that can contain raw non-IDN dependent - * data. We subtract IDN_ALIGNSIZE bytes to allow for fast bcopy - * alignment. - * Req: IDN_DATA_SIZE <= - * (IDN_SMR_BUFSIZE - sizeof (smr_pkthdr_t) - IDN_ALIGNSIZE) - * - * IDN_MTU (indirectly tunable via IDN_SMR_BUFSIZE) - * - * This size represents the portion of an SMR I/O buffers that can - * contain (ethernet headerless) data. - * Req: IDN_MTU <= IDN_DATA_SIZE - sizeof (ether_header) - * - * IDN_WINDOW_MAX (driver.conf) - * - * Maximum number of outstanding packets that are allowed per - * domain. If this value is exceeded for a particular domain - * no further I/Os will be transmitted to that domain until it - * has acknowledged enough of the previous transmission to bring - * down its outstanding I/O count (idn_domain.dio) below this - * value. In addition, if this value is exceeded then a Timer - * is scheduled to check for any response from the remote domain. - * - * IDN_WINDOW_INCR (driver.conf) - * - * As more channels/nets are activated on a particular domain - * the greater the number of possible outstanding data packets - * that can be outstanding to a given domain. Since this natural - * occurence can result in the outstanding-I/O count to a given - * domain to increase we run the risk of dropping into the - * IDN_WINDOW_MAX region even though the receiving domain - * may be fine with handling the load. In order to compensate - * for this increased activity and to not incur unjustified - * slips into the IDN_WINDOW_MAX region, the IDN_WINDOW_MAX - * value is adjusted by IDN_WINDOW_INCR for each channel/net - * that is activated for a given domain. - * - * IDN_WINDOW_EMAX (not tunable) - * - * The effective value of IDN_WINDOW_MAX once it has - * been adjusted by IDN_WINDOW_INCR. - * - * IDN_RECLAIM_MIN (driver.conf) - * - * Minimum number of outstanding packets that our allowed - * before subsequent sends will attempt to reclaim some number - * of outstanding data packets. - * - * IDN_RECLAIM_MAX (driver.conf) - * This value represents the maximum number of outstanding - * packets we will try to reclaim during a send once we've - * passed the IDN_RECLAIM_MIN boundary. - * - * IDN_MODUNLOADABLE (ndd) - * - * By default the IDN driver is unloadable. Setting this - * variable will allow the IDN driver to be unloaded provided - * it's not in use. - * - * IDN_LOWAT/IDN_HIWAT (driver.conf) - * - * Low/High water marks for the STREAM interface to IDN. - * - * IDN_MBOX_PER_NET (driver.conf) - * - * Number of mailbox entries that are allocated per channel/net. - * This value effectively represents the amount of outstanding - * activity that can reside at a domain. Increasing this value - * allows more packets to be in transit to a domain, however - * at some point there are diminishing returns since the receiver - * can only consume packets so fast. - * - * IDN_MAX_NETS (driver.conf) - * - * Maximum number of network interfaces (channels) that IDN - * is currently configured to allow. The absolute max is - * IDN_MAXMAX_NETS. We don't automatically default IDN_MAX_NETS - * to IDN_MAXMAX_NETS because it would mean wasted space in - * the mailbox region having to reserve mailboxes that will - * very likely go unused. The smaller this value the fewer - * the number of mailboxes in the SMR and thus the greater the - * number of possible I/O buffers available. - * Req: IDN_MAX_NETS <= IDN_MAXMAX_NETS - * - * IDN_CHECKSUM (driver.conf) - * - * If enabled, IDN validates the smr_pkthdr_t of incoming packets - * via a checksum, and calculates the checksum for outgoing packets. - * Only the first 3 fields of smr_pkthdr_t are checksummed and - * must be set to their expected values prior to calculating the - * checksum. Turned OFF by default when compiled DEBUG. - * - * IDN_SMR_MAXSIZE (not tunable) - * - * The absolute maximum size of the SMR region that we'll allow. - * Note that the virtual address space comes out kernelmap. - */ -#define IDN_AWOLMSG_INTERVAL 60 /* seconds */ -#define IDN_MSGWAIT_NEGO 20 /* seconds */ -#define IDN_MSGWAIT_CFG 40 -#define IDN_MSGWAIT_CON 20 -#define IDN_MSGWAIT_FIN 40 -#define IDN_MSGWAIT_CMD 40 -#define IDN_MSGWAIT_DATA 30 -#define IDN_RETRYFREQ_NEGO 2 -#define IDN_RETRYFREQ_CON 2 -#define IDN_RETRYFREQ_FIN 3 - -#define IDN_SMR_BUFSIZE_MIN 512 -#define IDN_SMR_BUFSIZE_MAX (512*1024) -#define IDN_SMR_BUFSIZE_DEF (16*1024) - -#define IDN_SMR_SHIFT (16) -#define IDN_SMR_ALIGN (1 << IDN_SMR_SHIFT) /* 64K */ -#define IDN_SMR_SIZE idn_smr_size -#define IDN_NWR_SIZE idn_nwr_size -#define IDN_SMR_BUFSIZE idn_smr_bufsize -#define IDN_DATA_SIZE (IDN_SMR_BUFSIZE \ - - sizeof (smr_pkthdr_t) \ - - IDN_ALIGNSIZE) -#define IDN_MTU (IDN_DATA_SIZE - sizeof (struct ether_header)) -#define IDN_WINDOW_MAX idn_window_max -#define IDN_WINDOW_INCR idn_window_incr -#define IDN_WINDOW_EMAX idn_window_emax -#define IDN_RECLAIM_MIN idn_reclaim_min -#define IDN_RECLAIM_MAX idn_reclaim_max -#define IDN_MODUNLOADABLE idn_modunloadable -#define IDN_LOWAT idn_lowat -#define IDN_HIWAT idn_hiwat -#define IDN_MBOX_PER_NET idn_mbox_per_net -#define IDN_MAX_NETS idn_max_nets -#define IDN_CHECKSUM idn_checksum -#define IDN_SMR_MAXSIZE 96 -#define _IDN_SMR_SIZE 32 /* 32M */ -#define _IDN_NWR_SIZE _IDN_SMR_SIZE /* 32M */ -#define _IDN_SMR_BUFSIZE (16 * 1024) /* 16K */ - - -#define IDN_TUNEVAR_NAME(v) (*(char **)((ulong_t)&(v)+(sizeof (ulong_t)))) -#define IDN_TUNEVAR_VALUE(v) (v) - -/* - * History structure to support problem analysis. - */ -#define IDN_HISTORY_NUM 1024 -#define IDN_HISTORY_LOG(op, d0, d1, d2) \ - if (idn_history) { \ - mutex_enter(&idnhlog.h_mutex); \ - idnhlog.h_log[idnhlog.h_index].e_time = TIMESTAMP(); \ - idnhlog.h_log[idnhlog.h_index].e_op = (ushort_t)(op); \ - idnhlog.h_log[idnhlog.h_index].e_data[0] = (ushort_t)(d0); \ - idnhlog.h_log[idnhlog.h_index].e_data[1] = (ushort_t)(d1); \ - idnhlog.h_log[idnhlog.h_index].e_data[2] = (ushort_t)(d2); \ - idnhlog.h_index++; \ - idnhlog.h_index &= (IDN_HISTORY_NUM - 1); \ - mutex_exit(&idnhlog.h_mutex); \ - } - -#define IDNH_GSTATE 0x0001 /* d0=gstate, d1=, d2= */ -#define IDNH_DSTATE 0x0002 /* d0=domid, d1=dstate, d2=cpuid */ -#define IDNH_AWOL 0x0003 /* d0=domid, d1=dstate, d2=cpuid */ -#define IDNH_MASTERID 0x0004 /* d0=masterid, d1=oldid, d2= */ -#define IDNH_NEGO 0x0005 /* d0=domid, d1=ds_trans_on, d2=ds_connected */ -#define IDNH_FIN 0x0006 /* d0=domid, d1=finstate, d2= */ -#define IDNH_RELINK 0x0007 /* d0=domid, d1=dstate, d2=ds_relink */ - -struct idn_h_entry { - hrtime_t e_time; - ushort_t e_op; - ushort_t e_data[3]; -}; - -struct idn_history { - kmutex_t h_mutex; - int h_index; - struct idn_h_entry h_log[IDN_HISTORY_NUM]; -}; -#endif /* _KERNEL */ - -/* - * IDN_SIGBPIL - Interrupt level at which IDN driver - * wakes up idn_sigbhandler_thread - */ -#define IDN_SIGBPIL PIL_3 - -/* - * Definition of sigbintr.sb_busy values which - * represents state of idn_sigbhandler. - */ -#define IDNSIGB_NOTREADY ((uchar_t)0) -#define IDNSIGB_INACTIVE ((uchar_t)1) -#define IDNSIGB_STARTED ((uchar_t)2) -#define IDNSIGB_ACTIVE ((uchar_t)3) -#define IDNSIGB_DIE ((uchar_t)4) - -/* - * Some Xfire based macros that assume 4 cpus per board. - */ -#define CPUID_TO_BOARDID(c) ((c) >> 2) -#define MAX_CPU_PER_BRD 4 -#define CPUSET_TO_BOARDSET(cset, bset) \ - { \ - register int c, b; \ - (bset) = 0; \ - for (b = 0; b < MAX_BOARDS; b++) \ - for (c = 0; c < MAX_CPU_PER_BRD; c++) \ - if (CPU_IN_SET((cset), \ - (b * MAX_CPU_PER_BRD) + c)) \ - (bset) |= 1 << b; \ - } - -/* - * Macros to manipulate boardset and domainset masks. - */ -typedef ushort_t boardset_t; /* assumes max of 16 boards */ -typedef ushort_t domainset_t; /* assumes max of 16 domains */ - -#define BOARDSET(brd) ((boardset_t)(1 << (brd))) -#define BOARDSET_ALL ((boardset_t)~0) -#define BOARD_IN_SET(set, brd) ((set) & BOARDSET(brd)) -#define BOARDSET_ADD(set, brd) ((set) |= BOARDSET(brd)) -#define BOARDSET_DEL(set, brd) ((set) &= ~BOARDSET(brd)) -#define DOMAINSET(d) ((domainset_t)1 << (d)) -#define DOMAINSET_ALL ((domainset_t)~0) -#define DOMAIN_IN_SET(s, d) ((s) & DOMAINSET(d)) -#define DOMAINSET_ADD(s, d) ((s) |= DOMAINSET(d)) -#define DOMAINSET_DEL(s, d) ((s) &= ~DOMAINSET(d)) - -/* - * PFN_TO_SMADDR macro converts a PFN to a IDN_SMR_ALIGN'ed - * address suitable for the CIC bar/lar registers. - */ -#if (IDN_SMR_SHIFT <= MMU_PAGESHIFT) -#define PFN_TO_SMADDR(pfn) ((pfn) << (MMU_PAGESHIFT - IDN_SMR_SHIFT)) -#else -#define PFN_TO_SMADDR(pfn) ((pfn) >> (IDN_SMR_SHIFT - MMU_PAGESHIFT)) -#endif - -/* - * Translate a physical address to a unique domain identifier. - * IMPORTANT - Assumes each board's memory is configured on a 8GB - * boundary. PA(8G) = PFN(1M). - */ -#define MEM8G_SHIFT 33 /* (1 << 33) == 8G */ -#define PADDR_TO_DOMAINID(paddr) ((int)((paddr) >> MEM8G_SHIFT) & 0xf) - -#define VALID_NWROFFSET(off, align) \ - (((uint_t)(off) >= 0) && \ - ((size_t)(off) < MB2B(IDN_NWR_SIZE)) && \ - !((uint_t)(off) & ((align) - 1))) -#define VALID_NWRADDR(addr, align) \ - (((caddr_t)(addr) >= idn.smr.vaddr) && \ - VALID_NWROFFSET(((caddr_t)(addr) - idn.smr.vaddr), (align))) -#define VALID_DOMAINID(d) (((d) >= 0) && ((d) < MAX_DOMAINS)) -#define VALID_UDOMAINID(d) ((d) < MAX_DOMAINS) -#define VALID_CPUID(c) (((c) >= 0) && ((c) < NCPU)) -#define VALID_CHANNEL(c) (((c) >= 0) && ((c) < IDN_MAX_NETS)) -#define VALID_UCHANNEL(c) ((c) < IDN_MAX_NETS) - -/* - * The following are bit values of idn_debug, currently - * only useful if compiled with DEBUG. - */ -#ifdef DEBUG -#define STRING(sss) char sss[20] -#define INUM2STR(mm, ss) inum2str((mm), (ss)) - -#define IDNDBG_XDC 0x00000001 -#define IDNDBG_XF 0x00000002 -#define IDNDBG_REGS 0x00000004 -#define IDNDBG_SMR 0x00000008 -#define IDNDBG_PROTO 0x00000010 -#define IDNDBG_STR 0x00000020 -#define IDNDBG_DRV 0x00000040 -#define IDNDBG_DATA 0x00000080 -#define IDNDBG_STATE 0x00000100 -#define IDNDBG_DLPI 0x00000200 -#define IDNDBG_KERN 0x00000400 -#define IDNDBG_ALLOC 0x00000800 -#define IDNDBG_REMAP 0x00001000 -#define IDNDBG_TIMER 0x00002000 -#define IDNDBG_CHAN 0x00004000 -#define IDNDBG_AWOL 0x00008000 -#define IDNDBG_SYNC 0x00010000 -#define _IDNDBG_UNUSED0 0x00020000 -#define IDNDBG_HITLIST 0x00040000 -#define IDNDBG_XMON 0x00080000 -#define IDNDBG_TEST 0x80000000 -#define IDNDBG_ALL ((uint_t)-1) - -#define PR_ALL if (idn_debug) printf -#define PR_XDC if (idn_debug & IDNDBG_XDC) printf -#define PR_XF if (idn_debug & IDNDBG_XF) printf -#define PR_REGS if (idn_debug & IDNDBG_REGS) printf -#define PR_SMR if (idn_debug & IDNDBG_SMR) printf -#define PR_PROTO if (idn_debug & IDNDBG_PROTO) printf -#define PR_STR if (idn_debug & IDNDBG_STR) printf -#define PR_DRV if (idn_debug & IDNDBG_DRV) printf -#define PR_DATA if (idn_debug & IDNDBG_DATA) printf -#define PR_STATE if (idn_debug & IDNDBG_STATE) printf -#define PR_DLPI if (idn_debug & IDNDBG_DLPI) printf -#define PR_KERN if (idn_debug & IDNDBG_KERN) printf -#define PR_ALLOC if (idn_debug & IDNDBG_ALLOC) printf -#define PR_REMAP if (idn_debug & (IDNDBG_SMR|IDNDBG_REMAP)) printf -#define PR_TIMER if (idn_debug & IDNDBG_TIMER) printf -#define PR_CHAN if (idn_debug & IDNDBG_CHAN) printf -#define PR_AWOL if (idn_debug & (IDNDBG_PROTO|IDNDBG_AWOL)) printf -#define PR_SYNC if (idn_debug & IDNDBG_SYNC) printf -#define _PR_UNUSED0 if (idn_debug & _IDNDBG_UNUSED0) printf -#define PR_HITLIST if (idn_debug & IDNDBG_HITLIST) printf -#define PR_XMON if (idn_debug & IDNDBG_XMON) printf -#define PR_TEST if (idn_debug & IDNDBG_TEST) printf -#else -#define STRING(sss) char *sss = "" -#define INUM2STR(mm, ss) - -#define PR_ALL if (0) printf -#define PR_XDC PR_ALL -#define PR_XF PR_ALL -#define PR_REGS PR_ALL -#define PR_SMR PR_ALL -#define PR_PROTO PR_ALL -#define PR_STR PR_ALL -#define PR_DRV PR_ALL -#define PR_DATA PR_ALL -#define PR_STATE PR_ALL -#define PR_DLPI PR_ALL -#define PR_KERN PR_ALL -#define PR_ALLOC PR_ALL -#define PR_REMAP PR_ALL -#define PR_TIMER PR_ALL -#define PR_CHAN PR_ALL -#define PR_AWOL PR_ALL -#define PR_SYNC PR_ALL -#define PR_SNOOP PR_ALL -#define PR_HITLIST PR_ALL -#define PR_XMON PR_ALL -#define PR_TEST PR_ALL -#endif /* DEBUG */ - -#ifdef _KERNEL -/* - * IDN drivers fields. - * - * IDNMINPSZ Minimum packet size the IDN supports. - * - * IDNMAXPSZ Maximum packet size that IDN supports from upper - * layers. Is equal to IDN_MTU + ether_header. Note - * that the IDN driver could support larger packets - * however the infrastructure to support fragmentation - * does not (and should not) exist with respect to - * ethernet packet types. - */ -#ifdef DEBUG -#define IDNDESC "Inter-Domain Network (DEBUG)" -#else -#define IDNDESC "Inter-Domain Network" -#endif /* DEBUG */ - -#define IDNIDNUM 8264 -#define IDNNAME "idn" -#define IDNMINPSZ 0 /* set at idnopen() */ -#define IDNMAXPSZ 0 /* set at idnopen() */ - -#endif /* _KERNEL */ - -/* - * IDN Global States. - */ -typedef enum { -/* 0 */ IDNGS_OFFLINE = 0, /* idle */ -/* 1 */ IDNGS_CONNECT, /* connecting initial domain */ -/* 2 */ IDNGS_ONLINE, /* master selected */ -/* 3 */ IDNGS_DISCONNECT, /* local is unlinking */ -/* 4 */ IDNGS_RECONFIG, /* selecting new master */ -/* 5 */ _IDNGS_UNUNSED5, -/* 6 */ _IDNGS_UNUNSED6, -/* 7 */ _IDNGS_UNUNSED7, -/* 8 */ _IDNGS_UNUNSED8, -/* 9 */ _IDNGS_UNUNSED9, -/* 10 */ IDNGS_IGNORE /* ignore requests (fault injection) */ -} idn_gstate_t; - -#ifdef _KERNEL - -#define TIMESTAMP() (gethrtime() / 1000000ull) - -/* - * Spaced defined in: - * sigblkp[cpu0.cpu_id]->sigb_idn.reserved1. - */ -#define IDNSB_GSTATE_NEW 0 -#define IDNSB_GSTATE_OLD 1 -#define IDNSB_MASTERCPU 2 -#define IDNSB_RESERVED 3 - -#define IDNSB_HWCHKPT_MAX 4 - -#define IDNSB_SIZE 72 -/* - * This structure gets overlay onto: - * sigblkp[cpu0.cpu_id]->sigb_idn.reserved1. - * - * This structure must be exactly IDNSB_SIZE bytes. - */ -typedef struct idnsb { - uchar_t id_gstate; - uchar_t id_pgstate; - uchar_t id_master_board; - uchar_t id_pmaster_board; - - uchar_t reserved_DO_NOT_USE[24]; /* idnevent_t field */ - - struct { - uchar_t d_board; - uchar_t d_state; - } id_status[MAX_DOMAINS]; - uint_t id_hwstate; - ushort_t id_hwchkpt[IDNSB_HWCHKPT_MAX]; -} idnsb_t; /* sizeof = 72 (0x48) 18X bytes */ - - -#define IDNSB_DOMAIN_UPDATE(dp) \ - { \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - int domid = (dp)->domid; \ - if ((dp)->dcpu == IDN_NIL_DCPU) \ - idn.idnsb->id_status[domid].d_board = \ - (uchar_t)0xff; \ - else if ((dp)->dvote.v.board == 0) \ - idn.idnsb->id_status[domid].d_board = \ - (uchar_t)CPUID_TO_BOARDID((dp)->dcpu); \ - else \ - idn.idnsb->id_status[domid].d_board = \ - (uchar_t)(dp)->dvote.v.board; \ - idn.idnsb->id_status[domid].d_state = \ - (uchar_t)(dp)->dstate; \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - } -/* - * The following definitions and macros pertain to the - * id_hwstate and id_hwchkpt[] fields. - * - * id_hwstate (m = mark: 1=open, 2=close) - * 0 1 2 3 4 5 6 7 - * --------------------------------- - * | m | m | m | m | XX unused XXX | - * --------------------------------- - * | | | | - * | | | +- CACHE - * | | +- CHAN - * | +- LINK - * +- SMR - * - * Note that nibble 4 is used in DEBUG for noting cache - * flush progress through idnxf_flushall_ecache(). This - * will override id_hwchkpt[] since it only has room for - * 4 items, however the BBSRAM space is there and - * unofficially available :-o - * - * id_hwchkpt[0] = SMR boardset - * id_hwchkpt[1] = LINK boardset - * id_hwchkpt[2] = CHAN boardset - * id_hwchkpt[3] = CACHE boardset. - */ -#define IDNSB_CHKPT_SMR 0 -#define IDNSB_CHKPT_LINK 1 -#define IDNSB_CHKPT_CHAN 2 -#define IDNSB_CHKPT_CACHE 3 -#define IDNSB_CHKPT_UNUSED 4 /* This is the max you can have */ - -#define _CHKPT_MARKIT(item, mark) \ - { \ - uint_t mk = (((uint_t)((mark) & 0xf)) << \ - (((sizeof (uint_t) << 1) - 1 - (item)) << 2)); \ - uint_t *sp = &idn.idnsb->id_hwstate; \ - ASSERT(idn.idnsb); \ - *sp &= ~(((uint_t)0xf) << (((sizeof (uint_t) << 1) \ - - 1 - (item)) << 2)); \ - *sp |= mk; \ - } - -#define CHECKPOINT_OPENED(item, bset, mark) \ - { \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \ - _CHKPT_MARKIT((item), (mark)); \ - sp[item] |= ((ushort_t)(bset)); \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - } - -#define CHECKPOINT_CLOSED(item, bset, mark) \ - { \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \ - _CHKPT_MARKIT((item), (mark)); \ - sp[item] &= (ushort_t)~(bset); \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - } - -#define CHECKPOINT_CLEAR(item, mark) \ - { \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - ushort_t *sp = &idn.idnsb->id_hwchkpt[0]; \ - _CHKPT_MARKIT((item), (mark)); \ - sp[item] = 0; \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - } -#ifdef DEBUG -#define CHECKPOINT_CACHE_CLEAR_DEBUG(mark) \ - CHECKPOINT_CLEAR(IDNSB_CHKPT_UNUSED, (mark)) -#define CHECKPOINT_CACHE_STEP_DEBUG(bset, mark) \ - CHECKPOINT_OPENED(IDNSB_CHKPT_UNUSED, (bset), (mark)) -#else -#define CHECKPOINT_CACHE_CLEAR_DEBUG(mark) -#define CHECKPOINT_CACHE_STEP_DEBUG(bset, mark) -#endif /* DEBUG */ - - -#ifdef DEBUG -#define IDN_GSTATE_TRANSITION(ns) \ - { \ - hrtime_t tstamp; \ - /*LINTED*/ \ - IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \ - tstamp = TIMESTAMP(); \ - ASSERT(IDN_GLOCK_IS_EXCL()); \ - PR_STATE("GSTATE:%ld: (l=%d) %s(%d) -> %s(%d)\n", \ - (uint64_t)tstamp, __LINE__, \ - idngs_str[idn.state], idn.state, \ - idngs_str[ns], (ns)); \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - idn.idnsb->id_pgstate = (uchar_t)idn.state; \ - idn.idnsb->id_gstate = (uchar_t)(ns); \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - idn.state = (ns); \ - } -#else -#define IDN_GSTATE_TRANSITION(ns) \ - { \ - IDN_HISTORY_LOG(IDNH_GSTATE, (ns), 0, 0); \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - idn.idnsb->id_pgstate = (uchar_t)idn.state; \ - idn.idnsb->id_gstate = (uchar_t)(ns); \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - idn.state = (ns); \ - } -#endif /* DEBUG */ - -/* - * IDN link/unlink operations occur asynchronously with respect to the - * caller. The following definitions are to support the return of - * success/failure back to the original requesting thread. It's - * unlikely to have multiple outstanding link/unlink requests so we - * just provide a very small cache of waiting list entries. If the - * cache becomes exhausted then additional ones are kmem_alloc'd. - */ -#define IDNOP_CACHE_SIZE 3 -#define IDNOP_IN_CACHE(dwl) \ - (((dwl) >= &idn.dopers->_dop_wcache[0]) && \ - ((dwl) < &idn.dopers->_dop_wcache[IDNOP_CACHE_SIZE])) - -typedef struct dop_waitlist { - struct dop_waitlist *dw_next; - domainset_t dw_reqset; - domainset_t dw_domset; - short dw_op; - domainset_t dw_errset; - idnsb_error_t *dw_idnerr; - short dw_errors[MAX_DOMAINS]; -} dop_waitlist_t; - -typedef uint_t idn_xdcargs_t[4]; -typedef uint_t idn_chanset_t; - -/* - * Types of synchronization zones which a connection - * could be in. - */ -typedef enum { - IDNSYNC_NIL, - IDNSYNC_CONNECT, - IDNSYNC_DISCONNECT -} idn_synccmd_t; - -/* - * Type of sync-registration that is being requested. - */ -typedef enum { - IDNSYNC_REG_REG, - IDNSYNC_REG_NEW, - IDNSYNC_REG_QUERY -} idn_syncreg_t; - -#define IDN_SYNC_NUMZONE 3 -#define IDN_SYNC_GETZONE(s) ((((s) != IDNSYNC_CONNECT) && \ - ((s) != IDNSYNC_DISCONNECT)) ? \ - -1 : (int)(s) - 1) -#define IDN_SYNC_GETTRANS(s) (((s) == IDNSYNC_CONNECT) ? \ - idn.domset.ds_trans_on : \ - ((s) == IDNSYNC_DISCONNECT) ? \ - idn.domset.ds_trans_off : 0) - -/* - * Generic states when in a state transition region. - * These ultimately map to domain states via - * a idn_xphase_t definition. General model: - * - * PEND - * /\ - * / \ - * | | - * V V - * SENT--->RCVD - * \ / - * \ / - * VV - * FINAL - * - * Start these types with PEND = 0 so that they're - * compatible with idnxs_state_table[] and idn_xphase_t - * phases that use the value as an index. - */ -typedef enum { -/* 0 */ IDNXS_PEND = 0, -/* 1 */ IDNXS_SENT, -/* 2 */ IDNXS_RCVD, -/* 3 */ IDNXS_FINAL, -/* 4 */ IDNXS_NIL -} idn_xstate_t; - -/* - * Locking protocol: - * - * Each routine is called with SYNC_LOCK and - * the respective domain's DLOCK(EXCL) held. - * The routines must return with these locks - * still held. - */ -struct idn_msgtype; - -typedef struct { - int t_state; - int (*t_check)(int domid, struct idn_msgtype *mtp, - idn_xdcargs_t xargs); - void (*t_action)(int domid, struct idn_msgtype *mtp, - idn_xdcargs_t xargs); - void (*t_error)(int domid, struct idn_msgtype *mtp, - idn_xdcargs_t xargs); -} idn_trans_t; - -/* - * The callback routines (xt_final & xt_exit) are called with - * DLOCK and SYNC_LOCK held and they are required to return - * with these locks still held. - */ -typedef struct { - uint_t xt_msgtype; - idn_trans_t xt_trans[4]; - void (*xt_final)(int domid); - void (*xt_exit)(int domid, uint_t msgtype); -} idn_xphase_t; - -/* - * Synchronization entry representing the synchronization - * state with respect to a given domain for a given zone. - */ -typedef struct idn_syncop { - struct idn_syncop *s_next; - int s_domid; - idn_synccmd_t s_cmd; - int s_msg; - - domainset_t s_set_exp; - domainset_t s_set_rdy; - int (*s_transfunc)(int domid, void *arg); - void *s_transarg; -#ifdef DEBUG - int s_query[MAX_DOMAINS]; -#endif /* DEBUG */ -} idn_syncop_t; - -#ifdef DEBUG -#define IDN_SYNC_QUERY_INIT(d) \ - (bzero((caddr_t)idn_domain[d].dsync.s_query, \ - sizeof (idn_domain[d].dsync.s_query))) -#define IDN_SYNC_QUERY_UPDATE(md, sd) (idn_domain[md].dsync.s_query[sd]++) -#else /* DEBUG */ -#define IDN_SYNC_QUERY_INIT(d) -#define IDN_SYNC_QUERY_UPDATE(md, sd) -#endif /* DEBUG */ - -typedef struct { - idn_syncop_t *sc_op; - int sc_cnt; -} idn_synczone_t; - -#endif /* _KERNEL */ - -/* - * Vote Ticket used during negotiations and elections. - * - * 31 0 - * ----------------------------------------- - * |m...|....|pppp|....|Cbbb|bccc|cccB|BBB1| - * ----------------------------------------- - * m [31] = master/slave - * . [30:24] = unused - * p [23:20] = priority - * . [19:16] = unused - * C [15] = connected (has master) - * b [14:11] = nmembrds-1 - * c [10:5] = ncpus-1 - * B [4:1] = board_id - * 1 [0] = one - */ -typedef union { - struct { - uint_t master :1; - uint_t unused0 :7; - uint_t priority :4; - uint_t unused1 :4; - uint_t connected :1; - uint_t nmembrds :4; - uint_t ncpus :6; - uint_t board :4; - uint_t one :1; - } v; - uint_t ticket; -} idn_vote_t; - -#define IDNVOTE_PRI_MASK 0xf -#define IDNVOTE_MAXPRI 0xf -#define IDNVOTE_MINPRI 0 -#define IDNVOTE_DEFPRI 1 /* must be larger than MINPRI */ -/* - * Initially: - * vote.v.priority = IDNVOTE_DEFPRI - * vote.v.one = 1 - */ -#define IDNVOTE_INITIAL_TICKET ((IDNVOTE_DEFPRI << 20) | 1) -#define IDNVOTE_PRIVALUE(vvv) \ - ((int)vvv.v.priority + ((int)vvv.v.master ? IDNVOTE_MAXPRI : 0)) - -/* - * During elections we only use the "elect" attributes of the - * election ticket, i.e. those physical attributes pertaining - * to the individual domain (priority, nboards, ncpus, board). - */ -#define IDNVOTE_ELECT_MASK 0x00f07fff -#define IDNVOTE_ELECT(tkt) ((tkt).ticket & IDNVOTE_ELECT_MASK) -#define IDNVOTE_BASICS_MASK 0x00f0ffff -#define IDNVOTE_BASICS(tkt) ((tkt).ticket & IDNVOTE_BASICS_MASK) - -/* - * Values used in idn_select_master(). - */ -#define MASTER_IS_NONE 0 /* index into master_select_table */ -#define MASTER_IS_OTHER 1 -#define MASTER_IS_LOCAL 2 -#define MASTER_IS_REMOTE 3 - -typedef enum { - MASTER_SELECT_VOTE, - MASTER_SELECT_VOTE_RCFG, - MASTER_SELECT_CONNECT, - MASTER_SELECT_REMOTE, - MASTER_SELECT_LOCAL, - MASTER_SELECT_WAIT, - MASTER_SELECT_ERROR -} idn_master_select_t; - -/* - * Used to synchronize completion of link/unlink with respect to - * the original requester (user). Necessary since link establishment - * occurs asynchronously. - */ -typedef enum { -/* 0 */ IDNOP_DISCONNECTED, /* successfully disconnected */ -/* 1 */ IDNOP_CONNECTED, /* successfully established */ -/* 2 */ IDNOP_ERROR /* error trying to link/unlink */ -} idn_opflag_t; - -/* - * IDN Protocol Messages. - * These are IDN version (IDN_VERSION) dependent. - * - * ----- 7, --- 6,5.................0 - * | ack | nack | IDN message type | - * ---------------------------------- - */ -#define IDN_VERSION 1 - -/* - * Must be no more than 6-bits. See DMV private data. - */ -#define IDNP_ACK 0x20 -#define IDNP_NACK 0x10 -#define IDNP_NULL 0x00 -#define IDNP_NEGO 0x01 -#define IDNP_CON 0x02 -#define IDNP_CFG 0x03 -#define IDNP_FIN 0x04 -#define IDNP_CMD 0x05 -#define IDNP_DATA 0x06 - -#define IDN_NUM_MSGTYPES 7 -#define IDNP_ACKNACK_MASK (IDNP_ACK | IDNP_NACK) -#define IDNP_MSGTYPE_MASK 0x0f -#define VALID_MSGTYPE(m) (((m) >= IDNP_NEGO) && ((m) < IDN_NUM_MSGTYPES)) - -typedef struct idn_msgtype { - ushort_t mt_mtype; - ushort_t mt_atype; - ushort_t mt_cookie; -} idn_msgtype_t; - -/* - * IDN private data section of DMV layout (48 bits). - * - * 47......40,39.....34,33.....28,27..24,23......16,15..............0 - * | version | msgtype | acktype | did | cpuid | cookie | - * ------------------------------------------------------------------ - * - * version Local domain's version of IDN software. - * msgtype Type of IDN message, e.g. nego, syn, etc. - * acktype If msgtype is a ACK or NACK, then acktype is the - * type of ack that we're receiving, e.g. ack/nego|ack. - * did Local domain's ID (netid) - system-wide unique. - * cpuid Local domain's CPU->cpu_id that sending message. - * cookie Cookie assigned by remote domain for authentication. - * For NEGO & NEGO+ACK messages, it's the cookie that - * the sender expects the receiver to use in subsequent - * messages. The upper-eight bits represent a timer - * cookie to associate timers with expected messages. - */ -#endif /* !_ASM */ - -#ifdef _KERNEL - -#define _IDNPD_COOKIE_MASK 0xffff -#define _IDNPD_COOKIE_SHIFT 32 -#define _IDNPD_VER_MASK 0xff -#define _IDNPD_VER_SHIFT 24 -#define _IDNPD_MTYPE_MASK 0x3f -#define _IDNPD_MTYPE_SHIFT 18 -#define _IDNPD_ATYPE_MASK 0x3f -#define _IDNPD_ATYPE_SHIFT 12 -#define _IDNPD_DOMID_MASK 0xf -#define _IDNPD_DOMID_SHIFT 8 -#define _IDNPD_CPUID_MASK 0xff -#define _IDNPD_CPUID_SHIFT 0 - -#define _IDNPD_COOKIE_LEN 16 - -#ifndef _ASM - -#define IDN_PD2COOKIE(pdata) \ - (((uint_t)((pdata) >> _IDNPD_COOKIE_SHIFT)) & _IDNPD_COOKIE_MASK) -#define IDN_PD2VER(pdata) \ - (((uint_t)((pdata) >> _IDNPD_VER_SHIFT)) & _IDNPD_VER_MASK) -#define IDN_PD2MTYPE(pdata) \ - (((uint_t)((pdata) >> _IDNPD_MTYPE_SHIFT)) & _IDNPD_MTYPE_MASK) -#define IDN_PD2ATYPE(pdata) \ - (((uint_t)((pdata) >> _IDNPD_ATYPE_SHIFT)) & _IDNPD_ATYPE_MASK) -#define IDN_PD2DOMID(pdata) \ - (((uint_t)((pdata) >> _IDNPD_DOMID_SHIFT)) & _IDNPD_DOMID_MASK) -#define IDN_PD2CPUID(pdata) \ - (((uint_t)((pdata) >> _IDNPD_CPUID_SHIFT)) & _IDNPD_CPUID_MASK) - -#define IDN_MAKE_PDATA(mtype, atype, cookie) \ - ((((uint64_t)(cookie) & UINT64_C(_IDNPD_COOKIE_MASK)) << \ - _IDNPD_COOKIE_SHIFT) | \ - (((uint64_t)idn.version & UINT64_C(_IDNPD_VER_MASK)) << \ - _IDNPD_VER_SHIFT) | \ - (((uint64_t)(mtype) & UINT64_C(_IDNPD_MTYPE_MASK)) << \ - _IDNPD_MTYPE_SHIFT) | \ - (((uint64_t)(atype) & UINT64_C(_IDNPD_ATYPE_MASK)) << \ - _IDNPD_ATYPE_SHIFT) | \ - (((uint64_t)idn.localid & UINT64_C(_IDNPD_DOMID_MASK)) << \ - _IDNPD_DOMID_SHIFT) | \ - (((uint64_t)CPU->cpu_id & UINT64_C(_IDNPD_CPUID_MASK)) << \ - _IDNPD_CPUID_SHIFT)) - -#define IDN_TCOOKIE(ck) (((ck) >> 8) & 0xff) -#define IDN_DCOOKIE(ck) ((ck) & 0xff) -#define IDN_MAKE_COOKIE(d, t) ((((t) & 0xff) << 8) | ((d) & 0xff)) - -/* - * IDNP_NEGO - * - * 127........96,95........64,63........32,31.........0 - * | vote | domainset | - * ---------------------------------------------------- - * vote Local/Remote domain's vote ticket. - * domainset Mask of cpuids of domains to which - * sender is connected. Position in domainset - * designates respective domainid. - * E.g. domainset[6] = 20 -> domainid 6 is - * accessible via cpuid 20. - * The slot for the receiving domain - * contains the masterid of the sending - * domain. If the sending domain does - * not have a master then the entry will - * contain IDNNEG_NO_MASTER. - * - * These macros insert a domainid-cpuid pair into the - * domainset to be subsequently passed in a NEGO message, - * also retrieve the cpuid from the domainset for a - * given domainid. - * - * Usage: - * Sending: - * mask = IDNNEG_DSET_MYMASK(); - * IDNNEG_DSET_INIT(dset, mask) - * for (all domains except self) - * IDNNEG_DSET_SET(dset, domain, cpuid, mask); - * - * Receiving: - * IDNNEG_DSET_GET_MASK(dset, recv_domid, recv_mask); - * for (all domains except recv_domid) - * IDNNEG_DSET_GET(dset, domid, cpuid, recv_mask); - */ -typedef uint_t idnneg_dset_t[3]; - -#define IDNNEG_NO_MASTER 0x3f -#define __IDNNEG_DSET_CLEAR(dset) (bzero((caddr_t)(dset), \ - sizeof (idnneg_dset_t))) -#define IDNNEG_DSET_MYMASK() (idn_domain[idn.localid].dcpu) - -#define IDNNEG_DSET_INIT(dset, mask) \ - { \ - __IDNNEG_DSET_CLEAR(dset); \ - IDNNEG_DSET_SET((dset), idn.localid, (mask), idn.localid); \ - } - -#define IDNNEG_DSET_SET(dset, domid, cpuid, mask) \ - { \ - uint_t _s = ((domid) & 0xf) * 6; \ - int _i = _s >> 5; \ - uint_t _s0 = _s & 0x1f; \ - uint_t _t = ((cpuid) ^ (mask)) & 0x3f; \ - /*LINTED*/ \ - ASSERT(((domid) == idn.localid) ? \ - ((mask) == idn.localid) : ((cpuid) != (mask))); \ - (dset)[_i] |= _t << _s0; \ - if ((_s0 + 6) > 32) \ - (dset)[_i + 1] |= _t >> (32 - _s0); \ - } - -#define __IDNNEG_DSET_GET(dset, domid, cpuid, mask, uncond) \ - { \ - uint_t _s = ((domid) & 0xf) * 6; \ - int _i = _s >> 5; \ - uint_t _s0 = _s & 0x1f; \ - uint_t _s1 = (_s + 6) & 0x1f; \ - (cpuid) = ((dset)[_i] >> _s0) & 0x3f; \ - if ((_s0 + 6) > 32) \ - (cpuid) |= ((dset)[_i + 1] << (6 - _s1)) & 0x3f; \ - if ((cpuid) || (uncond)) \ - (cpuid) ^= (mask) & 0x3f; \ - else \ - (cpuid) = -1; \ - } - -#define IDNNEG_DSET_GET_MASK(dset, domid, mask) \ - __IDNNEG_DSET_GET((dset), (domid), (mask), (domid), 1) - -#define IDNNEG_DSET_GET_MASTER(dset, master) \ - __IDNNEG_DSET_GET((dset), idn.localid, (master), \ - idn.localid+MAX_DOMAINS, 0) - -#define IDNNEG_DSET_SET_MASTER(dset, domid, master) \ - IDNNEG_DSET_SET((dset), (domid), (master), \ - (domid)+MAX_DOMAINS) - -#define IDNNEG_DSET_GET(dset, domid, cpuid, mask) \ - __IDNNEG_DSET_GET((dset), (domid), (cpuid), (mask), 0) - -/* - * IDNP_CFG sub-types. - * - * Format of first 32 bit word in XDC: - * stX = sub-type. - * staX = sub-type arg. - * X = position in idn_cfgsubtype_t.param.p[] array. - * num = number of parameters in this XDC (0-3) - * - * 31...28,27...24,23...20,19...16,15...12,11....8,7.....3,2....0 - * | st0 . sta0 | st1 . sta1 | st2 . sta2 | phase | num | - * -------------------------------------------------------------- - * - * Note that since the first 32-bit word in a (IDNP_CFG) XDC is used - * for a sub-type, subsequent three 32-bits words are used for data that - * pertains to respective sub-type, i.e. first sub-type corresponds - * to first of the 3x32-bit words (pos=0), second sub-type corresponds - * to second of the 3x32-bit words (pos=1), etc. Obviously, a max of - * only three sub-types can be sent per xdc. - */ -#define IDNCFG_BARLAR 0x1 /* SMR base/limit pfn */ -#define IDNCFGARG_BARLAR_BAR 0 /* BAR */ -#define IDNCFGARG_BARLAR_LAR 1 /* LAR */ -#define IDNCFG_MCADR 0x2 /* MC ADR, arg = board number */ -#define IDNCFG_NMCADR 0x3 /* Number of MC ADRs to expect */ -#define IDNCFG_CPUSET 0x4 /* dcpuset of remote domain */ -#define IDNCFGARG_CPUSET_UPPER 0 /* 1st word */ -#define IDNCFGARG_CPUSET_LOWER 1 /* 2nd word */ -#define IDNCFG_NETID 0x5 /* dnetid, arg = 0 */ -#define IDNCFG_BOARDSET 0x6 /* board set, arg = 0 */ -#define IDNCFG_SIZE 0x7 /* SMR size parameters */ -#define IDNCFGARG_SIZE_MTU 0 /* IDN_MTU */ -#define IDNCFGARG_SIZE_BUF 1 /* IDN_SMR_BUFSIZE */ -#define IDNCFGARG_SIZE_SLAB 2 /* IDN_SLAB_BUFCOUNT */ -#define IDNCFGARG_SIZE_NWR 3 /* IDN_NWR_SIZE */ -#define IDNCFG_DATAMBOX 0x8 /* SMR data mailbox info */ -#define IDNCFGARG_DATAMBOX_TABLE 0 /* recvmbox table */ -#define IDNCFGARG_DATAMBOX_DOMAIN 1 /* domain's recvmbox */ -#define IDNCFGARG_DATAMBOX_INDEX 2 /* domain's index into table */ -#define IDNCFG_DATASVR 0x9 /* Data server info */ -#define IDNCFGARG_DATASVR_MAXNETS 0 /* max # of nets/channels */ -#define IDNCFGARG_DATASVR_MBXPERNET 1 /* # mbox per net/channel */ -#define IDNCFG_OPTIONS 0xa /* various options */ -#define IDNCFGARG_CHECKSUM 0 /* IDN_CHECKSUM */ - -#define IDN_CFGPARAM(st, sta) ((uchar_t)((((st) & 0xf) << 4) | ((sta) & 0xf))) -#define IDN_CFGPARAM_TYPE(p) (((p) >> 4) & 0xf) -#define IDN_CFGPARAM_ARG(p) ((p) & 0xf) - -typedef union { - struct { - uchar_t p[3]; - uchar_t _num_phase; /* info.num, info.phase used instead */ - } param; - struct { - uint_t _p : 24; /* param.p[] used instead */ - uint_t num : 2; - uint_t phase : 6; - } info; - uint_t val; -} idn_cfgsubtype_t; - -/* - * IDN_MASTER_NCFGITEMS - * Minimum number of config items expected from master. - * - * IDN_SLAVE_NCFGITEMS - * Number of config items expected from slave. - */ -#define IDN_MASTER_NCFGITEMS 17 /* max = +14 (mcadrs) */ -#define IDN_SLAVE_NCFGITEMS 12 - -/* - * IDNP_CMD sub-types. - */ -typedef enum { -/* 1 */ IDNCMD_SLABALLOC = 1, /* Request to allocate a slab */ -/* 2 */ IDNCMD_SLABFREE, /* Request to free a slab */ -/* 3 */ IDNCMD_SLABREAP, /* Reap any free slabs */ -/* 4 */ IDNCMD_NODENAME /* Query nodename of domain */ -} idn_cmd_t; - -#define VALID_IDNCMD(c) (((int)(c) >= (int)IDNCMD_SLABALLOC) && \ - ((int)(c) <= (int)IDNCMD_NODENAME)) -/* - * IDNP_NACK - */ -typedef enum { -/* 1 */ IDNNACK_NOCONN = 1, -/* 2 */ IDNNACK_BADCHAN, -/* 3 */ IDNNACK_BADCFG, -/* 4 */ IDNNACK_BADCMD, -/* 5 */ IDNNACK_RETRY, -/* 6 */ IDNNACK_DUP, -/* 7 */ IDNNACK_EXIT, -/* 8 */ IDNNACK_RESERVED1, -/* 9 */ IDNNACK_RESERVED2, -/* 10 */ IDNNACK_RESERVED3 -} idn_nack_t; - -/* - * IDNP_CON sub-types. - */ -typedef enum { -/* 0 */ IDNCON_OFF = 0, -/* 1 */ IDNCON_NORMAL, /* regular connect sequence */ -/* 2 */ IDNCON_QUERY /* query for connect info */ -} idn_con_t; - -/* - * IDNP_FIN sub-types. - */ -typedef enum { -/* 0 */ IDNFIN_OFF = 0, /* active, no fin */ -/* 1 */ IDNFIN_NORMAL, /* normal disconnect req */ -/* 2 */ IDNFIN_FORCE_SOFT, /* normal dis, force if goes AWOL */ -/* 3 */ IDNFIN_FORCE_HARD, /* force disconnect of AWOL domain */ -/* 4 */ IDNFIN_QUERY /* query for fin info */ -} idn_fin_t; - -#define VALID_FIN(f) (((int)(f) > 0) && \ - ((int)(f) < (int)IDNFIN_QUERY)) -#define FIN_IS_FORCE(f) (((f) == IDNFIN_FORCE_SOFT) || \ - ((f) == IDNFIN_FORCE_HARD)) - -/* - * FIN ARG types - reasons a FIN was sent. - */ -typedef enum { -/* 0 */ IDNFIN_ARG_NONE = 0, /* no argument */ -/* 1 */ IDNFIN_ARG_SMRBAD, /* SMR is corrupted */ -/* 2 */ IDNFIN_ARG_CPUCFG, /* missing cpu per board */ -/* 3 */ IDNFIN_ARG_HWERR, /* error programming hardware */ -/* 4 */ IDNFIN_ARG_CFGERR_FATAL, /* Fatal error during CONFIG */ -/* 5 */ IDNFIN_ARG_CFGERR_MTU, /* MTU sizes conflict */ -/* 6 */ IDNFIN_ARG_CFGERR_BUF, /* SMR_BUF_SIZE conflicts */ -/* 7 */ IDNFIN_ARG_CFGERR_SLAB, /* SLAB sizes conflict */ -/* 8 */ IDNFIN_ARG_CFGERR_NWR, /* NWR sizes conflict */ -/* 9 */ IDNFIN_ARG_CFGERR_NETS, /* MAX_NETS conflict */ -/* 10 */ IDNFIN_ARG_CFGERR_MBOX, /* MBOX_PER_NET conflict */ -/* 11 */ IDNFIN_ARG_CFGERR_NMCADR, /* NMCADR mismatches actual */ -/* 12 */ IDNFIN_ARG_CFGERR_MCADR, /* missing some MCADRs */ -/* 13 */ IDNFIN_ARG_CFGERR_CKSUM, /* checksum settings conflict */ -/* 14 */ IDNFIN_ARG_CFGERR_SMR /* SMR sizes conflict */ -} idn_finarg_t; - -#define IDNFIN_ARG_IS_FATAL(fa) ((fa) > IDNFIN_ARG_NONE) - -#define SET_FIN_TYPE(x, t) \ - ((x) &= 0xffff, (x) |= (((uint_t)(t) & 0xffff) << 16)) -#define SET_FIN_ARG(x, a) \ - ((x) &= ~0xffff, (x) |= ((uint_t)(a) & 0xffff)) -#define GET_FIN_TYPE(x) ((idn_fin_t)(((x) >> 16) & 0xffff)) -#define GET_FIN_ARG(x) ((idn_finarg_t)((x) & 0xffff)) - -#define FINARG2IDNKERR(fa) \ - (((fa) == IDNFIN_ARG_SMRBAD) ? IDNKERR_SMR_CORRUPTED : \ - ((fa) == IDNFIN_ARG_CPUCFG) ? IDNKERR_CPU_CONFIG : \ - ((fa) == IDNFIN_ARG_HWERR) ? IDNKERR_HW_ERROR : \ - ((fa) == IDNFIN_ARG_CFGERR_FATAL) ? IDNKERR_HW_ERROR : \ - ((fa) == IDNFIN_ARG_CFGERR_MTU) ? IDNKERR_CONFIG_MTU : \ - ((fa) == IDNFIN_ARG_CFGERR_BUF) ? IDNKERR_CONFIG_BUF : \ - ((fa) == IDNFIN_ARG_CFGERR_SLAB) ? IDNKERR_CONFIG_SLAB : \ - ((fa) == IDNFIN_ARG_CFGERR_NWR) ? IDNKERR_CONFIG_NWR : \ - ((fa) == IDNFIN_ARG_CFGERR_NETS) ? IDNKERR_CONFIG_NETS : \ - ((fa) == IDNFIN_ARG_CFGERR_MBOX) ? IDNKERR_CONFIG_MBOX : \ - ((fa) == IDNFIN_ARG_CFGERR_NMCADR) ? IDNKERR_CONFIG_NMCADR : \ - ((fa) == IDNFIN_ARG_CFGERR_MCADR) ? IDNKERR_CONFIG_MCADR : \ - ((fa) == IDNFIN_ARG_CFGERR_CKSUM) ? IDNKERR_CONFIG_CKSUM : \ - ((fa) == IDNFIN_ARG_CFGERR_SMR) ? IDNKERR_CONFIG_SMR : 0) - -/* - * FIN SYNC types. - */ -#define IDNFIN_SYNC_OFF 0 /* not set */ -#define IDNFIN_SYNC_NO 1 /* no-sync necessary */ -#define IDNFIN_SYNC_YES 2 /* do fin synchronously */ - -typedef short idn_finsync_t; - -/* - * IDNP_FIN options. - */ -typedef enum { -/* 0 */ IDNFIN_OPT_NONE = 0, /* none (used w/query) */ -/* 1 */ IDNFIN_OPT_UNLINK, /* normal unlink request */ -/* 2 */ IDNFIN_OPT_RELINK /* disconnect and retry link */ -} idn_finopt_t; - -#define VALID_FINOPT(f) (((f) == IDNFIN_OPT_UNLINK) || \ - ((f) == IDNFIN_OPT_RELINK)) - -#define FIN_MASTER_DOMID(x) (((((x) >> 16) & 0xffff) == 0xffff) ? \ - IDN_NIL_DOMID : (((x) >> 16) & 0xffff)) -#define FIN_MASTER_CPUID(x) ((((x) & 0xffff) == 0xffff) ? \ - IDN_NIL_DCPU : ((x) & 0xfff)) -#define MAKE_FIN_MASTER(d, c) ((((uint_t)(d) & 0xffff) << 16) | \ - ((uint_t)(c) & 0xffff)) -#define NIL_FIN_MASTER MAKE_FIN_MASTER(IDN_NIL_DOMID, IDN_NIL_DCPU) - -#ifdef DEBUG -#define IDN_FSTATE_TRANSITION(dp, ns) \ - { \ - int _id; \ - _id = (dp)->domid; \ - if ((dp)->dfin != (ns)) { \ - hrtime_t tstamp; \ - tstamp = TIMESTAMP(); \ - IDN_HISTORY_LOG(IDNH_FIN, _id, (ns), 0); \ - PR_STATE("FSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \ - "%s(%d) -> %s(%d)\n", \ - (uint64_t)tstamp, _id, \ - __LINE__, \ - ((dp)->dcpu == IDN_NIL_DCPU) ? -1 : \ - CPUID_TO_BOARDID((dp)->dcpu), \ - (dp)->dcpu, \ - idnfin_str[(dp)->dfin], (dp)->dfin, \ - idnfin_str[ns], (ns)); \ - (dp)->dfin = (ns); \ - } \ - } -#else -#define IDN_FSTATE_TRANSITION(dp, ns) \ - { \ - IDN_HISTORY_LOG(IDNH_FIN, (dp)->domid, (ns), 0); \ - (dp)->dfin = (ns); \ - } -#endif /* DEBUG */ - -#endif /* !_ASM */ -#endif /* _KERNEL */ - -#ifndef _ASM -/* - * IDN Per-Domain States. - */ -typedef enum { -/* 0 */ IDNDS_CLOSED, /* idle */ -/* 1 */ IDNDS_NEGO_PEND, /* link initiating */ -/* 2 */ IDNDS_NEGO_SENT, /* link initiated, nego sent */ -/* 3 */ IDNDS_NEGO_RCVD, /* link wanted, nego+ack sent */ -/* 4 */ IDNDS_CONFIG, /* passing config info, prgm hw */ -/* 5 */ IDNDS_CON_PEND, /* connection pending */ -/* 6 */ IDNDS_CON_SENT, /* con sent */ -/* 7 */ IDNDS_CON_RCVD, /* con sent & received */ -/* 8 */ IDNDS_CON_READY, /* ready to establish link */ -/* 9 */ IDNDS_CONNECTED, /* established - linked */ -/* 10 */ IDNDS_FIN_PEND, /* unlink initiating */ -/* 11 */ IDNDS_FIN_SENT, /* unlink initiated, fin sent */ -/* 12 */ IDNDS_FIN_RCVD, /* unlink wanted by remote */ -/* 13 */ IDNDS_DMAP /* deprogramming hw */ -} idn_dstate_t; - -#define IDNDS_IS_CLOSED(dp) (((dp)->dstate == IDNDS_CLOSED) || \ - ((dp)->dstate == IDNDS_DMAP)) -#define IDNDS_IS_CONNECTING(dp) (((dp)->dstate > IDNDS_CLOSED) && \ - ((dp)->dstate < IDNDS_CONNECTED)) -#define IDNDS_IS_DISCONNECTING(dp) ((dp)->dstate > IDNDS_CONNECTED) -#define IDNDS_CONFIG_DONE(dp) (((dp)->dstate == IDNDS_CLOSED) || \ - ((dp)->dstate > IDNDS_CONFIG)) -#define IDNDS_SYNC_TYPE(dp) (((dp)->dfin_sync != IDNFIN_SYNC_OFF) ? \ - (dp)->dfin_sync : \ - ((dp)->dstate < IDNDS_CON_READY) ? \ - IDNFIN_SYNC_NO : IDNFIN_SYNC_YES) - -#endif /* !_ASM */ - -#ifdef _KERNEL -#ifndef _ASM -/* - * --------------------------------------------------------------------- - */ -typedef struct idn_timer { - struct idn_timer *t_forw, - *t_back; - struct idn_timerq *t_q; - - timeout_id_t t_id; - short t_domid; - short t_onq; - ushort_t t_type; - ushort_t t_subtype; - uint_t t_cookie; -#ifdef DEBUG - hrtime_t t_posttime; - hrtime_t t_exectime; -#endif /* DEBUG */ -} idn_timer_t; - -#define IDN_TIMER_PUBLIC_COOKIE 0xf - -#define IDN_TIMERQ_IS_LOCKED(tq) (MUTEX_HELD(&(tq)->tq_mutex)) -#define IDN_TIMERQ_LOCK(tq) (mutex_enter(&(tq)->tq_mutex)) -#define IDN_TIMERQ_UNLOCK(tq) (mutex_exit(&(tq)->tq_mutex)) - -#define IDN_TIMERQ_INIT(tq) (idn_timerq_init(tq)) -#define IDN_TIMERQ_DEINIT(tq) (idn_timerq_deinit(tq)) -#define IDN_TIMER_ALLOC() (idn_timer_alloc()) -#define IDN_TIMER_FREE(tp) (idn_timer_free(tp)) - -#define IDN_TIMER_START(tq, tp, tim) \ - (idn_timer_start((tq), (tp), (tim))) -#define IDN_TIMER_STOP(tq, typ, ck) \ - ((void) idn_timer_stop((tq), (typ), (ck))) -#define IDN_TIMER_STOPALL(tp) \ - ((void) idn_timer_stopall(tp)) -#define IDN_TIMER_GET(tq, typ, tp, ck) \ - { \ - mutex_enter(&((tq)->tq_mutex)); \ - (tp) = idn_timer_get((tq), (typ), (ck)); \ - mutex_exit(&((tq)->tq_mutex)); \ - } -#define IDN_TIMER_DEQUEUE(tq, tp) \ - (idn_timer_dequeue((tq), (tp))) -#ifdef DEBUG -#define IDN_TIMER_POST(tp) \ - ((tp)->t_posttime = gethrtime(), (tp)->t_exectime = 0) -#define IDN_TIMER_EXEC(tp) ((tp)->t_exectime = gethrtime()) -#else /* DEBUG */ -#define IDN_TIMER_POST(tp) -#define IDN_TIMER_EXEC(tp) -#endif /* DEBUG */ - -#define IDN_MSGTIMER_START(domid, typ, subtyp, tim, ckp) \ - { \ - idn_timer_t *_tp; \ - char _str[15]; \ - ushort_t *_ckp = (ckp); \ - inum2str((typ), _str); \ - PR_TIMER("msgtimer:%d: START: type = %s (0x%x)\n", \ - (domid), _str, (typ)); \ - _tp = IDN_TIMER_ALLOC(); \ - _tp->t_type = (ushort_t)(typ); \ - _tp->t_subtype = (ushort_t)(subtyp); \ - _tp->t_domid = (short)(domid); \ - _tp->t_cookie = (_ckp) ? *(_ckp) : 0; \ - IDN_TIMER_POST(_tp); \ - if (_ckp) { \ - *(_ckp) = IDN_TIMER_START(&idn_domain[domid].dtimerq, \ - _tp, (tim)); \ - } else { \ - (void) IDN_TIMER_START(&idn_domain[domid].dtimerq, \ - _tp, (tim)); \ - } \ - } -#define IDN_MSGTIMER_STOP(domid, typ, ck) \ - { \ - char _str[15]; \ - inum2str((typ), _str); \ - PR_TIMER("msgtimer:%d: STOP: type = %s (0x%x), " \ - "cookie = 0x%x\n", \ - (domid), _str, (typ), (ck)); \ - IDN_TIMER_STOP(&idn_domain[domid].dtimerq, (typ), (ck)); \ - } -#define IDN_MSGTIMER_GET(dp, typ, tp, ck) \ - IDN_TIMER_GET(&(dp)->dtimerq, (typ), (tp), (ck)) - -/* - * IDN_SLABALLOC_WAITTIME - * Max wait time in ticks that local domains waits for - * master to respond to a slab allocation request. Has - * to be at least as long as wait time for a response to - * the command. - */ -#define IDN_SLABALLOC_WAITTIME ((3 * idn_msg_waittime[IDNP_CMD]) / 2) - -/* - * Domain state transition macros. - */ -#ifdef DEBUG -#define IDN_DSTATE_TRANSITION(dp, ns) \ - { \ - int id; \ - hrtime_t tstamp; \ - tstamp = TIMESTAMP(); \ - ASSERT(RW_WRITE_HELD(&(dp)->drwlock)); \ - id = (dp)->domid; \ - IDN_HISTORY_LOG(IDNH_DSTATE, id, (ns), \ - (uint_t)(dp)->dcpu); \ - PR_STATE("DSTATE:%ld:%d: (l=%d, b/p=%d/%d) " \ - "%s(%d) -> %s(%d)\n", \ - (uint64_t)tstamp, id, \ - __LINE__, \ - ((dp)->dcpu == IDN_NIL_DCPU) ? \ - -1 : CPUID_TO_BOARDID((dp)->dcpu), \ - (dp)->dcpu, \ - idnds_str[(dp)->dstate], (dp)->dstate, \ - idnds_str[ns], (ns)); \ - (dp)->dstate = (ns); \ - IDNSB_DOMAIN_UPDATE(dp); \ - } -#else -#define IDN_DSTATE_TRANSITION(dp, ns) \ - { \ - IDN_HISTORY_LOG(IDNH_DSTATE, (dp)->domid, \ - (ns), (uint_t)(dp)->dcpu); \ - (dp)->dstate = (ns); \ - IDNSB_DOMAIN_UPDATE(dp); \ - } -#endif /* DEBUG */ - -#define IDN_XSTATE_TRANSITION(dp, xs) \ - { \ - int _xs = (xs); \ - (dp)->dxstate = _xs; \ - if (_xs != IDNXS_NIL) { \ - ASSERT((dp)->dxp); \ - IDN_DSTATE_TRANSITION((dp), \ - (dp)->dxp->xt_trans[_xs].t_state); \ - } \ - } - -/* - * --------------------------------------------------------------------- - * IDN Per-Domain Data - * - * The comment to the right of the respective field represents - * what lock protects that field. If there is no comment then - * no lock is required to access the field. - * --------------------------------------------------------------------- - */ - -#define MAXDNAME 32 - -typedef struct idn_domain { - krwlock_t drwlock; - /* - * Assigned domid for domain. Never - * changes once idn_domain[] is - * initialized. We are guaranteed that - * all domains in IDN will have a - * uniqueue domid in the range (0-15). - */ - int domid; - idn_dstate_t dstate; /* drwlock */ - idn_xstate_t dxstate; /* drwlock */ - /* - * Gotten from uname -n for local - * domain. Remote domains pass - * theirs during Config phase. - */ - char dname[MAXDNAME]; /* drwlock */ - /* - * IDN-wide unique identifier for the - * given domain. This value will be - * the same as the domid. - */ - ushort_t dnetid; /* drwlock */ - idn_vote_t dvote; /* drwlock */ - /* - * Used during FIN sequenece to - * determine what type of shutdown - * (unlink) we're executing with - * respect to the given domain. - */ - idn_fin_t dfin; /* drwlock */ - /* - * A non-zero value for dfin_sync - * indicates that unlink of respective - * domain does not need to be performed - * synchronously among all the IDN - * member domains. - */ - short dfin_sync; /* grwlock */ - /* - * Cookie used to determine the - * proper context in which we're - * receiving messages from the given - * domain. Assigned cookies are exchanged - * during initial NEGO messages. - */ - ushort_t dcookie_send; /* drwlock */ - ushort_t dcookie_recv; /* drwlock */ - short dcookie_err; /* drwlock */ - int dcookie_errcnt; /* drwlock */ - /* - * Primary target cpu for sending - * messages. Can change to help - * distribute interrupts on receiving - * side. - */ - int dcpu; /* drwlock */ - /* - * Used to store dcpu from a previous - * life. Only used when requesting - * a RELINK with a domain we were just - * previously linked with. Thus, it - * does represent a valid cpu in the - * remote domain. - */ - int dcpu_save; /* drwlock */ - /* - * Used to store from which cpu the - * last message was received. - */ - int dcpu_last; - /* - * Transition phase area. This field - * points to the proper phase structure - * depending on what stage the given - * domain is in. - */ - idn_xphase_t *dxp; /* drwlock */ - /* - * Actual synchronization object for - * the given domain. - */ - idn_syncop_t dsync; /* drwlock & idn.sync.sz_mutex */ - /* - * Slab information for given domain. - * If the local domain is a master, - * then this field in each domain is used - * to store which slabs have been assigned - * to given domain. If the local domain - * is a slave, then this information is - * NULL for all remote idn_domain[] - * entries, but for local domain holds - * those slabs assigned to local domain. - */ - smr_slab_t *dslab; /* dslab_rwlock */ - short dnslabs; /* dslab_rwlock */ - short dslab_state; /* dslab_rwlock */ - krwlock_t dslab_rwlock; - /* - * Set of cpus belonging to domain. - */ - cpuset_t dcpuset; /* drwlock */ - - int dncpus; /* drwlock */ - /* - * Index into dcpumap to determine - * which cpu to target next for - * interrupt. Intended to allow fair - * distribution of interrupts on - * remote domain. - */ - uint_t dcpuindex; /* drwlock */ - /* - * Quick look-up map of cpus belonging - * to domain. Used to select next target. - */ - uchar_t *dcpumap; /* drwlock */ - /* - * Non-zero indicates outstanding - * I/O's to given domain. - */ - int dio; /* drwlock */ - int dioerr; /* drwlock */ - /* - * Set when we fail to allocate a buffer - * for a domain. Dictates whether to - * reclaim max buffers or not. - */ - lock_t diowanted; - /* - * Set when remote domain does not - * seem to be picking up messages sent - * to it. Non-zero indicates we have - * an outstanding "ping" to domain. - */ - lock_t diocheck; /* drwlock */ - short dslabsize; /* drwlock */ - uint_t dmtu; /* drwlock */ - - uint_t dbufsize; /* drwlock */ - short dnwrsize; /* drwlock */ - lock_t dreclaim_inprogress; /* drwlock */ - uchar_t dreclaim_index; /* drwlock */ - /* - * The following field is primarily - * used during CFG exchange to keep - * track of certain per-domain information. - */ - union { /* all - drwlock */ - struct { - uint_t _dcfgphase : 6; - uint_t _dcfgsnddone : 1; - uint_t _dcfgrcvdone : 1; - uint_t _dcksum : 2; - uint_t _dmaxnets : 6; - uint_t _dmboxpernet : 9; - uint_t _dncfgitems : 6; - uint_t _drecfg : 1; - } _s; - int _dtmp; - } _u; - /* - * Each domain entry maintains a - * timer queue holding timers for - * messages outstanding to that domain. - */ - struct idn_timerq { - int tq_cookie; /* tq_mutex */ - kmutex_t tq_mutex; - int tq_count; /* tq_mutex */ - idn_timer_t *tq_queue; /* tq_mutex */ - } dtimerq; - /* - * dawol is used to keep - * track of AWOL details for - * given domain when it is - * non-responsive. - */ - struct { - int a_count; /* drwlock */ - clock_t a_time; /* drwlock */ - clock_t a_last; /* drwlock */ - clock_t a_msg; /* drwlock */ - } dawol; - - struct hwconfig { - short dh_nboards; /* drwlock */ - short dh_nmcadr; /* drwlock */ - boardset_t dh_boardset; /* drwlock */ - uint_t dh_mcadr[MAX_BOARDS]; /* drwlock */ - } dhw; - /* - * Mailbox information used to - * send/recv messages to given domain. - */ - struct { - kmutex_t m_mutex; - struct idn_mboxtbl *m_tbl; /* m_mutex */ - struct idn_mainmbox *m_send; /* m_mutex */ - struct idn_mainmbox *m_recv; /* m_mutex */ - } dmbox; -} idn_domain_t; - -typedef struct idn_timerq idn_timerq_t; - -#define dcfgphase _u._s._dcfgphase -#define dcfgsnddone _u._s._dcfgsnddone -#define dcfgrcvdone _u._s._dcfgrcvdone -#define dcksum _u._s._dcksum -#define dmaxnets _u._s._dmaxnets -#define dmboxpernet _u._s._dmboxpernet -#define dncfgitems _u._s._dncfgitems -#define drecfg _u._s._drecfg -#define dbindport _u._dbindport -#define dconnected _u._dconnected -#define dtmp _u._dtmp - -#define IDN_DLOCK_EXCL(dd) (rw_enter(&idn_domain[dd].drwlock, RW_WRITER)) -#define IDN_DLOCK_SHARED(dd) (rw_enter(&idn_domain[dd].drwlock, RW_READER)) -#define IDN_DLOCK_TRY_SHARED(dd) \ - (rw_tryenter(&idn_domain[dd].drwlock, \ - RW_READER)) -#define IDN_DLOCK_DOWNGRADE(dd) (rw_downgrade(&idn_domain[dd].drwlock)) -#define IDN_DUNLOCK(dd) (rw_exit(&idn_domain[dd].drwlock)) -#define IDN_DLOCK_IS_EXCL(dd) (RW_WRITE_HELD(&idn_domain[dd].drwlock)) -#define IDN_DLOCK_IS_SHARED(dd) (RW_READ_HELD(&idn_domain[dd].drwlock)) -#define IDN_DLOCK_IS_HELD(dd) (RW_LOCK_HELD(&idn_domain[dd].drwlock)) - -#define IDN_MBOX_LOCK(dd) (mutex_enter(&idn_domain[dd].dmbox.m_mutex)) -#define IDN_MBOX_UNLOCK(dd) (mutex_exit(&idn_domain[dd].dmbox.m_mutex)) - -#define IDN_RESET_COOKIES(dd) \ - (idn_domain[dd].dcookie_send = idn_domain[dd].dcookie_recv = 0) - -#define DSLAB_STATE_UNKNOWN 0 -#define DSLAB_STATE_LOCAL 1 -#define DSLAB_STATE_REMOTE 2 - -#define DSLAB_READ_HELD(d) RW_READ_HELD(&idn_domain[d].dslab_rwlock) -#define DSLAB_WRITE_HELD(d) RW_WRITE_HELD(&idn_domain[d].dslab_rwlock) - -#define DSLAB_LOCK_EXCL(d) \ - rw_enter(&idn_domain[d].dslab_rwlock, RW_WRITER) -#define DSLAB_LOCK_SHARED(d) \ - rw_enter(&idn_domain[d].dslab_rwlock, RW_READER) -#define DSLAB_LOCK_TRYUPGRADE(d) \ - rw_tryupgrade(&idn_domain[d].dslab_rwlock) -#define DSLAB_UNLOCK(d) rw_exit(&idn_domain[d].dslab_rwlock) - -/* - * --------------------------------------------------------------------- - * Macro to pick another target for the given domain. This hopefully - * improves performance by better distributing the SSI responsibilities - * at the target domain. - * --------------------------------------------------------------------- - */ -#define BUMP_INDEX(set, index) \ - { \ - register int p; \ - for (p = (index)+1; p < NCPU; p++) \ - if (CPU_IN_SET((set), p)) \ - break; \ - if (p >= NCPU) \ - for (p = 0; p <= (index); p++) \ - if (CPU_IN_SET((set), p)) \ - break; \ - if (!CPU_IN_SET((set), p)) { \ - uint_t _u32, _l32; \ - _u32 = UPPER32_CPUMASK(set); \ - _l32 = LOWER32_CPUMASK(set); \ - cmn_err(CE_PANIC, \ - "IDN: cpu %d not in cpuset 0x%x.%0x\n", \ - p, _u32, _l32); \ - } \ - (index) = p; \ - } - -#define IDN_ASSIGN_DCPU(dp, cookie) \ - ((dp)->dcpu = (int)((dp)->dcpumap[(cookie) & (NCPU-1)])) - -/* - * --------------------------------------------------------------------- - * Atomic increment/decrement, swap, compare-swap functions. - * --------------------------------------------------------------------- - */ -#define ATOMIC_INC(v) atomic_inc_32((uint_t *)&(v)) -#define ATOMIC_DEC(v) atomic_dec_32((uint_t *)&(v)) -#define ATOMIC_SUB(v, n) atomic_add_32((uint_t *)&(v), -(n)) -#define ATOMIC_CAS(a, c, n) atomic_cas_32((uint32_t *)(a), (uint32_t)(c), \ - (uint32_t)(n)) -#define ATOMIC_SWAPL(a, v) atomic_swap_32((uint32_t *)(a), (uint32_t)(v)) - -/* - * DMV vector interrupt support. - * - * A fixed-size circular buffer is maintained as a queue of - * incoming interrupts. The low-level idn_dmv_handler() waits - * for an entry to become FREE and will atomically mark it INUSE. - * Once it has filled in the appropriate fields it will be marked - * as READY. The high-level idn_handler() will be invoked and will - * process all messages in the queue that are READY. Each message - * is marked PROCESS, a protojob job created and filled in, and - * then the interrupt message is marked FREE for use in the next - * interrupt. The iv_state field is used to hold the relevant - * state and is updated atomically. - */ -#define IDN_PIL PIL_8 -#define IDN_DMV_PENDING_MAX 128 /* per cpu */ - -#endif /* !_ASM */ - -#ifndef _ASM - -/* - * The size of this structure must be a power of 2 - * so that we can do a simple shift to calculate - * our offset into based on cpuid. - */ -typedef struct idn_dmv_cpu { - uint32_t idn_dmv_current; - int32_t idn_dmv_lostintr; - lock_t idn_dmv_active; - char _padding[(2 * sizeof (uint64_t)) - \ - sizeof (uint32_t) - \ - sizeof (lock_t) - \ - sizeof (int32_t)]; -} idn_dmv_cpu_t; - -typedef struct idn_dmv_data { - uint64_t idn_soft_inum; - uint64_t idn_dmv_qbase; - idn_dmv_cpu_t idn_dmv_cpu[NCPU]; -} idn_dmv_data_t; - -/* - * Requirements of the following data structure: - * - MUST be double-word (8 bytes) aligned. - * - _iv_head field MUST start on double-word boundary. - * - iv_xargs0 MUST start on double-word boundary - * with iv_xargs1 immediately following. - * - iv_xargs2 MUST start on double-word boundary - * with iv_xargs3 immediately following. - */ -typedef struct idn_dmv_msg { - uint32_t iv_next; /* offset */ - uchar_t iv_inuse; - uchar_t iv_ready; - ushort_t _padding; - uint32_t iv_head : 16; - uint32_t iv_cookie : 16; - uint32_t iv_ver : 8; - uint32_t iv_mtype : 6; - uint32_t iv_atype : 6; - uint32_t iv_domid : 4; - uint32_t iv_cpuid : 8; - uint32_t iv_xargs0; - uint32_t iv_xargs1; - uint32_t iv_xargs2; - uint32_t iv_xargs3; -} idn_dmv_msg_t; - -extern uint_t idn_dmv_inum; -extern uint_t idn_soft_inum; - -/* - * An IDN-network address has the following format: - * - * 31......16,15........0 - * | channel | dnetid | - * ---------------------- - * channel - network interface. - * netid - idn_domain[].dnetid - */ -#define IDN_MAXMAX_NETS 32 -#define IDN_BROADCAST_ALLCHAN ((ushort_t)-1) -#define IDN_BROADCAST_ALLNETID ((ushort_t)-1) - -typedef union { - struct { - ushort_t chan; - ushort_t netid; - } net; - uint_t netaddr; -} idn_netaddr_t; - -#define CHANSET_ALL (~((idn_chanset_t)0)) -#define CHANSET(c) \ - ((idn_chanset_t)1 << ((c) & 31)) -#define CHAN_IN_SET(m, c) \ - (((m) & ((idn_chanset_t)1 << ((c) & 31))) != 0) -#define CHANSET_ADD(m, c) \ - ((m) |= ((idn_chanset_t)1 << ((c) & 31))) -#define CHANSET_DEL(m, c) \ - ((m) &= ~((idn_chanset_t)1 << ((c) & 31))) -#define CHANSET_ZERO(m) ((m) = 0) - -typedef enum { -/* 0 */ IDNCHAN_OPEN, -/* 1 */ IDNCHAN_SOFT_CLOSE, -/* 2 */ IDNCHAN_HARD_CLOSE, -/* 3 */ IDNCHAN_OFFLINE, -/* 4 */ IDNCHAN_ONLINE -} idn_chanop_t; - -/* - * Retry support. - */ -#define IDN_RETRY_TOKEN(d, x) ((((d) & 0xf) << 16) | \ - (0xffff & (uint_t)(x))) -#define IDN_RETRY_TOKEN2DOMID(t) ((int)(((t) >> 16) & 0xf)) -#define IDN_RETRY_TOKEN2TYPE(t) ((idn_retry_t)((t) & 0xffff)) -#define IDN_RETRY_TYPEALL ((idn_retry_t)0xffff) -#define IDN_RETRY_INTERVAL hz /* 1 sec */ -#define IDN_RETRY_RECFG_MULTIPLE 10 - -#define IDN_RETRYINTERVAL_NEGO (2 * hz) -#define IDN_RETRYINTERVAL_CON (2 * hz) -#define IDN_RETRYINTERVAL_FIN (2 * hz) - -typedef struct idn_retry_job { - struct idn_retry_job *rj_prev; - struct idn_retry_job *rj_next; - void (*rj_func)(uint_t token, void *arg); - void *rj_arg; - uint_t rj_token; - short rj_onq; - timeout_id_t rj_id; -} idn_retry_job_t; - -#define IDNRETRY_ALLOCJOB() \ - ((idn_retry_job_t *)kmem_cache_alloc(idn.retryqueue.rq_cache, KM_SLEEP)) -#define IDNRETRY_FREEJOB(j) \ - (kmem_cache_free(idn.retryqueue.rq_cache, (void *)(j))) - -typedef enum { -/* 0 */ IDNRETRY_NIL = 0, -/* 1 */ IDNRETRY_NEGO, -/* 2 */ IDNRETRY_CON, -/* 3 */ IDNRETRY_CONQ, /* for CON queries */ -/* 4 */ IDNRETRY_FIN, -/* 5 */ IDNRETRY_FINQ, /* for FIN queries */ -/* 6 */ IDN_NUM_RETRYTYPES -} idn_retry_t; - -/* - * --------------------------------------------------------------------- - */ -typedef struct { - int m_domid; - int m_cpuid; - ushort_t m_msgtype; - ushort_t m_acktype; - ushort_t m_cookie; - idn_xdcargs_t m_xargs; -} idn_protomsg_t; - -typedef struct idn_protojob { - struct idn_protojob *j_next; - int j_cache; - idn_protomsg_t j_msg; -} idn_protojob_t; - -typedef struct idn_protoqueue { - struct idn_protoqueue *q_next; - idn_protojob_t *q_joblist; - idn_protojob_t *q_joblist_tail; - int q_die; - int q_id; - ksema_t *q_morgue; - kthread_id_t q_threadp; - kcondvar_t q_cv; - kmutex_t q_mutex; -} idn_protoqueue_t; - -#define IDN_PROTOCOL_NSERVERS 4 -#define IDN_PROTOCOL_SERVER_HASH(d) ((d) % idn.nservers) -#define IDN_PROTOJOB_CHUNKS (idn.nservers) - -/* - * --------------------------------------------------------------------- - * Data Server definitions. - * - * idn_datasvr_t - Describes data server thread. - * . ds_id - Per-domain identifier for data server. - * . ds_domid - Domain which data server is handling. - * . ds_state - Flag to enable/disable/terminate - * data server. - * . ds_mboxp - Pointer to data server's (local) - * mailbox to be serviced. - * . ds_waittime - cv_timedwait sleep time before - * checking respective mailbox. - * . ds_threadp - Pointer to data server thread. - * . ds_cv - Condvar for sleeping. - * . ds_morguep - Semaphore for terminating thread. - * - * idn_mboxhdr_t - Resides in SMR space (MUST be cache_linesize). - * . mh_svr_active - Non-zero indicates data server is - * actively reading mailbox for messages. - * . mh_svr_ready - Non-zero indicates data server has - * allocated and is ready to accept data. - * . mh_cookie - Identifier primarily for debug purposes. - * - * idn_mboxmsg_t - Entry in the SMR space circular queue use to - * represent a data packet. - * . mm_owner - Non-zero indicates entry is available - * to be processed by receiver's data server. - * . mm_flag - Indicates whether entry needs to be - * reclaimed by the sender. Also holds error - * indications (e.g. bad offset). - * . mm_offset - SMR offset of respective data packet. - * - * idn_mboxtbl_t - Encapsulation of a per-domain mailbox (SMR space). - * . mt_header - Header information for synchronization. - * . mt_queue - Circular queue of idn_mboxmsg_t entries. - * - * idn_mainmbox_t - Encapsulation of main SMR recv/send mailboxes. - * . mm_mutex - Protects mm_* entries, enqueuing, and - * dequeuing of messages. Also protects - * updates to the route table pointed to - * by mm_routetbl. - * . mm_count - send: Current number of messages - * enqueued. - * - recv: Cumulative number of messages - * processed. - * . mm_max_count - send: Maximum number of messages - * enqueued per iteration. - * recv: Maximum number of messages - * dequeued per iteration. - * . mm_smr_mboxp - Pointer to SMR (vaddr) space where - * respective mailbox resides. - * --------------------------------------------------------------------- - */ -#define IDN_MBOXHDR_COOKIE_TOP ((uint_t)0xc0c0) -#define IDN_MAKE_MBOXHDR_COOKIE(pd, sd, ch) \ - ((IDN_MBOXHDR_COOKIE_TOP << 16) \ - | (((uint_t)(pd) & 0xf) << 12) \ - | (((uint_t)(sd) & 0xf) << 8) \ - | ((uint_t)(ch) & 0xf)) -#define IDN_GET_MBOXHDR_COOKIE(mhp) \ - ((mhp)->mh_cookie & ~0xff00) -#define VALID_MBOXHDR(mhp, ch, cksum) \ - ((IDN_GET_MBOXHDR_COOKIE(mhp) == \ - IDN_MAKE_MBOXHDR_COOKIE(0, 0, (ch))) && \ - ((cksum) == (*(mhp)).mh_cksum)) -/* - * The number of entries in a mailbox queue must be chosen so - * that (IDN_MMBOX_NUMENTRIES * sizeof (idn_mboxmsg_t)) is a multiple - * of a cacheline size (64). - */ -#define IDN_MMBOX_NUMENTRIES IDN_MBOX_PER_NET -/* - * We step through the mailboxes in effectively cacheline size - * incremenents so that the source and receiving cpus are not competing - * for the same cacheline when transmitting/receiving messages into/from - * the mailboxes. The hard requirement is that the step value be even - * since the mailbox size will be chosen odd. This allows us to wraparound - * the mailbox uniquely touching each entry until we've exhausted them - * all at which point we'll end up where we initially started and repeat - * again. - */ -#define IDN_MMBOXINDEX_STEP (((64 / sizeof (idn_mboxmsg_t)) + 1) & 0xfffe) -#define IDN_MMBOXINDEX_INC(i) \ - { \ - if (((i) += IDN_MMBOXINDEX_STEP) >= IDN_MMBOX_NUMENTRIES) \ - (i) -= IDN_MMBOX_NUMENTRIES; \ - } - -#define IDN_MMBOXINDEX_DIFF(i, j) \ - (((i) >= (j)) ? (((i) - (j)) / IDN_MMBOXINDEX_STEP) \ - : ((((i) + IDN_MMBOX_NUMENTRIES) - (j)) / IDN_MMBOXINDEX_STEP)) - -/* - * Require IDN_MBOXAREA_SIZE <= IDN_SLAB_SIZE so we don't waste - * slab space. - * - * Each domain maintains a MAX_DOMAIN(16) entry mbox_table. Each - * entry represents a receive mailbox for a possible domain to which - * the given domain may have a connection. The send mailbox for each - * respective domain is given to the local domain at the time of - * connection establishment. - */ - -/* - * --------------------------------------------------------------------- - */ -#define IDN_MBOXTBL_SIZE \ - (IDNROUNDUP(((IDN_MBOX_PER_NET * sizeof (idn_mboxmsg_t)) \ - + sizeof (idn_mboxhdr_t)), IDN_ALIGNSIZE)) - -/* - * --------------------------------------------------------------------- - * Each domain has idn_max_nets worth of possible mailbox tables - * for each domain to which it might possibly be connected. - * --------------------------------------------------------------------- - */ -#define IDN_MBOXAREA_SIZE \ - (IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS * MAX_DOMAINS) -#define IDN_MBOXAREA_OFFSET(d) \ - ((d) * IDN_MBOXTBL_SIZE * IDN_MAX_NETS * MAX_DOMAINS) - -/* - * --------------------------------------------------------------------- - * Return the base of the mailbox area (set of tables) assigned - * to the given domain id. - * --------------------------------------------------------------------- - */ -#define IDN_MBOXAREA_BASE(m, d) \ - ((idn_mboxtbl_t *)(((ulong_t)(m)) + IDN_MBOXAREA_OFFSET(d))) - -/* - * --------------------------------------------------------------------- - * Return the pointer to the respective receive mailbox (table set) - * for the given domain id relative to the given base mailbox table. - * --------------------------------------------------------------------- - */ -#define IDN_MBOXTBL_PTR(t, d) \ - ((idn_mboxtbl_t *)(((ulong_t)(t)) + ((d) * IDN_MBOXTBL_SIZE \ - * IDN_MAX_NETS))) -/* - * --------------------------------------------------------------------- - * Return the pointer to the actual target mailbox based on the - * given channel in the given mailbox table. - * --------------------------------------------------------------------- - */ -#define IDN_MBOXTBL_PTR_CHAN(t, c) \ - ((idn_mboxtbl_t *)(((ulong_t)(t)) + ((c) * IDN_MBOXTBL_SIZE))) - -#define IDN_MBOXTBL_PTR_INC(t) \ - ((t) = (idn_mboxtbl_t *)(((ulong_t)(t)) + IDN_MBOXTBL_SIZE)) - -#define IDN_MBOXCHAN_INC(i) \ - { \ - if (++(i) == IDN_MAX_NETS) \ - (i) = 0; \ - } - -/* - * --------------------------------------------------------------------- - * Return the absolute location within the entire mailbox area - * of the mboxtbl for the given primary and secondary domain and - * channel. Only relevant when done by the master. - * --------------------------------------------------------------------- - */ -#define IDN_MBOXTBL_ABS_PTR(mt, pd, sd, ch) \ - (IDN_MBOXTBL_PTR_CHAN( \ - IDN_MBOXTBL_PTR( \ - IDN_MBOXAREA_BASE((mt), (pd)), \ - (sd)), \ - (ch))) - -#define IDN_BFRAME_SHIFT idn.bframe_shift -#define IDN_BFRAME2OFFSET(bf) ((bf) << IDN_BFRAME_SHIFT) -#define IDN_BFRAME2ADDR(bf) IDN_OFFSET2ADDR(IDN_BFRAME2OFFSET(bf)) -#define IDN_OFFSET2BFRAME(off) (((off) >> IDN_BFRAME_SHIFT) & 0xffffff) -#define IDN_ADDR2BFRAME(addr) IDN_OFFSET2BFRAME(IDN_ADDR2OFFSET(addr)) - -typedef struct idn_mboxmsg { - uint_t ms_owner : 1, - ms_flag : 7, - ms_bframe : 24; -} idn_mboxmsg_t; - -typedef idn_mboxmsg_t idn_mboxq_t[1]; - -#define IDN_CKSUM_MBOX_COUNT (offsetof(idn_mboxhdr_t, mh_svr_ready) / 2) - -#define IDN_CKSUM_MBOX(h) \ - (IDN_CHECKSUM ? \ - idn_cksum((ushort_t *)(h), IDN_CKSUM_MBOX_COUNT) : 0) - -typedef struct idn_mboxhdr { - uint_t mh_cookie; - uint_t mh_svr_ready_ptr; - uint_t mh_svr_active_ptr; - ushort_t mh_svr_ready; - ushort_t mh_svr_active; - - uint_t _padding[(64 - - (4*sizeof (uint_t)) - - (2*sizeof (ushort_t))) / sizeof (uint_t)]; - - uint_t mh_cksum; -} idn_mboxhdr_t; - -typedef struct idn_mboxtbl { - idn_mboxhdr_t mt_header; - idn_mboxq_t mt_queue; -} idn_mboxtbl_t; - -#define IDN_CHAN_DOMAIN_REGISTER(csp, dom) \ - (DOMAINSET_ADD((csp)->ch_reg_domset, (dom))) - -#define IDN_CHAN_DOMAIN_UNREGISTER(csp, dom) \ - (DOMAINSET_DEL((csp)->ch_reg_domset, (dom))) - -#define IDN_CHAN_DOMAIN_IS_REGISTERED(csp, dom) \ - (DOMAIN_IN_SET((csp)->ch_reg_domset, (dom))) - -#define IDN_CHANSVR_SCANSET_ADD_PENDING(csp, dom) \ - { \ - register int _d; \ - register uint64_t _domset; \ - (dom) &= MAX_DOMAINS - 1; /* Assumes power of 2 */ \ - _domset = 0ull; \ - for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \ - if ((int)(((csp)->ch_recv_scanset_pending >> \ - (_d * 4)) & 0xf) == (dom)) \ - break; \ - else \ - _domset = (_domset << 4) | 0xfull; \ - } \ - if (_d == (csp)->ch_recv_domcount) { \ - _domset &= (csp)->ch_recv_scanset_pending; \ - _domset |= (uint64_t)(dom) << \ - ((csp)->ch_recv_domcount * 4); \ - (csp)->ch_recv_domcount++; \ - (csp)->ch_recv_scanset_pending = 0ull; \ - for (_d = 0; _d < 16; \ - _d += (csp)->ch_recv_domcount) { \ - (csp)->ch_recv_scanset_pending |= _domset; \ - _domset <<= (csp)->ch_recv_domcount * 4; \ - } \ - } \ - } -#define IDN_CHANSVR_SCANSET_DEL_PENDING(csp, dom) \ - { \ - register int _d; \ - register uint64_t _domset; \ - (dom) &= MAX_DOMAINS - 1; /* Assumes power of 2 */ \ - _domset = 0ull; \ - for (_d = 0; _d < (csp)->ch_recv_domcount; _d++) { \ - if ((int)(((csp)->ch_recv_scanset_pending >> \ - (_d * 4)) & 0xf) == (dom)) \ - break; \ - else \ - _domset = (_domset << 4) | 0xfull; \ - } \ - if (_d < (csp)->ch_recv_domcount) { \ - _domset &= (csp)->ch_recv_scanset_pending; \ - (csp)->ch_recv_scanset_pending >>= 4; \ - (csp)->ch_recv_domcount--; \ - for (; _d < (csp)->ch_recv_domcount; _d++) \ - _domset |= (csp)->ch_recv_scanset_pending &\ - (0xfull << (_d * 4)); \ - (csp)->ch_recv_scanset_pending = 0ull; \ - if ((csp)->ch_recv_domcount) { \ - for (_d = 0; _d < 16; \ - _d += (csp)->ch_recv_domcount) { \ - (csp)->ch_recv_scanset_pending |= \ - _domset; \ - _domset <<= \ - (csp)->ch_recv_domcount * 4; \ - } \ - } \ - } \ - } - -#define IDN_CHAN_TRYLOCK_GLOBAL(csp) \ - mutex_tryenter(&(csp)->ch_mutex) -#define IDN_CHAN_LOCK_GLOBAL(csp) \ - mutex_enter(&(csp)->ch_mutex) -#define IDN_CHAN_UNLOCK_GLOBAL(csp) \ - mutex_exit(&(csp)->ch_mutex) -#define IDN_CHAN_GLOBAL_IS_LOCKED(csp) \ - (MUTEX_HELD(&(csp)->ch_mutex)) - -#define IDN_CHAN_LOCAL_IS_LOCKED(csp) \ - (MUTEX_HELD(&(csp)->ch_send.c_mutex) && \ - MUTEX_HELD(&(csp)->ch_recv.c_mutex)) -#define IDN_CHAN_LOCK_LOCAL(csp) \ - (mutex_enter(&(csp)->ch_recv.c_mutex, \ - mutex_enter(&(csp)->ch_send.c_mutex)) -#define IDN_CHAN_UNLOCK_LOCAL(csp) \ - (mutex_exit(&(csp)->ch_send.c_mutex), \ - mutex_exit(&(csp)->ch_recv.c_mutex)) - -#define IDN_CHAN_RECV_IS_LOCKED(csp) \ - (MUTEX_HELD(&(csp)->ch_recv.c_mutex)) -#define IDN_CHAN_TRYLOCK_RECV(csp) \ - (mutex_tryenter(&(csp)->ch_recv.c_mutex)) -#define IDN_CHAN_LOCK_RECV(csp) \ - (mutex_enter(&(csp)->ch_recv.c_mutex)) -#define IDN_CHAN_UNLOCK_RECV(csp) \ - (mutex_exit(&(csp)->ch_recv.c_mutex)) - -#define IDN_CHAN_SEND_IS_LOCKED(csp) \ - (MUTEX_HELD(&(csp)->ch_send.c_mutex)) -#define IDN_CHAN_TRYLOCK_SEND(csp) \ - (mutex_tryenter(&(csp)->ch_send.c_mutex)) -#define IDN_CHAN_LOCK_SEND(csp) \ - (mutex_enter(&(csp)->ch_send.c_mutex)) -#define IDN_CHAN_UNLOCK_SEND(csp) \ - (mutex_exit(&(csp)->ch_send.c_mutex)) - -/* - * A channel table is an array of pointers to mailboxes - * for the respective domains for the given channel. - * Used a cache for the frequently used items. Respective - * fields in mainmbox are updated just prior to sleeping. - */ - -/* - * Reading c_state requires either c_mutex or ch_mutex. - * Writing c_state requires both c_mutex and ch_mutex in the order: - * ch_mutex - * c_mutex - */ -typedef struct idn_chaninfo { - kmutex_t c_mutex; - uchar_t c_state; /* protected by c_mutex */ - uchar_t c_checkin; /* asynchronous flag */ - kcondvar_t c_cv; - ushort_t c_waiters; /* protected by c_mutex */ - ushort_t c_inprogress; /* protected by c_mutex */ -} idn_chaninfo_t; - -/* - * Reading/Writing ch_state requires ch_mutex. - * When updating both recv and send c_state's for the locks - * must be grabbed in the following order: - * ch_mutex - * ch_recv.c_mutex - * ch_send.c_mutex - * This order is necessary to prevent deadlocks. - * In general ch_state is intended to represent c_state of - * individual send/recv sides. During state transitions the - * ch_state and c_state values may be slightly different, - * but eventually should end up identical. - */ -typedef struct idn_chansvr { - uchar_t ch_id; - uchar_t ch_state; /* protected by ch_mutex */ - lock_t ch_initlck; - lock_t ch_actvlck; - domainset_t ch_reg_domset; - kmutex_t ch_mutex; - - idn_chaninfo_t ch_send; - int _padding2[(64 - - (2*sizeof (uchar_t)) - (2*sizeof (lock_t)) - - sizeof (uint_t) - sizeof (kmutex_t) - - sizeof (idn_chaninfo_t)) / sizeof (int)]; - - idn_chaninfo_t ch_recv; - - uint64_t ch_recv_scanset; - uint64_t ch_recv_scanset_pending; - - domainset_t ch_recv_domset; - domainset_t ch_recv_domset_pending; - short ch_recv_domcount; - kcondvar_t ch_recv_cv; - int ch_recv_waittime; - int ch_recv_changed; - - kthread_id_t ch_recv_threadp; - ksema_t *ch_recv_morguep; - int ch_bound_cpuid; - int ch_bound_cpuid_pending; -} idn_chansvr_t; - -typedef struct idn_mainmbox { - kmutex_t mm_mutex; - short mm_channel; - short mm_domid; - ushort_t mm_flags; - short mm_type; - - idn_chansvr_t *mm_csp; /* non-NULL indicates reg'd */ - int mm_count; - int mm_dropped; - idn_mboxtbl_t *mm_smr_mboxp; /* SMR vaddr */ - - ushort_t *mm_smr_activep; /* SMR pointer */ - ushort_t *mm_smr_readyp; /* SMR pointer */ - int mm_qiget; /* next msg to get */ - int mm_qiput; /* next slot to put msg */ -} idn_mainmbox_t; - -/* - * mm_flags - */ -#define IDNMMBOX_FLAG_CORRUPTED 0x01 -/* - * mm_type - */ -#define IDNMMBOX_TYPE_RECV 0x1 -#define IDNMMBOX_TYPE_SEND 0x2 - -#define IDNMBOX_IS_RECV(m) ((m) == IDNMMBOX_TYPE_RECV) -#define IDNMBOX_IS_SEND(m) ((m) == IDNMMBOX_TYPE_SEND) - -/* - * Period between sending wakeup xdc's to remote domain. - */ -#define IDN_CHANNEL_WAKEUP_PERIOD (hz >> 1) -/* - * ms_flag bit values. - */ -#define IDN_MBOXMSG_FLAG_RECLAIM 0x1 /* needs to be reclaimed */ -#define IDN_MBOXMSG_FLAG_INPROCESS 0x2 -#define IDN_MBOXMSG_FLAG_ERR_BADOFFSET 0x4 -#define IDN_MBOXMSG_FLAG_ERR_NOMBOX 0x8 -#define IDN_MBOXMSG_FLAG_ERRMASK 0xc -/* - * ch_state/c_state bit values. - */ -#define IDN_CHANSVC_STATE_ATTACHED 0x01 -#define IDN_CHANSVC_STATE_ENABLED 0x02 -#define IDN_CHANSVC_STATE_ACTIVE 0x04 -#define IDN_CHANSVC_STATE_FLUSH 0x10 -#define IDN_CHANSVC_STATE_CORRUPTED 0x20 -#define IDN_CHANSVC_STATE_MASK 0x07 /* ATTACHED/ENABLED/ACTIVE */ - -#define IDN_CHANSVC_PENDING_BITS (IDN_CHANSVC_STATE_ATTACHED | \ - IDN_CHANSVC_STATE_ENABLED) - -/* - * GLOBAL - */ -#define IDN_CHANNEL_IS_ATTACHED(csp) \ - ((csp)->ch_state & IDN_CHANSVC_STATE_ATTACHED) -#define IDN_CHANNEL_IS_DETACHED(csp) \ - (!IDN_CHANNEL_IS_ATTACHED(csp)) -#define IDN_CHANNEL_IS_PENDING(csp) \ - (((csp)->ch_state & IDN_CHANSVC_STATE_MASK) == \ - IDN_CHANSVC_PENDING_BITS) -#define IDN_CHANNEL_IS_ACTIVE(csp) \ - ((csp)->ch_state & IDN_CHANSVC_STATE_ACTIVE) -#define IDN_CHANNEL_IS_ENABLED(csp) \ - ((csp)->ch_state & IDN_CHANSVC_STATE_ENABLED) -/* - * SEND - */ -#define IDN_CHANNEL_IS_SEND_ACTIVE(csp) \ - ((csp)->ch_send.c_state & IDN_CHANSVC_STATE_ACTIVE) -/* - * RECV - */ -#define IDN_CHANNEL_IS_RECV_ACTIVE(csp) \ - ((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_ACTIVE) -#define IDN_CHANNEL_IS_RECV_CORRUPTED(csp) \ - ((csp)->ch_recv.c_state & IDN_CHANSVC_STATE_CORRUPTED) - - -#define IDN_CHAN_SEND_INPROGRESS(csp) ((csp)->ch_send.c_inprogress++) -#define IDN_CHAN_SEND_DONE(csp) \ - { \ - ASSERT((csp)->ch_send.c_inprogress > 0); \ - if ((--((csp)->ch_send.c_inprogress) == 0) && \ - ((csp)->ch_send.c_waiters != 0)) \ - cv_broadcast(&(csp)->ch_send.c_cv); \ - } -#define IDN_CHAN_RECV_INPROGRESS(csp) ((csp)->ch_recv.c_inprogress++) -#define IDN_CHAN_RECV_DONE(csp) \ - { \ - ASSERT((csp)->ch_recv.c_inprogress > 0); \ - if ((--((csp)->ch_recv.c_inprogress) == 0) && \ - ((csp)->ch_recv.c_waiters != 0)) \ - cv_broadcast(&(csp)->ch_recv.c_cv); \ - } - -#define IDN_CHANSVC_MARK_ATTACHED(csp) \ - ((csp)->ch_state = IDN_CHANSVC_STATE_ATTACHED) -#define IDN_CHANSVC_MARK_DETACHED(csp) \ - ((csp)->ch_state = 0) -#define IDN_CHANSVC_MARK_PENDING(csp) \ - ((csp)->ch_state |= IDN_CHANSVC_STATE_ENABLED) -#define IDN_CHANSVC_MARK_DISABLED(csp) \ - ((csp)->ch_state &= ~IDN_CHANSVC_STATE_ENABLED) -#define IDN_CHANSVC_MARK_ACTIVE(csp) \ - ((csp)->ch_state |= IDN_CHANSVC_STATE_ACTIVE) -#define IDN_CHANSVC_MARK_IDLE(csp) \ - ((csp)->ch_state &= ~IDN_CHANSVC_STATE_ACTIVE) - -#define IDN_CHANSVC_MARK_RECV_ACTIVE(csp) \ - ((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_ACTIVE) -#define IDN_CHANSVC_MARK_RECV_CORRUPTED(csp) \ - ((csp)->ch_recv.c_state |= IDN_CHANSVC_STATE_CORRUPTED) -#define IDN_CHANSVC_MARK_SEND_ACTIVE(csp) \ - ((csp)->ch_send.c_state |= IDN_CHANSVC_STATE_ACTIVE) - -typedef enum { - IDNCHAN_ACTION_DETACH, /* DETACH (ATTACHED = 0) */ - IDNCHAN_ACTION_STOP, /* DISABLE (ENABLED = 0) */ - IDNCHAN_ACTION_SUSPEND, /* IDLE (ACTIVE = 0) */ - IDNCHAN_ACTION_RESUME, - IDNCHAN_ACTION_RESTART, - IDNCHAN_ACTION_ATTACH -} idn_chanaction_t; - -#define IDN_CHANNEL_SUSPEND(c, w) \ - (idn_chan_action((c), IDNCHAN_ACTION_SUSPEND, (w))) -#define IDN_CHANNEL_RESUME(c) \ - (idn_chan_action((c), IDNCHAN_ACTION_RESUME, 0)) -#define IDN_CHANNEL_STOP(c, w) \ - (idn_chan_action((c), IDNCHAN_ACTION_STOP, (w))) -#define IDN_CHANNEL_RESTART(c) \ - (idn_chan_action((c), IDNCHAN_ACTION_RESTART, 0)) -#define IDN_CHANNEL_DETACH(c, w) \ - (idn_chan_action((c), IDNCHAN_ACTION_DETACH, (w))) -#define IDN_CHANNEL_ATTACH(c) \ - (idn_chan_action((c), IDNCHAN_ACTION_ATTACH, 0)) - -/* - * ds_waittime range values. - * When a packet arrives the waittime starts at MIN and gradually - * shifts up to MAX until another packet arrives. If still no - * packet arrives then we go to a hard sleep - */ -#define IDN_NETSVR_SPIN_COUNT idn_netsvr_spin_count -#define IDN_NETSVR_WAIT_MIN idn_netsvr_wait_min -#define IDN_NETSVR_WAIT_MAX idn_netsvr_wait_max -#define IDN_NETSVR_WAIT_SHIFT idn_netsvr_wait_shift - -/* - * --------------------------------------------------------------------- - * IDN Global Data - * - * The comment to the right of the respective field represents - * what lock protects that field. If there is no comment then - * no lock is required to access the field. - * --------------------------------------------------------------------- - */ -typedef struct idn_global { /* protected by... */ - krwlock_t grwlock; - /* - * Global state of IDN w.r.t. - * the local domain. - */ - idn_gstate_t state; /* grwlock */ - /* - * Version of the IDN driver. - * Is passed in DMV header so that - * other domains can validate they - * support protocol used by local - * domain. - */ - int version; - /* - * Set to 1 if SMR region properly - * allocated and available. - */ - int enabled; - /* - * Local domains "domain id". - */ - int localid; - /* - * Domain id of the Master domain. - * Set to IDN_NIL_DOMID if none - * currently exists. - */ - int masterid; /* grwlock */ - /* - * Primarily used during Reconfiguration - * to track the expected new Master. - * Once the current IDN is dismantled - * the local domain will attempt to - * connect to this new domain. - */ - int new_masterid; /* grwlock */ - /* - * Number of protocol servers configured. - */ - int nservers; - - dev_info_t *dip; - - struct { - /* - * dmv_inum - * Interrupt number assigned by - * DMV subsystem to IDN's DMV - * handler. - * soft_inum - * Soft interrupt number assigned - * by OS (add_softintr) for Soft - * interrupt dispatched by DMV - * handler. - */ - uint_t dmv_inum; - uint64_t soft_inum; - caddr_t dmv_data; - size_t dmv_data_len; - } intr; - /* - * first_swlink - * Used as synchronization to - * know whether channels need - * to be activated or not. - * first_hwlink - * Used as mechanism to determine - * whether local domain needs - * to publicize its SMR, assuming - * it is the Master. - * first_hwmaster - * Domainid of the domain that - * was the master at the time - * the hardware was programmed. - * We need to keep this so that - * we deprogram with respect to - * the correct domain that the - * hardware was originally - * programmed to. - */ - lock_t first_swlink; - lock_t first_hwlink; - short first_hwmasterid; - /* - * The xmit* fields are used to set-up a background - * thread to monitor when a channel is ready to be - * enabled again. This is necessary since IDN - * can't rely on hardware to interrupt it when - * things are ready to go. We need this ability - * to wakeup our STREAMS queues. - * Criteria for reenabling queues. - * gstate == IDNGS_ONLINE - * channel = !check-in - * buffers are available - * - * xmit_chanset_wanted - * Indicates which channels wish to have - * their queues reenabled when ready. - * xmit_tid - * Timeout-id of monitor. - */ - kmutex_t xmit_lock; - idn_chanset_t xmit_chanset_wanted; /* xmit_lock */ - timeout_id_t xmit_tid; /* xmit_lock */ - - struct { - /* - * ready - * Indicates SMR region allocated - * and available from OBP. - * vaddr - * Virtual address assigned to SMR. - * locpfn - * Page Frame Number associated - * with local domain's SMR. - * rempfn - * Page Frame Number associated - * with remote (Master) domain's SMR. - * rempfnlim - * PFN past end of remote domain's - * SMR. - * prom_paddr/prom_size - * Physical address and size of - * SMR that were assigned by OBP. - */ - int ready; - caddr_t vaddr; - pfn_t locpfn; - pfn_t rempfn; /* grwlock */ - - pfn_t rempfnlim; /* grwlock */ - uint64_t prom_paddr; - - uint64_t prom_size; - } smr; - - /* - * idnsb_mutex - * Protects access to IDN's - * sigblock area. - * idnsb_eventp - * IDN's private area in sigblock - * used for signaling events - * regarding IDN state to SSP. - * idnsb - * Area within IDN's private - * sigblock area used for tracking - * certain IDN state which might - * be useful during arbstop - * conditions (if caused by IDN!). - */ - kmutex_t idnsb_mutex; - idnsb_event_t *idnsb_eventp; - idnsb_t *idnsb; - - struct sigbintr { - /* - * sb_mutex - * Protects sigbintr elements - * to synchronize execution of - * sigblock (IDN) mailbox handling. - * sb_cpuid - * Cpu whose sigblock mailbox - * originally received IDN request - * from SSP. Necessary to know - * where to put response. - * sb_busy - * Flag indicating state of - * sigblock handler thread. - * Synchronize activity between - * SSP and current IDN requests that - * are in progress. - * sb_cv - * Condition variable for sigblock - * handler thread to wait on. - * sb_inum - * Soft interrupt number assigned - * by OS to handle soft interrupt - * request make by low-level (IDN) - * sigblock handler to dispatch actual - * processing of sigblock (mailbox) - * request. - */ - kmutex_t sb_mutex; - uchar_t sb_cpuid; /* sigbintr.sb_mutex */ - uchar_t sb_busy; /* sigbintr.sb_mutex */ - kcondvar_t sb_cv; /* sigbintr.sb_mutex */ - uint64_t sb_inum; /* sigbintr.sb_mutex */ - } sigbintr; - - /* - * struprwlock, strup, sip, siplock - * Standard network streams - * handling structures to manage - * instances of IDN driver. - */ - krwlock_t struprwlock; - struct idnstr *strup; /* struprwlock */ - - struct idn *sip; /* siplock */ - kmutex_t sipwenlock; - kmutex_t siplock; - - /* - * Area where IDN maintains its kstats. - */ - kstat_t *ksp; - /* - * Number of domains that local domain - * has "open". - */ - int ndomains; /* grwlock */ - /* - * Number of domains that local domain - * has registered as non-responsive. - */ - int nawols; /* grwlock */ - /* - * Number of network channels (interfaces) - * which are currently active. - */ - int nchannels; /* grwlock */ - /* - * Bitmask representing channels - * that are currently active. - */ - idn_chanset_t chanset; /* grwlock */ - /* - * Array of channel (network/data) servers - * that have been created. Not necessarily - * all active. - */ - idn_chansvr_t *chan_servers; /* elmts = ch_mutex */ - /* - * Pointer to sigblock handler thread - * which ultimately processes SSP - * IDN requests. - */ - kthread_id_t sigb_threadp; - /* - * Pointer to area used by Master - * to hold mailbox structures. - * Actual memory is in SMR. - */ - idn_mboxtbl_t *mboxarea; /* grwlock */ - - struct { - /* - * IDN_SYNC_LOCK - Provides serialization - * mechanism when performing synchronous - * operations across domains. - */ - kmutex_t sz_mutex; - /* - * Actual synchronization zones for - * CONNECT/DISCONNECT phases. - */ - idn_synczone_t sz_zone[IDN_SYNC_NUMZONE]; - } sync; /* sz_mutex */ - - struct { - /* - * ds_trans_on - * Set of domains which are trying - * to establish a link w/local. - * ds_ready_on - * Set of domains which local knows - * are ready for linking, but has - * not yet confirmed w/peers. - * ds_connected - * Set of domains that local has - * confirmed as being ready. - * ds_trans_off - * Set of domains which are trying - * to unlink from local. - * ds_ready_off - * Set of domains which local knows - * are ready for unlink, but has - * not yet confirmed w/peers. - * ds_relink - * Set of domains we're expecting - * to relink with subsequent to - * a RECONFIG (new master selection). - * ds_hwlinked - * Set of domains for which local - * has programmed its hardware. - * ds_flush - * Set of domains requiring that - * local flush its ecache prior - * to unlinking. - * ds_awol - * Set of domains believed to be - * AWOL - haven't responded to - * any queries. - * ds_hitlist - * Set of domains which local domain - * is unlinking from and wishes to ignore - * any extraneous indirect link requests - * from other domains, e.g. during a - * Reconfig. - */ - domainset_t ds_trans_on; /* sz_mutex */ - domainset_t ds_ready_on; /* sz_mutex */ - - domainset_t ds_connected; /* sz_mutex */ - domainset_t ds_trans_off; /* sz_mutex */ - - domainset_t ds_ready_off; /* sz_mutex */ - domainset_t ds_relink; /* sz_mutex */ - - domainset_t ds_hwlinked; /* sz_mutex */ - domainset_t ds_flush; /* sz_mutex */ - - domainset_t ds_awol; /* sz_mutex */ - domainset_t ds_hitlist; /* sz_mutex */ - } domset; - /* - * Bitmask identifying all cpus in - * the local IDN. - */ - cpuset_t dc_cpuset; - /* - * Bitmask identifying all boards in - * the local IDN. - */ - boardset_t dc_boardset; - - struct dopers { - /* - * Waiting area for IDN requests, - * i.e. link & unlinks. IDN requests - * are performed asynchronously so - * we need a place to wait until the - * operation has completed. - * - * dop_domset - * Identifies which domains the - * current waiter is interested in. - * dop_waitcount - * Number of waiters in the room. - * dop_waitlist - * Actual waiting area. - * dop_freelist - * Freelist (small cache) of - * structs for waiting area. - */ - kmutex_t dop_mutex; - kcondvar_t dop_cv; /* dop_mutex */ - domainset_t dop_domset; /* dop_mutex */ - int dop_waitcount; /* dop_mutex */ - dop_waitlist_t *dop_waitlist; /* dop_mutex */ - dop_waitlist_t *dop_freelist; /* dop_mutex */ - /* dop_mutex */ - dop_waitlist_t _dop_wcache[IDNOP_CACHE_SIZE]; - } *dopers; - - struct { - /* - * Protocol Server: - * - * p_server - * Linked list of queues - * describing protocol - * servers in use. - * p_jobpool - * Kmem cache of structs - * used to enqueue protocol - * jobs for protocol servers. - * p_morgue - * Synchronization (check-in) - * area used when terminating - * protocol servers (threads). - */ - struct idn_protoqueue *p_serverq; - kmem_cache_t *p_jobpool; - ksema_t p_morgue; - } protocol; - - struct idn_retry_queue { - /* - * rq_jobs - * Queue of Retry jobs - * that are outstanding. - * rq_count - * Number of jobs on retry - * queue. - * rq_cache - * Kmem cache for structs - * used to describe retry - * jobs. - */ - idn_retry_job_t *rq_jobs; /* rq_mutex */ - int rq_count; /* rq_mutex */ - kmutex_t rq_mutex; /* rq_mutex */ - - kcondvar_t rq_cv; /* rq_mutex */ - kmem_cache_t *rq_cache; - } retryqueue; - - struct slabpool { - /* - * Slabpool: - * - * ntotslabs - * Total number of slabs - * in SMR (free & in-use). - * npools - * Number of pools available - * in list. One smr_slabtbl - * exists for each pool. - */ - int ntotslabs; - int npools; - struct smr_slabtbl { - /* - * sarray - * Array of slab structs - * representing slabs in SMR. - * nfree - * Number of slabs actually - * available in sarray. - * nslabs - * Number of slabs represented - * in sarray (free & in-use). - */ - smr_slab_t *sarray; - int nfree; - int nslabs; - } *pool; - /* - * Holds array of smr_slab_t structs kmem_alloc'd - * for slabpool. - */ - smr_slab_t *savep; - } *slabpool; - - struct slabwaiter { - /* - * Waiting area for threads - * requesting slab allocations. - * Used by Slaves for all requests, - * but used by Master only for - * redundant requests, i.e. multiple - * requests on behalf of the same - * domain. One slabwaiter area - * exist for each possible domain. - * - * w_nwaiters - * Number of threads waiting - * in waiting area. - * w_done - * Flag to indicate that - * allocation request has - * completed. - * w_serrno - * Non-zero indicates an - * errno value to represent - * error that occurred during - * attempt to allocate slab. - * w_closed - * Indicates that waiting area is - * closed and won't allow any new - * waiters. This occurs during - * the small window where we're - * trying to suspend a channel. - * w_cv - * Condvar for waiting on. - * w_sp - * Holds slab structure of - * successfully allocated slab. - */ - kmutex_t w_mutex; - short w_nwaiters; /* w_mutex */ - short w_done; /* w_mutex */ - short w_serrno; /* w_mutex */ - short w_closed; /* w_mutex */ - kcondvar_t w_cv; /* w_mutex */ - smr_slab_t *w_sp; /* w_mutex */ - } *slabwaiter; - /* - * Kmem cache used for allocating - * timer structures for outstanding - * IDN requests. - */ - kmem_cache_t *timer_cache; - /* - * Effectively constant used in - * translating buffer frames in - * mailbox message frames to - * offsets within SMR. - */ - int bframe_shift; -} idn_global_t; - -typedef struct idn_retry_queue idn_retry_queue_t; - -#define IDN_GET_MASTERID() (idn.masterid) -#define IDN_SET_MASTERID(mid) \ - { \ - int _mid = (mid); \ - mutex_enter(&idn.idnsb_mutex); \ - if (idn.idnsb) { \ - idn.idnsb->id_pmaster_board = \ - idn.idnsb->id_master_board; \ - if (_mid == IDN_NIL_DOMID) \ - idn.idnsb->id_master_board = (uchar_t)0xff; \ - else \ - idn.idnsb->id_master_board = \ - (uchar_t)idn_domain[_mid].dvote.v.board; \ - } \ - mutex_exit(&idn.idnsb_mutex); \ - IDN_HISTORY_LOG(IDNH_MASTERID, _mid, idn.masterid, 0); \ - PR_STATE("%d: MASTERID %d -> %d\n", __LINE__, \ - idn.masterid, _mid); \ - idn.masterid = _mid; \ - } -#define IDN_GET_NEW_MASTERID() (idn.new_masterid) -#define IDN_SET_NEW_MASTERID(mid) \ - { \ - PR_STATE("%d: NEW MASTERID %d -> %d\n", __LINE__, \ - idn.new_masterid, (mid)); \ - idn.new_masterid = (mid); \ - } - -#define IDN_GLOCK_EXCL() (rw_enter(&idn.grwlock, RW_WRITER)) -#define IDN_GLOCK_SHARED() (rw_enter(&idn.grwlock, RW_READER)) -#define IDN_GLOCK_TRY_SHARED() (rw_tryenter(&idn.grwlock, RW_READER)) -#define IDN_GLOCK_DOWNGRADE() (rw_downgrade(&idn.grwlock)) -#define IDN_GUNLOCK() (rw_exit(&idn.grwlock)) -#define IDN_GLOCK_IS_EXCL() (RW_WRITE_HELD(&idn.grwlock)) -#define IDN_GLOCK_IS_SHARED() (RW_READ_HELD(&idn.grwlock)) -#define IDN_GLOCK_IS_HELD() (RW_LOCK_HELD(&idn.grwlock)) - -#define IDN_SYNC_LOCK() (mutex_enter(&idn.sync.sz_mutex)) -#define IDN_SYNC_TRYLOCK() (mutex_tryenter(&idn.sync.sz_mutex)) -#define IDN_SYNC_UNLOCK() (mutex_exit(&idn.sync.sz_mutex)) -#define IDN_SYNC_IS_LOCKED() (MUTEX_HELD(&idn.sync.sz_mutex)) - -/* - * Macro to reset some globals necessary in preparing - * for initialization of HW for IDN. - */ -#define IDN_PREP_HWINIT() \ - { \ - ASSERT(IDN_GLOCK_IS_EXCL()); \ - lock_clear(&idn.first_swlink); \ - lock_clear(&idn.first_hwlink); \ - idn.first_hwmasterid = (short)IDN_NIL_DOMID; \ - } - -/* - * Return values of idn_send_data. - */ -#define IDNXMIT_OKAY 0 /* xmit successful */ -#define IDNXMIT_LOOP 1 /* loopback */ -#define IDNXMIT_DROP 2 /* drop packet */ -#define IDNXMIT_RETRY 3 /* retry packet (requeue and qenable) */ -#define IDNXMIT_REQUEUE 4 /* requeue packet, but don't qenable */ - -/* - * --------------------------------------------------------------------- - * ss_rwlock must be acquired _before_ any idn_domain locks are - * acquired if both structs need to be accessed. - * idn.struprwlock is acquired when traversing IDN's strup list - * and when adding or deleting entries. - * - * ss_nextp Linked list of streams. - * ss_rq Respective read queue. - * ss_sip Attached device. - * ss_state Current DL state. - * ss_sap Bound SAP. - * ss_flags Misc. flags. - * ss_mccount # enabled multicast addrs. - * ss_mctab Table of multicast addrs. - * ss_minor Minor device number. - * ss_rwlock Protects ss_linkup fields and DLPI state machine. - * ss_linkup Boolean flag indicating whether particular (domain) link - * is up. - * --------------------------------------------------------------------- - */ -struct idnstr { /* gets shoved into q_ptr */ - struct idnstr *ss_nextp; - queue_t *ss_rq; - struct idn *ss_sip; - t_uscalar_t ss_state; - t_uscalar_t ss_sap; - uint_t ss_flags; - uint_t ss_mccount; - struct ether_addr *ss_mctab; - minor_t ss_minor; - krwlock_t ss_rwlock; -}; - -/* - * idnstr.ss_flags - Per-stream flags - */ -#define IDNSFAST 0x01 /* "M_DATA fastpath" mode */ -#define IDNSRAW 0x02 /* M_DATA plain raw mode */ -#define IDNSALLPHYS 0x04 /* "promiscuous mode" */ -#define IDNSALLMULTI 0x08 /* enable all multicast addresses */ -#define IDNSALLSAP 0x10 /* enable all ether type values */ - -/* - * Maximum number of multicast address per stream. - */ -#define IDNMAXMC 64 -#define IDNMCALLOC (IDNMAXMC * sizeof (struct ether_addr)) - -/* - * Full DLSAP address length (in struct dladdr format). - */ -#define IDNADDRL (ETHERADDRL + sizeof (ushort_t)) - -struct idndladdr { - struct ether_addr dl_phys; - ushort_t dl_sap; -}; - -#define IDNHEADROOM 64 -#define IDNROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1)) - -/* - * Respective interpretation of bytes in 6 byte ethernet address. - */ -#define IDNETHER_ZERO 0 -#define IDNETHER_COOKIE1 1 -#define IDNETHER_COOKIE1_VAL 0xe5 -#define IDNETHER_COOKIE2 2 -#define IDNETHER_COOKIE2_VAL 0x82 -#define IDNETHER_NETID 3 -#define IDNETHER_CHANNEL 4 -#define IDNETHER_RESERVED 5 -#define IDNETHER_RESERVED_VAL 0x64 - -/* - * IDN driver supports multliple instances, however they - * still all refer to the same "physical" device. Multiple - * instances are supported primarily to allow increased - * STREAMs bandwidth since each instance has it's own IP queue. - * This structure is primarily defined to be consistent with - * other network drivers and also to hold the kernel stats. - */ -struct idn_kstat { - ulong_t si_ipackets; /* # packets received */ - ulong_t si_ierrors; /* # total input errors */ - ulong_t si_opackets; /* # packets sent */ - ulong_t si_oerrors; /* # total output errors */ - - ulong_t si_txcoll; /* # xmit collisions */ - ulong_t si_rxcoll; /* # recv collisions */ - ulong_t si_crc; /* # recv crc errors */ - ulong_t si_buff; /* # recv pkt sz > buf sz */ - - ulong_t si_nolink; /* # loss of connection */ - ulong_t si_linkdown; /* # link is down */ - ulong_t si_inits; /* # driver inits */ - ulong_t si_nocanput; /* # canput() failures */ - - ulong_t si_allocbfail; /* # allocb() failures */ - ulong_t si_notbufs; /* # out of xmit buffers */ - ulong_t si_reclaim; /* # reclaim failures */ - ulong_t si_smraddr; /* # bad SMR addrs */ - - ulong_t si_txmax; /* # xmit over limit */ - ulong_t si_txfull; /* # xmit mbox full */ - ulong_t si_xdcall; /* # xdcalls sent */ - ulong_t si_sigsvr; /* # data server wakeups */ - - ulong_t si_mboxcrc; /* # send mbox crc errors */ - /* - * MIB II kstat variables - */ - ulong_t si_rcvbytes; /* # bytes received */ - ulong_t si_xmtbytes; /* # bytes transmitted */ - ulong_t si_multircv; /* # multicast packets received */ - - ulong_t si_multixmt; /* # multicast packets for xmit */ - ulong_t si_brdcstrcv; /* # broadcast packets received */ - ulong_t si_brdcstxmt; /* # broadcast packets for xmit */ - ulong_t si_norcvbuf; /* # rcv packets discarded */ - - ulong_t si_noxmtbuf; /* # xmit packets discarded */ - /* - * PSARC 1997/198 : 64 bit kstats - */ - uint64_t si_ipackets64; /* # packets received */ - uint64_t si_opackets64; /* # packets transmitted */ - uint64_t si_rbytes64; /* # bytes received */ - uint64_t si_obytes64; /* # bytes transmitted */ - /* - * PSARC 1997/247 : RFC 1643 dot3Stats... - */ - ulong_t si_fcs_errors; /* FCSErrors */ - ulong_t si_macxmt_errors; /* InternalMacTransmitErrors */ - ulong_t si_toolong_errors; /* FrameTooLongs */ - ulong_t si_macrcv_errors; /* InternalMacReceiveErrors */ -}; - -/* - * Per logical interface private data structure. - */ -struct idn { - struct idn *si_nextp; /* linked instances */ - dev_info_t *si_dip; /* assoc. dev_info */ - struct ether_addr si_ouraddr; /* enet address */ - - uint_t si_flags; /* misc. flags */ - uint_t si_wantw; /* xmit: out of res. */ - queue_t *si_ip4q; /* ip (v4) read queue */ - queue_t *si_ip6q; /* ip (v6) read queue */ - - kstat_t *si_ksp; /* kstat pointer */ - struct idn_kstat si_kstat; /* per-inst kstat */ -}; - -struct idn_gkstat { - ulong_t gk_reconfigs; /* # reconfigs */ - ulong_t gk_reconfig_last; /* timestamep */ - ulong_t gk_reaps; /* # of reap request */ - ulong_t gk_reap_last; /* timestamep */ - - ulong_t gk_links; /* # of IDN links */ - ulong_t gk_link_last; /* timestamep */ - ulong_t gk_unlinks; /* # of IDN unlinks */ - ulong_t gk_unlink_last; /* timestamep */ - - ulong_t gk_buffail; /* # bad bufalloc */ - ulong_t gk_buffail_last; /* timestamp */ - ulong_t gk_slabfail; /* # bad slaballoc */ - ulong_t gk_slabfail_last; /* timestamp */ - - ulong_t gk_reap_count; /* # of slabs reaped */ - ulong_t gk_dropped_intrs; /* dropped intrs */ -}; - -extern struct idn_gkstat sg_kstat; - -#ifdef IDN_NO_KSTAT - -#define IDN_KSTAT_INC(s, i) -#define IDN_KSTAT_ADD(s, i, n) -#define IDN_GKSTAT_INC(i) -#define IDN_GKSTAT_ADD(vvv, iii) -#define IDN_GKSTAT_GLOBAL_EVENT(vvv, nnn) - -#else /* IDN_NO_KSTAT */ - -#define IDN_KSTAT_INC(sss, vvv) \ - ((((struct idn *)(sss))->si_kstat.vvv)++) -#define IDN_KSTAT_ADD(sss, vvv, nnn) \ - ((((struct idn *)(sss))->si_kstat.vvv) += (nnn)) -#define IDN_GKSTAT_INC(vvv) ((sg_kstat.vvv)++) -#define IDN_GKSTAT_ADD(vvv, iii) ((sg_kstat.vvv) += (iii)) -#define IDN_GKSTAT_GLOBAL_EVENT(vvv, ttt) \ - ((sg_kstat.vvv)++, ((sg_kstat.ttt) = ddi_get_lbolt())) - -#endif /* IDN_NO_KSTAT */ - -/* - * idn.si_flags - */ -#define IDNRUNNING 0x01 /* IDNnet is UP */ -#define IDNPROMISC 0x02 /* promiscuous mode enabled */ -#define IDNSUSPENDED 0x04 /* suspended (DR) */ - -typedef struct kstat_named kstate_named_t; - -struct idn_kstat_named { - kstat_named_t sk_ipackets; /* # packets received */ - kstat_named_t sk_ierrors; /* # total input errors */ - kstat_named_t sk_opackets; /* # packets sent */ - kstat_named_t sk_oerrors; /* # total output errors */ - - kstat_named_t sk_txcoll; /* # xmit collisions */ - kstat_named_t sk_rxcoll; /* # recv collisions */ - kstat_named_t sk_crc; /* # recv crc errors */ - kstat_named_t sk_buff; /* # recv pkt sz > buf sz */ - - kstat_named_t sk_nolink; /* # loss of connection */ - kstat_named_t sk_linkdown; /* # link is down */ - kstat_named_t sk_inits; /* # driver inits */ - kstat_named_t sk_nocanput; /* # canput() failures */ - - kstat_named_t sk_allocbfail; /* # allocb() failures */ - kstat_named_t sk_notbufs; /* # out of xmit buffers */ - kstat_named_t sk_reclaim; /* # reclaim failures */ - kstat_named_t sk_smraddr; /* # bad SMR addrs */ - - kstat_named_t sk_txmax; /* # xmit over limit */ - kstat_named_t sk_txfull; /* # xmit mbox full */ - kstat_named_t sk_xdcall; /* # xdcalls sent */ - kstat_named_t sk_sigsvr; /* # data server wakeups */ - - kstat_named_t sk_mboxcrc; /* # send mbox crc errors */ - /* - * MIB II kstat variables - */ - kstat_named_t sk_rcvbytes; /* # bytes received */ - kstat_named_t sk_xmtbytes; /* # bytes transmitted */ - kstat_named_t sk_multircv; /* # multicast packets received */ - - kstat_named_t sk_multixmt; /* # multicast packets for xmit */ - kstat_named_t sk_brdcstrcv; /* # broadcast packets received */ - kstat_named_t sk_brdcstxmt; /* # broadcast packets for xmit */ - kstat_named_t sk_norcvbuf; /* # rcv packets discarded */ - - kstat_named_t sk_noxmtbuf; /* # xmit packets discarded */ - /* - * PSARC 1997/198 : 64bit kstats - */ - kstat_named_t sk_ipackets64; /* # packets received */ - kstat_named_t sk_opackets64; /* # packets transmitted */ - kstat_named_t sk_rbytes64; /* # bytes received */ - kstat_named_t sk_obytes64; /* # bytes transmitted */ - /* - * PSARC 1997/247 : RFC 1643 dot3Stats... - */ - kstat_named_t sk_fcs_errors; /* FCSErr */ - kstat_named_t sk_macxmt_errors; /* InternalMacXmtErr */ - kstat_named_t sk_toolong_errors; /* FrameTooLongs */ - kstat_named_t sk_macrcv_errors; /* InternalMacRcvErr */ -}; - -/* - * Stats for global events of interest (non-counters). - */ -struct idn_gkstat_named { - kstat_named_t sk_curtime; /* current time */ - kstat_named_t sk_reconfigs; /* # master recfgs */ - kstat_named_t sk_reconfig_last; /* timestamp */ - kstat_named_t sk_reaps; /* # of reap req */ - kstat_named_t sk_reap_last; /* timestamp */ - kstat_named_t sk_links; /* # of links */ - kstat_named_t sk_link_last; /* timestamp */ - kstat_named_t sk_unlinks; /* # of unlinks */ - kstat_named_t sk_unlink_last; /* timestamp */ - kstat_named_t sk_buffail; /* # bad buf alloc */ - kstat_named_t sk_buffail_last; /* timestamp */ - kstat_named_t sk_slabfail; /* # bad buf alloc */ - kstat_named_t sk_slabfail_last; /* timestamp */ - kstat_named_t sk_reap_count; /* # slabs reaped */ - kstat_named_t sk_dropped_intrs; /* intrs dropped */ -}; - -/* - * --------------------------------------------------------------------- - */ -#ifdef DEBUG -#define IDNXDC(d, mt, a1, a2, a3, a4) \ - ((void) debug_idnxdc("idnxdc", (int)(d), (mt), \ - (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4))) -#else /* DEBUG */ -#define IDNXDC(d, mt, a1, a2, a3, a4) \ - (idnxdc((int)(d), (mt), \ - (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4))) -#endif /* DEBUG */ -#define IDNXDC_BROADCAST(ds, mt, a1, a2, a3, a4) \ - (idnxdc_broadcast((domainset_t)(ds), (mt), \ - (uint_t)(a1), (uint_t)(a2), (uint_t)(a3), (uint_t)(a4))) - -/* - * --------------------------------------------------------------------- - */ -#define SET_XARGS(x, a0, a1, a2, a3) \ - ((x)[0] = (uint_t)(a0), (x)[1] = (uint_t)(a1), \ - (x)[2] = (uint_t)(a2), (x)[3] = (uint_t)(a3)) - -#define GET_XARGS(x, a0, a1, a2, a3) \ - ((*(uint_t *)(a0) = (x)[0]), \ - (*(uint_t *)(a1) = (x)[1]), \ - (*(uint_t *)(a2) = (x)[2]), \ - (*(uint_t *)(a3) = (x)[3])) - -#define CLR_XARGS(x) \ - ((x)[0] = (x)[1] = (x)[2] = (x)[3] = 0) - -#define GET_XARGS_NEGO_TICKET(x) ((uint_t)(x)[0]) -#define GET_XARGS_NEGO_DSET(x, d) \ - ((d)[0] = (x)[1], (d)[1] = (x)[2], (d)[2] = (x)[3]) -#define SET_XARGS_NEGO_TICKET(x, t) ((x)[0] = (uint_t)(t)) -#define SET_XARGS_NEGO_DSET(x, d) \ - ((x)[1] = (uint_t)(d)[0], \ - (x)[2] = (uint_t)(d)[1], \ - (x)[3] = (uint_t)(d)[2]) - -#define GET_XARGS_CON_TYPE(x) ((idn_con_t)(x)[0]) -#define GET_XARGS_CON_DOMSET(x) ((domainset_t)(x)[1]) -#define SET_XARGS_CON_TYPE(x, t) ((x)[0] = (uint_t)(t)) -#define SET_XARGS_CON_DOMSET(x, s) ((x)[1] = (uint_t)(s)) - -#define GET_XARGS_FIN_TYPE(x) GET_FIN_TYPE((x)[0]) -#define GET_XARGS_FIN_ARG(x) GET_FIN_ARG((x)[0]) -#define GET_XARGS_FIN_DOMSET(x) ((domainset_t)(x)[1]) -#define GET_XARGS_FIN_OPT(x) ((idn_finopt_t)(x)[2]) -#define GET_XARGS_FIN_MASTER(x) ((uint_t)(x)[3]) -#define SET_XARGS_FIN_TYPE(x, t) SET_FIN_TYPE((x)[0], (t)) -#define SET_XARGS_FIN_ARG(x, a) SET_FIN_ARG((x)[0], (a)) -#define SET_XARGS_FIN_DOMSET(x, s) ((x)[1] = (uint_t)(s)) -#define SET_XARGS_FIN_OPT(x, o) ((x)[2] = (uint_t)(o)) -#define SET_XARGS_FIN_MASTER(x, m) ((x)[3] = (uint_t)(m)) - -#define GET_XARGS_NACK_TYPE(x) ((idn_nack_t)(x)[0]) -#define GET_XARGS_NACK_ARG1(x) ((x)[1]) -#define GET_XARGS_NACK_ARG2(x) ((x)[2]) -#define SET_XARGS_NACK_TYPE(x, t) ((x)[0] = (uint_t)(t)) -#define SET_XARGS_NACK_ARG1(x, a1) ((x)[1] = (uint_t)(a1)) -#define SET_XARGS_NACK_ARG2(x, a2) ((x)[2] = (uint_t)(a2)) - -#define GET_XARGS_CFG_PHASE(x) ((int)(x)[0]) -#define SET_XARGS_CFG_PHASE(x, p) ((x)[0] = (uint_t)(p)) - -/* - * --------------------------------------------------------------------- - */ -/* - * Device instance to SIP (IDN instance pointer). - */ -#ifdef DEBUG -#define IDN_INST2SIP(i) \ - (ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))), \ - idn_i2s_table[i]) -#else /* DEBUG */ -#define IDN_INST2SIP(i) (idn_i2s_table[i]) -#endif /* DEBUG */ - -#define IDN_SET_INST2SIP(i, s) \ - { \ - ASSERT(((i) >= 0) && ((i) < (IDN_MAXMAX_NETS << 1))); \ - idn_i2s_table[i] = (s); \ - } - -#define IDN_NETID2DOMID(n) (VALID_UDOMAINID(n) ? \ - ((int)(n)) : IDN_NIL_DOMID) -#define IDN_DOMID2NETID(d) ((ushort_t)(d)) - -#ifdef DEBUG -#define IDNDL_ETHER2DOMAIN(eap) \ - (_idndl_ether2domain(eap)) -#define IDNDL_ETHER2SIP(eap) \ - (_idndl_ether2sip(eap)) -#else -/* - * The following values can be returned from IDNDL_ETHER2DOMAIN: - * IDN_NIL_DOMID - * Ether address is broadcast (0xff) or domain doesn't exist. - * domid Domain id with drwlock(reader) held. - */ -#define IDNDL_ETHER2DOMAIN(eap) \ - (IDN_NETID2DOMID((eap)->ether_addr_octet[IDNETHER_NETID])) -#define IDNDL_ETHER2SIP(eap) \ - (((eap)->ether_addr_octet[IDNETHER_CHANNEL] == 0xff) ? NULL : \ - IDN_INST2SIP((int)(eap)->ether_addr_octet[IDNETHER_CHANNEL])) -#endif /* DEBUG */ - -#define UPPER32_CPUMASK(s) _upper32cpumask(s) -#define LOWER32_CPUMASK(s) _lower32cpumask(s) -#define MAKE64_CPUMASK(s, u, l) _make64cpumask(&(s), (u), (l)) - -#ifdef DEBUG -extern caddr_t _idn_getstruct(char *structname, int size); -extern void _idn_freestruct(caddr_t ptr, char *structname, int size); - -#define GETSTRUCT(structure, num) \ - ((structure *)_idn_getstruct("structure", sizeof (structure)*(num))) -#define FREESTRUCT(ptr, structure, num) \ - (_idn_freestruct((caddr_t)ptr, "structure", sizeof (structure)*(num))) -#else /* DEBUG */ -#define GETSTRUCT(structure, num) \ - ((structure *)kmem_zalloc((uint_t)(sizeof (structure) * (num)), \ - KM_SLEEP)) -#define FREESTRUCT(ptr, structure, num) \ - (kmem_free((caddr_t)(ptr), sizeof (structure) * (num))) -#endif /* DEBUG */ - -extern int idn_debug; -extern idn_global_t idn; -extern idn_domain_t idn_domain[]; -extern struct idn *idn_i2s_table[]; -extern int idn_history; -extern struct idn_history idnhlog; - -extern int idn_smr_size; -extern int idn_nwr_size; -extern int idn_protocol_nservers; -extern int idn_awolmsg_interval; -extern int idn_smr_bufsize; -extern int idn_slab_bufcount; -extern int idn_slab_prealloc; -extern int idn_slab_mintotal; -extern int idn_window_max; -extern int idn_window_incr; -extern int idn_reclaim_min; -extern int idn_reclaim_max; -extern int idn_mbox_per_net; -extern int idn_max_nets; - -extern int idn_netsvr_spin_count; -extern int idn_netsvr_wait_min; -extern int idn_netsvr_wait_max; -extern int idn_netsvr_wait_shift; - -extern int idn_checksum; - -extern int idn_msgwait_nego; -extern int idn_msgwait_cfg; -extern int idn_msgwait_con; -extern int idn_msgwait_fin; -extern int idn_msgwait_cmd; -extern int idn_msgwait_data; - -extern int idn_retryfreq_nego; -extern int idn_retryfreq_con; -extern int idn_retryfreq_fin; - -extern int idn_window_emax; /* calculated */ -extern int idn_slab_maxperdomain; /* calculated */ - -/* - * --------------------------------------------------------------------- - * io/idn.c - * --------------------------------------------------------------------- - */ -extern int board_to_ready_cpu(int board, cpuset_t cpuset); -extern int idn_open_domain(int domid, int cpuid, uint_t ticket); -extern void idn_close_domain(int domid); -extern void inum2str(uint_t inum, char str[]); -extern idn_timer_t *idn_timer_alloc(); -extern void idn_timer_free(idn_timer_t *tp); -extern void idn_timerq_init(idn_timerq_t *tq); -extern void idn_timerq_deinit(idn_timerq_t *tq); -extern void idn_timerq_free(idn_timerq_t *tq); -extern ushort_t idn_timer_start(idn_timerq_t *tq, idn_timer_t *tp, - clock_t tval); -extern int idn_timer_stopall(idn_timer_t *tp); -extern void idn_timer_dequeue(idn_timerq_t *tq, idn_timer_t *tp); -extern void idn_timer_stop(idn_timerq_t *tq, int subtype, ushort_t tcookie); -extern idn_timer_t *idn_timer_get(idn_timerq_t *tq, int subtype, - ushort_t tcookie); -extern void idn_domain_resetentry(idn_domain_t *dp); -extern void idn_strlinks_enable(uint_t netaddr, int domid); -extern void idn_strlinks_disable(uint_t domset, uint_t netaddr, - int disconnect); -extern void idn_dopcache_init(); -extern void idn_dopcache_deinit(); -extern void *idn_init_op(idn_opflag_t opflag, boardset_t boardset, - idnsb_error_t *sep); -extern void idn_add_op(idn_opflag_t opflag, domainset_t domset); -extern void idn_update_op(idn_opflag_t opflag, domainset_t domset, - idnsb_error_t *sep); -extern void idn_deinit_op(void *cookie); -extern int idn_wait_op(void *cookie, boardset_t *domsetp, - int wait_timeout); -extern int idn_wakeup_op(boardset_t boardset, uint_t domset, - idn_opflag_t opflag, int error); -extern void idn_error_op(uint_t domset, boardset_t boardset, int error); -extern void cpuset2str(cpuset_t cset, char buffer[]); -extern void domainset2str(domainset_t dset, char buffer[]); -extern void boardset2str(boardset_t bset, char buffer[]); -extern void mask2str(uint_t mask, char buffer[], int maxnum); -extern int idnxdc(int domid, idn_msgtype_t *mtp, - uint_t arg1, uint_t arg2, - uint_t arg3, uint_t arg4); -extern void idnxdc_broadcast(domainset_t domset, idn_msgtype_t *mtp, - uint_t arg1, uint_t arg2, - uint_t arg3, uint_t arg4); -extern void idn_awol_event_set(boardset_t boardset); -extern void idn_awol_event_clear(boardset_t boardset); -#ifdef DEBUG -extern int debug_idnxdc(char *f, int domid, idn_msgtype_t *mtp, - uint_t arg1, uint_t arg2, - uint_t arg3, uint_t arg4); -#endif /* DEBUG */ -extern boardset_t cpuset2boardset(cpuset_t portset); -extern uint_t _upper32cpumask(cpuset_t cset); -extern uint_t _lower32cpumask(cpuset_t cset); -extern void _make64cpumask(cpuset_t *csetp, uint_t upper, uint_t lower); - -/* - * --------------------------------------------------------------------- - * io/idn_proto.c - * --------------------------------------------------------------------- - */ -extern void idn_assign_cookie(int domid); -extern int idn_rput_data(queue_t *q, mblk_t *mp, int isput); -extern int idn_wput_data(queue_t *q, mblk_t *mp, int isput); -extern int idn_send_data(int dst_domid, idn_netaddr_t dst_netaddr, - queue_t *wq, mblk_t *mp); -extern void idn_recv_signal(mblk_t *mp); -extern int idn_link(int domid, int cpuid, int pri, int waittime, - idnsb_error_t *sep); -extern int idn_unlink(int domid, boardset_t idnset, idn_fin_t fintype, - idn_finopt_t finopt, int waittime, - idnsb_error_t *sep); -extern int idnh_recv_dataack(int domid, int src_proc, - uint_t acknack, idn_xdcargs_t xargs); -extern int idnh_recv_other(int sourceid, int src_proc, int dst_proc, - uint_t inum, uint_t acknack, - idn_xdcargs_t xargs); -extern void idn_send_cmd(int domid, idn_cmd_t cmdtype, - uint_t arg1, uint_t arg2, uint_t arg3); -extern void idn_send_cmdresp(int domid, idn_msgtype_t *mtp, - idn_cmd_t cmdtype, uint_t arg1, - uint_t arg2, uint_t cerrno); -extern void idn_broadcast_cmd(idn_cmd_t cmdtype, - uint_t arg1, uint_t arg2, uint_t arg3); -extern int idn_reclaim_mboxdata(int domid, int channel, int nbufs); -extern void idn_clear_awol(int domid); -extern int idn_protocol_init(int nservers); -extern void idn_protocol_deinit(); -extern void idn_timer_expired(void *arg); -extern int idn_open_channel(int channel); -extern void idn_close_channel(int channel, idn_chanop_t chanop); -extern idn_mainmbox_t *idn_mainmbox_init(int domid, int mbx); -extern void idn_mainmbox_deinit(int domid, idn_mainmbox_t *mmp); -extern void idn_signal_data_server(int domid, ushort_t channel); -extern int idn_chanservers_init(); -extern void idn_chanservers_deinit(); -extern void idn_chanserver_bind(int net, int cpuid); -extern int idn_retry_terminate(uint_t token); -extern idn_protojob_t *idn_protojob_alloc(int kmflag); -extern void idn_protojob_submit(int cookie, idn_protojob_t *jp); -extern int idn_domain_is_registered(int domid, int channel, - idn_chanset_t *chansetp); -extern void idn_xmit_monitor_kickoff(int chan_wanted); -extern void idn_sync_exit(int domid, idn_synccmd_t cmd); -/* - * --------------------------------------------------------------------- - * io/idn_xf.c - * --------------------------------------------------------------------- - */ -extern void idnxf_flushall_ecache(); -extern int idnxf_shmem_add(int is_master, boardset_t boardset, - pfn_t pfnbase, pfn_t pfnlimit, - uint_t *mcadr); -extern int idnxf_shmem_sub(int is_master, boardset_t boardset); -extern int idn_cpu_per_board(void *p2o, cpuset_t cset, - struct hwconfig *hwp); -/* - * --------------------------------------------------------------------- - * io/idn_dlpi.c - * --------------------------------------------------------------------- - */ -extern int idndl_init(struct idn *sip); -extern void idndl_uninit(struct idn *sip); -extern void idndl_statinit(struct idn *sip); -extern void idndl_dodetach(struct idnstr *); -extern int idnioc_dlpi(queue_t *wq, mblk_t *mp, int *argsize); -extern void idndl_localetheraddr(struct idn *sip, struct ether_addr *eap); -extern int idndl_domain_etheraddr(int domid, int instance, - struct ether_addr *eap); -extern void idndl_dlpi_init(); -extern int idndl_start(queue_t *wq, mblk_t *mp, struct idn *sip); -extern void idndl_read(struct idn *sip, mblk_t *mp); -extern void idndl_proto(queue_t *wq, mblk_t *mp); -extern void idndl_sendup(struct idn *, mblk_t *, struct idnstr *(*)()); -extern struct idnstr *idndl_accept(struct idnstr *, struct idn *, int, - struct ether_addr *); -extern struct idnstr *idndl_paccept(struct idnstr *, struct idn *, int, - struct ether_addr *); -extern void idndl_wenable(struct idn *); -/* - * --------------------------------------------------------------------- - * io/idn_smr.c - * --------------------------------------------------------------------- - */ -extern void smr_slabwaiter_open(domainset_t domset); -extern void smr_slabwaiter_close(domainset_t domset); -/* - * --------------------------------------------------------------------- - */ -extern void idn_smrsize_init(); -extern void idn_init_autolink(); -extern void idn_deinit_autolink(); - -extern void idn_dmv_handler(void *arg); -extern void idnxf_init_mondo(uint64_t dmv_word0, - uint64_t dmv_word1, uint64_t dmv_word2); -extern int idnxf_send_mondo(int upaid); - -extern clock_t idn_msg_waittime[]; -extern clock_t idn_msg_retrytime[]; - -#endif /* !_ASM */ -#endif /* _KERNEL */ - -#ifndef _ASM -/* - * --------------------------------------------------------------------- - */ -#define IDN_NIL_DOMID -1 -#define IDN_NIL_DCPU -1 - -/* - * --------------------------------------------------------------------- - */ - -/* - * IOCTL Interface - * - * Commands must stay in the range (1 - 4096) since only 12 bits - * are allotted. - */ -#define _IDN(n) (('I' << 20) | ('D' << 12) | (n)) -#define IDNIOC_LINK _IDN(1) /* domain_link */ -#define IDNIOC_UNLINK _IDN(2) /* domain_unlink */ -#define IDNIOC_unused0 _IDN(3) -#define IDNIOC_unused1 _IDN(4) -#define IDNIOC_unused2 _IDN(5) -#define IDNIOC_unused3 _IDN(6) -#define IDNIOC_unused4 _IDN(7) -#define IDNIOC_DLPI_ON _IDN(8) /* Turn ON DLPI on str */ -#define IDNIOC_DLPI_OFF _IDN(9) /* Turn OFF DLPI on str */ -#define IDNIOC_PING _IDN(10) /* For latency testing */ -#define IDNIOC_PING_INIT _IDN(11) -#define IDNIOC_PING_DEINIT _IDN(12) -#define IDNIOC_MEM_RW _IDN(13) /* Random R/W of SMR */ - - -#define VALID_NDOP(op) (((op) == ND_SET) || ((op) == ND_GET)) - -#define VALID_DLPIOP(op) (((op) == DLIOCRAW) || \ - ((op) == DL_IOC_HDR_INFO)) - -#define VALID_IDNOP(op) (((op) >= _IDN(1)) && ((op) <= _IDN(13))) - -#define VALID_IDNIOCTL(op) (VALID_IDNOP(op) || \ - VALID_NDOP(op) || \ - VALID_DLPIOP(op)) - -typedef union idnop { - struct { - int domid; /* input */ - int cpuid; /* input */ - int master; /* input */ - int wait; /* input */ - } link; - struct { - int domid; /* input */ - int cpuid; /* input */ - int force; /* input */ - int wait; /* input */ - } unlink; - struct { - int domid; /* input */ - int cpuid; /* input */ - } ping; - struct { - uint_t lo_off; /* input */ - uint_t hi_off; /* input */ - int blksize; /* input */ - int num; /* input */ - int rw; /* input */ - int goawol; /* input */ - } rwmem; -} idnop_t; - -#ifdef _KERNEL -/* - * ndd support for IDN tunables. - */ -typedef struct idnparam { - ulong_t sp_min; - ulong_t sp_max; - ulong_t sp_val; - char *sp_name; -} idnparam_t; - -extern idnparam_t idn_param_arr[]; - -#define idn_modunloadable idn_param_arr[0].sp_val -#ifdef IDN_PERF -#define _LP 0 -#define _xxx_tbd idn_param_arr[_LP+1].sp_val -#endif /* IDN_PERF */ - -/* - * ===================================================================== - */ - -/* - * Some junk to pretty print board lists and cpu lists in - * log/console messages. Length is big enough to display 64 double - * digit cpus separated by a command and single space. (Board list - * is similar, but only 16 entries possible. - */ -#define _DSTRLEN 400 -#define ALLOC_DISPSTRING() ((char *)kmem_alloc(_DSTRLEN, KM_NOSLEEP)) -#define FREE_DISPSTRING(b) (kmem_free((void *)(b), _DSTRLEN)) - -/* - * These are declared in idn.c. - */ -extern const char *idnds_str[]; -extern const char *idnxs_str[]; -extern const char *idngs_str[]; -extern const char *idncmd_str[]; -extern const char *idncon_str[]; -extern const char *idnfin_str[]; -extern const char *idnfinarg_str[]; -extern const char *idnfinopt_str[]; -extern const char *idnreg_str[]; -extern const char *idnnack_str[]; -extern const char *idnop_str[]; -extern const char *idnsync_str[]; -extern const char *chanop_str[]; -extern const char *chanaction_str[]; -extern const char *inum_str[]; -extern const int inum_bump; -extern const int inum_max; -extern const int acknack_shift; - -extern const char *timer_str[]; -extern const char *res_str[]; - -#endif /* _KERNEL */ -#endif /* !_ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_IDN_H */ diff --git a/usr/src/uts/sun4u/starfire/sys/idn_sigb.h b/usr/src/uts/sun4u/starfire/sys/idn_sigb.h deleted file mode 100644 index 9e1d256d9a..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/idn_sigb.h +++ /dev/null @@ -1,401 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999-2000 by Sun Microsystems, Inc. - * All rights reserved. - * - * Inter-Domain Network Sigblock Interface. - * - * ****************************************************** - * ****************************************************** - * IMPORTANT: THE DEFINITIONS HERE ARE DUPLICATES OF - * THE cbe_idn_sigb.h FILE IN cbe/cbutils. - * ANY CHANGES THERE MUST BE RELECTED - * HERE AND VICE VERSA. WE CANNOT INCLUDE - * THIS HEADER IN THE BUILD OF CBE. - * ****************************************************** - * ****************************************************** - */ - -#ifndef _SYS_IDN_SIGB_H -#define _SYS_IDN_SIGB_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _SSP -#include <domain_config.h> -#include <sigblock.h> -#define _MAX_DOMAINS MAX_DOMAINS_PER_MACH -#else /* _SSP */ -#include <sys/starfire.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/cpu_sgn.h> -#define MAX_BOARDS STARFIRE_MAX_BOARDS -#define MAX_DOMAINS MAX_BOARDS -#define _MAX_DOMAINS MAX_DOMAINS -#endif /* _SSP */ - -#define SSI_LINK (('I' << 8) | 0x01) -#define SSI_UNLINK (('I' << 8) | 0x02) -#define SSI_INFO (('I' << 8) | 0x03) -#define SSI_ACK 0x10 - -#define VALID_IDNSIGBCMD(c) ((((c) & ~SSI_ACK) == SSI_LINK) || \ - (((c) & ~SSI_ACK) == SSI_UNLINK) || \ - (((c) & ~SSI_ACK) == SSI_INFO)) - -/* - * SSI_LINK - * timeout field must be first. - */ -typedef struct { - int32_t timeout; /* seconds */ - int32_t cpuid; - int32_t domid; - int32_t master_pri; -} idnsb_link_t; - - -/* - * SSI_UNLINK - * timeout field must be first. - * - * If both cpuid and domid are specified then they must match the - * correct domain from the local domain's perspective. The cpuid - * and/or domid have precedence over the boardset parameter. - * The boardset parameter is provided if the caller is unable to - * determine the cpuid/domid of the target domain. This may happen - * if the target domain is currently down. - * - * idnsb_unlink_t.force values. - */ -#define SSIFORCE_OFF 0 -#define SSIFORCE_SOFT 1 -#define SSIFORCE_HARD 2 - -typedef struct { - int32_t timeout; /* seconds */ - int32_t cpuid; - int32_t domid; - ushort_t boardset; - short force; - ushort_t idnset; -} idnsb_unlink_t; - - -/* - * SSI_INFO - * Assumes max of 16 boards/domain. - * - * idnsb_info_t.idn_active values. - */ -#define SSISTATE_INACTIVE 0 -#define SSISTATE_BUSY 1 -#define SSISTATE_ACTIVE 2 - -typedef struct { - ushort_t domain_boardset[_MAX_DOMAINS]; - uchar_t idn_active; - uchar_t idn_state; /* same as GSTATE */ - uchar_t local_index; - uchar_t local_cpuid; - uchar_t master_index; - uchar_t master_cpuid; - ushort_t awol_domset; - ushort_t conn_domset; - ushort_t _filler; -} idnsb_info_t; - -#define INIT_IDNKERR(ep) \ - (bzero((caddr_t)(ep), sizeof (idnsb_error_t))) -#define SET_IDNKERR_ERRNO(ep, err) ((ep)->k_errno = (int)(err)) -#define SET_IDNKERR_IDNERR(ep, err) ((ep)->k_idnerr = (int)(err)) -#define SET_IDNKERR_PARAM0(ep, p0) ((ep)->k_param[0] = (uint_t)(p0)) -#define SET_IDNKERR_PARAM1(ep, p1) ((ep)->k_param[1] = (uint_t)(p1)) -#define SET_IDNKERR_PARAM2(ep, p2) ((ep)->k_param[2] = (uint_t)(p2)) -#define GET_IDNKERR_ERRNO(ep) ((ep)->k_errno) -#define GET_IDNKERR_IDNERR(ep) ((ep)->k_idnerr) -#define GET_IDNKERR_PARAM0(ep) ((ep)->k_param[0]) -#define GET_IDNKERR_PARAM1(ep) ((ep)->k_param[1]) -#define GET_IDNKERR_PARAM2(ep) ((ep)->k_param[2]) - -#define IDNKERR_DRV_DISABLED 0x100 /* IDN driver disabled */ - /* param=none */ -#define IDNKERR_DATA_LEN 0x101 /* invalid length of idnsb_data_t */ - /* p0=length */ -#define IDNKERR_INFO_FAILED 0x102 /* SSI_INFO failed */ - /* param=none */ -#define IDNKERR_INVALID_DOMAIN 0x103 /* invalid domain specified */ - /* p0=domid, p1=cpuid */ -#define IDNKERR_INVALID_FORCE 0x104 /* invalid force option specified */ - /* p0=force */ -#define IDNKERR_INVALID_CMD 0x105 /* invalid IDN/SSI command req */ - /* p0=cmd */ -#define IDNKERR_INVALID_WTIME 0x106 /* invalid waittime specified */ - /* p0=waittime */ -#define IDNKERR_SMR_CORRUPTED 0x107 /* SMR memory is corrupted */ - /* p0=domid (against who detected) */ -#define IDNKERR_CPU_CONFIG 0x108 /* missing a cpu per board */ - /* p0=domid */ -#define IDNKERR_HW_ERROR 0x109 /* error programming hardware */ - /* p0=domid */ -#define IDNKERR_SIGBINTR_LOCKED 0x10a /* sigbintr is locked */ -#define IDNKERR_SIGBINTR_BUSY 0x10b /* sigbintr is busy working */ -#define IDNKERR_SIGBINTR_NOTRDY 0x10c /* sigbintr thread not ready */ -#define IDNKERR_CONFIG_FATAL 0x10d /* fatal error during config */ -#define IDNKERR_CONFIG_MULTIPLE 0x10e /* multiple config conflicts */ - /* p0=domid, p1=count */ - /* - * For all CONFIG errors: - * p0=domid, p1=expected, p2=actual. - */ -#define IDNKERR_CONFIG_MTU 0x10f /* MTU configs conflict */ -#define IDNKERR_CONFIG_BUF 0x110 /* SMR_BUF_SIZE conflicts */ -#define IDNKERR_CONFIG_SLAB 0x111 /* slab-size conflicts */ -#define IDNKERR_CONFIG_NWR 0x112 /* NWR sizes conflict */ -#define IDNKERR_CONFIG_NETS 0x113 /* MAX_NETS conflict */ -#define IDNKERR_CONFIG_MBOX 0x114 /* MBOX_PER_NETS conflict */ -#define IDNKERR_CONFIG_NMCADR 0x115 /* Number of MCADRS conflicts */ -#define IDNKERR_CONFIG_MCADR 0x116 /* Missing MCADR */ -#define IDNKERR_CONFIG_CKSUM 0x117 /* checksum setting conflicts */ -#define IDNKERR_CONFIG_SMR 0x118 /* master's SMR too large */ - -typedef struct { - int k_errno; - int k_idnerr; - uint_t k_param[3]; -} idnsb_error_t; - -typedef struct { - union { - int _ssb_timeout; /* link & unlink only (secs) */ - idnsb_link_t _ssb_link; - idnsb_unlink_t _ssb_unlink; - idnsb_info_t _ssb_info; - } _u; - idnsb_error_t ssb_error; -} idnsb_data_t; - -#define ssb_timeout _u._ssb_timeout -#define ssb_link _u._ssb_link -#define ssb_unlink _u._ssb_unlink -#define ssb_info _u._ssb_info - - -/* - * Boot information set by IDN driver when loaded. - * SSIEVENT_BOOT Indicates IDN driver is ready for linking. - * If this nibble is cleared (0) it - * indicates domain has halted. - * SSIEVENT_AWOL Indicates local IDN has reported - * some domains (boards) have gone AWOL. - * (event_handled) is primarily used by SSP/CB applications for - * synchronization with respect to handling event triggered in (event). - * The respective bits from (event) are set in (event_handled) - * when the event has been successfully processed by IDNevent(SSP). - * It is cleared by CBE based TCL scripts (mon_signatures.tcl, idn.tcl) - * when event is detected and needs processing. - * SSIEVENT_VERSION represents the version of the SSP side of - * the IDN software. While idnsb_event_t.version represents the - * version of the OS side of the IDN software. - * - * Protocol: Host SSP - * ---- --- - * event - * - 1 -> evt[].e_handled - * - X -> evt[].e_event - * - Y -> evt[].e_event_data - * - 0 -> evt[].e_handled - * (!evt[].e_handled) - * ...process(evt[].e_event) - * - evt[].e_handled_data = - * evt[].e_event_data - * - evt[].e_handled = 1 - */ -#define SSIEVENT_COOKIE "IDN" -#define SSIEVENT_COOKIE_LEN 3 -#define SSIEVENT_VERSION 1 - -#define SSIEVENT_BOOT 0 /* index to evt[] */ -#define _SSIEVENT_BOOT_VAL 0xb -#define _SSIEVENT_BOOT_SHIFT (SSIEVENT_BOOT << 2) -#define _SSIEVENT_BOOT_MASK (_SSIEVENT_BOOT_VAL << _SSIEVENT_BOOT_SHIFT) - -#define SSIEVENT_AWOL 1 -#define _SSIEVENT_AWOL_VAL 0xa -#define _SSIEVENT_AWOL_SHIFT (SSIEVENT_AWOL << 2) -#define _SSIEVENT_AWOL_MASK (_SSIEVENT_AWOL_VAL << _SSIEVENT_AWOL_SHIFT) - -#define SSIEVENT_NUM 2 /* actual max simultaneous events */ -#define SSIEVENT_MAXNUM 3 /* last one in reserve */ - -#define _SSIEVENT_VALUE(i) \ - ((i == 0) ? _SSIEVENT_BOOT_VAL : ((i == 1) ? _SSIEVENT_AWOL_VAL : 0)) - -#define _SSIEVENT_MASKS(i) \ - ((i == 0) ? _SSIEVENT_BOOT_MASK : ((i == 1) ? _SSIEVENT_AWOL_MASK : 0)) -/* - * Get a bitmask of the current "state". - */ -#define SSIEVENT_GET_STATE_MASK(s) \ - (((s).idn_evt[SSIEVENT_BOOT].e_event ? _SSIEVENT_BOOT_MASK : 0) \ - | ((s).idn_evt[SSIEVENT_AWOL].e_event ? _SSIEVENT_AWOL_MASK : 0)) - -#define SSIEVENT_GET_STATE(s, e) \ - ((s).idn_evt[e].e_event ? _SSIEVENT_VALUE(e) : 0) -#define SSIEVENT_CLR_STATE(s, e) \ - ((s).idn_evt[e].e_event = 0) -#define SSIEVENT_SET_STATE(s, e) \ - ((s).idn_evt[e].e_event = _SSIEVENT_VALUE(e)) - -/* - * Get a bitmask of the currently handled states. - */ -#define SSIEVENT_GET_HANDLED_MASK(s) \ - (((s).idn_evt[SSIEVENT_BOOT].e_handled ? _SSIEVENT_BOOT_MASK : 0) \ - | ((s).idn_evt[SSIEVENT_AWOL].e_handled ? _SSIEVENT_AWOL_MASK : 0)) - -#define SSIEVENT_GET_HANDLED(s, e) \ - ((s).idn_evt[e].e_handled ? _SSIEVENT_VALUE(e) : 0) -#define SSIEVENT_CLR_HANDLED(s, e) \ - ((s).idn_evt[e].e_handled = 0) -#define SSIEVENT_SET_HANDLED(s, e) \ - ((s).idn_evt[e].e_handled = _SSIEVENT_VALUE(e)) -#define SSIEVENT_SET_HANDLED_DATA(s, e, d) \ - ((s).idn_evt[e].e_handled_data = (ushort_t)(d)) -#define SSIEVENT_GET_HANDLED_EVT(i, e) \ - ((i).e_handled ? _SSIEVENT_VALUE(e) : 0) -#define SSIEVENT_CLR_HANDLED_EVT(i) ((i).e_handled = 0) -#define SSIEVENT_SET_HANDLED_EVT(i, e) ((i).e_handled = _SSIEVENT_VALUE(e)) - -/* - * Check for the state of a particular event within a state bitmask. - */ -#define SSIEVENT_CHK_STATE_MASK(m, e) \ - ((((m) & (0xf << ((e) << 2))) == _SSIEVENT_MASKS(e)) ? 1 : 0) -#define SSIEVENT_CHK_HANDLED_MASK(m, e) SSIEVENT_CHK_STATE_MASK((m), (e)) - -/* - * Build the state mask managed in the cbe to represent the state - * of the respective events above. - */ -#define SSIEVENT_DEL_STATE_MASK(m, e) ((m) &= ~(0xf << ((e) << 2))) -#define SSIEVENT_ADD_STATE_MASK(m, e) \ - (SSIEVENT_DEL_STATE_MASK((m), (e)), \ - ((m) |= _SSIEVENT_MASKS(e))) -#define SSIEVENT_STATE_MASK (_SSIEVENT_BOOT_MASK | _SSIEVENT_AWOL_MASK) -#define SSIEVENT_STATE_NIL 0 - -#ifdef _KERNEL -#define SSIEVENT_SET(s, e, d) { \ - SSIEVENT_SET_HANDLED(*(s), (e)); \ - membar_stst_stld(); \ - SSIEVENT_SET_STATE(*(s), (e)); \ - (s)->idn_evt[e].e_event_data = (ushort_t)(d); \ - membar_stst_stld(); \ - SSIEVENT_CLR_HANDLED(*(s), (e)); \ -} -#define SSIEVENT_CLEAR(s, e, d) { \ - SSIEVENT_SET_HANDLED(*(s), (e)); \ - membar_stst_stld(); \ - SSIEVENT_CLR_STATE(*(s), (e)); \ - (s)->idn_evt[e].e_event_data &= (ushort_t)~(d); \ - membar_stst_stld(); \ - SSIEVENT_CLR_HANDLED(*(s), (e)); \ -} -#define SSIEVENT_ADD(s, e, d) { \ - SSIEVENT_SET_HANDLED(*(s), (e)); \ - membar_stst_stld(); \ - SSIEVENT_SET_STATE(*(s), (e)); \ - (s)->idn_evt[e].e_event_data |= (ushort_t)(d); \ - membar_stst_stld(); \ - SSIEVENT_CLR_HANDLED(*(s), (e)); \ -} -#define SSIEVENT_DEL(s, e, d) { \ - SSIEVENT_SET_HANDLED(*(s), (e)); \ - membar_stst_stld(); \ - (s)->idn_evt[e].e_event_data &= (ushort_t)~(d); \ - if ((s)->idn_evt[e].e_event_data != 0) { \ - SSIEVENT_SET_STATE(*(s), (e)); \ - membar_stst_stld(); \ - SSIEVENT_CLR_HANDLED(*(s), (e)); \ - } else { \ - membar_stst_stld(); \ - SSIEVENT_CLR_STATE(*(s), (e)); \ - } \ -} -#endif /* _KERNEL */ - -typedef struct idnevent { - uchar_t e_event; - uchar_t e_handled; - ushort_t e_event_data; - ushort_t e_handled_data; - ushort_t reserved; -} idnevent_t; - -/* - * IMPORTANT: This data structure must be the size of a sigbmbox_t - * so that it fits in the space it steals in the sigblock. - * Also, any changes to this structure must be cross-checked - * with (struct idnsb) in <sun4u1/sys/idn.h> with respect - * the area from reserved1 on down. - */ -#define IDNSB_EVENT_SIZE (sizeof (sigbmbox_t)) -typedef struct { - struct _idnsb_event { - union { - struct { - char _cookie[SSIEVENT_COOKIE_LEN]; - uchar_t _version; - } _ss; - struct { - uint_t _cookie : 24; - uint_t _version : 8; - } _sn; - } _u; - uint_t _reserved1; /* reserved for IDN driver */ - idnevent_t _evt[SSIEVENT_MAXNUM]; - } _s; - - /* reserved for IDN driver */ - char reserved2[IDNSB_EVENT_SIZE - sizeof (struct _idnsb_event)]; -} idnsb_event_t; - -#define idn_evt _s._evt -#define idn_reserved1 _s._reserved1 -#define idn_cookie_str _s._u._ss._cookie -#define idn_version_byte _s._u._ss._version -#define idn_cookie _s._u._sn._cookie -#define idn_version _s._u._sn._version - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_IDN_SIGB_H */ diff --git a/usr/src/uts/sun4u/starfire/sys/idn_smr.h b/usr/src/uts/sun4u/starfire/sys/idn_smr.h deleted file mode 100644 index 8a0e4cddb2..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/idn_smr.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999 by Sun Microsystems, Inc. - * All rights reserved. - * - * Inter-Domain Network - SMR support. - */ - -#ifndef _SYS_IDN_SMR_H -#define _SYS_IDN_SMR_H - -#include <sys/sysmacros.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint_t smr_offset_t; - -#define IDN_NIL_SMROFFSET ((smr_offset_t)-1) - -/* - * --------------------------------------------------------------------- - * Data in the SMR is automatically aligned on 64 byte boundaries due - * to the large IDN_SMR_BUFSIZE, however the streams buffers may not be - * so we bump them in order to allow us to align appropriately and thus - * maximize bcopy performance. - * --------------------------------------------------------------------- - */ -#define IDN_ALIGNSIZE 64 -/* - * Align the pointer "p" to the same relative offset as the reference - * pointer "r" within IDN_ALIGNSIZE bytes. - */ -#define IDN_ALIGNPTR(p, r) ((uintptr_t)(p) + (((uintptr_t)(r) - \ - (uintptr_t)(p)) & \ - (uintptr_t)(IDN_ALIGNSIZE - 1))) - -#define IDN_OFFSET2ADDR(off) ((caddr_t)((uintptr_t)(off) + \ - (uintptr_t)idn.smr.vaddr)) -#define IDN_ADDR2OFFSET(va) ((smr_offset_t)((caddr_t)(va) - idn.smr.vaddr)) -#define IDN_BUF2DATA(b, o) ((caddr_t)((uintptr_t)(b) + (uintptr_t)(o))) -#define IDN_BUF2HDR(b) ((smr_pkthdr_t *)(b)) - -#define IDN_CKSUM_PKT_COUNT (offsetof(smr_pkthdr_t, b_cksum) / 2) - -#define IDN_CKSUM_PKT(h) \ - (IDN_CHECKSUM ? \ - idn_cksum((ushort_t *)(h), IDN_CKSUM_PKT_COUNT) : 0) - -typedef struct smr_pkthdr { - uint_t b_netaddr; - uint_t b_netports; - smr_offset_t b_offset; - int b_length; - - ushort_t b_rawio; - ushort_t b_cksum; - smr_offset_t b_next; /* used during reclamation */ -} smr_pkthdr_t; - -/* - * --------------------------------------------------------------------- - * IDN Slab related definitions. - * - * Domains are allocated SMR buffers in slabs. Slaves keep track of - * their own slabs in their respective idn_domain entry. The Master - * keeps track of slave slabs via their respective idn_domain entry. - * The global slab pools representing all of the SMR and managed by - * the master are maintained in the idn_global structure. - * - * The minimum number of slabs is chosen so that there is at least - * one slab available for every possible domain that might be attached. - * - * NOTE: idn_slab_bufcount * idn_smr_bufsize should be on a 64-byte - * (IDN_ALIGNSIZE) boundary for maximum bcopy performance. - * --------------------------------------------------------------------- - */ -#define IDN_SLAB_BUFCOUNT idn_slab_bufcount -#define IDN_SLAB_SIZE (IDN_SLAB_BUFCOUNT * IDN_SMR_BUFSIZE) -#define IDN_SLAB_MAXNUM (idn.slabpool->ntotslabs) -#define IDN_SLAB_MINPERPOOL 3 -#define IDN_SLAB_MINTOTAL idn_slab_mintotal -#define IDN_SLAB_PREALLOC idn_slab_prealloc - -/* - * --------------------------------------------------------------------- - * Maximum number of slabs per domain the master will - * allow to be allocated. Further requests simply result - * in a failed allocation. - * Nominal value is 1/6 of the total available (~10). - * Maximum number of bufs a domain can expect based on - * IDN_SLAB_MAXPERDOMAIN. - * --------------------------------------------------------------------- - */ -#define IDN_SLAB_MAXPERDOMAIN idn_slab_maxperdomain -#define IDN_BUF_MAXPERDOMAIN (IDN_SLAB_MAXPERDOMAIN * IDN_SLAB_BUFCOUNT) -/* - * --------------------------------------------------------------------- - * If the total number of available slabs managed by the master - * goes below this minimum total threshold, then the master kicks - * off a reap request to all domains to check for free slabs and - * to give them up. For performance reasons, domains do not - * automatically flush out free slabs. They rely on the master - * to tell them to look for some. - * --------------------------------------------------------------------- - */ -#define IDN_SLAB_THRESHOLD MIN(MAX_DOMAINS, \ - (IDN_SLAB_MINTOTAL + \ - (IDN_SLAB_MINTOTAL / 5))) -#define IDN_REAP_INTERVAL (2 * hz) - -#define SMR_SLABPOOL_HASH(d) ((d) % idn.slabpool->npools) -#define SMR_SLABPOOL_HASHSTEP(p) (((p)+4) % idn.slabpool->npools) -#define SMR_SLAB_HASH(p, d) \ - ((d) % idn.slabpool->pool[p].nslabs) -#define SMR_SLAB_HASHSTEP(p, s) \ - (((s)+1) % idn.slabpool->pool[p].nslabs) - -/* - * --------------------------------------------------------------------- - * There is one smr_slabbuf for each buffer in the respective slab. - * - * sb_domid Domainid currently owning respective buffer. - * Local domains use this field to determine what buffers - * are outstanding at which domains. The master uses this - * field to know which domain owns given slab. - * sb_bufp Actual pointer to (VA) buffer. - * sb_next Used to manage free and in-use lists. - * --------------------------------------------------------------------- - */ -typedef struct smr_slabbuf { - int sb_domid; - caddr_t sb_bufp; - struct smr_slabbuf *sb_next; -} smr_slabbuf_t; - -/* - * --------------------------------------------------------------------- - * There is one smr_slab per slab of buffers. - * - * sl_next List of slabs allocated to same requester. - * sl_start Base virtual address (SMR) of slab. - * sl_end Points to byte immediately following end of slab. - * sl_lock Atomic lock used to manage free/inuse lists. - * sl_domid Used by Master to indicate which slave owns - * respective slab. - * sl_free Freelist of available buffers. - * sl_inuse List of buffers currently allocated and in-use. - * sl_head Pointer to memory allocated to hold smr_slabbuf_t's. - * --------------------------------------------------------------------- - */ -typedef struct smr_slab { - struct smr_slab *sl_next; - caddr_t sl_start, - sl_end; - lock_t sl_lock; - - union { - int _sl_domid; - struct { - smr_slabbuf_t *_sl_free; - smr_slabbuf_t *_sl_inuse; - smr_slabbuf_t *_sl_head; - } _s; - } _u; -} smr_slab_t; - -#define sl_domid _u._sl_domid -#define sl_free _u._s._sl_free -#define sl_inuse _u._s._sl_inuse -#define sl_head _u._s._sl_head - -/* - * --------------------------------------------------------------------- - * io/idn_smr.c - * --------------------------------------------------------------------- - */ -extern void smr_slab_reap(int domid, int *nslabs); -extern int smr_slab_alloc(int domid, smr_slab_t **spp); -extern void smr_slab_free(int domid, smr_slab_t *sp); -extern void smr_slab_garbage_collection(smr_slab_t *sp); -extern int smr_slab_busy(smr_slab_t *sp); -extern int smr_buf_alloc(int domid, uint_t len, caddr_t *bufpp); -extern int smr_buf_free(int domid, caddr_t bufp, uint_t len); -extern int smr_buf_free_locked(int domid, caddr_t bufp, uint_t len); -extern int smr_buf_free_all(int domid); -extern int smr_buf_reclaim(int domid, int nbufs); -extern int smr_slaballoc_put(int domid, smr_slab_t *sp, int forceflag, - int serrno); -extern void smr_alloc_buflist(smr_slab_t *sp); -extern void smr_free_buflist(smr_slab_t *sp); -extern int smr_slabwaiter_init(); -extern void smr_slabwaiter_deinit(); -extern int smr_slabwaiter_abort(int domid, int serrno); -extern smr_slab_t *smr_slaballoc_get(int domid, caddr_t bufp, - caddr_t ebufp); -extern int smr_slabpool_init(size_t reserved_size, - caddr_t *reserved_area); -extern void smr_slabpool_deinit(); -extern void smr_remap(struct as *as, register caddr_t vaddr, - register pfn_t new_pfn, uint_t mblen); - -extern int idn_slab_prealloc; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_IDN_SMR_H */ diff --git a/usr/src/uts/sun4u/starfire/sys/idn_xf.h b/usr/src/uts/sun4u/starfire/sys/idn_xf.h deleted file mode 100644 index e23b9005d3..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/idn_xf.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1999 by Sun Microsystems, Inc. - * All rights reserved. - * - * Inter-Domain Network - Xfire specifics. - */ - -#ifndef _SYS_IDN_XF_H -#define _SYS_IDN_XF_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/pda.h> -#include <sys/cpu_sgnblk_defs.h> -#include <sys/idn_sigb.h> -#include <sys/starfire.h> - -#include <sys/idn.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * These address bits fit into PA[17:9]. - */ -#define CIC_CONFIG0_ADDR 0x002 -#define CIC_CONFIG1_ADDR 0x003 -#define CIC_DOMAIN_MASK_ADDR 0x004 -#define CIC_SM_MASK_ADDR 0x005 -#define CIC_SM_BAR_LSB_ADDR 0x006 -#define CIC_SM_BAR_MSB_ADDR 0x007 -#define CIC_SM_LAR_LSB_ADDR 0x008 -#define CIC_SM_LAR_MSB_ADDR 0x009 - -#define CIC_CONFIG0_BUSMODE_MASK 0x3 -#define CIC_CONFIG0_BUSMODE_SHIFT 2 -#define CIC_CONFIG0_BUSMODE(c) \ - (((c) >> CIC_CONFIG0_BUSMODE_SHIFT) & CIC_CONFIG0_BUSMODE_MASK) -#define CIC_CONFIG1_SMMASK_MASK 0x1 -#define CIC_CONFIG1_SMMASK_SHIFT 1 -#define CIC_CONFIG1_SMMASK_BIT(c) \ - (((c) >> CIC_CONFIG1_SMMASK_SHIFT) & CIC_CONFIG1_SMMASK_MASK) - -#define CIC_CSR_ADDR_MASK 0x1ff -#define CIC_CSR_ADDR_SHIFT 9 -#define CSR_TYPE_CIC 0xe - -#define CSR_BOARD_MASK 0xf /* PA[39:36] */ -#define CSR_BOARD_SHIFT 36 - -#define CSR_TYPE_MASK 0xf /* PA[35:32] */ -#define CSR_TYPE_SHIFT 32 - -#define CSR_BUS_MASK 0x3 -#define CSR_BUS_SHIFT 6 /* XXX - depends on config/shuffle */ - - /* bd=board, t=type, a=addr, bs=bus */ -#define MAKE_CIC_CSR_PA(bd, t, a, bs) \ - (((u_longlong_t)1 << 40) \ - | ((u_longlong_t)((bd) & CSR_BOARD_MASK) \ - << CSR_BOARD_SHIFT) \ - | ((u_longlong_t)((t) & CSR_TYPE_MASK) \ - << CSR_TYPE_SHIFT) \ - | ((u_longlong_t)((a) & CIC_CSR_ADDR_MASK) \ - << CIC_CSR_ADDR_SHIFT) \ - | ((u_longlong_t)((bs) & CSR_BUS_MASK) \ - << CSR_BUS_SHIFT)) - -#define STARFIRE_PC_MADR_VALIDBIT 0x80000000 - -/* - * Macro to calculate address of CIC prep buffer - * that resides in PC. - * This macro really belongs in <sys/starfire.h> - */ -#define STARFIRE_PC_CICBUF_ADDR(bb, p) \ - (STARFIRE_BRD_TO_PSI(bb) | \ - ((uint64_t)(p) << STARFIRE_UPS_MID_SHIFT) | \ - STARFIRE_PSI_PCREG_OFF | \ - STARFIRE_PC_CIC_WRITE_DATA) - -/* - * --------------------------------------------------------------------- - */ - -extern cpu_t cpu0; - -extern int get_hw_config(struct hwconfig *loc_hw); -extern int update_local_hw_config(idn_domain_t *ldp, - struct hwconfig *loc_hw); -extern boardset_t cic_read_domain_mask(int board, int bus); -extern boardset_t cic_read_sm_mask(int board, int bus); -extern uint_t cic_read_sm_bar(int board, int bus); -extern uint_t cic_read_sm_lar(int board, int bus); -extern void pc_read_madr(pda_handle_t ph, int lboard, - uint_t mc_adr[], int local_only); -extern void mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], - int *nmcadr); -extern int post2obp_valid(post2obp_info_t *p2o); - -extern uint_t xf_physio_rdword(u_longlong_t physaddr); -extern void xf_physio_wrword(u_longlong_t physaddr, uint_t value); -extern ushort_t xf_physio_rdhword(u_longlong_t physaddr); -extern void xf_physio_wrhword(u_longlong_t physaddr, ushort_t value); - - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_IDN_XF_H */ diff --git a/usr/src/uts/sun4u/starfire/sys/pda.h b/usr/src/uts/sun4u/starfire/sys/pda.h deleted file mode 100644 index 0725f45347..0000000000 --- a/usr/src/uts/sun4u/starfire/sys/pda.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_PDA_H -#define _SYS_PDA_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> - -/* - * Contains definitions used for PDA (Post Descriptor Array) [post2obp] - * support. - * - * XXX - These data structures is defined in SSP-land in: - * src/post/export/xf_postif.h. It is not anticipated - * that any future changes will be made to this data - * structure so we'll allow this hack on this go around. - */ - -#define MAX_ABUSES 4 /* Address buses */ -#define MAX_DBUSES 2 /* Data buses */ - -#define MAX_SYSBDS 16 /* no more than 16 system boards */ -#define MAX_PROCMODS 4 /* Per system board */ -#define MAX_PC 3 /* Per system board */ -#define MAX_XDB 4 /* Per system board */ -#define MAX_CIC 4 /* Per system board */ -#define MAX_MGROUPS 4 /* Per MC and system board */ -#define MAX_IOCS 2 /* Per system board */ -#define MAX_SLOTS_PER_IOC 4 /* Per ioc */ - -typedef struct { - ushort_t bda_board; /* BDAN 0|Anyred|mem|Board */ - ushort_t bda_proc; /* BDAN Processor 3:0 */ - ushort_t bda_pc; /* BDAN PC asic 2:0 */ - ushort_t bda_xdb; /* BDAN XDB asic 3:0 */ - ushort_t bda_cic; /* BDAN CIC asic 3:0 */ - ushort_t bda_ldpath; /* BDAN 0|0| ldpath [dbus] */ - ushort_t bda_ioc; /* BDAN 0|0| ioc 1:0 */ - ushort_t bda_ios[MAX_IOCS]; /* BDAN Scard 3:0 */ - ushort_t bda_mgroup; /* BDAN memory group 3:0 */ -} board_desc_t; - -typedef struct { - ushort_t bada_proc [MAX_PROCMODS]; /* Extra status on procs */ - uchar_t bada_iom_type; /* I/O module type. */ - uchar_t bada_fill[3]; - ushort_t bada_ioc[MAX_IOCS]; /* Extra status on iocs */ -} board_auxdesc_t; - -/* - * The three lsb of bada_proc holds the ecache size of that proc - * module, as (log-base-2 - 19), so 1/2 MB is 0, 1 MB is 1, ... - * 32 MB is 6. 7 is a bogus value. - */ -#define BADA_PROC_GET_ECL2M19(bada_proc) ((bada_proc) & 0x7) - -typedef struct { - uint32_t bmda_adr; /* MC ADR */ - uint32_t bmda_gab_bank_sel; /* MC gab bank sel reg */ - ushort_t bmda_bank_setup; /* MC gab bank setup reg */ - ushort_t bmda_filler; - int32_t bmda_badpage[MAX_MGROUPS]; - /* - * One bad page offset per - * mgroup is allowed. No - * bad page if < 0. - */ -} board_mdesc_t; - -/* - * BDA nibble status definitions: - * These are ordered in terms of preserving interesting information - * in POST displays where all configurations are displayed in a - * single value. The highest value for a resource over all - * configurations is shown. - * Of course, this is just for help to engineers/technicians in - * understanding what happened; for the most part, everything - * except "GOOD" is just different flavors of "BAD". - * Note the special macro SET_BDA_NBL_CRUNCH below which requires - * that BDAN_CRUNCH be 0. - */ -#define BDAN_CRUNCH 0x0 /* Unusable by implication */ -#define BDAN_UNDEFINED 0x1 /* Architecturally Missing */ -#define BDAN_MISS 0x2 /* Missing */ -#define BDAN_FAIL 0x3 /* Tested and failed */ -#define BDAN_BLACK 0x4 /* Blacklisted */ -#define BDAN_RED 0x5 /* Redlisted */ -#define BDAN_EXCLUDED 0x6 /* Board is not in this domain */ -#define BDAN_UNCONFIG 0x7 /* Good, but not in config. */ -#define BDAN_GOOD 0x8 /* Like it says. */ -#define BDAN_MASK 0xF - - -/* Macros for accessing BDA nibbles */ -#define BDA_NBL(shrt, nibix) \ - (((shrt) >> ((nibix) << 2)) & BDAN_MASK) -#define SET_BDA_NBL(shrt, nibix, val) \ -{ \ - shrt &= ~(BDAN_MASK << ((nibix) << 2)); \ - shrt |= (val) << ((nibix) << 2); \ -} - -/* - * This exists to keep lint from complaining about statements with - * null efect when we OR in a constant 0 in SET_BDA_NBL. It's a pain, - * but it does save the code optimizer some work. ;-{ - */ -#define SET_BDA_NBL_CRUNCH(shrt, nibix) \ - (shrt &= ~(BDAN_MASK << ((nibix) << 2))) - -/* Definitions for nibbles in the bda_board element: */ -#define BDA_GEN_NBL 0 /* Overall state of the board */ -#define BDA_MC_NBL 1 /* State of the memory. */ -/* - * BDAN_RED if anything red on board, or board is BDAN_EXCLUDED; - * otherwise BDAN_GOOD - */ -#define BDA_ANYRED_NBL 2 -/* - * Macro BDA_PAGESHIFT hides Solaris page size to Starfire POST, as POST - * assumes Solaris basic page size as 8K. - * Note: Only BDA_PAGESHIFT is used, BDA_PAGESIZE is added for readability. - */ -#define BDA_PAGESHIFT 13 -#define BDA_PAGESIZE (1<<BDA_PAGESHIFT) - -typedef struct { /* Memory Total Descriptor */ - int32_t Memt_NumPages; /* 8 KB each */ - int32_t Memt_NumChunks; -} MemoryTotal_t; - -typedef struct { /* Chunk Descriptor */ - uint32_t Memc_StartAddress; /* In 8 KB pages */ - int32_t Memc_Size; /* In 8 KB pages */ -} MemChunk_t; - - -#define P2OBP_MAGIC "XFPOST_2OBP" -#define VAR_ARRAY_LEN 1 - -typedef struct { - char p2o_magic[12]; /* magic cookie = P2OBP_MAGIC */ - int32_t p2o_struct_version; /* equal to P2OBP_VERSION */ - uint32_t p2o_csum; /* sum(uint[]) */ - uint32_t p2o_post_time; /* creation time */ - uint32_t p2o_post_pid; /* pid of sequencer on SSP */ - uint32_t p2o_post_level; /* level at which hpost ran */ - short p2o_abus_mask; /* [3:0] = Valid PA buses */ - /* [5:4] = bus shuffle mode */ - short p2o_dbus_mask; /* Valid physdata buses */ - uint32_t p2o_intercon_freq; /* hz */ - uint32_t p2o_procssor_freq; /* hz */ - int32_t p2o_post_private; - uint32_t p2o_flags; /* See P2OFLAG_XXX */ - uchar_t p2o_procint_intx_freq_ratio; /* 0 if not known */ - uchar_t p2o_fill_byte[3]; - uint_t p2o_filler[6]; /* for expansion */ - board_desc_t p2o_bdinfo[MAX_SYSBDS]; - board_mdesc_t p2o_bdminfo[MAX_SYSBDS]; - board_auxdesc_t p2o_auxinfo[MAX_SYSBDS]; - MemoryTotal_t p2o_memtotal; - /* - * Array of descriptors of existing memory. - * Number of descriptors is given in memtotal.NumChunks. - */ - MemChunk_t p2o_mchunks[VAR_ARRAY_LEN]; -} post2obp_info_t; - -#ifdef _KERNEL -/* - * Following definitions in support of DR. - */ -typedef void *pda_handle_t; - -extern pda_handle_t pda_open(); -extern void pda_close(pda_handle_t ph); -extern int pda_board_present(pda_handle_t ph, int boardnum); -extern void *pda_get_board_info(pda_handle_t ph, int boardnum); -extern uint_t pda_get_mem_size(pda_handle_t ph, int boardnum); -extern void pda_mem_add_span(pda_handle_t ph, - uint64_t basepa, - uint64_t nbytes); -extern void pda_mem_del_span(pda_handle_t ph, - uint64_t basepa, - uint64_t nbytes); -extern void pda_mem_sync(pda_handle_t ph, int board, int unit); -extern void pda_get_busmask(pda_handle_t ph, - short *amask, short *dmask); -extern int pda_is_valid(pda_handle_t ph); - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_PDA_H */ diff --git a/usr/src/uts/sun4u/starfire/unix/Makefile b/usr/src/uts/sun4u/starfire/unix/Makefile deleted file mode 100644 index e474a9fe90..0000000000 --- a/usr/src/uts/sun4u/starfire/unix/Makefile +++ /dev/null @@ -1,189 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of unix (and unix.o). -# -# sun4u starfire implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../../.. - -# -# Define the module and object file sets. -# -UNIX = unix -OBJECTS = $(SPECIAL_OBJS:%=$(OBJS_DIR)/%) \ - $(CORE_OBJS:%=$(OBJS_DIR)/%) \ - $(MACH_NOT_YET_KMODS:%=$(OBJS_DIR)/%) -LINTS = $(SPECIAL_OBJS:%.o=$(LINTS_DIR)/%.ln) \ - $(CORE_OBJS:%.o=$(LINTS_DIR)/%.ln) \ - $(MACH_NOT_YET_KMODS:%.o=$(LINTS_DIR)/%.ln) \ - $(LINTS_DIR)/vers.ln \ - $(LINTS_DIR)/modstubs.ln - -KRTLD_MAPFILE = $(UTSBASE)/sparc/krtld/mapfile -KRTLD_OBJECTS = $(KRTLD_OBJS:%=$(OBJS_DIR)/%) -KRTLD_O = $(OBJS_DIR)/krtld.o - -ROOTMODULE = $(ROOT_STARFIRE_KERN_DIR)/$(UNIX) -UNIX32_LINK = $(ROOT_STARFIRE_KERN_DIR_32)/$(UNIX) -UNIX_BIN = $(OBJS_DIR)/$(UNIX) - -LIBS = $(GENLIB) $(PLATLIB) $(CPULIB) - -GENUNIX = genunix -GENUNIX_DIR = ../../$(GENUNIX) -GENOPTS = -L $(GENUNIX_DIR)/$(OBJS_DIR) -l $(GENUNIX) - -CPU_DIR = . -CPUOPTS = -L $(CPU_DIR)/$(OBJS_DIR) -l $(CPUNAME) - -PLAT_DIR = ../../platmod -PLATOPTS = -L $(PLAT_DIR)/$(OBJS_DIR) -l $(PLATMOD) - -LIBOPTS = $(GENOPTS) $(PLATOPTS) $(CPUOPTS) - -CTFEXTRAOBJS = $(OBJS_DIR)/vers.o - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/starfire/Makefile.starfire - -# -# Define targets -# -ALL_TARGET = $(UNIX_BIN) -LINT_TARGET = $(LINT_LIB) -INSTALL_TARGET = $(UNIX_BIN) $(ROOTMODULE) $(UNIX32_LINK) - -# -# This is UNIX_DIR. Use a short path. -# -UNIX_DIR = . - -# -# Overrides -# -CLEANFILES += $(UNIX_O) $(MODSTUBS_O) $(KRTLD_O) $(KRTLD_OBJECTS) \ - $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ - $(CPU_OBJ) $(CPULIB) \ - $(DTRACESTUBS_O) $(DTRACESTUBS) - -CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) -CLEANLINTFILES += $(LINT_LIB) - -# -# lint pass one enforcement -# Turn on doubleword alignment for 64 bit counter timer registers -# -CFLAGS += $(CCVERBOSE) -dalign - -CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized -CERRWARN += -_gcc=-Wno-char-subscripts -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-unused-function -CERRWARN += -_gcc=-Wno-unused-label -CERRWARN += -_gcc=-Wno-type-limits -CERRWARN += -_gcc=-Wno-clobbered -CERRWARN += -_gcc=-Wno-empty-body -CERRWARN += -_gcc=-Wno-unused-value -CERRWARN += -_gcc=-Wno-switch - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -$(UNIX_BIN): $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(MAPFILE) $(LIBS) \ - $(DTRACESTUBS) - $(LD) -dy -b -o $@ -e _start -M $(MAPFILE) \ - $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) - $(CTFMERGE_UNIQUIFY_AGAINST_GENUNIX) - $(POST_PROCESS) - $(CHK4UBINARY) - -$(UNIX32_LINK): $(ROOT_PSM_KERN_DIR_32) $(UNIX_BIN) - -$(RM) $@; ln -s $(SUBDIR64)/$(UNIX) $@ - -symcheck: $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBS) - $(LD) -dy -b -o $(SYM_MOD) -M $(MAPFILE) \ - $(UNIX_O) $(KRTLD_O) $(MODSTUBS_O) $(LIBOPTS) $(DTRACESTUBS) - -$(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o - $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o - -$(KRTLD_O): $(KRTLD_OBJECTS) - $(LD) -r -o $@ -M$(KRTLD_MAPFILE) $(KRTLD_OBJECTS) - -# -# CPU_OBJ now comprises of 2 object files which come from sun4 common -# and from architecture dependent code. OBJS_DIR is prepended where -# CPU_OBJ is defined to allow for building multiple CPU_OBJ's -# -$(CPULIB): $(CPU_OBJ) - $(BUILD.SO) $(CPU_OBJ) - -# -# The global lint target builds the kernel lint library (llib-lunix.ln) -# which is equivalent to a lint of /unix.o. Then all kernel modules for -# this architecture are linted against the kernel lint library. -# -# Note: lint errors in the kernel lint library will be repeated for -# each module. It is important that the kernel lint library -# be clean to keep the textual output to a reasonable level. -# - -$(LINT_LIB): $(LINT_LIB_DIR) $(LINTS) - @-$(ECHO) "\n$(UNIX): (library construction):" - @$(LINT) -o $(UNIX) $(LINTFLAGS) $(LINTS) - @$(MV) $(@F) $@ - -lintlib: $(LINT_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/starfire/Makefile.targ diff --git a/usr/src/uts/sun4u/sys/Makefile b/usr/src/uts/sun4u/sys/Makefile index 8e73425995..612e09ecb8 100644 --- a/usr/src/uts/sun4u/sys/Makefile +++ b/usr/src/uts/sun4u/sys/Makefile @@ -20,6 +20,7 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2019 Peter Tribble. # # uts/sun4u/sys/Makefile # @@ -90,7 +91,6 @@ HDRS= \ pte.h \ sbd_ioctl.h \ spitregs.h \ - starfire.h \ sysioerr.h \ sysiosbus.h \ todmostek.h \ diff --git a/usr/src/uts/sun4u/sys/machintreg.h b/usr/src/uts/sun4u/sys/machintreg.h index 2ca8a37b46..1610f9148a 100644 --- a/usr/src/uts/sun4u/sys/machintreg.h +++ b/usr/src/uts/sun4u/sys/machintreg.h @@ -23,12 +23,13 @@ * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_MACHINTREG_H #define _SYS_MACHINTREG_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -150,16 +151,6 @@ extern "C" { #define INR_EN_SHIFT 31 #define INR_PID_SHIFT 26 #define INR_PID_MASK (IRSR_PID_MASK << (INR_PID_SHIFT)) -#ifdef _STARFIRE -/* - * Starfire interrupt group number is 7 bits - * Starfire's IGN (inter group #) is not the same as upaid - */ -#define IGN_SIZE 7 /* Interrupt Group Number bit size */ -#define UPAID_TO_IGN(upaid) ((((upaid & 0x3C) >> 1) | (upaid & 0x1)) | \ - (((upaid & 0x2) << 4) | \ - ((upaid & 0x40) ^ 0x40))) -#else /* * IGN_SIZE can be defined in a platform's makefile. If it is not defined, * use a default of 5. @@ -168,7 +159,6 @@ extern "C" { #define IGN_SIZE 5 /* Interrupt Group Number bit size */ #endif #define UPAID_TO_IGN(upaid) (upaid) -#endif /* _STARFIRE */ #define IR_CPU_CLEAR 0x4 /* clear pending register for cpu */ #define IR_MASK_OFFSET 0x4 diff --git a/usr/src/uts/sun4u/sys/machparam.h b/usr/src/uts/sun4u/sys/machparam.h index b0130af21f..a205b21be1 100644 --- a/usr/src/uts/sun4u/sys/machparam.h +++ b/usr/src/uts/sun4u/sys/machparam.h @@ -19,6 +19,9 @@ * CDDL HEADER END */ /* + * Copyright 2019 Peter Tribble. + */ +/* * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -54,28 +57,17 @@ extern "C" { * The maximum possible number of UPA devices in a system. * MAX_UPA maybe defined in a platform's makefile. */ -#ifdef _STARFIRE -/* - * We have a 7 bit id space for UPA devices in Xfire - */ -#define MAX_UPA 128 -#else #ifndef MAX_UPA #define MAX_UPA 32 #endif -#endif /* _STARFIRE */ /* * Maximum cpuid value that we support. NCPU can be defined in a platform's * makefile. */ -#if (defined(_STARFIRE) && !defined(lint)) -#define NCPU 64 -#else #ifndef NCPU #define NCPU 32 #endif -#endif /* _STARFIRE && !lint */ #if (NCPU <= 1) #define NCPU_LOG2 0 @@ -323,11 +315,7 @@ extern "C" { #define PFN_TO_BUSTYPE(pfn) (((pfn) >> 19) & 0x1FF) #define IO_BUSTYPE(pfn) ((PFN_TO_BUSTYPE(pfn) & 0x100) >> 8) -#ifdef _STARFIRE -#define PFN_TO_UPAID(pfn) BUSTYPE_TO_UPAID(PFN_TO_BUSTYPE(pfn)) -#else #define PFN_TO_UPAID(pfn) (((pfn) >> 20) & 0x1F) -#endif /* _STARFIRE */ /* * Defines used for the ptl1_panic parameter, which is passed to the diff --git a/usr/src/uts/sun4u/sys/machthread.h b/usr/src/uts/sun4u/sys/machthread.h index 7b844bea44..d72dc7c91a 100644 --- a/usr/src/uts/sun4u/sys/machthread.h +++ b/usr/src/uts/sun4u/sys/machthread.h @@ -22,12 +22,13 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_MACHTHREAD_H #define _SYS_MACHTHREAD_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/asi.h> #include <sys/sun4asi.h> #include <sys/machasi.h> @@ -51,31 +52,7 @@ extern "C" { sll out, 16, out; \ srl out, 16, out; -#ifdef _STARFIRE -/* - * CPU_INDEX(r, scr) - * Returns cpu id in r. - * On Starfire, this is read from the Port Controller's Port ID - * register in local space. - * - * Need to load the 64 bit address of the PC's PortID reg - * using only one register. Kludge the 41 bits address constant to - * be 32bits by shifting it 12 bits to the right first. - */ -#define LOCAL_PC_PORTID_ADDR_SRL12 0x1FFF4000 -#define PC_PORT_ID 0xD0 - -#define CPU_INDEX(r, scr) \ - rdpr %pstate, scr; \ - andn scr, PSTATE_IE | PSTATE_AM, r; \ - wrpr r, 0, %pstate; \ - set LOCAL_PC_PORTID_ADDR_SRL12, r; \ - sllx r, 12, r; \ - or r, PC_PORT_ID, r; \ - lduwa [r]ASI_IO, r; \ - wrpr scr, 0, %pstate - -#elif defined(_OPL) +#ifdef _OPL /* * For OPL platform, we get CPU_INDEX from ASI_EIDR. */ @@ -84,7 +61,7 @@ extern "C" { and r, 0xfff, r -#else /* _STARFIRE */ +#else /* _OPL */ /* * UPA supports up to 32 devices while Safari supports up to @@ -112,7 +89,7 @@ extern "C" { srlx r, 17, r; \ and r, CPU_MASK, r -#endif /* _STARFIRE */ +#endif /* _OPL */ /* * Given a cpu id extract the appropriate word diff --git a/usr/src/uts/sun4u/sys/pci/pci_cb.h b/usr/src/uts/sun4u/sys/pci/pci_cb.h index 6907fc3b4f..8584e5cf31 100644 --- a/usr/src/uts/sun4u/sys/pci/pci_cb.h +++ b/usr/src/uts/sun4u/sys/pci/pci_cb.h @@ -23,12 +23,13 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_PCI_CB_H #define _SYS_PCI_CB_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -78,10 +79,6 @@ struct cb { uint64_t cb_obsta_pa; /* 1st-attached-side sta reg base PA */ uint64_t *cb_imr_save; - -#ifdef _STARFIRE - caddr_t cb_ittrans_cookie; /* intr tgt translation */ -#endif }; #define CB_INO_TO_MONDO(cb_p, ino) ((cb_p)->cb_ign << PCI_INO_BITS | (ino)) diff --git a/usr/src/uts/sun4u/sys/pci/pci_ib.h b/usr/src/uts/sun4u/sys/pci/pci_ib.h index c85f972a8a..b034043ced 100644 --- a/usr/src/uts/sun4u/sys/pci/pci_ib.h +++ b/usr/src/uts/sun4u/sys/pci/pci_ib.h @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_PCI_IB_H #define _SYS_PCI_IB_H @@ -178,17 +181,6 @@ struct ib_ino_info { #define IB_IS_OBIO_INO(ino) (ino & 0x20) -#ifdef _STARFIRE -/* - * returns a uniq ino per interrupt mapping register - * For on board devices, inos are not shared. But for plugin devices, - * return the 1st ino of the 4 that are sharing the same mapping register. - */ -#define IB_GET_MAPREG_INO(ino) \ - ((volatile uint64_t *)(uintptr_t)((ino & 0x20) ? \ - ino : ((ino >> 2) << 2))) -#endif /* _STARFIRE */ - #define IB_IGN_TO_MONDO(ign, ino) (((ign) << PCI_INO_BITS) | (ino)) #define IB_INO_TO_MONDO(ib_p, ino) IB_IGN_TO_MONDO((ib_p)->ib_ign, ino) diff --git a/usr/src/uts/sun4u/sys/pci/pci_regs.h b/usr/src/uts/sun4u/sys/pci/pci_regs.h index 74aa47a6aa..724cdb3cfb 100644 --- a/usr/src/uts/sun4u/sys/pci/pci_regs.h +++ b/usr/src/uts/sun4u/sys/pci/pci_regs.h @@ -22,12 +22,13 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_PCI_REGS_H #define _SYS_PCI_REGS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -65,8 +66,6 @@ extern "C" { /* * (psycho and schizo) control register bit definitions: */ -#define COMMON_CB_CONTROL_STATUS_IGN 0x0007c00000000000ull -#define COMMON_CB_CONTROL_STATUS_IGN_SHIFT 46 #define COMMON_CB_CONTROL_STATUS_APCKEN 0x0000000000000008ull #define COMMON_CB_CONTROL_STATUS_APERR 0x0000000000000004ull #define COMMON_CB_CONTROL_STATUS_IAP 0x0000000000000002ull diff --git a/usr/src/uts/sun4u/sys/prom_plat.h b/usr/src/uts/sun4u/sys/prom_plat.h index 66ea55b2c1..39616187ca 100644 --- a/usr/src/uts/sun4u/sys/prom_plat.h +++ b/usr/src/uts/sun4u/sys/prom_plat.h @@ -22,12 +22,13 @@ * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_PROM_PLAT_H #define _SYS_PROM_PLAT_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/feature_tests.h> #include <sys/cpuvar.h> @@ -262,16 +263,6 @@ extern int prom_starcat_iosram_write(uint32_t key, uint32_t offset, uint32_t len, caddr_t buf); /* - * Starfire-specific routines - */ -extern int prom_starfire_add_brd(uint_t cpuid); -extern int prom_starfire_rm_brd(uint_t brdnum); -extern void prom_starfire_add_cpu(uint_t cpuid); -extern void prom_starfire_rm_cpu(uint_t cpuid); -extern int prom_starfire_move_cpu0(uint_t cpuid); -extern void prom_starfire_init_console(uint_t cpuid); - -/* * OPL-specific routines */ extern void prom_opl_get_tod(time_t *time, int64_t *stickval); diff --git a/usr/src/uts/sun4u/sys/sbd_ioctl.h b/usr/src/uts/sun4u/sys/sbd_ioctl.h index 16efc10bd7..e8c8ca1e2b 100644 --- a/usr/src/uts/sun4u/sys/sbd_ioctl.h +++ b/usr/src/uts/sun4u/sys/sbd_ioctl.h @@ -22,6 +22,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SBD_IOCTL_H #define _SBD_IOCTL_H @@ -505,34 +508,6 @@ typedef struct { #define ESTC_NWSWITCH 1037 /* Cannot unconfigure I/O board: network switch failed */ -/* Starfire error codes */ - -#define ESTF_NONE 2000 /* No error */ -#define ESTF_GETPROP 2001 /* Cannot read property value */ -#define ESTF_GETPROPLEN 2002 /* Cannot determine property length */ -#define ESTF_BNUM 2003 /* Invalid board number */ -#define ESTF_CONFIGBUSY 2004 - /* Cannot proceed; Board is configured or busy */ -#define ESTF_NOCPUID 2005 /* No CPU specified for connect */ -#define ESTF_PROBE 2006 /* Firmware probe failed */ -#define ESTF_DEPROBE 2007 /* Firmware deprobe failed */ -#define ESTF_MOVESIGB 2008 /* Firmware move-cpu0 failed */ -#define ESTF_JUGGLE 2009 /* Cannot move SIGB assignment */ -#define ESTF_HASSIGB 2010 - /* Cannot disconnect CPU; SIGB is currently assigned */ -#define ESTF_SUPPORT 2011 /* Operation not supported */ -#define ESTF_DRVFAIL 2012 /* Device driver failure */ -#define ESTF_SETCPUVAL 2013 - /* Must specify a CPU on the given board */ -#define ESTF_NODEV 2014 /* No such device */ -#define ESTF_INTERBOARD 2015 - /* Memory configured with inter-board interleaving */ -#define ESTF_UNKPTCMD 2016 /* Unrecognized platform command */ -#define ESTF_NOTID 2017 /* drmach parameter is not a valid ID */ -#define ESTF_INAPPROP 2018 - /* drmach parameter is inappropriate for operation */ -#define ESTF_INTERNAL 2019 /* Unexpected internal condition */ - /* Daktari error codes */ #define EDAK_NONE 3000 /* no error */ diff --git a/usr/src/uts/sun4u/sys/spitregs.h b/usr/src/uts/sun4u/sys/spitregs.h index 492990c720..1c246f1446 100644 --- a/usr/src/uts/sun4u/sys/spitregs.h +++ b/usr/src/uts/sun4u/sys/spitregs.h @@ -23,12 +23,13 @@ * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_SPITREGS_H #define _SYS_SPITREGS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -37,24 +38,11 @@ extern "C" { * This file is cpu dependent. */ -#ifdef _STARFIRE -/* - * Starfire's cpu upaids are not the same - * as cpuids. - * XXX - our obp took the liberty of - * converting cpu upaids into cpuids when - * presenting it as upa-portid property. - */ -#define CPUID_TO_UPAID(upaid) (((upaid & 0x3C) << 1) | \ - ((upaid & 0x40) >> 4) | \ - (upaid &0x3)) -#else /* * The mid is the same as the cpu id. * We might want to change this later */ #define CPUID_TO_UPAID(cpuid) (cpuid) -#endif /* _STARFIRE */ /* * LSU Control Register diff --git a/usr/src/uts/sun4u/sys/starfire.h b/usr/src/uts/sun4u/sys/starfire.h deleted file mode 100644 index 038f0b3c0e..0000000000 --- a/usr/src/uts/sun4u/sys/starfire.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright (c) 1996-2000 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _STARFIRE_H -#define _STARFIRE_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* I/O space definitions */ -#define STARFIRE_IO_BASE 0x10000000000ULL - -/* UPA Port Space (UPS) definitions */ -#define STARFIRE_UPS_MID_SHIFT 33 /* MID is 7 bits */ -#define STARFIRE_UPS_BRD_SHIFT 36 -#define STARFIRE_UPS_BUS_SHIFT 6 - -/* Starfire Interconnect Space (IS) definitions */ -#define STARFIRE_IS_MC_BASE 0x10e80000000ULL /* MC Register Space */ - - -/* Port Specific Interconnect Space (PSI) */ -#define STARFIRE_PSI_BASE \ - 0x100f8000000ULL /* put mid in [39:33] */ -#define STARFIRE_PSI_PCREG_OFF \ - 0x4000000ULL /* PSI offset for PC regs */ -#define STARFIRE_BRD_TO_PSI(board) \ - (STARFIRE_PSI_BASE | \ - (((uint64_t)board) << STARFIRE_UPS_BRD_SHIFT)) - - -/* Starfire BootBus Space (BS) definitions */ -#define STARFIRE_PSI_BS_BASE \ - STARFIRE_PSI_BASE /* BS at start of PSI Space */ - -#define STARFIRE_UPAID2PSI_BS(upaid) \ - (STARFIRE_PSI_BS_BASE | \ - ((u_longlong_t)STARFIRE_UPAID2HWMID(upaid) << \ - STARFIRE_UPS_MID_SHIFT)) - -#define STARFIRE_DEV2UPAID(b, p, i) \ - ((((i) & 0x1) << 6) | \ - (((b) & 0xf) << 2) | \ - ((p) & 0x3)) - -/* Starfire Port Controller Register offsets */ -#define STARFIRE_PC_CONF 0x000000UL /* Configuration Reg */ -#define STARFIRE_PC_COMP_ID 0x000010UL /* Component ID Reg */ -#define STARFIRE_PC_BUS_CONF 0x000020UL /* Bus Configuration Reg */ -#define STARFIRE_PC_TO_HOLD_CONF 0x000030UL /* Timeout/Hold Config Reg */ -#define STARFIRE_PC_CIC_WRITE_DATA 0x000040UL /* CIC Write Data Reg */ -#define STARFIRE_PC_FORCE_PARITY_ERR 0x000050UL /* Force Parity Err Reg */ -#define STARFIRE_PC_ERR_0_MASK 0x000060UL /* Err 0 Mask Reg */ -#define STARFIRE_PC_ERR_1_MASK 0x000070UL /* Err 1 Mask Reg */ -#define STARFIRE_PC_ERR_0 0x000080UL /* Err 0 Reg */ -#define STARFIRE_PC_ERR_1 0x000090UL /* Err 1 Reg */ -#define STARFIRE_PC_ERR_DATA_SRC 0x0000a0UL /* Err Data Src Reg */ -#define STARFIRE_PC_ERR_DATA_LOW 0x0000b0UL /* Err Data Lower Reg */ -#define STARFIRE_PC_ERR_DATA_HI 0x0000c0UL /* Err Data Upper Reg */ -#define STARFIRE_PC_PORT_ID 0x0000d0UL -#define STARFIRE_PC_PERF_COUNT_0 0x0000e0UL -#define STARFIRE_PC_PERF_COUNT_1 0x0000f0UL -#define STARFIRE_PC_PERF_COUNT_CNTRL 0x000100UL -#define STARFIRE_PC_BLOCK 0x0001c0UL /* 512 Byte scr area */ -#define STARFIRE_PC_INT_MAP 0x000200UL /* 32 regs 00.0200-00.03f0 */ -#define STARFIRE_PC_MADR 0x000400UL /* 16 regs 00.0400-00.04f0 */ - -/* Starfire PC definitions/macros */ -#define STARFIRE_PC_MADR_BOARD_SHIFT 4 -#define STARFIRE_PC_MADR_ADDR(bb, rb, p) \ - (STARFIRE_BRD_TO_PSI(bb) | \ - ((uint64_t)(p) << STARFIRE_UPS_MID_SHIFT) | \ - ((uint64_t)(rb) << STARFIRE_PC_MADR_BOARD_SHIFT) | \ - STARFIRE_PSI_PCREG_OFF | \ - STARFIRE_PC_MADR) - -/* Starfire BB (BootBus) definitions/macros */ -#define STARFIRE_BB_SYSRESET_CNTRL 0x800000ULL -#define STARFIRE_BB_PAUSE_FLUSH 0x800016ULL - -#define STARFIRE_BB_PC_PAUSE(i) ((uchar_t)(1 << (i))) -#define STARFIRE_BB_PC_FLUSH(i) ((uchar_t)(1 << ((i)+2))) -#define STARFIRE_BB_PC_IDLE(i) ((uchar_t)(1 << ((i)+4))) - -#define STARFIRE_BB_SYSRESET(i) ((uchar_t)(1 << (i))) - -#define STARFIRE_BB_PC_ADDR(bb, p, io) \ - (STARFIRE_UPAID2PSI_BS(STARFIRE_DEV2UPAID((bb), (p), (io))) | \ - STARFIRE_BB_PAUSE_FLUSH) -#define STARFIRE_BB_RESET_ADDR(bb, p) \ - (STARFIRE_UPAID2PSI_BS(STARFIRE_DEV2UPAID((bb), (p), 0)) | \ - STARFIRE_BB_SYSRESET_CNTRL) - -/* Starfire Memory Controller Register offsets */ -#define STARFIRE_MC_ASR 0x000400U /* Addr Select Reg */ -#define STARFIRE_MC_DIMMTYPE 0x00c800U /* DIMM Type Code Reg */ -#define STARFIRE_MC_IDLE 0x00cc00U /* Idle MC Reg */ - -/* Starfire MC definitions/macros */ -#define STARFIRE_MC_MEM_PRESENT_MASK 0x80000000U -#define STARFIRE_MC_MEM_BASEADDR_MASK 0x7fff0000U -#define STARFIRE_MC_IDLE_MASK 0x00008000U -#define STARFIRE_MC_MASK_MASK 0x00007f00U -#define STARFIRE_MC_DIMMSIZE_MASK 0x0000001fU -#define STARFIRE_MC_INTERLEAVE_MASK 0x00000001U -#define STARFIRE_MC_MASK_SHIFT 18 -#define STARFIRE_MC_BASE_SHIFT 10 -#define STARFIRE_MC_ADDR_HIBITS 0x1fe00000000ULL -#define STARFIRE_MC_ASR_ADDR(reg) ((reg) | (uint64_t)STARFIRE_MC_ASR) -#define STARFIRE_MC_IDLE_ADDR(reg) ((reg) | (uint64_t)STARFIRE_MC_IDLE) -#define STARFIRE_MC_DIMMTYPE_ADDR(reg) ((reg) | (uint64_t)STARFIRE_MC_DIMMTYPE) -#define STARFIRE_MC_ASR_ADDR_BOARD(b) \ - (((uint64_t)(b) << STARFIRE_UPS_BRD_SHIFT) | \ - STARFIRE_IS_MC_BASE | \ - (uint64_t)STARFIRE_MC_ASR) - -/* - * Memory boards on Starfire are aligned on 8GB - * boundaries, i.e. the physical address space - * is not physically contiguous. - */ -#define STARFIRE_MC_MEMBOARD_SHIFT 33 -#define STARFIRE_MC_MEMBOARD_ALIGNMENT \ - (UINT64_C(1) << STARFIRE_MC_MEMBOARD_SHIFT) - -/* - * Starfire has a special regspec for the "reg" property of the - * mem-unit node since this node is homegrown. - */ -struct sf_memunit_regspec { - uint_t regspec_addr_hi; - uint_t regspec_addr_lo; - uint_t regspec_size_hi; - uint_t regspec_size_lo; -}; - -/* - * Conversion macros - */ - -/* - * Starfire hardware version of the upaid (commonly known as - * HWMID) is different from the software version (also known as upaid). - * HW version BBBBIPp == SW version IBBBBPp - */ -#define STARFIRE_UPAID2HWMID(upaid) (((upaid & 0x3C) << 1) | \ - ((upaid & 0x40) >> 4) | (upaid & 0x3)) - - -/* Xfire UPA ID to UPA Port Specific Space */ -#define STARFIRE_UPAID2UPS(upaid) \ - (((u_longlong_t)STARFIRE_UPAID2HWMID(upaid) << \ - STARFIRE_UPS_MID_SHIFT) | STARFIRE_IO_BASE) - -/* - * Macro to convert our 7 bits HW MID to 7 bits SW MID - * That is "BBBBIPp" to "IBBBBPp". - */ -#define STARFIRE_HWMID2SWMID(mid) ((mid & 0x3) | ((mid & 0x78) >> 1) | \ - ((mid & 0x4) << 4)) - -/* - * Macro to convert our 7 bits UPAid to Sun's 5 bit HW Interrupt - * group number required in some hardware registers (sysios). - * That is "IBBBBPp" to "BBBBp", where "BBBB" is the board number, - * "IP" is the PC id and "p" is the port number. - */ -#define STARFIRE_UPAID2HWIGN(upaid) \ - (((upaid & 0x3C) >> 1) | (upaid & 0x1)) - -/* - * Macro to convert our UPAid to a 7 bit Starfire version of the - * interrupt group number. This so-called IGN is part of - * the interrupt vector number read by the CPU serving this interrupt. - * Thanks to the warp minds of our hardware guys, it is in this - * convoluted weird format. Note that the interrupt vector number is - * then used to index into the interrupt dispatch table to get its - * interrupt handler. - * Convert "IBBBBPp" to "XPBBBBp" where "BBBB" is the 4bit board #, - * "IP" is the 2 bit PC id, "p" is the port # and "X" is ~I. - */ -#define STARFIRE_UPAID2IGN(upaid) (STARFIRE_UPAID2HWIGN(upaid) | \ - ((upaid & 0x2) << 4) | \ - ((upaid & 0x40) ^ 0x40)) - -/* - * Starfire platform specific routines currently only defined - * in starfire.c and referenced by DR. - */ -extern int plat_max_boards(); -extern int plat_max_cpu_units_per_board(); -extern int plat_max_mem_units_per_board(); -extern int plat_max_io_units_per_board(); - -/* - * Starfire platform specific interrupt translation routines - */ -extern void pc_ittrans_init(int, caddr_t *); -extern void pc_ittrans_uninit(caddr_t); -extern int pc_translate_tgtid(caddr_t, int, volatile uint64_t *); -extern void pc_ittrans_cleanup(caddr_t, volatile uint64_t *); - -/* - * Maximum number of system boards supported in a Starfire. - */ -#define STARFIRE_MAX_BOARDS 16 - -/* - * We reserve some "fake" DMV values for Starfire IDN. These are treated - * as hardware interrupt numbers, but they don't correspond to an actual UPA - * port; they can thus be allocated as "well-known" numbers for IDN purposes. - */ -#define STARFIRE_DMV_EXTRA 4 -#define STARFIRE_DMV_HWINT (MAX_UPA+STARFIRE_DMV_EXTRA) -#define STARFIRE_DMV_IDN_BASE (MAX_UPA) - - -#ifdef __cplusplus -} -#endif - -#endif /* _STARFIRE_H */ diff --git a/usr/src/uts/sun4u/sys/sysiosbus.h b/usr/src/uts/sun4u/sys/sysiosbus.h index d72c1c0aa3..05029e9fb8 100644 --- a/usr/src/uts/sun4u/sys/sysiosbus.h +++ b/usr/src/uts/sun4u/sys/sysiosbus.h @@ -23,12 +23,13 @@ * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Peter Tribble. + */ #ifndef _SYS_SYSIOSBUS_H #define _SYS_SYSIOSBUS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifndef _ASM #include <sys/avintr.h> #include <sys/vmem.h> @@ -319,9 +320,6 @@ struct sbus_soft_state { pfn_t sbus_io_hi_pfn; struct iophyslist *sbus_io_ranges; int intr_mapping_ign; /* placeholder for the IGN */ -#ifdef _STARFIRE - caddr_t ittrans_cookie; /* starfire intr target translation */ -#endif /* _STARFIRE */ #ifdef DEBUG kmutex_t iomemlock; /* Memory usage lock (debug only) */ struct io_mem_list *iomem; /* Memory usage list (debug only) */ diff --git a/usr/src/uts/sun4u/todstarfire/Makefile b/usr/src/uts/sun4u/todstarfire/Makefile deleted file mode 100644 index cbaee6f875..0000000000 --- a/usr/src/uts/sun4u/todstarfire/Makefile +++ /dev/null @@ -1,87 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/sun4u/todmostek/Makefile -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the todstarfire -# kernel module. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = todstarfire -OBJECTS = $(TODSTARFIRE_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(TODSTARFIRE_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_PSM_TOD_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/sun4u/Makefile.sun4u - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/sun4u/Makefile.targ diff --git a/usr/src/uts/sun4v/os/mach_mp_startup.c b/usr/src/uts/sun4v/os/mach_mp_startup.c index 06a6f59279..a0c3928a2f 100644 --- a/usr/src/uts/sun4v/os/mach_mp_startup.c +++ b/usr/src/uts/sun4v/os/mach_mp_startup.c @@ -23,6 +23,10 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright 2019 Peter Tribble. + */ + #include <sys/machsystm.h> #include <sys/cpu_module.h> #include <sys/dtrace.h> @@ -70,11 +74,6 @@ init_cpu_info(struct cpu *cp) (void) strcpy(pi->pi_fputypes, "sparcv9"); /* - * StarFire requires the signature block stuff setup here - */ - CPU_SGN_MAPIN(cpuid); - - /* * cpu0 is always initialized at boot time, but it can be initialized * again if it is dynamically removed and then re-added. We check if * we are booting by verifying cpu_list. During boot, cpu0 is already |