The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/vgamach64xx.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "io.h"
    7 #include "../port/error.h"
    8 
    9 #define Image   IMAGE
   10 #include <draw.h>
   11 #include <memdraw.h>
   12 #include <cursor.h>
   13 #include "screen.h"
   14 
   15 char Eunsupportedformat[] = "unsupported video format";
   16 char Enotconfigured[] = "device not configured";
   17 
   18 #define SCALE_ZERO_EXTEND               0x0
   19 #define SCALE_DYNAMIC                           0x1
   20 #define SCALE_RED_TEMP_6500K            0x0
   21 #define SCALE_RED_TEMP_9800K            0x2
   22 #define SCALE_HORZ_BLEND                0x0
   23 #define SCALE_HORZ_REP                          0x4
   24 #define SCALE_VERT_BLEND                        0x0
   25 #define SCALE_VERT_REP                          0x8
   26 #define SCALE_BANDWIDTH_NORMAL     0x0
   27 #define SCALE_BANDWIDTH_EXCEEDED  0x4000000
   28 #define SCALE_BANDWIDTH_RESET           0x4000000
   29 #define SCALE_CLK_ACTIVITY              0x0
   30 #define SCALE_CLK_CONTINUOUS            0x20000000
   31 #define OVERLAY_DISABLE                         0x0
   32 #define OVERLAY_ENABLE                          0x40000000
   33 #define SCALE_DISABLE                           0x0
   34 #define SCALE_ENABLE                            0x80000000
   35 
   36 #define SCALER_FRAME_READ_MODE_FULL     0x0
   37 #define SCALER_BUF_MODE_SINGLE                  0x0
   38 #define SCALER_BUF_MODE_DOUBLE                  0x40000
   39 #define SCALER_BUF_NEXT_0                       0x0
   40 #define SCALER_BUF_NEXT_1                       0x80000
   41 #define SCALER_BUF_STATUS_0                     0x0
   42 #define SCALER_BUF_STATUS_1                     0x100000
   43 
   44 #define OVERLAY_MIX_G_CMP                       0x0
   45 #define OVERLAY_MIX_ALWAYS_G                    0x100
   46 #define OVERLAY_MIX_ALWAYS_V                    0x200
   47 #define OVERLAY_MIX_NOT_G                       0x300
   48 #define OVERLAY_MIX_NOT_V                       0x400
   49 #define OVERLAY_MIX_G_XOR_V                     0x500
   50 #define OVERLAY_MIX_NOT_G_XOR_V         0x600
   51 #define OVERLAY_MIX_V_CMP                       0x700
   52 #define OVERLAY_MIX_NOT_G_OR_NOT_V      0x800
   53 #define OVERLAY_MIX_G_OR_NOT_V          0x900
   54 #define OVERLAY_MIX_NOT_G_OR_V          0xA00
   55 #define OVERLAY_MIX_G_OR_V                      0xB00
   56 #define OVERLAY_MIX_G_AND_V                     0xC00
   57 #define OVERLAY_MIX_NOT_G_AND_V         0xD00
   58 #define OVERLAY_MIX_G_AND_NOT_V         0xE00
   59 #define OVERLAY_MIX_NOT_G_AND_NOT_V     0xF00
   60 #define OVERLAY_EXCLUSIVE_NORMAL        0x0
   61 #define OVERLAY_EXCLUSIVE_V_ONLY        0x80000000
   62 
   63 #define VIDEO_IN_8BPP                                   0x2
   64 #define VIDEO_IN_16BPP                                  0x4
   65 #define VIDEO_IN_32BPP                                  0x6
   66 #define VIDEO_IN_VYUY422                                0xB                     /*16 bpp */
   67 #define VIDEO_IN_YVYU422                                0xC                     /* 16 bpp */
   68 #define SCALE_IN_15BPP                                  0x30000         /* aRGB 1555 */
   69 #define SCALE_IN_16BPP                                  0x40000         /* RGB 565 */
   70 #define SCALE_IN_32BPP                                  0x60000         /* aRGB 8888 */
   71 #define SCALE_IN_YUV9                                   0x90000         /* planar */
   72 #define SCALE_IN_YUV12                                  0xA0000         /* planar */
   73 #define SCALE_IN_VYUY422                                0xB0000         /* 16 bpp */
   74 #define SCALE_IN_YVYU422                                0xC0000         /* 16 bpp */
   75 #define HOST_YUV_APERTURE_UPPER                 0x0
   76 #define HOST_YUV_APERTURE_LOWER         0x20000000
   77 #define HOST_MEM_MODE_Y                         0x40000000
   78 #define HOST_MEM_MODE_U                         0x80000000
   79 #define HOST_MEM_MODE_V                         0xC0000000
   80 #define HOST_MEM_MODE_NORMAL                    HOST_YUV_APERTURE_UPPER 
   81 
   82 static Chan *ovl_chan;          /* Channel of controlling process */
   83 static int ovl_width;           /* Width of input overlay buffer */
   84 static int ovl_height;          /* Height of input overlay buffer */
   85 static int ovl_format;          /* Overlay format */
   86 static ulong ovl_fib;           /* Frame in bytes */
   87 
   88 enum {
   89          VTGTB1S1       = 0x01, /* Asic description for VTB1S1 and GTB1S1. */
   90          VT4GTIIC       = 0x3A,         /* asic descr for VT4 and RAGE IIC */
   91          GTB1U1         = 0x19,         /* Asic description for GTB1U1. */
   92          GTB1S2         = 0x41,         /* Asic description for GTB1S2. */
   93          GTB2U1         = 0x1A,
   94          GTB2U2         = 0x5A,
   95          GTB2U3         = 0x9A,
   96          GTIIIC1U1      = 0x1B,         /* 3D RAGE PRO asic descrp. */
   97          GTIIIC1U2      = 0x5B,         /* 3D RAGE PRO asic descrp. */
   98          GTIIIC2U1      = 0x1C,         /* 3D RAGE PRO asic descrp. */
   99          GTIIIC2U2      = 0x5C,         /* 3D RAGE PRO asic descrp. */
  100          GTIIIC2U3      = 0x7C,         /* 3D RAGE PRO asic descrp. */
  101          GTBC           = 0x3A,         /* 3D RAGE IIC asic descrp. */
  102          LTPRO          = 0x9C,         /* 3D RAGE LT PRO */
  103 };
  104 
  105 /*
  106  * ATI Mach64(CT|ET|G*|V*|L*).
  107  */
  108 typedef struct Mach64types Mach64types;
  109 struct Mach64types {
  110         ushort  m64_id;                 /* Chip ID */
  111         int     m64_vtgt;               /* Is this a VT or GT chipset? */
  112         ulong   m64_ovlclock;           /* Max. overlay clock frequency */
  113         int     m64_pro;                /* Is this a PRO? */
  114 };
  115 
  116 static ulong mach64refclock;
  117 static Mach64types *mach64type;
  118 static int mach64revb;                  /* Revision B or greater? */
  119 static ulong mach64overlay;             /* Overlay buffer */
  120 
  121 static Mach64types mach64s[] = {
  122         ('C'<<8)|'T',   0,      1350000, /*?*/  0,      /* 4354: CT */
  123         ('E'<<8)|'T',   0,      1350000, /*?*/  0,      /* 4554: ET */
  124         ('G'<<8)|'B',   1,      1250000,        1,      /* 4742: 264GT PRO */
  125         ('G'<<8)|'D',   1,      1250000,        1,      /* 4744: 264GT PRO */
  126         ('G'<<8)|'I',   1,      1250000,        1,      /* 4749: 264GT PRO */
  127         ('G'<<8)|'M',   0,      1350000,        0,      /* 474D: Rage XL */
  128         ('G'<<8)|'P',   1,      1250000,        1,      /* 4750: 264GT PRO */
  129         ('G'<<8)|'Q',   1,      1250000,        1,      /* 4751: 264GT PRO */
  130         ('G'<<8)|'R',   1,      1250000,        1,      /* 4752: */
  131         ('G'<<8)|'T',   1,      800000,         0,      /* 4754: 264GT[B] */
  132         ('G'<<8)|'U',   1,      1000000,        0,      /* 4755: 264GT DVD */
  133         ('G'<<8)|'V',   1,      1000000,        0,      /* 4756: Rage2C */
  134         ('G'<<8)|'Z',   1,      1000000,        0,      /* 475A: Rage2C */
  135         ('V'<<8)|'T',   1,      800000,         0,      /* 5654: 264VT/GT/VTB */
  136         ('V'<<8)|'U',   1,      800000,         0,      /* 5655: 264VT3 */
  137         ('V'<<8)|'V',   1,      1000000,        0,      /* 5656: 264VT4 */
  138         ('L'<<8)|'B',   0,      1350000,        1,      /* 4C42: Rage LTPro AGP */
  139         ('L'<<8)|'I',   0,      1350000,        0,      /* 4C49: Rage LTPro AGP */
  140         ('L'<<8)|'M',   0,      1350000,        0,      /* 4C4D: Rage Mobility */
  141         ('L'<<8)|'P',   0,      1350000,        1,      /* 4C50: 264LT PRO */
  142 };
  143 
  144 
  145 static int hwfill(VGAscr*, Rectangle, ulong);
  146 static int hwscroll(VGAscr*, Rectangle, Rectangle);
  147 static void initengine(VGAscr*);
  148 
  149 static Pcidev*
  150 mach64xxpci(void)
  151 {
  152         Pcidev *p;
  153         int i;
  154 
  155         if((p = pcimatch(nil, 0x1002, 0)) == nil)
  156                 return nil;
  157 
  158         for (i = 0; i != nelem(mach64s); i++)
  159                 if (mach64s[i].m64_id == p->did) {
  160                         mach64type = &mach64s[i];
  161                         return p;
  162                 }
  163         return nil;
  164 }
  165 
  166 static void
  167 mach64xxenable(VGAscr* scr)
  168 {
  169         Pcidev *p;
  170 
  171         if(scr->io)
  172                 return;
  173         if(p = mach64xxpci()){
  174                 scr->id = p->did;
  175                 scr->pci = p;
  176 
  177                 /*
  178                  * The CT doesn't always have the I/O base address
  179                  * in the PCI base registers. There is a way to find
  180                  * it via the vendor-specific PCI config space but
  181                  * this will do for now.
  182                  */
  183                 scr->io = p->mem[1].bar & ~0x03;
  184 
  185                 if(scr->io == 0)
  186                         scr->io = 0x2EC;
  187         }
  188 }
  189 
  190 static void
  191 mach64xxlinear(VGAscr* scr, int size, int)
  192 {
  193         vgalinearpci(scr);
  194         if(scr->paddr == 0)
  195                 return;
  196         scr->mmio = (ulong*)((uchar*)scr->vaddr+size-1024);
  197         addvgaseg("mach64mmio", scr->paddr+size-BY2PG, BY2PG);
  198         addvgaseg("mach64screen", scr->paddr, scr->apsize);
  199 }
  200 
  201 enum {
  202         CrtcOffPitch    = 0x05,
  203         CrtcGenCtl      = 0x07,
  204         CurClr0         = 0x0B,         /* I/O Select */
  205         CurClr1         = 0x0C,
  206         CurOffset       = 0x0D,
  207         CurHVposn       = 0x0E,
  208         CurHVoff        = 0x0F,
  209         BusCntl = 0x13,
  210         GenTestCntl     = 0x19,
  211 
  212         CrtcHsyncDis    = 0x04,
  213         CrtcVsyncDis    = 0x08,
  214 
  215         ContextMask     = 0x100,        /* not accessible via I/O */
  216         FifoStat,
  217         GuiStat,
  218         DpFrgdClr,
  219         DpBkgdClr,
  220         DpWriteMask,
  221         DpMix,
  222         DpPixWidth,
  223         DpSrc,
  224         ClrCmpCntl,
  225         GuiTrajCntl,
  226         ScLeftRight,
  227         ScTopBottom,
  228         DstOffPitch,
  229         DstYX,
  230         DstHeightWidth,
  231         DstCntl,
  232         DstHeight,
  233         DstBresErr,
  234         DstBresInc,
  235         DstBresDec,
  236         SrcCntl,
  237         SrcHeight1Width1,
  238         SrcHeight2Width2,
  239         SrcYX,
  240         SrcWidth1,
  241         SrcYXstart,
  242         HostCntl,
  243         PatReg0,
  244         PatReg1,
  245         PatCntl,
  246         ScBottom,
  247         ScLeft,
  248         ScRight,
  249         ScTop,
  250         ClrCmpClr,
  251         ClrCmpMask,
  252         DpChainMask,
  253         SrcOffPitch,    
  254         LcdIndex,
  255         LcdData,
  256         ClockCntl,
  257         OverlayScaleCntl,
  258         ConfigChipId,
  259         Buf0Pitch,
  260         ScalerBuf0Pitch,
  261         CaptureConfig,
  262         OverlayKeyCntl,
  263         ScalerColourCntl,
  264         ScalerHCoef0,
  265         ScalerHCoef1,
  266         ScalerHCoef2,
  267         ScalerHCoef3,
  268         ScalerHCoef4,
  269         VideoFormat,
  270         Buf0Offset,
  271         ScalerBuf0Offset,
  272         CrtcGenCntl,
  273         OverlayScaleInc,
  274         OverlayYX,
  275         OverlayYXEnd,
  276         ScalerHeightWidth,
  277         HTotalDisp,
  278         VTotalDisp,
  279 };
  280 
  281 enum {
  282         LCD_ConfigPanel = 0,
  283         LCD_GenCtrl,
  284         LCD_DstnCntl,
  285         LCD_HfbPitchAddr,
  286         LCD_HorzStretch,
  287         LCD_VertStretch,
  288         LCD_ExtVertStretch,
  289         LCD_LtGio,
  290         LCD_PowerMngmnt,
  291         LCD_ZvgPio,
  292         Nlcd,
  293 };
  294 
  295 #define Bank1                   (-0x100)                /* 1KB */
  296 
  297 static int mmoffset[] = {
  298         [HTotalDisp]            0x00,
  299         [VTotalDisp]            0x02,
  300         [CrtcOffPitch]          0x05,
  301         [CrtcGenCntl]           0x07,
  302         [CurClr0]                       0x18,
  303         [CurClr1]                       0x19,
  304         [CurOffset]             0x1A,
  305         [CurHVposn]             0x1B,
  306         [CurHVoff]              0x1C,
  307         [ClockCntl]             0x24,
  308         [BusCntl]                       0x28,
  309         [LcdIndex]              0x29,
  310         [LcdData]                       0x2A,
  311         [GenTestCntl]           0x34,
  312         [ConfigChipId]          0x38,
  313         [DstOffPitch]           0x40,
  314         [DstYX]                 0x43,
  315         [DstHeight]             0x45,
  316         [DstHeightWidth]        0x46,
  317         [DstBresErr]            0x49,
  318         [DstBresInc]            0x4A,
  319         [DstBresDec]            0x4B,
  320         [DstCntl]                       0x4C,
  321         [SrcOffPitch]           0x60,
  322         [SrcYX]                 0x63,
  323         [SrcWidth1]             0x64,
  324         [SrcYXstart]            0x69,
  325         [SrcHeight1Width1]      0x66,
  326         [SrcHeight2Width2]      0x6C,
  327         [SrcCntl]                       0x6D,
  328         [HostCntl]                      0x90,
  329         [PatReg0]                       0xA0,
  330         [PatReg1]                       0xA1,
  331         [PatCntl]                       0xA2,
  332         [ScLeft]                        0xA8,
  333         [ScRight]                       0xA9,
  334         [ScLeftRight]           0xAA,
  335         [ScTop]                 0xAB,
  336         [ScBottom]              0xAC,
  337         [ScTopBottom]           0xAD,
  338         [DpBkgdClr]             0xB0,
  339         [DpFrgdClr]             0xB1,
  340         [DpWriteMask]           0xB2,
  341         [DpChainMask]           0xB3,
  342         [DpPixWidth]            0xB4,
  343         [DpMix]                 0xB5,
  344         [DpSrc]                 0xB6,
  345         [ClrCmpClr]             0xC0,
  346         [ClrCmpMask]            0xC1,
  347         [ClrCmpCntl]            0xC2,
  348         [FifoStat]                      0xC4,
  349         [ContextMask]           0xC8,
  350         [GuiTrajCntl]           0xCC,
  351         [GuiStat]                       0xCE,
  352 
  353         /* Bank1 */
  354         [OverlayYX]             Bank1 + 0x00,
  355         [OverlayYXEnd]          Bank1 + 0x01,
  356         [OverlayKeyCntl]        Bank1 + 0x06,
  357         [OverlayScaleInc]       Bank1 + 0x08,
  358         [OverlayScaleCntl]      Bank1 + 0x09,
  359         [ScalerHeightWidth]     Bank1 + 0x0A,
  360         [ScalerBuf0Offset]      Bank1 + 0x0D,
  361         [ScalerBuf0Pitch]       Bank1 + 0x0F,
  362         [VideoFormat]           Bank1 + 0x12,
  363         [CaptureConfig] Bank1 + 0x14,
  364         [Buf0Offset]            Bank1 + 0x20,
  365         [Buf0Pitch]             Bank1 + 0x23,
  366         [ScalerColourCntl]      Bank1 + 0x54,
  367         [ScalerHCoef0]          Bank1 + 0x55,
  368         [ScalerHCoef1]          Bank1 + 0x56,
  369         [ScalerHCoef2]          Bank1 + 0x57,
  370         [ScalerHCoef3]          Bank1 + 0x58,
  371         [ScalerHCoef4]          Bank1 + 0x59,
  372 };
  373 
  374 static ulong
  375 ior32(VGAscr* scr, int r)
  376 {
  377         if(scr->io == 0x2EC || scr->io == 0x1C8)
  378                 return inl((r<<10)+scr->io);
  379         if(r >= 0x100 && scr->mmio != nil)
  380                 return scr->mmio[mmoffset[r]];
  381         return inl((mmoffset[r]<<2)+scr->io);
  382 }
  383 
  384 static void
  385 iow32(VGAscr* scr, int r, ulong l)
  386 {
  387         if(scr->io == 0x2EC || scr->io == 0x1C8)
  388                 outl(((r)<<10)+scr->io, l);
  389         else if(r >= 0x100 && scr->mmio != nil)
  390                 scr->mmio[mmoffset[r]] = l;
  391         else
  392                 outl((mmoffset[r]<<2)+scr->io, l);
  393 }
  394 
  395 static ulong
  396 lcdr32(VGAscr *scr, ulong r)
  397 {
  398         ulong or;
  399 
  400         or = ior32(scr, LcdIndex);
  401         iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F));
  402         return ior32(scr, LcdData);
  403 }
  404 
  405 static void
  406 lcdw32(VGAscr *scr, ulong r, ulong v)
  407 {
  408         ulong or;
  409 
  410         or = ior32(scr, LcdIndex);
  411         iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F));
  412         iow32(scr, LcdData, v);
  413 }
  414 
  415 static void
  416 mach64xxcurdisable(VGAscr* scr)
  417 {
  418         ulong r;
  419 
  420         r = ior32(scr, GenTestCntl);
  421         iow32(scr, GenTestCntl, r & ~0x80);
  422 }
  423 
  424 static void
  425 mach64xxcurload(VGAscr* scr, Cursor* curs)
  426 {
  427         uchar *p;
  428         int i, y;
  429         ulong c, s, m, r;
  430 
  431         /*
  432          * Disable the cursor.
  433          */
  434         r = ior32(scr, GenTestCntl);
  435         iow32(scr, GenTestCntl, r & ~0x80);
  436 
  437         p = scr->vaddr;
  438         p += scr->storage;
  439 
  440         /*
  441          * Initialise the 64x64 cursor RAM array.
  442          * The cursor mode gives the following truth table:
  443          *      p1 p0   colour
  444          *       0  0   Cursor Colour 0
  445          *       0  1   Cursor Colour 1
  446          *       1  0   Transparent
  447          *       1  1   Complement
  448          * Put the cursor into the top-right of the 64x64 array.
  449          */
  450         for(y = 0; y < 16; y++){
  451                 for(i = 0; i < (64-16)/8; i++){
  452                         *p++ = 0xAA;
  453                         *p++ = 0xAA;
  454                 }
  455 
  456                 c = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
  457                 s = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
  458 
  459                 m = 0x00000000;
  460                 for(i = 0; i < 16; i++){
  461                         if(s & (1<<(15-i)))
  462                                 m |= 0x01<<(2*i);
  463                         else if(c & (1<<(15-i))){
  464                                 /* nothing to do */
  465                         }
  466                         else
  467                                 m |= 0x02<<(2*i);
  468                 }
  469                 *p++ = m;
  470                 *p++ = m>>8;
  471                 *p++ = m>>16;
  472                 *p++ = m>>24;
  473         }
  474         memset(p, 0xAA, (64-16)*16);
  475 
  476         /*
  477          * Set the cursor hotpoint and enable the cursor.
  478          */
  479         scr->offset = curs->offset;
  480         iow32(scr, GenTestCntl, 0x80|r);
  481 }
  482 
  483 static int
  484 ptalmostinrect(Point p, Rectangle r)
  485 {
  486         return p.x>=r.min.x && p.x<=r.max.x &&
  487                p.y>=r.min.y && p.y<=r.max.y;
  488 }
  489 
  490 /*
  491  * If necessary, translate the rectangle physr
  492  * some multiple of [dx dy] so that it includes p.
  493  * Return 1 if the rectangle changed.
  494  */
  495 static int
  496 screenpan(Point p, Rectangle *physr, int dx, int dy)
  497 {
  498         int d;
  499 
  500         if(ptalmostinrect(p, *physr))
  501                 return 0;
  502 
  503         if(p.y < physr->min.y){
  504                 d = physr->min.y - (p.y&~(dy-1));
  505                 physr->min.y -= d;
  506                 physr->max.y -= d;
  507         }
  508         if(p.y > physr->max.y){
  509                 d = ((p.y+dy-1)&~(dy-1)) - physr->max.y;
  510                 physr->min.y += d;
  511                 physr->max.y += d;
  512         }
  513 
  514         if(p.x < physr->min.x){
  515                 d = physr->min.x - (p.x&~(dx-1));
  516                 physr->min.x -= d;
  517                 physr->max.x -= d;
  518         }
  519         if(p.x > physr->max.x){
  520                 d = ((p.x+dx-1)&~(dx-1)) - physr->max.x;
  521                 physr->min.x += d;
  522                 physr->max.x += d;
  523         }
  524         return 1;
  525 }
  526 
  527 static int
  528 mach64xxcurmove(VGAscr* scr, Point p)
  529 {
  530         int x, xo, y, yo;
  531         int dx;
  532         ulong off, pitch;
  533 
  534         /*
  535          * If the point we want to display is outside the current
  536          * screen rectangle, pan the screen to display it.
  537          *
  538          * We have to move in 64-bit chunks.
  539          */
  540         if(scr->gscreen->depth == 24)
  541                 dx = (64*3)/24;
  542         else
  543                 dx = 64 / scr->gscreen->depth;
  544 
  545         if(panning && screenpan(p, &physgscreenr, dx, 1)){
  546                 off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx;
  547                 pitch = Dx(scr->gscreen->r)/8;
  548                 iow32(scr, CrtcOffPitch, (pitch<<22)|off);
  549         }
  550 
  551         p.x -= physgscreenr.min.x;
  552         p.y -= physgscreenr.min.y;
  553 
  554         /*
  555          * Mustn't position the cursor offscreen even partially,
  556          * or it disappears. Therefore, if x or y is -ve, adjust the
  557          * cursor presets instead. If y is negative also have to
  558          * adjust the starting offset.
  559          */
  560         if((x = p.x+scr->offset.x) < 0){
  561                 xo = x;
  562                 x = 0;
  563         }
  564         else
  565                 xo = 0;
  566         if((y = p.y+scr->offset.y) < 0){
  567                 yo = y;
  568                 y = 0;
  569         }
  570         else
  571                 yo = 0;
  572 
  573         iow32(scr, CurHVoff, ((64-16-yo)<<16)|(64-16-xo));
  574         iow32(scr, CurOffset, scr->storage/8 + (-yo*2));
  575         iow32(scr, CurHVposn, (y<<16)|x);
  576 
  577         return 0;
  578 }
  579 
  580 static void
  581 mach64xxcurenable(VGAscr* scr)
  582 {
  583         ulong r, storage;
  584 
  585         mach64xxenable(scr);
  586         if(scr->io == 0)
  587                 return;
  588 
  589         r = ior32(scr, GenTestCntl);
  590         iow32(scr, GenTestCntl, r & ~0x80);
  591 
  592         iow32(scr, CurClr0, (Pwhite<<24)|(Pwhite<<16)|(Pwhite<<8)|Pwhite);
  593         iow32(scr, CurClr1, (Pblack<<24)|(Pblack<<16)|(Pblack<<8)|Pblack);
  594 
  595         /*
  596          * Find a place for the cursor data in display memory.
  597          * Must be 64-bit aligned.
  598          */
  599         storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+7)/8;
  600         iow32(scr, CurOffset, storage);
  601         scr->storage = storage*8;
  602 
  603         /*
  604          * Cursor goes in the top right corner of the 64x64 array
  605          * so the horizontal and vertical presets are 64-16.
  606          */
  607         iow32(scr, CurHVposn, (0<<16)|0);
  608         iow32(scr, CurHVoff, ((64-16)<<16)|(64-16));
  609 
  610         /*
  611          * Load, locate and enable the 64x64 cursor.
  612          */
  613         mach64xxcurload(scr, &arrow);
  614         mach64xxcurmove(scr, ZP);
  615         iow32(scr, GenTestCntl, 0x80|r);
  616 }
  617 
  618 static void
  619 waitforfifo(VGAscr *scr, int entries)
  620 {
  621         int x;
  622 
  623         x = 0;
  624         while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000)
  625                 ;
  626         if(x >= 1000000)
  627                 iprint("fifo %d stat %#.8lux %#.8lux scrio %#.8lux mmio %#p scr %#p pc %#p\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));
  628 }
  629 
  630 static void
  631 waitforidle(VGAscr *scr)
  632 {
  633         int x;
  634 
  635         waitforfifo(scr, 16);
  636         x = 0;
  637         while((ior32(scr, GuiStat)&1) && x++ < 1000000)
  638                 ;
  639         if(x >= 1000000)
  640                 iprint("idle stat %#.8lux %#.8lux scrio %#.8lux mmio %#p scr %#p pc %#p\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));
  641 }
  642 
  643 static void
  644 resetengine(VGAscr *scr)
  645 {
  646         ulong x;
  647         x = ior32(scr, GenTestCntl);
  648         iow32(scr, GenTestCntl, x&~0x100);
  649         iow32(scr, GenTestCntl, x|0x100);
  650         iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000);
  651 }
  652 
  653 static void
  654 init_overlayclock(VGAscr *scr)
  655 {
  656         uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div, 
  657                         vclk_fb_div, ecp_div;
  658         int i;
  659         ulong dotclock;
  660 
  661         /* Taken from GLX */
  662         /* Get monitor dotclock, check for Overlay Scaler clock limit */
  663         cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]];
  664         save = cc[1]; i = cc[0] & 3;
  665         cc[1] = 2<<2; pll_ref_div = cc[2];
  666         cc[1] = 5<<2; pll_vclk_cntl = cc[2];
  667         cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3;
  668         cc[1] = (7+i)<<2; vclk_fb_div = cc[2];
  669 
  670         dotclock = 2 * mach64refclock * vclk_fb_div / 
  671                         (pll_ref_div * (1 << vclk_post_div));
  672         /* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */
  673         ecp_div = dotclock / mach64type->m64_ovlclock;
  674         if (ecp_div>2) ecp_div = 2;
  675 
  676         /* Force a scaler clock factor of 1 if refclock *
  677           * is unknown (VCLK_SRC not PLLVCLK)  */
  678         if ((pll_vclk_cntl & 0x03) != 0x03) 
  679                 ecp_div = 0;
  680         if ((pll_vclk_cntl & 0x30) != ecp_div<<4) {
  681                 cc[1] = (5<<2)|2;
  682                 cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4);
  683         }
  684 
  685         /* Restore PLL Register Index */
  686         cc[1] = save;
  687 }
  688 
  689 static void
  690 initengine(VGAscr *scr)
  691 {
  692         ulong pitch;
  693         uchar *bios;
  694         ushort table;
  695 
  696         pitch = Dx(scr->gscreen->r)/8;
  697         if(scr->gscreen->depth == 24)
  698                 pitch *= 3;
  699 
  700         resetengine(scr);
  701         waitforfifo(scr, 14);
  702         iow32(scr, ContextMask, ~0);
  703         iow32(scr, DstOffPitch, pitch<<22);
  704         iow32(scr, DstYX, 0);
  705         iow32(scr, DstHeight, 0);
  706         iow32(scr, DstBresErr, 0);
  707         iow32(scr, DstBresInc, 0);
  708         iow32(scr, DstBresDec, 0);
  709         iow32(scr, DstCntl, 0x23);
  710         iow32(scr, SrcOffPitch, pitch<<22);
  711         iow32(scr, SrcYX, 0);
  712         iow32(scr, SrcHeight1Width1, 1);
  713         iow32(scr, SrcYXstart, 0);
  714         iow32(scr, SrcHeight2Width2, 1);
  715         iow32(scr, SrcCntl, 0x01);
  716 
  717         waitforfifo(scr, 13);
  718         iow32(scr, HostCntl, 0);
  719         iow32(scr, PatReg0, 0);
  720         iow32(scr, PatReg1, 0);
  721         iow32(scr, PatCntl, 0);
  722         iow32(scr, ScLeft, 0);
  723         iow32(scr, ScTop, 0);
  724         iow32(scr, ScBottom, 0xFFFF);
  725         iow32(scr, ScRight, 0xFFFF);
  726         iow32(scr, DpBkgdClr, 0);
  727         iow32(scr, DpFrgdClr, ~0);
  728         iow32(scr, DpWriteMask, ~0);
  729         iow32(scr, DpMix, 0x70003);
  730         iow32(scr, DpSrc, 0x00010100);
  731 
  732         waitforfifo(scr, 3);
  733         iow32(scr, ClrCmpClr, 0);
  734         iow32(scr, ClrCmpMask, ~0);
  735         iow32(scr, ClrCmpCntl, 0);
  736 
  737         waitforfifo(scr, 2);
  738         switch(scr->gscreen->depth){
  739         case 8:
  740         case 24:        /* [sic] */
  741                 iow32(scr, DpPixWidth, 0x00020202);
  742                 iow32(scr, DpChainMask, 0x8080);
  743                 break;
  744         case 16:
  745                 iow32(scr, DpPixWidth, 0x00040404);
  746                 iow32(scr, DpChainMask, 0x8410);
  747                 break;
  748         case 32:
  749                 iow32(scr, DpPixWidth, 0x00060606);
  750                 iow32(scr, DpChainMask, 0x8080);
  751                 break;
  752         }
  753 
  754         /* Get the base freq from the BIOS */
  755         bios  = kaddr(0xC000);
  756         table = *(ushort *)(bios + 0x48);
  757         table = *(ushort *)(bios + table + 0x10);
  758         switch (*(ushort *)(bios + table + 0x08)) {
  759         case 2700: 
  760                 mach64refclock = 270000; 
  761                 break;
  762         case 2863: 
  763         case 2864: 
  764                 mach64refclock = 286363; 
  765                 break;
  766         case 2950: 
  767                 mach64refclock = 294989; 
  768                 break;
  769         case 1432: 
  770         default:
  771                 mach64refclock = 143181; 
  772                 break ; 
  773         }
  774         
  775         /* Figure out which revision this chip is */
  776         switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) {
  777         case VTGTB1S1:
  778         case GTB1U1:
  779         case GTB1S2:
  780         case GTB2U1:
  781         case GTB2U2:
  782         case GTB2U3:
  783         case GTBC:
  784         case GTIIIC1U1:
  785         case GTIIIC1U2:
  786         case GTIIIC2U1:
  787         case GTIIIC2U2: 
  788         case GTIIIC2U3: 
  789         case LTPRO:
  790                         mach64revb = 1;
  791                         break;
  792         default: 
  793                         mach64revb = 0;
  794                         break;
  795         }
  796 
  797         waitforidle(scr);
  798 }
  799 
  800 static int
  801 mach64hwfill(VGAscr *scr, Rectangle r, ulong sval)
  802 {
  803         ulong pitch;
  804         ulong ctl;
  805 
  806 if(drawdebug)
  807         iprint("hwfill %R val %lux...\n", r, sval);
  808 
  809         /* shouldn't happen */
  810         if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0)
  811                 return 0;
  812 
  813         pitch = Dx(scr->gscreen->r)/8;
  814         ctl = 1|2;      /* left-to-right, top-to-bottom */
  815         if(scr->gscreen->depth == 24){
  816                 r.min.x *= 3;
  817                 r.max.x *= 3;
  818                 pitch *= 3;
  819                 ctl |= (1<<7)|(((r.min.x/4)%6)<<8);
  820         }
  821 
  822         waitforfifo(scr, 11);
  823         iow32(scr, DpFrgdClr, sval);
  824         iow32(scr, DpWriteMask, 0xFFFFFFFF);
  825         iow32(scr, DpMix, 0x00070003);
  826         iow32(scr, DpSrc, 0x00000111);
  827         iow32(scr, ClrCmpCntl, 0x00000000);
  828         iow32(scr, ScLeftRight, 0x1FFF0000);
  829         iow32(scr, ScTopBottom, 0x1FFF0000);
  830         iow32(scr, DstOffPitch, pitch<<22);
  831         iow32(scr, DstCntl, ctl);
  832         iow32(scr, DstYX, (r.min.x<<16)|r.min.y);
  833         iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r));
  834 
  835         waitforidle(scr);
  836         return 1;
  837 }
  838 
  839 static int
  840 mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  841 {
  842         ulong pitch;
  843         Point dp, sp;
  844         ulong ctl;
  845         int dx, dy;
  846 
  847         dx = Dx(r);
  848         dy = Dy(r);
  849         pitch = Dx(scr->gscreen->r)/8;
  850         if(scr->gscreen->depth == 24){
  851                 dx *= 3;
  852                 pitch *= 3;
  853                 r.min.x *= 3;
  854                 sr.min.x *= 3;
  855         }
  856 
  857         ctl = 0;
  858         if(r.min.x <= sr.min.x){
  859                 ctl |= 1;
  860                 dp.x = r.min.x;
  861                 sp.x = sr.min.x;
  862         }else{
  863                 dp.x = r.min.x+dx-1;
  864                 sp.x = sr.min.x+dx-1;
  865         }
  866 
  867         if(r.min.y <= sr.min.y){
  868                 ctl |= 2;
  869                 dp.y = r.min.y;
  870                 sp.y = sr.min.y;
  871         }else{
  872                 dp.y = r.min.y+dy-1;
  873                 sp.y = sr.min.y+dy-1;
  874         }
  875 
  876         if(scr->gscreen->depth == 24)
  877                 ctl |= (1<<7)|(((dp.x/4)%6)<<8);
  878 
  879         waitforfifo(scr, 6);
  880         iow32(scr, ScLeftRight, 0x1FFF0000);
  881         iow32(scr, ScTopBottom, 0x1FFF0000);
  882         iow32(scr, DpWriteMask, 0xFFFFFFFF);
  883         iow32(scr, DpMix, 0x00070003);
  884         iow32(scr, DpSrc, 0x00000300);
  885         iow32(scr, ClrCmpCntl, 0x00000000);
  886 
  887         waitforfifo(scr, 8);
  888         iow32(scr, SrcOffPitch, pitch<<22);
  889         iow32(scr, SrcCntl, 0x00000000);
  890         iow32(scr, SrcYX, (sp.x<<16)|sp.y);
  891         iow32(scr, SrcWidth1, dx);
  892         iow32(scr, DstOffPitch, pitch<<22);
  893         iow32(scr, DstCntl, ctl);
  894 
  895         iow32(scr, DstYX, (dp.x<<16)|dp.y);
  896         iow32(scr, DstHeightWidth, (dx<<16)|dy);
  897 
  898         waitforidle(scr);
  899 
  900         return 1;
  901 }
  902 
  903 /*
  904  * This should work, but doesn't.
  905  * It messes up the screen timings for some reason.
  906  */
  907 static void
  908 mach64blank(VGAscr *scr, int blank)
  909 {
  910         ulong ctl;
  911 
  912         ctl = ior32(scr, CrtcGenCtl) & ~(CrtcHsyncDis|CrtcVsyncDis);
  913         if(blank)
  914                 ctl |= CrtcHsyncDis|CrtcVsyncDis;
  915         iow32(scr, CrtcGenCtl, ctl);
  916 }
  917 
  918 /*
  919  * We squirrel away whether the LCD and/or CRT were
  920  * on when we were called to blank the screen, and
  921  * restore the old state.  If we are called to blank the
  922  * screen when it is already blank, we don't update the state.
  923  * Such a call sequence should not happen, though.
  924  *
  925  * We could try forcing the chip into power management
  926  * mode instead, but I'm not sure how that would interact
  927  * with screen updates going on while the screen is blanked.
  928  */
  929 static void
  930 mach64lcdblank(VGAscr *scr, int blank)
  931 {
  932         static int crtlcd;
  933         ulong x;
  934 
  935         if(blank) {
  936                 x = lcdr32(scr, LCD_GenCtrl);
  937                 if(x & 3) {
  938                         crtlcd = x & 3;
  939                         lcdw32(scr, LCD_GenCtrl,  x&~3);
  940                 }
  941         } else {
  942                 if(crtlcd == 0)
  943                         crtlcd = 2;     /* lcd only */
  944                 x = lcdr32(scr, LCD_GenCtrl);
  945                 lcdw32(scr, LCD_GenCtrl, x | crtlcd);
  946         }
  947 }
  948 
  949 static void
  950 mach64xxdrawinit(VGAscr *scr)
  951 {
  952         if(scr->io > 0x2FF){
  953                 initengine(scr);
  954                 scr->fill = mach64hwfill;
  955                 scr->scroll = mach64hwscroll;
  956         }
  957 /*      scr->blank = mach64blank; */
  958         switch(scr->id){
  959         default:
  960                 break;
  961         case ('L'<<8)|'B':              /* 4C42: Rage 3D LTPro */
  962         case ('L'<<8)|'I':              /* 4C49: Rage 3D LTPro */
  963         case ('L'<<8)|'M':              /* 4C4D: Rage Mobility */
  964         case ('L'<<8)|'P':              /* 4C50: Rage 3D LTPro */
  965                 scr->blank = mach64lcdblank;
  966                 hwblank = 1;
  967                 break;
  968         }
  969 }
  970 
  971 static void
  972 ovl_configure(VGAscr *scr, Chan *c, char **field)
  973 {
  974         int w, h;
  975         char *format;
  976 
  977         w = (int)strtol(field[1], nil, 0);
  978         h = (int)strtol(field[2], nil, 0);
  979         format = field[3];
  980 
  981         if (c != ovl_chan) 
  982                 error(Einuse);
  983         if (strcmp(format, "YUYV"))
  984                 error(Eunsupportedformat);
  985         
  986         ovl_width  = w;
  987         ovl_height = h;
  988         ovl_fib       = w * h * sizeof(ushort);
  989 
  990         waitforidle(scr);
  991         scr->mmio[mmoffset[BusCntl]] |= 0x08000000;     /* Enable regblock 1 */
  992         scr->mmio[mmoffset[OverlayScaleCntl]] = 
  993                 SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K|
  994                 SCALE_HORZ_BLEND|SCALE_VERT_BLEND;
  995         scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w;
  996         scr->mmio[mmoffset[CaptureConfig]] = 
  997                 SCALER_FRAME_READ_MODE_FULL|
  998                 SCALER_BUF_MODE_SINGLE|
  999                 SCALER_BUF_NEXT_0;
 1000         scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb?
 1001                 OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28): 
 1002                 0x011;
 1003 
 1004         if (mach64type->m64_pro) {
 1005                 waitforfifo(scr, 6);
 1006 
 1007                 /* set the scaler co-efficient registers */
 1008                 scr->mmio[mmoffset[ScalerColourCntl]] = 
 1009                         (0x00) | (0x10 << 8) | (0x10 << 16);
 1010                 scr->mmio[mmoffset[ScalerHCoef0]] = 
 1011                         (0x00) | (0x20 << 8);
 1012                 scr->mmio[mmoffset[ScalerHCoef1]] = 
 1013                         (0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24);
 1014                 scr->mmio[mmoffset[ScalerHCoef2]] = 
 1015                         (0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24);
 1016                 scr->mmio[mmoffset[ScalerHCoef3]] = 
 1017                         (0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24);
 1018                 scr->mmio[mmoffset[ScalerHCoef4]] = 
 1019                         (0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24);
 1020         }
 1021         
 1022         waitforfifo(scr, 3);
 1023         scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 |
 1024                 (!mach64revb? 0xC: 0);
 1025 
 1026         if (mach64overlay == 0)
 1027                 mach64overlay = scr->storage + 64 * 64 * sizeof(uchar);
 1028         scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] = 
 1029                 mach64overlay;
 1030 }
 1031 
 1032 static void
 1033 ovl_enable(VGAscr *scr, Chan *c, char **field)
 1034 {
 1035         int x, y, w, h;
 1036         long h_inc, v_inc;
 1037 
 1038         x = (int)strtol(field[1], nil, 0);
 1039         y = (int)strtol(field[2], nil, 0);
 1040         w = (int)strtol(field[3], nil, 0);
 1041         h = (int)strtol(field[4], nil, 0);
 1042 
 1043         if (x < 0 || x + w > physgscreenr.max.x ||
 1044              y < 0 || y + h > physgscreenr.max.y)
 1045                 error(Ebadarg);
 1046 
 1047         if (c != ovl_chan) 
 1048                 error(Einuse);
 1049         if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) {     /* double scan enable */
 1050                 y *= 2;
 1051                 h *= 2;
 1052         }
 1053 
 1054         waitforfifo(scr, 2);
 1055         scr->mmio[mmoffset[OverlayYX]] = 
 1056                         ((x & 0xFFFF) << 16) | (y & 0xFFFF);
 1057         scr->mmio[mmoffset[OverlayYXEnd]] = 
 1058                         (((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF);
 1059 
 1060         h_inc = (ovl_width << 12) / (w >> 1);  /* ??? */
 1061         v_inc = (ovl_height << 12) / h;
 1062         waitforfifo(scr, 2);
 1063         scr->mmio[mmoffset[OverlayScaleInc]] = 
 1064                         ((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF);
 1065         scr->mmio[mmoffset[ScalerHeightWidth]] = 
 1066                         ((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF);
 1067         waitforidle(scr);
 1068         scr->mmio[mmoffset[OverlayScaleCntl]] |= 
 1069                         (SCALE_ENABLE|OVERLAY_ENABLE);
 1070 }
 1071 
 1072 static void
 1073 ovl_status(VGAscr *scr, Chan *, char **field)
 1074 {
 1075         pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %d, rev B %s, refclock %ld\n",
 1076                    scr->dev->name, field[0], mach64type->m64_id,
 1077                    mach64type->m64_vtgt? "yes": "no",
 1078                    mach64type->m64_pro? "yes": "no",
 1079                    mach64type->m64_ovlclock,
 1080                    mach64revb? "yes": "no",
 1081                    mach64refclock);
 1082         pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n",
 1083                    scr->dev->name, scr->storage, scr->paddr,
 1084                    mach64overlay);
 1085 }
 1086         
 1087 static void
 1088 ovl_openctl(VGAscr *, Chan *c, char **)
 1089 {
 1090         if (ovl_chan) 
 1091                 error(Einuse);
 1092         ovl_chan = c;
 1093 }
 1094 
 1095 static void
 1096 ovl_closectl(VGAscr *scr, Chan *c, char **)
 1097 {
 1098         if (c != ovl_chan) return;
 1099 
 1100         waitforidle(scr);
 1101         scr->mmio[mmoffset[OverlayScaleCntl]] &=
 1102                         ~(SCALE_ENABLE|OVERLAY_ENABLE);
 1103         ovl_chan = nil;
 1104         ovl_width = ovl_height = ovl_fib = 0;
 1105 }
 1106 
 1107 enum
 1108 {
 1109         CMclosectl,
 1110         CMconfigure,
 1111         CMenable,
 1112         CMopenctl,
 1113         CMstatus,
 1114 };
 1115 
 1116 static void (*ovl_cmds[])(VGAscr *, Chan *, char **) =
 1117 {
 1118         [CMclosectl]    ovl_closectl,
 1119         [CMconfigure]   ovl_configure,
 1120         [CMenable]      ovl_enable,
 1121         [CMopenctl]     ovl_openctl,
 1122         [CMstatus]      ovl_status,
 1123 };
 1124 
 1125 static Cmdtab mach64xxcmd[] =
 1126 {
 1127         CMclosectl,     "closectl",     1,
 1128         CMconfigure,    "configure",    4,
 1129         CMenable,       "enable",       5,
 1130         CMopenctl,      "openctl",      1,
 1131         CMstatus,       "status",       1,
 1132 };
 1133 
 1134 static void
 1135 mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n)
 1136 {
 1137         Cmdbuf *cb;
 1138         Cmdtab *ct;
 1139 
 1140         if(!mach64type->m64_vtgt) 
 1141                 error(Enodev);
 1142 
 1143         if(!scr->overlayinit){
 1144                 scr->overlayinit = 1;
 1145                 init_overlayclock(scr);
 1146         }
 1147         cb = parsecmd(a, n);
 1148         if(waserror()){
 1149                 free(cb);
 1150                 nexterror();
 1151         }
 1152 
 1153         ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd));
 1154 
 1155         ovl_cmds[ct->index](scr, c, cb->f);
 1156 
 1157         poperror();
 1158         free(cb);
 1159 }
 1160 
 1161 static int
 1162 mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs)
 1163 {
 1164         uchar *src;
 1165         int _len;
 1166 
 1167         if (ovl_chan == nil) return len;        /* Acts as a /dev/null */
 1168         
 1169         /* Calculate the destination address */
 1170         _len = len;
 1171         src   = (uchar *)a;
 1172         while (len > 0) {
 1173                 ulong _offs;
 1174                 int nb;
 1175 
 1176                 _offs = (ulong)(offs % ovl_fib);
 1177                 nb     = (_offs + len > ovl_fib)? ovl_fib - _offs: len;
 1178                 memmove((uchar *)scr->vaddr + mach64overlay + _offs, 
 1179                                   src, nb);
 1180                 offs += nb;
 1181                 src  += nb;
 1182                 len  -= nb;
 1183         }
 1184         return _len;
 1185 }
 1186 
 1187 VGAdev vgamach64xxdev = {
 1188         "mach64xx",
 1189 
 1190         mach64xxenable,                 /* enable */
 1191         0,                              /* disable */
 1192         0,                              /* page */
 1193         mach64xxlinear,                 /* linear */
 1194         mach64xxdrawinit,       /* drawinit */
 1195         0,
 1196         mach64xxovlctl, /* overlay control */
 1197         mach64xxovlwrite,       /* write the overlay */
 1198 };
 1199 
 1200 VGAcur vgamach64xxcur = {
 1201         "mach64xxhwgc",
 1202 
 1203         mach64xxcurenable,              /* enable */
 1204         mach64xxcurdisable,             /* disable */
 1205         mach64xxcurload,                /* load */
 1206         mach64xxcurmove,                /* move */
 1207 
 1208         1                                       /* doespanning */
 1209 };
 1210 

Cache object: 5c1b65112363855ea9a0334cebe6effc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.