Ticket #645: os_win32.patch

File os_win32.patch, 19.7 KB (added by kenjiuno, 5 years ago)

Win32 Highpoint support.

  • trunk/smartmontools/os_win32.cpp

    diff --git a/trunk/smartmontools/os_win32.cpp b/trunk/smartmontools/os_win32.cpp
    a b  
    415415
    416416
    417417/////////////////////////////////////////////////////////////////////////////
     418// Highpoint support
    418419
     420#pragma pack(push, 1)
     421
     422typedef struct _TIME_RECORD {
     423  uint32_t        seconds:6;      /* 0 - 59 */
     424  uint32_t        minutes:6;      /* 0 - 59 */
     425  uint32_t        month:4;        /* 1 - 12 */
     426  uint32_t        hours:6;        /* 0 - 59 */
     427  uint32_t        day:5;          /* 1 - 31 */
     428  uint32_t        year:5;         /* 0=2000, 31=2031 */
     429} TIME_RECORD;
     430
     431typedef struct _CONTROLLER_INFO_V2 {
     432  uint8_t ChipType;                    /* chip type */
     433  uint8_t InterruptLevel;              /* IRQ level */
     434  uint8_t NumBuses;                    /* bus count */
     435  uint8_t ChipFlags;
     436
     437  uint8_t szProductID[36];/* product name */
     438  uint8_t szVendorID[36]; /* vender name */
     439
     440  uint32_t GroupId;                    /* low 32bit of vbus pointer the controller belongs
     441                                        * the master controller has CHIP_MASTER flag set*/
     442  uint8_t  pci_tree;
     443  uint8_t  pci_bus;
     444  uint8_t  pci_device;
     445  uint8_t  pci_function;
     446
     447  uint32_t ExFlags;
     448} CONTROLLER_INFO_V2, *PCONTROLLER_INFO_V2;
     449
     450typedef struct _HPT_ARRAY_INFO_V4 {
     451  uint8_t      Name[16];/* array name */
     452  uint8_t      Description[64];        /* array description */
     453  uint8_t      CreateManager[16];      /* who created it */
     454  TIME_RECORD CreateTime;             /* when created it */
     455
     456  uint8_t      ArrayType;              /* array type */
     457  uint8_t      BlockSizeShift;         /* stripe size */
     458  uint8_t      nDisk;                  /* member count: Number of ID in Members[] */
     459  uint8_t      SubArrayType;
     460
     461  uint32_t     Flags;                  /* working flags, see ARRAY_FLAG_XXX */
     462
     463  uint32_t     RebuildingProgress;
     464  uint64_t     RebuiltSectors; /* rebuilding point (LBA) for single member */
     465
     466  uint32_t    TransformSource;
     467  uint32_t    TransformTarget;   /* destination device ID */
     468  uint32_t     TransformingProgress;
     469  uint32_t     Signature;          /* persistent identification*/
     470  uint8_t       SectorSizeShift; /*sector size = 512B<<SectorSizeShift*/
     471  uint8_t       reserved2[7];
     472  uint64_t     Critical_Members;
     473  uint32_t     Members[64];  /* member array/disks */
     474} HPT_ARRAY_INFO_V4, *PHPT_ARRAY_INFO_V4;
     475
     476typedef struct _IDENTIFY_DATA2 {
     477  uint16_t GeneralConfiguration;
     478  uint16_t NumberOfCylinders;
     479  uint16_t Reserved1;
     480  uint16_t NumberOfHeads;
     481  uint16_t UnformattedBytesPerTrack;
     482  uint16_t UnformattedBytesPerSector;
     483  uint8_t  SasAddress[8];
     484  uint16_t SerialNumber[10];
     485  uint16_t BufferType;
     486  uint16_t BufferSectorSize;
     487  uint16_t NumberOfEccBytes;
     488  uint16_t FirmwareRevision[4];
     489  uint16_t ModelNumber[20];
     490  uint8_t  MaximumBlockTransfer;
     491  uint8_t  VendorUnique2;
     492  uint16_t DoubleWordIo;
     493  uint16_t Capabilities;
     494  uint16_t Reserved2;
     495  uint8_t  VendorUnique3;
     496  uint8_t  PioCycleTimingMode;
     497  uint8_t  VendorUnique4;
     498  uint8_t  DmaCycleTimingMode;
     499  uint16_t TranslationFieldsValid;
     500  uint16_t NumberOfCurrentCylinders;
     501  uint16_t NumberOfCurrentHeads;
     502  uint16_t CurrentSectorsPerTrack;
     503  uint32_t CurrentSectorCapacity;
     504  uint16_t CurrentMultiSectorSetting;
     505  uint32_t UserAddressableSectors;
     506  uint8_t  SingleWordDMASupport;
     507  uint8_t  SingleWordDMAActive;
     508  uint8_t  MultiWordDMASupport;
     509  uint8_t  MultiWordDMAActive;
     510  uint8_t  AdvancedPIOModes;
     511  uint8_t  Reserved4;
     512  uint16_t MinimumMWXferCycleTime;
     513  uint16_t RecommendedMWXferCycleTime;
     514  uint16_t MinimumPIOCycleTime;
     515  uint16_t MinimumPIOCycleTimeIORDY;
     516  uint16_t Reserved5[2];
     517  uint16_t ReleaseTimeOverlapped;
     518  uint16_t ReleaseTimeServiceCommand;
     519  uint16_t MajorRevision;
     520  uint16_t MinorRevision;
     521} __attribute__((packed)) IDENTIFY_DATA2, *PIDENTIFY_DATA2;
     522
     523typedef struct _DEVICE_INFO_V2 {
     524  uint8_t   ControllerId;          /* controller id */
     525  uint8_t   PathId;                /* bus */
     526  uint8_t   TargetId;              /* id */
     527  uint8_t   DeviceModeSetting;     /* Current Data Transfer mode: 0-4 PIO 0-4 */
     528                                   /* 5-7 MW DMA0-2, 8-13 UDMA0-5             */
     529  uint8_t   DeviceType;            /* device type */
     530  uint8_t   UsableMode;            /* highest usable mode */
     531
     532#ifdef __BIG_ENDIAN_BITFIELD
     533  uint8_t   NCQEnabled: 1;
     534  uint8_t   NCQSupported: 1;
     535  uint8_t   TCQEnabled: 1;
     536  uint8_t   TCQSupported: 1;
     537  uint8_t   WriteCacheEnabled: 1;
     538  uint8_t   WriteCacheSupported: 1;
     539  uint8_t   ReadAheadEnabled: 1;
     540  uint8_t   ReadAheadSupported: 1;
     541  uint8_t   reserved6: 6;
     542  uint8_t   SpinUpMode: 2;
     543#else
     544  uint8_t   ReadAheadSupported: 1;
     545  uint8_t   ReadAheadEnabled: 1;
     546  uint8_t   WriteCacheSupported: 1;
     547  uint8_t   WriteCacheEnabled: 1;
     548  uint8_t   TCQSupported: 1;
     549  uint8_t   TCQEnabled: 1;
     550  uint8_t   NCQSupported: 1;
     551  uint8_t   NCQEnabled: 1;
     552  uint8_t   SpinUpMode: 2;
     553  uint8_t   reserved6: 6;
     554#endif
     555
     556  uint32_t     Flags;              /* working flags, see DEVICE_FLAG_XXX */
     557
     558  IDENTIFY_DATA2 IdentifyData;    /* Identify Data of this device */
     559
     560  uint64_t TotalFree;
     561  uint64_t MaxFree;
     562  uint64_t BadSectors;
     563  uint32_t ParentArrays[8];
     564
     565  //#define DEVICE_FLAG_SATA            0x00000010 /* SATA or SAS device */
     566  //#define DEVICE_FLAG_ON_PM_PORT      0x00000020 /* PM port */
     567  //#define DEVICE_FLAG_SAS             0x00000040 /* SAS device */
     568  // #define DEVICE_FLAG_SSD                    0x00000100 /* SSD device */   ////////////////////////////////////////
     569
     570  bool is_sata() const { return 0 != (Flags & 0x00000010); }
     571  bool is_sas() const { return 0 != (Flags & 0x00000040); }
     572  bool is_ssd() const { return 0 != (Flags & 0x00000100); }
     573}
     574__attribute__((packed)) DEVICE_INFO_V2, *PDEVICE_INFO_V2, DEVICE_INFO_V3, *PDEVICE_INFO_V3;
     575
     576typedef struct _LOGICAL_DEVICE_INFO_V4 {
     577  uint32_t    dwSize;
     578  uint8_t      revision;
     579  uint8_t      reserved[7];
     580
     581  uint8_t      Type;                   /* LDT_ARRAY or LDT_DEVICE */
     582  uint8_t      CachePolicy;            /* refer to CACHE_POLICY_xxx */
     583  uint8_t      VBusId;                 /* vbus sequence in vbus_list */
     584  uint8_t      TargetId;               /* OS target id. Value 0xFF is invalid */
     585                                       /* OS disk name: HPT DISK $VBusId_$TargetId */
     586  uint64_t     Capacity;               /* array capacity */
     587  uint32_t    ParentArray;            /* for physical device, don't use this field.
     588                                       * use ParentArrays field in DEVICE_INFO_V2 instead.
     589                                       */
     590  uint32_t     TotalIOs;
     591  uint32_t     TobalMBs;
     592  uint32_t     IOPerSec;
     593  uint32_t     MBPerSec;
     594
     595  union {
     596    HPT_ARRAY_INFO_V4 array;
     597    DEVICE_INFO_V3 device;
     598  } __attribute__((packed)) u;
     599}
     600__attribute__((packed)) LOGICAL_DEVICE_INFO_V4, *PLOGICAL_DEVICE_INFO_V4;
     601
     602typedef struct _IDE_PASS_THROUGH_HEADER {
     603  uint32_t idDisk;             /* disk ID */
     604  uint8_t     bFeaturesReg;     /* feature register */
     605  uint8_t     bSectorCountReg;  /* IDE sector count register. */
     606  uint8_t     bLbaLowReg;       /* IDE LBA low value. */
     607  uint8_t     bLbaMidReg;       /* IDE LBA mid register. */
     608  uint8_t     bLbaHighReg;      /* IDE LBA high value. */
     609  uint8_t     bDriveHeadReg;    /* IDE drive/head register. */
     610  uint8_t     bCommandReg;      /* Actual IDE command. Checked for validity by driver. */
     611  uint8_t     nSectors;         /* data size in sectors, if the command has data transfer */
     612  uint8_t     protocol;         /* IO_COMMAND_(READ,WRITE) or zero for non-DATA */
     613  uint8_t     reserve[3];
     614  #define IDE_PASS_THROUGH_buffer(p) ((uint8_t *)(p) + sizeof(IDE_PASS_THROUGH_HEADER))
     615  /* uint8_t     DataBuffer[0]; */
     616
     617  //#define IO_COMMAND_READ     1
     618  //#define IO_COMMAND_WRITE    2
     619  void setNone() { protocol = 0; }
     620  void setRead() { protocol = 1; }
     621  void setWrite() { protocol = 2; }
     622}
     623IDE_PASS_THROUGH_HEADER, *PIDE_PASS_THROUGH_HEADER;
     624
     625typedef struct _HPT_SCSI_PASSTHROUGH_IN {
     626  uint32_t idDisk;
     627  uint8_t   protocol;
     628  uint8_t   reserve1;
     629  uint8_t   reserve2;
     630  uint8_t   cdbLength;
     631  uint8_t   cdb[16];
     632  uint32_t  dataLength;
     633  /* data follows, if any */
     634
     635  //#define IO_COMMAND_READ     1
     636  //#define IO_COMMAND_WRITE    2
     637  void setNone() { protocol = 0; }
     638  void setRead() { protocol = 1; }
     639  void setWrite() { protocol = 2; }
     640}
     641HPT_SCSI_PASSTHROUGH_IN, *PHPT_SCSI_PASSTHROUGH_IN;
     642
     643typedef struct _HPT_SCSI_PASSTHROUGH_OUT {
     644  uint8_t   scsiStatus;
     645  uint8_t   reserve1;
     646  uint8_t   reserve2;
     647  uint8_t   reserve3;
     648  uint32_t  dataLength;
     649  /* data/sense follows if any */
     650}
     651HPT_SCSI_PASSTHROUGH_OUT, *PHPT_SCSI_PASSTHROUGH_OUT;
     652
     653#pragma pack(pop)
     654
     655class hptdev
     656{
     657public:
     658  HMODULE hlib;
     659 
     660  hptdev() {
     661    hlib = NULL;
     662  }
     663  ~hptdev() {
     664    if (hlib) {
     665      FreeLibrary(hlib);
     666      hlib = NULL;
     667    }
     668  }
     669 
     670  uint32_t get_version() {
     671    if (hlib == NULL)
     672      hlib = LoadLibrary("hptdev.dll");
     673    if (hlib) {
     674      typedef uint32_t (* func_t)(void);
     675      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_get_version");
     676      if (pfn != NULL) {
     677        return pfn();
     678      }
     679    }
     680    return 0;
     681  }
     682 
     683  int get_controller_count() {
     684    if (hlib) {
     685      typedef int (* func_t)(void);
     686      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_get_controller_count");
     687      if (pfn != NULL) {
     688        return pfn();
     689      }
     690    }
     691    return 0;
     692  }
     693 
     694  int get_physical_devices(uint32_t *pIds, int nMaxCount) {
     695    if (hlib) {
     696      typedef int (* func_t)(uint32_t *pIds, int nMaxCount);
     697      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_get_physical_devices");
     698      if (pfn != NULL) {
     699        return pfn(pIds, nMaxCount);
     700      }
     701    }
     702    return 0;
     703  }
     704 
     705  int get_controller_info_v2(int id, PCONTROLLER_INFO_V2 pInfo) {
     706    if (hlib) {
     707      typedef int (* func_t)(int id, PCONTROLLER_INFO_V2 pInfo);
     708      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_get_controller_info_v2");
     709      if (pfn != NULL) {
     710        return pfn(id, pInfo);
     711      }
     712    }
     713    return -1;
     714  }
     715 
     716  int get_device_info_v4(uint32_t id, PLOGICAL_DEVICE_INFO_V4 pInfo) {
     717    if (hlib) {
     718      typedef int (* func_t)(uint32_t id, PLOGICAL_DEVICE_INFO_V4 pInfo);
     719      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_get_device_info_v4");
     720      if (pfn != NULL) {
     721        return pfn(id, pInfo);
     722      }
     723    }
     724    return -1;
     725  }
     726
     727  int ide_pass_through(PIDE_PASS_THROUGH_HEADER p) {
     728    if (hlib) {
     729      typedef int (* func_t)(PIDE_PASS_THROUGH_HEADER p);
     730      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_ide_pass_through");
     731      if (pfn != NULL) {
     732        return pfn(p);
     733      }
     734    }
     735    return -1;
     736  }
     737 
     738  int scsi_passthrough(PHPT_SCSI_PASSTHROUGH_IN in, uint32_t insize,
     739    PHPT_SCSI_PASSTHROUGH_OUT out, uint32_t outsize
     740  ) {
     741    if (hlib) {
     742      typedef int (* func_t)(PHPT_SCSI_PASSTHROUGH_IN in, uint32_t insize,
     743        PHPT_SCSI_PASSTHROUGH_OUT out, uint32_t outsize);
     744      func_t pfn = (func_t)GetProcAddress(hlib, "hpt_scsi_passthrough");
     745      if (pfn != NULL) {
     746        return pfn(in, insize, out, outsize);
     747      }
     748    }
     749    return -1;
     750  }
     751 
     752};
     753
     754static hptdev hptIf;
     755
     756class win_hpt_ata_device
     757: virtual public /*extends*/ smart_device,
     758  virtual public /*implements*/ ata_device
     759{
     760protected:
     761  int idDisk;
     762 
     763public:
     764  win_hpt_ata_device(smart_interface * intf, const char * dev_name,
     765    const char * req_type)
     766  : smart_device(intf, dev_name, "hpt-ata", req_type)
     767  {
     768    if (sscanf(dev_name, "/dev/hpt%u", &idDisk) == 1) {
     769      // ok
     770    }
     771    else if (sscanf(dev_name, "hpt%u", &idDisk) == 1) {
     772      // ok
     773    }
     774    else idDisk = -1; // invalid
     775  }
     776
     777  virtual bool open() { return is_open(); }
     778
     779  virtual bool close() { return true; }
     780
     781  virtual bool is_open() const { return hptIf.get_version() != 0 && idDisk >= 0; }
     782 
     783  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) {
     784    // [IDE_PASS_THROUGH_HEADER in]
     785    // +[in buff] if write
     786    // +[IDE_PASS_THROUGH_HEADER out]
     787    // +[out buff] if read
     788   
     789    const bool readdata = in.direction == ata_cmd_in::data_in;
     790    const bool writedata = in.direction == ata_cmd_in::data_out;
     791    const size_t cbInDat = writedata ? in.size : 0;
     792    const size_t cbInAll = sizeof(IDE_PASS_THROUGH_HEADER) +cbInDat;
     793    const size_t cbOutDat = readdata ? in.size : 0;
     794    const size_t cbOutAll = sizeof(IDE_PASS_THROUGH_HEADER) +cbOutDat;
     795    uint8_t *blk = reinterpret_cast<uint8_t *>(malloc(cbInAll +cbOutAll));
     796    if (!blk) {
     797      return set_err(ENOMEM, "malloc failure");
     798    }
     799    memset(blk, -1, cbInAll +cbOutAll);
     800   
     801    PIDE_PASS_THROUGH_HEADER thruIn = reinterpret_cast<PIDE_PASS_THROUGH_HEADER>(blk);
     802    void *datIn = blk +sizeof(IDE_PASS_THROUGH_HEADER);
     803    PIDE_PASS_THROUGH_HEADER thruOut = reinterpret_cast<PIDE_PASS_THROUGH_HEADER>(blk +cbInAll);
     804    void *datOut = blk +cbInAll +sizeof(IDE_PASS_THROUGH_HEADER);
     805   
     806    thruIn->idDisk = idDisk;
     807    thruIn->bCommandReg = in.in_regs.command;
     808    thruIn->bFeaturesReg = in.in_regs.features;
     809    thruIn->bLbaLowReg = in.in_regs.lba_low;
     810    thruIn->bLbaMidReg = in.in_regs.lba_mid;
     811    thruIn->bLbaHighReg = in.in_regs.lba_high;
     812    thruIn->bDriveHeadReg = in.in_regs.device;
     813    thruIn->bSectorCountReg = in.in_regs.sector_count;
     814    if (false) { }
     815    else if (readdata) thruIn->setRead();
     816    else if (writedata) thruIn->setWrite();
     817    else thruIn->setNone();
     818    thruIn->nSectors = in.in_regs.sector_count;
     819   
     820    memcpy(datIn, in.buffer, cbInDat);
     821   
     822    bool ok = false;
     823    int ret = hptIf.ide_pass_through(thruIn);
     824    if (ret == 0) {
     825      ata_out_regs_48bit &r = out.out_regs;
     826      r.error           = thruOut->bFeaturesReg;
     827      r.sector_count_16 = thruOut->bSectorCountReg;
     828      r.lba_low_16      = thruOut->bLbaLowReg;
     829      r.lba_mid_16      = thruOut->bLbaMidReg;
     830      r.lba_high_16     = thruOut->bLbaHighReg;
     831      r.device          = thruOut->bDriveHeadReg;
     832      r.status          = thruOut->bCommandReg;
     833      memcpy(in.buffer, datOut, cbOutDat);
     834      ok = true;
     835    }
     836    else {
     837      set_err(EIO);
     838    }
     839    free(blk);
     840    return ok;
     841  }
     842};
     843
     844class win_hpt_scsi_device
     845: virtual public /*extends*/ smart_device,
     846  virtual public /*extends*/ scsi_device
     847{
     848protected:
     849  int idDisk;
     850 
     851public:
     852  win_hpt_scsi_device(smart_interface * intf, const char * dev_name,
     853    const char * req_type)
     854  : smart_device(intf, dev_name, "hpt-scsi", req_type)
     855  {
     856    if (sscanf(dev_name, "/dev/hpt%u", &idDisk) == 1) {
     857      // ok
     858    }
     859    else if (sscanf(dev_name, "hpt%u", &idDisk) == 1) {
     860      // ok
     861    }
     862    else idDisk = -1; // invalid
     863  }
     864 
     865  virtual bool open() { return is_open(); }
     866
     867  virtual bool close() { return true; }
     868
     869  virtual bool is_open() const { return hptIf.get_version() != 0 && idDisk >= 0; }
     870 
     871  virtual bool scsi_pass_through(struct scsi_cmnd_io *iop) {
     872    const bool readdata = iop->dxfer_dir == DXFER_FROM_DEVICE;
     873    const bool writedata = iop->dxfer_dir == DXFER_TO_DEVICE;
     874   
     875    const size_t cbInDat = writedata?iop->dxfer_len:0;
     876    const size_t cbInAll = sizeof(HPT_SCSI_PASSTHROUGH_IN) +cbInDat;
     877    const size_t cbOutDat = readdata?iop->dxfer_len:0;
     878    const size_t cbOutAll = sizeof(HPT_SCSI_PASSTHROUGH_OUT) +cbOutDat;
     879   
     880    PHPT_SCSI_PASSTHROUGH_IN thruIn = reinterpret_cast<PHPT_SCSI_PASSTHROUGH_IN>(malloc(cbInAll));
     881    PHPT_SCSI_PASSTHROUGH_OUT thruOut = reinterpret_cast<PHPT_SCSI_PASSTHROUGH_OUT>(malloc(cbOutAll));
     882     
     883    if (!thruIn || !thruOut) {
     884      if (thruIn) free(thruIn);
     885      if (thruOut) free(thruOut);
     886      return set_err(ENOMEM, "malloc failure");
     887    }
     888   
     889    memset(thruIn, -1, cbInAll);
     890    memset(thruOut, -1, cbOutAll);
     891   
     892    thruIn->idDisk = idDisk;
     893    thruIn->setNone();
     894    if (readdata) thruIn->setRead();
     895    if (writedata) thruIn->setWrite();
     896    thruIn->cdbLength = iop->cmnd_len;
     897    memcpy(thruIn->cdb, iop->cmnd, iop->cmnd_len);
     898    thruIn->dataLength = iop->dxfer_len;
     899   
     900    memcpy(&thruIn[1], iop->dxferp, cbInDat);
     901   
     902    bool ok = false;
     903    int ret = hptIf.scsi_passthrough(thruIn, cbInAll, thruOut, cbOutAll);
     904    if (ret == 0) {
     905      memcpy(iop->dxferp, &thruOut[1], cbOutDat);
     906     
     907      iop->scsi_status = thruOut->scsiStatus;
     908      iop->resp_sense_len = thruOut->dataLength;
     909      iop->resid = 0;
     910      ok = true;
     911    }
     912    else {
     913      set_err(EIO);
     914    }
     915   
     916    free(thruIn);
     917    free(thruOut);
     918    return ok;
     919  }
     920};
     921
     922/////////////////////////////////////////////////////////////////////////////
     923
    419924class csmi_device
    420925: virtual public /*extends*/ smart_device
    421926{
     
    9281433    return 0;
    9291434  }
    9301435
     1436  // Highpoint ?
     1437  if (stricmp(type, "hpt-ata") == 0)
     1438    return new win_hpt_ata_device(this, name, "hpt-ata");
     1439  if (stricmp(type, "hpt-scsi") == 0)
     1440    return new win_hpt_scsi_device(this, name, "hpt-scsi");
     1441
    9311442  return 0;
    9321443}
    9331444
     
    9491460  if (str_starts_with(testname, "csmi"))
    9501461    return new win_csmi_device(this, name, "");
    9511462
     1463  if (str_starts_with(testname, "hpt")) {
     1464    if (hptIf.get_version() != 0) {
     1465      LOGICAL_DEVICE_INFO_V4 info;
     1466      if (hptIf.get_device_info_v4(atoi(testname +3), &info) != 0) {
     1467        // err
     1468      }
     1469      else if (!info.u.device.is_sata() && !info.u.device.is_sas()) {
     1470        // no hdd
     1471      }
     1472      else {
     1473        return info.u.device.is_sas()
     1474          ? static_cast<smart_device *>(new win_hpt_scsi_device(this, name, "hpt-scsi"))
     1475          : static_cast<smart_device *>(new win_hpt_ata_device(this, name, "hpt-ata"))
     1476          ;
     1477      }
     1478    }
     1479    return 0;
     1480  }
     1481
    9521482  int phydrive = -1;
    9531483  win_dev_type type = get_dev_type(name, phydrive);
    9541484
     
    10071537  }
    10081538
    10091539  // Set valid types
    1010   bool ata, scsi, sat, usb, csmi;
     1540  bool ata, scsi, sat, usb, csmi, hpt;
    10111541  if (!type) {
    1012     ata = scsi = usb = sat = csmi = true;
     1542    ata = scsi = usb = sat = csmi = hpt = true;
    10131543  }
    10141544  else {
    1015     ata = scsi = usb = sat = csmi = false;
     1545    ata = scsi = usb = sat = csmi = hpt = false;
    10161546    if (!strcmp(type, "ata"))
    10171547      ata = true;
    10181548    else if (!strcmp(type, "scsi"))
     
    10231553      usb = true;
    10241554    else if (!strcmp(type, "csmi"))
    10251555      csmi = true;
     1556    else if (!strcmp(type, "hpt"))
     1557      hpt = true;
    10261558    else {
    10271559      set_err(EINVAL,
    1028               "Invalid type '%s', valid arguments are: ata[,pd], scsi[,pd], sat[,pd], usb[,pd], csmi, pd",
     1560              "Invalid type '%s', valid arguments are: ata[,pd], scsi[,pd], sat[,pd], usb[,pd], csmi, hpt, pd",
    10291561              type);
    10301562      return false;
    10311563    }
     
    11391671      }
    11401672    }
    11411673  }
     1674  if (hpt) {
     1675    // Scan hpt devices
     1676    if (hptIf.get_version() != 0) {
     1677      const int maxids = 100;
     1678      uint32_t ids[maxids];
     1679      int nCtrl = hptIf.get_controller_count();
     1680      int nPhys = hptIf.get_physical_devices(ids, maxids);
     1681      for (int iC = 0; iC < nCtrl; iC++) {
     1682        CONTROLLER_INFO_V2 conInfo;
     1683        if (hptIf.get_controller_info_v2(iC, &conInfo) != 0)
     1684          continue;
     1685        for (int iP = 0; iP < nPhys; iP++) {
     1686          LOGICAL_DEVICE_INFO_V4 info;
     1687          if (hptIf.get_device_info_v4(ids[iP], &info) != 0)
     1688            continue;
     1689          if (info.u.device.ControllerId != iC)
     1690            continue;
     1691          if (!info.u.device.is_sata() && !info.u.device.is_sas())
     1692            continue;
     1693         
     1694          snprintf(name, sizeof(name)-1, "/dev/hpt%d"
     1695            , ids[iP]
     1696            );
     1697          devlist.push_back( info.u.device.is_sas()
     1698            ? static_cast<smart_device *>(new win_hpt_scsi_device(this, name, "hpt-scsi"))
     1699            : static_cast<smart_device *>(new win_hpt_ata_device(this, name, "hpt-ata"))
     1700            );
     1701        }
     1702      }
     1703    }
     1704  }
    11421705  return true;
    11431706}
    11441707