]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Real harddrive automatic IDE identity read and use.
authorToni Wilen <twilen@winuae.net>
Sat, 3 Feb 2018 09:17:23 +0000 (11:17 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 3 Feb 2018 09:17:23 +0000 (11:17 +0200)
cfgfile.cpp
ide.cpp
include/filesys.h
include/options.h
od-win32/hardfile_win32.cpp
od-win32/resources/resource.h
od-win32/resources/winuae.rc
od-win32/win32gui.cpp

index 905f124cbde6db8164aff457197d6ec73c88886b..9e80b444fe1d272e5e2e8dde5ad03b9990eb3a86 100644 (file)
@@ -1096,6 +1096,10 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f)
                                _tcscat(tmp, _T(",lock"));
                                _tcscat(tmp3, _T(",lock"));
                        }
+                       if (ci->loadidentity) {
+                               _tcscat(tmp, _T(",identity"));
+                               _tcscat(tmp3, _T(",identity"));
+                       }
 
                        if (ci->type == UAEDEV_HDF)
                                cfgfile_write_str (f, _T("hardfile2"), tmp);
@@ -4585,7 +4589,9 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHA
 
                        if (cfgfile_option_find(tmpp2, _T("lock")))
                                uci.lock = true;
-                                       
+                       if (cfgfile_option_find(tmpp2, _T("identity")))
+                               uci.loadidentity = true;
+
                        if (cfgfile_option_find(tmpp2, _T("SCSI2")))
                                uci.unit_feature_level = HD_LEVEL_SCSI_2;
                        else if (cfgfile_option_find(tmpp2, _T("SCSI1")))
diff --git a/ide.cpp b/ide.cpp
index f65f7a4fec6e748f492a9f9f89a69e0618761482..defd668efb964d348247f7eb406e793c75c9026c 100644 (file)
--- a/ide.cpp
+++ b/ide.cpp
@@ -448,6 +448,7 @@ static void ide_identity_buffer(struct ide_hdf *ide)
        TCHAR tmp[100];
        bool atapi = ide->atapi;
        bool cf = ide->media_type > 0;
+       bool real = false;
        int v;
 
        memset(ide->secbuf, 0, 512);
@@ -461,6 +462,14 @@ static void ide_identity_buffer(struct ide_hdf *ide)
                        ata_byteswapidentity(ide->secbuf);
                }
 
+       } else if (ide->hdhfd.hfd.ci.loadidentity && (ide->hdhfd.hfd.identity[0] || ide->hdhfd.hfd.identity[1])) {
+
+               memcpy(ide->secbuf, ide->hdhfd.hfd.identity, 512);
+               if (ide->byteswap) {
+                       ata_byteswapidentity(ide->secbuf);
+               }
+               real = true;
+
        } else {
 
                pw (ide, 0, atapi ? 0x85c0 : (cf ? 0x848a : (1 << 6)));
@@ -527,8 +536,10 @@ static void ide_identity_buffer(struct ide_hdf *ide)
                ata_get_identity(ide->hdhfd.hfd.geometry, ide->secbuf, false);
        }
 
