Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Add 3Dfx Voodoo2 driver. Still needs some cleanu...



details:   https://anonhg.NetBSD.org/src/rev/b2cc5ce12aac
branches:  trunk
changeset: 780277:b2cc5ce12aac
user:      rkujawa <rkujawa%NetBSD.org@localhost>
date:      Wed Jul 18 23:30:13 2012 +0000

description:
Add 3Dfx Voodoo2 driver. Still needs some cleanup and prettyfying, but hey
it works.

diffstat:

 sys/dev/pci/files.pci  |    8 +-
 sys/dev/pci/tdvfb.c    |  753 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/tdvfbreg.h |  179 +++++++++++
 sys/dev/pci/tdvfbvar.h |   84 +++++
 4 files changed, 1023 insertions(+), 1 deletions(-)

diffs (truncated from 1047 to 300 lines):

diff -r 9219b2f7bab4 -r b2cc5ce12aac sys/dev/pci/files.pci
--- a/sys/dev/pci/files.pci     Wed Jul 18 22:22:26 2012 +0000
+++ b/sys/dev/pci/files.pci     Wed Jul 18 23:30:13 2012 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.pci,v 1.357 2012/04/19 17:50:51 bouyer Exp $
+#      $NetBSD: files.pci,v 1.358 2012/07/18 23:30:13 rkujawa Exp $
 #
 # Config file and device description for machine-independent PCI code.
 # Included by ports that need it.  Requires that the SCSI files be
@@ -1112,3 +1112,9 @@
 device lynxfb: wsemuldisplaydev, rasops16
 attach lynxfb at pci
 file   dev/pci/lynxfb.c        lynxfb needs-flag
