/*
 * Copyright 1999 Egbert Eich
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the authors not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  The authors makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */
#define DELETE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <readline/readline.h>
#include <readline/history.h>
#if defined(__alpha__) || defined (__ia64__)
#include <sys/io.h>
#elif defined(HAVE_SYS_PERM)
#include <sys/perm.h>
#endif
#include "debug.h"
#include "v86bios.h"
#include "pci.h"
#include "AsmMacros.h"

#define SIZE 0x100000
#define VRAM_START 0xA0000
#define VRAM_SIZE 0x1FFFF
#define V_BIOS_SIZE 0x1FFFF
#define BIOS_START 0x7C00            /* default BIOS entry */
#define BIOS_MEM 0x600

//CARD8 code[] = { 0xb8 , 0xf0 , 0xf0, 0xf4 };
#define VB_X(x) (V_BIOS >> x) & 0xFF
CARD8 code[] = { 6, 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xf4 };
//CARD8 code[] = { 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xb8, 0x03, 0x00,
//0xcd, 0x10, 0xf4 };
//CARD8 code[] = {  0xb8 , 0xf0 , 0xf0 ,0xf4 };

int ioperm_list[IOPERM_BITS] = {0,};

static void sig_handler(int);
static int map(void);
static void unmap(void);
static void bootBIOS(CARD16 ax);
static int map_vram(void);
static void unmap_vram(void);
static int copy_vbios(memType v_base);
static int copy_sys_bios(void);
static void save_bios_to_file(void);
static int setup_system_bios(void);
static CARD32 setup_int_vect(void);
#ifdef __ia32__
static CARD32 setup_primary_int_vect(void);
#endif
static int chksum(CARD8 *start);
static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax);
static void print_regs(i86biosRegsPtr regs);
static void print_usage(void);
static void set_hlt(Bool set);
static void set_ioperm(void);

extern void yyparse();

void loadCodeToMem(unsigned char *ptr, CARD8 *code);
void dprint(unsigned long start, unsigned long size);

static int vram_mapped = 0;
static char* bios_var = NULL;
static CARD8 save_msr;
static CARD8 save_pos102;
static CARD8 save_vse;
static CARD8 save_46e8;
static haltpoints hltp[20] = { {0, 0}, };

console Console = {-1,-1};
struct config Config;

int main(int argc,char **argv)
{
    int c;
    
    Config.PrintPort = PRINT_PORT;
    Config.IoStatistics = IO_STATISTICS;
    Config.PrintIrq = PRINT_IRQ;
    Config.PrintPci = PRINT_PCI;
    Config.ShowAllDev = SHOW_ALL_DEV;        
    Config.PrintIp = PRINT_IP;           
    Config.SaveBios = SAVE_BIOS;          
    Config.Trace = TRACE;             
    Config.ConfigActiveOnly = CONFIG_ACTIVE_ONLY;  /* boot */
    Config.ConfigActiveDevice = CONFIG_ACTIVE_DEVICE; /* boot */
    Config.MapSysBios = MAP_SYS_BIOS;        
    Config.Resort = RESORT;  /* boot */          
    Config.FixRom = FIX_ROM;            
    Config.NoConsole = NO_CONSOLE;
    Config.BootOnly = FALSE;
    Config.Verbose = VERBOSE;
    
    opterr = 0;    
    while ((c = getopt(argc,argv,"psicaPStAdbrfnv:?")) != EOF) {
    switch(c) {
    case 'p':
        Config.PrintPort = TRUE;
        break;
    case 's':
        Config.IoStatistics = TRUE;
        break;
    case 'i':
        Config.PrintIrq = TRUE;
        break;
    case 'c':
        Config.PrintPci = TRUE;
        break;
    case 'a':
        Config.ShowAllDev = TRUE;
        break;
    case 'P':
        Config.PrintIp = TRUE;
        break;
    case 'S':
        Config.SaveBios = TRUE;
        break;
    case 't':
        Config.Trace = TRUE;
        break;
    case 'A':
        Config.ConfigActiveOnly = TRUE;
        break;
    case 'd':
        Config.ConfigActiveDevice = TRUE;
        break;
    case 'b':
        Config.MapSysBios = TRUE;
        break;
    case 'r':
        Config.Resort = TRUE;
        break;
    case 'f':
        Config.FixRom = TRUE;
        break;
    case 'n':
        Config.NoConsole = TRUE;
        break;
    case 'v':
        Config.Verbose = strtol(optarg,NULL,0);
        break;
    case '?':
        print_usage();
        break;
    default:
        break;
    }
    }
    
    
    if (!map())
    exit(1);
    
    if (!setup_system_bios())
    exit(1);
    
    iopl(3);

    scan_pci();

    save_msr = inb(0x3CC);
    save_vse = inb(0x3C3);
    save_46e8 = inb(0x46e8);
    save_pos102 = inb(0x102);

    if (Config.BootOnly) {
    
    if (!CurrentPci && !Config.ConfigActiveDevice
        && !Config.ConfigActiveOnly) {
        iopl(0);
        unmap();
        exit (1);
    }
    call_boot(NULL);
    } else {
    using_history();
    yyparse();
    }
    
    unmap();

    pciVideoRestore();
    
    outb(0x102, save_pos102);
    outb(0x46e8, save_46e8);
    outb(0x3C3, save_vse);
    outb(0x3C2, save_msr);

    iopl(0);

    close_console(Console);

    exit(0);
}


