Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

/*
*/


#include <stdlib.h>
#include <stdio.h>              /* for printf */
#include <string.h>             /* for memset */
#include <unistd.h>
//#include <sys/mman.h>         /* for mmap */
#include "vga.h"
#include "libvga.h"
#include "driver.h"

/* New style driver interface. */
#include "timing.h"
#include "vgaregs.h"
#include "interface.h"
#include "lrmi.h"
#include "vbe.h"
#define VESAREG_SAVE(i) (VGA_TOTAL_REGS+i)
#define VESA_TOTAL_REGS (VGA_TOTAL_REGS + 4024)

/* #define VESA_savebitmap 0x0e */
int __svgalib_VESA_savebitmap=0x0e;
int __svgalib_VESA_textmode=3;

static int vesa_init(int, int, int);
static void vesa_unlock(void);

static int vesa_memory,vesa_chiptype;
static int vesa_is_linear, vesa_logical_width, vesa_bpp, vesa_granularity;
static int vesa_regs_size, vesa_linear_base, vesa_last_mode_set;
static struct LRMI_regs vesa_r;
static int vesa_read_write, vesa_read_window, vesa_write_window;
static void * LRMI_mem1, * LRMI_mem2;

static CardSpecs *cardspecs;
static struct
        {
        struct vbe_info_block *info;
        struct vbe_mode_info_block *mode;
        } vesa_data;

static int SVGALIB_VESA[__GLASTMODE+1];

char VideoModeNames [96][40] = {
   "100 - 640x400      256 colors", "101 - 640x480      256 colors",  "102 - 800x600       16 colors",
   "103 - 800x600      256 colors", "104 - 1024x768      16 colors",  "105 - 1024x768     256 colors",
   "106 - 1280x1024     16 colors", "107 - 1280x1024    256 colors",  "108 - 80x60         Text Mode",
   "109 - 132x25        Text Mode", "10A - 132x43        Text Mode",  "10B - 132x50        Text Mode",
   "10C - 132x60        Text Mode", "10D - 320x200   32,768 colors",  "10E - 320x200   65,536 colors",
   "10F - 320x200      16m colors", "110 - 640x480   32,768 colors",  "111 - 640x480   65,536 colors",
   "112 - 640x480      16m colors", "113 - 800x600   32,768 colors",  "114 - 800x600   65,536 colors",
   "115 - 800x600      16m colors", "116 - 1024x768  32,768 colors",  "117 - 1024x768  65,536 colors",
   "118 - 1024x768     16m colors", "119 - 1280x1024 32,768 colors",  "11A - 1280x1024 65,536 colors",
   "11B - 1280x1024    16m colors", "11C - 640x350      256 colors",  "11D - 640x350   32,768 colors",
   "11E - 640x400   32,768 colors", "11F - 640x350   65,536 colors",  "120 - 640x400   65,536 colors",
   "121 - 640x350      16m colors", "122 - 640x400      16m colors",  "123 - 1600x1200     16 colors",
   "124 - 1600x1200    256 colors", "125 - 1600x1200 32,768 colors",  "126 - 1600x1200 65,536 colors",
   "127 - 1600x1200    16m colors", "128 - 640x480   16m colors(*)",  "129 - 800x600   16m colors(*)",
   "12A - 1024x768  16m colors(*)", "12B - 1280x1024 16m colors(*)",  "12C - 1600x1200 16m colors(*)",
   "12D - 320x240   32,768 colors", "12E - 320x400   32,768 colors",  "12F - 360x200   32,768 colors",
   "130 - 360x240   32,768 colors", "131 - 360x400   32,768 colors",  "132 - 320x240   65,536 colors",
   "133 - 320x400   65,536 colors", "134 - 360x200   65,536 colors",  "135 - 360x240   65,536 colors",
   "136 - 360x400   65,536 colors", "137 - 320x240      16m colors",  "138 - 320x400      16m colors",
   "139 - name n/a",                "13A - name n/a",                 "13B - name n/a",
   "13C - name n/a",                "13D - name n/a",                 "13E - name n/a",
   "13F - name n/a",                "140 - name n/a",                 "141 - name n/a",
   "142 - 640x350   16m colors(*)", "143 - 640x400   16m colors(*)",  "144 - name n/a",
   "145 - name n/a",                "146 - name n/a",                 "147 - name n/a",
   "148 - name n/a",                "149 - name n/a",                 "14A - name n/a",
   "14B - name n/a",                "14C - name n/a",                 "14D - name n/a",
   "14E - name n/a",                "14F - name n/a",                 "150 - 640x350       16 colors",
   "151 - 640x400       16 colors", "152 - 640x480       16 colors",  "153 - 320x200      256 colors",
   "154 - 320x240      256 colors", "155 - 320x400      256 colors",  "156 - 360x200      256 colors",
   "157 - 360x240      256 colors", "158 - 360x400      256 colors",  "159 - name n/a",
   "15A - name n/a",                "15B - name n/a",                 "15C - name n/a",
   "15D - name n/a",                "15E - name n/a",                 "15F - name n/a"
};

