All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Turner <lefticus@gmail.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] parallel port support for qemu.
Date: Sun, 13 Mar 2005 07:43:03 -0700	[thread overview]
Message-ID: <58e14cf0050313064327ab1c8e@mail.gmail.com> (raw)
In-Reply-To: <E1DAPco-0002Sj-00@savannah.gnu.org>

> On Fri, Jan 07, 2005 at 06:59:26PM +0100, Mark Jonckheere wrote:
>
> >    - redirecting printer output to a physical device.
> 
> This would be useful for running the Xilinx FPGA tools under qemu,
> which use a parallel port JTAG dongle.  I'm trying to read out the
> FPGA bitstream as described in their datasheets using CFG_IN/CFG_OUT
> but it just doesn't seem to work as they describe -- this would be
> useful for figuring out how it all really works.
> 
> I'll have a go at this in a few days when I come back home.
> 
>
> cheers,
> Lennert

I decided to take a shot at this. The patch below works ONLY on linux
and requires the "Support for user-space parallel port device drivers"
driver (aka parport). I'm sure it breaks non-linux builds. I'm also
fairly certain that interrupts are not working correctly. However, it
is good enough that I have managed to read and programming my remote
control which has a parallel port interface! (This was the remaining
reason that I had to re-boot into Windows) and should work with
Lennerts FPGA tools (see above).

This patch was made against CVS this morning. If you want to try it,
do something like:

qemu -hda my.img -parallel /dev/parport0

Of course, this might be dangerous code, so use at your own risk.


-Jason


diff --exclude=CVS -upr qemu/hw/parallel.c qemu-sandbox/hw/parallel.c
--- qemu/hw/parallel.c  2005-01-23 13:42:59.000000000 -0700
+++ qemu-sandbox/hw/parallel.c  2005-03-12 19:00:37.000000000 -0700
@@ -22,6 +22,9 @@
  * THE SOFTWARE.
  */
 #include "vl.h"
+#include <sys/ioctl.h>
+#include <linux/parport.h>
+#include <linux/ppdev.h>

 //#define DEBUG_PARALLEL

@@ -43,15 +46,6 @@
 #define PARA_CTR_AUTOLF        0x02    /* Auto linefeed complement */
 #define PARA_CTR_STROBE        0x01    /* Strobe complement */

