Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Add a driver for DisplayLink DL-1x0/1x5 based US...



details:   https://anonhg.NetBSD.org/src/rev/09f978c6ee54
branches:  trunk
changeset: 749478:09f978c6ee54
user:      tsutsui <tsutsui%NetBSD.org@localhost>
date:      Mon Nov 30 16:18:34 2009 +0000

description:
Add a driver for DisplayLink DL-1x0/1x5 based USB LCDs and USB-VGA adaptors.
Ported by FUKAUMI Naoki from OpenBSD with many modification.
No particular comments (except from me) on tech-kern@.

There are still many TODO even in MI wscons(4) API to handle this device:

 * No detach function for wsdisplay(9).
   Unpluging a device causes a panic. (should be trivial?)

 * ioctl() for X server support is currently commented out. ("notyet")
   OpenBSD allows device depedent ioctl()s and they introduced
   UDLIO_DAMAGE ioctl for the damage extension ops of X servers for udl(4).
   Before blindly pulling such ioctl(), probably we should discuss
   how such specific operations should be handled in MI wscons(4) API.

 * Screen text of wsemul tty could be mangled during large scroll ops.
   All tty output operations are invoked via ttstart() with the giant
   tty_lock mutex held, so we can't call cv_wait(9) to wait resources
   for data xfers via usbdi(9).h, then text output is silently discarded
   on resource shortage. To handle this without tty_lock reorganization,
   we have to change wsdisplay(9) APIs (especially wsdisplaystart()) to
   return a number of actually handled characters as OpenBSD does, but
   it may require whole API changes around child rasops(9) etc.

 * No MI API definition to convert mmap(9) cookie to physical address.
   The conversion is required to create a cookie which will be passed to
   pmap_phys_address(9) in uvm/uvm_device.c:udv_fault(). Most other
   drivers use bus_dmamem_mmap(9) or bus_space_mmap(9), but udl(4) uses
   kmem_alloc(9)'ed memory for bitmap data.
   Furthermore, pmap(9) man page says about pmap_phys_address(9):

     "This function is provided to accommodate systems which have
      physical address spaces larger than can be directly addressed
      by the platform's paddr_t type. The existence of this function is
      highly dubious, and it is expected that this function will be
      removed from the pmap API in a future release of NetBSD."

   As the man page says we have already had split paddr_t and vaddr_t,
   so it's time to remove such old ugly cookie and change all mmap(4)
   functions (mostly in MD bus_dma(9) and bus_space(9) APIs) to return
   simple physical address in paddr_t?

 * We need proper device names for wsdisplay1 (and more devices).
   Currently wsdisplay0 uses ttyE0 through ttyE253 (minor 0 to 253)
   for screens, ttyEstat (254) for status, and ttyEcfg (255) for config.
   The next wsdisplay1 will use 256 through 509 for screens, 510 for stat,
   and 511 for config but what names should we use for them? ttyFxxx?

 * How to handle multiple sets of wskbd/wsdisplay on a single machine.
   rc.d/wscons doesn't provide method to specify wscons control devices.
   There is no proper interface to specify which keyboard should be connected
   to which wsdisplay, etc.

 * And maybe more...

diffstat:

 sys/dev/usb/files.usb |     7 +-
 sys/dev/usb/udl.c     |  1744 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/usb/udl.h     |   196 +++++
 3 files changed, 1946 insertions(+), 1 deletions(-)

diffs (truncated from 1966 to 300 lines):

diff -r e010e7403285 -r 09f978c6ee54 sys/dev/usb/files.usb
--- a/sys/dev/usb/files.usb     Mon Nov 30 16:16:53 2009 +0000
+++ b/sys/dev/usb/files.usb     Mon Nov 30 16:18:34 2009 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.usb,v 1.91 2009/06/19 01:16:23 mrg Exp $
+#      $NetBSD: files.usb,v 1.92 2009/11/30 16:18:34 tsutsui Exp $
 #
 # Config file and device description for machine-independent USB code.
 # Included by ports that need it.  Ports that use it must provide
@@ -331,3 +331,8 @@
 device zyd: ether, ifnet, arp, wlan, firmload
 attach zyd at usbdevif
 file   dev/usb/if_zyd.c                zyd
