~kris/9p

9hist

df6c1bb53cdf1ddaf8c63e9023278f44f64b952b — David du Colombier 24 years ago a506f5d
Plan 9 from Bell Labs 2001-10-05
6 files changed, 596 insertions(+), 104 deletions(-)

M pc/devusb.c
M pc/devvga.c
M pc/etherec2t.c
M pc/screen.h
M pc/vgamach64xx.c
M port/devdup.c
M pc/devusb.c => pc/devusb.c +1 -1
@@ 685,7 685,7 @@ static Block *
isoxmit(Endpt *e, Block *b, int pid)
{
	Block *ob;
	static int ioc;
	static int ioc, n, id;
	TD *td;

	td = e->etd;

M pc/devvga.c => pc/devvga.c +53 -2
@@ 17,11 17,15 @@
enum {
	Qdir,
	Qvgactl,
	Qvgaovl,
	Qvgaovlctl,
};

static Dirtab vgadir[] = {
	".",	{ Qdir, 0, QTDIR },		0,	0550,
	"vgactl",	{ Qvgactl, 0 },		0,	0660,
	"vgactl",		{ Qvgactl, 0 },		0,	0660,
	"vgaovl",		{ Qvgaovl, 0 },		0,	0660,
	"vgaovlctl",	{ Qvgaovlctl, 0 },	0, 	0660,
};

static void


@@ 58,12 62,34 @@ vgastat(Chan* c, uchar* dp, int n)
static Chan*
vgaopen(Chan* c, int omode)
{
	VGAscr *scr;
	static char *openctl = "openctl\n";

	scr = &vgascreen[0];
	if ((ulong)c->qid.path == Qvgaovlctl) {
		if (scr->dev->ovlctl)
			scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
		else 
			error(Enonexist);
	}
	return devopen(c, omode, vgadir, nelem(vgadir), devgen);
}

static void
vgaclose(Chan*)
vgaclose(Chan* c)
{
	VGAscr *scr;
	static char *closectl = "closectl\n";

	scr = &vgascreen[0];
	if ((ulong)c->qid.path == Qvgaovlctl) {
		if (scr->dev->ovlctl){
			if(waserror())
				return;
			scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
			poperror();
		}
	}
}

static void


@@ 132,6 158,11 @@ vgaread(Chan* c, void* a, long n, vlong off)

		return n;

	case Qvgaovl:
	case Qvgaovlctl:
		error(Ebadusefd);
		break;

	default:
		error(Egreg);
		break;


@@ 339,11 370,14 @@ vgactl(char* a)
	error(Ebadarg);
}

char Enooverlay[] = "No overlay support";

