text: #include <u.h>
  #include <libc.h>
  
  #include "vga.h"
  
  /*
   * SGS-Thompson STG1702 Enhanced True Color Palette-DAC
   * with 16-bit Pixel Port.
   */
  enum {
  	Command		= 0x00,		/* Pixel Command Register */
  	IndexLO		= 0x01,		/* LO-byte of 16-bit Index */
  	IndexHI		= 0x02,		/* HI-byte of 16-bit Index */
  	Index		= 0x03,		/* Indexed Register */
  
  	CompanyID	= 0x00,		/* Company ID = 0x44 */
  	DeviceID	= 0x01,		/* Device ID = 0x02 */
  	Pmode		= 0x03,		/* Primary Pixel Mode Select */
  	Smode		= 0x04,		/* Secondary Pixel Mode Select */
  	Pipeline	= 0x05,		/* Pipeline Timing Control */
  	Sreset		= 0x06,		/* Soft Reset */
  	Power		= 0x07,		/* Power Management */
  
  	Nindex		= 0x08,
  };
  
  static void
  pixmask(void)
  {
  	inportb(PaddrW);
  }
  
  static void
  commandrw(void)
  {
  	int i;
  
  	pixmask();
  	for(i = 0; i < 4; i++)
  		inportb(Pixmask);
  }
  
  static uchar
  commandr(void)
  {
  	uchar command;
  
  	commandrw();
  	command = inportb(Pixmask);
  	pixmask();
  
  	return command;
  }
  
  static void
  commandw(uchar command)
  {
  	commandrw();
  	outportb(Pixmask, command);
  	pixmask();
  }
  
  static void
  indexrw(uchar index)
  {
  	uchar command;
  
  	command = commandr();
  	commandw(command|0x10);
  
  	commandrw();
  	inportb(Pixmask);
  	outportb(Pixmask, index & 0xFF);
  	outportb(Pixmask, (index>>8) & 0xFF);
  }
  
  static void
  options(Vga *vga, Ctlr *ctlr)
  {
  	USED(vga);
  	verbose("%s->options\n", ctlr->name);
  
  	ctlr->flag |= Hpclk2x8|Foptions;
  }
  
  static void
  init(Vga *vga, Ctlr *ctlr)
  {
  	ulong pclk;
  
  	verbose("%s->init\n", ctlr->name);
  	/*
  	 * Part comes in -135MHz speed-grade.
  	 * In 8-bit mode the max. PCLK is 110MHz. In 2x8-bit mode
  	 * the max. PCLK is the speed-grade, using the 2x doubler.
  	 * We can use mode 2 (2x8-bit, internal clock doubler)
  	 * if connected to a suitable graphics chip, e.g. the
  	 * ET4000-w32p.
  	 */
  	if(vga->ctlr && ((vga->ctlr->flag & Hpclk2x8) && vga->mode->z == 8))
  		pclk = 135000000;
  	else
  		pclk = 110000000;
  
  	/*
  	 * If we don't already have a desired pclk,
  	 * take it from the mode.
  	 * Check it's within range.
  	 */
  	if(vga->f == 0)
  		vga->f = vga->mode->frequency;
  	if(vga->f < 16000000 || vga->f > pclk)
  		error("%s: invalid pclk - %ld\n", ctlr->name, vga->f);
  
  	/*
  	 * Determine whether to use 2x8-bit mode or not.
  	 * If yes and the clock has already been initialised,
  	 * initialise it again.
  	 */
  	if(vga->ctlr && (vga->ctlr->flag & Hpclk2x8) && vga->mode->z == 8 && vga->f >= 110000000){
  		vga->f /= 2;
  		resyncinit(vga, ctlr, Upclk2x8, 0);
  	}
  
  	ctlr->flag |= Finit;
  }
  
  static void
  load(Vga *vga, Ctlr *ctlr)
  {
  	uchar command, mode, pipeline;
  
  	verbose("%s->load\n", ctlr->name);
  
  	command = 0x00;
  	mode = 0x00;
  	pipeline = 0x02;
  	if(ctlr->flag & Upclk2x8){
  		command = 0x08;
  		mode = 0x05;
  		pipeline = 0x02;
  		if(vga->f < 16000000)
  			pipeline = 0x00;
  		else if(vga->f < 32000000)
  			pipeline = 0x01;
  	}
  
  	indexrw(Pmode);
  	outportb(Pixmask, mode);
  	outportb(Pixmask, mode);
  	outportb(Pixmask, pipeline);
  	sleep(1);
  	commandw(command);
  
  	ctlr->flag |= Fload;
  }
  
  static void
  dump(Vga *vga, Ctlr *ctlr)
  {
  	int i;
  
  	USED(vga);
  
  	printitem(ctlr->name, "command");
  	printreg(commandr());
  
  	printitem(ctlr->name, "index");
  	indexrw(CompanyID);
  	for(i = 0; i < Nindex; i++)
  		printreg(inportb(Pixmask));
  
  	pixmask();
  }
  
  Ctlr stg1702 = {
  	"stg1702",			/* name */
  	0,				/* snarf */
  	options,			/* options */
  	init,				/* init */
  	load,				/* load */
  	dump,				/* dump */
  };
  