nvidiacore.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 702 行 · 第 1/2 页

JAVA
702
字号
/*
 * $Id: NVidiaCore.java,v 1.5 2004/01/04 11:01:58 epr Exp $
 */
package org.jnode.driver.video.nvidia;

import java.awt.Color;
import java.awt.image.ColorModel;
import java.awt.image.Raster;

import javax.naming.NameNotFoundException;

import org.apache.log4j.Logger;
import org.jnode.awt.util.BitmapGraphics;
import org.jnode.driver.DriverException;
import org.jnode.driver.pci.PCIBaseAddress;
import org.jnode.driver.pci.PCIDevice;
import org.jnode.driver.pci.PCIDeviceConfig;
import org.jnode.driver.video.FrameBufferConfiguration;
import org.jnode.driver.video.ddc.DisplayDataChannelAPI;
import org.jnode.driver.video.util.AbstractSurface;
import org.jnode.driver.video.vgahw.DisplayMode;
import org.jnode.naming.InitialNaming;
import org.jnode.system.MemoryResource;
import org.jnode.system.ResourceManager;
import org.jnode.system.ResourceNotFreeException;
import org.jnode.util.NumberUtils;
import org.jnode.vm.Address;

/**
 * @author Ewout Prangsma (epr@users.sourceforge.net)
 */
public class NVidiaCore extends AbstractSurface implements NVidiaConstants, DisplayDataChannelAPI {

	/** My logger */
	private final Logger log = Logger.getLogger(getClass());
	private final NVidiaDriver driver;
	private FrameBufferConfiguration config;
	private final MemoryResource mmio;
	private final MemoryResource videoRam;
	private int bitsPerPixel = 32;
	private int bytesPerLine;
	private BitmapGraphics bitmapGraphics;
	private final NVidiaVgaIO vgaIO;
	private final NVidiaVgaState oldVgaState = new NVidiaVgaState();
	private final int architecture;
	/** Size of card memory in MB */
	private final int memSize;
	private final int DDCBase = 0x3e;
	private final int CrystalFreqKHz;
	private final int MaxVClockFreqKHz;
	/** Hardware cursor implementation */
	private final NVidiaHardwareCursor hwCursor;
	/** Acceleration functions */
	private final NVidiaAcceleration acc;
	/** Should acceleration be used */
	private final boolean useAcc = true;

	/**
	 * @param driver
	 * @param architecture
	 * @param model
	 * @param device
	 */
	public NVidiaCore(NVidiaDriver driver, int architecture, String model, PCIDevice device) throws ResourceNotFreeException, DriverException {
		super(640, 480);
		this.driver = driver;
		this.architecture = architecture;
		final PCIDeviceConfig pciCfg = device.getConfig();
		final PCIBaseAddress ioAddr = pciCfg.getBaseAddresses()[0];
		final PCIBaseAddress fbAddr = pciCfg.getBaseAddresses()[1];
		log.info("Found NVidia " + model + ", chipset 0x" + NumberUtils.hex(pciCfg.getRevision()));
		try {
			final ResourceManager rm = (ResourceManager) InitialNaming.lookup(ResourceManager.NAME);
			final int ioBase = (int) ioAddr.getMemoryBase() & 0xFF800000;
			final int ioSize = ioAddr.getSize();
			final int fbBase = (int) fbAddr.getMemoryBase() & 0xFF800000;
			final int fbSize = fbAddr.getSize();

			log.debug("Found NVidia, FB at 0x" + NumberUtils.hex(fbBase) + "s0x" + NumberUtils.hex(fbSize) + ", MMIO at 0x" + NumberUtils.hex(ioBase));

			this.mmio = rm.claimMemoryResource(device, Address.valueOf(ioBase), ioSize, ResourceManager.MEMMODE_NORMAL);
			this.videoRam = rm.claimMemoryResource(device, Address.valueOf(fbBase), fbSize, ResourceManager.MEMMODE_NORMAL);
			this.vgaIO = new NVidiaVgaIO(mmio, videoRam);

		} catch (NameNotFoundException ex) {
			throw new ResourceNotFreeException(ex);
		}
		this.hwCursor = new NVidiaHardwareCursor(vgaIO, architecture);
		this.acc = new NVidiaAcceleration(vgaIO, architecture);
		this.memSize = getMemorySize();

		switch (architecture) {
			case NV04A :
				{
					final int bootInfo = vgaIO.getReg32(NV32_NVSTRAPINFO2);
					CrystalFreqKHz = ((bootInfo & 0x00000040) != 0) ? 14318 : 13500;
					MaxVClockFreqKHz = 250000;
				}
				break;
			case NV10A :
				{
					final int bootInfo = vgaIO.getReg32(NV32_NVSTRAPINFO2);
					CrystalFreqKHz = ((bootInfo & 0x00000040) != 0) ? 14318 : 13500;
					MaxVClockFreqKHz = 350000;
				}
				break;
			default :
				throw new DriverException("Unknown architecture " + architecture);
		}
		log.debug("Memory size     =" + memSize + "MB");
		log.debug("CrystalFreqKHz  =" + CrystalFreqKHz);
		log.debug("MaxVClockFreqKHz=" + MaxVClockFreqKHz);
	}

