Added Lemote Yeeloong Notebook support.

This commit is contained in:
nonaka 2012-03-02 13:20:57 +00:00
parent a4373e9a91
commit ccf5af0f11
13 changed files with 1148 additions and 109 deletions

View File

@ -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 Ridge file system
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?
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?
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 snapshot device
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

View File

@ -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 mcclock_isa
# 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

View File

@ -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 *aux)
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);
}
}

View File

@ -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, device_t self, void *aux)
{
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;

View File

@ -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 tag, int dev)
/*
* 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 tag, int dev)
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:

View File

@ -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_ */

View File

@ -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_io.c,v 1.1 2011/08/27 13:42:45 bouyer E
#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_io.c,v 1.1 2011/08/27 13:42:45 bouyer E
#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);
}

View File

@ -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 1.3 2011/09/20 05:51:34 macallan Exp $")
#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, int32_t enva, int32_t callvec,
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, int32_t enva, int32_t callvec,
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;

View File

@ -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, device_t self,
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, device_t self,
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, device_t self,
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, device_t self,
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, device_t self,
/* 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, pci_intr_handle_t *ihp)
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 irq, int type, int level,
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 */
for (bitno = BONITO_NISA - 1, mask = 1UL << bitno;
mask != 0;
bitno--, mask >>= 1) {
if ((isr & mask) == 0)
continue;
/* 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++;
}
}
if (rc == 0) {
if (stray_intr[bitno]++ & 0x10000) {
printf("spurious isa interrupt %d\n",
bitno);
stray_intr[bitno] = 0;
}
}
loongson_isa_specific_eoi(bitno);
if ((isr ^= mask) == 0)
break;
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;
}
}
/*
* 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);
}

View File

@ -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

808
sys/dev/pci/lynxfb.c Normal file
View File

@ -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 <nonaka@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);
}
}

74
sys/dev/pci/lynxfbreg.h Normal file
View File

@ -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

29
sys/dev/pci/lynxfbvar.h Normal file
View File

@ -0,0 +1,29 @@
/* $NetBSD: lynxfbvar.h,v 1.1 2012/03/02 13:20:57 nonaka Exp $ */
/*-
* Copyright (C) 2012 NONAKA Kimihiro <nonaka@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);