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 a basic driver for the SIS315 Pro frame buff...



details:   https://anonhg.NetBSD.org/src/rev/3b95769172e6
branches:  trunk
changeset: 768776:3b95769172e6
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sat Aug 27 13:28:37 2011 +0000

description:
Add a basic driver for the SIS315 Pro frame buffer found on some loogson2-based
systems, from OpenBSD.
At this time it can only map the framebuffer and attaches wscons,
using whatever resolution was configured by the firmware.
It doens't support any accelaration or mode change.

diffstat:

 sys/dev/pci/files.pci |    6 +-
 sys/dev/pci/sisfb.c   |  755 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/sisfb.h   |    3 +
 3 files changed, 763 insertions(+), 1 deletions(-)

diffs (truncated from 783 to 300 lines):

diff -r ffeaa67c0bee -r 3b95769172e6 sys/dev/pci/files.pci
--- a/sys/dev/pci/files.pci     Sat Aug 27 13:23:52 2011 +0000
+++ b/sys/dev/pci/files.pci     Sat Aug 27 13:28:37 2011 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.pci,v 1.346 2011/08/24 20:27:35 dyoung Exp $
+#      $NetBSD: files.pci,v 1.347 2011/08/27 13:28:37 bouyer Exp $
 #
 # Config file and device description for machine-independent PCI code.
 # Included by ports that need it.  Requires that the SCSI files be
@@ -1080,3 +1080,7 @@
 attach pwdog at pci
 file   dev/pci/pwdog.c         pwdog
 
