static int VmbusOnISR(struct hv_driver *drv) { int ret = 0; int cpu = smp_processor_id(); void *page_addr; struct hv_message *msg; union hv_synic_event_flags *event; page_addr = gHvContext.synICMessagePage[cpu]; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; DPRINT_ENTER(VMBUS); /* Check if there are actual msgs to be process */ if (msg->Header.MessageType != HvMessageTypeNone) { DPRINT_DBG(VMBUS, "received msg type %d size %d", msg->Header.MessageType, msg->Header.PayloadSize); ret |= 0x1; } /* TODO: Check if there are events to be process */ page_addr = gHvContext.synICEventPage[cpu]; event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) { DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]); ret |= 0x2; } DPRINT_EXIT(VMBUS); return ret; }
/* * read out all the action frame which are queued in the driver even * before issuing any wl cmd. This is essential because due to late arrival of frame it can * get queued after the read expires. */ void rwl_wifi_purge_actionframes(void *wl) { dot11_action_wifi_vendor_specific_t *rec_frame; void *ptr = NULL; if ((rec_frame = (dot11_action_wifi_vendor_specific_t *) malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) { DPRINT_DBG(OUTPUT, "Purge Error in reading the frame \n"); return; } for (;;) { if (rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame, RWL_WIFI_ACTION_FRAME_SIZE, &ptr) < 0) { DPRINT_DBG(OUTPUT, "rwl_wifi_purge_actionframes:" "Purge Error in reading the frame \n"); break; } memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE); if ((rec_frame->category != RWL_ACTION_WIFI_CATEGORY)) break; } free(rec_frame); return; }
static void DumpMonitorPage(struct hv_monitor_page *MonitorPage) { int i = 0; int j = 0; DPRINT_DBG(VMBUS, "monitorPage - %p, trigger state - %d", MonitorPage, MonitorPage->TriggerState); for (i = 0; i < 4; i++) DPRINT_DBG(VMBUS, "trigger group (%d) - %llx", i, MonitorPage->TriggerGroup[i].AsUINT64); for (i = 0; i < 4; i++) { for (j = 0; j < 32; j++) { DPRINT_DBG(VMBUS, "latency (%d)(%d) - %llx", i, j, MonitorPage->Latency[i][j]); } } for (i = 0; i < 4; i++) { for (j = 0; j < 32; j++) { DPRINT_DBG(VMBUS, "param-conn id (%d)(%d) - %d", i, j, MonitorPage->Parameter[i][j].ConnectionId.Asu32); DPRINT_DBG(VMBUS, "param-flag (%d)(%d) - %d", i, j, MonitorPage->Parameter[i][j].FlagNumber); } } }
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo, struct scatterlist *sglist, u32 sgcount) { int i = 0; u32 byteAvailToWrite; u32 byteAvailToRead; u32 totalBytesToWrite = 0; struct scatterlist *sg; volatile u32 nextWriteLocation; u64 prevIndices = 0; unsigned long flags; DPRINT_ENTER(VMBUS); for_each_sg(sglist, sg, sgcount, i) { totalBytesToWrite += sg->length; } totalBytesToWrite += sizeof(u64); spin_lock_irqsave(&OutRingInfo->ring_lock, flags); GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite); DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite); /* DumpRingInfo(OutRingInfo, "BEFORE "); */ /* If there is only room for the packet, assume it is full. */ /* Otherwise, the next time around, we think the ring buffer */ /* is empty since the read index == write index */ if (byteAvailToWrite <= totalBytesToWrite) { DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer " "(needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite); spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags); DPRINT_EXIT(VMBUS); return -1; } /* Write to the ring buffer */ nextWriteLocation = GetNextWriteLocation(OutRingInfo); for_each_sg(sglist, sg, sgcount, i) { nextWriteLocation = CopyToRingBuffer(OutRingInfo, nextWriteLocation, sg_virt(sg), sg->length); }
/*++ Name: RingBufferRead() Description: Read and advance the read index --*/ int RingBufferRead( RING_BUFFER_INFO* InRingInfo, PVOID Buffer, UINT32 BufferLen, UINT32 Offset ) { UINT32 bytesAvailToWrite; UINT32 bytesAvailToRead; UINT32 nextReadLocation=0; UINT64 prevIndices=0; ASSERT(BufferLen > 0); SpinlockAcquire(InRingInfo->RingLock); GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite); DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen); //DumpRingInfo(InRingInfo, "BEFORE "); // Make sure there is something to read if (bytesAvailToRead < BufferLen ) { DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen); SpinlockRelease(InRingInfo->RingLock); return -1; } nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset); nextReadLocation = CopyFromRingBuffer(InRingInfo, Buffer, BufferLen, nextReadLocation); nextReadLocation = CopyFromRingBuffer(InRingInfo, &prevIndices, sizeof(UINT64), nextReadLocation); // Make sure all reads are done before we update the read index since // the writer may start writing to the read area once the read index is updated MemoryFence(); // Update the read index SetNextReadLocation(InRingInfo, nextReadLocation); //DumpRingInfo(InRingInfo, "AFTER "); SpinlockRelease(InRingInfo->RingLock); return 0; }
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo, struct scatterlist *sglist, u32 sgcount) { int i=0; u32 byteAvailToWrite; u32 byteAvailToRead; u32 totalBytesToWrite=0; struct scatterlist *sg; volatile u32 nextWriteLocation; u64 prevIndices=0; unsigned long flags; DPRINT_ENTER(VMBUS); for_each_sg(sglist, sg, sgcount, i) { totalBytesToWrite += sg->length; } totalBytesToWrite += sizeof(u64); spin_lock_irqsave(&OutRingInfo->ring_lock, flags); GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite); DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite); if (byteAvailToWrite <= totalBytesToWrite) { DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite); spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags); DPRINT_EXIT(VMBUS); return -1; } nextWriteLocation = GetNextWriteLocation(OutRingInfo); for_each_sg(sglist, sg, sgcount, i) { nextWriteLocation = CopyToRingBuffer(OutRingInfo, nextWriteLocation, sg_virt(sg), sg->length); }
/* * Heartbeat functionality. * Every two seconds, Hyper-V send us a heartbeat request message. * we respond to this message, and Hyper-V knows we are alive. */ static void heartbeat_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u8 *buf; u32 buflen, recvlen; u64 requestid; struct icmsg_hdr *icmsghdrp; struct heartbeat_msg_data *heartbeat_msg; DPRINT_ENTER(VMBUS); buflen = PAGE_SIZE; buf = kmalloc(buflen, GFP_ATOMIC); VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid); if (recvlen > 0) { DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld", recvlen, requestid); icmsghdrp = (struct icmsg_hdr *)&buf[ sizeof(struct vmbuspipe_hdr)]; icmsghdrp = (struct icmsg_hdr *)&buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { prep_negotiate_resp(icmsghdrp, NULL, buf); } else { heartbeat_msg = (struct heartbeat_msg_data *)&buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; DPRINT_DBG(VMBUS, "heartbeat seq = %lld", heartbeat_msg->seq_num); heartbeat_msg->seq_num += 1; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; VmbusChannelSendPacket(channel, buf, recvlen, requestid, VmbusPacketTypeDataInBand, 0); } kfree(buf); DPRINT_EXIT(VMBUS); }
/*++ Name: CopyFromRingBuffer() Description: Helper routine to copy to source from ring buffer. Assume there is enough room. Handles wrap-around in src case only!! --*/ UINT32 CopyFromRingBuffer( RING_BUFFER_INFO *RingInfo, PVOID Dest, UINT32 DestLen, UINT32 StartReadOffset) { /* Fixme: This should not be a void pointer! */ PVOID ringBuffer=GetRingBuffer(RingInfo); UINT32 ringBufferSize=GetRingBufferSize(RingInfo); UINT32 fragLen; if (DestLen > ringBufferSize - StartReadOffset) // wrap-around detected at the src { DPRINT_DBG(VMBUS, "src wrap-around detected!"); fragLen = ringBufferSize - StartReadOffset; /* Fixme: Cast needed due to void pointer */ memcpy(Dest, (UCHAR *)ringBuffer + StartReadOffset, fragLen); /* Fixme: Cast needed due to void pointer */ memcpy((UCHAR *)Dest + fragLen, ringBuffer, DestLen - fragLen); } else { /* Fixme: Cast needed due to void pointer */ memcpy(Dest, (UCHAR *)ringBuffer + StartReadOffset, DestLen); } StartReadOffset += DestLen; StartReadOffset %= ringBufferSize; return StartReadOffset; }
static void shutdown_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; u8 execute_shutdown = false; struct shutdown_msg_data *shutdown_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; vmbus_recvpacket(channel, shut_txf_buf, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld", recvlen, requestid); icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); } else { shutdown_msg = (struct shutdown_msg_data *)&shut_txf_buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; switch (shutdown_msg->flags) { case 0: case 1: icmsghdrp->status = HV_S_OK; execute_shutdown = true; DPRINT_INFO(VMBUS, "Shutdown request received -" " gracefull shutdown initiated"); break; default: icmsghdrp->status = HV_E_FAIL; execute_shutdown = false; DPRINT_INFO(VMBUS, "Shutdown request received -" " Invalid request"); break; }; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, shut_txf_buf, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } if (execute_shutdown == true) orderly_poweroff(false); }
/* * Send the response to the remote if the channel of the server matches with the * server channel. */ void remote_wifi_response(void* wl) { #ifdef RWL_WIFI dot11_action_wifi_vendor_specific_t *list; if ((list = rwl_wifi_allocate_actionframe()) == NULL) { DPRINT_DBG(OUTPUT, "remote_wifi_response: Failed to allocate frame \n"); return; } /* it's sync frame and received from client */ memcpy((char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET], &g_rem_pkt_ptr[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE); memcpy((char*)&list->data[REMOTE_SIZE], g_rem_pkt_ptr->message, RWL_WIFI_FRAG_DATA_SIZE); list->type = RWL_WIFI_FIND_MY_PEER; /* Store the client mac addr */ memcpy((void*)&rwlea, (void*)&list->data[RWL_DUT_MAC_ADDRESS_OFFSET], ETHER_ADDR_LEN); /* send the response to client if server is on the same channel */ rwl_wifi_find_server_response(wl, list); free(list); #else UNUSED_PARAMETER(wl); #endif /* RWL_WIFI */ return; }
/* Function to get the shell response from the file */ int remote_shell_async_get_resp(char* shell_fname, char* buf_ptr, int msg_len) { int sts = 0; FILE *shell_fpt; shell_fpt = fopen(shell_fname, "rb"); if (shell_fpt == NULL) { DPRINT_ERR(ERR, "\nShell Cmd:File open error\n"); return sts; } /* If there is any response from the shell, Read the file and * update the buffer for the shell response * else Just send the return value of the command executed */ if (g_shellsync_pid != SHELL_ASYNCCMD_ID) { if (msg_len) sts = fread(buf_ptr, sizeof(char), msg_len, shell_fpt); fscanf(shell_fpt, "%2x", &sts); } else sts = fread(buf_ptr, sizeof(char), MAX_SHELL_CMD_LENTH, shell_fpt); fclose(shell_fpt); remove(shell_fname); DPRINT_DBG(OUTPUT, "\n Resp buff from shell cmdis %s\n", buf_ptr); return sts; }
/* * NetVscInitialize - Main entry point */ int NetVscInitialize(struct hv_driver *drv) { struct netvsc_driver *driver = (struct netvsc_driver *)drv; DPRINT_DBG(NETVSC, "sizeof(struct hv_netvsc_packet)=%zd, " "sizeof(struct nvsp_message)=%zd, " "sizeof(struct vmtransfer_page_packet_header)=%zd", sizeof(struct hv_netvsc_packet), sizeof(struct nvsp_message), sizeof(struct vmtransfer_page_packet_header)); /* Make sure we are at least 2 pages since 1 page is used for control */ /* ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1)); */ drv->name = gDriverName; memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(struct hv_guid)); /* Make sure it is set by the caller */ /* FIXME: These probably should still be tested in some way */ /* ASSERT(driver->OnReceiveCallback); */ /* ASSERT(driver->OnLinkStatusChanged); */ /* Setup the dispatch table */ driver->Base.OnDeviceAdd = NetVscOnDeviceAdd; driver->Base.OnDeviceRemove = NetVscOnDeviceRemove; driver->Base.OnCleanup = NetVscOnCleanup; driver->OnSend = NetVscOnSend; RndisFilterInit(driver); return 0; }
int rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread) { int ret; uint total_numread = 0; while (total_numread < data_size) { ret = read(*(int *)hndle, read_buf, data_size - total_numread); *numread = ret; if (ret == -1) { perror("ReadFromPort Failed"); DPRINT_ERR(ERR, "Errno:%d\n", errno); return FAIL; } if (*numread != data_size - total_numread) { DPRINT_DBG(OUTPUT, "asked for %d bytes got %d bytes\n", data_size - total_numread, *numread); } if (*numread == 0) break; total_numread += *numread; read_buf += *numread; } return SUCCESS; }
/* Transmit the response in the opened TCP stream socket */ int rwl_send_to_streamsocket(int SocketDes, const char* SendBuff, int data_size, int Flag) { int total_numwritten = 0, numwritten = 0; while (total_numwritten < data_size) { if ((numwritten = send(SocketDes, SendBuff, data_size - total_numwritten, Flag)) == -1) { perror("Failed to send()"); DPRINT_ERR(ERR, "\n errno:%d\n", errno); return (FAIL); } /* Sent successfully at first attempt no more retries */ if (numwritten == data_size) { total_numwritten = numwritten; break; } /* If socket is busy we may hit this condition */ if (numwritten != data_size - total_numwritten) { DPRINT_DBG(OUTPUT, "wanted to send %d bytes sent only %d bytes\n", data_size - total_numwritten, numwritten); } /* Now send the remaining buffer */ total_numwritten += numwritten; SendBuff += numwritten; } return total_numwritten; }
/* Receive the response from the opened TCP stream socket */ int rwl_receive_from_streamsocket(int SocketDes, char* RecvBuff, int data_size, int Flag) { int numread; int total_numread = 0; while (total_numread < data_size) { if ((numread = recv(SocketDes, RecvBuff, data_size - total_numread, Flag)) == -1) { perror("Failed to Receive()"); DPRINT_ERR(ERR, "\n errno:%d\n", errno); return FAIL; } if (numread != data_size - total_numread) { DPRINT_DBG(OUTPUT, "asked %d bytes got %d bytes\n", data_size - total_numread, numread); } if (numread == 0) break; total_numread += numread; RecvBuff += numread; } return numread; }
int rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread) { uint total_numread = 0; int c = 0; while (total_numread < data_size) { if (ReadFile(hndle, read_buf, data_size - total_numread, numread, NULL) == 0) { DPRINT_ERR(ERR, "rwl_read_serial_port failed with:%d", WSAGetLastError()); return FAIL; } if (*numread != data_size - total_numread) { c++; DPRINT_DBG(OUTPUT, "asked %d bytes got %d bytes\n", data_size - total_numread, *numread); if (c > MAX_SERIAL_READ_RETRY) { DPRINT_ERR(ERR, "rwl_read_serial_port failed: " "reached max retry limit.\n"); return FAIL; } Sleep(10); } total_numread += *numread; read_buf += *numread; } return SUCCESS; }
static int rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf) { int pid, msg_len, error; g_sig_ctrlc = 1; g_child_pid = pid = rwl_shell_createproc(wl); if (pid == 0) { while (g_sig_ctrlc); remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0); exit(0); } do { if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0, NULL, RWL_WIFI_SHELL_CMD)) < 0) { DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):" "error in reading shell response\n"); continue; } msg_len = rem_ptr->msg.len; error = rem_ptr->msg.cmd; } while (msg_len); rwl_shell_killproc(pid); return error; }
/* This function will send the buffer to the dongle driver */ int rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len) { int len; memset(rwl_buf, 0, WLC_IOCTL_MAXLEN); strcpy((char*) rwl_buf, iovar); /* include the null */ len = strlen(iovar) + 1; if (param_len) memcpy((void*)&rwl_buf[len+ OFFSETOF(wl_action_frame_t, data)], param, param_len); /* Set the PacketID (not used by remote WL */ memset((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4); /* Set the dest addr */ memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, da)], (void*)&rwlea, ETHER_ADDR_LEN); /* set the length */ memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, len)], (void*) ¶m_len, 2); len += param_len + ETHER_ADDR_LEN + 2 + 4; DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len); return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len); }
/*++ Name: CopyToRingBuffer() Description: Helper routine to copy from source to ring buffer. Assume there is enough room. Handles wrap-around in dest case only!! --*/ UINT32 CopyToRingBuffer( RING_BUFFER_INFO *RingInfo, UINT32 StartWriteOffset, PVOID Src, UINT32 SrcLen) { /* Fixme: This should not be a void pointer! */ PVOID ringBuffer=GetRingBuffer(RingInfo); UINT32 ringBufferSize=GetRingBufferSize(RingInfo); UINT32 fragLen; if (SrcLen > ringBufferSize - StartWriteOffset) // wrap-around detected! { DPRINT_DBG(VMBUS, "wrap-around detected!"); fragLen = ringBufferSize - StartWriteOffset; /* Fixme: Cast needed due to void pointer */ memcpy((UCHAR *)ringBuffer + StartWriteOffset, Src, fragLen); /* Fixme: Cast needed due to void pointer */ memcpy(ringBuffer, (UCHAR *)Src + fragLen, SrcLen - fragLen); } else { /* Fixme: Cast needed due to void pointer */ memcpy((unsigned char *)ringBuffer + StartWriteOffset, Src, SrcLen); } StartWriteOffset += SrcLen; StartWriteOffset %= ringBufferSize; return StartWriteOffset; }
/* * Time Sync Channel message handler. */ static void timesync_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct icmsg_hdr *icmsghdrp; struct ictimesync_data *timedatap; vmbus_recvpacket(channel, time_txf_buf, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld", recvlen, requestid); icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); } else { timedatap = (struct ictimesync_data *)&time_txf_buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; adj_guesttime(timedatap->parenttime, timedatap->flags); } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, time_txf_buf, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } }
int rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size) { DPRINT_DBG(OUTPUT, "sockconnet SockDes=%d\n", SockDes); if (rwl_connectsocket(SockDes, servAddr, size) < 0) { DPRINT_ERR(ERR, "\n Server is not running\n"); return FAIL; } return SUCCESS; }
static int rwl_opensocket(int AddrFamily, int Type, int Protocol) { int SockDes; if ((SockDes = socket(AddrFamily, Type, Protocol)) == INVALID_SOCKET) { DPRINT_ERR(ERR, "\n rwl_opensocket Fails:%d\n", WSAGetLastError()); return FAIL; } DPRINT_DBG(OUTPUT, "SockDes=%d\n", SockDes); return SockDes; }
/* * Heartbeat functionality. * Every two seconds, Hyper-V send us a heartbeat request message. * we respond to this message, and Hyper-V knows we are alive. */ static void heartbeat_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct icmsg_hdr *icmsghdrp; struct heartbeat_msg_data *heartbeat_msg; vmbus_recvpacket(channel, hbeat_txf_buf, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld", recvlen, requestid); icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); } else { heartbeat_msg = (struct heartbeat_msg_data *)&hbeat_txf_buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; DPRINT_DBG(VMBUS, "heartbeat seq = %lld", heartbeat_msg->seq_num); heartbeat_msg->seq_num += 1; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, hbeat_txf_buf, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } }
rem_ioctl_t * remote_CDC_rx_hdr(void *remote, int debug) { #ifdef RWL_SOCKET int ret; #endif /* RWL_SOCKET */ uint numread = 0; rem_ioctl_t *rem_ptr = &rem_cdc; memset(rem_ptr, 0, sizeof(rem_ioctl_t)); #ifdef RWL_WIFI UNUSED_PARAMETER(remote); UNUSED_PARAMETER(numread); #endif /* RWL_WIFI */ UNUSED_PARAMETER(debug); switch (remote_type) { #if defined(RWL_SERIAL) || defined(RWL_DONGLE) case REMOTE_SERIAL: case REMOTE_DONGLE: if (rwl_read_serial_port(remote, (char *)rem_ptr, sizeof(rem_ioctl_t), &numread) < 0) { DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Header Read failed \n"); return (NULL); } break; #endif /* RWL_SERIAL | RWL_DONGLE */ #ifdef RWL_SOCKET case REMOTE_SOCKET: ret = rwl_receive_from_streamsocket(*(int*)remote, (char *)rem_ptr, sizeof(rem_ioctl_t), 0); numread = ret; if (ret == -1) { DPRINT_ERR(ERR, "remote_CDC_rx_hdr: numread:%d", numread); return (NULL); } if (numread == 0) { DPRINT_DBG(OUTPUT, "\n remote_CDC_rx_hdr:No data to receive\n"); return NULL; } break; #endif default: DPRINT_ERR(ERR, "\n Unknown Transport Type\n"); break; } return (rem_ptr); }
/* Make initial connection from client to server through sockets */ static int rwl_connect_socket_server(void) { int SockDes = -1; struct sockaddr_in servAddr; int retries = 0; int max_retries = 20; int connected = 0; memset(&servAddr, 0, sizeof(servAddr)); while ((connected == 0) && (retries < max_retries)) { DPRINT_DBG(OUTPUT, "rwl_connect_socket_server retry %d\n", retries); if ((SockDes = (*(int *)rwl_open_pipe(remote_type, "\0", 0, 0))) == FAIL) { retries++; continue; } /*if (!validate_server_address()) { retries++; continue; }*/ DPRINT_DBG(OUTPUT, "ServerIP:%s,ServerPort:%d\n", g_rwl_servIP, g_rwl_servport); servAddr.sin_family = AF_INET; servAddr.sin_port = hton16(g_rwl_servport); servAddr.sin_addr.s_addr = inet_addr(g_rwl_servIP); if (rwl_sockconnect(SockDes, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) { rwl_close_pipe(remote_type, (void*) &SockDes); retries++; continue; } else connected = 1; } return SockDes; }
int rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread) { uint total_numread = 0; int c = 0; while (total_numread < data_size) { if (ReadFile(hndle, read_buf, data_size - total_numread, (LPDWORD) numread, NULL) == 0) { DPRINT_ERR(ERR, "rwl_read_serial_port failed with:%d", GetLastError()); return FAIL; } if (*numread != data_size - total_numread) { c++; DPRINT_DBG(OUTPUT, "asked %d bytes got %d bytes\n", data_size - total_numread, *numread); if (c > MAX_SERIAL_READ_RETRY) { DPRINT_ERR(ERR, "rwl_read_serial_port failed: " "reached max retry limit.\n"); return FAIL; } Sleep(10); } total_numread += *numread; read_buf += *numread; } #ifdef DEBUG_SERIAL printf( "\nr %04d < ", total_numread); int i; for( i = 0; i < total_numread; i++ ) { #ifdef READABLE_SERIAL_DUMP if ( ( orig_read_buf[i] >= 0x20 ) && ( orig_read_buf[i] <= 0x7E ) ) { printf( "%c",orig_read_buf[i]); } else { printf( "\\x%02X",(unsigned char)orig_read_buf[i]); } #else /* ifdef READABLE_SERIAL_DUMP */ printf( " %02X",(unsigned char)orig_read_buf[i]); #endif /* ifdef READABLE_SERIAL_DUMP */ } printf("\n"); #endif /* ifdef DEBUG_SERIAL */ return SUCCESS; }
/* Function: rwl_transport_setup * This will do the initialization for * for all the transports */ static int rwl_transport_setup(int argc, char** argv) { int transport_descriptor = -1; UNUSED_PARAMETER(argc); UNUSED_PARAMETER(argv); #ifdef RWL_SOCKET /* This function will parse the socket command line arguments * & open the socket in listen mode */ remote_type = REMOTE_SOCKET; transport_descriptor = rwl_init_server_socket_setup(argc, argv, remote_type); if (transport_descriptor < 0) { DPRINT_ERR(ERR, "wl_socket_server:Transport setup failed \n"); } #endif /* RWL_SOCKET */ #if defined (RWL_DONGLE) || defined (RWL_WIFI) || defined (RWL_SERIAL) g_rem_pkt_ptr = &g_rem_pkt; transport_descriptor = 0; #ifdef RWL_WIFI remote_type = REMOTE_WIFI; #endif #ifdef RWL_DONGLE remote_type = REMOTE_DONGLE; #endif /* RWL_DONGLE */ #ifdef RWL_SERIAL remote_type = REMOTE_SERIAL; if (argc < 2) { DPRINT_ERR(ERR, "Port name is required from the command line\n"); } else { (void)*argv++; DPRINT_DBG(OUTPUT, "Port name is %s\n", *argv); transport_descriptor = *(int*) rwl_open_transport(remote_type, *argv, 0, 0); } #endif /* RWL_SERIAL */ #endif /* RWL_DONGLE ||RWL_SERIAL ||RWL_WIFI */ #ifdef RWLASD g_serv_sock_desc = transport_descriptor; #endif return transport_descriptor; }
/* This routine is common to both set and Get Ioctls for the dongle case */ static int rwl_information_dongle(void *wl, int cmd, void* input_buf, unsigned long *input_len, uint tx_len, uint flags) { int error; rem_ioctl_t *rem_ptr = NULL; if (remote_CDC_tx(wl, cmd, input_buf, *input_len, tx_len, flags, 0) < 0) { DPRINT_ERR(ERR, "query_info_fe: Send command failed\n"); return FAIL; } /* Get the header */ if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) { DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n"); return SERIAL_PORT_ERR; } /* Make sure there is enough room */ if (rem_ptr->msg.len > *input_len) { DPRINT_DBG(OUTPUT, "query_info_fe: needed size(%d) > actual" "size(%ld)\n", rem_ptr->msg.len, *input_len); return FAIL; } /* We can grab short frames all at once. Longer frames (> 960 bytes) * come in fragments. */ if (rem_ptr->data_len < DATA_FRAME_LEN) { if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) { DPRINT_ERR(ERR, "query_info_fe: No results!\n"); return FAIL; } if (rem_ptr->msg.flags & REMOTE_REPLY) error = rem_ptr->msg.cmd; else error = 0; } else { /* rwl_serial_fragmented_response_fe returns either valid number or FAIL. * In any case return the same value to caller */ error = rwl_serial_fragmented_response_fe(wl, rem_ptr, input_buf, input_len); } return error; }
/** * VmbusInitialize - Main entry point */ int VmbusInitialize(struct hv_driver *drv) { struct vmbus_driver *driver = (struct vmbus_driver *)drv; int ret; DPRINT_ENTER(VMBUS); DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++", VersionDate, VersionTime); DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++", VersionDesc); DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++", VMBUS_REVISION_NUMBER); DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT); DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%zd, " "sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%zd", sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)); drv->name = gDriverName; memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid)); /* Setup dispatch table */ driver->Base.OnDeviceAdd = VmbusOnDeviceAdd; driver->Base.OnDeviceRemove = VmbusOnDeviceRemove; driver->Base.OnCleanup = VmbusOnCleanup; driver->OnIsr = VmbusOnISR; driver->OnMsgDpc = VmbusOnMsgDPC; driver->OnEventDpc = VmbusOnEventDPC; driver->GetChannelOffers = VmbusGetChannelOffers; driver->GetChannelInterface = VmbusGetChannelInterface; driver->GetChannelInfo = VmbusGetChannelInfo; /* Hypervisor initialization...setup hypercall page..etc */ ret = HvInit(); if (ret != 0) DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x", ret); gDriver = drv; DPRINT_EXIT(VMBUS); return ret; }
/* * Time Sync Channel message handler. */ static void timesync_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u8 *buf; u32 buflen, recvlen; u64 requestid; struct icmsg_hdr *icmsghdrp; struct ictimesync_data *timedatap; DPRINT_ENTER(VMBUS); buflen = PAGE_SIZE; buf = kmalloc(buflen, GFP_ATOMIC); VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid); if (recvlen > 0) { DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld", recvlen, requestid); icmsghdrp = (struct icmsg_hdr *)&buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { prep_negotiate_resp(icmsghdrp, NULL, buf); } else { timedatap = (struct ictimesync_data *)&buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; adj_guesttime(timedatap->parenttime, timedatap->flags); } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; VmbusChannelSendPacket(channel, buf, recvlen, requestid, VmbusPacketTypeDataInBand, 0); } kfree(buf); DPRINT_EXIT(VMBUS); }