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

Subversion Repositories zet86

[/] [zet86/] [trunk/] [soc/] [bios/] [vgabios.c] - Blame information for rev 42

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 34 zeus
#include "vgabios.h"
2
 
3
/* Declares */
4
static Bit8u          read_byte();
5
static Bit16u         read_word();
6
static void           write_byte();
7
static void           write_word();
8
static Bit8u          inb();
9
static Bit16u         inw();
10
static void           outb();
11
static void           outw();
12
 
13
static Bit16u         get_SS();
14
 
15 39 zeus
// Output
16
static void           printf();
17
 
18 34 zeus
static Bit8u find_vga_entry();
19
 
20
static void memsetb();
21
static void memsetw();
22
static void memcpyb();
23
static void memcpyw();
24
 
25
static void biosfn_set_video_mode();
26
static void biosfn_set_cursor_pos();
27
static void biosfn_get_cursor_pos();
28
static void biosfn_scroll();
29
static void biosfn_write_teletype();
30 39 zeus
static void biosfn_load_text_8_16_pat();
31 34 zeus
static void biosfn_write_string();
32
extern Bit8u video_save_pointer_table[];
33
 
34
// This is for compiling with gcc2 and gcc3
35
#define ASM_START #asm
36
#define ASM_END   #endasm
37
 
38
ASM_START
39
 
40
MACRO SET_INT_VECTOR
41
  push ds
42
  xor ax, ax
43
  mov ds, ax
44
  mov ax, ?3
45
  mov ?1*4, ax
46
  mov ax, ?2
47
  mov ?1*4+2, ax
48
  pop ds
49
MEND
50
 
51
ASM_END
52
 
53
ASM_START
54
.text
55
.rom
56
.org 0
57
 
58
use16 8086
59
 
60
vgabios_start:
61
.byte   0x55, 0xaa      /* BIOS signature, required for BIOS extensions */
62
 
63
.byte   0x40            /* BIOS extension length in units of 512 bytes */
64
 
65
 
66
vgabios_entry_point:
67 39 zeus
 
68 34 zeus
  jmp vgabios_init_func
69
 
70
vgabios_name:
71 37 zeus
.ascii  "Zet/Bochs VGABios"
72 34 zeus
.ascii  " "
73
.byte   0x00
74
 
75
// Info from Bart Oldeman
76
.org 0x1e
77
.ascii  "IBM"
78
.byte   0x00
79
 
80
vgabios_version:
81
#ifndef VGABIOS_VERS
82
.ascii  "current-cvs"
83
#else
84
.ascii VGABIOS_VERS
85
#endif
86
.ascii  " "
87
 
88
vgabios_date:
89
.ascii  VGABIOS_DATE
90
.byte   0x0a,0x0d
91
.byte   0x00
92
 
93
vgabios_copyright:
94
.ascii  "(C) 2003 the LGPL VGABios developers Team"
95
.byte   0x0a,0x0d
96
.byte   0x00
97
 
98
vgabios_license:
99
.ascii  "This VGA/VBE Bios is released under the GNU LGPL"
100
.byte   0x0a,0x0d
101
.byte   0x0a,0x0d
102
.byte   0x00
103
 
104
vgabios_website:
105
.ascii  "Please visit :"
106
.byte   0x0a,0x0d
107
;;.ascii  " . http://www.plex86.org"
108
;;.byte 0x0a,0x0d
109 37 zeus
.ascii  " . http://zet.aluzina.org"
110
.byte   0x0a,0x0d
111 34 zeus
.ascii  " . http://bochs.sourceforge.net"
112
.byte   0x0a,0x0d
113
.ascii  " . http://www.nongnu.org/vgabios"
114
.byte   0x0a,0x0d
115
.byte   0x0a,0x0d
116
.byte   0x00
117
 
118 39 zeus
 
119 34 zeus
;; ========================================================
120
;;
121
;; Init Entry point
122
;;
123
;; ========================================================
124
vgabios_init_func:
125
 
126 39 zeus
;; init vga card
127
  call init_vga_card
128
 
129 34 zeus
;; init basic bios vars
130
  call init_bios_area
131
 
132
;; set int10 vect
133
  SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
134
 
135
;; display splash screen
136
  call _display_splash_screen
137 37 zeus
 
138 34 zeus
;; init video mode and clear the screen
139
  mov ax,#0x0003
140
  int #0x10
141
 
142
;; show info
143
  call _display_info
144
 
145
  retf
146
ASM_END
147
 
148
/*
149
 *  int10 handled here
150
 */
151
ASM_START
152
vgabios_int10_handler:
153
  pushf
154 41 zeus
  cmp   ah, #0x0f
155
  jne   int10_test_1A
156
  call  biosfn_get_video_mode
157
  jmp   int10_end
158
int10_test_1A:
159 39 zeus
int10_test_1103:
160
  cmp   ax, #0x1103
161
  jne   int10_normal
162
  call  biosfn_set_text_block_specifier
163
  jmp   int10_end
164 34 zeus
 
165
int10_normal:
166
  push es
167
  push ds
168
  ;pusha ; we do this instead:
169
 
