1*1d4b38e0Srsmaeda /* 2*1d4b38e0Srsmaeda * CDDL HEADER START 3*1d4b38e0Srsmaeda * 4*1d4b38e0Srsmaeda * The contents of this file are subject to the terms of the 5*1d4b38e0Srsmaeda * Common Development and Distribution License (the "License"). 6*1d4b38e0Srsmaeda * You may not use this file except in compliance with the License. 7*1d4b38e0Srsmaeda * 8*1d4b38e0Srsmaeda * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1d4b38e0Srsmaeda * or http://www.opensolaris.org/os/licensing. 10*1d4b38e0Srsmaeda * See the License for the specific language governing permissions 11*1d4b38e0Srsmaeda * and limitations under the License. 12*1d4b38e0Srsmaeda * 13*1d4b38e0Srsmaeda * When distributing Covered Code, include this CDDL HEADER in each 14*1d4b38e0Srsmaeda * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1d4b38e0Srsmaeda * If applicable, add the following below this CDDL HEADER, with the 16*1d4b38e0Srsmaeda * fields enclosed by brackets "[]" replaced with your own identifying 17*1d4b38e0Srsmaeda * information: Portions Copyright [yyyy] [name of copyright owner] 18*1d4b38e0Srsmaeda * 19*1d4b38e0Srsmaeda * CDDL HEADER END 20*1d4b38e0Srsmaeda */ 21*1d4b38e0Srsmaeda 22*1d4b38e0Srsmaeda /* 23*1d4b38e0Srsmaeda * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*1d4b38e0Srsmaeda * Use is subject to license terms. 25*1d4b38e0Srsmaeda */ 26*1d4b38e0Srsmaeda 27*1d4b38e0Srsmaeda #pragma ident "%Z%%M% %I% %E% SMI" 28*1d4b38e0Srsmaeda 29*1d4b38e0Srsmaeda /* 30*1d4b38e0Srsmaeda * sun4v DR daemon 31*1d4b38e0Srsmaeda */ 32*1d4b38e0Srsmaeda 33*1d4b38e0Srsmaeda #include <stdio.h> 34*1d4b38e0Srsmaeda #include <stdlib.h> 35*1d4b38e0Srsmaeda #include <unistd.h> 36*1d4b38e0Srsmaeda #include <string.h> 37*1d4b38e0Srsmaeda #include <strings.h> 38*1d4b38e0Srsmaeda #include <fcntl.h> 39*1d4b38e0Srsmaeda #include <errno.h> 40*1d4b38e0Srsmaeda #include <libgen.h> 41*1d4b38e0Srsmaeda #include <syslog.h> 42*1d4b38e0Srsmaeda #include <door.h> 43*1d4b38e0Srsmaeda #include <assert.h> 44*1d4b38e0Srsmaeda #include <sys/types.h> 45*1d4b38e0Srsmaeda #include <sys/stat.h> 46*1d4b38e0Srsmaeda 47*1d4b38e0Srsmaeda #include <sys/drctl_impl.h> 48*1d4b38e0Srsmaeda #include <sys/drctl.h> 49*1d4b38e0Srsmaeda #include "drd.h" 50*1d4b38e0Srsmaeda 51*1d4b38e0Srsmaeda boolean_t drd_debug = B_FALSE; 52*1d4b38e0Srsmaeda boolean_t drd_daemonized = B_FALSE; 53*1d4b38e0Srsmaeda 54*1d4b38e0Srsmaeda #define DRD_DOOR_FILE "/tmp/drd_door" 55*1d4b38e0Srsmaeda #define DRD_DOOR_RETURN_ERR() (void) door_return(NULL, 0, NULL, 0) 56*1d4b38e0Srsmaeda 57*1d4b38e0Srsmaeda static char *cmdname; 58*1d4b38e0Srsmaeda static int drctl_fd; 59*1d4b38e0Srsmaeda static drctl_rsrc_t *drd_result = NULL; 60*1d4b38e0Srsmaeda 61*1d4b38e0Srsmaeda /* 62*1d4b38e0Srsmaeda * Currently, the only supported backend is for the Reconfiguration 63*1d4b38e0Srsmaeda * Coordination Manager (RCM). When there are other backends, this 64*1d4b38e0Srsmaeda * variable should be set dynamically. 65*1d4b38e0Srsmaeda */ 66*1d4b38e0Srsmaeda static drd_backend_t *drd_backend = &drd_rcm_backend; 67*1d4b38e0Srsmaeda 68*1d4b38e0Srsmaeda static void drd_daemonize(void); 69*1d4b38e0Srsmaeda static int drd_init_drctl_dev(boolean_t standalone); 70*1d4b38e0Srsmaeda static int drd_init_door_server(boolean_t standalone); 71*1d4b38e0Srsmaeda static void drd_door_server(void *, char *, size_t, door_desc_t *, uint_t); 72*1d4b38e0Srsmaeda 73*1d4b38e0Srsmaeda int 74*1d4b38e0Srsmaeda main(int argc, char **argv) 75*1d4b38e0Srsmaeda { 76*1d4b38e0Srsmaeda int opt; 77*1d4b38e0Srsmaeda boolean_t standalone = 0; 78*1d4b38e0Srsmaeda 79*1d4b38e0Srsmaeda cmdname = basename(argv[0]); 80*1d4b38e0Srsmaeda 81*1d4b38e0Srsmaeda /* 82*1d4b38e0Srsmaeda * Process command line arguments 83*1d4b38e0Srsmaeda */ 84*1d4b38e0Srsmaeda opterr = 0; /* disable getopt error messages */ 85*1d4b38e0Srsmaeda while ((opt = getopt(argc, argv, "ds")) != EOF) { 86*1d4b38e0Srsmaeda 87*1d4b38e0Srsmaeda switch (opt) { 88*1d4b38e0Srsmaeda case 'd': 89*1d4b38e0Srsmaeda drd_debug = B_TRUE; 90*1d4b38e0Srsmaeda break; 91*1d4b38e0Srsmaeda case 's': 92*1d4b38e0Srsmaeda standalone = B_TRUE; 93*1d4b38e0Srsmaeda break; 94*1d4b38e0Srsmaeda default: 95*1d4b38e0Srsmaeda drd_err("unkown option: -%c", optopt); 96*1d4b38e0Srsmaeda exit(1); 97*1d4b38e0Srsmaeda } 98*1d4b38e0Srsmaeda } 99*1d4b38e0Srsmaeda 100*1d4b38e0Srsmaeda drd_dbg("initializing %s...", cmdname); 101*1d4b38e0Srsmaeda 102*1d4b38e0Srsmaeda /* must be root */ 103*1d4b38e0Srsmaeda if (geteuid() != 0) { 104*1d4b38e0Srsmaeda drd_err("permission denied: must run as root"); 105*1d4b38e0Srsmaeda exit(1); 106*1d4b38e0Srsmaeda } 107*1d4b38e0Srsmaeda 108*1d4b38e0Srsmaeda /* open the drctl device */ 109*1d4b38e0Srsmaeda if (drd_init_drctl_dev(standalone) != 0) { 110*1d4b38e0Srsmaeda drd_err("unable to initialize drctl device"); 111*1d4b38e0Srsmaeda exit(1); 112*1d4b38e0Srsmaeda } 113*1d4b38e0Srsmaeda 114*1d4b38e0Srsmaeda /* daemonize */ 115*1d4b38e0Srsmaeda if (!standalone) { 116*1d4b38e0Srsmaeda drd_daemonize(); 117*1d4b38e0Srsmaeda } 118*1d4b38e0Srsmaeda 119*1d4b38e0Srsmaeda /* initialize door server */ 120*1d4b38e0Srsmaeda if (drd_init_door_server(standalone) != 0) { 121*1d4b38e0Srsmaeda drd_err("unable to initialize door server"); 122*1d4b38e0Srsmaeda exit(1); 123*1d4b38e0Srsmaeda } 124*1d4b38e0Srsmaeda 125*1d4b38e0Srsmaeda /* initialize the backend */ 126*1d4b38e0Srsmaeda if ((*drd_backend->init)() != 0) { 127*1d4b38e0Srsmaeda drd_err("unable to initialize backend processor"); 128*1d4b38e0Srsmaeda exit(1); 129*1d4b38e0Srsmaeda } 130*1d4b38e0Srsmaeda 131*1d4b38e0Srsmaeda /* loop forever */ 132*1d4b38e0Srsmaeda for (;;) { 133*1d4b38e0Srsmaeda pause(); 134*1d4b38e0Srsmaeda } 135*1d4b38e0Srsmaeda 136*1d4b38e0Srsmaeda /*NOTREACHED*/ 137*1d4b38e0Srsmaeda return (0); 138*1d4b38e0Srsmaeda } 139*1d4b38e0Srsmaeda 140*1d4b38e0Srsmaeda static void 141*1d4b38e0Srsmaeda drd_daemonize(void) 142*1d4b38e0Srsmaeda { 143*1d4b38e0Srsmaeda pid_t pid; 144*1d4b38e0Srsmaeda 145*1d4b38e0Srsmaeda if ((pid = fork()) == -1) { 146*1d4b38e0Srsmaeda drd_err("failed to fork: %s", strerror(errno)); 147*1d4b38e0Srsmaeda exit(1); 148*1d4b38e0Srsmaeda } 149*1d4b38e0Srsmaeda 150*1d4b38e0Srsmaeda if (pid != 0) { 151*1d4b38e0Srsmaeda /* parent */ 152*1d4b38e0Srsmaeda exit(0); 153*1d4b38e0Srsmaeda } 154*1d4b38e0Srsmaeda 155*1d4b38e0Srsmaeda /* 156*1d4b38e0Srsmaeda * Initialize child process 157*1d4b38e0Srsmaeda */ 158*1d4b38e0Srsmaeda (void) setsid(); 159*1d4b38e0Srsmaeda (void) chdir("/"); 160*1d4b38e0Srsmaeda (void) umask(0); 161*1d4b38e0Srsmaeda 162*1d4b38e0Srsmaeda /* 163*1d4b38e0Srsmaeda * Initialize file descriptors 164*1d4b38e0Srsmaeda */ 165*1d4b38e0Srsmaeda assert(drctl_fd == (STDERR_FILENO + 1)); 166*1d4b38e0Srsmaeda 167*1d4b38e0Srsmaeda (void) close(STDIN_FILENO); 168*1d4b38e0Srsmaeda (void) open("/dev/null", O_RDWR); 169*1d4b38e0Srsmaeda (void) dup2(STDIN_FILENO, STDOUT_FILENO); 170*1d4b38e0Srsmaeda (void) dup2(STDIN_FILENO, STDERR_FILENO); 171*1d4b38e0Srsmaeda 172*1d4b38e0Srsmaeda closefrom(drctl_fd + 1); 173*1d4b38e0Srsmaeda 174*1d4b38e0Srsmaeda /* initialize logging */ 175*1d4b38e0Srsmaeda openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON); 176*1d4b38e0Srsmaeda 177*1d4b38e0Srsmaeda drd_daemonized = B_TRUE; 178*1d4b38e0Srsmaeda } 179*1d4b38e0Srsmaeda 180*1d4b38e0Srsmaeda static int 181*1d4b38e0Srsmaeda drd_init_drctl_dev(boolean_t standalone) 182*1d4b38e0Srsmaeda { 183*1d4b38e0Srsmaeda void (*drd_output)(char *, ...); 184*1d4b38e0Srsmaeda 185*1d4b38e0Srsmaeda drd_output = (standalone) ? drd_info : drd_err; 186*1d4b38e0Srsmaeda 187*1d4b38e0Srsmaeda /* open the drctl device */ 188*1d4b38e0Srsmaeda if ((drctl_fd = open(DRCTL_DEV, O_RDWR)) == -1) { 189*1d4b38e0Srsmaeda drd_output("open %s failed: %s", DRCTL_DEV, strerror(errno)); 190*1d4b38e0Srsmaeda return ((standalone) ? 0 : -1); 191*1d4b38e0Srsmaeda } 192*1d4b38e0Srsmaeda 193*1d4b38e0Srsmaeda return (0); 194*1d4b38e0Srsmaeda } 195*1d4b38e0Srsmaeda 196*1d4b38e0Srsmaeda static int 197*1d4b38e0Srsmaeda drd_init_door_server(boolean_t standalone) 198*1d4b38e0Srsmaeda { 199*1d4b38e0Srsmaeda int door_fd; 200*1d4b38e0Srsmaeda int dbg_fd; 201*1d4b38e0Srsmaeda drctl_setup_t setup; 202*1d4b38e0Srsmaeda 203*1d4b38e0Srsmaeda assert((drctl_fd != -1) || standalone); 204*1d4b38e0Srsmaeda 205*1d4b38e0Srsmaeda /* create the door */ 206*1d4b38e0Srsmaeda if ((door_fd = door_create(drd_door_server, NULL, 0)) == -1) { 207*1d4b38e0Srsmaeda drd_err("door_create failed: %s", strerror(errno)); 208*1d4b38e0Srsmaeda return (-1); 209*1d4b38e0Srsmaeda } 210*1d4b38e0Srsmaeda 211*1d4b38e0Srsmaeda if (drctl_fd != -1) { 212*1d4b38e0Srsmaeda 213*1d4b38e0Srsmaeda setup.did = door_fd; 214*1d4b38e0Srsmaeda 215*1d4b38e0Srsmaeda /* send the door descriptor to drctl */ 216*1d4b38e0Srsmaeda if (ioctl(drctl_fd, DRCTL_IOCTL_CONNECT_SERVER, &setup) == -1) { 217*1d4b38e0Srsmaeda drd_err("drctl ioctl failed: %s", strerror(errno)); 218*1d4b38e0Srsmaeda (void) door_revoke(door_fd); 219*1d4b38e0Srsmaeda return (-1); 220*1d4b38e0Srsmaeda } 221*1d4b38e0Srsmaeda 222*1d4b38e0Srsmaeda drd_dbg("connection to drctl established"); 223*1d4b38e0Srsmaeda 224*1d4b38e0Srsmaeda /* setup is complete in daemon mode */ 225*1d4b38e0Srsmaeda if (!standalone) { 226*1d4b38e0Srsmaeda return (0); 227*1d4b38e0Srsmaeda } 228*1d4b38e0Srsmaeda } 229*1d4b38e0Srsmaeda 230*1d4b38e0Srsmaeda /* 231*1d4b38e0Srsmaeda * At this point, the daemon is running in standalone 232*1d4b38e0Srsmaeda * mode for testing purposes. This allows the daemon 233*1d4b38e0Srsmaeda * to be controlled directly through a door exported 234*1d4b38e0Srsmaeda * to the filesystem. No drctl device is required in 235*1d4b38e0Srsmaeda * this mode. 236*1d4b38e0Srsmaeda */ 237*1d4b38e0Srsmaeda 238*1d4b38e0Srsmaeda /* create the door file */ 239*1d4b38e0Srsmaeda unlink(DRD_DOOR_FILE); 240*1d4b38e0Srsmaeda if ((dbg_fd = creat(DRD_DOOR_FILE, 0644)) == -1) { 241*1d4b38e0Srsmaeda drd_err("failed to create door file '%s': %s", 242*1d4b38e0Srsmaeda DRD_DOOR_FILE, strerror(errno)); 243*1d4b38e0Srsmaeda (void) door_revoke(door_fd); 244*1d4b38e0Srsmaeda return (-1); 245*1d4b38e0Srsmaeda } 246*1d4b38e0Srsmaeda close(dbg_fd); 247*1d4b38e0Srsmaeda 248*1d4b38e0Srsmaeda /* attach the door file to the door descriptor */ 249*1d4b38e0Srsmaeda if (fattach(door_fd, DRD_DOOR_FILE) == -1) { 250*1d4b38e0Srsmaeda drd_err("failed to fattach door file '%s': %s", 251*1d4b38e0Srsmaeda DRD_DOOR_FILE, strerror(errno)); 252*1d4b38e0Srsmaeda unlink(DRD_DOOR_FILE); 253*1d4b38e0Srsmaeda (void) door_revoke(door_fd); 254*1d4b38e0Srsmaeda return (-1); 255*1d4b38e0Srsmaeda } 256*1d4b38e0Srsmaeda 257*1d4b38e0Srsmaeda drd_dbg("door server attached to '%s'", DRD_DOOR_FILE); 258*1d4b38e0Srsmaeda 259*1d4b38e0Srsmaeda return (0); 260*1d4b38e0Srsmaeda } 261*1d4b38e0Srsmaeda 262*1d4b38e0Srsmaeda static size_t 263*1d4b38e0Srsmaeda drd_pack_response(drctl_rsrc_t *rsrcs, int nrsrc) 264*1d4b38e0Srsmaeda { 265*1d4b38e0Srsmaeda drctl_rsrc_t *orsrcsp; 266*1d4b38e0Srsmaeda void *resizep; 267*1d4b38e0Srsmaeda size_t osize; 268*1d4b38e0Srsmaeda char *str; 269*1d4b38e0Srsmaeda size_t offset; 270*1d4b38e0Srsmaeda char *off; 271*1d4b38e0Srsmaeda int idx; 272*1d4b38e0Srsmaeda size_t len; 273*1d4b38e0Srsmaeda 274*1d4b38e0Srsmaeda drd_dbg("drd_pack_response..."); 275*1d4b38e0Srsmaeda 276*1d4b38e0Srsmaeda /* 277*1d4b38e0Srsmaeda * Deallocate the global response buffer if it is 278*1d4b38e0Srsmaeda * in use. This assumes that there will only ever 279*1d4b38e0Srsmaeda * be one pending operation in the daemon. This is 280*1d4b38e0Srsmaeda * enforced by the kernel. 281*1d4b38e0Srsmaeda */ 282*1d4b38e0Srsmaeda s_free(drd_result); 283*1d4b38e0Srsmaeda 284*1d4b38e0Srsmaeda orsrcsp = calloc(sizeof (*orsrcsp), nrsrc); 285*1d4b38e0Srsmaeda osize = sizeof (*orsrcsp) * nrsrc; 286*1d4b38e0Srsmaeda bcopy(rsrcs, orsrcsp, osize); 287*1d4b38e0Srsmaeda 288*1d4b38e0Srsmaeda offset = osize; 289*1d4b38e0Srsmaeda 290*1d4b38e0Srsmaeda /* 291*1d4b38e0Srsmaeda * Loop through all the resources and concatenate 292*1d4b38e0Srsmaeda * all the error strings to the end of the resource 293*1d4b38e0Srsmaeda * array. Also, update the offset field of each 294*1d4b38e0Srsmaeda * resource. 295*1d4b38e0Srsmaeda */ 296*1d4b38e0Srsmaeda for (idx = 0; idx < nrsrc; idx++) { 297*1d4b38e0Srsmaeda 298*1d4b38e0Srsmaeda str = (char *)(uintptr_t)rsrcs[idx].offset; 299*1d4b38e0Srsmaeda 300*1d4b38e0Srsmaeda /* skip if no error string */ 301*1d4b38e0Srsmaeda if (str == NULL) 302*1d4b38e0Srsmaeda continue; 303*1d4b38e0Srsmaeda 304*1d4b38e0Srsmaeda len = strlen(str) + 1; 305*1d4b38e0Srsmaeda 306*1d4b38e0Srsmaeda /* increase the size of the buffer */ 307*1d4b38e0Srsmaeda resizep = realloc(orsrcsp, osize + len); 308*1d4b38e0Srsmaeda if (resizep == NULL) { 309*1d4b38e0Srsmaeda drd_err("realloc failed: %s", strerror(errno)); 310*1d4b38e0Srsmaeda s_free(orsrcsp); 311*1d4b38e0Srsmaeda 312*1d4b38e0Srsmaeda /* clean up any remaining strings */ 313*1d4b38e0Srsmaeda while (idx < nrsrc) { 314*1d4b38e0Srsmaeda str = (char *)(uintptr_t)rsrcs[idx++].offset; 315*1d4b38e0Srsmaeda s_free(str); 316*1d4b38e0Srsmaeda } 317*1d4b38e0Srsmaeda return (0); 318*1d4b38e0Srsmaeda } 319*1d4b38e0Srsmaeda 320*1d4b38e0Srsmaeda orsrcsp = resizep; 321*1d4b38e0Srsmaeda 322*1d4b38e0Srsmaeda /* copy the error string into the response */ 323*1d4b38e0Srsmaeda off = (char *)orsrcsp + offset; 324*1d4b38e0Srsmaeda bcopy(str, off, len); 325*1d4b38e0Srsmaeda orsrcsp[idx].offset = offset; 326*1d4b38e0Srsmaeda 327*1d4b38e0Srsmaeda /* 328*1d4b38e0Srsmaeda * Now that the error string has been copied 329*1d4b38e0Srsmaeda * into the response message, the memory that 330*1d4b38e0Srsmaeda * was allocated for it is no longer needed. 331*1d4b38e0Srsmaeda */ 332*1d4b38e0Srsmaeda s_free(str); 333*1d4b38e0Srsmaeda rsrcs[idx].offset = 0; 334*1d4b38e0Srsmaeda 335*1d4b38e0Srsmaeda /* update size and offset */ 336*1d4b38e0Srsmaeda offset += len; 337*1d4b38e0Srsmaeda osize += len; 338*1d4b38e0Srsmaeda } 339*1d4b38e0Srsmaeda 340*1d4b38e0Srsmaeda drd_result = orsrcsp; 341*1d4b38e0Srsmaeda return (osize); 342*1d4b38e0Srsmaeda } 343*1d4b38e0Srsmaeda 344*1d4b38e0Srsmaeda /*ARGSUSED*/ 345*1d4b38e0Srsmaeda static void 346*1d4b38e0Srsmaeda drd_door_server(void *cookie, char *argp, size_t arg_sz, door_desc_t *dp, 347*1d4b38e0Srsmaeda uint_t n_desc) 348*1d4b38e0Srsmaeda { 349*1d4b38e0Srsmaeda drd_msg_t *msg = (drd_msg_t *)(uintptr_t)argp; 350*1d4b38e0Srsmaeda drctl_rsrc_t *rsrcs; 351*1d4b38e0Srsmaeda size_t osize; 352*1d4b38e0Srsmaeda int nrsrc; 353*1d4b38e0Srsmaeda 354*1d4b38e0Srsmaeda drd_dbg("drd_door_server..."); 355*1d4b38e0Srsmaeda drd_dbg("message received: %d bytes", arg_sz); 356*1d4b38e0Srsmaeda 357*1d4b38e0Srsmaeda /* sanity check incoming arg */ 358*1d4b38e0Srsmaeda if ((argp == NULL) || (arg_sz == 0)) 359*1d4b38e0Srsmaeda DRD_DOOR_RETURN_ERR(); 360*1d4b38e0Srsmaeda 361*1d4b38e0Srsmaeda drd_dbg(" cmd=%d, count=%d, flags=%d", msg->cmd, 362*1d4b38e0Srsmaeda msg->count, msg->flags); 363*1d4b38e0Srsmaeda 364*1d4b38e0Srsmaeda rsrcs = (drctl_rsrc_t *)(uintptr_t)msg->data; 365*1d4b38e0Srsmaeda nrsrc = msg->count; 366*1d4b38e0Srsmaeda 367*1d4b38e0Srsmaeda /* pass off to backend for processing */ 368*1d4b38e0Srsmaeda switch (msg->cmd) { 369*1d4b38e0Srsmaeda case DRCTL_CPU_CONFIG_REQUEST: 370*1d4b38e0Srsmaeda (*drd_backend->cpu_config_request)(rsrcs, nrsrc); 371*1d4b38e0Srsmaeda break; 372*1d4b38e0Srsmaeda 373*1d4b38e0Srsmaeda case DRCTL_CPU_CONFIG_NOTIFY: 374*1d4b38e0Srsmaeda (*drd_backend->cpu_config_notify)(rsrcs, nrsrc); 375*1d4b38e0Srsmaeda break; 376*1d4b38e0Srsmaeda 377*1d4b38e0Srsmaeda case DRCTL_CPU_UNCONFIG_REQUEST: 378*1d4b38e0Srsmaeda (*drd_backend->cpu_unconfig_request)(rsrcs, nrsrc); 379*1d4b38e0Srsmaeda break; 380*1d4b38e0Srsmaeda 381*1d4b38e0Srsmaeda case DRCTL_CPU_UNCONFIG_NOTIFY: 382*1d4b38e0Srsmaeda (*drd_backend->cpu_unconfig_notify)(rsrcs, nrsrc); 383*1d4b38e0Srsmaeda break; 384*1d4b38e0Srsmaeda 385*1d4b38e0Srsmaeda case DRCTL_MEM_CONFIG_REQUEST: 386*1d4b38e0Srsmaeda case DRCTL_MEM_CONFIG_NOTIFY: 387*1d4b38e0Srsmaeda case DRCTL_MEM_UNCONFIG_REQUEST: 388*1d4b38e0Srsmaeda case DRCTL_MEM_UNCONFIG_NOTIFY: 389*1d4b38e0Srsmaeda drd_err("memory DR operations not supported yet"); 390*1d4b38e0Srsmaeda DRD_DOOR_RETURN_ERR(); 391*1d4b38e0Srsmaeda break; 392*1d4b38e0Srsmaeda 393*1d4b38e0Srsmaeda case DRCTL_IO_CONFIG_REQUEST: 394*1d4b38e0Srsmaeda case DRCTL_IO_CONFIG_NOTIFY: 395*1d4b38e0Srsmaeda case DRCTL_IO_UNCONFIG_REQUEST: 396*1d4b38e0Srsmaeda case DRCTL_IO_UNCONFIG_NOTIFY: 397*1d4b38e0Srsmaeda drd_err("I/O DR operations not supported yet"); 398*1d4b38e0Srsmaeda DRD_DOOR_RETURN_ERR(); 399*1d4b38e0Srsmaeda break; 400*1d4b38e0Srsmaeda 401*1d4b38e0Srsmaeda default: 402*1d4b38e0Srsmaeda drd_err("unknown command: %d", msg->cmd); 403*1d4b38e0Srsmaeda DRD_DOOR_RETURN_ERR(); 404*1d4b38e0Srsmaeda break; 405*1d4b38e0Srsmaeda } 406*1d4b38e0Srsmaeda 407*1d4b38e0Srsmaeda osize = drd_pack_response(rsrcs, nrsrc); 408*1d4b38e0Srsmaeda if (osize == 0) 409*1d4b38e0Srsmaeda DRD_DOOR_RETURN_ERR(); 410*1d4b38e0Srsmaeda 411*1d4b38e0Srsmaeda (void) door_return((char *)drd_result, osize, NULL, 0); 412*1d4b38e0Srsmaeda } 413