Change default configuration to 2GB limit, no parity, no attention. v4.00.03
authorMichael McMaster <michael@codesrc.com>
Thu, 8 Jan 2015 10:54:27 +0000 (20:54 +1000)
committerMichael McMaster <michael@codesrc.com>
Thu, 8 Jan 2015 10:54:27 +0000 (20:54 +1000)
16 files changed:
CHANGELOG
software/SCSI2SD/src/cdrom.c
software/SCSI2SD/src/config.c
software/SCSI2SD/src/disk.c
software/SCSI2SD/src/inquiry.c
software/SCSI2SD/src/mode.c
software/SCSI2SD/src/scsi.c
software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch
software/SCSI2SD/v4/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c
software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit
software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch
software/include/scsi2sd.h
software/scsi2sd-util/ConfigUtil.cc
software/scsi2sd-util/Makefile
software/scsi2sd-util/TargetPanel.cc
software/scsi2sd-util/TargetPanel.hh

index 66bfdda..d9d299c 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,4 @@
-20141223               4.0
+20150108               4.0
        - Fix handling requests for LUNs other than 0 from SCSI-2 hosts.
        - Handle glitches of the scsi signals to improve stability and operate with
        multiple devices on the SCSI bus.
index 6a30938..44d03a3 100755 (executable)
 #include "config.h"
 #include "cdrom.h"
 
-uint8_t SimpleTOC[] =
+static const uint8_t SimpleTOC[] =
 {
        0x00, // toc length, MSB
-       0x0A, // toc length, LSB
+       0x12, // toc length, LSB
        0x01, // First track number
        0x01, // Last track number,
        // TRACK 1 Descriptor
-       0x00, // reservied
-       0x06, // Q sub-channel not supplied, Digital track
+       0x00, // reserved
+       0x14, // Q sub-channel encodes current position, Digital track
        0x01, // Track 1,
        0x00, // Reserved
-       0x00,0x00,0x00,0x00 // Track start sector (LBA)
+       0x00,0x00,0x00,0x00, // Track start sector (LBA)
+       0x00, // reserved
+       0x14, // Q sub-channel encodes current position, Digital track
+       0xAA, // Leadout Track
+       0x00, // Reserved
+       0x00,0x00,0x00,0x00, // Track start sector (LBA)
+};
+
+static const uint8_t SessionTOC[] =
+{
+       0x00, // toc length, MSB
+       0x0A, // toc length, LSB
+       0x01, // First session number
+       0x01, // Last session number,
+       // TRACK 1 Descriptor
+       0x00, // reserved
+       0x14, // Q sub-channel encodes current position, Digital track
+       0x01, // First track number in last complete session
+       0x00, // Reserved
+       0x00,0x00,0x00,0x00 // LBA of first track in last session
+};
+
+
+static const uint8_t FullTOC[] =
+{
+       0x00, // toc length, MSB
+       0x44, // toc length, LSB
+       0x01, // First session number
+       0x01, // Last session number,
+       // A0 Descriptor
+       0x01, // session number
+       0x14, // ADR/Control
+       0x00, // TNO
+       0xA0, // POINT
+       0x00, // Min
+       0x00, // Sec
+       0x00, // Frame
+       0x00, // Zero
+       0x01, // First Track number.
+       0x00, // Disc type 00 = Mode 1
+       0x00,  // PFRAME
+       // A1
+       0x01, // session number
+       0x14, // ADR/Control
+       0x00, // TNO
+       0xA1, // POINT
+       0x00, // Min
+       0x00, // Sec
+       0x00, // Frame
+       0x00, // Zero
+       0x01, // Last Track number
+       0x00, // PSEC
+       0x00,  // PFRAME
+       // A2
+       0x01, // session number
+       0x14, // ADR/Control
+       0x00, // TNO
+       0xA2, // POINT
+       0x00, // Min
+       0x00, // Sec
+       0x00, // Frame
+       0x00, // Zero
+       0x79, // LEADOUT position BCD
+       0x59, // leadout PSEC BCD
+       0x74, // leadout PFRAME BCD
+       // TRACK 1 Descriptor
+       0x01, // session number
+       0x14, // ADR/Control
+       0x00, // TNO
+       0x01, // Point
+       0x00, // Min
+       0x00, // Sec
+       0x00, // Frame
+       0x00, // Zero
+       0x00, // PMIN
+       0x00, // PSEC
+       0x00,  // PFRAME
+       // b0
+       0x01, // session number
+       0x54, // ADR/Control
+       0x00, // TNO
+       0xB1, // POINT
+       0x79, // Min BCD
+       0x59, // Sec BCD
+       0x74, // Frame BCD
+       0x00, // Zero
+       0x79, // PMIN BCD
+       0x59, // PSEC BCD
+       0x74,  // PFRAME BCD
+       // c0
+       0x01, // session number
+       0x54, // ADR/Control
+       0x00, // TNO
+       0xC0, // POINT
+       0x00, // Min
+       0x00, // Sec
+       0x00, // Frame
+       0x00, // Zero
+       0x00, // PMIN
+       0x00, // PSEC
+       0x00  // PFRAME
 };
 