170
  push ax
171
  push cx
172
  push dx
173
  push bx
174
  push sp
175
  mov  bx, sp
176
  add  [bx], #10
177
  mov  bx, [bx+2]
178
  push bp
179
  push si
180
  push di
181
 
182
;; We have to set ds to access the right data segment
183
  mov   bx, #0xc000
184
  mov   ds, bx
185 37 zeus
 
186 34 zeus
  call _int10_func
187
 
188
  ; popa ; we do this instead:
189
  pop di
190
  pop si
191
  pop bp
192
  add sp, #2
193
  pop bx
194
  pop dx
195
  pop cx
196
  pop ax
197
 
198
  pop ds
199
  pop es
200
int10_end:
201
  popf
202
  iret
203
ASM_END
204
 
205
#include "vgatables.h"
206 39 zeus
#include "vgafonts.h"
207 34 zeus
 
208
/*
209 39 zeus
 * Boot time harware inits
210 34 zeus
 */
211
ASM_START
212 39 zeus
init_vga_card:
213
;; switch to color mode and enable CPU access 480 lines
214
  mov dx, #0x3C2
215
  mov al, #0xC3
216
  outb dx,al
217
 
218
;; more than 64k 3C4/04
219
  mov dx, #0x3C4
220
  mov al, #0x04
221
  outb dx,al
222
  mov dx, #0x3C5
223
  mov al, #0x02
224
  outb dx,al
225
 
226
#if defined(USE_BX_INFO) || defined(DEBUG)
227
  mov  bx, #msg_vga_init
228
  push bx
229
  call _printf
230
#endif
231
;  inc  sp
232
;  inc  sp
233
  ret
234
 
235
#if defined(USE_BX_INFO) || defined(DEBUG)
236
msg_vga_init:
237 42 zeus
.ascii "VGABios $Id: vgabios.c,v 1.6 2009-01-26 02:37:39 zeus Exp $"
238 39 zeus
.byte 0x0d,0x0a,0x00
239
#endif
240
ASM_END
241
 
242
// --------------------------------------------------------------------------------------------
243
/*
244
 *  Boot time bios area inits
245
 */
246
ASM_START
247 34 zeus
init_bios_area:
248
  push  ds
249
  mov   ax, # BIOSMEM_SEG
250
  mov   ds, ax
251
 
252
;; init detected hardware BIOS Area
253
  mov   bx, # BIOSMEM_INITIAL_MODE
254
  mov   ax, [bx]
255
  and   ax, #0xffcf
256
;; set 80x25 color (not clear from RBIL but usual)
257
  or    ax, #0x0020
258
  mov   [bx], ax
259
 
260
;; Just for the first int10 find its children
261
 
262
;; the default char height
263
  mov   bx, # BIOSMEM_CHAR_HEIGHT
264
  mov   al, #0x10
265
  mov   [bx], al
266
 
267 39 zeus
;; Clear the screen
268 34 zeus
  mov   bx, # BIOSMEM_VIDEO_CTL
269
  mov   al, #0x60
270
  mov   [bx], al
271
 
272
;; Set the basic screen we have
273
  mov   bx, # BIOSMEM_SWITCHES
274
  mov   al, #0xf9
275
  mov   [bx], al
276
 
277
;; Set the basic modeset options
278
  mov   bx, # BIOSMEM_MODESET_CTL
279
  mov   al, #0x51
280
  mov   [bx], al
281
 
282
;; Set the  default MSR
283
  mov   bx, # BIOSMEM_CURRENT_MSR
284
  mov   al, #0x09
285
  mov   [bx], al
286
 
287
  pop ds
288
  ret
289
 
290
_video_save_pointer_table:
291
  .word _video_param_table
292
  .word 0xc000
293
 
294
  .word 0 /* XXX: fill it */
295
  .word 0
296
 
297
  .word 0 /* XXX: fill it */
298
  .word 0
299
 
300
  .word 0 /* XXX: fill it */
301
  .word 0
302
 
303
  .word 0 /* XXX: fill it */
304
  .word 0
305
 
306
  .word 0 /* XXX: fill it */
307
  .word 0
308
 
309
  .word 0 /* XXX: fill it */
310
  .word 0
311
 
312
ASM_END
313
 
314 39 zeus
// --------------------------------------------------------------------------------------------
315 34 zeus
/*
316
 *  Boot time Splash screen
317
 */
318
static void display_splash_screen()
319
{
320
}
321
 
322
// --------------------------------------------------------------------------------------------
323
/*
324
 *  Tell who we are
325
 */
326
 
327
static void display_info()
328
{
329
ASM_START
330
 mov ax,#0xc000
331
 mov ds,ax
332
 mov si,#vgabios_name
333
 call _display_string
334
 mov si,#vgabios_version
335
 call _display_string
336 37 zeus
 
337 34 zeus
 ;;mov si,#vgabios_copyright
338
 ;;call _display_string
339
 ;;mov si,#crlf
340
 ;;call _display_string
341
 
342
 mov si,#vgabios_license
343
 call _display_string
344
 mov si,#vgabios_website
345
 call _display_string
346
ASM_END
347
}
348
 