void
call_boot(struct device *dev)
{
    int Active_is_Pci = 0;
    CARD32 vbios_base;
    
    CurrentPci = PciList;
    Console = open_console();
    
    set_ioperm();

    
    signal(2,sig_handler);
    signal(11,sig_handler);
    
    /* disable primary card */
    pciVideoRestore(); /* reset PCI state to see primary card */
    outb(0x3C2,~(CARD8)0x03 & save_msr);
    outb(0x3C3,~(CARD8)0x01 & save_vse);
    outb(0x46e8, ~(CARD8)0x08 & save_46e8);
    outb(0x102, ~(CARD8)0x01 & save_pos102);
    
    pciVideoDisable();
    
    while (CurrentPci) {
    CARD16 ax;
    
    if (CurrentPci->active) {
        Active_is_Pci = 1;
        if (!Config.ConfigActiveDevice && !dev) {
        CurrentPci = CurrentPci->next;
        continue;
        }
    } else if (Config.ConfigActiveOnly && !dev) {
        CurrentPci = CurrentPci->next;
        continue;
    }
    if (dev && ((dev->type != PCI)
            || (dev->type == PCI
            && (dev->loc.pci.dev != CurrentPci->dev
                || dev->loc.pci.bus != CurrentPci->bus
                || dev->loc.pci.func != CurrentPci->func)))) {
        CurrentPci = CurrentPci->next;
        continue;
    }
    
    EnableCurrent();
    
    if (CurrentPci->active) {
        outb(0x102, save_pos102);
        outb(0x46e8, save_46e8);
        outb(0x3C3, save_vse);
        outb(0x3C2, save_msr);
    }
    
    /* clear interrupt vectors */
#ifdef __ia32__
    vbios_base = CurrentPci->active ? setup_primary_int_vect()
        : setup_int_vect();
#else
    vbios_base = setup_int_vect();
#endif
    ax = ((CARD16)(CurrentPci->bus) << 8)
        | (CurrentPci->dev << 3) | (CurrentPci->func & 0x7);
    if (Config.Verbose > 1) P_printf("ax: 0x%x\n",ax);
    
    BootBios = findPciByIDs(CurrentPci->bus,CurrentPci->dev,
                   CurrentPci->func);
    if (!((mapPciRom(BootBios) && chksum((CARD8*)V_BIOS))
          || (CurrentPci->active && copy_vbios(vbios_base)))) {
        CurrentPci = CurrentPci->next;
        continue;
    }
    if (!map_vram()) {
        CurrentPci = CurrentPci->next;
        continue;
    }
    if (Config.SaveBios) save_bios_to_file();
    printf("initializing PCI bus: %i dev: %i func: %i\n",CurrentPci->bus,
           CurrentPci->dev,CurrentPci->func);
    bootBIOS(ax);
    unmap_vram();

    if (CurrentPci->active)
        close_console(Console);

    if (dev) return;
    
    CurrentPci = CurrentPci->next;
    }
    
    /* We have an ISA device - configure if requested */
    if (!Active_is_Pci /* no isa card in system! */
    && ((!dev && (Config.ConfigActiveDevice || Config.ConfigActiveOnly))
        || (dev && dev->type == ISA))) {

    pciVideoDisable();

    if (!dev || dev->type == ISA) {
        outb(0x102, save_pos102);
        outb(0x46e8, save_46e8);
        outb(0x3C3, save_vse);
        outb(0x3C2, save_msr);
        
#ifdef __ia32__
        vbios_base = setup_primary_int_vect();
#else
        vbios_base = setup_int_vect();
#endif
        if (copy_vbios(vbios_base)) {
        
        if (Config.SaveBios) save_bios_to_file();
        if  (map_vram()) {
            printf("initializing ISA bus\n");
            bootBIOS(0);
        }
        }
    
        unmap_vram();
        sleep(1);
        close_console(Console);
    }
    }
    
    
}

