Module Name: src
Committed By: nonaka
Date: Fri Mar 2 13:20:57 UTC 2012
Modified Files:
src/sys/arch/evbmips/conf: LOONGSON files.loongson
src/sys/arch/evbmips/loongson: autoconf.c bonito_mainbus.c
loongson_bus_defs.h loongson_bus_io.c machdep.c yeeloong_machdep.c
src/sys/arch/evbmips/loongson/dev: glx.c
src/sys/dev/pci: files.pci
Added Files:
src/sys/dev/pci: lynxfb.c lynxfbreg.h lynxfbvar.h
Log Message:
Added Lemote Yeeloong Notebook support.
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/evbmips/conf/LOONGSON
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbmips/conf/files.loongson
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/evbmips/loongson/autoconf.c \
src/sys/arch/evbmips/loongson/bonito_mainbus.c \
src/sys/arch/evbmips/loongson/loongson_bus_defs.h \
src/sys/arch/evbmips/loongson/loongson_bus_io.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbmips/loongson/machdep.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbmips/loongson/yeeloong_machdep.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbmips/loongson/dev/glx.c
cvs rdiff -u -r1.355 -r1.356 src/sys/dev/pci/files.pci
cvs rdiff -u -r0 -r1.1 src/sys/dev/pci/lynxfb.c src/sys/dev/pci/lynxfbreg.h \
src/sys/dev/pci/lynxfbvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/evbmips/conf/LOONGSON
diff -u src/sys/arch/evbmips/conf/LOONGSON:1.8 src/sys/arch/evbmips/conf/LOONGSON:1.9
--- src/sys/arch/evbmips/conf/LOONGSON:1.8 Sun Dec 18 05:49:26 2011
+++ src/sys/arch/evbmips/conf/LOONGSON Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-# $NetBSD: LOONGSON,v 1.8 2011/12/18 05:49:26 dholland Exp $
+# $NetBSD: LOONGSON,v 1.9 2012/03/02 13:20:57 nonaka Exp $
#
# LOONGSON machine description file
#
@@ -22,7 +22,7 @@ include "arch/evbmips/conf/std.loongson
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GDIUM-$Revision: 1.8 $"
+#ident "LOONGSON-$Revision: 1.9 $"
maxusers 16
@@ -74,13 +74,13 @@ file-system CD9660 # ISO 9660 + Rock R
file-system MSDOSFS # MS-DOS file system
#file-system FDESC # /dev/fd
file-system KERNFS # /kern (kernel informational filesystem)
-#file-system NULLFS # loopback file system
+file-system NULLFS # loopback file system
#file-system OVERLAY # overlay file system
file-system PROCFS # /proc
#file-system UMAPFS # NULLFS + uid and gid remapping
file-system UNION
file-system PTYFS # /dev/pts/N support
-#file-system TMPFS # Efficient memory file-system
+file-system TMPFS # Efficient memory file-system
#file-system UDF # experimental - OSTA UDF CD/DVD file-system
options NFSSERVER # Sun NFS-compatible filesystem (server)
@@ -162,10 +162,11 @@ sisfb0 at pci0 dev ? function ?
voyager0 at pci0 dev ? function ? # SM502 on GDIUM
voyagerfb0 at voyager0 # framebuffer portion
iic* at voyager0
-strtc* at iic? addr 0x68 # GDIUM's real time clock
-options STRTC_NO_USERRAM
-lmtemp* at iic? addr 0x48 # GDIUM's temperature sensor
-stvii* at iic? addr 0x40 # GDIUM's onboard microcontroller
+strtc* at iic? addr 0x68 # GDIUM's real time clock
+options STRTC_NO_USERRAM
+lmtemp* at iic? addr 0x48 # GDIUM's temperature sensor
+stvii* at iic? addr 0x40 # GDIUM's onboard microcontroller
+lynxfb0 at pci0 dev ? function ? # SM712 on Yeeloong Notebook
#genfb0 at pci0 dev ? function ?
wsdisplay* at wsemuldisplaydev?
ehci* at pci0 dev ? function ?
@@ -173,17 +174,28 @@ ehci* at pci0 dev ? function ?
ohci* at pci0 dev ? function ?
#options OHCI_DEBUG, USB_DEBUG, UHUB_DEBUG
-gcscpcib* at pci? dev ? function ? # AMD CS5535/CS5536 PCI-ISA w/
-gpio* at gcscpcib? # timecounter, watchdog and GPIO
-isa0 at gcscpcib?
-
-pcib* at pci?
-isa0 at pcib?
+gcscpcib* at pci? dev ? function ? # AMD CS5535/CS5536 PCI-ISA w/
+gpio* at gcscpcib? # timecounter, watchdog and GPIO
+isa0 at gcscpcib?
+
+pcib* at pci?
+isa0 at pcib?
+
+pckbc0 at isa? # PC keyboard controller
+pckbd* at pckbc? # PC keyboard
+pms* at pckbc? # PS/2 mouse for wsmouse
+options PMS_SYNAPTICS_TOUCHPAD # Enable support for Synaptics Touchpads
+options PMS_ELANTECH_TOUCHPAD # Enable support for Elantech Touchpads
+wskbd* at pckbd? console ?
+wsmouse* at pms? mux 0
mcclock* at isa? port 0x70 # mc146818-compatible
com0 at isa? port 0x2f8 irq 3 # Fuloong 2F only
com1 at isa? port 0x3f8 irq 4 # Fuloong 2F only (IR port)
+gcscaudio* at pci?
+audio* at audiobus?
+
pciide* at pci? dev ? function ? flags 0x0000 # GENERIC pciide driver
viaide* at pci? dev ? function ? # VIA/AMD/Nvidia IDE controllers
options WDC_NO_IDS #workaround CS5536+JMH330 interrupt disable bug
@@ -297,6 +309,7 @@ pseudo-device fss # file system snapsh
pseudo-device clockctl # user control of clock subsystem
pseudo-device wsmux # mouse & keyboard multiplexor
+pseudo-device wsfont
#pseudo-device md # memory disk device (ramdisk)
#pseudo-device raid 8 # RAIDframe disk driver
Index: src/sys/arch/evbmips/conf/files.loongson
diff -u src/sys/arch/evbmips/conf/files.loongson:1.2 src/sys/arch/evbmips/conf/files.loongson:1.3
--- src/sys/arch/evbmips/conf/files.loongson:1.2 Thu Sep 1 14:07:36 2011
+++ src/sys/arch/evbmips/conf/files.loongson Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-# $NetBSD: files.loongson,v 1.2 2011/09/01 14:07:36 macallan Exp $
+# $NetBSD: files.loongson,v 1.3 2012/03/02 13:20:57 nonaka Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
@@ -13,7 +13,7 @@ file arch/evbmips/evbmips/interrupt.c
file arch/evbmips/loongson/gdium_machdep.c
file arch/evbmips/loongson/generic2e_machdep.c
file arch/evbmips/loongson/yeeloong_machdep.c
-file arch/evbmips/loongson/isa_machdep.c isa
+file arch/evbmips/loongson/isa_machdep.c isa
file arch/evbmips/loongson/loongson2_machdep.c
file arch/evbmips/loongson/machdep.c
@@ -26,18 +26,19 @@ file dev/md_root.c memory_disk_hooks
include "dev/ata/files.ata"
include "dev/scsipi/files.scsipi"
-include "dev/i2o/files.i2o"
-include "dev/isa/files.isa"
-include "dev/pci/files.pci"
-include "dev/pci/files.agp"
-include "dev/usb/files.usb"
+include "dev/i2o/files.i2o"
+include "dev/isa/files.isa"
+include "dev/pci/files.pci"
+include "dev/pci/files.agp"
+include "dev/usb/files.usb"
include "dev/bluetooth/files.bluetooth"
+include "dev/pckbport/files.pckbport"
device mainbus {[addr = -1] }
attach mainbus at root
-file arch/evbmips/loongson/mainbus.c mainbus
+file arch/evbmips/loongson/mainbus.c mainbus
-file arch/evbmips/loongson/bonito_mainbus.c bonito_mainbus
+file arch/evbmips/loongson/bonito_mainbus.c bonito_mainbus
device cpu
attach cpu at mainbus
@@ -52,8 +53,8 @@ include "arch/mips/conf/files.bonito"
file arch/evbmips/loongson/dev/glx.c bonito & pci
# AMD Geode CS5535/CS5536 PCI-ISA bridge
-device gcscpcib: isabus, sysmon_wdog, gpiobus
-attach gcscpcib at pci with gcscpcib_pci
+device gcscpcib: isabus, sysmon_wdog, gpiobus
+attach gcscpcib at pci with gcscpcib_pci
file arch/evbmips/loongson/dev/gcscpcib_pci.c gcscpcib_pci
file dev/ic/gcscpcib.c gcscpcib
@@ -71,14 +72,14 @@ file arch/evbmips/isa/mcclock_isa.c mcc
# Lemote Yeeloong KB3310B Embedded Controller
device ykbec
attach ykbec at isa
-file arch/evbmips/loongson/dev/kb3310.c ykbec needs-flag
+file arch/evbmips/loongson/dev/kb3310.c ykbec needs-flag
# Gdium ST7 controller
device stvii
attach stvii at iic
-file arch/evbmips/loongson/dev/stvii.c stvii
+file arch/evbmips/loongson/dev/stvii.c stvii
defflag opt_stvii.h STVII_DEBUG
# SM502 OHCI
#attach ohci at voyager with ohci_voyager
-#file arch/loongson/dev/ohci_voyager.c ohci_voyager
+#file arch/loongson/dev/ohci_voyager.c ohci_voyager
Index: src/sys/arch/evbmips/loongson/autoconf.c
diff -u src/sys/arch/evbmips/loongson/autoconf.c:1.1 src/sys/arch/evbmips/loongson/autoconf.c:1.2
--- src/sys/arch/evbmips/loongson/autoconf.c:1.1 Sat Aug 27 13:42:44 2011
+++ src/sys/arch/evbmips/loongson/autoconf.c Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: autoconf.c,v 1.1 2011/08/27 13:42:44 bouyer Exp $ */
+/* $NetBSD: autoconf.c,v 1.2 2012/03/02 13:20:57 nonaka Exp $ */
/*
* Copyright 2002 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.1 2011/08/27 13:42:44 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.2 2012/03/02 13:20:57 nonaka Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -131,4 +131,17 @@ device_register(struct device *dev, void
prop_dictionary_set_uint32(dict, "linebytes", 2048);
prop_dictionary_set_uint32(dict, "address", 0x04000000);
}
+ if (device_is_a(dev, "lynxfb")) {
+ dict = device_properties(dev);
+ /*
+ * this is a hack
+ * is_console and address need to be checked against reality
+ */
+ prop_dictionary_set_bool(dict, "is_console", 1);
+ prop_dictionary_set_uint32(dict, "width", 1024);
+ prop_dictionary_set_uint32(dict, "height", 600);
+ prop_dictionary_set_uint32(dict, "depth", 16);
+ prop_dictionary_set_uint32(dict, "linebytes", 2048);
+ prop_dictionary_set_bool(dict, "swapBR", 1);
+ }
}
Index: src/sys/arch/evbmips/loongson/bonito_mainbus.c
diff -u src/sys/arch/evbmips/loongson/bonito_mainbus.c:1.1 src/sys/arch/evbmips/loongson/bonito_mainbus.c:1.2
--- src/sys/arch/evbmips/loongson/bonito_mainbus.c:1.1 Sat Aug 27 13:42:44 2011
+++ src/sys/arch/evbmips/loongson/bonito_mainbus.c Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: bonito_mainbus.c,v 1.1 2011/08/27 13:42:44 bouyer Exp $ */
+/* $NetBSD: bonito_mainbus.c,v 1.2 2012/03/02 13:20:57 nonaka Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bonito_mainbus.c,v 1.1 2011/08/27 13:42:44 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bonito_mainbus.c,v 1.2 2012/03/02 13:20:57 nonaka Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -70,18 +70,38 @@ bonito_mainbus_attach(device_t parent, d
{
struct pcibus_attach_args pba;
pcireg_t rev;
+ bool compatible;
self->dv_private = __UNCONST(&sys_platform->bonito_config);
/*
+ * Loongson 2F processors do not use a real Bonito64 chip but
+ * their own derivative, which is no longer 100% compatible.
+ * We need to make sure we never try to access an unimplemented
+ * register...
+ */
+ if (loongson_ver >= 0x2f)
+ compatible = false;
+ else
+ compatible = true;
+
+ /*
* There is only one PCI controller on a Loongson chip.
*/
rev = PCI_REVISION(REGVAL(BONITO_PCICLASS));
+ if (compatible) {
+ aprint_normal(": BONITO Memory and PCI controller,"
+ " %s rev. %d.%d\n", BONITO_REV_FPGA(rev) ? "FPGA" : "ASIC",
+ BONITO_REV_MAJOR(rev), BONITO_REV_MINOR(rev));
+ } else {
+ aprint_normal(": Memory and PCI-X controller, rev. %d\n",
+ PCI_REVISION(rev));
+ }
- aprint_normal(": BONITO Memory and PCI controller, %s rev. %d.%d\n",
- BONITO_REV_FPGA(rev) ? "FPGA" : "ASIC",
- BONITO_REV_MAJOR(rev), BONITO_REV_MINOR(rev));
+ /*
+ * Attach PCI bus.
+ */
pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
pba.pba_bus = 0;
Index: src/sys/arch/evbmips/loongson/loongson_bus_defs.h
diff -u src/sys/arch/evbmips/loongson/loongson_bus_defs.h:1.1 src/sys/arch/evbmips/loongson/loongson_bus_defs.h:1.2
--- src/sys/arch/evbmips/loongson/loongson_bus_defs.h:1.1 Sat Aug 27 13:42:45 2011
+++ src/sys/arch/evbmips/loongson/loongson_bus_defs.h Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: loongson_bus_defs.h,v 1.1 2011/08/27 13:42:45 bouyer Exp $ */
+/* $NetBSD: loongson_bus_defs.h,v 1.2 2012/03/02 13:20:57 nonaka Exp $ */
#ifndef _LOONGSON_BUS_H_
#define _LOONGSON_BUS_H_
@@ -16,4 +16,7 @@ extern struct mips_pci_chipset bonito_pc
void bonito_bus_io_init(bus_space_tag_t, void *);
void bonito_bus_mem_init(bus_space_tag_t, void *);
+int bonito_bus_io_legacy_map(void *, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *, int);
+
#endif /* _LOONGSON_BUS_H_ */
Index: src/sys/arch/evbmips/loongson/loongson_bus_io.c
diff -u src/sys/arch/evbmips/loongson/loongson_bus_io.c:1.1 src/sys/arch/evbmips/loongson/loongson_bus_io.c:1.2
--- src/sys/arch/evbmips/loongson/loongson_bus_io.c:1.1 Sat Aug 27 13:42:45 2011
+++ src/sys/arch/evbmips/loongson/loongson_bus_io.c Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: loongson_bus_io.c,v 1.1 2011/08/27 13:42:45 bouyer Exp $ */
+/* $NetBSD: loongson_bus_io.c,v 1.2 2012/03/02 13:20:57 nonaka Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: loongson_bus_io.c,v 1.1 2011/08/27 13:42:45 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: loongson_bus_io.c,v 1.2 2012/03/02 13:20:57 nonaka Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -51,6 +51,7 @@ __KERNEL_RCSID(0, "$NetBSD: loongson_bus
#include <sys/bus.h>
#include <evbmips/loongson/loongson_bus_defs.h>
+#include <evbmips/loongson/autoconf.h>
#define CHIP bonito
#define CHIP_IO /* defined */
@@ -65,3 +66,25 @@ __KERNEL_RCSID(0, "$NetBSD: loongson_bus
#define CHIP_W1_SYS_END(v) ((u_long)BONITO_PCIIO_BASE + 0x000fffffUL)
#include <mips/mips/bus_space_alignstride_chipdep.c>
+
+int
+bonito_bus_io_legacy_map(void *v, bus_addr_t addr, bus_size_t size, int flags,
+ bus_space_handle_t *hp, int acct)
+{
+ const struct legacy_io_range *r;
+ bus_addr_t rend;
+
+ if (addr < BONITO_PCIIO_LEGACY) {
+ r = sys_platform->legacy_io_ranges;
+ if (r == NULL)
+ return (ENXIO);
+
+ rend = addr + size - 1;
+ for (; r->start != 0; r++)
+ if (addr >= r->start && rend <= r->end)
+ break;
+ if (r->end == 0)
+ return (ENXIO);
+ }
+ return __BS(map)(v, addr, size, flags, hp, acct);
+}
Index: src/sys/arch/evbmips/loongson/machdep.c
diff -u src/sys/arch/evbmips/loongson/machdep.c:1.3 src/sys/arch/evbmips/loongson/machdep.c:1.4
--- src/sys/arch/evbmips/loongson/machdep.c:1.3 Tue Sep 20 05:51:34 2011
+++ src/sys/arch/evbmips/loongson/machdep.c Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.3 2011/09/20 05:51:34 macallan Exp $ */
+/* $NetBSD: machdep.c,v 1.4 2012/03/02 13:20:57 nonaka Exp $ */
/*
* Copyright 2001, 2002 Wasabi Systems, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.3 2011/09/20 05:51:34 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.4 2012/03/02 13:20:57 nonaka Exp $");
#include "opt_ddb.h"
#include "opt_execfmt.h"
@@ -133,7 +133,31 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v
#include <mips/bonito/bonitoreg.h>
#include <mips/bonito/bonitovar.h>
#include <mips/pmon/pmon.h>
+
+#include "sisfb.h"
+#if NSISFB > 0
#include <dev/pci/sisfb.h>
+#endif
+
+#include "lynxfb.h"
+#if NLYNXFB > 0
+#include <dev/pci/lynxfbvar.h>
+#endif
+
+#include "pckbc.h"
+#if NPCKBC > 0
+#include <dev/isa/isareg.h>
+#include <dev/ic/i8042reg.h>
+#include <dev/ic/pckbcvar.h>
+#endif
+#include "pckbd.h"
+#include "ukbd.h"
+#if NUKBD > 0
+#include <dev/usb/ukbdvar.h>
+#endif
+#if NPCKBD > 0 || NUKBD > 0
+#include <dev/wscons/wskbdvar.h>
+#endif
#include "com.h"
#if NCOM > 0
@@ -153,8 +177,6 @@ int comconsrate = 0;
#define DPPRINTF(x)
#endif
-#include "sisfb.h"
-
int ex_mallocsafe = 0;
struct extent *loongson_io_ex = NULL;
@@ -480,6 +502,8 @@ mach_init(int32_t argc, int32_t argva, i
loongson_pciide_compat_intr_establish;
DPRINTF(("bonito_bus_io_init "));
bonito_bus_io_init(&bonito_iot, NULL);
+ /* override mapping function */
+ bonito_iot.bs_map = bonito_bus_io_legacy_map;
DPRINTF(("bonito_bus_mem_init\n"));
bonito_bus_mem_init(&bonito_memt, NULL);
@@ -510,13 +534,33 @@ mach_init(int32_t argc, int32_t argva, i
DPRINTF((" id 0x%x; ", reg));
#if NSISFB > 0
if (cn_tab == &pmoncons)
- sisfb_cnattach(&bonito_memt, &bonito_iot, &bonito_pc,
+ sisfb_cnattach(&bonito_memt, &bonito_iot, &bonito_pc,
+ pcitag, reg);
+#endif
+#if NLYNXFB > 0
+ if (cn_tab == &pmoncons)
+ lynxfb_cnattach(&bonito_memt, &bonito_iot, &bonito_pc,
pcitag, reg);
#endif
if (cn_tab == &pmoncons)
- gdium_cnattach(&bonito_memt, &bonito_iot, &bonito_pc,
+ gdium_cnattach(&bonito_memt, &bonito_iot, &bonito_pc,
pcitag, reg);
+ if (cn_tab != &pmoncons)
+ break;
}
+#if NPCKBC > 0 || NUKBD > 0
+ if (cn_tab != &pmoncons) {
+ int rc = ENXIO;
+#if NPCKBC > 0
+ if (rc != 0)
+ rc = pckbc_cnattach(&bonito_iot, IO_KBD, KBCMDP, 0);
+#endif
+#if NUKBD > 0
+ if (rc != 0)
+ rc = ukbd_cnattach();
+#endif
+ }
+#endif /* NPCKBC > 0 || NUKBD > 0 */
DPRINTF(("\n"));
/*
@@ -657,7 +701,6 @@ cpu_startup(void)
* that memory allocation is now safe.
*/
ex_mallocsafe = 1;
-
}
int waittime = -1;
Index: src/sys/arch/evbmips/loongson/yeeloong_machdep.c
diff -u src/sys/arch/evbmips/loongson/yeeloong_machdep.c:1.2 src/sys/arch/evbmips/loongson/yeeloong_machdep.c:1.3
--- src/sys/arch/evbmips/loongson/yeeloong_machdep.c:1.2 Tue Feb 14 21:42:22 2012
+++ src/sys/arch/evbmips/loongson/yeeloong_machdep.c Fri Mar 2 13:20:57 2012
@@ -1,3 +1,4 @@
+/* $NetBSD: yeeloong_machdep.c,v 1.3 2012/03/02 13:20:57 nonaka Exp $ */
/* $OpenBSD: yeeloong_machdep.c,v 1.16 2011/04/15 20:40:06 deraadt Exp $ */
/*
@@ -21,6 +22,9 @@
* (this file really ought to be named lemote_machdep.c by now)
*/
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: yeeloong_machdep.c,v 1.3 2012/03/02 13:20:57 nonaka Exp $");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
@@ -242,8 +246,8 @@ lemote_pci_attach_hook(device_t parent,
struct pcibus_attach_args *pba)
{
pci_chipset_tag_t pc = pba->pba_pc;
- pcireg_t id;
pcitag_t tag;
+ pcireg_t id;
int dev, i;
if (pba->pba_bus != 0)
@@ -264,6 +268,7 @@ lemote_pci_attach_hook(device_t parent,
break;
}
}
+
wrmsr(GCSC_PIC_SHDW, 0);
DPRINTF(("PMON setup picregs:"));
for (i = 0; i < 12; i++) {
@@ -274,6 +279,7 @@ lemote_pci_attach_hook(device_t parent,
DPRINTF(("\n"));
DPRINTF(("intsel 0x%x 0x%x\n", REGVAL8(BONITO_PCIIO_BASE + 0x4d0),
REGVAL8(BONITO_PCIIO_BASE + 0x4d1)));
+
/* setup legacy interrupt controller */
REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff;
REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW1) =
@@ -286,8 +292,7 @@ lemote_pci_attach_hook(device_t parent,
REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff;
/* read ISR by default. */
- REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) =
- OCW3_SELECT | OCW3_RR;
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = OCW3_SELECT | OCW3_RR;
(void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3);
/* reset; program device, four bytes */
@@ -301,8 +306,7 @@ lemote_pci_attach_hook(device_t parent,
/* leave interrupts masked */
REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff;
/* read ISR by default. */
- REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) =
- OCW3_SELECT | OCW3_RR;
+ REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = OCW3_SELECT | OCW3_RR;
(void)REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3);
}
@@ -318,34 +322,33 @@ lemote_intr_map(int dev, int fn, int pin
if (pin == PCI_INTERRUPT_PIN_A) {
*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
(dev - 6));
- return 0;
+ return (0);
}
break;
/* PCI slot */
case 10:
*ihp = BONITO_DIRECT_IRQ(LOONGSON_INTR_PCIA +
(pin - PCI_INTERRUPT_PIN_A));
- return 0;
+ return (0);
/* Geode chip */
case 14:
switch (fn) {
case 1: /* Flash */
*ihp = BONITO_ISA_IRQ(6);
- return 0;
+ return (0);
case 3: /* AC97 */
*ihp = BONITO_ISA_IRQ(9);
- return 0;
+ return (0);
case 4: /* OHCI */
case 5: /* EHCI */
*ihp = BONITO_ISA_IRQ(11);
- return 0;
+ return (0);
}
break;
default:
break;
}
-
- return 1;
+ return (1);
}
/*
@@ -356,6 +359,7 @@ void
lemote_isa_attach_hook(struct device *parent, struct device *self,
struct isabus_attach_args *iba)
{
+
loongson_set_isa_imr(loongson_isaimr);
}
@@ -368,19 +372,20 @@ lemote_isa_intr_establish(void *v, int i
ih = evbmips_intr_establish(BONITO_ISA_IRQ(irq), handler, arg);
if (ih == NULL)
- return NULL;
+ return (NULL);
+
/* enable interrupt */
imr = lemote_get_isa_imr();
imr |= (1 << irq);
- DPRINTF(("lemote_isa_intr_establish: enable irq %d 0x%x\n",
- irq, imr));
+ DPRINTF(("lemote_isa_intr_establish: enable irq %d 0x%x\n", irq, imr));
loongson_set_isa_imr(imr);
- return ih;
+ return (ih);
}
void
lemote_isa_intr_disestablish(void *v, void *ih)
{
+
evbmips_intr_disestablish(ih);
}
@@ -418,59 +423,53 @@ void
lemote_isa_intr(int ipl, vaddr_t pc, uint32_t ipending)
{
#if NISA > 0
- uint32_t isr, imr, mask;
- int bit;
struct evbmips_intrhand *ih;
+ uint32_t isr, imr, mask;
+ int bitno;
int rc;
- //int i;
imr = lemote_get_isa_imr();
isr = lemote_get_isa_isr() & imr;
+ if (isr == 0)
+ return;
/*
* Now process allowed interrupts.
*/
- if (isr != 0) {
- int bitno, ret;
-
- /* Service higher level interrupts first */
- bit = BONITO_NISA - 1;
- for (bitno = bit, mask = 1UL << bitno;
- mask != 0;
- bitno--, mask >>= 1) {
- if ((isr & mask) == 0)
- continue;
- loongson_isa_specific_eoi(bitno);
- rc = 0;
- LIST_FOREACH(ih,
- &bonito_intrhead[BONITO_ISA_IRQ(bitno)].intrhand_head,
- ih_q) {
- ret = (*ih->ih_func)(ih->ih_arg);
- if (ret) {
- rc = 1;
- bonito_intrhead[BONITO_ISA_IRQ(bitno)].intr_count.ev_count++;
- }
+ /* Service higher level interrupts first */
+ for (bitno = BONITO_NISA - 1, mask = 1UL << bitno;
+ mask != 0;
+ bitno--, mask >>= 1) {
+ if ((isr & mask) == 0)
+ continue;
+
+ loongson_isa_specific_eoi(bitno);
+
+ rc = 0;
+ LIST_FOREACH(ih,
+ &bonito_intrhead[BONITO_ISA_IRQ(bitno)].intrhand_head,
+ ih_q) {
+ if ((*ih->ih_func)(ih->ih_arg) != 0) {
+ rc = 1;
+ bonito_intrhead[BONITO_ISA_IRQ(bitno)].intr_count.ev_count++;
}
- if (rc == 0) {
- if (stray_intr[bitno]++ & 0x10000) {
- printf("spurious isa interrupt %d\n",
- bitno);
- stray_intr[bitno] = 0;
- }
+ }
+ if (rc == 0) {
+ if (stray_intr[bitno]++ & 0x10000) {
+ printf("spurious isa interrupt %d\n", bitno);
+ stray_intr[bitno] = 0;
}
-
- if ((isr ^= mask) == 0)
- break;
}
- /*
- * Reenable interrupts which have been serviced.
- */
- loongson_set_isa_imr(imr);
+ if ((isr ^= mask) == 0)
+ break;
}
+ /*
+ * Reenable interrupts which have been serviced.
+ */
+ loongson_set_isa_imr(imr);
#endif
- return;
}
uint
@@ -478,23 +477,23 @@ lemote_get_isa_imr(void)
{
uint imr1, imr2;
- imr1 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + 1);
+ imr1 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1);
imr1 &= ~(1 << 2); /* hide cascade */
- imr2 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + 1);
+ imr2 = 0xff & ~REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1);
- return (imr2 << 8) | imr1;
+ return ((imr2 << 8) | imr1);
}
uint
lemote_get_isa_isr(void)
{
- uint isr1, isr2 = 0;
+ uint isr1, isr2;
isr1 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU1);
- isr1 &= ~(1<<2);
+ isr1 &= ~(1 << 2);
isr2 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU2);
- return (isr1 | (isr2 << 8));
+ return ((isr2 << 8) | isr1);
}
/*
@@ -516,6 +515,7 @@ fuloong_powerdown(void)
void
yeeloong_powerdown(void)
{
+
REGVAL(BONITO_GPIODATA) &= ~0x00000001;
REGVAL(BONITO_GPIOIE) &= ~0x00000001;
}
@@ -523,6 +523,7 @@ yeeloong_powerdown(void)
void
lemote_reset(void)
{
+
wrmsr(GCSC_GLCP_SYS_RST, rdmsr(GCSC_GLCP_SYS_RST) | 1);
}
Index: src/sys/arch/evbmips/loongson/dev/glx.c
diff -u src/sys/arch/evbmips/loongson/dev/glx.c:1.2 src/sys/arch/evbmips/loongson/dev/glx.c:1.3
--- src/sys/arch/evbmips/loongson/dev/glx.c:1.2 Tue Feb 14 22:22:45 2012
+++ src/sys/arch/evbmips/loongson/dev/glx.c Fri Mar 2 13:20:57 2012
@@ -21,7 +21,7 @@
* XXX too many hardcoded numbers... need to expand glxreg.h
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.2 2012/02/14 22:22:45 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.3 2012/03/02 13:20:57 nonaka Exp $");
#include <sys/param.h>
@@ -136,7 +136,6 @@ glx_init(pci_chipset_tag_t pc, pcitag_t
/*
* Route usb and audio
*/
-
msr = 0;
msr |= 11 << 8;
msr |= 9 << 16;
@@ -157,10 +156,17 @@ glx_init(pci_chipset_tag_t pc, pcitag_t
msr |= 1 << 14;
wrmsr(GCSC_PIC_IRQM_PRIM, msr);
+ /*
+ * keyboard and mouse interrupts
+ */
+ msr = 0;
+ msr |= 1 << 1; /* keyboard */
+ msr |= 1 << 12; /* mouse */
+ wrmsr(GCSC_PIC_IRQM_LPC, msr);
+
/* no interrupts from theses */
wrmsr(GCSC_PIC_ZSEL_LOW, 0);
wrmsr(GCSC_PIC_ZSEL_HIGH, 0);
- wrmsr(GCSC_PIC_IRQM_LPC, 0);
DPRINTF(("IO space 0x%" PRIx64 "\n", rdmsr(0x80000014)));
}
@@ -485,7 +491,7 @@ glx_fn2_read(int reg)
data = glx_get_status();
data |= PCI_COMMAND_IO_ENABLE;
msr = rdmsr(GCSC_GLIU_PAE);
- if ((msr & (0x3 << 4)) == 0x03)
+ if ((msr & (0x3 << 4)) == (0x3 << 4))
data |= PCI_COMMAND_MASTER_ENABLE;
break;
case PCI_CLASS_REG:
@@ -612,7 +618,7 @@ glx_fn3_read(int reg)
data = glx_get_status();
data |= PCI_COMMAND_IO_ENABLE;
msr = rdmsr(GCSC_GLIU_PAE);
- if ((msr & (0x3 << 8)) == 0x03)
+ if ((msr & (0x3 << 8)) == (0x3 << 8))
data |= PCI_COMMAND_MASTER_ENABLE;
break;
case PCI_CLASS_REG:
Index: src/sys/dev/pci/files.pci
diff -u src/sys/dev/pci/files.pci:1.355 src/sys/dev/pci/files.pci:1.356
--- src/sys/dev/pci/files.pci:1.355 Thu Feb 16 17:33:28 2012
+++ src/sys/dev/pci/files.pci Fri Mar 2 13:20:57 2012
@@ -1,4 +1,4 @@
-# $NetBSD: files.pci,v 1.355 2012/02/16 17:33:28 macallan Exp $
+# $NetBSD: files.pci,v 1.356 2012/03/02 13:20:57 nonaka Exp $
#
# Config file and device description for machine-independent PCI code.
# Included by ports that need it. Requires that the SCSI files be
@@ -1102,3 +1102,8 @@ file dev/pci/viomb.c viomb
device vioif
attach vioif at virtio
file dev/pci/if_vioif.c vioif
+
+# Silicon Motion SM712(LynxEM+) frame buffer
+device lynxfb: wsemuldisplaydev, rasops16
+attach lynxfb at pci
+file dev/pci/lynxfb.c lynxfb needs-flag
Added files:
Index: src/sys/dev/pci/lynxfb.c
diff -u /dev/null src/sys/dev/pci/lynxfb.c:1.1
--- /dev/null Fri Mar 2 13:20:57 2012
+++ src/sys/dev/pci/lynxfb.c Fri Mar 2 13:20:57 2012
@@ -0,0 +1,808 @@
+/* $NetBSD: lynxfb.c,v 1.1 2012/03/02 13:20:57 nonaka Exp $ */
+/* $OpenBSD: smfb.c,v 1.13 2011/07/21 20:36:12 miod Exp $ */
+
+/*
+ * Copyright (c) 2012 NONAKA Kimihiro <[email protected]>
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * SiliconMotion SM712 frame buffer driver.
+ *
+ * Assumes its video output is an LCD panel, in 5:6:5 mode, and fixed
+ * 1024x600 resolution, depending on the system model.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: lynxfb.c,v 1.1 2012/03/02 13:20:57 nonaka Exp $");
+
+#include "opt_wsemul.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/endian.h>
+
+#include <sys/bus.h>
+
+#include <dev/ic/vgareg.h>
+#include <dev/isa/isareg.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pciio.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+#include <dev/wscons/wsdisplay_vconsvar.h>
+#include <dev/pci/wsdisplay_pci.h>
+
+#include <dev/pci/lynxfbreg.h>
+#include <dev/pci/lynxfbvar.h>
+
+#ifndef LYNXFB_DEFAULT_WIDTH
+#define LYNXFB_DEFAULT_WIDTH 1024
+#endif
+#ifndef LYNXFB_DEFAULT_HEIGHT
+#define LYNXFB_DEFAULT_HEIGHT 600
+#endif
+#ifndef LYNXFB_DEFAULT_DEPTH
+#define LYNXFB_DEFAULT_DEPTH 16
+#endif
+#ifndef LYNXFB_DEFAULT_STRIDE
+#define LYNXFB_DEFAULT_STRIDE 0
+#endif
+#ifndef LYNXFB_DEFAULT_FLAGS
+#ifdef __MIPSEL__
+#define LYNXFB_DEFAULT_FLAGS LYNXFB_FLAG_SWAPBR
+#else
+#define LYNXFB_DEFAULT_FLAGS 0
+#endif
+#endif
+
+struct lynxfb_softc;
+
+/* minimal frame buffer information, suitable for early console */
+struct lynxfb {
+ struct lynxfb_softc *sc;
+ void *fbaddr;
+
+ bus_space_tag_t memt;
+ bus_space_handle_t memh;
+
+ /* DPR registers */
+ bus_space_tag_t dprt;
+ bus_space_handle_t dprh;
+ /* MMIO space */
+ bus_space_tag_t mmiot;
+ bus_space_handle_t mmioh;
+
+ struct vcons_screen vcs;
+ struct wsscreen_descr wsd;
+
+ int width, height, depth, stride;
+ int accel;
+ int blank;
+
+ /* LYNXFB_FLAG_* */
+ int flags;
+#define LYNXFB_FLAG_SWAPBR (1 << 0)
+};
+
+#define DPR_READ(fb, reg) \
+ bus_space_read_4((fb)->memt, (fb)->dprh, (reg))
+#define DPR_WRITE(fb, reg, val) \
+ bus_space_write_4((fb)->memt, (fb)->dprh, (reg), (val))
+
+struct lynxfb_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_memt;
+ bus_space_handle_t sc_memh;
+
+ pci_chipset_tag_t sc_pc;
+ pcitag_t sc_pcitag;
+
+ struct lynxfb *sc_fb;
+ struct lynxfb sc_fb_store;
+
+ struct vcons_data sc_vd;
+ struct wsscreen_list sc_screenlist;
+ const struct wsscreen_descr *sc_screens[1];
+ int sc_mode;
+};
+
+static int lynxfb_match_by_id(pcireg_t);
+static int lynxfb_match(device_t, cfdata_t, void *);
+static void lynxfb_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(lynxfb, sizeof(struct lynxfb_softc),
+ lynxfb_match, lynxfb_attach, NULL, NULL);
+
+static int lynxfb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
+static paddr_t lynxfb_mmap(void *, void *, off_t, int);
+
+static struct wsdisplay_accessops lynxfb_accessops = {
+ lynxfb_ioctl,
+ lynxfb_mmap,
+ NULL, /* alloc_screen */
+ NULL, /* free_screen */
+ NULL, /* show_screen */
+ NULL, /* load_font */
+ NULL, /* pollc */
+ NULL, /* scroll */
+};
+
+static bool lynxfb_is_console(struct lynxfb_softc *, pcitag_t);
+static void lynxfb_init_screen(void *, struct vcons_screen *, int, long *);
+static int lynxfb_setup(struct lynxfb *);
+
+static int lynxfb_wait(struct lynxfb *);
+static void lynxfb_copyrect(struct lynxfb *, int, int, int, int, int, int);
+static void lynxfb_fillrect(struct lynxfb *, int, int, int, int, int);
+static void lynxfb_copyrows(void *, int, int, int);
+static void lynxfb_copycols(void *, int, int, int, int);
+static void lynxfb_erasecols(void *, int, int, int, long);
+static void lynxfb_eraserows(void *, int, int, long);
+static void lynxfb_vcons_copyrows(void *, int, int, int);
+static void lynxfb_vcons_copycols(void *, int, int, int, int);
+static void lynxfb_vcons_erasecols(void *, int, int, int, long);
+static void lynxfb_vcons_eraserows(void *, int, int, long);
+static void lynxfb_blank(struct lynxfb *, int);
+
+static struct {
+ bool is_console;
+ pcitag_t tag;
+ bus_space_tag_t memt;
+ bus_space_handle_t memh;
+ struct lynxfb fb;
+} lynxfb_console;
+
+int lynxfb_default_width = LYNXFB_DEFAULT_WIDTH;
+int lynxfb_default_height = LYNXFB_DEFAULT_HEIGHT;
+int lynxfb_default_depth = LYNXFB_DEFAULT_DEPTH;
+int lynxfb_default_stride = LYNXFB_DEFAULT_STRIDE;
+int lynxfb_default_flags = LYNXFB_DEFAULT_FLAGS;
+
+static int
+lynxfb_match_by_id(pcireg_t id)
+{
+
+ if (PCI_VENDOR(id) != PCI_VENDOR_SILMOTION)
+ return (0);
+ if (PCI_PRODUCT(id) != PCI_PRODUCT_SILMOTION_SM712)
+ return (0);
+ return (1);
+}
+
+int
+lynxfb_cnattach(bus_space_tag_t memt, bus_space_tag_t iot, pci_chipset_tag_t pc,
+ pcitag_t tag, pcireg_t id)
+{
+ struct rasops_info *ri = &lynxfb_console.fb.vcs.scr_ri;
+ struct lynxfb *fb;
+ bus_space_handle_t memh;
+ bus_addr_t base;
+ bus_size_t size;
+ long defattr;
+ int mapflags;
+ int error;
+
+ if (!lynxfb_match_by_id(id))
+ return (ENODEV);
+
+ if (pci_mapreg_info(pc, tag, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM,
+ &base, &size, &mapflags))
+ return (EINVAL);
+ error = bus_space_map(memt, base, size, BUS_SPACE_MAP_LINEAR | mapflags,
+ &memh);
+ if (error)
+ return (error);
+
+ fb = &lynxfb_console.fb;
+ fb->memt = memt;
+ fb->memh = memh;
+ fb->width = lynxfb_default_width;
+ fb->height = lynxfb_default_height;
+ fb->depth = lynxfb_default_depth;
+ fb->stride = lynxfb_default_stride;
+ if (fb->stride == 0)
+ fb->stride = fb->width * fb->depth / 8;
+ fb->flags = lynxfb_default_flags;
+ error = lynxfb_setup(fb);
+ if (error) {
+ bus_space_unmap(memt, memh, size);
+ return (error);
+ }
+
+ lynxfb_console.is_console = true;
+ lynxfb_console.tag = tag;
+ (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
+ wsdisplay_preattach(&fb->wsd, ri, 0, 0, defattr);
+
+ return (0);
+}
+
+static bool
+lynxfb_is_console(struct lynxfb_softc *sc, pcitag_t tag)
+{
+
+ return (lynxfb_console.is_console &&
+ !memcmp(&lynxfb_console.tag, &tag, sizeof(tag)));
+}
+
+static int
+lynxfb_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 (!lynxfb_match_by_id(pa->pa_id))
+ return (0);
+ return (1);
+}
+
+static void
+lynxfb_attach(device_t parent, device_t self, void *aux)
+{
+ struct lynxfb_softc *sc = device_private(self);
+ struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+ struct wsemuldisplaydev_attach_args waa;
+ struct lynxfb *fb;
+ struct rasops_info *ri;
+ prop_dictionary_t dict;
+ bus_size_t size;
+ long defattr;
+ bool is_console;
+
+ sc->sc_dev = self;
+ sc->sc_pc = pa->pa_pc;
+ sc->sc_pcitag = pa->pa_tag;
+
+ pci_aprint_devinfo(pa, NULL);
+
+ is_console = lynxfb_is_console(sc, sc->sc_pcitag);
+
+ fb = is_console ? &lynxfb_console.fb : &sc->sc_fb_store;
+ sc->sc_fb = fb;
+ fb->sc = sc;
+
+ if (!is_console) {
+ if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM,
+ BUS_SPACE_MAP_LINEAR, &fb->memt, &fb->memh, NULL, &size)) {
+ aprint_error_dev(self, "can't map frame buffer\n");
+ return;
+ }
+
+ dict = device_properties(self);
+ if (!prop_dictionary_get_uint32(dict, "width", &fb->width))
+ fb->width = lynxfb_default_width;
+ if (!prop_dictionary_get_uint32(dict, "height", &fb->height))
+ fb->height = lynxfb_default_height;
+ if (!prop_dictionary_get_uint32(dict, "depth", &fb->depth))
+ fb->depth = lynxfb_default_depth;
+ if (!prop_dictionary_get_uint32(dict, "linebytes", &fb->stride)) {
+ if (lynxfb_default_stride == 0)
+ fb->stride = fb->width * fb->depth / 8;
+ else
+ fb->stride = lynxfb_default_stride;
+ }
+ if (!prop_dictionary_get_uint32(dict, "flags", &fb->flags))
+ fb->flags = lynxfb_default_flags;
+
+ if (lynxfb_setup(fb)) {
+ aprint_error_dev(self, "can't setup frame buffer\n");
+ bus_space_unmap(fb->memt, fb->memh, size);
+ return;
+ }
+ }
+ sc->sc_memt = fb->memt;
+ sc->sc_memh = fb->memh;
+
+ aprint_normal_dev(self, "%d x %d, %d bpp, stride %d\n", fb->width,
+ fb->height, fb->depth, fb->stride);
+
+ fb->wsd = (struct wsscreen_descr) {
+ "default",
+ 0, 0,
+ NULL,
+ 8, 16,
+ WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
+ NULL,
+ };
+ sc->sc_screens[0] = &fb->wsd;
+ sc->sc_screenlist = (struct wsscreen_list){ 1, sc->sc_screens };
+ sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
+
+ vcons_init(&sc->sc_vd, sc, &fb->wsd, &lynxfb_accessops);
+ sc->sc_vd.init_screen = lynxfb_init_screen;
+
+ ri = &fb->vcs.scr_ri;
+ if (is_console) {
+ vcons_init_screen(&sc->sc_vd, &fb->vcs, 1, &defattr);
+ fb->vcs.scr_flags |= VCONS_SCREEN_IS_STATIC;
+
+ fb->wsd.textops = &ri->ri_ops;
+ fb->wsd.capabilities = ri->ri_caps;
+ fb->wsd.nrows = ri->ri_rows;
+ fb->wsd.ncols = ri->ri_cols;
+ wsdisplay_cnattach(&fb->wsd, ri, 0, 0, defattr);
+ vcons_replay_msgbuf(&fb->vcs);
+ } else {
+ /*
+ * since we're not the console we can postpone the rest
+ * until someone actually allocates a screen for us
+ */
+ (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
+ }
+
+ waa.console = is_console;
+ waa.scrdata = &sc->sc_screenlist;
+ waa.accessops = &lynxfb_accessops;
+ waa.accesscookie = &sc->sc_vd;
+
+ config_found(self, &waa, wsemuldisplaydevprint);
+}
+
+/*
+ * vga sequencer access through MMIO space
+ */
+static __inline uint8_t
+lynxfb_vgats_read(struct lynxfb *fb, uint regno)
+{
+
+ bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_INDEX, regno);
+ return bus_space_read_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_DATA);
+}
+
+static __inline void
+lynxfb_vgats_write(struct lynxfb *fb, uint regno, uint8_t value)
+{
+
+ bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_INDEX, regno);
+ bus_space_write_1(fb->mmiot, fb->mmioh, IO_VGA + VGA_TS_DATA, value);
+}
+
+/*
+ * wsdisplay accesops
+ */
+static int
+lynxfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flags,
+ struct lwp *l)
+{
+ struct vcons_data *vd = v;
+ struct lynxfb_softc *sc = vd->cookie;
+ struct lynxfb *fb = sc->sc_fb;
+ struct vcons_screen *ms = vd->active;
+ struct wsdisplay_fbinfo *wdf;
+ struct wsdisplay_param *param;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(uint *)data = WSDISPLAY_TYPE_PCIMISC;
+ return (0);
+
+ /* PCI config read/write passthrough. */
+ case PCI_IOC_CFGREAD:
+ case PCI_IOC_CFGWRITE:
+ return pci_devioctl(sc->sc_pc, sc->sc_pcitag,
+ cmd, data, flags, l);
+
+ case WSDISPLAYIO_GET_BUSID:
+ return wsdisplayio_busid_pci(device_parent(sc->sc_dev),
+ sc->sc_pc, sc->sc_pcitag, data);
+
+ case WSDISPLAYIO_GINFO:
+ if (ms == NULL)
+ return (ENODEV);
+ wdf = (struct wsdisplay_fbinfo *)data;
+ wdf->width = ms->scr_ri.ri_width;
+ wdf->height = ms->scr_ri.ri_height;
+ wdf->depth = ms->scr_ri.ri_depth;
+ wdf->cmsize = 0;
+ return (0);
+
+ case WSDISPLAYIO_LINEBYTES:
+ *(uint *)data = fb->stride;
+ return (0);
+
+ case WSDISPLAYIO_GVIDEO:
+ *(int *)data = fb->blank ? WSDISPLAYIO_VIDEO_OFF :
+ WSDISPLAYIO_VIDEO_ON;
+ return (0);
+
+ case WSDISPLAYIO_SVIDEO:
+ lynxfb_blank(fb, *(int *)data);
+ return (0);
+
+ case WSDISPLAYIO_GETPARAM:
+ param = (struct wsdisplay_param *)data;
+ switch (param->param) {
+ case WSDISPLAYIO_PARAM_BACKLIGHT:
+ param->min = 0;
+ param->max = 1;
+ param->curval = fb->blank;
+ return (0);
+ }
+ break;
+
+ case WSDISPLAYIO_SETPARAM:
+ param = (struct wsdisplay_param *)data;
+ switch (param->param) {
+ case WSDISPLAYIO_PARAM_BACKLIGHT:
+ lynxfb_blank(fb, param->curval);
+ return (0);
+ }
+ break;
+ }
+ return (EPASSTHROUGH);
+}
+
+static paddr_t
+lynxfb_mmap(void *v, void *vs, off_t offset, int prot)
+{
+ struct vcons_data *vd = v;
+ struct lynxfb_softc *sc = vd->cookie;
+ struct rasops_info *ri = &sc->sc_fb->vcs.scr_ri;
+
+ if ((offset & PAGE_MASK) != 0)
+ return (-1);
+
+ if (offset < 0 || offset >= ri->ri_stride * ri->ri_height)
+ return (-1);
+
+ return bus_space_mmap(sc->sc_memt, offset, 0, prot,
+ BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
+}
+
+static void
+lynxfb_init_screen(void *cookie, struct vcons_screen *scr,
+ int existing, long *defattr)
+{
+ struct lynxfb_softc *sc = cookie;
+ struct lynxfb *fb = sc->sc_fb;
+ struct rasops_info *ri = &scr->scr_ri;
+
+ ri->ri_width = fb->width;
+ ri->ri_height = fb->height;
+ ri->ri_depth = fb->depth;
+ ri->ri_stride = fb->stride;
+ ri->ri_flg = RI_CENTER;
+ ri->ri_bits = fb->fbaddr;
+
+#ifdef VCONS_DRAW_INTR
+ scr->scr_flags |= VCONS_DONT_READ;
+#endif
+
+ if (existing)
+ ri->ri_flg |= RI_CLEAR;
+
+ rasops_init(ri, 0, 0);
+ ri->ri_caps = WSSCREEN_WSCOLORS;
+ rasops_reconfig(ri, fb->height / ri->ri_font->fontheight,
+ fb->width / ri->ri_font->fontwidth);
+
+ ri->ri_hw = scr;
+
+ if (fb->accel) {
+ ri->ri_ops.copycols = lynxfb_vcons_copycols;
+ ri->ri_ops.copyrows = lynxfb_vcons_copyrows;
+ ri->ri_ops.erasecols = lynxfb_vcons_erasecols;
+ ri->ri_ops.eraserows = lynxfb_vcons_eraserows;
+ }
+}
+
+/*
+ * Frame buffer initialization.
+ */
+static int
+lynxfb_setup(struct lynxfb *fb)
+{
+ struct rasops_info *ri = &fb->vcs.scr_ri;
+ int error;
+
+ fb->dprt = fb->memt;
+ error = bus_space_subregion(fb->memt, fb->memh, SM7XX_DPR_BASE,
+ SMXXX_DPR_SIZE, &fb->dprh);
+ if (error != 0)
+ return (error);
+
+ fb->mmiot = fb->memt;
+ error = bus_space_subregion(fb->mmiot, fb->memh, SM7XX_MMIO_BASE,
+ SM7XX_MMIO_SIZE, &fb->mmioh);
+ if (error != 0)
+ return (error);
+
+ ri->ri_width = fb->width;
+ ri->ri_height = fb->height;
+ ri->ri_depth = fb->depth;
+ ri->ri_stride = fb->stride;
+ ri->ri_flg = RI_CENTER | RI_CLEAR | RI_NO_AUTO;
+ fb->fbaddr = ri->ri_bits = (void *)bus_space_vaddr(fb->memt, fb->memh);
+ ri->ri_hw = fb;
+
+ if (fb->flags & LYNXFB_FLAG_SWAPBR) {
+ switch (fb->depth) {
+ case 16:
+ ri->ri_rnum = 5;
+ ri->ri_rpos = 11;
+ ri->ri_gnum = 6;
+ ri->ri_gpos = 5;
+ ri->ri_bnum = 5;
+ ri->ri_bpos = 0;
+ break;
+ }
+ }
+
+ rasops_init(ri, 0, 0);
+ rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight,
+ ri->ri_width / ri->ri_font->fontwidth);
+
+ fb->wsd.name = "std";
+ fb->wsd.ncols = ri->ri_cols;
+ fb->wsd.nrows = ri->ri_rows;
+ fb->wsd.textops = &ri->ri_ops;
+ fb->wsd.fontwidth = ri->ri_font->fontwidth;
+ fb->wsd.fontheight = ri->ri_font->fontheight;
+ fb->wsd.capabilities = ri->ri_caps;
+
+ /*
+ * Setup 2D acceleration whenever possible
+ */
+ if (lynxfb_wait(fb) == 0) {
+ fb->accel = 1;
+
+ DPR_WRITE(fb, DPR_CROP_TOPLEFT_COORDS, DPR_COORDS(0, 0));
+ /* use of width both times is intentional */
+ DPR_WRITE(fb, DPR_PITCH,
+ DPR_COORDS(ri->ri_width, ri->ri_width));
+ DPR_WRITE(fb, DPR_SRC_WINDOW,
+ DPR_COORDS(ri->ri_width, ri->ri_width));
+ DPR_WRITE(fb, DPR_BYTE_BIT_MASK, 0xffffffff);
+ DPR_WRITE(fb, DPR_COLOR_COMPARE_MASK, 0);
+ DPR_WRITE(fb, DPR_COLOR_COMPARE, 0);
+ DPR_WRITE(fb, DPR_SRC_BASE, 0);
+ DPR_WRITE(fb, DPR_DST_BASE, 0);
+ DPR_READ(fb, DPR_DST_BASE);
+
+ ri->ri_ops.copycols = lynxfb_copycols;
+ ri->ri_ops.copyrows = lynxfb_copyrows;
+ ri->ri_ops.erasecols = lynxfb_erasecols;
+ ri->ri_ops.eraserows = lynxfb_eraserows;
+ }
+
+ return (0);
+}
+
+static int
+lynxfb_wait(struct lynxfb *fb)
+{
+ uint32_t reg;
+ int i;
+
+ for (i = 10000; i > 0; i--) {
+ reg = lynxfb_vgats_read(fb, 0x16);
+ if ((reg & 0x18) == 0x10)
+ return (0);
+ delay(1);
+ }
+ return (EBUSY);
+}
+
+static void
+lynxfb_copyrect(struct lynxfb *fb, int sx, int sy, int dx, int dy, int w, int h)
+{
+ uint32_t dir;
+
+ /* Compute rop direction */
+ if (sy < dy || (sy == dy && sx <= dx)) {
+ sx += w - 1;
+ dx += w - 1;
+ sy += h - 1;
+ dy += h - 1;
+ dir = DE_CTRL_RTOL;
+ } else
+ dir = 0;
+
+ DPR_WRITE(fb, DPR_SRC_COORDS, DPR_COORDS(sx, sy));
+ DPR_WRITE(fb, DPR_DST_COORDS, DPR_COORDS(dx, dy));
+ DPR_WRITE(fb, DPR_SPAN_COORDS, DPR_COORDS(w, h));
+ DPR_WRITE(fb, DPR_DE_CTRL, DE_CTRL_START | DE_CTRL_ROP_ENABLE | dir |
+ (DE_CTRL_COMMAND_BITBLT << DE_CTRL_COMMAND_SHIFT) |
+ (DE_CTRL_ROP_SRC << DE_CTRL_ROP_SHIFT));
+ DPR_READ(fb, DPR_DE_CTRL);
+
+ lynxfb_wait(fb);
+}
+
+static void
+lynxfb_fillrect(struct lynxfb *fb, int x, int y, int w, int h, int bg)
+{
+ struct rasops_info *ri = &fb->vcs.scr_ri;
+
+ DPR_WRITE(fb, DPR_FG_COLOR, ri->ri_devcmap[bg]);
+ DPR_WRITE(fb, DPR_DST_COORDS, DPR_COORDS(x, y));
+ DPR_WRITE(fb, DPR_SPAN_COORDS, DPR_COORDS(w, h));
+ DPR_WRITE(fb, DPR_DE_CTRL, DE_CTRL_START | DE_CTRL_ROP_ENABLE |
+ (DE_CTRL_COMMAND_SOLIDFILL << DE_CTRL_COMMAND_SHIFT) |
+ (DE_CTRL_ROP_SRC << DE_CTRL_ROP_SHIFT));
+ DPR_READ(fb, DPR_DE_CTRL);
+
+ lynxfb_wait(fb);
+}
+
+static inline void
+lynxfb_copyrows1(struct rasops_info *ri, int src, int dst, int num,
+ struct lynxfb *fb)
+{
+ struct wsdisplay_font *f = ri->ri_font;
+
+ num *= f->fontheight;
+ src *= f->fontheight;
+ dst *= f->fontheight;
+
+ lynxfb_copyrect(fb, ri->ri_xorigin, ri->ri_yorigin + src,
+ ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
+}
+
+static inline void
+lynxfb_copycols1(struct rasops_info *ri, int row, int src, int dst, int num,
+ struct lynxfb *fb)
+{
+ struct wsdisplay_font *f = ri->ri_font;
+
+ num *= f->fontwidth;
+ src *= f->fontwidth;
+ dst *= f->fontwidth;
+ row *= f->fontheight;
+
+ lynxfb_copyrect(fb, ri->ri_xorigin + src, ri->ri_yorigin + row,
+ ri->ri_xorigin + dst, ri->ri_yorigin + row, num, f->fontheight);
+}
+
+static inline void
+lynxfb_erasecols1(struct rasops_info *ri, int row, int col, int num, long attr,
+ struct lynxfb *fb)
+{
+ struct wsdisplay_font *f = ri->ri_font;
+ int32_t bg, fg, ul;
+
+ row *= f->fontheight;
+ col *= f->fontwidth;
+ num *= f->fontwidth;
+ rasops_unpack_attr(attr, &fg, &bg, &ul);
+
+ lynxfb_fillrect(fb, ri->ri_xorigin + col, ri->ri_yorigin + row,
+ num, f->fontheight, bg);
+}
+
+static inline void
+lynxfb_eraserows1(struct rasops_info *ri, int row, int num, long attr,
+ struct lynxfb *fb)
+{
+ struct wsdisplay_font *f = ri->ri_font;
+ int32_t bg, fg, ul;
+ int x, y, w;
+
+ if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
+ num = ri->ri_height;
+ x = y = 0;
+ w = ri->ri_width;
+ } else {
+ num *= f->fontheight;
+ x = ri->ri_xorigin;
+ y = ri->ri_yorigin + row * f->fontheight;
+ w = ri->ri_emuwidth;
+ }
+ rasops_unpack_attr(attr, &fg, &bg, &ul);
+ lynxfb_fillrect(fb, x, y, w, num, bg);
+}
+
+static void
+lynxfb_copyrows(void *cookie, int src, int dst, int num)
+{
+ struct rasops_info *ri = cookie;
+ struct lynxfb *fb = ri->ri_hw;
+
+ lynxfb_copyrows1(ri, src, dst, num, fb);
+}
+
+static void
+lynxfb_copycols(void *cookie, int row, int src, int dst, int num)
+{
+ struct rasops_info *ri = cookie;
+ struct lynxfb *fb = ri->ri_hw;
+
+ lynxfb_copycols1(ri, row, src, dst, num, fb);
+}
+
+static void
+lynxfb_erasecols(void *cookie, int row, int col, int num, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct lynxfb *fb = ri->ri_hw;
+
+ lynxfb_erasecols1(ri, row, col, num, attr, fb);
+}
+
+static void
+lynxfb_eraserows(void *cookie, int row, int num, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct lynxfb *fb = ri->ri_hw;
+
+ lynxfb_eraserows1(ri, row, num, attr, fb);
+}
+
+static void
+lynxfb_vcons_copyrows(void *cookie, int src, int dst, int num)
+{
+ struct rasops_info *ri = cookie;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct lynxfb_softc *sc = scr->scr_cookie;
+ struct lynxfb *fb = sc->sc_fb;
+
+ lynxfb_copyrows1(ri, src, dst, num, fb);
+}
+
+static void
+lynxfb_vcons_copycols(void *cookie, int row, int src, int dst, int num)
+{
+ struct rasops_info *ri = cookie;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct lynxfb_softc *sc = scr->scr_cookie;
+ struct lynxfb *fb = sc->sc_fb;
+
+ lynxfb_copycols1(ri, row, src, dst, num, fb);
+}
+
+static void
+lynxfb_vcons_erasecols(void *cookie, int row, int col, int num, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct lynxfb_softc *sc = scr->scr_cookie;
+ struct lynxfb *fb = sc->sc_fb;
+
+ lynxfb_erasecols1(ri, row, col, num, attr, fb);
+}
+
+static void
+lynxfb_vcons_eraserows(void *cookie, int row, int num, long attr)
+{
+ struct rasops_info *ri = cookie;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct lynxfb_softc *sc = scr->scr_cookie;
+ struct lynxfb *fb = sc->sc_fb;
+
+ lynxfb_eraserows1(ri, row, num, attr, fb);
+}
+
+static void
+lynxfb_blank(struct lynxfb *fb, int blank)
+{
+
+ fb->blank = blank;
+ if (!blank) {
+ lynxfb_vgats_write(fb, 0x31,
+ lynxfb_vgats_read(fb, 0x31) | 0x01);
+ } else {
+ lynxfb_vgats_write(fb, 0x21,
+ lynxfb_vgats_read(fb, 0x21) | 0x30);
+ lynxfb_vgats_write(fb, 0x31,
+ lynxfb_vgats_read(fb, 0x31) & ~0x01);
+ }
+}
Index: src/sys/dev/pci/lynxfbreg.h
diff -u /dev/null src/sys/dev/pci/lynxfbreg.h:1.1
--- /dev/null Fri Mar 2 13:20:57 2012
+++ src/sys/dev/pci/lynxfbreg.h Fri Mar 2 13:20:57 2012
@@ -0,0 +1,74 @@
+/* $NetBSD: lynxfbreg.h,v 1.1 2012/03/02 13:20:57 nonaka Exp $ */
+/* $OpenBSD: smfbreg.h,v 1.5 2010/08/27 12:48:54 miod Exp $ */
+
+/*
+ * Copyright (c) 2009, 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.
+ */
+
+/*
+ * Silicon Motion SM712 registers
+ */
+
+/*
+ * DPR (2D drawing engine)
+ */
+
+#define DPR_COORDS(x, y) (((x) << 16) | (y))
+
+#define SM7XX_DPR_BASE 0x00408000
+#define SMXXX_DPR_SIZE 0x00004000
+
+#define DPR_SRC_COORDS 0x00
+#define DPR_DST_COORDS 0x04
+#define DPR_SPAN_COORDS 0x08
+#define DPR_DE_CTRL 0x0c
+#define DPR_PITCH 0x10
+#define DPR_FG_COLOR 0x14
+#define DPR_BG_COLOR 0x18
+#define DPR_STRETCH 0x1c
+#define DPR_COLOR_COMPARE 0x20
+#define DPR_COLOR_COMPARE_MASK 0x24
+#define DPR_BYTE_BIT_MASK 0x28
+#define DPR_CROP_TOPLEFT_COORDS 0x2c
+#define DPR_CROP_BOTRIGHT_COORDS 0x30
+#define DPR_MONO_PATTERN_LO32 0x34
+#define DPR_MONO_PATTERN_HI32 0x38
+#define DPR_SRC_WINDOW 0x3c
+#define DPR_SRC_BASE 0x40
+#define DPR_DST_BASE 0x44
+
+#define DE_CTRL_START 0x80000000
+#define DE_CTRL_RTOL 0x08000000
+#define DE_CTRL_COMMAND_MASK 0x001f0000
+#define DE_CTRL_COMMAND_SHIFT 16
+#define DE_CTRL_COMMAND_BITBLT 0x00
+#define DE_CTRL_COMMAND_SOLIDFILL 0x01
+#define DE_CTRL_ROP_ENABLE 0x00008000
+#define DE_CTRL_ROP_MASK 0x000000ff
+#define DE_CTRL_ROP_SHIFT 0
+#define DE_CTRL_ROP_SRC 0x0c
+
+/*
+ * VPR (Video Parameter Registers)
+ */
+
+#define SM7XX_VPR_BASE 0x0040c000
+
+/*
+ * MMIO (SM7XX only)
+ */
+
+#define SM7XX_MMIO_BASE 0x00700000
+#define SM7XX_MMIO_SIZE 0x00004000
Index: src/sys/dev/pci/lynxfbvar.h
diff -u /dev/null src/sys/dev/pci/lynxfbvar.h:1.1
--- /dev/null Fri Mar 2 13:20:57 2012
+++ src/sys/dev/pci/lynxfbvar.h Fri Mar 2 13:20:57 2012
@@ -0,0 +1,29 @@
+/* $NetBSD: lynxfbvar.h,v 1.1 2012/03/02 13:20:57 nonaka Exp $ */
+
+/*-
+ * Copyright (C) 2012 NONAKA Kimihiro <[email protected]>
+ * 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.
+ */
+
+int lynxfb_cnattach(bus_space_tag_t, bus_space_tag_t, pci_chipset_tag_t pc,
+ pcitag_t, pcireg_t);