/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* Driver for full-screen console.31*32* As of this writing the full-screen console is not supported in33* System/161, so this driver is untested and probably broken.34*/35#include <types.h>36#include <lib.h>37#include <spinlock.h>38#include <platform/bus.h>39#include <lamebus/lscreen.h>40#include "autoconf.h"4142/* Registers (offsets within slot) */43#define LSCR_REG_POSN 0 /* Cursor position */44#define LSCR_REG_SIZE 4 /* Display size */45#define LSCR_REG_CHAR 8 /* Character in */46#define LSCR_REG_RIRQ 12 /* Read interrupt status */4748/* Bits in the IRQ registers */49#define LSCR_IRQ_ENABLE 150#define LSCR_IRQ_ACTIVE 25152/* Offset within slot of screen buffer */53#define LSCR_SCREEN 327685455/* Convert a 32-bit X/Y pair to X and Y coordinates. */56static57inline58void59splitxy(uint32_t xy, unsigned *x, unsigned *y)60{61*x = xy >> 16;62*y = xy & 0xffff;63}6465/* Convert X and Y coordinates to a single 32-bit value. */66static67inline68uint32_t69mergexy(unsigned x, unsigned y)70{71uint32_t val = x;7273return (val << 16) | y;74}7576////////////////////////////////////////////////////////////7778/*79* Interrupt handler.80*/81void82lscreen_irq(void *vsc)83{84struct lscreen_softc *sc = vsc;85uint32_t ch, x;8687spinlock_acquire(&sc->ls_lock);8889x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);90if (x & LSCR_IRQ_ACTIVE) {91ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,92LSCR_REG_CHAR);93bus_write_register(sc->ls_busdata, sc->ls_buspos,94LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);9596spinlock_release(&sc->ls_lock);97if (sc->ls_input) {98sc->ls_input(sc->ls_devdata, ch);99}100}101else {102spinlock_release(&sc->ls_lock);103}104}105106////////////////////////////////////////////////////////////107108/*109* Handle a newline on the screen.110*/111static112void113lscreen_newline(struct lscreen_softc *sc)114{115if (sc->ls_cy >= sc->ls_height-1) {116/*117* Scroll118*/119120memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,121sc->ls_width * (sc->ls_height-1));122bzero(sc->ls_screen + sc->ls_width * (sc->ls_height-1),123sc->ls_width);124}125else {126sc->ls_cy++;127}128sc->ls_cx=0;129}130131/*132* Handle a printable character being written to the screen.133*/134static135void136lscreen_char(struct lscreen_softc *sc, int ch)137{138if (sc->ls_cx >= sc->ls_width) {139lscreen_newline(sc);140}141142sc->ls_screen[sc->ls_cy*sc->ls_width + sc->ls_cx] = ch;143sc->ls_cx++;144}145146/*147* Send a character to the screen.148* This should probably know about backspace and tab.149*/150void151lscreen_write(void *vsc, int ch)152{153struct lscreen_softc *sc = vsc;154int ccx, ccy;155156spinlock_acquire(&sc->ls_lock);157158switch (ch) {159case '\n': lscreen_newline(sc); break;160default: lscreen_char(sc, ch); break;161}162163/*164* ccx/ccy = corrected cursor position165* (The cursor marks the next space text will appear in. But166* at the very end of the line, it should not move off the edge.)167*/168ccx = sc->ls_cx;169ccy = sc->ls_cy;170if (ccx==sc->ls_width) {171ccx--;172}173174/* Set the cursor position */175bus_write_register(sc->ls_busdata, sc->ls_buspos,176LSCR_REG_POSN, mergexy(ccx, ccy));177178spinlock_release(&sc->ls_lock);179}180181////////////////////////////////////////////////////////////182183/*184* Setup routine called by autoconf.c when an lscreen is found.185*/186int187config_lscreen(struct lscreen_softc *sc, int lscreenno)188{189uint32_t val;190191(void)lscreenno;192193spinlock_init(&sc->ls_lock);194195/*196* Enable interrupting.197*/198199bus_write_register(sc->ls_busdata, sc->ls_buspos,200LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);201202/*203* Get screen size.204*/205val = bus_read_register(sc->ls_busdata, sc->ls_buspos,206LSCR_REG_SIZE);207splitxy(val, &sc->ls_width, &sc->ls_height);208209/*210* Get cursor position.211*/212val = bus_read_register(sc->ls_busdata, sc->ls_buspos,213LSCR_REG_POSN);214splitxy(val, &sc->ls_cx, &sc->ls_cy);215216/*217* Get a pointer to the memory-mapped screen area.218*/219sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos,220LSCR_SCREEN);221222return 0;223}224225226227