-       v = ide->multiple_mode;
-       pwor(ide, 59, v > 0 ? 0x100 : 0);
+       if (!real) {
+               v = ide->multiple_mode;
+               pwor(ide, 59, v > 0 ? 0x100 : 0);
+       }
        if (!atapi && cf) {
                pw(ide, 0, 0x848a);
        } else if (!atapi && !cf) {
index 15d3db67b5e416a435b101d2f2d61d4017d3c597..eb0b4cea64943657d46e5de482a3943ca56bc4e3 100644 (file)
@@ -70,6 +70,7 @@ struct hardfiledata {
        struct hdf_cache bcache[MAX_HDF_CACHE_BLOCKS];
        uae_u8 scsi_sense[MAX_SCSI_SENSE];
        uae_u8 sector_buffer[512];
+       uae_u8 identity[512];
 
        struct uaedev_config_info delayedci;
        int reinsertdelay;
@@ -133,8 +134,7 @@ extern int hdf_read_rdb (struct hardfiledata *hfd, void *buffer, uae_u64 offset,
 extern int hdf_read(struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
 extern int hdf_write(struct hardfiledata *hfd, void *buffer, uae_u64 offset, int len);
 extern int hdf_getnumharddrives (void);
-extern TCHAR *hdf_getnameharddrive (int index, int flags, int *sectorsize, int *dangerousdrive);
-extern int isspecialdrive(const TCHAR *name);
+extern TCHAR *hdf_getnameharddrive (int index, int flags, int *sectorsize, int *dangerousdrive, uae_u32 *outflags);
 extern int get_native_path(TrapContext *ctx, uae_u32 lock, TCHAR *out);
 extern void hardfile_do_disk_change (struct uaedev_config_data *uci, bool insert);
 extern void hardfile_send_disk_change (struct hardfiledata *hfd, bool insert);
index a194a0f2a43661bcc00081bd25261496cbdb70f6..cd785f49e386399fa96955fcd4327df6e39373f1 100644 (file)
@@ -191,6 +191,7 @@ struct uaedev_config_info {
        TCHAR rootdir[MAX_DPATH];
        bool readonly;
        bool lock;
+       bool loadidentity;
        int bootpri;
        TCHAR filesys[MAX_DPATH];
        TCHAR geometry[MAX_DPATH];
index 9cc5d19e19fce212d7e4a32e50eddf8a24f58031..8c61066920453e2dd6501b2da00ad4006fdb817b 100644 (file)
@@ -57,6 +57,7 @@ struct uae_driveinfo {
        TCHAR device_name[1024];
        TCHAR device_path[1024];
        TCHAR device_full_path[2048];
+       uae_u8 identity[512];
        uae_u64 size;
        uae_u64 offset;
        int bytespersector;
@@ -67,6 +68,8 @@ struct uae_driveinfo {
        int readonly;
        int cylinders, sectors, heads;
        int BusType;
+       uae_u16 usb_vid, usb_pid;
+       int devicetype;
 
 };
 
@@ -534,6 +537,7 @@ static void queryataidentity(HANDLE h)
 #endif
 
 static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_driveinfo *udi, int ignoreduplicates);
+static bool getstorageinfo(uae_driveinfo *udi, STORAGE_DEVICE_NUMBER sdnp);
 
 #if 0
 typedef enum _STORAGE_PROTOCOL_TYPE { 
@@ -607,7 +611,7 @@ static void bintotextpart(TCHAR *out, uae_u8 *data, int size)
        out[size] = 0;
 }
 
-static void bintotextline(TCHAR *out, uae_u8 *data, int size)
+static TCHAR *bintotextline(TCHAR *out, uae_u8 *data, int size)
 {
        TCHAR tmp2[MAX_DPATH];
        int w = 32;
@@ -630,6 +634,64 @@ static void bintotextline(TCHAR *out, uae_u8 *data, int size)
                _tcscat (out, tmp2);
                _tcscat (out, _T("\r\n"));
        }
+       return out + _tcslen(out);
+}
+
+static int chsdialogactive, chs_secs, chs_cyls, chs_heads;
+static TCHAR *parse_identity(uae_u8 *data, struct ini_data *ini, TCHAR *s)
+{
+       uae_u16 v;
+
+       v = (data[1 * 2 + 0] << 8) | (data[1 * 2 + 1] << 0);
+       chs_cyls = v;
+       if (ini)
+               ini_addnewval(ini, _T("IDENTITY"), _T("Geometry_Cylinders"), v);
+       if (s) {
+               _stprintf(s, _T("Cylinders: %04X (%u)\r\n"), v, v);
+               s += _tcslen(s);
+       }
+       v = (data[3 * 2 + 0] << 8) | (data[3 * 2 + 1] << 0);
+       chs_heads = v;
+       if (ini)
+               ini_addnewval(ini, _T("IDENTITY"), _T("Geometry_Heads"), v);
+       if (s) {
+               _stprintf(s, _T("Heads: %04X (%u)\r\n"), v, v);
+               s += _tcslen(s);
+       }
+       v = (data[6 * 2 + 0] << 8) | (data[6 * 2 + 1] << 0);
+       chs_secs = v;
+       if (ini)
+               ini_addnewval(ini, _T("IDENTITY"), _T("Geometry_Surfaces"), v);
+       if (s) {
+               _stprintf(s, _T("Surfaces: %04X (%u)\r\n"), v, v);
+               s += _tcslen(s);
+       }
+
+       v = (data[49 * 2 + 0] << 8) | (data[49 * 2 + 1] << 0);
+       if (v & (1 << 9)) {
+               // LBA supported
+               uae_u32 lba = (data[60 * 2 + 0] << 24) | (data[60 * 2 + 1] << 16) | (data[61 * 2 + 0] << 8) | (data[61 * 2 + 1] << 0);
+               if (ini)
+                       ini_addnewval(ini, _T("IDENTITY"), _T("LBA"), lba);
+               if (s) {
+                       _stprintf(s, _T("LBA: %08X (%u)\r\n"), lba, lba);
+                       s += _tcslen(s);
+               }
+       }
+       v = (data[83 * 2 + 0] << 8) | (data[83 * 2 + 1] << 0);
+       if ((v & 0xc000) == 0x4000 && (v & (1 << 10))) {
+               // LBA48 supported
+               uae_u64 lba = (data[100 * 2 + 0] << 24) | (data[100 * 2 + 1] << 16) | (data[101 * 2 + 0] << 8) | (data[101 * 2 + 1] << 0);
+               lba <<= 32;
+               lba |= (data[102 * 2 + 0] << 24) | (data[102 * 2 + 1] << 16) | (data[103 * 2 + 0] << 8) | (data[103 * 2 + 1] << 0);
+               if (ini)
+                       ini_addnewval64(ini, _T("IDENTITY"), _T("LBA48"), lba);
+               if (s) {
+                       _stprintf(s, _T("LBA48: %012llX (%llu)\r\n"), lba, lba);
+                       s += _tcslen(s);
+               }
+       }
+       return s;
 }
 
 void gui_infotextbox(HWND hDlg, const TCHAR *text);
@@ -663,21 +725,66 @@ static bool hd_get_meta_ata(HWND hDlg, HANDLE h, bool atapi, uae_u8 *datap)
 
 #define INQUIRY_LEN 240
 
-static const uae_u8 realtek_inquiry_0x83[] = { 0x12, 0x01, 0x83, 0, 0xf0, 0 };
-static const uae_u8 realtek_read[] = { 0xf0, 0x0d, 0xfa, 0x00, 0x02, 0x00 };
-
-static bool hd_get_meta_hack(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 *inq)
+static bool hd_meta_hack_jmicron(HANDLE h, uae_u8 *data, uae_u8 *inq)
 {
        uae_u8 cmd[16];
 
-       memset(data, 0, 512);
-       memcpy(cmd, realtek_inquiry_0x83, sizeof(realtek_inquiry_0x83));
-       if (do_scsi_in(h, cmd, 6, data, 0xf0) < 0)
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0xdf;
+       cmd[1] = 0x10;
+       cmd[4] = 1;
+       cmd[6] = 0x72;
+       cmd[7] = 0x0f;
+       cmd[11] = 0xfd;
+       if (do_scsi_in(h, cmd, 12, data + 32, 1) < 0) {
+               memset(data, 0, 512);
                return false;
-       if (memcmp(data + 20, "realtek\0", 8)) {
+       }
+       if (!(data[32] & 0x40) && !(data[32] & 0x04)) {
                memset(data, 0, 512);
                return false;
        }
+#if 0
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0xdf;
+       cmd[1] = 0x10;
+       cmd[4] = 16;
+       cmd[6] = 0x80;
+       cmd[11] = 0xfd;
+       if (do_scsi_in(h, cmd, 12, data, 16) < 0) {
+               memset(data, 0, 512);
+               return false;
+       }
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0xdf;
+       cmd[1] = 0x10;
+       cmd[4] = 16;
+       cmd[6] = 0x90;
+       cmd[11] = 0xfd;
+       if (do_scsi_in(h, cmd, 12, data + 16, 16) < 0) {
+               memset(data, 0, 512);
+               return false;
+       }
+#endif 
+       memset(cmd, 0, sizeof(cmd));
+       cmd[0] = 0xdf;
+       cmd[1] = 0x10;
+       cmd[3] = 512 >> 8;
+       cmd[10] = 0xa0 | ((data[32] & 0x40) ? 0x10 : 0x00);
+       cmd[11] = ID_CMD;
+       if (do_scsi_in(h, cmd, 12, data, 512) < 0) {
+               memset(data, 0, 512);
+               return false;
+       }
+       return true;
+}
+
+static const uae_u8 realtek_inquiry_0x83[] = { 0x12, 0x01, 0x83, 0, 0xf0, 0 };
+static const uae_u8 realtek_read[] = { 0xf0, 0x0d, 0xfa, 0x00, 0x02, 0x00 };
+
+static bool hd_get_meta_hack_realtek(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 *inq)
+{
+       uae_u8 cmd[16];
 
        memset(data, 0, 512);
        memcpy(cmd, realtek_read, sizeof(realtek_read));
@@ -754,6 +861,112 @@ static bool hd_get_meta_hack(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 *inq)
        return false;
 }
 
+static bool hd_get_meta_hack(HWND hDlg, HANDLE h, uae_u8 *data, uae_u8 *inq, struct uae_driveinfo *udi)
+{
+       uae_u8 cmd[16];
+
+       memset(data, 0, 512);
+       if (udi->usb_vid == 0x152d && (udi->usb_pid == 0x2329 && udi->usb_pid == 0x2336 || udi->usb_pid == 0x2338 || udi->usb_pid == 0x2339)) {
+               return hd_meta_hack_jmicron(h, data, inq);
+       }
+       if (!hDlg)
+               return false;
+       memcpy(cmd, realtek_inquiry_0x83, sizeof(realtek_inquiry_0x83));
+       if (do_scsi_in(h, cmd, 6, data, 0xf0) >= 0 && !memcmp(data + 20, "realtek\0", 8)) {
+               return hd_get_meta_hack_realtek(hDlg, h, data, inq);
+       }
+       memset(data, 0, 512);
+       return false;
+}
+
+static bool readidentity(HANDLE h, struct uae_driveinfo *udi, struct hardfiledata *hfd)
+{
+       uae_u8 cmd[16];
+       uae_u8 *data = NULL;
+       bool ret = false;
+       bool satl = false;
+       bool handleopen = false;
+
+       memset(udi->identity, 0, 512);
+       if (hfd)
+               memset(hfd->identity, 0, 512);
+
+       data = (uae_u8*)VirtualAlloc(NULL, 65536, MEM_COMMIT, PAGE_READWRITE);
+       if (!data)
+               goto end;
+
+       if (h == INVALID_HANDLE_VALUE) {
+               DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS;
+               h = CreateFile(udi->device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, flags, NULL);
+               if (h == INVALID_HANDLE_VALUE)
+                       goto end;
+               handleopen = true;
+       }
+
+       if (udi->BusType == BusTypeAta || udi->BusType == BusTypeSata || udi->BusType == BusTypeAtapi) {
+               if (!_tcscmp(udi->vendor_id, _T("ATA"))) {
+                       satl = true;
+               }
+       }
+
+       if (satl || udi->BusType == BusTypeScsi || udi->BusType == BusTypeUsb || udi->BusType == BusTypeRAID) {
+
+               if (udi->devicetype == 5) {
+
+                       memset(cmd, 0, sizeof(cmd));
+                       memset(data, 0, 512);
+                       cmd[0] = 0x85; // SAT ATA PASSTHROUGH (16)
+                       cmd[1] = 4 << 1; // PIO data-in
+                       cmd[2] = 0x08 | 0x04 | 0x02; // dir = from device, 512 byte block, sector count = block cnt
+                       cmd[6] = 1; // block count
+                       cmd[14] = 0xa1; // identity packet device
+                       if (do_scsi_in(h, cmd, 16, data, 512) > 0) {
+                               ret = true;
+                       } else {
+                               write_log(_T("SAT: ATA PASSTHROUGH(16) failed\n"));
+                       }
+
+               } else {
+
+                       memset(cmd, 0, sizeof(cmd));
+                       memset(data, 0, 512);
+                       cmd[0] = 0xa1; // SAT ATA PASSTHROUGH (12)
+                       cmd[1] = 4 << 1; // PIO data-in
+                       cmd[2] = 0x08 | 0x04 | 0x02; // dir = from device, 512 byte block, sector count = block cnt
+                       cmd[4] = 1; // block count
+                       cmd[9] = 0xec; // identity
+                       if (do_scsi_in(h, cmd, 12, data, 512) > 0) {
+                               ret = true;
+                       } else {
+                               write_log(_T("SAT: ATA PASSTHROUGH(12) failed\n"));
+                       }
+               }
+       }
+
+       if (!ret) {
+               if (udi->BusType == BusTypeUsb) {
+                       ret = hd_get_meta_hack(NULL, h, data, NULL, udi);
+               } else if (udi->BusType == BusTypeAta || udi->BusType == BusTypeSata || udi->BusType == BusTypeAtapi) {
+                       ret = hd_get_meta_ata(NULL, h, udi->BusType == BusTypeAtapi, data);
+               }
+       }
+
+       if (ret) {
+               memcpy(udi->identity, data, 512);
+               if (hfd)
+                       memcpy(hfd->identity, data, 512);
+               write_log(_T("Real harddrive IDENTITY read\n"));
+       }
+
+end:
+
+       if (handleopen && h != INVALID_HANDLE_VALUE)
+               CloseHandle(h);
+       if (data)
+               VirtualFree(data, 65536, MEM_RELEASE);
+       return ret;
+}
+
 static bool do_scsi_read10_chs(HANDLE handle, uae_u32 lba, int c, int h, int s, uae_u8 *data, int cnt, bool log)
 {
        uae_u8 cmd[10] = { 0 };
@@ -806,7 +1019,6 @@ static bool hd_get_meta_satl(HWND hDlg, HANDLE h, uae_u8 *data, TCHAR *text, str
 {
        uae_u8 cmd[16];
        TCHAR cline[256];
-       bool invalidcapacity = false;
        bool ret = false;
 
        *atapi = false;
@@ -843,8 +1055,6 @@ static bool hd_get_meta_satl(HWND hDlg, HANDLE h, uae_u8 *data, TCHAR *text, str
                bintotextline(text, data, 8);
                _tcscat (text, _T("\r\n"));
                ini_addnewdata(ini, _T("READ CAPACITY"), _T("DATA"), data, 8);
-               if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff && data[3] == 0xff)
-                       invalidcapacity = true;
        }
 
        // get supported evpd pages
@@ -983,52 +1193,9 @@ static bool hd_get_meta_satl(HWND hDlg, HANDLE h, uae_u8 *data, TCHAR *text, str
                }
        }
 
-       if (invalidcapacity) {
-               bool chs0 = do_scsi_read10_chs(h, 0xffffffff, 0, 0, 0, data, 1, true);
-               bool chs1 = do_scsi_read10_chs(h, 0xffffffff, 0, 0, 1, data, 1, true);
-               write_log(_T("CHS0=%d CHS1=%d\n"), chs0, chs1);
-               int hh, ss;
-               for (ss = 1; ss < 256; ss++) {
-                       if (!do_scsi_read10_chs(h, 0xffffffff, 0, 0, ss, data, 1, true)) {
-                               ss--;
-                               break;
-                       }
-               }
-               write_log(_T("Sectors=%d\n"), ss);
-               for (hh = 0; hh < 16; hh++) {
-                       if (!do_scsi_read10_chs(h, 0xffffffff, 0, hh, 1, data, 1, true)) {
-                               break;
-                       }
-               }
-               write_log(_T("Heads=%d\n"), hh);
-               if (hh <= 0 || ss <= 1 || ss >= 256) {
-                       write_log(_T("Invalid H and/or S value.\n"));
-                       goto end;
-               }
-#if 0
-               int cc;
-               for (cc = 0; cc < 10000; cc++) {
-                       write_log(_T("%d "), cc);
-                       for (int hhh = 0; hhh < hh; hhh++) {
-                               for (int sss = 1; sss < ss; sss++) {
-                                       if (!do_scsi_read10_chs(h, cc, hhh, sss, data)) {
-                                               write_log("\n\n");
-                                               if (hhh != 0 || sss != 1) {
-                                                       write_log(_T("Read error when not first head and sector! %d:%d:%d\n"), cc, hhh, sss);
-                                               }
-                                               goto end;
-                                       }
-                               }
-                       }
-               }
-#endif
-end:;
-       }
-
        return ret;
 }
 
-static int chsdialogactive, chs_secs, chs_cyls, chs_heads;
 static INT_PTR CALLBACK CHSDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 {
        switch (msg)
@@ -1041,7 +1208,9 @@ static INT_PTR CALLBACK CHSDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM
                DestroyWindow(hDlg);
                return TRUE;
        case WM_INITDIALOG:
-               chs_secs = chs_cyls = chs_heads = 0;
+               SetDlgItemInt(hDlg, IDC_CHS_SECTORS, chs_secs, FALSE);
+               SetDlgItemInt(hDlg, IDC_CHS_CYLINDERS, chs_cyls, FALSE);
+               SetDlgItemInt(hDlg, IDC_CHS_HEADS, chs_heads, FALSE);
                return TRUE;
        case WM_COMMAND:
                switch (LOWORD(wParam))
@@ -1070,7 +1239,7 @@ static INT_PTR CALLBACK CHSDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM
 }
 
 
-static int gethdfchs(HWND hDlg, HANDLE h, int *cylsp, int *headsp, int *secsp)
+static int gethdfchs(HWND hDlg, struct uae_driveinfo *udi, HANDLE h, int *cylsp, int *headsp, int *secsp)
 {
        uae_u8 cmd[10];
        int cyls = 0, heads = 0, secs = 0;
@@ -1097,6 +1266,11 @@ static int gethdfchs(HWND hDlg, HANDLE h, int *cylsp, int *headsp, int *secsp)
        }
        if (!cylsp || !headsp || !secsp)
                return err;
+
+       if (readidentity(h, udi, NULL)) {
+               parse_identity(udi->identity, NULL, NULL);
+       }
+
        chsdialogactive = 1;
        HWND hwnd = CustomCreateDialog(IDD_CHSQUERY, hDlg, CHSDialogProc);
        if (hwnd == NULL) {
@@ -1199,13 +1373,14 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
        bool satl = false;
        uae_u8 *data = NULL;
        uae_u8 inq[INQUIRY_LEN + 4] = { 0 };
-       TCHAR *text;
+       TCHAR *text, *tptr;
        struct ini_data *ini = NULL;
        bool atapi = false;
 
        geometryfile[0] = 0;
        text = xcalloc(TCHAR, 100000);
 
+
        HANDLE h = CreateFile(udi->device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
@@ -1225,20 +1400,28 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
                }
        }
 
-       _stprintf(text, _T("BusType: 0x%02x\r\nVendor: '%s'\r\nProduct: '%s'\r\nRevision: '%s'\r\nSerial: '%s'\r\nSize: %llu\r\n\r\n"),
+       _stprintf(text, _T("BusType: 0x%02x\r\nVendor: '%s'\r\nProduct: '%s'\r\nRevision: '%s'\r\nSerial: '%s'\r\nSize: %llu\r\n"),
                 udi->BusType, udi->vendor_id, udi->product_id, udi->product_rev, udi->product_serial, udi->size);
+       tptr = text + _tcslen(text);
+       if (udi->BusType == BusTypeUsb && udi->usb_vid && udi->usb_pid) {
+               _stprintf(tptr, _T("VID: %04x PID: %04x\r\n"), udi->usb_vid, udi->usb_pid);
+               tptr += _tcslen(tptr);
+       }
+       _tcscpy(tptr, _T("\r\n"));
+       tptr += _tcslen(tptr);
+
        write_log(_T("SATL=%d\n%s"), satl, text);
 
        if (satl || udi->BusType == BusTypeScsi || udi->BusType == BusTypeUsb || udi->BusType == BusTypeRAID) {
                write_log(_T("SCSI ATA passthrough\n"));
-               if (!hd_get_meta_satl(hDlg, h, data, text, ini, &atapi)) {
+               if (!hd_get_meta_satl(hDlg, h, data, tptr, ini, &atapi)) {
                        write_log(_T("SAT Passthrough failed\n"));
                        memset(data, 0, 512);
                        if (udi->BusType == BusTypeUsb) {
-                               hd_get_meta_hack(hDlg, h, data, inq);
+                               hd_get_meta_hack(hDlg, h, data, inq, udi);
                        }
-                       if (text[0] == 0) {
-                               _tcscpy(text, _T("SCSI ATA Passthrough error!"));
+                       if (tptr[0] == 0) {
+                               _tcscpy(tptr, _T("\r\nSCSI ATA Passthrough error."));
                                goto doout;
                        }
                }
@@ -1246,11 +1429,11 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
                write_log(_T("ATA passthrough\n"));
                if (!hd_get_meta_ata(hDlg, h, udi->BusType == BusTypeAtapi, data)) {
                        write_log(_T("ATA Passthrough failed\n"));
-                       _tcscpy(text, _T("ATA Passthrough error!"));
+                       _tcscpy(tptr, _T("\r\nATA Passthrough error."));
                        goto doout;
                }
        } else {
-               _stprintf(text, _T("Unsupported bus type %02x\n"), udi->BusType);
+               _stprintf(tptr, _T("Unsupported bus type %02x\n"), udi->BusType);
                goto doout;
        }
 
@@ -1262,8 +1445,8 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
 
        if (empty) {
                write_log(_T("Nothing returned!\n"));
-               if (text[0] == 0) {
-                       _tcscpy(text, _T("Nothing returned!"));
+               if (tptr[0] == 0) {
+                       _tcscpy(tptr, _T("Nothing returned!"));
                        goto doout;
                }
        }
@@ -1272,8 +1455,11 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
 
        if (!empty) {
                TCHAR cline[256];
-               _tcscat (text, _T("IDENTITY:\r\n"));
-               bintotextline(text, data, 512);
+               _tcscat (tptr, _T("IDENTITY:\r\n"));
+               tptr += _tcslen(tptr);
+               tptr = bintotextline(tptr, data, 512);
+               _tcscpy(tptr, _T("\r\n"));
+               tptr += _tcslen(tptr);
 
                bintotextpart(cline, data + 27 * 2, 40);
                ini_addnewcomment(ini, _T("IDENTITY"), cline);
@@ -1286,6 +1472,8 @@ void hd_get_meta(HWND hDlg, int idx, TCHAR *geometryfile)
                        ini_addnewstring(ini, _T("IDENTITY"), _T("ATAPI"), _T("true"));
 
                ini_addnewdata(ini, _T("IDENTITY"), _T("DATA"), data, 512);
+
+               tptr = parse_identity(data, ini, tptr);
        }
 
 doout:
@@ -1419,6 +1607,12 @@ static bool getdeviceinfo (HANDLE hDevice, struct uae_driveinfo *udi)
                return false;
        }
 
+       STORAGE_DEVICE_NUMBER sdn;
+       if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &returnedLength, NULL)) {
+               getstorageinfo(udi, sdn);
+       }
+       readidentity(INVALID_HANDLE_VALUE, udi, NULL);
+
        if (!DeviceIoControl (hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (void*)&dg, sizeof (dg), &returnedLength, NULL)) {
                DWORD err = GetLastError();
                if (isnomediaerr (err)) {
@@ -1653,8 +1847,7 @@ int hdf_open_target (struct hardfiledata *hfd, const TCHAR *pname)
                                if (udi->readonly)
                                        hfd->ci.readonly = 1;
                        }
-
-                       //hfd->ci.readonly = false;
+                       readidentity(INVALID_HANDLE_VALUE, udi, hfd);
 
                        flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS;
                        h = CreateFile (udi->device_path,
@@ -2296,6 +2489,7 @@ static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_dri
                write_log (_T("not a direct access device, ignored (type=%d)\n"), devDesc->DeviceType);
                return -2;
        }
+       udi->devicetype = devDesc->DeviceType;
        if (size > offsetof(STORAGE_DEVICE_DESCRIPTOR, VendorIdOffset) && validoffset(devDesc->VendorIdOffset, size2) && p[devDesc->VendorIdOffset]) {
                j = 0;
                for (i = devDesc->VendorIdOffset; p[i] != (UCHAR) NULL && i < returnedLength; i++)
@@ -2372,6 +2566,93 @@ static int getstorageproperty (PUCHAR outBuf, int returnedLength, struct uae_dri
        return -1;
 }
 
+static bool getstorageinfo(uae_driveinfo *udi, STORAGE_DEVICE_NUMBER sdnp)
+{
+       int idx;
+       const GUID *di = udi->devicetype == INQ_ROMD ? &GUID_DEVINTERFACE_CDROM : &GUID_DEVINTERFACE_DISK;
+       HDEVINFO hIntDevInfo;
+       DWORD vpm[3];
+
+       vpm[0] = 0xffffffff;
+       vpm[1] = 0xffffffff;
+       vpm[2] = 0xffffffff;
+       hIntDevInfo = SetupDiGetClassDevs(di, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+       if (!hIntDevInfo)
+               return false;
+       idx = -1;
+       for (;;) {
+               PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
+               SP_DEVICE_INTERFACE_DATA interfaceData = { 0 };
+               SP_DEVINFO_DATA deviceInfoData = { 0 };
+               DWORD dwRequiredSize, returnedLength;
+
+               idx++;
+               interfaceData.cbSize = sizeof(interfaceData);
+               if (!SetupDiEnumDeviceInterfaces(hIntDevInfo, NULL, di, idx, &interfaceData))
+                       break;
+               dwRequiredSize = 0;
+               if (!SetupDiGetDeviceInterfaceDetail(hIntDevInfo, &interfaceData, NULL, 0, &dwRequiredSize, NULL)) {
+                       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+                               break;
+                       if (dwRequiredSize <= 0)
+                               break;
+               }
+               pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, dwRequiredSize);
+               pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+               deviceInfoData.cbSize = sizeof(deviceInfoData);
+               if (!SetupDiGetDeviceInterfaceDetail(hIntDevInfo, &interfaceData, pInterfaceDetailData, dwRequiredSize, &dwRequiredSize, &deviceInfoData)) {
+                       LocalFree(pInterfaceDetailData);
+                       continue;
+               }
+               HANDLE hDev = CreateFile(pInterfaceDetailData->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+               if (hDev == INVALID_HANDLE_VALUE) {
+                       LocalFree(pInterfaceDetailData);
+                       continue;
+               }
+               LocalFree(pInterfaceDetailData);
+               STORAGE_DEVICE_NUMBER sdn;
+               if (!DeviceIoControl(hDev, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &returnedLength, NULL)) {
+                       CloseHandle(hDev);
+                       continue;
+               }
+               CloseHandle(hDev);
+               if (sdnp.DeviceType != sdn.DeviceType || sdnp.DeviceNumber != sdn.DeviceNumber) {
+                       continue;
+               }
+               TCHAR pszDeviceInstanceId[1024];
+               DEVINST dnDevInstParent, dwDeviceInstanceIdSize;
+               dwDeviceInstanceIdSize = sizeof(pszDeviceInstanceId) / sizeof(TCHAR);
+               if (!SetupDiGetDeviceInstanceId(hIntDevInfo, &deviceInfoData, pszDeviceInstanceId, dwDeviceInstanceIdSize, &dwRequiredSize)) {
+                       continue;
+               }
+               if (CM_Get_Parent(&dnDevInstParent, deviceInfoData.DevInst, 0) == CR_SUCCESS) {
+                       TCHAR szDeviceInstanceID[MAX_DEVICE_ID_LEN];
+                       if (CM_Get_Device_ID(dnDevInstParent, szDeviceInstanceID, MAX_DEVICE_ID_LEN, 0) == CR_SUCCESS) {
+                               const static LPCTSTR arPrefix[3] = { TEXT("VID_"), TEXT("PID_"), TEXT("MI_") };
+                               LPTSTR pszNextToken;
+                               LPTSTR pszToken = _tcstok_s(szDeviceInstanceID, TEXT("\\#&"), &pszNextToken);
+                               while (pszToken != NULL) {
+                                       for (int j = 0; j < 3; j++) {
+                                               if (_tcsncmp(pszToken, arPrefix[j], lstrlen(arPrefix[j])) == 0) {
+                                                       wchar_t *endptr;
+                                                       vpm[j] = _tcstol(pszToken + lstrlen(arPrefix[j]), &endptr, 16);
+                                               }
+                                       }
+                                       pszToken = _tcstok_s(NULL, TEXT("\\#&"), &pszNextToken);
+                               }
+                       }
+               }
+               if (vpm[0] != 0xffffffff && vpm[1] != 0xffffffff)
+                       break;
+       }
+       SetupDiDestroyDeviceInfoList(hIntDevInfo);
+       if (vpm[0] == 0xffffffff || vpm[1] == 0xffffffff)
+               return false;
+       udi->usb_vid = vpm[0];
+       udi->usb_pid = vpm[1];
+       return true;
+}
+
 static void checkhdname(struct uae_driveinfo *udi)
 {
        int cnt = 1;
@@ -2481,6 +2762,11 @@ static BOOL GetDevicePropertyFromName(const TCHAR *DevicePath, DWORD Index, DWOR
                        ret = 1;
                        goto end;
                }
+               STORAGE_DEVICE_NUMBER sdn;
+               if (DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &returnedLength, NULL)) {
+                       getstorageinfo(udi, sdn);
+               }
+               readidentity(INVALID_HANDLE_VALUE, udi, NULL);
        }
        udi = &uae_drives[udiindex < 0 ? *index2 : udiindex];
        memcpy (udi, &tmpudi, sizeof (struct uae_driveinfo));
@@ -2816,7 +3102,7 @@ int hdf_getnumharddrives (void)
        return num_drives;
 }
 
-TCHAR *hdf_getnameharddrive (int index, int flags, int *sectorsize, int *dangerousdrive)
+TCHAR *hdf_getnameharddrive (int index, int flags, int *sectorsize, int *dangerousdrive, uae_u32 *outflags)
 {
        struct uae_driveinfo *udi = &uae_drives[index];
        static TCHAR name[512];
@@ -2827,6 +3113,12 @@ TCHAR *hdf_getnameharddrive (int index, int flags, int *sectorsize, int *dangero
        TCHAR *rw = _T("RW");
        bool noaccess = false;
 
+       if (outflags) {
+               *outflags = 0;
+               if (udi->identity[0] || udi->identity[1])
+                       *outflags = 1;
+       }
+
        if (dangerousdrive)
                *dangerousdrive = 0;
        switch (udi->dangerous)
@@ -3075,9 +3367,9 @@ int harddrive_to_hdf (HWND hDlg, struct uae_prefs *p, int idx)
        h = CreateFile(uae_drives[idx].device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (h != INVALID_HANDLE_VALUE) {
-               if (!gethdfchs(hDlg, h, NULL, NULL, NULL)) {
+               if (!gethdfchs(hDlg, &uae_drives[idx], h, NULL, NULL, NULL)) {
                        chsmode = true;
-                       erc = gethdfchs(hDlg, h, &cyls, &heads, &secs);
+                       erc = gethdfchs(hDlg, &uae_drives[idx], h, &cyls, &heads, &secs);
                        if (erc == -100) {
                                chsmode = false;
                                CloseHandle(h);
@@ -3227,13 +3519,15 @@ int harddrive_to_hdf (HWND hDlg, struct uae_prefs *p, int idx)
 err:
        if (!erc)
                erc = GetLastError ();
-       LPWSTR pBuffer = NULL;
-       WIN32GUI_LoadUIString (IDS_HDCLONE_FAIL, tmp, MAX_DPATH);
-       if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, erc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&pBuffer, 0, NULL))
-               pBuffer = NULL;
-       _stprintf (tmp2, tmp, progressdialogreturn, erc, pBuffer ? _T("<unknown>") : pBuffer);
-       gui_message (tmp2);
-       LocalFree (pBuffer);
+       if (erc) {
+               LPWSTR pBuffer = NULL;
+               WIN32GUI_LoadUIString(IDS_HDCLONE_FAIL, tmp, MAX_DPATH);
+               if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, erc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&pBuffer, 0, NULL))
+                       pBuffer = NULL;
+               _stprintf(tmp2, tmp, progressdialogreturn, erc, pBuffer ? _T("<unknown>") : pBuffer);
+               gui_message(tmp2);
+               LocalFree(pBuffer);
+       }
 
 ok:
        if (h != INVALID_HANDLE_VALUE)
index 06d29ff40c5beece83b2189a0f4d54e30c42c391..d110c827cc5dfb7aa94e5e9abad88effb51f8044 100644 (file)
 #define IDC_HDF_LOCK                    1780
 #define IDC_DBG_DASM2                   1781
 #define IDC_HF_DYNAMIC                  1781
+#define IDC_HDF_IDENTITY                1781
 #define IDC_DBG_MEM2                    1782
 #define IDC_HDFINFO2                    1782
 #define IDC_DBG_MEMINPUT2               1783
+#define IDC_HDFINFO3                    1783
 #define IDC_DBG_ADDRINPUTTXT            1784
 #define IDC_RTG_SCALE                   1785
 #define IDC_RTG_MATCH_DEPTH             1786
index 1a573b40bdac88f38457f16279c049d1c52f1e39..194bc8445c9a3eb56185e50f84d04e4189897dd8 100644 (file)
@@ -952,8 +952,8 @@ BEGIN
     COMBOBOX        IDC_HDF_CONTROLLER_TYPE,113,111,110,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
     COMBOBOX        IDC_HDF_FEATURE_LEVEL,7,152,97,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
     COMBOBOX        IDC_HDF_CONTROLLER,7,132,216,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
-    DEFPUSHBUTTON   "Add hard drive",IDOK,237,195,73,14,WS_DISABLED
-    PUSHBUTTON      "Cancel",IDCANCEL,316,195,73,14
+    DEFPUSHBUTTON   "Add hard drive",IDOK,237,190,73,14,WS_DISABLED
+    PUSHBUTTON      "Cancel",IDCANCEL,316,190,73,14
     CONTROL         "Lock",IDC_HDF_LOCK,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,233,90,55,10
     DEFPUSHBUTTON   "Create hard disk image file",IDC_HARDDRIVE_IMAGE,5,88,158,14,WS_DISABLED
     CONTROL         "Manual geometry",IDC_HDF_PHYSGEOMETRY,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,299,90,87,10
@@ -968,6 +968,8 @@ BEGIN
     COMBOBOX        IDC_PATH_GEOMETRY,49,29,325,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
     PUSHBUTTON      "...",IDC_PATH_GEOMETRY_SELECTOR,377,28,11,15,WS_DISABLED
     RTEXT           "Geometry:",IDC_STATIC,3,31,41,10
+    CONTROL         "Identity",IDC_HDF_IDENTITY,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,233,110,55,10
+    EDITTEXT        IDC_HDFINFO3,7,173,217,12,ES_CENTER | ES_READONLY
 END
 
 IDD_MISC2 DIALOGEX 0, 0, 396, 278
index 458200d84eda7a7b4bcea6a12230a01ce111247a..850772398ef81e57771950ae1f0278279efa4c50 100644 (file)
@@ -12822,6 +12822,8 @@ static void sethardfile (HWND hDlg)
        hide (hDlg, IDC_HARDFILE_BOOTPRI, !disables);
        hide (hDlg, IDC_HARDFILE_BOOTPRI_TEXT, !disables);
        hide (hDlg, IDC_HDF_PHYSGEOMETRY, !rdb);
+       if (!rdb)
+               setchecked(hDlg, IDC_HDF_PHYSGEOMETRY, false);
        hide(hDlg, IDC_RESERVED_TEXT, rdb);
        hide(hDlg, IDC_CYLINDERS_TEXT, !rdb);
        gui_set_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER, current_hfdlg.ci.controller_type +  current_hfdlg.ci.controller_type_unit * HD_CONTROLLER_NEXT_UNIT);
@@ -13052,6 +13054,15 @@ static void updatehdfinfo (HWND hDlg, bool force, bool defaults)
                } else {
                        current_hfdlg.forcedcylinders = current_hfdlg.ci.pcyls;
                }
+               if (hDlg && (hfd.identity[0] || hfd.identity[1])) {
+                       TCHAR ident[256];
+                       int i;
+                       for (i = 0; i < 11; i++) {
+                               _stprintf(ident + i * 5, _T("%02X%02X."), hfd.identity[i * 2 + 1], hfd.identity[i * 2 + 0]);
+                       }
+                       ident[i * 5 - 1] = 0;
+                       SetDlgItemText(hDlg, IDC_HDFINFO3, ident);
+               }
                hdf_close (&hfd);
        }
 
@@ -13104,8 +13115,8 @@ static void updatehdfinfo (HWND hDlg, bool force, bool defaults)
                        }
                }
                if (hDlg != NULL) {
-                       SetDlgItemText (hDlg, IDC_HDFINFO, tmp);
-                       SetDlgItemText (hDlg, IDC_HDFINFO2, tmp2);
+                       SetDlgItemText(hDlg, IDC_HDFINFO, tmp);
+                       SetDlgItemText(hDlg, IDC_HDFINFO2, tmp2);
                }
        }
 }
@@ -13657,15 +13668,16 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                        setharddrive(hDlg);
                        inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, current_hfdlg.ci.rootdir[0] != 0);
                        CheckDlgButton (hDlg, IDC_HDF_RW, !current_hfdlg.ci.readonly);
-                       CheckDlgButton (hDlg, IDC_HDF_LOCK, current_hfdlg.ci.lock);
+                       CheckDlgButton(hDlg, IDC_HDF_LOCK, current_hfdlg.ci.lock);
+                       CheckDlgButton(hDlg, IDC_HDF_IDENTITY, current_hfdlg.ci.loadidentity);
                        SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_RESETCONTENT, 0, 0);
                        ew (hDlg, IDC_HARDDRIVE_IMAGE, FALSE);
                        index = -1;
                        for (i = 0; i < hdf_getnumharddrives (); i++) {
-                               SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_ADDSTRING, 0, (LPARAM)hdf_getnameharddrive (i, 1, NULL, NULL));
-                               TCHAR *name1 = hdf_getnameharddrive (i, 4, NULL, NULL);
-                               TCHAR *name2 = hdf_getnameharddrive (i, 2, NULL, NULL);
-                               TCHAR *name3 = hdf_getnameharddrive (i, 0, NULL, NULL);
+                               SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_ADDSTRING, 0, (LPARAM)hdf_getnameharddrive (i, 1, NULL, NULL, NULL));
+                               TCHAR *name1 = hdf_getnameharddrive (i, 4, NULL, NULL, NULL);
+                               TCHAR *name2 = hdf_getnameharddrive (i, 2, NULL, NULL, NULL);
+                               TCHAR *name3 = hdf_getnameharddrive (i, 0, NULL, NULL, NULL);
                                if (!_tcscmp (current_hfdlg.ci.rootdir, name1) || !_tcscmp (current_hfdlg.ci.rootdir, name2) || !_tcscmp (current_hfdlg.ci.rootdir, name3))
                                        index = i;
                        }
