From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572290643; cv=none; d=zoho.com; s=zohoarc; b=I/HmRiNDoxys1jKTHJyiOOqeWVU4VaDLD/+n4F2jvytX3l4n/OzbpEom6IuDazHdahMpH8PTTGhHJzxJRbU0fn/N/9FoUOcqetXR7iwRjrxkoOvC0ek/g44kIi32i8WqWulucnfWu8unChRDEpQILTXXREC8vGTGUjSDusKldfc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572290643; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=22N6BBq2i6lNEoqq8rHHuSUULqCZBsIc3THfZ0Df2vs=; b=VDAW6DHt5cu2tsPCMfNCMCvkFiOwTlQjxnzfF/oa2v8HJc2qKxXj2mPrYbZqOjUodWNpykF+C5P0Ry/D0+Y9l1pPgdIQQQ7TKIEuFeGNSvsIWqJHJSHNza9Mi3/vfxuS3nyHvWbFH9MqblJ/SSHyuT4Xccl4kCTL5ij2JyuruoI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572290643502891.7064712815237; Mon, 28 Oct 2019 12:24:03 -0700 (PDT) Received: from localhost ([::1]:54424 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAcR-00067B-T2 for importer@patchew.org; Mon, 28 Oct 2019 15:23:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56483) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zj-0002ah-L5 for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zi-0003yM-GA for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:07 -0400 Received: from mout.kundenserver.de ([217.72.192.73]:43407) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zi-0003vl-6y; Mon, 28 Oct 2019 14:17:06 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MzQTm-1i3LMJ2Sxc-00vPK3; Mon, 28 Oct 2019 19:16:51 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 01/11] esp: move handle_ti_cmd() cleanup code to esp_do_dma(). Date: Mon, 28 Oct 2019 19:16:33 +0100 Message-Id: <20191028181643.5143-2-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:f0f3VsU7pIFM9a0tTGFuUNiJCy/m45d8E/qz8yT6lnKpRSFjbRG 90MtUWzuSSGx0K+fzbLNikmDGZMvhLyIeHOanKpj10uBM6a4KWfbcqhNce/+zXD8yinoSOd K+m7Bse0uBhoYxj0BtO6JvcbTzEUN6RyWBORMqB0yRsZbZwsYZJ4aQtTaGL579KBGQrUlux hrhHXvSwmsc2U2nxzHqzw== X-UI-Out-Filterresults: notjunk:1;V03:K0:TdhUQeu37QY=:0vykORaRaQJSnqCl/48wEg j5RVfxPZKnbPIVyUYI7sJOlgsW5iDbHHJ1bfrv6FUZOwEyjN76RL2DCuKCFSTcch7P7mw/Ngw iTnVFMcv5gG+2mB0W62l6SX/k7WAoUIzjd1fYpWs538XxvvY7v8GlfwgubpQhYpxne5a5Z76W XckECgTiirf26FnyNtKBsuc8cicyY1JKmnJutrRMarACo4ti638fBxmsU9Ue6HGx8mgLHsU5r g2otDC3RgIgZ1Qv2NB5c9rfKs80vdnyRza8KZJDGe+vPyaDob8/8n2Ht5C/5wqbzBmZ+pjdmt lGSweUB+8NhL3wc3WBIJWuI1EtvEGu12ualAziCYAl1bdE/78efwKrlfrGfe14y0OIib4iIwZ qDiBU8ICuJgKPcUoGfIyBfDwsD/VV+Ka8j/CdJ8vj0OI1ABLuEAzq4JJVUeeFS1LCIAu7OVqq cwrj1Hrj57ovsi2yWQS1lEiH7GM12o1gLafwN9xBnFVhDtJBQjWi96511+40LXQH+Hk5Ibu2Q /uYVCzATOnbc2A4vrWZ6z8fErf6GBiCZ/PUHUJL0re/WkQr9ADzXOtddmKJ0I+4RAqmMMn+Z7 rndsKYHnMeLgKgZu8SkYB7T2DX+yWRyHCiv1uXTv/jXWCg1HWF92FCQPC2baQOvITVLC0rBgg gJbcDy1R7l+3vsZH+Oe+RMo3LTArYA4O9lALxAQwReQql8ff5rC0V0lDsKX8OpOORAtTAF+SE KnvFHwi474oWh4bvkmorkSRqhSFbtdGGCgqk05Hc23X6eGepc+RrytH8CvYPY5p/rCGlC+DFz dHJf+PgOeHPVo17eZP52RUFbPpPw/ZIzIyD+OOQBWTuuNhx8ejtew8hXrp3YTC6aQ8wS4NqT8 5YWZLQaz8QYaDedeNZZg== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.73 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Laurent Vivier , Max Reitz , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" To prepare following patches move do_cmd and DMA special case from handle_ti() to esp_do_dma(). This part of the code must be only executed with real DMA, not with pseudo-DMA. And PDMA is detected in esp_do_dma(), so move this part of the code in esp_do_dma(). We keep the code in handle_ti_cmd() in the case no DMA is done. Signed-off-by: Laurent Vivier Acked-by: Paolo Bonzini Message-Id: <20191026164546.30020-2-laurent@vivier.eu> --- hw/scsi/esp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 841d79b60e..09b28cba17 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -249,10 +249,19 @@ static void esp_do_dma(ESPState *s) =20 len =3D s->dma_left; if (s->do_cmd) { + /* + * handle_ti_cmd() case: esp_do_dma() is called only from + * handle_ti_cmd() with do_cmd !=3D NULL (see the assert()) + */ trace_esp_do_dma(s->cmdlen, len); assert (s->cmdlen <=3D sizeof(s->cmdbuf) && len <=3D sizeof(s->cmdbuf) - s->cmdlen); s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); + trace_esp_handle_ti_cmd(s->cmdlen); + s->ti_size =3D 0; + s->cmdlen =3D 0; + s->do_cmd =3D 0; + do_cmd(s, s->cmdbuf); return; } if (s->async_len =3D=3D 0) { @@ -373,8 +382,7 @@ static void handle_ti(ESPState *s) s->dma_left =3D minlen; s->rregs[ESP_RSTAT] &=3D ~STAT_TC; esp_do_dma(s); - } - if (s->do_cmd) { + } else if (s->do_cmd) { trace_esp_handle_ti_cmd(s->cmdlen); s->ti_size =3D 0; s->cmdlen =3D 0; --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572288228; cv=none; d=zoho.com; s=zohoarc; b=NmgjCiJ/wvO/2jALB/iruk5pfj09RC8/TYkfP65roRqZf2NjsTSXhiEq1CTP3rumfeh9M3DC3XYpFojJo92TVucUFWTZhh4qkelbXyShUSSThnIGcGsH6IED572RRleaWdiPe3J2oIHgHD3hC+94Ua5uGDDjUIhMOp/23rpLTJM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572288228; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=OcAYN4jJLYaQIPy45AhWPPmY62tFiXjwaV/Pm32405I=; b=QpkUb2AKRtTLJl+o8ocrZY6WZhg4SE18xg+KtD81jbPSWioN7E6HG1sKLybv9iUmMOutkgYhqiCRXiaUjCmQII2mrhPOCR7T0LyGGPFy+tIoAp8+wxEOy/tHT7TevDb1m1nF7MlObqxx6m/sz+8aplqE3dcUpr0i1N7nUYoNpZc= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572288228520403.0796611231933; Mon, 28 Oct 2019 11:43:48 -0700 (PDT) Received: from localhost ([::1]:46704 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9zT-0003aB-Ei for importer@patchew.org; Mon, 28 Oct 2019 14:43:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56455) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zh-0002YO-Vh for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zg-0003xD-LO for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:05 -0400 Received: from mout.kundenserver.de ([217.72.192.73]:37703) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zg-0003w4-Bq; Mon, 28 Oct 2019 14:17:04 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MpUpW-1hdxG41tG8-00psSJ; Mon, 28 Oct 2019 19:16:52 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 02/11] esp: move get_cmd() post-DMA code to get_cmd_cb() Date: Mon, 28 Oct 2019 19:16:34 +0100 Message-Id: <20191028181643.5143-3-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:KoHlabvA03FPSJtuk/zidWr5y9K83Kjw8M/6QBYO9SOrVlvEj0q Y+Fx2srY+x9yshKO/JHF0k3ROtiME7Vy+nBvUC0FFcLIxPABVCuf54y1pKWQHp9vdTOBx1T KnWPh9qksyK61U687NLS6gPWAyG3GO6kApNJ2vT7ZjiEWt+tNL/tniilDPB5aBS72OPP4Ux FZY20yGhpgaS2S6JALd/A== X-UI-Out-Filterresults: notjunk:1;V03:K0:/AS9RZQHuQ0=:gn5w/ToHbGeW7B0irQRTDi AsUS4MNxHANf041FJEQqpqD+MUJCr3rVlFha10fEkyJv4cKLbHxh4OHGIKKzwUoZ09hJmz/bU UeG5LY/Edonh7c8wN7Ja0bTmZdgbxPVHaQhNalhIh7GF+vkW+sRn3j61iHR+SfA5Ue94VpEWS dqzaH3xPLxRuDhlKSUf/oYje0HkfAE8TzZYOdUTi0Jjkb/CEQOqFeYwT5QgN4gRnZQTZv59zW bPG51kYUj6+umEaI4e1PiC8w7nJD4/fvJFPNCZ65w6Xyw2HGKt3uqH2sMKA7VYqXUTS1LZkeg KerEsMKZY16Hzaxt/0xZcWKRiHgtqZZfJhcoxtfCve3D+ADXRK4La2w9vB8N1m4XzZ9ri/cy2 GLMa4EmssZMVQd04z80wb299IsoG109WCe6ORU9YnbfAjXwotCqOTLHcVXQmFxbewo1+jEaIQ koakGuYK1+IJeNhy0ZXIzfV8jaZog+pXKhemcirURI+E14UWIPhqBEFfh3jqK/vl/zGKJtda9 z0rFyIt2eqtt6/sZKnYoNxzV8xTOh0DJr2As/6w7uuJwWyRDoDEyE1zrXTZUpjWoVszGLrcMO hfyEPHBoeVAV2zgPrB0W+oe/mY6/BNx8dwXFlT+zB+lkyRvBenxj4bG5Z0fdVySCtx+j0eXyH iInbs2HgaVok5SzpxLo5s2IszbRKPbkOX5lQpfaxOOp6mA/dyiTSBjrBxeBmBrl3AGBISEhuh Qro+3vymdKwQNKpHRhKiSEKda2FIoOcw5SStyrCXEse+62H4kRzJSSMwGjteRAq+SLy4llMvb 3SnaXTJ9MvbW4qBxkLczAhjxKRvmepHkk8ucvP9ebY393hL3r3wl/i2GBtJI4HmkOPn4T36xO /PNJMkTo8CvR6IlVpskl0kK9mYS6T0rht8128yTSY= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.73 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Laurent Vivier , Max Reitz , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" This will be needed to implement pseudo-DMA Signed-off-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daud=C3=A9 Acked-by: Paolo Bonzini Message-Id: <20191026164546.30020-3-laurent@vivier.eu> --- hw/scsi/esp.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 09b28cba17..0230ede21d 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -84,6 +84,34 @@ void esp_request_cancelled(SCSIRequest *req) } } =20 +static int get_cmd_cb(ESPState *s) +{ + int target; + + target =3D s->wregs[ESP_WBUSID] & BUSID_DID; + + s->ti_size =3D 0; + s->ti_rptr =3D 0; + s->ti_wptr =3D 0; + + if (s->current_req) { + /* Started a new command before the old one finished. Cancel it. = */ + scsi_req_cancel(s->current_req); + s->async_len =3D 0; + } + + s->current_dev =3D scsi_device_find(&s->bus, 0, target, 0); + if (!s->current_dev) { + /* No such drive */ + s->rregs[ESP_RSTAT] =3D 0; + s->rregs[ESP_RINTR] =3D INTR_DC; + s->rregs[ESP_RSEQ] =3D SEQ_0; + esp_raise_irq(s); + return -1; + } + return 0; +} + static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen) { uint32_t dmalen; @@ -108,23 +136,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uin= t8_t buflen) } trace_esp_get_cmd(dmalen, target); =20 - s->ti_size =3D 0; - s->ti_rptr =3D 0; - s->ti_wptr =3D 0; - - if (s->current_req) { - /* Started a new command before the old one finished. Cancel it. = */ - scsi_req_cancel(s->current_req); - s->async_len =3D 0; - } - - s->current_dev =3D scsi_device_find(&s->bus, 0, target, 0); - if (!s->current_dev) { - // No such drive - s->rregs[ESP_RSTAT] =3D 0; - s->rregs[ESP_RINTR] =3D INTR_DC; - s->rregs[ESP_RSEQ] =3D SEQ_0; - esp_raise_irq(s); + if (get_cmd_cb(s) < 0) { return 0; } return dmalen; --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572290835; cv=none; d=zoho.com; s=zohoarc; b=CWGg9Y9pTMygOpLqMIu5rQEiqRdqdHuTiRUzP+28EM9FwmgmQcPZZKeNQQA7xuBtls6oof9Uv2C3KMQfv509ZGxxrj+wmD8N5lss4PWc4QfWHXbQR8Ue6uN+38ZI4U566zEjj4pfNZpeoTfN9c0ksK/yslPAGksHbdwgeBtKhG8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572290835; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ISHfz20tW6LwkBIyna00/ERW9M0r9Drm/pRbs4MdYc4=; b=HIKnNYOg3Lm2JfhUtjW83qQV54NlD5No0+94HrEUd3Npqz4lCgFnBuIBi1OsWGpubBx71d0DcTgOzievtsDfnEkbGfMnnz4xqfPLl5XwQva6i2ZSvGwvE7by+GvGv259uYzLL3mk7AYAtdhswjNamDsxmCk1DjCYinCYNvPmosI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572290835886535.8850056636603; Mon, 28 Oct 2019 12:27:15 -0700 (PDT) Received: from localhost ([::1]:55154 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAfa-0002We-3e for importer@patchew.org; Mon, 28 Oct 2019 15:27:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56476) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zj-0002a8-6k for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zg-0003xJ-Mg for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:06 -0400 Received: from mout.kundenserver.de ([212.227.17.13]:59775) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zg-0003wr-CI; Mon, 28 Oct 2019 14:17:04 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MrxfX-1hbTLk22Nh-00nwVm; Mon, 28 Oct 2019 19:16:53 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 03/11] esp: add pseudo-DMA as used by Macintosh Date: Mon, 28 Oct 2019 19:16:35 +0100 Message-Id: <20191028181643.5143-4-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:AFOtUh6PpkpWFbg8mN1uNFzv/C1O9bAc9E5FGVIdwZXRe+g3Gom iLnTOiR3aFarDOkWbjI6Ure835PEVSNOb3jCxuxHs/qJthYvpEUhGhdIeRo6W+K2bmq7B+J M6ZVCkdf191fU7jr5jZb1qrI5SUxXki8CyifzERXGT3dhMHgI4IBtDWuHcFdhPFeFNi17Lc Gr+5hZOtEPxixn7YKBkfw== X-UI-Out-Filterresults: notjunk:1;V03:K0:CugUPy9Zr+Q=:MWOnvLISG49V0AeS4axXSL mpgc+rCcW1PpWM6y8iTsh96f07/nLpiGgKxBell7a42DLjVbHjv35JDCczIde/ZenfBWUdvSt JK7UXM68+d9O4qPHFUyyyB9Od1d2KgBxMOP0zG8VhUOrbBBUl049RP58B5C4CwLIaZx+Rt64i Xw29bp85Bf/7lsWNUUGDfsCm/pz+lETihvLIUdmOKVU1hx9yi5jC2volM6ZzMmdHbNzYktvf6 lHTpCMxCXam2hFzVvxkkuwGSfkgFkqOLS48XWD0fhB6EOBh3JWAZAK3XVMKW6vYPXLriHqoWF l4nhKYGG1iUVv1Wc1FZxluyyaD3AKFm5x8Aje1MBW8TwuIUOhLeYuRzJh7uiQ36hnKak07FGu MIrobLgIo2YLWuX9VR8DXjXLEtSrlhjMFl2z4wD+xOWjAmoJAo6EgK562V9QffI5AzUiiRPDU ClF7pi5SVkw+3p63DRV0oAN49O3nWJZizfuslaxUzmUJhTIulRa17I/Bfo/YyRQVT0k9xeKaV ZHxIb6w1w6mYjqVqgDCsr4FpLGBspD4dM0z82zexpoHve8+vnBClG9WUIzXJ3d433Wcd5cwY0 oewM7oDH2Ll4jSDimlkI15m+JnFte6Fiuq0CBkS6nsYkJtiKXGX7y21AuJaLq9zjM6SKSLEdE uclS2ffurxt4DNAtt5nr0GCFKF3I99su3rbQ8lb/LuF0LPeVo0SwWPjZ8heb88pNc1PqOVL0e X390cXQF1fYQAwsmwukS+woI5BHc0nN1jpuwGEk8fV00uOcVnxf0QN7kixtpp6nEwzdIFYmIZ nwUmBK648JHzYdDO9W+bfiRkZs8sozSk/MqjaKIjLMbCaG8MQ7l7J+tbiM5ZCjlW6FJg+y0Yn I48M8SAQjN9FmxpFlJuA== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , Paolo Bonzini , "Dr . David Alan Gilbert" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" There is no DMA in Quadra 800, so the CPU reads/writes the data from the PDMA register (offset 0x100, ESP_PDMA in hw/m68k/q800.c) and copies them to/from the memory. There is a nice assembly loop in the kernel to do that, see linux/drivers/scsi/mac_esp.c:MAC_ESP_PDMA_LOOP(). The start of the transfer is triggered by the DREQ interrupt (see linux mac_esp_send_pdma_cmd()), the CPU polls on the IRQ flag to start the transfer after a SCSI command has been sent (in Quadra 800 it goes through the VIA2, the via2-irq line and the vIFR register) The Macintosh hardware includes hardware handshaking to prevent the CPU from reading invalid data or writing data faster than the peripheral device can accept it. This is the "blind mode", and from the doc: "Approximate maximum SCSI transfer rates within a blocks are 1.4 MB per second for blind transfers in the Macintosh II" Some references can be found in: Apple Macintosh Family Hardware Reference, ISBN 0-201-19255-1 Guide to the Macintosh Family Hardware, ISBN-0-201-52405-8 Acked-by: Dr. David Alan Gilbert Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Acked-by: Paolo Bonzini Message-Id: <20191026164546.30020-4-laurent@vivier.eu> --- include/hw/scsi/esp.h | 15 +++ hw/scsi/esp.c | 278 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 284 insertions(+), 9 deletions(-) diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index adab63d1c9..6ba47dac41 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -14,10 +14,18 @@ typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque,= uint8_t *buf, int len); =20 typedef struct ESPState ESPState; =20 +enum pdma_origin_id { + PDMA, + TI, + CMD, + ASYNC, +}; + struct ESPState { uint8_t rregs[ESP_REGS]; uint8_t wregs[ESP_REGS]; qemu_irq irq; + qemu_irq irq_data; uint8_t chip_id; bool tchi_written; int32_t ti_size; @@ -48,6 +56,12 @@ struct ESPState { ESPDMAMemoryReadWriteFunc dma_memory_write; void *dma_opaque; void (*dma_cb)(ESPState *s); + uint8_t pdma_buf[32]; + int pdma_origin; + uint32_t pdma_len; + uint32_t pdma_start; + uint32_t pdma_cur; + void (*pdma_cb)(ESPState *s); }; =20 #define TYPE_ESP "esp" @@ -59,6 +73,7 @@ typedef struct { /*< public >*/ =20 MemoryRegion iomem; + MemoryRegion pdma; uint32_t it_shift; ESPState esp; } SysBusESPState; diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 0230ede21d..f8fc30cccb 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -38,6 +38,8 @@ * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C1= 00.txt * and * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9= X.txt + * + * On Macintosh Quadra it is a NCR53C96. */ =20 static void esp_raise_irq(ESPState *s) @@ -58,6 +60,16 @@ static void esp_lower_irq(ESPState *s) } } =20 +static void esp_raise_drq(ESPState *s) +{ + qemu_irq_raise(s->irq_data); +} + +static void esp_lower_drq(ESPState *s) +{ + qemu_irq_lower(s->irq_data); +} + void esp_dma_enable(ESPState *s, int irq, int level) { if (level) { @@ -84,6 +96,30 @@ void esp_request_cancelled(SCSIRequest *req) } } =20 +static void set_pdma(ESPState *s, enum pdma_origin_id origin, + uint32_t index, uint32_t len) +{ + s->pdma_origin =3D origin; + s->pdma_start =3D index; + s->pdma_cur =3D index; + s->pdma_len =3D len; +} + +static uint8_t *get_pdma_buf(ESPState *s) +{ + switch (s->pdma_origin) { + case PDMA: + return s->pdma_buf; + case TI: + return s->ti_buf; + case CMD: + return s->cmdbuf; + case ASYNC: + return s->async_buf; + } + return NULL; +} + static int get_cmd_cb(ESPState *s) { int target; @@ -125,7 +161,14 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uin= t8_t buflen) if (dmalen > buflen) { return 0; } - s->dma_memory_read(s->dma_opaque, buf, dmalen); + if (s->dma_memory_read) { + s->dma_memory_read(s->dma_opaque, buf, dmalen); + } else { + memcpy(s->pdma_buf, buf, dmalen); + set_pdma(s, PDMA, 0, dmalen); + esp_raise_drq(s); + return 0; + } } else { dmalen =3D s->ti_size; if (dmalen > TI_BUFSZ) { @@ -177,6 +220,16 @@ static void do_cmd(ESPState *s, uint8_t *buf) do_busid_cmd(s, &buf[1], busid); } =20 +static void satn_pdma_cb(ESPState *s) +{ + if (get_cmd_cb(s) < 0) { + return; + } + if (s->pdma_cur !=3D s->pdma_start) { + do_cmd(s, get_pdma_buf(s) + s->pdma_start); + } +} + static void handle_satn(ESPState *s) { uint8_t buf[32]; @@ -186,11 +239,22 @@ static void handle_satn(ESPState *s) s->dma_cb =3D handle_satn; return; } + s->pdma_cb =3D satn_pdma_cb; len =3D get_cmd(s, buf, sizeof(buf)); if (len) do_cmd(s, buf); } =20 +static void s_without_satn_pdma_cb(ESPState *s) +{ + if (get_cmd_cb(s) < 0) { + return; + } + if (s->pdma_cur !=3D s->pdma_start) { + do_busid_cmd(s, get_pdma_buf(s) + s->pdma_start, 0); + } +} + static void handle_s_without_atn(ESPState *s) { uint8_t buf[32]; @@ -200,18 +264,36 @@ static void handle_s_without_atn(ESPState *s) s->dma_cb =3D handle_s_without_atn; return; } + s->pdma_cb =3D s_without_satn_pdma_cb; len =3D get_cmd(s, buf, sizeof(buf)); if (len) { do_busid_cmd(s, buf, 0); } } =20 +static void satn_stop_pdma_cb(ESPState *s) +{ + if (get_cmd_cb(s) < 0) { + return; + } + s->cmdlen =3D s->pdma_cur - s->pdma_start; + if (s->cmdlen) { + trace_esp_handle_satn_stop(s->cmdlen); + s->do_cmd =3D 1; + s->rregs[ESP_RSTAT] =3D STAT_TC | STAT_CD; + s->rregs[ESP_RINTR] =3D INTR_BS | INTR_FC; + s->rregs[ESP_RSEQ] =3D SEQ_CD; + esp_raise_irq(s); + } +} + static void handle_satn_stop(ESPState *s) { if (s->dma && !s->dma_enabled) { s->dma_cb =3D handle_satn_stop; return; } + s->pdma_cb =3D satn_stop_pdma_cb;; s->cmdlen =3D get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf)); if (s->cmdlen) { trace_esp_handle_satn_stop(s->cmdlen); @@ -223,16 +305,31 @@ static void handle_satn_stop(ESPState *s) } } =20 +static void write_response_pdma_cb(ESPState *s) +{ + s->rregs[ESP_RSTAT] =3D STAT_TC | STAT_ST; + s->rregs[ESP_RINTR] =3D INTR_BS | INTR_FC; + s->rregs[ESP_RSEQ] =3D SEQ_CD; + esp_raise_irq(s); +} + static void write_response(ESPState *s) { trace_esp_write_response(s->status); s->ti_buf[0] =3D s->status; s->ti_buf[1] =3D 0; if (s->dma) { - s->dma_memory_write(s->dma_opaque, s->ti_buf, 2); - s->rregs[ESP_RSTAT] =3D STAT_TC | STAT_ST; - s->rregs[ESP_RINTR] =3D INTR_BS | INTR_FC; - s->rregs[ESP_RSEQ] =3D SEQ_CD; + if (s->dma_memory_write) { + s->dma_memory_write(s->dma_opaque, s->ti_buf, 2); + s->rregs[ESP_RSTAT] =3D STAT_TC | STAT_ST; + s->rregs[ESP_RINTR] =3D INTR_BS | INTR_FC; + s->rregs[ESP_RSEQ] =3D SEQ_CD; + } else { + set_pdma(s, TI, 0, 2); + s->pdma_cb =3D write_response_pdma_cb; + esp_raise_drq(s); + return; + } } else { s->ti_size =3D 2; s->ti_rptr =3D 0; @@ -254,6 +351,41 @@ static void esp_dma_done(ESPState *s) esp_raise_irq(s); } =20 +static void do_dma_pdma_cb(ESPState *s) +{ + int to_device =3D (s->ti_size < 0); + int len =3D s->pdma_cur - s->pdma_start; + if (s->do_cmd) { + s->ti_size =3D 0; + s->cmdlen =3D 0; + s->do_cmd =3D 0; + do_cmd(s, s->cmdbuf); + return; + } + s->dma_left -=3D len; + s->async_buf +=3D len; + s->async_len -=3D len; + if (to_device) { + s->ti_size +=3D len; + } else { + s->ti_size -=3D len; + } + if (s->async_len =3D=3D 0) { + scsi_req_continue(s->current_req); + /* + * If there is still data to be read from the device then + * complete the DMA operation immediately. Otherwise defer + * until the scsi layer has completed. + */ + if (to_device || s->dma_left !=3D 0 || s->ti_size =3D=3D 0) { + return; + } + } + + /* Partially filled a scsi buffer. Complete immediately. */ + esp_dma_done(s); +} + static void esp_do_dma(ESPState *s) { uint32_t len; @@ -268,7 +400,14 @@ static void esp_do_dma(ESPState *s) trace_esp_do_dma(s->cmdlen, len); assert (s->cmdlen <=3D sizeof(s->cmdbuf) && len <=3D sizeof(s->cmdbuf) - s->cmdlen); - s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); + if (s->dma_memory_read) { + s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); + } else { + set_pdma(s, CMD, s->cmdlen, len); + s->pdma_cb =3D do_dma_pdma_cb; + esp_raise_drq(s); + return; + } trace_esp_handle_ti_cmd(s->cmdlen); s->ti_size =3D 0; s->cmdlen =3D 0; @@ -285,9 +424,23 @@ static void esp_do_dma(ESPState *s) } to_device =3D (s->ti_size < 0); if (to_device) { - s->dma_memory_read(s->dma_opaque, s->async_buf, len); + if (s->dma_memory_read) { + s->dma_memory_read(s->dma_opaque, s->async_buf, len); + } else { + set_pdma(s, ASYNC, 0, len); + s->pdma_cb =3D do_dma_pdma_cb; + esp_raise_drq(s); + return; + } } else { - s->dma_memory_write(s->dma_opaque, s->async_buf, len); + if (s->dma_memory_write) { + s->dma_memory_write(s->dma_opaque, s->async_buf, len); + } else { + set_pdma(s, ASYNC, 0, len); + s->pdma_cb =3D do_dma_pdma_cb; + esp_raise_drq(s); + return; + } } s->dma_left -=3D len; s->async_buf +=3D len; @@ -421,6 +574,7 @@ void esp_hard_reset(ESPState *s) static void esp_soft_reset(ESPState *s) { qemu_irq_lower(s->irq); + qemu_irq_lower(s->irq_data); esp_hard_reset(s); } =20 @@ -610,6 +764,28 @@ static bool esp_mem_accepts(void *opaque, hwaddr addr, return (size =3D=3D 1) || (is_write && size =3D=3D 4); } =20 +static bool esp_pdma_needed(void *opaque) +{ + ESPState *s =3D opaque; + return s->dma_memory_read =3D=3D NULL && s->dma_memory_write =3D=3D NU= LL && + s->dma_enabled; +} + +static const VMStateDescription vmstate_esp_pdma =3D { + .name =3D "esp/pdma", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D esp_pdma_needed, + .fields =3D (VMStateField[]) { + VMSTATE_BUFFER(pdma_buf, ESPState), + VMSTATE_INT32(pdma_origin, ESPState), + VMSTATE_UINT32(pdma_len, ESPState), + VMSTATE_UINT32(pdma_start, ESPState), + VMSTATE_UINT32(pdma_cur, ESPState), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_esp =3D { .name =3D"esp", .version_id =3D 4, @@ -631,6 +807,10 @@ const VMStateDescription vmstate_esp =3D { VMSTATE_UINT32(do_cmd, ESPState), VMSTATE_UINT32(dma_left, ESPState), VMSTATE_END_OF_LIST() + }, + .subsections =3D (const VMStateDescription * []) { + &vmstate_esp_pdma, + NULL } }; =20 @@ -661,6 +841,82 @@ static const MemoryRegionOps sysbus_esp_mem_ops =3D { .valid.accepts =3D esp_mem_accepts, }; =20 +static void sysbus_esp_pdma_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int size) +{ + SysBusESPState *sysbus =3D opaque; + ESPState *s =3D &sysbus->esp; + uint32_t dmalen; + uint8_t *buf =3D get_pdma_buf(s); + + dmalen =3D s->rregs[ESP_TCLO]; + dmalen |=3D s->rregs[ESP_TCMID] << 8; + dmalen |=3D s->rregs[ESP_TCHI] << 16; + if (dmalen =3D=3D 0 || s->pdma_len =3D=3D 0) { + return; + } + switch (size) { + case 1: + buf[s->pdma_cur++] =3D val; + s->pdma_len--; + dmalen--; + break; + case 2: + buf[s->pdma_cur++] =3D val >> 8; + buf[s->pdma_cur++] =3D val; + s->pdma_len -=3D 2; + dmalen -=3D 2; + break; + } + s->rregs[ESP_TCLO] =3D dmalen & 0xff; + s->rregs[ESP_TCMID] =3D dmalen >> 8; + s->rregs[ESP_TCHI] =3D dmalen >> 16; + if (s->pdma_len =3D=3D 0 && s->pdma_cb) { + esp_lower_drq(s); + s->pdma_cb(s); + s->pdma_cb =3D NULL; + } +} + +static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr, + unsigned int size) +{ + SysBusESPState *sysbus =3D opaque; + ESPState *s =3D &sysbus->esp; + uint8_t *buf =3D get_pdma_buf(s); + uint64_t val =3D 0; + + if (s->pdma_len =3D=3D 0) { + return 0; + } + switch (size) { + case 1: + val =3D buf[s->pdma_cur++]; + s->pdma_len--; + break; + case 2: + val =3D buf[s->pdma_cur++]; + val =3D (val << 8) | buf[s->pdma_cur++]; + s->pdma_len -=3D 2; + break; + } + + if (s->pdma_len =3D=3D 0 && s->pdma_cb) { + esp_lower_drq(s); + s->pdma_cb(s); + s->pdma_cb =3D NULL; + } + return val; +} + +static const MemoryRegionOps sysbus_esp_pdma_ops =3D { + .read =3D sysbus_esp_pdma_read, + .write =3D sysbus_esp_pdma_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 2, +}; + static const struct SCSIBusInfo esp_scsi_info =3D { .tcq =3D false, .max_target =3D ESP_MAX_DEVS, @@ -693,12 +949,16 @@ static void sysbus_esp_realize(DeviceState *dev, Erro= r **errp) ESPState *s =3D &sysbus->esp; =20 sysbus_init_irq(sbd, &s->irq); + sysbus_init_irq(sbd, &s->irq_data); assert(sysbus->it_shift !=3D -1); =20 s->chip_id =3D TCHI_FAS100A; memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_= ops, - sysbus, "esp", ESP_REGS << sysbus->it_shift); + sysbus, "esp-regs", ESP_REGS << sysbus->it_shift= ); sysbus_init_mmio(sbd, &sysbus->iomem); + memory_region_init_io(&sysbus->pdma, OBJECT(sysbus), &sysbus_esp_pdma_= ops, + sysbus, "esp-pdma", 2); + sysbus_init_mmio(sbd, &sysbus->pdma); =20 qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2); =20 --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572291069; cv=none; d=zoho.com; s=zohoarc; b=Vz/owQay1qlZKtbFZzc3bSHQNxIxa2MzSawyOYn+Qoqku7rnuxYfaniOPoaeWly6PfRrGD8WQVBfDLnTJhxMtAJBR/nItYYb1m2EXww4Bpmg6OHKGSWWjxCqiOdjjbtGj8P480B5qJ7XkUiYYAIIG0+ECTIb/61dLXRjFys+nac= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572291069; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=zSq6SnYJJObyGDNIOc/cWgF2BH8HYzCpTg5JXDg7Yvk=; b=lzZ2XgJ83Vj1mn9PndnDMoYIUp3ULNU1VjvpFzqKHpJbYgCAm8sItSvkvJmkgCkwxNFLcC8veKHERZ7vZ2ho54fFjXm+zGJxzBEHKaOZTsVuk8r3L9KVLNqA/k9+q/gRjvSy2gOlKsOdvt8xwR69FtvKc9gJgG+V+MVfcAZ1rLQ= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572291069704279.9204159704518; Mon, 28 Oct 2019 12:31:09 -0700 (PDT) Received: from localhost ([::1]:55848 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAjJ-0007kB-Ll for importer@patchew.org; Mon, 28 Oct 2019 15:31:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56607) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zp-0002hB-CW for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zn-00042y-HE for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:13 -0400 Received: from mout.kundenserver.de ([212.227.17.24]:52963) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zi-0003yC-QK; Mon, 28 Oct 2019 14:17:07 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MGhi0-1iBM4D0CSw-00Dn53; Mon, 28 Oct 2019 19:16:55 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 04/11] dp8393x: manage big endian bus Date: Mon, 28 Oct 2019 19:16:36 +0100 Message-Id: <20191028181643.5143-5-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:SRHVVvKWAENMmfZJjHF9g6iEGZFLNXNExMJ6J0oLXGspb30Sf2z xWsXAA/wCPV25G4ys0los6x28oHCJvvMHU5e0VGnk+VC+v8cPGcz476lU2L1YoISOMXMKik jmkwBY4mwfstGj2vpY65z9wwK3dzD3CCxcINkXABEB77c1zfpellsbchghCKTItBmc3RZYq PKSZngDfho8CpApdheezQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:u0FRLH4e08s=:WtYCkYYTFmFyuSAyGZ4t07 BbdOnSgZm/S4y/bJv0Aqz80wTui0xVUVMaGgakAucgXh2d7/N3tQbK87YHUpUxlKciXPCpAoZ OSpTl9Rqbh4xq/aA/hIuoyfJTJ0+gRo7AXGo5K1rWrW6mwx2M4jLnuZJ4T0gMxUUkAgCBvyw+ qdyjHIVQi4dwV8FR3Ei8kJ+Z+RaYRZJxhxQbo+lGEuaNq0u2kKTLnLbAmxhvtXs1ndZ/G/dme SOgEkMBq4J7vsLWoTBIBRKcsg306TmoKfJmZBpFN+29SE/mFWPoLVqaDH0ZORj6Bd7Du5uRRG FOupdX6UhlWA4mgfGUlGgmpbPFaeU4EyxEXYXnUcSilI5+Fd1wcQ6/Fpa20josq58byGhGgK7 qxkDwMEkfekY0xeZkJwXxwJPnorjF6Jyi2JpdCXEqQjYuseYNfSZgKM2BgKSmgZCEOoBpHLBe GjaCoyELOxPwrvDrLcRpoB/lD/tUCCbOEA/UKvTGP1X6iHgp9AAVwLvzwaZTN5SW5HKNO6A1j I4NtKiZYeM1LzfT48bt7SDSk9nrI3qJY5aQybkMTIOlOV7slKHXRwUEub0NoqQAiho/7ourek nSl4LvnQGw/Z15B7aZv3KnNidGYLOykow5bF5XsPywdGo6Utz5wvSXNfUehEpXxsJZ9Bv41sd T2jnNwzvzdeGn7W4P6poS2eid5YpVyGgPQASqmPpUFBFdwhmNdcFT22LMrmaJXBWAUYpJ5cjW E9Y5YMwEErSNvvuwPSKuLWD0ZdrECRd6tGpCuLV/istAUyl7nk7BsacS/HAe3grT/JObuuxjo T6XFDkqkDKG5l3h/rwxcCilx63JvCjp7/jlKdlds3+Ng7YBGySf+W4jDrHlmPzoXyIUkyVs0U bi1qx9Sfxt/LePShsNRHXUjjHR23hT834NTbYVjD4= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.24 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Laurent Vivier , Max Reitz , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" This is needed by Quadra 800, this card can run on little-endian or big-endian bus. Signed-off-by: Laurent Vivier Tested-by: Herv=C3=A9 Poussineau Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Herv=C3=A9 Poussineau Message-Id: <20191026164546.30020-5-laurent@vivier.eu> --- hw/net/dp8393x.c | 88 +++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index a5678e11fa..693e244ce6 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -153,6 +153,7 @@ typedef struct dp8393xState { =20 /* Hardware */ uint8_t it_shift; + bool big_endian; qemu_irq irq; #ifdef DEBUG_SONIC int irq_level; @@ -223,6 +224,29 @@ static uint32_t dp8393x_wt(dp8393xState *s) return s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0]; } =20 +static uint16_t dp8393x_get(dp8393xState *s, int width, uint16_t *base, + int offset) +{ + uint16_t val; + + if (s->big_endian) { + val =3D be16_to_cpu(base[offset * width + width - 1]); + } else { + val =3D le16_to_cpu(base[offset * width]); + } + return val; +} + +static void dp8393x_put(dp8393xState *s, int width, uint16_t *base, int of= fset, + uint16_t val) +{ + if (s->big_endian) { + base[offset * width + width - 1] =3D cpu_to_be16(val); + } else { + base[offset * width] =3D cpu_to_le16(val); + } +} + static void dp8393x_update_irq(dp8393xState *s) { int level =3D (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0; @@ -254,12 +278,12 @@ static void dp8393x_do_load_cam(dp8393xState *s) /* Fill current entry */ address_space_rw(&s->as, dp8393x_cdp(s), MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); - s->cam[index][0] =3D data[1 * width] & 0xff; - s->cam[index][1] =3D data[1 * width] >> 8; - s->cam[index][2] =3D data[2 * width] & 0xff; - s->cam[index][3] =3D data[2 * width] >> 8; - s->cam[index][4] =3D data[3 * width] & 0xff; - s->cam[index][5] =3D data[3 * width] >> 8; + s->cam[index][0] =3D dp8393x_get(s, width, data, 1) & 0xff; + s->cam[index][1] =3D dp8393x_get(s, width, data, 1) >> 8; + s->cam[index][2] =3D dp8393x_get(s, width, data, 2) & 0xff; + s->cam[index][3] =3D dp8393x_get(s, width, data, 2) >> 8; + s->cam[index][4] =3D dp8393x_get(s, width, data, 3) & 0xff; + s->cam[index][5] =3D dp8393x_get(s, width, data, 3) >> 8; DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index, s->cam[index][0], s->cam[index][1], s->cam[index][2], s->cam[index][3], s->cam[index][4], s->cam[index][5]); @@ -272,7 +296,7 @@ static void dp8393x_do_load_cam(dp8393xState *s) /* Read CAM enable */ address_space_rw(&s->as, dp8393x_cdp(s), MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); - s->regs[SONIC_CE] =3D data[0 * width]; + s->regs[SONIC_CE] =3D dp8393x_get(s, width, data, 0); DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]); =20 /* Done */ @@ -293,10 +317,10 @@ static void dp8393x_do_read_rra(dp8393xState *s) MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); =20 /* Update SONIC registers */ - s->regs[SONIC_CRBA0] =3D data[0 * width]; - s->regs[SONIC_CRBA1] =3D data[1 * width]; - s->regs[SONIC_RBWC0] =3D data[2 * width]; - s->regs[SONIC_RBWC1] =3D data[3 * width]; + s->regs[SONIC_CRBA0] =3D dp8393x_get(s, width, data, 0); + s->regs[SONIC_CRBA1] =3D dp8393x_get(s, width, data, 1); + s->regs[SONIC_RBWC0] =3D dp8393x_get(s, width, data, 2); + s->regs[SONIC_RBWC1] =3D dp8393x_get(s, width, data, 3); DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n", s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1], s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]); @@ -411,12 +435,12 @@ static void dp8393x_do_transmit_packets(dp8393xState = *s) tx_len =3D 0; =20 /* Update registers */ - s->regs[SONIC_TCR] =3D data[0 * width] & 0xf000; - s->regs[SONIC_TPS] =3D data[1 * width]; - s->regs[SONIC_TFC] =3D data[2 * width]; - s->regs[SONIC_TSA0] =3D data[3 * width]; - s->regs[SONIC_TSA1] =3D data[4 * width]; - s->regs[SONIC_TFS] =3D data[5 * width]; + s->regs[SONIC_TCR] =3D dp8393x_get(s, width, data, 0) & 0xf000; + s->regs[SONIC_TPS] =3D dp8393x_get(s, width, data, 1); + s->regs[SONIC_TFC] =3D dp8393x_get(s, width, data, 2); + s->regs[SONIC_TSA0] =3D dp8393x_get(s, width, data, 3); + s->regs[SONIC_TSA1] =3D dp8393x_get(s, width, data, 4); + s->regs[SONIC_TFS] =3D dp8393x_get(s, width, data, 5); =20 /* Handle programmable interrupt */ if (s->regs[SONIC_TCR] & SONIC_TCR_PINT) { @@ -442,9 +466,9 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) address_space_rw(&s->as, dp8393x_ttda(s) + sizeof(uint16_t) * (4 + 3 * i) * wid= th, MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); - s->regs[SONIC_TSA0] =3D data[0 * width]; - s->regs[SONIC_TSA1] =3D data[1 * width]; - s->regs[SONIC_TFS] =3D data[2 * width]; + s->regs[SONIC_TSA0] =3D dp8393x_get(s, width, data, 0); + s->regs[SONIC_TSA1] =3D dp8393x_get(s, width, data, 1); + s->regs[SONIC_TFS] =3D dp8393x_get(s, width, data, 2); } } =20 @@ -471,7 +495,8 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) s->regs[SONIC_TCR] |=3D SONIC_TCR_PTX; =20 /* Write status */ - data[0 * width] =3D s->regs[SONIC_TCR] & 0x0fff; /* status */ + dp8393x_put(s, width, data, 0, + s->regs[SONIC_TCR] & 0x0fff); /* status */ size =3D sizeof(uint16_t) * width; address_space_rw(&s->as, dp8393x_ttda(s), @@ -485,8 +510,8 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) sizeof(uint16_t) * (4 + 3 * s->regs[SONIC_TFC]) * width, MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); - s->regs[SONIC_CTDA] =3D data[0 * width] & ~0x1; - if (data[0 * width] & 0x1) { + s->regs[SONIC_CTDA] =3D dp8393x_get(s, width, data, 0) & ~0x1; + if (dp8393x_get(s, width, data, 0) & 0x1) { /* EOL detected */ break; } @@ -749,7 +774,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, cons= t uint8_t * buf, address =3D dp8393x_crda(s) + sizeof(uint16_t) * 5 * width; address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); - if (data[0 * width] & 0x1) { + if (dp8393x_get(s, width, data, 0) & 0x1) { /* Still EOL ; stop reception */ return -1; } else { @@ -793,11 +818,11 @@ static ssize_t dp8393x_receive(NetClientState *nc, co= nst uint8_t * buf, =20 /* Write status to memory */ DPRINTF("Write status at %08x\n", dp8393x_crda(s)); - data[0 * width] =3D s->regs[SONIC_RCR]; /* status */ - data[1 * width] =3D rx_len; /* byte count */ - data[2 * width] =3D s->regs[SONIC_TRBA0]; /* pkt_ptr0 */ - data[3 * width] =3D s->regs[SONIC_TRBA1]; /* pkt_ptr1 */ - data[4 * width] =3D s->regs[SONIC_RSC]; /* seq_no */ + dp8393x_put(s, width, data, 0, s->regs[SONIC_RCR]); /* status */ + dp8393x_put(s, width, data, 1, rx_len); /* byte count */ + dp8393x_put(s, width, data, 2, s->regs[SONIC_TRBA0]); /* pkt_ptr0 */ + dp8393x_put(s, width, data, 3, s->regs[SONIC_TRBA1]); /* pkt_ptr1 */ + dp8393x_put(s, width, data, 4, s->regs[SONIC_RSC]); /* seq_no */ size =3D sizeof(uint16_t) * 5 * width; address_space_rw(&s->as, dp8393x_crda(s), MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1); @@ -806,12 +831,12 @@ static ssize_t dp8393x_receive(NetClientState *nc, co= nst uint8_t * buf, size =3D sizeof(uint16_t) * width; address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * widt= h, MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0); - s->regs[SONIC_LLFA] =3D data[0 * width]; + s->regs[SONIC_LLFA] =3D dp8393x_get(s, width, data, 0); if (s->regs[SONIC_LLFA] & 0x1) { /* EOL detected */ s->regs[SONIC_ISR] |=3D SONIC_ISR_RDE; } else { - data[0 * width] =3D 0; /* in_use */ + dp8393x_put(s, width, data, 0, 0); /* in_use */ address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 6 * = width, MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, sizeof(uint16_t), 1); s->regs[SONIC_CRDA] =3D s->regs[SONIC_LLFA]; @@ -924,6 +949,7 @@ static Property dp8393x_properties[] =3D { DEFINE_NIC_PROPERTIES(dp8393xState, conf), DEFINE_PROP_PTR("dma_mr", dp8393xState, dma_mr), DEFINE_PROP_UINT8("it_shift", dp8393xState, it_shift, 0), + DEFINE_PROP_BOOL("big_endian", dp8393xState, big_endian, false), DEFINE_PROP_END_OF_LIST(), }; =20 --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572290825; cv=none; d=zoho.com; s=zohoarc; b=dwXbdv8KoboqaMZMVBxedf5B260WE9eJ7SLS4zkRU/5X4+OLhHbjgt1Kp+wcUo906BnnzXnhp/+bBrl/bIUoxVfaPPZMoYBNTIjXlMDLWAXjPkcT1T6vJHXkQjQ70+Vzx9GEYqIdTWE3rEBwlGo0s41KU4gvjZUPB+iPDd+1+T0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572290825; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=U73L3xvO01x9bBpgB9FWzLsB2qFuQO4sL9sHdJF6Tts=; b=LJ2IVU3Ftq+gqhJ5vxYrGMNCSdi4GyZTiZQAdhtHk3d7CEohYq//yPi4xu5DWcKoASb8Q94C17RpL7t0yPC3txmx+Icaj+mt87Pbyxwc7IdK2ux6KGsxFMNPxIBI7xblg1HEEhofmLpZkeU20BCceaxhdyr5JzKVpQ3OLT+Yz6s= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572290825246751.8881500931002; Mon, 28 Oct 2019 12:27:05 -0700 (PDT) Received: from localhost ([::1]:55110 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAfN-0002F5-L9 for importer@patchew.org; Mon, 28 Oct 2019 15:27:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56566) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zn-0002eN-1s for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zj-0003yz-40 for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:10 -0400 Received: from mout.kundenserver.de ([212.227.17.24]:35127) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zi-0003y6-LH; Mon, 28 Oct 2019 14:17:07 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MJn4B-1iikvB0wMD-00KAl4; Mon, 28 Oct 2019 19:16:57 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 05/11] hw/m68k: add VIA support Date: Mon, 28 Oct 2019 19:16:37 +0100 Message-Id: <20191028181643.5143-6-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:I8g/cG3FJvuu+q3Y1wrYVBUtIoLDUlB9bvL7bCKfcxbqh5Q1eN3 mzahzcj8i8cHgsvsWwhMwEEcufxOFX2YLXKCj/2cdDcj7o3XrS0K4nm2fOPYawiG9o5Je6y JlVG+f0qaCGhVO2D3sxplqcY1XJ1argP+PRwqEmPydtTanOVbe/aBZZjvnlzzl5N9duhWwO ZMOZfXVDGEKH9QA+ST5mw== X-UI-Out-Filterresults: notjunk:1;V03:K0:SGbNyLktJsQ=:mxvijTJ+dKqOtg2eRKC2WD v988SWvNG9KBUnccoF3iBKs6XrhRihPGo0HEOdy3D1pK31pnw5T1LQbnutI8qqCKfxC+rt9Dx DUs716zrioIdTQmznjeTwggAHZ9kdm0Emq49m+FC5CtyIGdJkmjmp4LnxZJJ3kkD1yTFx7J/e C+X5EKFnRGZJNs5bU0EAqHtX44ovwti4s8mj3K5QCaOi1/ShbUj/5uo0t/N3uN0EkJuP6VHoR rr1JHjQVGpdPnbChruOj0wwZKA1MpOGJS7hfiArqtej7k0OdB8DrQcvqGBFmLklL4o9I4FIe7 kfiaxLoP93EHXuRa1LFCGtO8zAiolEue7NHhmaPiXot0WcFDIQ5gnzRnktMKZqBLMABN55fH3 lyC4ntK10FcF+RVqmay5Y6LJOtZ7rYL2Ec8u1EO+XC3WYKnhJY9RWDwp/EV99PdiwaGPM9xd5 pH39eo8jc/YwYXAs80VW/N1Nel8h+s1NLR6f7l3Ng1HKWVvW4IlMu0dzAYX1pfkP227Qi4/fG idXt701INue3zJ2v5GLCCapMqzlAM03arp4bxV0VXd//HljVVqivObS54dna2c799nQiM7YuV QlJNCDgc3Rp2vrczJW8r7eOjzfD5r8CbR7bcdKx4ZGpYLybxT0ruljQIEXRbptcmM37hDGQ4s GY50qxYLSMJbbUdCWvQpksm3eCfyKGsO8GBowQ7nDOgt9Z33SOvilZB8i+GckuJgdw7e+C0ec RHpERlDkBLyopPAFLLf5rXrIF5rrc0i1KlTkkz5V+lt/wLdQqFDfg3lxTPQycKhu0pt4HlJUH mH9jvVP3HZ4NNDsF+59WSe6UhSTFO9YWh8fIQ3tnIRoXSCSI7a2ZR36ioRn8HtMCFrlkHZBz9 EIitPUmZThBRkyE5YzIE1UzoYozVtPXqTDk5tOyPI= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.24 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Inside the 680x0 Macintosh, VIA (Versatile Interface Adapter) is used to interface the keyboard, Mouse, and real-time clock. It also provides control line for the floppy disk driver, video interface, sound circuitry and serial interface. This implementation is based on the MOS6522 object. Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Reviewed-by: Herv=C3=A9 Poussineau Message-Id: <20191026164546.30020-6-laurent@vivier.eu> --- default-configs/m68k-softmmu.mak | 1 + include/hw/misc/mac_via.h | 108 +++++ hw/misc/mac_via.c | 767 +++++++++++++++++++++++++++++++ MAINTAINERS | 6 + hw/m68k/Kconfig | 4 + hw/misc/Kconfig | 4 + hw/misc/Makefile.objs | 1 + 7 files changed, 891 insertions(+) create mode 100644 include/hw/misc/mac_via.h create mode 100644 hw/misc/mac_via.c diff --git a/default-configs/m68k-softmmu.mak b/default-configs/m68k-softmm= u.mak index d67ab8b96d..6629fd2aa3 100644 --- a/default-configs/m68k-softmmu.mak +++ b/default-configs/m68k-softmmu.mak @@ -7,3 +7,4 @@ CONFIG_SEMIHOSTING=3Dy CONFIG_AN5206=3Dy CONFIG_MCF5208=3Dy CONFIG_NEXTCUBE=3Dy +CONFIG_Q800=3Dy diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h new file mode 100644 index 0000000000..efc8ef3ce3 --- /dev/null +++ b/include/hw/misc/mac_via.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (c) 2011-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_MISC_MAC_VIA_H +#define HW_MISC_MAC_VIA_H + +#include "exec/memory.h" +#include "hw/sysbus.h" +#include "hw/misc/mos6522.h" + + +/* VIA 1 */ +#define VIA1_IRQ_ONE_SECOND_BIT 0 +#define VIA1_IRQ_VBLANK_BIT 1 +#define VIA1_IRQ_ADB_READY_BIT 2 +#define VIA1_IRQ_ADB_DATA_BIT 3 +#define VIA1_IRQ_ADB_CLOCK_BIT 4 + +#define VIA1_IRQ_NB 8 + +#define VIA1_IRQ_ONE_SECOND (1 << VIA1_IRQ_ONE_SECOND_BIT) +#define VIA1_IRQ_VBLANK (1 << VIA1_IRQ_VBLANK_BIT) +#define VIA1_IRQ_ADB_READY (1 << VIA1_IRQ_ADB_READY_BIT) +#define VIA1_IRQ_ADB_DATA (1 << VIA1_IRQ_ADB_DATA_BIT) +#define VIA1_IRQ_ADB_CLOCK (1 << VIA1_IRQ_ADB_CLOCK_BIT) + + +#define TYPE_MOS6522_Q800_VIA1 "mos6522-q800-via1" +#define MOS6522_Q800_VIA1(obj) OBJECT_CHECK(MOS6522Q800VIA1State, (obj), \ + TYPE_MOS6522_Q800_VIA1) + +typedef struct MOS6522Q800VIA1State { + /*< private >*/ + MOS6522State parent_obj; + + qemu_irq irqs[VIA1_IRQ_NB]; + uint8_t last_b; + uint8_t PRAM[256]; + + /* external timers */ + QEMUTimer *one_second_timer; + int64_t next_second; + QEMUTimer *VBL_timer; + int64_t next_VBL; +} MOS6522Q800VIA1State; + + +/* VIA 2 */ +#define VIA2_IRQ_SCSI_DATA_BIT 0 +#define VIA2_IRQ_SLOT_BIT 1 +#define VIA2_IRQ_UNUSED_BIT 2 +#define VIA2_IRQ_SCSI_BIT 3 +#define VIA2_IRQ_ASC_BIT 4 + +#define VIA2_IRQ_NB 8 + +#define VIA2_IRQ_SCSI_DATA (1 << VIA2_IRQ_SCSI_DATA_BIT) +#define VIA2_IRQ_SLOT (1 << VIA2_IRQ_SLOT_BIT) +#define VIA2_IRQ_UNUSED (1 << VIA2_IRQ_SCSI_BIT) +#define VIA2_IRQ_SCSI (1 << VIA2_IRQ_UNUSED_BIT) +#define VIA2_IRQ_ASC (1 << VIA2_IRQ_ASC_BIT) + +#define TYPE_MOS6522_Q800_VIA2 "mos6522-q800-via2" +#define MOS6522_Q800_VIA2(obj) OBJECT_CHECK(MOS6522Q800VIA2State, (obj), \ + TYPE_MOS6522_Q800_VIA2) + +typedef struct MOS6522Q800VIA2State { + /*< private >*/ + MOS6522State parent_obj; +} MOS6522Q800VIA2State; + + +#define TYPE_MAC_VIA "mac_via" +#define MAC_VIA(obj) OBJECT_CHECK(MacVIAState, (obj), TYPE_MAC_VIA) + +typedef struct MacVIAState { + SysBusDevice busdev; + + /* MMIO */ + MemoryRegion mmio; + MemoryRegion via1mem; + MemoryRegion via2mem; + + /* VIAs */ + MOS6522Q800VIA1State mos6522_via1; + MOS6522Q800VIA2State mos6522_via2; + + /* RTC */ + uint32_t tick_offset; + + uint8_t data_out; + int data_out_cnt; + uint8_t data_in; + uint8_t data_in_cnt; + uint8_t cmd; + int wprotect; + int alt; + + /* ADB */ + ADBBusState adb_bus; +} MacVIAState; + +#endif diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c new file mode 100644 index 0000000000..d2da8b8e60 --- /dev/null +++ b/hw/misc/mac_via.c @@ -0,0 +1,767 @@ +/* + * QEMU m68k Macintosh VIA device support + * + * Copyright (c) 2011-2018 Laurent Vivier + * Copyright (c) 2018 Mark Cave-Ayland + * + * Some parts from hw/misc/macio/cuda.c + * + * Copyright (c) 2004-2007 Fabrice Bellard + * Copyright (c) 2007 Jocelyn Mayer + * + * some parts from linux-2.6.29, arch/m68k/include/asm/mac_via.h + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "migration/vmstate.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "qemu/timer.h" +#include "hw/misc/mac_via.h" +#include "hw/misc/mos6522.h" +#include "hw/input/adb.h" +#include "sysemu/runstate.h" +#include "qapi/error.h" +#include "qemu/cutils.h" + + +/* + * VIAs: There are two in every machine, + */ + +#define VIA_SIZE (0x2000) + +/* + * Not all of these are true post MacII I think. + * CSA: probably the ones CHRP marks as 'unused' change purposes + * when the IWM becomes the SWIM. + * http://www.rs6000.ibm.com/resource/technology/chrpio/via5.mak.html + * ftp://ftp.austin.ibm.com/pub/technology/spec/chrp/inwork/CHRP_IORef_1.0= .pdf + * + * also, http://developer.apple.com/technotes/hw/hw_09.html claims the + * following changes for IIfx: + * VIA1A_vSccWrReq not available and that VIA1A_vSync has moved to an IOP. + * Also, "All of the functionality of VIA2 has been moved to other chips". + */ + +#define VIA1A_vSccWrReq 0x80 /* + * SCC write. (input) + * [CHRP] SCC WREQ: Reflects the state of t= he + * Wait/Request pins from the SCC. + * [Macintosh Family Hardware] + * as CHRP on SE/30,II,IIx,IIcx,IIci. + * on IIfx, "0 means an active request" + */ +#define VIA1A_vRev8 0x40 /* + * Revision 8 board ??? + * [CHRP] En WaitReqB: Lets the WaitReq_L + * signal from port B of the SCC appear on + * the PA7 input pin. Output. + * [Macintosh Family] On the SE/30, this + * is the bit to flip screen buffers. + * 0=3Dalternate, 1=3Dmain. + * on II,IIx,IIcx,IIci,IIfx this is a bit + * for Rev ID. 0=3DII,IIx, 1=3DIIcx,IIci,II= fx + */ +#define VIA1A_vHeadSel 0x20 /* + * Head select for IWM. + * [CHRP] unused. + * [Macintosh Family] "Floppy disk + * state-control line SEL" on all but IIfx + */ +#define VIA1A_vOverlay 0x10 /* + * [Macintosh Family] On SE/30,II,IIx,IIcx + * this bit enables the "Overlay" address + * map in the address decoders as it is on + * reset for mapping the ROM over the reset + * vector. 1=3Duse overlay map. + * On the IIci,IIfx it is another bit of the + * CPU ID: 0=3Dnormal IIci, 1=3DIIci with p= arity + * feature or IIfx. + * [CHRP] En WaitReqA: Lets the WaitReq_L + * signal from port A of the SCC appear + * on the PA7 input pin (CHRP). Output. + * [MkLinux] "Drive Select" + * (with 0x20 being 'disk head select') + */ +#define VIA1A_vSync 0x08 /* + * [CHRP] Sync Modem: modem clock select: + * 1: select the external serial clock to + * drive the SCC's /RTxCA pin. + * 0: Select the 3.6864MHz clock to drive + * the SCC cell. + * [Macintosh Family] Correct on all but II= fx + */ + +/* + * Macintosh Family Hardware sez: bits 0-2 of VIA1A are volume control + * on Macs which had the PWM sound hardware. Reserved on newer models. + * On IIci,IIfx, bits 1-2 are the rest of the CPU ID: + * bit 2: 1=3DIIci, 0=3DIIfx + * bit 1: 1 on both IIci and IIfx. + * MkLinux sez bit 0 is 'burnin flag' in this case. + * CHRP sez: VIA1A bits 0-2 and 5 are 'unused': if programmed as + * inputs, these bits will read 0. + */ +#define VIA1A_vVolume 0x07 /* Audio volume mask for PWM */ +#define VIA1A_CPUID0 0x02 /* CPU id bit 0 on RBV, others */ +#define VIA1A_CPUID1 0x04 /* CPU id bit 0 on RBV, others */ +#define VIA1A_CPUID2 0x10 /* CPU id bit 0 on RBV, others */ +#define VIA1A_CPUID3 0x40 /* CPU id bit 0 on RBV, others */ + +/* + * Info on VIA1B is from Macintosh Family Hardware & MkLinux. + * CHRP offers no info. + */ +#define VIA1B_vSound 0x80 /* + * Sound enable (for compatibility with + * PWM hardware) 0=3Denabled. + * Also, on IIci w/parity, shows parity err= or + * 0=3Derror, 1=3DOK. + */ +#define VIA1B_vMystery 0x40 /* + * On IIci, parity enable. 0=3Denabled,1=3D= disabled + * On SE/30, vertical sync interrupt enable. + * 0=3Denabled. This vSync interrupt shows = up + * as a slot $E interrupt. + */ +#define VIA1B_vADBS2 0x20 /* ADB state input bit 1 (unused on IIfx) */ +#define VIA1B_vADBS1 0x10 /* ADB state input bit 0 (unused on IIfx) */ +#define VIA1B_vADBInt 0x08 /* ADB interrupt 0=3Dinterrupt (unused on I= Ifx)*/ +#define VIA1B_vRTCEnb 0x04 /* Enable Real time clock. 0=3Denabled. */ +#define VIA1B_vRTCClk 0x02 /* Real time clock serial-clock line. */ +#define VIA1B_vRTCData 0x01 /* Real time clock serial-data line. */ + +/* + * VIA2 A register is the interrupt lines raised off the nubus + * slots. + * The below info is from 'Macintosh Family Hardware.' + * MkLinux calls the 'IIci internal video IRQ' below the 'RBV slot 0 = irq.' + * It also notes that the slot $9 IRQ is the 'Ethernet IRQ' and + * defines the 'Video IRQ' as 0x40 for the 'EVR' VIA work-alike. + * Perhaps OSS uses vRAM1 and vRAM2 for ADB. + */ + +#define VIA2A_vRAM1 0x80 /* RAM size bit 1 (IIci: reserved) */ +#define VIA2A_vRAM0 0x40 /* RAM size bit 0 (IIci: internal video IRQ= ) */ +#define VIA2A_vIRQE 0x20 /* IRQ from slot $E */ +#define VIA2A_vIRQD 0x10 /* IRQ from slot $D */ +#define VIA2A_vIRQC 0x08 /* IRQ from slot $C */ +#define VIA2A_vIRQB 0x04 /* IRQ from slot $B */ +#define VIA2A_vIRQA 0x02 /* IRQ from slot $A */ +#define VIA2A_vIRQ9 0x01 /* IRQ from slot $9 */ + +/* + * RAM size bits decoded as follows: + * bit1 bit0 size of ICs in bank A + * 0 0 256 kbit + * 0 1 1 Mbit + * 1 0 4 Mbit + * 1 1 16 Mbit + */ + +/* + * Register B has the fun stuff in it + */ + +#define VIA2B_vVBL 0x80 /* + * VBL output to VIA1 (60.15Hz) driven by + * timer T1. + * on IIci, parity test: 0=3Dtest mode. + * [MkLinux] RBV_PARODD: 1=3Dodd,0=3Deven. + */ +#define VIA2B_vSndJck 0x40 /* + * External sound jack status. + * 0=3Dplug is inserted. On SE/30, always 0 + */ +#define VIA2B_vTfr0 0x20 /* Transfer mode bit 0 ack from NuBus */ +#define VIA2B_vTfr1 0x10 /* Transfer mode bit 1 ack from NuBus */ +#define VIA2B_vMode32 0x08 /* + * 24/32bit switch - doubles as cache flush + * on II, AMU/PMMU control. + * if AMU, 0=3D24bit to 32bit translation + * if PMMU, 1=3DPMMU is accessing page tab= le. + * on SE/30 tied low. + * on IIx,IIcx,IIfx, unused. + * on IIci/RBV, cache control. 0=3Dflush cac= he. + */ +#define VIA2B_vPower 0x04 /* + * Power off, 0=3Dshut off power. + * on SE/30 this signal sent to PDS card. + */ +#define VIA2B_vBusLk 0x02 /* + * Lock NuBus transactions, 0=3Dlocked. + * on SE/30 sent to PDS card. + */ +#define VIA2B_vCDis 0x01 /* + * Cache control. On IIci, 1=3Ddisable cache = card + * on others, 0=3Ddisable processor's instruc= tion + * and data caches. + */ + +/* interrupt flags */ + +#define IRQ_SET 0x80 + +/* common */ + +#define VIA_IRQ_TIMER1 0x40 +#define VIA_IRQ_TIMER2 0x20 + +/* + * Apple sez: http://developer.apple.com/technotes/ov/ov_04.html + * Another example of a valid function that has no ROM support is the use + * of the alternate video page for page-flipping animation. Since there + * is no ROM call to flip pages, it is necessary to go play with the + * right bit in the VIA chip (6522 Versatile Interface Adapter). + * [CSA: don't know which one this is, but it's one of 'em!] + */ + +/* + * 6522 registers - see databook. + * CSA: Assignments for VIA1 confirmed from CHRP spec. + */ + +/* partial address decode. 0xYYXX : XX part for RBV, YY part for VIA */ +/* Note: 15 VIA regs, 8 RBV regs */ + +#define vBufB 0x0000 /* [VIA/RBV] Register B */ +#define vBufAH 0x0200 /* [VIA only] Buffer A, with handshake. DON'T USE= ! */ +#define vDirB 0x0400 /* [VIA only] Data Direction Register B. */ +#define vDirA 0x0600 /* [VIA only] Data Direction Register A. */ +#define vT1CL 0x0800 /* [VIA only] Timer one counter low. */ +#define vT1CH 0x0a00 /* [VIA only] Timer one counter high. */ +#define vT1LL 0x0c00 /* [VIA only] Timer one latches low. */ +#define vT1LH 0x0e00 /* [VIA only] Timer one latches high. */ +#define vT2CL 0x1000 /* [VIA only] Timer two counter low. */ +#define vT2CH 0x1200 /* [VIA only] Timer two counter high. */ +#define vSR 0x1400 /* [VIA only] Shift register. */ +#define vACR 0x1600 /* [VIA only] Auxilary control register. */ +#define vPCR 0x1800 /* [VIA only] Peripheral control register. */ + /* + * CHRP sez never ever to *write* this. + * Mac family says never to *change* t= his. + * In fact we need to initialize it once at start. + */ +#define vIFR 0x1a00 /* [VIA/RBV] Interrupt flag register. */ +#define vIER 0x1c00 /* [VIA/RBV] Interrupt enable register. */ +#define vBufA 0x1e00 /* [VIA/RBV] register A (no handshake) */ + +/* from linux 2.6 drivers/macintosh/via-macii.c */ + +/* Bits in ACR */ + +#define VIA1ACR_vShiftCtrl 0x1c /* Shift register control b= its */ +#define VIA1ACR_vShiftExtClk 0x0c /* Shift on external clock = */ +#define VIA1ACR_vShiftOut 0x10 /* Shift out if 1 */ + +/* + * Apple Macintosh Family Hardware Refenece + * Table 19-10 ADB transaction states + */ + +#define VIA1B_vADB_StateMask (VIA1B_vADBS1 | VIA1B_vADBS2) +#define VIA1B_vADB_StateShift 4 + +#define VIA_TIMER_FREQ (783360) + +/* VIA returns time offset from Jan 1, 1904, not 1970 */ +#define RTC_OFFSET 2082844800 + +static void via1_VBL_update(MOS6522Q800VIA1State *v1s) +{ + MOS6522State *s =3D MOS6522(v1s); + + /* 60 Hz irq */ + v1s->next_VBL =3D (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 16630) / + 16630 * 16630; + + if (s->ier & VIA1_IRQ_VBLANK) { + timer_mod(v1s->VBL_timer, v1s->next_VBL); + } else { + timer_del(v1s->VBL_timer); + } +} + +static void via1_one_second_update(MOS6522Q800VIA1State *v1s) +{ + MOS6522State *s =3D MOS6522(v1s); + + v1s->next_second =3D (qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000) / + 1000 * 1000; + if (s->ier & VIA1_IRQ_ONE_SECOND) { + timer_mod(v1s->one_second_timer, v1s->next_second); + } else { + timer_del(v1s->one_second_timer); + } +} + +static void via1_VBL(void *opaque) +{ + MOS6522Q800VIA1State *v1s =3D opaque; + MOS6522State *s =3D MOS6522(v1s); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_GET_CLASS(s); + + s->ifr |=3D VIA1_IRQ_VBLANK; + mdc->update_irq(s); + + via1_VBL_update(v1s); +} + +static void via1_one_second(void *opaque) +{ + MOS6522Q800VIA1State *v1s =3D opaque; + MOS6522State *s =3D MOS6522(v1s); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_GET_CLASS(s); + + s->ifr |=3D VIA1_IRQ_ONE_SECOND; + mdc->update_irq(s); + + via1_one_second_update(v1s); +} + +static void via1_irq_request(void *opaque, int irq, int level) +{ + MOS6522Q800VIA1State *v1s =3D opaque; + MOS6522State *s =3D MOS6522(v1s); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_GET_CLASS(s); + + if (level) { + s->ifr |=3D 1 << irq; + } else { + s->ifr &=3D ~(1 << irq); + } + + mdc->update_irq(s); +} + +static void via2_irq_request(void *opaque, int irq, int level) +{ + MOS6522Q800VIA2State *v2s =3D opaque; + MOS6522State *s =3D MOS6522(v2s); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_GET_CLASS(s); + + if (level) { + s->ifr |=3D 1 << irq; + } else { + s->ifr &=3D ~(1 << irq); + } + + mdc->update_irq(s); +} + +static void via1_rtc_update(MacVIAState *m) +{ + MOS6522Q800VIA1State *v1s =3D &m->mos6522_via1; + MOS6522State *s =3D MOS6522(v1s); + + if (s->b & VIA1B_vRTCEnb) { + return; + } + + if (s->dirb & VIA1B_vRTCData) { + /* send bits to the RTC */ + if (!(v1s->last_b & VIA1B_vRTCClk) && (s->b & VIA1B_vRTCClk)) { + m->data_out <<=3D 1; + m->data_out |=3D s->b & VIA1B_vRTCData; + m->data_out_cnt++; + } + } else { + /* receive bits from the RTC */ + if ((v1s->last_b & VIA1B_vRTCClk) && + !(s->b & VIA1B_vRTCClk) && + m->data_in_cnt) { + s->b =3D (s->b & ~VIA1B_vRTCData) | + ((m->data_in >> 7) & VIA1B_vRTCData); + m->data_in <<=3D 1; + m->data_in_cnt--; + } + } + + if (m->data_out_cnt =3D=3D 8) { + m->data_out_cnt =3D 0; + + if (m->cmd =3D=3D 0) { + if (m->data_out & 0x80) { + /* this is a read command */ + uint32_t time =3D m->tick_offset + + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / + NANOSECONDS_PER_SECOND); + if (m->data_out =3D=3D 0x81) { /* seconds register = 0 */ + m->data_in =3D time & 0xff; + m->data_in_cnt =3D 8; + } else if (m->data_out =3D=3D 0x85) { /* seconds register = 1 */ + m->data_in =3D (time >> 8) & 0xff; + m->data_in_cnt =3D 8; + } else if (m->data_out =3D=3D 0x89) { /* seconds register = 2 */ + m->data_in =3D (time >> 16) & 0xff; + m->data_in_cnt =3D 8; + } else if (m->data_out =3D=3D 0x8d) { /* seconds register = 3 */ + m->data_in =3D (time >> 24) & 0xff; + m->data_in_cnt =3D 8; + } else if ((m->data_out & 0xf3) =3D=3D 0xa1) { + /* PRAM address 0x10 -> 0x13 */ + int addr =3D (m->data_out >> 2) & 0x03; + m->data_in =3D v1s->PRAM[addr]; + m->data_in_cnt =3D 8; + } else if ((m->data_out & 0xf3) =3D=3D 0xa1) { + /* PRAM address 0x00 -> 0x0f */ + int addr =3D (m->data_out >> 2) & 0x0f; + m->data_in =3D v1s->PRAM[addr]; + m->data_in_cnt =3D 8; + } else if ((m->data_out & 0xf8) =3D=3D 0xb8) { + /* extended memory designator and sector number */ + m->cmd =3D m->data_out; + } + } else { + /* this is a write command */ + m->cmd =3D m->data_out; + } + } else { + if (m->cmd & 0x80) { + if ((m->cmd & 0xf8) =3D=3D 0xb8) { + /* extended memory designator and sector number */ + int sector =3D m->cmd & 0x07; + int addr =3D (m->data_out >> 2) & 0x1f; + + m->data_in =3D v1s->PRAM[sector * 8 + addr]; + m->data_in_cnt =3D 8; + } + } else if (!m->wprotect) { + /* this is a write command */ + if (m->alt !=3D 0) { + /* extended memory designator and sector number */ + int sector =3D m->cmd & 0x07; + int addr =3D (m->alt >> 2) & 0x1f; + + v1s->PRAM[sector * 8 + addr] =3D m->data_out; + + m->alt =3D 0; + } else if (m->cmd =3D=3D 0x01) { /* seconds register 0 */ + /* FIXME */ + } else if (m->cmd =3D=3D 0x05) { /* seconds register 1 */ + /* FIXME */ + } else if (m->cmd =3D=3D 0x09) { /* seconds register 2 */ + /* FIXME */ + } else if (m->cmd =3D=3D 0x0d) { /* seconds register 3 */ + /* FIXME */ + } else if (m->cmd =3D=3D 0x31) { + /* Test Register */ + } else if (m->cmd =3D=3D 0x35) { + /* Write Protect register */ + m->wprotect =3D m->data_out & 1; + } else if ((m->cmd & 0xf3) =3D=3D 0xa1) { + /* PRAM address 0x10 -> 0x13 */ + int addr =3D (m->cmd >> 2) & 0x03; + v1s->PRAM[addr] =3D m->data_out; + } else if ((m->cmd & 0xf3) =3D=3D 0xa1) { + /* PRAM address 0x00 -> 0x0f */ + int addr =3D (m->cmd >> 2) & 0x0f; + v1s->PRAM[addr] =3D m->data_out; + } else if ((m->cmd & 0xf8) =3D=3D 0xb8) { + /* extended memory designator and sector number */ + m->alt =3D m->cmd; + } + } + } + m->data_out =3D 0; + } +} + +static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned= size) +{ + MOS6522Q800VIA1State *s =3D MOS6522_Q800_VIA1(opaque); + MOS6522State *ms =3D MOS6522(s); + int64_t now =3D qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + + /* + * If IRQs are disabled, timers are disabled, but we need to update + * VIA1_IRQ_VBLANK and VIA1_IRQ_ONE_SECOND bits in the IFR + */ + + if (now >=3D s->next_VBL) { + ms->ifr |=3D VIA1_IRQ_VBLANK; + via1_VBL_update(s); + } + if (now >=3D s->next_second) { + ms->ifr |=3D VIA1_IRQ_ONE_SECOND; + via1_one_second_update(s); + } + + addr =3D (addr >> 9) & 0xf; + return mos6522_read(ms, addr, size); +} + +static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t va= l, + unsigned size) +{ + MOS6522Q800VIA1State *v1s =3D MOS6522_Q800_VIA1(opaque); + MOS6522State *ms =3D MOS6522(v1s); + + addr =3D (addr >> 9) & 0xf; + mos6522_write(ms, addr, val, size); + + via1_one_second_update(v1s); + via1_VBL_update(v1s); +} + +static const MemoryRegionOps mos6522_q800_via1_ops =3D { + .read =3D mos6522_q800_via1_read, + .write =3D mos6522_q800_via1_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, +}; + +static uint64_t mos6522_q800_via2_read(void *opaque, hwaddr addr, unsigned= size) +{ + MOS6522Q800VIA2State *s =3D MOS6522_Q800_VIA2(opaque); + MOS6522State *ms =3D MOS6522(s); + + addr =3D (addr >> 9) & 0xf; + return mos6522_read(ms, addr, size); +} + +static void mos6522_q800_via2_write(void *opaque, hwaddr addr, uint64_t va= l, + unsigned size) +{ + MOS6522Q800VIA2State *s =3D MOS6522_Q800_VIA2(opaque); + MOS6522State *ms =3D MOS6522(s); + + addr =3D (addr >> 9) & 0xf; + mos6522_write(ms, addr, val, size); +} + +static const MemoryRegionOps mos6522_q800_via2_ops =3D { + .read =3D mos6522_q800_via2_read, + .write =3D mos6522_q800_via2_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, +}; + +static void mac_via_reset(DeviceState *dev) +{ + MacVIAState *m =3D MAC_VIA(dev); + MOS6522Q800VIA1State *v1s =3D &m->mos6522_via1; + + timer_del(v1s->VBL_timer); + v1s->next_VBL =3D 0; + timer_del(v1s->one_second_timer); + v1s->next_second =3D 0; +} + +static void mac_via_realize(DeviceState *dev, Error **errp) +{ + MacVIAState *m =3D MAC_VIA(dev); + MOS6522State *ms; + struct tm tm; + + /* Init VIAs 1 and 2 */ + sysbus_init_child_obj(OBJECT(dev), "via1", &m->mos6522_via1, + sizeof(m->mos6522_via1), TYPE_MOS6522_Q800_VIA1); + + sysbus_init_child_obj(OBJECT(dev), "via2", &m->mos6522_via2, + sizeof(m->mos6522_via2), TYPE_MOS6522_Q800_VIA2); + + /* Pass through mos6522 output IRQs */ + ms =3D MOS6522(&m->mos6522_via1); + object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms), + SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort); + ms =3D MOS6522(&m->mos6522_via2); + object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms), + SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort); + + /* Pass through mos6522 input IRQs */ + qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq"); + qdev_pass_gpios(DEVICE(&m->mos6522_via2), dev, "via2-irq"); + + /* VIA 1 */ + m->mos6522_via1.one_second_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL, + via1_one_second, + &m->mos6522_via1); + m->mos6522_via1.VBL_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, via1_VB= L, + &m->mos6522_via1); + + qemu_get_timedate(&tm, 0); + m->tick_offset =3D (uint32_t)mktimegm(&tm) + RTC_OFFSET; +} + +static void mac_via_init(Object *obj) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + MacVIAState *m =3D MAC_VIA(obj); + + /* MMIO */ + memory_region_init(&m->mmio, obj, "mac-via", 2 * VIA_SIZE); + sysbus_init_mmio(sbd, &m->mmio); + + memory_region_init_io(&m->via1mem, obj, &mos6522_q800_via1_ops, + &m->mos6522_via1, "via1", VIA_SIZE); + memory_region_add_subregion(&m->mmio, 0x0, &m->via1mem); + + memory_region_init_io(&m->via2mem, obj, &mos6522_q800_via2_ops, + &m->mos6522_via2, "via2", VIA_SIZE); + memory_region_add_subregion(&m->mmio, VIA_SIZE, &m->via2mem); + + /* ADB */ + qbus_create_inplace((BusState *)&m->adb_bus, sizeof(m->adb_bus), + TYPE_ADB_BUS, DEVICE(obj), "adb.0"); +} + +static const VMStateDescription vmstate_mac_via =3D { + .name =3D "mac-via", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + /* VIAs */ + VMSTATE_STRUCT(mos6522_via1.parent_obj, MacVIAState, 0, vmstate_mo= s6522, + MOS6522State), + VMSTATE_UINT8(mos6522_via1.last_b, MacVIAState), + VMSTATE_BUFFER(mos6522_via1.PRAM, MacVIAState), + VMSTATE_TIMER_PTR(mos6522_via1.one_second_timer, MacVIAState), + VMSTATE_INT64(mos6522_via1.next_second, MacVIAState), + VMSTATE_TIMER_PTR(mos6522_via1.VBL_timer, MacVIAState), + VMSTATE_INT64(mos6522_via1.next_VBL, MacVIAState), + VMSTATE_STRUCT(mos6522_via2.parent_obj, MacVIAState, 0, vmstate_mo= s6522, + MOS6522State), + /* RTC */ + VMSTATE_UINT32(tick_offset, MacVIAState), + VMSTATE_UINT8(data_out, MacVIAState), + VMSTATE_INT32(data_out_cnt, MacVIAState), + VMSTATE_UINT8(data_in, MacVIAState), + VMSTATE_UINT8(data_in_cnt, MacVIAState), + VMSTATE_UINT8(cmd, MacVIAState), + VMSTATE_INT32(wprotect, MacVIAState), + VMSTATE_INT32(alt, MacVIAState), + VMSTATE_END_OF_LIST() + } +}; + +static void mac_via_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->realize =3D mac_via_realize; + dc->reset =3D mac_via_reset; + dc->vmsd =3D &vmstate_mac_via; +} + +static TypeInfo mac_via_info =3D { + .name =3D TYPE_MAC_VIA, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(MacVIAState), + .instance_init =3D mac_via_init, + .class_init =3D mac_via_class_init, +}; + +/* VIA 1 */ +static void mos6522_q800_via1_portB_write(MOS6522State *s) +{ + MOS6522Q800VIA1State *v1s =3D container_of(s, MOS6522Q800VIA1State, + parent_obj); + MacVIAState *m =3D container_of(v1s, MacVIAState, mos6522_via1); + + via1_rtc_update(m); + + v1s->last_b =3D s->b; +} + +static void mos6522_q800_via1_reset(DeviceState *dev) +{ + MOS6522State *ms =3D MOS6522(dev); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_GET_CLASS(ms); + + mdc->parent_reset(dev); + + ms->timers[0].frequency =3D VIA_TIMER_FREQ; + ms->timers[1].frequency =3D VIA_TIMER_FREQ; + + ms->b =3D VIA1B_vADB_StateMask | VIA1B_vADBInt | VIA1B_vRTCEnb; +} + +static void mos6522_q800_via1_init(Object *obj) +{ + qdev_init_gpio_in_named(DEVICE(obj), via1_irq_request, "via1-irq", + VIA1_IRQ_NB); +} + +static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_CLASS(oc); + + dc->reset =3D mos6522_q800_via1_reset; + mdc->portB_write =3D mos6522_q800_via1_portB_write; +} + +static const TypeInfo mos6522_q800_via1_type_info =3D { + .name =3D TYPE_MOS6522_Q800_VIA1, + .parent =3D TYPE_MOS6522, + .instance_size =3D sizeof(MOS6522Q800VIA1State), + .instance_init =3D mos6522_q800_via1_init, + .class_init =3D mos6522_q800_via1_class_init, +}; + +/* VIA 2 */ +static void mos6522_q800_via2_portB_write(MOS6522State *s) +{ + if (s->dirb & VIA2B_vPower && (s->b & VIA2B_vPower) =3D=3D 0) { + /* shutdown */ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } +} + +static void mos6522_q800_via2_reset(DeviceState *dev) +{ + MOS6522State *ms =3D MOS6522(dev); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_GET_CLASS(ms); + + mdc->parent_reset(dev); + + ms->timers[0].frequency =3D VIA_TIMER_FREQ; + ms->timers[1].frequency =3D VIA_TIMER_FREQ; + + ms->dirb =3D 0; + ms->b =3D 0; +} + +static void mos6522_q800_via2_init(Object *obj) +{ + qdev_init_gpio_in_named(DEVICE(obj), via2_irq_request, "via2-irq", + VIA2_IRQ_NB); +} + +static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + MOS6522DeviceClass *mdc =3D MOS6522_DEVICE_CLASS(oc); + + dc->reset =3D mos6522_q800_via2_reset; + mdc->portB_write =3D mos6522_q800_via2_portB_write; +} + +static const TypeInfo mos6522_q800_via2_type_info =3D { + .name =3D TYPE_MOS6522_Q800_VIA2, + .parent =3D TYPE_MOS6522, + .instance_size =3D sizeof(MOS6522Q800VIA2State), + .instance_init =3D mos6522_q800_via2_init, + .class_init =3D mos6522_q800_via2_class_init, +}; + +static void mac_via_register_types(void) +{ + type_register_static(&mos6522_q800_via1_type_info); + type_register_static(&mos6522_q800_via2_type_info); + type_register_static(&mac_via_info); +} + +type_init(mac_via_register_types); diff --git a/MAINTAINERS b/MAINTAINERS index ed41d7d1b6..3ce8d10b58 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -917,6 +917,12 @@ F: hw/m68k/next-*.c F: hw/display/next-fb.c F: include/hw/m68k/next-cube.h =20 +q800 +M: Laurent Vivier +S: Maintained +F: hw/misc/mac_via.c +F: include/hw/misc/mac_via.h + MicroBlaze Machines ------------------- petalogix_s3adsp1800 diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index a74fac5abd..22a357609c 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -12,3 +12,7 @@ config NEXTCUBE bool select FRAMEBUFFER select ESCC + +config Q800 + bool + select MAC_VIA diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 51754bb47c..18a5dc9c09 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -120,4 +120,8 @@ config AUX config UNIMP bool =20 +config MAC_VIA + bool + select MOS6522 + source macio/Kconfig diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index c89f3816a5..ba898a5781 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -79,5 +79,6 @@ common-obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_xdma.o common-obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_scu.o aspeed_sdmc.o common-obj-$(CONFIG_MSF2) +=3D msf2-sysreg.o common-obj-$(CONFIG_NRF51_SOC) +=3D nrf51_rng.o +obj-$(CONFIG_MAC_VIA) +=3D mac_via.o =20 common-obj-$(CONFIG_GRLIB) +=3D grlib_ahb_apb_pnp.o --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572288721; cv=none; d=zoho.com; s=zohoarc; b=Jo5xy5sMEIjiBnSQBGRXy6qJ26bL0XTjSRtUNqf1GIxoxMZp3Hu9oSEkqglWsErI/VHdvOd7AGRRL639YNfix0Krrt3HWeMT/RuPfgzNUfEUWqD/RLYbYQ3QEsyWdytU1JGf3cF9XkWhbZ5EKesHmxXFVfwNIENcvyTiZuuVHFs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572288721; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=HFF4SvQ/WZYxem8t5Mw0COcQcAVdzp0PqiG1XvaPWAs=; b=kHu3ouFXRw1AV8c7lPxW1NYWY2HBJBkrHMCcHUomP+jF/tPQCRXQZFhurpvezr+XyT0jlrxs8XrsCfABdD6MXeGay0l5bPb2/5CoLjWD5EZv6kNVKrxOQDhnqFCRjUzWVMww24vtyj5ADb1KRPvz80eXWz/6/uICUAJXA1UP+cQ= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572288721384438.59122592000676; Mon, 28 Oct 2019 11:52:01 -0700 (PDT) Received: from localhost ([::1]:48582 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPA7S-0001xM-5l for importer@patchew.org; Mon, 28 Oct 2019 14:51:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56611) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zp-0002hT-Pz for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zn-00043B-Rd for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:13 -0400 Received: from mout.kundenserver.de ([212.227.17.13]:51391) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zj-0003yY-Fa; Mon, 28 Oct 2019 14:17:07 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1McHQA-1hrCnW2N5A-00cf2x; Mon, 28 Oct 2019 19:16:59 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 06/11] hw/m68k: implement ADB bus support for via Date: Mon, 28 Oct 2019 19:16:38 +0100 Message-Id: <20191028181643.5143-7-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:ML494i2SGiUImlmvTOOclLBZ3Ydc1KcCBKhfLOr8gsyq0LmBZW/ /KKnIVdtjsGHJkYcUNHGpgbvw3Tf26lFg1dkSxDtlxx4TV+ndKJ/d6IxBNZF/Vt5nb8xzVY PFM5NjKDdtH/0BIoSHfOtxXNjDFHGYbwq1TlwyF+ngJ4ZdHSAWftEU3u6brWctMWSVWzsWk A7tRtSKAVKwnm0DkCQRPw== X-UI-Out-Filterresults: notjunk:1;V03:K0:3JKCi0FPCFo=:hUD9ByI7XqpuySEFY8XECp kqsdWTraQqV5HsbzS2tWyclsXbHauWvF48O59wt8AYHKlHlWO79/Y6SlUSPcUyBtByEmxFO0t FqqkFyBlA5BN3mZqKIX4uUM5H8po6oyDRE739Hg6Z0p+Z2rJ7sXMoIOYIYPqFE1GbQbyBxF4u w3rQJ9YY/XC+IvjoIdc2EMTHxTbV+hXTWID0GCZS6Et3DkPQaZqg223agLqGMXYkO3EkYpa6F 9s+1OH18pZBzvBbuxu5wZZlJgjO0o1cdLaFNziocto5Wa1g3UHmouWIWWCELoDHEFNihk4TFz 0xYfTcpPUEpIM0QZAJarcmEODRa10fUmUvSBD9evAuAKoDOwJAQ/PvYwGkfFfVtKSw1TsjiAq gf7JSdImiXB2ayWpAfkaYi8NrJ7uYPlVVB+RQRU0bSs1cM3TsUI59xNSCjlt3Dl461K+0j/gd WtV0eQspDQAD3dqGhwIg2A8POsPPtQ5IYWXUJTxIqh/8CbeqyLFemi0JCiGQAk6cW23AzN0SS 2KZ1HbWB+b+7BBsNKqDX0I4lEubROesjYBPF7/VR1tUBuaN8vPtsrTNxXqkyW2mobTJ8Hp28M hJdb2Mkq1ZtZOnxXDno2kmdgBrD0Bzyq0oCby91Zk4xO/35vzYIxVXoOHFcCVQ+bf5GRmRvSn IMttXvzg3EefmLxCStLsVqUsS8bUIpJyenkd8+u5Y2+bWY9jeqSi2dQaQhUBMu7mBqDx36HbC 7vjt46pfqOl6DsN6509a9SdUIOHjrRK+6039qZkW9SUGU7jMZP+0jQHD8X0PTLu0mc4feHaDS 1Ln4hg/9hqtoZypuB4oqEkdTLiw2gl0bisFGfKUuY57+vkVHMzCHwuntj7WAUolFH/ra5WI57 eRDJeyKYwYLtFSoI64CgEWKIA686PcoolB6qZDFJA= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Thomas Huth , Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" VIA needs to be able to poll the ADB interface and to read/write data from/to the bus. This patch adds functions allowing that. Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Reviewed-by: Herv=C3=A9 Poussineau Reviewed-by: Thomas Huth Message-Id: <20191026164546.30020-7-laurent@vivier.eu> --- include/hw/misc/mac_via.h | 7 ++ hw/misc/mac_via.c | 197 ++++++++++++++++++++++++++++++++++++++ hw/misc/Kconfig | 1 + 3 files changed, 205 insertions(+) diff --git a/include/hw/misc/mac_via.h b/include/hw/misc/mac_via.h index efc8ef3ce3..3f86fcb7e1 100644 --- a/include/hw/misc/mac_via.h +++ b/include/hw/misc/mac_via.h @@ -103,6 +103,13 @@ typedef struct MacVIAState { =20 /* ADB */ ADBBusState adb_bus; + QEMUTimer *adb_poll_timer; + qemu_irq adb_data_ready; + int adb_data_in_size; + int adb_data_in_index; + int adb_data_out_index; + uint8_t adb_data_in[128]; + uint8_t adb_data_out[16]; } MacVIAState; =20 #endif diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c index d2da8b8e60..f3f130ad96 100644 --- a/hw/misc/mac_via.c +++ b/hw/misc/mac_via.c @@ -264,10 +264,16 @@ * Table 19-10 ADB transaction states */ =20 +#define ADB_STATE_NEW 0 +#define ADB_STATE_EVEN 1 +#define ADB_STATE_ODD 2 +#define ADB_STATE_IDLE 3 + #define VIA1B_vADB_StateMask (VIA1B_vADBS1 | VIA1B_vADBS2) #define VIA1B_vADB_StateShift 4 =20 #define VIA_TIMER_FREQ (783360) +#define VIA_ADB_POLL_FREQ 50 /* XXX: not real */ =20 /* VIA returns time offset from Jan 1, 1904, not 1970 */ #define RTC_OFFSET 2082844800 @@ -472,6 +478,181 @@ static void via1_rtc_update(MacVIAState *m) } } =20 +static int adb_via_poll(MacVIAState *s, int state, uint8_t *data) +{ + if (state !=3D ADB_STATE_IDLE) { + return 0; + } + + if (s->adb_data_in_size < s->adb_data_in_index) { + return 0; + } + + if (s->adb_data_out_index !=3D 0) { + return 0; + } + + s->adb_data_in_index =3D 0; + s->adb_data_out_index =3D 0; + s->adb_data_in_size =3D adb_poll(&s->adb_bus, s->adb_data_in, 0xffff); + + if (s->adb_data_in_size) { + *data =3D s->adb_data_in[s->adb_data_in_index++]; + qemu_irq_raise(s->adb_data_ready); + } + + return s->adb_data_in_size; +} + +static int adb_via_send(MacVIAState *s, int state, uint8_t data) +{ + switch (state) { + case ADB_STATE_NEW: + s->adb_data_out_index =3D 0; + break; + case ADB_STATE_EVEN: + if ((s->adb_data_out_index & 1) =3D=3D 0) { + return 0; + } + break; + case ADB_STATE_ODD: + if (s->adb_data_out_index & 1) { + return 0; + } + break; + case ADB_STATE_IDLE: + return 0; + } + + assert(s->adb_data_out_index < sizeof(s->adb_data_out) - 1); + + s->adb_data_out[s->adb_data_out_index++] =3D data; + qemu_irq_raise(s->adb_data_ready); + return 1; +} + +static int adb_via_receive(MacVIAState *s, int state, uint8_t *data) +{ + switch (state) { + case ADB_STATE_NEW: + return 0; + + case ADB_STATE_EVEN: + if (s->adb_data_in_size <=3D 0) { + qemu_irq_raise(s->adb_data_ready); + return 0; + } + + if (s->adb_data_in_index >=3D s->adb_data_in_size) { + *data =3D 0; + qemu_irq_raise(s->adb_data_ready); + return 1; + } + + if ((s->adb_data_in_index & 1) =3D=3D 0) { + return 0; + } + + break; + + case ADB_STATE_ODD: + if (s->adb_data_in_size <=3D 0) { + qemu_irq_raise(s->adb_data_ready); + return 0; + } + + if (s->adb_data_in_index >=3D s->adb_data_in_size) { + *data =3D 0; + qemu_irq_raise(s->adb_data_ready); + return 1; + } + + if (s->adb_data_in_index & 1) { + return 0; + } + + break; + + case ADB_STATE_IDLE: + if (s->adb_data_out_index =3D=3D 0) { + return 0; + } + + s->adb_data_in_size =3D adb_request(&s->adb_bus, s->adb_data_in, + s->adb_data_out, + s->adb_data_out_index); + s->adb_data_out_index =3D 0; + s->adb_data_in_index =3D 0; + if (s->adb_data_in_size < 0) { + *data =3D 0xff; + qemu_irq_raise(s->adb_data_ready); + return -1; + } + + if (s->adb_data_in_size =3D=3D 0) { + return 0; + } + + break; + } + + assert(s->adb_data_in_index < sizeof(s->adb_data_in) - 1); + + *data =3D s->adb_data_in[s->adb_data_in_index++]; + qemu_irq_raise(s->adb_data_ready); + if (*data =3D=3D 0xff || *data =3D=3D 0) { + return 0; + } + return 1; +} + +static void via1_adb_update(MacVIAState *m) +{ + MOS6522Q800VIA1State *v1s =3D MOS6522_Q800_VIA1(&m->mos6522_via1); + MOS6522State *s =3D MOS6522(v1s); + int state; + int ret; + + state =3D (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift; + + if (s->acr & VIA1ACR_vShiftOut) { + /* output mode */ + ret =3D adb_via_send(m, state, s->sr); + if (ret > 0) { + s->b &=3D ~VIA1B_vADBInt; + } else { + s->b |=3D VIA1B_vADBInt; + } + } else { + /* input mode */ + ret =3D adb_via_receive(m, state, &s->sr); + if (ret > 0 && s->sr !=3D 0xff) { + s->b &=3D ~VIA1B_vADBInt; + } else { + s->b |=3D VIA1B_vADBInt; + } + } +} + +static void via_adb_poll(void *opaque) +{ + MacVIAState *m =3D opaque; + MOS6522Q800VIA1State *v1s =3D MOS6522_Q800_VIA1(&m->mos6522_via1); + MOS6522State *s =3D MOS6522(v1s); + int state; + + if (s->b & VIA1B_vADBInt) { + state =3D (s->b & VIA1B_vADB_StateMask) >> VIA1B_vADB_StateShift; + if (adb_via_poll(m, state, &s->sr)) { + s->b &=3D ~VIA1B_vADBInt; + } + } + + timer_mod(m->adb_poll_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + (NANOSECONDS_PER_SECOND / VIA_ADB_POLL_FREQ)); +} + static uint64_t mos6522_q800_via1_read(void *opaque, hwaddr addr, unsigned= size) { MOS6522Q800VIA1State *s =3D MOS6522_Q800_VIA1(opaque); @@ -553,6 +734,10 @@ static void mac_via_reset(DeviceState *dev) MacVIAState *m =3D MAC_VIA(dev); MOS6522Q800VIA1State *v1s =3D &m->mos6522_via1; =20 + timer_mod(m->adb_poll_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + (NANOSECONDS_PER_SECOND / VIA_ADB_POLL_FREQ)); + timer_del(v1s->VBL_timer); v1s->next_VBL =3D 0; timer_del(v1s->one_second_timer); @@ -593,6 +778,10 @@ static void mac_via_realize(DeviceState *dev, Error **= errp) =20 qemu_get_timedate(&tm, 0); m->tick_offset =3D (uint32_t)mktimegm(&tm) + RTC_OFFSET; + + m->adb_poll_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, via_adb_poll, m= ); + m->adb_data_ready =3D qdev_get_gpio_in_named(dev, "via1-irq", + VIA1_IRQ_ADB_READY_BIT); } =20 static void mac_via_init(Object *obj) @@ -642,6 +831,13 @@ static const VMStateDescription vmstate_mac_via =3D { VMSTATE_UINT8(cmd, MacVIAState), VMSTATE_INT32(wprotect, MacVIAState), VMSTATE_INT32(alt, MacVIAState), + /* ADB */ + VMSTATE_TIMER_PTR(adb_poll_timer, MacVIAState), + VMSTATE_INT32(adb_data_in_size, MacVIAState), + VMSTATE_INT32(adb_data_in_index, MacVIAState), + VMSTATE_INT32(adb_data_out_index, MacVIAState), + VMSTATE_BUFFER(adb_data_in, MacVIAState), + VMSTATE_BUFFER(adb_data_out, MacVIAState), VMSTATE_END_OF_LIST() } }; @@ -671,6 +867,7 @@ static void mos6522_q800_via1_portB_write(MOS6522State = *s) MacVIAState *m =3D container_of(v1s, MacVIAState, mos6522_via1); =20 via1_rtc_update(m); + via1_adb_update(m); =20 v1s->last_b =3D s->b; } diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 18a5dc9c09..2164646553 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -123,5 +123,6 @@ config UNIMP config MAC_VIA bool select MOS6522 + select ADB =20 source macio/Kconfig --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572291137; cv=none; d=zoho.com; s=zohoarc; b=ksCZTkSpLCJqepFZMJxSucDt1kLtSXJGWpqSLJoH4Ril1EwCbD7Dk/wUsVNfVYuzP7YgAqy0A4nfF6pHgcjmUGxQ4V8xovwB48pHM8f/idBjnMyfMLl1HnDg9O8yjCa8VB1p4ya+HBAN4cwOdydSLBbTISSlkQZiBUhEW+m7G9E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572291137; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=GiZPCONGaMyKlEXIEMFk2frr8pTOa7zqS/ehVYb1ovE=; b=PEm/nx/34qcTYceLK+uzYF22r8houQbQFa+3066ymxkWleEeEUoAPww7AQlVg05eI3WZq106ibDG9+vIM95Cf8Iwbp2/yciUwCKSkI8ddkaVNBvw7La/r6nZZwb84aX75jucvieUqLiU2UULUCu8VGhenFi3WEZFPHRgB1Rfbhw= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15722911377671015.3566332026267; Mon, 28 Oct 2019 12:32:17 -0700 (PDT) Received: from localhost ([::1]:55872 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAkQ-00008U-Hy for importer@patchew.org; Mon, 28 Oct 2019 15:32:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56588) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zn-0002fS-VZ for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zl-00040k-3Y for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:11 -0400 Received: from mout.kundenserver.de ([217.72.192.75]:37633) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zk-0003zb-N4; Mon, 28 Oct 2019 14:17:09 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MybX9-1i4BN83F2z-00yz9u; Mon, 28 Oct 2019 19:17:00 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 07/11] hw/m68k: add Nubus support Date: Mon, 28 Oct 2019 19:16:39 +0100 Message-Id: <20191028181643.5143-8-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:UUdLXYmSaQDohvTJAglMNvi/GdEBqmT6A1ffCFFhktsNWgh2Hm+ og/HQEJT1aDnbzT+CYpa37ZOTlkNWHRUDFMg9TFBByLo3YrLYDRQ7H71otHN2kldtdd0TNo axPd9WPIOcZrgOQC9Rl7IGinjjYfkZyCWQ5h00DoxVnBKDLAsmSs6EoiUM3lJJDkUNofxF3 iA8vbHES83r+W4GoBmHiw== X-UI-Out-Filterresults: notjunk:1;V03:K0:XAGtPPdzNtg=:q3W4+773TD+3Y+tst9OMil s5laxSX0uiSTzz1Va7t/F3Og658uWwpQHV1r+xlBeC6sVDgkv0LbvviDII7uTOqA6EpH2BU3M Hd0v6sSlipS5n0433qm75sEceeGK6AQMoRufpp7ZO+cV9y+GuMr3s6IzZi+DF9zUIzHMEpVYn H45qtxtzyPF2tZ1tvKD4uwAg0ArovrRZ3l+cpdoLTCHBAOahdnpJb51QUskqvEE2rRDVTWRak E/4IZumE5RSM7uV9dMoiJdp2CFu6eAUyhDe8kfm9VaD1J0UM1UdFM2DLDXHnEX8/h1FJuN88i uKrcDjRWm0Lr604+DCDr1QWjT/hIbM60cJTan2sBj2TXvZmh6+Tu7dHFqdymEpYh3srfEoyO0 cK161EnwC6UZzzYrVomvrO6oPyinMt7DqDWmmuRbs3t0HYOSMKF0YXHADl2iinVM/YOm6Ao9Y mx3mAdPip89KUHrd9TIZLjJF7hk/jBqlGLttoWJznNdanLM6x+OpjF2QLa5EAgT9bqDraNf0J aYt/YJF+N41612fYOc9Gb14nHYHBVv5BMIVfE6/b12/NcIxork/0sdxG9UN0MIyTLu+xf1raC Tx2DsxwVIMLBuQmweh6W3kkjwb7cmaXWPiIHJwHNxz15YI9uVzjmTEgk28nz6/Jc/+ueE791l 9G6B+lfjbvKCJ4znSoU6Sfbvxesib3k7ljsyHaf/7UUx7kkQyzO/rctVAd8HJJAs+6v3TZOLk LghTlsh7hGz6SWzEnjqaAhlLuRxoMaLEOXPn8jHiAbG1KPe5RI8RTQ4kwPoPebesM72ox/Kj4 1uqqt2lXFEoOTyHpW4++2ZqDI2ZH7RiJEhwFhe95EGgb6rNePOdlO7ycqlv9DWR8CqbYyKykm +pF2a8lkr59zS/xBTc7Q== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.75 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Thomas Huth , Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This patch adds basic support for the NuBus bus. This is used by 680x0 Macintosh. Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Reviewed-by: Thomas Huth Message-Id: <20191026164546.30020-8-laurent@vivier.eu> --- include/hw/nubus/mac-nubus-bridge.h | 24 ++++ include/hw/nubus/nubus.h | 69 +++++++++ hw/nubus/mac-nubus-bridge.c | 45 ++++++ hw/nubus/nubus-bridge.c | 34 +++++ hw/nubus/nubus-bus.c | 111 ++++++++++++++ hw/nubus/nubus-device.c | 215 ++++++++++++++++++++++++++++ MAINTAINERS | 2 + hw/Kconfig | 1 + hw/Makefile.objs | 1 + hw/m68k/Kconfig | 1 + hw/nubus/Kconfig | 2 + hw/nubus/Makefile.objs | 4 + 12 files changed, 509 insertions(+) create mode 100644 include/hw/nubus/mac-nubus-bridge.h create mode 100644 include/hw/nubus/nubus.h create mode 100644 hw/nubus/mac-nubus-bridge.c create mode 100644 hw/nubus/nubus-bridge.c create mode 100644 hw/nubus/nubus-bus.c create mode 100644 hw/nubus/nubus-device.c create mode 100644 hw/nubus/Kconfig create mode 100644 hw/nubus/Makefile.objs diff --git a/include/hw/nubus/mac-nubus-bridge.h b/include/hw/nubus/mac-nub= us-bridge.h new file mode 100644 index 0000000000..ce9c789d99 --- /dev/null +++ b/include/hw/nubus/mac-nubus-bridge.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_NUBUS_MAC_H +#define HW_NUBUS_MAC_H + +#include "hw/nubus/nubus.h" + +#define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge" +#define MAC_NUBUS_BRIDGE(obj) OBJECT_CHECK(MacNubusState, (obj), \ + TYPE_MAC_NUBUS_BRIDGE) + +typedef struct MacNubusState { + SysBusDevice sysbus_dev; + + NubusBus *bus; +} MacNubusState; + +#endif diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h new file mode 100644 index 0000000000..a8634e54c5 --- /dev/null +++ b/include/hw/nubus/nubus.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef HW_NUBUS_NUBUS_H +#define HW_NUBUS_NUBUS_H + +#include "hw/qdev-properties.h" +#include "exec/address-spaces.h" + +#define NUBUS_SUPER_SLOT_SIZE 0x10000000U +#define NUBUS_SUPER_SLOT_NB 0x9 + +#define NUBUS_SLOT_SIZE 0x01000000 +#define NUBUS_SLOT_NB 0xF + +#define NUBUS_FIRST_SLOT 0x9 +#define NUBUS_LAST_SLOT 0xF + +#define TYPE_NUBUS_DEVICE "nubus-device" +#define NUBUS_DEVICE(obj) \ + OBJECT_CHECK(NubusDevice, (obj), TYPE_NUBUS_DEVICE) + +#define TYPE_NUBUS_BUS "nubus-bus" +#define NUBUS_BUS(obj) OBJECT_CHECK(NubusBus, (obj), TYPE_NUBUS_BUS) + +#define TYPE_NUBUS_BRIDGE "nubus-bridge" +#define NUBUS_BRIDGE(obj) OBJECT_CHECK(NubusBridge, (obj), TYPE_NUBUS_BRID= GE) + +typedef struct NubusBus { + BusState qbus; + + MemoryRegion super_slot_io; + MemoryRegion slot_io; + + int current_slot; +} NubusBus; + +typedef struct NubusDevice { + DeviceState qdev; + + int slot_nb; + MemoryRegion slot_mem; + + /* Format Block */ + + MemoryRegion fblock_io; + + uint32_t rom_length; + uint32_t rom_crc; + uint8_t rom_rev; + uint8_t rom_format; + uint8_t byte_lanes; + int32_t directory_offset; + + /* ROM */ + + MemoryRegion rom_io; + const uint8_t *rom; +} NubusDevice; + +void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t siz= e, + int revision, int format, uint8_t byte_lanes); + +#endif diff --git a/hw/nubus/mac-nubus-bridge.c b/hw/nubus/mac-nubus-bridge.c new file mode 100644 index 0000000000..7c329300b8 --- /dev/null +++ b/hw/nubus/mac-nubus-bridge.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/nubus/mac-nubus-bridge.h" + + +static void mac_nubus_bridge_init(Object *obj) +{ + MacNubusState *s =3D MAC_NUBUS_BRIDGE(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + s->bus =3D NUBUS_BUS(qbus_create(TYPE_NUBUS_BUS, DEVICE(s), NULL)); + + sysbus_init_mmio(sbd, &s->bus->super_slot_io); + sysbus_init_mmio(sbd, &s->bus->slot_io); +} + +static void mac_nubus_bridge_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->desc =3D "Nubus bridge"; +} + +static const TypeInfo mac_nubus_bridge_info =3D { + .name =3D TYPE_MAC_NUBUS_BRIDGE, + .parent =3D TYPE_NUBUS_BRIDGE, + .instance_init =3D mac_nubus_bridge_init, + .instance_size =3D sizeof(MacNubusState), + .class_init =3D mac_nubus_bridge_class_init, +}; + +static void mac_nubus_bridge_register_types(void) +{ + type_register_static(&mac_nubus_bridge_info); +} + +type_init(mac_nubus_bridge_register_types) diff --git a/hw/nubus/nubus-bridge.c b/hw/nubus/nubus-bridge.c new file mode 100644 index 0000000000..cd8c6a91eb --- /dev/null +++ b/hw/nubus/nubus-bridge.c @@ -0,0 +1,34 @@ +/* + * QEMU Macintosh Nubus + * + * Copyright (c) 2013-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/nubus/nubus.h" + +static void nubus_bridge_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->fw_name =3D "nubus"; +} + +static const TypeInfo nubus_bridge_info =3D { + .name =3D TYPE_NUBUS_BRIDGE, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(SysBusDevice), + .class_init =3D nubus_bridge_class_init, +}; + +static void nubus_register_types(void) +{ + type_register_static(&nubus_bridge_info); +} + +type_init(nubus_register_types) diff --git a/hw/nubus/nubus-bus.c b/hw/nubus/nubus-bus.c new file mode 100644 index 0000000000..942a6d5342 --- /dev/null +++ b/hw/nubus/nubus-bus.c @@ -0,0 +1,111 @@ +/* + * QEMU Macintosh Nubus + * + * Copyright (c) 2013-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "hw/nubus/nubus.h" +#include "hw/sysbus.h" +#include "qapi/error.h" + + +static NubusBus *nubus_find(void) +{ + /* Returns NULL unless there is exactly one nubus device */ + return NUBUS_BUS(object_resolve_path_type("", TYPE_NUBUS_BUS, NULL)); +} + +static void nubus_slot_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + /* read only */ +} + + +static uint64_t nubus_slot_read(void *opaque, hwaddr addr, + unsigned int size) +{ + return 0; +} + +static const MemoryRegionOps nubus_slot_ops =3D { + .read =3D nubus_slot_read, + .write =3D nubus_slot_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, +}; + +static void nubus_super_slot_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + /* read only */ +} + +static uint64_t nubus_super_slot_read(void *opaque, hwaddr addr, + unsigned int size) +{ + return 0; +} + +static const MemoryRegionOps nubus_super_slot_ops =3D { + .read =3D nubus_super_slot_read, + .write =3D nubus_super_slot_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, +}; + +static void nubus_realize(BusState *bus, Error **errp) +{ + if (!nubus_find()) { + error_setg(errp, "at most one %s device is permitted", TYPE_NUBUS_= BUS); + return; + } +} + +static void nubus_init(Object *obj) +{ + NubusBus *nubus =3D NUBUS_BUS(obj); + + memory_region_init_io(&nubus->super_slot_io, obj, &nubus_super_slot_op= s, + nubus, "nubus-super-slots", + NUBUS_SUPER_SLOT_NB * NUBUS_SUPER_SLOT_SIZE); + + memory_region_init_io(&nubus->slot_io, obj, &nubus_slot_ops, + nubus, "nubus-slots", + NUBUS_SLOT_NB * NUBUS_SLOT_SIZE); + + nubus->current_slot =3D NUBUS_FIRST_SLOT; +} + +static void nubus_class_init(ObjectClass *oc, void *data) +{ + BusClass *bc =3D BUS_CLASS(oc); + + bc->realize =3D nubus_realize; +} + +static const TypeInfo nubus_bus_info =3D { + .name =3D TYPE_NUBUS_BUS, + .parent =3D TYPE_BUS, + .instance_size =3D sizeof(NubusBus), + .instance_init =3D nubus_init, + .class_init =3D nubus_class_init, +}; + +static void nubus_register_types(void) +{ + type_register_static(&nubus_bus_info); +} + +type_init(nubus_register_types) diff --git a/hw/nubus/nubus-device.c b/hw/nubus/nubus-device.c new file mode 100644 index 0000000000..01ccad9e8e --- /dev/null +++ b/hw/nubus/nubus-device.c @@ -0,0 +1,215 @@ +/* + * QEMU Macintosh Nubus + * + * Copyright (c) 2013-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "hw/nubus/nubus.h" +#include "qapi/error.h" + + +/* The Format Block Structure */ + +#define FBLOCK_DIRECTORY_OFFSET 0 +#define FBLOCK_LENGTH 4 +#define FBLOCK_CRC 8 +#define FBLOCK_REVISION_LEVEL 12 +#define FBLOCK_FORMAT 13 +#define FBLOCK_TEST_PATTERN 14 +#define FBLOCK_RESERVED 18 +#define FBLOCK_BYTE_LANES 19 + +#define FBLOCK_SIZE 20 +#define FBLOCK_PATTERN_VAL 0x5a932bc7 + +static uint64_t nubus_fblock_read(void *opaque, hwaddr addr, unsigned int = size) +{ + NubusDevice *dev =3D opaque; + uint64_t val; + +#define BYTE(v, b) (((v) >> (24 - 8 * (b))) & 0xff) + switch (addr) { + case FBLOCK_BYTE_LANES: + val =3D dev->byte_lanes; + val |=3D (val ^ 0xf) << 4; + break; + case FBLOCK_RESERVED: + val =3D 0x00; + break; + case FBLOCK_TEST_PATTERN...FBLOCK_TEST_PATTERN + 3: + val =3D BYTE(FBLOCK_PATTERN_VAL, addr - FBLOCK_TEST_PATTERN); + break; + case FBLOCK_FORMAT: + val =3D dev->rom_format; + break; + case FBLOCK_REVISION_LEVEL: + val =3D dev->rom_rev; + break; + case FBLOCK_CRC...FBLOCK_CRC + 3: + val =3D BYTE(dev->rom_crc, addr - FBLOCK_CRC); + break; + case FBLOCK_LENGTH...FBLOCK_LENGTH + 3: + val =3D BYTE(dev->rom_length, addr - FBLOCK_LENGTH); + break; + case FBLOCK_DIRECTORY_OFFSET...FBLOCK_DIRECTORY_OFFSET + 3: + val =3D BYTE(dev->directory_offset, addr - FBLOCK_DIRECTORY_OFFSET= ); + break; + default: + val =3D 0; + break; + } + return val; +} + +static void nubus_fblock_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + /* read only */ +} + +static const MemoryRegionOps nubus_format_block_ops =3D { + .read =3D nubus_fblock_read, + .write =3D nubus_fblock_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + } +}; + +static void nubus_register_format_block(NubusDevice *dev) +{ + char *fblock_name; + + fblock_name =3D g_strdup_printf("nubus-slot-%d-format-block", + dev->slot_nb); + + hwaddr fblock_offset =3D memory_region_size(&dev->slot_mem) - FBLOCK_S= IZE; + memory_region_init_io(&dev->fblock_io, NULL, &nubus_format_block_ops, + dev, fblock_name, FBLOCK_SIZE); + memory_region_add_subregion(&dev->slot_mem, fblock_offset, + &dev->fblock_io); + + g_free(fblock_name); +} + +static void mac_nubus_rom_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ + /* read only */ +} + +static uint64_t mac_nubus_rom_read(void *opaque, hwaddr addr, + unsigned int size) +{ + NubusDevice *dev =3D opaque; + + return dev->rom[addr]; +} + +static const MemoryRegionOps mac_nubus_rom_ops =3D { + .read =3D mac_nubus_rom_read, + .write =3D mac_nubus_rom_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 1, + }, +}; + + +void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t siz= e, + int revision, int format, uint8_t byte_lanes) +{ + hwaddr rom_offset; + char *rom_name; + + /* FIXME : really compute CRC */ + dev->rom_length =3D 0; + dev->rom_crc =3D 0; + + dev->rom_rev =3D revision; + dev->rom_format =3D format; + + dev->byte_lanes =3D byte_lanes; + dev->directory_offset =3D -size; + + /* ROM */ + + dev->rom =3D rom; + rom_name =3D g_strdup_printf("nubus-slot-%d-rom", dev->slot_nb); + memory_region_init_io(&dev->rom_io, NULL, &mac_nubus_rom_ops, + dev, rom_name, size); + memory_region_set_readonly(&dev->rom_io, true); + + rom_offset =3D memory_region_size(&dev->slot_mem) - FBLOCK_SIZE + + dev->directory_offset; + memory_region_add_subregion(&dev->slot_mem, rom_offset, &dev->rom_io); + + g_free(rom_name); +} + +static void nubus_device_realize(DeviceState *dev, Error **errp) +{ + NubusBus *nubus =3D NUBUS_BUS(qdev_get_parent_bus(DEVICE(dev))); + NubusDevice *nd =3D NUBUS_DEVICE(dev); + char *name; + hwaddr slot_offset; + + if (nubus->current_slot < NUBUS_FIRST_SLOT || + nubus->current_slot > NUBUS_LAST_SLOT) { + error_setg(errp, "Cannot register nubus card, not enough slots"); + return; + } + + nd->slot_nb =3D nubus->current_slot++; + name =3D g_strdup_printf("nubus-slot-%d", nd->slot_nb); + + if (nd->slot_nb < NUBUS_FIRST_SLOT) { + /* Super */ + slot_offset =3D (nd->slot_nb - 6) * NUBUS_SUPER_SLOT_SIZE; + + memory_region_init(&nd->slot_mem, OBJECT(dev), name, + NUBUS_SUPER_SLOT_SIZE); + memory_region_add_subregion(&nubus->super_slot_io, slot_offset, + &nd->slot_mem); + } else { + /* Normal */ + slot_offset =3D nd->slot_nb * NUBUS_SLOT_SIZE; + + memory_region_init(&nd->slot_mem, OBJECT(dev), name, NUBUS_SLOT_SI= ZE); + memory_region_add_subregion(&nubus->slot_io, slot_offset, + &nd->slot_mem); + } + + g_free(name); + nubus_register_format_block(nd); +} + +static void nubus_device_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->realize =3D nubus_device_realize; + dc->bus_type =3D TYPE_NUBUS_BUS; +} + +static const TypeInfo nubus_device_type_info =3D { + .name =3D TYPE_NUBUS_DEVICE, + .parent =3D TYPE_DEVICE, + .abstract =3D true, + .instance_size =3D sizeof(NubusDevice), + .class_init =3D nubus_device_class_init, +}; + +static void nubus_register_types(void) +{ + type_register_static(&nubus_device_type_info); +} + +type_init(nubus_register_types) diff --git a/MAINTAINERS b/MAINTAINERS index 3ce8d10b58..7892ab5f02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -921,7 +921,9 @@ q800 M: Laurent Vivier S: Maintained F: hw/misc/mac_via.c +F: hw/nubus/* F: include/hw/misc/mac_via.h +F: include/hw/nubus/* =20 MicroBlaze Machines ------------------- diff --git a/hw/Kconfig b/hw/Kconfig index b45db3c813..0501a55315 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -21,6 +21,7 @@ source isa/Kconfig source mem/Kconfig source misc/Kconfig source net/Kconfig +source nubus/Kconfig source nvram/Kconfig source pci-bridge/Kconfig source pci-host/Kconfig diff --git a/hw/Makefile.objs b/hw/Makefile.objs index ece6cc3755..457b95e28d 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -37,6 +37,7 @@ devices-dirs-y +=3D virtio/ devices-dirs-y +=3D watchdog/ devices-dirs-y +=3D xen/ devices-dirs-$(CONFIG_MEM_DEVICE) +=3D mem/ +devices-dirs-$(CONFIG_NUBUS) +=3D nubus/ devices-dirs-y +=3D semihosting/ devices-dirs-y +=3D smbios/ endif diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index 22a357609c..947cd42c01 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -16,3 +16,4 @@ config NEXTCUBE config Q800 bool select MAC_VIA + select NUBUS diff --git a/hw/nubus/Kconfig b/hw/nubus/Kconfig new file mode 100644 index 0000000000..8fb8b22189 --- /dev/null +++ b/hw/nubus/Kconfig @@ -0,0 +1,2 @@ +config NUBUS + bool diff --git a/hw/nubus/Makefile.objs b/hw/nubus/Makefile.objs new file mode 100644 index 0000000000..135ba7878d --- /dev/null +++ b/hw/nubus/Makefile.objs @@ -0,0 +1,4 @@ +common-obj-y +=3D nubus-device.o +common-obj-y +=3D nubus-bus.o +common-obj-y +=3D nubus-bridge.o +common-obj-$(CONFIG_Q800) +=3D mac-nubus-bridge.o --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572291342; cv=none; d=zoho.com; s=zohoarc; b=Q31iXOgsvEOXxZthN8S78eXeMj9FNZBUL+zDCTxCBFCA2dfZL1z81PmAKtqb8PD0f8kOHATcSM9NzN5oSdz+c+rnyghDNuD6DAwk9kLXG5SVM4Fbvp2rXTwiatrqyBE9Bd9FAFTx+fYWJQWDJeG4+fvPD5urvmNVN9ORWuPNaB0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572291342; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=OZ6Fe+43yWFNKFQGC1mie+mMJnMWTVSj9leZo3QucmI=; b=XYrP7kNzvQ8UCwmdeYX8KCAjpfPBq8GIRPirx3xptVoG6UAbe+jm5RGYA2o6UGvitd/9RgE888/lJHtkLJJI/7GeZFwhYMGErwTXFi21b+q8GS0DOoh6I7Yg1SpUaiQoNQhEoV7V6mh5sSM0qo+Wqpq0PhgUJ2o7VWjBt4+rUtM= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572291342205176.19410033720555; Mon, 28 Oct 2019 12:35:42 -0700 (PDT) Received: from localhost ([::1]:56472 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAnj-0006CU-7i for importer@patchew.org; Mon, 28 Oct 2019 15:35:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56606) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zp-0002gu-F4 for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zl-00041G-Kp for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:13 -0400 Received: from mout.kundenserver.de ([212.227.17.13]:54419) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zl-000403-6E; Mon, 28 Oct 2019 14:17:09 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1N6LIF-1hwRc547Kb-016iv0; Mon, 28 Oct 2019 19:17:01 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 08/11] hw/m68k: add Nubus macfb video card Date: Mon, 28 Oct 2019 19:16:40 +0100 Message-Id: <20191028181643.5143-9-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:pozmg89cgGeamZ0YP0v9FeLQAnrAAdHbVEwc0f0h4QTBME5IWLs 9j1vXMt9z5uVWEB1CaRH6n+ZXZdbomHyhQOgGJly+cdo3n4cfueyuS+UVHw2UvEAtmQ4Jn+ 560fK6o4rA8ozIVa2etHylpHCXZiHC2YlktIeqoYBPpdHTT99XalIZU6UR30KLqArMsbCFW 5woU3+rMLeXPEgVQO41Xw== X-UI-Out-Filterresults: notjunk:1;V03:K0:C8HlVZPaQoA=:ogbVonjDJaBwVT8VlpzB2l IAJ7xTDjKUt1Gv5jpEHdrbwym18z0KwctHPyC+6OjzWtUCRIIUEFYGG3mJ5v75QtA8Z6w+/xF 3JuDz/3CHOHq5XM1ONgAYTMMRBGUXxp4VDNqCeOhz1qZxXwqFPeQ5q1LG63nRDL+CoJj+QBGO wgxRG3+7ctDC3gvyJztaCY8+dqOaWMw+ZoEL+2aCfQVhzcPFIl9wyVTPuyY6CifLHWHpVvlI/ gsGrbC5AGDNNj7K0fQFu2J0N8n7eb/YnXnbhnrlQ3lEmZplDCmqAu79t2f3ii/9CQK/sqoX68 yn0bZChQFGXQQjWxRBr/8MLLJk9Bv84ABCT4tgO5f1xaY0ypp99ratU6Oj0aet9GjDiA9Ride CZfMYYGlB0M+q6kw3k96ZWeyvWM8Wvkl/hAW7rsa6Vkx6KW/a5SnNNOa7RcNvn+U6dK9BcgTp SRnWBMrVtAnUdnYDEiT+TatXMIy+OAFF4Tk4A3BzJ9xjeqgcqKd0u+HI9fda8L9JIN4dNrsU7 hHug8rjniOuK3fvMpegugK+cxc7l9Fw2TpWRA+TO0VvSXh0ESnFcabaq+pF8ClFrmxBgrseli s5u63DrhmV8vZvfuTXYZbMMAP2bqRegzXup1cx0sYUG/8p/7pXumZkSsbNhxlkJhPNGdypz1b k9p/cUr+I7c3I6A0Ps6f+l1daXFb5dMVz38lQ15X2ZqIAZ7xtQ/IHumUZUagn9SiEGiAjFa7j oS711r2tdteQT9PutS4wPFRsHQa2mKuKz7cffcyBEHqJyY7DHZ7jhIqMROQ4iDS2OmAdefJ1a +6eJOtTrIeegOZ+RJrz5plLKxtJa0C7sDsXMpAeuAWBhcLtP6q9WALnOU2KRhrxUyMAEgzQXQ Mky1hVKHejfhf0KlgUoALbhoEiuJfhDxVMrpAQX3I= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Thomas Huth , Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" This patch adds support for a graphic framebuffer device. This device can be added as a sysbus device or as a NuBus device. It is accessed as a framebuffer but the color palette can be set. Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Reviewed-by: Herv=C3=A9 Poussineau Reviewed-by: Thomas Huth Message-Id: <20191026164546.30020-9-laurent@vivier.eu> --- include/hw/display/macfb.h | 64 +++++ arch_init.c | 4 + hw/display/macfb.c | 477 +++++++++++++++++++++++++++++++++++++ vl.c | 3 +- MAINTAINERS | 2 + hw/display/Kconfig | 5 + hw/display/Makefile.objs | 1 + hw/m68k/Kconfig | 1 + qemu-options.hx | 2 +- 9 files changed, 557 insertions(+), 2 deletions(-) create mode 100644 include/hw/display/macfb.h create mode 100644 hw/display/macfb.c diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h new file mode 100644 index 0000000000..26367ae2c4 --- /dev/null +++ b/include/hw/display/macfb.h @@ -0,0 +1,64 @@ +/* + * QEMU Motorola 680x0 Macintosh Video Card Emulation + * Copyright (c) 2012-2018 Laurent Vivier + * + * some parts from QEMU G364 framebuffer Emulator. + * Copyright (c) 2007-2011 Herve Poussineau + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef MACFB_H +#define MACFB_H + +#include "qemu/osdep.h" +#include "exec/memory.h" +#include "ui/console.h" + +typedef struct MacfbState { + MemoryRegion mem_vram; + MemoryRegion mem_ctrl; + QemuConsole *con; + + uint8_t *vram; + uint32_t vram_bit_mask; + uint32_t palette_current; + uint8_t color_palette[256 * 3]; + uint32_t width, height; /* in pixels */ + uint8_t depth; +} MacfbState; + +#define TYPE_MACFB "sysbus-macfb" +#define MACFB(obj) \ + OBJECT_CHECK(MacfbSysBusState, (obj), TYPE_MACFB) + +typedef struct { + SysBusDevice busdev; + + MacfbState macfb; +} MacfbSysBusState; + +#define MACFB_NUBUS_DEVICE_CLASS(class) \ + OBJECT_CLASS_CHECK(MacfbNubusDeviceClass, (class), TYPE_NUBUS_MACFB) +#define MACFB_NUBUS_GET_CLASS(obj) \ + OBJECT_GET_CLASS(MacfbNubusDeviceClass, (obj), TYPE_NUBUS_MACFB) + +typedef struct MacfbNubusDeviceClass { + DeviceClass parent_class; + + DeviceRealize parent_realize; +} MacfbNubusDeviceClass; + +#define TYPE_NUBUS_MACFB "nubus-macfb" +#define NUBUS_MACFB(obj) \ + OBJECT_CHECK(MacfbNubusState, (obj), TYPE_NUBUS_MACFB) + +typedef struct { + NubusDevice busdev; + + MacfbState macfb; +} MacfbNubusState; + +#endif diff --git a/arch_init.c b/arch_init.c index 0a1531124c..705d0b94ad 100644 --- a/arch_init.c +++ b/arch_init.c @@ -38,6 +38,10 @@ int graphic_width =3D 1024; int graphic_height =3D 768; int graphic_depth =3D 8; +#elif defined(TARGET_M68K) +int graphic_width =3D 800; +int graphic_height =3D 600; +int graphic_depth =3D 8; #else int graphic_width =3D 800; int graphic_height =3D 600; diff --git a/hw/display/macfb.c b/hw/display/macfb.c new file mode 100644 index 0000000000..f4fa8e3206 --- /dev/null +++ b/hw/display/macfb.c @@ -0,0 +1,477 @@ +/* + * QEMU Motorola 680x0 Macintosh Video Card Emulation + * Copyright (c) 2012-2018 Laurent Vivier + * + * some parts from QEMU G364 framebuffer Emulator. + * Copyright (c) 2007-2011 Herve Poussineau + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "hw/sysbus.h" +#include "ui/console.h" +#include "ui/pixel_ops.h" +#include "hw/nubus/nubus.h" +#include "hw/display/macfb.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" + +#define VIDEO_BASE 0x00001000 +#define DAFB_BASE 0x00800000 + +#define MACFB_PAGE_SIZE 4096 +#define MACFB_VRAM_SIZE (4 * MiB) + +#define DAFB_RESET 0x200 +#define DAFB_LUT 0x213 + + +typedef void macfb_draw_line_func(MacfbState *s, uint8_t *d, uint32_t addr, + int width); + +static inline uint8_t macfb_read_byte(MacfbState *s, uint32_t addr) +{ + return s->vram[addr & s->vram_bit_mask]; +} + +/* 1-bit color */ +static void macfb_draw_line1(MacfbState *s, uint8_t *d, uint32_t addr, + int width) +{ + uint8_t r, g, b; + int x; + + for (x =3D 0; x < width; x++) { + int bit =3D x & 7; + int idx =3D (macfb_read_byte(s, addr) >> (7 - bit)) & 1; + r =3D g =3D b =3D ((1 - idx) << 7); + addr +=3D (bit =3D=3D 7); + + *(uint32_t *)d =3D rgb_to_pixel32(r, g, b); + d +=3D 4; + } +} + +/* 2-bit color */ +static void macfb_draw_line2(MacfbState *s, uint8_t *d, uint32_t addr, + int width) +{ + uint8_t r, g, b; + int x; + + for (x =3D 0; x < width; x++) { + int bit =3D (x & 3); + int idx =3D (macfb_read_byte(s, addr) >> ((3 - bit) << 1)) & 3; + r =3D s->color_palette[idx * 3]; + g =3D s->color_palette[idx * 3 + 1]; + b =3D s->color_palette[idx * 3 + 2]; + addr +=3D (bit =3D=3D 3); + + *(uint32_t *)d =3D rgb_to_pixel32(r, g, b); + d +=3D 4; + } +} + +/* 4-bit color */ +static void macfb_draw_line4(MacfbState *s, uint8_t *d, uint32_t addr, + int width) +{ + uint8_t r, g, b; + int x; + + for (x =3D 0; x < width; x++) { + int bit =3D x & 1; + int idx =3D (macfb_read_byte(s, addr) >> ((1 - bit) << 2)) & 15; + r =3D s->color_palette[idx * 3]; + g =3D s->color_palette[idx * 3 + 1]; + b =3D s->color_palette[idx * 3 + 2]; + addr +=3D (bit =3D=3D 1); + + *(uint32_t *)d =3D rgb_to_pixel32(r, g, b); + d +=3D 4; + } +} + +/* 8-bit color */ +static void macfb_draw_line8(MacfbState *s, uint8_t *d, uint32_t addr, + int width) +{ + uint8_t r, g, b; + int x; + + for (x =3D 0; x < width; x++) { + r =3D s->color_palette[macfb_read_byte(s, addr) * 3]; + g =3D s->color_palette[macfb_read_byte(s, addr) * 3 + 1]; + b =3D s->color_palette[macfb_read_byte(s, addr) * 3 + 2]; + addr++; + + *(uint32_t *)d =3D rgb_to_pixel32(r, g, b); + d +=3D 4; + } +} + +/* 16-bit color */ +static void macfb_draw_line16(MacfbState *s, uint8_t *d, uint32_t addr, + int width) +{ + uint8_t r, g, b; + int x; + + for (x =3D 0; x < width; x++) { + uint16_t pixel; + pixel =3D (macfb_read_byte(s, addr) << 8) | macfb_read_byte(s, add= r + 1); + r =3D ((pixel >> 10) & 0x1f) << 3; + g =3D ((pixel >> 5) & 0x1f) << 3; + b =3D (pixel & 0x1f) << 3; + addr +=3D 2; + + *(uint32_t *)d =3D rgb_to_pixel32(r, g, b); + d +=3D 4; + } +} + +/* 24-bit color */ +static void macfb_draw_line24(MacfbState *s, uint8_t *d, uint32_t addr, + int width) +{ + uint8_t r, g, b; + int x; + + for (x =3D 0; x < width; x++) { + r =3D macfb_read_byte(s, addr); + g =3D macfb_read_byte(s, addr + 1); + b =3D macfb_read_byte(s, addr + 2); + addr +=3D 3; + + *(uint32_t *)d =3D rgb_to_pixel32(r, g, b); + d +=3D 4; + } +} + + +enum { + MACFB_DRAW_LINE1, + MACFB_DRAW_LINE2, + MACFB_DRAW_LINE4, + MACFB_DRAW_LINE8, + MACFB_DRAW_LINE16, + MACFB_DRAW_LINE24, + MACFB_DRAW_LINE_NB, +}; + +static macfb_draw_line_func * const + macfb_draw_line_table[MACFB_DRAW_LINE_NB] = =3D { + macfb_draw_line1, + macfb_draw_line2, + macfb_draw_line4, + macfb_draw_line8, + macfb_draw_line16, + macfb_draw_line24, +}; + +static int macfb_check_dirty(MacfbState *s, DirtyBitmapSnapshot *snap, + ram_addr_t addr, int len) +{ + return memory_region_snapshot_get_dirty(&s->mem_vram, snap, addr, len); +} + +static void macfb_draw_graphic(MacfbState *s) +{ + DisplaySurface *surface =3D qemu_console_surface(s->con); + DirtyBitmapSnapshot *snap =3D NULL; + ram_addr_t page; + uint32_t v =3D 0; + int y, ymin; + int macfb_stride =3D (s->depth * s->width + 7) / 8; + macfb_draw_line_func *macfb_draw_line; + + switch (s->depth) { + case 1: + v =3D MACFB_DRAW_LINE1; + break; + case 2: + v =3D MACFB_DRAW_LINE2; + break; + case 4: + v =3D MACFB_DRAW_LINE4; + break; + case 8: + v =3D MACFB_DRAW_LINE8; + break; + case 16: + v =3D MACFB_DRAW_LINE16; + break; + case 24: + v =3D MACFB_DRAW_LINE24; + break; + } + + macfb_draw_line =3D macfb_draw_line_table[v]; + assert(macfb_draw_line !=3D NULL); + + snap =3D memory_region_snapshot_and_clear_dirty(&s->mem_vram, 0x0, + memory_region_size(&s->mem_vr= am), + DIRTY_MEMORY_VGA); + + ymin =3D -1; + page =3D 0; + for (y =3D 0; y < s->height; y++, page +=3D macfb_stride) { + if (macfb_check_dirty(s, snap, page, macfb_stride)) { + uint8_t *data_display; + + data_display =3D surface_data(surface) + y * surface_stride(su= rface); + macfb_draw_line(s, data_display, page, s->width); + + if (ymin < 0) { + ymin =3D y; + } + } else { + if (ymin >=3D 0) { + dpy_gfx_update(s->con, 0, ymin, s->width, y - ymin); + ymin =3D -1; + } + } + } + + if (ymin >=3D 0) { + dpy_gfx_update(s->con, 0, ymin, s->width, y - ymin); + } + + g_free(snap); +} + +static void macfb_invalidate_display(void *opaque) +{ + MacfbState *s =3D opaque; + + memory_region_set_dirty(&s->mem_vram, 0, MACFB_VRAM_SIZE); +} + +static void macfb_update_display(void *opaque) +{ + MacfbState *s =3D opaque; + DisplaySurface *surface =3D qemu_console_surface(s->con); + + qemu_flush_coalesced_mmio_buffer(); + + if (s->width =3D=3D 0 || s->height =3D=3D 0) { + return; + } + + if (s->width !=3D surface_width(surface) || + s->height !=3D surface_height(surface)) { + qemu_console_resize(s->con, s->width, s->height); + } + + macfb_draw_graphic(s); +} + +static void macfb_reset(MacfbState *s) +{ + int i; + + s->palette_current =3D 0; + for (i =3D 0; i < 256; i++) { + s->color_palette[i * 3] =3D 255 - i; + s->color_palette[i * 3 + 1] =3D 255 - i; + s->color_palette[i * 3 + 2] =3D 255 - i; + } + memset(s->vram, 0, MACFB_VRAM_SIZE); + macfb_invalidate_display(s); +} + +static uint64_t macfb_ctrl_read(void *opaque, + hwaddr addr, + unsigned int size) +{ + return 0; +} + +static void macfb_ctrl_write(void *opaque, + hwaddr addr, + uint64_t val, + unsigned int size) +{ + MacfbState *s =3D opaque; + switch (addr) { + case DAFB_RESET: + s->palette_current =3D 0; + break; + case DAFB_LUT: + s->color_palette[s->palette_current++] =3D val; + if (s->palette_current % 3) { + macfb_invalidate_display(s); + } + break; + } +} + +static const MemoryRegionOps macfb_ctrl_ops =3D { + .read =3D macfb_ctrl_read, + .write =3D macfb_ctrl_write, + .endianness =3D DEVICE_BIG_ENDIAN, + .impl.min_access_size =3D 1, + .impl.max_access_size =3D 4, +}; + +static int macfb_post_load(void *opaque, int version_id) +{ + macfb_invalidate_display(opaque); + return 0; +} + +static const VMStateDescription vmstate_macfb =3D { + .name =3D "macfb", + .version_id =3D 1, + .minimum_version_id =3D 1, + .minimum_version_id_old =3D 1, + .post_load =3D macfb_post_load, + .fields =3D (VMStateField[]) { + VMSTATE_UINT8_ARRAY(color_palette, MacfbState, 256 * 3), + VMSTATE_UINT32(palette_current, MacfbState), + VMSTATE_END_OF_LIST() + } +}; + +static const GraphicHwOps macfb_ops =3D { + .invalidate =3D macfb_invalidate_display, + .gfx_update =3D macfb_update_display, +}; + +static void macfb_common_realize(DeviceState *dev, MacfbState *s, Error **= errp) +{ + DisplaySurface *surface; + + if (s->depth !=3D 1 && s->depth !=3D 2 && s->depth !=3D 4 && s->depth = !=3D 8 && + s->depth !=3D 16 && s->depth !=3D 24) { + error_setg(errp, "unknown guest depth %d", s->depth); + return; + } + + s->con =3D graphic_console_init(dev, 0, &macfb_ops, s); + surface =3D qemu_console_surface(s->con); + + if (surface_bits_per_pixel(surface) !=3D 32) { + error_setg(errp, "unknown host depth %d", + surface_bits_per_pixel(surface)); + return; + } + + memory_region_init_io(&s->mem_ctrl, NULL, &macfb_ctrl_ops, s, "macfb-c= trl", + 0x1000); + + memory_region_init_ram_nomigrate(&s->mem_vram, OBJECT(s), "macfb-vram", + MACFB_VRAM_SIZE, errp); + s->vram =3D memory_region_get_ram_ptr(&s->mem_vram); + s->vram_bit_mask =3D MACFB_VRAM_SIZE - 1; + vmstate_register_ram(&s->mem_vram, dev); + memory_region_set_coalescing(&s->mem_vram); +} + +static void macfb_sysbus_realize(DeviceState *dev, Error **errp) +{ + MacfbSysBusState *s =3D MACFB(dev); + MacfbState *ms =3D &s->macfb; + + macfb_common_realize(dev, ms, errp); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &ms->mem_ctrl); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &ms->mem_vram); +} + +const uint8_t macfb_rom[] =3D { + 255, 0, 0, 0, +}; + +static void macfb_nubus_realize(DeviceState *dev, Error **errp) +{ + NubusDevice *nd =3D NUBUS_DEVICE(dev); + MacfbNubusState *s =3D NUBUS_MACFB(dev); + MacfbNubusDeviceClass *ndc =3D MACFB_NUBUS_GET_CLASS(dev); + MacfbState *ms =3D &s->macfb; + + ndc->parent_realize(dev, errp); + + macfb_common_realize(dev, ms, errp); + memory_region_add_subregion(&nd->slot_mem, DAFB_BASE, &ms->mem_ctrl); + memory_region_add_subregion(&nd->slot_mem, VIDEO_BASE, &ms->mem_vram); + + nubus_register_rom(nd, macfb_rom, sizeof(macfb_rom), 1, 9, 0xf); +} + +static void macfb_sysbus_reset(DeviceState *d) +{ + MacfbSysBusState *s =3D MACFB(d); + macfb_reset(&s->macfb); +} + +static void macfb_nubus_reset(DeviceState *d) +{ + MacfbNubusState *s =3D NUBUS_MACFB(d); + macfb_reset(&s->macfb); +} + +static Property macfb_sysbus_properties[] =3D { + DEFINE_PROP_UINT32("width", MacfbSysBusState, macfb.width, 640), + DEFINE_PROP_UINT32("height", MacfbSysBusState, macfb.height, 480), + DEFINE_PROP_UINT8("depth", MacfbSysBusState, macfb.depth, 8), + DEFINE_PROP_END_OF_LIST(), +}; + +static Property macfb_nubus_properties[] =3D { + DEFINE_PROP_UINT32("width", MacfbNubusState, macfb.width, 640), + DEFINE_PROP_UINT32("height", MacfbNubusState, macfb.height, 480), + DEFINE_PROP_UINT8("depth", MacfbNubusState, macfb.depth, 8), + DEFINE_PROP_END_OF_LIST(), +}; + +static void macfb_sysbus_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D macfb_sysbus_realize; + dc->desc =3D "SysBus Macintosh framebuffer"; + dc->reset =3D macfb_sysbus_reset; + dc->vmsd =3D &vmstate_macfb; + dc->props =3D macfb_sysbus_properties; +} + +static void macfb_nubus_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + MacfbNubusDeviceClass *ndc =3D MACFB_NUBUS_DEVICE_CLASS(klass); + + device_class_set_parent_realize(dc, macfb_nubus_realize, + &ndc->parent_realize); + dc->desc =3D "Nubus Macintosh framebuffer"; + dc->reset =3D macfb_nubus_reset; + dc->vmsd =3D &vmstate_macfb; + dc->props =3D macfb_nubus_properties; +} + +static TypeInfo macfb_sysbus_info =3D { + .name =3D TYPE_MACFB, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(MacfbSysBusState), + .class_init =3D macfb_sysbus_class_init, +}; + +static TypeInfo macfb_nubus_info =3D { + .name =3D TYPE_NUBUS_MACFB, + .parent =3D TYPE_NUBUS_DEVICE, + .instance_size =3D sizeof(MacfbNubusState), + .class_init =3D macfb_nubus_class_init, + .class_size =3D sizeof(MacfbNubusDeviceClass), +}; + +static void macfb_register_types(void) +{ + type_register_static(&macfb_sysbus_info); + type_register_static(&macfb_nubus_info); +} + +type_init(macfb_register_types) diff --git a/vl.c b/vl.c index 4489cfb2bb..59e82fba35 100644 --- a/vl.c +++ b/vl.c @@ -3226,7 +3226,8 @@ int main(int argc, char **argv, char **envp) if (*p =3D=3D 'x') { p++; depth =3D strtol(p, (char **)&p, 10); - if (depth !=3D 8 && depth !=3D 15 && depth !=3D 16= && + if (depth !=3D 1 && depth !=3D 2 && depth !=3D 4 && + depth !=3D 8 && depth !=3D 15 && depth !=3D 16= && depth !=3D 24 && depth !=3D 32) goto graphic_error; } else if (*p =3D=3D '\0') { diff --git a/MAINTAINERS b/MAINTAINERS index 7892ab5f02..bd0df67e62 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -922,8 +922,10 @@ M: Laurent Vivier S: Maintained F: hw/misc/mac_via.c F: hw/nubus/* +F: hw/display/macfb.c F: include/hw/misc/mac_via.h F: include/hw/nubus/* +F: include/hw/display/macfb.h =20 MicroBlaze Machines ------------------- diff --git a/hw/display/Kconfig b/hw/display/Kconfig index cbdf7b1a67..c500d1fc6d 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -132,3 +132,8 @@ config ATI_VGA select VGA select BITBANG_I2C select DDC + +config MACFB + bool + select FRAMEBUFFER + depends on NUBUS diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index 5a4066383b..f2182e3bef 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -26,6 +26,7 @@ common-obj-$(CONFIG_EXYNOS4) +=3D exynos4210_fimd.o common-obj-$(CONFIG_FRAMEBUFFER) +=3D framebuffer.o obj-$(CONFIG_MILKYMIST) +=3D milkymist-vgafb.o common-obj-$(CONFIG_ZAURUS) +=3D tc6393xb.o +common-obj-$(CONFIG_MACFB) +=3D macfb.o =20 obj-$(CONFIG_MILKYMIST_TMU2) +=3D milkymist-tmu2.o milkymist-tmu2.o-cflags :=3D $(X11_CFLAGS) $(OPENGL_CFLAGS) diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index 947cd42c01..ef4917dee6 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -17,3 +17,4 @@ config Q800 bool select MAC_VIA select NUBUS + select MACFB diff --git a/qemu-options.hx b/qemu-options.hx index 996b6fba74..1c5bc8ae99 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1839,7 +1839,7 @@ ETEXI =20 DEF("g", 1, QEMU_OPTION_g , "-g WxH[xDEPTH] Set the initial graphical resolution and depth\n", - QEMU_ARCH_PPC | QEMU_ARCH_SPARC) + QEMU_ARCH_PPC | QEMU_ARCH_SPARC | QEMU_ARCH_M68K) STEXI @item -g @var{width}x@var{height}[x@var{depth}] @findex -g --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572288957; cv=none; d=zoho.com; s=zohoarc; b=mDQZTke5FaD1oRHGeJLs4x0eT4xeGJGlyzagbHpsAKFjL4joayMGUrt6byMhDiN+TY6Oj5PkKS0+/bCzKOAb4K6cxjgJF23zOYHGneQamHUKliAOSHkp6gCNbvViO7mJarn9Ava+AQyox4gHxU4rHh6xez6gvznoSQ16/CXTOWQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572288957; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=fmJ268S8t0bRecMuu8lGCi01HW7Q+tqOWvw8Kvboscc=; b=jjfBOq0+nvdx5wfrgLGEb0TPUZi3n4D/V+N+/WMpRM4KIiMAf+9Y3++dJV2CXms5+VY534KAPbXjUi1+lrylbD41cSA2fKn7/LlXxFkXehRs6l0+ANmxiLRp9RR0ZbJddDeJMQvqRe54wMFcrktHJ17n7UIOVw7yCxGd0v9Pahk= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572288957546859.001385956016; Mon, 28 Oct 2019 11:55:57 -0700 (PDT) Received: from localhost ([::1]:49210 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPABF-0007iV-Up for importer@patchew.org; Mon, 28 Oct 2019 14:55:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56649) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zr-0002jK-El for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zo-00043g-Fs for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:15 -0400 Received: from mout.kundenserver.de ([217.72.192.74]:59127) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zo-00042R-2P; Mon, 28 Oct 2019 14:17:12 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MfHxt-1hn3vZ1Atf-00gm3I; Mon, 28 Oct 2019 19:17:03 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 09/11] hw/m68k: add a dummy SWIM floppy controller Date: Mon, 28 Oct 2019 19:16:41 +0100 Message-Id: <20191028181643.5143-10-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:/2sj+tTvZWKfLgVr1+5qrkh3VEK+95cn/cIU/PAXe8+SU/gldTi HPLrmEJjyp2mZ9vpeWzW8GVBsXP7BopBL8pJaJZwrlG2KDjpSyBu5sGqhSsTvgO0cajQ2vu AlE1wiQ+L4mgqAUDeRO6nbXlEvhj3TnECrWsBp5gcsUS99eM07tBwxi6AzXVg12QJdbxGCp g4QNsun0Wz9GRhSdRPn3Q== X-UI-Out-Filterresults: notjunk:1;V03:K0:kozwNVPxmVY=:f2ORaWpjSKoe+4pXcr9Xx2 fSC5X+dDES3S0kYqFyj8i7C/xzhdNP7nkFVFXgjMno09mvWYuQbcnVHGUhhHuRlDaioMf1yrg cvbm/BImVak5AKUp2XZL3jGiGMhxc37M3d3nAe6wc3vhdyIYEn3Exs71kojnnhFhIppuWxhXh Ml+GfBeyoGS5ONh6N2daGFXB2BXtjqGHJeoZnbZlxKKL0DrJdtO4TQMVhL4yrKF05rztKXaYD gYCk9db7+54GmtE7nvtSrKae08AHllF+rOKgVGWd9ZP1E3jQpD7tVKId7NfkPYxHDiVhOy1mf 47GFrhzvJzF9Q5xNq0J7+JzzVsqMwxa56H4z4U3k3VonsywGJ84Z58Y9l7MOZMsh/GhqAoyUH 7lVnGBopu9MiIAE1C3pFyCx3kjn8pGFIKRBZhr52cIiQqMddKR33fSHCjdB1bXqNUNLthZ+pb D2DPqRlUv55/T2HQvyp6/MHSgsBrNXYrLZgiI6ag3QcOMVP5mFuW+6hkkszgccOO4itPmAB6t GUmzB1IabFNZKkX/Yk9LOTZliiUZ4uh6yi/pFvNsi0YpQPCaS8EIH2dYUyVGhaSjdUQGHaN1b TnG7zTQVjqzXltXGzUXK9tPxG3SKisLMbwgYxrirD/ZizHpMgTfM+tAPRGy0zeB7AFGI1MBT+ OgTgJBLOX4m3izaaz7LQqssrQEdAyLI0GkHCYyDLWuX3+A/9gACGtSCwgU8mn8ZhU/lqN7Uh5 3o1sxT1kKSmHK3jiuv3oyLd1phKe/cE2o0yf1hZyLQ/SrMr4hosnAJYCIFJA64RPVXFEUDeJx 6CNXRlSUn7aD+x/qiCjmlqSQYuij42avDZFIuzaVQF/9ZLIQAVeR/7v3DOwSq1NTfSyijNRkO zJPdJUydf+1lxcOhrXB/Df6B+E1KN5FxArMpE1qUo= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.74 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , =?UTF-8?q?Herv=C3=A9=20Poussineau?= , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" SWIM (Sander-Wozniak Integrated Machine) is the floppy controller of the 680x0 Macintosh. This patch introduces only the basic support: it allows to switch from IWM (Integrated WOZ Machine) mode to the SWIM mode and makes the linux driver happy. It cannot read any floppy image. Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Reviewed-by: Herv=C3=A9 Poussineau Message-Id: <20191026164546.30020-10-laurent@vivier.eu> --- include/hw/block/swim.h | 76 +++++++ hw/block/swim.c | 489 ++++++++++++++++++++++++++++++++++++++++ MAINTAINERS | 2 + hw/block/Kconfig | 3 + hw/block/Makefile.objs | 1 + hw/m68k/Kconfig | 1 + 6 files changed, 572 insertions(+) create mode 100644 include/hw/block/swim.h create mode 100644 hw/block/swim.c diff --git a/include/hw/block/swim.h b/include/hw/block/swim.h new file mode 100644 index 0000000000..6add3499d0 --- /dev/null +++ b/include/hw/block/swim.h @@ -0,0 +1,76 @@ +/* + * QEMU Macintosh floppy disk controller emulator (SWIM) + * + * Copyright (c) 2014-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef SWIM_H +#define SWIM_H + +#include "qemu/osdep.h" +#include "hw/sysbus.h" + +#define SWIM_MAX_FD 2 + +typedef struct SWIMDrive SWIMDrive; +typedef struct SWIMBus SWIMBus; +typedef struct SWIMCtrl SWIMCtrl; + +#define TYPE_SWIM_DRIVE "swim-drive" +#define SWIM_DRIVE(obj) OBJECT_CHECK(SWIMDrive, (obj), TYPE_SWIM_DRIVE) + +struct SWIMDrive { + DeviceState qdev; + int32_t unit; + BlockConf conf; +}; + +#define TYPE_SWIM_BUS "swim-bus" +#define SWIM_BUS(obj) OBJECT_CHECK(SWIMBus, (obj), TYPE_SWIM_BUS) + +struct SWIMBus { + BusState bus; + struct SWIMCtrl *ctrl; +}; + +typedef struct FDrive { + SWIMCtrl *swimctrl; + BlockBackend *blk; + BlockConf *conf; +} FDrive; + +struct SWIMCtrl { + MemoryRegion iomem; + FDrive drives[SWIM_MAX_FD]; + int mode; + /* IWM mode */ + int iwm_switch; + uint16_t regs[8]; +#define IWM_PH0 0 +#define IWM_PH1 1 +#define IWM_PH2 2 +#define IWM_PH3 3 +#define IWM_MTR 4 +#define IWM_DRIVE 5 +#define IWM_Q6 6 +#define IWM_Q7 7 + uint8_t iwm_data; + uint8_t iwm_mode; + /* SWIM mode */ + uint8_t swim_phase; + uint8_t swim_mode; + SWIMBus bus; +}; + +#define TYPE_SWIM "swim" +#define SWIM(obj) OBJECT_CHECK(SWIM, (obj), TYPE_SWIM) + +typedef struct SWIM { + SysBusDevice parent_obj; + SWIMCtrl ctrl; +} SWIM; +#endif diff --git a/hw/block/swim.c b/hw/block/swim.c new file mode 100644 index 0000000000..c6d117e89b --- /dev/null +++ b/hw/block/swim.c @@ -0,0 +1,489 @@ +/* + * QEMU Macintosh floppy disk controller emulator (SWIM) + * + * Copyright (c) 2014-2018 Laurent Vivier + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Only the basic support: it allows to switch from IWM (Integrated WOZ + * Machine) mode to the SWIM mode and makes the linux driver happy. + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "sysemu/block-backend.h" +#include "hw/sysbus.h" +#include "migration/vmstate.h" +#include "hw/block/block.h" +#include "hw/block/swim.h" +#include "hw/qdev-properties.h" + +/* IWM registers */ + +#define IWM_PH0L 0 +#define IWM_PH0H 1 +#define IWM_PH1L 2 +#define IWM_PH1H 3 +#define IWM_PH2L 4 +#define IWM_PH2H 5 +#define IWM_PH3L 6 +#define IWM_PH3H 7 +#define IWM_MTROFF 8 +#define IWM_MTRON 9 +#define IWM_INTDRIVE 10 +#define IWM_EXTDRIVE 11 +#define IWM_Q6L 12 +#define IWM_Q6H 13 +#define IWM_Q7L 14 +#define IWM_Q7H 15 + +/* SWIM registers */ + +#define SWIM_WRITE_DATA 0 +#define SWIM_WRITE_MARK 1 +#define SWIM_WRITE_CRC 2 +#define SWIM_WRITE_PARAMETER 3 +#define SWIM_WRITE_PHASE 4 +#define SWIM_WRITE_SETUP 5 +#define SWIM_WRITE_MODE0 6 +#define SWIM_WRITE_MODE1 7 + +#define SWIM_READ_DATA 8 +#define SWIM_READ_MARK 9 +#define SWIM_READ_ERROR 10 +#define SWIM_READ_PARAMETER 11 +#define SWIM_READ_PHASE 12 +#define SWIM_READ_SETUP 13 +#define SWIM_READ_STATUS 14 +#define SWIM_READ_HANDSHAKE 15 + +#define REG_SHIFT 9 + +#define SWIM_MODE_IWM 0 +#define SWIM_MODE_SWIM 1 + +/* bits in phase register */ + +#define SWIM_SEEK_NEGATIVE 0x074 +#define SWIM_STEP 0x071 +#define SWIM_MOTOR_ON 0x072 +#define SWIM_MOTOR_OFF 0x076 +#define SWIM_INDEX 0x073 +#define SWIM_EJECT 0x077 +#define SWIM_SETMFM 0x171 +#define SWIM_SETGCR 0x175 +#define SWIM_RELAX 0x033 +#define SWIM_LSTRB 0x008 +#define SWIM_CA_MASK 0x077 + +/* Select values for swim_select and swim_readbit */ + +#define SWIM_READ_DATA_0 0x074 +#define SWIM_TWOMEG_DRIVE 0x075 +#define SWIM_SINGLE_SIDED 0x076 +#define SWIM_DRIVE_PRESENT 0x077 +#define SWIM_DISK_IN 0x170 +#define SWIM_WRITE_PROT 0x171 +#define SWIM_TRACK_ZERO 0x172 +#define SWIM_TACHO 0x173 +#define SWIM_READ_DATA_1 0x174 +#define SWIM_MFM_MODE 0x175 +#define SWIM_SEEK_COMPLETE 0x176 +#define SWIM_ONEMEG_MEDIA 0x177 + +/* Bits in handshake register */ + +#define SWIM_MARK_BYTE 0x01 +#define SWIM_CRC_ZERO 0x02 +#define SWIM_RDDATA 0x04 +#define SWIM_SENSE 0x08 +#define SWIM_MOTEN 0x10 +#define SWIM_ERROR 0x20 +#define SWIM_DAT2BYTE 0x40 +#define SWIM_DAT1BYTE 0x80 + +/* bits in setup register */ + +#define SWIM_S_INV_WDATA 0x01 +#define SWIM_S_3_5_SELECT 0x02 +#define SWIM_S_GCR 0x04 +#define SWIM_S_FCLK_DIV2 0x08 +#define SWIM_S_ERROR_CORR 0x10 +#define SWIM_S_IBM_DRIVE 0x20 +#define SWIM_S_GCR_WRITE 0x40 +#define SWIM_S_TIMEOUT 0x80 + +/* bits in mode register */ + +#define SWIM_CLFIFO 0x01 +#define SWIM_ENBL1 0x02 +#define SWIM_ENBL2 0x04 +#define SWIM_ACTION 0x08 +#define SWIM_WRITE_MODE 0x10 +#define SWIM_HEDSEL 0x20 +#define SWIM_MOTON 0x80 + +static void fd_recalibrate(FDrive *drive) +{ +} + +static void swim_change_cb(void *opaque, bool load, Error **errp) +{ + FDrive *drive =3D opaque; + + if (!load) { + blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort); + } else { + if (!blkconf_apply_backend_options(drive->conf, + blk_is_read_only(drive->blk), f= alse, + errp)) { + return; + } + } +} + +static const BlockDevOps swim_block_ops =3D { + .change_media_cb =3D swim_change_cb, +}; + +static Property swim_drive_properties[] =3D { + DEFINE_PROP_INT32("unit", SWIMDrive, unit, -1), + DEFINE_BLOCK_PROPERTIES(SWIMDrive, conf), + DEFINE_PROP_END_OF_LIST(), +}; + +static void swim_drive_realize(DeviceState *qdev, Error **errp) +{ + SWIMDrive *dev =3D SWIM_DRIVE(qdev); + SWIMBus *bus =3D SWIM_BUS(qdev->parent_bus); + FDrive *drive; + int ret; + + if (dev->unit =3D=3D -1) { + for (dev->unit =3D 0; dev->unit < SWIM_MAX_FD; dev->unit++) { + drive =3D &bus->ctrl->drives[dev->unit]; + if (!drive->blk) { + break; + } + } + } + + if (dev->unit >=3D SWIM_MAX_FD) { + error_setg(errp, "Can't create floppy unit %d, bus supports " + "only %d units", dev->unit, SWIM_MAX_FD); + return; + } + + drive =3D &bus->ctrl->drives[dev->unit]; + if (drive->blk) { + error_setg(errp, "Floppy unit %d is in use", dev->unit); + return; + } + + if (!dev->conf.blk) { + /* Anonymous BlockBackend for an empty drive */ + dev->conf.blk =3D blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); + ret =3D blk_attach_dev(dev->conf.blk, qdev); + assert(ret =3D=3D 0); + } + + blkconf_blocksizes(&dev->conf); + if (dev->conf.logical_block_size !=3D 512 || + dev->conf.physical_block_size !=3D 512) + { + error_setg(errp, "Physical and logical block size must " + "be 512 for floppy"); + return; + } + + /* + * rerror/werror aren't supported by fdc and therefore not even regist= ered + * with qdev. So set the defaults manually before they are used in + * blkconf_apply_backend_options(). + */ + dev->conf.rerror =3D BLOCKDEV_ON_ERROR_AUTO; + dev->conf.werror =3D BLOCKDEV_ON_ERROR_AUTO; + + if (!blkconf_apply_backend_options(&dev->conf, + blk_is_read_only(dev->conf.blk), + false, errp)) { + return; + } + + /* + * 'enospc' is the default for -drive, 'report' is what blk_new() give= s us + * for empty drives. + */ + if (blk_get_on_error(dev->conf.blk, 0) !=3D BLOCKDEV_ON_ERROR_ENOSPC && + blk_get_on_error(dev->conf.blk, 0) !=3D BLOCKDEV_ON_ERROR_REPORT) { + error_setg(errp, "fdc doesn't support drive option werror"); + return; + } + if (blk_get_on_error(dev->conf.blk, 1) !=3D BLOCKDEV_ON_ERROR_REPORT) { + error_setg(errp, "fdc doesn't support drive option rerror"); + return; + } + + drive->conf =3D &dev->conf; + drive->blk =3D dev->conf.blk; + drive->swimctrl =3D bus->ctrl; + + blk_set_dev_ops(drive->blk, &swim_block_ops, drive); +} + +static void swim_drive_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *k =3D DEVICE_CLASS(klass); + k->realize =3D swim_drive_realize; + set_bit(DEVICE_CATEGORY_STORAGE, k->categories); + k->bus_type =3D TYPE_SWIM_BUS; + k->props =3D swim_drive_properties; + k->desc =3D "virtual SWIM drive"; +} + +static const TypeInfo swim_drive_info =3D { + .name =3D TYPE_SWIM_DRIVE, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(SWIMDrive), + .class_init =3D swim_drive_class_init, +}; + +static const TypeInfo swim_bus_info =3D { + .name =3D TYPE_SWIM_BUS, + .parent =3D TYPE_BUS, + .instance_size =3D sizeof(SWIMBus), +}; + +static void iwmctrl_write(void *opaque, hwaddr reg, uint64_t value, + unsigned size) +{ + SWIMCtrl *swimctrl =3D opaque; + + reg >>=3D REG_SHIFT; + + swimctrl->regs[reg >> 1] =3D reg & 1; + + if (swimctrl->regs[IWM_Q6] && + swimctrl->regs[IWM_Q7]) { + if (swimctrl->regs[IWM_MTR]) { + /* data register */ + swimctrl->iwm_data =3D value; + } else { + /* mode register */ + swimctrl->iwm_mode =3D value; + /* detect sequence to switch from IWM mode to SWIM mode */ + switch (swimctrl->iwm_switch) { + case 0: + if (value =3D=3D 0x57) { + swimctrl->iwm_switch++; + } + break; + case 1: + if (value =3D=3D 0x17) { + swimctrl->iwm_switch++; + } + break; + case 2: + if (value =3D=3D 0x57) { + swimctrl->iwm_switch++; + } + break; + case 3: + if (value =3D=3D 0x57) { + swimctrl->mode =3D SWIM_MODE_SWIM; + swimctrl->iwm_switch =3D 0; + } + break; + } + } + } +} + +static uint64_t iwmctrl_read(void *opaque, hwaddr reg, unsigned size) +{ + SWIMCtrl *swimctrl =3D opaque; + + reg >>=3D REG_SHIFT; + + swimctrl->regs[reg >> 1] =3D reg & 1; + + return 0; +} + +static void swimctrl_write(void *opaque, hwaddr reg, uint64_t value, + unsigned size) +{ + SWIMCtrl *swimctrl =3D opaque; + + if (swimctrl->mode =3D=3D SWIM_MODE_IWM) { + iwmctrl_write(opaque, reg, value, size); + return; + } + + reg >>=3D REG_SHIFT; + + switch (reg) { + case SWIM_WRITE_PHASE: + swimctrl->swim_phase =3D value; + break; + case SWIM_WRITE_MODE0: + swimctrl->swim_mode &=3D ~value; + break; + case SWIM_WRITE_MODE1: + swimctrl->swim_mode |=3D value; + break; + case SWIM_WRITE_DATA: + case SWIM_WRITE_MARK: + case SWIM_WRITE_CRC: + case SWIM_WRITE_PARAMETER: + case SWIM_WRITE_SETUP: + break; + } +} + +static uint64_t swimctrl_read(void *opaque, hwaddr reg, unsigned size) +{ + SWIMCtrl *swimctrl =3D opaque; + uint32_t value =3D 0; + + if (swimctrl->mode =3D=3D SWIM_MODE_IWM) { + return iwmctrl_read(opaque, reg, size); + } + + reg >>=3D REG_SHIFT; + + switch (reg) { + case SWIM_READ_PHASE: + value =3D swimctrl->swim_phase; + break; + case SWIM_READ_HANDSHAKE: + if (swimctrl->swim_phase =3D=3D SWIM_DRIVE_PRESENT) { + /* always answer "no drive present" */ + value =3D SWIM_SENSE; + } + break; + case SWIM_READ_DATA: + case SWIM_READ_MARK: + case SWIM_READ_ERROR: + case SWIM_READ_PARAMETER: + case SWIM_READ_SETUP: + case SWIM_READ_STATUS: + break; + } + + return value; +} + +static const MemoryRegionOps swimctrl_mem_ops =3D { + .write =3D swimctrl_write, + .read =3D swimctrl_read, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static void sysbus_swim_reset(DeviceState *d) +{ + SWIM *sys =3D SWIM(d); + SWIMCtrl *ctrl =3D &sys->ctrl; + int i; + + ctrl->mode =3D 0; + ctrl->iwm_switch =3D 0; + for (i =3D 0; i < 8; i++) { + ctrl->regs[i] =3D 0; + } + ctrl->iwm_data =3D 0; + ctrl->iwm_mode =3D 0; + ctrl->swim_phase =3D 0; + ctrl->swim_mode =3D 0; + for (i =3D 0; i < SWIM_MAX_FD; i++) { + fd_recalibrate(&ctrl->drives[i]); + } +} + +static void sysbus_swim_init(Object *obj) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + SWIM *sbs =3D SWIM(obj); + SWIMCtrl *swimctrl =3D &sbs->ctrl; + + memory_region_init_io(&swimctrl->iomem, obj, &swimctrl_mem_ops, swimct= rl, + "swim", 0x2000); + sysbus_init_mmio(sbd, &swimctrl->iomem); +} + +static void sysbus_swim_realize(DeviceState *dev, Error **errp) +{ + SWIM *sys =3D SWIM(dev); + SWIMCtrl *swimctrl =3D &sys->ctrl; + + qbus_create_inplace(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, de= v, + NULL); + swimctrl->bus.ctrl =3D swimctrl; +} + +static const VMStateDescription vmstate_fdrive =3D { + .name =3D "fdrive", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription vmstate_swim =3D { + .name =3D "swim", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_INT32(mode, SWIMCtrl), + /* IWM mode */ + VMSTATE_INT32(iwm_switch, SWIMCtrl), + VMSTATE_UINT16_ARRAY(regs, SWIMCtrl, 8), + VMSTATE_UINT8(iwm_data, SWIMCtrl), + VMSTATE_UINT8(iwm_mode, SWIMCtrl), + /* SWIM mode */ + VMSTATE_UINT8(swim_phase, SWIMCtrl), + VMSTATE_UINT8(swim_mode, SWIMCtrl), + /* Drives */ + VMSTATE_STRUCT_ARRAY(drives, SWIMCtrl, SWIM_MAX_FD, 1, + vmstate_fdrive, FDrive), + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription vmstate_sysbus_swim =3D { + .name =3D "SWIM", + .version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_STRUCT(ctrl, SWIM, 0, vmstate_swim, SWIMCtrl), + VMSTATE_END_OF_LIST() + } +}; + +static void sysbus_swim_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->realize =3D sysbus_swim_realize; + dc->reset =3D sysbus_swim_reset; + dc->vmsd =3D &vmstate_sysbus_swim; +} + +static const TypeInfo sysbus_swim_info =3D { + .name =3D TYPE_SWIM, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(SWIM), + .instance_init =3D sysbus_swim_init, + .class_init =3D sysbus_swim_class_init, +}; + +static void swim_register_types(void) +{ + type_register_static(&sysbus_swim_info); + type_register_static(&swim_bus_info); + type_register_static(&swim_drive_info); +} + +type_init(swim_register_types) diff --git a/MAINTAINERS b/MAINTAINERS index bd0df67e62..7f806eb1b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -923,9 +923,11 @@ S: Maintained F: hw/misc/mac_via.c F: hw/nubus/* F: hw/display/macfb.c +F: hw/block/swim.c F: include/hw/misc/mac_via.h F: include/hw/nubus/* F: include/hw/display/macfb.h +F: include/hw/block/swim.h =20 MicroBlaze Machines ------------------- diff --git a/hw/block/Kconfig b/hw/block/Kconfig index df96dc5dcc..2d17f481ad 100644 --- a/hw/block/Kconfig +++ b/hw/block/Kconfig @@ -37,3 +37,6 @@ config VHOST_USER_BLK # Only PCI devices are provided for now default y if VIRTIO_PCI depends on VIRTIO && VHOST_USER && LINUX + +config SWIM + bool diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs index f5f643f0cc..28c2495a00 100644 --- a/hw/block/Makefile.objs +++ b/hw/block/Makefile.objs @@ -8,6 +8,7 @@ common-obj-$(CONFIG_XEN) +=3D xen-block.o common-obj-$(CONFIG_ECC) +=3D ecc.o common-obj-$(CONFIG_ONENAND) +=3D onenand.o common-obj-$(CONFIG_NVME_PCI) +=3D nvme.o +common-obj-$(CONFIG_SWIM) +=3D swim.o =20 obj-$(CONFIG_SH4) +=3D tc58128.o =20 diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index ef4917dee6..bab4885ca5 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -18,3 +18,4 @@ config Q800 select MAC_VIA select NUBUS select MACFB + select SWIM --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572289818; cv=none; d=zoho.com; s=zohoarc; b=V49LvflJ4n2ZDDoJ0UZYMLb4qeeVQOr8YwDFyzzFTwvIKPFMNYNzdG6XQz6GkbrL5Een6Q50OtQQ84PXddqK9w2+Yg8NX3FhR7XdhkY7TnTfZj4lqcYu2y5IRSFeHjsSz/FD3JMJyNTzxd32Q/glWXoZcseNdbzizPDAk12LiII= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572289818; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=STmkULJ7J4FeApAPqr6WsMBdW99mzDPzTtjH5+C4jcg=; b=NDbqGlj74MqhS6GiGthRQzVtJpQro9meX9+lVCLlMxGZOEXjbpFh6JPwkQq6s9Lfe8GUq5cspGS6uaxnWFwyjBGg8jrvfyt4daZfVuRciE4vuZsqxyXVoZABxEUBEHJ6iSxNwja67gCSt/MABMHrImHfdrlKjSB8k2d70eiYc9w= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572289818702102.64942268267089; Mon, 28 Oct 2019 12:10:18 -0700 (PDT) Received: from localhost ([::1]:53686 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPAP9-0001ch-73 for importer@patchew.org; Mon, 28 Oct 2019 15:10:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56643) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zr-0002iw-9X for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zn-00043J-U6 for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:14 -0400 Received: from mout.kundenserver.de ([212.227.17.24]:46565) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zn-000428-HS; Mon, 28 Oct 2019 14:17:11 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MKc0o-1ihvyV3dW8-00Kzhj; Mon, 28 Oct 2019 19:17:04 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 10/11] hw/m68k: define Macintosh Quadra 800 Date: Mon, 28 Oct 2019 19:16:42 +0100 Message-Id: <20191028181643.5143-11-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:OX+sjSNFYeEXQ07gLbA9civ7IfFph6WZBWhYEyzlgrFhtJghdR6 4VRrXhVxARWTIqu/+4aAzXYwUKc6fvlSN8VH9MhzuRX+xnMFhv0xa9x8oW2+WpfBMjoED7Y WZzMo0SHld/rCLxixXHcKjRKtTLiUopgskPl24llyL5+SbHn1m2M1SIbBkCcOftEeCT3s61 g4U/v7Vz02nA3iIjcbx2w== X-UI-Out-Filterresults: notjunk:1;V03:K0:bKiteAM4m+w=:xfWZPlsiR9ABpOdXKf09hR 57WBayGR1J0cPJGNtWmWMEJpXQQC8JPpyu0AG5DBzi7LXdYq79fAuBBbXNz9mYNc0w+w0/Xsr xaaOkKNTZS/5nDpX9ZaLyirK61X8aJjERxTCq/LKujGIVxwORuP8FVV5sHNyFDMa2R/pJK+pF ywBjyhPC/EsN7nXvbyMtV2+IrT8d33r7xZLzVL/Dp0dc8zksFvwIb97+43Ft/jKmAk4kjZOCA QLbVZViaQ4DgAKw1mqN8H0li5gOjCMQzXtXjYu5RAhhhsw/4pndHwHEAR8uK6dIf/c4tv3xqP Lf79bd6Ocjybj91oN7eQbjipikYRi0sV4q1cNeFkl5gH5ATHfefX47OSQgXsDwGnDcmIl3Mc7 1L9aWJ9s1/ZrNB2ywe1Y8JfsSRQzOK+MZ433NCGXruAWjFuLxailCRWz/yjq4HMltWw1I/ty8 fwhUN53XohTMi0vDVIuRZ7h1/oFLKZFu32zL5ylC4hY6y3XCz2DVqIP2lk/7ZULDgAdNM9v6P CgtFxfkWP1gY9GswXJlTMcNPFK5z0S8cyJBjp68Vts9kx3FcMTfTYSfYQav9dG0Ksx5hMVSwk A7PJUGzacw/gAUdJdRigb9JGUnkjPVKINmaQ7BjtqdDnKkl4l57IM89zvfGOEEp/3TxH9B0sP +tYvGTjFsVl2HYuEShe9ftv/jTulq2pJq7zhWczP5DQTi5pyTyw4ZdMwrS9HiZt2jnprzRNW2 jU+PEFgoY2e6C23bJQaTx72xDCEBdD/AkYmWsEc14Rwykw7PFKZ3uLHlpNsPXsAPQIGdxwuqO ZnQxZR5FUqqmS7ePYmVH7YolF+KcrmmMEqwxx0qRI+bkJx4R+vz33udQGUTo2T3SYLR1tqcIM YH0AXY9rwrk7XALZ13fHu4d0HNBm7Zc2WIyS5L7eE= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.17.24 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Mark Cave-Ayland , Laurent Vivier , Max Reitz , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" If you want to test the machine, it doesn't yet boot a MacROM, but you can boot a linux kernel from the command line. You can install your own disk using debian-installer with: ./qemu-system-m68k \ -M q800 \ -serial none -serial mon:stdio \ -m 1000M -drive file=3Dm68k.qcow2,format=3Dqcow2 \ -net nic,model=3Ddp83932,addr=3D09:00:07:12:34:57 \ -append "console=3DttyS0 vga=3Doff" \ -kernel vmlinux-4.15.0-2-m68k \ -initrd initrd.gz \ -drive file=3Ddebian-9.0-m68k-NETINST-1.iso \ -drive file=3Dm68k.qcow2,format=3Dqcow2 \ -nographic If you use a graphic adapter instead of "-nographic", you can use "-g" to set the size of the display (I use "-g 1600x800x24"). Tested-by: Philippe Mathieu-Daud=C3=A9 Co-developed-by: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: Laurent Vivier Message-Id: <20191026164546.30020-11-laurent@vivier.eu> --- hw/m68k/bootinfo.h | 114 ++++++++++++ hw/m68k/q800.c | 401 ++++++++++++++++++++++++++++++++++++++++++ MAINTAINERS | 2 + hw/m68k/Kconfig | 3 + hw/m68k/Makefile.objs | 1 + 5 files changed, 521 insertions(+) create mode 100644 hw/m68k/bootinfo.h create mode 100644 hw/m68k/q800.c diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h new file mode 100644 index 0000000000..5f8ded2686 --- /dev/null +++ b/hw/m68k/bootinfo.h @@ -0,0 +1,114 @@ +/* + * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note + * + * Bootinfo tags from linux bootinfo.h and bootinfo-mac.h: + * This is an easily parsable and extendable structure containing all + * information to be passed from the bootstrap to the kernel + * + * This structure is copied right after the kernel by the bootstrap + * routine. + */ + +#ifndef HW_M68K_BOOTINFO_H +#define HW_M68K_BOOTINFO_H +struct bi_record { + uint16_t tag; /* tag ID */ + uint16_t size; /* size of record */ + uint32_t data[0]; /* data */ +}; + +/* machine independent tags */ + +#define BI_LAST 0x0000 /* last record */ +#define BI_MACHTYPE 0x0001 /* machine type (u_long) */ +#define BI_CPUTYPE 0x0002 /* cpu type (u_long) */ +#define BI_FPUTYPE 0x0003 /* fpu type (u_long) */ +#define BI_MMUTYPE 0x0004 /* mmu type (u_long) */ +#define BI_MEMCHUNK 0x0005 /* memory chunk address and size */ + /* (struct mem_info) */ +#define BI_RAMDISK 0x0006 /* ramdisk address and size */ + /* (struct mem_info) */ +#define BI_COMMAND_LINE 0x0007 /* kernel command line parameters */ + /* (string) */ + +/* Macintosh-specific tags (all u_long) */ + +#define BI_MAC_MODEL 0x8000 /* Mac Gestalt ID (model type) */ +#define BI_MAC_VADDR 0x8001 /* Mac video base address */ +#define BI_MAC_VDEPTH 0x8002 /* Mac video depth */ +#define BI_MAC_VROW 0x8003 /* Mac video rowbytes */ +#define BI_MAC_VDIM 0x8004 /* Mac video dimensions */ +#define BI_MAC_VLOGICAL 0x8005 /* Mac video logical base */ +#define BI_MAC_SCCBASE 0x8006 /* Mac SCC base address */ +#define BI_MAC_BTIME 0x8007 /* Mac boot time */ +#define BI_MAC_GMTBIAS 0x8008 /* Mac GMT timezone offset */ +#define BI_MAC_MEMSIZE 0x8009 /* Mac RAM size (sanity check) */ +#define BI_MAC_CPUID 0x800a /* Mac CPU type (sanity check) */ +#define BI_MAC_ROMBASE 0x800b /* Mac system ROM base address */ + +/* Macintosh hardware profile data */ + +#define BI_MAC_VIA1BASE 0x8010 /* Mac VIA1 base address (always present) = */ +#define BI_MAC_VIA2BASE 0x8011 /* Mac VIA2 base address (type varies) */ +#define BI_MAC_VIA2TYPE 0x8012 /* Mac VIA2 type (VIA, RBV, OSS) */ +#define BI_MAC_ADBTYPE 0x8013 /* Mac ADB interface type */ +#define BI_MAC_ASCBASE 0x8014 /* Mac Apple Sound Chip base address */ +#define BI_MAC_SCSI5380 0x8015 /* Mac NCR 5380 SCSI (base address, multi)= */ +#define BI_MAC_SCSIDMA 0x8016 /* Mac SCSI DMA (base address) */ +#define BI_MAC_SCSI5396 0x8017 /* Mac NCR 53C96 SCSI (base address, multi= ) */ +#define BI_MAC_IDETYPE 0x8018 /* Mac IDE interface type */ +#define BI_MAC_IDEBASE 0x8019 /* Mac IDE interface base address */ +#define BI_MAC_NUBUS 0x801a /* Mac Nubus type (none, regular, pseudo) = */ +#define BI_MAC_SLOTMASK 0x801b /* Mac Nubus slots present */ +#define BI_MAC_SCCTYPE 0x801c /* Mac SCC serial type (normal, IOP) */ +#define BI_MAC_ETHTYPE 0x801d /* Mac builtin ethernet type (Sonic, MACE = */ +#define BI_MAC_ETHBASE 0x801e /* Mac builtin ethernet base address */ +#define BI_MAC_PMU 0x801f /* Mac power management / poweroff hardwar= e */ +#define BI_MAC_IOP_SWIM 0x8020 /* Mac SWIM floppy IOP */ +#define BI_MAC_IOP_ADB 0x8021 /* Mac ADB IOP */ + +#define BOOTINFO0(as, base, id) \ + do { \ + stw_phys(as, base, id); \ + base +=3D 2; \ + stw_phys(as, base, sizeof(struct bi_record)); \ + base +=3D 2; \ + } while (0) + +#define BOOTINFO1(as, base, id, value) \ + do { \ + stw_phys(as, base, id); \ + base +=3D 2; \ + stw_phys(as, base, sizeof(struct bi_record) + 4); \ + base +=3D 2; \ + stl_phys(as, base, value); \ + base +=3D 4; \ + } while (0) + +#define BOOTINFO2(as, base, id, value1, value2) \ + do { \ + stw_phys(as, base, id); \ + base +=3D 2; \ + stw_phys(as, base, sizeof(struct bi_record) + 8); \ + base +=3D 2; \ + stl_phys(as, base, value1); \ + base +=3D 4; \ + stl_phys(as, base, value2); \ + base +=3D 4; \ + } while (0) + +#define BOOTINFOSTR(as, base, id, string) \ + do { \ + int i; \ + stw_phys(as, base, id); \ + base +=3D 2; \ + stw_phys(as, base, \ + (sizeof(struct bi_record) + strlen(string) + 2) & ~1); \ + base +=3D 2; \ + for (i =3D 0; string[i]; i++) { \ + stb_phys(as, base++, string[i]); \ + } \ + stb_phys(as, base++, 0); \ + base =3D (parameters_base + 1) & ~1; \ + } while (0) +#endif diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c new file mode 100644 index 0000000000..2b4842f8c6 --- /dev/null +++ b/hw/m68k/q800.c @@ -0,0 +1,401 @@ +/* + * QEMU Motorla 680x0 Macintosh hardware System Emulator + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu-common.h" +#include "sysemu/sysemu.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "elf.h" +#include "hw/loader.h" +#include "ui/console.h" +#include "exec/address-spaces.h" +#include "hw/char/escc.h" +#include "hw/sysbus.h" +#include "hw/scsi/esp.h" +#include "bootinfo.h" +#include "hw/misc/mac_via.h" +#include "hw/input/adb.h" +#include "hw/nubus/mac-nubus-bridge.h" +#include "hw/display/macfb.h" +#include "hw/block/swim.h" +#include "net/net.h" +#include "qapi/error.h" +#include "sysemu/qtest.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" + +#define MACROM_ADDR 0x40000000 +#define MACROM_SIZE 0x00100000 + +#define MACROM_FILENAME "MacROM.bin" + +#define Q800_MACHINE_ID 35 +#define Q800_CPU_ID (1 << 2) +#define Q800_FPU_ID (1 << 2) +#define Q800_MMU_ID (1 << 2) + +#define MACH_MAC 3 +#define Q800_MAC_CPU_ID 2 + +#define VIA_BASE 0x50f00000 +#define SONIC_PROM_BASE 0x50f08000 +#define SONIC_BASE 0x50f0a000 +#define SCC_BASE 0x50f0c020 +#define ESP_BASE 0x50f10000 +#define ESP_PDMA 0x50f10100 +#define ASC_BASE 0x50F14000 +#define SWIM_BASE 0x50F1E000 +#define NUBUS_SUPER_SLOT_BASE 0x60000000 +#define NUBUS_SLOT_BASE 0xf0000000 + +/* + * the video base, whereas it a Nubus address, + * is needed by the kernel to have early display and + * thus provided by the bootloader + */ +#define VIDEO_BASE 0xf9001000 + +#define MAC_CLOCK 3686418 + +/* + * The GLUE (General Logic Unit) is an Apple custom integrated circuit chip + * that performs a variety of functions (RAM management, clock generation,= ...). + * The GLUE chip receives interrupt requests from various devices, + * assign priority to each, and asserts one or more interrupt line to the + * CPU. + */ + +typedef struct { + M68kCPU *cpu; + uint8_t ipr; +} GLUEState; + +static void GLUE_set_irq(void *opaque, int irq, int level) +{ + GLUEState *s =3D opaque; + int i; + + if (level) { + s->ipr |=3D 1 << irq; + } else { + s->ipr &=3D ~(1 << irq); + } + + for (i =3D 7; i >=3D 0; i--) { + if ((s->ipr >> i) & 1) { + m68k_set_irq_level(s->cpu, i + 1, i + 25); + return; + } + } + m68k_set_irq_level(s->cpu, 0, 0); +} + +static void main_cpu_reset(void *opaque) +{ + M68kCPU *cpu =3D opaque; + CPUState *cs =3D CPU(cpu); + + cpu_reset(cs); + cpu->env.aregs[7] =3D ldl_phys(cs->as, 0); + cpu->env.pc =3D ldl_phys(cs->as, 4); +} + +static void q800_init(MachineState *machine) +{ + M68kCPU *cpu =3D NULL; + int linux_boot; + int32_t kernel_size; + uint64_t elf_entry; + char *filename; + int bios_size; + ram_addr_t initrd_base; + int32_t initrd_size; + MemoryRegion *rom; + MemoryRegion *ram; + ram_addr_t ram_size =3D machine->ram_size; + const char *kernel_filename =3D machine->kernel_filename; + const char *initrd_filename =3D machine->initrd_filename; + const char *kernel_cmdline =3D machine->kernel_cmdline; + hwaddr parameters_base; + CPUState *cs; + DeviceState *dev; + DeviceState *via_dev; + SysBusESPState *sysbus_esp; + ESPState *esp; + SysBusDevice *sysbus; + BusState *adb_bus; + NubusBus *nubus; + GLUEState *irq; + qemu_irq *pic; + + linux_boot =3D (kernel_filename !=3D NULL); + + if (ram_size > 1 * GiB) { + error_report("Too much memory for this machine: %" PRId64 " MiB, " + "maximum 1024 MiB", ram_size / MiB); + exit(1); + } + + /* init CPUs */ + cpu =3D M68K_CPU(cpu_create(machine->cpu_type)); + qemu_register_reset(main_cpu_reset, cpu); + + ram =3D g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, NULL, "m68k_mac.ram", ram_size, &error_abo= rt); + memory_region_add_subregion(get_system_memory(), 0, ram); + + /* IRQ Glue */ + + irq =3D g_new0(GLUEState, 1); + irq->cpu =3D cpu; + pic =3D qemu_allocate_irqs(GLUE_set_irq, irq, 8); + + /* VIA */ + + via_dev =3D qdev_create(NULL, TYPE_MAC_VIA); + qdev_init_nofail(via_dev); + sysbus =3D SYS_BUS_DEVICE(via_dev); + sysbus_mmio_map(sysbus, 0, VIA_BASE); + qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 0, pic[0]); + qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1, pic[1]); + + + adb_bus =3D qdev_get_child_bus(via_dev, "adb.0"); + dev =3D qdev_create(adb_bus, TYPE_ADB_KEYBOARD); + qdev_init_nofail(dev); + dev =3D qdev_create(adb_bus, TYPE_ADB_MOUSE); + qdev_init_nofail(dev); + + /* MACSONIC */ + + if (nb_nics > 1) { + error_report("q800 can only have one ethernet interface"); + exit(1); + } + + qemu_check_nic_model(&nd_table[0], "dp83932"); + + /* + * MacSonic driver needs an Apple MAC address + * Valid prefix are: + * 00:05:02 Apple + * 00:80:19 Dayna Communications, Inc. + * 00:A0:40 Apple + * 08:00:07 Apple + * (Q800 use the last one) + */ + nd_table[0].macaddr.a[0] =3D 0x08; + nd_table[0].macaddr.a[1] =3D 0x00; + nd_table[0].macaddr.a[2] =3D 0x07; + + dev =3D qdev_create(NULL, "dp8393x"); + qdev_set_nic_properties(dev, &nd_table[0]); + qdev_prop_set_uint8(dev, "it_shift", 2); + qdev_prop_set_bit(dev, "big_endian", true); + qdev_prop_set_ptr(dev, "dma_mr", get_system_memory()); + qdev_init_nofail(dev); + sysbus =3D SYS_BUS_DEVICE(dev); + sysbus_mmio_map(sysbus, 0, SONIC_BASE); + sysbus_mmio_map(sysbus, 1, SONIC_PROM_BASE); + sysbus_connect_irq(sysbus, 0, pic[2]); + + /* SCC */ + + dev =3D qdev_create(NULL, TYPE_ESCC); + qdev_prop_set_uint32(dev, "disabled", 0); + qdev_prop_set_uint32(dev, "frequency", MAC_CLOCK); + qdev_prop_set_uint32(dev, "it_shift", 1); + qdev_prop_set_bit(dev, "bit_swap", true); + qdev_prop_set_chr(dev, "chrA", serial_hd(0)); + qdev_prop_set_chr(dev, "chrB", serial_hd(1)); + qdev_prop_set_uint32(dev, "chnBtype", 0); + qdev_prop_set_uint32(dev, "chnAtype", 0); + qdev_init_nofail(dev); + sysbus =3D SYS_BUS_DEVICE(dev); + sysbus_connect_irq(sysbus, 0, pic[3]); + sysbus_connect_irq(sysbus, 1, pic[3]); + sysbus_mmio_map(sysbus, 0, SCC_BASE); + + /* SCSI */ + + dev =3D qdev_create(NULL, TYPE_ESP); + sysbus_esp =3D ESP_STATE(dev); + esp =3D &sysbus_esp->esp; + esp->dma_memory_read =3D NULL; + esp->dma_memory_write =3D NULL; + esp->dma_opaque =3D NULL; + sysbus_esp->it_shift =3D 4; + esp->dma_enabled =3D 1; + qdev_init_nofail(dev); + + sysbus =3D SYS_BUS_DEVICE(dev); + sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in_named(via_dev, + "via2-irq", + VIA2_IRQ_SCSI_BIT= )); + sysbus_connect_irq(sysbus, 1, + qdev_get_gpio_in_named(via_dev, "via2-irq", + VIA2_IRQ_SCSI_DATA_BIT)); + sysbus_mmio_map(sysbus, 0, ESP_BASE); + sysbus_mmio_map(sysbus, 1, ESP_PDMA); + + scsi_bus_legacy_handle_cmdline(&esp->bus); + + /* SWIM floppy controller */ + + dev =3D qdev_create(NULL, TYPE_SWIM); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, SWIM_BASE); + + /* NuBus */ + + dev =3D qdev_create(NULL, TYPE_MAC_NUBUS_BRIDGE); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, NUBUS_SUPER_SLOT_BASE); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, NUBUS_SLOT_BASE); + + nubus =3D MAC_NUBUS_BRIDGE(dev)->bus; + + /* framebuffer in nubus slot #9 */ + + dev =3D qdev_create(BUS(nubus), TYPE_NUBUS_MACFB); + qdev_prop_set_uint32(dev, "width", graphic_width); + qdev_prop_set_uint32(dev, "height", graphic_height); + qdev_prop_set_uint8(dev, "depth", graphic_depth); + qdev_init_nofail(dev); + + cs =3D CPU(cpu); + if (linux_boot) { + uint64_t high; + kernel_size =3D load_elf(kernel_filename, NULL, NULL, NULL, + &elf_entry, NULL, &high, 1, + EM_68K, 0, 0); + if (kernel_size < 0) { + error_report("could not load kernel '%s'", kernel_filename); + exit(1); + } + stl_phys(cs->as, 4, elf_entry); /* reset initial PC */ + parameters_base =3D (high + 1) & ~1; + + BOOTINFO1(cs->as, parameters_base, BI_MACHTYPE, MACH_MAC); + BOOTINFO1(cs->as, parameters_base, BI_FPUTYPE, Q800_FPU_ID); + BOOTINFO1(cs->as, parameters_base, BI_MMUTYPE, Q800_MMU_ID); + BOOTINFO1(cs->as, parameters_base, BI_CPUTYPE, Q800_CPU_ID); + BOOTINFO1(cs->as, parameters_base, BI_MAC_CPUID, Q800_MAC_CPU_ID); + BOOTINFO1(cs->as, parameters_base, BI_MAC_MODEL, Q800_MACHINE_ID); + BOOTINFO1(cs->as, parameters_base, + BI_MAC_MEMSIZE, ram_size >> 20); /* in MB */ + BOOTINFO2(cs->as, parameters_base, BI_MEMCHUNK, 0, ram_size); + BOOTINFO1(cs->as, parameters_base, BI_MAC_VADDR, VIDEO_BASE); + BOOTINFO1(cs->as, parameters_base, BI_MAC_VDEPTH, graphic_depth); + BOOTINFO1(cs->as, parameters_base, BI_MAC_VDIM, + (graphic_height << 16) | graphic_width); + BOOTINFO1(cs->as, parameters_base, BI_MAC_VROW, + (graphic_width * graphic_depth + 7) / 8); + BOOTINFO1(cs->as, parameters_base, BI_MAC_SCCBASE, SCC_BASE); + + if (kernel_cmdline) { + BOOTINFOSTR(cs->as, parameters_base, BI_COMMAND_LINE, + kernel_cmdline); + } + + /* load initrd */ + if (initrd_filename) { + initrd_size =3D get_image_size(initrd_filename); + if (initrd_size < 0) { + error_report("could not load initial ram disk '%s'", + initrd_filename); + exit(1); + } + + initrd_base =3D (ram_size - initrd_size) & TARGET_PAGE_MASK; + load_image_targphys(initrd_filename, initrd_base, + ram_size - initrd_base); + BOOTINFO2(cs->as, parameters_base, BI_RAMDISK, initrd_base, + initrd_size); + } else { + initrd_base =3D 0; + initrd_size =3D 0; + } + BOOTINFO0(cs->as, parameters_base, BI_LAST); + } else { + uint8_t *ptr; + /* allocate and load BIOS */ + rom =3D g_malloc(sizeof(*rom)); + memory_region_init_ram(rom, NULL, "m68k_mac.rom", MACROM_SIZE, + &error_abort); + if (bios_name =3D=3D NULL) { + bios_name =3D MACROM_FILENAME; + } + filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + memory_region_set_readonly(rom, true); + memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom); + + /* Load MacROM binary */ + if (filename) { + bios_size =3D load_image_targphys(filename, MACROM_ADDR, MACRO= M_SIZE); + g_free(filename); + } else { + bios_size =3D -1; + } + + /* Remove qtest_enabled() check once firmware files are in the tre= e */ + if (!qtest_enabled()) { + if (bios_size < 0 || bios_size > MACROM_SIZE) { + error_report("could not load MacROM '%s'", bios_name); + exit(1); + } + + ptr =3D rom_ptr(MACROM_ADDR, MACROM_SIZE); + stl_phys(cs->as, 0, ldl_p(ptr)); /* reset initial SP */ + stl_phys(cs->as, 4, + MACROM_ADDR + ldl_p(ptr + 4)); /* reset initial PC */ + } + } +} + +static void q800_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + mc->desc =3D "Macintosh Quadra 800"; + mc->init =3D q800_init; + mc->default_cpu_type =3D M68K_CPU_TYPE_NAME("m68040"); + mc->max_cpus =3D 1; + mc->is_default =3D 0; + mc->block_default_type =3D IF_SCSI; +} + +static const TypeInfo q800_machine_typeinfo =3D { + .name =3D MACHINE_TYPE_NAME("q800"), + .parent =3D TYPE_MACHINE, + .class_init =3D q800_machine_class_init, +}; + +static void q800_machine_register_types(void) +{ + type_register_static(&q800_machine_typeinfo); +} + +type_init(q800_machine_register_types) diff --git a/MAINTAINERS b/MAINTAINERS index 7f806eb1b2..afe9dc5b57 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -920,10 +920,12 @@ F: include/hw/m68k/next-cube.h q800 M: Laurent Vivier S: Maintained +F: hw/m68k/q800.c F: hw/misc/mac_via.c F: hw/nubus/* F: hw/display/macfb.c F: hw/block/swim.c +F: hw/m68k/bootinfo.h F: include/hw/misc/mac_via.h F: include/hw/nubus/* F: include/hw/display/macfb.h diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig index bab4885ca5..c757e7dfa4 100644 --- a/hw/m68k/Kconfig +++ b/hw/m68k/Kconfig @@ -19,3 +19,6 @@ config Q800 select NUBUS select MACFB select SWIM + select ESCC + select ESP + select DP8393X diff --git a/hw/m68k/Makefile.objs b/hw/m68k/Makefile.objs index f25854730d..b2c9e5ab12 100644 --- a/hw/m68k/Makefile.objs +++ b/hw/m68k/Makefile.objs @@ -1,3 +1,4 @@ obj-$(CONFIG_AN5206) +=3D an5206.o mcf5206.o obj-$(CONFIG_MCF5208) +=3D mcf5208.o mcf_intc.o obj-$(CONFIG_NEXTCUBE) +=3D next-kbd.o next-cube.o +obj-$(CONFIG_Q800) +=3D q800.o --=20 2.21.0 From nobody Mon Apr 29 08:26:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1572288971; cv=none; d=zoho.com; s=zohoarc; b=DcJ3gfif6geQnCvLRhDrFqvoTMo6i9y5q8E017yPMQ9rcr3O+tHX30Gm264rdNWFVNrGUd5pn2BAW35ImiVXyJAWN4sgawkC2stwLFnTJcge2J8TOXP/q1wi/MOW3wCrXFZQ+lQAQU0GIVgHtjsVIniXt4U+Lid8ySU4zANQJ98= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1572288971; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=v98HvsdQKrhJwWk4QbYCIM1jV/uK/rpYjIS6HnTrWkQ=; b=C+Dxmv69yZQClJXbNi/e81E0J3rztKG1rRIEu2DRLGr0GrVj9nYgYJNaR4kE7Xin7SP3dngSBrjfPEtvoZuneW/aouMFYCyLDumrpdzYysNOh5jZsebCpoqnWxLZ8W5iF4ZSPvKesdrxjivDcoso4AMXdPYT9GMt1ZzEClgdcZQ= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1572288971303941.7992896889991; Mon, 28 Oct 2019 11:56:11 -0700 (PDT) Received: from localhost ([::1]:49230 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iPABV-0008AJ-EZ for importer@patchew.org; Mon, 28 Oct 2019 14:56:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56652) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iP9Zr-0002jb-F0 for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iP9Zp-00044P-S9 for qemu-devel@nongnu.org; Mon, 28 Oct 2019 14:17:15 -0400 Received: from mout.kundenserver.de ([217.72.192.73]:46913) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iP9Zp-00043q-ID; Mon, 28 Oct 2019 14:17:13 -0400 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MAgMY-1iIWnR0RRo-00B43T; Mon, 28 Oct 2019 19:17:05 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [PULL 11/11] BootLinuxConsoleTest: Test the Quadra 800 Date: Mon, 28 Oct 2019 19:16:43 +0100 Message-Id: <20191028181643.5143-12-laurent@vivier.eu> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191028181643.5143-1-laurent@vivier.eu> References: <20191028181643.5143-1-laurent@vivier.eu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:o08aWP6ZOacsS3hGUm/am5Sa4PAey+DdtlQJJRvy4Vn18I4VFtY Ipl3V611sQoz8acaAtH6SIXCjDjsdrxxyEJYIQliIazhj5xdhciKZ8uZupDPfnaqd7aNhR5 Qk4ODrYz/NSG0cr11p8jOssn3UCwEaGYknUMKxOyMRnNVf+ojsX1goquhOrskI8CUT6bIAA 6v5w8KU12/6GH0xNWEYKA== X-UI-Out-Filterresults: notjunk:1;V03:K0:5obZ+yN4IaQ=:ZGFjsGjOQZQn2/Tn9+WTie C3XVsqL0rQUdJwPXZUm445UOQC9UmvHfYUBB7oLFlNV5Phua35gjvarVWeyjvZCN4Uf8hBtAN o0iH8FrjiWG54OMy5xWxFzYQ9d8+m3jqmth8OSPfPmwACqIxXZ8aDeKUwUO9455pk69mOj+nj lwJrvsganKUKfO+Os61auwDGcPp6UTWrBc2yR28nJswuSntXkzIYkviPX34aNwu/Fp6GyG9UQ j8SnwbVW7DGbuYg1+DnfGoEs4HNAYiSGYVhrXWekDBNaFgW77REzCYoHE6skCA1Sr1ysXgo7Z Ap/6HwByHOXMxGvti3Mkz1mw5nFGdns9qvbBVv38DXvXpG3Z8ECwGR6+Y3mGvPfuT5VKoOOIy HQ9J6HIwHgVguz953YjqMXyN2mwzvWvqTV1dRhKDgCrdhJFnAEZuJpzrdf6+40QZpcasgiQ10 d864pqXXBM6eLodCcPEJfJ8YkeT0Kdx+pCIES6kLLbEylAkkEWn7KPAeqZgc2dQHueII1wdZ5 yTdeM1pOIHhVVSidOokLwOEZg4Oln/cfqsgouYSOlUfuVeIAODFHzfhgl099xShcupjX3F0aF mnzhK9eoeKQphqO6MJMkU0/Q2itOEHTi0PKEGs26veBvVFH83PoKetbQ3a/VwNEW4CGR3L8Ml QaKtVyjY4XGDOlMhJILzO51zV9u/19ZldqFviTgE3rZPdjnwDOovm6wHfRsymYJkG8F0Ggctx tuKqKondo1dIrcXBHriwg3B//Bl/53QAe6jc8vBWm2M1olPstqaWj3lxVCQRWU22EcOa/KZBS ev9hmx+3b2qHn9+aEbwg7F46eBIO9u/TBSJhyqgGtSoqV7wR3rqQNaT60zceXq6aXhytUyLfv DBVWHSsPbwegnDwCXKTZcR27gVnf/bDERlgCpHyUs= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.72.192.73 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , qemu-block@nongnu.org, Jason Wang , Laurent Vivier , Max Reitz , Cleber Rosa , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" From: Philippe Mathieu-Daud=C3=A9 This test boots a Linux kernel on a Quadra 800 board and verify the serial is working. Example: $ avocado --show=3Dapp,console run -t machine:q800 tests/acceptance/boot_= linux_console.py console: ABCFGHIJK console: Linux version 5.2.0-2-m68k (debian-kernel@lists.debian.org) (gcc= version 8.3.0 (Debian 8.3.0-21)) #1 Debian 5.2.9-2 (2019-08-21) console: Detected Macintosh model: 35 console: Apple Macintosh Quadra 800 console: Built 1 zonelists, mobility grouping on. Total pages: 32448 console: Kernel command line: printk.time=3D0 console=3DttyS0 vga=3Doff [...] console: Calibrating delay loop... 1236.99 BogoMIPS (lpj=3D6184960) [...] console: NuBus: Scanning NuBus slots. console: Slot 9: Board resource not found! console: SCSI subsystem initialized console: clocksource: Switched to clocksource via1 [...] console: macfb: framebuffer at 0xf9001000, mapped to 0x(ptrval), size 468k console: macfb: mode is 800x600x8, linelength=3D800 console: Console: switching to colour frame buffer device 100x37 console: fb0: DAFB frame buffer device console: pmac_zilog: 0.6 (Benjamin Herrenschmidt ) console: scc.0: ttyS0 at MMIO 0x50f0c022 (irq =3D 4, base_baud =3D 230400= ) is a Z85c30 ESCC - Serial port console: scc.1: ttyS1 at MMIO 0x50f0c020 (irq =3D 4, base_baud =3D 230400= ) is a Z85c30 ESCC - Serial port console: Non-volatile memory driver v1.3 console: adb: Mac II ADB Driver v1.0 for Unified ADB console: mousedev: PS/2 mouse device common for all mice console: random: fast init done console: Detected ADB keyboard, type . console: input: ADB keyboard as /devices/virtual/input/input0 console: input: ADB mouse as /devices/virtual/input/input1 console: rtc-generic rtc-generic: registered as rtc0 console: ledtrig-cpu: registered to indicate activity on CPUs [...] console: rtc-generic rtc-generic: setting system clock to 2019-09-10T16:2= 0:25 UTC (1568132425) console: List of all partitions: console: No filesystem could mount root, tried: JOB TIME : 2.91 s Signed-off-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Laurent Vivier Tested-by: Cleber Rosa Reviewed-by: Cleber Rosa Message-Id: <20190910163430.11326-1-f4bug@amsat.org> Signed-off-by: Laurent Vivier Message-Id: <20191026164546.30020-12-laurent@vivier.eu> Signed-off-by: Laurent Vivier --- tests/acceptance/boot_linux_console.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot= _linux_console.py index 8a9a314ab4..df27813c78 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -378,3 +378,27 @@ class BootLinuxConsole(Test): self.vm.launch() console_pattern =3D 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) + + def test_m68k_q800(self): + """ + :avocado: tags=3Darch:m68k + :avocado: tags=3Dmachine:q800 + """ + deb_url =3D ('http://ftp.ports.debian.org/debian-ports/pool-m68k/m= ain' + '/l/linux/kernel-image-5.2.0-2-m68k-di_5.2.9-2_m68k.ude= b') + deb_hash =3D '0797e05129595f22f3c0142db5e199769a723bf9' + deb_path =3D self.fetch_asset(deb_url, asset_hash=3Ddeb_hash) + kernel_path =3D self.extract_from_deb(deb_path, + '/boot/vmlinux-5.2.0-2-m68k') + + self.vm.set_machine('q800') + self.vm.set_console() + kernel_command_line =3D (self.KERNEL_COMMON_COMMAND_LINE + + 'console=3DttyS0 vga=3Doff') + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern =3D 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + console_pattern =3D 'No filesystem could mount root' + self.wait_for_console_pattern(console_pattern) --=20 2.21.0