Add support for XBOX to the FreeBSD port. The xbox architecture is

nearly identical to wintel/ia32, with a couple of tweaks.  Since it is
so similar to ia32, it is optionally added to a i386 kernel.  This
port is preliminary, but seems to work well.  Further improvements
will improve the interaction with syscons(4), port Linux nforce driver
and future versions of the xbox.

This supports the 64MB and 128MB boxes.  You'll need the most recent
CVS version of Cromwell (the Linux BIOS for the XBOX) to boot.

Rink will be maintaining this port, and is interested in feedback.
He's setup a website http://xbox-bsd.nl to report the latest
developments.

Any silly mistakes are my fault.

Submitted by: Rink P.W. Springer rink at stack dot nl and
	Ed Schouten ed at fxq dot nl
This commit is contained in:
Warner Losh 2005-11-09 03:55:40 +00:00
parent 24ea970aff
commit 51ef421d92
13 changed files with 945 additions and 0 deletions

View File

@ -462,3 +462,7 @@ pci/agp_intel.c optional agp
pci/agp_nvidia.c optional agp
pci/agp_sis.c optional agp
pci/agp_via.c optional agp
i386/xbox/xbox.c optional xbox
i386/xbox/xboxfb.c optional xboxfb
dev/fb/boot_font.c optional xboxfb
i386/xbox/pic16l.s optional xbox

View File

@ -163,3 +163,6 @@ ASR_COMPAT opt_asr.h
# Debugging
STOP_NMI opt_cpu.h
NPX_DEBUG opt_npx.h
# XBOX support in the kernel
XBOX opt_xbox.h

104
sys/i386/conf/XBOX Normal file
View File

@ -0,0 +1,104 @@
#
# XBOX -- kernel for an XBOX
#
# $FreeBSD$
machine i386
cpu I686_CPU # Celeron
ident XBOX
makeoptions MODULES_OVERRIDE=""
options KDB
options DDB
options XBOX # kernel is for XBOX
device xboxfb # frame buffer support (REQUIRED!)
# no support yet for root device name fetching
options ROOTDEVNAME=\"ufs:ad0s1a\"
#options ROOTDEVNAME=\"cd9660:acd0\"
options SCHED_4BSD # 4BSD scheduler
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
#options UFS_ACL # Support for access control lists
#options UFS_DIRHASH # Improve performance on big directories
#options MD_ROOT # MD is a potential root device
options NFSCLIENT # Network Filesystem Client
#options NFSSERVER # Network Filesystem Server
#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
#options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
#options PROCFS # Process filesystem (requires PSEUDOFS)
#options PSEUDOFS # Pseudo-filesystem framework
#options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
#options COMPAT_FREEBSD4 # Compatible with FreeBSD4
#options KTRACE # ktrace(1) support
#options SYSVSHM # SYSV-style shared memory
#options SYSVMSG # SYSV-style message queues
#options SYSVSEM # SYSV-style semaphores
#options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
#options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options ADAPTIVE_GIANT # Giant mutex is adaptive.
#device apic # I/O APIC
# Bus support. Do not remove isa, even if you have no isa slots
device isa
device pci
# ATA and ATAPI devices
device ata
device atadisk # ATA disk drives
device atapicd # ATAPI CDROM drives
options ATA_STATIC_ID # Static device numbering
# SCSI peripherals
device scbus # SCSI bus (required for SCSI)
device da # Direct Access (disks)
# Floating point support - do not disable.
device npx
# Pseudo devices.
device loop # Network loopback
device mem # Memory and kernel memory devices
device io # I/O device
device random # Entropy device
device ether # Ethernet support
#device tun # Packet tunnel.
device pty # Pseudo-ttys (telnet etc)
#device md # Memory "disks"
#device gif # IPv6 and IPv4 tunneling
#device faith # IPv6-to-IPv4 relaying (translation)
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
# Note that 'bpf' is required for DHCP.
device bpf # Berkeley packet filter
# USB support
#device uhci # UHCI PCI->USB interface
device ohci # OHCI PCI->USB interface
device usb # USB Bus (required)
device ugen # Generic
device uhid # "Human Interface Devices"
device ukbd # Keyboard
device ulpt # Printer
device umass # Disks/Mass storage - Requires scbus and da
device ums # Mouse
device urio # Diamond Rio 500 MP3 player
device uscanner # Scanners
device miibus
device aue # ADMtek USB Ethernet
device axe # ASIX Electronics USB Ethernet
device cdce # Generic USB over Ethernet
device cue # CATC USB Ethernet
device kue # Kawasaki LSI USB Ethernet
device rue # RealTek RTL8150 USB Ethernet
device sound
device snd_ich # nForce audio