static void vesa_setpage(int page)
{
vesa_r.eax=0x4f05;
vesa_r.ebx=0;
vesa_r.edx=page*64/vesa_granularity;
__svgalib_LRMI_int(0x10,&vesa_r);

if(vesa_read_write){
   vesa_r.eax=0x4f05;
   vesa_r.ebx=1;
   vesa_r.edx=page*64/vesa_granularity;
   __svgalib_LRMI_int(0x10,&vesa_r);
};
}


static int __svgalib_vesa_inlinearmode(void)
{
return vesa_is_linear;
}


/* Fill in chipset specific mode information */

static void vesa_getmodeinfo(int mode, vga_modeinfo *modeinfo)
{
    if (IS_IN_STANDARD_VGA_DRIVER(mode))
        return __svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo);

    if(modeinfo->colors==16)return;

    modeinfo->maxpixels = vesa_memory*1024/modeinfo->bytesperpixel;
    modeinfo->maxlogicalwidth = 4088; /* just a guess, */
    modeinfo->startaddressrange = vesa_memory * 1024 - 1;
    modeinfo->haveblit = 0;
    modeinfo->flags &= ~HAVE_RWPAGE;
    modeinfo->flags |= vesa_read_write;  /* sets HAVE_RWPAGE bit */

    /* for linear need VBE2 */
    if(vesa_chiptype>=1)
      if (modeinfo->bytesperpixel >= 1) {
        modeinfo->flags |= CAPABLE_LINEAR;
        if (__svgalib_vesa_inlinearmode())
            modeinfo->flags |= IS_LINEAR | LINEAR_MODE;
      }
     
    /* to get the logical scanline width */
    memset(&vesa_r, 0, sizeof(vesa_r));

    vesa_r.eax = 0x4f01;
    vesa_r.ecx = SVGALIB_VESA[mode];
    vesa_r.es = (unsigned int)vesa_data.mode >> 4;
    vesa_r.edi = (unsigned int)vesa_data.mode & 0xf;

    if (!__svgalib_LRMI_int(0x10, &vesa_r)) {
       printk(KERN_ERR "Can't get mode info (vm86 failure)\n");
       return;
    }
    modeinfo->linewidth = vesa_data.mode->bytes_per_scanline;
}

/* Read and save chipset-specific registers */
static int vesa_saveregs(uint8_t regs[])
{
  void * buf;
  buf=LRMI_mem1;
  vesa_r.eax=0x4f04;
  vesa_r.ebx=0;
  vesa_r.es=((long)buf)>>4;
  vesa_r.edx=1;
  vesa_r.ecx=__svgalib_VESA_savebitmap;
  __svgalib_LRMI_int(0x10,&vesa_r);
  memcpy(&regs[VGA_TOTAL_REGS],buf,vesa_regs_size);  
    return vesa_regs_size;
}

/* Set chipset-specific registers */

static void vesa_setregs(const uint8_t regs[], int mode)
{  

  void * buf;
  buf=LRMI_mem1;
  memcpy(buf,&regs[VGA_TOTAL_REGS],vesa_regs_size);  
  vesa_r.eax=0x4f04;
  vesa_r.ebx=0;
  vesa_r.es=((long)buf)>>4;
  vesa_r.edx=2;
  vesa_r.ecx=__svgalib_VESA_savebitmap;
  __svgalib_LRMI_int(0x10,&vesa_r);
}


/* Return nonzero if mode is available */