int  
map(void)
{
    void* mem;
    mem = mmap(0, (size_t)SIZE,
               PROT_EXEC | PROT_READ | PROT_WRITE,
               MAP_FIXED | MAP_PRIVATE | MAP_ANON,
               -1, 0 ); 
    if (mem != 0) {
        perror("anonymous map");
        return (0);
    }
    memset(mem,0,SIZE);

    return (1);
}

static void
unmap(void)
{
    munmap(0,SIZE);
}

static void
bootBIOS(CARD16 ax)
{
    i86biosRegs bRegs;
#ifdef V86BIOS_DEBUG
    printf("starting BIOS\n");
#endif
    setup_io();
    setup_bios_regs(&bRegs, ax);
    loadCodeToMem((unsigned char *) BIOS_START, code);
    do_x86(BIOS_START,&bRegs);
#ifdef V86BIOS_DEBUG
    printf("done\n");
#endif
}

static int
map_vram(void)
{
    int mem_fd;

#ifdef __ia64__
    if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0) 
#else
    if ((mem_fd = open(MEM_FILE,O_RDWR))<0) 
#endif
        {
        perror("opening memory");
        return 0;
    }

#ifdef __alpha__
       if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */
         if (!_bus_base_sparse()) sparse_shift = 0;
         if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift),
                                                 PROT_READ | PROT_WRITE,
                                                 MAP_SHARED,
                                                 mem_fd, (VRAM_START << sparse_shift)
                                                 | _bus_base_sparse())) == (void *) -1)
#else
      if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE,
                         PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
                         mem_fd, VRAM_START) == (void *) -1) 
#endif
      {
        perror("mmap error in map_hardware_ram (1)");
            close(mem_fd);
            return (0);
        }
    vram_mapped = 1;
    close(mem_fd);
    return (1);
}

static void
unmap_vram(void)
{
    if (!vram_mapped) return;
    
    munmap((void*)VRAM_START,VRAM_SIZE);
    vram_mapped = 0;
}

static int
copy_vbios(memType v_base)
{
    int mem_fd;
    unsigned char *tmp;
    int size;

    if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
        perror("opening memory");
        return (0);
    }

    if (lseek(mem_fd,(off_t) v_base, SEEK_SET) != (off_t) v_base) { 
          fprintf(stderr,"Cannot lseek\n");
          goto Error;
      }
    tmp = (unsigned char *)malloc(3);
    if (read(mem_fd, (char *)tmp, (size_t) 3) != (size_t) 3) {
            fprintf(stderr,"Cannot read\n");
        goto Error;
    }
    if (lseek(mem_fd,(off_t) v_base,SEEK_SET) != (off_t) v_base) 
        goto Error;

    if (*tmp != 0x55 || *(tmp+1) != 0xAA ) {
        fprintf(stderr,"No bios found at: 0x%lx\n",v_base);
        goto Error;
    }
#ifdef DEBUG
        dprint((unsigned long)tmp,0x100);
#endif
    size = *(tmp+2) * 512;

    if (read(mem_fd, (char *)v_base, (size_t) size) != (size_t) size) {
            fprintf(stderr,"Cannot read\n");
        goto Error;
    }
    free(tmp);
    close(mem_fd);
    if (!chksum((CARD8*)v_base))
        return (0);

    return (1);