View File

@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include "opt_msgbuf.h"
#include "opt_npx.h"
#include "opt_perfmon.h"
#include "opt_xbox.h"
#include <sys/param.h>
#include <sys/proc.h>
@ -133,6 +134,13 @@ __FBSDID("$FreeBSD$");
#include <i386/isa/icu.h>
#endif
#ifdef XBOX
#include <machine/xbox.h>
int arch_i386_is_xbox = 0;
uint32_t arch_i386_xbox_memsize = 0;
#endif
/* Sanity check for __curthread() */
CTASSERT(offsetof(struct pcpu, pc_curthread) == 0);
@ -1625,6 +1633,21 @@ getmemsize(int first)
struct bios_smap *smap;
quad_t dcons_addr, dcons_size;
#ifdef XBOX
if (arch_i386_is_xbox) {
/*
* We queried the memory size before, so chop off 4MB for
* the framebuffer and inform the OS of this.
*/
extmem = (arch_i386_xbox_memsize - 4) * 1024;
basemem = 0;
physmap[0] = 0;
physmap[1] = extmem * 1024;
physmap_idx = 0;
goto physmap_done;
}
#endif
hasbrokenint12 = 0;
TUNABLE_INT_FETCH("hw.hasbrokenint12", &hasbrokenint12);
bzero(&vmf, sizeof(vmf));
@ -2158,6 +2181,28 @@ init386(first)
r_idt.rd_base = (int) idt;
lidt(&r_idt);
#ifdef XBOX
/*
* The following code queries the PCI ID of 0:0:0. For the XBOX,
* This should be 0x10de / 0x02a5.
*
* This is exactly what Linux does.
*/
outl(0xcf8, 0x80000000);
if (inl(0xcfc) == 0x02a510de) {
arch_i386_is_xbox = 1;
pic16l_setled(XBOX_LED_GREEN);
/*
* We are an XBOX, but we may have either 64MB or 128MB of
* memory. The PCI host bridge should be programmed for this,
* so we just query it.
*/
outl (0xcf8, 0x80000084);
arch_i386_xbox_memsize = (inl (0xcfc) == 0x7FFFFFF) ? 128 : 64;
}
#endif /* XBOX */
/*
* Initialize the console before we print anything out.
*/

View File

