/*
* Generic VGA registers.
*/
enum {
       MiscW           = 0x03C2,       /* Miscellaneous Output (W) */
       MiscR           = 0x03CC,       /* Miscellaneous Output (R) */
       Status0         = 0x03C2,       /* Input status 0 (R) */
       Status1         = 0x03DA,       /* Input Status 1 (R) */
       FeatureR        = 0x03CA,       /* Feature Control (R) */
       FeatureW        = 0x03DA,       /* Feature Control (W) */

       Seqx            = 0x03C4,       /* Sequencer Index, Data at Seqx+1 */
       Crtx            = 0x03D4,       /* CRT Controller Index, Data at Crtx+1 */
       Grx             = 0x03CE,       /* Graphics Controller Index, Data at Grx+1 */
       Attrx           = 0x03C0,       /* Attribute Controller Index and Data */

       PaddrW          = 0x03C8,       /* Palette Address Register, write */
       Pdata           = 0x03C9,       /* Palette Data Register */
       Pixmask         = 0x03C6,       /* Pixel Mask Register */
       PaddrR          = 0x03C7,       /* Palette Address Register, read */
       Pstatus         = 0x03C7,       /* DAC Status (RO) */

       Pcolours        = 256,          /* Palette */
       Red             = 0,
       Green           = 1,
       Blue            = 2,

       Pblack          = 0x00,
       Pwhite          = 0xFF,
};

enum {
       RefFreq         = 14318180,     /* External Reference Clock frequency */
       VgaFreq0        = 25175000,
       VgaFreq1        = 28322000,
};

enum {
       Namelen         = 32,
};

typedef struct Ctlr Ctlr;
typedef struct Vga Vga;

typedef struct Ctlr {
       char    name[Namelen+1];
       void    (*snarf)(Vga*, Ctlr*);
       void    (*options)(Vga*, Ctlr*);
       void    (*init)(Vga*, Ctlr*);
       void    (*load)(Vga*, Ctlr*);
       void    (*dump)(Vga*, Ctlr*);
       char*   type;

       ulong   flag;

       Ctlr*   link;
} Ctlr;

enum {                                  /* flag */
       Fsnarf          = 0x00000001,   /* snarf done */
       Foptions        = 0x00000002,   /* options done */
       Finit           = 0x00000004,   /* init done */
       Fload           = 0x00000008,   /* load done */
       Fdump           = 0x00000010,   /* dump done */
       Ferror          = 0x00000020, /* error during snarf */

       Hpclk2x8        = 0x00000100,   /* have double 8-bit mode */
       Upclk2x8        = 0x00000200,   /* use double 8-bit mode */
       Henhanced       = 0x00000400,   /* have enhanced mode */
       Uenhanced       = 0x00000800,   /* use enhanced mode */
       Hpvram          = 0x00001000,   /* have parallel VRAM */
       Upvram          = 0x00002000,   /* use parallel VRAM */
       Hextsid         = 0x00004000,   /* have external SID mode */
       Uextsid         = 0x00008000,   /* use external SID mode */
       Hclk2           = 0x00010000,   /* have clock-doubler */
       Uclk2           = 0x00020000,   /* use clock-doubler */
       Hlinear         = 0x00040000,   /* have linear-address mode */
       Ulinear         = 0x00080000,   /* use linear-address mode */
       Hclkdiv         = 0x00100000,   /* have a clock-divisor */
       Uclkdiv         = 0x00200000,   /* use clock-divisor */
       Hsid32          = 0x00400000,   /* have a 32-bit (as opposed to 64-bit) SID */
};

typedef struct Attr Attr;
struct Attr {
       char*   attr;
       char*   val;

       Attr*   next;
};