static long
vgawrite(Chan* c, void* a, long n, vlong off)
{
	char *p;
	ulong offset = off;
	VGAscr *scr;

	switch((ulong)c->qid.path){



@@ 365,6 399,23 @@ vgawrite(Chan* c, void* a, long n, vlong off)
		free(p);
		return n;

	case Qvgaovl:
		scr = &vgascreen[0];
		if (scr->dev->ovlwrite == nil) {
			error(Enooverlay);
			break;
		}
		return scr->dev->ovlwrite(scr, a, n, off);

	case Qvgaovlctl:
		scr = &vgascreen[0];
		if (scr->dev->ovlctl == nil) {
			error(Enooverlay);
			break;
		}
		scr->dev->ovlctl(scr, c, a, n);
		return n;

	default:
		error(Egreg);
		break;

M pc/etherec2t.c => pc/etherec2t.c +28 -20
@@ 18,13 18,19 @@ enum {
	Reset		= 0x1F,		/* offset from I/O base of reset port */
};

static char* ec2tpcmcia[] = {
	"EC2T",				/* Linksys Combo PCMCIA EthernetCard */
	"PCMPC100",			/* EtherFast 10/100 PC Card */
	"EN2216",			/* Accton EtherPair-PCMCIA */
	"FA410TX",			/* Netgear FA410TX */
	"Network Everywhere",		/* Linksys NP10T 10BaseT Card */
	nil,
typedef struct Ec2t {
	char*	name;
	int	iochecksum;
} Ec2t;

static Ec2t ec2tpcmcia[] = {
	{ "EC2T", 0, },			/* Linksys Combo PCMCIA EthernetCard */
	{ "PCMPC100", 1, },		/* EtherFast 10/100 PC Card */
	{ "EN2216", 0, },		/* Accton EtherPair-PCMCIA */
	{ "FA410TX", 1, },		/* Netgear FA410TX */
	{ "Network Everywhere", 0, },	/* Linksys NP10T 10BaseT Card */
	{ "10/100 Port Attached", 1, },	/* SMC 8040TX */
	{ nil, 0, },
};

static int


@@ 35,7 41,7 @@ reset(Ether* ether)
	Dp8390 *ctlr;
	int i, slot;
	uchar ea[Eaddrlen], sum, x;
	char *type;
	Ec2t *ec2t, tmpec2t;

	/*
	 * Set up the software configuration.


@@ 57,19 63,21 @@ reset(Ether* ether)
	if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
		return -1;
	slot = -1;
	type = nil;
	for(i = 0; ec2tpcmcia[i] != nil; i++){
		type = ec2tpcmcia[i];
		if((slot = pcmspecial(type, ether)) >= 0)
	for(ec2t = ec2tpcmcia; ec2t->name != nil; ec2t++){
		if((slot = pcmspecial(ec2t->name, ether)) >= 0)
			break;
	}
	if(ec2tpcmcia[i] == nil){
	if(ec2t->name == nil){
		ec2t = &tmpec2t;
		ec2t->name = nil;
		ec2t->iochecksum = 0;
		for(i = 0; i < ether->nopt; i++){
			if(cistrncmp(ether->opt[i], "id=", 3))
				continue;
			type = &ether->opt[i][3];
			if((slot = pcmspecial(type, ether)) >= 0)
				break;
			if(cistrncmp(ether->opt[i], "id=", 3) == 0){
				ec2t->name = &ether->opt[i][3];
				slot = pcmspecial(ec2t->name, ether);
			}
			else if(cistrncmp(ether->opt[i], "iochecksum", 10) == 0)
				ec2t->iochecksum = 1;
		}
	}
	if(slot < 0){


@@ 117,9 125,9 @@ reset(Ether* ether)
	 */
	dp8390reset(ether);
	sum = 0;
	if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
	if(ec2t->iochecksum){
		/*
		 * The PCMPC100 has the ethernet address in I/O space.
		 * These cards have the ethernet address in I/O space.
		 * There's a checksum over 8 bytes which sums to 0xFF.
		 */
		for(i = 0; i < 8; i++){

M pc/screen.h => pc/screen.h +2 -0
@@ 68,6 68,8 @@ struct VGAdev {
	ulong	(*linear)(VGAscr*, int*, int*);
	void	(*drawinit)(VGAscr*);
	int	(*fill)(VGAscr*, Rectangle, ulong);
	void	(*ovlctl)(VGAscr*, Chan*, void*, int);
	int	(*ovlwrite)(VGAscr*, void*, int, vlong);
};

struct VGAcur {

M pc/vgamach64xx.c => pc/vgamach64xx.c +509 -73
@@ 12,32 12,134 @@
#include <cursor.h>
#include "screen.h"

char Eunsupportedformat[] = "unsupported video format";
char Enotconfigured[] = "device not configured";

#define SCALE_ZERO_EXTEND           	0x0
#define SCALE_DYNAMIC               		0x1
#define SCALE_RED_TEMP_6500K        	0x0
#define SCALE_RED_TEMP_9800K        	0x2
#define SCALE_HORZ_BLEND            	0x0
#define SCALE_HORZ_REP              		0x4
#define SCALE_VERT_BLEND            		0x0
#define SCALE_VERT_REP              		0x8
#define SCALE_BANDWIDTH_NORMAL     0x0
#define SCALE_BANDWIDTH_EXCEEDED  0x4000000
#define SCALE_BANDWIDTH_RESET       	0x4000000
#define SCALE_CLK_ACTIVITY          	0x0
#define SCALE_CLK_CONTINUOUS        	0x20000000
#define OVERLAY_DISABLE             		0x0
#define OVERLAY_ENABLE              		0x40000000
#define SCALE_DISABLE               		0x0
#define SCALE_ENABLE                		0x80000000

#define SCALER_FRAME_READ_MODE_FULL 	0x0
#define SCALER_BUF_MODE_SINGLE      		0x0
#define SCALER_BUF_MODE_DOUBLE      		0x40000
#define SCALER_BUF_NEXT_0           		0x0
#define SCALER_BUF_NEXT_1           		0x80000
#define SCALER_BUF_STATUS_0         		0x0
#define SCALER_BUF_STATUS_1         		0x100000

#define OVERLAY_MIX_G_CMP           		0x0
#define OVERLAY_MIX_ALWAYS_G        		0x100
#define OVERLAY_MIX_ALWAYS_V        		0x200
#define OVERLAY_MIX_NOT_G           		0x300
#define OVERLAY_MIX_NOT_V           		0x400
#define OVERLAY_MIX_G_XOR_V         		0x500
#define OVERLAY_MIX_NOT_G_XOR_V     	0x600
#define OVERLAY_MIX_V_CMP           		0x700
#define OVERLAY_MIX_NOT_G_OR_NOT_V	0x800
#define OVERLAY_MIX_G_OR_NOT_V      	0x900
#define OVERLAY_MIX_NOT_G_OR_V      	0xA00
#define OVERLAY_MIX_G_OR_V          		0xB00
#define OVERLAY_MIX_G_AND_V         		0xC00
#define OVERLAY_MIX_NOT_G_AND_V     	0xD00
#define OVERLAY_MIX_G_AND_NOT_V     	0xE00
#define OVERLAY_MIX_NOT_G_AND_NOT_V 	0xF00
#define OVERLAY_EXCLUSIVE_NORMAL    	0x0
#define OVERLAY_EXCLUSIVE_V_ONLY    	0x80000000

#define VIDEO_IN_8BPP               			0x2
#define VIDEO_IN_16BPP              			0x4
#define VIDEO_IN_32BPP              			0x6
#define VIDEO_IN_VYUY422            			0xB         		/*16 bpp */
#define VIDEO_IN_YVYU422            			0xC         		/* 16 bpp */
#define SCALE_IN_15BPP              			0x30000     	/* aRGB 1555 */
#define SCALE_IN_16BPP              			0x40000     	/* RGB 565 */
#define SCALE_IN_32BPP              			0x60000     	/* aRGB 8888 */
#define SCALE_IN_YUV9               			0x90000     	/* planar */
#define SCALE_IN_YUV12              			0xA0000     	/* planar */
#define SCALE_IN_VYUY422            			0xB0000     	/* 16 bpp */
#define SCALE_IN_YVYU422            			0xC0000     	/* 16 bpp */
#define HOST_YUV_APERTURE_UPPER     		0x0
#define HOST_YUV_APERTURE_LOWER     	0x20000000
#define HOST_MEM_MODE_Y             		0x40000000
#define HOST_MEM_MODE_U             		0x80000000
#define HOST_MEM_MODE_V             		0xC0000000
#define HOST_MEM_MODE_NORMAL     		HOST_YUV_APERTURE_UPPER 

static Chan *ovl_chan;	/* Channel of controlling process */
static int ovl_width;		/* Width of input overlay buffer */
static int ovl_height;		/* Height of input overlay buffer */
static int ovl_format;	/* Overlay format */
static ulong ovl_fib;		/* Frame in bytes */

enum {
	 VTGTB1S1        = 0x01,            //  Asic description for VTB1S1 and GTB1S1.
	 VT4GTIIC        	= 0x3A,            // asic descr for VT4 and RAGE IIC
	 GTB1U1          	= 0x19,            //  Asic description for GTB1U1.
	 GTB1S2          	= 0x41,            //  Asic description for GTB1S2.
	 GTB2U1          	= 0x1A,
	 GTB2U2          	= 0x5A,
	 GTB2U3          	= 0x9A,
	 GTIIIC1U1       	= 0x1B,            // 3D RAGE PRO asic descrp.
	 GTIIIC1U2       	= 0x5B,            // 3D RAGE PRO asic descrp.
	 GTIIIC2U1       	= 0x1C,            // 3D RAGE PRO asic descrp.
	 GTIIIC2U2       	= 0x5C,           // 3D RAGE PRO asic descrp.
	 GTIIIC2U3       	= 0x7C,            // 3D RAGE PRO asic descrp.
	 GTBC            	= 0x3A,            // 3D RAGE IIC asic descrp.
	 LTPRO           	= 0x9C,            // 3D RAGE LT PRO
};

/*
 * ATI Mach64(CT|ET|G*|V*|L*).
 */
static ushort mach64xxdid[] = {
	('C'<<8)|'T',
	('E'<<8)|'T',
	('G'<<8)|'B',
	('G'<<8)|'D',
	('G'<<8)|'I',
	('G'<<8)|'M',
	('G'<<8)|'P',
	('G'<<8)|'Q',
	('G'<<8)|'T',
	('G'<<8)|'U',
	('G'<<8)|'V',
	('G'<<8)|'Z',
	('V'<<8)|'T',
	('V'<<8)|'U',
	('V'<<8)|'V',
	('L'<<8)|'B',
	('L'<<8)|'I',
	('L'<<8)|'M',
	('L'<<8)|'P',
	0,
typedef struct {
	ushort 	m64_id;			/* Chip ID */
	int 		m64_vtgt;		/* Is this a VT or GT chipset? */
	double	m64_ovlclock;		/* Max. overlay clock frequency */
	int		m64_pro;			/* Is this a PRO? */
} mach64types;

static double mach64refclock;
static mach64types *mach64type;
static int mach64revb;			/* Revision B or greater? */
static ulong mach64overlay;		/* Overlay buffer */

static mach64types mach64s[] = {
	('C'<<8)|'T',	0,	0.,		0,	/* 4354: CT */
	('E'<<8)|'T',	0,	0.,		0,	/* 4554: ET */
	('G'<<8)|'B',	1,	125.,		1, 	/* 4742: 264GT PRO */
	('G'<<8)|'D',	1,	125.,		1, 	/* 4744: 264GT PRO */
	('G'<<8)|'I',	1,	125.,		1, 	/* 4749: 264GT PRO */
	('G'<<8)|'M',	0,	135.,		0,	/* 474D: Rage XL */
	('G'<<8)|'P',	1,	125.,		1, 	/* 4750: 264GT PRO */
	('G'<<8)|'Q',	1,	125.,		1,	/* 4751: 264GT PRO */
	('G'<<8)|'T',	1,	80.,		0,	/* 4754: 264GT[B] */
	('G'<<8)|'U',	1,	100.,		0,	/* 4755: 264GT DVD */
	('G'<<8)|'V',	1,	100.,		0,	/* 4756: Rage2C */
	('G'<<8)|'Z',	1,	100.,		0,	/* 475A: Rage2C */
	('V'<<8)|'T',	1,	80.,		0,	/* 5654: 264VT/GT/VTB */
	('V'<<8)|'U',	1,	80.,		0,	/* 5655: 264VT3 */
	('V'<<8)|'V',	1,	100.,		0,	/* 5656: 264VT4 */
	('L'<<8)|'B',	0,	135.,		1,	/* 4C42: Rage LTPro AGP */
	('L'<<8)|'I',		0,	135.,		0,	/* 4C49: Rage LTPro AGP */
	('L'<<8)|'M',	0,	135.,		0,	/* 4C4D: Rage Mobility */
	('L'<<8)|'P',	0,	135.,		1,	/* 4C50: 264LT PRO */
};


static int hwfill(VGAscr*, Rectangle, ulong);
static int hwscroll(VGAscr*, Rectangle, Rectangle);
static void initengine(VGAscr*);


@@ 46,15 148,16 @@ static Pcidev*
mach64xxpci(void)
{
	Pcidev *p;
	ushort *did;
	int i;

	if((p = pcimatch(nil, 0x1002, 0)) == nil)
		return nil;
	for(did = mach64xxdid; *did; did++){
		if(*did == p->did)
			return p;
	}

	for (i = 0; i != nelem(mach64s); i++)
		if (mach64s[i].m64_id == p->did) {
			mach64type = &mach64s[i];
			return p;
		}
	return nil;
}



@@ 188,6 291,29 @@ enum {
	SrcOffPitch,	
	LcdIndex,
	LcdData,
	ClockCntl,
	OverlayScaleCntl,
	ConfigChipId,
	Buf0Pitch,
	ScalerBuf0Pitch,
	CaptureConfig,
	OverlayKeyCntl,
	ScalerColourCntl,
	ScalerHCoef0,
	ScalerHCoef1,
	ScalerHCoef2,
	ScalerHCoef3,
	ScalerHCoef4,
	VideoFormat,
	Buf0Offset,
	ScalerBuf0Offset,
	CrtcGenCntl,
	OverlayScaleInc,
	OverlayYX,
	OverlayYXEnd,
	ScalerHeightWidth,
	HTotalDisp,
	VTotalDisp,
};

enum {


@@ 204,56 330,83 @@ enum {
	Nlcd,
};

static uchar mmoffset[] = {
	[CrtcOffPitch]	0x05,
	[CurClr0]	0x18,
	[CurClr1]	0x19,
	[CurOffset]	0x1A,
	[CurHVposn]	0x1B,
	[CurHVoff]	0x1C,
	[BusCntl]		0x28,
	[LcdIndex]	0x29,
	[LcdData]	0x2A,
	[GenTestCntl]	0x34,
	[DstOffPitch]	0x40,
	[DstYX]		0x43,
	[DstHeight]	0x45,
#define Bank1			(-0x100)		/* 1KB */

static int mmoffset[] = {
	[HTotalDisp]		0x00,
	[VTotalDisp]		0x02,
	[CrtcOffPitch]		0x05,
	[CrtcGenCntl]		0x07,
	[CurClr0]			0x18,
	[CurClr1]			0x19,
	[CurOffset]		0x1A,
	[CurHVposn]		0x1B,
	[CurHVoff]		0x1C,
	[ClockCntl]		0x24,
	[BusCntl]			0x28,
	[LcdIndex]		0x29,
	[LcdData]			0x2A,
	[GenTestCntl]		0x34,
	[ConfigChipId]		0x38,
	[DstOffPitch]		0x40,
	[DstYX]			0x43,
	[DstHeight]		0x45,
	[DstHeightWidth]	0x46,
	[DstBresErr]	0x49,
	[DstBresInc]	0x4A,
	[DstBresDec]	0x4B,
	[DstCntl]		0x4C,
	[SrcOffPitch]	0x60,
	[SrcYX]	0x63,
	[SrcWidth1]	0x64,
	[SrcYXstart]	0x69,
	[DstBresErr]		0x49,
	[DstBresInc]		0x4A,
	[DstBresDec]		0x4B,
	[DstCntl]			0x4C,
	[SrcOffPitch]		0x60,
	[SrcYX]			0x63,
	[SrcWidth1]		0x64,
	[SrcYXstart]		0x69,
	[SrcHeight1Width1]	0x66,
	[SrcHeight2Width2]	0x6C,
	[SrcCntl]		0x6D,
	[HostCntl]	0x90,
	[PatReg0]	0xA0,
	[PatReg1]	0xA1,
	[PatCntl]	0xA2,
	[ScLeft]	0xA8,
	[ScRight]	0xA9,
	[ScLeftRight]	0xAA,
	[ScTop]	0xAB,
	[ScBottom] 0xAC,
	[ScTopBottom]	0xAD,
	[DpBkgdClr]	0xB0,
	[DpFrgdClr]	0xB1,
	[DpWriteMask]	0xB2,
	[DpChainMask]	0xB3,
	[DpPixWidth]	0xB4,
	[DpMix]		0xB5,
	[DpSrc]		0xB6,
	[ClrCmpClr]	0xC0,
	[ClrCmpMask]	0xC1,
	[ClrCmpCntl]	0xC2,
	[FifoStat]		0xC4,
	[ContextMask]	0xC8,
	[GuiTrajCntl]	0xCC,
	[GuiStat]		0xCE,
	[SrcCntl]			0x6D,
	[HostCntl]			0x90,
	[PatReg0]			0xA0,
	[PatReg1]			0xA1,
	[PatCntl]			0xA2,
	[ScLeft]			0xA8,
	[ScRight]			0xA9,
	[ScLeftRight]		0xAA,
	[ScTop]			0xAB,
	[ScBottom] 		0xAC,
	[ScTopBottom]		0xAD,
	[DpBkgdClr]		0xB0,
	[DpFrgdClr]		0xB1,
	[DpWriteMask]		0xB2,
	[DpChainMask]		0xB3,
	[DpPixWidth]		0xB4,
	[DpMix]			0xB5,
	[DpSrc]			0xB6,
	[ClrCmpClr]		0xC0,
	[ClrCmpMask]		0xC1,
	[ClrCmpCntl]		0xC2,
	[FifoStat]			0xC4,
	[ContextMask]		0xC8,
	[GuiTrajCntl]		0xCC,
	[GuiStat]			0xCE,

	/* Bank1 */
	[OverlayYX]		Bank1 + 0x00,
	[OverlayYXEnd]		Bank1 + 0x01,
	[OverlayKeyCntl]	Bank1 + 0x06,
	[OverlayScaleInc]	Bank1 + 0x08,
	[OverlayScaleCntl]	Bank1 + 0x09,
	[ScalerHeightWidth]	Bank1 + 0x0A,
	[ScalerBuf0Offset]	Bank1 + 0x0D,
	[ScalerBuf0Pitch]	Bank1 + 0x0F,
	[VideoFormat]		Bank1 + 0x12,
	[CaptureConfig]	Bank1 + 0x14,
	[Buf0Offset]		Bank1 + 0x20,
	[Buf0Pitch]		Bank1 + 0x23,
	[ScalerColourCntl]	Bank1 + 0x54,
	[ScalerHCoef0]		Bank1 + 0x55,
	[ScalerHCoef1]		Bank1 + 0x56,
	[ScalerHCoef2]		Bank1 + 0x57,
	[ScalerHCoef3]		Bank1 + 0x58,
	[ScalerHCoef4]		Bank1 + 0x59,
};

static ulong


@@ 534,9 687,46 @@ resetengine(VGAscr *scr)
}

static void
init_overlayclock(VGAscr *scr)
{
	uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div, 
			vclk_fb_div, ecp_div;
	int i;
	double dotclock;

	/* Taken from GLX */
	/* Get monitor dotclock, check for Overlay Scaler clock limit */
 	cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]];
  	save = cc[1]; i = cc[0] & 3;
  	cc[1] = 2<<2; pll_ref_div = cc[2];
  	cc[1] = 5<<2; pll_vclk_cntl = cc[2];
  	cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3;
  	cc[1] = (7+i)<<2; vclk_fb_div = cc[2];

  	dotclock = 2.0 * mach64refclock * vclk_fb_div / 
			(pll_ref_div * (1 << vclk_post_div));
	/* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */
  	ecp_div = dotclock / mach64type->m64_ovlclock;
  	if (ecp_div>2) ecp_div = 2;

  	/* Force a scaler clock factor of 1 if refclock *
   	  * is unknown (VCLK_SRC not PLLVCLK)  */
  	if ((pll_vclk_cntl & 0x03) != 0x03) dotclock = ecp_div = 0;
  	if ((pll_vclk_cntl & 0x30) != ecp_div<<4) {
    		cc[1] = (5<<2)|2;
    		cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4);
	}

  	/* Restore PLL Register Index */
  	cc[1] = save;
}

static void
initengine(VGAscr *scr)
{
	ulong pitch;
	uchar *bios;
	ushort table;

	pitch = Dx(scr->gscreen->r)/8;
	if(scr->gscreen->depth == 24)


@@ 596,6 786,50 @@ initengine(VGAscr *scr)
		break;
	}

	/* Get the base freq from the BIOS */
	bios  = KADDR(0xC000);
	table = *(ushort *)(bios + 0x48);
	table = *(ushort *)(bios + table + 0x10);
	switch (*(ushort *)(bios + table + 0x08)) {
      	case 2700: 
		mach64refclock = 27.0; 
		break;
      	case 2863: 
      	case 2864: 
		mach64refclock = 28.63636; 
		break;
      	case 2950: 
		mach64refclock = 29.498928713; 
		break;
    	case 1432: 
	default:
		mach64refclock = 14.31818; 
		break ;	
	}
	
	/* Figure out which revision this chip is */
	switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) {
	case VTGTB1S1:
	case GTB1U1:
	case GTB1S2:
	case GTB2U1:
	case GTB2U2:
	case GTB2U3:
	case GTBC:
	case GTIIIC1U1:
	case GTIIIC1U2:
	case GTIIIC2U1:
	case GTIIIC2U2: 
	case GTIIIC2U3: 
	case LTPRO:
			mach64revb = 1;
			break;
	default: 
			mach64revb = 0;
			break;
	}

	init_overlayclock(scr);
	waitforidle(scr);
}



@@ 769,6 1003,205 @@ mach64xxdrawinit(VGAscr *scr)
	}
}

static void
ovl_configure(VGAscr *scr, Chan *c, int nfields, char **field)
{
	int w, h;
	char *format;

	if (nfields != 4) error(Ebadarg);

	w = (int)strtol(field[1], nil, 0);
	h = (int)strtol(field[2], nil, 0);
	format = field[3];

	if (c != ovl_chan) error(Einuse);
	if (strcmp(format, "YUYV"))
		error(Eunsupportedformat);
	
	ovl_width  = w;
	ovl_height = h;
	ovl_fib       = w * h * sizeof(ushort);

	waitforidle(scr);
	scr->mmio[mmoffset[BusCntl]] |= 0x08000000;	/* Enable regblock 1 */
	scr->mmio[mmoffset[OverlayScaleCntl]] = 
		SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K|
		SCALE_HORZ_BLEND|SCALE_VERT_BLEND;
	scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w;
	scr->mmio[mmoffset[CaptureConfig]] = 
		SCALER_FRAME_READ_MODE_FULL|
		SCALER_BUF_MODE_SINGLE|
		SCALER_BUF_NEXT_0;
	scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb?
		OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28): 
		0x011;

	if (mach64type->m64_pro) {
		waitforfifo(scr, 6);

		/* set the scaler co-efficient registers */
		scr->mmio[mmoffset[ScalerColourCntl]] = 
			(0x00) | (0x10 << 8) | (0x10 << 16);
		scr->mmio[mmoffset[ScalerHCoef0]] = 
			(0x00) | (0x20 << 8);
		scr->mmio[mmoffset[ScalerHCoef1]] = 
			(0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24);
		scr->mmio[mmoffset[ScalerHCoef2]] = 
			(0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24);
		scr->mmio[mmoffset[ScalerHCoef3]] = 
			(0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24);
		scr->mmio[mmoffset[ScalerHCoef4]] = 
			(0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24);
	}
	
	waitforfifo(scr, 3);
	scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 |
		(!mach64revb? 0xC: 0);

	if (mach64overlay == 0)
		mach64overlay = scr->storage + 64 * 64 * sizeof(uchar);
	scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] = 
		mach64overlay;
}

