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

Subversion Repositories zet86

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

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

powered by: WebSVN 2.1.0

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