text: /*
  	Copyright 2008 Haiku, Inc.  All rights reserved.
  	Distributed under the terms of the MIT license.
  
  	Authors:
  	Gerald Zajac 2008
  */
  
  #include "accel.h"
  
  #include <unistd.h>
  
  
  // Macros for memory mapped I/O.
  //==============================
  
  #define INREG8(addr)		*((vuint8*)(gInfo.regs + addr))
  #define INREG16(addr)		*((vuint16*)(gInfo.regs + addr))
  #define INREG32(addr)		*((vuint32*)(gInfo.regs + addr))
  
  #define OUTREG8(addr, val)	*((vuint8*)(gInfo.regs + addr)) = val
  #define OUTREG16(addr, val)	*((vuint16*)(gInfo.regs + addr)) = val
  #define OUTREG32(addr, val)	*((vuint32*)(gInfo.regs + addr)) = val
  
  
  // Functions for PIO.
  //===================
  
  uint32 ReadPIO(uint32 addr, uint8 numBytes)
  {
  	S3GetSetPIO gsp;
  	gsp.magic = S3_PRIVATE_DATA_MAGIC;
  	gsp.offset = addr;
  	gsp.size = numBytes;
  	gsp.value = 0;
  
  	status_t result = ioctl(gInfo.deviceFileDesc, S3_GET_PIO, &gsp, sizeof(gsp));
  	if (result != B_OK)
  		TRACE("ReadPIO() failed, result = 0x%x\n", result);
  
  	return gsp.value;
  }
  
  
  void WritePIO(uint32 addr, uint8 numBytes, uint32 value)
  {
  	S3GetSetPIO gsp;
  	gsp.magic = S3_PRIVATE_DATA_MAGIC;
  	gsp.offset = addr;
  	gsp.size = numBytes;
  	gsp.value = value;
  
  	status_t result = ioctl(gInfo.deviceFileDesc, S3_SET_PIO, &gsp, sizeof(gsp));
  	if (result != B_OK)
  		TRACE("WritePIO() failed, result = 0x%x\n", result);
  }
  
  
  // Functions to read 8/16/32 bit registers.
  //=========================================
  
  uint8 ReadReg8(uint32 addr)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		return ReadPIO(addr, 1);
  
  	return INREG8(addr);
  }
  
  
  uint16 ReadReg16(uint32 addr)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		return ReadPIO(addr, 2);
  
  	return INREG16(addr);
  }
  
  
  uint32 ReadReg32(uint32 addr)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		return ReadPIO(addr, 4);
  
  	return INREG32(addr);
  }
  
  
  // Functions to write 8/16/32 bit registers.
  //=========================================
  
  void WriteReg8(uint32 addr, uint8 value)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		WritePIO(addr, 1, value);
  	else
  		OUTREG8(addr, value);
  }
  
  
  void WriteReg16(uint32 addr, uint16 value)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		WritePIO(addr, 2, value);
  	else
  		OUTREG16(addr, value);
  }
  
  
  void WriteReg32(uint32 addr, uint32 value)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		WritePIO(addr, 4, value);
  	else
  		OUTREG32(addr, value);
  }
  
  
  // Functions to read/write CRTC registers.
  //========================================
  
  uint8 ReadCrtcReg(uint8 index)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
  		WritePIO_8(0x3d4, index);
  		return ReadPIO_8(0x3d5);
  	}
  
  	OUTREG8(0x83d4, index);
  	return INREG8(0x83d5);
  }
  
  
  void WriteCrtcReg(uint8 index, uint8 value)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
  		WritePIO_8(0x3d4, index);
  		WritePIO_8(0x3d5, value);
  	} else {
  		OUTREG8(0x83d4, index);
  		OUTREG8(0x83d5, value);
  	}
  }
  
  
  void WriteCrtcReg(uint8 index, uint8 value, uint8 mask)
  {
  	// Write a value to a CRTC reg using a mask.  The mask selects the
  	// bits to be modified.
  
  	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
  		WritePIO_8(0x3d4, index);
  		WritePIO_8(0x3d5, (ReadPIO_8(0x3d5) & ~mask) | (value & mask));
  	} else {
  		OUTREG8(0x83d4, index);
  		OUTREG8(0x83d5, (INREG8(0x83d5) & ~mask) | (value & mask));
  	}
  }
  
  
  // Functions to read/write Sequence registers.
  //============================================
  
  uint8 ReadSeqReg(uint8 index)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
  		WritePIO_8(0x3c4, index);
  		return ReadPIO_8(0x3c5);
  	}
  
  	OUTREG8(0x83c4, index);
  	return INREG8(0x83c5);
  }
  
  
  void WriteSeqReg(uint8 index, uint8 value)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
  		WritePIO_8(0x3c4, index);
  		WritePIO_8(0x3c5, value);
  	} else {
  		OUTREG8(0x83c4, index);
  		OUTREG8(0x83c5, value);
  	}
  }
  
  
  void WriteSeqReg(uint8 index, uint8 value, uint8 mask)
  {
  	// Write a value to a Sequencer reg using a mask.  The mask selects the
  	// bits to be modified.
  
  	if (gInfo.sharedInfo->chipType == S3_TRIO64) {
  		WritePIO_8(0x3c4, index);
  		WritePIO_8(0x3c5, (ReadPIO_8(0x3c5) & ~mask) | (value & mask));
  	} else {
  		OUTREG8(0x83c4, index);
  		OUTREG8(0x83c5, (INREG8(0x83c5) & ~mask) | (value & mask));
  	}
  }
  
  
  // Functions to read/write the misc output register.
  //==================================================
  
  uint8 ReadMiscOutReg()
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		return ReadPIO_8(0x3cc);
  
  	return INREG8(0x83cc);
  }
  
  
  void WriteMiscOutReg(uint8 value)
  {
  	if (gInfo.sharedInfo->chipType == S3_TRIO64)
  		WritePIO_8(0x3c2, value);
  	else
  		OUTREG8(0x83c2, value);
  }
  
  
  void WriteIndexedColor(uint8 index, uint8 red, uint8 green, uint8 blue)
  {
  	// Write an indexed color.  Argument index is the index (0-255) of the
  	// color, and arguments red, green, & blue are the components of the color.
  
  	// Note that although the Trio64V+ chip supports MMIO in nearly all areas,
  	// it does not support MMIO for setting indexed colors;  thus, use PIO to
  	// set the indexed color.
  
  	if (gInfo.sharedInfo->chipType == S3_TRIO64
  			|| gInfo.sharedInfo->chipType == S3_TRIO64_VP) {
  		WritePIO_8(0x3c8, index);	// color index
  		WritePIO_8(0x3c9, red);
  		WritePIO_8(0x3c9, green);
  		WritePIO_8(0x3c9, blue);
  	} else {
  		OUTREG8(0x83c8, index);		// color index
  		OUTREG8(0x83c9, red);
  		OUTREG8(0x83c9, green);
  		OUTREG8(0x83c9, blue);
  	}
  }
  