+# SIS 315 Pro frame buffer
+device  sisfb: wsemuldisplaydev, rasops8, rasops15, rasops16, rasops32, vcons
+attach  sisfb at pci
+file    dev/pci/sisfb.c                sisfb   needs-flag
diff -r ffeaa67c0bee -r 3b95769172e6 sys/dev/pci/sisfb.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/sisfb.c       Sat Aug 27 13:28:37 2011 +0000
@@ -0,0 +1,755 @@
+/*     $OpenBSD: sisfb.c,v 1.2 2010/12/26 15:40:59 miod Exp $  */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * 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.
+ */
+
+/*
+ * Minimalistic driver for the SIS315 Pro frame buffer found on the
+ * Lemote Fuloong 2F systems.
+ * Does not support accelaration, mode change, secondary output, or
+ * anything fancy.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sisfb.c,v 1.1 2011/08/27 13:28:37 bouyer Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pciio.h>
+
+#include <dev/videomode/videomode.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/wsfont/wsfont.h>
+#include <dev/rasops/rasops.h>
+#include <dev/wscons/wsdisplay_vconsvar.h>
+#include <dev/pci/wsdisplay_pci.h>
+
+#include <dev/i2c/i2cvar.h>
+
+#include <dev/pci/sisfb.h>
+
+struct sisfb_softc;
+
+/* minimal frame buffer information, suitable for early console */
+
+struct sisfb {
+       struct sisfb_softc      *sc;
+       uint8_t                  cmap[256 * 3];
+
+       bus_space_tag_t          fbt;
+       bus_space_handle_t       fbh;
+
+       bus_space_tag_t          mmiot;
+       bus_space_handle_t       mmioh;
+
+       bus_space_tag_t          iot;
+       bus_space_handle_t       ioh;
+
+       struct vcons_screen      vcs;
+       struct wsscreen_descr    wsd;
+
+       int                      fb_depth;
+       int                      fb_width;
+       int                      fb_height;
+       int                      fb_stride;
+       void                     *fb_addr;
+};
+
+struct sisfb_softc {
+       device_t                 sc_dev;
+       struct sisfb            *sc_fb;
+       struct sisfb             sc_fb_store;
+
+       struct vcons_data       vd;
+       struct wsscreen_list    sc_wsl;
+       const struct wsscreen_descr     *sc_scrlist[1];
+       int                     sc_nscr;
+       int                     sc_mode;
+};
+
+int    sisfb_match(device_t, cfdata_t, void *);
+void   sisfb_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(sisfb, sizeof(struct sisfb_softc),
+    sisfb_match, sisfb_attach, NULL, NULL);
+
+
+int    sisfb_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
+           int *, long *);
+void   sisfb_free_screen(void *, void *);
+int    sisfb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
+int    sisfb_show_screen(void *, void *, int, void (*)(void *, int, int),
+           void *);
+paddr_t        sisfb_mmap(void *, void *, off_t, int);
+void   sisfb_init_screen(void *, struct vcons_screen *, int, long *);
+
+
+struct wsdisplay_accessops sisfb_accessops = {
+       sisfb_ioctl,
+       sisfb_mmap,
+       sisfb_alloc_screen,
+       sisfb_free_screen,
+       sisfb_show_screen,
+       NULL,   /* load_font */
+       NULL,   /* poolc */
+       NULL    /* scroll */
+};
+
+int    sisfb_getcmap(uint8_t *, struct wsdisplay_cmap *);
+void   sisfb_loadcmap(struct sisfb *, int, int);
+int    sisfb_putcmap(uint8_t *, struct wsdisplay_cmap *);
+int    sisfb_setup(struct sisfb *);
+
+static struct sisfb sisfbcn;
+
+/*
+ * Control Register access
+ *
+ * These are 8 bit registers; the choice of larger width types is intentional.
+ */
+
+#define        SIS_VGA_PORT_OFFSET     0x380
+
+#define        SEQ_ADDR                (0x3c4 - SIS_VGA_PORT_OFFSET)
+#define        SEQ_DATA                (0x3c5 - SIS_VGA_PORT_OFFSET)
+#define        DAC_ADDR                (0x3c8 - SIS_VGA_PORT_OFFSET)
+#define        DAC_DATA                (0x3c9 - SIS_VGA_PORT_OFFSET)
+#undef CRTC_ADDR
+#define        CRTC_ADDR               (0x3d4 - SIS_VGA_PORT_OFFSET)
+#define        CRTC_DATA               (0x3d5 - SIS_VGA_PORT_OFFSET)
+
+#define        CRTC_HDISPLE    0x01    /* horizontal display end */
+#define        CRTC_OVERFLL    0x07    /* overflow low */
+#define        CRTC_STARTADRH  0x0C    /* linear start address mid */
+#define        CRTC_STARTADRL  0x0D    /* linear start address low */
+#define        CRTC_VDE        0x12    /* vertical display end */
+
+
+static inline uint sisfb_crtc_read(struct sisfb *, uint);
+static inline void sisfb_crtc_write(struct sisfb *, uint, uint);
+static inline uint sisfb_seq_read(struct sisfb *, uint);
+static inline void sisfb_seq_write(struct sisfb *, uint, uint);
+
+static inline uint
+sisfb_crtc_read(struct sisfb *fb, uint idx)
+{
+       uint val;
+       bus_space_write_1(fb->iot, fb->ioh, CRTC_ADDR, idx);
+       val = bus_space_read_1(fb->iot, fb->ioh, CRTC_DATA);
+#ifdef SIS_DEBUG
+       printf("CRTC %04x -> %02x\n", idx, val);
+#endif
+       return val;
+}
+
+static inline void
+sisfb_crtc_write(struct sisfb *fb, uint idx, uint val)
+{
+#ifdef SIS_DEBUG
+       printf("CRTC %04x <- %02x\n", idx, val);
+#endif
+       bus_space_write_1(fb->iot, fb->ioh, CRTC_ADDR, idx);
+       bus_space_write_1(fb->iot, fb->ioh, CRTC_DATA, val);
+}
+
+static inline uint
+sisfb_seq_read(struct sisfb *fb, uint idx)
+{
+       uint val;
+       bus_space_write_1(fb->iot, fb->ioh, SEQ_ADDR, idx);
+       val = bus_space_read_1(fb->iot, fb->ioh, SEQ_DATA);
+#ifdef SIS_DEBUG
+       printf("SEQ %04x -> %02x\n", idx, val);
+#endif
+       return val;
+}
+
+static inline void
+sisfb_seq_write(struct sisfb *fb, uint idx, uint val)
+{
+#ifdef SIS_DEBUG
+       printf("SEQ %04x <- %02x\n", idx, val);
+#endif
+       bus_space_write_1(fb->iot, fb->ioh, SEQ_ADDR, idx);
+       bus_space_write_1(fb->iot, fb->ioh, SEQ_DATA, val);
+}
+
+int
+sisfb_match(device_t parent, cfdata_t match, void *aux)
+{
+       struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+
+       if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
+               return 0;
+
+       if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_SIS)
+               return 0;
+
+       if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SIS_315PRO_VGA)
+               return 100;
+       return (0);
+}
+
+void
+sisfb_attach(device_t parent, device_t self, void *aux)
+{
+       struct sisfb_softc *sc = device_private(self);
+       struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+       struct rasops_info *ri;
+       struct wsemuldisplaydev_attach_args waa;
+       bus_size_t fbsize, mmiosize, iosize;
+       struct sisfb *fb;
+       char devinfo[256];
+       int console;
+       unsigned long defattr;
+
+       sc->sc_dev = self;
+       console = sisfbcn.vcs.scr_ri.ri_hw != NULL;
+
+       if (console)
+               fb = &sisfbcn;
+       else {
+               fb = &sc->sc_fb_store;
+       }
+
+       sc->sc_fb = fb;
+       fb->sc = sc;
+
+       pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
+       aprint_normal(": %s\n", devinfo);
+
+       if (!console) {
+               fb->fbt = pa->pa_memt;
+               fb->mmiot = pa->pa_memt;
+               fb->iot = pa->pa_iot;
+               if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM,
+                   BUS_SPACE_MAP_LINEAR, &fb->fbt, &fb->fbh, NULL, &fbsize) != 0) {
+                       aprint_error_dev(self, ": can't map frame buffer\n");
+                       return;
+               }
+
+               if (pci_mapreg_map(pa, PCI_MAPREG_START + 4, PCI_MAPREG_TYPE_MEM,
+                   0, &fb->mmiot, &fb->mmioh, NULL, &mmiosize) != 0) {
+                       aprint_error_dev(self, ": can't map mmio area\n");
+                       goto fail1;
+               }
+
+               if (pci_mapreg_map(pa, PCI_MAPREG_START + 8, PCI_MAPREG_TYPE_IO,
+                   0, &fb->iot, &fb->ioh, NULL, &iosize) != 0) {
+                       aprint_error_dev(self, ": can't map registers\n");
+                       goto fail2;
+               }
+
+
+               if (sisfb_setup(sc->sc_fb) != 0) {
+                       aprint_error_dev(self, ": can't setup frame buffer\n");
+                       goto fail3;
+               }
+       }
+
+       aprint_normal_dev(self, ": %dx%dx%d frame buffer\n",
+           fb->vcs.scr_ri.ri_width, fb->vcs.scr_ri.ri_height, fb->vcs.scr_ri.ri_depth);
+
+       fb->wsd = (struct wsscreen_descr){
+               "default",
+               0, 0,
+               NULL,



Home | Main Index | Thread Index | Old Index