Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Aug 2012 06:31:27 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r239478 - in head/sys: conf powerpc/wii
Message-ID:  <201208210631.q7L6VRQb078654@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Tue Aug 21 06:31:26 2012
New Revision: 239478
URL: http://svn.freebsd.org/changeset/base/239478

Log:
  Initial support for running FreeBSD on the Nintendo Wii. We're able to
  reach single user mode using a memory disk device as the file system.
  
  This port includes the framebuffer driver, the PIC driver, a platform
  driver and the GPIO driver. The IPC driver (to talk to IOS kernels) is
  not yet written but there's a placeholder for it.
  
  There are still some MMU problems and to get a working system you need to
  patch locore32.S. Since we haven't found the best way yet to address that
  problem, we're not committing those changes yet. The problem is related to
  the different BAT layout on the Wii and to the fact that the Homebrew
  loader doesn't clean up the special registers (including the 8 BATs)
  before passing control to us.
  
  You'll need a Wii with Homebrew loader and a TV that can do NTSC (for now).
  
  Submitted by:	Margarida Gouveia

Added:
  head/sys/powerpc/wii/
  head/sys/powerpc/wii/platform_wii.c   (contents, props changed)
  head/sys/powerpc/wii/wii_bus.c   (contents, props changed)
  head/sys/powerpc/wii/wii_exireg.h   (contents, props changed)
  head/sys/powerpc/wii/wii_fb.c   (contents, props changed)
  head/sys/powerpc/wii/wii_fbreg.h   (contents, props changed)
  head/sys/powerpc/wii/wii_fbvar.h   (contents, props changed)
  head/sys/powerpc/wii/wii_gpio.c   (contents, props changed)
  head/sys/powerpc/wii/wii_gpioreg.h   (contents, props changed)
  head/sys/powerpc/wii/wii_ipc.c   (contents, props changed)
  head/sys/powerpc/wii/wii_ipcreg.h   (contents, props changed)
  head/sys/powerpc/wii/wii_pic.c   (contents, props changed)
  head/sys/powerpc/wii/wii_picreg.h   (contents, props changed)
Modified:
  head/sys/conf/files.powerpc
  head/sys/conf/options.powerpc

Modified: head/sys/conf/files.powerpc
==============================================================================
--- head/sys/conf/files.powerpc	Tue Aug 21 06:14:08 2012	(r239477)
+++ head/sys/conf/files.powerpc	Tue Aug 21 06:31:26 2012	(r239478)
@@ -228,6 +228,12 @@ powerpc/psim/iobus.c 		optional	psim
 powerpc/psim/ata_iobus.c	optional	ata psim
 powerpc/psim/openpic_iobus.c	optional	psim
 powerpc/psim/uart_iobus.c	optional	uart psim
+powerpc/wii/platform_wii.c	optional	wii
+powerpc/wii/wii_bus.c		optional	wii
+powerpc/wii/wii_pic.c		optional	wii
+powerpc/wii/wii_fb.c		optional	wii
+powerpc/wii/wii_gpio.c		optional	wii
+powerpc/wii/wii_ipc.c		optional	wii
 
 compat/freebsd32/freebsd32_ioctl.c	optional	compat_freebsd32
 compat/freebsd32/freebsd32_misc.c	optional	compat_freebsd32

Modified: head/sys/conf/options.powerpc
==============================================================================
--- head/sys/conf/options.powerpc	Tue Aug 21 06:14:08 2012	(r239477)
+++ head/sys/conf/options.powerpc	Tue Aug 21 06:31:26 2012	(r239478)
@@ -23,6 +23,7 @@ POWERMAC		opt_platform.h
 PS3			opt_platform.h
 MAMBO
 PSIM
+WII			opt_platform.h
 
 SC_OFWFB		opt_ofwfb.h
 