+
+# DisplayLink DL-1x0/DL-1x5
+device udl: wsemuldisplaydev, rasops16, edid, firmload
+attach udl at usbdevif
+file   dev/usb/udl.c                   udl
diff -r e010e7403285 -r 09f978c6ee54 sys/dev/usb/udl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/usb/udl.c Mon Nov 30 16:18:34 2009 +0000
@@ -0,0 +1,1744 @@
+/*     $NetBSD: udl.c,v 1.1 2009/11/30 16:18:34 tsutsui Exp $  */
+
+/*-
+ * Copyright (c) 2009 FUKAUMI Naoki.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2009 Marcus Glocker <mglocker%openbsd.org@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for the ``DisplayLink DL-1x0 / DL-1x5'' graphic chips based
+ * on the reversed engineered specifications of Florian Echtler
+ * <floe at butterbrot dot org>:
+ *
+ *     http://floe.butterbrot.org/displaylink/doku.php
+ *
+ * This driver was written by Marcus Glocker for OpenBSD and ported to
+ * NetBSD by FUKAUMI Naoki with many modification.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.1 2009/11/30 16:18:34 tsutsui Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+#include <uvm/uvm.h>
+
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/usbdevs.h>
+
+#include <dev/firmload.h>
+
+#include <dev/videomode/videomode.h>
+#include <dev/videomode/edidvar.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+
+#include <dev/usb/udl.h>
+#ifdef notyet
+#include <dev/usb/udlio.h>
+#endif
+
+/*
+ * Defines.
+ */
+#ifdef UDL_DEBUG
+#define DPRINTF(x)     do { if (udl_debug) printf x; } while (0)
+#define DPRINTFN(n, x) do { if (udl_debug >= (n)) printf x; } while (0)
+int udl_debug = 1;
+#else
+#define DPRINTF(x)     do {} while (0)
+#define DPRINTFN(n, x) do {} while (0)
+#endif
+
+/*
+ * Prototypes.
+ */
+static int             udl_match(device_t, cfdata_t, void *);
+static void            udl_attach(device_t, device_t, void *);
+static int             udl_detach(device_t, int);
+
+static int             udl_ioctl(void *, void *, u_long, void *, int,
+                           struct lwp *);
+static paddr_t         udl_mmap(void *, void *, off_t, int);
+static int             udl_alloc_screen(void *, const struct wsscreen_descr *,
+                           void **, int *, int *, long *);
+static void            udl_free_screen(void *, void *);
+static int             udl_show_screen(void *, void *, int,
+                           void (*)(void *, int, int), void *);
+
+static void            udl_comp_load(struct udl_softc *);
+static void            udl_comp_unload(struct udl_softc *);
+static int             udl_fbmem_alloc(struct udl_softc *);
+static void            udl_fbmem_free(struct udl_softc *);
+static int             udl_cmdq_alloc(struct udl_softc *);
+static void            udl_cmdq_free(struct udl_softc *);
+static struct udl_cmdq *udl_cmdq_get(struct udl_softc *sc);
+static void            udl_cmdq_put(struct udl_softc *sc,
+                           struct udl_cmdq *cmdq);
+static void            udl_cmdq_flush(struct udl_softc *);
+
+static void            udl_cursor(void *, int, int, int);
+static void            udl_putchar(void *, int, int, u_int, long);
+static void            udl_copycols(void *, int, int, int, int);
+static void            udl_erasecols(void *, int, int, int, long);
+static void            udl_copyrows(void *, int, int, int);
+static void            udl_eraserows(void *, int, int, long);
+
+static void            udl_restore_char(struct rasops_info *);
+static void            udl_draw_char(struct rasops_info *, uint16_t *, u_int,
+                           int, int);
+static void            udl_copy_rect(struct udl_softc *, int, int, int, int,
+                           int, int);
+static void            udl_fill_rect(struct udl_softc *, uint16_t, int, int,
+                           int, int);
+#ifdef notyet
+static void            udl_draw_rect(struct udl_softc *,
+                           struct udl_ioctl_damage *);
+static void            udl_draw_rect_comp(struct udl_softc *,
+                           struct udl_ioctl_damage *);
+#endif
+
+static inline void     udl_copy_line(struct udl_softc *, int, int, int);
+static inline void     udl_fill_line(struct udl_softc *, uint16_t, int, int);
+static inline void     udl_draw_line(struct udl_softc *, uint16_t *, int,
+                           int);
+static inline void     udl_draw_line_comp(struct udl_softc *, uint16_t *, int,
+                           int);
+
+static int             udl_cmd_send(struct udl_softc *);
+static void            udl_cmd_send_async(struct udl_softc *);
+static void            udl_cmd_send_async_cb(usbd_xfer_handle,
+                           usbd_private_handle, usbd_status);
+
+static int             udl_ctrl_msg(struct udl_softc *, uint8_t, uint8_t,
+                           uint16_t, uint16_t, uint8_t *, uint16_t);
+static int             udl_init(struct udl_softc *);
+static void            udl_read_edid(struct udl_softc *);
+static void            udl_set_address(struct udl_softc *, int, int, int,
+                           int);
+static void            udl_blank(struct udl_softc *, int);
+static uint16_t                udl_lfsr(uint16_t);
+static int             udl_set_resolution(struct udl_softc *,
+                           const struct videomode *);
+static const struct videomode *udl_videomode_lookup(const char *);
+
+static inline void
+udl_cmd_add_1(struct udl_softc *sc, uint8_t val)
+{
+
+       *sc->sc_cmd_buf++ = val;
+}
+
+static inline void
+udl_cmd_add_2(struct udl_softc *sc, uint16_t val)
+{
+
+       be16enc(sc->sc_cmd_buf, val);
+       sc->sc_cmd_buf += 2;
+}
+
+static inline void
+udl_cmd_add_3(struct udl_softc *sc, uint32_t val)
+{
+
+       udl_cmd_add_2(sc, val >> 8);
+       udl_cmd_add_1(sc, val);
+}
+
+static inline void
+udl_cmd_add_4(struct udl_softc *sc, uint32_t val)
+{
+
+       be32enc(sc->sc_cmd_buf, val);
+       sc->sc_cmd_buf += 4;
+}
+
+static inline void
+udl_cmd_add_buf(struct udl_softc *sc, uint16_t *buf, int width)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+       memcpy(sc->sc_cmd_buf, buf, width * 2);
+       sc->sc_cmd_buf += width * 2;
+#else
+       uint16_t *endp;
+
+       endp = buf + width;
+
+       if (((uintptr_t)sc->sc_cmd_buf & 1) == 0) {
+               while (buf < endp) {
+                       *(uint16_t *)sc->sc_cmd_buf = htobe16(*buf++);
+                       sc->sc_cmd_buf += 2;
+               }
+       } else {
+               while (buf < endp) {
+                       be16enc(sc->sc_cmd_buf, *buf++);
+                       sc->sc_cmd_buf += 2;
+               }
+       }
+#endif
+}
+
+static inline void
+udl_reg_write_1(struct udl_softc *sc, uint8_t reg, uint8_t val)
+{
+
+       udl_cmd_add_4(sc, (UDL_BULK_SOC << 24) |
+           (UDL_BULK_CMD_REG_WRITE_1 << 16) | (reg << 8) | val);
+}
+
+static inline void
+udl_reg_write_2(struct udl_softc *sc, uint8_t reg, uint16_t val)
+{
+
+       udl_reg_write_1(sc, reg++, val >> 8);
+       udl_reg_write_1(sc, reg, val);
+}
+
+static inline void
+udl_reg_write_3(struct udl_softc *sc, uint8_t reg, uint32_t val)
+{
+
+       udl_reg_write_1(sc, reg++, val >> 16);
+       udl_reg_write_1(sc, reg++, val >> 8);
+       udl_reg_write_1(sc, reg, val);
+}
+
+/* XXX */
+static int
+firmware_load(const char *dname, const char *iname, uint8_t **ucodep,
+    size_t *sizep)
+{
+       firmware_handle_t fh;
+       int error;
+
+       if ((error = firmware_open(dname, iname, &fh)) != 0)
+               return error;
+       *sizep = firmware_get_size(fh);
+       if ((*ucodep = firmware_malloc(*sizep)) == NULL) {
+               firmware_close(fh);
+               return ENOMEM;
+       }
+       if ((error = firmware_read(fh, 0, *ucodep, *sizep)) != 0)
+               firmware_free(*ucodep, *sizep);
+       firmware_close(fh);
+
+       return error;
+}
+
+/*
+ * Driver glue.



Home | Main Index | Thread Index | Old Index