349
static void display_string()
350
{
351
 // Get length of string
352
ASM_START
353
 mov ax,ds
354
 mov es,ax
355
 mov di,si
356
 xor cx,cx
357
 not cx
358
 xor al,al
359
 cld
360 39 zeus
 repne
361 34 zeus
  scasb
362
 not cx
363
 dec cx
364
 push cx
365
 
366
 mov ax,#0x0300
367
 mov bx,#0x0000
368
 int #0x10
369 37 zeus
 
370 34 zeus
 pop cx
371
 mov ax,#0x1301
372
 mov bx,#0x000b
373
 mov bp,si
374
 int #0x10
375
ASM_END
376
}
377
 
378
// --------------------------------------------------------
379
/*
380
 * int10 main dispatcher
381
 */
382
static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
383
  Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
384
{
385
 // BIOS functions
386
 switch(GET_AH())
387
  {
388
   case 0x00:
389
     biosfn_set_video_mode(GET_AL());
390
     switch(GET_AL()&0x7F)
391 37 zeus
      {case 6:
392 34 zeus
        SET_AL(0x3F);
393
        break;
394
       case 0:
395
       case 1:
396
       case 2:
397
       case 3:
398
       case 4:
399
       case 5:
400
       case 7:
401
        SET_AL(0x30);
402
        break;
403
      default:
404
        SET_AL(0x20);
405
      }
406
     break;
407 37 zeus
   case 0x02:
408
     biosfn_set_cursor_pos(GET_BH(),DX);
409
     break;
410 34 zeus
   case 0x03:
411
     biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
412
     break;
413 41 zeus
   case 0x06:
414
     biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
415
     break;
416
   case 0x07:
417
     biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
418
     break;
419 34 zeus
   case 0x0E:
420
     // Ralf Brown Interrupt list is WRONG on bh(page)
421
     // We do output only on the current page !
422
     biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
423
     break;
424 39 zeus
   case 0x11:
425
     switch(GET_AL())
426
      {
427
       case 0x04:
428
       case 0x14:
429
        biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
430
        break;
431
      }
432
     break;
433 34 zeus
   case 0x13:
434
     biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
435
     break;
436
  }
437
}
438
 
439
// ============================================================================================
440 39 zeus
//
441 34 zeus
// BIOS functions
442 39 zeus
//
443 34 zeus
// ============================================================================================
444
 
445 39 zeus
static void biosfn_set_video_mode(mode) Bit8u mode;
446 34 zeus
{// mode: Bit 7 is 1 if no clear screen
447
 
448
 // Should we clear the screen ?
449
 Bit8u noclearmem=mode&0x80;
450
 Bit8u line,mmask,*palette,vpti;
451
 Bit16u i,twidth,theightm1,cheight;
452
 Bit8u modeset_ctl,video_ctl,vga_switches;
453
 Bit16u crtc_addr;
454 37 zeus
 
455 34 zeus
 // The real mode
456
 mode=mode&0x7f;
457
 
458
 // find the entry in the video modes
459
 line=find_vga_entry(mode);
460
 
461
 if(line==0xFF)
462
  return;
463
 
464
 vpti=line_to_vpti[line];
465
 twidth=video_param_table[vpti].twidth;
466
 theightm1=video_param_table[vpti].theightm1;
467
 cheight=video_param_table[vpti].cheight;
468 39 zeus
 
469 34 zeus
 // Read the bios vga control
470
 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
471
 
472
 // Read the bios vga switches
473
 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
474
 
475
 // Read the bios mode set control
476
 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
477
 
478 39 zeus
 // Then we know the number of lines
479
// FIXME
480
 
481
 // if palette loading (bit 3 of modeset ctl = 0)
482
 if((modeset_ctl&0x08)==0)
483
  {// Set the PEL mask
484
   outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
485
 
486
   // Set the whole dac always, from 0
487
   outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
488
 
489
   // From which palette
490
   switch(vga_modes[line].dacmodel)
491
    {case 0:
492
      palette=&palette0;
493
      break;
494
     case 1:
495
      palette=&palette1;
496
      break;
497
     case 2:
498
      palette=&palette2;
499
      break;
500
     case 3:
501
      palette=&palette3;
502
      break;
503
    }
504
   // Always 256*3 values
505
   for(i=0;i<0x0100;i++)
506
    {if(i<=dac_regs[vga_modes[line].dacmodel])
507
      {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
508
       outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
509
       outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
510
      }
511
     else
512
      {outb(VGAREG_DAC_DATA,0);
513
       outb(VGAREG_DAC_DATA,0);
514
       outb(VGAREG_DAC_DATA,0);
515
      }
516
    }
517
  }
518
 
519
 // Reset Attribute Ctl flip-flop
520
 inb(VGAREG_ACTL_RESET);
521
 
522
 // Set Attribute Ctl
523
 for(i=0;i<=0x13;i++)
524
  {outb(VGAREG_ACTL_ADDRESS,i);
525
   outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
526
  }
527
 outb(VGAREG_ACTL_ADDRESS,0x14);
528
 outb(VGAREG_ACTL_WRITE_DATA,0x00);
529
 
530
 // Set Sequencer Ctl
531
 outb(VGAREG_SEQU_ADDRESS,0);
532
 outb(VGAREG_SEQU_DATA,0x03);
533
 for(i=1;i<=4;i++)
534
  {outb(VGAREG_SEQU_ADDRESS,i);
535
   outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
536
  }
537
 
538
 // Set Grafx Ctl
539
 for(i=0;i<=8;i++)
540
  {outb(VGAREG_GRDC_ADDRESS,i);
541
   outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
542
  }
543
 
544
 // Set CRTC address VGA or MDA
545 34 zeus
 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
546
 
547 39 zeus
 // Disable CRTC write protection
548
 outw(crtc_addr,0x0011);
549
 // Set CRTC regs
550
 for(i=0;i<=0x18;i++)
551
  {outb(crtc_addr,i);
552
   outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
553
  }
554
 
555
 // Set the misc register
556
 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
557
 
558
 // Enable video
559
 outb(VGAREG_ACTL_ADDRESS,0x20);
560
 inb(VGAREG_ACTL_RESET);
561
 
562
 if(noclearmem==0x00)
563
  {
564
   if(vga_modes[line].class==TEXT)
565
    {
566
     memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
567
    }
568
   else
569
    {
570
     if(mode<0x0d)
571
      {
572
       memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
573
      }
574
     else
575
      {
576
       outb( VGAREG_SEQU_ADDRESS, 0x02 );
577
       mmask = inb( VGAREG_SEQU_DATA );
578
       outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
579
       memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
580
       outb( VGAREG_SEQU_DATA, mmask );
581
      }
582
    }
583
  }
584
 
585 34 zeus
 // Set the BIOS mem
586
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
587
 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
588
 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
589
 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
590
 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
591
 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
592
 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
593
 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
594
 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
595
 
596
 // FIXME We nearly have the good tables. to be reworked
597
 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08);    // 8 is VGA should be ok for now
