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/vganeomagic.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 typedef struct CursorNM CursorNM;
   16 struct CursorNM {
   17         int     enable;
   18         int     x;
   19         int     y;
   20         int     colour1;
   21         int     colour2;
   22         int     addr;
   23 };
   24 
   25 static void
   26 neomagicenable(VGAscr* scr)
   27 {
   28         Pcidev *p;
   29         int curoff, vmsize;
   30         ulong ioaddr;
   31         ulong iosize;
   32 
   33         /*
   34          * scr->mmio holds the virtual address of the cursor registers
   35          * in the MMIO space. This may need to change for older chips
   36          * which have the MMIO space offset in the framebuffer region.
   37          *
   38          * scr->io holds the offset into mmio of the CursorNM struct.
   39          */
   40         if(scr->mmio)
   41                 return;
   42         if(p = pcimatch(nil, 0x10C8, 0)){
   43                 switch(p->did){
   44                 case 0x0003:            /* MagicGraph 128ZV */
   45                         curoff = 0x100;
   46                         vmsize = 1152*1024;
   47                         ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
   48                         iosize = 0x200000;
   49                         break;
   50                 case 0x0083:            /* MagicGraph 128ZV+ */
   51                         curoff = 0x100;
   52                         vmsize = 1152*1024;
   53                         ioaddr = p->mem[1].bar & ~0x0F;
   54                         iosize = p->mem[1].size;
   55                         break;
   56                 case 0x0004:            /* MagicGraph 128XD */
   57                         curoff = 0x100;
   58                         vmsize = 2048*1024;
   59                         ioaddr = p->mem[1].bar & ~0x0F;
   60                         iosize = p->mem[1].size;
   61                         break;
   62                 case 0x0005:            /* MagicMedia 256AV */
   63                         curoff = 0x1000;
   64                         vmsize = 2560*1024;
   65                         ioaddr = p->mem[1].bar & ~0x0F;
   66                         iosize = p->mem[1].size;
   67                         break;
   68                 case 0x0006:            /* MagicMedia 256ZX */
   69                         curoff = 0x1000;
   70                         vmsize = 4096*1024;
   71                         ioaddr = p->mem[1].bar & ~0x0F;
   72                         iosize = p->mem[1].size;
   73                         break;
   74                 case 0x0016:            /* MagicMedia 256XL+ */
   75                         curoff = 0x1000;
   76                         /* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
   77                         vmsize = 4096*1024;
   78                         ioaddr = p->mem[1].bar & ~0x0F;
   79                         iosize = p->mem[1].size;
   80                         break;
   81                 default:
   82                         return;
   83                 }
   84         }
   85         else
   86                 return;
   87         scr->pci = p;
   88 
   89         scr->mmio = vmap(ioaddr, iosize);
   90         if(scr->mmio == nil)
   91                 return;
   92         addvgaseg("neomagicmmio", ioaddr, iosize);
   93 
   94         /*
   95          * Find a place for the cursor data in display memory.
   96          * 2 cursor images might be needed, 1KB each so use the
   97          * last 2KB of the framebuffer.
   98          */
   99         scr->storage = vmsize-2*1024;
  100         scr->io = curoff;
  101         vgalinearpci(scr);
  102         if(scr->paddr)
  103                 addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
  104 }
  105 
  106 static void
  107 neomagiccurdisable(VGAscr* scr)
  108 {
  109         CursorNM *cursornm;
  110 
  111         if(scr->mmio == 0)
  112                 return;
  113         cursornm = (void*)((char*)scr->mmio + scr->io);
  114         cursornm->enable = 0;
  115 }
  116 
  117 static void
  118 neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
  119 {
  120         uchar *p;
  121         uint p0, p1;
  122         int x, y;
  123 
  124         p = (uchar*)scr->vaddr;
  125         p += scr->storage + index*1024;
  126 
  127         for(y = yo; y < 16; y++){
  128                 p0 = scr->set[2*y];
  129                 p1 = scr->set[2*y+1];
  130                 if(xo){
  131                         p0 = (p0<<xo)|(p1>>(8-xo));
  132                         p1 <<= xo;
  133                 }
  134                 *p++ = p0;
  135                 *p++ = p1;
  136 
  137                 for(x = 16; x < 64; x += 8)
  138                         *p++ = 0x00;
  139 
  140                 p0 = scr->clr[2*y]|scr->set[2*y];
  141                 p1 = scr->clr[2*y+1]|scr->set[2*y+1];
  142                 if(xo){
  143                         p0 = (p0<<xo)|(p1>>(8-xo));
  144                         p1 <<= xo;
  145                 }
  146                 *p++ = p0;
  147                 *p++ = p1;
  148 
  149                 for(x = 16; x < 64; x += 8)
  150                         *p++ = 0x00;
  151         }
  152         while(y < 64+yo){
  153                 for(x = 0; x < 64; x += 8){
  154                         *p++ = 0x00;
  155                         *p++ = 0x00;
  156                 }
  157                 y++;
  158         }
  159 }
  160 
  161 static void
  162 neomagiccurload(VGAscr* scr, Cursor* curs)
  163 {
  164         CursorNM *cursornm;
  165 
  166         if(scr->mmio == 0)
  167                 return;
  168         cursornm = (void*)((char*)scr->mmio + scr->io);
  169 
  170         cursornm->enable = 0;
  171         memmove(&scr->Cursor, curs, sizeof(Cursor));
  172         neomagicinitcursor(scr, 0, 0, 0);
  173         cursornm->enable = 1;
  174 }
  175 
  176 static int
  177 neomagiccurmove(VGAscr* scr, Point p)
  178 {
  179         CursorNM *cursornm;
  180         int addr, index, x, xo, y, yo;
  181 
  182         if(scr->mmio == 0)
  183                 return 1;
  184         cursornm = (void*)((char*)scr->mmio + scr->io);
  185 
  186         index = 0;
  187         if((x = p.x+scr->offset.x) < 0){
  188                 xo = -x;
  189                 x = 0;
  190         }
  191         else
  192                 xo = 0;
  193         if((y = p.y+scr->offset.y) < 0){
  194                 yo = -y;
  195                 y = 0;
  196         }
  197         else
  198                 yo = 0;
  199 
  200         if(xo || yo){
  201                 index = 1;
  202                 neomagicinitcursor(scr, xo, yo, index);
  203         }
  204         addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
  205         addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
  206         if(cursornm->addr != addr)
  207                 cursornm->addr = addr;
  208 
  209         cursornm->x = x;
  210         cursornm->y = y;
  211 
  212         return 0;
  213 }
  214 
  215 static void
  216 neomagiccurenable(VGAscr* scr)
  217 {
  218         CursorNM *cursornm;
  219 
  220         neomagicenable(scr);
  221         if(scr->mmio == 0)
  222                 return;
  223         cursornm = (void*)((char*)scr->mmio + scr->io);
  224         cursornm->enable = 0;
  225 
  226         /*
  227          * Cursor colours.
  228          */
  229         cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
  230         cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
  231 
  232         /*
  233          * Load, locate and enable the 64x64 cursor.
  234          */
  235         neomagiccurload(scr, &arrow);
  236         neomagiccurmove(scr, ZP);
  237         cursornm->enable = 1;
  238 }
  239 
  240 static int neomagicbltflags;
  241 
  242 /* registers */
  243 enum {
  244         BltStat = 0,
  245         BltCntl = 1,
  246         XPColor = 2,
  247         FGColor = 3,
  248         BGColor = 4,
  249         Pitch = 5,
  250         ClipLT = 6,
  251         ClipRB = 7,
  252         SrcBitOff = 8,
  253         SrcStartOff = 9,
  254 
  255         DstStartOff = 11,
  256         XYExt = 12,
  257 
  258         PageCntl = 20,
  259         PageBase,
  260         PostBase,
  261         PostPtr,
  262         DataPtr,
  263 };
  264 
  265 /* flags */
  266 enum {
  267         NEO_BS0_BLT_BUSY =      0x00000001,
  268         NEO_BS0_FIFO_AVAIL =    0x00000002,
  269         NEO_BS0_FIFO_PEND =     0x00000004,
  270 
  271         NEO_BC0_DST_Y_DEC =     0x00000001,
  272         NEO_BC0_X_DEC =         0x00000002,
  273         NEO_BC0_SRC_TRANS =     0x00000004,
  274         NEO_BC0_SRC_IS_FG =     0x00000008,
  275         NEO_BC0_SRC_Y_DEC =     0x00000010,
  276         NEO_BC0_FILL_PAT =      0x00000020,
  277         NEO_BC0_SRC_MONO =      0x00000040,
  278         NEO_BC0_SYS_TO_VID =    0x00000080,
  279 
  280         NEO_BC1_DEPTH8 =        0x00000100,
  281         NEO_BC1_DEPTH16 =       0x00000200,
  282         NEO_BC1_DEPTH24 =       0x00000300,
  283         NEO_BC1_X_320 =         0x00000400,
  284         NEO_BC1_X_640 =         0x00000800,
  285         NEO_BC1_X_800 =         0x00000c00,
  286         NEO_BC1_X_1024 =        0x00001000,
  287         NEO_BC1_X_1152 =        0x00001400,
  288         NEO_BC1_X_1280 =        0x00001800,
  289         NEO_BC1_X_1600 =        0x00001c00,
  290         NEO_BC1_DST_TRANS =     0x00002000,
  291         NEO_BC1_MSTR_BLT =      0x00004000,
  292         NEO_BC1_FILTER_Z =      0x00008000,
  293 
  294         NEO_BC2_WR_TR_DST =     0x00800000,
  295 
  296         NEO_BC3_SRC_XY_ADDR =   0x01000000,
  297         NEO_BC3_DST_XY_ADDR =   0x02000000,
  298         NEO_BC3_CLIP_ON =       0x04000000,
  299         NEO_BC3_FIFO_EN =       0x08000000,
  300         NEO_BC3_BLT_ON_ADDR =   0x10000000,
  301         NEO_BC3_SKIP_MAPPING =  0x80000000,
  302 
  303         NEO_MODE1_DEPTH8 =      0x0100,
  304         NEO_MODE1_DEPTH16 =     0x0200,
  305         NEO_MODE1_DEPTH24 =     0x0300,
  306         NEO_MODE1_X_320 =       0x0400,
  307         NEO_MODE1_X_640 =       0x0800,
  308         NEO_MODE1_X_800 =       0x0c00,
  309         NEO_MODE1_X_1024 =      0x1000,
  310         NEO_MODE1_X_1152 =      0x1400,
  311         NEO_MODE1_X_1280 =      0x1800,
  312         NEO_MODE1_X_1600 =      0x1c00,
  313         NEO_MODE1_BLT_ON_ADDR = 0x2000,
  314 };
  315 
  316 /* Raster Operations */
  317 enum {
  318         GXclear =               0x000000,       /* 0x0000 */
  319         GXand =                 0x080000,       /* 0x1000 */
  320         GXandReverse =          0x040000,       /* 0x0100 */
  321         GXcopy =                0x0c0000,       /* 0x1100 */
  322         GXandInvert =           0x020000,       /* 0x0010 */
  323         GXnoop =                0x0a0000,       /* 0x1010 */
  324         GXxor =                 0x060000,       /* 0x0110 */
  325         GXor =                  0x0e0000,       /* 0x1110 */
  326         GXnor =                 0x010000,       /* 0x0001 */
  327         GXequiv =               0x090000,       /* 0x1001 */
  328         GXinvert =              0x050000,       /* 0x0101 */
  329         GXorReverse =           0x0d0000,       /* 0x1101 */
  330         GXcopyInvert =          0x030000,       /* 0x0011 */
  331         GXorInverted =          0x0b0000,       /* 0x1011 */
  332         GXnand =                0x070000,       /* 0x0111 */
  333         GXset =                 0x0f0000,       /* 0x1111 */
  334 };
  335 
  336 static void
  337 waitforidle(VGAscr *scr)
  338 {
  339         ulong *mmio;
  340         long x;
  341 
  342         mmio = scr->mmio;
  343         x = 0;
  344         while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
  345                 ;
  346         //if(x >= 1000000)
  347         //      iprint("idle stat %lud scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
  348 }
  349 
  350 static void
  351 waitforfifo(VGAscr *scr, int entries)
  352 {
  353         ulong *mmio;
  354         long x;
  355 
  356         mmio = scr->mmio;
  357         x = 0;
  358         while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
  359                 ;
  360         //if(x >= 1000000)
  361         //      iprint("fifo stat %d scrmmio %#.8lux scr %#p pc %#p\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
  362         /* DirectFB says the above doesn't work.  if so... */
  363         /* waitforidle(scr); */
  364 }
  365 
  366 static int
  367 neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
  368 {
  369         ulong *mmio;
  370 
  371         mmio = scr->mmio;
  372 
  373         waitforfifo(scr, 1);
  374         mmio[FGColor] = sval;
  375         waitforfifo(scr, 3);
  376         mmio[BltCntl] = neomagicbltflags
  377                 | NEO_BC3_FIFO_EN
  378                 | NEO_BC0_SRC_IS_FG
  379                 | NEO_BC3_SKIP_MAPPING
  380                 | GXcopy;
  381         mmio[DstStartOff] = scr->paddr
  382                 + r.min.y*scr->gscreen->width*BY2WD
  383                 + r.min.x*scr->gscreen->depth/BI2BY;
  384         mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
  385         waitforidle(scr);
  386         return 1;
  387 }
  388 
  389 static int
  390 neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  391 {
  392         ulong *mmio;
  393         int pitch, pixel;
  394 
  395         mmio = scr->mmio;
  396 
  397         pitch = scr->gscreen->width*BY2WD;
  398         pixel = scr->gscreen->depth/BI2BY;
  399 
  400         waitforfifo(scr, 4);
  401         if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
  402                 /* start from upper-left */
  403                 mmio[BltCntl] = neomagicbltflags
  404                         | NEO_BC3_FIFO_EN
  405                         | NEO_BC3_SKIP_MAPPING
  406                         | GXcopy;
  407                 mmio[SrcStartOff] = scr->paddr
  408                         + sr.min.y*pitch + sr.min.x*pixel;
  409                 mmio[DstStartOff] = scr->paddr
  410                         + r.min.y*pitch + r.min.x*pixel;
  411         } else {
  412                 /* start from lower-right */
  413                 mmio[BltCntl] = neomagicbltflags
  414                         | NEO_BC0_X_DEC
  415                         | NEO_BC0_DST_Y_DEC
  416                         | NEO_BC0_SRC_Y_DEC
  417                         | NEO_BC3_FIFO_EN
  418                         | NEO_BC3_SKIP_MAPPING
  419                         | GXcopy;
  420                 mmio[SrcStartOff] = scr->paddr
  421                         + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
  422                 mmio[DstStartOff] = scr->paddr
  423                         + (r.max.y-1)*pitch + (r.max.x-1)*pixel;
  424         }
  425         mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
  426         waitforidle(scr);
  427         return 1;
  428 }
  429 
  430 static void
  431 neomagicdrawinit(VGAscr *scr)
  432 {
  433         ulong *mmio;
  434         uint bltmode, pitch;
  435 
  436         mmio = scr->mmio;
  437 
  438         pitch = scr->gscreen->width*BY2WD;
  439 
  440         neomagicbltflags = bltmode = 0;
  441 
  442         switch(scr->gscreen->depth) {
  443         case 8:
  444                 bltmode |= NEO_MODE1_DEPTH8;
  445                 neomagicbltflags |= NEO_BC1_DEPTH8;
  446                 break;
  447         case 16:
  448                 bltmode |= NEO_MODE1_DEPTH16;
  449                 neomagicbltflags |= NEO_BC1_DEPTH16;
  450                 break;
  451         case 24:        /* I can't get it to work, and XFree86 doesn't either. */
  452         default:        /* give up */
  453                 return;
  454         }
  455 
  456         switch(Dx(scr->gscreen->r)) {
  457         case 320:
  458                 bltmode |= NEO_MODE1_X_320;
  459                 neomagicbltflags |= NEO_BC1_X_320;
  460                 break;
  461         case 640:
  462                 bltmode |= NEO_MODE1_X_640;
  463                 neomagicbltflags |= NEO_BC1_X_640;
  464                 break;
  465         case 800:
  466                 bltmode |= NEO_MODE1_X_800;
  467                 neomagicbltflags |= NEO_BC1_X_800;
  468                 break;
  469         case 1024:
  470                 bltmode |= NEO_MODE1_X_1024;
  471                 neomagicbltflags |= NEO_BC1_X_1024;
  472                 break;
  473         case 1152:
  474                 bltmode |= NEO_MODE1_X_1152;
  475                 neomagicbltflags |= NEO_BC1_X_1152;
  476                 break;
  477         case 1280:
  478                 bltmode |= NEO_MODE1_X_1280;
  479                 neomagicbltflags |= NEO_BC1_X_1280;
  480                 break;
  481         case 1600:
  482                 bltmode |= NEO_MODE1_X_1600;
  483                 neomagicbltflags |= NEO_BC1_X_1600;
  484                 break;
  485         default:
  486                 /* don't worry about it */
  487                 break;
  488         }
  489 
  490         waitforidle(scr);
  491         mmio[BltStat] = bltmode << 16;
  492         mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
  493 
  494         scr->fill = neomagichwfill;
  495         scr->scroll = neomagichwscroll;
  496 }
  497 
  498 VGAdev vganeomagicdev = {
  499         "neomagic",
  500 
  501         neomagicenable,
  502         nil,
  503         nil,
  504         nil,
  505         neomagicdrawinit,
  506 };
  507 
  508 VGAcur vganeomagiccur = {
  509         "neomagichwgc",
  510 
  511         neomagiccurenable,
  512         neomagiccurdisable,
  513         neomagiccurload,
  514         neomagiccurmove,
  515 };
  516 

Cache object: 688fb460d34dd160022c892185d3c38f


[ 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.