Subversion Repositories HelenOS

Rev

Rev 4347 | 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 <string.h>
  48. #include <console/chardev.h>
  49. #include <console/console.h>
  50. #include <sysinfo/sysinfo.h>
  51. #include <ddi/ddi.h>
  52.  
  53. /*
  54.  * The EGA driver.
  55.  * Simple and short. Function for displaying characters and "scrolling".
  56.  */
  57.  
  58. SPINLOCK_INITIALIZE(egalock);
  59. static uint32_t ega_cursor;
  60. static uint8_t *videoram;
  61. static uint8_t *backbuf;
  62. static ioport8_t *ega_base;
  63.  
  64. #define SPACE  0x20
  65. #define STYLE  0x1e
  66. #define INVAL  0x17
  67.  
  68. #define EMPTY_CHAR  ((STYLE << 8) | SPACE)
  69.  
  70. static uint16_t ega_oem_glyph(const wchar_t ch)
  71. {
  72.     if ((ch >= 0x0000) && (ch <= 0x007f))
  73.         return ch;
  74.    
  75.     if (ch == 0x00a0)
  76.         return 255;
  77.    
  78.     if (ch == 0x00a1)
  79.         return 173;
  80.    
  81.     if ((ch >= 0x00a2) && (ch <= 0x00a3))
  82.         return (ch - 7);
  83.    
  84.     if (ch == 0x00a5)
  85.         return 157;
  86.    
  87.     if (ch == 0x00aa)
  88.         return 166;
  89.    
  90.     if (ch == 0x00ab)
  91.         return 174;
  92.    
  93.     if (ch == 0x00ac)
  94.         return 170;
  95.    
  96.     if (ch == 0x00b0)
  97.         return 248;
  98.    
  99.     if (ch == 0x00b1)
  100.         return 241;
  101.    
  102.     if (ch == 0x00b2)
  103.         return 253;
  104.    
  105.     if (ch == 0x00b5)
  106.         return 230;
  107.    
  108.     if (ch == 0x00b7)
  109.         return 250;
  110.    
  111.     if (ch == 0x00ba)
  112.         return 167;
  113.    
  114.     if (ch == 0x00bb)
  115.         return 175;
  116.    
  117.     if (ch == 0x00bc)
  118.         return 172;
  119.    
  120.     if (ch == 0x00bd)
  121.         return 171;
  122.    
  123.     if (ch == 0x00bf)
  124.         return 168;
  125.    
  126.     if ((ch >= 0x00c4) && (ch <= 0x00c5))
  127.         return (ch - 54);
  128.    
  129.     if (ch == 0x00c6)
  130.         return 146;
  131.    
  132.     if (ch == 0x00c7)
  133.         return 128;
  134.    
  135.     if (ch == 0x00c9)
  136.         return 144;
  137.    
  138.     if (ch == 0x00d1)
  139.         return 165;
  140.    
  141.     if (ch == 0x00d6)
  142.         return 153;
  143.    
  144.     if (ch == 0x00dc)
  145.         return 154;
  146.    
  147.     if (ch == 0x00df)
  148.         return 225;
  149.    
  150.     if (ch == 0x00e0)
  151.         return 133;
  152.    
  153.     if (ch == 0x00e1)
  154.         return 160;
  155.    
  156.     if (ch == 0x00e2)
  157.         return 131;
  158.    
  159.     if (ch == 0x00e4)
  160.         return 132;
  161.    
  162.     if (ch == 0x00e5)
  163.         return 134;
  164.    
  165.     if (ch == 0x00e6)
  166.         return 145;
  167.    
  168.     if (ch == 0x00e7)
  169.         return 135;
  170.    
  171.     if (ch == 0x00e8)
  172.         return 138;
  173.    
  174.     if (ch == 0x00e9)
  175.         return 130;
  176.    
  177.     if ((ch >= 0x00ea) && (ch <= 0x00eb))
  178.         return (ch - 98);
  179.    
  180.     if (ch == 0x00ec)
  181.         return 141;
  182.    
  183.     if (ch == 0x00ed)
  184.         return 161;
  185.    
  186.     if (ch == 0x00ee)
  187.         return 140;
  188.    
  189.     if (ch == 0x00ef)
  190.         return 139;
  191.    
  192.     if (ch == 0x00f1)
  193.         return 164;
  194.    
  195.     if (ch == 0x00f2)
  196.         return 149;
  197.    
  198.     if (ch == 0x00f3)
  199.         return 162;
  200.    
  201.     if (ch == 0x00f4)
  202.         return 147;
  203.    
  204.     if (ch == 0x00f6)
  205.         return 148;
  206.    
  207.     if (ch == 0x00f7)
  208.         return 246;
  209.    
  210.     if (ch == 0x00f9)
  211.         return 151;
  212.    
  213.     if (ch == 0x00fa)
  214.         return 163;
  215.    
  216.     if (ch == 0x00fb)
  217.         return 150;
  218.    
  219.     if (ch == 0x00fc)
  220.         return 129;
  221.    
  222.     if (ch == 0x00ff)
  223.         return 152;
  224.    
  225.     if (ch == 0x0192)
  226.         return 159;
  227.    
  228.     if (ch == 0x0393)
  229.         return 226;
  230.    
  231.     if (ch == 0x0398)
  232.         return 233;
  233.    
  234.     if (ch == 0x03a3)
  235.         return 228;
  236.    
  237.     if (ch == 0x03a6)
  238.         return 232;
  239.    
  240.     if (ch == 0x03a9)
  241.         return 234;
  242.    
  243.     if (ch == 0x03b1)
  244.         return 224;
  245.    
  246.     if (ch == 0x03b4)
  247.         return 235;
  248.    
  249.     if (ch == 0x03b5)
  250.         return 238;
  251.    
  252.     if (ch == 0x03c0)
  253.         return 227;
  254.    
  255.     if (ch == 0x03c3)
  256.         return 229;
  257.    
  258.     if (ch == 0x03c4)
  259.         return 231;
  260.    
  261.     if (ch == 0x03c6)
  262.         return 237;
  263.    
  264.     if (ch == 0x207f)
  265.         return 252;
  266.    
  267.     if (ch == 0x20a7)
  268.         return 158;
  269.    
  270.     if (ch == 0x2219)
  271.         return 249;
  272.    
  273.     if (ch == 0x221a)
  274.         return 251;
  275.    
  276.     if (ch == 0x221e)
  277.         return 236;
  278.    
  279.     if (ch == 0x2229)
  280.         return 239;
  281.    
  282.     if (ch == 0x2248)
  283.         return 247;
  284.    
  285.     if (ch == 0x2261)
  286.         return 240;
  287.    
  288.     if (ch == 0x2264)
  289.         return 243;
  290.    
  291.     if (ch == 0x2265)
  292.         return 242;
  293.    
  294.     if (ch == 0x2310)
  295.         return 169;
  296.    
  297.     if ((ch >= 0x2320) && (ch <= 0x2321))
  298.         return (ch - 8748);
  299.    
  300.     if (ch == 0x2500)
  301.         return 196;
  302.    
  303.     if (ch == 0x2502)
  304.         return 179;
  305.    
  306.     if (ch == 0x250c)
  307.         return 218;
  308.    
  309.     if (ch == 0x2510)
  310.         return 191;
  311.    
  312.     if (ch == 0x2514)
  313.         return 192;
  314.    
  315.     if (ch == 0x2518)
  316.         return 217;
  317.    
  318.     if (ch == 0x251c)
  319.         return 195;
  320.    
  321.     if (ch == 0x2524)
  322.         return 180;
  323.    
  324.     if (ch == 0x252c)
  325.         return 194;
  326.    
  327.     if (ch == 0x2534)
  328.         return 193;
  329.    
  330.     if (ch == 0x253c)
  331.         return 197;
  332.    
  333.     if (ch == 0x2550)
  334.         return 205;
  335.    
  336.     if (ch == 0x2551)
  337.         return 186;
  338.    
  339.     if ((ch >= 0x2552) && (ch <= 0x2553))
  340.         return (ch - 9341);
  341.    
  342.     if (ch == 0x2554)
  343.         return 201;
  344.    
  345.     if (ch == 0x2555)
  346.         return 184;
  347.    
  348.     if (ch == 0x2556)
  349.         return 183;
  350.    
  351.     if (ch == 0x2557)
  352.         return 187;
  353.    
  354.     if (ch == 0x2558)
  355.         return 212;
  356.    
  357.     if (ch == 0x2559)
  358.         return 211;
  359.    
  360.     if (ch == 0x255a)
  361.         return 200;
  362.    
  363.     if (ch == 0x255b)
  364.         return 190;
  365.    
  366.     if (ch == 0x255c)
  367.         return 189;
  368.    
  369.     if (ch == 0x255d)
  370.         return 188;
  371.    
  372.     if ((ch >= 0x255e) && (ch <= 0x255f))
  373.         return (ch - 9368);
  374.    
  375.     if (ch == 0x2560)
  376.         return 204;
  377.    
  378.     if ((ch >= 0x2561) && (ch <= 0x2562))
  379.         return (ch - 9388);
  380.    
  381.     if (ch == 0x2563)
  382.         return 185;
  383.    
  384.     if ((ch >= 0x2564) && (ch <= 0x2565))
  385.         return (ch - 9363);
  386.    
  387.     if (ch == 0x2566)
  388.         return 203;
  389.    
  390.     if ((ch >= 0x2567) && (ch <= 0x2568))
  391.         return (ch - 9368);
  392.    
  393.     if (ch == 0x2569)
  394.         return 202;
  395.    
  396.     if (ch == 0x256a)
  397.         return 216;
  398.    
  399.     if (ch == 0x256b)
  400.         return 215;
  401.    
  402.     if (ch == 0x256c)
  403.         return 206;
  404.    
  405.     if (ch == 0x2580)
  406.         return 223;
  407.    
  408.     if (ch == 0x2584)
  409.         return 220;
  410.    
  411.     if (ch == 0x2588)
  412.         return 219;
  413.    
  414.     if (ch == 0x258c)
  415.         return 221;
  416.    
  417.     if (ch == 0x2590)
  418.         return 222;
  419.    
  420.     if ((ch >= 0x2591) && (ch <= 0x2593))
  421.         return (ch - 9441);
  422.    
  423.     return 256;
  424. }
  425.  
  426. /*
  427.  * This function takes care of scrolling.
  428.  */
  429. static void ega_check_cursor(bool silent)
  430. {
  431.     if (ega_cursor < EGA_SCREEN)
  432.         return;
  433.    
  434.     memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
  435.         (EGA_SCREEN - EGA_COLS) * 2);
  436.     memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
  437.    
  438.     if (!silent) {
  439.         memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
  440.             (EGA_SCREEN - EGA_COLS) * 2);
  441.         memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
  442.     }
  443.    
  444.     ega_cursor = ega_cursor - EGA_COLS;
  445. }
  446.  
  447. static void ega_show_cursor(bool silent)
  448. {
  449.     if (!silent) {
  450.         pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
  451.         uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
  452.         pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
  453.         pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
  454.     }
  455. }
  456.  
  457. static void ega_move_cursor(bool silent)
  458. {
  459.     if (!silent) {
  460.         pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
  461.         pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
  462.         pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
  463.         pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
  464.     }
  465. }
  466.  
  467. static void ega_sync_cursor(bool silent)
  468. {
  469.     if (!silent) {
  470.         pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
  471.         uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
  472.         pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
  473.         uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
  474.        
  475.         ega_cursor = (hi << 8) | lo;
  476.     } else
  477.         ega_cursor = 0;
  478.    
  479.     if (ega_cursor >= EGA_SCREEN)
  480.         ega_cursor = 0;
  481.    
  482.     if ((ega_cursor % EGA_COLS) != 0)
  483.         ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
  484.    
  485.     memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
  486.    
  487.     if (!silent)
  488.         memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
  489.    
  490.     ega_check_cursor(silent);
  491.     ega_move_cursor(silent);
  492.     ega_show_cursor(silent);
  493. }
  494.  
  495. static void ega_display_char(wchar_t ch, bool silent)
  496. {
  497.     uint16_t index = ega_oem_glyph(ch);
  498.     uint8_t glyph;
  499.     uint8_t style;
  500.    
  501.     if ((index >> 8)) {
  502.         glyph = U_SPECIAL;
  503.         style = INVAL;
  504.     } else {
  505.         glyph = index & 0xff;
  506.         style = STYLE;
  507.     }
  508.    
  509.     backbuf[ega_cursor * 2] = glyph;
  510.     backbuf[ega_cursor * 2 + 1] = style;
  511.    
  512.     if (!silent) {
  513.         videoram[ega_cursor * 2] = glyph;
  514.         videoram[ega_cursor * 2 + 1] = style;
  515.     }
  516. }
  517.  
  518. static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
  519. {
  520.     ipl_t ipl;
  521.    
  522.     ipl = interrupts_disable();
  523.     spinlock_lock(&egalock);
  524.    
  525.     switch (ch) {
  526.     case '\n':
  527.         ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
  528.         break;
  529.     case '\t':
  530.         ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
  531.         break;
  532.     case '\b':
  533.         if (ega_cursor % EGA_COLS)
  534.             ega_cursor--;
  535.         break;
  536.     default:
  537.         ega_display_char(ch, silent);
  538.         ega_cursor++;
  539.         break;
  540.     }
  541.     ega_check_cursor(silent);
  542.     ega_move_cursor(silent);
  543.    
  544.     spinlock_unlock(&egalock);
  545.     interrupts_restore(ipl);
  546. }
  547.  
  548. static outdev_t ega_console;
  549. static outdev_operations_t ega_ops = {
  550.     .write = ega_putchar
  551. };
  552.  
  553. void ega_init(ioport8_t *base, uintptr_t videoram_phys)
  554. {
  555.     /* Initialize the software structure. */
  556.     ega_base = base;
  557.    
  558.     backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
  559.     if (!backbuf)
  560.         panic("Unable to allocate backbuffer.");
  561.    
  562.     videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
  563.    
  564.     /* Synchronize the back buffer and cursor position. */
  565.     memcpy(backbuf, videoram, EGA_VRAM_SIZE);
  566.     ega_sync_cursor(silent);
  567.    
  568.     outdev_initialize("ega", &ega_console, &ega_ops);
  569.     stdout = &ega_console;
  570.    
  571.     sysinfo_set_item_val("fb", NULL, true);
  572.     sysinfo_set_item_val("fb.kind", NULL, 2);
  573.     sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
  574.     sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
  575.     sysinfo_set_item_val("fb.blinking", NULL, true);
  576.     sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
  577. }
  578.  
  579. void ega_redraw(void)
  580. {
  581.     memcpy(videoram, backbuf, EGA_VRAM_SIZE);
  582.     ega_move_cursor(silent);
  583.     ega_show_cursor(silent);
  584. }
  585.  
  586. /** @}
  587.  */
  588.