@@ -13725,16 +13737,22 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                posn = SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_GETCURSEL, 0, 0);
                                if (posn != CB_ERR) {
                                        int dang = 1;
-                                       hdf_getnameharddrive (posn, 1, NULL, &dang);
+                                       hdf_getnameharddrive (posn, 1, NULL, &dang, NULL);
                                        current_hfdlg.ci.readonly = (ischecked (hDlg, IDC_HDF_RW) && !dang) ? false : true;
                                }
                                break;
                        case IDC_HDF_LOCK:
-                               posn = SendDlgItemMessage (hDlg, IDC_HARDDRIVE, CB_GETCURSEL, 0, 0);
+                               posn = SendDlgItemMessage(hDlg, IDC_HARDDRIVE, CB_GETCURSEL, 0, 0);
                                if (posn != CB_ERR) {
                                        int dang = 1;
-                                       hdf_getnameharddrive (posn, 1, NULL, &dang);
-                                       current_hfdlg.ci.lock = ischecked (hDlg, IDC_HDF_LOCK);
+                                       hdf_getnameharddrive(posn, 1, NULL, &dang, NULL);
+                                       current_hfdlg.ci.lock = ischecked(hDlg, IDC_HDF_LOCK);
+                               }
+                               break;
+                       case IDC_HDF_IDENTITY:
+                               posn = SendDlgItemMessage(hDlg, IDC_HDF_IDENTITY, CB_GETCURSEL, 0, 0);
+                               if (posn != CB_ERR) {
+                                       current_hfdlg.ci.loadidentity = ischecked(hDlg, IDC_HDF_IDENTITY);
                                }
                                break;
                        }
