win-pvdrivers

changeset 784:744be619e07c

More scsi compliance updates
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 16 14:54:42 2010 +1100 (2010-02-16)
parents 644e5ddb1b47
children b18131bbbaf0
files xenvbd/xenvbd.c
line diff
     1.1 --- a/xenvbd/xenvbd.c	Mon Feb 15 20:53:57 2010 +1100
     1.2 +++ b/xenvbd/xenvbd.c	Tue Feb 16 14:54:42 2010 +1100
     1.3 @@ -639,25 +639,26 @@ XenVbd_HwScsiInitialize(PVOID DeviceExte
     1.4  static ULONG
     1.5  XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
     1.6  {
     1.7 -  PMODE_PARAMETER_HEADER parameter_header;
     1.8 +  PMODE_PARAMETER_HEADER parameter_header = NULL;
     1.9 +  PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
    1.10    PMODE_PARAMETER_BLOCK param_block;
    1.11    PMODE_FORMAT_PAGE format_page;
    1.12 -  ULONG offset;
    1.13 -  UCHAR buffer[256];
    1.14 +  ULONG offset = 0;
    1.15 +  UCHAR buffer[1024];
    1.16    BOOLEAN valid_page = FALSE;
    1.17    BOOLEAN cdb_llbaa;
    1.18    BOOLEAN cdb_dbd;
    1.19    UCHAR cdb_page_code;
    1.20    USHORT cdb_allocation_length;
    1.21 -  PVOID data_buffer;
    1.22 -  //ULONG data_buffer_length;
    1.23  
    1.24    UNREFERENCED_PARAMETER(xvdd);
    1.25  
    1.26 +  RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
    1.27 +  RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
    1.28 +  offset = 0;
    1.29 +
    1.30    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    1.31    
    1.32 -  data_buffer = srb->DataBuffer;
    1.33 -  //cdb = (PCDB)srb->Cdb;
    1.34    switch (srb->Cdb[0])
    1.35    {
    1.36    case SCSIOP_MODE_SENSE:
    1.37 @@ -667,6 +668,15 @@ XenVbd_FillModePage(PXENVBD_DEVICE_DATA 
    1.38      cdb_allocation_length = srb->Cdb[4];
    1.39      KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
    1.40        cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
    1.41 +    parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
    1.42 +    parameter_header->MediumType = 0;
    1.43 +    parameter_header->DeviceSpecificParameter = 0;
    1.44 +    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
    1.45 +    {
    1.46 +      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
    1.47 +      parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
    1.48 +    }
    1.49 +    offset += sizeof(MODE_PARAMETER_HEADER);
    1.50      break;
    1.51    case SCSIOP_MODE_SENSE10:
    1.52      cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
    1.53 @@ -675,31 +685,23 @@ XenVbd_FillModePage(PXENVBD_DEVICE_DATA 
    1.54      cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
    1.55      KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
    1.56        cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
    1.57 +    parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
    1.58 +    parameter_header10->MediumType = 0;
    1.59 +    parameter_header10->DeviceSpecificParameter = 0;
    1.60 +    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
    1.61 +    {
    1.62 +      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
    1.63 +      parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
    1.64 +    }
    1.65 +    offset += sizeof(MODE_PARAMETER_HEADER10);
    1.66      break;
    1.67    default:
    1.68      KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
    1.69      return FALSE;
    1.70 -  }
    1.71 -  offset = 0;
    1.72 -  
    1.73 -  RtlZeroMemory(data_buffer, srb->DataTransferLength);
    1.74 -  RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
    1.75 -
    1.76 -  parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
    1.77 -  parameter_header->MediumType = 0;
    1.78 -  parameter_header->DeviceSpecificParameter = 0;
    1.79 -  parameter_header->BlockDescriptorLength = 0;
    1.80 -  offset += sizeof(MODE_PARAMETER_HEADER);
    1.81 -  
    1.82 -  if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
    1.83 -  {
    1.84 -    KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
    1.85 -    parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT; 
    1.86 -  }
    1.87 +  }  
    1.88    
    1.89    if (!cdb_dbd)
    1.90    {
    1.91 -    parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
    1.92      param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
    1.93      if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
    1.94      {
    1.95 @@ -723,6 +725,16 @@ XenVbd_FillModePage(PXENVBD_DEVICE_DATA 
    1.96      }
    1.97      offset += sizeof(MODE_PARAMETER_BLOCK);
    1.98    }
    1.99 +  switch (srb->Cdb[0])
   1.100 +  {
   1.101 +  case SCSIOP_MODE_SENSE:
   1.102 +    parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
   1.103 +    break;
   1.104 +  case SCSIOP_MODE_SENSE10:
   1.105 +    parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
   1.106 +    parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
   1.107 +    break;
   1.108 +  }
   1.109    if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
   1.110    {
   1.111      valid_page = TRUE;
   1.112 @@ -739,7 +751,42 @@ XenVbd_FillModePage(PXENVBD_DEVICE_DATA 
   1.113      format_page->SoftSectorFormating = TRUE;
   1.114      offset += sizeof(MODE_FORMAT_PAGE);
   1.115    }
   1.116 -  parameter_header->ModeDataLength = (UCHAR)(offset - 1);
   1.117 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
   1.118 +  {
   1.119 +    PMODE_CACHING_PAGE caching_page;
   1.120 +    valid_page = TRUE;
   1.121 +    caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
   1.122 +    caching_page->PageCode = MODE_PAGE_CACHING;
   1.123 +    caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
   1.124 +    // caching_page-> // all zeros is just fine... maybe
   1.125 +    offset += sizeof(MODE_CACHING_PAGE);
   1.126 +  }
   1.127 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
   1.128 +  {
   1.129 +    PUCHAR medium_types_page;
   1.130 +    valid_page = TRUE;
   1.131 +    medium_types_page = &buffer[offset];
   1.132 +    medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
   1.133 +    medium_types_page[1] = 0x06;
   1.134 +    medium_types_page[2] = 0;
   1.135 +    medium_types_page[3] = 0;
   1.136 +    medium_types_page[4] = 0;
   1.137 +    medium_types_page[5] = 0;
   1.138 +    medium_types_page[6] = 0;
   1.139 +    medium_types_page[7] = 0;
   1.140 +    offset += 8;
   1.141 +  }
   1.142 +  switch (srb->Cdb[0])
   1.143 +  {
   1.144 +  case SCSIOP_MODE_SENSE:
   1.145 +    parameter_header->ModeDataLength = (UCHAR)(offset - 1);
   1.146 +    break;
   1.147 +  case SCSIOP_MODE_SENSE10:
   1.148 +    parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
   1.149 +    parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
   1.150 +    break;
   1.151 +  }
   1.152 +
   1.153    if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
   1.154    {
   1.155      srb->SrbStatus = SRB_STATUS_ERROR;
   1.156 @@ -750,7 +797,7 @@ XenVbd_FillModePage(PXENVBD_DEVICE_DATA 
   1.157      srb->SrbStatus = SRB_STATUS_SUCCESS;
   1.158    srb->DataTransferLength = min(srb->DataTransferLength, offset);
   1.159    srb->ScsiStatus = 0;
   1.160 -  memcpy(data_buffer, buffer, srb->DataTransferLength);
   1.161 +  memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
   1.162    
   1.163    //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   1.164  
   1.165 @@ -1073,9 +1120,11 @@ if (xvdd->aligned_buffer_in_use)
   1.166            {
   1.167              PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
   1.168              id->DeviceType = DIRECT_ACCESS_DEVICE;
   1.169 -            id->Versions = 3;
   1.170 +            id->Versions = 4; /* minimum that WHQL says we must support */
   1.171              id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
   1.172 -            id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
   1.173 +            id->HiSupport = 1; /* WHQL test says we should set this */
   1.174 +            //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
   1.175 +            id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
   1.176              id->CommandQueue = 1;
   1.177              memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
   1.178              memcpy(id->ProductId, scsi_disk_model, 16); // product id
   1.179 @@ -1087,23 +1136,35 @@ if (xvdd->aligned_buffer_in_use)
   1.180          {
   1.181            switch (srb->Cdb[2])
   1.182            {
   1.183 -          case 0x00:
   1.184 +          case VPD_SUPPORTED_PAGES: /* list of pages we support */
   1.185              data_buffer[0] = DIRECT_ACCESS_DEVICE;
   1.186 -            data_buffer[1] = 0x00;
   1.187 +            data_buffer[1] = VPD_SUPPORTED_PAGES;
   1.188              data_buffer[2] = 0x00;
   1.189              data_buffer[3] = 2;
   1.190              data_buffer[4] = 0x00;
   1.191              data_buffer[5] = 0x80;
   1.192              data_transfer_length = 6;
   1.193              break;
   1.194 -          case 0x80:
   1.195 +          case VPD_SERIAL_NUMBER: /* serial number */
   1.196              data_buffer[0] = DIRECT_ACCESS_DEVICE;
   1.197 -            data_buffer[1] = 0x80;
   1.198 +            data_buffer[1] = VPD_SERIAL_NUMBER;
   1.199              data_buffer[2] = 0x00;
   1.200              data_buffer[3] = 8;
   1.201              memset(&data_buffer[4], ' ', 8);
   1.202              data_transfer_length = 12;
   1.203              break;
   1.204 +          case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
   1.205 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
   1.206 +            data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
   1.207 +            data_buffer[2] = 0x00;
   1.208 +            data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
   1.209 +            data_buffer[4] = 2; /* ASCII */
   1.210 +            data_buffer[5] = 1; /* VendorId */
   1.211 +            data_buffer[6] = 0;
   1.212 +            data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
   1.213 +            memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
   1.214 +            data_transfer_length = 8 + strlen(xvdd->vectors.path);
   1.215 +            break;
   1.216            default:
   1.217              //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
   1.218              srb->SrbStatus = SRB_STATUS_ERROR;