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 <non...@netbsd.org> + * 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 <non...@netbsd.org> + * 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);