Error:
    perror("v_bios");
    close(mem_fd);
    return (0);
}

static int
copy_sys_bios(void)
{
#define SYS_BIOS 0xF0000
    int mem_fd;

    if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
        perror("opening memory");
        return (0);
    }
  
    if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS) 
        goto Error;
    if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF) 
        goto Error;

    close(mem_fd);
    return (1);

Error:
    perror("sys_bios");
    close(mem_fd);
    return (0);
}

void
loadCodeToMem(unsigned char *ptr, CARD8 code[])
{
    int i;
    CARD8 val;
    int size = code[0];
    
    for ( i=1;i<=size;i++) {
        val = code[i];
        *ptr++ = val;
    }
    return;
}
        
void 
dprint(unsigned long start, unsigned long size)
{
    int i,j;
    char *c = (char *)start;

    for (j = 0; j < (size >> 4); j++) {
    char *d = c;
    printf("\n0x%lx:  ",(unsigned long)c);
    for (i = 0; i<16; i++) 
        printf("%2.2x ",(unsigned char) (*(c++)));
    c = d;
    for (i = 0; i<16; i++) {
        printf("%c",((((CARD8)(*c)) > 32) && (((CARD8)(*c)) < 128)) ?
           (unsigned char) (*(c)): '.');
        c++;
    }
    }
    printf("\n");
}

static void
save_bios_to_file(void)
{
    static int num = 0;
    int size, count;
    char file_name[256];
    int fd;
    
    sprintf(file_name,"bios_%i.fil",num);
    if ((fd =  open(file_name,O_WRONLY | O_CREAT | O_TRUNC,00644)) == -1)
        return;
    size = (*(unsigned char*)(V_BIOS + 2)) * 512;
#ifdef V86BIOS_DEBUG
    dprint(V_BIOS,20);
#endif
    if ((count = write(fd,(void *)(V_BIOS),size)) != size)
        fprintf(stderr,"only saved %i of %i bytes\n",size,count);
    num++;
}

static void
sig_handler(int unused)
{
    fflush(stdout);
    fflush(stderr);

    /* put system back in a save state */
    unmap_vram();
    pciVideoRestore();
    outb(0x102, save_pos102);
    outb(0x46e8, save_46e8);
    outb(0x3C3, save_vse);
    outb(0x3C2, save_msr);

    close_console(Console);
    iopl(0);
    unmap();

    exit(1);
}

/*
 * For initialization we just pass ax to the BIOS.
 * PCI BIOSes need this. All other register are set 0.
 */
static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax)
{
    regs->ax = ax;
    regs->bx = 0;
    regs->cx = 0;
    regs->dx = 0;
    regs->es = 0;
    regs->ds = 0x40;               /* standard pc ds */
    regs->si = 0;
    regs->di = 0;
}

/*
 * here we are really paranoid about faking a "real"
 * BIOS. Most of this information was pulled from
 * dosem.
 */

#ifdef __ia32__
static CARD32
setup_primary_int_vect(void)
{
    int mem_fd;
    CARD32 vbase;
    void *map;

    if ((mem_fd = open(MEM_FILE,O_RDWR))<0) 
            {
    perror("opening memory");
    return (0);
    }
  
    if ((map = mmap((void *) 0, (size_t) 0x2000,
         PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED,
         mem_fd, 0)) == (void *)-1)   {
    perror("mmap error in map_hardware_ram (2)");
    close(mem_fd);
    return (0);
    }

    close(mem_fd);
    memcpy(0,map,BIOS_MEM);
    munmap(map,0x2000);
    /*
     * create a backup copy of the bios variables to write back the
     * modified values
     */
    if (!bios_var)
    bios_var = (char *)malloc(BIOS_MEM);
    memcpy(bios_var,0,BIOS_MEM);
    
    vbase = (*((CARD16*)(0x10 << 2) + 1)) << 4;
    if (Config.Verbose > 0) printf("vbase: 0x%x\n",vbase);
    return vbase;
}
#endif