-struct ParallelState {
-    uint8_t data;
-    uint8_t status; /* read only register */
-    uint8_t control;
-    int irq;
-    int irq_pending;
-    CharDriverState *chr;
-};
-
 static void parallel_update_irq(ParallelState *s)
 {
     if (s->irq_pending)
@@ -70,29 +64,29 @@ static void parallel_ioport_write(void *
 #endif
     switch(addr) {
     case 0:
-        s->data = val;
+        qemu_pp_write_data(s, (uint8_t)val);
         parallel_update_irq(s);
         break;
     case 2:
+        qemu_pp_write_control(s, (uint8_t)val);
         if ((val & PARA_CTR_INIT) == 0 ) {
-            s->status = PARA_STS_BUSY;
-            s->status |= PARA_STS_ACK;
-            s->status |= PARA_STS_ONLINE;
-            s->status |= PARA_STS_ERROR;
+         s->status = PARA_STS_BUSY;
+         s->status |= PARA_STS_ACK;
+         s->status |= PARA_STS_ONLINE;
+         s->status |= PARA_STS_ERROR;
         }
         else if (val & PARA_CTR_SELECT) {
-            if (val & PARA_CTR_STROBE) {
-                s->status &= ~PARA_STS_BUSY;
-                if ((s->control & PARA_CTR_STROBE) == 0)
-                    qemu_chr_write(s->chr, &s->data, 1);
-            } else {
-                if (s->control & PARA_CTR_INTEN) {
-                    s->irq_pending = 1;
-                }
-            }
+         if (val & PARA_CTR_STROBE) {
+             s->status &= ~PARA_STS_BUSY;
+             if ((s->control & PARA_CTR_STROBE) == 0)
+               qemu_chr_write(s->chr, &s->data, 1);
+         } else {
+             if (s->control & PARA_CTR_INTEN) {
+               s->irq_pending = 1;
+             }
+         }
         }
         parallel_update_irq(s);
-        s->control = val;
         break;
     }
 }
@@ -105,25 +99,25 @@ static uint32_t parallel_ioport_read(voi
     addr &= 7;
     switch(addr) {
     case 0:
-        ret = s->data;
+        ret = qemu_pp_read_data(s);
         break;
     case 1:
-        ret = s->status;
+        ret = qemu_pp_read_status(s);
         s->irq_pending = 0;
         if ((s->status & PARA_STS_BUSY) == 0 && (s->control &
PARA_CTR_STROBE)== 0) {
-            /* XXX Fixme: wait 5 microseconds */
-            if (s->status & PARA_STS_ACK)
-                s->status &= ~PARA_STS_ACK;
-            else {
-            /* XXX Fixme: wait 5 microseconds */
-                s->status |= PARA_STS_ACK;
-                s->status |= PARA_STS_BUSY;
-            }
+         /* XXX Fixme: wait 5 microseconds */
+         if (s->status & PARA_STS_ACK)
+             s->status &= ~PARA_STS_ACK;
+         else {
+         /* XXX Fixme: wait 5 microseconds */
+             s->status |= PARA_STS_ACK;
+             s->status |= PARA_STS_BUSY;
+         }
         }
         parallel_update_irq(s);
         break;
     case 2:
-        ret = s->control;
+        ret = qemu_pp_read_control(s);
         break;
     }
 #ifdef DEBUG_PARALLEL
Only in qemu-sandbox: kqemu
Only in qemu-sandbox: qemu-doc.html
Only in qemu-sandbox: qemu-img.1
Only in qemu-sandbox: qemu-tech.html
Only in qemu-sandbox: qemu.1
diff --exclude=CVS -upr qemu/vl.c qemu-sandbox/vl.c
--- qemu/vl.c   2005-03-13 02:43:36.000000000 -0700
+++ qemu-sandbox/vl.c   2005-03-13 07:16:54.000000000 -0700
@@ -46,6 +46,8 @@
 #include <libutil.h>
 #endif
 #else
+#include <linux/parport.h>
+#include <linux/ppdev.h>
 #include <linux/if.h>
 #include <linux/if_tun.h>
 #include <pty.h>
@@ -1028,10 +1030,14 @@ CharDriverState *qemu_chr_open_null(void
     return chr;
 }

+
+
+
 #ifndef _WIN32

 typedef struct {
     int fd_in, fd_out;
+    int parport_device;
     /* for nographic stdio only */
     IOCanRWHandler *fd_can_read;
     IOReadHandler *fd_read;
@@ -1084,6 +1090,76 @@ static void fd_chr_add_read_handler(Char
     }
 }

+uint8_t qemu_pp_read_status(ParallelState *s)
+{
+    uint8_t ret, status;
+    FDCharDriver *fd = s->chr->opaque;
+
+    if (fd->parport_device) {
+        ioctl(fd->fd_out, PPRSTATUS, &status);
+        ret = status;
+    } else {
+        ret = s->status;
+    }
+
+    return ret;
+}
+
+
+uint8_t qemu_pp_read_control(ParallelState *s)
+{
+    uint8_t ret, control;
+    FDCharDriver *fd = s->chr->opaque;
+
+    if (fd->parport_device) {
+        ioctl(fd->fd_out, PPRCONTROL, &control);
+        ret = control;
+    } else {
+        ret = s->control;
+    }
+
+    return ret;
+
+}
+uint8_t qemu_pp_read_data(ParallelState *s)
+{
+    uint8_t ret, data;
+    FDCharDriver *fd = s->chr->opaque;
+
+    if (fd->parport_device) {
+        ioctl(fd->fd_out, PPRDATA, &data);
+        ret = data;
+    } else {
+        ret = s->data;
+    }
+
+    return ret;
+}
+void qemu_pp_write_data(ParallelState *s, uint8_t val)
+{
+    uint8_t data;
+    FDCharDriver *fd = s->chr->opaque;
+
+    if (fd->parport_device) {
+        data = (uint8_t)val;
+        ioctl(fd->fd_out, PPWDATA, &data);
+    } else {
+        s->data = val;
+    }
+}
+
+void qemu_pp_write_control(ParallelState *s, uint8_t val)
+{
+    uint8_t control;
+    FDCharDriver *fd = s->chr->opaque;
+
+    if (fd->parport_device) {
+        control = (uint8_t)val;
+        ioctl(fd->fd_out, PPWCONTROL, &control);
+    } else {
+        s->control = val;
+    }
+}
 /* open a character device to a unix fd */
 CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
 {
@@ -1263,6 +1339,24 @@ CharDriverState *qemu_chr_open_stdio(voi
     return chr;
 }

+CharDriverState *qemu_chr_open_dev(const char *filename)
+{
+    int fd = 0;
+
+    fd = open(filename, O_RDWR);
+    CharDriverState *s = qemu_chr_open_fd(fd, fd);
+
+    if (strstr(filename, "parport") != NULL) {
+        if (ioctl(((FDCharDriver *)s->opaque)->fd_in, PPCLAIM) == 0) {
+         ((FDCharDriver *)s->opaque)->parport_device = 1;
+        } else {
+         ((FDCharDriver *)s->opaque)->parport_device = 0;
+        }
+    }
+
+    return s;
+}
+
 #if defined(__linux__)
 CharDriverState *qemu_chr_open_pty(void)
 {
@@ -1297,11 +1391,14 @@ CharDriverState *qemu_chr_open(const cha
         return qemu_chr_open_pty();
     } else if (!strcmp(filename, "stdio")) {
         return qemu_chr_open_stdio();
-    } else
-#endif
+    } else {
+                               return qemu_chr_open_dev(filename);
+               }
+#else
     {
         return NULL;
     }
+#endif
 }

 /***********************************************************/
diff --exclude=CVS -upr qemu/vl.h qemu-sandbox/vl.h
--- qemu/vl.h   2005-03-13 02:43:36.000000000 -0700
+++ qemu-sandbox/vl.h   2005-03-13 07:16:54.000000000 -0700
@@ -199,6 +199,17 @@ typedef struct CharDriverState {
     void *opaque;
 } CharDriverState;

+
+typedef struct ParallelState {
+    uint8_t data;
+    uint8_t status; /* read only register */
+    uint8_t control;
+    int irq;
+    int irq_pending;
+    CharDriverState *chr;
+} ParallelState;
+
+
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
@@ -206,6 +217,13 @@ void qemu_chr_add_read_handler(CharDrive
                                IOCanRWHandler *fd_can_read,
                                IOReadHandler *fd_read, void *opaque);
 void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
+
+
+uint8_t qemu_pp_read_status(ParallelState *s);
+uint8_t qemu_pp_read_control(ParallelState *s);
+uint8_t qemu_pp_read_data(ParallelState *s);
+void qemu_pp_write_data(ParallelState *s, uint8_t data);
+void qemu_pp_write_control(ParallelState *s, uint8_t control);

 /* consoles */

@@ -643,8 +661,6 @@ typedef struct SerialState SerialState;
 SerialState *serial_init(int base, int irq, CharDriverState *chr);

 /* parallel.c */
-
-typedef struct ParallelState ParallelState;
 ParallelState *parallel_init(int base, int irq, CharDriverState *chr);

 /* i8259.c */

  reply	other threads:[~2005-03-13 19:33 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-13  9:43 [Qemu-devel] qemu qemu-doc.texi Fabrice Bellard
2005-03-13 14:43 ` Jason Turner [this message]
2005-03-13 20:14   ` [Qemu-devel] [PATCH] parallel port support for qemu Adrian Smarzewski
2005-03-13 20:53     ` Jason Turner
2005-03-13 23:30       ` Adrian Smarzewski
  -- strict thread matches above, loose matches on Subject: below --
2005-01-07 17:59 Mark Jonckheere
2005-01-08 11:15 ` Lennert Buytenhek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=58e14cf0050313064327ab1c8e@mail.gmail.com \
    --to=lefticus@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.