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

Subversion Repositories zet86

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

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

powered by: WebSVN 2.1.0

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