typedef struct Mode {
       char    type[Namelen+1];        /* monitor type e.g. "vs1782" */
       char    size[Namelen+1];        /* size e.g. "1376x1024x8" */
       char    chan[Namelen+1];        /* channel descriptor, e.g. "m8" or "r8g8b8a8" */
       char name[Namelen+1];   /* optional */

       int     frequency;              /* Dot Clock (MHz) */
       int     deffrequency;           /* Default dot clock if calculation can't be done */
       int     x;                      /* Horizontal Display End (Crt01), from .size[] */
       int     y;                      /* Vertical Display End (Crt18), from .size[] */
       int     z;                      /* depth, from .size[] */

       int     ht;                     /* Horizontal Total (Crt00) */
       int     shb;                    /* Start Horizontal Blank (Crt02) */
       int     ehb;                    /* End Horizontal Blank (Crt03) */

       int     shs;                    /* optional Start Horizontal Sync (Crt04) */
       int     ehs;                    /* optional End Horizontal Sync (Crt05) */

       int     vt;                     /* Vertical Total (Crt06) */
       int     vrs;                    /* Vertical Retrace Start (Crt10) */
       int     vre;                    /* Vertical Retrace End (Crt11) */

       ulong   videobw;

       char    hsync;
       char    vsync;
       char    interlace;

       Attr*   attr;
} Mode;

typedef struct Modelist Modelist;
struct Modelist {
       Mode;
       Modelist *next;
};

typedef struct Edid {
       char            mfr[4];         /* manufacturer */
       char            serialstr[16];  /* serial number as string (in extended data) */
       char            name[16];       /* monitor name as string (in extended data) */
       ushort          product;        /* product code, 0 = unused */
       ulong           serial;         /* serial number, 0 = unused */
       uchar           version;        /* major version number */
       uchar           revision;       /* minor version number */
       uchar           mfrweek;        /* week of manufacture, 0 = unused */
       int             mfryear;        /* year of manufacture, 0 = unused */
       uchar           dxcm;           /* horizontal image size in cm. */
       uchar           dycm;           /* vertical image size in cm. */
       int             gamma;          /* gamma*100 */
       int             rrmin;          /* minimum vertical refresh rate */
       int             rrmax;          /* maximum vertical refresh rate */
       int             hrmin;          /* minimum horizontal refresh rate */
       int             hrmax;          /* maximum horizontal refresh rate */
       ulong           pclkmax;        /* maximum pixel clock */
       int             flags;
       Modelist        *modelist;      /* list of supported modes */
} Edid;

typedef struct Flag {
       int bit;
       char *desc;
} Flag;

/*
* The sizes of the register sets are large as many SVGA and GUI chips have extras.
* The Crt registers are ushorts in order to keep overflow bits handy.
* The clock elements are used for communication between the VGA, RAMDAC and clock chips;
* they can use them however they like, it's assumed they will be used compatibly.
*
* The mode->x, mode->y coordinates are the physical size of the screen.
* Virtx and virty are the coordinates of the underlying memory image.
* This can be used to implement panning around a larger screen or to cope
* with chipsets that need the in-memory pixel line width to be a round number.
* For example, virge.c uses this because the Savage chipset needs the pixel
* width to be a multiple of 16.  Also, mga2164w.c needs the pixel width
* to be a multiple of 128.
*
* Vga->panning differentiates between these two uses of virtx, virty.
*
* (14 October 2001, rsc) Most drivers don't know the difference between
* mode->x and virtx, a bug that should be corrected.  Vga.c, virge.c, and
* mga2164w.c know.  For the others, the computation that sets crt[0x13]
* should use virtx instead of mode->x (and maybe other places change too,
* dependent on the driver).
*/
typedef struct Vga {
       uchar   misc;
       uchar   feature;
       uchar   sequencer[256];
       ushort  crt[256];
       uchar   graphics[256];
       uchar   attribute[256];
       uchar   pixmask;
       uchar   pstatus;
       uchar   palette[Pcolours][3];

       ulong   f[2];                   /* clock */
       ulong   d[2];
       ulong   i[2];
       ulong   m[2];
       ulong   n[2];
       ulong   p[2];
       ulong   q[2];
       ulong   r[2];

       ulong   vma;                    /* video memory linear-address alignment */
       ulong   vmb;                    /* video memory linear-address base */
       ulong   apz;                    /* aperture size */
       ulong   vmz;                    /* video memory size */

       ulong   membw;                  /* memory bandwidth, MB/s */

       long    offset;                 /* BIOS string offset */
       char*   bios;                   /* matching BIOS string */
       Pcidev* pci;                    /* matching PCI device if any */

       Mode*   mode;

       ulong   virtx;                  /* resolution of virtual screen */
       ulong   virty;

       int     panning;                /* pan the virtual screen */

       Ctlr*   ctlr;
       Ctlr*   ramdac;
       Ctlr*   clock;
       Ctlr*   hwgc;
       Ctlr*   vesa;
       Ctlr*   link;
       int     linear;
       Attr*   attr;

       Edid*   edid[8];                /* edid information for connected monitors */

       void*   private;
} Vga;