598
 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
599
 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
600
 
601
 // FIXME
602
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
603
 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
604 39 zeus
 
605
 // Write the fonts in memory
606
 if(vga_modes[line].class==TEXT)
607
  {
608
ASM_START
609
  ;; copy and activate 8x16 font
610
  mov ax, #0x1104
611
  mov bl, #0x00
612
  int #0x10
613
  mov ax, #0x1103
614
  mov bl, #0x00
615
  int #0x10
616
ASM_END
617
  }
618 34 zeus
}
619
 
620
// --------------------------------------------------------------------------------------------
621 39 zeus
static void biosfn_set_cursor_pos (page, cursor)
622 34 zeus
Bit8u page;Bit16u cursor;
623
{
624
 Bit8u xcurs,ycurs,current;
625
 Bit16u nbcols,nbrows,address,crtc_addr;
626
 
627
 // Should not happen...
628
 if(page>7)return;
629
 
630
 // Bios cursor pos
631
 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
632
 
633
 // Set the hardware cursor
634
 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
635
 if(page==current)
636
  {
637
   // Get the dimensions
638
   nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
639
   nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
640
 
641
   xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
642 39 zeus
 
643 34 zeus
   // Calculate the address knowing nbcols nbrows and page num
644
   address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
645 39 zeus
 
646 34 zeus
   // CRTC regs 0x0e and 0x0f
647
   crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
648
   outb(crtc_addr,0x0e);
649
   outb(crtc_addr+1,(address&0xff00)>>8);
650
   outb(crtc_addr,0x0f);
651
   outb(crtc_addr+1,address&0x00ff);
652 39 zeus
   outw(0xb800,cursor);
653 34 zeus
  }
654
}
655
 
656
// --------------------------------------------------------------------------------------------
657 39 zeus
static void biosfn_get_cursor_pos (page,shape, pos)
658 34 zeus
Bit8u page;Bit16u *shape;Bit16u *pos;
659
{
660
 Bit16u ss=get_SS();
661
 
662
 // Default
663
 write_word(ss, shape, 0);
664
 write_word(ss, pos, 0);
665
 
666
 if(page>7)return;
667
 // FIXME should handle VGA 14/16 lines
668
 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
669
 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
670
}
671
 
672
// --------------------------------------------------------------------------------------------
673
static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
674
Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
675
{
676
 // page == 0xFF if current
677
 
678
 Bit8u mode,line,cheight,bpp,cols;
679
 Bit16u nbcols,nbrows,i;
680
 Bit16u address;
681
 
682
 if(rul>rlr)return;
683
 if(cul>clr)return;
684
 
685
 // Get the mode
686
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
687
 line=find_vga_entry(mode);
688
 if(line==0xFF)return;
689
 
690
 // Get the dimensions
691
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
692
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
693
 
694
 // Get the current page
695
 if(page==0xFF)
696
  page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
697
 
698
 if(rlr>=nbrows)rlr=nbrows-1;
699
 if(clr>=nbcols)clr=nbcols-1;
700
 if(nblines>nbrows)nblines=0;
701
 cols=clr-cul+1;
702
 
703
 if(vga_modes[line].class==TEXT)
704
  {
705
   // Compute the address
706
   address=SCREEN_MEM_START(nbcols,nbrows,page);
707
#ifdef DEBUG
708
   printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
709
#endif
710
 
711
   if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
712
    {
713
     memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
714
    }
715
   else
716
    {// if Scroll up
717
     if(dir==SCROLL_UP)
718
      {for(i=rul;i<=rlr;i++)
719
        {
720
         if((i+nblines>rlr)||(nblines==0))
721
          memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
722
         else
723
          memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
724
        }
725
      }
726
     else
727
      {for(i=rlr;i>=rul;i--)
728
        {
729
         if((i<rul+nblines)||(nblines==0))
730
          memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
731
         else
732
          memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
733
         if (i>rlr) break;
734
        }
735
      }
736
    }
737
  }
738
}
739
 