+
+# 3Dfx Voodoo Graphics
+defflag        opt_tdvfb.h             TDVFB_CONSOLE
+device tdvfb: wsemuldisplaydev, rasops8, vcons, videomode
+attach tdvfb at pci
+file   dev/pci/tdvfb.c         tdvfb   
diff -r 9219b2f7bab4 -r b2cc5ce12aac sys/dev/pci/tdvfb.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/tdvfb.c       Wed Jul 18 23:30:13 2012 +0000
@@ -0,0 +1,753 @@
+/*     $NetBSD: tdvfb.c,v 1.1 2012/07/18 23:30:14 rkujawa Exp $        */
+
+/*
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.   
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * 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.
+ */
+
+/*
+ * A console driver for 3Dfx Voodoo2 (CVG). 
+ *
+ * 3Dfx Glide 2.x source code, Linux driver by Ghozlane Toumi, and 
+ * "Voodoo2 Graphics Engine for 3D Game Acceleration" document were used as 
+ * reference. wscons attachment code based mostly on genfb by Michael
+ * Lorenz.
+ *
+ * This driver currently only support boards with ICS GENDAC (which seems to
+ * be most popular, however at least two different DACs were used with CVG).
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: tdvfb.c,v 1.1 2012/07/18 23:30:14 rkujawa Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/endian.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pciio.h>
+
+#include <dev/pci/tdvfbreg.h>
+#include <dev/pci/tdvfbvar.h>
+
+#include <dev/videomode/videomode.h>
+
+#include "opt_wsemul.h"
+#include "opt_tdvfb.h"
+
+#define MAXLOOP 4096 
+
+static int     tdvfb_match(device_t, cfdata_t, void *);
+static void    tdvfb_attach(device_t, device_t, void *);
+
+static uint32_t        tdvfb_cvg_read(struct tdvfb_softc *sc, uint32_t reg);
+static void    tdvfb_cvg_write(struct tdvfb_softc *sc, uint32_t reg,
+                   uint32_t val);
+static void    tdvfb_cvg_set(struct tdvfb_softc *sc, uint32_t reg, 
+                   uint32_t bits);
+static void    tdvfb_cvg_unset(struct tdvfb_softc *sc, uint32_t reg, 
+                   uint32_t bits);
+static uint8_t tdvfb_cvg_dac_read(struct tdvfb_softc *sc, uint32_t reg);
+void           tdvfb_cvg_dac_write(struct tdvfb_softc *sc, uint32_t reg, 
+                   uint32_t val);
+static void    tdvfb_wait(struct tdvfb_softc *sc);
+
+static bool    tdvfb_init(struct tdvfb_softc *sc);
+static void    tdvfb_fbiinit_defaults(struct tdvfb_softc *sc);
+static size_t  tdvfb_mem_size(struct tdvfb_softc *sc);
+
+static bool    tdvfb_videomode_set(struct tdvfb_softc *sc);
+static void    tdvfb_videomode_dac(struct tdvfb_softc *sc);
+
+static bool    tdvfb_gendac_detect(struct tdvfb_softc *sc);
+static struct tdvfb_dac_timing tdvfb_gendac_calc_pll(int freq);
+static void    tdvfb_gendac_set_cvg_timing(struct tdvfb_softc *sc, 
+                   struct tdvfb_dac_timing *timing);
+static void    tdvfb_gendac_set_vid_timing(struct tdvfb_softc *sc, 
+                   struct tdvfb_dac_timing *timing);
+
+static void    tdvfb_init_screen(void *cookie, struct vcons_screen *scr, 
+                   int existing, long *defattr);
+static void    tdvfb_init_palette(struct tdvfb_softc *sc);
+
+CFATTACH_DECL_NEW(tdvfb, sizeof(struct tdvfb_softc),
+    tdvfb_match, tdvfb_attach, NULL, NULL);
+
+static int
+tdvfb_match(device_t parent, cfdata_t match, void *aux)
+{
+       const struct pci_attach_args *pa = (const struct pci_attach_args *)aux;
+
+       if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_3DFX) &&
+           (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DFX_VOODOO2))
+               return 100;
+
+       return 0;
+}
+
+static void
+tdvfb_attach(device_t parent, device_t self, void *aux)
+{
+       struct tdvfb_softc *sc = device_private(self);
+       struct wsemuldisplaydev_attach_args ws_aa;
+       struct rasops_info *ri;
+       const struct pci_attach_args *pa = aux;
+       pcireg_t screg;
+       bool console;
+       long defattr;
+
+#ifdef TDVFB_CONSOLE
+       console = true; 
+#else
+       console = false;
+#endif
+
+       sc->sc_pc = pa->pa_pc;
+       sc->sc_pcitag = pa->pa_tag;
+       sc->sc_dev = self;
+
+       screg = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+           PCI_COMMAND_STATUS_REG);
+       screg |= PCI_COMMAND_MEM_ENABLE;
+       pci_conf_write(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, 
+           screg);
+
+       pci_aprint_devinfo(pa, NULL);
+
+       /* map the BAR */
+       if (pci_mapreg_map(pa, TDV_MM_BAR, PCI_MAPREG_TYPE_MEM, 0,
+           &sc->sc_cvgt, &sc->sc_cvgh, &sc->sc_cvg_pa, 0) != 0 ) {
+               aprint_error_dev(sc->sc_dev, "unable to map CVG BAR");
+               return;
+       }
+
+       /* Map the framebuffer. */
+       if (bus_space_subregion(sc->sc_cvgt, sc->sc_cvgh, TDV_OFF_FB, 
+           TDV_FB_SIZE, &sc->sc_fbh)) {
+               aprint_error_dev(sc->sc_dev, "unable to map the framebuffer");  
+       }
+
+       aprint_normal_dev(sc->sc_dev, "CVG at 0x%08x, fb at 0x%08x\n", 
+           sc->sc_cvg_pa, sc->sc_cvg_pa + TDV_OFF_FB);
+
+       /* Do the low level setup. */
+       if (!tdvfb_init(sc)) {
+               aprint_error_dev(sc->sc_dev, "could not initialize CVG\n");
+               return;
+       }
+
+       /* 
+        * The card is alive now, let's check how much framebuffer memory 
+        * do we have.
+        */
+       sc->sc_memsize = tdvfb_mem_size(sc);
+
+       /* Select video mode, 800x600x60 by default... */
+       sc->sc_width = 800;
+       sc->sc_height = 600;
+       sc->sc_bpp = 32;
+       sc->sc_linebytes = 1024 * (sc->sc_bpp / 8);
+       sc->sc_videomode = pick_mode_by_ref(sc->sc_width, sc->sc_height, 60);
+
+       tdvfb_videomode_set(sc);
+
+       sc->sc_defaultscreen_descr = (struct wsscreen_descr){
+               "default",
+               0, 0,
+               NULL,
+               8, 16,
+               WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
+               NULL
+       };
+       sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
+       sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
+       sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
+       
+       vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
+           &sc->sc_accessops);
+       sc->vd.init_screen = tdvfb_init_screen;
+
+       ri = &sc->sc_console_screen.scr_ri;
+
+       tdvfb_init_palette(sc);
+
+       if (console) {
+               vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
+                   &defattr);
+
+               sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC |
+                   VCONS_DONT_READ; 
+               vcons_redraw_screen(&sc->sc_console_screen);
+
+               sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
+               sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
+               sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
+               sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
+
+               wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
+                   defattr);
+               vcons_replay_msgbuf(&sc->sc_console_screen);
+       } else if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
+               vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
+                   &defattr);
+       }
+
+       ws_aa.console = console;
+       ws_aa.scrdata = &sc->sc_screenlist;
+       ws_aa.accessops = &sc->sc_accessops;
+       ws_aa.accesscookie = &sc->vd;
+       
+       config_found(sc->sc_dev, &ws_aa, wsemuldisplaydevprint);
+}
+
+static void
+tdvfb_init_palette(struct tdvfb_softc *sc)
+{
+       int i, j;
+
+       j = 0;
+       for (i = 0; i < 256; i++) {
+               sc->sc_cmap_red[i] = rasops_cmap[j];
+               sc->sc_cmap_green[i] = rasops_cmap[j + 1];
+               sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
+               j += 3;
+       }
+}
+
+static void
+tdvfb_init_screen(void *cookie, struct vcons_screen *scr, int existing,
+    long *defattr)
+{
+       struct tdvfb_softc *sc = cookie;
+       struct rasops_info *ri = &scr->scr_ri;
+
+       wsfont_init();
+
+       ri->ri_depth = sc->sc_bpp;
+       ri->ri_width = sc->sc_width;
+       ri->ri_height = sc->sc_height;
+       ri->ri_stride = sc->sc_linebytes;
+       ri->ri_flg = RI_CENTER;
+       ri->ri_bits = (char *) bus_space_vaddr(sc->sc_cvgt, sc->sc_fbh);        
+
+       scr->scr_flags |= VCONS_DONT_READ;
+
+       rasops_init(ri, 0, 0);
+       ri->ri_caps = WSSCREEN_WSCOLORS;
+       rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
+           sc->sc_width / ri->ri_font->fontwidth);
+
+       ri->ri_hw = scr;
+}
+
+static bool
+tdvfb_videomode_set(struct tdvfb_softc *sc) 
+{
+       uint32_t fbiinit1, fbiinit5, fbiinit6, lfbmode;
+       uint16_t vbackporch, vsyncon, vsyncoff;
+       uint16_t hbackporch, hsyncon, hsyncoff; 
+       uint16_t yheight, xwidth; 
+



Home | Main Index | Thread Index | Old Index