static void
ovl_enable(VGAscr *scr, Chan *c, int nfields, char **field)
{
	int x, y, w, h;
	long h_inc, v_inc;

	if (nfields != 5) error(Ebadarg);

	x = (int)strtol(field[1], nil, 0);
	y = (int)strtol(field[2], nil, 0);
	w = (int)strtol(field[3], nil, 0);
	h = (int)strtol(field[4], nil, 0);

	if (x < 0 || x + w > physgscreenr.max.x ||
	     y < 0 || y + h > physgscreenr.max.y)
		error(Ebadarg);

	if (c != ovl_chan) error(Einuse);
	if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) {	/* double scan enable */
		y *= 2;
		h *= 2;
	}

	waitforfifo(scr, 2);
	scr->mmio[mmoffset[OverlayYX]] = 
			((x & 0xFFFF) << 16) | (y & 0xFFFF);
	scr->mmio[mmoffset[OverlayYXEnd]] = 
			(((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF);

	h_inc = (ovl_width << 12) / (w >> 1);  /* ??? */
	v_inc = (ovl_height << 12) / h;
	waitforfifo(scr, 2);
	scr->mmio[mmoffset[OverlayScaleInc]] = 
			((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF);
	scr->mmio[mmoffset[ScalerHeightWidth]] = 
			((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF);
	waitforidle(scr);
	scr->mmio[mmoffset[OverlayScaleCntl]] |= 
			(SCALE_ENABLE|OVERLAY_ENABLE);
}

static void
ovl_status(VGAscr *scr, Chan *, int nfields, char **field)
{
	if (nfields != 1) error(Ebadarg);

	pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %d, rev B %s, refclock %d\n",
		   scr->dev->name, field[0], mach64type->m64_id,
		   mach64type->m64_vtgt? "yes": "no",
		   mach64type->m64_pro? "yes": "no",
		   (int)(mach64type->m64_ovlclock  * 10000.),
		   mach64revb? "yes": "no",
		   (int)(mach64refclock * 10000.));
	pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n",
		   scr->dev->name, scr->storage, scr->aperture,
		   mach64overlay);
}
	
static void
ovl_openctl(VGAscr *, Chan *c, int nfields, char **)
{
	if (nfields != 1) error(Ebadarg);
	if (ovl_chan) error(Einuse);
	ovl_chan = c;
}

static void
ovl_closectl(VGAscr *scr, Chan *c, int nfields, char **)
{
	if (c != ovl_chan || nfields != 1) return;

	waitforidle(scr);
	scr->mmio[mmoffset[OverlayScaleCntl]] &=
			~(SCALE_ENABLE|OVERLAY_ENABLE);
	ovl_chan = nil;
	ovl_width = ovl_height = ovl_fib = 0;
}

static struct {
	char *ovl_command;
	void	 (*ovl_f)(VGAscr *, Chan *, int, char **);
} ovl_cmds[] = {
	{	"openctl",		ovl_openctl	},
	{	"configure", 	ovl_configure,	},
	{	"enable",		ovl_enable,	},
	{	"closectl",		ovl_closectl	},
	{	"status",		ovl_status		},
};

static void
mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int)
{
#define MAXARGS	10
	char *field[MAXARGS];
	int nfields, i;

	if (!mach64type->m64_vtgt) error(Enodev);

	nfields = getfields(a, field, nelem(field), 1, "\t\n\r ");
	if (nfields < 1) error(Ebadarg);

	for (i = 0; i != nelem(ovl_cmds); i++)
		if (!strcmp(field[0], ovl_cmds[i].ovl_command))
			break;

	if (i == nelem(ovl_cmds))
		error(Ebadarg);

	ovl_cmds[i].ovl_f(scr, c, nfields, field);
}