740
// --------------------------------------------------------------------------------------------
741 39 zeus
static void biosfn_write_teletype (car, page, attr, flag)
742 34 zeus
Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
743
{// flag = WITH_ATTR / NO_ATTR
744
 
745
 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
746
 Bit16u nbcols,nbrows,address;
747
 Bit16u cursor,dummy;
748
 
749
 // special case if page is 0xff, use current page
750
 if(page==0xff)
751
  page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
752
 
753
 // Get the mode
754
 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
755
 line=find_vga_entry(mode);
756
 if(line==0xFF)return;
757
 
758
 // Get the cursor pos for the page
759
 biosfn_get_cursor_pos(page,&dummy,&cursor);
760
 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
761
 
762
 // Get the dimensions
763
 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
764
 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
765
 
766
 switch(car)
767
  {
768
   case 7:
769
    //FIXME should beep
770
    break;
771
 
772
   case 8:
773
    if(xcurs>0)xcurs--;
774
    break;
775
 
776
   case '\r':
777
    xcurs=0;
778
    break;
779
 
780
   case '\n':
781
    ycurs++;
782
    break;
783
 
784
   case '\t':
785
    do
786
     {
787
      biosfn_write_teletype(' ',page,attr,flag);
788
      biosfn_get_cursor_pos(page,&dummy,&cursor);
789
      xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
790
     }while(xcurs%8==0);
791
    break;
792
 
793
   default:
794
 
795
    if(vga_modes[line].class==TEXT)
796
     {
797 39 zeus
      // Compute the address
798 34 zeus
      address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
799
 
800 39 zeus
      // Write the char
801 34 zeus
      write_byte(vga_modes[line].sstart,address,car);
802
 
803
      if(flag==WITH_ATTR)
804
       write_byte(vga_modes[line].sstart,address+1,attr);
805
     }
806
    xcurs++;
807
  }
808
 
809
 // Do we need to wrap ?
810
 if(xcurs==nbcols)
811
  {xcurs=0;
812
   ycurs++;
813
  }
814
 
815
 // Do we need to scroll ?
816
 if(ycurs==nbrows)
817
  {
818
   if(vga_modes[line].class==TEXT)
819
    {
820
     biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
821
    }
822
   ycurs-=1;
823
  }
824 39 zeus
 
825 34 zeus
 // Set the cursor for the page
826
 cursor=ycurs; cursor<<=8; cursor+=xcurs;
827
 biosfn_set_cursor_pos(page,cursor);
828
}
829
 
830
// --------------------------------------------------------------------------------------------
831 41 zeus
ASM_START
832
biosfn_get_video_mode:
833
  push  ds
834
  mov   ax, # BIOSMEM_SEG
835
  mov   ds, ax
836
  push  bx
837
  mov   bx, # BIOSMEM_CURRENT_PAGE
838
  mov   al, [bx]
839
  pop   bx
840
  mov   bh, al
841
  push  bx
842
  mov   bx, # BIOSMEM_VIDEO_CTL
843
  mov   ah, [bx]
844
  and   ah, #0x80
845
  mov   bx, # BIOSMEM_CURRENT_MODE
846
  mov   al, [bx]
847
  or    al, ah
848
  mov   bx, # BIOSMEM_NB_COLS
849
  mov   ah, [bx]
850
  pop   bx
851
  pop   ds
852
  ret
853
ASM_END
854
 
855
// --------------------------------------------------------------------------------------------
856 39 zeus
static void get_font_access()
857
{
858
ASM_START
859
 mov dx, # VGAREG_SEQU_ADDRESS
860
 mov ax, #0x0100
861
 out dx, ax
862
 mov ax, #0x0402
863
 out dx, ax
864
 mov ax, #0x0704
865
 out dx, ax
866
 mov ax, #0x0300
867
 out dx, ax
868
 mov dx, # VGAREG_GRDC_ADDRESS
869
 mov ax, #0x0204
870
 out dx, ax
871
 mov ax, #0x0005
872
 out dx, ax
873
 mov ax, #0x0406
874
 out dx, ax
875
ASM_END
876
}
877
 
