xref: /titanic_51/usr/src/cmd/drd/drd.c (revision 1d4b38e0077763e7c9b20768eacb841957e787bc)
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