static int vesa_modeavailable(int mode)
{
    struct info *info;
    ModeTiming *modetiming;
    ModeInfo *modeinfo;


    if (IS_IN_STANDARD_VGA_DRIVER(mode))
        return __svgalib_vga_driverspecs.modeavailable(mode);

    info = &__svgalib_infotable[mode];

    modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode);

    modetiming = malloc(sizeof(ModeTiming));
    if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) {
        free(modetiming);
        free(modeinfo);
        return 0;
    }
    free(modetiming);
    free(modeinfo);

return SVGALIB_VESA[mode];
}


static int vesa_setmode(int mode, int prv_mode)
{
    vesa_bpp=1;
    vesa_granularity=1;
    if (IS_IN_STANDARD_VGA_DRIVER(mode)) {

        if(__svgalib_vesatext){
            vesa_r.eax=0x4f02; /* make sure we are in a regular VGA mode before we start */
            vesa_r.ebx=__svgalib_VESA_textmode;    /* without this, if we start in SVGA mode the result might */
            __svgalib_LRMI_int(0x10,&vesa_r); /* be something weird */
        };
        return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
    }
    if (!vesa_modeavailable(mode)) return 1;
    vesa_r.eax=0x4f02;
    vesa_r.ebx=SVGALIB_VESA[mode]|0x8000|(vesa_is_linear*0x4000);
    vesa_last_mode_set=vesa_r.ebx;
    __svgalib_LRMI_int(0x10,&vesa_r);

    vesa_data.info = LRMI_mem2 ;
    vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1);
    vesa_r.eax = 0x4f01;
    vesa_r.ecx=SVGALIB_VESA[mode];
    vesa_r.es = (unsigned int)vesa_data.mode >> 4;
    vesa_r.edi = (unsigned int)vesa_data.mode&0xf;    
    __svgalib_LRMI_int(0x10, &vesa_r);
    vesa_logical_width=vesa_data.mode->bytes_per_scanline;
    vesa_bpp=(vesa_data.mode->bits_per_pixel+7)/8;
    if(vesa_logical_width==0) vesa_logical_width=vesa_bpp*vesa_data.mode->x_resolution;
                                                /* if not reported then guess */
    vesa_granularity=vesa_data.mode->win_granularity;
    if(vesa_granularity==0)vesa_granularity=64; /* if not reported then guess */
    if(vesa_chiptype>=1)vesa_linear_base=vesa_data.mode->phys_base_ptr;
    vesa_read_write=0;
    vesa_read_window=0;
    vesa_write_window=0;
    if((vesa_data.mode->win_a_attributes&6)!=6){
        vesa_read_write=1;
        if ((vesa_data.mode->win_b_attributes&2) == 2) vesa_read_window=1;
        if ((vesa_data.mode->win_b_attributes&4) == 4) vesa_write_window=1;
    }
    return 0;
}


/* Unlock chipset-specific registers */

static void vesa_unlock(void)
{
}


/* Relock chipset-specific registers */
/* (currently not used) */

static void vesa_lock(void)
{
}


/* Indentify chipset, initialize and return non-zero if detected */

int vesa_test(void)
{
        __svgalib_LRMI_init();
        LRMI_mem2 = __svgalib_LRMI_alloc_real(sizeof(struct vbe_info_block)
                                        + sizeof(struct vbe_mode_info_block));
        vesa_data.info = LRMI_mem2;
        vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1);
        vesa_r.eax = 0x4f00;
        vesa_r.es = (unsigned int)vesa_data.info >> 4;
        vesa_r.ds = (unsigned int)vesa_data.info >> 4;
        vesa_r.edi = 0;

        __svgalib_LRMI_free_real(LRMI_mem2,sizeof(struct vbe_info_block) + sizeof(struct vbe_mode_info_block));

        __svgalib_LRMI_int(0x10, &vesa_r);

        printk(KERN_INFO "Int 0x10 result ax=%2x\n",vesa_r.eax);

        if (vesa_r.eax!=0x4f) return 0;
        return !vesa_init(0,0,0);
}


/* No r/w paging */
static void vesa_setrdpage(int page)
{
vesa_r.eax=0x4f05;
vesa_r.ebx=vesa_read_window;
vesa_r.edx=page*64/vesa_granularity;
__svgalib_LRMI_int(0x10,&vesa_r);
}
static void vesa_setwrpage(int page)
{
vesa_r.eax=0x4f05;
vesa_r.ebx=vesa_write_window;
vesa_r.edx=page*64/vesa_granularity;
__svgalib_LRMI_int(0x10,&vesa_r);
}