Added: head/sys/powerpc/wii/platform_wii.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/wii/platform_wii.c	Tue Aug 21 06:31:26 2012	(r239478)
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/smp.h>
+#include <sys/fbio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hid.h>
+#include <machine/platform.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+#include <machine/smp.h>
+#include <machine/spr.h>
+#include <machine/vmparam.h>
+
+#include <powerpc/wii/wii_fbreg.h>
+
+#include "platform_if.h"
+
+static int		wii_probe(platform_t);
+static int		wii_attach(platform_t);
+static void		wii_mem_regions(platform_t, struct mem_region **,
+			    int *, struct mem_region **, int *);
+static unsigned long	wii_timebase_freq(platform_t, struct cpuref *cpuref);
+static void		wii_reset(platform_t);
+static void		wii_cpu_idle(void);
+
+static platform_method_t wii_methods[] = {
+	PLATFORMMETHOD(platform_probe,		wii_probe),
+	PLATFORMMETHOD(platform_attach,		wii_attach),
+	PLATFORMMETHOD(platform_mem_regions,	wii_mem_regions),
+	PLATFORMMETHOD(platform_timebase_freq,	wii_timebase_freq),
+	PLATFORMMETHOD(platform_reset,		wii_reset),
+ 
+	{ 0, 0 }
+};
+
+static platform_def_t wii_platform = {
+	"wii",
+	wii_methods,
+	0
+};
+
+PLATFORM_DEF(wii_platform);
+
+static int
+wii_probe(platform_t plat)
+{
+	register_t vers = mfpvr();
+
+	/*
+	 * The Wii includes a PowerPC 750CL with custom modifications
+	 * ("Broadway").
+	 * For now, we just assume that if we are running on a
+	 * PowerPC 750CL, then this platform is a Nintendo Wii.
+	 */
+	if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL))
+		return (BUS_PROBE_SPECIFIC);
+
+	return (ENXIO);
+}
+
+static int
+wii_attach(platform_t plat)
+{
+	cpu_idle_hook = wii_cpu_idle;
+
+	return (0);
+}
+
+#define MEM_REGIONS     2
+static struct mem_region avail_regions[MEM_REGIONS];
+
+static void
+wii_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
+    struct mem_region **avail, int *availsz)
+{
+	/* 24MB 1T-SRAM */
+	avail_regions[0].mr_start = 0x00000000;
+	avail_regions[0].mr_size  = 0x01800000 - 0x0004000;
+
+	/*
+	 * Reserve space for the framebuffer which is located
+	 * at the end of this 24MB memory region. See wii_fbreg.h.
+	 */
+	avail_regions[0].mr_size -= WIIFB_FB_LEN;
+
+	/* 64MB GDDR3 SDRAM */
+	avail_regions[1].mr_start = 0x10000000 + 0x0004000;
+	avail_regions[1].mr_size  = 0x04000000 - 0x0004000;
+
+	/* XXX for now only use the first memory region */
+#undef MEM_REGIONS
+#define MEM_REGIONS 1
+
+	*phys = *avail = avail_regions;
+	*physsz = *availsz = MEM_REGIONS;
+}
+
+static u_long
+wii_timebase_freq(platform_t plat, struct cpuref *cpuref)
+{
+	
+	/* Bus Frequency (243MHz) / 4 */
+	return (60750000);
+}
+
+static void
+wii_reset(platform_t plat)
+{
+}
+
+static void
+wii_cpu_idle(void)
+{
+}