@@ -13747,34 +13765,40 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                        oposn = posn;
                                        if (posn >= 0) {
                                                BOOL ena;
+                                               uae_u32 flags;
                                                int dang = 1;
-                                               hdf_getnameharddrive (posn, 1, NULL, &dang);
-                                               _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive (posn, 4, NULL, &dang));
+                                               hdf_getnameharddrive (posn, 1, NULL, &dang, &flags);
+                                               _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive (posn, 4, NULL, &dang, NULL));
                                                ena = dang >= 0;
-                                               ew (hDlg, IDC_HARDDRIVE_IMAGE, ena);
-                                               ew (hDlg, IDC_HARDDRIVE_ID, ena);
-                                               ew (hDlg, IDC_HDF_LOCK, ena);
-                                               ew (hDlg, IDOK, ena);
-                                               ew (hDlg, IDC_HDF_RW, !dang);
-                                               ew (hDlg, IDC_HDF_FEATURE_LEVEL, ena);
-                                               ew (hDlg, IDC_HDF_CONTROLLER, ena);
-                                               ew (hDlg, IDC_HDF_CONTROLLER_UNIT, ena);
-                                               ew (hDlg, IDC_HDF_CONTROLLER_TYPE, ena);
-                                               ew (hDlg, IDC_PATH_GEOMETRY, ena);
-                                               ew (hDlg, IDC_PATH_GEOMETRY_SELECTOR, ena);
-                                               ew (hDlg, IDC_HDF_PHYSGEOMETRY, ena && current_hfdlg.ci.geometry[0] == 0);
+                                               ew(hDlg, IDC_HARDDRIVE_IMAGE, ena);
+                                               ew(hDlg, IDC_HARDDRIVE_ID, ena);
+                                               ew(hDlg, IDC_HDF_LOCK, ena);
+                                               ew(hDlg, IDOK, ena);
+                                               ew(hDlg, IDC_HDF_RW, !dang);
+                                               ew(hDlg, IDC_HDF_FEATURE_LEVEL, ena);
+                                               ew(hDlg, IDC_HDF_CONTROLLER, ena);
+                                               ew(hDlg, IDC_HDF_CONTROLLER_UNIT, ena);
+                                               ew(hDlg, IDC_HDF_CONTROLLER_TYPE, ena);
+                                               ew(hDlg, IDC_PATH_GEOMETRY, ena);
+                                               ew(hDlg, IDC_PATH_GEOMETRY_SELECTOR, ena);
+                                               ew(hDlg, IDC_HDF_PHYSGEOMETRY, ena && current_hfdlg.ci.geometry[0] == 0);
                                                if (dang)
                                                        current_hfdlg.ci.readonly = true;
                                                current_hfdlg.ci.blocksize = 512;
                                                current_hfdlg.forcedcylinders = 0;
                                                current_hfdlg.ci.cyls = current_hfdlg.ci.highcyl = current_hfdlg.ci.sectors = current_hfdlg.ci.surfaces = 0;