/* 3dfx.c */
extern Ctlr tdfx;
extern Ctlr tdfxhwgc;

/* ark2000pv.c */
extern Ctlr ark2000pv;
extern Ctlr ark2000pvhwgc;

/* att20c49x.c */
extern Ctlr att20c490;
extern Ctlr att20c491;
extern Ctlr att20c492;

/* att21c498.c */
extern uchar attdaci(uchar);
extern void attdaco(uchar, uchar);
extern Ctlr att21c498;

/* bt485.c */
extern uchar bt485i(uchar);
extern void bt485o(uchar, uchar);
extern Ctlr bt485;

/* ch9294.c */
extern Ctlr ch9294;

/* clgd542x.c */
extern void clgd54xxclock(Vga*, Ctlr*);
extern Ctlr clgd542x;
extern Ctlr clgd542xhwgc;

/* clgd546x.c */
extern Ctlr clgd546x;
extern Ctlr clgd546xhwgc;

/* ct65540.c */
extern Ctlr ct65540;
extern Ctlr ct65545;
extern Ctlr ct65545hwgc;

/* cyber938x.c */
extern Ctlr cyber938x;
extern Ctlr cyber938xhwgc;

/* data.c */
extern int cflag;
extern int dflag;
extern Ctlr *ctlrs[];
extern ushort dacxreg[4];

/* db.c */
extern Attr* mkattr(Attr*, char*, char*, ...);
extern char* dbattr(Attr*, char*);
extern int dbctlr(char*, Vga*);
extern Mode* dbmode(char*, char*, char*);
extern void dbdumpmode(Mode*);

/* edid.c */
enum {
       Fdigital        = 1<<0, /* is a digital display */
       Fdpmsstandby    = 1<<1, /* supports DPMS standby mode */
       Fdpmssuspend    = 1<<2, /* supports DPMS suspend mode */
       Fdpmsactiveoff  = 1<<3, /* supports DPMS active off mode */
       Fmonochrome     = 1<<4, /* is a monochrome display */
       Fgtf            = 1<<5, /* supports VESA GTF: see /public/doc/vesa/gtf10.pdf */
};
extern Flag edidflags[];
extern void printflags(Flag *f, int b);
extern Edid* parseedid128(void *v);
extern void printedid(Edid *e);

/* error.c */
extern void error(char*, ...);
extern void trace(char*, ...);
extern int vflag, Vflag;

/* et4000.c */
extern Ctlr et4000;

/* et4000hwgc.c */
extern Ctlr et4000hwgc;

/* hiqvideo.c */
extern Ctlr hiqvideo;
extern Ctlr hiqvideohwgc;

/* i81x.c */
extern Ctlr i81x;
extern Ctlr i81xhwgc;

/* ibm8514.c */
extern Ctlr ibm8514;

/* icd2061a.c */
extern Ctlr icd2061a;

/* ics2494.c */
extern Ctlr ics2494;
extern Ctlr ics2494a;

/* ics534x.c */
extern Ctlr ics534x;

/* io.c */
extern uchar inportb(long);
extern void outportb(long, uchar);
extern ushort inportw(long);
extern void outportw(long, ushort);
extern ulong inportl(long);
extern void outportl(long, ulong);
extern char* vgactlr(char*, char*);
extern void vgactlw(char*, char*);
extern char* readbios(long, long);
extern void dumpbios(long);
extern void error(char*, ...);
extern void* alloc(ulong);
extern void printitem(char*, char*);
extern void printreg(ulong);
extern void printflag(ulong);
extern void setpalette(int, int, int, int);
extern int curprintindex;
extern uvlong rdmsr(long);
extern void wrmsr(long, uvlong);

/* geode.c */
extern Ctlr geode;
extern Ctlr geodehwgc;

/* igfx.c */
extern Ctlr igfx;
extern Ctlr igfxhwgc;