Added: head/sys/powerpc/wii/wii_bus.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/wii/wii_bus.c	Tue Aug 21 06:31:26 2012	(r239478)
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/cpu.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+
+#include <powerpc/wii/wii_picreg.h>
+#include <powerpc/wii/wii_fbreg.h>
+#include <powerpc/wii/wii_exireg.h>
+#include <powerpc/wii/wii_ipcreg.h>
+#include <powerpc/wii/wii_gpioreg.h>
+
+static void	wiibus_identify(driver_t *, device_t);
+static int	wiibus_probe(device_t);
+static int	wiibus_attach(device_t);
+static int	wiibus_print_child(device_t, device_t);
+static struct resource *
+		wiibus_alloc_resource(device_t, device_t, int, int *,
+		    unsigned long, unsigned long, unsigned long,
+		    unsigned int);
+static int	wiibus_activate_resource(device_t, device_t, int, int,
+		    struct resource *);
+
+static device_method_t wiibus_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_identify,	wiibus_identify),
+	DEVMETHOD(device_probe,		wiibus_probe),
+	DEVMETHOD(device_attach,	wiibus_attach),
+
+        /* Bus interface */
+	DEVMETHOD(bus_add_child,	bus_generic_add_child),
+	DEVMETHOD(bus_print_child,	wiibus_print_child),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,   wiibus_alloc_resource),
+	DEVMETHOD(bus_activate_resource,wiibus_activate_resource),
+
+	DEVMETHOD_END
+};
+
+struct wiibus_softc {
+	device_t		sc_dev;
+	struct rman		sc_rman;
+};
+
+static MALLOC_DEFINE(M_WIIBUS, "wiibus", "Nintendo Wii system bus");
+
+struct wiibus_devinfo {
+	struct resource_list	di_resources;
+	uint8_t			di_init;
+};
+
+static driver_t wiibus_driver = {
+	"wiibus",
+	wiibus_methods,
+	sizeof(struct wiibus_softc)
+};
+
+static devclass_t wiibus_devclass;
+
+DRIVER_MODULE(wiibus, nexus, wiibus_driver, wiibus_devclass, 0, 0);
+
+static void
+wiibus_identify(driver_t *driver, device_t parent)
+{
+	if (strcmp(installed_platform(), "wii") != 0)
+		return;
+
+	if (device_find_child(parent, "wiibus", -1) == NULL)
+		BUS_ADD_CHILD(parent, 0, "wiibus", 0);
+}
+
+
+static int
+wiibus_probe(device_t dev)
+{
+        /* Do not attach to any OF nodes that may be present */
+
+	device_set_desc(dev, "Nintendo Wii System Bus");
+
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static void
+wiibus_init_device_resources(struct rman *rm, struct wiibus_devinfo *dinfo,
+    unsigned int rid, uintptr_t addr, size_t len, unsigned int irq)
+
+{
+	if (!dinfo->di_init) {
+		resource_list_init(&dinfo->di_resources);
+		dinfo->di_init++;
+	}
+	if (addr) {
+		rman_manage_region(rm, addr, addr + len - 1);
+		resource_list_add(&dinfo->di_resources, SYS_RES_MEMORY, rid,
+		    addr, addr + len, len);
+	}
+	if (irq)
+		resource_list_add(&dinfo->di_resources, SYS_RES_IRQ, rid,
+		    irq, irq, 1);
+}
+
+static int
+wiibus_attach(device_t self)
+{
+	struct wiibus_softc *sc;
+	struct wiibus_devinfo *dinfo;
+	device_t cdev;
+
+	sc = device_get_softc(self);
+	sc->sc_rman.rm_type = RMAN_ARRAY;
+	sc->sc_rman.rm_descr = "Wii Bus Memory Mapped I/O";
+	rman_init(&sc->sc_rman);
+
+	/* Nintendo PIC */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIPIC_REG_ADDR,
+	    WIIPIC_REG_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiipic", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* Framebuffer */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIFB_REG_ADDR,
+	    WIIFB_REG_LEN, 8);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 1, WIIFB_FB_ADDR,
+	    WIIFB_FB_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiifb", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* External Interface Bus */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIEXI_REG_ADDR,
+	    WIIEXI_REG_LEN, 4);
+	cdev = BUS_ADD_CHILD(self, 0, "wiiexi", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* Nintendo IOS IPC */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIIPC_REG_ADDR,
+	    WIIIPC_REG_LEN, 14);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 1, WIIIPC_IOH_ADDR,
+	    WIIIPC_IOH_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiiipc", 0);
+	device_set_ivars(cdev, dinfo);
+
+	/* GPIO */
+	dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
+	wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIGPIO_REG_ADDR,
+	    WIIGPIO_REG_LEN, 0);
+	cdev = BUS_ADD_CHILD(self, 0, "wiigpio", 0);
+	device_set_ivars(cdev, dinfo);
+
+	return (bus_generic_attach(self));
+}
+
+static int
+wiibus_print_child(device_t dev, device_t child)
+{
+	struct wiibus_devinfo *dinfo = device_get_ivars(child);
+	int retval = 0;
+
+	retval += bus_print_child_header(dev, child);
+	retval += resource_list_print_type(&dinfo->di_resources, "mem",
+	    SYS_RES_MEMORY, "%#lx");
+	retval += resource_list_print_type(&dinfo->di_resources, "irq",
+	    SYS_RES_IRQ, "%ld");
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
+static struct resource *
+wiibus_alloc_resource(device_t bus, device_t child, int type,
+    int *rid, unsigned long start, unsigned long end,
+    unsigned long count, unsigned int flags)
+{
+	struct wiibus_softc *sc;
+	struct wiibus_devinfo *dinfo;
+	struct resource_list_entry *rle;
+	struct resource *rv;
+	int needactivate;
+
+	sc = device_get_softc(bus);
+	dinfo = device_get_ivars(child);
+	needactivate = flags & RF_ACTIVE;
+	flags &= ~RF_ACTIVE;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		rle = resource_list_find(&dinfo->di_resources, SYS_RES_MEMORY,
+		    *rid);
+		if (rle == NULL) {
+			device_printf(bus, "no res entry for %s memory 0x%x\n",
+			    device_get_nameunit(child), *rid);
+			return (NULL);
+		}
+		rv = rman_reserve_resource(&sc->sc_rman, rle->start, rle->end,
+		    rle->count, flags, child);
+		if (rv == NULL) {
+			device_printf(bus,
+			    "failed to reserve resource for %s\n",
+			    device_get_nameunit(child));
+			return (NULL);
+		}
+		rman_set_rid(rv, *rid);
+		break;
+	/* XXX IRQ */
+	default:
+		device_printf(bus, "unknown resource request from %s\n",
+		    device_get_nameunit(child));
+		return (NULL);
+	}
+
+	if (needactivate) {
+		if (bus_activate_resource(child, type, *rid, rv) != 0) {
+			device_printf(bus,
+			    "failed to activate resource for %s\n",
+			    device_get_nameunit(child));
+			return (NULL);
+		}
+	}
+	
+	return (rv);
+}
+
+static int
+wiibus_activate_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *res)
+{
+	void *p;
+
+	switch (type) {
+	case SYS_RES_MEMORY:
+		p = pmap_mapdev(rman_get_start(res), rman_get_size(res));
+		if (p == NULL)
+			return (ENOMEM);
+		rman_set_virtual(res, p);
+		rman_set_bustag(res, &bs_be_tag);
+		rman_set_bushandle(res, (unsigned long)p);
+		break;
+	/* XXX IRQ */
+	default:
+		device_printf(bus,
+		    "unknown activate resource request from %s\n",
+		    device_get_nameunit(child));
+		return (ENXIO);
+	}
+	
+	return (rman_activate_resource(res));
+}
+

