OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [bios/] [display.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include "bios.h"
19
#include "serial.h"
20
#include "io.h"
21
 
22
static const unsigned frame_buffer_segment = 0xb000;
23
static const unsigned frame_buffer_offset = 0x8000;
24
 
25
union cursor {
26
    struct {
27
        unsigned char col;
28
        unsigned char row;
29
    } c;
30
    unsigned short v;
31
};
32
 
33
static void noinline crtc_reg_write(unsigned char reg, unsigned char val)
34
{
35
    outb(0x3d4, reg);
36
    outb(0x3d5, val);
37
}
38
 
39
static unsigned char noinline crtc_reg_read(unsigned char reg)
40
{
41
    outb(0x3d4, reg);
42
 
43
    return inb(0x3d5);
44
}
45
 
46
static void noinline read_cursor(union cursor *c)
47
{
48
    unsigned short pos;
49
 
50
    pos = (unsigned short)crtc_reg_read(0xe) << 8;
51
    pos |= crtc_reg_read(0xf);
52
 
53
    c->c.row = pos / 80;
54
    c->c.col = pos % 80;
55
}
56
 
57
static void noinline write_cursor(union cursor *c)
58
{
59
    unsigned short pos = (unsigned short)c->c.row * 80 + c->c.col;
60
 
61
    crtc_reg_write(0xe, pos >> 8);
62
    crtc_reg_write(0xf, pos);
63
 
64
    bda_write(cursor_offsets[0], c->v);
65
}
66
 
67
static void noinline clear_row(unsigned char row,
68
                               unsigned char col_left,
69
                               unsigned char col_right,
70
                               unsigned char attr)
71
{
72
    unsigned char col;
73
    const signed short blank = ((signed short)attr << 8) | 0x20;
74
 
75
    for (col = col_left; col <= col_right; ++col)
76
        writew(frame_buffer_segment, frame_buffer_offset + (row * 80 + col) * 2,
77
               blank);
78
}
79
 
80
static void noinline copy_row(unsigned char dst_row,
81
                              unsigned char src_row,
82
                              unsigned char col_left,
83
                              unsigned char col_right,
84
                              unsigned char attr)
85
{
86
    unsigned char col;
87
 
88
    for (col = col_left; col <= col_right; ++col) {
89
        unsigned short b =
90
            readw(frame_buffer_segment,
91
                  frame_buffer_offset + (src_row * 80 + col) * 2);
92
        writew(frame_buffer_segment,
93
               frame_buffer_offset + (dst_row * 80 + col) * 2, b);
94
    }
95
}
96
 
97
void __scroll_up(signed char row_top,
98
                 signed char row_bottom,
99
                 signed char col_left,
100
                 signed char col_right,
101
                 signed char blank_attr,
102
                 signed char scroll_count)
103
{
104
    signed char row;
105
 
106
    for (row = row_top; row <= row_bottom; ++row) {
107
        if (row + scroll_count > row_bottom)
108
            clear_row(row, col_left, col_right, blank_attr);
109
        else
110
            copy_row(row, row + scroll_count, col_left, col_right, blank_attr);
111
    }
112
}
113
 
114
void noinline scroll_up(union cursor *cursor, struct callregs *regs)
115
{
116
    signed char row_top = regs->cx.h;
117
    signed char row_bottom = regs->dx.h;
118
    signed char col_left = regs->cx.l;
119
    signed char col_right = regs->dx.l;
120
    signed char blank_attr = regs->bx.h;
121
    signed char scroll_count = regs->ax.l == 0 ? 25 : regs->ax.l;
122
 
123
    __scroll_up(row_top, row_bottom, col_left, col_right, blank_attr,
124
                scroll_count);
125
}
126
 
127
static void __scroll_down(signed char row_top,
128
                          signed char row_bottom,
129
                          signed char col_left,
130
                          signed char col_right,
131
                          signed char blank_attr,
132
                          signed char scroll_count)
133
{
134
    signed char row;
135
 
136
    for (row = row_bottom; row >= row_top; --row) {
137
        if (row - scroll_count < 0)
138
            clear_row(row, col_left, col_right, blank_attr);
139
        else
140
            copy_row(row, row - scroll_count, col_left, col_right, blank_attr);
141
    }
142
}
143
 
144
void noinline scroll_down(union cursor *cursor, struct callregs *regs)
145
{
146
    signed char row_top = regs->cx.h;
147
    signed char row_bottom = regs->dx.h;
148
    signed char col_left = regs->cx.l;
149
    signed char col_right = regs->dx.l;
150
    signed char blank_attr = regs->bx.h;
151
    signed char scroll_count = regs->ax.l == 0 ? 25 : regs->ax.l;
152
 
153
    __scroll_down(row_top, row_bottom, col_left, col_right, blank_attr,
154
                  scroll_count);
155
}
156
 
157
void noinline scroll_up_one(void)
158
{
159
    __scroll_up(0, 24, 0, 79, 0x07, 1);
160
}
161
 
162
static void do_backspace(union cursor *cursor)
163
{
164
    int i;
165
 
166
    for (i = 0; i < 2 && cursor->c.col > 0; ++i) {
167
        --cursor->c.col;
168
        writeb(frame_buffer_segment,
169
               frame_buffer_offset + (cursor->c.row * 80 + cursor->c.col) * 2,
170
               ' ');
171
    }
172
}
173
 
174
static void noinline emit_char(char c)
175
{
176
    union cursor cursor;
177
 
178
    read_cursor(&cursor);
179
 
180
    writeb(frame_buffer_segment,
181
           frame_buffer_offset + (cursor.c.row * 80 + cursor.c.col) * 2, c);
182
    ++cursor.c.col;
183
 
184
    if (c == '\b')
185
        do_backspace(&cursor);
186
 
187
    if (c == '\r' || c == '\n') {
188
        unsigned m = 0;
189
        --cursor.c.col;
190
        for (m = cursor.c.col; m < 80; ++m)
191
            writew(frame_buffer_segment,
192
                   frame_buffer_offset + (cursor.c.row * 80 + m) * 2, 0x0720);
193
    }
194
 
195
    if (cursor.c.col == 80 || c == '\n') {
196
        cursor.c.col = 0;
197
        ++cursor.c.row;
198
    }
199
 
200
    if (cursor.c.row >= 25) {
201
        scroll_up_one();
202
        cursor.c.row = 24;
203
    }
204
    write_cursor(&cursor);
205
}
206
 
207
static void read_char(struct callregs *regs)
208
{
209
    union cursor cursor;
210
 
211
    read_cursor(&cursor);
212
    regs->ax.x =
213
        readw(frame_buffer_segment,
214
              frame_buffer_offset + (cursor.c.row * 80 + cursor.c.col) * 2);
215
    write_cursor(&cursor);
216
}
217
 
218
static void write_char_and_attribute(struct callregs *regs)
219
{
220
    union cursor cursor;
221
 
222
    read_cursor(&cursor);
223
    unsigned short v = ((unsigned short)regs->bx.l << 8) | regs->ax.l;
224
    writew(frame_buffer_segment,
225
           frame_buffer_offset + (cursor.c.row * 80 + cursor.c.col) * 2, v);
226
}
227
 
228
void video_putchar(char c)
229
{
230
    if (c == '\r')
231
        return;
232
 
233
    emit_char(c);
234
}
235
 
236
static void write_char(struct callregs *regs)
237
{
238
    putchar(regs->ax.l);
239
}
240
 
241
static void set_cursor(struct callregs *regs)
242
{
243
    union cursor cursor;
244
 
245
    read_cursor(&cursor);
246
    cursor.c.col = regs->dx.l;
247
    cursor.c.row = regs->dx.h;
248
    write_cursor(&cursor);
249
}
250
 
251
static void get_cursor(struct callregs *regs)
252
{
253
    union cursor cursor;
254
 
255
    read_cursor(&cursor);
256
    regs->cx.h = bda_read(cursor_start);
257
    regs->cx.l = bda_read(cursor_end);
258
    regs->dx.h = cursor.c.row;
259
    regs->dx.l = cursor.c.col;
260
    write_cursor(&cursor);
261
}
262
 
263
static void noinline set_cursor_scan_start(unsigned char scan_start)
264
{
265
    // Cursor disabled requested
266
    if (scan_start & 0x20)
267
        scan_start = 0x10 | (scan_start & 0xf);
268
    crtc_reg_write(0xa, scan_start);
269
}
270
 
271
static void noinline set_cursor_scan_end(unsigned char scan_end)
272
{
273
    crtc_reg_write(0xb, scan_end);
274
}
275
 
276
static void noinline set_cursor_bda(unsigned char scan_start,
277
                                    unsigned char scan_end)
278
{
279
    bda_write(cursor_start, scan_start);
280
    bda_write(cursor_end, scan_end);
281
}
282
 
283
static void noinline __set_cursor_shape(unsigned char scan_start,
284
                                        unsigned char scan_end)
285
{
286
    set_cursor_scan_end(scan_end);
287
    set_cursor_scan_start(scan_start);
288
 
289
    set_cursor_bda(scan_start, scan_end);
290
}
291
 
292
static void noinline set_cursor_shape(struct callregs *regs)
293
{
294
    unsigned char scan_start = regs->cx.h;
295
    unsigned char scan_end = regs->cx.l;
296
 
297
    __set_cursor_shape(scan_start, scan_end);
298
}
299
 
300
static void get_video_mode(struct callregs *regs)
301
{
302
    regs->ax.h = 80;
303
    regs->ax.l = 0x03;
304
    regs->bx.h = 0;
305
}
306
 
307
static void video_services(struct callregs *regs)
308
{
309
    union cursor cursor;
310
    regs->flags &= ~CF;
311
 
312
    switch (regs->ax.h) {
313
    case 0xe: write_char(regs); break;
314
    case 0x2: set_cursor(regs); break;
315
    case 0x3: get_cursor(regs); break;
316
    case 0x1: set_cursor_shape(regs); break;
317
    case 0x6:
318
        read_cursor(&cursor);
319
        scroll_up(&cursor, regs);
320
        write_cursor(&cursor);
321
        break;
322
    case 0x7:
323
        read_cursor(&cursor);
324
        scroll_down(&cursor, regs);
325
        write_cursor(&cursor);
326
        break;
327
    case 0xf: get_video_mode(regs); break;
328
    case 0x9: write_char_and_attribute(regs); break;
329
    case 0x8: read_char(regs); break;
330
    default: regs->flags |= CF;
331
    }
332
}
333
VECTOR(0x10, video_services);
334
 
335
void display_init(void)
336
{
337
    unsigned r, c;
338
 
339
    for (r = 0; r < 25; ++r)
340
        for (c = 0; c < 80; ++c)
341
            writew(frame_buffer_segment, frame_buffer_offset + (r * 80 + c) * 2,
342
                   0x0720);
343
 
344
    bda_write(video_mode, 0x03);
345
    bda_write(num_screen_cols, 80);
346
    bda_write(last_screen_row, 25 - 1);
347
    bda_write(crt_controller_base, 0x3d4);
348
 
349
    __set_cursor_shape(7, 7);
350
 
351
    union cursor cursor;
352
    cursor.c.col = cursor.c.row = 0;
353
    write_cursor(&cursor);
354
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.