878
static void release_font_access()
879
{
880
ASM_START
881
 mov dx, # VGAREG_SEQU_ADDRESS
882
 mov ax, #0x0100
883
 out dx, ax
884
 mov ax, #0x0302
885
 out dx, ax
886
 mov ax, #0x0304
887
 out dx, ax
888
 mov ax, #0x0300
889
 out dx, ax
890
 mov dx, # VGAREG_READ_MISC_OUTPUT
891
 in  al, dx
892
 and al, #0x01
893
 push cx
894
 mov cl,*2
895
 shl al,cl
896
 pop cx
897
 or  al, #0x0a
898
 mov ah, al
899
 mov al, #0x06
900
 mov dx, # VGAREG_GRDC_ADDRESS
901
 out dx, ax
902
 mov ax, #0x0004
903
 out dx, ax
904
 mov ax, #0x1005
905
 out dx, ax
906
ASM_END
907
}
908
 
909
ASM_START
910
idiv_u:
911
  xor dx,dx
912
  div bx
913
  ret
914
ASM_END
915
 
916
static void set_scan_lines(lines) Bit8u lines;
917
{
918
 Bit16u crtc_addr,cols,page,vde;
919
 Bit8u crtc_r9,ovl,rows;
920
 
921
 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
922
 outb(crtc_addr, 0x09);
923
 crtc_r9 = inb(crtc_addr+1);
924
 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
925
 outb(crtc_addr+1, crtc_r9);
926
/*
927
 if(lines==8)
928
  {
929
   biosfn_set_cursor_shape(0x06,0x07);
930
  }
931
 else
932
  {
933
   biosfn_set_cursor_shape(lines-4,lines-3);
934
  }
935
*/
936
 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
937
 outb(crtc_addr, 0x12);
938
 vde = inb(crtc_addr+1);
939
 outb(crtc_addr, 0x07);
940
 ovl = inb(crtc_addr+1);
941
 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
942
 rows = vde / lines;
943
 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
944
 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
945
 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
946
}
947
 
948
// --------------------------------------------------------------------------------------------
949
ASM_START
950
biosfn_set_text_block_specifier:
951
  push  ax
952
  push  dx
953
  mov   dx, # VGAREG_SEQU_ADDRESS
954
  mov   ah, bl
955
  mov   al, #0x03
956
  out   dx, ax
957
  pop   dx
958
  pop   ax
959
  ret
960
ASM_END
961
 
962
// --------------------------------------------------------------------------------------------
963
static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
964
{
965
 Bit16u blockaddr,dest,i,src;
966
 
967
 get_font_access();
968
 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
969
 for(i=0;i<0x100;i++)
970
  {
971
   src = i * 16;
972
   dest = blockaddr + i * 32;
973
   memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
974
  }
975
 release_font_access();
976
 if(AL>=0x10)
977
  {
978
   set_scan_lines(16);
979
  }
980
}
981
 
982
// --------------------------------------------------------------------------------------------
983
static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
984 34 zeus
Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
985
{
986
 Bit16u newcurs,oldcurs,dummy;
987
 Bit8u car,carattr;
988
 
989
 // Read curs info for the page
990
 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
991
 
992
 // if row=0xff special case : use current cursor position
993
 if(row==0xff)
994
  {col=oldcurs&0x00ff;
995
   row=(oldcurs&0xff00)>>8;
996
  }
997
 
998
 newcurs=row; newcurs<<=8; newcurs+=col;
999
 biosfn_set_cursor_pos(page,newcurs);
1000 39 zeus
 
1001 34 zeus
 while(count--!=0)
1002
  {
1003
   car=read_byte(seg,offset++);
1004
   if((flag&0x02)!=0)
1005
    attr=read_byte(seg,offset++);
1006
 
1007
   biosfn_write_teletype(car,page,attr,WITH_ATTR);
1008
  }
1009 39 zeus
 
1010
 // Set back curs pos
1011 34 zeus
 if((flag&0x01)==0)
1012
  biosfn_set_cursor_pos(page,oldcurs);
1013
}
1014
 
1015
// ============================================================================================
1016
//
1017
// Video Utils
1018
//
1019
// ============================================================================================
1020 39 zeus
 
1021 34 zeus
// --------------------------------------------------------------------------------------------
1022 39 zeus
static Bit8u find_vga_entry(mode)
1023 34 zeus
Bit8u mode;
1024
{
1025
 Bit8u i,line=0xFF;
1026
 for(i=0;i<=MODE_MAX;i++)
1027
  if(vga_modes[i].svgamode==mode)
1028
   {line=i;
1029
    break;
1030
   }
1031
 return line;
1032
}
1033
 
1034
// --------------------------------------------------------------------------------------------
1035
static void memsetw(seg,offset,value,count)
1036
  Bit16u seg;
1037
  Bit16u offset;
1038
  Bit16u value;
1039
  Bit16u count;
1040
{
1041
ASM_START
1042
  push bp
1043
  mov  bp, sp
1044
 
1045
    push ax
1046
    push cx
1047
    push es
1048
    push di
1049
 
1050
    mov  cx, 10[bp] ; count
1051
    cmp  cx, #0x00
1052
    je   memsetw_end
1053
    mov  ax, 4[bp] ; segment
1054
    mov  es, ax
1055
    mov  ax, 6[bp] ; offset
1056
    mov  di, ax
1057
    mov  ax, 8[bp] ; value
1058
    cld
1059
    rep
1060
     stosw
1061
 
1062
memsetw_end:
1063
    pop di
1064
    pop es
1065
    pop cx
1066
    pop ax
1067
 
1068
  pop bp
1069
ASM_END
1070
}
1071
 
