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