-void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
+static void LBA2MSF(uint32_t LBA, uint8_t* MSF)
+{
+       MSF[0] = 0; // reserved.
+       MSF[3] = LBA % 75; // M
+       uint32_t rem = LBA / 75;
+
+       MSF[2] = rem % 60; // S
+       MSF[1] = rem / 60;
+
+}
+
+static void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
 {
        // We only support track 1.
        // track 0 means "return all tracks"
@@ -45,18 +156,29 @@ void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
                scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
                scsiDev.phase = STATUS;
        }
-       else if (MSF)
-       {
-               // MSF addressing not currently supported.
-               scsiDev.status = CHECK_CONDITION;
-               scsiDev.target->sense.code = ILLEGAL_REQUEST;
-               scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
-               scsiDev.phase = STATUS;
-       }
        else
        {
                uint32_t len = sizeof(SimpleTOC);
                memcpy(scsiDev.data, SimpleTOC, len);
+
+               uint32_t capacity = getScsiCapacity(
+                       scsiDev.target->cfg->sdSectorStart,
+                       scsiDev.target->liveCfg.bytesPerSector,
+                       scsiDev.target->cfg->scsiSectors);
+
+               // Replace start of leadout track
+               if (MSF)
+               {
+                       LBA2MSF(capacity, scsiDev.data + 0x0E);
+               }
+               else
+               {
+                       scsiDev.data[0x0E] = capacity >> 24;
+                       scsiDev.data[0x0F] = capacity >> 16;
+                       scsiDev.data[0x10] = capacity >> 8;
+                       scsiDev.data[0x11] = capacity;
+               }
+
                if (len > allocationLength)
                {
                        len = allocationLength;
@@ -66,20 +188,30 @@ void doReadTOC(int MSF, uint8_t track, uint16_t allocationLength)
        }
 }
 
-uint8_t SimpleHeader[] =
+static void doReadSessionInfo(uint8_t session, uint16_t allocationLength)
 {
-       0x01, // 2048byte user data, L-EC in 288 byte aux field.
-       0x00, // reserved
-       0x00, // reserved
-       0x00, // reserved
-       0x00,0x00,0x00,0x00 // Track start sector (LBA)
-};
+       uint32_t len = sizeof(SessionTOC);
+       memcpy(scsiDev.data, SessionTOC, len);
 