Added: head/sys/powerpc/wii/wii_exireg.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/wii/wii_exireg.h	Tue Aug 21 06:31:26 2012	(r239478)
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	_POWERPC_WII_WII_EXIREG_H
+#define	_POWERPC_WII_WII_EXIREG_H
+
+#define	WIIEXI_REG_ADDR		0x0d006800
+#define	WIIEXI_REG_LEN		0x40
+
+#endif	/* _POWERPC_WII_WII_IPCREG_H */

Added: head/sys/powerpc/wii/wii_fb.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/powerpc/wii/wii_fb.c	Tue Aug 21 06:31:26 2012	(r239478)
@@ -0,0 +1,881 @@
+/*-
+ * Copyright (C) 2012 Margarida Gouveia
+ * Copyright (c) 2003 Peter Grehan
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 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.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/limits.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/fbio.h>
+#include <sys/consio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/sc_machdep.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+
+#include <sys/rman.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/syscons/syscons.h>
+
+#include <powerpc/wii/wii_fbreg.h>
+#include <powerpc/wii/wii_fbvar.h>
+
+/*
+ * Driver for the Nintendo Wii's framebuffer. Based on Linux's gcnfb.c.
+ */
+
+/*
+ * Syscons glue.
+ */
+static int	wiifb_scprobe(device_t);
+static int	wiifb_scattach(device_t);
+
+static device_method_t wiifb_sc_methods[] = {
+	DEVMETHOD(device_probe,		wiifb_scprobe),
+	DEVMETHOD(device_attach,	wiifb_scattach),
+
+	DEVMETHOD_END
+};
+
+static driver_t wiifb_sc_driver = {
+	"wiifb",
+	wiifb_sc_methods,
+	sizeof(sc_softc_t),
+};
+
+static devclass_t sc_devclass;
+
+DRIVER_MODULE(sc, wiibus, wiifb_sc_driver, sc_devclass, 0, 0);
+
+static int
+wiifb_scprobe(device_t dev)
+{
+	int error;
+
+	device_set_desc(dev, "Nintendo Wii frambuffer");
+
+	error = sc_probe_unit(device_get_unit(dev),
+	    device_get_flags(dev) | SC_AUTODETECT_KBD);
+	if (error != 0)
+		return (error);
+
+	/* This is a fake device, so make sure we added it ourselves */
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+wiifb_scattach(device_t dev)
+{
+
+	return (sc_attach_unit(device_get_unit(dev),
+	    device_get_flags(dev) | SC_AUTODETECT_KBD));
+}
+
+/*
+ * Video driver routines and glue.
+ */
+static void			wiifb_reset_video(struct wiifb_softc *);
+static void			wiifb_enable_interrupts(struct wiifb_softc *);
+static void			wiifb_configure_tv_mode(struct wiifb_softc *);
+static void			wiifb_setup_framebuffer(struct wiifb_softc *);
+static int			wiifb_configure(int);
+static vi_probe_t		wiifb_probe;
+static vi_init_t		wiifb_init;
+static vi_get_info_t		wiifb_get_info;
+static vi_query_mode_t		wiifb_query_mode;
+static vi_set_mode_t		wiifb_set_mode;
+static vi_save_font_t		wiifb_save_font;
+static vi_load_font_t		wiifb_load_font;
+static vi_show_font_t		wiifb_show_font;
+static vi_save_palette_t	wiifb_save_palette;
+static vi_load_palette_t	wiifb_load_palette;
+static vi_set_border_t		wiifb_set_border;
+static vi_save_state_t		wiifb_save_state;
+static vi_load_state_t		wiifb_load_state;
+static vi_set_win_org_t		wiifb_set_win_org;
+static vi_read_hw_cursor_t	wiifb_read_hw_cursor;
+static vi_set_hw_cursor_t	wiifb_set_hw_cursor;
+static vi_set_hw_cursor_shape_t	wiifb_set_hw_cursor_shape;
+static vi_blank_display_t	wiifb_blank_display;
+static vi_mmap_t		wiifb_mmap;
+static vi_ioctl_t		wiifb_ioctl;
+static vi_clear_t		wiifb_clear;
+static vi_fill_rect_t		wiifb_fill_rect;
+static vi_bitblt_t		wiifb_bitblt;
+static vi_diag_t		wiifb_diag;
+static vi_save_cursor_palette_t	wiifb_save_cursor_palette;
+static vi_load_cursor_palette_t	wiifb_load_cursor_palette;
+static vi_copy_t		wiifb_copy;
+static vi_putp_t		wiifb_putp;
+static vi_putc_t		wiifb_putc;
+static vi_puts_t		wiifb_puts;
+static vi_putm_t		wiifb_putm;
+
+static video_switch_t wiifbvidsw = {
+	.probe			= wiifb_probe,
+	.init			= wiifb_init,
+	.get_info		= wiifb_get_info,
+	.query_mode		= wiifb_query_mode,
+	.set_mode		= wiifb_set_mode,
+	.save_font		= wiifb_save_font,
+	.load_font		= wiifb_load_font,
+	.show_font		= wiifb_show_font,
+	.save_palette		= wiifb_save_palette,
+	.load_palette		= wiifb_load_palette,
+	.set_border		= wiifb_set_border,
+	.save_state		= wiifb_save_state,
+	.load_state		= wiifb_load_state,
+	.set_win_org		= wiifb_set_win_org,
+	.read_hw_cursor		= wiifb_read_hw_cursor,
+	.set_hw_cursor		= wiifb_set_hw_cursor,
+	.set_hw_cursor_shape	= wiifb_set_hw_cursor_shape,
+	.blank_display		= wiifb_blank_display,
+	.mmap			= wiifb_mmap,
+	.ioctl			= wiifb_ioctl,
+	.clear			= wiifb_clear,
+	.fill_rect		= wiifb_fill_rect,
+	.bitblt			= wiifb_bitblt,
+	.diag			= wiifb_diag,
+	.save_cursor_palette	= wiifb_save_cursor_palette,
+	.load_cursor_palette	= wiifb_load_cursor_palette,
+	.copy			= wiifb_copy,
+	.putp			= wiifb_putp,
+	.putc			= wiifb_putc,
+	.puts			= wiifb_puts,
+	.putm			= wiifb_putm,
+};
+
+VIDEO_DRIVER(wiifb, wiifbvidsw, wiifb_configure);
+
+extern sc_rndr_sw_t txtrndrsw;
+RENDERER(wiifb, 0, txtrndrsw, gfb_set);
+RENDERER_MODULE(wiifb, gfb_set);
+
+static struct wiifb_softc wiifb_softc;
+static uint16_t wiifb_static_window[ROW*COL];
+extern u_char dflt_font_8[];
+
+/*
+ * Map the syscons colors to YUY2 (Y'UV422).
+ * Some colours are an approximation.
+ *
+ * The Wii has a 16 bit pixel, so each 32 bit DWORD encodes
+ * two pixels.  The upper 16 bits is for pixel 0 (left hand pixel
+ * in a pair), the lower 16 bits is for pixel 1. 
+ *
+ * For now, we're going to ignore that entirely and just use the
+ * lower 16 bits for each pixel. We'll take the upper value into
+ * account later.
+ */
+static uint32_t wiifb_cmap[16] = {
+	0x00800080,	/* Black */
+	0x1dff1d6b,	/* Blue */
+	0x4b554b4a,	/* Green */
+	0x80808080,	/* Cyan */
+	0x4c544cff,	/* Red */
+	0x3aaa34b5,	/* Magenta */
+	0x7140718a,	/* Brown */
+	0xff80ff80,	/* White */
+	0x80808080,	/* Gray */
+	0xc399c36a,	/* Bright Blue */
+	0xd076d074,	/* Bright Green */
+	0x80808080,	/* Bright Cyan */
+	0x4c544cff,	/* Bright Red */
+	0x3aaa34b5,	/* Bright Magenta */
+	0xe100e194,	/* Bright Yellow */
+	0xff80ff80	/* Bright White */
+};
+
+static struct wiifb_mode_desc wiifb_modes[] = {
+	[WIIFB_MODE_NTSC_480i] = {
+		"NTSC 480i",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_INTERLACED,
+	},
+	[WIIFB_MODE_NTSC_480p] = {
+		"NTSC 480p",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_PROGRESSIVE,
+	},
+	[WIIFB_MODE_PAL_576i] = {
+		"PAL 576i (50Hz)",
+		640, 574,
+		625,
+		WIIFB_MODE_FLAG_INTERLACED,
+	},
+	[WIIFB_MODE_PAL_480i] = {
+		"PAL 480i (60Hz)",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_INTERLACED,
+	},
+	[WIIFB_MODE_PAL_480p] = {
+		"PAL 480p",
+		640, 480,
+		525,
+		WIIFB_MODE_FLAG_PROGRESSIVE,
+	},
+};
+
+static const uint32_t wiifb_filter_coeft[] = {
+	0x1ae771f0, 0x0db4a574, 0x00c1188e, 0xc4c0cbe2, 0xfcecdecf,
+	0x13130f08, 0x00080c0f
+};
+
+static __inline int
+wiifb_background(uint8_t attr)
+{
+
+	return (attr >> 4);
+}
+
+static __inline int
+wiifb_foreground(uint8_t attr)
+{
+
+	return (attr & 0x0f);
+}
+
+static void
+wiifb_reset_video(struct wiifb_softc *sc)
+{
+	struct wiifb_dispcfg dc;
+
+	wiifb_dispcfg_read(sc, &dc);
+	dc.dc_reset = 1;
+	wiifb_dispcfg_write(sc, &dc);
+	dc.dc_reset = 0;
+	wiifb_dispcfg_write(sc, &dc);
+}
+
+static void
+wiifb_enable_interrupts(struct wiifb_softc *sc)
+{
+	struct wiifb_dispint di;
+
+#ifdef notyet
+	/*
+	 * Display Interrupt 0
+	 */
+	di.di_htiming = 1;
+	di.di_vtiming = 1;
+	di.di_enable = 1;
+	di.di_irq    = 1;
+	wiifb_dispint_write(sc, 0, &di);
+
+	/*
+	 * Display Interrupt 1
+	 */
+	di.di_htiming = sc->sc_format == WIIFB_FORMAT_PAL ? 433 : 430;
+	di.di_vtiming = sc->sc_mode->fd_lines;
+	di.di_enable = 1;
+	di.di_irq    = 1;
+	if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
+		di.di_vtiming /= 2;
+	wiifb_dispint_write(sc, 1, &di);
+
+	/*
+	 * Display Interrupts 2 and 3 are not used.
+	 */
+	memset(&di, 0, sizeof(di));
+	wiifb_dispint_write(sc, 2, &di);
+	wiifb_dispint_write(sc, 3, &di);
+#else
+	memset(&di, 0, sizeof(di));
+	wiifb_dispint_write(sc, 0, &di);
+	wiifb_dispint_write(sc, 1, &di);
+	wiifb_dispint_write(sc, 2, &di);
+	wiifb_dispint_write(sc, 3, &di);
+#endif
+}
+
+/*
+ * Reference gcnfb.c for an in depth explanation.
+ * XXX only works with NTSC.
+ */
+static void
+wiifb_configure_tv_mode(struct wiifb_softc *sc)
+{
+	struct wiifb_vtiming vt;
+	struct wiifb_hscaling hs;
+	struct wiifb_htiming0 ht0;
+	struct wiifb_htiming1 ht1;
+	struct wiifb_vtimingodd vto;
+	struct wiifb_vtimingeven vte;
+	struct wiifb_burstblankodd bbo;
+	struct wiifb_burstblankeven bbe;
+	struct wiifb_picconf pc;
+	struct wiifb_mode_desc *mode = sc->sc_mode;
+	unsigned int height = mode->fd_height;
+	unsigned int width = mode->fd_width;
+	unsigned int eqpulse, interlacebias, shift;
+	const unsigned int maxwidth = 714;
+	unsigned int hblanking = maxwidth - width;
+	unsigned int hmargin = hblanking / 2;
+	unsigned int A = 20 + hmargin, C = 60 + hblanking - hmargin;
+	unsigned int maxheight = 484;
+	unsigned int P = 2 * (20 - 10 + 1);
+	unsigned int Q = 1;
+	unsigned int vblanking = maxheight - height;
+	unsigned int vmargin = vblanking / 2;
+	unsigned int prb = vmargin;
+	unsigned int psb = vblanking - vmargin;
+	int i;
+
+	/*
+	 * Vertical timing.
+	 */
+	if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) {
+		vt.vt_actvideo = height / 2;
+		interlacebias = 1;
+		shift = 0;
+	} else {
+		vt.vt_actvideo = height;
+		interlacebias = 0;
+		shift = 1;
+	}
+	/* Lines of equalization */
+	if (mode->fd_lines == 625)
+		eqpulse = 2 * 2.5;
+	else
+		eqpulse = 2 * 3;
+	vt.vt_eqpulse = eqpulse << shift;
+	wiifb_vtiming_write(sc, &vt);
+
+	/*
+	 * Horizontal timings.
+	 */
+	ht0.ht0_hlinew = 858 / 2;
+	ht1.ht1_hsyncw = 64;
+	ht0.ht0_hcolourstart = 71;
+	ht0.ht0_hcolourend = 71 + 34;
+	ht1.ht1_hblankstart = (858 / 2) - A;
+	ht1.ht1_hblankend = 64 + C;
+	wiifb_htiming0_write(sc, &ht0);
+	wiifb_htiming1_write(sc, &ht1);
+
+	/*
+	 * Vertical timing odd/even.
+	 */
+	if (vmargin & 1) {
+		vto.vto_preb = (P + interlacebias + prb) << shift;
+		vto.vto_postb = (Q - interlacebias + psb) << shift;
+		vte.vte_preb = (P + prb) << shift;
+		vte.vte_postb = (Q - psb) << shift;
+	} else {
+		/* XXX if this isn't 0, it doesn't work? */
+		prb = 0;
+		psb = 0;
+		vte.vte_preb = (P + interlacebias + prb) << shift;
+		vte.vte_postb = (Q - interlacebias + psb) << shift;
+		vto.vto_preb = (P + prb) << shift;
+		vto.vto_postb = (Q - psb) << shift;
+	}
+	wiifb_vtimingodd_write(sc, &vto);
+	wiifb_vtimingeven_write(sc, &vte);
+
+	/*
+	 * Burst blanking odd/even interval.
+	 */
+	bbo.bbo_bs1 = 2 * (18 - 7 + 1);
+	bbe.bbe_bs2 = bbo.bbo_bs3 = bbe.bbe_bs4 = bbo.bbo_bs1;
+	bbo.bbo_be1 = 2 * (525 - 7 + 1);
+	bbe.bbe_be2 = bbo.bbo_be3 = bbe.bbe_be4 = bbo.bbo_be1;
+	wiifb_burstblankodd_write(sc, &bbo);
+	wiifb_burstblankeven_write(sc, &bbe);
+
+	/*
+	 * Picture configuration.
+	 */ 
+	pc.pc_strides = (mode->fd_width * 2) / 32;
+	if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
+		pc.pc_strides *= 2;
+	pc.pc_reads = (mode->fd_width * 2) / 32;
+	wiifb_picconf_write(sc, &pc);
+
+	/*
+	 * Horizontal scaling disabled.
+	 */
+	hs.hs_enable = 0;
+	hs.hs_step = 256;
+	wiifb_hscaling_write(sc, &hs);
+
+	/*
+	 * Filter coeficient table.
+	 */
+	for (i = 0; i < 7; i++)
+		wiifb_filtcoeft_write(sc, i, wiifb_filter_coeft[i]);
+
+	/*
+	 * Anti alias.
+	 */
+	wiifb_antialias_write(sc, 0x00ff0000);
+
+	/*
+	 * Video clock.
+	 */
+	wiifb_videoclk_write(sc, 
+	    mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED ? 0 : 1);
+
+	/*
+	 * Disable horizontal scaling width.
+	 */
+	wiifb_hscalingw_write(sc, mode->fd_width);
+
+	/*
+	 * DEBUG mode borders. Not used.
+	 */
+	wiifb_hborderend_write(sc, 0);
+	wiifb_hborderstart_write(sc, 0);
+
+	/*
+	 * XXX unknown registers.
+	 */
+	wiifb_unknown1_write(sc, 0x00ff);
+	wiifb_unknown2_write(sc, 0x00ff00ff);
+	wiifb_unknown3_write(sc, 0x00ff00ff);
+}
+
+static void
+wiifb_setup_framebuffer(struct wiifb_softc *sc)
+{
+	intptr_t addr = sc->sc_fb_addr;
+	struct wiifb_topfieldbasel tfbl;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208210631.q7L6VRQb078654>