static CARD32
setup_int_vect(void)
{
    const CARD16 cs = 0x0;
    const CARD16 ip = 0x0;
    int i;
    
    /* let the int vects point to the SYS_BIOS seg */
    for (i=0; i<0x80; i++) {
        ((CARD16*)0)[i<<1] = ip;
        ((CARD16*)0)[(i<<1)+1] = cs;
    }
    /* video interrupts default location */
    ((CARD16*)0)[(0x42<<1)+1] = 0xf000;
    ((CARD16*)0)[0x42<<1] = 0xf065;
    ((CARD16*)0)[(0x10<<1)+1] = 0xf000;
    ((CARD16*)0)[0x10<<1] = 0xf065;
    /* video param table default location (int 1d) */
    ((CARD16*)0)[(0x1d<<1)+1] = 0xf000;
    ((CARD16*)0)[0x1d<<1] = 0xf0A4;
    /* font tables default location (int 1F) */
    ((CARD16*)0)[(0x1f<<1)+1] = 0xf000;
    ((CARD16*)0)[0x1f<<1] = 0xfa6e;

    /* int 11 default location */
    ((CARD16*)0)[(0x11<<1)+1] = 0xf000;
    ((CARD16*)0)[0x11<<1] = 0xf84d;
    /* int 12 default location */
    ((CARD16*)0)[(0x12<<1)+1] = 0xf000;
    ((CARD16*)0)[0x12<<1] = 0xf841;
    /* int 15 default location */
    ((CARD16*)0)[(0x15<<1)+1] = 0xf000;
    ((CARD16*)0)[0x15<<1] = 0xf859;
    /* int 1A default location */
    ((CARD16*)0)[(0x1a<<1)+1] = 0xf000;
    ((CARD16*)0)[0x1a<<1] = 0xff6e;
    /* int 05 default location */
    ((CARD16*)0)[(0x05<<1)+1] = 0xf000;
    ((CARD16*)0)[0x05<<1] = 0xff54;
    /* int 08 default location */
    ((CARD16*)0)[(0x8<<1)+1] = 0xf000;
    ((CARD16*)0)[0x8<<1] = 0xfea5;
    /* int 13 default location (fdd) */
    ((CARD16*)0)[(0x13<<1)+1] = 0xf000;
    ((CARD16*)0)[0x13<<1] = 0xec59;
    /* int 0E default location */
    ((CARD16*)0)[(0xe<<1)+1] = 0xf000;
    ((CARD16*)0)[0xe<<1] = 0xef57;
    /* int 17 default location */
    ((CARD16*)0)[(0x17<<1)+1] = 0xf000;
    ((CARD16*)0)[0x17<<1] = 0xefd2;
    /* fdd table default location (int 1e) */
    ((CARD16*)0)[(0x1e<<1)+1] = 0xf000;
    ((CARD16*)0)[0x1e<<1] = 0xefc7;
    return V_BIOS;
}

static int
setup_system_bios(void)
{
    char *date = "06/01/99";
    char *eisa_ident = "PCI/ISA";
    
    if (Config.MapSysBios) {

        if (!copy_sys_bios()) return 0;
        return 1;

    } else {

//    memset((void *)0xF0000,0xf4,0xfff7);
    
        /*
         * we trap the "industry standard entry points" to the BIOS
         * and all other locations by filling them with "hlt"
         * TODO: implement hlt-handler for these
         */
        memset((void *)0xF0000,0xf4,0x10000);
        
        /*
         * TODO: we should copy the fdd table (0xfec59-0xfec5b)
         * the video parameter table (0xf0ac-0xf0fb)
         * and the font tables (0xfa6e-0xfe6d)
         * from the original bios here
         */
    
        /* set bios date */
        strcpy((char *)0xFFFF5,date);
        /* set up eisa ident string */
        strcpy((char *)0xFFFD9,eisa_ident);
        /* write system model id for IBM-AT */
        ((char *)0)[0xFFFFE] = 0xfc;

        return 1;
    }
    
}

static void
update_bios_vars(void)
{
    int mem_fd;
    void *map;
    memType i;
    
#ifdef __ia64__
    if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0) 
#else
    if ((mem_fd = open(MEM_FILE,O_RDWR))<0) 