-                                               SetDlgItemText (hDlg, IDC_HDFINFO, _T(""));
-                                               SetDlgItemText (hDlg, IDC_HDFINFO2, _T(""));
+                                               SetDlgItemText(hDlg, IDC_HDFINFO, _T(""));
+                                               SetDlgItemText(hDlg, IDC_HDFINFO2, _T(""));
+                                               SetDlgItemText(hDlg, IDC_HDFINFO3, _T(""));
                                                updatehdfinfo (hDlg, true, current_hfdlg.ci.geometry[0] ? false : true);
+                                               hdf_getnameharddrive(posn, 1, NULL, &dang, &flags);
+                                               ew(hDlg, IDC_HDF_IDENTITY, ena && (flags & 1));
+                                               if (!(flags & 1))
+                                                       current_hfdlg.ci.loadidentity = false;
                                                gui_set_string_cursor(hdmenutable, hDlg, IDC_HDF_CONTROLLER, current_hfdlg.ci.controller_type + current_hfdlg.ci.controller_type_unit * MAX_DUPLICATE_EXPANSION_BOARDS);
                                                SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_hfdlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_hfdlg.ci.controller_unit : current_hfdlg.ci.controller_type_unit, 0);
                                                CheckDlgButton(hDlg, IDC_HDF_RW, !current_hfdlg.ci.readonly);