	/**
	 * Open the given configuration
	 * 
	 * @param config
	 */
	final void open(NVidiaConfiguration config) {
		this.config = config;
		// Save the current state
		oldVgaState.saveFromVGA(vgaIO);
		//log.debug("Old VGA State: " + oldVgaState);
		//log.debug("Old start address:0x" +
		// NumberUtils.hex(getVideoStartAddress()));

		// Enabled access to extended registers
		vgaIO.unlock();

		// Turn off the screen
		final NVidiaDpmsState dpmsState = getDpms();
		//log.debug("Old DPMS state: " + dpmsState);
		setDpms(NVidiaDpmsState.OFF);

		/* power-up all nvidia hardware function blocks */
		/*
		 * bit 28: OVERLAY ENGINE (BES), bit 25: CRTC2, (> NV04A) bit 24: CRTC1, bit 20: framebuffer, bit 16: PPMI, bit 12: PGRAPH, bit 8: PFIFO, bit 4: PMEDIA, bit 0: TVOUT. (> NV04A)
		 */
		//log.debug("PWRUPCTRL=0x" +
		// NumberUtils.hex(mmio.getInt(NV32_PWRUPCTRL)));
		mmio.setInt(NV32_PWRUPCTRL, 0x13111111);

		// Set the new configuration
		this.bitsPerPixel = config.getBitsPerPixel();
		this.width = config.getScreenWidth();
		this.height = config.getScreenHeight();
		final int pixelDepth = (this.bitsPerPixel + 1) / 8;
		this.bytesPerLine = width * pixelDepth;
		final int startAddress = 2048;
		try {
			final NVidiaVgaState newState = config.getVgaState();
			newState.calcForConfiguration(config, architecture, vgaIO);
			newState.restoreToVGA(vgaIO);
			setPLL(config.getMode());
			//setColourDepth
			setPalette(1.0f);
			// setDacMode
			setPitch(bytesPerLine);
			setVideoStartAddress(startAddress);
			setTiming(config.getMode());
			hwCursor.initCursor();
			// Setup accelration
			acc.accInit(startAddress, bytesPerLine, memSize, bitsPerPixel);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		// Create the graphics helper & clear the screen
		final int pixels = width * height;
		switch (bitsPerPixel) {
			case 8 :
				bitmapGraphics = BitmapGraphics.create8bppInstance(videoRam, width, height, bytesPerLine, startAddress);
				videoRam.setByte(startAddress, (byte) 0, pixels);
				break;
			case 16 :
				bitmapGraphics = BitmapGraphics.create16bppInstance(videoRam, width, height, bytesPerLine, startAddress);
				videoRam.setShort(startAddress, (byte) 0, pixels);
				break;
			case 24 :
				bitmapGraphics = BitmapGraphics.create24bppInstance(videoRam, width, height, bytesPerLine, startAddress);
				videoRam.setInt24(startAddress, 0, pixels);
				break;
			case 32 :
				bitmapGraphics = BitmapGraphics.create32bppInstance(videoRam, width, height, bytesPerLine, startAddress);
				videoRam.setInt(startAddress, 0, pixels);
				break;
		}

		// Turn the screen back on
		setDpms(dpmsState);

	}

	/**
	 * Close the SVGA screen
	 * 
	 * @see org.jnode.driver.video.Surface#close()
	 */
	public synchronized void close() {
		hwCursor.closeCursor();
		final NVidiaDpmsState dpmsState = getDpms();
		//log.debug("Old DPMS state: " + dpmsState);
		setDpms(NVidiaDpmsState.OFF);
		vgaIO.unlock();
		oldVgaState.restoreToVGA(vgaIO);
		setDpms(dpmsState);

		// For debugging purposes
		//final NVidiaVgaState debugState = new NVidiaVgaState();
		//debugState.saveFromVGA(vgaIO);
		//log.debug("Restored state: " + debugState);
		// End of debugging purposes

		driver.close(this);
		super.close();
	}

	/**
	 * Release all resources
	 */
	final void release() {
		mmio.release();
		videoRam.release();
	}

	/**
	 * @see org.jnode.driver.video.util.AbstractSurface#convertColor(java.awt.Color)
	 */
	protected int convertColor(Color color) {
		return color.getRGB();
	}

	/**
	 * @see org.jnode.driver.video.util.AbstractSurface#drawPixel(int, int, int, int)
	 */
	protected final void drawPixel(int x, int y, int color, int mode) {
		bitmapGraphics.drawPixels(x, y, 1, color, mode);
	}

	/**
	 * @see org.jnode.driver.video.Surface#drawCompatibleRaster(java.awt.image.Raster, int, int, int, int, int, int, java.awt.Color)
	 */
	public final void drawCompatibleRaster(Raster raster, int srcX, int srcY, int dstX, int dstY, int width, int height, Color bgColor) {
		if (bgColor == null) {
			bitmapGraphics.drawImage(raster, srcX, srcY, dstX, dstY, width, height);
		} else {
			bitmapGraphics.drawImage(raster, srcX, srcY, dstX, dstY, width, height, convertColor(bgColor));
		}
	}

	/**
	 * @see org.jnode.driver.video.Surface#getColorModel()
	 */
	public ColorModel getColorModel() {
		return config.getColorModel();
	}

	private void setPitch(int bytesPerLine) {
		final int offset = bytesPerLine / 8;
		//log.info("setPitch: offset 0x" + NumberUtils.hex(offset) + "
		// bytesPerLine 0x" + NumberUtils.hex(bytesPerLine));
		//program the card!
		vgaIO.setCRT(NVCRTCX_PITCHL, offset & 0x00ff);
		final int temp = vgaIO.getCRT(NVCRTCX_REPAINT0);
		vgaIO.setCRT(NVCRTCX_REPAINT0, (temp & 0x1f) | ((offset & 0x0700) >> 3));
	}

	/**
	 * Sets the start address of the video memory
	 * 
	 * @param startadd
	 */
	private void setVideoStartAddress(int startadd) {
		if (architecture < NV10A) {
			/* upto 32Mb RAM adressing: must be used this way on pre-NV10! */

			/* set standard registers */
			/* (NVidia: startadress in 32bit words (b2 - b17) */
			vgaIO.setCRT(NVCRTCX_FBSTADDL, (startadd >> 2) & 0xFF);
			vgaIO.setCRT(NVCRTCX_FBSTADDH, (startadd >> 10) & 0xFF);

			/* set extended registers */
			/* NV4 extended bits: (b18-22) */
			int temp = vgaIO.getCRT(NVCRTCX_REPAINT0) & 0xE0;
			vgaIO.setCRT(NVCRTCX_REPAINT0, temp | ((startadd >> 18) & 0x1f));
			/* NV4 extended bits: (b23-24) */
			temp = vgaIO.getCRT(NVCRTCX_HEB) & 0xdf;
			vgaIO.setCRT(NVCRTCX_HEB, temp | ((startadd >> 18) & 0x20));
			//temp = (CRTCR(HEB) & 0x9f);
			//CRTCW(HEB, (temp | ((startadd & 0x01800000) >> 18)));
		} else {
			/* upto 4Gb RAM adressing: must be used on NV10 and later! */
			/*
			 * NOTE: While this register also exists on pre-NV10 cards, it will wrap-around at 16Mb boundaries!!
			 */

			/* 30bit adress in 32bit words */
			vgaIO.setReg32(NV32_NV10FBSTADD32, startadd & 0xfffffffc);
		}

		int temp = vgaIO.getATT(NVATBX_HORPIXPAN) & 0xf9;
		vgaIO.setATT(NVATBX_HORPIXPAN, temp | ((startadd & 3) << 1));
	}

	/**
	 * Gets the start address of the video memory
	 */
	final int getVideoStartAddress() {
		int startadd = 0;
		if (architecture < NV10A) {
			/* upto 32Mb RAM adressing: must be used this way on pre-NV10! */

			/* set standard registers */
			/* (NVidia: startadress in 32bit words (b2 - b17) */
			startadd |= ((vgaIO.getCRT(NVCRTCX_FBSTADDL) & 0xFF) << 2);
			startadd |= ((vgaIO.getCRT(NVCRTCX_FBSTADDH) & 0xFF) << 10);

			/* set extended registers */
			/* NV4 extended bits: (b18-22) */
			int temp = vgaIO.getCRT(NVCRTCX_REPAINT0) & 0x1f;
			startadd |= (temp << 18);
			/* NV4 extended bits: (b23-24) */
			temp = vgaIO.getCRT(NVCRTCX_HEB) & 0x60;
			startadd |= (temp << 18);
		} else {
			/* upto 4Gb RAM adressing: must be used on NV10 and later! */
			/*
			 * NOTE: While this register also exists on pre-NV10 cards, it will wrap-around at 16Mb boundaries!!
			 */

			/* 30bit adress in 32bit words */
			startadd = vgaIO.getReg32(NV32_NV10FBSTADD32) & 0xfffffffc;
		}
		return startadd;
	}

	private void setDpms(NVidiaDpmsState state) {
		//log.debug("Setting DPMS to " + state);
		/* start synchronous reset: required before turning screen off! */
		vgaIO.setSEQ(NVSEQX_RESET, 0x01);

		/* turn screen off */
		int clkmode = vgaIO.getSEQ(NVSEQX_CLKMODE);
		if (state.isDisplay()) {
			vgaIO.setSEQ(NVSEQX_CLKMODE, clkmode & ~0x20);
			/* end synchronous reset if display should be enabled */
			vgaIO.setSEQ(NVSEQX_RESET, 0x03);
		} else {
			vgaIO.setSEQ(NVSEQX_CLKMODE, clkmode | 0x20);
		}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?