/* Set display start address (not for 16 color modes) */

static void vesa_setdisplaystart(int address)
{
  vesa_r.eax=0x4f07;
  vesa_r.ebx=0;
  vesa_r.ecx=address % vesa_logical_width;
  vesa_r.edx=address / vesa_logical_width;

  __svgalib_LRMI_int(0x10,&vesa_r);

}

/* Set logical scanline length (usually multiple of 8) */

static void vesa_setlogicalwidth(int width)
{
  vesa_r.eax=0x4f06;
  vesa_r.ebx=0;
  vesa_r.ecx=width / vesa_bpp ;
  __svgalib_LRMI_int(0x10,&vesa_r);
  vesa_logical_width=vesa_r.ebx;

}

static int vesa_linear(int op, int param)
{
if (op==LINEAR_ENABLE) {  
  vesa_r.eax=0x4f02;
  vesa_r.ebx=vesa_last_mode_set|0x4000;
  __svgalib_LRMI_int(0x10,&vesa_r);
  vesa_is_linear=1;
};

if (op==LINEAR_DISABLE){
  vesa_r.eax=0x4f02;
  vesa_r.ebx=vesa_last_mode_set;
  __svgalib_LRMI_int(0x10,&vesa_r);
  vesa_is_linear=0;
};
if (op==LINEAR_QUERY_BASE) {return vesa_linear_base ;}
if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0;               /* No granularity or range. */
    else return -1;             /* Unknown function. */
}

static int vesa_match_programmable_clock(int clock)
{
return clock ;
}
static int vesa_map_clock(int bpp, int clock)
{
return clock ;
}
static int vesa_map_horizontal_crtc(int bpp, int pixelclock, int htiming)
{
return htiming;
}
/* Function table (exported) */

DriverSpecs __svgalib_vesa_driverspecs =
{
    vesa_saveregs,
    vesa_setregs,
    vesa_unlock,
    vesa_lock,
    vesa_test,
    vesa_init,
    vesa_setpage,
    vesa_setrdpage,
    vesa_setwrpage,
    vesa_setmode,
    vesa_modeavailable,
    vesa_setdisplaystart,
    vesa_setlogicalwidth,
    vesa_getmodeinfo,
    0,                          /* old blit funcs */
    0,
    0,
    0,
    0,
    0,                          /* ext_set */
    0,                          /* accel */
    vesa_linear,
    0,                          /* accelspecs, filled in during init. */
    NULL,                       /* Emulation */
};

/* Initialize chipset (called after detection) */

