root/kern/dev/lamebus/lscreen.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. splitxy
  2. mergexy
  3. lscreen_irq
  4. lscreen_newline
  5. lscreen_char
  6. lscreen_write
  7. config_lscreen

   1 /*
   2  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
   3  *      The President and Fellows of Harvard College.
   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  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the University nor the names of its contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * Driver for full-screen console.
  32  *
  33  * As of this writing the full-screen console is not supported in
  34  * System/161, so this driver is untested and probably broken.
  35  */
  36 #include <types.h>
  37 #include <lib.h>
  38 #include <spinlock.h>
  39 #include <platform/bus.h>
  40 #include <lamebus/lscreen.h>
  41 #include "autoconf.h"
  42 
  43 /* Registers (offsets within slot) */
  44 #define LSCR_REG_POSN    0   /* Cursor position */
  45 #define LSCR_REG_SIZE    4   /* Display size */
  46 #define LSCR_REG_CHAR    8   /* Character in */
  47 #define LSCR_REG_RIRQ    12  /* Read interrupt status */
  48 
  49 /* Bits in the IRQ registers */
  50 #define LSCR_IRQ_ENABLE  1
  51 #define LSCR_IRQ_ACTIVE  2
  52 
  53 /* Offset within slot of screen buffer */
  54 #define LSCR_SCREEN      32768
  55 
  56 /* Convert a 32-bit X/Y pair to X and Y coordinates. */ 
  57 static
  58 inline
  59 void
  60 splitxy(uint32_t xy, unsigned *x, unsigned *y)
  61 {
  62         *x = xy >> 16;
  63         *y = xy & 0xffff;
  64 }
  65 
  66 /* Convert X and Y coordinates to a single 32-bit value. */
  67 static
  68 inline
  69 uint32_t
  70 mergexy(unsigned x, unsigned y)
  71 {
  72         uint32_t val = x;
  73 
  74         return (val << 16) | y;
  75 }
  76 
  77 ////////////////////////////////////////////////////////////
  78 
  79 /*
  80  * Interrupt handler.
  81  */
  82 void
  83 lscreen_irq(void *vsc)
  84 {
  85         struct lscreen_softc *sc = vsc;
  86         uint32_t ch, x;
  87 
  88         spinlock_acquire(&sc->ls_lock);
  89 
  90         x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
  91         if (x & LSCR_IRQ_ACTIVE) {
  92                 ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
  93                                        LSCR_REG_CHAR);
  94                 bus_write_register(sc->ls_busdata, sc->ls_buspos,
  95                                    LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
  96 
  97                 spinlock_release(&sc->ls_lock);
  98                 if (sc->ls_input) {
  99                         sc->ls_input(sc->ls_devdata, ch);
 100                 }
 101         }
 102         else {
 103                 spinlock_release(&sc->ls_lock);
 104         }
 105 }
 106 
 107 ////////////////////////////////////////////////////////////
 108 
 109 /*
 110  * Handle a newline on the screen.
 111  */
 112 static
 113 void
 114 lscreen_newline(struct lscreen_softc *sc)
 115 {
 116         if (sc->ls_cy >= sc->ls_height-1) {
 117                 /*
 118                  * Scroll
 119                  */
 120 
 121                 memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
 122                         sc->ls_width * (sc->ls_height-1));
 123                 bzero(sc->ls_screen + sc->ls_width * (sc->ls_height-1),
 124                       sc->ls_width);
 125         }
 126         else {
 127                 sc->ls_cy++;
 128         }
 129         sc->ls_cx=0;
 130 }
 131 
 132 /*
 133  * Handle a printable character being written to the screen.
 134  */
 135 static
 136 void
 137 lscreen_char(struct lscreen_softc *sc, int ch)
 138 {
 139         if (sc->ls_cx >= sc->ls_width) {
 140                 lscreen_newline(sc);
 141         }
 142 
 143         sc->ls_screen[sc->ls_cy*sc->ls_width + sc->ls_cx] = ch;
 144         sc->ls_cx++;
 145 }
 146 
 147 /*
 148  * Send a character to the screen.
 149  * This should probably know about backspace and tab.
 150  */
 151 void
 152 lscreen_write(void *vsc, int ch)
 153 {
 154         struct lscreen_softc *sc = vsc;
 155         int ccx, ccy;
 156 
 157         spinlock_acquire(&sc->ls_lock);
 158 
 159         switch (ch) {
 160             case '\n': lscreen_newline(sc); break;
 161             default: lscreen_char(sc, ch); break;
 162         }
 163 
 164         /*
 165          * ccx/ccy = corrected cursor position
 166          * (The cursor marks the next space text will appear in. But
 167          * at the very end of the line, it should not move off the edge.)
 168          */
 169         ccx = sc->ls_cx;
 170         ccy = sc->ls_cy;
 171         if (ccx==sc->ls_width) {
 172                 ccx--;
 173         }
 174 
 175         /* Set the cursor position */
 176         bus_write_register(sc->ls_busdata, sc->ls_buspos,
 177                            LSCR_REG_POSN, mergexy(ccx, ccy));
 178 
 179         spinlock_release(&sc->ls_lock);
 180 }
 181 
 182 ////////////////////////////////////////////////////////////
 183 
 184 /*
 185  * Setup routine called by autoconf.c when an lscreen is found.
 186  */
 187 int
 188 config_lscreen(struct lscreen_softc *sc, int lscreenno)
 189 {
 190         uint32_t val;
 191 
 192         (void)lscreenno;
 193 
 194         spinlock_init(&sc->ls_lock);
 195 
 196         /*
 197          * Enable interrupting.
 198          */
 199 
 200         bus_write_register(sc->ls_busdata, sc->ls_buspos,
 201                            LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
 202 
 203         /*
 204          * Get screen size.
 205          */
 206         val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
 207                                 LSCR_REG_SIZE);
 208         splitxy(val, &sc->ls_width, &sc->ls_height);
 209 
 210         /*
 211          * Get cursor position.
 212          */
 213         val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
 214                                 LSCR_REG_POSN);
 215         splitxy(val, &sc->ls_cx, &sc->ls_cy);
 216 
 217         /*
 218          * Get a pointer to the memory-mapped screen area.
 219          */
 220         sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos,
 221                                      LSCR_SCREEN);
 222 
 223         return 0;
 224 }
 225 

/* [<][>][^][v][top][bottom][index][help] */