From nobody Tue Nov 4 22:05:03 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530815181590603.4408467120103; Thu, 5 Jul 2018 11:26:21 -0700 (PDT) Received: from localhost ([::1]:54299 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fb8xQ-0000NG-Po for importer@patchew.org; Thu, 05 Jul 2018 14:26:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fb8rg-0004NC-RM for qemu-devel@nongnu.org; Thu, 05 Jul 2018 14:20:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fb8rf-0006Cx-Kq for qemu-devel@nongnu.org; Thu, 05 Jul 2018 14:20:24 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:40482) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fb8rf-0006CH-Cl for qemu-devel@nongnu.org; Thu, 05 Jul 2018 14:20:23 -0400 Received: by mail-pf0-x242.google.com with SMTP id z24-v6so6131448pfe.7 for ; Thu, 05 Jul 2018 11:20:23 -0700 (PDT) Received: from localhost.localdomain (c-73-158-53-43.hsd1.ca.comcast.net. [73.158.53.43]) by smtp.gmail.com with ESMTPSA id g75-v6sm14170847pfg.145.2018.07.05.11.20.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Jul 2018 11:20:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=geb7wkrTy69hhxPs6pvzHV1uV+AiOxc6zIx/4mjRWwo=; b=teT82R/gwtI8+b6kRQYg3PDbmc1sS2+Gy2EnkWQXn6PYnMn8LxM1/F+Xur2EC0YgJX isCb/0UnRi2fZUS8RIZQ8aVo7K7d9ExyNlSEbiW+x+nFSWGQumqifwfjzh4NJXLQS/tK 3v/xxFw7kToPdgYpHeVrC/TjO6BJY/W3tsEGmAA+u1NITSt6njgKKAIiXinX8RgiOBeq RlNM1a2yJcz5wV3yuZ0xK5ZE6ohaoxvMqzSwNIJWST2LoM4nnE514spOPjgq49JaSvZz 5fFXs0jwNS8N6IlND0LynNd9raazlKUjSaaQhRFYgXDqvLmWIYflqFhN45VKQUxb5KpR QbqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=geb7wkrTy69hhxPs6pvzHV1uV+AiOxc6zIx/4mjRWwo=; b=jCMR7/q1izVRf4Uof2PqwU41VezAe4b6OWwKKSPKW/0DTWmqgdmoD4eQSKADxUhpxk nGQM3BOMfPSAt0+hSVHA3cxHGzmnYe/efeYSJh8goVBsqldxkhSUcS7Dnkhe4317SpR/ QG1qlMCtNTG0ZSzdiNP9Rq+DDcw2OfxxyOssI+HEQvgXxrscjcCDMkQZwC3gbOimp2Cx sZ5ZLgw/IbJW8Fesn4UJ3jzHG3E7ggJRlokUtkdOftcke7G40Cu4QuCPxu2ibS6OYYLF 0dM4a9e2utu0C1bMX93Yqy3TMy++tFaqyCBdafYz9R15zS4iiaV5Je3qi58mMC15nPt0 uH/A== X-Gm-Message-State: APt69E0y7YL6sR1P3fQFVbKNIrpX4pzqc7faC5WxCwbeX0f1strCRXPa SGM/71NlSj1lORNmhEFIsrliVA== X-Google-Smtp-Source: AAOMgpcKQxxH+YPKjR2hLWB52njJgqiUg+3qDvnOuTTtNLRMBKMcrDDMJDQ1lFHDLdfp7XY7mLUNTA== X-Received: by 2002:a63:2e81:: with SMTP id u123-v6mr6540394pgu.225.1530814822513; Thu, 05 Jul 2018 11:20:22 -0700 (PDT) From: Michael Davidsaver To: Peter Maydell , Paolo Bonzini Date: Thu, 5 Jul 2018 11:19:52 -0700 Message-Id: <20180705182001.16537-6-mdavidsaver@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180705182001.16537-1-mdavidsaver@gmail.com> References: <20180705182001.16537-1-mdavidsaver@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::242 Subject: [Qemu-devel] [PATCH 05/14] timer: ds1338 change write handling and fix wday_offset handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antoine Mathys , Thomas Huth , Michael Davidsaver , qemu-devel@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" instead of a read-modify-write, do direct translation of device registers to struct tm members. This new ds1338_update() is the reverse of the existing capture_current_time(). Simplifies later handling of CENTURY bit in similar Dallas RTC chips. Correctly handle different real weekday in guest and host timezones. Allow guest to use any day as start of week (day 1). eg. Monday instead of Sunday. Signed-off-by: Michael Davidsaver --- hw/timer/ds1338.c | 95 ++++++++++++++++++++++++++++-----------------------= ---- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/hw/timer/ds1338.c b/hw/timer/ds1338.c index 637a0f4246..0134ffd72a 100644 --- a/hw/timer/ds1338.c +++ b/hw/timer/ds1338.c @@ -110,7 +110,10 @@ static void capture_current_time(DS1338State *s) /* 24 hour mode. */ s->nvram[R_HOUR] =3D to_bcd(now.tm_hour); } - s->nvram[R_WDAY] =3D (now.tm_wday + s->wday_offset) % 7 + 1; + s->nvram[R_WDAY] =3D (now.tm_wday + s->wday_offset) % 7; + if (s->nvram[R_WDAY] =3D=3D 0) { + s->nvram[R_WDAY] =3D 7; + } s->nvram[R_DATE] =3D to_bcd(now.tm_mday); s->nvram[R_MONTH] =3D to_bcd(now.tm_mon + 1); s->nvram[R_YEAR] =3D to_bcd(now.tm_year - 100); @@ -161,6 +164,46 @@ static int ds1338_recv(I2CSlave *i2c) return res; } =20 +/* call after guest writes to current time registers + * to re-compute our offset from host time. + */ +static void ds1338_update(DS1338State *s) +{ + + struct tm now =3D {}; + + /* TODO: Implement CH (stop) bit? */ + now.tm_sec =3D from_bcd(s->nvram[R_SEC] & 0x7f); + now.tm_min =3D from_bcd(s->nvram[R_MIN] & 0x7f); + if (ARRAY_FIELD_EX32(s->nvram, HOUR, SET12)) { + /* 12 hour (1-12) */ + /* read and wrap 1-12 -> 0-11 */ + now.tm_hour =3D from_bcd(ARRAY_FIELD_EX32(s->nvram, HOUR, HOUR12))= % 12u; + if (ARRAY_FIELD_EX32(s->nvram, HOUR, AMPM)) { + now.tm_hour +=3D 12; + } + + } else { + now.tm_hour =3D from_bcd(ARRAY_FIELD_EX32(s->nvram, HOUR, HOUR24)); + } + now.tm_wday =3D from_bcd(s->nvram[R_WDAY]) - 1u; + now.tm_mday =3D from_bcd(s->nvram[R_DATE] & 0x3f); + now.tm_mon =3D from_bcd(s->nvram[R_MONTH] & 0x1f) - 1; + now.tm_year =3D from_bcd(s->nvram[R_YEAR]) + 100; + s->offset =3D qemu_timedate_diff(&now); + + { + /* Round trip to get real wday_offset based on time delta and + * ref. timezone. + * Race if midnight (in ref. timezone) happens here. + */ + int user_wday =3D now.tm_wday; + qemu_get_timedate(&now, s->offset); + + s->wday_offset =3D (user_wday - now.tm_wday) % 7 + 1; + } +} + static int ds1338_send(I2CSlave *i2c, uint8_t data) { DS1338State *s =3D DS1338(i2c); @@ -170,52 +213,7 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) s->addr_byte =3D false; return 0; } - if (s->ptr < 7) { - /* Time register. */ - struct tm now; - qemu_get_timedate(&now, s->offset); - switch(s->ptr) { - case R_SEC: - /* TODO: Implement CH (stop) bit. */ - now.tm_sec =3D from_bcd(data & 0x7f); - break; - case R_MIN: - now.tm_min =3D from_bcd(data & 0x7f); - break; - case R_HOUR: - if (FIELD_EX32(data, HOUR, SET12)) { - /* 12 hour (1-12) */ - /* read and wrap 1-12 -> 0-11 */ - now.tm_hour =3D from_bcd(FIELD_EX32(data, HOUR, HOUR12)) %= 12u; - if (FIELD_EX32(data, HOUR, AMPM)) { - now.tm_hour +=3D 12; - } - - } else { - now.tm_hour =3D from_bcd(FIELD_EX32(data, HOUR, HOUR24)); - } - break; - case R_WDAY: - { - /* The day field is supposed to contain a value in - the range 1-7. Otherwise behavior is undefined. - */ - int user_wday =3D (data & 7) - 1; - s->wday_offset =3D (user_wday - now.tm_wday + 7) % 7; - } - break; - case R_DATE: - now.tm_mday =3D from_bcd(data & 0x3f); - break; - case R_MONTH: - now.tm_mon =3D from_bcd(data & 0x1f) - 1; - break; - case R_YEAR: - now.tm_year =3D from_bcd(data) + 100; - break; - } - s->offset =3D qemu_timedate_diff(&now); - } else if (s->ptr =3D=3D R_CTRL) { + if (s->ptr =3D=3D R_CTRL) { /* Control register. */ =20 /* Ensure bits 2, 3 and 6 will read back as zero. */ @@ -227,6 +225,9 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data) =20 } s->nvram[s->ptr] =3D data; + if (s->ptr <=3D R_YEAR) { + ds1338_update(s); + } inc_regptr(s); return 0; } --=20 2.11.0