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

Subversion Repositories zet86

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

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

powered by: WebSVN 2.1.0

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