diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 4be8226b08dc..f5de557f27a2 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -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 diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index 7dafd5e1e36f..9e7c6503e1a3 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -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 diff --git a/sys/i386/conf/XBOX b/sys/i386/conf/XBOX new file mode 100644 index 000000000000..e6f7bfb10c33 --- /dev/null +++ b/sys/i386/conf/XBOX @@ -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 diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index fa29b9c4e28b..bb38901ae56c 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include "opt_msgbuf.h" #include "opt_npx.h" #include "opt_perfmon.h" +#include "opt_xbox.h" #include #include @@ -133,6 +134,13 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef XBOX +#include + +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. */ diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 0f0f3ad044b6..d6f654120a49 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -106,6 +106,7 @@ __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include "opt_pmap.h" #include "opt_msgbuf.h" +#include "opt_xbox.h" #include #include @@ -144,6 +145,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef XBOX +#include +#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; diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index ca51b8f77c20..217ae8b85b75 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include "opt_npx.h" #include "opt_reset.h" #include "opt_cpu.h" +#include "opt_xbox.h" #include #include @@ -94,6 +95,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef XBOX +#include +#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; diff --git a/sys/i386/include/xbox.h b/sys/i386/include/xbox.h new file mode 100644 index 000000000000..06db5df7babc --- /dev/null +++ b/sys/i386/include/xbox.h @@ -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_ */ diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c index a4ae751489fe..38b238f6dd92 100644 --- a/sys/i386/isa/clock.c +++ b/sys/i386/isa/clock.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include "opt_clock.h" #include "opt_isa.h" #include "opt_mca.h" +#include "opt_xbox.h" #include #include @@ -90,6 +91,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef XBOX +#include +#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); diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c index adea6dc8037d..869649de34a9 100644 --- a/sys/i386/pci/pci_cfgreg.c +++ b/sys/i386/pci/pci_cfgreg.c @@ -30,6 +30,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_xbox.h" + #include #include #include @@ -49,6 +51,10 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef XBOX +#include +#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 diff --git a/sys/i386/xbox/pic16l.s b/sys/i386/xbox/pic16l.s new file mode 100644 index 000000000000..612c306e5942 --- /dev/null +++ b/sys/i386/xbox/pic16l.s @@ -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 + +.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 diff --git a/sys/i386/xbox/xbox.c b/sys/i386/xbox/xbox.c new file mode 100644 index 000000000000..b0da531c5a74 --- /dev/null +++ b/sys/i386/xbox/xbox.c @@ -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 +#include +#include +#include +#include +#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) diff --git a/sys/i386/xbox/xboxfb.c b/sys/i386/xbox/xboxfb.c new file mode 100644 index 000000000000..6271b8a728e0 --- /dev/null +++ b/sys/i386/xbox/xboxfb.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c index a4ae751489fe..38b238f6dd92 100644 --- a/sys/isa/atrtc.c +++ b/sys/isa/atrtc.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include "opt_clock.h" #include "opt_isa.h" #include "opt_mca.h" +#include "opt_xbox.h" #include #include @@ -90,6 +91,10 @@ __FBSDID("$FreeBSD$"); #include #endif +#ifdef XBOX +#include +#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);