LCOV - code coverage report
Current view: top level - drivers/video/console - vgacon.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 211 540 39.1 %
Date: 2022-04-01 14:17:54 Functions: 16 31 51.6 %
Branches: 68 330 20.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  linux/drivers/video/vgacon.c -- Low level VGA based console driver
       3                 :            :  *
       4                 :            :  *      Created 28 Sep 1997 by Geert Uytterhoeven
       5                 :            :  *
       6                 :            :  *      Rewritten by Martin Mares <mj@ucw.cz>, July 1998
       7                 :            :  *
       8                 :            :  *  This file is based on the old console.c, vga.c and vesa_blank.c drivers.
       9                 :            :  *
      10                 :            :  *      Copyright (C) 1991, 1992  Linus Torvalds
      11                 :            :  *                          1995  Jay Estabrook
      12                 :            :  *
      13                 :            :  *      User definable mapping table and font loading by Eugene G. Crosser,
      14                 :            :  *      <crosser@average.org>
      15                 :            :  *
      16                 :            :  *      Improved loadable font/UTF-8 support by H. Peter Anvin
      17                 :            :  *      Feb-Sep 1995 <peter.anvin@linux.org>
      18                 :            :  *
      19                 :            :  *      Colour palette handling, by Simon Tatham
      20                 :            :  *      17-Jun-95 <sgt20@cam.ac.uk>
      21                 :            :  *
      22                 :            :  *      if 512 char mode is already enabled don't re-enable it,
      23                 :            :  *      because it causes screen to flicker, by Mitja Horvat
      24                 :            :  *      5-May-96 <mitja.horvat@guest.arnes.si>
      25                 :            :  *
      26                 :            :  *      Use 2 outw instead of 4 outb_p to reduce erroneous text
      27                 :            :  *      flashing on RHS of screen during heavy console scrolling .
      28                 :            :  *      Oct 1996, Paul Gortmaker.
      29                 :            :  *
      30                 :            :  *
      31                 :            :  *  This file is subject to the terms and conditions of the GNU General Public
      32                 :            :  *  License.  See the file COPYING in the main directory of this archive for
      33                 :            :  *  more details.
      34                 :            :  */
      35                 :            : 
      36                 :            : #include <linux/module.h>
      37                 :            : #include <linux/types.h>
      38                 :            : #include <linux/fs.h>
      39                 :            : #include <linux/kernel.h>
      40                 :            : #include <linux/console.h>
      41                 :            : #include <linux/string.h>
      42                 :            : #include <linux/kd.h>
      43                 :            : #include <linux/slab.h>
      44                 :            : #include <linux/vt_kern.h>
      45                 :            : #include <linux/sched.h>
      46                 :            : #include <linux/selection.h>
      47                 :            : #include <linux/spinlock.h>
      48                 :            : #include <linux/ioport.h>
      49                 :            : #include <linux/init.h>
      50                 :            : #include <linux/screen_info.h>
      51                 :            : #include <video/vga.h>
      52                 :            : #include <asm/io.h>
      53                 :            : 
      54                 :            : static DEFINE_RAW_SPINLOCK(vga_lock);
      55                 :            : static int cursor_size_lastfrom;
      56                 :            : static int cursor_size_lastto;
      57                 :            : static u32 vgacon_xres;
      58                 :            : static u32 vgacon_yres;
      59                 :            : static struct vgastate vgastate;
      60                 :            : 
      61                 :            : #define BLANK 0x0020
      62                 :            : 
      63                 :            : #define VGA_FONTWIDTH       8   /* VGA does not support fontwidths != 8 */
      64                 :            : /*
      65                 :            :  *  Interface used by the world
      66                 :            :  */
      67                 :            : 
      68                 :            : static const char *vgacon_startup(void);
      69                 :            : static void vgacon_init(struct vc_data *c, int init);
      70                 :            : static void vgacon_deinit(struct vc_data *c);
      71                 :            : static void vgacon_cursor(struct vc_data *c, int mode);
      72                 :            : static int vgacon_switch(struct vc_data *c);
      73                 :            : static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
      74                 :            : static void vgacon_scrolldelta(struct vc_data *c, int lines);
      75                 :            : static int vgacon_set_origin(struct vc_data *c);
      76                 :            : static void vgacon_save_screen(struct vc_data *c);
      77                 :            : static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
      78                 :            : static struct uni_pagedir *vgacon_uni_pagedir;
      79                 :            : static int vgacon_refcount;
      80                 :            : 
      81                 :            : /* Description of the hardware situation */
      82                 :            : static bool             vga_init_done;
      83                 :            : static unsigned long    vga_vram_base           __read_mostly;  /* Base of video memory */
      84                 :            : static unsigned long    vga_vram_end            __read_mostly;  /* End of video memory */
      85                 :            : static unsigned int     vga_vram_size           __read_mostly;  /* Size of video memory */
      86                 :            : static u16              vga_video_port_reg      __read_mostly;  /* Video register select port */
      87                 :            : static u16              vga_video_port_val      __read_mostly;  /* Video register value port */
      88                 :            : static unsigned int     vga_video_num_columns;                  /* Number of text columns */
      89                 :            : static unsigned int     vga_video_num_lines;                    /* Number of text lines */
      90                 :            : static bool             vga_can_do_color;                       /* Do we support colors? */
      91                 :            : static unsigned int     vga_default_font_height __read_mostly;  /* Height of default screen font */
      92                 :            : static unsigned char    vga_video_type          __read_mostly;  /* Card type */
      93                 :            : static bool             vga_font_is_default = true;
      94                 :            : static int              vga_vesa_blanked;
      95                 :            : static bool             vga_palette_blanked;
      96                 :            : static bool             vga_is_gfx;
      97                 :            : static bool             vga_512_chars;
      98                 :            : static int              vga_video_font_height;
      99                 :            : static int              vga_scan_lines          __read_mostly;
     100                 :            : static unsigned int     vga_rolled_over;
     101                 :            : 
     102                 :            : static bool vgacon_text_mode_force;
     103                 :            : static bool vga_hardscroll_enabled;
     104                 :            : static bool vga_hardscroll_user_enable = true;
     105                 :            : 
     106                 :         11 : bool vgacon_text_force(void)
     107                 :            : {
     108                 :         11 :         return vgacon_text_mode_force;
     109                 :            : }
     110                 :            : EXPORT_SYMBOL(vgacon_text_force);
     111                 :            : 
     112                 :          0 : static int __init text_mode(char *str)
     113                 :            : {
     114                 :          0 :         vgacon_text_mode_force = true;
     115                 :            : 
     116                 :          0 :         pr_warn("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");
     117                 :          0 :         pr_warn("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n");
     118                 :          0 :         pr_warn("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");
     119                 :            : 
     120                 :          0 :         return 1;
     121                 :            : }
     122                 :            : 
     123                 :            : /* force text mode - used by kernel modesetting */
     124                 :            : __setup("nomodeset", text_mode);
     125                 :            : 
     126                 :          0 : static int __init no_scroll(char *str)
     127                 :            : {
     128                 :            :         /*
     129                 :            :          * Disabling scrollback is required for the Braillex ib80-piezo
     130                 :            :          * Braille reader made by F.H. Papenmeier (Germany).
     131                 :            :          * Use the "no-scroll" bootflag.
     132                 :            :          */
     133                 :          0 :         vga_hardscroll_user_enable = vga_hardscroll_enabled = false;
     134                 :          0 :         return 1;
     135                 :            : }
     136                 :            : 
     137                 :            : __setup("no-scroll", no_scroll);
     138                 :            : 
     139                 :            : /*
     140                 :            :  * By replacing the four outb_p with two back to back outw, we can reduce
     141                 :            :  * the window of opportunity to see text mislocated to the RHS of the
     142                 :            :  * console during heavy scrolling activity. However there is the remote
     143                 :            :  * possibility that some pre-dinosaur hardware won't like the back to back
     144                 :            :  * I/O. Since the Xservers get away with it, we should be able to as well.
     145                 :            :  */
     146                 :         44 : static inline void write_vga(unsigned char reg, unsigned int val)
     147                 :            : {
     148                 :         44 :         unsigned int v1, v2;
     149                 :         44 :         unsigned long flags;
     150                 :            : 
     151                 :            :         /*
     152                 :            :          * ddprintk might set the console position from interrupt
     153                 :            :          * handlers, thus the write has to be IRQ-atomic.
     154                 :            :          */
     155                 :         44 :         raw_spin_lock_irqsave(&vga_lock, flags);
     156                 :         44 :         v1 = reg + (val & 0xff00);
     157                 :         44 :         v2 = reg + 1 + ((val << 8) & 0xff00);
     158                 :         44 :         outw(v1, vga_video_port_reg);
     159                 :         44 :         outw(v2, vga_video_port_reg);
     160                 :         44 :         raw_spin_unlock_irqrestore(&vga_lock, flags);
     161                 :         44 : }
     162                 :            : 
     163                 :         22 : static inline void vga_set_mem_top(struct vc_data *c)
     164                 :            : {
     165                 :         22 :         write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
     166                 :          0 : }
     167                 :            : 
     168                 :            : #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
     169                 :            : /* software scrollback */
     170                 :            : struct vgacon_scrollback_info {
     171                 :            :         void *data;
     172                 :            :         int tail;
     173                 :            :         int size;
     174                 :            :         int rows;
     175                 :            :         int cnt;
     176                 :            :         int cur;
     177                 :            :         int save;
     178                 :            :         int restore;
     179                 :            : };
     180                 :            : 
     181                 :            : static struct vgacon_scrollback_info *vgacon_scrollback_cur;
     182                 :            : static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
     183                 :            : static bool scrollback_persistent = \
     184                 :            :         IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
     185                 :            : module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
     186                 :            : MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
     187                 :            : 
     188                 :         22 : static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
     189                 :            : {
     190                 :         22 :         struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
     191                 :            : 
     192   [ +  -  +  - ]:         22 :         if (scrollback->data && reset_size > 0)
     193                 :         22 :                 memset(scrollback->data, 0, reset_size);
     194                 :            : 
     195                 :         22 :         scrollback->cnt  = 0;
     196                 :         22 :         scrollback->tail = 0;
     197                 :         22 :         scrollback->cur  = 0;
     198                 :         22 : }
     199                 :            : 
     200                 :         11 : static void vgacon_scrollback_init(int vc_num)
     201                 :            : {
     202                 :         11 :         int pitch = vga_video_num_columns * 2;
     203                 :         11 :         size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
     204                 :         11 :         int rows = size / pitch;
     205                 :         11 :         void *data;
     206                 :            : 
     207                 :         11 :         data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
     208                 :            :                              GFP_NOWAIT);
     209                 :            : 
     210                 :         11 :         vgacon_scrollbacks[vc_num].data = data;
     211                 :         11 :         vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
     212                 :            : 
     213                 :         11 :         vgacon_scrollback_cur->rows = rows - 1;
     214                 :         11 :         vgacon_scrollback_cur->size = rows * pitch;
     215                 :            : 
     216                 :         11 :         vgacon_scrollback_reset(vc_num, size);
     217                 :         11 : }
     218                 :            : 
     219                 :         11 : static void vgacon_scrollback_switch(int vc_num)
     220                 :            : {
     221         [ +  - ]:         11 :         if (!scrollback_persistent)
     222                 :         11 :                 vc_num = 0;
     223                 :            : 
     224         [ -  + ]:         11 :         if (!vgacon_scrollbacks[vc_num].data) {
     225                 :          0 :                 vgacon_scrollback_init(vc_num);
     226                 :            :         } else {
     227         [ -  + ]:         11 :                 if (scrollback_persistent) {
     228                 :          0 :                         vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
     229                 :            :                 } else {
     230                 :         11 :                         size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
     231                 :            : 
     232                 :         11 :                         vgacon_scrollback_reset(vc_num, size);
     233                 :            :                 }
     234                 :            :         }
     235                 :         11 : }
     236                 :            : 
     237                 :         11 : static void vgacon_scrollback_startup(void)
     238                 :            : {
     239                 :         11 :         vgacon_scrollback_cur = &vgacon_scrollbacks[0];
     240                 :         11 :         vgacon_scrollback_init(0);
     241                 :            : }
     242                 :            : 
     243                 :          0 : static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
     244                 :            : {
     245                 :          0 :         void *p;
     246                 :            : 
     247   [ #  #  #  # ]:          0 :         if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
     248         [ #  # ]:          0 :             c->vc_num != fg_console)
     249                 :            :                 return;
     250                 :            : 
     251                 :          0 :         p = (void *) (c->vc_origin + t * c->vc_size_row);
     252                 :            : 
     253         [ #  # ]:          0 :         while (count--) {
     254                 :          0 :                 scr_memcpyw(vgacon_scrollback_cur->data +
     255         [ #  # ]:          0 :                             vgacon_scrollback_cur->tail,
     256                 :            :                             p, c->vc_size_row);
     257                 :            : 
     258                 :          0 :                 vgacon_scrollback_cur->cnt++;
     259                 :          0 :                 p += c->vc_size_row;
     260                 :          0 :                 vgacon_scrollback_cur->tail += c->vc_size_row;
     261                 :            : 
     262         [ #  # ]:          0 :                 if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
     263                 :          0 :                         vgacon_scrollback_cur->tail = 0;
     264                 :            : 
     265         [ #  # ]:          0 :                 if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
     266                 :          0 :                         vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
     267                 :            : 
     268                 :          0 :                 vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
     269                 :            :         }
     270                 :            : }
     271                 :            : 
     272                 :         22 : static void vgacon_restore_screen(struct vc_data *c)
     273                 :            : {
     274                 :         22 :         c->vc_origin = c->vc_visible_origin;
     275                 :         22 :         vgacon_scrollback_cur->save = 0;
     276                 :            : 
     277   [ +  -  +  + ]:         22 :         if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
     278                 :         11 :                 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
     279                 :         11 :                             c->vc_screenbuf_size > vga_vram_size ?
     280                 :            :                             vga_vram_size : c->vc_screenbuf_size);
     281                 :         11 :                 vgacon_scrollback_cur->restore = 1;
     282                 :         11 :                 vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
     283                 :            :         }
     284                 :         22 : }
     285                 :            : 
     286                 :          0 : static void vgacon_scrolldelta(struct vc_data *c, int lines)
     287                 :            : {
     288                 :          0 :         int start, end, count, soff;
     289                 :            : 
     290         [ #  # ]:          0 :         if (!lines) {
     291                 :          0 :                 vgacon_restore_screen(c);
     292                 :          0 :                 return;
     293                 :            :         }
     294                 :            : 
     295         [ #  # ]:          0 :         if (!vgacon_scrollback_cur->data)
     296                 :            :                 return;
     297                 :            : 
     298         [ #  # ]:          0 :         if (!vgacon_scrollback_cur->save) {
     299                 :          0 :                 vgacon_cursor(c, CM_ERASE);
     300                 :          0 :                 vgacon_save_screen(c);
     301                 :          0 :                 c->vc_origin = (unsigned long)c->vc_screenbuf;
     302                 :          0 :                 vgacon_scrollback_cur->save = 1;
     303                 :            :         }
     304                 :            : 
     305                 :          0 :         vgacon_scrollback_cur->restore = 0;
     306                 :          0 :         start = vgacon_scrollback_cur->cur + lines;
     307                 :          0 :         end = start + abs(lines);
     308                 :            : 
     309                 :          0 :         if (start < 0)
     310                 :            :                 start = 0;
     311                 :            : 
     312                 :          0 :         if (start > vgacon_scrollback_cur->cnt)
     313                 :            :                 start = vgacon_scrollback_cur->cnt;
     314                 :            : 
     315                 :          0 :         if (end < 0)
     316                 :            :                 end = 0;
     317                 :            : 
     318                 :          0 :         if (end > vgacon_scrollback_cur->cnt)
     319                 :            :                 end = vgacon_scrollback_cur->cnt;
     320                 :            : 
     321                 :          0 :         vgacon_scrollback_cur->cur = start;
     322                 :          0 :         count = end - start;
     323                 :          0 :         soff = vgacon_scrollback_cur->tail -
     324                 :          0 :                 ((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
     325                 :          0 :         soff -= count * c->vc_size_row;
     326                 :            : 
     327         [ #  # ]:          0 :         if (soff < 0)
     328                 :          0 :                 soff += vgacon_scrollback_cur->size;
     329                 :            : 
     330                 :          0 :         count = vgacon_scrollback_cur->cnt - start;
     331                 :            : 
     332         [ #  # ]:          0 :         if (count > c->vc_rows)
     333                 :          0 :                 count = c->vc_rows;
     334                 :            : 
     335         [ #  # ]:          0 :         if (count) {
     336                 :          0 :                 int copysize;
     337                 :            : 
     338                 :          0 :                 int diff = c->vc_rows - count;
     339                 :          0 :                 void *d = (void *) c->vc_visible_origin;
     340                 :          0 :                 void *s = (void *) c->vc_screenbuf;
     341                 :            : 
     342                 :          0 :                 count *= c->vc_size_row;
     343                 :            :                 /* how much memory to end of buffer left? */
     344                 :          0 :                 copysize = min(count, vgacon_scrollback_cur->size - soff);
     345         [ #  # ]:          0 :                 scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
     346                 :          0 :                 d += copysize;
     347                 :          0 :                 count -= copysize;
     348                 :            : 
     349         [ #  # ]:          0 :                 if (count) {
     350                 :          0 :                         scr_memcpyw(d, vgacon_scrollback_cur->data, count);
     351                 :          0 :                         d += count;
     352                 :            :                 }
     353                 :            : 
     354         [ #  # ]:          0 :                 if (diff)
     355                 :          0 :                         scr_memcpyw(d, s, diff * c->vc_size_row);
     356                 :            :         } else
     357                 :          0 :                 vgacon_cursor(c, CM_MOVE);
     358                 :            : }
     359                 :            : 
     360                 :          0 : static void vgacon_flush_scrollback(struct vc_data *c)
     361                 :            : {
     362                 :          0 :         size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
     363                 :            : 
     364                 :          0 :         vgacon_scrollback_reset(c->vc_num, size);
     365                 :          0 : }
     366                 :            : #else
     367                 :            : #define vgacon_scrollback_startup(...) do { } while (0)
     368                 :            : #define vgacon_scrollback_init(...)    do { } while (0)
     369                 :            : #define vgacon_scrollback_update(...)  do { } while (0)
     370                 :            : #define vgacon_scrollback_switch(...)  do { } while (0)
     371                 :            : 
     372                 :            : static void vgacon_restore_screen(struct vc_data *c)
     373                 :            : {
     374                 :            :         if (c->vc_origin != c->vc_visible_origin)
     375                 :            :                 vgacon_scrolldelta(c, 0);
     376                 :            : }
     377                 :            : 
     378                 :            : static void vgacon_scrolldelta(struct vc_data *c, int lines)
     379                 :            : {
     380                 :            :         vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
     381                 :            :                         vga_vram_size);
     382                 :            :         vga_set_mem_top(c);
     383                 :            : }
     384                 :            : 
     385                 :            : static void vgacon_flush_scrollback(struct vc_data *c)
     386                 :            : {
     387                 :            : }
     388                 :            : #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
     389                 :            : 
     390                 :         11 : static const char *vgacon_startup(void)
     391                 :            : {
     392                 :         11 :         const char *display_desc = NULL;
     393                 :         11 :         u16 saved1, saved2;
     394                 :         11 :         volatile u16 *p;
     395                 :            : 
     396         [ -  + ]:         11 :         if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB ||
     397                 :            :             screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
     398                 :          0 :               no_vga:
     399                 :            : #ifdef CONFIG_DUMMY_CONSOLE
     400                 :          0 :                 conswitchp = &dummy_con;
     401                 :          0 :                 return conswitchp->con_startup();
     402                 :            : #else
     403                 :            :                 return NULL;
     404                 :            : #endif
     405                 :            :         }
     406                 :            : 
     407                 :            :         /* boot_params.screen_info reasonably initialized? */
     408         [ +  - ]:         11 :         if ((screen_info.orig_video_lines == 0) ||
     409         [ -  + ]:         11 :             (screen_info.orig_video_cols  == 0))
     410                 :          0 :                 goto no_vga;
     411                 :            : 
     412                 :            :         /* VGA16 modes are not handled by VGACON */
     413                 :         11 :         if ((screen_info.orig_video_mode == 0x0D) ||    /* 320x200/4 */
     414         [ +  - ]:         11 :             (screen_info.orig_video_mode == 0x0E) ||    /* 640x200/4 */
     415         [ +  - ]:         11 :             (screen_info.orig_video_mode == 0x10) ||    /* 640x350/4 */
     416         [ -  + ]:         11 :             (screen_info.orig_video_mode == 0x12) ||    /* 640x480/4 */
     417                 :            :             (screen_info.orig_video_mode == 0x6A))      /* 800x600/4 (VESA) */
     418                 :          0 :                 goto no_vga;
     419                 :            : 
     420                 :         11 :         vga_video_num_lines = screen_info.orig_video_lines;
     421                 :         11 :         vga_video_num_columns = screen_info.orig_video_cols;
     422                 :         11 :         vgastate.vgabase = NULL;
     423                 :            : 
     424         [ -  + ]:         11 :         if (screen_info.orig_video_mode == 7) {
     425                 :            :                 /* Monochrome display */
     426                 :          0 :                 vga_vram_base = 0xb0000;
     427                 :          0 :                 vga_video_port_reg = VGA_CRT_IM;
     428                 :          0 :                 vga_video_port_val = VGA_CRT_DM;
     429         [ #  # ]:          0 :                 if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
     430                 :          0 :                         static struct resource ega_console_resource =
     431                 :            :                             { .name     = "ega",
     432                 :            :                               .flags    = IORESOURCE_IO,
     433                 :            :                               .start    = 0x3B0,
     434                 :            :                               .end      = 0x3BF };
     435                 :          0 :                         vga_video_type = VIDEO_TYPE_EGAM;
     436                 :          0 :                         vga_vram_size = 0x8000;
     437                 :          0 :                         display_desc = "EGA+";
     438                 :          0 :                         request_resource(&ioport_resource,
     439                 :            :                                          &ega_console_resource);
     440                 :            :                 } else {
     441                 :          0 :                         static struct resource mda1_console_resource =
     442                 :            :                             { .name     = "mda",
     443                 :            :                               .flags    = IORESOURCE_IO,
     444                 :            :                               .start    = 0x3B0,
     445                 :            :                               .end      = 0x3BB };
     446                 :          0 :                         static struct resource mda2_console_resource =
     447                 :            :                             { .name     = "mda",
     448                 :            :                               .flags    = IORESOURCE_IO,
     449                 :            :                               .start    = 0x3BF,
     450                 :            :                               .end      = 0x3BF };
     451                 :          0 :                         vga_video_type = VIDEO_TYPE_MDA;
     452                 :          0 :                         vga_vram_size = 0x2000;
     453                 :          0 :                         display_desc = "*MDA";
     454                 :          0 :                         request_resource(&ioport_resource,
     455                 :            :                                          &mda1_console_resource);
     456                 :          0 :                         request_resource(&ioport_resource,
     457                 :            :                                          &mda2_console_resource);
     458                 :          0 :                         vga_video_font_height = 14;
     459                 :            :                 }
     460                 :            :         } else {
     461                 :            :                 /* If not, it is color. */
     462                 :         11 :                 vga_can_do_color = true;
     463                 :         11 :                 vga_vram_base = 0xb8000;
     464                 :         11 :                 vga_video_port_reg = VGA_CRT_IC;
     465                 :         11 :                 vga_video_port_val = VGA_CRT_DC;
     466         [ +  - ]:         11 :                 if ((screen_info.orig_video_ega_bx & 0xff) != 0x10) {
     467                 :         11 :                         int i;
     468                 :            : 
     469                 :         11 :                         vga_vram_size = 0x8000;
     470                 :            : 
     471         [ -  + ]:         11 :                         if (!screen_info.orig_video_isVGA) {
     472                 :          0 :                                 static struct resource ega_console_resource =
     473                 :            :                                     { .name     = "ega",
     474                 :            :                                       .flags    = IORESOURCE_IO,
     475                 :            :                                       .start    = 0x3C0,
     476                 :            :                                       .end      = 0x3DF };
     477                 :          0 :                                 vga_video_type = VIDEO_TYPE_EGAC;
     478                 :          0 :                                 display_desc = "EGA";
     479                 :          0 :                                 request_resource(&ioport_resource,
     480                 :            :                                                  &ega_console_resource);
     481                 :            :                         } else {
     482                 :         11 :                                 static struct resource vga_console_resource =
     483                 :            :                                     { .name     = "vga+",
     484                 :            :                                       .flags    = IORESOURCE_IO,
     485                 :            :                                       .start    = 0x3C0,
     486                 :            :                                       .end      = 0x3DF };
     487                 :         11 :                                 vga_video_type = VIDEO_TYPE_VGAC;
     488                 :         11 :                                 display_desc = "VGA+";
     489                 :         11 :                                 request_resource(&ioport_resource,
     490                 :            :                                                  &vga_console_resource);
     491                 :            : 
     492                 :            :                                 /*
     493                 :            :                                  * Normalise the palette registers, to point
     494                 :            :                                  * the 16 screen colours to the first 16
     495                 :            :                                  * DAC entries.
     496                 :            :                                  */
     497                 :            : 
     498         [ +  + ]:        198 :                                 for (i = 0; i < 16; i++) {
     499                 :        176 :                                         inb_p(VGA_IS1_RC);
     500                 :        176 :                                         outb_p(i, VGA_ATT_W);
     501                 :        176 :                                         outb_p(i, VGA_ATT_W);
     502                 :            :                                 }
     503                 :         11 :                                 outb_p(0x20, VGA_ATT_W);
     504                 :            : 
     505                 :            :                                 /*
     506                 :            :                                  * Now set the DAC registers back to their
     507                 :            :                                  * default values
     508                 :            :                                  */
     509         [ +  + ]:        198 :                                 for (i = 0; i < 16; i++) {
     510                 :        176 :                                         outb_p(color_table[i], VGA_PEL_IW);
     511                 :        176 :                                         outb_p(default_red[i], VGA_PEL_D);
     512                 :        176 :                                         outb_p(default_grn[i], VGA_PEL_D);
     513                 :        176 :                                         outb_p(default_blu[i], VGA_PEL_D);
     514                 :            :                                 }
     515                 :            :                         }
     516                 :            :                 } else {
     517                 :          0 :                         static struct resource cga_console_resource =
     518                 :            :                             { .name     = "cga",
     519                 :            :                               .flags    = IORESOURCE_IO,
     520                 :            :                               .start    = 0x3D4,
     521                 :            :                               .end      = 0x3D5 };
     522                 :          0 :                         vga_video_type = VIDEO_TYPE_CGA;
     523                 :          0 :                         vga_vram_size = 0x2000;
     524                 :          0 :                         display_desc = "*CGA";
     525                 :          0 :                         request_resource(&ioport_resource,
     526                 :            :                                          &cga_console_resource);
     527                 :          0 :                         vga_video_font_height = 8;
     528                 :            :                 }
     529                 :            :         }
     530                 :            : 
     531         [ +  - ]:         11 :         vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
     532                 :         11 :         vga_vram_end = vga_vram_base + vga_vram_size;
     533                 :            : 
     534                 :            :         /*
     535                 :            :          *      Find out if there is a graphics card present.
     536                 :            :          *      Are there smarter methods around?
     537                 :            :          */
     538                 :         11 :         p = (volatile u16 *) vga_vram_base;
     539                 :         11 :         saved1 = scr_readw(p);
     540                 :         11 :         saved2 = scr_readw(p + 1);
     541                 :         11 :         scr_writew(0xAA55, p);
     542                 :         11 :         scr_writew(0x55AA, p + 1);
     543   [ +  -  -  + ]:         11 :         if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
     544                 :          0 :                 scr_writew(saved1, p);
     545                 :          0 :                 scr_writew(saved2, p + 1);
     546                 :          0 :                 goto no_vga;
     547                 :            :         }
     548                 :         11 :         scr_writew(0x55AA, p);
     549                 :         11 :         scr_writew(0xAA55, p + 1);
     550   [ +  -  -  + ]:         11 :         if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
     551                 :          0 :                 scr_writew(saved1, p);
     552                 :          0 :                 scr_writew(saved2, p + 1);
     553                 :          0 :                 goto no_vga;
     554                 :            :         }
     555                 :         11 :         scr_writew(saved1, p);
     556                 :         11 :         scr_writew(saved2, p + 1);
     557                 :            : 
     558                 :         11 :         if (vga_video_type == VIDEO_TYPE_EGAC
     559                 :            :             || vga_video_type == VIDEO_TYPE_VGAC
     560         [ +  - ]:         11 :             || vga_video_type == VIDEO_TYPE_EGAM) {
     561                 :         11 :                 vga_hardscroll_enabled = vga_hardscroll_user_enable;
     562                 :         11 :                 vga_default_font_height = screen_info.orig_video_points;
     563                 :         11 :                 vga_video_font_height = screen_info.orig_video_points;
     564                 :            :                 /* This may be suboptimal but is a safe bet - go with it */
     565                 :         11 :                 vga_scan_lines =
     566                 :         11 :                     vga_video_font_height * vga_video_num_lines;
     567                 :            :         }
     568                 :            : 
     569                 :         11 :         vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
     570                 :         11 :         vgacon_yres = vga_scan_lines;
     571                 :            : 
     572         [ +  - ]:         11 :         if (!vga_init_done) {
     573                 :         11 :                 vgacon_scrollback_startup();
     574                 :         11 :                 vga_init_done = true;
     575                 :            :         }
     576                 :            : 
     577                 :            :         return display_desc;
     578                 :            : }
     579                 :            : 
     580                 :         11 : static void vgacon_init(struct vc_data *c, int init)
     581                 :            : {
     582                 :         11 :         struct uni_pagedir *p;
     583                 :            : 
     584                 :            :         /*
     585                 :            :          * We cannot be loaded as a module, therefore init is always 1,
     586                 :            :          * but vgacon_init can be called more than once, and init will
     587                 :            :          * not be 1.
     588                 :            :          */
     589                 :         11 :         c->vc_can_do_color = vga_can_do_color;
     590                 :            : 
     591                 :            :         /* set dimensions manually if init != 0 since vc_resize() will fail */
     592         [ +  - ]:         11 :         if (init) {
     593                 :         11 :                 c->vc_cols = vga_video_num_columns;
     594                 :         11 :                 c->vc_rows = vga_video_num_lines;
     595                 :            :         } else
     596                 :          0 :                 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
     597                 :            : 
     598                 :         11 :         c->vc_scan_lines = vga_scan_lines;
     599                 :         11 :         c->vc_font.height = vga_video_font_height;
     600                 :         11 :         c->vc_complement_mask = 0x7700;
     601         [ -  + ]:         11 :         if (vga_512_chars)
     602                 :          0 :                 c->vc_hi_font_mask = 0x0800;
     603                 :         11 :         p = *c->vc_uni_pagedir_loc;
     604         [ +  - ]:         11 :         if (c->vc_uni_pagedir_loc != &vgacon_uni_pagedir) {
     605                 :         11 :                 con_free_unimap(c);
     606                 :         11 :                 c->vc_uni_pagedir_loc = &vgacon_uni_pagedir;
     607                 :         11 :                 vgacon_refcount++;
     608                 :            :         }
     609   [ +  -  -  + ]:         11 :         if (!vgacon_uni_pagedir && p)
     610                 :          0 :                 con_set_default_unimap(c);
     611                 :            : 
     612                 :            :         /* Only set the default if the user didn't deliberately override it */
     613         [ +  - ]:         11 :         if (global_cursor_default == -1)
     614                 :         11 :                 global_cursor_default =
     615                 :         11 :                         !(screen_info.flags & VIDEO_FLAGS_NOCURSOR);
     616                 :         11 : }
     617                 :            : 
     618                 :          0 : static void vgacon_deinit(struct vc_data *c)
     619                 :            : {
     620                 :            :         /* When closing the active console, reset video origin */
     621         [ #  # ]:          0 :         if (con_is_visible(c)) {
     622                 :          0 :                 c->vc_visible_origin = vga_vram_base;
     623                 :          0 :                 vga_set_mem_top(c);
     624                 :            :         }
     625                 :            : 
     626         [ #  # ]:          0 :         if (!--vgacon_refcount)
     627                 :          0 :                 con_free_unimap(c);
     628                 :          0 :         c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
     629                 :          0 :         con_set_default_unimap(c);
     630                 :          0 : }
     631                 :            : 
     632                 :         22 : static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
     633                 :            :                             u8 blink, u8 underline, u8 reverse, u8 italic)
     634                 :            : {
     635                 :         22 :         u8 attr = color;
     636                 :            : 
     637         [ +  - ]:         22 :         if (vga_can_do_color) {
     638         [ -  + ]:         22 :                 if (italic)
     639                 :          0 :                         attr = (attr & 0xF0) | c->vc_itcolor;
     640         [ -  + ]:         22 :                 else if (underline)
     641                 :          0 :                         attr = (attr & 0xf0) | c->vc_ulcolor;
     642         [ -  + ]:         22 :                 else if (intensity == 0)
     643                 :          0 :                         attr = (attr & 0xf0) | c->vc_halfcolor;
     644                 :            :         }
     645         [ -  + ]:         22 :         if (reverse)
     646                 :          0 :                 attr =
     647                 :          0 :                     ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) &
     648                 :            :                                        0x77);
     649         [ -  + ]:         22 :         if (blink)
     650                 :          0 :                 attr ^= 0x80;
     651         [ -  + ]:         22 :         if (intensity == 2)
     652                 :          0 :                 attr ^= 0x08;
     653         [ -  + ]:         22 :         if (!vga_can_do_color) {
     654         [ #  # ]:          0 :                 if (italic)
     655                 :          0 :                         attr = (attr & 0xF8) | 0x02;
     656         [ #  # ]:          0 :                 else if (underline)
     657                 :          0 :                         attr = (attr & 0xf8) | 0x01;
     658         [ #  # ]:          0 :                 else if (intensity == 0)
     659                 :          0 :                         attr = (attr & 0xf0) | 0x08;
     660                 :            :         }
     661                 :         22 :         return attr;
     662                 :            : }
     663                 :            : 
     664                 :          0 : static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
     665                 :            : {
     666                 :          0 :         const bool col = vga_can_do_color;
     667                 :            : 
     668         [ #  # ]:          0 :         while (count--) {
     669                 :          0 :                 u16 a = scr_readw(p);
     670         [ #  # ]:          0 :                 if (col)
     671                 :          0 :                         a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
     672                 :          0 :                             (((a) & 0x0700) << 4);
     673                 :            :                 else
     674         [ #  # ]:          0 :                         a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
     675                 :          0 :                 scr_writew(a, p++);
     676                 :            :         }
     677                 :          0 : }
     678                 :            : 
     679                 :            : static void vgacon_set_cursor_size(int xpos, int from, int to)
     680                 :            : {
     681                 :            :         unsigned long flags;
     682                 :            :         int curs, cure;
     683                 :            : 
     684                 :            :         if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto))
     685                 :            :                 return;
     686                 :            :         cursor_size_lastfrom = from;
     687                 :            :         cursor_size_lastto = to;
     688                 :            : 
     689                 :            :         raw_spin_lock_irqsave(&vga_lock, flags);
     690                 :            :         if (vga_video_type >= VIDEO_TYPE_VGAC) {
     691                 :            :                 outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
     692                 :            :                 curs = inb_p(vga_video_port_val);
     693                 :            :                 outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
     694                 :            :                 cure = inb_p(vga_video_port_val);
     695                 :            :         } else {
     696                 :            :                 curs = 0;
     697                 :            :                 cure = 0;
     698                 :            :         }
     699                 :            : 
     700                 :            :         curs = (curs & 0xc0) | from;
     701                 :            :         cure = (cure & 0xe0) | to;
     702                 :            : 
     703                 :            :         outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
     704                 :            :         outb_p(curs, vga_video_port_val);
     705                 :            :         outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
     706                 :            :         outb_p(cure, vga_video_port_val);
     707                 :            :         raw_spin_unlock_irqrestore(&vga_lock, flags);
     708                 :            : }
     709                 :            : 
     710                 :         22 : static void vgacon_cursor(struct vc_data *c, int mode)
     711                 :            : {
     712         [ +  - ]:         22 :         if (c->vc_mode != KD_TEXT)
     713                 :            :                 return;
     714                 :            : 
     715                 :         22 :         vgacon_restore_screen(c);
     716                 :            : 
     717      [ +  +  - ]:         22 :         switch (mode) {
     718                 :         11 :         case CM_ERASE:
     719                 :         11 :                 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
     720         [ +  - ]:         11 :                 if (vga_video_type >= VIDEO_TYPE_VGAC)
     721                 :         11 :                         vgacon_set_cursor_size(c->vc_x, 31, 30);
     722                 :            :                 else
     723                 :          0 :                         vgacon_set_cursor_size(c->vc_x, 31, 31);
     724                 :            :                 break;
     725                 :            : 
     726                 :         11 :         case CM_MOVE:
     727                 :            :         case CM_DRAW:
     728                 :         11 :                 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
     729   [ +  -  -  -  :         11 :                 switch (c->vc_cursor_type & 0x0f) {
                   -  - ]
     730                 :         11 :                 case CUR_UNDERLINE:
     731                 :         33 :                         vgacon_set_cursor_size(c->vc_x,
     732                 :         11 :                                                c->vc_font.height -
     733                 :            :                                                (c->vc_font.height <
     734                 :         11 :                                                 10 ? 2 : 3),
     735         [ +  - ]:         11 :                                                c->vc_font.height -
     736                 :            :                                                (c->vc_font.height <
     737         [ +  - ]:         11 :                                                 10 ? 1 : 2));
     738                 :         11 :                         break;
     739                 :          0 :                 case CUR_TWO_THIRDS:
     740                 :          0 :                         vgacon_set_cursor_size(c->vc_x,
     741                 :          0 :                                                c->vc_font.height / 3,
     742                 :          0 :                                                c->vc_font.height -
     743                 :            :                                                (c->vc_font.height <
     744         [ #  # ]:          0 :                                                 10 ? 1 : 2));
     745                 :          0 :                         break;
     746                 :          0 :                 case CUR_LOWER_THIRD:
     747                 :          0 :                         vgacon_set_cursor_size(c->vc_x,
     748                 :          0 :                                                (c->vc_font.height * 2) / 3,
     749                 :          0 :                                                c->vc_font.height -
     750                 :            :                                                (c->vc_font.height <
     751         [ #  # ]:          0 :                                                 10 ? 1 : 2));
     752                 :          0 :                         break;
     753                 :          0 :                 case CUR_LOWER_HALF:
     754                 :          0 :                         vgacon_set_cursor_size(c->vc_x,
     755                 :          0 :                                                c->vc_font.height / 2,
     756                 :          0 :                                                c->vc_font.height -
     757                 :            :                                                (c->vc_font.height <
     758         [ #  # ]:          0 :                                                 10 ? 1 : 2));
     759                 :          0 :                         break;
     760                 :          0 :                 case CUR_NONE:
     761         [ #  # ]:          0 :                         if (vga_video_type >= VIDEO_TYPE_VGAC)
     762                 :          0 :                                 vgacon_set_cursor_size(c->vc_x, 31, 30);
     763                 :            :                         else
     764                 :          0 :                                 vgacon_set_cursor_size(c->vc_x, 31, 31);
     765                 :            :                         break;
     766                 :          0 :                 default:
     767                 :          0 :                         vgacon_set_cursor_size(c->vc_x, 1,
     768                 :          0 :                                                c->vc_font.height);
     769                 :          0 :                         break;
     770                 :            :                 }
     771                 :            :                 break;
     772                 :            :         }
     773                 :         22 : }
     774                 :            : 
     775                 :            : static int vgacon_doresize(struct vc_data *c,
     776                 :            :                 unsigned int width, unsigned int height)
     777                 :            : {
     778                 :            :         unsigned long flags;
     779                 :            :         unsigned int scanlines = height * c->vc_font.height;
     780                 :            :         u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
     781                 :            : 
     782                 :            :         raw_spin_lock_irqsave(&vga_lock, flags);
     783                 :            : 
     784                 :            :         vgacon_xres = width * VGA_FONTWIDTH;
     785                 :            :         vgacon_yres = height * c->vc_font.height;
     786                 :            :         if (vga_video_type >= VIDEO_TYPE_VGAC) {
     787                 :            :                 outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
     788                 :            :                 max_scan = inb_p(vga_video_port_val);
     789                 :            : 
     790                 :            :                 if (max_scan & 0x80)
     791                 :            :                         scanlines <<= 1;
     792                 :            : 
     793                 :            :                 outb_p(VGA_CRTC_MODE, vga_video_port_reg);
     794                 :            :                 mode = inb_p(vga_video_port_val);
     795                 :            : 
     796                 :            :                 if (mode & 0x04)
     797                 :            :                         scanlines >>= 1;
     798                 :            : 
     799                 :            :                 scanlines -= 1;
     800                 :            :                 scanlines_lo = scanlines & 0xff;
     801                 :            : 
     802                 :            :                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
     803                 :            :                 r7 = inb_p(vga_video_port_val) & ~0x42;
     804                 :            : 
     805                 :            :                 if (scanlines & 0x100)
     806                 :            :                         r7 |= 0x02;
     807                 :            :                 if (scanlines & 0x200)
     808                 :            :                         r7 |= 0x40;
     809                 :            : 
     810                 :            :                 /* deprotect registers */
     811                 :            :                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
     812                 :            :                 vsync_end = inb_p(vga_video_port_val);
     813                 :            :                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
     814                 :            :                 outb_p(vsync_end & ~0x80, vga_video_port_val);
     815                 :            :         }
     816                 :            : 
     817                 :            :         outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
     818                 :            :         outb_p(width - 1, vga_video_port_val);
     819                 :            :         outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
     820                 :            :         outb_p(width >> 1, vga_video_port_val);
     821                 :            : 
     822                 :            :         if (vga_video_type >= VIDEO_TYPE_VGAC) {
     823                 :            :                 outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
     824                 :            :                 outb_p(scanlines_lo, vga_video_port_val);
     825                 :            :                 outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
     826                 :            :                 outb_p(r7,vga_video_port_val);
     827                 :            : 
     828                 :            :                 /* reprotect registers */
     829                 :            :                 outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
     830                 :            :                 outb_p(vsync_end, vga_video_port_val);
     831                 :            :         }
     832                 :            : 
     833                 :            :         raw_spin_unlock_irqrestore(&vga_lock, flags);
     834                 :            :         return 0;
     835                 :            : }
     836                 :            : 
     837                 :         11 : static int vgacon_switch(struct vc_data *c)
     838                 :            : {
     839                 :         11 :         int x = c->vc_cols * VGA_FONTWIDTH;
     840                 :         11 :         int y = c->vc_rows * c->vc_font.height;
     841                 :         11 :         int rows = screen_info.orig_video_lines * vga_default_font_height/
     842                 :            :                 c->vc_font.height;
     843                 :            :         /*
     844                 :            :          * We need to save screen size here as it's the only way
     845                 :            :          * we can spot the screen has been resized and we need to
     846                 :            :          * set size of freshly allocated screens ourselves.
     847                 :            :          */
     848                 :         11 :         vga_video_num_columns = c->vc_cols;
     849                 :         11 :         vga_video_num_lines = c->vc_rows;
     850                 :            : 
     851                 :            :         /* We can only copy out the size of the video buffer here,
     852                 :            :          * otherwise we get into VGA BIOS */
     853                 :            : 
     854         [ +  - ]:         11 :         if (!vga_is_gfx) {
     855                 :         11 :                 scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
     856         [ +  - ]:         11 :                             c->vc_screenbuf_size > vga_vram_size ?
     857                 :            :                                 vga_vram_size : c->vc_screenbuf_size);
     858                 :            : 
     859   [ +  -  -  + ]:         11 :                 if ((vgacon_xres != x || vgacon_yres != y) &&
     860         [ #  # ]:          0 :                     (!(vga_video_num_columns % 2) &&
     861   [ #  #  #  # ]:          0 :                      vga_video_num_columns <= screen_info.orig_video_cols &&
     862                 :            :                      vga_video_num_lines <= rows))
     863                 :          0 :                         vgacon_doresize(c, c->vc_cols, c->vc_rows);
     864                 :            :         }
     865                 :            : 
     866                 :         11 :         vgacon_scrollback_switch(c->vc_num);
     867                 :         11 :         return 0;               /* Redrawing not needed */
     868                 :            : }
     869                 :            : 
     870                 :         11 : static void vga_set_palette(struct vc_data *vc, const unsigned char *table)
     871                 :            : {
     872                 :         11 :         int i, j;
     873                 :            : 
     874         [ -  + ]:         11 :         vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
     875         [ +  + ]:        187 :         for (i = j = 0; i < 16; i++) {
     876         [ -  + ]:        176 :                 vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
     877         [ -  + ]:        176 :                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
     878         [ -  + ]:        176 :                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
     879         [ -  + ]:        176 :                 vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
     880                 :            :         }
     881                 :         11 : }
     882                 :            : 
     883                 :         22 : static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table)
     884                 :            : {
     885   [ +  -  +  - ]:         22 :         if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked
     886         [ +  + ]:         22 :             || !con_is_visible(vc))
     887                 :         11 :                 return;
     888                 :         11 :         vga_set_palette(vc, table);
     889                 :            : }
     890                 :            : 
     891                 :            : /* structure holding original VGA register settings */
     892                 :            : static struct {
     893                 :            :         unsigned char SeqCtrlIndex;     /* Sequencer Index reg.   */
     894                 :            :         unsigned char CrtCtrlIndex;     /* CRT-Contr. Index reg.  */
     895                 :            :         unsigned char CrtMiscIO;        /* Miscellaneous register */
     896                 :            :         unsigned char HorizontalTotal;  /* CRT-Controller:00h */
     897                 :            :         unsigned char HorizDisplayEnd;  /* CRT-Controller:01h */
     898                 :            :         unsigned char StartHorizRetrace;        /* CRT-Controller:04h */
     899                 :            :         unsigned char EndHorizRetrace;  /* CRT-Controller:05h */
     900                 :            :         unsigned char Overflow; /* CRT-Controller:07h */
     901                 :            :         unsigned char StartVertRetrace; /* CRT-Controller:10h */
     902                 :            :         unsigned char EndVertRetrace;   /* CRT-Controller:11h */
     903                 :            :         unsigned char ModeControl;      /* CRT-Controller:17h */
     904                 :            :         unsigned char ClockingMode;     /* Seq-Controller:01h */
     905                 :            : } vga_state;
     906                 :            : 
     907                 :            : static void vga_vesa_blank(struct vgastate *state, int mode)
     908                 :            : {
     909                 :            :         /* save original values of VGA controller registers */
     910                 :            :         if (!vga_vesa_blanked) {
     911                 :            :                 raw_spin_lock_irq(&vga_lock);
     912                 :            :                 vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
     913                 :            :                 vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
     914                 :            :                 vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
     915                 :            :                 raw_spin_unlock_irq(&vga_lock);
     916                 :            : 
     917                 :            :                 outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
     918                 :            :                 vga_state.HorizontalTotal = inb_p(vga_video_port_val);
     919                 :            :                 outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
     920                 :            :                 vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
     921                 :            :                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
     922                 :            :                 vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
     923                 :            :                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
     924                 :            :                 vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
     925                 :            :                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
     926                 :            :                 vga_state.Overflow = inb_p(vga_video_port_val);
     927                 :            :                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
     928                 :            :                 vga_state.StartVertRetrace = inb_p(vga_video_port_val);
     929                 :            :                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
     930                 :            :                 vga_state.EndVertRetrace = inb_p(vga_video_port_val);
     931                 :            :                 outb_p(0x17, vga_video_port_reg);       /* ModeControl */
     932                 :            :                 vga_state.ModeControl = inb_p(vga_video_port_val);
     933                 :            :                 vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE);
     934                 :            :         }
     935                 :            : 
     936                 :            :         /* assure that video is enabled */
     937                 :            :         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
     938                 :            :         raw_spin_lock_irq(&vga_lock);
     939                 :            :         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
     940                 :            : 
     941                 :            :         /* test for vertical retrace in process.... */
     942                 :            :         if ((vga_state.CrtMiscIO & 0x80) == 0x80)
     943                 :            :                 vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF);
     944                 :            : 
     945                 :            :         /*
     946                 :            :          * Set <End of vertical retrace> to minimum (0) and
     947                 :            :          * <Start of vertical Retrace> to maximum (incl. overflow)
     948                 :            :          * Result: turn off vertical sync (VSync) pulse.
     949                 :            :          */
     950                 :            :         if (mode & VESA_VSYNC_SUSPEND) {
     951                 :            :                 outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
     952                 :            :                 outb_p(0xff, vga_video_port_val);       /* maximum value */
     953                 :            :                 outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
     954                 :            :                 outb_p(0x40, vga_video_port_val);       /* minimum (bits 0..3)  */
     955                 :            :                 outb_p(0x07, vga_video_port_reg);       /* Overflow */
     956                 :            :                 outb_p(vga_state.Overflow | 0x84, vga_video_port_val);  /* bits 9,10 of vert. retrace */
     957                 :            :         }
     958                 :            : 
     959                 :            :         if (mode & VESA_HSYNC_SUSPEND) {
     960                 :            :                 /*
     961                 :            :                  * Set <End of horizontal retrace> to minimum (0) and
     962                 :            :                  *  <Start of horizontal Retrace> to maximum
     963                 :            :                  * Result: turn off horizontal sync (HSync) pulse.
     964                 :            :                  */
     965                 :            :                 outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
     966                 :            :                 outb_p(0xff, vga_video_port_val);       /* maximum */
     967                 :            :                 outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
     968                 :            :                 outb_p(0x00, vga_video_port_val);       /* minimum (0) */
     969                 :            :         }
     970                 :            : 
     971                 :            :         /* restore both index registers */
     972                 :            :         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
     973                 :            :         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
     974                 :            :         raw_spin_unlock_irq(&vga_lock);
     975                 :            : }
     976                 :            : 
     977                 :            : static void vga_vesa_unblank(struct vgastate *state)
     978                 :            : {
     979                 :            :         /* restore original values of VGA controller registers */
     980                 :            :         raw_spin_lock_irq(&vga_lock);
     981                 :            :         vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
     982                 :            : 
     983                 :            :         outb_p(0x00, vga_video_port_reg);       /* HorizontalTotal */
     984                 :            :         outb_p(vga_state.HorizontalTotal, vga_video_port_val);
     985                 :            :         outb_p(0x01, vga_video_port_reg);       /* HorizDisplayEnd */
     986                 :            :         outb_p(vga_state.HorizDisplayEnd, vga_video_port_val);
     987                 :            :         outb_p(0x04, vga_video_port_reg);       /* StartHorizRetrace */
     988                 :            :         outb_p(vga_state.StartHorizRetrace, vga_video_port_val);
     989                 :            :         outb_p(0x05, vga_video_port_reg);       /* EndHorizRetrace */
     990                 :            :         outb_p(vga_state.EndHorizRetrace, vga_video_port_val);
     991                 :            :         outb_p(0x07, vga_video_port_reg);       /* Overflow */
     992                 :            :         outb_p(vga_state.Overflow, vga_video_port_val);
     993                 :            :         outb_p(0x10, vga_video_port_reg);       /* StartVertRetrace */
     994                 :            :         outb_p(vga_state.StartVertRetrace, vga_video_port_val);
     995                 :            :         outb_p(0x11, vga_video_port_reg);       /* EndVertRetrace */
     996                 :            :         outb_p(vga_state.EndVertRetrace, vga_video_port_val);
     997                 :            :         outb_p(0x17, vga_video_port_reg);       /* ModeControl */
     998                 :            :         outb_p(vga_state.ModeControl, vga_video_port_val);
     999                 :            :         /* ClockingMode */
    1000                 :            :         vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode);
    1001                 :            : 
    1002                 :            :         /* restore index/control registers */
    1003                 :            :         vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
    1004                 :            :         outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
    1005                 :            :         raw_spin_unlock_irq(&vga_lock);
    1006                 :            : }
    1007                 :            : 
    1008                 :            : static void vga_pal_blank(struct vgastate *state)
    1009                 :            : {
    1010                 :            :         int i;
    1011                 :            : 
    1012                 :            :         vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
    1013                 :            :         for (i = 0; i < 16; i++) {
    1014                 :            :                 vga_w(state->vgabase, VGA_PEL_IW, i);
    1015                 :            :                 vga_w(state->vgabase, VGA_PEL_D, 0);
    1016                 :            :                 vga_w(state->vgabase, VGA_PEL_D, 0);
    1017                 :            :                 vga_w(state->vgabase, VGA_PEL_D, 0);
    1018                 :            :         }
    1019                 :            : }
    1020                 :            : 
    1021                 :          0 : static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
    1022                 :            : {
    1023      [ #  #  # ]:          0 :         switch (blank) {
    1024                 :          0 :         case 0:         /* Unblank */
    1025         [ #  # ]:          0 :                 if (vga_vesa_blanked) {
    1026                 :          0 :                         vga_vesa_unblank(&vgastate);
    1027                 :          0 :                         vga_vesa_blanked = 0;
    1028                 :            :                 }
    1029         [ #  # ]:          0 :                 if (vga_palette_blanked) {
    1030                 :          0 :                         vga_set_palette(c, color_table);
    1031                 :          0 :                         vga_palette_blanked = false;
    1032                 :          0 :                         return 0;
    1033                 :            :                 }
    1034                 :          0 :                 vga_is_gfx = false;
    1035                 :            :                 /* Tell console.c that it has to restore the screen itself */
    1036                 :          0 :                 return 1;
    1037                 :          0 :         case 1:         /* Normal blanking */
    1038                 :            :         case -1:        /* Obsolete */
    1039   [ #  #  #  # ]:          0 :                 if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
    1040                 :          0 :                         vga_pal_blank(&vgastate);
    1041                 :          0 :                         vga_palette_blanked = true;
    1042                 :          0 :                         return 0;
    1043                 :            :                 }
    1044                 :          0 :                 vgacon_set_origin(c);
    1045                 :          0 :                 scr_memsetw((void *) vga_vram_base, BLANK,
    1046                 :            :                             c->vc_screenbuf_size);
    1047         [ #  # ]:          0 :                 if (mode_switch)
    1048                 :          0 :                         vga_is_gfx = true;
    1049                 :            :                 return 1;
    1050                 :          0 :         default:                /* VESA blanking */
    1051         [ #  # ]:          0 :                 if (vga_video_type == VIDEO_TYPE_VGAC) {
    1052                 :          0 :                         vga_vesa_blank(&vgastate, blank - 1);
    1053                 :          0 :                         vga_vesa_blanked = blank;
    1054                 :            :                 }
    1055                 :            :                 return 0;
    1056                 :            :         }
    1057                 :            : }
    1058                 :            : 
    1059                 :            : /*
    1060                 :            :  * PIO_FONT support.
    1061                 :            :  *
    1062                 :            :  * The font loading code goes back to the codepage package by
    1063                 :            :  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
    1064                 :            :  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
    1065                 :            :  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
    1066                 :            :  *
    1067                 :            :  * Change for certain monochrome monitors by Yury Shevchuck
    1068                 :            :  * (sizif@botik.yaroslavl.su).
    1069                 :            :  */
    1070                 :            : 
    1071                 :            : #define colourmap 0xa0000
    1072                 :            : /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
    1073                 :            :    should use 0xA0000 for the bwmap as well.. */
    1074                 :            : #define blackwmap 0xa0000
    1075                 :            : #define cmapsz 8192
    1076                 :            : 
    1077                 :          0 : static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
    1078                 :            :                 bool ch512)
    1079                 :            : {
    1080                 :          0 :         unsigned short video_port_status = vga_video_port_reg + 6;
    1081                 :          0 :         int font_select = 0x00, beg, i;
    1082                 :          0 :         char *charmap;
    1083                 :          0 :         bool clear_attribs = false;
    1084         [ #  # ]:          0 :         if (vga_video_type != VIDEO_TYPE_EGAM) {
    1085                 :          0 :                 charmap = (char *) VGA_MAP_MEM(colourmap, 0);
    1086                 :          0 :                 beg = 0x0e;
    1087                 :            :         } else {
    1088                 :          0 :                 charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
    1089                 :          0 :                 beg = 0x0a;
    1090                 :            :         }
    1091                 :            : 
    1092                 :            : #ifdef BROKEN_GRAPHICS_PROGRAMS
    1093                 :            :         /*
    1094                 :            :          * All fonts are loaded in slot 0 (0:1 for 512 ch)
    1095                 :            :          */
    1096                 :            : 
    1097         [ #  # ]:          0 :         if (!arg)
    1098                 :            :                 return -EINVAL; /* Return to default font not supported */
    1099                 :            : 
    1100                 :          0 :         vga_font_is_default = false;
    1101         [ #  # ]:          0 :         font_select = ch512 ? 0x04 : 0x00;
    1102                 :            : #else
    1103                 :            :         /*
    1104                 :            :          * The default font is kept in slot 0 and is never touched.
    1105                 :            :          * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
    1106                 :            :          */
    1107                 :            : 
    1108                 :            :         if (set) {
    1109                 :            :                 vga_font_is_default = !arg;
    1110                 :            :                 if (!arg)
    1111                 :            :                         ch512 = false;  /* Default font is always 256 */
    1112                 :            :                 font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
    1113                 :            :         }
    1114                 :            : 
    1115                 :            :         if (!vga_font_is_default)
    1116                 :            :                 charmap += 4 * cmapsz;
    1117                 :            : #endif
    1118                 :            : 
    1119                 :          0 :         raw_spin_lock_irq(&vga_lock);
    1120                 :            :         /* First, the Sequencer */
    1121         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
    1122                 :            :         /* CPU writes only to map 2 */
    1123         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04); 
    1124                 :            :         /* Sequential addressing */
    1125         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07); 
    1126                 :            :         /* Clear synchronous reset */
    1127         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
    1128                 :            : 
    1129                 :            :         /* Now, the graphics controller, select map 2 */
    1130         [ #  # ]:          0 :         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);          
    1131                 :            :         /* disable odd-even addressing */
    1132         [ #  # ]:          0 :         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
    1133                 :            :         /* map start at A000:0000 */
    1134         [ #  # ]:          0 :         vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
    1135                 :          0 :         raw_spin_unlock_irq(&vga_lock);
    1136                 :            : 
    1137                 :          0 :         if (arg) {
    1138         [ #  # ]:          0 :                 if (set)
    1139         [ #  # ]:          0 :                         for (i = 0; i < cmapsz; i++) {
    1140                 :          0 :                                 vga_writeb(arg[i], charmap + i);
    1141                 :          0 :                                 cond_resched();
    1142                 :            :                         }
    1143                 :            :                 else
    1144         [ #  # ]:          0 :                         for (i = 0; i < cmapsz; i++) {
    1145                 :          0 :                                 arg[i] = vga_readb(charmap + i);
    1146                 :          0 :                                 cond_resched();
    1147                 :            :                         }
    1148                 :            : 
    1149                 :            :                 /*
    1150                 :            :                  * In 512-character mode, the character map is not contiguous if
    1151                 :            :                  * we want to remain EGA compatible -- which we do
    1152                 :            :                  */
    1153                 :            : 
    1154         [ #  # ]:          0 :                 if (ch512) {
    1155                 :          0 :                         charmap += 2 * cmapsz;
    1156                 :          0 :                         arg += cmapsz;
    1157         [ #  # ]:          0 :                         if (set)
    1158         [ #  # ]:          0 :                                 for (i = 0; i < cmapsz; i++) {
    1159                 :          0 :                                         vga_writeb(arg[i], charmap + i);
    1160                 :          0 :                                         cond_resched();
    1161                 :            :                                 }
    1162                 :            :                         else
    1163         [ #  # ]:          0 :                                 for (i = 0; i < cmapsz; i++) {
    1164                 :          0 :                                         arg[i] = vga_readb(charmap + i);
    1165                 :          0 :                                         cond_resched();
    1166                 :            :                                 }
    1167                 :            :                 }
    1168                 :            :         }
    1169                 :            : 
    1170                 :          0 :         raw_spin_lock_irq(&vga_lock);
    1171                 :            :         /* First, the sequencer, Synchronous reset */
    1172         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);       
    1173                 :            :         /* CPU writes to maps 0 and 1 */
    1174         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
    1175                 :            :         /* odd-even addressing */
    1176         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
    1177                 :            :         /* Character Map Select */
    1178         [ #  # ]:          0 :         if (set)
    1179         [ #  # ]:          0 :                 vga_wseq(state->vgabase, VGA_SEQ_CHARACTER_MAP, font_select);
    1180                 :            :         /* clear synchronous reset */
    1181         [ #  # ]:          0 :         vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
    1182                 :            : 
    1183                 :            :         /* Now, the graphics controller, select map 0 for CPU */
    1184         [ #  # ]:          0 :         vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x00);
    1185                 :            :         /* enable even-odd addressing */
    1186         [ #  # ]:          0 :         vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x10);
    1187                 :            :         /* map starts at b800:0 or b000:0 */
    1188         [ #  # ]:          0 :         vga_wgfx(state->vgabase, VGA_GFX_MISC, beg);
    1189                 :            : 
    1190                 :            :         /* if 512 char mode is already enabled don't re-enable it. */
    1191   [ #  #  #  # ]:          0 :         if ((set) && (ch512 != vga_512_chars)) {
    1192                 :          0 :                 vga_512_chars = ch512;
    1193                 :            :                 /* 256-char: enable intensity bit
    1194                 :            :                    512-char: disable intensity bit */
    1195                 :          0 :                 inb_p(video_port_status);       /* clear address flip-flop */
    1196                 :            :                 /* color plane enable register */
    1197   [ #  #  #  # ]:          0 :                 vga_wattr(state->vgabase, VGA_ATC_PLANE_ENABLE, ch512 ? 0x07 : 0x0f);
    1198                 :            :                 /* Wilton (1987) mentions the following; I don't know what
    1199                 :            :                    it means, but it works, and it appears necessary */
    1200                 :          0 :                 inb_p(video_port_status);
    1201         [ #  # ]:          0 :                 vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); 
    1202                 :            :                 clear_attribs = true;
    1203                 :            :         }
    1204                 :          0 :         raw_spin_unlock_irq(&vga_lock);
    1205                 :            : 
    1206         [ #  # ]:          0 :         if (clear_attribs) {
    1207         [ #  # ]:          0 :                 for (i = 0; i < MAX_NR_CONSOLES; i++) {
    1208                 :          0 :                         struct vc_data *c = vc_cons[i].d;
    1209   [ #  #  #  # ]:          0 :                         if (c && c->vc_sw == &vga_con) {
    1210                 :            :                                 /* force hi font mask to 0, so we always clear
    1211                 :            :                                    the bit on either transition */
    1212                 :          0 :                                 c->vc_hi_font_mask = 0x00;
    1213                 :          0 :                                 clear_buffer_attributes(c);
    1214         [ #  # ]:          0 :                                 c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
    1215                 :            :                         }
    1216                 :            :                 }
    1217                 :            :         }
    1218                 :            :         return 0;
    1219                 :            : }
    1220                 :            : 
    1221                 :            : /*
    1222                 :            :  * Adjust the screen to fit a font of a certain height
    1223                 :            :  */
    1224                 :            : static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
    1225                 :            : {
    1226                 :            :         unsigned char ovr, vde, fsr;
    1227                 :            :         int rows, maxscan, i;
    1228                 :            : 
    1229                 :            :         rows = vc->vc_scan_lines / fontheight;       /* Number of video rows we end up with */
    1230                 :            :         maxscan = rows * fontheight - 1;        /* Scan lines to actually display-1 */
    1231                 :            : 
    1232                 :            :         /* Reprogram the CRTC for the new font size
    1233                 :            :            Note: the attempt to read the overflow register will fail
    1234                 :            :            on an EGA, but using 0xff for the previous value appears to
    1235                 :            :            be OK for EGA text modes in the range 257-512 scan lines, so I
    1236                 :            :            guess we don't need to worry about it.
    1237                 :            : 
    1238                 :            :            The same applies for the spill bits in the font size and cursor
    1239                 :            :            registers; they are write-only on EGA, but it appears that they
    1240                 :            :            are all don't care bits on EGA, so I guess it doesn't matter. */
    1241                 :            : 
    1242                 :            :         raw_spin_lock_irq(&vga_lock);
    1243                 :            :         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
    1244                 :            :         ovr = inb_p(vga_video_port_val);
    1245                 :            :         outb_p(0x09, vga_video_port_reg);       /* Font size register */
    1246                 :            :         fsr = inb_p(vga_video_port_val);
    1247                 :            :         raw_spin_unlock_irq(&vga_lock);
    1248                 :            : 
    1249                 :            :         vde = maxscan & 0xff;       /* Vertical display end reg */
    1250                 :            :         ovr = (ovr & 0xbd) +        /* Overflow register */
    1251                 :            :             ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
    1252                 :            :         fsr = (fsr & 0xe0) + (fontheight - 1);      /*  Font size register */
    1253                 :            : 
    1254                 :            :         raw_spin_lock_irq(&vga_lock);
    1255                 :            :         outb_p(0x07, vga_video_port_reg);       /* CRTC overflow register */
    1256                 :            :         outb_p(ovr, vga_video_port_val);
    1257                 :            :         outb_p(0x09, vga_video_port_reg);       /* Font size */
    1258                 :            :         outb_p(fsr, vga_video_port_val);
    1259                 :            :         outb_p(0x12, vga_video_port_reg);       /* Vertical display limit */
    1260                 :            :         outb_p(vde, vga_video_port_val);
    1261                 :            :         raw_spin_unlock_irq(&vga_lock);
    1262                 :            :         vga_video_font_height = fontheight;
    1263                 :            : 
    1264                 :            :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
    1265                 :            :                 struct vc_data *c = vc_cons[i].d;
    1266                 :            : 
    1267                 :            :                 if (c && c->vc_sw == &vga_con) {
    1268                 :            :                         if (con_is_visible(c)) {
    1269                 :            :                                 /* void size to cause regs to be rewritten */
    1270                 :            :                                 cursor_size_lastfrom = 0;
    1271                 :            :                                 cursor_size_lastto = 0;
    1272                 :            :                                 c->vc_sw->con_cursor(c, CM_DRAW);
    1273                 :            :                         }
    1274                 :            :                         c->vc_font.height = fontheight;
    1275                 :            :                         vc_resize(c, 0, rows);  /* Adjust console size */
    1276                 :            :                 }
    1277                 :            :         }
    1278                 :            :         return 0;
    1279                 :            : }
    1280                 :            : 
    1281                 :          0 : static int vgacon_font_set(struct vc_data *c, struct console_font *font,
    1282                 :            :                            unsigned int flags)
    1283                 :            : {
    1284                 :          0 :         unsigned charcount = font->charcount;
    1285                 :          0 :         int rc;
    1286                 :            : 
    1287         [ #  # ]:          0 :         if (vga_video_type < VIDEO_TYPE_EGAM)
    1288                 :            :                 return -EINVAL;
    1289                 :            : 
    1290         [ #  # ]:          0 :         if (font->width != VGA_FONTWIDTH ||
    1291         [ #  # ]:          0 :             (charcount != 256 && charcount != 512))
    1292                 :            :                 return -EINVAL;
    1293                 :            : 
    1294                 :          0 :         rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
    1295         [ #  # ]:          0 :         if (rc)
    1296                 :            :                 return rc;
    1297                 :            : 
    1298         [ #  # ]:          0 :         if (!(flags & KD_FONT_FLAG_DONT_RECALC))
    1299                 :          0 :                 rc = vgacon_adjust_height(c, font->height);
    1300                 :            :         return rc;
    1301                 :            : }
    1302                 :            : 
    1303                 :          0 : static int vgacon_font_get(struct vc_data *c, struct console_font *font)
    1304                 :            : {
    1305         [ #  # ]:          0 :         if (vga_video_type < VIDEO_TYPE_EGAM)
    1306                 :            :                 return -EINVAL;
    1307                 :            : 
    1308                 :          0 :         font->width = VGA_FONTWIDTH;
    1309                 :          0 :         font->height = c->vc_font.height;
    1310         [ #  # ]:          0 :         font->charcount = vga_512_chars ? 512 : 256;
    1311         [ #  # ]:          0 :         if (!font->data)
    1312                 :            :                 return 0;
    1313                 :          0 :         return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
    1314                 :            : }
    1315                 :            : 
    1316                 :          0 : static int vgacon_resize(struct vc_data *c, unsigned int width,
    1317                 :            :                          unsigned int height, unsigned int user)
    1318                 :            : {
    1319         [ #  # ]:          0 :         if ((width << 1) * height > vga_vram_size)
    1320                 :            :                 return -EINVAL;
    1321                 :            : 
    1322   [ #  #  #  # ]:          0 :         if (width % 2 || width > screen_info.orig_video_cols ||
    1323                 :          0 :             height > (screen_info.orig_video_lines * vga_default_font_height)/
    1324         [ #  # ]:          0 :             c->vc_font.height)
    1325                 :            :                 /* let svgatextmode tinker with video timings and
    1326                 :            :                    return success */
    1327         [ #  # ]:          0 :                 return (user) ? 0 : -EINVAL;
    1328                 :            : 
    1329   [ #  #  #  # ]:          0 :         if (con_is_visible(c) && !vga_is_gfx) /* who knows */
    1330                 :          0 :                 vgacon_doresize(c, width, height);
    1331                 :            :         return 0;
    1332                 :            : }
    1333                 :            : 
    1334                 :         22 : static int vgacon_set_origin(struct vc_data *c)
    1335                 :            : {
    1336         [ +  - ]:         22 :         if (vga_is_gfx ||       /* We don't play origin tricks in graphic modes */
    1337   [ -  +  -  - ]:         22 :             (console_blanked && !vga_palette_blanked))  /* Nor we write to blanked screens */
    1338                 :            :                 return 0;
    1339                 :         22 :         c->vc_origin = c->vc_visible_origin = vga_vram_base;
    1340                 :         22 :         vga_set_mem_top(c);
    1341                 :         22 :         vga_rolled_over = 0;
    1342                 :         22 :         return 1;
    1343                 :            : }
    1344                 :            : 
    1345                 :         11 : static void vgacon_save_screen(struct vc_data *c)
    1346                 :            : {
    1347                 :         11 :         static int vga_bootup_console = 0;
    1348                 :            : 
    1349         [ +  - ]:         11 :         if (!vga_bootup_console) {
    1350                 :            :                 /* This is a gross hack, but here is the only place we can
    1351                 :            :                  * set bootup console parameters without messing up generic
    1352                 :            :                  * console initialization routines.
    1353                 :            :                  */
    1354                 :         11 :                 vga_bootup_console = 1;
    1355                 :         11 :                 c->vc_x = screen_info.orig_x;
    1356                 :         11 :                 c->vc_y = screen_info.orig_y;
    1357                 :            :         }
    1358                 :            : 
    1359                 :            :         /* We can't copy in more than the size of the video buffer,
    1360                 :            :          * or we'll be copying in VGA BIOS */
    1361                 :            : 
    1362         [ +  - ]:         11 :         if (!vga_is_gfx)
    1363                 :         11 :                 scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
    1364                 :         11 :                             c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
    1365                 :         11 : }
    1366                 :            : 
    1367                 :          0 : static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
    1368                 :            :                 enum con_scroll dir, unsigned int lines)
    1369                 :            : {
    1370                 :          0 :         unsigned long oldo;
    1371                 :          0 :         unsigned int delta;
    1372                 :            : 
    1373   [ #  #  #  #  :          0 :         if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT)
             #  #  #  # ]
    1374                 :            :                 return false;
    1375                 :            : 
    1376   [ #  #  #  # ]:          0 :         if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2)
    1377                 :            :                 return false;
    1378                 :            : 
    1379                 :          0 :         vgacon_restore_screen(c);
    1380                 :          0 :         oldo = c->vc_origin;
    1381                 :          0 :         delta = lines * c->vc_size_row;
    1382         [ #  # ]:          0 :         if (dir == SM_UP) {
    1383                 :          0 :                 vgacon_scrollback_update(c, t, lines);
    1384         [ #  # ]:          0 :                 if (c->vc_scr_end + delta >= vga_vram_end) {
    1385                 :          0 :                         scr_memcpyw((u16 *) vga_vram_base,
    1386                 :          0 :                                     (u16 *) (oldo + delta),
    1387                 :          0 :                                     c->vc_screenbuf_size - delta);
    1388                 :          0 :                         c->vc_origin = vga_vram_base;
    1389                 :          0 :                         vga_rolled_over = oldo - vga_vram_base;
    1390                 :            :                 } else
    1391                 :          0 :                         c->vc_origin += delta;
    1392                 :          0 :                 scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
    1393                 :          0 :                                      delta), c->vc_video_erase_char,
    1394                 :            :                             delta);
    1395                 :            :         } else {
    1396         [ #  # ]:          0 :                 if (oldo - delta < vga_vram_base) {
    1397                 :          0 :                         scr_memmovew((u16 *) (vga_vram_end -
    1398                 :          0 :                                               c->vc_screenbuf_size +
    1399                 :            :                                               delta), (u16 *) oldo,
    1400                 :          0 :                                      c->vc_screenbuf_size - delta);
    1401                 :          0 :                         c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
    1402                 :          0 :                         vga_rolled_over = 0;
    1403                 :            :                 } else
    1404                 :          0 :                         c->vc_origin -= delta;
    1405                 :          0 :                 c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
    1406                 :          0 :                 scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
    1407                 :            :                             delta);
    1408                 :            :         }
    1409                 :          0 :         c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
    1410                 :          0 :         c->vc_visible_origin = c->vc_origin;
    1411                 :          0 :         vga_set_mem_top(c);
    1412                 :          0 :         c->vc_pos = (c->vc_pos - oldo) + c->vc_origin;
    1413                 :          0 :         return true;
    1414                 :            : }
    1415                 :            : 
    1416                 :            : /*
    1417                 :            :  *  The console `switch' structure for the VGA based console
    1418                 :            :  */
    1419                 :            : 
    1420                 :          0 : static void vgacon_clear(struct vc_data *vc, int sy, int sx, int height,
    1421                 :          0 :                          int width) { }
    1422                 :          0 : static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
    1423                 :        121 : static void vgacon_putcs(struct vc_data *vc, const unsigned short *s,
    1424                 :        121 :                          int count, int ypos, int xpos) { }
    1425                 :            : 
    1426                 :            : const struct consw vga_con = {
    1427                 :            :         .owner = THIS_MODULE,
    1428                 :            :         .con_startup = vgacon_startup,
    1429                 :            :         .con_init = vgacon_init,
    1430                 :            :         .con_deinit = vgacon_deinit,
    1431                 :            :         .con_clear = vgacon_clear,
    1432                 :            :         .con_putc = vgacon_putc,
    1433                 :            :         .con_putcs = vgacon_putcs,
    1434                 :            :         .con_cursor = vgacon_cursor,
    1435                 :            :         .con_scroll = vgacon_scroll,
    1436                 :            :         .con_switch = vgacon_switch,
    1437                 :            :         .con_blank = vgacon_blank,
    1438                 :            :         .con_font_set = vgacon_font_set,
    1439                 :            :         .con_font_get = vgacon_font_get,
    1440                 :            :         .con_resize = vgacon_resize,
    1441                 :            :         .con_set_palette = vgacon_set_palette,
    1442                 :            :         .con_scrolldelta = vgacon_scrolldelta,
    1443                 :            :         .con_set_origin = vgacon_set_origin,
    1444                 :            :         .con_save_screen = vgacon_save_screen,
    1445                 :            :         .con_build_attr = vgacon_build_attr,
    1446                 :            :         .con_invert_region = vgacon_invert_region,
    1447                 :            :         .con_flush_scrollback = vgacon_flush_scrollback,
    1448                 :            : };
    1449                 :            : EXPORT_SYMBOL(vga_con);
    1450                 :            : 
    1451                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14