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/devvga.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 /*
    2  * VGA controller
    3  */
    4 #include "u.h"
    5 #include "../port/lib.h"
    6 #include "mem.h"
    7 #include "dat.h"
    8 #include "fns.h"
    9 #include "io.h"
   10 #include "../port/error.h"
   11 
   12 #define Image   IMAGE
   13 #include <draw.h>
   14 #include <memdraw.h>
   15 #include <cursor.h>
   16 #include "screen.h"
   17 
   18 enum {
   19         Qdir,
   20         Qvgabios,
   21         Qvgactl,
   22         Qvgaovl,
   23         Qvgaovlctl,
   24 };
   25 
   26 static Dirtab vgadir[] = {
   27         ".",    { Qdir, 0, QTDIR },             0,      0550,
   28         "vgabios",      { Qvgabios, 0 },        0x100000, 0440,
   29         "vgactl",               { Qvgactl, 0 },         0,      0660,
   30         "vgaovl",               { Qvgaovl, 0 },         0,      0660,
   31         "vgaovlctl",    { Qvgaovlctl, 0 },      0,      0660,
   32 };
   33 
   34 enum {
   35         CMactualsize,
   36         CMblank,
   37         CMblanktime,
   38         CMdrawinit,
   39         CMhwaccel,
   40         CMhwblank,
   41         CMhwgc,
   42         CMlinear,
   43         CMpalettedepth,
   44         CMpanning,
   45         CMsize,
   46         CMtextmode,
   47         CMtype,
   48         CMunblank,
   49 };
   50 
   51 static Cmdtab vgactlmsg[] = {
   52         CMactualsize,   "actualsize",   2,
   53         CMblank,        "blank",        1,
   54         CMblanktime,    "blanktime",    2,
   55         CMdrawinit,     "drawinit",     1,
   56         CMhwaccel,      "hwaccel",      2,
   57         CMhwblank,      "hwblank",      2,
   58         CMhwgc,         "hwgc",         2,
   59         CMlinear,       "linear",       0,
   60         CMpalettedepth, "palettedepth", 2,
   61         CMpanning,      "panning",      2,
   62         CMsize,         "size",         3,
   63         CMtextmode,     "textmode",     1,
   64         CMtype,         "type",         2,
   65         CMunblank,      "unblank",      1,
   66 };
   67 
   68 static void
   69 vgareset(void)
   70 {
   71         /* reserve the 'standard' vga registers */
   72         if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
   73                 panic("vga ports already allocated"); 
   74         if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
   75                 panic("vga ports already allocated"); 
   76         conf.monitor = 1;
   77 }
   78 
   79 static Chan*
   80 vgaattach(char* spec)
   81 {
   82         if(*spec && strcmp(spec, ""))
   83                 error(Eio);
   84         return devattach('v', spec);
   85 }
   86 
   87 Walkqid*
   88 vgawalk(Chan* c, Chan *nc, char** name, int nname)
   89 {
   90         return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
   91 }
   92 
   93 static int
   94 vgastat(Chan* c, uchar* dp, int n)
   95 {
   96         return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
   97 }
   98 
   99 static Chan*
  100 vgaopen(Chan* c, int omode)
  101 {
  102         VGAscr *scr;
  103         static char *openctl = "openctl\n";
  104 
  105         scr = &vgascreen[0];
  106         if ((ulong)c->qid.path == Qvgaovlctl) {
  107                 if (scr->dev && scr->dev->ovlctl)
  108                         scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
  109                 else 
  110                         error(Enonexist);
  111         }
  112         return devopen(c, omode, vgadir, nelem(vgadir), devgen);
  113 }
  114 
  115 static void
  116 vgaclose(Chan* c)
  117 {
  118         VGAscr *scr;
  119         static char *closectl = "closectl\n";
  120 
  121         scr = &vgascreen[0];
  122         if((ulong)c->qid.path == Qvgaovlctl)
  123                 if(scr->dev && scr->dev->ovlctl){
  124                         if(waserror()){
  125                                 print("ovlctl error: %s\n", up->errstr);
  126                                 return;
  127                         }
  128                         scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
  129                         poperror();
  130                 }
  131 }
  132 
  133 static void
  134 checkport(int start, int end)
  135 {
  136         /* standard vga regs are OK */
  137         if(start >= 0x2b0 && end <= 0x2df+1)
  138                 return;
  139         if(start >= 0x3c0 && end <= 0x3da+1)
  140                 return;
  141 
  142         if(iounused(start, end))
  143                 return;
  144         error(Eperm);
  145 }
  146 
  147 static long
  148 vgaread(Chan* c, void* a, long n, vlong off)
  149 {
  150         int len;
  151         char *p, *s;
  152         VGAscr *scr;
  153         ulong offset = off;
  154         char chbuf[30];
  155 
  156         switch((ulong)c->qid.path){
  157 
  158         case Qdir:
  159                 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
  160 
  161         case Qvgabios:
  162                 if(offset >= 0x100000)
  163                         return 0;
  164                 if(offset+n >= 0x100000)
  165                         n = 0x100000 - offset;
  166                 memmove(a, (uchar*)kaddr(0)+offset, n);
  167                 return n;
  168 
  169         case Qvgactl:
  170                 scr = &vgascreen[0];
  171 
  172                 p = malloc(READSTR);
  173                 if(waserror()){
  174                         free(p);
  175                         nexterror();
  176                 }
  177 
  178                 len = 0;
  179 
  180                 if(scr->dev)
  181                         s = scr->dev->name;
  182                 else
  183                         s = "cga";
  184                 len += snprint(p+len, READSTR-len, "type %s\n", s);
  185 
  186                 if(scr->gscreen) {
  187                         len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
  188                                 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
  189                                 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
  190 
  191                         if(Dx(scr->gscreen->r) != Dx(physgscreenr) 
  192                         || Dy(scr->gscreen->r) != Dy(physgscreenr))
  193                                 len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
  194                                         physgscreenr.max.x, physgscreenr.max.y);
  195                 }
  196 
  197                 len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
  198                         blanktime, drawidletime(), scr->isblank ? "off" : "on");
  199                 len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
  200                 len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
  201                 len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
  202                 len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
  203                 USED(len);
  204 
  205                 n = readstr(offset, a, n, p);
  206                 poperror();
  207                 free(p);
  208 
  209                 return n;
  210 
  211         case Qvgaovl:
  212         case Qvgaovlctl:
  213                 error(Ebadusefd);
  214                 break;
  215 
  216         default:
  217                 error(Egreg);
  218                 break;
  219         }
  220 
  221         return 0;
  222 }
  223 
  224 static char Ebusy[] = "vga already configured";
  225 
  226 static void
  227 vgactl(Cmdbuf *cb)
  228 {
  229         int align, i, size, x, y, z;
  230         char *chanstr, *p;
  231         ulong chan;
  232         Cmdtab *ct;
  233         VGAscr *scr;
  234         extern VGAdev *vgadev[];
  235         extern VGAcur *vgacur[];
  236 
  237         scr = &vgascreen[0];
  238         ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
  239         switch(ct->index){
  240         case CMhwgc:
  241                 if(strcmp(cb->f[1], "off") == 0){
  242                         lock(&cursor);
  243                         if(scr->cur){
  244                                 if(scr->cur->disable)
  245                                         scr->cur->disable(scr);
  246                                 scr->cur = nil;
  247                         }
  248                         unlock(&cursor);
  249                         return;
  250                 }
  251                 if(strcmp(cb->f[1], "soft") == 0){
  252                         lock(&cursor);
  253                         swcursorinit();
  254                         if(scr->cur && scr->cur->disable)
  255                                 scr->cur->disable(scr);
  256                         scr->cur = &swcursor;
  257                         if(scr->cur->enable)
  258                                 scr->cur->enable(scr);
  259                         unlock(&cursor);
  260                         return;
  261                 }
  262                 for(i = 0; vgacur[i]; i++){
  263                         if(strcmp(cb->f[1], vgacur[i]->name))
  264                                 continue;
  265                         lock(&cursor);
  266                         if(scr->cur && scr->cur->disable)
  267                                 scr->cur->disable(scr);
  268                         scr->cur = vgacur[i];
  269                         if(scr->cur->enable)
  270                                 scr->cur->enable(scr);
  271                         unlock(&cursor);
  272                         return;
  273                 }
  274                 break;
  275 
  276         case CMtype:
  277                 for(i = 0; vgadev[i]; i++){
  278                         if(strcmp(cb->f[1], vgadev[i]->name))
  279                                 continue;
  280                         if(scr->dev && scr->dev->disable)
  281                                 scr->dev->disable(scr);
  282                         scr->dev = vgadev[i];
  283                         if(scr->dev->enable)
  284                                 scr->dev->enable(scr);
  285                         return;
  286                 }
  287                 break;
  288 
  289         case CMtextmode:
  290                 screeninit();
  291                 return;
  292 
  293         case CMsize:
  294 
  295                 x = strtoul(cb->f[1], &p, 0);
  296                 if(x == 0 || x > 10240)
  297                         error(Ebadarg);
  298                 if(*p)
  299                         p++;
  300 
  301                 y = strtoul(p, &p, 0);
  302                 if(y == 0 || y > 10240)
  303                         error(Ebadarg);
  304                 if(*p)
  305                         p++;
  306 
  307                 z = strtoul(p, &p, 0);
  308 
  309                 chanstr = cb->f[2];
  310                 if((chan = strtochan(chanstr)) == 0)
  311                         error("bad channel");
  312 
  313                 if(chantodepth(chan) != z)
  314                         error("depth, channel do not match");
  315 
  316                 cursoroff(1);
  317                 deletescreenimage();
  318                 if(screensize(x, y, z, chan))
  319                         error(Egreg);
  320                 vgascreenwin(scr);
  321                 resetscreenimage();
  322                 cursoron(1);
  323                 return;
  324 
  325         case CMactualsize:
  326                 if(scr->gscreen == nil)
  327                         error("set the screen size first");
  328 
  329                 x = strtoul(cb->f[1], &p, 0);
  330                 if(x == 0 || x > 2048)
  331                         error(Ebadarg);
  332                 if(*p)
  333                         p++;
  334 
  335                 y = strtoul(p, nil, 0);
  336                 if(y == 0 || y > 2048)
  337                         error(Ebadarg);
  338 
  339                 if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
  340                         error("physical screen bigger than virtual");
  341 
  342                 physgscreenr = Rect(0,0,x,y);
  343                 scr->gscreen->clipr = physgscreenr;
  344                 return;
  345         
  346         case CMpalettedepth:
  347                 x = strtoul(cb->f[1], &p, 0);
  348                 if(x != 8 && x != 6)
  349                         error(Ebadarg);
  350 
  351                 scr->palettedepth = x;
  352                 return;
  353 
  354         case CMdrawinit:
  355                 memimagedraw(scr->gscreen, scr->gscreen->r, memblack, ZP, nil, ZP, S);
  356                 if(scr && scr->dev && scr->dev->drawinit)
  357                         scr->dev->drawinit(scr);
  358                 return;
  359         
  360         case CMlinear:
  361                 if(cb->nf!=2 && cb->nf!=3)
  362                         error(Ebadarg);
  363                 size = strtoul(cb->f[1], 0, 0);
  364                 if(cb->nf == 2)
  365                         align = 0;
  366                 else
  367                         align = strtoul(cb->f[2], 0, 0);
  368                 if(screenaperture(size, align) < 0)
  369                         error("not enough free address space");
  370                 return;
  371 /*      
  372         case CMmemset:
  373                 memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3]));
  374                 return;
  375 */
  376 
  377         case CMblank:
  378                 drawblankscreen(1);
  379                 return;
  380         
  381         case CMunblank:
  382                 drawblankscreen(0);
  383                 return;
  384         
  385         case CMblanktime:
  386                 blanktime = strtoul(cb->f[1], 0, 0);
  387                 return;
  388 
  389         case CMpanning:
  390                 if(strcmp(cb->f[1], "on") == 0){
  391                         if(scr == nil || scr->cur == nil)
  392                                 error("set screen first");
  393                         if(!scr->cur->doespanning)
  394                                 error("panning not supported");
  395                         scr->gscreen->clipr = scr->gscreen->r;
  396                         panning = 1;
  397                 }
  398                 else if(strcmp(cb->f[1], "off") == 0){
  399                         scr->gscreen->clipr = physgscreenr;
  400                         panning = 0;
  401                 }else
  402                         break;
  403                 return;
  404 
  405         case CMhwaccel:
  406                 if(strcmp(cb->f[1], "on") == 0)
  407                         hwaccel = 1;
  408                 else if(strcmp(cb->f[1], "off") == 0)
  409                         hwaccel = 0;
  410                 else
  411                         break;
  412                 return;
  413         
  414         case CMhwblank:
  415                 if(strcmp(cb->f[1], "on") == 0)
  416                         hwblank = 1;
  417                 else if(strcmp(cb->f[1], "off") == 0)
  418                         hwblank = 0;
  419                 else
  420                         break;
  421                 return;
  422         }
  423 
  424         cmderror(cb, "bad VGA control message");
  425 }
  426 
  427 char Enooverlay[] = "No overlay support";
  428 
  429 static long
  430 vgawrite(Chan* c, void* a, long n, vlong off)
  431 {
  432         ulong offset = off;
  433         Cmdbuf *cb;
  434         VGAscr *scr;
  435 
  436         switch((ulong)c->qid.path){
  437 
  438         case Qdir:
  439                 error(Eperm);
  440 
  441         case Qvgactl:
  442                 if(offset || n >= READSTR)
  443                         error(Ebadarg);
  444                 cb = parsecmd(a, n);
  445                 if(waserror()){
  446                         free(cb);
  447                         nexterror();
  448                 }
  449                 vgactl(cb);
  450                 poperror();
  451                 free(cb);
  452                 return n;
  453 
  454         case Qvgaovl:
  455                 scr = &vgascreen[0];
  456                 if (scr->dev == nil || scr->dev->ovlwrite == nil) {
  457                         error(Enooverlay);
  458                         break;
  459                 }
  460                 return scr->dev->ovlwrite(scr, a, n, off);
  461 
  462         case Qvgaovlctl:
  463                 scr = &vgascreen[0];
  464                 if (scr->dev == nil || scr->dev->ovlctl == nil) {
  465                         error(Enooverlay);
  466                         break;
  467                 }
  468                 scr->dev->ovlctl(scr, c, a, n);
  469                 return n;
  470 
  471         default:
  472                 error(Egreg);
  473                 break;
  474         }
  475 
  476         return 0;
  477 }
  478 
  479 Dev vgadevtab = {
  480         'v',
  481         "vga",
  482 
  483         vgareset,
  484         devinit,
  485         devshutdown,
  486         vgaattach,
  487         vgawalk,
  488         vgastat,
  489         vgaopen,
  490         devcreate,
  491         vgaclose,
  492         vgaread,
  493         devbread,
  494         vgawrite,
  495         devbwrite,
  496         devremove,
  497         devwstat,
  498 };

Cache object: 2cff91564cf8dbf70489685ddbd9a5a7


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