1072
// --------------------------------------------------------------------------------------------
1073 39 zeus
static void memcpyb(dseg,doffset,sseg,soffset,count)
1074
  Bit16u dseg;
1075
  Bit16u doffset;
1076
  Bit16u sseg;
1077
  Bit16u soffset;
1078
  Bit16u count;
1079
{
1080
ASM_START
1081
  push bp
1082
  mov  bp, sp
1083
 
1084
    push ax
1085
    push cx
1086
    push es
1087
    push di
1088
    push ds
1089
    push si
1090
 
1091
    mov  cx, 12[bp] ; count
1092
    cmp  cx, #0x0000
1093
    je   memcpyb_end
1094
    mov  ax, 4[bp] ; dsegment
1095
    mov  es, ax
1096
    mov  ax, 6[bp] ; doffset
1097
    mov  di, ax
1098
    mov  ax, 8[bp] ; ssegment
1099
    mov  ds, ax
1100
    mov  ax, 10[bp] ; soffset
1101
    mov  si, ax
1102
    cld
1103
    rep
1104
     movsb
1105
 
1106
memcpyb_end:
1107
    pop si
1108
    pop ds
1109
    pop di
1110
    pop es
1111
    pop cx
1112
    pop ax
1113
 
1114
  pop bp
1115
ASM_END
1116
}
1117
 
1118
// --------------------------------------------------------------------------------------------
1119 34 zeus
static void memcpyw(dseg,doffset,sseg,soffset,count)
1120
  Bit16u dseg;
1121
  Bit16u doffset;
1122
  Bit16u sseg;
1123
  Bit16u soffset;
1124
  Bit16u count;
1125
{
1126
ASM_START
1127
  push bp
1128
  mov  bp, sp
1129
 
1130
    push ax
1131
    push cx
1132
    push es
1133
    push di
1134
    push ds
1135
    push si
1136
 
1137
    mov  cx, 12[bp] ; count
1138
    cmp  cx, #0x0000
1139
    je   memcpyw_end
1140
    mov  ax, 4[bp] ; dsegment
1141
    mov  es, ax
1142
    mov  ax, 6[bp] ; doffset
1143
    mov  di, ax
1144
    mov  ax, 8[bp] ; ssegment
1145
    mov  ds, ax
1146
    mov  ax, 10[bp] ; soffset
1147
    mov  si, ax
1148
    cld
1149
    rep
1150
     movsw
1151
 
1152
memcpyw_end:
1153
    pop si
1154
    pop ds
1155
    pop di
1156
    pop es
1157
    pop cx
1158
    pop ax
1159
 
1160
  pop bp
1161
ASM_END
1162
}
1163
 
1164
// --------------------------------------------------------------------------------------------
1165
static Bit8u
1166
read_byte(seg, offset)
1167
  Bit16u seg;
1168
  Bit16u offset;
1169
{
1170
ASM_START
1171
  push bp
1172
  mov  bp, sp
1173
 
1174
    push bx
1175
    push ds
1176
    mov  ax, 4[bp] ; segment
1177
    mov  ds, ax
1178
    mov  bx, 6[bp] ; offset
1179
    mov  al, [bx]
1180
    ;; al = return value (byte)
1181
    pop  ds
1182
    pop  bx
1183
 
1184
  pop  bp
1185
ASM_END
1186
}
1187
 
1188
// --------------------------------------------------------------------------------------------
1189
static Bit16u
1190
read_word(seg, offset)
1191
  Bit16u seg;
1192
  Bit16u offset;
1193
{
1194
ASM_START
1195
  push bp
1196
  mov  bp, sp
1197
 
1198
    push bx
1199
    push ds
1200
    mov  ax, 4[bp] ; segment
1201
    mov  ds, ax
1202
    mov  bx, 6[bp] ; offset
1203
    mov  ax, [bx]
1204
    ;; ax = return value (word)
1205
    pop  ds
1206
    pop  bx
1207
 
1208
  pop  bp
1209
ASM_END
1210
}
1211
 
1212
// --------------------------------------------------------------------------------------------
1213
static void
1214
write_byte(seg, offset, data)
1215
  Bit16u seg;
1216
  Bit16u offset;
1217
  Bit8u  data;
1218
{
1219
ASM_START
1220
  push bp
1221
  mov  bp, sp
1222
 
1223
    push ax
1224
    push bx
1225
    push ds
1226
    mov  ax, 4[bp] ; segment
1227
    mov  ds, ax
1228
    mov  bx, 6[bp] ; offset
1229
    mov  al, 8[bp] ; data byte
1230
    mov  [bx], al  ; write data byte
1231
    pop  ds
1232
    pop  bx
1233
    pop  ax
1234
 
1235
  pop  bp
1236
ASM_END
1237
}
1238
 
