00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <types.h>
00037 #include <lib.h>
00038 #include <spinlock.h>
00039 #include <platform/bus.h>
00040 #include <lamebus/lscreen.h>
00041 #include "autoconf.h"
00042
00043
00044 #define LSCR_REG_POSN 0
00045 #define LSCR_REG_SIZE 4
00046 #define LSCR_REG_CHAR 8
00047 #define LSCR_REG_RIRQ 12
00048
00049
00050 #define LSCR_IRQ_ENABLE 1
00051 #define LSCR_IRQ_ACTIVE 2
00052
00053
00054 #define LSCR_SCREEN 32768
00055
00056
00057 static
00058 inline
00059 void
00060 splitxy(uint32_t xy, unsigned *x, unsigned *y)
00061 {
00062 *x = xy >> 16;
00063 *y = xy & 0xffff;
00064 }
00065
00066
00067 static
00068 inline
00069 uint32_t
00070 mergexy(unsigned x, unsigned y)
00071 {
00072 uint32_t val = x;
00073
00074 return (val << 16) | y;
00075 }
00076
00077
00078
00079
00080
00081
00082 void
00083 lscreen_irq(void *vsc)
00084 {
00085 struct lscreen_softc *sc = vsc;
00086 uint32_t ch, x;
00087
00088 spinlock_acquire(&sc->ls_lock);
00089
00090 x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
00091 if (x & LSCR_IRQ_ACTIVE) {
00092 ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
00093 LSCR_REG_CHAR);
00094 bus_write_register(sc->ls_busdata, sc->ls_buspos,
00095 LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
00096
00097 spinlock_release(&sc->ls_lock);
00098 if (sc->ls_input) {
00099 sc->ls_input(sc->ls_devdata, ch);
00100 }
00101 }
00102 else {
00103 spinlock_release(&sc->ls_lock);
00104 }
00105 }
00106
00107
00108
00109
00110
00111
00112 static
00113 void
00114 lscreen_newline(struct lscreen_softc *sc)
00115 {
00116 if (sc->ls_cy >= sc->ls_height-1) {
00117
00118
00119
00120
00121 memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
00122 sc->ls_width * (sc->ls_height-1));
00123 bzero(sc->ls_screen + sc->ls_width * (sc->ls_height-1),
00124 sc->ls_width);
00125 }
00126 else {
00127 sc->ls_cy++;
00128 }
00129 sc->ls_cx=0;
00130 }
00131
00132
00133
00134
00135 static
00136 void
00137 lscreen_char(struct lscreen_softc *sc, int ch)
00138 {
00139 if (sc->ls_cx >= sc->ls_width) {
00140 lscreen_newline(sc);
00141 }
00142
00143 sc->ls_screen[sc->ls_cy*sc->ls_width + sc->ls_cx] = ch;
00144 sc->ls_cx++;
00145 }
00146
00147
00148
00149
00150
00151 void
00152 lscreen_write(void *vsc, int ch)
00153 {
00154 struct lscreen_softc *sc = vsc;
00155 int ccx, ccy;
00156
00157 spinlock_acquire(&sc->ls_lock);
00158
00159 switch (ch) {
00160 case '\n': lscreen_newline(sc); break;
00161 default: lscreen_char(sc, ch); break;
00162 }
00163
00164
00165
00166
00167
00168
00169 ccx = sc->ls_cx;
00170 ccy = sc->ls_cy;
00171 if (ccx==sc->ls_width) {
00172 ccx--;
00173 }
00174
00175
00176 bus_write_register(sc->ls_busdata, sc->ls_buspos,
00177 LSCR_REG_POSN, mergexy(ccx, ccy));
00178
00179 spinlock_release(&sc->ls_lock);
00180 }
00181
00182
00183
00184
00185
00186
00187 int
00188 config_lscreen(struct lscreen_softc *sc, int lscreenno)
00189 {
00190 uint32_t val;
00191
00192 (void)lscreenno;
00193
00194 spinlock_init(&sc->ls_lock);
00195
00196
00197
00198
00199
00200 bus_write_register(sc->ls_busdata, sc->ls_buspos,
00201 LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
00202
00203
00204
00205
00206 val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
00207 LSCR_REG_SIZE);
00208 splitxy(val, &sc->ls_width, &sc->ls_height);
00209
00210
00211
00212
00213 val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
00214 LSCR_REG_POSN);
00215 splitxy(val, &sc->ls_cx, &sc->ls_cy);
00216
00217
00218
00219
00220 sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos,
00221 LSCR_SCREEN);
00222
00223 return 0;
00224 }
00225