vmbus_ic.c revision 298446
1250199Sgrehan/*-
2298446Ssephe * Copyright (c) 2014,2016 Microsoft Corp.
3250199Sgrehan * All rights reserved.
4250199Sgrehan *
5250199Sgrehan * Redistribution and use in source and binary forms, with or without
6250199Sgrehan * modification, are permitted provided that the following conditions
7250199Sgrehan * are met:
8250199Sgrehan * 1. Redistributions of source code must retain the above copyright
9250199Sgrehan *    notice unmodified, this list of conditions, and the following
10250199Sgrehan *    disclaimer.
11250199Sgrehan * 2. Redistributions in binary form must reproduce the above copyright
12250199Sgrehan *    notice, this list of conditions and the following disclaimer in the
13250199Sgrehan *    documentation and/or other materials provided with the distribution.
14250199Sgrehan *
15250199Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16250199Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17250199Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18250199Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19250199Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20250199Sgrehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21250199Sgrehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22250199Sgrehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23250199Sgrehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24250199Sgrehan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25271493Sdelphij *
26271493Sdelphij * $FreeBSD: head/sys/dev/hyperv/utilities/hv_util.c 298446 2016-04-22 05:01:43Z sephe $
27250199Sgrehan */
28250199Sgrehan
29271493Sdelphij/*
30250199Sgrehan * A common driver for all hyper-V util services.
31250199Sgrehan */
32250199Sgrehan
33250199Sgrehan#include <sys/param.h>
34250199Sgrehan#include <sys/kernel.h>
35250199Sgrehan#include <sys/bus.h>
36250199Sgrehan#include <sys/malloc.h>
37250199Sgrehan#include <sys/module.h>
38250199Sgrehan#include <sys/reboot.h>
39250199Sgrehan#include <sys/timetc.h>
40255414Sgrehan#include <sys/syscallsubr.h>
41250199Sgrehan
42250199Sgrehan#include <dev/hyperv/include/hyperv.h>
43295958Ssephe#include "hv_util.h"
44250199Sgrehan
45295958Ssephevoid
46250199Sgrehanhv_negotiate_version(
47250199Sgrehan	struct hv_vmbus_icmsg_hdr*		icmsghdrp,
48250199Sgrehan	struct hv_vmbus_icmsg_negotiate*	negop,
49250199Sgrehan	uint8_t*				buf)
50255414Sgrehan{
51250199Sgrehan	icmsghdrp->icmsgsize = 0x10;
52250199Sgrehan
53250199Sgrehan	negop = (struct hv_vmbus_icmsg_negotiate *)&buf[
54250199Sgrehan		sizeof(struct hv_vmbus_pipe_hdr) +
55250199Sgrehan		sizeof(struct hv_vmbus_icmsg_hdr)];
56250199Sgrehan
57255414Sgrehan	if (negop->icframe_vercnt >= 2 &&
58250199Sgrehan	    negop->icversion_data[1].major == 3) {
59250199Sgrehan		negop->icversion_data[0].major = 3;
60250199Sgrehan		negop->icversion_data[0].minor = 0;
61250199Sgrehan		negop->icversion_data[1].major = 3;
62250199Sgrehan		negop->icversion_data[1].minor = 0;
63250199Sgrehan	} else {
64250199Sgrehan		negop->icversion_data[0].major = 1;
65250199Sgrehan		negop->icversion_data[0].minor = 0;
66250199Sgrehan		negop->icversion_data[1].major = 1;
67250199Sgrehan		negop->icversion_data[1].minor = 0;
68250199Sgrehan	}
69250199Sgrehan
70250199Sgrehan	negop->icframe_vercnt = 1;
71250199Sgrehan	negop->icmsg_vercnt = 1;
72250199Sgrehan}
73250199Sgrehan
74295958Ssepheint
75295958Ssephehv_util_attach(device_t dev)
76250199Sgrehan{
77295958Ssephe	struct hv_device*	hv_dev;
78295958Ssephe	struct hv_util_sc*	softc;
79250199Sgrehan	int			ret;
80250199Sgrehan
81250199Sgrehan	hv_dev = vmbus_get_devctx(dev);
82295958Ssephe	softc = device_get_softc(dev);
83295958Ssephe	softc->hv_dev = hv_dev;
84295958Ssephe	softc->receive_buffer =
85255414Sgrehan		malloc(4 * PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
86250199Sgrehan
87282212Swhu	/*
88282212Swhu	 * These services are not performance critical and do not need
89282212Swhu	 * batched reading. Furthermore, some services such as KVP can
90282212Swhu	 * only handle one message from the host at a time.
91282212Swhu	 * Turn off batched reading for all util drivers before we open the
92282212Swhu	 * channel.
93282212Swhu	 */
94282212Swhu	hv_set_channel_read_state(hv_dev->channel, FALSE);
95282212Swhu
96255414Sgrehan	ret = hv_vmbus_channel_open(hv_dev->channel, 4 * PAGE_SIZE,
97295958Ssephe			4 * PAGE_SIZE, NULL, 0,
98295958Ssephe			softc->callback, softc);
99250199Sgrehan
100250199Sgrehan	if (ret)
101295958Ssephe		goto error0;
102250199Sgrehan
103250199Sgrehan	return (0);
104250199Sgrehan
105295958Ssepheerror0:
106295958Ssephe	free(softc->receive_buffer, M_DEVBUF);
107250199Sgrehan	return (ret);
108250199Sgrehan}
109250199Sgrehan
110295958Ssepheint
111250199Sgrehanhv_util_detach(device_t dev)
112250199Sgrehan{
113295958Ssephe	struct hv_device*	hv_dev;
114295958Ssephe	struct hv_util_sc*	softc;
115250199Sgrehan
116250199Sgrehan	hv_dev = vmbus_get_devctx(dev);
117250199Sgrehan
118250199Sgrehan	hv_vmbus_channel_close(hv_dev->channel);
119295958Ssephe	softc = device_get_softc(dev);
120250199Sgrehan
121295958Ssephe	free(softc->receive_buffer, M_DEVBUF);
122250199Sgrehan	return (0);
123250199Sgrehan}
124