From 7fd50afbbf8bb36642efe0254706039af3c9c588 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 8 Mar 2002 19:24:56 +0000 Subject: new DOS driver files from Daniel Borca --- src/mesa/drivers/dos/vbeaf.c | 607 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 607 insertions(+) create mode 100644 src/mesa/drivers/dos/vbeaf.c (limited to 'src/mesa/drivers/dos/vbeaf.c') diff --git a/src/mesa/drivers/dos/vbeaf.c b/src/mesa/drivers/dos/vbeaf.c new file mode 100644 index 0000000000..eef1793985 --- /dev/null +++ b/src/mesa/drivers/dos/vbeaf.c @@ -0,0 +1,607 @@ +/* + * Mesa 3-D graphics library + * Version: 4.0 + * + * Copyright (C) 1999 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * DOS/DJGPP device driver v0.2 for Mesa 4.0 + * + * Copyright (C) 2002 - Borca Daniel + * Email : dborca@yahoo.com + * Web : http://www.geocities.com/dborca + */ + + +#include +#include +#include +#include +#include +#include + +#include "dpmiint.h" +#include "vbeaf.h" + + + +#define MMAP unsigned long +#define NOMM 0 +#define MVAL(a) (void *)((a)-__djgpp_base_address) + + + +#define SAFE_CALL(FUNC)\ +{ \ + int _ds, _es, _ss; \ + \ + __asm__ __volatile__( \ + " movw %%ds, %w0 ; " \ + " movw %%es, %w1 ; " \ + " movw %%ss, %w2 ; " \ + " movw %w3, %%ds ; " \ + " movw %w3, %%es ; " \ + " movw %w3, %%ss ; " \ + \ + : "=&q" (_ds), \ + "=&q" (_es), \ + "=&q" (_ss) \ + : "q" (__djgpp_ds_alias) \ + ); \ + \ + FUNC \ + \ + __asm__ __volatile__( \ + "movw %w0, %%ds ; " \ + "movw %w1, %%es ; " \ + "movw %w2, %%ss ; " \ + : \ + : "q" (_ds), \ + "q" (_es), \ + "q" (_ss) \ + ); \ +} + +#define SAFISH_CALL(FUNC) FUNC + + + +extern void _af_int86(), _af_call_rm(), _af_wrapper_end(); + + + +static AF_DRIVER *af_driver = NULL; /* the VBE/AF driver */ +int _accel_active = FALSE; /* is the accelerator busy? */ +static FAF_HWPTR_DATA *faf_farptr; /* FreeBE/AF farptr data */ +static MMAP af_memmap[4] = { NOMM, NOMM, NOMM, NOMM }; +static MMAP af_banked_mem = NOMM; +static MMAP af_linear_mem = NOMM; + + + +__inline__ fixed itofix (int x) +{ + return x << 16; +} + + + +/* + * loads the driver from disk + */ +static int load_driver (char *filename) +{ + FILE *f; + size_t size; + + if ((f=fopen(filename, "rb"))!=NULL) { + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + if ((af_driver=(AF_DRIVER *)malloc(size))!=NULL) { + if (fread(af_driver, size, 1, f)) { + return 0; + } else { + free(af_driver); + } + } + fclose(f); + } + + return -1; +} + + + +/* + * Calls a VBE/AF function using the version 1.0 style asm interface. + */ +static int call_vbeaf_asm (void *proc) +{ + int ret; + + proc = (void *)((long)af_driver + (long)proc); + + /* use gcc-style inline asm */ + __asm__("\n\ + pushl %%ebx \n\ + movl %%ecx, %%ebx \n\ + call *%%edx \n\ + popl %%ebx \n\ + ": "=&a" (ret) /* return value in eax */ + : "c" (af_driver), /* VBE/AF driver in ds:ebx */ + "d" (proc) /* function ptr in edx */ + : "memory" /* assume everything is clobbered */ + ); + + return ret; +} + + + +/* + * prepares the FreeBE/AF extension functions. + */ +static int initialise_freebeaf_extensions (void) +{ + typedef unsigned long (*EXT_INIT_FUNC)(AF_DRIVER *af, unsigned long id); + EXT_INIT_FUNC ext_init; + unsigned long magic; + int v1, v2; + void *ptr; + + /* safety check */ + if (!af_driver->OemExt) { + return 0; + } + + /* call the extension init function */ + ext_init = (EXT_INIT_FUNC)((long)af_driver + (long)af_driver->OemExt); + + magic = ext_init(af_driver, FAFEXT_INIT); + + /* check that it returned a nice magic number */ + v1 = (magic>>8)&0xFF; + v2 = magic&0xFF; + + if (((magic&0xFFFF0000) != FAFEXT_MAGIC) || (!isdigit(v1)) || (!isdigit(v2))) { + return 0; + } + + /* export libc and pmode functions if the driver wants them */ + ptr = af_driver->OemExt(af_driver, FAFEXT_LIBC); +#ifdef _FAFEXT_LIBC + if (ptr) + _fill_vbeaf_libc_exports(ptr); +#endif + + ptr = af_driver->OemExt(af_driver, FAFEXT_PMODE); +#ifdef _FAFEXT_PMODE + if (ptr) + _fill_vbeaf_pmode_exports(ptr); +#endif + + return (v1-'0')*10 + (v2-'0'); +} + + + +/* + * Sets up the DPMI memory mappings required by the VBE/AF driver, + * returning zero on success. + */ +static int initialise_vbeaf_driver (int faf_ext) +{ + int c; + + /* query driver for the FreeBE/AF farptr extension */ + if (faf_ext > 0) + faf_farptr = af_driver->OemExt(af_driver, FAFEXT_HWPTR); + else + faf_farptr = NULL; + + if (faf_farptr) { + /* use farptr access */ + for (c=0; c<4; c++) { + faf_farptr->IOMemMaps[c].sel = 0; + faf_farptr->IOMemMaps[c].offset = 0; + } + + faf_farptr->BankedMem.sel = 0; + faf_farptr->BankedMem.offset = 0; + + faf_farptr->LinearMem.sel = 0; + faf_farptr->LinearMem.offset = 0; + } else { + /* enable nearptr access */ + return -5; + } + + /* create mapping for MMIO ports */ + for (c=0; c<4; c++) { + if (af_driver->IOMemoryBase[c]) { + if ((af_memmap[c]=_create_linear_mapping(af_driver->IOMemoryBase[c], af_driver->IOMemoryLen[c]))==NULL) + return -4; + + if (faf_farptr) { + /* farptr IO mapping */ + if ((faf_farptr->IOMemMaps[c].sel=_create_selector(af_memmap[c], af_driver->IOMemoryLen[c]))<0) { + _remove_linear_mapping(af_memmap+c); + return -4; + } + faf_farptr->IOMemMaps[c].offset = 0; + af_driver->IOMemMaps[c] = NULL; + } else { + /* nearptr IO mapping */ + af_driver->IOMemMaps[c] = MVAL(af_memmap[c]); + } + } + } + + /* create mapping for banked video RAM */ + if (af_driver->BankedBasePtr) { + if ((af_banked_mem=_create_linear_mapping(af_driver->BankedBasePtr, 0x10000))==NULL) + return -4; + + if (faf_farptr) { + /* farptr banked vram mapping */ + if ((faf_farptr->BankedMem.sel=_create_selector(af_banked_mem, 0x10000))<0) { + _remove_linear_mapping(&af_banked_mem); + return -4; + } + faf_farptr->BankedMem.offset = 0; + af_driver->BankedMem = NULL; + } else { + /* nearptr banked vram mapping */ + af_driver->BankedMem = MVAL(af_banked_mem); + } + } + + /* create mapping for linear video RAM */ + if (af_driver->LinearBasePtr) { + if ((af_linear_mem=_create_linear_mapping(af_driver->LinearBasePtr, af_driver->LinearSize*1024))==NULL) + return -4; + + if (faf_farptr) { + /* farptr linear vram mapping */ + if ((faf_farptr->LinearMem.sel=_create_selector(af_linear_mem, af_driver->LinearSize*1024))<0) { + _remove_linear_mapping(&af_linear_mem); + return -4; + } + faf_farptr->LinearMem.offset = 0; + af_driver->LinearMem = NULL; + } else { + /* nearptr linear vram mapping */ + af_driver->LinearMem = MVAL(af_linear_mem); + } + } + + /* callback functions: why are these needed? ugly, IMHO */ + af_driver->Int86 = (void *)_af_int86; + af_driver->CallRealMode = (void *)_af_call_rm; + + return 0; +} + + + +/* go_accel: + * Prepares the hardware for an accelerated drawing operation. + */ +static __inline__ void go_accel (void) +{ + /* turn on the accelerator */ + if (!_accel_active) { + if (af_driver->DisableDirectAccess) + af_driver->DisableDirectAccess(af_driver); + + _accel_active = TRUE; + } +} + + + +void af_exit (void) +{ + int c; + + /* undo memory mappings */ + if (faf_farptr) { + for (c=0; c<4; c++) + _remove_selector(&faf_farptr->IOMemMaps[c].sel); + + _remove_selector(&faf_farptr->BankedMem.sel); + _remove_selector(&faf_farptr->LinearMem.sel); + } + + for (c=0; c<4; c++) + _remove_linear_mapping(af_memmap+c); + + _remove_linear_mapping(&af_banked_mem); + _remove_linear_mapping(&af_linear_mem); + + if (af_driver) { + free(af_driver); + } +} + + + +int af_init (char *filename) +{ + int faf_ext, r; + + if (load_driver(filename)) { + /* driver not found */ + return -1; + } + + faf_ext = initialise_freebeaf_extensions(); + + /* special setup for Plug and Play hardware */ + if (call_vbeaf_asm(af_driver->PlugAndPlayInit)) { + af_exit(); + /* Plug and Play initialisation failed */ + return -2; + } + + if ((r=initialise_vbeaf_driver(faf_ext))) { + af_exit(); + /* -4, ... */ + return r; + } + + /* low level driver initialisation */ + if (call_vbeaf_asm(af_driver->InitDriver)) { + af_exit(); + /* VBE/AF device not present */ + return -3; + } + + _go32_dpmi_lock_code((void *)_af_int86, (long)_af_wrapper_end-(long)_af_int86); + + return 0; +} + + + +#include "video.h" + + + +static long page, xres, startx, starty; + + + +AF_MODE_INFO *af_getmode (int i, int *granularity) +{ + static AF_MODE_INFO info; + int mode = af_driver->AvailableModes[i]; + + if ((mode==-1)||af_driver->GetVideoModeInfo(af_driver, mode, &info)) { + return NULL; + } else { + *granularity = af_driver->BankSize * 1024; + return &info; + } +} + + + +void *af_dump_virtual (void *buffer, int width, int height, int pitch) +{ + SAFISH_CALL( + go_accel(); + + af_driver->BitBltSys(af_driver, buffer, pitch, 0, 0, width, height, startx, starty, 0); + ); + return buffer; +} + + + +void af_switch_bank (int bank) +{ + af_driver->SetBank(af_driver, bank); +} + + + +int af_flip (void) +{ + SAFISH_CALL( + go_accel(); + + af_driver->SetDisplayStart(af_driver, page*xres, 0, 1); + ); + if (page ^= 1) { + startx += xres; + } else { + startx -= xres; + } + + return page; +} + + + +void af_fillrect (void *buffer, int x, int y, int width, int height, int color) +{ + (void)buffer; + SAFISH_CALL( + go_accel(); + + af_driver->DrawRect(af_driver, color, startx+x, starty+y, width, height); + ); +} + + + +void af_triangle (int x1, int y1, int x2, int y2, int x3, int y3, int color) +{ + AF_TRAP trap; + + /* sort along the vertical axis */ + #define TRI_SWAP(a, b) \ + { \ + int tmp = x##a; \ + x##a = x##b; \ + x##b = tmp; \ + \ + tmp = y##a; \ + y##a = y##b; \ + y##b = tmp; \ + } + + if (y2 < y1) + TRI_SWAP(1, 2); + + if (y3 < y1) { + TRI_SWAP(1, 3); + TRI_SWAP(2, 3); + } else if (y3 < y2) + TRI_SWAP(2, 3); + + SAFISH_CALL( + go_accel(); + + if (y2 > y1) { + /* draw the top half of the triangle as one trapezoid */ + trap.y = y1+starty; + trap.count = y2-y1; + trap.x1 = trap.x2 = itofix(x1+startx); + trap.slope1 = itofix(x2-x1) / (y2-y1); + trap.slope2 = itofix(x3-x1) / (y3-y1); + + if (trap.slope1 < 0) + trap.x1 += MIN(trap.slope1+itofix(1), 0); + + if (trap.slope2 < 0) + trap.x2 += MIN(trap.slope2+itofix(1), 0); + + if (trap.slope1 > trap.slope2) + trap.x1 += MAX(ABS(trap.slope1), itofix(1)); + else + trap.x2 += MAX(ABS(trap.slope2), itofix(1)); + + af_driver->DrawTrap(af_driver, color, &trap); + + if (y3 > y2) { + /* draw the bottom half as a second trapezoid */ + if (trap.slope1 < 0) + trap.x1 -= MIN(trap.slope1+itofix(1), 0); + + if (trap.slope1 > trap.slope2) + trap.x1 -= MAX(ABS(trap.slope1), itofix(1)); + + trap.count = y3-y2; + trap.slope1 = itofix(x3-x2) / (y3-y2); + + if (trap.slope1 < 0) + trap.x1 += MIN(trap.slope1+itofix(1), 0); + + if (trap.x1 > trap.x2) + trap.x1 += MAX(ABS(trap.slope1), itofix(1)); + + af_driver->DrawTrap(af_driver, color, &trap); + } + } else if (y3 > y2) { + /* we can draw the entire thing with a single trapezoid */ + trap.y = y1+starty; + trap.count = y3-y2; + trap.x1 = itofix(x2+startx); + trap.x2 = itofix(x1+startx); + trap.slope1 = itofix(x3-x2) / (y3-y2); + trap.slope2 = (y3 > y1) ? (itofix(x3-x1) / (y3-y1)) : 0; + + if (trap.slope1 < 0) + trap.x1 += MIN(trap.slope1+itofix(1), 0); + + if (trap.slope2 < 0) + trap.x2 += MIN(trap.slope2+itofix(1), 0); + + if (trap.x1 > trap.x2) + trap.x1 += MAX(ABS(trap.slope1), itofix(1)); + else + trap.x2 += MAX(ABS(trap.slope2), itofix(1)); + + af_driver->DrawTrap(af_driver, color, &trap); + } + ); +} + + + +int af_setup_mode (int mode, int caps) +{ + if (CHECK_SOFTDB(caps) && af_driver->BitBltSys) { + vl_flip = af_dump_virtual; + } + if (af_driver->SetBank) { + vl_switch_bank = af_switch_bank; + } + if (!CHECK_SOFTDB(caps) && af_driver->DrawRect) { + vl_clear = af_fillrect; + } + + if (CHECK_SINGLE(caps) || CHECK_SOFTDB(caps)) { + page = 0; + } else { + page = 1; + } + + return (mode&0x4000)?faf_farptr->LinearMem.sel:faf_farptr->BankedMem.sel; +} + + + +int af_setup_buffer (int x, int y) +{ + startx = x + page*xres; + starty = y; + + return page; +} + + + +void *af_getprim (int primitive) +{ + switch (primitive) { + case TRI_RGB_FLAT: + return af_driver->DrawTrap?(void *)af_triangle:NULL; + default: + return NULL; + } +} + + + +int af_enter_mode (int mode, int width, int height) +{ + long wret; + if (!af_driver->SetVideoMode(af_driver, mode, width, height, &wret, 1, NULL)) { + xres = width/2; + return wret; + } else { + return -1; + } +} -- cgit v1.2.3