-void doReadHeader(int MSF, uint32_t lba, uint16_t allocationLength)
+       if (len > allocationLength)
+       {
+               len = allocationLength;
+       }
+       scsiDev.dataLen = len;
+       scsiDev.phase = DATA_IN;
+}
+
+static inline uint8_t
+fromBCD(uint8_t val)
 {
-       if (MSF)
+       return ((val >> 4) * 10) + (val & 0xF);
+}
+
+static void doReadFullTOC(int convertBCD, uint8_t session, uint16_t allocationLength)
+{
+       // We only support session 1.
+       if (session > 1)
        {
-               // MSF addressing not currently supported.
                scsiDev.status = CHECK_CONDITION;
                scsiDev.target->sense.code = ILLEGAL_REQUEST;
                scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
@@ -87,8 +219,25 @@ void doReadHeader(int MSF, uint32_t lba, uint16_t allocationLength)
        }
        else
        {
-               uint32_t len = sizeof(SimpleHeader);
-               memcpy(scsiDev.data, SimpleHeader, len);
+               uint32_t len = sizeof(FullTOC);
+               memcpy(scsiDev.data, FullTOC, len);
+
+               if (convertBCD)
+               {
+                       int descriptor = 4;
+                       while (descriptor < len)
+                       {
+                               int i;
+                               for (i = 0; i < 7; ++i)
+                               {
+                                       scsiDev.data[descriptor + i] =
+                                               fromBCD(scsiDev.data[descriptor + 4 + i]);
+                               }
+                               descriptor += 11;
+                       }
+
+               }
+
                if (len > allocationLength)
                {
                        len = allocationLength;
@@ -98,6 +247,27 @@ void doReadHeader(int MSF, uint32_t lba, uint16_t allocationLength)
        }
 }
 
+static uint8_t SimpleHeader[] =
+{
+       0x01, // 2048byte user data, L-EC in 288 byte aux field.
+       0x00, // reserved
+       0x00, // reserved
+       0x00, // reserved
+       0x00,0x00,0x00,0x00 // Track start sector (LBA or MSF)
+};
+
+void doReadHeader(int MSF, uint32_t lba, uint16_t allocationLength)
+{
+       uint32_t len = sizeof(SimpleHeader);
+       memcpy(scsiDev.data, SimpleHeader, len);
+       if (len > allocationLength)
+       {
+               len = allocationLength;
+       }
+       scsiDev.dataLen = len;
+       scsiDev.phase = DATA_IN;
+}
+
 
 // Handle direct-access scsi device commands
 int scsiCDRomCommand()
@@ -116,7 +286,24 @@ int scsiCDRomCommand()
                                (((uint32_t) scsiDev.cdb[7]) << 8) +
                                scsiDev.cdb[8];
 
-                       doReadTOC(MSF, track, allocationLength);
+                       // Reject MMC commands for now, otherwise the TOC data format
+                       // won't be understood.
+                       // The "format" field is reserved for SCSI-2
+                       uint8_t format = scsiDev.cdb[2] & 0x0F;
+                       switch (format)
+                       {
+                               case 0: doReadTOC(MSF, track, allocationLength); break; // SCSI-2
+                               case 1: doReadSessionInfo(MSF, allocationLength); break; // MMC2
+                               case 2: doReadFullTOC(0, track, allocationLength); break; // MMC2
+                               case 3: doReadFullTOC(1, track, allocationLength); break; // MMC2
+                               default:
+                               {
+                                       scsiDev.status = CHECK_CONDITION;
+                                       scsiDev.target->sense.code = ILLEGAL_REQUEST;
+                                       scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB;
+                                       scsiDev.phase = STATUS;
+                               }
+                       }
                }
                else if (command == 0x44)
                {
index 492181a..4b009c8 100755 (executable)
@@ -29,7 +29,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x0401;\r
+static const uint16_t FIRMWARE_VERSION = 0x0403;\r
 \r
 enum USB_ENDPOINTS\r
 {\r
index ec28f98..0329e99 100755 (executable)
@@ -165,7 +165,9 @@ static void doReadCapacity()
 \r
 static void doWrite(uint32 lba, uint32 blocks)\r
 {\r
-       if (blockDev.state & DISK_WP)\r
+       if ((blockDev.state & DISK_WP) ||\r
+               (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL))\r
+\r
        {\r
                scsiDev.status = CHECK_CONDITION;\r
                scsiDev.target->sense.code = ILLEGAL_REQUEST;\r
index 2067297..5420beb 100755 (executable)
@@ -185,6 +185,8 @@ void scsiInquiry()
                        scsiDev.data[0] = 0x05; // device type\r
                        scsiDev.data[1] |= 0x80; // Removable bit.\r
                        break;\r
+\r
+               case CONFIG_FLOPPY_14MB:\r
                case CONFIG_REMOVEABLE:\r
                        scsiDev.data[1] |= 0x80; // Removable bit.\r
                        break;\r
index 5538cb4..56f34d7 100755 (executable)
@@ -150,11 +150,37 @@ static void doModeSense(
                int idx = 1;\r
                if (!sixByteCmd) ++idx;\r
 \r
-               scsiDev.data[idx++] = 0; // Medium type. 0 = default\r
+               uint8_t mediumType = 0;\r
+               uint8_t deviceSpecificParam = 0;\r
+               uint8_t density = 0;\r
+               switch (scsiDev.target->cfg->deviceType == CONFIG_OPTICAL)\r
+               {\r
+               case CONFIG_FIXED:\r
+               case CONFIG_REMOVEABLE:\r
+                       mediumType = 0; // We should support various floppy types here!\r
+                       // Contains cache bits (0) and a Write-Protect bit.\r
+                       deviceSpecificParam =\r
+                               (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+                       density = 0; // reserved for direct access\r
+                       break;\r
+\r
+               case CONFIG_FLOPPY_14MB:\r
+                       mediumType = 0x1E; // 90mm/3.5"\r
+                       deviceSpecificParam =\r
+                               (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+                       density = 0; // reserved for direct access\r
+                       break;\r
+\r
+               case CONFIG_OPTICAL:\r
+                       mediumType = 0x02; // 120mm CDROM, data only.\r
+                       deviceSpecificParam = 0;\r
+                       density = 0x01; // User data only, 2048bytes per sector.\r
+                       break;\r
+\r
+               };\r
 \r
-               // Device-specific parameter. Contains cache bits (0) and\r
-               // a Write-Protect bit.\r
-               scsiDev.data[idx++] = (blockDev.state & DISK_WP) ? 0x80 : 0;\r
+               scsiDev.data[idx++] = mediumType;\r
+               scsiDev.data[idx++] = deviceSpecificParam;\r
 \r
                if (sixByteCmd)\r
                {\r
@@ -189,7 +215,7 @@ static void doModeSense(
                ////////////////////////////////////\r
                if (!dbd)\r
                {\r
-                       scsiDev.data[idx++] = 0; // Density code. Reserved for direct-access\r
+                       scsiDev.data[idx++] = density;\r
                        // Number of blocks\r
                        // Zero == all remaining blocks shall have the medium\r
                        // characteristics specified.\r
index 25a3815..b507bd3 100755 (executable)
@@ -668,7 +668,7 @@ static void process_MessageOut()
                }\r
 \r
                scsiDev.lun = scsiDev.msgOut & 0x7;\r
-               scsiDev.discPriv =\r
+               scsiDev.discPriv = \r
                        ((scsiDev.msgOut & 0x40) && (scsiDev.initiatorId >= 0))\r
                                ? 1 : 0;\r
        }\r
index 2045a12..9d0ffff 100755 (executable)
Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ
index 2c28d90..cbc85a9 100644 (file)
@@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used))
 const uint8 cy_meta_loadable[] = {
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
-    0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x01u, 0x04u,
+    0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x03u, 0x04u,
     0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
     0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
index 0ccf4be..efc7483 100644 (file)
Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit differ
index e533583..f9d8dc1 100755 (executable)
Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v4/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ
index c611288..2ca053a 100755 (executable)
@@ -91,7 +91,8 @@ typedef enum
 {
        CONFIG_FIXED,
        CONFIG_REMOVEABLE,
-       CONFIG_OPTICAL
+       CONFIG_OPTICAL,
+       CONFIG_FLOPPY_14MB
 } CONFIG_TYPE;
 
 typedef struct __attribute__((packed))
index f4526b9..9055460 100644 (file)
@@ -90,10 +90,15 @@ ConfigUtil::Default(size_t targetIdx)
                config.scsiId = config.scsiId | CONFIG_TARGET_ENABLED;
        }
        config.deviceType = CONFIG_FIXED;
-       config.flags = CONFIG_ENABLE_PARITY | CONFIG_ENABLE_UNIT_ATTENTION;
+
+       // Default to maximum fail-safe options.
+       config.flags = 0;// CONFIG_ENABLE_PARITY | CONFIG_ENABLE_UNIT_ATTENTION;
        config.pad0 = 0;
        config.sdSectorStart = 0;
-       config.scsiSectors = 2147483648; // 1TB
+
+       // Default to 2GB. Many systems have trouble with > 2GB disks, and
+       // a few start to complain at 1GB.
+       config.scsiSectors = 4194303; // 2GB - 1 sector
        config.bytesPerSector = 512;
        config.sectorsPerTrack = 63;
        config.headsPerCylinder = 255;
index f5ccdbf..d1ae745 100755 (executable)
@@ -8,7 +8,9 @@ LDFLAGS += -L$(BUILD)/libzipper/.libs -lzipper -L$(BUILD)/zlib -lz
 LIBZIPPER_CONFIG = --disable-shared LDFLAGS="-L../zlib" CPPFLAGS="-I../zlib"
 
 # wxWidgets 3.0.2 uses broken Webkit headers under OSX Yosemeti
+# liblzma not available on OSX 10.7
 WX_CONFIG=--disable-webkit --disable-webviewwebkit  \
+       --without-libtiff --without-libjbig --without-liblzma --without-opengl \
        --enable-monolithic --enable-stl --disable-shared
 
 TARGET ?= $(shell uname -s)
index f84f91d..594b91c 100644 (file)
@@ -102,7 +102,13 @@ TargetPanel::TargetPanel(wxWindow* parent, const TargetConfig& initialConfig) :
        Bind(wxEVT_SPINCTRL, &TargetPanel::onInput<wxSpinEvent>, this, ID_scsiIdCtrl);
 
        fgs->Add(new wxStaticText(this, wxID_ANY, wxT("Device Type")));
-       wxString deviceTypes[] = {wxT("Hard Drive"), wxT("Removable"), wxT("CDROM")};
+       wxString deviceTypes[] =
+       {
+               wxT("Hard Drive"),
+               wxT("Removable"),
+               wxT("CDROM"),
+               wxT("3.5\" Floppy")
+       };
        myDeviceTypeCtrl =
                new wxChoice(
                        this,
@@ -304,6 +310,41 @@ TargetPanel::evaluate()
        bool valid = true;
        std::stringstream conv;
 
+       bool enabled = myEnableCtrl->IsChecked();
+       {
+               myScsiIdCtrl->Enable(enabled);
+               myDeviceTypeCtrl->Enable(enabled);
+               myParityCtrl->Enable(enabled);
+               myUnitAttCtrl->Enable(enabled);
+               myStartSDSectorCtrl->Enable(enabled && !myAutoStartSectorCtrl->IsChecked());
+               myAutoStartSectorCtrl->Enable(enabled);
+               mySectorSizeCtrl->Enable(enabled);
+               myNumSectorCtrl->Enable(enabled);
+               mySizeCtrl->Enable(enabled);
+               mySizeUnitCtrl->Enable(enabled);
+               myVendorCtrl->Enable(enabled);
+               myProductCtrl->Enable(enabled);
+               myRevisionCtrl->Enable(enabled);
+               mySerialCtrl->Enable(enabled);
+       }
+
+       switch (myDeviceTypeCtrl->GetSelection())
+       {
+       case CONFIG_OPTICAL:
+               mySectorSizeCtrl->ChangeValue("2048");
+               mySectorSizeCtrl->Enable(false);
+               break;
+       case CONFIG_FLOPPY_14MB:
+               mySectorSizeCtrl->ChangeValue("512");
+               mySectorSizeCtrl->Enable(false);
+               myNumSectorCtrl->ChangeValue("2880");
+               myNumSectorCtrl->Enable(false);
+               mySizeUnitCtrl->Enable(false);
+               mySizeCtrl->Enable(false);
+               break;
+       };
+       evaluateSize();
+
        if (myAutoStartSectorCtrl->IsChecked())
        {
                std::stringstream ss; ss << myAutoStartSector;
@@ -393,23 +434,6 @@ TargetPanel::evaluate()
                mySerialMsg->SetLabelMarkup("");
        }
 
-       bool enabled = myEnableCtrl->IsChecked();
-       {
-               myScsiIdCtrl->Enable(enabled);
-               myDeviceTypeCtrl->Enable(enabled);
-               myParityCtrl->Enable(enabled);
-               myUnitAttCtrl->Enable(enabled);
-               myStartSDSectorCtrl->Enable(enabled && !myAutoStartSectorCtrl->IsChecked());
-               myAutoStartSectorCtrl->Enable(enabled);
-               mySectorSizeCtrl->Enable(enabled);
-               myNumSectorCtrl->Enable(enabled);
-               mySizeCtrl->Enable(enabled);
-               mySizeUnitCtrl->Enable(enabled);
-               myVendorCtrl->Enable(enabled);
-               myProductCtrl->Enable(enabled);
-               myRevisionCtrl->Enable(enabled);
-               mySerialCtrl->Enable(enabled);
-       }
        return valid || !enabled;
 }
 
@@ -423,49 +447,51 @@ TargetPanel::onInput(EvtType& event)
 void
 TargetPanel::onSizeInput(wxCommandEvent& event)
 {
-       if (event.GetId() == ID_numSectorCtrl)
-       {
-               uint32_t numSectors;
-               std::stringstream conv;
-               conv << myNumSectorCtrl->GetValue();
-               conv >> numSectors;
-
-               conv.str(""); conv.clear();
-
-               if (conv)
-               {
-                       uint64_t bytes =
-                               uint64_t(numSectors) *
-                                       CtrlGetValue<uint16_t>(mySectorSizeCtrl).first;
-
-                       if (bytes >= 1024 * 1024 * 1024)
-                       {
-                               conv << (bytes / (1024.0 * 1024 * 1024));
-                               mySizeUnitCtrl->SetSelection(UNIT_GB);
-                       }
-                       else if (bytes >= 1024 * 1024)
-                       {
-                               conv << (bytes / (1024.0 * 1024));
-                               mySizeUnitCtrl->SetSelection(UNIT_MB);
-                       }
-                       else
-                       {
-                               conv << (bytes / 1024.0);
-                               mySizeUnitCtrl->SetSelection(UNIT_KB);
-                       }
-                       mySizeCtrl->ChangeValue(conv.str());
-               }
-       }
-       else
+       if (event.GetId() != ID_numSectorCtrl)
        {
                std::stringstream ss;
                ss << convertUnitsToSectors().first;
                myNumSectorCtrl->ChangeValue(ss.str());
        }
-
+       evaluateSize();
        onInput(event); // propagate
 }
 
+void
+TargetPanel::evaluateSize()
+{
+       uint32_t numSectors;
+       std::stringstream conv;
+       conv << myNumSectorCtrl->GetValue();
+       conv >> numSectors;
+
+       conv.str(""); conv.clear();
+
+       if (conv)
+       {
+               uint64_t bytes =
+                       uint64_t(numSectors) *
+                               CtrlGetValue<uint16_t>(mySectorSizeCtrl).first;
+
+               if (bytes >= 1024 * 1024 * 1024)
+               {
+                       conv << (bytes / (1024.0 * 1024 * 1024));
+                       mySizeUnitCtrl->SetSelection(UNIT_GB);
+               }
+               else if (bytes >= 1024 * 1024)
+               {
+                       conv << (bytes / (1024.0 * 1024));
+                       mySizeUnitCtrl->SetSelection(UNIT_MB);
+               }
+               else
+               {
+                       conv << (bytes / 1024.0);
+                       mySizeUnitCtrl->SetSelection(UNIT_KB);
+               }
+               mySizeCtrl->ChangeValue(conv.str());
+       }
+}
+
 std::pair<uint32_t, bool>
 TargetPanel::convertUnitsToSectors() const
 {
index 7639f62..faf3d66 100644 (file)
@@ -66,6 +66,7 @@ public:
 private:
        template<typename EvtType> void onInput(EvtType& event);
        void onSizeInput(wxCommandEvent& event);
+       void evaluateSize();
 
        std::pair<uint32_t, bool> convertUnitsToSectors() const;