#endif
            {
    perror("opening memory");
    return;
    }
  
    if ((map = mmap((void *) 0, (size_t) 0x2000,
         PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED,
         mem_fd, 0)) == (void *)-1)   {
    perror("mmap error in map_hardware_ram (3)");
    close(mem_fd);
    return;
    }

    for (i = 0; i < BIOS_MEM; i++) {
    if (bios_var[i] != *(CARD8*)i) 
        *((CARD8*)map + i) = *(CARD8*)i;
    }

    munmap(map,0x2000);
    close(mem_fd);
}

static int
chksum(CARD8 *start)
{
  CARD16 size;
  CARD8 val = 0;
  int i;

  size = *(start+2) * 512;  
  for (i = 0; i<size; i++)
    val += *(start + i);
    
  if (!val)
    return 1;

    fprintf(stderr,"BIOS cksum wrong!\n");
  return 0;
}

void
runINT(int num, i86biosRegsPtr Regs)
{
    Bool isVideo = FALSE;
    CARD8 code_int[] = { 3, 0xcd, 0x00, 0xf4 };

    code_int[2] = (CARD8) num;
    
    if (num == 0x10)
    isVideo = TRUE;
    
    if (!setup_system_bios())
    return;

    if ((isVideo && (!CurrentPci || CurrentPci->active)) || !isVideo) {
    CARD32 vbios_base;

#ifdef __ia32__
    if (!(vbios_base = setup_primary_int_vect()))
#else
    if (!(vbios_base = setup_int_vect()))
#endif
        return;
    if (!copy_vbios(vbios_base))
        return;
    }
    
    if (!map_vram())
    return;
    
#ifdef V86BIOS_DEBUG
        printf("starting BIOS\n");
#endif
    loadCodeToMem((unsigned char *) BIOS_START, code_int);
    setup_io();
    print_regs(Regs);
    set_ioperm();
    set_hlt(TRUE);
    do_x86(BIOS_START,Regs);
    set_hlt(FALSE);
    print_regs(Regs);
    
#ifdef V86BIOS_DEBUG
    printf("done\n");
#endif

    if ((isVideo && (!CurrentPci || CurrentPci->active)) || !isVideo) 
    update_bios_vars();
}

static void
print_regs(i86biosRegsPtr regs)
{
    printf("ax=%x bx=%x cx=%x dx=%x ds=%x es=%x di=%x si=%x\n",
       (CARD16)regs->ax,(CARD16)regs->bx,(CARD16)regs->cx,(CARD16)regs->dx,
       (CARD16)regs->ds,(CARD16)regs->es,(CARD16)regs->di,
       (CARD16)regs->si);
}

static void
print_usage(void)
{
}

void
add_hlt(unsigned long val)
{
    int i;

    if (val < BIOS_MEM || (val > VRAM_START && val < (VRAM_START + VRAM_SIZE))
    || val >= SIZE) {
    printf("address out of range\n");
    return;
    }
    
    for (i=0; i<20; i++) {
    if (hltp[i].address == 0) {
        hltp[i].address = (void*)val;
        break;
    }
    }
    if (i == 20) printf("no more hltpoints available\n");
}

void
del_hlt(int val)
{
    if (val == 21) { /* delete all */
    int i;
    printf("clearing all hltpoints\n");
    for (i=0; i <20; i++)
        hltp[i].address = NULL;
    } else if (val >= 0 &&  val <20)
    hltp[val].address = NULL;
    else printf("hltpoint %i out of range: valid range 0-19\n",val);
}

void
list_hlt()
{
    int i;
    for (i=0; i<20; i++) 
    if (hltp[i].address)
        printf("hltpoint[%i]: 0x%lx\n",i,(unsigned long)hltp[i].address);
}

static void
set_hlt(Bool set)
{
    int i;
    for (i=0; i<20; i++) 
    if (hltp[i].address) {
        if (set) {
        hltp[i].orgval = *(CARD8*)hltp[i].address;
        *(CARD8*)hltp[i].address = 0xf4;
        } else 
        *(CARD8*)hltp[i].address = hltp[i].orgval;
    }
}

static void
set_ioperm(void)
{
    int i, start;

    ioperm(0,IOPERM_BITS,0);

    for (i = 0; i < IOPERM_BITS;i++)
    if (ioperm_list[i]) {
        start = i;
        for (;i < IOPERM_BITS; i++) {
        if (!ioperm_list[i]) {
            ioperm(start,i - start, 1);
            break;
        }
        }
    }
}
