/* * Mesa 3-D graphics library * Version: 5.0 * * Copyright (C) 1999-2002 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 v1.3 for Mesa 5.0 -- MGA2064W HW mapping * * Copyright (c) 2003 - Borca Daniel * Email : dborca@yahoo.com * Web : http://www.geocities.com/dborca */ #include #include #include #include #include #include #include "../internal.h" #include "mga_reg.h" #include "mga_hw.h" /* Hack alert: * these should really be externs */ /* PCI access routines */ static int pci_find_device (int deviceID, int vendorID, int deviceIndex, int *handle); static unsigned long pci_read_long (int handle, int index); static void pci_write_long (int handle, int index, unsigned long value); /* PCI device identifiers */ #define MATROX_VENDOR_ID 0x102B typedef enum { MATROX_MILL_ID = 0x0519 } MATROX_ID; static MATROX_ID matrox_id_list[] = { MATROX_MILL_ID, 0 }; /* internal hardware data structures */ #if !MGA_FARPTR static int dirty; #endif static int bus_id; static unsigned long reg40; static unsigned long io_mem_base[4], linear_base; static unsigned long io_mem_size[4], linear_size; static MATROX_ID matrox_id; /* interface structures containing hardware pointer data */ MGA_HWPTR mgaptr; /* Desc: create MMAP * * In : * Out : * * Note: */ static int _create_mmap (__dpmi_paddr *m, unsigned long base, unsigned long size) { #if MGA_FARPTR int sel; if (_create_selector(&sel, base, size)) { return -1; } m->selector = sel; m->offset32 = 0; #else m->selector = _my_ds(); if (_create_linear_mapping(&m->offset32, base, size)) { return -1; } m->offset32 -= __djgpp_base_address; #endif return 0; } /* Desc: destroy MMAP * * In : * Out : * * Note: */ static void _destroy_mmap (__dpmi_paddr *m) { #if MGA_FARPTR int sel = m->selector; _remove_selector(&sel); #else m->offset32 += __djgpp_base_address; _remove_linear_mapping(&m->offset32); #endif m->selector = 0; m->offset32 = 0; } /* Desc: Counts amount of installed RAM * * In : * Out : * * Note: */ static int _mga_get_vram (MATROX_ID chip, unsigned long base) { int ProbeSize = 8; int SizeFound = 2; unsigned char tmp; int i; __dpmi_paddr fb; switch (chip) { case MATROX_MILL_ID: ProbeSize = 8; break; } if (_create_mmap(&fb, base, ProbeSize*1024*1024)) { return 0; } /* turn MGA mode on - enable linear frame buffer (CRTCEXT3) */ mga_select(); mga_outb(M_CRTC_EXT_INDEX, 3); tmp = mga_inb(M_CRTC_EXT_DATA); mga_outb(M_CRTC_EXT_DATA, tmp | M_MGAMODE); /* write, read and compare method */ for (i=ProbeSize; i>2; i-= 2) { hwptr_pokeb(fb, i*1024*1024 - 1, 0xAA); mga_select(); mga_outb(M_CRTC_INDEX, 0); /* flush the cache */ mga_inl(M_STATUS); /* delay */ mga_inl(M_STATUS); /* delay */ mga_inl(M_STATUS); /* delay */ if (hwptr_peekb(fb, i*1024*1024 - 1) == 0xAA) { SizeFound = i; break; } } /* restore CRTCEXT3 state */ mga_select(); mga_outb(M_CRTC_EXT_INDEX, 3); mga_outb(M_CRTC_EXT_DATA, tmp); _destroy_mmap(&fb); return SizeFound*1024*1024; } /* Desc: Frees all resources allocated by MGA init code. * * In : * Out : * * Note: */ void mga_hw_fini (void) { int i; pci_write_long(bus_id, 0x40, reg40); for (i=0; i<4; i++) { _destroy_mmap(&mgaptr.io_mem_map[i]); } _destroy_mmap(&mgaptr.linear_map); #if !MGA_FARPTR if (dirty) { __djgpp_nearptr_disable(); dirty = FALSE; } #endif matrox_id = 0; } /* Desc: Attempts to detect MGA. * * In : * Out : * * Note: The first thing ever to be called. This is in charge of filling in * the driver header with all the required information and function * pointers. We do not yet have access to the video memory, so we can't * talk directly to the card. */ int mga_hw_init (unsigned long *vram, int *interleave, char *name) { int i; unsigned long pci_base[2]; if (matrox_id) { return matrox_id; } #if !MGA_FARPTR /* enable nearptr access */ if (_crt0_startup_flags & _CRT0_FLAG_NEARPTR) { dirty = FALSE; } else { if (__djgpp_nearptr_enable() == 0) return NULL; dirty = TRUE; } #endif /* find PCI device */ matrox_id = 0; for (bus_id=0, i=0; matrox_id_list[i]; i++) { if (pci_find_device(matrox_id_list[i], MATROX_VENDOR_ID, 0, &bus_id)) { matrox_id = matrox_id_list[i]; break; } } /* set up the card name */ switch (matrox_id) { case MATROX_MILL_ID: if (name) strcpy(name, "Millennium"); break; default: matrox_id = 0; return -1; } reg40 = pci_read_long(bus_id, 0x40); #if 0 /* overclock a little :) */ { int rfhcnt = (reg40 >> 16) & 0xF; if ((reg40 & 0x200000) && (rfhcnt < 0xC)) { pci_write_long(bus_id, 0x40, (reg40 & 0xFFF0FFFF) | 0x000C0000); } } #endif /* read hardware configuration data */ for (i=0; i<2; i++) pci_base[i] = pci_read_long(bus_id, 16+i*4); /* work out the linear framebuffer and MMIO addresses */ if (matrox_id == MATROX_MILL_ID) { if (pci_base[0]) io_mem_base[0] = pci_base[0] & 0xFFFFC000; if (pci_base[1]) linear_base = pci_base[1] & 0xFF800000; } if (!linear_base || !io_mem_base[0]) return NULL; /* deal with the memory mapping crap */ io_mem_size[0] = 0x4000; for (i=0; i<4; i++) { if (io_mem_base[i]) { if (_create_mmap(&mgaptr.io_mem_map[i], io_mem_base[i], io_mem_size[i])) { mga_hw_fini(); return NULL; } } } *vram = linear_size = _mga_get_vram(matrox_id, linear_base); if (_create_mmap(&mgaptr.linear_map, linear_base, linear_size)) { mga_hw_fini(); return NULL; } /* fill in user data */ *interleave = linear_size > 2*1024*1024; return matrox_id; } /* PCI routines added by SET */ #define PCIAddr 0xCF8 #define PCIData 0xCFC #define PCIEnable 0x80000000 /* FindPCIDevice: * Replacement for the INT 1A - PCI BIOS v2.0c+ - FIND PCI DEVICE, AX = B102h * * Note: deviceIndex is because a card can hold more than one PCI chip. * * Searches the board of the vendor supplied in vendorID with * identification number deviceID and index deviceIndex (normally 0). * The value returned in handle can be used to access the PCI registers * of this board. * * Return: 1 if found 0 if not found. */ static int pci_find_device (int deviceID, int vendorID, int deviceIndex, int *handle) { int model, vendor, card, device; unsigned value, full_id, bus, busMax; deviceIndex <<= 8; /* for each PCI bus */ for (bus=0, busMax=0x10000; bus> 16; if (vendor != 0xFFFF) { /* is this the one we want? */ if ((deviceID == model) && (vendorID == vendor)) { *handle = value; return 1; } /* is it a bridge to a secondary bus? */ outportl(PCIAddr, value | 8); if (((inportl(PCIData) >> 16) == 0x0600) || (full_id==0x00011011)) busMax += 0x10000; } } } return 0; } /* Desc: * * In : * Out : * * Note: */ static unsigned long pci_read_long (int handle, int index) { outportl(PCIAddr, PCIEnable | handle | index); return inportl(PCIData); } /* Desc: * * In : * Out : * * Note: */ static void pci_write_long (int handle, int index, unsigned long value) { outportl(PCIAddr, PCIEnable | handle | index); outportl(PCIData, value); }