@@ -93,7 +93,6 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
93
93
static void vgacon_invert_region (struct vc_data * c , u16 * p , int count );
94
94
static unsigned long vgacon_uni_pagedir [2 ];
95
95
96
-
97
96
/* Description of the hardware situation */
98
97
static unsigned long vga_vram_base ; /* Base of video memory */
99
98
static unsigned long vga_vram_end ; /* End of video memory */
@@ -161,6 +160,201 @@ static inline void write_vga(unsigned char reg, unsigned int val)
161
160
spin_unlock_irqrestore (& vga_lock , flags );
162
161
}
163
162
163
+ static inline void vga_set_mem_top (struct vc_data * c )
164
+ {
165
+ write_vga (12 , (c -> vc_visible_origin - vga_vram_base ) / 2 );
166
+ }
167
+
168
+ #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
169
+ #include <linux/bootmem.h>
170
+ /* software scrollback */
171
+ static void * vgacon_scrollback ;
172
+ static int vgacon_scrollback_tail ;
173
+ static int vgacon_scrollback_size ;
174
+ static int vgacon_scrollback_rows ;
175
+ static int vgacon_scrollback_cnt ;
176
+ static int vgacon_scrollback_cur ;
177
+ static int vgacon_scrollback_save ;
178
+ static int vgacon_scrollback_restore ;
179
+
180
+ static void vgacon_scrollback_init (int pitch )
181
+ {
182
+ int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024 /pitch ;
183
+
184
+ if (vgacon_scrollback ) {
185
+ vgacon_scrollback_cnt = 0 ;
186
+ vgacon_scrollback_tail = 0 ;
187
+ vgacon_scrollback_cur = 0 ;
188
+ vgacon_scrollback_rows = rows - 1 ;
189
+ vgacon_scrollback_size = rows * pitch ;
190
+ }
191
+ }
192
+
193
+ static void __init vgacon_scrollback_startup (void )
194
+ {
195
+ vgacon_scrollback = alloc_bootmem (CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
196
+ * 1024 );
197
+ vgacon_scrollback_init (vga_video_num_columns * 2 );
198
+ }
199
+
200
+ static void vgacon_scrollback_update (struct vc_data * c , int t , int count )
201
+ {
202
+ void * p ;
203
+
204
+ if (!vgacon_scrollback_size || c -> vc_num != fg_console )
205
+ return ;
206
+
207
+ p = (void * ) (c -> vc_origin + t * c -> vc_size_row );
208
+
209
+ while (count -- ) {
210
+ scr_memcpyw (vgacon_scrollback + vgacon_scrollback_tail ,
211
+ p , c -> vc_size_row );
212
+ vgacon_scrollback_cnt ++ ;
213
+ p += c -> vc_size_row ;
214
+ vgacon_scrollback_tail += c -> vc_size_row ;
215
+
216
+ if (vgacon_scrollback_tail >= vgacon_scrollback_size )
217
+ vgacon_scrollback_tail = 0 ;
218
+
219
+ if (vgacon_scrollback_cnt > vgacon_scrollback_rows )
220
+ vgacon_scrollback_cnt = vgacon_scrollback_rows ;
221
+
222
+ vgacon_scrollback_cur = vgacon_scrollback_cnt ;
223
+ }
224
+ }
225
+
226
+ static void vgacon_restore_screen (struct vc_data * c )
227
+ {
228
+ vgacon_scrollback_save = 0 ;
229
+
230
+ if (!vga_is_gfx && !vgacon_scrollback_restore ) {
231
+ scr_memcpyw ((u16 * ) c -> vc_origin , (u16 * ) c -> vc_screenbuf ,
232
+ c -> vc_screenbuf_size > vga_vram_size ?
233
+ vga_vram_size : c -> vc_screenbuf_size );
234
+ vgacon_scrollback_restore = 1 ;
235
+ vgacon_scrollback_cur = vgacon_scrollback_cnt ;
236
+ }
237
+ }
238
+
239
+ static int vgacon_scrolldelta (struct vc_data * c , int lines )
240
+ {
241
+ int start , end , count , soff , diff ;
242
+ void * d , * s ;
243
+
244
+ if (!lines ) {
245
+ c -> vc_visible_origin = c -> vc_origin ;
246
+ vga_set_mem_top (c );
247
+ return 1 ;
248
+ }
249
+
250
+ if (!vgacon_scrollback )
251
+ return 1 ;
252
+
253
+ if (!vgacon_scrollback_save ) {
254
+ vgacon_cursor (c , CM_ERASE );
255
+ vgacon_save_screen (c );
256
+ vgacon_scrollback_save = 1 ;
257
+ }
258
+
259
+ vgacon_scrollback_restore = 0 ;
260
+ start = vgacon_scrollback_cur + lines ;
261
+ end = start + abs (lines );
262
+
263
+ if (start < 0 )
264
+ start = 0 ;
265
+
266
+ if (start > vgacon_scrollback_cnt )
267
+ start = vgacon_scrollback_cnt ;
268
+
269
+ if (end < 0 )
270
+ end = 0 ;
271
+
272
+ if (end > vgacon_scrollback_cnt )
273
+ end = vgacon_scrollback_cnt ;
274
+
275
+ vgacon_scrollback_cur = start ;
276
+ count = end - start ;
277
+ soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end ) *
278
+ c -> vc_size_row );
279
+ soff -= count * c -> vc_size_row ;
280
+
281
+ if (soff < 0 )
282
+ soff += vgacon_scrollback_size ;
283
+
284
+ count = vgacon_scrollback_cnt - start ;
285
+
286
+ if (count > c -> vc_rows )
287
+ count = c -> vc_rows ;
288
+
289
+ diff = c -> vc_rows - count ;
290
+
291
+ d = (void * ) c -> vc_origin ;
292
+ s = (void * ) c -> vc_screenbuf ;
293
+
294
+ while (count -- ) {
295
+ scr_memcpyw (d , vgacon_scrollback + soff , c -> vc_size_row );
296
+ d += c -> vc_size_row ;
297
+ soff += c -> vc_size_row ;
298
+
299
+ if (soff >= vgacon_scrollback_size )
300
+ soff = 0 ;
301
+ }
302
+
303
+ if (diff == c -> vc_rows ) {
304
+ vgacon_cursor (c , CM_MOVE );
305
+ } else {
306
+ while (diff -- ) {
307
+ scr_memcpyw (d , s , c -> vc_size_row );
308
+ d += c -> vc_size_row ;
309
+ s += c -> vc_size_row ;
310
+ }
311
+ }
312
+
313
+ return 1 ;
314
+ }
315
+ #else
316
+ #define vgacon_scrollback_startup (...) do { } while (0)
317
+ #define vgacon_scrollback_init (...) do { } while (0)
318
+ #define vgacon_scrollback_update (...) do { } while (0)
319
+
320
+ static void vgacon_restore_screen (struct vc_data * c )
321
+ {
322
+ if (c -> vc_origin != c -> vc_visible_origin )
323
+ vgacon_scrolldelta (c , 0 );
324
+ }
325
+
326
+ static int vgacon_scrolldelta (struct vc_data * c , int lines )
327
+ {
328
+ if (!lines ) /* Turn scrollback off */
329
+ c -> vc_visible_origin = c -> vc_origin ;
330
+ else {
331
+ int margin = c -> vc_size_row * 4 ;
332
+ int ul , we , p , st ;
333
+
334
+ if (vga_rolled_over >
335
+ (c -> vc_scr_end - vga_vram_base ) + margin ) {
336
+ ul = c -> vc_scr_end - vga_vram_base ;
337
+ we = vga_rolled_over + c -> vc_size_row ;
338
+ } else {
339
+ ul = 0 ;
340
+ we = vga_vram_size ;
341
+ }
342
+ p = (c -> vc_visible_origin - vga_vram_base - ul + we ) % we +
343
+ lines * c -> vc_size_row ;
344
+ st = (c -> vc_origin - vga_vram_base - ul + we ) % we ;
345
+ if (st < 2 * margin )
346
+ margin = 0 ;
347
+ if (p < margin )
348
+ p = 0 ;
349
+ if (p > st - margin )
350
+ p = st ;
351
+ c -> vc_visible_origin = vga_vram_base + (p + ul ) % we ;
352
+ }
353
+ vga_set_mem_top (c );
354
+ return 1 ;
355
+ }
356
+ #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
357
+
164
358
static const char __init * vgacon_startup (void )
165
359
{
166
360
const char * display_desc = NULL ;
@@ -330,7 +524,7 @@ static const char __init *vgacon_startup(void)
330
524
331
525
vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH ;
332
526
vgacon_yres = vga_scan_lines ;
333
-
527
+ vgacon_scrollback_startup ();
334
528
return display_desc ;
335
529
}
336
530
@@ -357,11 +551,6 @@ static void vgacon_init(struct vc_data *c, int init)
357
551
con_set_default_unimap (c );
358
552
}
359
553
360
- static inline void vga_set_mem_top (struct vc_data * c )
361
- {
362
- write_vga (12 , (c -> vc_visible_origin - vga_vram_base ) / 2 );
363
- }
364
-
365
554
static void vgacon_deinit (struct vc_data * c )
366
555
{
367
556
/* When closing the last console, reset video origin */
@@ -455,8 +644,8 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
455
644
456
645
static void vgacon_cursor (struct vc_data * c , int mode )
457
646
{
458
- if ( c -> vc_origin != c -> vc_visible_origin )
459
- vgacon_scrolldelta ( c , 0 );
647
+ vgacon_restore_screen ( c );
648
+
460
649
switch (mode ) {
461
650
case CM_ERASE :
462
651
write_vga (14 , (c -> vc_pos - vga_vram_base ) / 2 );
@@ -606,6 +795,7 @@ static int vgacon_switch(struct vc_data *c)
606
795
vgacon_doresize (c , c -> vc_cols , c -> vc_rows );
607
796
}
608
797
798
+ vgacon_scrollback_init (c -> vc_size_row );
609
799
return 0 ; /* Redrawing not needed */
610
800
}
611
801
@@ -1073,37 +1263,6 @@ static int vgacon_resize(struct vc_data *c, unsigned int width,
1073
1263
return 0 ;
1074
1264
}
1075
1265
1076
- static int vgacon_scrolldelta (struct vc_data * c , int lines )
1077
- {
1078
- if (!lines ) /* Turn scrollback off */
1079
- c -> vc_visible_origin = c -> vc_origin ;
1080
- else {
1081
- int margin = c -> vc_size_row * 4 ;
1082
- int ul , we , p , st ;
1083
-
1084
- if (vga_rolled_over >
1085
- (c -> vc_scr_end - vga_vram_base ) + margin ) {
1086
- ul = c -> vc_scr_end - vga_vram_base ;
1087
- we = vga_rolled_over + c -> vc_size_row ;
1088
- } else {
1089
- ul = 0 ;
1090
- we = vga_vram_size ;
1091
- }
1092
- p = (c -> vc_visible_origin - vga_vram_base - ul + we ) % we +
1093
- lines * c -> vc_size_row ;
1094
- st = (c -> vc_origin - vga_vram_base - ul + we ) % we ;
1095
- if (st < 2 * margin )
1096
- margin = 0 ;
1097
- if (p < margin )
1098
- p = 0 ;
1099
- if (p > st - margin )
1100
- p = st ;
1101
- c -> vc_visible_origin = vga_vram_base + (p + ul ) % we ;
1102
- }
1103
- vga_set_mem_top (c );
1104
- return 1 ;
1105
- }
1106
-
1107
1266
static int vgacon_set_origin (struct vc_data * c )
1108
1267
{
1109
1268
if (vga_is_gfx || /* We don't play origin tricks in graphic modes */
@@ -1146,15 +1305,14 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
1146
1305
if (t || b != c -> vc_rows || vga_is_gfx )
1147
1306
return 0 ;
1148
1307
1149
- if (c -> vc_origin != c -> vc_visible_origin )
1150
- vgacon_scrolldelta (c , 0 );
1151
-
1152
1308
if (!vga_hardscroll_enabled || lines >= c -> vc_rows / 2 )
1153
1309
return 0 ;
1154
1310
1311
+ vgacon_restore_screen (c );
1155
1312
oldo = c -> vc_origin ;
1156
1313
delta = lines * c -> vc_size_row ;
1157
1314
if (dir == SM_UP ) {
1315
+ vgacon_scrollback_update (c , t , lines );
1158
1316
if (c -> vc_scr_end + delta >= vga_vram_end ) {
1159
1317
scr_memcpyw ((u16 * ) vga_vram_base ,
1160
1318
(u16 * ) (oldo + delta ),
0 commit comments