|
@@ -70,14 +70,14 @@ struct console_driver vesafb_console __console_driver;
|
70
|
70
|
struct vesafb {
|
71
|
71
|
/** Frame buffer console */
|
72
|
72
|
struct fbcon fbcon;
|
|
73
|
+ /** Physical start address */
|
|
74
|
+ physaddr_t start;
|
73
|
75
|
/** Pixel geometry */
|
74
|
76
|
struct fbcon_geometry pixel;
|
75
|
77
|
/** Colour mapping */
|
76
|
78
|
struct fbcon_colour_map map;
|
77
|
79
|
/** Font definition */
|
78
|
80
|
struct fbcon_font font;
|
79
|
|
- /** Total length */
|
80
|
|
- size_t len;
|
81
|
81
|
/** Saved VGA mode */
|
82
|
82
|
uint8_t saved_mode;
|
83
|
83
|
};
|
|
@@ -215,12 +215,10 @@ static int vesafb_mode_list ( uint16_t **mode_numbers ) {
|
215
|
215
|
*
|
216
|
216
|
* @v mode_number Mode number
|
217
|
217
|
* @v mode Mode information
|
218
|
|
- * @v pixbuf Background picture (if any)
|
219
|
218
|
* @ret rc Return status code
|
220
|
219
|
*/
|
221
|
220
|
static int vesafb_set_mode ( unsigned int mode_number,
|
222
|
|
- struct vbe_mode_info *mode,
|
223
|
|
- struct pixel_buffer *pixbuf ) {
|
|
221
|
+ struct vbe_mode_info *mode ) {
|
224
|
222
|
uint16_t status;
|
225
|
223
|
int rc;
|
226
|
224
|
|
|
@@ -236,6 +234,7 @@ static int vesafb_set_mode ( unsigned int mode_number,
|
236
|
234
|
}
|
237
|
235
|
|
238
|
236
|
/* Record mode parameters */
|
|
237
|
+ vesafb.start = mode->phys_base_ptr;
|
239
|
238
|
vesafb.pixel.width = mode->x_resolution;
|
240
|
239
|
vesafb.pixel.height = mode->y_resolution;
|
241
|
240
|
vesafb.pixel.len = ( ( mode->bits_per_pixel + 7 ) / 8 );
|
|
@@ -251,38 +250,26 @@ static int vesafb_set_mode ( unsigned int mode_number,
|
251
|
250
|
vesafb.map.green_lsb = mode->green_field_position;
|
252
|
251
|
vesafb.map.blue_lsb = mode->blue_field_position;
|
253
|
252
|
|
254
|
|
- /* Get font data */
|
255
|
|
- vesafb_font();
|
256
|
|
-
|
257
|
|
- /* Initialise frame buffer console */
|
258
|
|
- fbcon_init ( &vesafb.fbcon, phys_to_user ( mode->phys_base_ptr ),
|
259
|
|
- &vesafb.pixel, &vesafb.map, &vesafb.font, pixbuf );
|
260
|
|
-
|
261
|
253
|
return 0;
|
262
|
254
|
}
|
263
|
255
|
|
264
|
256
|
/**
|
265
|
257
|
* Select and set video mode
|
266
|
258
|
*
|
|
259
|
+ * @v mode_numbers Mode number list (terminated with VBE_MODE_END)
|
267
|
260
|
* @v min_width Minimum required width (in pixels)
|
268
|
261
|
* @v min_height Minimum required height (in pixels)
|
269
|
262
|
* @v min_bpp Minimum required colour depth (in bits per pixel)
|
270
|
|
- * @v pixbuf Background picture (if any)
|
271
|
263
|
* @ret rc Return status code
|
272
|
264
|
*/
|
273
|
|
-static int vesafb_select_mode ( unsigned int min_width, unsigned int min_height,
|
274
|
|
- unsigned int min_bpp,
|
275
|
|
- struct pixel_buffer *pixbuf ) {
|
|
265
|
+static int vesafb_select_mode ( const uint16_t *mode_numbers,
|
|
266
|
+ unsigned int min_width, unsigned int min_height,
|
|
267
|
+ unsigned int min_bpp ) {
|
276
|
268
|
struct vbe_mode_info *mode = &vbe_buf.mode;
|
277
|
|
- uint16_t *mode_numbers;
|
278
|
269
|
uint16_t mode_number;
|
279
|
270
|
uint16_t status;
|
280
|
271
|
int rc;
|
281
|
272
|
|
282
|
|
- /* Get VESA mode list */
|
283
|
|
- if ( ( rc = vesafb_mode_list ( &mode_numbers ) ) != 0 )
|
284
|
|
- goto err_mode_list;
|
285
|
|
-
|
286
|
273
|
/* Find the first suitable mode */
|
287
|
274
|
while ( ( mode_number = *(mode_numbers++) ) != VBE_MODE_END ) {
|
288
|
275
|
|
|
@@ -339,20 +326,77 @@ static int vesafb_select_mode ( unsigned int min_width, unsigned int min_height,
|
339
|
326
|
}
|
340
|
327
|
|
341
|
328
|
/* Select this mode */
|
342
|
|
- if ( ( rc = vesafb_set_mode ( mode_number, mode,
|
343
|
|
- pixbuf ) ) != 0 ) {
|
344
|
|
- goto err_set_mode;
|
345
|
|
- }
|
|
329
|
+ if ( ( rc = vesafb_set_mode ( mode_number, mode ) ) != 0 )
|
|
330
|
+ return rc;
|
346
|
331
|
|
347
|
|
- break;
|
|
332
|
+ return 0;
|
348
|
333
|
}
|
349
|
334
|
|
350
|
|
- err_set_mode:
|
|
335
|
+ DBGC ( &vbe_buf, "VESAFB found no suitable mode\n" );
|
|
336
|
+ return -ENOENT;
|
|
337
|
+}
|
|
338
|
+
|
|
339
|
+/**
|
|
340
|
+ * Initialise VESA frame buffer
|
|
341
|
+ *
|
|
342
|
+ * @v min_width Minimum required width (in pixels)
|
|
343
|
+ * @v min_height Minimum required height (in pixels)
|
|
344
|
+ * @v min_bpp Minimum required colour depth (in bits per pixel)
|
|
345
|
+ * @v pixbuf Background picture (if any)
|
|
346
|
+ * @ret rc Return status code
|
|
347
|
+ */
|
|
348
|
+static int vesafb_init ( unsigned int min_width, unsigned int min_height,
|
|
349
|
+ unsigned int min_bpp, struct pixel_buffer *pixbuf ) {
|
|
350
|
+ uint32_t discard_b;
|
|
351
|
+ uint16_t *mode_numbers;
|
|
352
|
+ int rc;
|
|
353
|
+
|
|
354
|
+ /* Record current VGA mode */
|
|
355
|
+ __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
|
|
356
|
+ : "=a" ( vesafb.saved_mode ), "=b" ( discard_b )
|
|
357
|
+ : "a" ( VBE_GET_VGA_MODE ) );
|
|
358
|
+ DBGC ( &vbe_buf, "VESAFB saved VGA mode %#02x\n", vesafb.saved_mode );
|
|
359
|
+
|
|
360
|
+ /* Get VESA mode list */
|
|
361
|
+ if ( ( rc = vesafb_mode_list ( &mode_numbers ) ) != 0 )
|
|
362
|
+ goto err_mode_list;
|
|
363
|
+
|
|
364
|
+ /* Select and set mode */
|
|
365
|
+ if ( ( rc = vesafb_select_mode ( mode_numbers, min_width, min_height,
|
|
366
|
+ min_bpp ) ) != 0 )
|
|
367
|
+ goto err_select_mode;
|
|
368
|
+
|
|
369
|
+ /* Get font data */
|
|
370
|
+ vesafb_font();
|
|
371
|
+
|
|
372
|
+ /* Initialise frame buffer console */
|
|
373
|
+ fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ),
|
|
374
|
+ &vesafb.pixel, &vesafb.map, &vesafb.font, pixbuf );
|
|
375
|
+
|
|
376
|
+ err_select_mode:
|
351
|
377
|
free ( mode_numbers );
|
352
|
378
|
err_mode_list:
|
353
|
379
|
return rc;
|
354
|
380
|
}
|
355
|
381
|
|
|
382
|
+/**
|
|
383
|
+ * Finalise VESA frame buffer
|
|
384
|
+ *
|
|
385
|
+ */
|
|
386
|
+static void vesafb_fini ( void ) {
|
|
387
|
+ uint32_t discard_a;
|
|
388
|
+
|
|
389
|
+ /* Finalise frame buffer console */
|
|
390
|
+ fbcon_fini ( &vesafb.fbcon );
|
|
391
|
+
|
|
392
|
+ /* Restore VGA mode */
|
|
393
|
+ __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
|
|
394
|
+ : "=a" ( discard_a )
|
|
395
|
+ : "a" ( VBE_SET_VGA_MODE | vesafb.saved_mode ) );
|
|
396
|
+ DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n",
|
|
397
|
+ vesafb.saved_mode );
|
|
398
|
+}
|
|
399
|
+
|
356
|
400
|
/**
|
357
|
401
|
* Print a character to current cursor position
|
358
|
402
|
*
|
|
@@ -370,37 +414,24 @@ static void vesafb_putchar ( int character ) {
|
370
|
414
|
* @ret rc Return status code
|
371
|
415
|
*/
|
372
|
416
|
static int vesafb_configure ( struct console_configuration *config ) {
|
373
|
|
- uint32_t discard_a;
|
374
|
|
- uint32_t discard_b;
|
375
|
417
|
int rc;
|
376
|
418
|
|
377
|
419
|
/* Reset console, if applicable */
|
378
|
420
|
if ( ! vesafb_console.disabled ) {
|
379
|
|
- fbcon_fini ( &vesafb.fbcon );
|
380
|
|
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
|
381
|
|
- : "=a" ( discard_a )
|
382
|
|
- : "a" ( VBE_SET_VGA_MODE |
|
383
|
|
- vesafb.saved_mode ) );
|
384
|
|
- DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n",
|
385
|
|
- vesafb.saved_mode );
|
|
421
|
+ vesafb_fini();
|
386
|
422
|
bios_console.disabled &= ~CONSOLE_DISABLED_OUTPUT;
|
387
|
423
|
}
|
388
|
424
|
vesafb_console.disabled = CONSOLE_DISABLED;
|
389
|
425
|
|
390
|
|
- /* Record current video mode */
|
391
|
|
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
|
392
|
|
- : "=a" ( vesafb.saved_mode ), "=b" ( discard_b )
|
393
|
|
- : "a" ( VBE_GET_VGA_MODE ) );
|
394
|
|
-
|
395
|
426
|
/* Do nothing more unless we have a usable configuration */
|
396
|
427
|
if ( ( config == NULL ) ||
|
397
|
428
|
( config->width == 0 ) || ( config->height == 0 ) ) {
|
398
|
429
|
return 0;
|
399
|
430
|
}
|
400
|
431
|
|
401
|
|
- /* Try to select an appropriate mode */
|
402
|
|
- if ( ( rc = vesafb_select_mode ( config->width, config->height,
|
403
|
|
- config->bpp, config->pixbuf ) ) != 0 )
|
|
432
|
+ /* Initialise VESA frame buffer */
|
|
433
|
+ if ( ( rc = vesafb_init ( config->width, config->height, config->bpp,
|
|
434
|
+ config->pixbuf ) ) != 0 )
|
404
|
435
|
return rc;
|
405
|
436
|
|
406
|
437
|
/* Mark console as enabled */
|