@ -106,6 +106,7 @@ __FBSDID("$FreeBSD$");
#include "opt_cpu.h"
#include "opt_pmap.h"
#include "opt_msgbuf.h"
#include "opt_xbox.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -144,6 +145,10 @@ __FBSDID("$FreeBSD$");
#include <machine/smp.h>
#endif
#ifdef XBOX
#include <machine/xbox.h>
#endif
#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
#define CPU_ENABLE_SSE
#endif
@ -393,6 +398,13 @@ pmap_bootstrap(firstaddr, loadaddr)
virtual_avail = va;
*CMAP1 = 0;
#ifdef XBOX
/* FIXME: This is gross, but needed for the XBOX. Since we are in such
* an early stadium, we cannot yet neatly map video memory ... :-(
* Better fixes are very welcome! */
if (!arch_i386_is_xbox)
#endif
for (i = 0; i < NKPT; i++)
PTD[i] = 0;

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include "opt_npx.h"
#include "opt_reset.h"
#include "opt_cpu.h"
#include "opt_xbox.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$");
#include <i386/isa/isa.h>
#endif
#ifdef XBOX
#include <machine/xbox.h>
#endif
#ifndef NSFBUFS
#define NSFBUFS (512 + maxusers * 16)
#endif
@ -536,6 +541,14 @@ cpu_reset_proxy()
void
cpu_reset()
{
#ifdef XBOX
if (arch_i386_is_xbox) {
/* Kick the PIC16L, it can reboot the box */
pic16l_reboot();
for (;;);
}
#endif
#ifdef SMP
u_int cnt, map;

45
sys/i386/include/xbox.h Normal file
View File

@ -0,0 +1,45 @@
/*-
* Copyright (c) 2005 Rink Springer
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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 _MACHINE_XBOX_H_
#define _MACHINE_XBOX_H_
#define XBOX_LED_GREEN 0x0f
#define XBOX_LED_RED 0xf0
#define XBOX_LED_FLASHRED 0xa0
#define XBOX_LED_FLASHGREEN 0x03
extern int arch_i386_is_xbox;
extern uint32_t arch_i386_xbox_memsize; /* Megabytes */
void pic16l_setbyte(int addr, int reg, int data);
void pic16l_setled(int val);
void pic16l_reboot(void);
void pic16l_poweroff(void);
#endif /* !_MACHINE_XBOX_H_ */

View File

@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include "opt_clock.h"
#include "opt_isa.h"
#include "opt_mca.h"
#include "opt_xbox.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -90,6 +91,10 @@ __FBSDID("$FreeBSD$");
#include <i386/bios/mca_machdep.h>
#endif
#ifdef XBOX
#include <machine/xbox.h>
#endif
/*
* 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
* can use a simple formula for leap years.
@ -522,6 +527,11 @@ calibrate_clocks(void)
return (tot_count);
fail:
#ifdef XBOX
if (arch_i386_is_xbox)
timer_freq = 1125000; /* gives ~733.34MHz CPU clock */
#endif
if (bootverbose)
printf("failed, using default i8254 clock of %u Hz\n",
timer_freq);

View File

@ -30,6 +30,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_xbox.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@ -49,6 +51,10 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/pmap.h>
#ifdef XBOX
#include <machine/xbox.h>
#endif
#define PRVERB(a) do { \
if (bootverbose) \
printf a ; \
@ -207,6 +213,39 @@ pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
{
int dataport = 0;
#ifdef XBOX
if (arch_i386_is_xbox) {
/*
* The Xbox MCPX chipset is a derivative of the nForce 1
* chipset. It almost has the same bus layout; some devices
* cannot be used, because they have been removed.
*/
/*
* Devices 00:00.1 and 00:00.2 used to be memory controllers on
* the nForce chipset, but on the Xbox, using them will lockup
* the chipset.
*/
if (bus == 0 && slot == 0 && (func == 1 || func == 2))
return dataport;
/*
* Bus 1 only contains a VGA controller at 01:00.0. When you try
* to probe beyond that device, you only get garbage, which
* could cause lockups.
*/
if (bus == 1 && (slot != 0 || func != 0))
return dataport;
/*
* Bus 2 used to contain the AGP controller, but the Xbox MCPX
* doesn't have one. Probing it can cause lockups.
*/
if (bus >= 2)
return dataport;
}
#endif
if (bus <= PCI_BUSMAX
&& slot < devmax
&& func <= PCI_FUNCMAX

202
sys/i386/xbox/pic16l.s Normal file
View File

@ -0,0 +1,202 @@
/*-
* Copyright (c) 2005 Rink Springer
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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$
*/
#include <machine/asmacros.h>
.text
/*
* send a command to the PIC16L
*
* void pic16l_setbyte (int addr, int reg, int data)
*
*/
ENTRY(pic16l_setbyte)
push %ebp
mov %esp,%ebp
push %ebx
movw $0xc000,%dx
1: xor %eax,%eax
inw %dx,%ax
shr $0x0b,%eax
and $0x01,%eax
test %eax,%eax
jne 1b
mov $50,%ecx
2: movw $0xc004,%dx
movl 0x8(%ebp),%eax
outb %al,%dx
movw $0xc008,%dx
movl 0xc(%ebp),%eax
outb %al,%dx
movw $0xc006,%dx
movl 0x10(%ebp),%eax
outw %ax,%dx
movw $0xc000,%dx
inw %dx,%ax
outw %ax,%dx
movw $0xc002,%dx
movb $0x1a,%al
outb %al,%dx
movw $0xc000,%dx
3:
inb %dx,%al
movb %al,%bl
orb $0x36,%al
jz 3b
orb $0x10,%bl
jnz 5f
4:
push %ecx
xor %ecx,%ecx
l: loop l
pop %ecx
dec %ecx
jz 5f
jmp 2b
5:
pop %ebx
leave
ret
/*
* instructs the pic16l to reboot the xbox
*
* void pic16l_reboot();
*
*/
ENTRY(pic16l_reboot)
pushl $0x01
pushl $0x02
pushl $0x20
call pic16l_setbyte
addl $12,%esp
ret
/*
* instructs the pic16l to power-off the xbox
*
* void pic16l_poweroff();
*
*/
ENTRY(pic16l_poweroff)
pushl $0x80
pushl $0x02
pushl $0x20
call pic16l_setbyte
addl $12,%esp
ret
pic16l_ledhlp:
movw $0xc000,%dx
1: xor %eax,%eax
inw %dx,%ax
shr $0x0b,%eax
and $0x01,%eax
test %eax,%eax
jne 1b
mov $400,%ecx
2:
movw $0xc004,%dx
movb $0x20,%al
outb %al,%dx
movw $0xc008,%dx
movb %bh,%al
outb %al,%dx
movw $0xc006,%dx
movb %bl,%al
outb %al,%dx
movw $0xc000,%dx
inw %dx,%ax
outw %ax,%dx
movw $0xc002,%dx
movb $0x1a,%al
outb %al,%dx
movw $0xc000,%dx
3:
inb %dx,%al
movb %al,%bl
orb $0x36,%al
jz 3b
orb $0x10,%bl
jz 4f
ret
4:
push %ecx
xor %ecx,%ecx
l2: loop l2
pop %ecx
dec %ecx
jz 5f
jmp 2b
5:
ret
/*
* changes the front led
*
* void pic16l_setled (int val);
*/
ENTRY(pic16l_setled)
push %ebp
mov %esp,%ebp
push %ebx
movl 0x8(%ebp),%ebx
orl $0x800,%ebx
call pic16l_ledhlp
movl $0x701,%ebx
call pic16l_ledhlp
pop %ebx
leave
ret

60
sys/i386/xbox/xbox.c Normal file
View File

@ -0,0 +1,60 @@
/*-
* Copyright (c) 2005 Rink Springer
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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$
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/eventhandler.h>
#include <sys/reboot.h>
#include <machine/xbox.h>
#include "opt_global.h"
#ifndef I686_CPU
#error You must have a I686_CPU in your kernel if you want to make an XBOX-compitable kernel
#endif
static void
xbox_poweroff(void* junk, int howto)
{
if (!(howto & RB_POWEROFF))
return;
pic16l_poweroff();
}
static void
xbox_init(void)
{
if (!arch_i386_is_xbox)
return;
/* register our poweroff function */
EVENTHANDLER_REGISTER (shutdown_final, xbox_poweroff, NULL,
SHUTDOWN_PRI_LAST);
}
SYSINIT(xbox, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, xbox_init, NULL)

398
sys/i386/xbox/xboxfb.c Normal file
View File

@ -0,0 +1,398 @@
/*-
* Copyright (c) 2005 Rink Springer
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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$
*/
/*
* This will handles video output using the XBOX' frame buffer. It assumes
* the graphics have been set up by Cromwell. This driver uses all video memory
* to avoid expensive memcpy()'s.
*
* It is usuable as console (to see the initial boot) as well as for interactive
* use. The latter is handeled using kbd_*() functionality. Keyboard hotplug is
* fully supported, the console will periodically rescan if no keyboard was
* found.
*
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <vm/vm_param.h>
#include <sys/kernel.h>
#include <sys/cons.h>
#include <sys/conf.h>
#include <sys/consio.h>
#include <sys/tty.h>
#include <sys/kbio.h>
#include <sys/fbio.h>
#include <dev/kbd/kbdreg.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
#include <machine/xbox.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/gfb.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 4
#define SCREEN_SIZE (SCREEN_WIDTH*SCREEN_HEIGHT*SCREEN_BPP)
/* FONT_xxx declares the dimensions of the charachter structure, CHAR_xxx is how
* they appear on-screen. Having slightly more spacing improves readability. */
#define FONT_HEIGHT 16
#define FONT_WIDTH 8
#define CHAR_HEIGHT 16
#define CHAR_WIDTH 10
#define RAM_SIZE (arch_i386_xbox_memsize * 1024 * 1024)
#define FB_SIZE (0x400000)
#define FB_START (0xf0000000 | (RAM_SIZE - FB_SIZE))
#define FB_START_PTR (0xFD600800)
/* colours */
#define CONSOLE_COL 0xFF88FF88 /* greenish */
#define NORM_COL 0xFFAAAAAA /* grayish */
#define BLACK_COL 0x00000000 /* black */
static int xcon_x = 0;
static int xcon_y = 0;
static int xcon_yoffs = 0;
extern struct gfb_font bold8x16;
static char* xcon_map;
static int* xcon_memstartptr;
static struct tty* xboxfb_tp = NULL;
static struct keyboard* xbfb_kbd = NULL;
static int xbfb_keyboard = -1;
static d_open_t xboxfb_dev_open;
static d_close_t xboxfb_dev_close;
static int xboxfb_kbdevent(keyboard_t* thiskbd, int event, void* arg);
static struct cdevsw xboxfb_cdevsw = {
.d_version = D_VERSION,
.d_open = xboxfb_dev_open,
.d_close = xboxfb_dev_close,
.d_name = "xboxfb",
.d_flags = D_TTY | D_NEEDGIANT,
};
static void
xcon_probe(struct consdev* cp)
{
if (arch_i386_is_xbox)
cp->cn_pri = CN_REMOTE;
else
cp->cn_pri = CN_DEAD;
}
static int
xcon_getc(struct consdev* cp)
{
return 0;
}
static int
xcon_checkc(struct consdev* cp)
{
return 0;
}
static void
xcon_real_putc(int basecol, int c)
{
int i, j, ch = c, col;
char mask;
int* ptri = (int*)xcon_map;
/* special control chars */
switch (ch) {
case '\r': /* carriage return */
xcon_x = 0;
return;
case '\n': /* newline */
xcon_y += CHAR_HEIGHT;
goto scroll;
case 7: /* beep */
return;
case 8: /* backspace */
if (xcon_x > 0) {
xcon_x -= CHAR_WIDTH;
} else {
if (xcon_y > CHAR_HEIGHT) {
xcon_y -= CHAR_HEIGHT;
xcon_x = (SCREEN_WIDTH - CHAR_WIDTH);
}
}
return;
case 9: /* tab */
xcon_real_putc (basecol, ' ');
while ((xcon_x % (8 * CHAR_WIDTH)) != 0) {
xcon_real_putc (basecol, ' ');
}
return;
}
ptri += (xcon_y * SCREEN_WIDTH) + xcon_x;
/* we plot the font pixel-by-pixel. bit 7 is skipped as it renders the
* console unreadable ... */
for (i = 0; i < FONT_HEIGHT; i++) {
mask = 0x40;
for (j = 0; j < FONT_WIDTH; j++) {
col = (bold8x16.data[(ch * FONT_HEIGHT) + i] & mask) ? basecol : BLACK_COL;
*ptri++ = col;
mask >>= 1;
}
ptri += (SCREEN_WIDTH - FONT_WIDTH);
}
xcon_x += CHAR_WIDTH;
if (xcon_x >= SCREEN_WIDTH) {
xcon_x = 0;
xcon_y += CHAR_HEIGHT;
}
scroll:
if (((xcon_yoffs + CHAR_HEIGHT) * SCREEN_WIDTH * SCREEN_BPP) > (FB_SIZE - SCREEN_SIZE)) {
/* we are about to run out of video memory, so move everything
* back to the beginning of the video memory */
memcpy ((char*)xcon_map,
(char*)(xcon_map + (xcon_yoffs * SCREEN_WIDTH * SCREEN_BPP)),
SCREEN_SIZE);
xcon_y -= xcon_yoffs; xcon_yoffs = 0;
*xcon_memstartptr = FB_START;
}
/* we achieve much faster scrolling by just altering the video memory
* address base. once all memory is used, we return to the beginning
* again */
while ((xcon_y - xcon_yoffs) >= SCREEN_HEIGHT) {
xcon_yoffs += CHAR_HEIGHT;
memset ((char*)(xcon_map + (xcon_y * SCREEN_WIDTH * SCREEN_BPP)), 0, CHAR_HEIGHT * SCREEN_WIDTH * SCREEN_BPP);
*xcon_memstartptr = FB_START + (xcon_yoffs * SCREEN_WIDTH * SCREEN_BPP);
}
}
static void
xcon_putc(struct consdev* cp, int c)
{
xcon_real_putc (CONSOLE_COL, c);
}
static void
xcon_init(struct consdev* cp)
{
int i;
int* iptr;
/* Don't init the framebuffer on non-XBOX-es */
if (!arch_i386_is_xbox)
return;
/*
* We must make a mapping from video framebuffer memory to real. This is
* very crude: we map the entire videomemory to PAGE_SIZE! Since our
* kernel lives at it's relocated address range (0xc0xxxxxx), it won't
* care.
*
* We use address PAGE_SIZE and up so we can still trap NULL pointers.
* Once xboxfb_drvinit() is called, the mapping will be done via the OS
* and stored in a more sensible location ... but since we're not fully
* initialized, this is our only way to go :-(
*/
for (i = 0; i < (FB_SIZE / PAGE_SIZE); i++) {
pmap_kenter (((i + 1) * PAGE_SIZE), FB_START + (i * PAGE_SIZE));
}
pmap_kenter ((i + 1) * PAGE_SIZE, FB_START_PTR - FB_START_PTR % PAGE_SIZE);
xcon_map = (char*)PAGE_SIZE;
xcon_memstartptr = (int*)((i + 1) * PAGE_SIZE + FB_START_PTR % PAGE_SIZE);
/* clear the screen */
iptr = (int*)xcon_map;
for (i = 0; i < SCREEN_HEIGHT * SCREEN_WIDTH; i++)
*iptr++ = BLACK_COL;
sprintf(cp->cn_name, "xboxfb");
cp->cn_tp = xboxfb_tp;
}
static void
xboxfb_timer(void* arg)
{
int i;
if (xbfb_kbd != NULL)
return;
i = kbd_allocate ("*", 0, (void*)&xbfb_keyboard, xboxfb_kbdevent, NULL);
if (i != -1) {
/* allocation was successfull; xboxfb_kbdevent() is called to
* feed the keystrokes to the tty driver */
xbfb_kbd = kbd_get_keyboard (i);
xbfb_keyboard = i;
return;
}
/* probe again in a few */
timeout (xboxfb_timer, NULL, hz / 10);
}
static int
xboxfb_kbdevent(keyboard_t* thiskbd, int event, void* arg)
{
int c;
if (event == KBDIO_UNLOADING) {
/* keyboard was unplugged; clean up and enable probing */
xbfb_kbd = NULL;
xbfb_keyboard = -1;
kbd_release (thiskbd, (void*)&xbfb_keyboard);
timeout (xboxfb_timer, NULL, hz / 10);
return 0;
}
for (;;) {
c = (kbdsw[xbfb_kbd->kb_index])->read_char (xbfb_kbd, 0);
if (c == NOKEY)
return 0;
/* only feed non-special keys to an open console */
if (c != ERRKEY) {
if ((KEYFLAGS(c)) == 0x0)
if (xboxfb_tp->t_state & TS_ISOPEN)
ttyld_rint (xboxfb_tp, KEYCHAR(c));
}
}
return 0;
}
static void
xboxfb_drvinit (void* unused)
{
struct cdev* dev;
int i;
/* Don't init the framebuffer on non-XBOX-es */
if (!arch_i386_is_xbox)
return;
/*
* When this function is called, the OS is capable of doing
* device-memory mappings using pmap_mapdev(). Therefore, we ditch the
* ugly PAGE_SIZE-based mapping and ask the OS to create a decent
* mapping for us.
*/
dev = make_dev (&xboxfb_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "%s", "xboxfb");
xcon_map = pmap_mapdev (FB_START, FB_SIZE);
xcon_memstartptr = (int*)pmap_mapdev (FB_START_PTR, PAGE_SIZE);
*xcon_memstartptr = FB_START;
/* ditch all ugly previous mappings */
for (i = 0; i < (FB_SIZE / PAGE_SIZE); i++) {
pmap_kremove (((i + 1) * PAGE_SIZE));
}
pmap_kremove (PAGE_SIZE + FB_SIZE);
/* probe for a keyboard */
xboxfb_timer (NULL);
}
static void
xboxfb_tty_start(struct tty* tp)
{
struct clist* cl;
int len, i;
u_char buf[128];
if (tp->t_state & TS_BUSY)
return;
/* simply feed all outstanding tty data to real_putc() */
tp->t_state |= TS_BUSY;
cl = &tp->t_outq;
len = q_to_b(cl, buf, 128);
for (i = 0; i < len; i++)
xcon_real_putc(NORM_COL, buf[i]);
tp->t_state &= ~TS_BUSY;
}
static void
xboxfb_tty_stop(struct tty* tp, int flag) {
if (tp->t_state & TS_BUSY)
if ((tp->t_state & TS_TTSTOP) == 0)
tp->t_state |= TS_FLUSH;
}
static int
xboxfb_tty_param(struct tty* tp, struct termios* t)
{
return 0;
}
static int
xboxfb_dev_open(struct cdev* dev, int flag, int mode, struct thread* td)
{
struct tty* tp;
tp = xboxfb_tp = dev->si_tty = ttymalloc (xboxfb_tp);
tp->t_oproc = xboxfb_tty_start;
tp->t_param = xboxfb_tty_param;
tp->t_stop = xboxfb_tty_stop;
tp->t_dev = dev;
if ((tp->t_state & TS_ISOPEN) == 0) {
tp->t_state |= TS_CARR_ON;
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
ttsetwater(tp);
}
return ttyld_open (tp, dev);
}
static int
xboxfb_dev_close(struct cdev* dev, int flag, int mode, struct thread* td)
{
struct tty* tp;
tp = xboxfb_tp;
ttyld_close (tp, flag);
tty_close(tp);
return 0;
}
SYSINIT(xboxfbdev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, xboxfb_drvinit, NULL)
CONS_DRIVER(xcon, xcon_probe, xcon_init, NULL, xcon_getc, xcon_checkc, xcon_putc, NULL);

View File

@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include "opt_clock.h"
#include "opt_isa.h"
#include "opt_mca.h"
#include "opt_xbox.h"
#include <sys/param.h>
#include <sys/systm.h>
@ -90,6 +91,10 @@ __FBSDID("$FreeBSD$");
#include <i386/bios/mca_machdep.h>
#endif
#ifdef XBOX
#include <machine/xbox.h>
#endif
/*
* 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
* can use a simple formula for leap years.
@ -522,6 +527,11 @@ calibrate_clocks(void)
return (tot_count);
fail:
#ifdef XBOX
if (arch_i386_is_xbox)
timer_freq = 1125000; /* gives ~733.34MHz CPU clock */
#endif
if (bootverbose)
printf("failed, using default i8254 clock of %u Hz\n",
timer_freq);