Subversion Repositories HelenOS

Rev

Rev 4346 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2001-2004 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup genarch_drivers
  30.  * @{
  31.  */
  32. /**
  33.  * @file
  34.  * @brief EGA driver.
  35.  */
  36.  
  37. #include <genarch/drivers/ega/ega.h>
  38. #include <putchar.h>
  39. #include <mm/page.h>
  40. #include <mm/as.h>
  41. #include <mm/slab.h>
  42. #include <arch/mm/page.h>
  43. #include <synch/spinlock.h>
  44. #include <arch/types.h>
  45. #include <arch/asm.h>
  46. #include <memstr.h>
  47. #include <console/chardev.h>
  48. #include <console/console.h>
  49. #include <sysinfo/sysinfo.h>
  50. #include <ddi/ddi.h>
  51.  
  52. /*
  53.  * The EGA driver.
  54.  * Simple and short. Function for displaying characters and "scrolling".
  55.  */
  56.  
  57. SPINLOCK_INITIALIZE(egalock);
  58. static uint32_t ega_cursor;
  59. static uint8_t *videoram;
  60. static uint8_t *backbuf;
  61. static ioport8_t *ega_base;
  62.  
  63. #define SPACE  0x20
  64. #define STYLE  0x1e
  65. #define INVAL  0x17
  66.  
  67. #define EMPTY_CHAR  ((STYLE << 8) | SPACE)
  68.  
  69. static uint16_t ega_oem_glyph(const wchar_t ch)
  70. {
  71.     if ((ch >= 0x0000) && (ch <= 0x007f))
  72.         return ch;
  73.    
  74.     if (ch == 0x00a0)
  75.         return 255;
  76.    
  77.     if (ch == 0x00a1)
  78.         return 173;
  79.    
  80.     if ((ch >= 0x00a2) && (ch <= 0x00a3))
  81.         return (ch - 7);
  82.    
  83.     if (ch == 0x00a5)
  84.         return 157;
  85.    
  86.     if (ch == 0x00aa)
  87.         return 166;
  88.    
  89.     if (ch == 0x00ab)
  90.         return 174;
  91.    
  92.     if (ch == 0x00ac)
  93.         return 170;
  94.    
  95.     if (ch == 0x00b0)
  96.         return 248;
  97.    
  98.     if (ch == 0x00b1)
  99.         return 241;
  100.    
  101.     if (ch == 0x00b2)
  102.         return 253;
  103.    
  104.     if (ch == 0x00b5)
  105.         return 230;
  106.    
  107.     if (ch == 0x00b7)
  108.         return 250;
  109.    
  110.     if (ch == 0x00ba)
  111.         return 167;
  112.    
  113.     if (ch == 0x00bb)
  114.         return 175;
  115.    
  116.     if (ch == 0x00bc)
  117.         return 172;
  118.    
  119.     if (ch == 0x00bd)
  120.         return 171;
  121.    
  122.     if (ch == 0x00bf)
  123.         return 168;
  124.    
  125.     if ((ch >= 0x00c4) && (ch <= 0x00c5))
  126.         return (ch - 54);
  127.    
  128.     if (ch == 0x00c6)
  129.         return 146;
  130.    
  131.     if (ch == 0x00c7)
  132.         return 128;
  133.    
  134.     if (ch == 0x00c9)
  135.         return 144;
  136.    
  137.     if (ch == 0x00d1)
  138.         return 165;
  139.    
  140.     if (ch == 0x00d6)
  141.         return 153;
  142.    
  143.     if (ch == 0x00dc)
  144.         return 154;
  145.    
  146.     if (ch == 0x00df)
  147.         return 225;
  148.    
  149.     if (ch == 0x00e0)
  150.         return 133;
  151.    
  152.     if (ch == 0x00e1)
  153.         return 160;
  154.    
  155.     if (ch == 0x00e2)
  156.         return 131;
  157.    
  158.     if (ch == 0x00e4)
  159.         return 132;
  160.    
  161.     if (ch == 0x00e5)
  162.         return 134;
  163.    
  164.     if (ch == 0x00e6)
  165.         return 145;
  166.    
  167.     if (ch == 0x00e7)
  168.         return 135;
  169.    
  170.     if (ch == 0x00e8)
  171.         return 138;
  172.    
  173.     if (ch == 0x00e9)
  174.         return 130;
  175.    
  176.     if ((ch >= 0x00ea) && (ch <= 0x00eb))
  177.         return (ch - 98);
  178.    
  179.     if (ch == 0x00ec)
  180.         return 141;
  181.    
  182.     if (ch == 0x00ed)
  183.         return 161;
  184.    
  185.     if (ch == 0x00ee)
  186.         return 140;
  187.    
  188.     if (ch == 0x00ef)
  189.         return 139;
  190.    
  191.     if (ch == 0x00f1)
  192.         return 164;
  193.    
  194.     if (ch == 0x00f2)
  195.         return 149;
  196.    
  197.     if (ch == 0x00f3)
  198.         return 162;
  199.    
  200.     if (ch == 0x00f4)
  201.         return 147;
  202.    
  203.     if (ch == 0x00f6)
  204.         return 148;
  205.    
  206.     if (ch == 0x00f7)
  207.         return 246;
  208.    
  209.     if (ch == 0x00f9)
  210.         return 151;
  211.    
  212.     if (ch == 0x00fa)
  213.         return 163;
  214.    
  215.     if (ch == 0x00fb)
  216.         return 150;
  217.    
  218.     if (ch == 0x00fc)
  219.         return 129;
  220.    
  221.     if (ch == 0x00ff)
  222.         return 152;
  223.    
  224.     if (ch == 0x0192)
  225.         return 159;
  226.    
  227.     if (ch == 0x0393)
  228.         return 226;
  229.    
  230.     if (ch == 0x0398)
  231.         return 233;
  232.    
  233.     if (ch == 0x03a3)
  234.         return 228;
  235.    
  236.     if (ch == 0x03a6)
  237.         return 232;
  238.    
  239.     if (ch == 0x03a9)
  240.         return 234;
  241.    
  242.     if (ch == 0x03b1)
  243.         return 224;
  244.    
  245.     if (ch == 0x03b4)
  246.         return 235;
  247.    
  248.     if (ch == 0x03b5)
  249.         return 238;
  250.    
  251.     if (ch == 0x03c0)
  252.         return 227;
  253.    
  254.     if (ch == 0x03c3)
  255.         return 229;
  256.    
  257.     if (ch == 0x03c4)
  258.         return 231;
  259.    
  260.     if (ch == 0x03c6)
  261.         return 237;
  262.    
  263.     if (ch == 0x207f)
  264.         return 252;
  265.    
  266.     if (ch == 0x20a7)
  267.         return 158;
  268.    
  269.     if (ch == 0x2219)
  270.         return 249;
  271.    
  272.     if (ch == 0x221a)
  273.         return 251;
  274.    
  275.     if (ch == 0x221e)
  276.         return 236;
  277.    
  278.     if (ch == 0x2229)
  279.         return 239;
  280.    
  281.     if (ch == 0x2248)
  282.         return 247;
  283.    
  284.     if (ch == 0x2261)
  285.         return 240;
  286.    
  287.     if (ch == 0x2264)
  288.         return 243;
  289.    
  290.     if (ch == 0x2265)
  291.         return 242;
  292.    
  293.     if (ch == 0x2310)
  294.         return 169;
  295.    
  296.     if ((ch >= 0x2320) && (ch <= 0x2321))
  297.         return (ch - 8748);
  298.    
  299.     if (ch == 0x2500)
  300.         return 196;
  301.    
  302.     if (ch == 0x2502)
  303.         return 179;
  304.    
  305.     if (ch == 0x250c)
  306.         return 218;
  307.    
  308.     if (ch == 0x2510)
  309.         return 191;
  310.    
  311.     if (ch == 0x2514)
  312.         return 192;
  313.    
  314.     if (ch == 0x2518)
  315.         return 217;
  316.    
  317.     if (ch == 0x251c)
  318.         return 195;
  319.    
  320.     if (ch == 0x2524)
  321.         return 180;
  322.    
  323.     if (ch == 0x252c)
  324.         return 194;
  325.    
  326.     if (ch == 0x2534)
  327.         return 193;
  328.    
  329.     if (ch == 0x253c)
  330.         return 197;
  331.    
  332.     if (ch == 0x2550)
  333.         return 205;
  334.    
  335.     if (ch == 0x2551)
  336.         return 186;
  337.    
  338.     if ((ch >= 0x2552) && (ch <= 0x2553))
  339.         return (ch - 9341);
  340.    
  341.     if (ch == 0x2554)
  342.         return 201;
  343.    
  344.     if (ch == 0x2555)
  345.         return 184;
  346.    
  347.     if (ch == 0x2556)
  348.         return 183;
  349.    
  350.     if (ch == 0x2557)
  351.         return 187;
  352.    
  353.     if (ch == 0x2558)
  354.         return 212;
  355.    
  356.     if (ch == 0x2559)
  357.         return 211;
  358.    
  359.     if (ch == 0x255a)
  360.         return 200;
  361.    
  362.     if (ch == 0x255b)
  363.         return 190;
  364.    
  365.     if (ch == 0x255c)
  366.         return 189;
  367.    
  368.     if (ch == 0x255d)
  369.         return 188;
  370.    
  371.     if ((ch >= 0x255e) && (ch <= 0x255f))
  372.         return (ch - 9368);
  373.    
  374.     if (ch == 0x2560)
  375.         return 204;
  376.    
  377.     if ((ch >= 0x2561) && (ch <= 0x2562))
  378.         return (ch - 9388);
  379.    
  380.     if (ch == 0x2563)
  381.         return 185;
  382.    
  383.     if ((ch >= 0x2564) && (ch <= 0x2565))
  384.         return (ch - 9363);
  385.    
  386.     if (ch == 0x2566)
  387.         return 203;
  388.    
  389.     if ((ch >= 0x2567) && (ch <= 0x2568))
  390.         return (ch - 9368);
  391.    
  392.     if (ch == 0x2569)
  393.         return 202;
  394.    
  395.     if (ch == 0x256a)
  396.         return 216;
  397.    
  398.     if (ch == 0x256b)
  399.         return 215;
  400.    
  401.     if (ch == 0x256c)
  402.         return 206;
  403.    
  404.     if (ch == 0x2580)
  405.         return 223;
  406.    
  407.     if (ch == 0x2584)
  408.         return 220;
  409.    
  410.     if (ch == 0x2588)
  411.         return 219;
  412.    
  413.     if (ch == 0x258c)
  414.         return 221;
  415.    
  416.     if (ch == 0x2590)
  417.         return 222;
  418.    
  419.     if ((ch >= 0x2591) && (ch <= 0x2593))
  420.         return (ch - 9441);
  421.    
  422.     return 256;
  423. }
  424.  
  425. /*
  426.  * This function takes care of scrolling.
  427.  */
  428. static void ega_check_cursor(void)
  429. {
  430.     if (ega_cursor < EGA_SCREEN)
  431.         return;
  432.    
  433.     memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
  434.         (EGA_SCREEN - EGA_COLS) * 2);
  435.     memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
  436.         (EGA_SCREEN - EGA_COLS) * 2);
  437.     memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
  438.     memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
  439.     ega_cursor = ega_cursor - EGA_COLS;
  440. }
  441.  
  442. static void ega_show_cursor(void)
  443. {
  444.     pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
  445.     uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
  446.     pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
  447.     pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
  448. }
  449.  
  450. static void ega_move_cursor(void)
  451. {
  452.     pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
  453.     pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
  454.     pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
  455.     pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
  456. }
  457.  
  458. static void ega_sync_cursor(void)
  459. {
  460.     pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
  461.     uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
  462.     pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
  463.     uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
  464.    
  465.     ega_cursor = (hi << 8) | lo;
  466.    
  467.     if (ega_cursor >= EGA_SCREEN)
  468.         ega_cursor = 0;
  469.    
  470.     if ((ega_cursor % EGA_COLS) != 0)
  471.         ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
  472.    
  473.     memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
  474.     memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
  475.    
  476.     ega_check_cursor();
  477.     ega_move_cursor();
  478.     ega_show_cursor();
  479. }
  480.  
  481. static void ega_display_char(wchar_t ch, bool silent)
  482. {
  483.     uint16_t index = ega_oem_glyph(ch);
  484.     uint8_t glyph;
  485.     uint8_t style;
  486.    
  487.     if ((index >> 8)) {
  488.         glyph = '?';
  489.         style = INVAL;
  490.     } else {
  491.         glyph = index & 0xff;
  492.         style = STYLE;
  493.     }
  494.    
  495.     backbuf[ega_cursor * 2] = glyph;
  496.     backbuf[ega_cursor * 2 + 1] = style;
  497.    
  498.     if (!silent) {
  499.         videoram[ega_cursor * 2] = glyph;
  500.         videoram[ega_cursor * 2 + 1] = style;
  501.     }
  502. }
  503.  
  504. static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
  505. {
  506.     ipl_t ipl;
  507.    
  508.     ipl = interrupts_disable();
  509.     spinlock_lock(&egalock);
  510.    
  511.     switch (ch) {
  512.     case '\n':
  513.         ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
  514.         break;
  515.     case '\t':
  516.         ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
  517.         break;
  518.     case '\b':
  519.         if (ega_cursor % EGA_COLS)
  520.             ega_cursor--;
  521.         break;
  522.     default:
  523.         ega_display_char(ch, silent);
  524.         ega_cursor++;
  525.         break;
  526.     }
  527.     ega_check_cursor();
  528.    
  529.     if (!silent)
  530.         ega_move_cursor();
  531.    
  532.     spinlock_unlock(&egalock);
  533.     interrupts_restore(ipl);
  534. }
  535.  
  536. static outdev_t ega_console;
  537. static outdev_operations_t ega_ops = {
  538.     .write = ega_putchar
  539. };
  540.  
  541. void ega_init(ioport8_t *base, uintptr_t videoram_phys)
  542. {
  543.     /* Initialize the software structure. */
  544.     ega_base = base;
  545.    
  546.     backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
  547.     if (!backbuf)
  548.         panic("Unable to allocate backbuffer.");
  549.    
  550.     videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
  551.    
  552.     /* Synchronize the back buffer and cursor position. */
  553.     memcpy(backbuf, videoram, EGA_VRAM_SIZE);
  554.     ega_sync_cursor();
  555.    
  556.     outdev_initialize("ega", &ega_console, &ega_ops);
  557.     stdout = &ega_console;
  558.    
  559.     sysinfo_set_item_val("fb", NULL, true);
  560.     sysinfo_set_item_val("fb.kind", NULL, 2);
  561.     sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
  562.     sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
  563.     sysinfo_set_item_val("fb.blinking", NULL, true);
  564.     sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
  565. }
  566.  
  567. void ega_redraw(void)
  568. {
  569.     memcpy(videoram, backbuf, EGA_VRAM_SIZE);
  570.     ega_move_cursor();
  571.     ega_show_cursor();
  572. }
  573.  
  574. /** @}
  575.  */
  576.