-                                               _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 4, &current_hfdlg.ci.blocksize, NULL));
+                                               _tcscpy (current_hfdlg.ci.rootdir, hdf_getnameharddrive ((int)posn, 4, &current_hfdlg.ci.blocksize, NULL, NULL));
                                                setharddrive(hDlg);
                                        }
                                }
@@ -13786,8 +13810,9 @@ static INT_PTR CALLBACK HarddriveSettingsProc (HWND hDlg, UINT msg, WPARAM wPara
                                        current_hfdlg.ci.controller_type_unit = posn / HD_CONTROLLER_NEXT_UNIT;
                                        current_hfdlg.forcedcylinders = 0;
                                        current_hfdlg.ci.cyls = current_hfdlg.ci.highcyl = current_hfdlg.ci.sectors = current_hfdlg.ci.surfaces = 0;
-                                       SetDlgItemText (hDlg, IDC_HDFINFO, _T(""));
-                                       SetDlgItemText (hDlg, IDC_HDFINFO2, _T(""));
+                                       SetDlgItemText(hDlg, IDC_HDFINFO, _T(""));
+                                       SetDlgItemText(hDlg, IDC_HDFINFO2, _T(""));
+                                       SetDlgItemText(hDlg, IDC_HDFINFO3, _T(""));
                                        updatehdfinfo (hDlg, true, true);
                                        inithdcontroller(hDlg, current_hfdlg.ci.controller_type, current_hfdlg.ci.controller_type_unit, UAEDEV_HDF, current_hfdlg.ci.rootdir[0] != 0);
                                        SendDlgItemMessage(hDlg, IDC_HDF_CONTROLLER_UNIT, CB_SETCURSEL, current_hfdlg.ci.controller_type != HD_CONTROLLER_TYPE_PCMCIA ? current_hfdlg.ci.controller_unit : current_hfdlg.ci.controller_type_unit, 0);