/* mach32.c */
extern Ctlr mach32;

/* mach64.c */
extern Ctlr mach64;

/* mach64xx.c */
extern Ctlr mach64xx;
extern Ctlr mach64xxhwgc;

/* main.c */
extern char* chanstr[];
extern void resyncinit(Vga*, Ctlr*, ulong, ulong);
extern void sequencer(Vga*, int);
extern void main(int, char*[]);
Biobuf stdout;

/* mga2164w.c */
extern Ctlr mga2164w;
extern Ctlr mga2164whwgc;

/* neomagic.c */
extern Ctlr neomagic;
extern Ctlr neomagichwgc;

/* nvidia.c */
extern Ctlr nvidia;
extern Ctlr nvidiahwgc;

/* radeon.c */
extern Ctlr radeon;
extern Ctlr radeonhwgc;

/* palette.c */
extern Ctlr palette;

/* pci.c */
typedef struct Pcidev Pcidev;

extern int pcicfgr8(Pcidev*, int);
extern int pcicfgr16(Pcidev*, int);
extern int pcicfgr32(Pcidev*, int);
extern void pcicfgw8(Pcidev*, int, int);
extern void pcicfgw16(Pcidev*, int, int);
extern void pcicfgw32(Pcidev*, int, int);
extern void pcihinv(Pcidev*);
extern Pcidev* pcimatch(Pcidev*, int, int);

/* rgb524.c */
extern Ctlr rgb524;

/* rgb524mn.c */
extern uchar (*rgb524mnxi)(Vga*, int);
extern void (*rgb524mnxo)(Vga*, int, uchar);
extern Ctlr rgb524mn;

/* s3801.c */
extern Ctlr s3801;
extern Ctlr s3805;

/* s3928.c */
extern Ctlr s3928;

/* s3clock.c */
extern Ctlr s3clock;

/* s3generic.c */
extern Ctlr s3generic;

/* s3hwgc.c */
extern Ctlr bt485hwgc;
extern Ctlr rgb524hwgc;
extern Ctlr s3hwgc;
extern Ctlr tvp3020hwgc;
extern Ctlr tvp3026hwgc;

/* sc15025.c */
extern Ctlr sc15025;

/* stg1702.c */
extern Ctlr stg1702;

/* t2r4.c */
extern Ctlr t2r4;
extern Ctlr t2r4hwgc;

/* trio64.c */
extern void trio64clock(Vga*, Ctlr*);
extern Ctlr trio64;

/* tvp3020.c */
extern uchar tvp3020i(uchar);
extern uchar tvp3020xi(uchar);
extern void tvp3020o(uchar, uchar);
extern void tvp3020xo(uchar, uchar);
extern Ctlr tvp3020;

/* tvp3025.c */
extern Ctlr tvp3025;

/* tvp3025clock.c */
extern Ctlr tvp3025clock;

/* tvp3026.c */
extern uchar tvp3026xi(uchar);
extern void tvp3026xo(uchar, uchar);
extern Ctlr tvp3026;

/* tvp3026clock.c */
extern Ctlr tvp3026clock;

/* vga.c */
extern uchar vgai(long);
extern uchar vgaxi(long, uchar);
extern void vgao(long, uchar);
extern void vgaxo(long, uchar, uchar);
extern Ctlr generic;

/* vesa.c */
extern Ctlr vesa;
extern Ctlr softhwgc;   /* has to go somewhere */
extern int dbvesa(Vga*);
extern Mode *dbvesamode(Vga*,char*);
extern void vesatextmode(void);

/* vesadb.c */
extern Mode *vesamodes[];

/* virge.c */
extern Ctlr virge;

/* vision864.c */
extern Ctlr vision864;

/* vision964.c */
extern Ctlr vision964;

/* vision968.c */
extern Ctlr vision968;

/* vmware.c */
extern Ctlr vmware;
extern Ctlr vmwarehwgc;

/* w30c516.c */
extern Ctlr w30c516;

/* mga4xx.c */
extern Ctlr mga4xx;
extern Ctlr mga4xxhwgc;

#pragma varargck        argpos  error   1
#pragma varargck        argpos  trace   1
#pragma varargck        argpos  mkattr  3