From df6c1bb53cdf1ddaf8c63e9023278f44f64b952b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 5 Oct 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-10-05 --- pc/devusb.c | 2 +- pc/devvga.c | 55 ++++- pc/etherec2t.c | 48 ++-- pc/screen.h | 2 + pc/vgamach64xx.c | 582 +++++++++++++++++++++++++++++++++++++++++------ port/devdup.c | 11 +- 6 files changed, 596 insertions(+), 104 deletions(-) diff --git a/pc/devusb.c b/pc/devusb.c index 065a36dcc1bad76b804b7d32dc0c5fdcf341602f..4d9a7af057105054b4a283ca9d756a53551cd44e 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -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; diff --git a/pc/devvga.c b/pc/devvga.c index 2fcfe8e195caad5997baa2b43225ae9fcbaf45b4..e9ecc51564dfd5f4627d356840478435a664d849 100644 --- a/pc/devvga.c +++ b/pc/devvga.c @@ -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; diff --git a/pc/etherec2t.c b/pc/etherec2t.c index 3dd8ec891447d4a663130eda605a40d9bfd006d2..c590c8fd5dc382fc66e4681a2babcc799d61eb30 100644 --- a/pc/etherec2t.c +++ b/pc/etherec2t.c @@ -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 = ðer->opt[i][3]; - if((slot = pcmspecial(type, ether)) >= 0) - break; + if(cistrncmp(ether->opt[i], "id=", 3) == 0){ + ec2t->name = ðer->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++){ diff --git a/pc/screen.h b/pc/screen.h index fa61836334e1d7ee70a8667e341f88b63d397e78..2f034d23b517ed2cfd72911e88c9a242cae8414b 100644 --- a/pc/screen.h +++ b/pc/screen.h @@ -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 { diff --git a/pc/vgamach64xx.c b/pc/vgamach64xx.c index d2f3ddcd3fdf2bb5cc01ff767d0f601599c140d0..ee6c1ff87878e080758be57d8da70a1745f73099 100644 --- a/pc/vgamach64xx.c +++ b/pc/vgamach64xx.c @@ -12,32 +12,134 @@ #include #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 @@ -533,10 +686,47 @@ resetengine(VGAscr *scr) iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000); } +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 = { diff --git a/port/devdup.c b/port/devdup.c index ad4e42df79ca98240e1fd8cdcb2bef15f00c5869..d9c6e3dd90e80585177b6437e19c9baa2fef6ea8 100644 --- a/port/devdup.c +++ b/port/devdup.c @@ -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");