1239
// --------------------------------------------------------------------------------------------
1240
static void
1241
write_word(seg, offset, data)
1242
  Bit16u seg;
1243
  Bit16u offset;
1244
  Bit16u data;
1245
{
1246
ASM_START
1247
  push bp
1248
  mov  bp, sp
1249
 
1250
    push ax
1251
    push bx
1252
    push ds
1253
    mov  ax, 4[bp] ; segment
1254
    mov  ds, ax
1255
    mov  bx, 6[bp] ; offset
1256
    mov  ax, 8[bp] ; data word
1257
    mov  [bx], ax  ; write data word
1258
    pop  ds
1259
    pop  bx
1260
    pop  ax
1261
 
1262
  pop  bp
1263
ASM_END
1264
}
1265
 
1266
// --------------------------------------------------------------------------------------------
1267
 Bit8u
1268
inb(port)
1269
  Bit16u port;
1270
{
1271
ASM_START
1272
  push bp
1273
  mov  bp, sp
1274
 
1275
    push dx
1276
    mov  dx, 4[bp]
1277
    in   al, dx
1278
    pop  dx
1279
 
1280
  pop  bp
1281
ASM_END
1282
}
1283
 
1284
  Bit16u
1285
inw(port)
1286
  Bit16u port;
1287
{
1288
ASM_START
1289
  push bp
1290
  mov  bp, sp
1291
 
1292
    push dx
1293
    mov  dx, 4[bp]
1294
    in   ax, dx
1295
    pop  dx
1296
 
1297
  pop  bp
1298
ASM_END
1299
}
1300
 
1301
// --------------------------------------------------------------------------------------------
1302
  void
1303
outb(port, val)
1304
  Bit16u port;
1305
  Bit8u  val;
1306
{
1307
ASM_START
1308
  push bp
1309
  mov  bp, sp
1310
 
1311
    push ax
1312
    push dx
1313
    mov  dx, 4[bp]
1314
    mov  al, 6[bp]
1315
    out  dx, al
1316
    pop  dx
1317
    pop  ax
1318
 
1319
  pop  bp
1320
ASM_END
1321
}
1322
 
1323
// --------------------------------------------------------------------------------------------
1324
  void
1325
outw(port, val)
1326
  Bit16u port;
1327
  Bit16u  val;
1328
{
1329
ASM_START
1330
  push bp
1331
  mov  bp, sp
1332
 
1333
    push ax
1334
    push dx
1335
    mov  dx, 4[bp]
1336
    mov  ax, 6[bp]
1337
    out  dx, ax
1338
    pop  dx
1339
    pop  ax
1340
 
1341
  pop  bp
1342
ASM_END
1343
}
1344
 
1345
Bit16u get_SS()
1346
{
1347
ASM_START
1348
  mov  ax, ss
1349
ASM_END
1350
}
1351
 
1352 39 zeus
void printf(s)
1353
  Bit8u *s;
1354
{
1355
  Bit8u c, format_char;
1356
  Boolean  in_format;
1357
  unsigned format_width, i;
1358
  Bit16u  *arg_ptr;
1359
  Bit16u   arg_seg, arg, digit, nibble, shift_count;
1360
 
1361
  arg_ptr = &s;
1362
  arg_seg = get_SS();
1363
 
1364
  in_format = 0;
1365
  format_width = 0;
1366
 
1367
  while (c = read_byte(0xc000, s)) {
1368
    if ( c == '%' ) {
1369
      in_format = 1;
1370
      format_width = 0;
1371
      }
1372
    else if (in_format) {
1373
      if ( (c>='0') && (c<='9') ) {
1374
        format_width = (format_width * 10) + (c - '0');
1375
        }
1376
      else if (c == 'x') {
1377
        arg_ptr++; // increment to next arg
1378
        arg = read_word(arg_seg, arg_ptr);
1379
        if (format_width == 0)
1380
          format_width = 4;
1381
        i = 0;
1382
        digit = format_width - 1;
1383
        for (i=0; i<format_width; i++) {
1384
          nibble = (arg >> (4 * digit)) & 0x000f;
1385
          if (nibble <= 9)
1386
            outb(0x0500, nibble + '0');
1387
          else
1388
            outb(0x0500, (nibble - 10) + 'A');
1389
          digit--;
1390
          }
1391
        in_format = 0;
1392
        }
1393
      //else if (c == 'd') {
1394
      //  in_format = 0;
1395
      //  }
1396
      }
1397
    else {
1398
      outb(0x0500, c);
1399
      }
1400
    s ++;
1401
    }
1402
}
1403
 
1404 34 zeus
// --------------------------------------------------------------------------------------------
1405
 
1406 39 zeus
ASM_START
1407 34 zeus
;; DATA_SEG_DEFS_HERE
1408
ASM_END
1409
 
1410
ASM_START
1411
.ascii "vgabios ends here"
1412
.byte  0x00
1413
vgabios_end:
1414
.byte 0xCB
1415
;; BLOCK_STRINGS_BEGIN
1416
ASM_END

powered by: WebSVN 2.1.0

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