static int
mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs)
{
	uchar *src;
	int _len;

	if (ovl_chan == nil) return len;	/* Acts as a /dev/null */
	
	/* Calculate the destination address */
	_len = len;
	src   = (uchar *)a;
	while (len > 0) {
		ulong _offs;
		int nb;

		_offs = (ulong)(offs % ovl_fib);
		nb     = (_offs + len > ovl_fib)? ovl_fib - _offs: len;
		memmove((uchar *)KADDR(scr->aperture + mach64overlay + _offs), 
				  src, nb);
		offs += nb;
		src  += nb;
		len  -= nb;
	}
	return _len;
}

VGAdev vgamach64xxdev = {
	"mach64xx",



@@ 777,6 1210,9 @@ VGAdev vgamach64xxdev = {
	0,				/* page */
	mach64xxlinear,			/* linear */
	mach64xxdrawinit,	/* drawinit */
	0,
	mach64xxovlctl,	/* overlay control */
	mach64xxovlwrite,	/* write the overlay */
};

VGAcur vgamach64xxcur = {

M port/devdup.c => port/devdup.c +3 -8
@@ 83,10 83,8 @@ dupopen(Chan *c, int omode)
		f->offset = 0;
	}else{
		/* fd file */
		fdtochan(fd, openmode(omode), 0, 0);	/* error check only */
		f = up->fgrp->fd[fd];
		f = fdtochan(fd, openmode(omode), 0, 1);
		cclose(c);
		incref(f);
	}
	if(omode & OCEXEC)
		f->flag |= CCEXEC;


@@ 104,18 102,15 @@ dupread(Chan *c, void *va, long n, vlong offset)
	char *a = va;
	char buf[256];
	int fd, twicefd;
	Fgrp *f;

	if(c->qid.type == QTDIR)
		return devdirread(c, a, n, (Dirtab *)0, 0L, dupgen);
	twicefd = c->qid.path - 1;
	fd = twicefd/2;
	f = up->fgrp;
	if(twicefd & 1){
		if(fd<0 || f->nfd<=fd)
			error(Ebadfd);
		c = fdtochan(fd, -1, 0, 0);
		c = fdtochan(fd, -1, 0, 1);
		procfdprint(c, fd, 0, buf, sizeof buf);
		cclose(c);
		return readstr((ulong)offset, va, n, buf);
	}
	panic("dupread");