diff options
Diffstat (limited to 'cfe/cfe/pccons')
-rw-r--r-- | cfe/cfe/pccons/Makefile | 3 | ||||
-rw-r--r-- | cfe/cfe/pccons/README | 19 | ||||
-rw-r--r-- | cfe/cfe/pccons/dev_pcconsole.c | 339 | ||||
-rw-r--r-- | cfe/cfe/pccons/dev_pcconsole2.c | 298 | ||||
-rw-r--r-- | cfe/cfe/pccons/kbd_subr.c | 371 | ||||
-rw-r--r-- | cfe/cfe/pccons/kbd_subr.h | 82 | ||||
-rw-r--r-- | cfe/cfe/pccons/pcibios.h | 72 | ||||
-rw-r--r-- | cfe/cfe/pccons/vga.h | 76 | ||||
-rw-r--r-- | cfe/cfe/pccons/vga_subr.c | 285 | ||||
-rw-r--r-- | cfe/cfe/pccons/vga_subr.h | 82 | ||||
-rw-r--r-- | cfe/cfe/pccons/vgainit.c | 1164 | ||||
-rw-r--r-- | cfe/cfe/pccons/x86mem.c | 423 | ||||
-rw-r--r-- | cfe/cfe/pccons/x86mem.h | 109 |
13 files changed, 3323 insertions, 0 deletions
diff --git a/cfe/cfe/pccons/Makefile b/cfe/cfe/pccons/Makefile new file mode 100644 index 0000000..09b8610 --- /dev/null +++ b/cfe/cfe/pccons/Makefile @@ -0,0 +1,3 @@ + +CFLAGS += -DCFG_VGACONSOLE=1 +ALLOBJS += vgainit.o vga_subr.o kbd_subr.o x86mem.o dev_pcconsole.o dev_pcconsole2.o diff --git a/cfe/cfe/pccons/README b/cfe/cfe/pccons/README new file mode 100644 index 0000000..0160ad5 --- /dev/null +++ b/cfe/cfe/pccons/README @@ -0,0 +1,19 @@ + +This directory contains "PC Console" routines, to enable the +SWARM board to use PC-style devices for its console. In +particular, it contains the code to use the X86 emulator +to initialize the VGA, and code to map scan codes to +ASCII characters for a PC keyboard. + +What is this good for, you ask? Just for fun, mostly. Many of +us have had this screwy notion that a SWARM could be used as +a Linux "workstation" if we could get VGA support and USB +keyboards implemented (oh, yeah, and there's this whole +matter of PC console support in Linux, and X, and ...). + +Like the USB host stack, this is among the least-supported +portions of CFE. If you find it useful, great! If it doesn't +work or build properly, let us know, but we may not get to fixing +it right away. + + diff --git a/cfe/cfe/pccons/dev_pcconsole.c b/cfe/cfe/pccons/dev_pcconsole.c new file mode 100644 index 0000000..fe85eca --- /dev/null +++ b/cfe/cfe/pccons/dev_pcconsole.c @@ -0,0 +1,339 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PC Console driver File: dev_pcconsole.c + * + * A console driver for a PC-style keyboard and mouse + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + + + +#include "sbmips.h" +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "cfe_iocb.h" +#include "cfe_device.h" + +#include "lib_physio.h" + +#include "kbd_subr.h" +#include "vga_subr.h" + +#include "bsp_config.h" +#include "pcireg.h" +#include "pcivar.h" + + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define KBD_RXFULL 1 /* bit set if kb has data */ +#define KBD_TXFULL 2 /* bit set if we can send cmd */ +#define VGA_TEXTBUF_COLOR 0xB8000 /* VGA frame buffer */ + +#if defined(_P5064_) || defined(_P6064_) + #define PCI_MEM_SPACE 0x10000000 /* 128MB: s/w configurable */ + #define __ISAaddr(addr) ((physaddr_t)(PCI_MEM_SPACE+(addr))) +#else + #define __ISAaddr(addr) ((physaddr_t)0x40000000+(addr)) +#endif + +#define cpu_isamap(x,y) __ISAaddr(x) + +/* ********************************************************************* + * Forward references + ********************************************************************* */ + +static void pcconsole_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr); + + +static int pcconsole_open(cfe_devctx_t *ctx); +static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); +static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int pcconsole_close(cfe_devctx_t *ctx); +static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks); + +const static cfe_devdisp_t pcconsole_dispatch = { + pcconsole_open, + pcconsole_read, + pcconsole_inpstat, + pcconsole_write, + pcconsole_ioctl, + pcconsole_close, + pcconsole_poll, + NULL +}; + +const cfe_driver_t pcconsole = { + "PC Console", + "pcconsole", + CFE_DEV_SERIAL, + &pcconsole_dispatch, + pcconsole_probe +}; + + +/* ********************************************************************* + * Structures + ********************************************************************* */ + + +typedef struct pcconsole_s { + vga_term_t vga; + keystate_t ks; + uint32_t kbd_status; + uint32_t kbd_data; +} pcconsole_t; + + +/* ********************************************************************* + * pcconsole_poll(ctx,ticks) + * + * Poll routine - check for new keyboard events + * + * Input parameters: + * ctx - device context + * ticks - current time + * + * Return value: + * nothing + ********************************************************************* */ + + +static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks) +{ + pcconsole_t *softc = ctx->dev_softc; + uint8_t status; + uint8_t b; + + status = inb(softc->kbd_status); + + if (status & KBD_RXFULL) { + b = inb(softc->kbd_data); + kbd_doscan(&(softc->ks),b); + } +} + +/* ********************************************************************* + * pcconsole_waitcmdready(softc) + * + * Wait for the keyboard to be ready to accept a command + * + * Input parameters: + * softc - console structure + * + * Return value: + * nothing + ********************************************************************* */ + +static void pcconsole_waitcmdready(pcconsole_t *softc) +{ + uint8_t status; + uint8_t data; + + for (;;) { + status = inb(softc->kbd_status); /* read status */ + if (status & KBD_RXFULL) { + data = inb(softc->kbd_data); /* get data */ + kbd_doscan(&(softc->ks),data); /* process scan codes */ + } + if (!(status & KBD_TXFULL)) break; /* stop when kbd ready */ + } +} + + +/* ********************************************************************* + * pcconsole_setleds(ks,leds) + * + * Callback from the keyboard routines for setting the LEDS + * + * Input parameters: + * ks - keyboard state + * leds - new LED state + * + * Return value: + * 0 + ********************************************************************* */ + +static int pcconsole_setleds(keystate_t *ks,int leds) +{ + pcconsole_t *softc = kbd_getref(ks); + + pcconsole_waitcmdready(softc); + outb(softc->kbd_data,KBDCMD_SETLEDS); + pcconsole_waitcmdready(softc); + outb(softc->kbd_data,(leds & 7)); + + return 0; +} + + +/* ********************************************************************* + * pcconsole_probe(drv,probe_a,probe_b,probe_ptr) + * + * Probe routine. This routine sets up the pcconsole device + * + * Input parameters: + * drv - driver structure + * probe_a + * probe_b + * probe_ptr + * + * Return value: + * nothing + ********************************************************************* */ + +static void pcconsole_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr) +{ + pcconsole_t *softc; + char descr[80]; + volatile uint8_t *isamem; + + /* + * probe_a is + * probe_b is + * probe_ptr is + */ + + softc = (pcconsole_t *) KMALLOC(sizeof(pcconsole_t),0); + if (softc) { + /* + * XXX This should not be hardwired. + */ + softc->kbd_status = 0x64; + softc->kbd_data = 0x60; + kbd_init(&(softc->ks),pcconsole_setleds,softc); + + /* + * XXX this should not be hardwired + */ + isamem = (volatile uint8_t *) ((uintptr_t)cpu_isamap(0,1024*1024)); + vga_init(&(softc->vga),__ISAaddr(VGA_TEXTBUF_COLOR),outb); + + xsprintf(descr,"%s",drv->drv_description,probe_a,probe_b); + cfe_attach(drv,softc,NULL,descr); + } + +} + + +static int pcconsole_open(cfe_devctx_t *ctx) +{ + pcconsole_t *softc = ctx->dev_softc; + + outb(softc->kbd_data,KBDCMD_RESET); /* reset keyboard */ + kbd_init(&(softc->ks),pcconsole_setleds,softc); + vga_clear(&(softc->vga)); + vga_setcursor(&(softc->vga),0,0); + + return 0; +} + +static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + pcconsole_t *softc = ctx->dev_softc; + unsigned char *bptr; + int blen; + + pcconsole_poll(ctx,0); + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + while ((blen > 0) && (kbd_inpstat(&(softc->ks)))) { + *bptr++ = (kbd_read(&(softc->ks)) & 0xFF); + blen--; + } + + buffer->buf_retlen = buffer->buf_length - blen; + return 0; +} + +static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) +{ + pcconsole_t *softc = ctx->dev_softc; + + pcconsole_poll(ctx,0); + + inpstat->inp_status = kbd_inpstat(&(softc->ks)) ? 1 : 0; + + return 0; +} + +static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + pcconsole_t *softc = ctx->dev_softc; + unsigned char *bptr; + int blen; + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + vga_writestr(&(softc->vga),bptr,7,blen); + + buffer->buf_retlen = buffer->buf_length; + return 0; +} + +static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ +/* pcconsole_t *softc = ctx->dev_softc;*/ + + return -1; +} + +static int pcconsole_close(cfe_devctx_t *ctx) +{ +/* pcconsole_t *softc = ctx->dev_softc;*/ + + return 0; +} + + diff --git a/cfe/cfe/pccons/dev_pcconsole2.c b/cfe/cfe/pccons/dev_pcconsole2.c new file mode 100644 index 0000000..e078c13 --- /dev/null +++ b/cfe/cfe/pccons/dev_pcconsole2.c @@ -0,0 +1,298 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PC Console driver File: dev_pcconsole2.c + * + * A console driver for a PC-style keyboard and mouse + * + * This version is for USB keyboards. Someday we'll consolidate + * everything. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + + + +#include "sbmips.h" +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "lib_string.h" + +#include "cfe_iocb.h" +#include "cfe_device.h" +#include "cfe_timer.h" + +#include "lib_physio.h" + +#include "vga_subr.h" + +#include "bsp_config.h" +#include "pcireg.h" +#include "pcivar.h" + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define KBD_RXFULL 1 /* bit set if kb has data */ +#define KBD_TXFULL 2 /* bit set if we can send cmd */ +#define VGA_TEXTBUF_COLOR 0xB8000 /* VGA frame buffer */ + +/* XXX SB1250 specific */ +#define __ISAaddr(x)(0x40000000+(x)) + +/* ********************************************************************* + * Forward references + ********************************************************************* */ + +int pcconsole_enqueue(uint8_t ch); + +static void pcconsole_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr); + + +static int pcconsole_open(cfe_devctx_t *ctx); +static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); +static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); +static int pcconsole_close(cfe_devctx_t *ctx); +static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks); + +const static cfe_devdisp_t pcconsole_dispatch = { + pcconsole_open, + pcconsole_read, + pcconsole_inpstat, + pcconsole_write, + pcconsole_ioctl, + pcconsole_close, + pcconsole_poll, + NULL +}; + +const cfe_driver_t pcconsole2 = { + "PC Console (USB)", + "pcconsole", + CFE_DEV_SERIAL, + &pcconsole_dispatch, + pcconsole_probe +}; + + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +#define KBD_QUEUE_LEN 32 + +typedef struct pcconsole_s { + vga_term_t vga; + int kbd_in; + int kbd_out; + uint8_t kbd_data[KBD_QUEUE_LEN]; +} pcconsole_t; + +static pcconsole_t *pcconsole_current = NULL; + +/* ********************************************************************* + * pcconsole_poll(ctx,ticks) + * + * Poll routine - check for new keyboard events + * + * Input parameters: + * ctx - device context + * ticks - current time + * + * Return value: + * nothing + ********************************************************************* */ + + +static void pcconsole_poll(cfe_devctx_t *ctx,int64_t ticks) +{ + /* No polling needed, USB will do the work for us */ +} + + + +/* ********************************************************************* + * pcconsole_probe(drv,probe_a,probe_b,probe_ptr) + * + * Probe routine. This routine sets up the pcconsole device + * + * Input parameters: + * drv - driver structure + * probe_a + * probe_b + * probe_ptr + * + * Return value: + * nothing + ********************************************************************* */ + +static void pcconsole_probe(cfe_driver_t *drv, + unsigned long probe_a, unsigned long probe_b, + void *probe_ptr) +{ + pcconsole_t *softc; + char descr[80]; + + /* + * probe_a is + * probe_b is + * probe_ptr is + */ + + softc = (pcconsole_t *) KMALLOC(sizeof(pcconsole_t),0); + if (softc) { + + memset(softc,0,sizeof(pcconsole_t)); + + /* + * XXX this should not be hardwired + */ + vga_init(&(softc->vga),__ISAaddr(VGA_TEXTBUF_COLOR),outb); + + xsprintf(descr,"%s",drv->drv_description,probe_a,probe_b); + cfe_attach(drv,softc,NULL,descr); + } + +} + + +static int pcconsole_open(cfe_devctx_t *ctx) +{ + pcconsole_t *softc = ctx->dev_softc; + + pcconsole_current = softc; + + softc->kbd_in = 0; + softc->kbd_out = 0; + + vga_clear(&(softc->vga)); + vga_setcursor(&(softc->vga),0,0); + + return 0; +} + +static int pcconsole_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + pcconsole_t *softc = ctx->dev_softc; + unsigned char *bptr; + int blen; + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + while ((blen > 0) && (softc->kbd_in != softc->kbd_out)) { + *bptr++ = softc->kbd_data[softc->kbd_out]; + softc->kbd_out++; + if (softc->kbd_out >= KBD_QUEUE_LEN) { + softc->kbd_out = 0; + } + blen--; + } + + buffer->buf_retlen = buffer->buf_length - blen; + return 0; +} + +static int pcconsole_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) +{ + pcconsole_t *softc = ctx->dev_softc; + + POLL(); + + inpstat->inp_status = (softc->kbd_in != softc->kbd_out); + + return 0; +} + +static int pcconsole_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + pcconsole_t *softc = ctx->dev_softc; + unsigned char *bptr; + int blen; + + bptr = buffer->buf_ptr; + blen = buffer->buf_length; + + vga_writestr(&(softc->vga),bptr,7,blen); + + buffer->buf_retlen = buffer->buf_length; + return 0; +} + +static int pcconsole_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ +/* pcconsole_t *softc = ctx->dev_softc;*/ + + return -1; +} + +static int pcconsole_close(cfe_devctx_t *ctx) +{ +/* pcconsole_t *softc = ctx->dev_softc;*/ + pcconsole_current = NULL; + + return 0; +} + +/* + * Called by USB system to queue characters. + */ +int pcconsole_enqueue(uint8_t ch) +{ + int newidx; + + if (!pcconsole_current) return -1; + + newidx = pcconsole_current->kbd_in+1; + if (newidx >= KBD_QUEUE_LEN) newidx = 0; + + if (newidx == pcconsole_current->kbd_out) return -1; + + pcconsole_current->kbd_data[pcconsole_current->kbd_in] = ch; + pcconsole_current->kbd_in = newidx; + + return 0; +} diff --git a/cfe/cfe/pccons/kbd_subr.c b/cfe/cfe/pccons/kbd_subr.c new file mode 100644 index 0000000..860db94 --- /dev/null +++ b/cfe/cfe/pccons/kbd_subr.c @@ -0,0 +1,371 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PC-style keyboard interface File: KBD_SUBR.C + * + * This module converts a stream of scancodes into ASCII + * characters. The scan codes come from a PC-style + * keyboard. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" + +#include "kbd_subr.h" + + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define FLG_SCROLL 0x0001 /* Toggles: same as bit positions for LEDs! */ +#define FLG_NUM 0x0002 +#define FLG_CAPS 0x0004 +#define FLG_SHIFT 0x0008 /* Shifts */ +#define FLG_CTRL 0x0100 +#define FLG_ALT 0x0200 +#define FLG_FKEY 0x0400 /* function keys */ +#define FLG_NKPD 0x0800 /* numeric keypad */ +#define FLG_ASCII 0x1000 /* regular ASCII character */ +#define FLG_NONE 0x2000 +#define FLG_BREAKBIT 0x80 + + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +#define KC_RESPLEN 4 +typedef struct keycode_s { + int kc_type; + char kc_normal[KC_RESPLEN]; + char kc_shifted[KC_RESPLEN]; + char kc_ctrl[KC_RESPLEN]; +} keycode_t; + + +/* ********************************************************************* + * Scan code conversion table + ********************************************************************* */ + +static keycode_t scantable[] = { + { FLG_NONE, "", "", "" }, /* 0 */ + { FLG_ASCII, "\033", "\033", "\033" }, /* 1 ESC */ + { FLG_ASCII, "1", "!", "!" }, /* 2 1 */ + { FLG_ASCII, "2", "@", "\000" }, /* 3 2 */ + { FLG_ASCII, "3", "#", "#" }, /* 4 3 */ + { FLG_ASCII, "4", "$", "$" }, /* 5 4 */ + { FLG_ASCII, "5", "%", "%" }, /* 6 5 */ + { FLG_ASCII, "6", "^", "\036" }, /* 7 6 */ + { FLG_ASCII, "7", "&", "&" }, /* 8 7 */ + { FLG_ASCII, "8", "*", "\010" }, /* 9 8 */ + { FLG_ASCII, "9", "(", "(" }, /* 10 9 */ + { FLG_ASCII, "0", ")", ")" }, /* 11 0 */ + { FLG_ASCII, "-", "_", "\037" }, /* 12 - */ + { FLG_ASCII, "=", "+", "+" }, /* 13 = */ + { FLG_ASCII, "\177", "\177", "\010" }, /* 14 <- */ + { FLG_ASCII, "\t", "\177\t", "\t" }, /* 15 ->| */ + { FLG_ASCII, "q", "Q", "\021" }, /* 16 q */ + { FLG_ASCII, "w", "W", "\027" }, /* 17 w */ + { FLG_ASCII, "e", "E", "\005" }, /* 18 e */ + { FLG_ASCII, "r", "R", "\022" }, /* 19 r */ + { FLG_ASCII, "t", "T", "\024" }, /* 20 t */ + { FLG_ASCII, "y", "Y", "\031" }, /* 21 y */ + { FLG_ASCII, "u", "U", "\025" }, /* 22 u */ + { FLG_ASCII, "i", "I", "\011" }, /* 23 i */ + { FLG_ASCII, "o", "O", "\017" }, /* 24 o */ + { FLG_ASCII, "p", "P", "\020" }, /* 25 p */ + { FLG_ASCII, "[", "{", "\033" }, /* 26 [ */ + { FLG_ASCII, "]", "}", "\035" }, /* 27 ] */ + { FLG_ASCII, "\r", "\r", "\n" }, /* 28 ENT */ + { FLG_CTRL, "", "", "" }, /* 29 CTRL */ + { FLG_ASCII, "a", "A", "\001" }, /* 30 a */ + { FLG_ASCII, "s", "S", "\023" }, /* 31 s */ + { FLG_ASCII, "d", "D", "\004" }, /* 32 d */ + { FLG_ASCII, "f", "F", "\006" }, /* 33 f */ + { FLG_ASCII, "g", "G", "\007" }, /* 34 g */ + { FLG_ASCII, "h", "H", "\010" }, /* 35 h */ + { FLG_ASCII, "j", "J", "\n" }, /* 36 j */ + { FLG_ASCII, "k", "K", "\013" }, /* 37 k */ + { FLG_ASCII, "l", "L", "\014" }, /* 38 l */ + { FLG_ASCII, ";", ":", ";" }, /* 39 ; */ + { FLG_ASCII, "'", "\"", "'" }, /* 40 ' */ + { FLG_ASCII, "`", "~", "`" }, /* 41 ` */ + { FLG_SHIFT, "", "", "" }, /* 42 SHIFT */ + { FLG_ASCII, "\\", "|", "\034" }, /* 43 \ */ + { FLG_ASCII, "z", "Z", "\032" }, /* 44 z */ + { FLG_ASCII, "x", "X", "\030" }, /* 45 x */ + { FLG_ASCII, "c", "C", "\003" }, /* 46 c */ + { FLG_ASCII, "v", "V", "\026" }, /* 47 v */ + { FLG_ASCII, "b", "B", "\002" }, /* 48 b */ + { FLG_ASCII, "n", "N", "\016" }, /* 49 n */ + { FLG_ASCII, "m", "M", "\r" }, /* 50 m */ + { FLG_ASCII, ",", "<", "<" }, /* 51 , */ + { FLG_ASCII, ".", ">", ">" }, /* 52 . */ + { FLG_ASCII, "/", "?", "\037" }, /* 53 / */ + { FLG_SHIFT, "", "", "" }, /* 54 SHIFT */ + { FLG_NKPD, "*", "*", "*" }, /* 55 KP* */ + { FLG_ALT, "", "", "" }, /* 56 ALT */ + { FLG_ASCII, " ", " ", "\000" }, /* 57 SPC */ + { FLG_CAPS, "", "", "" }, /* 58 CAPS */ + { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 59 f1 */ + { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 60 f2 */ + { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 61 f3 */ + { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 62 f4 */ + { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 63 f5 */ + { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 64 f6 */ + { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 65 f7 */ + { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 66 f8 */ + { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 67 f9 */ + { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 68 f10 */ + { FLG_NUM, "", "", "" }, /* 69 NUMLK */ + { FLG_SCROLL, "", "", "" }, /* 70 SCRLK */ + { FLG_NKPD, "7", "\033[H", "7" }, /* 71 KP7 */ + { FLG_NKPD, "8", "\033[A", "8" }, /* 72 KP8 */ + { FLG_NKPD, "9", "\033[I", "9" }, /* 73 KP9 */ + { FLG_NKPD, "-", "-", "-" }, /* 74 KP- */ + { FLG_NKPD, "4", "\033[D", "4" }, /* 75 KP4 */ + { FLG_NKPD, "5", "\033[E", "5" }, /* 76 KP5 */ + { FLG_NKPD, "6", "\033[C", "6" }, /* 77 KP6 */ + { FLG_NKPD, "+", "+", "+" }, /* 78 KP+ */ + { FLG_NKPD, "1", "\033[F", "1" }, /* 79 KP1 */ + { FLG_NKPD, "2", "\033[B", "2" }, /* 80 KP2 */ + { FLG_NKPD, "3", "\033[G", "3" }, /* 81 KP3 */ + { FLG_NKPD, "0", "\033[L", "0" }, /* 82 KP0 */ + { FLG_NKPD, ".", "\177", "." }, /* 83 KP. */ + { FLG_NONE, "", "", "" }, /* 84 0 */ + { FLG_NONE, "100", "", "" }, /* 85 0 */ + { FLG_NONE, "101", "", "" }, /* 86 0 */ + { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 87 f11 */ + { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 88 f12 */ + { FLG_NONE, "102", "", "" }, /* 89 0 */ + { FLG_NONE, "103", "", "" }, /* 90 0 */ + { FLG_NONE, "", "", "" }, /* 91 0 */ + { FLG_NONE, "", "", "" }, /* 92 0 */ + { FLG_NONE, "", "", "" }, /* 93 0 */ + { FLG_NONE, "", "", "" }, /* 94 0 */ + { FLG_NONE, "", "", "" }, /* 95 0 */ + { FLG_NONE, "", "", "" }, /* 96 0 */ + { FLG_NONE, "", "", "" }, /* 97 0 */ + { FLG_NONE, "", "", "" }, /* 98 0 */ + { FLG_NONE, "", "", "" }, /* 99 0 */ + { FLG_NONE, "", "", "" }, /* 100 */ + { FLG_NONE, "", "", "" }, /* 101 */ + { FLG_NONE, "", "", "" }, /* 102 */ + { FLG_NONE, "", "", "" }, /* 103 */ + { FLG_NONE, "", "", "" }, /* 104 */ + { FLG_NONE, "", "", "" }, /* 105 */ + { FLG_NONE, "", "", "" }, /* 106 */ + { FLG_NONE, "", "", "" }, /* 107 */ + { FLG_NONE, "", "", "" }, /* 108 */ + { FLG_NONE, "", "", "" }, /* 109 */ + { FLG_NONE, "", "", "" }, /* 110 */ + { FLG_NONE, "", "", "" }, /* 111 */ + { FLG_NONE, "", "", "" }, /* 112 */ + { FLG_NONE, "", "", "" }, /* 113 */ + { FLG_NONE, "", "", "" }, /* 114 */ + { FLG_NONE, "", "", "" }, /* 115 */ + { FLG_NONE, "", "", "" }, /* 116 */ + { FLG_NONE, "", "", "" }, /* 117 */ + { FLG_NONE, "", "", "" }, /* 118 */ + { FLG_NONE, "", "", "" }, /* 119 */ + { FLG_NONE, "", "", "" }, /* 120 */ + { FLG_NONE, "", "", "" }, /* 121 */ + { FLG_NONE, "", "", "" }, /* 122 */ + { FLG_NONE, "", "", "" }, /* 123 */ + { FLG_NONE, "", "", "" }, /* 124 */ + { FLG_NONE, "", "", "" }, /* 125 */ + { FLG_NONE, "", "", "" }, /* 126 */ + { FLG_NONE, "", "", "" }, /* 127 */ +}; + + +/* ********************************************************************* + * KBD_ENQUEUECHAR(ks,ch) + * + * Put a character on the queue + * + * Input parameters: + * ks - keyboard state + * ch - character to enqueue + * + * Return value: + * nothing + ********************************************************************* */ + +static void kbd_enqueuechar(keystate_t *ks,char ch) +{ + if (((ks->ks_head+1) & (KEYQUEUELEN-1)) == ks->ks_tail) { + /* queue is full */ + return; + } + ks->ks_queue[ks->ks_head] = ch; + ks->ks_head = (ks->ks_head+1) & (KEYQUEUELEN-1); +} + + +/* ********************************************************************* + * KBD_DEQUEUECHAR(ks) + * + * Remove a character from the queue + * + * Input parameters: + * ks - keystate + * + * Return value: + * 0 if no characters in queue + * else character from queue + ********************************************************************* */ +static int kbd_dequeuechar(keystate_t *ks) +{ + char ch; + + if (ks->ks_head == ks->ks_tail) return 0; + + ch = ks->ks_queue[ks->ks_tail]; + ks->ks_tail = (ks->ks_tail+1) & (KEYQUEUELEN-1); + return ch; +} + +/* ********************************************************************* + * KBD_READ(ks) + * + * User call to kbd_dequeuechar - remove a character from + * the queue. + * + * Input parameters: + * ks - keyboard state + * + * Return value: + * character from queue or 0 if no chars + ********************************************************************* */ + +int kbd_read(keystate_t *ks) +{ + return kbd_dequeuechar(ks); +} + +/* ********************************************************************* + * KBD_INPSTAT(ks) + * + * Test input status (see if a character is waiting) + * + * Input parameters: + * ks - keyboard state + * + * Return value: + * 0 if no chars waiting, 1 if characters are waiting + ********************************************************************* */ + +int kbd_inpstat(keystate_t *ks) +{ + return (ks->ks_head != ks->ks_tail); +} + + +/* ********************************************************************* + * KBD_DOSCAN(ks,scan) + * + * Process a scan code from the keyboard. + * + * Input parameters: + * ks - keyboard state + * scan - scan code from the keyboard + * + * Return value: + * nothing + ********************************************************************* */ + +void kbd_doscan(keystate_t *ks,uint8_t scan) +{ + int breakflg; + keycode_t *code = 0; + char *str; + + breakflg = (scan & FLG_BREAKBIT); + scan &= ~FLG_BREAKBIT; + code = &scantable[scan]; + + if (code->kc_type & (FLG_SHIFT|FLG_CTRL|FLG_ALT)) { + if (breakflg) ks->ks_shiftflags &= ~code->kc_type; + else ks->ks_shiftflags |= code->kc_type; + } + if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) { + if (!breakflg) ks->ks_shiftflags ^= code->kc_type; + if (ks->ks_setleds) { + (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM)); + } + } + if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) { + if (ks->ks_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted; + else if (ks->ks_shiftflags & FLG_CTRL) str = code->kc_ctrl; + else str = code->kc_normal; + if (!breakflg) { + while (*str) { + kbd_enqueuechar(ks,*str++); + } + } + } +} + + +/* ********************************************************************* + * KBD_INIT(ks,setleds,ref) + * + * Initialize a keyboard state object. + * + * Input parameters: + * ks - keyboard state + * setleds - routine to call when we want to set the state + * of the keyboard's LEDs + * ref - data to store in the keyboard state object + * + * Return value: + * nothing + ********************************************************************* */ + +void kbd_init(keystate_t *ks,int (*setleds)(keystate_t *,int),void *ref) +{ + memset(ks,0,sizeof(keystate_t)); + ks->ks_setleds = setleds; + ks->ks_ref = ref; +} diff --git a/cfe/cfe/pccons/kbd_subr.h b/cfe/cfe/pccons/kbd_subr.h new file mode 100644 index 0000000..f18f8db --- /dev/null +++ b/cfe/cfe/pccons/kbd_subr.h @@ -0,0 +1,82 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PC-style keyboard interface File: KBD_SUBR.C + * + * This module converts a stream of scancodes into ASCII + * characters. The scan codes come from a PC-style + * keyboard. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define KEYQUEUELEN 16 + +#define KBDCMD_RESET 0xFF +#define KBDCMD_SETLEDS 0xED + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +typedef struct keystate_s { + int ks_shiftflags; + char ks_queue[KEYQUEUELEN]; + int ks_head; + int ks_tail; + int (*ks_setleds)(struct keystate_s *ks,int leds); + void *ks_ref; +} keystate_t; + +/* ********************************************************************* + * Prototypes + ********************************************************************* */ + +int kbd_read(keystate_t *ks); +int kbd_inpstat(keystate_t *ks); +void kbd_init(keystate_t *ks,int (*setleds)(keystate_t *,int),void *ref); +void kbd_doscan(keystate_t *ks,uint8_t scan); +#define kbd_getref(x) ((x)->ks_ref) + + diff --git a/cfe/cfe/pccons/pcibios.h b/cfe/cfe/pccons/pcibios.h new file mode 100644 index 0000000..8da8648 --- /dev/null +++ b/cfe/cfe/pccons/pcibios.h @@ -0,0 +1,72 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * PCI BIOS constants File: PCIBIOS.H + * + * This module contains constants related to the X86's PCI + * BIOS, as described in the PCI BIOS specification. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#define PCIBIOS_FN_MAJOR 0xB1 +#define PCIBIOS_FN_INSTCHK 0x01 +#define PCIBIOS_FN_FINDDEV 0x02 +#define PCIBIOS_FN_FINDCLASS 0x03 +#define PCIBIOS_FN_RDCFGBYTE 0x08 +#define PCIBIOS_FN_RDCFGWORD 0x09 +#define PCIBIOS_FN_RDCFGDWORD 0x0A + +#define PCIBIOS_FN_WRCFGBYTE 0x0B +#define PCIBIOS_FN_WRCFGWORD 0x0C +#define PCIBIOS_FN_WRCFGDWORD 0x0D +#define PCIBIOS_SUCCESSFUL 0 +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 + +#define PCIBIOS_VERSION 0x0210 +#define PCIBIOS_SIGNATURE 0x20494350 + +#define PCIBIOS_ROMSIG_OFFSET 0 +#define PCIBIOS_ROMSIG1 0x55 +#define PCIBIOS_ROMSIG2 0xAA +#define PCIBIOS_ROMSIZE(x) ((unsigned int)(x)*512) + +#define PCIBIOS_ROMSIZE_OFFSET 2 +#define PCIBIOS_ROMENTRY_OFFSET 3 diff --git a/cfe/cfe/pccons/vga.h b/cfe/cfe/pccons/vga.h new file mode 100644 index 0000000..5c43664 --- /dev/null +++ b/cfe/cfe/pccons/vga.h @@ -0,0 +1,76 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * VGA definitions File: VGA.H + * + * This module contains names of the registers and bits + * commonly used on VGA adapters. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + + +#define VGA_GFXCTL_INDEX 0x3CE +#define VGA_GFXCTL_DATA 0x3CF +#define VGA_CRTC_INDEX 0x3D4 +#define VGA_CRTC_DATA 0x3D5 +#define VGA_SEQ_INDEX 0x3C4 +#define VGA_SEQ_DATA 0x3C5 +#define VGA_INPSTATUS_R 0x3C2 +#define VGA_MISCOUTPUT_W 0x3C2 +#define VGA_MISCOUTPUT_R 0x3CC +#define VGA_ATTRIB_INDEX 0x3C0 +#define VGA_ATTRIB_DATA 0x3C1 +#define VGA_FEATURES_W 0x3DA +#define VGA_EXT_INDEX 0x3D6 +#define VGA_EXT_DATA 0x3D7 + +#define CRTC_CURSOR_HIGH 0x0E +#define CRTC_CURSOR_LOW 0x0F + +#define VGA_TEXTBUF_COLOR 0xB8000 +#define VGA_TEXTBUF_MONO 0xB0000 +#define VGA_TEXTBUF_SIZE 0x8000 + +#define VGA_ATTRIB_MONO 7 + +#define VGA_TEXTMODE_COLS 80 +#define VGA_TEXTMODE_ROWS 25 + diff --git a/cfe/cfe/pccons/vga_subr.c b/cfe/cfe/pccons/vga_subr.c new file mode 100644 index 0000000..7704054 --- /dev/null +++ b/cfe/cfe/pccons/vga_subr.c @@ -0,0 +1,285 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * VGA "teletype" routines File: VGA_SUBR.C + * + * These routines implement a simple "glass tty" interface + * to a vga monitor. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_printf.h" +#include "lib_malloc.h" + +#include "lib_physio.h" + +#include "vga_subr.h" +#include "vga.h" + + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define OUTB(vga,port,val) (*((vga)->vga_outb))(port,val) + +#ifdef __MIPSEB +#define VGA_SPACE_CHAR 0x2007 /* belongs somewhere else */ +#else +#define VGA_SPACE_CHAR 0x0720 +#endif + +/* ********************************************************************* + * Data + ********************************************************************* */ + + +/* ********************************************************************* + * VGA_CLEAR(vga) + * + * Clear the VGA screen + * + * Input parameters: + * vga - VGA object + * + * Return value: + * nothing + ********************************************************************* */ + +void vga_clear(vga_term_t *vga) +{ + int idx; + + /* Clear the frame buffer */ + + for (idx = 0; idx < VGA_TEXTBUF_SIZE; idx+=2) { + phys_write16(vga->vga_buffer+idx,VGA_SPACE_CHAR); + } +} + + +/* ********************************************************************* + * VGA_SETCURSOR(vga,x,y) + * + * Set the hardware cursor position + * + * Input parameters: + * vga - VGA object + * x,y - cursor location + * + * Return value: + * nothing + ********************************************************************* */ + +void vga_setcursor(vga_term_t *vga,int x,int y) +{ + unsigned int loc = y*vga->vga_ncols + x; + + OUTB(vga,VGA_CRTC_INDEX,CRTC_CURSOR_HIGH); + OUTB(vga,VGA_CRTC_DATA,(loc >> 8) & 0xFF); + OUTB(vga,VGA_CRTC_INDEX,CRTC_CURSOR_LOW); + OUTB(vga,VGA_CRTC_DATA,(loc >> 0) & 0xFF); + + vga->vga_cursorX = x; + vga->vga_cursorY = y; +} + +/* ********************************************************************* + * VGA_SCROLL(vga) + * + * Scroll the display up one line + * + * Input parameters: + * vga - VGA object + * + * Return value: + * nothing + ********************************************************************* */ + +static void vga_scroll(vga_term_t *vga) +{ + int idx; + int count; + int rowsize; + uint32_t t; + + rowsize = vga->vga_ncols * 2; + count = (vga->vga_nrows-1) * rowsize; + + for (idx = 0; idx < count; idx+=4) { + t = phys_read32(vga->vga_buffer+idx+rowsize); + phys_write32(vga->vga_buffer+idx,t); + } + + for (idx = 0; idx < rowsize; idx += 2) { + phys_write16(vga->vga_buffer+(vga->vga_nrows-1)*rowsize+idx,VGA_SPACE_CHAR); + } + + vga_setcursor(vga,0,vga->vga_nrows-1); +} + +/* ********************************************************************* + * VGA_WRITECHAR(vga,ch,attr) + * + * Write a character to the display. This routine also + * interprets some rudimentary control characters, such + * as tab, backspace, linefeed, and carriage return. + * + * Input parameters: + * vga - VGA object + * ch - character to write + * attr - attribute byte for new character + * + * Return value: + * nothing + ********************************************************************* */ + +void vga_writechar(vga_term_t *vga,uint8_t ch,uint8_t attr) +{ + physaddr_t addr; + + switch (ch) { + case 0x07: + break; + case 0x09: + vga_writechar(vga,' ',attr); + while (vga->vga_cursorX % 8) vga_writechar(vga,' ',attr); + break; + case 0x0A: + vga->vga_cursorY++; + if (vga->vga_cursorY > (vga->vga_nrows-1)) { + vga_scroll(vga); + } + break; + case 0x08: + if (vga->vga_cursorX) { + vga->vga_cursorX--; + addr = vga->vga_buffer + (vga->vga_cursorX*2+vga->vga_cursorY*vga->vga_ncols*2); + phys_write8(addr,' '); + } + break; + case 0x0D: + vga->vga_cursorX = 0; + break; + default: + addr = vga->vga_buffer + (vga->vga_cursorX*2+vga->vga_cursorY*vga->vga_ncols*2); + phys_write8(addr,ch); + phys_write8(addr+1,attr); + vga->vga_cursorX++; + if (vga->vga_cursorX > (vga->vga_ncols-1)) { + vga->vga_cursorX = 0; + vga->vga_cursorY++; + if (vga->vga_cursorY > (vga->vga_nrows-1)) { + vga_scroll(vga); + } + } + break; + } + + vga_setcursor(vga,vga->vga_cursorX,vga->vga_cursorY); +} + +/* ********************************************************************* + * VGA_WRITESTR(vga,str,attr,len) + * + * Write a string of characters to the VGA + * + * Input parameters: + * vga - VGA object + * str - pointer to buffer + * attr - attribute byte for characters we're writing + * len - number of characters to write + * + * Return value: + * nothing + ********************************************************************* */ + +void vga_writestr(vga_term_t *vga,uint8_t *str,uint8_t attr,int len) +{ + while (len) { + vga_writechar(vga,*str,attr); + str++; + len--; + } +} + +/* ********************************************************************* + * VGA_RESET(vga) + * + * (mostly unused) - reset the VGA + * + * Input parameters: + * vga - vga object + * + * Return value: + * nothing + ********************************************************************* */ + +void vga_reset(vga_term_t *vga) +{ + vga_clear(vga); +} + +/* ********************************************************************* + * VGA_INIT(vga,buffer,outfunc) + * + * Initialize a VGA object + * + * Input parameters: + * vga - VGA object + * buffer - pointer to VGA-style frame buffer (physical addr) + * outfunc - pointer to function to write ISA I/O ports + * + * Return value: + * nothing + ********************************************************************* */ + +void vga_init(vga_term_t *vga,physaddr_t buffer,void (*outfunc)(unsigned int port,uint8_t val)) +{ + vga->vga_buffer = buffer; + vga->vga_cursorX = 0; + vga->vga_cursorY = 0; + vga->vga_nrows = VGA_TEXTMODE_ROWS; + vga->vga_ncols = VGA_TEXTMODE_COLS; + vga->vga_outb = outfunc; +} diff --git a/cfe/cfe/pccons/vga_subr.h b/cfe/cfe/pccons/vga_subr.h new file mode 100644 index 0000000..eb0e0e0 --- /dev/null +++ b/cfe/cfe/pccons/vga_subr.h @@ -0,0 +1,82 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * VGA "teletype" routines File: VGA_SUBR.H + * + * These routines implement a simple "glass tty" interface + * to a vga monitor. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +typedef struct vga_term_s { + physaddr_t vga_buffer; + int vga_nrows; + int vga_ncols; + int vga_cursorX; + int vga_cursorY; + void (*vga_outb)(unsigned int isaport,uint8_t val); +} vga_term_t; + +/* ********************************************************************* + * Prototypes + ********************************************************************* */ + + +void vga_clear(vga_term_t *vga); +void vga_setcursor(vga_term_t *vga,int x,int y); +void vga_writechar(vga_term_t *vga,uint8_t ch,uint8_t attr); +void vga_writestr(vga_term_t *vga,uint8_t *str,uint8_t attr,int len); +void vga_reset(vga_term_t *vga); +void vga_init(vga_term_t *vga,physaddr_t buffer,void (*outfunc)(unsigned int port,uint8_t val)); + + + + + + + + + + + diff --git a/cfe/cfe/pccons/vgainit.c b/cfe/cfe/pccons/vgainit.c new file mode 100644 index 0000000..7c22af2 --- /dev/null +++ b/cfe/cfe/pccons/vgainit.c @@ -0,0 +1,1164 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * VGA BIOS initialization File: VGAINIT.C + * + * This module interfaces with the X86 emulator borrowed from + * XFree86 to do VGA initialization. + * + * WARNING: This code is SB1250-specific for now. It's not + * hard to change, but then again, aren't we interested in the 1250? + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +#include "sbmips.h" +#include "lib_types.h" +#include "lib_string.h" +#include "lib_printf.h" +#include "lib_malloc.h" +#include "pcireg.h" +#include "pcivar.h" +#include "cfe_console.h" +#include "vga.h" +#include "pcibios.h" +#include "lib_physio.h" +#include "vga_subr.h" +#include "x86mem.h" +#include "x86emu.h" +#include "env_subr.h" + + +/* ********************************************************************* + * Configuration + ********************************************************************* */ + +#define BYTESONLY 0 /* Always write registers as bytes */ +#define VGAINIT_NOISY 0 /* lots of debug output */ + +/* ********************************************************************* + * ISA port macros - currently SB1250-specific + ********************************************************************* */ + +#define INB(x) inb(x) +#define INW(x) inw(x) +#define INL(x) inl(x) +#define OUTB(x,y) outb(x,y) +#define OUTW(x,y) outw(x,y) +#define OUTL(x,y) outl(x,y) + +/* ********************************************************************* + * ISA memory macros - currently SB1250-specific + ********************************************************************* */ + +typedef uintptr_t vm_offset_t; + +#if defined(_P5064_) || defined(_P6064_) + #define PCI_MEM_SPACE 0x10000000 /* 128MB: s/w configurable */ + #define __ISAaddr(addr) ((physaddr_t)(PCI_MEM_SPACE+(addr))) +#else + #define __ISAaddr(addr) ((physaddr_t)0x40000000+(addr)) +#endif + +#define __ISAreadbyte(addr) phys_read8(__ISAaddr(addr)) +#define __ISAreadword(addr) phys_read16(__ISAaddr(addr)) +#define __ISAreaddword(addr) phys_read32(__ISAaddr(addr)) +#define __ISAwritebyte(addr,data) phys_write8(__ISAaddr(addr),(data)) +#define __ISAwriteword(addr,data) phys_write16(__ISAaddr(addr),(data)) +#define __ISAwritedword(addr,data) phys_write32(__ISAaddr(addr),(data)) + +/* ********************************************************************* + * Other macros + ********************************************************************* */ + +#define OFFSET(addr) (((addr) >> 0) & 0xffff) +#define SEGMENT(addr) (((addr) >> 4) & 0xf000) + +#define BSWAP_SHORT(s) ((((s) >> 8) & 0xFF) | (((s)&0xFF) << 8)) +#define BSWAP_LONG(s) ((((s) & 0xFF000000) >> 24) | \ + (((s) & 0x00FF0000) >> 8) | \ + (((s) & 0x0000FF00) << 8) | \ + (((s) & 0x000000FF) << 24)) + + +#ifdef __MIPSEB +#define CPU_TO_LE16(s) BSWAP_SHORT(s) +#define CPU_TO_LE32(s) BSWAP_LONG(s) +#define LE16_TO_CPU(s) BSWAP_SHORT(s) +#define LE32_TO_CPU(s) BSWAP_LONG(s) +#else +#define CPU_TO_LE16(s) (s) +#define CPU_TO_LE32(s) (s) +#define LE16_TO_CPU(s) (s) +#define LE32_TO_CPU(s) (s) +#endif + + +/* ********************************************************************* + * Prototypes + ********************************************************************* */ + +int vga_biosinit(void); +int vga_probe(void); +extern void ui_restart(int); +void vgaraw_dump(char *tail); +int x86emutest(void); + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +static vga_term_t vga; +static x86mem_t x86mem; + +#define BIOSRAMLOC (0xC0000) +#define STACKSIZE 4096 +#define IRETOFFSET 12 +static uint8_t x86initcode[] = { +#if (VGA_TEXTMODE_ROWS == 60) + 0xB8,0x02,0x4F, /* mov ax,042F */ + 0xBB,0x08,0x01, /* mov bx,0108 */ /* VESA 80x60 */ +#else + 0xB8,0x03,0x00, /* mov AX,0003 */ /* 80x25 mode */ +#endif + + 0xCD,0x10, /* int 10 */ + 0xB8,0x34,0x12, /* mov ax,1234 */ + 0xBB,0x78,0x56, /* mov bx,5678 */ + 0xCC, /* int 3 */ + 0xCF}; /* IRET */ + +static uint8_t x86testcode[] = { + 0x90,0x90,0x90,0x90,0x90, /* nop, nop, nop, nop, nop */ + 0xeb,0x09, /* jmp 10 */ + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, /* 9 nops */ + 0xb8,0x34,0x12, /* mov ax,1234 */ + 0xbb,0x78,0x56, /* mov bx,5678 */ + 0xcc, /* int 3 */ + 0xcf}; /* iret */ + +static uint32_t __ISAreadmem(x86mem_t *mem,uint32_t addr,int size) +{ + unsigned long val; + + switch (size) { + case M_BYTE: + val = __ISAreadbyte(addr); + break; + case M_WORD: + if (BYTESONLY || (addr & 0x1)) { + val = (__ISAreadbyte(addr) | (__ISAreadbyte(addr + 1) << 8)); + } + else { + val = __ISAreadword(addr); + val = LE16_TO_CPU(val); + } + break; + case M_DWORD: + if (BYTESONLY || (addr & 0x3)) { + val = (__ISAreadbyte(addr) | + (__ISAreadbyte(addr + 1) << 8) | + (__ISAreadbyte(addr + 2) << 16) | + (__ISAreadbyte(addr + 3) << 24)); + } + else { + val = __ISAreaddword(addr); + val = LE32_TO_CPU(val); + } + break; + default: + val = 0; + } + + return val; +} + + + +static void __ISAwritemem(x86mem_t *mem,uint32_t addr,uint32_t data,int size) +{ + switch (size) { + case M_BYTE: + __ISAwritebyte(addr, data); + break; + + case M_WORD: + if (BYTESONLY || (addr & 0x1)) { + __ISAwritebyte(addr, data >> 0); + __ISAwritebyte(addr + 1, data >> 8); + } + else { + data = CPU_TO_LE16(data); + __ISAwriteword(addr, data); + } + break; + + case M_DWORD: + if (BYTESONLY || (addr & 0x3)) { + __ISAwritebyte(addr, data >> 0); + __ISAwritebyte(addr + 1, data >> 8); + __ISAwritebyte(addr + 2, data >> 16); + __ISAwritebyte(addr + 3, data >> 24); + } + else { + data = CPU_TO_LE32(data); + __ISAwritedword(addr, data); + } + break; + } +} + + +static u8 __x86emu_rdb(u32 addr) +{ +#if VGAINIT_NOISY + if ((addr < 0x400) || (addr > 0x100000)) { + xprintf("Read %08X (int %02X) ",addr,addr/4); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); + } +#endif + return x86mem_readb(&x86mem,addr); +} + + +static u16 __x86emu_rdw(u32 addr) +{ +#if VGAINIT_NOISY + if ((addr < 0x400) || (addr > 0x100000)) { + xprintf("Read %08X (int %02X) ",addr,addr/4); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); + } +#endif + return x86mem_readw(&x86mem,addr); +} + + +static u32 __x86emu_rdl(u32 addr) +{ +#if VGAINIT_NOISY + if ((addr < 0x400) || (addr > 0x100000)) { + xprintf("Read %08X (int %02X) ",addr,addr/4); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); + } +#endif + return x86mem_readl(&x86mem,addr); +} + + +static void __x86emu_wrb(u32 addr, u8 val) +{ +#if VGAINIT_NOISY + if ((addr < 0x400) || (addr > 0x100000)) { + xprintf("Write %08X (int %02X) ",addr,addr/4); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); + } +#endif + x86mem_writeb(&x86mem,addr,val); +} + + +static void __x86emu_wrw(u32 addr, u16 val) +{ +#if VGAINIT_NOISY + if ((addr < 0x400) || (addr > 0x100000)) { + xprintf("Write %08X %04X (int %02X) ",addr,val,addr/4); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); + } +#endif + x86mem_writew(&x86mem,addr,val); +} + + +static void __x86emu_wrl(u32 addr, u32 val) +{ +#if VGAINIT_NOISY + if ((addr < 0x400) || (addr > 0x100000)) { + xprintf("Write %08X (int %02X) ",addr,addr/4); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); + } +#endif + x86mem_writel(&x86mem,addr,val); +} + + +#define TS_COMMAND 0 +#define TS_DATA1 1 +#define TS_DATA2 2 +static uint16_t timerCount = 0; +static int timerState = TS_COMMAND; +static u8 __x86emu_inb(X86EMU_pioAddr port) +{ + u8 val; + + /* + * Emulate just enough functionality of the + * timer chip to fool the Trident BIOS + */ + if (port == 0x40) { + timerCount++; + switch (timerState) { + case TS_COMMAND: + return 0; + case TS_DATA1: + timerState = TS_DATA1; + return timerCount & 0xFF; + case TS_DATA2: + timerState = TS_COMMAND; + return (timerCount >> 8) & 0xFF; + } + } + + val = INB(port); + +#if VGAINIT_NOISY + /*if (port < 0x100)*/ xprintf("INB %08X %02X\n",port,val); + if (console_status()) ui_restart(0); +#endif + + + return val; +} + + +static u16 __x86emu_inw(X86EMU_pioAddr port) +{ + u16 val; + + val = INW(port); + + val = LE16_TO_CPU(val); + +#if VGAINIT_NOISY + /*if (port < 0x100)*/ xprintf("INW %08X %04X\n",port,val); +#endif + + return val; +} + + +static u32 __x86emu_inl(X86EMU_pioAddr port) +{ + u32 val; + + val = INL(port); + + val = LE32_TO_CPU(val); + +#if VGAINIT_NOISY + /*if (port < 0x100)*/ xprintf("INL %08X %08X\n",port,val); +#endif + + + return val; +} + + +static void __x86emu_outb(X86EMU_pioAddr port, u8 val) +{ + /* + * Emulate just enough functionality of the timer + * chip to fool the Trident BIOS + */ + if (port == 0x43) { + timerCount++; + timerState = TS_DATA1; + return; + } + +#if VGAINIT_NOISY + /*if (port < 0x100)*/ xprintf("OUTB %08X %08X\n",port,val); +#endif + + OUTB(port,val); +} + + +static void __x86emu_outw(X86EMU_pioAddr port, u16 val) +{ + val = CPU_TO_LE16(val); + +#if VGAINIT_NOISY + /*if (port < 0x100)*/ xprintf("OUTW %08X %04X ",port,val); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); +#endif + + OUTW(port,val); +} + + +static void __x86emu_outl(X86EMU_pioAddr port, u32 val) +{ + if (port == 0x2D) return; + + val = CPU_TO_LE32(val); + +#if VGAINIT_NOISY + /*if (port < 0x100)*/ xprintf("OUTL %08X %08X ",port,val); + printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP); +#endif + + + OUTL(port,val); +} + + +static void regs2tag(pcitag_t *tag) +{ + pcitag_t mytag; + int bus,device,function; + + bus = M.x86.R_BH; + device = M.x86.R_BL >> 3; + function = M.x86.R_BL & 0x07; + + mytag = pci_make_tag(bus,device,function); + + *tag = mytag; +} + +static void __SIMint10(int intno) +{ +#if VGAINIT_NOISY + xprintf("Int10: BIOS function AX=%04X\n",M.x86.R_AX); +#endif + + /* + * The only BIOS function that VGAs appear to + * depend on in the real BIOS is the one + * that enables/disables video memory. + */ + + if ((M.x86.R_AH == 0x12) && (M.x86.R_BL == 0x32)) { + if (M.x86.R_AL == 0) { + /* enable video memory */ + __x86emu_outb(VGA_MISCOUTPUT_W, __x86emu_inb(VGA_MISCOUTPUT_R) | 0x02); + return; + } + else if (M.x86.R_AL == 1) { + /* disable video memory */ + __x86emu_outb(VGA_MISCOUTPUT_W, __x86emu_inb(VGA_MISCOUTPUT_R) & ~0x02); + return; + } + else { + xprintf("Int10 unknown function AX=%04X\n", + M.x86.R_AX); + } + } + else { + + /* Otherwise, pass the int10 on to the ROM */ + + X86EMU_prepareForInt(0x10); + } +} + + +static void __SIMint3(int intno) +{ +#if VGAINIT_NOISY + xprintf("Int3: Breakpoint reached.\n"); +#endif + HALT_SYS(); +} + + +static void __SIMintunk(int intno) +{ +#if VGAINIT_NOISY + xprintf("Int%02X: Unhandled interrupt!\n",intno); +#endif + HALT_SYS(); +} + +static void __SIMint42(int intno) +{ +#if VGAINIT_NOISY + xprintf("Int42: Function AX=%04X\n",M.x86.R_AX); +#endif + switch (M.x86.R_AH) { + case 0: + vga_reset(&vga); + break; + default: +#if VGAINIT_NOISY + xprintf("Int42: Unknown INT42 command: %x\n",M.x86.R_AH); +#endif + break; + } +} + + +static void __SIMint6D(int intno) +{ + int reflect = 1; + +#if VGAINIT_NOISY + xprintf("Int6D: Function AX=%04X\n",M.x86.R_AX); +#endif + + switch (M.x86.R_AH) { + case 0: + break; + case 0x13: + if (M.x86.R_AL == 1) { + unsigned long addr; + unsigned long count; + uint8_t ch; + + addr = (M.x86.R_ES << 4) + M.x86.R_BP; + count = M.x86.R_CX; + + while (count) { + ch = __x86emu_rdb(addr); + vga_writechar(&vga,ch,M.x86.R_BL); + addr++; + count--; + } + reflect = 0; + } + break; + default: +#if VGAINIT_NOISY + xprintf("Unknown INT6D command: %x\n",M.x86.R_AH); +#endif + break; + } + + if (reflect) X86EMU_prepareForInt(0x6D); +} + + + +static void __SIMint1A(int intno) +{ + pcitag_t tag; + int bus,device,function; + int ret; + + if (M.x86.R_AH != PCIBIOS_FN_MAJOR) return; + + switch (M.x86.R_AL) { + case PCIBIOS_FN_INSTCHK: + M.x86.R_EAX = 0x00; + M.x86.R_AL = 0x01; + M.x86.R_EDX = PCIBIOS_SIGNATURE; + M.x86.R_EBX = PCIBIOS_VERSION; + M.x86.R_ECX &= 0xFF00; + M.x86.R_CL = 0; /* Highest bus number */ +#ifdef VGAINIT_NOISY + xprintf("Int1A: Installation check\n"); +#endif + CLEAR_FLAG(F_CF); + break; + + case PCIBIOS_FN_FINDDEV: + ret = pci_find_device(M.x86.R_DX,M.x86.R_CX,M.x86.R_SI,&tag); +#if VGAINIT_NOISY + xprintf("Int1A: Find device VID=%04X,DID=%04X,Idx=%d: ", + M.x86.R_DX,M.x86.R_CX,M.x86.R_SI); + if (ret == 0) { + pci_break_tag(tag,&bus,&device,&function); + xprintf("Found Bus%d, Dev%d, Func%d\n",bus,device,function); + } + else { + xprintf("not found.\n"); + } +#endif + if (ret == 0) { + pci_break_tag(tag,&bus,&device,&function); + M.x86.R_BH = bus; + M.x86.R_BL = (device << 3) | function; + M.x86.R_AH = PCIBIOS_SUCCESSFUL; + } + else { + M.x86.R_AH = PCIBIOS_DEVICE_NOT_FOUND; + } + + CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL),F_CF); + break; + + case PCIBIOS_FN_FINDCLASS: + ret = pci_find_class(M.x86.R_ECX,M.x86.R_SI,&tag); +#if VGAINIT_NOISY + xprintf("Int1A: Find Class %08X,Idx=%d: ", + M.x86.R_ECX,M.x86.R_SI); + if (ret == 0) { + pci_break_tag(tag,&bus,&device,&function); + xprintf("Found Bus%d, Dev%d, Func%d\n",bus,device,function); + } + else { + xprintf("not found.\n"); + } +#endif + + if (ret == 0) { + pci_break_tag(tag,&bus,&device,&function); + M.x86.R_BH = bus; + M.x86.R_BL = (device << 3) | function; + M.x86.R_AH = PCIBIOS_SUCCESSFUL; + } + else { + M.x86.R_AH =PCIBIOS_DEVICE_NOT_FOUND; + } + + CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL),F_CF); + break; + + case PCIBIOS_FN_RDCFGBYTE: + regs2tag(&tag); + M.x86.R_CL = pci_conf_read8(tag,M.x86.R_DI); + M.x86.R_AH = PCIBIOS_SUCCESSFUL; +#if VGAINIT_NOISY + xprintf("Int1A: Read Cfg Byte %04X from ",M.x86.R_DI); + pci_break_tag(tag,&bus,&device,&function); + xprintf("Bus%d, Dev%d, Func%d",bus,device,function); + xprintf(": %02X\n",M.x86.R_CX); +#endif + + CLEAR_FLAG(F_CF); + break; + + case PCIBIOS_FN_RDCFGWORD: + regs2tag(&tag); + M.x86.R_CX = pci_conf_read16(tag,M.x86.R_DI); + M.x86.R_AH = PCIBIOS_SUCCESSFUL; +#if VGAINIT_NOISY + xprintf("Int1A: Read Cfg Word %04X from ",M.x86.R_DI); + pci_break_tag(tag,&bus,&device,&function); + xprintf("Bus%d, Dev%d, Func%d",bus,device,function); + xprintf(": %04X\n",M.x86.R_CX); +#endif + CLEAR_FLAG(F_CF); + break; + + case PCIBIOS_FN_RDCFGDWORD: + regs2tag(&tag); + M.x86.R_ECX = pci_conf_read(tag,M.x86.R_DI); +#if VGAINIT_NOISY + xprintf("Int1A: Read Cfg Dword %04X from ",M.x86.R_DI); + pci_break_tag(tag,&bus,&device,&function); + xprintf("Bus%d, Dev%d, Func%d",bus,device,function); + xprintf(": %08X\n",M.x86.R_ECX); +#endif + M.x86.R_AH = PCIBIOS_SUCCESSFUL; + CLEAR_FLAG(F_CF); + break; + + case PCIBIOS_FN_WRCFGBYTE: + regs2tag(&tag); + pci_conf_write8(tag,M.x86.R_DI,M.x86.R_CL); +#if VGAINIT_NOISY + xprintf("Int1A: Write Cfg byte %04X to ",M.x86.R_DI); + pci_break_tag(tag,&bus,&device,&function); + xprintf("Bus%d, Dev%d, Func%d",bus,device,function); + xprintf(": %02X\n",M.x86.R_CL); +#endif + + M.x86.R_AH = PCIBIOS_SUCCESSFUL; + CLEAR_FLAG(F_CF); + break; + + case PCIBIOS_FN_WRCFGWORD: + regs2tag(&tag); + pci_conf_write16(tag,M.x86.R_DI,M.x86.R_CX); +#if VGAINIT_NOISY + xprintf("Int1A: Write Cfg Word %04X to ",M.x86.R_DI); + pci_break_tag(tag,&bus,&device,&function); + xprintf("Bus%d, Dev%d, Func%d",bus,device,function); + xprintf(": %04X\n",M.x86.R_CX); +#endif + M.x86.R_AH = PCIBIOS_SUCCESSFUL; + CLEAR_FLAG(F_CF); + break; + + case PCIBIOS_FN_WRCFGDWORD: + regs2tag(&tag); + pci_conf_write(tag,M.x86.R_DI,M.x86.R_ECX); +#if VGAINIT_NOISY + xprintf("Int1A: Write Cfg Dword %04X to ",M.x86.R_DI); + pci_break_tag(tag,&bus,&device,&function); + xprintf("Bus%d, Dev%d, Func%d",bus,device,function); + xprintf(": %08X\n",M.x86.R_ECX); +#endif + M.x86.R_AH = PCIBIOS_SUCCESSFUL; + CLEAR_FLAG(F_CF); + break; + + default: +#if VGAINIT_NOISY + xprintf("Int1A: Unimplemented PCI BIOS function AX=%04x\n", M.x86.R_AX); +#endif + break; + } +} + + + +static int x86init(void) +{ + /* + * Access functions for I/O ports + */ + static X86EMU_pioFuncs piofuncs = { + __x86emu_inb, + __x86emu_inw, + __x86emu_inl, + __x86emu_outb, + __x86emu_outw, + __x86emu_outl + }; + + /* + * Access functions for memory + */ + static X86EMU_memFuncs memfuncs = { + __x86emu_rdb, + __x86emu_rdw, + __x86emu_rdl, + __x86emu_wrb, + __x86emu_wrw, + __x86emu_wrl + }; + + /* + * Interrupt table + */ + void (*funcs[256])(int num); /* XXX: can be 2 kilobytes! */ + int idx; + + /* + * Establish hooks in the simulator + */ + X86EMU_setupMemFuncs(&memfuncs); + X86EMU_setupPioFuncs(&piofuncs); + + /* + * Decode what X86 software interrupts we need to hook + */ + + for (idx = 0; idx < 256; idx++) { + funcs[idx] = __SIMintunk; /* assume all are bad */ + } + funcs[0x42] = __SIMint42; /* int42: video BIOS */ + funcs[0x1F] = NULL; /* reflect INT1F */ + funcs[0x43] = NULL; /* reflect INT43 */ + funcs[0x6D] = __SIMint6D; /* int6D: video BIOS */ + + funcs[0x03] = __SIMint3; /* int3: firmware exit */ + funcs[0x10] = __SIMint10; /* int10: video BIOS */ + funcs[0x1A] = __SIMint1A; /* int1A: PCI BIOS */ + + X86EMU_setupIntrFuncs(funcs); + + x86mem_init(&x86mem); + x86mem_hook(&x86mem,0xA0000,__ISAreadmem,__ISAwritemem); + x86mem_hook(&x86mem,0xA8000,__ISAreadmem,__ISAwritemem); + x86mem_hook(&x86mem,0xB0000,__ISAreadmem,__ISAwritemem); + x86mem_hook(&x86mem,0xB8000,__ISAreadmem,__ISAwritemem); + + return 0; + +} + + +static void x86uninit(void) +{ + x86mem_uninit(&x86mem); +} + + +int vga_probe(void) +{ + pcitag_t tag; + + if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) { + return 0; + } + + return -1; +} + +int vga_biosinit(void) +{ + physaddr_t biosaddr; + pcitag_t tag; + uint32_t addr; + uint32_t romaddr; + uint32_t destaddr; + uint32_t stackaddr; + uint32_t iretaddr; + unsigned int biossize; + int bus,device,function; + int idx; + int res; + + if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) { + romaddr = pci_conf_read(tag,PCI_MAPREG_ROM); + pci_conf_write(tag,PCI_MAPREG_ROM,romaddr | PCI_MAPREG_ROM_ENABLE); + } + else { + xprintf("No suitable VGA device found in the system.\n"); + return -1; + } + + addr = romaddr; + addr &= PCI_MAPREG_ROM_ADDR_MASK; +#if defined(_P5064_) || defined(_P6064_) + biosaddr = cpu_isamap((vm_offset_t) romaddr,0); +#else + biosaddr = (physaddr_t) romaddr; +#endif + + /* + * Check for the presence of a VGA BIOS on this adapter. + */ + + if (!((phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+0) == PCIBIOS_ROMSIG1) && + (phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+1) == PCIBIOS_ROMSIG2))) { + xprintf("No VGA BIOS on this adapter.\n"); + pci_conf_write(tag,PCI_MAPREG_ROM,romaddr); + return -1; + } + biossize = PCIBIOS_ROMSIZE(phys_read8(biosaddr+PCIBIOS_ROMSIZE_OFFSET)); + +#if VGAINIT_NOISY + xprintf("VGA BIOS size is %d bytes\n",biossize); +#endif + + /* + * Initialize the X86 emulator + */ + + if (x86init() != 0) { + xprintf("X86 emulator did not initialize.\n"); + pci_conf_write(tag,PCI_MAPREG_ROM,romaddr); + return -1; + } + + /* + * Allocate space for the ROM BIOS and the stack. + * The basic layout is: + * + * C000:0000 VGA BIOS + * C000:XXXX end of VGA BIOS, start of stack + * C000:YYYY end of stack, start of init code + * C000:ZZZZ end of allocated memory + * + * We put a little code stub after the stack to allow us to have + * a clean exit from the simulator. + */ + + + destaddr = BIOSRAMLOC; + stackaddr = destaddr + biossize + STACKSIZE; + + /* + * Copy the BIOS from the PCI rom into RAM + */ + +#if VGAINIT_NOISY + xprintf("Copying VGA BIOS to RAM.\n"); +#endif + + for (idx = 0; idx < biossize; idx+=4) { + uint32_t b; + + b = phys_read32(biosaddr+idx); + x86mem_memcpy(&x86mem,destaddr+idx,(uint8_t *) &b,sizeof(uint32_t)); + } + + /* + * Gross! The NVidia TNT2 BIOS expects to + * find a PC ROM BIOS date (just the slashes) + * at the right place in the ROMs. + */ + + x86mem_memcpy(&x86mem,0xFFFF5,"08/13/99",8); + + /* + * Turn off the BIOS ROM, we have our copy now. + */ + + pci_conf_write(tag,PCI_MAPREG_ROM,romaddr); + + /* + * Point certain vectors at a dummy IRET in our code space. + * Some ROMs don't take too kindly to null vectors, like + * the 3dfx Voodoo3 BIOS, which makes sure int1a is + * filled in before it attempts to call it. The + * code here is never really executed, since the emulator + * hooks it. + */ + + iretaddr = stackaddr + IRETOFFSET; + __x86emu_wrw(0x1A*4+0,OFFSET(iretaddr)); + __x86emu_wrw(0x1A*4+2,SEGMENT(iretaddr)); + + + /* + * The actual code begins 3 bytes after the beginning of the ROM. Set + * the start address to the first byte of executable code. + */ + + M.x86.R_CS = SEGMENT(destaddr + PCIBIOS_ROMENTRY_OFFSET); + M.x86.R_IP = OFFSET(destaddr + PCIBIOS_ROMENTRY_OFFSET); + + /* + * Set the stack to point after our copy of the ROM + */ + + M.x86.R_SS = SEGMENT(stackaddr - 8); + M.x86.R_SP = OFFSET(stackaddr - 8); + + /* + * GROSS! The Voodoo3 card expects BP to have + * the following value: + */ + + M.x86.R_BP = 0x197; + + /* + * The PCI BIOS spec says you pass the bus, device, and function + * numbers in the AX register when starting the ROM code. + */ + + pci_break_tag(tag,&bus,&device,&function); + M.x86.R_AH = bus; + M.x86.R_AL = (device << 3) | (function & 7); + + /* + * Arrange for the return address to point to a little piece + * of code that will do an int10 to set text mode, followed + * by storing a couple of simple signatures in the registers, + * and an int3 to stop the simulator. + * + * The location of this piece of code is just after our + * stack, and since the stack grows down, this is in 'stackaddr' + */ + + __x86emu_wrw(stackaddr-8,OFFSET(stackaddr)); + __x86emu_wrw(stackaddr-6,SEGMENT(stackaddr)); + + /* copy in the code. */ + + for (idx = 0; idx < sizeof(x86initcode); idx++) { + __x86emu_wrb(stackaddr+idx,x86initcode[idx]); + } + + /* + * Set up the VGA console descriptor. We need this to process the + * int10's that write firmware copyright notices and such. + */ + + vga_init(&vga,(__ISAaddr(VGA_TEXTBUF_COLOR)),outb); + + /* + * Launch the simulator. + */ + + xprintf("Initializing VGA.\n"); +#ifdef DEBUG + X86EMU_trace_on(); +#endif + X86EMU_exec(); + + /* + * Check for the magic exit values in the registers. These get set + * by the code in the array 'x86initcode' that was loaded above + */ + + if ((M.x86.R_AX == 0x1234) && (M.x86.R_BX == 0x5678)) res = 0; + else res = -1; + + /* + * Done! + */ + + x86uninit(); + + if (res < 0) { + xprintf("VGA initialization failed.\n"); + } + else { + char temp[32]; + char *str = "If you can see this message, the VGA has been successfully initialized!\r\n\r\n"; + + xprintf("VGA initialization successful.\n"); + vga_writestr(&vga,str,0x07,strlen(str)); + + sprintf(temp,"%d",VGA_TEXTMODE_ROWS); + env_setenv("VGA_ROWS",temp,ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN); + sprintf(temp,"%d",VGA_TEXTMODE_COLS); + env_setenv("VGA_COLS",temp,ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN); + + } + + return res; +} + +int x86emutest(void) +{ + uint32_t destaddr; + uint32_t stackaddr; + int res; + + /* + * Initialize the X86 emulator + */ + + if (x86init() != 0) { + xprintf("X86 emulator did not initialize.\n"); + return -1; + } + + destaddr = BIOSRAMLOC; + stackaddr = destaddr + 1024; + + /* + * Copy the BIOS from the PCI rom into RAM + */ + + xprintf("Copying test program to RAM.\n"); + x86mem_memcpy(&x86mem,destaddr,x86testcode,sizeof(x86testcode)); + + /* + * The actual code begins 3 bytes after the beginning of the ROM. Set + * the start address to the first byte of executable code. + */ + + M.x86.R_CS = SEGMENT(destaddr + PCIBIOS_ROMENTRY_OFFSET); + M.x86.R_IP = OFFSET(destaddr + PCIBIOS_ROMENTRY_OFFSET); + + /* + * Set the stack to point after our copy of the ROM + */ + + M.x86.R_SS = SEGMENT(stackaddr - 8); + M.x86.R_SP = OFFSET(stackaddr - 8); + + /* + * Launch the simulator. + */ + + xprintf("Running X86emu test.\n"); +#ifdef DEBUG + X86EMU_trace_on(); +#endif + X86EMU_exec(); + + /* + * Check for the magic exit values in the registers. These get set + * by the code in the array 'x86initcode' that was loaded above + */ + + if ((M.x86.R_AX == 0x1234) && (M.x86.R_BX == 0x5678)) res = 0; + else res = -1; + + /* + * Done! + */ + + x86uninit(); + + if (res < 0) xprintf("X86emu test failed.\n"); + else xprintf("X86emu test successful.\n"); + + return res; +} + + + +void vgaraw_dump(char *tail) +{ + physaddr_t biosaddr; + pcitag_t tag; + uint32_t addr; + uint32_t romaddr; + unsigned int biossize; + int idx; + int res; + + if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) { + romaddr = pci_conf_read(tag,PCI_MAPREG_ROM); + pci_conf_write(tag,PCI_MAPREG_ROM,romaddr | PCI_MAPREG_ROM_ENABLE); + } + else { + xprintf("No suitable VGA device found in the system.\n"); + return ; + } + + addr = romaddr; + addr &= PCI_MAPREG_ROM_ADDR_MASK; + + /* XXX This won't work if the PCI space is remapped somewhere else. */ +#if defined(_P5064_) || defined(_P6064_) + biosaddr = cpu_isamap((vm_offset_t) romaddr,0); +#else + biosaddr = romaddr; +#endif + + /* + * Check for the presence of a VGA BIOS on this adapter. + */ + + xprintf("VGA BIOS is mapped to %08X\n",(uint32_t) biosaddr); + + if (!((phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+0) == PCIBIOS_ROMSIG1) && + (phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+1) == PCIBIOS_ROMSIG2))) { + xprintf("No VGA BIOS on this adapter, assuming 32K ROM\n"); + biossize = 32768; + return; + } + else { + biossize = PCIBIOS_ROMSIZE(phys_read8(biosaddr+PCIBIOS_ROMSIZE_OFFSET)); + xprintf("VGA BIOS size is %d bytes\n",biossize); + } + + for (idx = 0; idx < biossize; idx+=16) { + xprintf("%04X: ",idx); + for (res = 0; res < 16; res++) { + xprintf("%02X ",phys_read8(biosaddr+idx+res)); + } + xprintf("\n"); + if (console_status()) break; + } + +// pci_conf_write(tag,PCI_MAPREG_ROM,romaddr); + +} diff --git a/cfe/cfe/pccons/x86mem.c b/cfe/cfe/pccons/x86mem.c new file mode 100644 index 0000000..2e9c49e --- /dev/null +++ b/cfe/cfe/pccons/x86mem.c @@ -0,0 +1,423 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * X86 simulator sparse memory File: X86MEM.C + * + * This module implements X86 memory for the X86 emulator + * used by the BIOS simulator. To avoid allocating the + * entire 1MB of PC's addressable memory, this is a "sparse" + * memory model, allocating chunks of storage as needed. + * VGA BIOSes seem to do all sorts of bizarre things to memory + * so this helps reduce the total amount we need to allocate + * significantly. + * + * In addition, this module lets the simulator "hook" + * ranges of memory to be handled by a callback + * routine. This is used so that we can redirect + * accesses to VGA memory space to the PCI bus handler. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include "lib_types.h" +#include "lib_string.h" +#include "lib_malloc.h" +#include "lib_printf.h" +#include "x86mem.h" + +/* ********************************************************************* + * Macros + ********************************************************************* */ + +#define BSWAP_SHORT(s) ((((s) >> 8) & 0xFF) | (((s)&0xFF) << 8)) +#define BSWAP_LONG(s) ((((s) & 0xFF000000) >> 24) | \ + (((s) & 0x00FF0000) >> 8) | \ + (((s) & 0x0000FF00) << 8) | \ + (((s) & 0x000000FF) << 24)) + + +/* ********************************************************************* + * X86MEM_INIT() + * + * Initialize an X86mem object + * + * Input parameters: + * mem - X86mem object + * + * Return value: + * nothing + ********************************************************************* */ + +void x86mem_init(x86mem_t *mem) +{ + memset(mem,0,sizeof(mem)); +} + +/* ********************************************************************* + * X86MEM_UNINIT(mem) + * + * Uninitialize an X86mem object, freeing any storage + * associated with it. + * + * Input parameters: + * mem - x86mem object + * + * Return value: + * nothing + ********************************************************************* */ + +void x86mem_uninit(x86mem_t *mem) +{ + int idx; + + for (idx = 0; idx < X86MEM_CHUNKS; idx++) { + if (mem->data[idx]) { + KFREE(mem->data[idx]); + mem->data[idx] = NULL; + } + } +} + +/* ********************************************************************* + * X86MEM_READB(mem,addr) + * + * Read a byte of memory from the X86mem object. + * + * Input parameters: + * mem - x86mem object + * addr - address of byte to read + * + * Return value: + * byte read + ********************************************************************* */ + +uint8_t x86mem_readb(x86mem_t *mem,uint32_t addr) +{ + uint8_t *p; + + if (mem->read[X86MEM_REGION(addr)]) { + return (uint8_t) (*(mem->read[X86MEM_REGION(addr)]))(mem,addr,1); + } + + p = (mem->data[X86MEM_REGION(addr)]); + + if (p) { + return *(p + X86MEM_OFFSET(addr)); + } + else { + return 0; + } +} + +/* ********************************************************************* + * X86MEM_READW(mem,addr) + * + * Read a 16-bit word of memory from the X86mem object. + * + * Input parameters: + * mem - x86mem object + * addr - address of word to read + * + * Return value: + * word read + ********************************************************************* */ + +uint16_t x86mem_readw(x86mem_t *mem,uint32_t addr) +{ + uint8_t *p; + uint16_t ret; + + if (mem->read[X86MEM_REGION(addr)]) { + return (uint8_t) (*(mem->read[X86MEM_REGION(addr)]))(mem,addr,2); + } + + p = (mem->data[X86MEM_REGION(addr)]); + if (!p) return 0; + + if ((addr & 1) || (X86MEM_OFFSET(addr) == X86MEM_CHUNKSIZE-1)) { + + ret = ((uint16_t) x86mem_readb(mem,addr+0)) | + (((uint16_t) x86mem_readb(mem,addr+1)) << 8); + return ret; + } + else { + ret = *((uint16_t *) (p+X86MEM_OFFSET(addr))); +#ifdef __MIPSEB + ret = BSWAP_SHORT(ret); +#endif + } + + return ret; +} + +/* ********************************************************************* + * X86MEM_READL(mem,addr) + * + * Read a 32-bit dword of memory from the X86mem object. + * + * Input parameters: + * mem - x86mem object + * addr - address of dword to read + * + * Return value: + * dword read + ********************************************************************* */ + +uint32_t x86mem_readl(x86mem_t *mem,uint32_t addr) +{ + uint8_t *p; + uint32_t ret; + + if (mem->read[X86MEM_REGION(addr)]) { + return (uint8_t) (*(mem->read[X86MEM_REGION(addr)]))(mem,addr,4); + } + + p = (mem->data[X86MEM_REGION(addr)]); + if (!p) return 0; + + if ((addr & 3) || (X86MEM_OFFSET(addr) >= X86MEM_CHUNKSIZE-3)) { + ret = ((uint32_t) x86mem_readb(mem,addr+0)) | + (((uint32_t) x86mem_readb(mem,addr+1)) << 8) | + (((uint32_t) x86mem_readb(mem,addr+2)) << 16) | + (((uint32_t) x86mem_readb(mem,addr+3)) << 24); + } + else { + ret = *((uint32_t *) (p+X86MEM_OFFSET(addr))); +#ifdef __MIPSEB + ret = BSWAP_LONG(ret); +#endif + } + + return ret; +} + +/* ********************************************************************* + * X86MEM_WRITEB(mem,addr,data) + * + * Write a byte to the X86mem object + * + * Input parameters: + * mem - x86mem object + * addr - address of byte to write + * data - data to write + * + * Return value: + * nothing + ********************************************************************* */ +void x86mem_writeb(x86mem_t *mem,uint32_t addr,uint8_t data) +{ + uint8_t *p; + + if (mem->write[X86MEM_REGION(addr)]) { + (*(mem->write[X86MEM_REGION(addr)]))(mem,addr,data,1); + return; + } + + p = (mem->data[X86MEM_REGION(addr)]); + + if (p) { + *(p + X86MEM_OFFSET(addr)) = data; + } + else { + p = mem->data[X86MEM_REGION(addr)] = KMALLOC(X86MEM_CHUNKSIZE,sizeof(uint32_t)); + if (p) { + memset(p,0,X86MEM_CHUNKSIZE); + *(p + X86MEM_OFFSET(addr)) = data; + } + } +} + +/* ********************************************************************* + * X86MEM_WRITEW(mem,addr,data) + * + * Write a 16-bit word to the X86mem object + * + * Input parameters: + * mem - x86mem object + * addr - address of word to write + * data - data to write + * + * Return value: + * nothing + ********************************************************************* */ +void x86mem_writew(x86mem_t *mem,uint32_t addr,uint16_t data) +{ + uint8_t *p; + + if (mem->write[X86MEM_REGION(addr)]) { + (*(mem->write[X86MEM_REGION(addr)]))(mem,addr,data,2); + return; + } + + p = (mem->data[X86MEM_REGION(addr)]); + + if (!p || (addr & 1) || (X86MEM_OFFSET(addr) == X86MEM_CHUNKSIZE-1)) { + x86mem_writeb(mem,addr+0,(data & 0xFF)); + x86mem_writeb(mem,addr+1,((data >> 8) & 0xFF)); + } + else { +#ifdef __MIPSEB + data = BSWAP_SHORT(data); +#endif + *((uint16_t *) (p+X86MEM_OFFSET(addr))) = data; + } +} + +/* ********************************************************************* + * X86MEM_WRITEL(mem,addr,data) + * + * Write a 32-bit dword to the X86mem object + * + * Input parameters: + * mem - x86mem object + * addr - address of dword to write + * data - data to write + * + * Return value: + * nothing + ********************************************************************* */ +void x86mem_writel(x86mem_t *mem,uint32_t addr,uint32_t data) +{ + uint8_t *p; + + if (mem->write[X86MEM_REGION(addr)]) { + (*(mem->write[X86MEM_REGION(addr)]))(mem,addr,data,4); + return; + } + + p = (mem->data[X86MEM_REGION(addr)]); + + if (!p || (addr & 3) || (X86MEM_OFFSET(addr) >= X86MEM_CHUNKSIZE-3)) { + x86mem_writeb(mem,addr+0,(data & 0xFF)); + x86mem_writeb(mem,addr+1,((data >> 8) & 0xFF)); + x86mem_writeb(mem,addr+2,((data >> 16) & 0xFF)); + x86mem_writeb(mem,addr+3,((data >> 24) & 0xFF)); + } + else { +#ifdef __MIPSEB + data = BSWAP_LONG(data); +#endif + *((uint32_t *) (p+X86MEM_OFFSET(addr))) = data; + } +} + +/* ********************************************************************* + * X86MEM_MEMCPY(mem,dest,src,cnt) + * + * memcpy data into the X86mem object + * + * Input parameters: + * mem - x86mem object + * destaddr - destination x86mem address + * src - source local address + * cnt - number of bytes to copy + * + * Return value: + * nothing + ********************************************************************* */ + +void x86mem_memcpy(x86mem_t *mem,uint32_t destaddr,uint8_t *src,int count) +{ + while (count) { + x86mem_writeb(mem,destaddr,*src); + destaddr++; + src++; + count--; + } +} + + +/* ********************************************************************* + * X86MEM_HOOK(mem,addr,readf,writef) + * + * Establish a hook for a block of simulated memory + * + * Input parameters: + * mem - x86mem object + * addr - address in memory, should be aligned on a "chunk" + * boundary. + * readf - function to call on READ accesses + * writef - function to call on WRITE accesses + * + * Return value: + * nothing + ********************************************************************* */ + +void x86mem_hook(x86mem_t *mem,uint32_t chunkaddr, + uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size), + void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size)) +{ + if (mem->data[X86MEM_REGION(chunkaddr)]) { + KFREE(mem->data[X86MEM_REGION(chunkaddr)]); + mem->data[X86MEM_REGION(chunkaddr)] = NULL; + } + mem->read[X86MEM_REGION(chunkaddr)] = readf; + mem->write[X86MEM_REGION(chunkaddr)] = writef; +} + +/* ********************************************************************* + * X86MEM_HOOK_RANGE(mem,addr,size,readf,writef) + * + * Establish a hook for a block of simulated memory + * + * Input parameters: + * mem - x86mem object + * addr - address in memory, should be aligned on a "chunk" + * boundary. + * size - size of region to hook. Should be a multiple + * of the chunk size + * readf - function to call on READ accesses + * writef - function to call on WRITE accesses + * + * Return value: + * nothing + ********************************************************************* */ + +void x86mem_hook_range(x86mem_t *mem,uint32_t chunkaddr,int size, + uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size), + void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size)) +{ + while (size > 0) { + x86mem_hook(mem,chunkaddr,readf,writef); + size -= X86MEM_CHUNKSIZE; + chunkaddr += X86MEM_CHUNKSIZE; + } +} + diff --git a/cfe/cfe/pccons/x86mem.h b/cfe/cfe/pccons/x86mem.h new file mode 100644 index 0000000..ed9132b --- /dev/null +++ b/cfe/cfe/pccons/x86mem.h @@ -0,0 +1,109 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * X86 simulator sparse memory File: X86MEM.H + * + * This module implements X86 memory for the X86 emulator + * used by the BIOS simulator. To avoid allocating the + * entire 1MB of PC's addressable memory, this is a "sparse" + * memory model, allocating chunks of storage as needed. + * VGA BIOSes seem to do all sorts of bizarre things to memory + * so this helps reduce the total amount we need to allocate + * significantly. + * + * In addition, this module lets the simulator "hook" + * ranges of memory to be handled by a callback + * routine. This is used so that we can redirect + * accesses to VGA memory space to the PCI bus handler. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define X86MEM_CHUNKBITS 15 +#define X86MEM_ADDRESSBITS 20 +#define X86MEM_CHUNKSIZE (1<<X86MEM_CHUNKBITS) +#define X86MEM_CHUNKS (1<<(X86MEM_ADDRESSBITS-X86MEM_CHUNKBITS)) +#define X86MEM_REGION(addr) (((addr) >> X86MEM_CHUNKBITS) & (X86MEM_CHUNKS-1)) +#define X86MEM_OFFSET(addr) ((addr) & (X86MEM_CHUNKSIZE-1)) + +#define M_BYTE 1 +#define M_WORD 2 +#define M_DWORD 4 + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +typedef struct x86mem_s { + uint8_t *data[X86MEM_CHUNKS]; + uint32_t (*read[X86MEM_CHUNKS])(struct x86mem_s *x86mem, + uint32_t addr,int size); + void (*write[X86MEM_CHUNKS])(struct x86mem_s *x86mem, + uint32_t addr,uint32_t val,int size); +} x86mem_t; + +/* ********************************************************************* + * Prototypes + ********************************************************************* */ + +void x86mem_init(x86mem_t *mem); +void x86mem_uninit(x86mem_t *mem); + + +uint8_t x86mem_readb(x86mem_t *mem,uint32_t addr); +uint16_t x86mem_readw(x86mem_t *mem,uint32_t addr); +uint32_t x86mem_readl(x86mem_t *mem,uint32_t addr); + + +void x86mem_writeb(x86mem_t *mem,uint32_t addr,uint8_t data); +void x86mem_writew(x86mem_t *mem,uint32_t addr,uint16_t data); +void x86mem_writel(x86mem_t *mem,uint32_t addr,uint32_t data); +void x86mem_memcpy(x86mem_t *mem,uint32_t destaddr,uint8_t *src,int count); +void x86mem_hook(x86mem_t *mem,uint32_t chunkaddr, + uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size), + void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size)); +void x86mem_hook_range(x86mem_t *mem,uint32_t chunkaddr,int size, + uint32_t (*readf)(x86mem_t *mem,uint32_t addr,int size), + void (*writef)(x86mem_t *mem,uint32_t addr,uint32_t val,int size)); + |