static int vesa_init(int force, int par1, int par2)
{  
    short int *mode_list;
    int i;
   
    __svgalib_textprog|=1;

    /* Get I/O priviledge */

    if (force) {
        vesa_memory = par1;
        vesa_chiptype = par2;
    } else {
        vesa_memory=4096;
    };

    vesa_data.info = __svgalib_LRMI_alloc_real(sizeof(struct vbe_info_block)
         + sizeof(struct vbe_mode_info_block));
    vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1);
    vesa_r.eax = 0x4f00;
    vesa_r.es = (unsigned int)vesa_data.info >> 4;
    vesa_r.ds = (unsigned int)vesa_data.info >> 4;
    vesa_r.edi = 0;
   
    memcpy(vesa_data.info->vbe_signature, "VBE2", 4);

    __svgalib_LRMI_int(0x10, &vesa_r);
   
    if ((vesa_r.eax & 0xffff) != 0x4f || strncmp(vesa_data.info->vbe_signature, "VESA", 4) != 0) {
        printk(KERN_ERR "No VESA bios detected!\n");
        printk(KERN_ERR "Try running vga_reset.\n");
        return 1;
    }

    if(vesa_data.info->vbe_version>=0x0200)vesa_chiptype=1 ; else vesa_chiptype=0;
    if(vesa_data.info->vbe_version>=0x0300)vesa_chiptype=2 ;

    vesa_memory = vesa_data.info->total_memory*64;

    for(i=0;i<__GLASTMODE;i++)SVGALIB_VESA[i]=IS_IN_STANDARD_VGA_DRIVER(i);

    mode_list = (short int *)(vesa_data.info->video_mode_list_seg * 16 + vesa_data.info->video_mode_list_off);

    while (*mode_list != -1) {
       memset(&vesa_r, 0, sizeof(vesa_r));

       vesa_r.eax = 0x4f01;
       vesa_r.ecx = *mode_list;
       vesa_r.es = (unsigned int)vesa_data.mode >> 4;
       vesa_r.ds = (unsigned int)vesa_data.mode >> 4;
       vesa_r.edi = (unsigned int)vesa_data.mode & 0xf;

       if((vesa_chiptype>=1)&&(vesa_data.mode->mode_attributes&0x80))
          vesa_linear_base=vesa_data.mode->phys_base_ptr;
       if (!__svgalib_LRMI_int(0x10, &vesa_r)) {
          printk(KERN_ERR "Can't get mode info (vm86 failure)\n");
          return 1;
       }

       for(i=0;i<=__GLASTMODE;i++)
          if((infotable[i].xdim==vesa_data.mode->x_resolution)&&
             (infotable[i].ydim==vesa_data.mode->y_resolution)&&
             (((vesa_data.mode->rsvd_mask_size==8)&&(infotable[i].bytesperpixel==4))||
              ((vesa_data.mode->bits_per_pixel==32)&&(infotable[i].bytesperpixel==4))||
              ((vesa_data.mode->bits_per_pixel==24)&&(infotable[i].bytesperpixel==3))||
              ((vesa_data.mode->green_mask_size==5)&&(infotable[i].colors==32768))||
              ((vesa_data.mode->green_mask_size==6)&&(infotable[i].colors==65536))||
              ((vesa_data.mode->memory_model==VBE_MODEL_PLANAR)&&(infotable[i].colors==16))||
              ((vesa_data.mode->memory_model==VBE_MODEL_256)&&(infotable[i].colors==256))||
              ((vesa_data.mode->memory_model==VBE_MODEL_PACKED)&&
               (infotable[i].colors==256)&&(vesa_data.mode->bits_per_pixel==8)))){
                        SVGALIB_VESA[i]=*mode_list;
                        i=__GLASTMODE+1;
          };

        mode_list++;
 
    };

    vesa_r.eax=0x4f04;
    vesa_r.edx=0;
    vesa_r.ecx=__svgalib_VESA_savebitmap;
    vesa_r.ebx=0;
    __svgalib_LRMI_int(0x10,&vesa_r);
    vesa_regs_size=vesa_r.ebx*64;
    __svgalib_LRMI_free_real(vesa_data.info,sizeof(vesa_data.info));

    SVGALIB_VESA[TEXT]=3;

    cardspecs = malloc(sizeof(CardSpecs));
    cardspecs->videoMemory = vesa_memory;
    cardspecs->maxPixelClock4bpp = 300000;     
    cardspecs->maxPixelClock8bpp = 300000;     
    cardspecs->maxPixelClock16bpp = 300000;    
    cardspecs->maxPixelClock24bpp = 300000;
    cardspecs->maxPixelClock32bpp = 300000;
    cardspecs->flags = CLOCK_PROGRAMMABLE;
    cardspecs->maxHorizontalCrtc = 4088;
    cardspecs->nClocks =1;
    cardspecs->clocks = NULL;
    cardspecs->mapClock = vesa_map_clock;
    cardspecs->mapHorizontalCrtc = vesa_map_horizontal_crtc;
    cardspecs->matchProgrammableClock=vesa_match_programmable_clock;
    __svgalib_driverspecs = &__svgalib_vesa_driverspecs;

    LRMI_mem1 = __svgalib_LRMI_alloc_real(vesa_regs_size);
    LRMI_mem2 = __svgalib_LRMI_alloc_real(sizeof(struct vbe_info_block)
                                    + sizeof(struct vbe_mode_info_block));

    __svgalib_banked_mem_base=0xa0000;
    __svgalib_banked_mem_size=0x10000;
    if(vesa_chiptype>=1) {
      __svgalib_linear_mem_base=vesa_linear_base;
      __svgalib_linear_mem_size=vesa_memory*0x400;
    };
   
    if (__svgalib_driver_report) {
        printk(KERN_INFO "Using VESA driver, %iKB. %s\n",vesa_memory,
                (vesa_chiptype==2)?"VBE3":(vesa_chiptype?"VBE2.0":"VBE1.2"));
    }

    sleep(4);
   
    return 0;

}