/** * Shutdown */ static void hv_shutdown_cb(void *context) { uint8_t* buf; hv_vmbus_channel* channel = context; uint8_t execute_shutdown = 0; hv_vmbus_icmsg_hdr* icmsghdrp; uint32_t recv_len; uint64_t request_id; int ret; hv_vmbus_shutdown_msg_data* shutdown_msg; buf = receive_buffer[HV_SHUT_DOWN]; ret = hv_vmbus_channel_recv_packet(channel, buf, PAGE_SIZE, &recv_len, &request_id); if ((ret == 0) && recv_len > 0) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &buf[sizeof(struct hv_vmbus_pipe_hdr)]; if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { hv_negotiate_version(icmsghdrp, NULL, buf); } else { shutdown_msg = (struct hv_vmbus_shutdown_msg_data *) &buf[sizeof(struct hv_vmbus_pipe_hdr) + sizeof(struct hv_vmbus_icmsg_hdr)]; switch (shutdown_msg->flags) { case 0: case 1: icmsghdrp->status = HV_S_OK; execute_shutdown = 1; if(bootverbose) printf("Shutdown request received -" " graceful shutdown initiated\n"); break; default: icmsghdrp->status = HV_E_FAIL; execute_shutdown = 0; printf("Shutdown request received -" " Invalid request\n"); break; } } icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; hv_vmbus_channel_send_packet(channel, buf, recv_len, request_id, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); } if (execute_shutdown) shutdown_nice(RB_POWEROFF); }
/** * Process heartbeat message */ static void hv_heartbeat_cb(void *context) { uint8_t* buf; hv_vmbus_channel* channel = context; uint32_t recvlen; uint64_t requestid; int ret; struct hv_vmbus_heartbeat_msg_data* heartbeat_msg; struct hv_vmbus_icmsg_hdr* icmsghdrp; buf = receive_buffer[HV_HEART_BEAT]; ret = hv_vmbus_channel_recv_packet(channel, buf, PAGE_SIZE, &recvlen, &requestid); if ((ret == 0) && recvlen > 0) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &buf[sizeof(struct hv_vmbus_pipe_hdr)]; if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { hv_negotiate_version(icmsghdrp, NULL, buf); } else { heartbeat_msg = (struct hv_vmbus_heartbeat_msg_data *) &buf[sizeof(struct hv_vmbus_pipe_hdr) + sizeof(struct hv_vmbus_icmsg_hdr)]; heartbeat_msg->seq_num += 1; } icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; hv_vmbus_channel_send_packet(channel, buf, recvlen, requestid, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); } }
/** * Time Sync Channel message handler */ static void hv_timesync_cb(void *context) { hv_vmbus_channel* channel; hv_vmbus_icmsg_hdr* icmsghdrp; uint32_t recvlen; uint64_t requestId; int ret; uint8_t* time_buf; struct hv_ictimesync_data* timedatap; hv_timesync_sc *softc; softc = (hv_timesync_sc*)context; channel = softc->util_sc.hv_dev->channel; time_buf = softc->util_sc.receive_buffer; ret = hv_vmbus_channel_recv_packet(channel, time_buf, PAGE_SIZE, &recvlen, &requestId); if ((ret == 0) && recvlen > 0) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &time_buf[ sizeof(struct hv_vmbus_pipe_hdr)]; if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { hv_negotiate_version(icmsghdrp, NULL, time_buf); } else { timedatap = (struct hv_ictimesync_data *) &time_buf[ sizeof(struct hv_vmbus_pipe_hdr) + sizeof(struct hv_vmbus_icmsg_hdr)]; hv_adj_guesttime(softc, timedatap->parenttime, timedatap->flags); } icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; hv_vmbus_channel_send_packet(channel, time_buf, recvlen, requestId, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); } }
/** * Time Sync Channel message handler */ static void hv_timesync_cb(struct vmbus_channel *channel, void *context) { hv_vmbus_icmsg_hdr* icmsghdrp; uint32_t recvlen; uint64_t requestId; int ret; uint8_t* time_buf; struct hv_ictimesync_data* timedatap; hv_timesync_sc *softc; softc = (hv_timesync_sc*)context; time_buf = softc->util_sc.receive_buffer; recvlen = PAGE_SIZE; ret = vmbus_chan_recv(channel, time_buf, &recvlen, &requestId); KASSERT(ret != ENOBUFS, ("hvtimesync recvbuf is not large enough")); /* XXX check recvlen to make sure that it contains enough data */ if ((ret == 0) && recvlen > 0) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &time_buf[ sizeof(struct hv_vmbus_pipe_hdr)]; if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { hv_negotiate_version(icmsghdrp, NULL, time_buf); } else { timedatap = (struct hv_ictimesync_data *) &time_buf[ sizeof(struct hv_vmbus_pipe_hdr) + sizeof(struct hv_vmbus_icmsg_hdr)]; hv_adj_guesttime(softc, timedatap->parenttime, timedatap->flags); } icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, time_buf, recvlen, requestId); } }
/* * Callback routine that gets called whenever there is a message from host */ static void hv_kvp_callback(void *context) { uint8_t* buf; hv_vmbus_channel* channel = context; uint32_t recvlen; uint64_t requestid; int ret; struct hv_vmbus_icmsg_hdr* icmsghdrp; buf = receive_buffer[0]; #if 0 /* If driver unloaded abruptly, return */ if (vmbus_kvp_channel == NULL) { #ifdef DEBUG printf("hv_kvp_cb: kvp unloaded abruptly\n"); #endif return; } #endif /* Check if kvp is ready to process */ if (!hv_kvp_ready()) { #ifdef DEBUG printf("hv_kvp_cb: kvp is not ready..initing\n"); #endif hv_queue_work_item(kvp_work_queue, hv_kvp_conn_register, NULL); } /* Check if already one transaction is under process */ if (hv_kvp_transaction_active()) { #ifdef DEBUG printf("hv_kvp_cb: Already one transaction is active\n"); #endif return; } ret = hv_vmbus_channel_recv_packet(channel, buf, PAGE_SIZE * 2, &recvlen, &requestid); #ifdef DEBUG printf("hv_kvp_cb: vmbus_recv ret:%d rLen:%d rId:%d\n", ret, recvlen, (int)requestid); #endif if ((ret == 0) && (recvlen > 0)) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &buf[sizeof(struct hv_vmbus_pipe_hdr)]; if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { #ifdef DEBUG printf("hv_kvp_cb: Negotiate message received\n"); #endif hv_negotiate_version(icmsghdrp, NULL, buf); } else { #ifdef DEBUG printf("hv_kvp_cb: New host message received\n"); #endif hv_kvp_transaction_init(recvlen,channel,requestid, buf); hv_queue_work_item(kvp_work_queue, hv_kvp_process_msg, NULL); return; /* deferred response by KVP process */ } icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; hv_vmbus_channel_send_packet(channel, buf, recvlen, requestid, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); } }
/** * Shutdown */ static void hv_shutdown_cb(struct vmbus_channel *channel, void *context) { uint8_t* buf; uint8_t execute_shutdown = 0; hv_vmbus_icmsg_hdr* icmsghdrp; uint32_t recv_len; uint64_t request_id; int ret; hv_vmbus_shutdown_msg_data* shutdown_msg; hv_util_sc *softc; softc = (hv_util_sc*)context; buf = softc->receive_buffer; recv_len = softc->ic_buflen; ret = vmbus_chan_recv(channel, buf, &recv_len, &request_id); KASSERT(ret != ENOBUFS, ("hvshutdown recvbuf is not large enough")); /* XXX check recv_len to make sure that it contains enough data */ if ((ret == 0) && recv_len > 0) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &buf[sizeof(struct hv_vmbus_pipe_hdr)]; if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { hv_negotiate_version(icmsghdrp, buf); } else { shutdown_msg = (struct hv_vmbus_shutdown_msg_data *) &buf[sizeof(struct hv_vmbus_pipe_hdr) + sizeof(struct hv_vmbus_icmsg_hdr)]; switch (shutdown_msg->flags) { case 0: case 1: icmsghdrp->status = HV_S_OK; execute_shutdown = 1; if(bootverbose) printf("Shutdown request received -" " graceful shutdown initiated\n"); break; default: icmsghdrp->status = HV_E_FAIL; execute_shutdown = 0; printf("Shutdown request received -" " Invalid request\n"); break; } } icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, buf, recv_len, request_id); } if (execute_shutdown) shutdown_nice(RB_POWEROFF); }