Index: head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c =================================================================== --- head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -87,6 +87,8 @@ #define STORVSC_WIN8_MAJOR 5 #define STORVSC_WIN8_MINOR 1 +#define VSTOR_PKT_SIZE (sizeof(struct vstor_packet) - vmscsi_size_delta) + #define HV_ALIGN(x, a) roundup2(x, a) struct storvsc_softc; @@ -202,6 +204,21 @@ STORVSC_RINGBUFFER_SIZE} }; +/* + * Sense buffer size changed in win8; have a run-time + * variable to track the size we should use. + */ +static int sense_buffer_size; + +/* + * The size of the vmscsi_request has changed in win8. The + * additional size is for the newly added elements in the + * structure. These elements are valid only when we are talking + * to a win8 host. + * Track the correct size we need to apply. + */ +static int vmscsi_size_delta; + static int storvsc_current_major; static int storvsc_current_minor; @@ -214,6 +231,7 @@ static int create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp); static void storvsc_free_request(struct storvsc_softc *sc, struct hv_storvsc_request *reqp); static enum hv_storage_type storvsc_get_storage_type(device_t dev); +static void hv_storvsc_rescan_target(struct storvsc_softc *sc); static void hv_storvsc_on_channel_callback(void *context); static void hv_storvsc_on_iocompletion( struct storvsc_softc *sc, struct vstor_packet *vstor_packet, @@ -381,7 +399,7 @@ ret = hv_vmbus_channel_send_packet( dev->channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -448,7 +466,7 @@ ret = hv_vmbus_channel_send_packet( dev->channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -481,7 +499,7 @@ ret = hv_vmbus_channel_send_packet( dev->channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -510,7 +528,7 @@ ret = hv_vmbus_channel_send_packet( dev->channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -546,7 +564,7 @@ ret = hv_vmbus_channel_send_packet( dev->channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -644,7 +662,7 @@ ret = hv_vmbus_channel_send_packet(dev->channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)&sc->hs_reset_req, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -695,9 +713,9 @@ vstor_packet->flags |= REQUEST_COMPLETION_FLAG; - vstor_packet->u.vm_srb.length = sizeof(struct vmscsi_req); + vstor_packet->u.vm_srb.length = VSTOR_PKT_SIZE; - vstor_packet->u.vm_srb.sense_info_len = SENSE_BUFFER_SIZE; + vstor_packet->u.vm_srb.sense_info_len = sense_buffer_size; vstor_packet->u.vm_srb.transfer_len = request->data_buf.length; @@ -711,14 +729,14 @@ outgoing_channel, &request->data_buf, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request); } else { ret = hv_vmbus_channel_send_packet( outgoing_channel, vstor_packet, - sizeof(struct vstor_packet), + VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request, HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -772,6 +790,41 @@ } static void +hv_storvsc_rescan_target(struct storvsc_softc *sc) +{ + path_id_t pathid; + target_id_t targetid; + union ccb *ccb; + + pathid = cam_sim_path(sc->hs_sim); + targetid = CAM_TARGET_WILDCARD; + + /* + * Allocate a CCB and schedule a rescan. + */ + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + printf("unable to alloc CCB for rescan\n"); + return; + } + + if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + printf("unable to create path for rescan, pathid: %d," + "targetid: %d\n", pathid, targetid); + xpt_free_ccb(ccb); + return; + } + + if (targetid == CAM_TARGET_WILDCARD) + ccb->ccb_h.func_code = XPT_SCAN_BUS; + else + ccb->ccb_h.func_code = XPT_SCAN_TGT; + + xpt_rescan(ccb); +} + +static void hv_storvsc_on_channel_callback(void *context) { int ret = 0; @@ -801,7 +854,7 @@ ret = hv_vmbus_channel_recv_packet( channel, packet, - roundup2(sizeof(struct vstor_packet), 8), + roundup2(VSTOR_PKT_SIZE, 8), &bytes_recvd, &request_id); @@ -826,11 +879,13 @@ vstor_packet, request); break; case VSTOR_OPERATION_REMOVEDEVICE: - case VSTOR_OPERATION_ENUMERATE_BUS: printf("VMBUS: storvsc operation %d not " "implemented.\n", vstor_packet->operation); /* TODO: implement */ break; + case VSTOR_OPERATION_ENUMERATE_BUS: + hv_storvsc_rescan_target(sc); + break; default: break; } @@ -838,7 +893,7 @@ ret = hv_vmbus_channel_recv_packet( channel, packet, - roundup2(sizeof(struct vstor_packet), 8), + roundup2(VSTOR_PKT_SIZE, 8), &bytes_recvd, &request_id); } @@ -861,13 +916,17 @@ int ata_disk_enable = 0; int ret = ENXIO; - if ((HV_VMBUS_VERSION_WIN8 == hv_vmbus_protocal_version) || - (HV_VMBUS_VERSION_WIN8_1 == hv_vmbus_protocal_version)){ - storvsc_current_major = STORVSC_WIN8_MAJOR; - storvsc_current_minor = STORVSC_WIN8_MINOR; - } else { + if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 || + hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) { + sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); storvsc_current_major = STORVSC_WIN7_MAJOR; storvsc_current_minor = STORVSC_WIN7_MINOR; + } else { + sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = 0; + storvsc_current_major = STORVSC_WIN8_MAJOR; + storvsc_current_minor = STORVSC_WIN8_MINOR; } switch (storvsc_get_storage_type(dev)) { Index: head/sys/dev/hyperv/storvsc/hv_vstorage.h =================================================================== --- head/sys/dev/hyperv/storvsc/hv_vstorage.h +++ head/sys/dev/hyperv/storvsc/hv_vstorage.h @@ -51,6 +51,8 @@ * V1 Beta 0.1 * V1 RC < 2008/1/31 1.0 * V1 RC > 2008/1/31 2.0 + * Win7: 4.2 + * Win8: 5.1 */ #define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(5, 1) @@ -83,9 +85,25 @@ */ #define CDB16GENERIC_LENGTH 0x10 -#define SENSE_BUFFER_SIZE 0x12 +#define SENSE_BUFFER_SIZE 0x14 #define MAX_DATA_BUFFER_LENGTH_WITH_PADDING 0x14 +#define POST_WIN7_STORVSC_SENSE_BUFFER_SIZE 0x14 +#define PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE 0x12 + + +struct vmscsi_win8_extension { + /* + * The following were added in Windows 8 + */ + uint16_t reserve; + uint8_t queue_tag; + uint8_t queue_action; + uint32_t srb_flags; + uint32_t time_out_value; + uint32_t queue_sort_ey; +} __packed; + struct vmscsi_req { uint16_t length; uint8_t srb_status; @@ -114,6 +132,11 @@ uint8_t reserved_array[MAX_DATA_BUFFER_LENGTH_WITH_PADDING]; } u; + /* + * The following was added in win8. + */ + struct vmscsi_win8_extension win8_extension; + } __packed; /**