00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 #define DEBUG_ROMBIOS 1
00126
00127 #define DEBUG_ATA 0
00128 #define DEBUG_INT13_HD 0
00129 #define DEBUG_INT13_CD 0
00130 #define DEBUG_INT13_ET 0
00131 #define DEBUG_INT13_FL 0
00132 #define DEBUG_INT15 0
00133 #define DEBUG_INT16 0
00134 #define DEBUG_INT1A 0
00135 #define DEBUG_INT74 0
00136 #define DEBUG_APM 0
00137
00138 #define BX_CPU 3
00139 #define BX_USE_PS2_MOUSE 1
00140 #define BX_CALL_INT15_4F 1
00141 #define BX_USE_EBDA 1
00142 #define BX_SUPPORT_FLOPPY 1
00143 #define BX_FLOPPY_ON_CNT 37
00144
00145 #define BX_APM 0
00146
00147 #define COREBOOT 1
00148
00149 #define BX_USE_ATADRV 1
00150
00151
00152 #define BX_MAX_ATA_INTERFACES 4
00153 #define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2)
00154
00155 #define BX_VIRTUAL_PORTS 1
00156 #define BX_DEBUG_SERIAL 1
00157
00158
00159 #define SYS_MODEL_ID 0xFC
00160 #define SYS_SUBMODEL_ID 0x00
00161 #define BIOS_REVISION 1
00162 #define BIOS_CONFIG_TABLE 0xe6f5
00163
00164 #ifndef BIOS_BUILD_DATE
00165 # define BIOS_BUILD_DATE "06/23/99"
00166 #endif
00167
00168
00169
00170 #define EBDA_SEG 0x9FC0
00171 #define EBDA_SIZE 1 // In KiB
00172 #define BASE_MEM_IN_K (640 - EBDA_SIZE)
00173
00174
00175 #ifdef PLEX86
00176 # define BX_APPNAME "Plex86"
00177 #else
00178 # define BX_APPNAME "Bochs"
00179 #endif
00180
00181
00182 #if BX_USE_ATADRV && BX_CPU<3
00183 # error The ATA/ATAPI Driver can only to be used with a 386+ cpu
00184 #endif
00185 #if BX_USE_ATADRV && !BX_USE_EBDA
00186 # error ATA/ATAPI Driver can only be used if EBDA is available
00187 #endif
00188 #if BX_ELTORITO_BOOT && !BX_USE_ATADRV
00189 # error El-Torito Boot can only be use if ATA/ATAPI Driver is available
00190 #endif
00191 #if BX_PCIBIOS && BX_CPU<3
00192 # error PCI BIOS can only be used with 386+ cpu
00193 #endif
00194 #if BX_APM && BX_CPU<3
00195 # error APM BIOS can only be used with 386+ cpu
00196 #endif
00197
00198 #define PANIC_PORT 0x400
00199 #define PANIC_PORT2 0x401
00200 #define INFO_PORT 0x402
00201 #define DEBUG_PORT 0x403
00202
00203
00204
00205
00206 #define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 #define ASM_START #asm
00224 #define ASM_END #endasm
00225
00226 ASM_START
00227 .rom
00228
00229 .org 0x0000
00230
00231 #if BX_CPU >= 3
00232 use16 386
00233 #else
00234 use16 286
00235 #endif
00236
00237 MACRO HALT
00238 ;; the HALT macro is called with the line number of the HALT call.
00239 ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
00240 ;; to print a BX_PANIC message. This will normally halt the simulation
00241 ;; with a message such as "BIOS panic at rombios.c, line 4091".
00242 ;; However, users can choose to make panics non-fatal and continue.
00243 #if BX_VIRTUAL_PORTS
00244 mov dx,#PANIC_PORT
00245 mov ax,#?1
00246 out dx,ax
00247 #else
00248 mov dx,#0x80
00249 mov ax,#?1
00250 out dx,al
00251 #endif
00252 MEND
00253
00254 MACRO JMP_AP
00255 db 0xea
00256 dw ?2
00257 dw ?1
00258 MEND
00259
00260 MACRO SET_INT_VECTOR
00261 mov ax, ?3
00262 mov ?1*4, ax
00263 mov ax, ?2
00264 mov ?1*4+2, ax
00265 MEND
00266
00267 ASM_END
00268
00269 typedef unsigned char Bit8u;
00270 typedef unsigned short Bit16u;
00271 typedef unsigned short bx_bool;
00272 typedef unsigned long Bit32u;
00273
00274 #if BX_USE_ATADRV
00275
00276 void memsetb(seg,offset,value,count);
00277 void memcpyb(dseg,doffset,sseg,soffset,count);
00278 void memcpyd(dseg,doffset,sseg,soffset,count);
00279
00280
00281 void
00282 memsetb(seg,offset,value,count)
00283 Bit16u seg;
00284 Bit16u offset;
00285 Bit16u value;
00286 Bit16u count;
00287 {
00288 ASM_START
00289 push bp
00290 mov bp, sp
00291
00292 push ax
00293 push cx
00294 push es
00295 push di
00296
00297 mov cx, 10[bp] ; count
00298 cmp cx, #0x00
00299 je memsetb_end
00300 mov ax, 4[bp] ; segment
00301 mov es, ax
00302 mov ax, 6[bp] ; offset
00303 mov di, ax
00304 mov al, 8[bp] ; value
00305 cld
00306 rep
00307 stosb
00308
00309 memsetb_end:
00310 pop di
00311 pop es
00312 pop cx
00313 pop ax
00314
00315 pop bp
00316 ASM_END
00317 }
00318
00319 #if 0
00320
00321 void
00322 memcpyb(dseg,doffset,sseg,soffset,count)
00323 Bit16u dseg;
00324 Bit16u doffset;
00325 Bit16u sseg;
00326 Bit16u soffset;
00327 Bit16u count;
00328 {
00329 ASM_START
00330 push bp
00331 mov bp, sp
00332
00333 push ax
00334 push cx
00335 push es
00336 push di
00337 push ds
00338 push si
00339
00340 mov cx, 12[bp] ; count
00341 cmp cx, #0x0000
00342 je memcpyb_end
00343 mov ax, 4[bp] ; dsegment
00344 mov es, ax
00345 mov ax, 6[bp] ; doffset
00346 mov di, ax
00347 mov ax, 8[bp] ; ssegment
00348 mov ds, ax
00349 mov ax, 10[bp] ; soffset
00350 mov si, ax
00351 cld
00352 rep
00353 movsb
00354
00355 memcpyb_end:
00356 pop si
00357 pop ds
00358 pop di
00359 pop es
00360 pop cx
00361 pop ax
00362
00363 pop bp
00364 ASM_END
00365 }
00366
00367
00368 void
00369 memcpyd(dseg,doffset,sseg,soffset,count)
00370 Bit16u dseg;
00371 Bit16u doffset;
00372 Bit16u sseg;
00373 Bit16u soffset;
00374 Bit16u count;
00375 {
00376 ASM_START
00377 push bp
00378 mov bp, sp
00379
00380 push ax
00381 push cx
00382 push es
00383 push di
00384 push ds
00385 push si
00386
00387 mov cx, 12[bp] ; count
00388 cmp cx, #0x0000
00389 je memcpyd_end
00390 mov ax, 4[bp] ; dsegment
00391 mov es, ax
00392 mov ax, 6[bp] ; doffset
00393 mov di, ax
00394 mov ax, 8[bp] ; ssegment
00395 mov ds, ax
00396 mov ax, 10[bp] ; soffset
00397 mov si, ax
00398 cld
00399 rep
00400 movsd
00401
00402 memcpyd_end:
00403 pop si
00404 pop ds
00405 pop di
00406 pop es
00407 pop cx
00408 pop ax
00409
00410 pop bp
00411 ASM_END
00412 }
00413 #endif
00414 #endif //BX_USE_ATADRV
00415
00416
00417 static Bit32u read_dword();
00418 static void write_dword();
00419
00420 Bit32u
00421 read_dword(seg, offset)
00422 Bit16u seg;
00423 Bit16u offset;
00424 {
00425 ASM_START
00426 push bp
00427 mov bp, sp
00428
00429 push bx
00430 push ds
00431 mov ax, 4[bp] ; segment
00432 mov ds, ax
00433 mov bx, 6[bp] ; offset
00434 mov ax, [bx]
00435 inc bx
00436 inc bx
00437 mov dx, [bx]
00438 ;; ax = return value (word)
00439 ;; dx = return value (word)
00440 pop ds
00441 pop bx
00442
00443 pop bp
00444 ASM_END
00445 }
00446
00447 void
00448 write_dword(seg, offset, data)
00449 Bit16u seg;
00450 Bit16u offset;
00451 Bit32u data;
00452 {
00453 ASM_START
00454 push bp
00455 mov bp, sp
00456
00457 push ax
00458 push bx
00459 push ds
00460 mov ax, 4[bp] ; segment
00461 mov ds, ax
00462 mov bx, 6[bp] ; offset
00463 mov ax, 8[bp] ; data word
00464 mov [bx], ax ; write data word
00465 inc bx
00466 inc bx
00467 mov ax, 10[bp] ; data word
00468 mov [bx], ax ; write data word
00469 pop ds
00470 pop bx
00471 pop ax
00472
00473 pop bp
00474 ASM_END
00475 }
00476
00477
00478 ASM_START
00479
00480 ;; and function
00481 landl:
00482 landul:
00483 SEG SS
00484 and ax,[di]
00485 SEG SS
00486 and bx,2[di]
00487 ret
00488
00489 ;; add function
00490 laddl:
00491 laddul:
00492 SEG SS
00493 add ax,[di]
00494 SEG SS
00495 adc bx,2[di]
00496 ret
00497
00498 ;; cmp function
00499 lcmpl:
00500 lcmpul:
00501 and eax, #0x0000FFFF
00502 shl ebx, #16
00503 add eax, ebx
00504 shr ebx, #16
00505 SEG SS
00506 cmp eax, dword ptr [di]
00507 ret
00508
00509 ;; sub function
00510 lsubl:
00511 lsubul:
00512 SEG SS
00513 sub ax,[di]
00514 SEG SS
00515 sbb bx,2[di]
00516 ret
00517
00518 ;; mul function
00519 lmull:
00520 lmulul:
00521 and eax, #0x0000FFFF
00522 shl ebx, #16
00523 add eax, ebx
00524 SEG SS
00525 mul eax, dword ptr [di]
00526 mov ebx, eax
00527 shr ebx, #16
00528 ret
00529
00530 ;; dec function
00531 ldecl:
00532 ldecul:
00533 SEG SS
00534 dec dword ptr [bx]
00535 ret
00536
00537 ;; or function
00538 lorl:
00539 lorul:
00540 SEG SS
00541 or ax,[di]
00542 SEG SS
00543 or bx,2[di]
00544 ret
00545
00546 ;; inc function
00547 lincl:
00548 lincul:
00549 SEG SS
00550 inc dword ptr [bx]
00551 ret
00552
00553 ;; tst function
00554 ltstl:
00555 ltstul:
00556 and eax, #0x0000FFFF
00557 shl ebx, #16
00558 add eax, ebx
00559 shr ebx, #16
00560 test eax, eax
00561 ret
00562
00563 ;; sr function
00564 lsrul:
00565 mov cx,di
00566 jcxz lsr_exit
00567 and eax, #0x0000FFFF
00568 shl ebx, #16
00569 add eax, ebx
00570 lsr_loop:
00571 shr eax, #1
00572 loop lsr_loop
00573 mov ebx, eax
00574 shr ebx, #16
00575 lsr_exit:
00576 ret
00577
00578 ;; sl function
00579 lsll:
00580 lslul:
00581 mov cx,di
00582 jcxz lsl_exit
00583 and eax, #0x0000FFFF
00584 shl ebx, #16
00585 add eax, ebx
00586 lsl_loop:
00587 shl eax, #1
00588 loop lsl_loop
00589 mov ebx, eax
00590 shr ebx, #16
00591 lsl_exit:
00592 ret
00593
00594 idiv_:
00595 cwd
00596 idiv bx
00597 ret
00598
00599 idiv_u:
00600 xor dx,dx
00601 div bx
00602 ret
00603
00604 ldivul:
00605 and eax, #0x0000FFFF
00606 shl ebx, #16
00607 add eax, ebx
00608 xor edx, edx
00609 SEG SS
00610 mov bx, 2[di]
00611 shl ebx, #16
00612 SEG SS
00613 mov bx, [di]
00614 div ebx
00615 mov ebx, eax
00616 shr ebx, #16
00617 ret
00618
00619 ASM_END
00620
00621
00622
00623
00624 typedef struct {
00625 unsigned char filler1[0x400];
00626 unsigned char filler2[0x6c];
00627 Bit16u ticks_low;
00628 Bit16u ticks_high;
00629 Bit8u midnight_flag;
00630 } bios_data_t;
00631
00632 #define BiosData ((bios_data_t *) 0)
00633
00634 #if BX_USE_ATADRV
00635 typedef struct {
00636 Bit16u heads;
00637 Bit16u cylinders;
00638 Bit16u spt;
00639 } chs_t;
00640
00641
00642 typedef struct {
00643 Bit16u iobase1;
00644 Bit16u iobase2;
00645 Bit8u prefix;
00646 Bit8u unused;
00647 Bit8u irq;
00648 Bit8u blkcount;
00649 Bit8u dma;
00650 Bit8u pio;
00651 Bit16u options;
00652 Bit16u reserved;
00653 Bit8u revision;
00654 Bit8u checksum;
00655 } dpte_t;
00656
00657 typedef struct {
00658 Bit8u iface;
00659 Bit16u iobase1;
00660 Bit16u iobase2;
00661 Bit8u irq;
00662 } ata_channel_t;
00663
00664 typedef struct {
00665 Bit8u type;
00666 Bit8u device;
00667 Bit8u removable;
00668 Bit8u lock;
00669
00670 Bit8u mode;
00671 Bit16u blksize;
00672
00673 Bit8u translation;
00674 chs_t lchs;
00675 chs_t pchs;
00676
00677 Bit32u sectors;
00678 } ata_device_t;
00679
00680 typedef struct {
00681
00682 ata_channel_t channels[BX_MAX_ATA_INTERFACES];
00683
00684
00685 ata_device_t devices[BX_MAX_ATA_DEVICES];
00686
00687
00688 Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES];
00689
00690
00691 Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES];
00692
00693
00694 dpte_t dpte;
00695
00696
00697 Bit16u trsfsectors;
00698 Bit32u trsfbytes;
00699
00700 } ata_t;
00701
00702 #if BX_ELTORITO_BOOT
00703
00704 typedef struct {
00705 Bit8u active;
00706 Bit8u media;
00707 Bit8u emulated_drive;
00708 Bit8u controller_index;
00709 Bit16u device_spec;
00710 Bit32u ilba;
00711 Bit16u buffer_segment;
00712 Bit16u load_segment;
00713 Bit16u sector_count;
00714
00715
00716 chs_t vdevice;
00717 } cdemu_t;
00718 #endif // BX_ELTORITO_BOOT
00719
00720
00721
00722
00723
00724 typedef struct {
00725 unsigned char filler1[0x3D];
00726
00727
00728 unsigned char fdpt0[0x10];
00729 unsigned char fdpt1[0x10];
00730
00731 unsigned char filler2[0xC4];
00732
00733
00734 ata_t ata;
00735
00736 #if BX_ELTORITO_BOOT
00737
00738 cdemu_t cdemu;
00739 #endif // BX_ELTORITO_BOOT
00740
00741 } ebda_data_t;
00742
00743 #define EbdaData ((ebda_data_t *) 0)
00744
00745
00746 typedef struct {
00747 Bit8u size;
00748 Bit8u reserved;
00749 Bit16u count;
00750 Bit16u offset;
00751 Bit16u segment;
00752 Bit32u lba1;
00753 Bit32u lba2;
00754 } int13ext_t;
00755
00756 #define Int13Ext ((int13ext_t *) 0)
00757
00758
00759 typedef struct {
00760 Bit16u size;
00761 Bit16u infos;
00762 Bit32u cylinders;
00763 Bit32u heads;
00764 Bit32u spt;
00765 Bit32u sector_count1;
00766 Bit32u sector_count2;
00767 Bit16u blksize;
00768 Bit16u dpte_segment;
00769 Bit16u dpte_offset;
00770 Bit16u key;
00771 Bit8u dpi_length;
00772 Bit8u reserved1;
00773 Bit16u reserved2;
00774 Bit8u host_bus[4];
00775 Bit8u iface_type[8];
00776 Bit8u iface_path[8];
00777 Bit8u device_path[8];
00778 Bit8u reserved3;
00779 Bit8u checksum;
00780 } dpt_t;
00781
00782 #define Int13DPT ((dpt_t *) 0)
00783
00784 #endif // BX_USE_ATADRV
00785
00786 typedef struct {
00787 union {
00788 struct {
00789 Bit16u di, si, bp, sp;
00790 Bit16u bx, dx, cx, ax;
00791 } r16;
00792 struct {
00793 Bit16u filler[4];
00794 Bit8u bl, bh, dl, dh, cl, ch, al, ah;
00795 } r8;
00796 } u;
00797 } pusha_regs_t;
00798
00799 typedef struct {
00800 union {
00801 struct {
00802 Bit32u edi, esi, ebp, esp;
00803 Bit32u ebx, edx, ecx, eax;
00804 } r32;
00805 struct {
00806 Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4;
00807 Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8;
00808 } r16;
00809 struct {
00810 Bit32u filler[4];
00811 Bit8u bl, bh;
00812 Bit16u filler1;
00813 Bit8u dl, dh;
00814 Bit16u filler2;
00815 Bit8u cl, ch;
00816 Bit16u filler3;
00817 Bit8u al, ah;
00818 Bit16u filler4;
00819 } r8;
00820 } u;
00821 } pushad_regs_t;
00822
00823 typedef struct {
00824 union {
00825 struct {
00826 Bit16u flags;
00827 } r16;
00828 struct {
00829 Bit8u flagsl;
00830 Bit8u flagsh;
00831 } r8;
00832 } u;
00833 } flags_t;
00834
00835 #define SetCF(x) x.u.r8.flagsl |= 0x01
00836 #define SetZF(x) x.u.r8.flagsl |= 0x40
00837 #define ClearCF(x) x.u.r8.flagsl &= 0xfe
00838 #define ClearZF(x) x.u.r8.flagsl &= 0xbf
00839 #define GetCF(x) (x.u.r8.flagsl & 0x01)
00840
00841 typedef struct {
00842 Bit16u ip;
00843 Bit16u cs;
00844 flags_t flags;
00845 } iret_addr_t;
00846
00847
00848
00849 static Bit8u inb();
00850 static Bit8u inb_cmos();
00851 static void outb();
00852 static void outb_cmos();
00853 static Bit16u inw();
00854 static void outw();
00855 static void init_rtc();
00856 static bx_bool rtc_updating();
00857
00858 static Bit8u read_byte();
00859 static Bit16u read_word();
00860 static void write_byte();
00861 static void write_word();
00862 static void bios_printf();
00863
00864 static Bit8u inhibit_mouse_int_and_events();
00865 static void enable_mouse_int_and_events();
00866 static Bit8u send_to_mouse_ctrl();
00867 static Bit8u get_mouse_data();
00868 static void set_kbd_command_byte();
00869
00870 static void int09_function();
00871 static void int13_harddisk();
00872 static void int13_cdrom();
00873 static void int13_cdemu();
00874 static void int13_eltorito();
00875 static void int13_diskette_function();
00876 static void int14_function();
00877 static void int15_function();
00878 static void int16_function();
00879 static void int17_function();
00880 static Bit32u int19_function();
00881 static void int1a_function();
00882 static void int70_function();
00883 static void int74_function();
00884 static Bit16u get_CS();
00885 static Bit16u get_SS();
00886 static unsigned int enqueue_key();
00887 static unsigned int dequeue_key();
00888 static void get_hd_geometry();
00889 static void set_diskette_ret_status();
00890 static void set_diskette_current_cyl();
00891 static void determine_floppy_media();
00892 static bx_bool floppy_drive_exists();
00893 static bx_bool floppy_drive_recal();
00894 static bx_bool floppy_media_known();
00895 static bx_bool floppy_media_sense();
00896 static bx_bool set_enable_a20();
00897 static void debugger_on();
00898 static void debugger_off();
00899 static void keyboard_init();
00900 static void keyboard_panic();
00901 static void shutdown_status_panic();
00902 static void nmi_handler_msg();
00903
00904 static void print_bios_banner();
00905 static void print_boot_device();
00906 static void print_boot_failure();
00907 static void print_cdromboot_failure();
00908
00909 # if BX_USE_ATADRV
00910
00911
00912 void ata_init();
00913 void ata_detect();
00914 void ata_reset();
00915
00916 Bit16u ata_cmd_non_data();
00917 Bit16u ata_cmd_data_in();
00918 Bit16u ata_cmd_data_out();
00919 Bit16u ata_cmd_packet();
00920
00921 Bit16u atapi_get_sense();
00922 Bit16u atapi_is_ready();
00923 Bit16u atapi_is_cdrom();
00924
00925 #endif // BX_USE_ATADRV
00926
00927 #if BX_ELTORITO_BOOT
00928
00929 void cdemu_init();
00930 Bit8u cdemu_isactive();
00931 Bit8u cdemu_emulated_drive();
00932
00933 Bit16u cdrom_boot();
00934
00935 #endif // BX_ELTORITO_BOOT
00936
00937 static char bios_cvs_version_string[] = "$Revision: 1.163 $ $Date: 2006/07/07 16:10:37 $";
00938
00939 #define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
00940
00941 #define BIOS_PRINTF_HALT 1
00942 #define BIOS_PRINTF_SCREEN 2
00943 #define BIOS_PRINTF_INFO 4
00944 #define BIOS_PRINTF_DEBUG 8
00945 #define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
00946 #define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
00947
00948 #define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
00949
00950
00951
00952
00953 #if DEBUG_ROMBIOS
00954 # define BX_DEBUG(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
00955 #else
00956 # define BX_DEBUG(format, p...)
00957 #endif
00958 #define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p)
00959 #define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
00960
00961 #if DEBUG_ATA
00962 # define BX_DEBUG_ATA(a...) BX_DEBUG(a)
00963 #else
00964 # define BX_DEBUG_ATA(a...)
00965 #endif
00966 #if DEBUG_INT13_HD
00967 # define BX_DEBUG_INT13_HD(a...) BX_DEBUG(a)
00968 #else
00969 # define BX_DEBUG_INT13_HD(a...)
00970 #endif
00971 #if DEBUG_INT13_CD
00972 # define BX_DEBUG_INT13_CD(a...) BX_DEBUG(a)
00973 #else
00974 # define BX_DEBUG_INT13_CD(a...)
00975 #endif
00976 #if DEBUG_INT13_ET
00977 # define BX_DEBUG_INT13_ET(a...) BX_DEBUG(a)
00978 #else
00979 # define BX_DEBUG_INT13_ET(a...)
00980 #endif
00981 #if DEBUG_INT13_FL
00982 # define BX_DEBUG_INT13_FL(a...) BX_DEBUG(a)
00983 #else
00984 # define BX_DEBUG_INT13_FL(a...)
00985 #endif
00986 #if DEBUG_INT15
00987 # define BX_DEBUG_INT15(a...) BX_DEBUG(a)
00988 #else
00989 # define BX_DEBUG_INT15(a...)
00990 #endif
00991 #if DEBUG_INT16
00992 # define BX_DEBUG_INT16(a...) BX_DEBUG(a)
00993 #else
00994 # define BX_DEBUG_INT16(a...)
00995 #endif
00996 #if DEBUG_INT1A
00997 # define BX_DEBUG_INT1A(a...) BX_DEBUG(a)
00998 #else
00999 # define BX_DEBUG_INT1A(a...)
01000 #endif
01001 #if DEBUG_INT74
01002 # define BX_DEBUG_INT74(a...) BX_DEBUG(a)
01003 #else
01004 # define BX_DEBUG_INT74(a...)
01005 #endif
01006
01007 #define SET_AL(val8) AX = ((AX & 0xff00) | (val8))
01008 #define SET_BL(val8) BX = ((BX & 0xff00) | (val8))
01009 #define SET_CL(val8) CX = ((CX & 0xff00) | (val8))
01010 #define SET_DL(val8) DX = ((DX & 0xff00) | (val8))
01011 #define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8))
01012 #define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8))
01013 #define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8))
01014 #define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8))
01015
01016 #define GET_AL() ( AX & 0x00ff )
01017 #define GET_BL() ( BX & 0x00ff )
01018 #define GET_CL() ( CX & 0x00ff )
01019 #define GET_DL() ( DX & 0x00ff )
01020 #define GET_AH() ( AX >> 8 )
01021 #define GET_BH() ( BX >> 8 )
01022 #define GET_CH() ( CX >> 8 )
01023 #define GET_DH() ( DX >> 8 )
01024
01025 #define GET_ELDL() ( ELDX & 0x00ff )
01026 #define GET_ELDH() ( ELDX >> 8 )
01027
01028 #define SET_CF() FLAGS |= 0x0001
01029 #define CLEAR_CF() FLAGS &= 0xfffe
01030 #define GET_CF() (FLAGS & 0x0001)
01031
01032 #define SET_ZF() FLAGS |= 0x0040
01033 #define CLEAR_ZF() FLAGS &= 0xffbf
01034 #define GET_ZF() (FLAGS & 0x0040)
01035
01036 #define UNSUPPORTED_FUNCTION 0x86
01037
01038 #define none 0
01039 #define MAX_SCAN_CODE 0x58
01040
01041 static struct {
01042 Bit16u normal;
01043 Bit16u shift;
01044 Bit16u control;
01045 Bit16u alt;
01046 Bit8u lock_flags;
01047 } scan_to_scanascii[MAX_SCAN_CODE + 1] = {
01048 { none, none, none, none, none },
01049 { 0x011b, 0x011b, 0x011b, 0x0100, none },
01050 { 0x0231, 0x0221, none, 0x7800, none },
01051 { 0x0332, 0x0340, 0x0300, 0x7900, none },
01052 { 0x0433, 0x0423, none, 0x7a00, none },
01053 { 0x0534, 0x0524, none, 0x7b00, none },
01054 { 0x0635, 0x0625, none, 0x7c00, none },
01055 { 0x0736, 0x075e, 0x071e, 0x7d00, none },
01056 { 0x0837, 0x0826, none, 0x7e00, none },
01057 { 0x0938, 0x092a, none, 0x7f00, none },
01058 { 0x0a39, 0x0a28, none, 0x8000, none },
01059 { 0x0b30, 0x0b29, none, 0x8100, none },
01060 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none },
01061 { 0x0d3d, 0x0d2b, none, 0x8300, none },
01062 { 0x0e08, 0x0e08, 0x0e7f, none, none },
01063 { 0x0f09, 0x0f00, none, none, none },
01064 { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 },
01065 { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 },
01066 { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 },
01067 { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 },
01068 { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 },
01069 { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 },
01070 { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 },
01071 { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 },
01072 { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 },
01073 { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 },
01074 { 0x1a5b, 0x1a7b, 0x1a1b, none, none },
01075 { 0x1b5d, 0x1b7d, 0x1b1d, none, none },
01076 { 0x1c0d, 0x1c0d, 0x1c0a, none, none },
01077 { none, none, none, none, none },
01078 { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 },
01079 { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 },
01080 { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 },
01081 { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 },
01082 { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 },
01083 { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 },
01084 { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 },
01085 { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 },
01086 { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 },
01087 { 0x273b, 0x273a, none, none, none },
01088 { 0x2827, 0x2822, none, none, none },
01089 { 0x2960, 0x297e, none, none, none },
01090 { none, none, none, none, none },
01091 { 0x2b5c, 0x2b7c, 0x2b1c, none, none },
01092 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 },
01093 { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 },
01094 { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 },
01095 { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 },
01096 { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 },
01097 { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 },
01098 { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 },
01099 { 0x332c, 0x333c, none, none, none },
01100 { 0x342e, 0x343e, none, none, none },
01101 { 0x352f, 0x353f, none, none, none },
01102 { none, none, none, none, none },
01103 { 0x372a, 0x372a, none, none, none },
01104 { none, none, none, none, none },
01105 { 0x3920, 0x3920, 0x3920, 0x3920, none },
01106 { none, none, none, none, none },
01107 { 0x3b00, 0x5400, 0x5e00, 0x6800, none },
01108 { 0x3c00, 0x5500, 0x5f00, 0x6900, none },
01109 { 0x3d00, 0x5600, 0x6000, 0x6a00, none },
01110 { 0x3e00, 0x5700, 0x6100, 0x6b00, none },
01111 { 0x3f00, 0x5800, 0x6200, 0x6c00, none },
01112 { 0x4000, 0x5900, 0x6300, 0x6d00, none },
01113 { 0x4100, 0x5a00, 0x6400, 0x6e00, none },
01114 { 0x4200, 0x5b00, 0x6500, 0x6f00, none },
01115 { 0x4300, 0x5c00, 0x6600, 0x7000, none },
01116 { 0x4400, 0x5d00, 0x6700, 0x7100, none },
01117 { none, none, none, none, none },
01118 { none, none, none, none, none },
01119 { 0x4700, 0x4737, 0x7700, none, 0x20 },
01120 { 0x4800, 0x4838, none, none, 0x20 },
01121 { 0x4900, 0x4939, 0x8400, none, 0x20 },
01122 { 0x4a2d, 0x4a2d, none, none, none },
01123 { 0x4b00, 0x4b34, 0x7300, none, 0x20 },
01124 { 0x4c00, 0x4c35, none, none, 0x20 },
01125 { 0x4d00, 0x4d36, 0x7400, none, 0x20 },
01126 { 0x4e2b, 0x4e2b, none, none, none },
01127 { 0x4f00, 0x4f31, 0x7500, none, 0x20 },
01128 { 0x5000, 0x5032, none, none, 0x20 },
01129 { 0x5100, 0x5133, 0x7600, none, 0x20 },
01130 { 0x5200, 0x5230, none, none, 0x20 },
01131 { 0x5300, 0x532e, none, none, 0x20 },
01132 { none, none, none, none, none },
01133 { none, none, none, none, none },
01134 { none, none, none, none, none },
01135 { 0x5700, 0x5700, none, none, none },
01136 { 0x5800, 0x5800, none, none, none }
01137 };
01138
01139 Bit8u
01140 inb(port)
01141 Bit16u port;
01142 {
01143 ASM_START
01144 push bp
01145 mov bp, sp
01146
01147 push dx
01148 mov dx, 4[bp]
01149 in al, dx
01150 pop dx
01151
01152 pop bp
01153 ASM_END
01154 }
01155
01156 #if BX_USE_ATADRV
01157 Bit16u
01158 inw(port)
01159 Bit16u port;
01160 {
01161 ASM_START
01162 push bp
01163 mov bp, sp
01164
01165 push dx
01166 mov dx, 4[bp]
01167 in ax, dx
01168 pop dx
01169
01170 pop bp
01171 ASM_END
01172 }
01173 #endif
01174
01175 void
01176 outb(port, val)
01177 Bit16u port;
01178 Bit8u val;
01179 {
01180 ASM_START
01181 push bp
01182 mov bp, sp
01183
01184 push ax
01185 push dx
01186 mov dx, 4[bp]
01187 mov al, 6[bp]
01188 out dx, al
01189 pop dx
01190 pop ax
01191
01192 pop bp
01193 ASM_END
01194 }
01195
01196 #if BX_USE_ATADRV
01197 void
01198 outw(port, val)
01199 Bit16u port;
01200 Bit16u val;
01201 {
01202 ASM_START
01203 push bp
01204 mov bp, sp
01205
01206 push ax
01207 push dx
01208 mov dx, 4[bp]
01209 mov ax, 6[bp]
01210 out dx, ax
01211 pop dx
01212 pop ax
01213
01214 pop bp
01215 ASM_END
01216 }
01217 #endif
01218
01219 void
01220 outb_cmos(cmos_reg, val)
01221 Bit8u cmos_reg;
01222 Bit8u val;
01223 {
01224 ASM_START
01225 push bp
01226 mov bp, sp
01227
01228 mov al, 4[bp] ;; cmos_reg
01229 out 0x70, al
01230 mov al, 6[bp] ;; val
01231 out 0x71, al
01232
01233 pop bp
01234 ASM_END
01235 }
01236
01237 Bit8u
01238 inb_cmos(cmos_reg)
01239 Bit8u cmos_reg;
01240 {
01241 ASM_START
01242 push bp
01243 mov bp, sp
01244
01245 mov al, 4[bp] ;; cmos_reg
01246 out 0x70, al
01247 in al, 0x71
01248
01249 pop bp
01250 ASM_END
01251 }
01252
01253 void
01254 init_rtc()
01255 {
01256 outb_cmos(0x0a, 0x26);
01257 outb_cmos(0x0b, 0x02);
01258 inb_cmos(0x0c);
01259 inb_cmos(0x0d);
01260 }
01261
01262 bx_bool
01263 rtc_updating()
01264 {
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 Bit16u count;
01275
01276 count = 25000;
01277 while (--count != 0) {
01278 if ( (inb_cmos(0x0a) & 0x80) == 0 )
01279 return(0);
01280 }
01281 return(1);
01282 }
01283
01284
01285 Bit8u
01286 read_byte(seg, offset)
01287 Bit16u seg;
01288 Bit16u offset;
01289 {
01290 ASM_START
01291 push bp
01292 mov bp, sp
01293
01294 push bx
01295 push ds
01296 mov ax, 4[bp] ; segment
01297 mov ds, ax
01298 mov bx, 6[bp] ; offset
01299 mov al, [bx]
01300 ;; al = return value (byte)
01301 pop ds
01302 pop bx
01303
01304 pop bp
01305 ASM_END
01306 }
01307
01308 Bit16u
01309 read_word(seg, offset)
01310 Bit16u seg;
01311 Bit16u offset;
01312 {
01313 ASM_START
01314 push bp
01315 mov bp, sp
01316
01317 push bx
01318 push ds
01319 mov ax, 4[bp] ; segment
01320 mov ds, ax
01321 mov bx, 6[bp] ; offset
01322 mov ax, [bx]
01323 ;; ax = return value (word)
01324 pop ds
01325 pop bx
01326
01327 pop bp
01328 ASM_END
01329 }
01330
01331 void
01332 write_byte(seg, offset, data)
01333 Bit16u seg;
01334 Bit16u offset;
01335 Bit8u data;
01336 {
01337 ASM_START
01338 push bp
01339 mov bp, sp
01340
01341 push ax
01342 push bx
01343 push ds
01344 mov ax, 4[bp] ; segment
01345 mov ds, ax
01346 mov bx, 6[bp] ; offset
01347 mov al, 8[bp] ; data byte
01348 mov [bx], al ; write data byte
01349 pop ds
01350 pop bx
01351 pop ax
01352
01353 pop bp
01354 ASM_END
01355 }
01356
01357 void
01358 write_word(seg, offset, data)
01359 Bit16u seg;
01360 Bit16u offset;
01361 Bit16u data;
01362 {
01363 ASM_START
01364 push bp
01365 mov bp, sp
01366
01367 push ax
01368 push bx
01369 push ds
01370 mov ax, 4[bp] ; segment
01371 mov ds, ax
01372 mov bx, 6[bp] ; offset
01373 mov ax, 8[bp] ; data word
01374 mov [bx], ax ; write data word
01375 pop ds
01376 pop bx
01377 pop ax
01378
01379 pop bp
01380 ASM_END
01381 }
01382
01383 Bit16u
01384 get_CS()
01385 {
01386 ASM_START
01387 mov ax, cs
01388 ASM_END
01389 }
01390
01391 Bit16u
01392 get_SS()
01393 {
01394 ASM_START
01395 mov ax, ss
01396 ASM_END
01397 }
01398
01399 #if BX_DEBUG_SERIAL
01400
01401 #define BX_DEBUG_PORT 0x03f8
01402
01403
01404 #define UART_RBR 0x00
01405 #define UART_THR 0x00
01406
01407
01408 #define UART_IER 0x01
01409 #define UART_IIR 0x02
01410 #define UART_FCR 0x02
01411 #define UART_LCR 0x03
01412 #define UART_MCR 0x04
01413 #define UART_DLL 0x00
01414 #define UART_DLM 0x01
01415
01416
01417 #define UART_LSR 0x05
01418 #define UART_MSR 0x06
01419 #define UART_SCR 0x07
01420
01421 int uart_can_tx_byte(base_port)
01422 Bit16u base_port;
01423 {
01424 return inb(base_port + UART_LSR) & 0x20;
01425 }
01426
01427 void uart_wait_to_tx_byte(base_port)
01428 Bit16u base_port;
01429 {
01430 while (!uart_can_tx_byte(base_port));
01431 }
01432
01433 void uart_wait_until_sent(base_port)
01434 Bit16u base_port;
01435 {
01436 while (!(inb(base_port + UART_LSR) & 0x40));
01437 }
01438
01439 void uart_tx_byte(base_port, data)
01440 Bit16u base_port;
01441 Bit8u data;
01442 {
01443 uart_wait_to_tx_byte(base_port);
01444 outb(base_port + UART_THR, data);
01445 uart_wait_until_sent(base_port);
01446 }
01447 #endif
01448
01449 void
01450 wrch(c)
01451 Bit8u c;
01452 {
01453 ASM_START
01454 push bp
01455 mov bp, sp
01456
01457 push bx
01458 mov ah, #0x0e
01459 mov al, 4[bp]
01460 xor bx,bx
01461 int #0x10
01462 pop bx
01463
01464 pop bp
01465 ASM_END
01466 }
01467
01468 void
01469 send(action, c)
01470 Bit16u action;
01471 Bit8u c;
01472 {
01473 #if BX_DEBUG_SERIAL
01474 if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
01475 uart_tx_byte(BX_DEBUG_PORT, c);
01476 #endif
01477 #if BX_VIRTUAL_PORTS
01478 if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c);
01479 if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);
01480 #endif
01481 if (action & BIOS_PRINTF_SCREEN) {
01482 if (c == '\n') wrch('\r');
01483 wrch(c);
01484 }
01485 }
01486
01487 void
01488 put_int(action, val, width, neg)
01489 Bit16u action;
01490 short val, width;
01491 bx_bool neg;
01492 {
01493 short nval = val / 10;
01494 if (nval)
01495 put_int(action, nval, width - 1, neg);
01496 else {
01497 while (--width > 0) send(action, ' ');
01498 if (neg) send(action, '-');
01499 }
01500 send(action, val - (nval * 10) + '0');
01501 }
01502
01503 void
01504 put_uint(action, val, width, neg)
01505 Bit16u action;
01506 unsigned short val;
01507 short width;
01508 bx_bool neg;
01509 {
01510 unsigned short nval = val / 10;
01511 if (nval)
01512 put_uint(action, nval, width - 1, neg);
01513 else {
01514 while (--width > 0) send(action, ' ');
01515 if (neg) send(action, '-');
01516 }
01517 send(action, val - (nval * 10) + '0');
01518 }
01519
01520 void
01521 put_luint(action, val, width, neg)
01522 Bit16u action;
01523 unsigned long val;
01524 short width;
01525 bx_bool neg;
01526 {
01527 unsigned long nval = val / 10;
01528 if (nval)
01529 put_luint(action, nval, width - 1, neg);
01530 else {
01531 while (--width > 0) send(action, ' ');
01532 if (neg) send(action, '-');
01533 }
01534 send(action, val - (nval * 10) + '0');
01535 }
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 void
01547 bios_printf(action, s)
01548 Bit16u action;
01549 Bit8u *s;
01550 {
01551 Bit8u c, format_char;
01552 bx_bool in_format;
01553 short i;
01554 Bit16u *arg_ptr;
01555 Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width;
01556
01557 arg_ptr = &s;
01558 arg_seg = get_SS();
01559
01560 in_format = 0;
01561 format_width = 0;
01562
01563 if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) {
01564 #if BX_VIRTUAL_PORTS
01565 outb(PANIC_PORT2, 0x00);
01566 #endif
01567 bios_printf (BIOS_PRINTF_SCREEN, "FATAL: ");
01568 }
01569
01570 while (c = read_byte(get_CS(), s)) {
01571 if ( c == '%' ) {
01572 in_format = 1;
01573 format_width = 0;
01574 }
01575 else if (in_format) {
01576 if ( (c>='0') && (c<='9') ) {
01577 format_width = (format_width * 10) + (c - '0');
01578 }
01579 else {
01580 arg_ptr++;
01581 arg = read_word(arg_seg, arg_ptr);
01582 if (c == 'x') {
01583 if (format_width == 0)
01584 format_width = 4;
01585 for (i=format_width-1; i>=0; i--) {
01586 nibble = (arg >> (4 * i)) & 0x000f;
01587 send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A'));
01588 }
01589 }
01590 else if (c == 'u') {
01591 put_uint(action, arg, format_width, 0);
01592 }
01593 else if (c == 'l') {
01594 s++;
01595 arg_ptr++;
01596 hibyte = read_word(arg_seg, arg_ptr);
01597 put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
01598 }
01599 else if (c == 'd') {
01600 if (arg & 0x8000)
01601 put_int(action, -arg, format_width - 1, 1);
01602 else
01603 put_int(action, arg, format_width, 0);
01604 }
01605 else if (c == 's') {
01606 bios_printf(action & (~BIOS_PRINTF_HALT), arg);
01607 }
01608 else if (c == 'c') {
01609 send(action, arg);
01610 }
01611 else
01612 BX_PANIC("bios_printf: unknown format\n");
01613 in_format = 0;
01614 }
01615 }
01616 else {
01617 send(action, c);
01618 }
01619 s ++;
01620 }
01621
01622 if (action & BIOS_PRINTF_HALT) {
01623
01624 ASM_START
01625 cli
01626 halt2_loop:
01627 hlt
01628 jmp halt2_loop
01629 ASM_END
01630 }
01631 }
01632
01633
01634
01635
01636
01637
01638 void
01639 keyboard_init()
01640 {
01641 #ifndef COREBOOT
01642 Bit16u max;
01643
01644
01645
01646 max=0xffff;
01647 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
01648
01649
01650 max=0x2000;
01651 while (--max > 0) {
01652 outb(0x80, 0x00);
01653 if (inb(0x64) & 0x01) {
01654 inb(0x60);
01655 max = 0x2000;
01656 }
01657 }
01658
01659
01660
01661
01662
01663
01664
01665
01666 outb(0x64, 0xaa);
01667
01668
01669 max=0xffff;
01670 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
01671 if (max==0x0) keyboard_panic(00);
01672
01673
01674 max=0xffff;
01675 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01);
01676 if (max==0x0) keyboard_panic(01);
01677
01678
01679 if ((inb(0x60) != 0x55)){
01680 keyboard_panic(991);
01681 }
01682
01683
01684 outb(0x64,0xab);
01685
01686
01687 max=0xffff;
01688 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10);
01689 if (max==0x0) keyboard_panic(10);
01690
01691
01692 max=0xffff;
01693 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11);
01694 if (max==0x0) keyboard_panic(11);
01695
01696
01697
01698 if ((inb(0x60) != 0x00)) {
01699 keyboard_panic(992);
01700 }
01701
01702
01703 outb(0x64,0xae);
01704 outb(0x64,0xa8);
01705
01706
01707
01708 outb(0x60, 0xff);
01709
01710
01711 max=0xffff;
01712 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20);
01713 if (max==0x0) keyboard_panic(20);
01714
01715
01716 max=0xffff;
01717 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21);
01718 if (max==0x0) keyboard_panic(21);
01719
01720
01721 if ((inb(0x60) != 0xfa)) {
01722 keyboard_panic(993);
01723 }
01724
01725
01726 max=0xffff;
01727 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x31);
01728 if (max==0x0) keyboard_panic(31);
01729
01730 if ((inb(0x60) != 0xaa)) {
01731 keyboard_panic(994);
01732 }
01733
01734
01735 outb(0x60, 0xf5);
01736
01737
01738 max=0xffff;
01739 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40);
01740 if (max==0x0) keyboard_panic(40);
01741
01742
01743 max=0xffff;
01744 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41);
01745 if (max==0x0) keyboard_panic(41);
01746
01747
01748 if ((inb(0x60) != 0xfa)) {
01749 keyboard_panic(995);
01750 }
01751
01752
01753 outb(0x64, 0x60);
01754
01755
01756 max=0xffff;
01757 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50);
01758 if (max==0x0) keyboard_panic(50);
01759
01760
01761 outb(0x60, 0x61);
01762
01763
01764 max=0xffff;
01765 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60);
01766 if (max==0x0) keyboard_panic(60);
01767
01768
01769 outb(0x60, 0xf4);
01770
01771
01772 max=0xffff;
01773 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70);
01774 if (max==0x0) keyboard_panic(70);
01775
01776
01777 max=0xffff;
01778 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71);
01779 if (max==0x0) keyboard_panic(70);
01780
01781
01782 if ((inb(0x60) != 0xfa)) {
01783 keyboard_panic(996);
01784 }
01785
01786 outb(0x80, 0x77);
01787 #endif
01788 }
01789
01790
01791
01792
01793 void
01794 keyboard_panic(status)
01795 Bit16u status;
01796 {
01797
01798
01799
01800 BX_PANIC("Keyboard error:%u\n",status);
01801 }
01802
01803
01804
01805
01806
01807 void
01808 shutdown_status_panic(status)
01809 Bit16u status;
01810 {
01811 BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
01812 }
01813
01814
01815
01816
01817
01818 void
01819 print_bios_banner()
01820 {
01821 printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
01822 BIOS_BUILD_DATE, bios_cvs_version_string);
01823 printf(
01824 #ifdef BX_PCIBIOS
01825 "pcibios "
01826 #endif
01827 #ifdef BX_ELTORITO_BOOT
01828 "eltorito "
01829 #endif
01830 "\n\n");
01831 }
01832
01833
01834
01835
01836
01837
01838 static char drivetypes[][10]={"Floppy","Hard Disk","CD-Rom"};
01839
01840 void
01841 print_boot_device(cdboot, drive)
01842 Bit8u cdboot; Bit16u drive;
01843 {
01844 Bit8u i;
01845
01846
01847
01848
01849 if(cdboot)i=2;
01850 else if((drive&0x0080)==0x00)i=0;
01851 else if((drive&0x0080)==0x80)i=1;
01852 else return;
01853
01854 printf("Booting from %s...\n",drivetypes[i]);
01855 }
01856
01857
01858
01859
01860
01861 void
01862 print_boot_failure(cdboot, drive, reason, lastdrive)
01863 Bit8u cdboot; Bit8u drive; Bit8u lastdrive;
01864 {
01865 Bit16u drivenum = drive&0x7f;
01866
01867
01868
01869
01870
01871
01872 if (cdboot)
01873 bios_printf(BIOS_PRINTF_INFO | BIOS_PRINTF_SCREEN, "Boot from %s failed\n",drivetypes[2]);
01874 else if (drive & 0x80)
01875 bios_printf(BIOS_PRINTF_INFO | BIOS_PRINTF_SCREEN, "Boot from %s %d failed\n", drivetypes[1],drivenum);
01876 else
01877 bios_printf(BIOS_PRINTF_INFO | BIOS_PRINTF_SCREEN, "Boot from %s %d failed\n", drivetypes[0],drivenum);
01878
01879 if (lastdrive==1) {
01880 if (reason==0)
01881 BX_PANIC("Not a bootable disk\n");
01882 else
01883 BX_PANIC("Could not read the boot disk\n");
01884 }
01885 }
01886
01887
01888
01889
01890
01891 void
01892 print_cdromboot_failure( code )
01893 Bit16u code;
01894 {
01895 bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code);
01896
01897 return;
01898 }
01899
01900 void
01901 nmi_handler_msg()
01902 {
01903 BX_PANIC("NMI Handler called\n");
01904 }
01905
01906 void
01907 int18_panic_msg()
01908 {
01909 BX_PANIC("INT18: BOOT FAILURE\n");
01910 }
01911
01912 void
01913 log_bios_start()
01914 {
01915 #if BX_DEBUG_SERIAL
01916 outb(BX_DEBUG_PORT+UART_LCR, 0x03);
01917 #endif
01918 BX_INFO("%s\n", bios_cvs_version_string);
01919 }
01920
01921 bx_bool
01922 set_enable_a20(val)
01923 bx_bool val;
01924 {
01925 Bit8u oldval;
01926
01927
01928
01929
01930 oldval = inb(0x92);
01931
01932
01933 if (val)
01934 outb(0x92, oldval | 0x02);
01935 else
01936 outb(0x92, oldval & 0xfd);
01937
01938 return((oldval & 0x02) != 0);
01939 }
01940
01941 void
01942 debugger_on()
01943 {
01944 outb(0xfedc, 0x01);
01945 }
01946
01947 void
01948 debugger_off()
01949 {
01950 outb(0xfedc, 0x00);
01951 }
01952
01953 #if BX_USE_ATADRV
01954
01955
01956
01957
01958
01959
01960
01961 #define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0
01962 #define ATA_CB_ERR 1 // error in pio_base_addr1+1
01963 #define ATA_CB_FR 1 // feature reg out pio_base_addr1+1
01964 #define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2
01965 #define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3
01966 #define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4
01967 #define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5
01968 #define ATA_CB_DH 6 // device head in/out pio_base_addr1+6
01969 #define ATA_CB_STAT 7 // primary status in pio_base_addr1+7
01970 #define ATA_CB_CMD 7 // command out pio_base_addr1+7
01971 #define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6
01972 #define ATA_CB_DC 6 // device control out pio_base_addr2+6
01973 #define ATA_CB_DA 7 // device address in pio_base_addr2+7
01974
01975 #define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
01976 #define ATA_CB_ER_BBK 0x80 // ATA bad block
01977 #define ATA_CB_ER_UNC 0x40 // ATA uncorrected error
01978 #define ATA_CB_ER_MC 0x20 // ATA media change
01979 #define ATA_CB_ER_IDNF 0x10 // ATA id not found
01980 #define ATA_CB_ER_MCR 0x08 // ATA media change request
01981 #define ATA_CB_ER_ABRT 0x04 // ATA command aborted
01982 #define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found
01983 #define ATA_CB_ER_NDAM 0x01 // ATA address mark not found
01984
01985 #define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask)
01986 #define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request
01987 #define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort
01988 #define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media
01989 #define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication
01990
01991
01992 #define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask)
01993 #define ATA_CB_SC_P_REL 0x04 // ATAPI release
01994 #define ATA_CB_SC_P_IO 0x02 // ATAPI I/O
01995 #define ATA_CB_SC_P_CD 0x01 // ATAPI C/D
01996
01997
01998 #define ATA_CB_DH_DEV0 0xa0 // select device 0
01999 #define ATA_CB_DH_DEV1 0xb0 // select device 1
02000
02001
02002 #define ATA_CB_STAT_BSY 0x80 // busy
02003 #define ATA_CB_STAT_RDY 0x40 // ready
02004 #define ATA_CB_STAT_DF 0x20 // device fault
02005 #define ATA_CB_STAT_WFT 0x20 // write fault (old name)
02006 #define ATA_CB_STAT_SKC 0x10 // seek complete
02007 #define ATA_CB_STAT_SERV 0x10 // service
02008 #define ATA_CB_STAT_DRQ 0x08 // data request
02009 #define ATA_CB_STAT_CORR 0x04 // corrected
02010 #define ATA_CB_STAT_IDX 0x02 // index
02011 #define ATA_CB_STAT_ERR 0x01 // error (ATA)
02012 #define ATA_CB_STAT_CHK 0x01 // check (ATAPI)
02013
02014
02015 #define ATA_CB_DC_HD15 0x08 // bit should always be set to one
02016 #define ATA_CB_DC_SRST 0x04 // soft reset
02017 #define ATA_CB_DC_NIEN 0x02 // disable interrupts
02018
02019
02020 #define ATA_CMD_CFA_ERASE_SECTORS 0xC0
02021 #define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
02022 #define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87
02023 #define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
02024 #define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
02025 #define ATA_CMD_CHECK_POWER_MODE1 0xE5
02026 #define ATA_CMD_CHECK_POWER_MODE2 0x98
02027 #define ATA_CMD_DEVICE_RESET 0x08
02028 #define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
02029 #define ATA_CMD_FLUSH_CACHE 0xE7
02030 #define ATA_CMD_FORMAT_TRACK 0x50
02031 #define ATA_CMD_IDENTIFY_DEVICE 0xEC
02032 #define ATA_CMD_IDENTIFY_DEVICE_PACKET 0xA1
02033 #define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1
02034 #define ATA_CMD_IDLE1 0xE3
02035 #define ATA_CMD_IDLE2 0x97
02036 #define ATA_CMD_IDLE_IMMEDIATE1 0xE1
02037 #define ATA_CMD_IDLE_IMMEDIATE2 0x95
02038 #define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
02039 #define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
02040 #define ATA_CMD_NOP 0x00
02041 #define ATA_CMD_PACKET 0xA0
02042 #define ATA_CMD_READ_BUFFER 0xE4
02043 #define ATA_CMD_READ_DMA 0xC8
02044 #define ATA_CMD_READ_DMA_QUEUED 0xC7
02045 #define ATA_CMD_READ_MULTIPLE 0xC4
02046 #define ATA_CMD_READ_SECTORS 0x20
02047 #define ATA_CMD_READ_VERIFY_SECTORS 0x40
02048 #define ATA_CMD_RECALIBRATE 0x10
02049 #define ATA_CMD_SEEK 0x70
02050 #define ATA_CMD_SET_FEATURES 0xEF
02051 #define ATA_CMD_SET_MULTIPLE_MODE 0xC6
02052 #define ATA_CMD_SLEEP1 0xE6
02053 #define ATA_CMD_SLEEP2 0x99
02054 #define ATA_CMD_STANDBY1 0xE2
02055 #define ATA_CMD_STANDBY2 0x96
02056 #define ATA_CMD_STANDBY_IMMEDIATE1 0xE0
02057 #define ATA_CMD_STANDBY_IMMEDIATE2 0x94
02058 #define ATA_CMD_WRITE_BUFFER 0xE8
02059 #define ATA_CMD_WRITE_DMA 0xCA
02060 #define ATA_CMD_WRITE_DMA_QUEUED 0xCC
02061 #define ATA_CMD_WRITE_MULTIPLE 0xC5
02062 #define ATA_CMD_WRITE_SECTORS 0x30
02063 #define ATA_CMD_WRITE_VERIFY 0x3C
02064
02065 #define ATA_IFACE_NONE 0x00
02066 #define ATA_IFACE_ISA 0x00
02067 #define ATA_IFACE_PCI 0x01
02068
02069 #define ATA_TYPE_NONE 0x00
02070 #define ATA_TYPE_UNKNOWN 0x01
02071 #define ATA_TYPE_ATA 0x02
02072 #define ATA_TYPE_ATAPI 0x03
02073
02074 #define ATA_DEVICE_NONE 0x00
02075 #define ATA_DEVICE_HD 0xFF
02076 #define ATA_DEVICE_CDROM 0x05
02077
02078 #define ATA_MODE_NONE 0x00
02079 #define ATA_MODE_PIO16 0x00
02080 #define ATA_MODE_PIO32 0x01
02081 #define ATA_MODE_ISADMA 0x02
02082 #define ATA_MODE_PCIDMA 0x03
02083 #define ATA_MODE_USEIRQ 0x10
02084
02085 #define ATA_TRANSLATION_NONE 0
02086 #define ATA_TRANSLATION_LBA 1
02087 #define ATA_TRANSLATION_LARGE 2
02088 #define ATA_TRANSLATION_RECHS 3
02089
02090 #define ATA_DATA_NO 0x00
02091 #define ATA_DATA_IN 0x01
02092 #define ATA_DATA_OUT 0x02
02093
02094
02095
02096
02097 void ata_init( )
02098 {
02099 Bit16u ebda_seg=read_word(0x0040,0x000E);
02100 Bit8u channel, device;
02101
02102
02103 for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
02104 write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE);
02105 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0);
02106 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2,0x0);
02107 write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
02108 }
02109
02110
02111 for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
02112 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
02113 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE);
02114 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable,0);
02115 write_byte(ebda_seg,&EbdaData->ata.devices[device].lock,0);
02116 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_NONE);
02117 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,0);
02118 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation,ATA_TRANSLATION_NONE);
02119 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads,0);
02120 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders,0);
02121 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt,0);
02122 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0);
02123 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
02124 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
02125
02126 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L);
02127 }
02128
02129
02130 for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
02131 write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
02132 write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
02133 }
02134
02135 write_byte(ebda_seg,&EbdaData->ata.hdcount,0);
02136 write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
02137 }
02138
02139
02140
02141
02142
02143 void ata_detect( )
02144 {
02145 Bit16u ebda_seg=read_word(0x0040,0x000E);
02146 Bit8u hdcount, cdcount, device, type;
02147 Bit8u buffer[0x0200];
02148 Bit16u i;
02149
02150 #if BX_MAX_ATA_INTERFACES > 0
02151 write_byte(ebda_seg,&EbdaData->ata.channels[0].iface,ATA_IFACE_ISA);
02152 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase1,0x1f0);
02153 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase2,0x3f0);
02154 write_byte(ebda_seg,&EbdaData->ata.channels[0].irq,14);
02155 #endif
02156 #if BX_MAX_ATA_INTERFACES > 1
02157 write_byte(ebda_seg,&EbdaData->ata.channels[1].iface,ATA_IFACE_ISA);
02158 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase1,0x170);
02159 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase2,0x370);
02160 write_byte(ebda_seg,&EbdaData->ata.channels[1].irq,15);
02161 #endif
02162 #if BX_MAX_ATA_INTERFACES > 2
02163 write_byte(ebda_seg,&EbdaData->ata.channels[2].iface,ATA_IFACE_ISA);
02164 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase1,0x1e8);
02165 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase2,0x3e0);
02166 write_byte(ebda_seg,&EbdaData->ata.channels[2].irq,12);
02167 #endif
02168 #if BX_MAX_ATA_INTERFACES > 3
02169 write_byte(ebda_seg,&EbdaData->ata.channels[3].iface,ATA_IFACE_ISA);
02170 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase1,0x168);
02171 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase2,0x360);
02172 write_byte(ebda_seg,&EbdaData->ata.channels[3].irq,11);
02173 #endif
02174 #if BX_MAX_ATA_INTERFACES > 4
02175 #error Please fill the ATA interface informations
02176 #endif
02177
02178
02179 hdcount=cdcount=0;
02180
02181 for(device=0; device<BX_MAX_ATA_DEVICES; device++) {
02182 Bit16u iobase1, iobase2;
02183 Bit8u channel, slave, shift;
02184 Bit8u sc, sn, cl, ch, st;
02185
02186 channel = device / 2;
02187 slave = device % 2;
02188
02189 iobase1 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1);
02190 iobase2 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2);
02191
02192
02193 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
02194
02195
02196 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
02197 outb(iobase1+ATA_CB_SC, 0x55);
02198 outb(iobase1+ATA_CB_SN, 0xaa);
02199 outb(iobase1+ATA_CB_SC, 0xaa);
02200 outb(iobase1+ATA_CB_SN, 0x55);
02201 outb(iobase1+ATA_CB_SC, 0x55);
02202 outb(iobase1+ATA_CB_SN, 0xaa);
02203
02204
02205 sc = inb(iobase1+ATA_CB_SC);
02206 sn = inb(iobase1+ATA_CB_SN);
02207
02208 if ( (sc == 0x55) && (sn == 0xaa) ) {
02209 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN);
02210
02211
02212 ata_reset(device);
02213
02214
02215 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
02216 sc = inb(iobase1+ATA_CB_SC);
02217 sn = inb(iobase1+ATA_CB_SN);
02218 if ((sc==0x01) && (sn==0x01)) {
02219 cl = inb(iobase1+ATA_CB_CL);
02220 ch = inb(iobase1+ATA_CB_CH);
02221 st = inb(iobase1+ATA_CB_STAT);
02222
02223 if ((cl==0x14) && (ch==0xeb)) {
02224 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI);
02225 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
02226 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA);
02227 } else if ((cl==0xff) && (ch==0xff)) {
02228 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
02229 }
02230 }
02231 }
02232
02233 type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
02234
02235
02236 if(type == ATA_TYPE_ATA) {
02237 Bit32u sectors;
02238 Bit16u cylinders, heads, spt, blksize;
02239 Bit8u translation, removable, mode;
02240
02241
02242 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
02243 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
02244
02245 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, get_SS(),buffer) !=0 )
02246 BX_PANIC("ata-detect: Failed to detect ATA device\n");
02247
02248 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
02249 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
02250 blksize = read_word(get_SS(),buffer+10);
02251
02252 cylinders = read_word(get_SS(),buffer+(1*2));
02253 heads = read_word(get_SS(),buffer+(3*2));
02254 spt = read_word(get_SS(),buffer+(6*2));
02255
02256 sectors = read_dword(get_SS(),buffer+(60*2));
02257
02258 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
02259 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
02260 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
02261 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
02262 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);
02263 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders);
02264 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
02265 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors);
02266 BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
02267
02268 translation = inb_cmos(0x39 + channel/2);
02269 for (shift=device%4; shift>0; shift--) translation >>= 2;
02270 translation &= 0x03;
02271
02272 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation, translation);
02273
02274 switch (translation) {
02275 case ATA_TRANSLATION_NONE:
02276 BX_INFO("none");
02277 break;
02278 case ATA_TRANSLATION_LBA:
02279 BX_INFO("lba");
02280 break;
02281 case ATA_TRANSLATION_LARGE:
02282 BX_INFO("large");
02283 break;
02284 case ATA_TRANSLATION_RECHS:
02285 BX_INFO("r-echs");
02286 break;
02287 }
02288 switch (translation) {
02289 case ATA_TRANSLATION_NONE:
02290 break;
02291 case ATA_TRANSLATION_LBA:
02292 spt = 63;
02293 sectors /= 63;
02294 heads = sectors / 1024;
02295 if (heads>128) heads = 255;
02296 else if (heads>64) heads = 128;
02297 else if (heads>32) heads = 64;
02298 else if (heads>16) heads = 32;
02299 else heads=16;
02300 cylinders = sectors / heads;
02301 break;
02302 case ATA_TRANSLATION_RECHS:
02303
02304 if (heads==16) {
02305 if(cylinders>61439) cylinders=61439;
02306 heads=15;
02307 cylinders = (Bit16u)((Bit32u)(cylinders)*16/15);
02308 }
02309
02310 case ATA_TRANSLATION_LARGE:
02311 while(cylinders > 1024) {
02312 cylinders >>= 1;
02313 heads <<= 1;
02314
02315
02316 if (heads > 127) break;
02317 }
02318 break;
02319 }
02320
02321 if (cylinders > 1024) cylinders=1024;
02322 BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
02323
02324 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);
02325 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders);
02326 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt);
02327
02328
02329 write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device);
02330 hdcount++;
02331 }
02332
02333
02334 if(type == ATA_TYPE_ATAPI) {
02335
02336 Bit8u type, removable, mode;
02337 Bit16u blksize;
02338
02339
02340 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM);
02341 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
02342
02343 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, get_SS(),buffer) != 0)
02344 BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
02345
02346 type = read_byte(get_SS(),buffer+1) & 0x1f;
02347 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
02348 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
02349 blksize = 2048;
02350
02351 write_byte(ebda_seg,&EbdaData->ata.devices[device].device, type);
02352 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
02353 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
02354 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
02355
02356
02357 write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device);
02358 cdcount++;
02359 }
02360
02361 {
02362 Bit32u sizeinmb;
02363 Bit16u ataversion;
02364 Bit8u c, i, version, model[41];
02365
02366 switch (type) {
02367 case ATA_TYPE_ATA:
02368 sizeinmb = read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors);
02369 sizeinmb >>= 11;
02370 case ATA_TYPE_ATAPI:
02371
02372 ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
02373 for(version=15;version>0;version--) {
02374 if((ataversion&(1<<version))!=0)
02375 break;
02376 }
02377
02378
02379 for(i=0;i<20;i++){
02380 write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
02381 write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
02382 }
02383
02384
02385 write_byte(get_SS(),model+40,0x00);
02386 for(i=39;i>0;i--){
02387 if(read_byte(get_SS(),model+i)==0x20)
02388 write_byte(get_SS(),model+i,0x00);
02389 else break;
02390 }
02391 break;
02392 }
02393
02394 switch (type) {
02395 case ATA_TYPE_ATA:
02396 printf("ata%d %s: ",channel,slave?" slave":"master");
02397 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
02398 printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
02399 break;
02400 case ATA_TYPE_ATAPI:
02401 printf("ata%d %s: ",channel,slave?" slave":"master");
02402 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
02403 if(read_byte(ebda_seg,&EbdaData->ata.devices[device].device)==ATA_DEVICE_CDROM)
02404 printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version);
02405 else
02406 printf(" ATAPI-%d Device\n",version);
02407 break;
02408 case ATA_TYPE_UNKNOWN:
02409 printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
02410 break;
02411 }
02412 }
02413 }
02414
02415
02416 write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
02417 write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount);
02418 write_byte(0x40,0x75, hdcount);
02419
02420 printf("\n");
02421
02422
02423
02424
02425
02426 }
02427
02428
02429
02430
02431
02432
02433
02434 void ata_reset(device)
02435 Bit16u device;
02436 {
02437 Bit16u ebda_seg=read_word(0x0040,0x000E);
02438 Bit16u iobase1, iobase2;
02439 Bit8u channel, slave, sn, sc;
02440 Bit16u max;
02441
02442 channel = device / 2;
02443 slave = device % 2;
02444
02445 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
02446 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
02447
02448
02449
02450
02451 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
02452
02453
02454 max=0xff;
02455 while(--max>0) {
02456 Bit8u status = inb(iobase1+ATA_CB_STAT);
02457 if ((status & ATA_CB_STAT_BSY) != 0) break;
02458 }
02459
02460
02461 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
02462
02463 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_NONE) {
02464
02465
02466
02467 outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
02468 sc = inb(iobase1+ATA_CB_SC);
02469 sn = inb(iobase1+ATA_CB_SN);
02470
02471 if ( (sc==0x01) && (sn==0x01) ) {
02472
02473
02474 max=0xff;
02475 while(--max>0) {
02476 Bit8u status = inb(iobase1+ATA_CB_STAT);
02477 if ((status & ATA_CB_STAT_BSY) == 0) break;
02478 }
02479 }
02480 }
02481
02482
02483 max=0xfff;
02484 while(--max>0) {
02485 Bit8u status = inb(iobase1+ATA_CB_STAT);
02486 if ((status & ATA_CB_STAT_RDY) != 0) break;
02487 }
02488
02489
02490 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
02491 }
02492
02493
02494
02495
02496
02497 Bit16u ata_cmd_non_data()
02498 {return 0;}
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512 Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, segment, offset)
02513 Bit16u device, command, count, cylinder, head, sector, segment, offset;
02514 Bit32u lba;
02515 {
02516 Bit16u ebda_seg=read_word(0x0040,0x000E);
02517 Bit16u iobase1, iobase2, blksize;
02518 Bit8u channel, slave;
02519 Bit8u status, current, mode;
02520
02521 channel = device / 2;
02522 slave = device % 2;
02523
02524 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
02525 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
02526 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
02527 blksize = 0x200;
02528 if (mode == ATA_MODE_PIO32) blksize>>=2;
02529 else blksize>>=1;
02530
02531
02532 if (sector == 0) {
02533 sector = (Bit16u) (lba & 0x000000ffL);
02534 lba >>= 8;
02535 cylinder = (Bit16u) (lba & 0x0000ffffL);
02536 lba >>= 16;
02537 head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
02538 }
02539
02540
02541 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
02542 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
02543 current = 0;
02544
02545 status = inb(iobase1 + ATA_CB_STAT);
02546 if (status & ATA_CB_STAT_BSY) return 1;
02547
02548 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
02549 outb(iobase1 + ATA_CB_FR, 0x00);
02550 outb(iobase1 + ATA_CB_SC, count);
02551 outb(iobase1 + ATA_CB_SN, sector);
02552 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
02553 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
02554 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
02555 outb(iobase1 + ATA_CB_CMD, command);
02556
02557 while (1) {
02558 status = inb(iobase1 + ATA_CB_STAT);
02559 if ( !(status & ATA_CB_STAT_BSY) ) break;
02560 }
02561
02562 if (status & ATA_CB_STAT_ERR) {
02563 BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
02564 return 2;
02565 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
02566 BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n", (unsigned) status);
02567 return 3;
02568 }
02569
02570
02571
02572 ASM_START
02573 sti ;; enable higher priority interrupts
02574 ASM_END
02575
02576 while (1) {
02577
02578 ASM_START
02579 push bp
02580 mov bp, sp
02581 mov di, _ata_cmd_data_in.offset + 2[bp]
02582 mov ax, _ata_cmd_data_in.segment + 2[bp]
02583 mov cx, _ata_cmd_data_in.blksize + 2[bp]
02584
02585 ;; adjust if there will be an overrun. 2K max sector size
02586 cmp di, #0xf800 ;;
02587 jbe ata_in_no_adjust
02588
02589 ata_in_adjust:
02590 sub di, #0x0800 ;; sub 2 kbytes from offset
02591 add ax, #0x0080 ;; add 2 Kbytes to segment
02592
02593 ata_in_no_adjust:
02594 mov es, ax ;; segment in es
02595
02596 mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port
02597
02598 mov ah, _ata_cmd_data_in.mode + 2[bp]
02599 cmp ah, #ATA_MODE_PIO32
02600 je ata_in_32
02601
02602 ata_in_16:
02603 rep
02604 insw ;; CX words transfered from port(DX) to ES:[DI]
02605 jmp ata_in_done
02606
02607 ata_in_32:
02608 rep
02609 insd ;; CX dwords transfered from port(DX) to ES:[DI]
02610
02611 ata_in_done:
02612 mov _ata_cmd_data_in.offset + 2[bp], di
02613 mov _ata_cmd_data_in.segment + 2[bp], es
02614 pop bp
02615 ASM_END
02616
02617 current++;
02618 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
02619 count--;
02620 status = inb(iobase1 + ATA_CB_STAT);
02621 if (count == 0) {
02622 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
02623 != ATA_CB_STAT_RDY ) {
02624 BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status);
02625 return 4;
02626 }
02627 break;
02628 }
02629 else {
02630 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
02631 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
02632 BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status);
02633 return 5;
02634 }
02635 continue;
02636 }
02637 }
02638
02639 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
02640 return 0;
02641 }
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655 Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, segment, offset)
02656 Bit16u device, command, count, cylinder, head, sector, segment, offset;
02657 Bit32u lba;
02658 {
02659 Bit16u ebda_seg=read_word(0x0040,0x000E);
02660 Bit16u iobase1, iobase2, blksize;
02661 Bit8u channel, slave;
02662 Bit8u status, current, mode;
02663
02664 channel = device / 2;
02665 slave = device % 2;
02666
02667 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
02668 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
02669 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
02670 blksize = 0x200;
02671 if (mode == ATA_MODE_PIO32) blksize>>=2;
02672 else blksize>>=1;
02673
02674
02675 if (sector == 0) {
02676 sector = (Bit16u) (lba & 0x000000ffL);
02677 lba >>= 8;
02678 cylinder = (Bit16u) (lba & 0x0000ffffL);
02679 lba >>= 16;
02680 head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
02681 }
02682
02683
02684 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
02685 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
02686 current = 0;
02687
02688 status = inb(iobase1 + ATA_CB_STAT);
02689 if (status & ATA_CB_STAT_BSY) return 1;
02690
02691 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
02692 outb(iobase1 + ATA_CB_FR, 0x00);
02693 outb(iobase1 + ATA_CB_SC, count);
02694 outb(iobase1 + ATA_CB_SN, sector);
02695 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
02696 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
02697 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
02698 outb(iobase1 + ATA_CB_CMD, command);
02699
02700 while (1) {
02701 status = inb(iobase1 + ATA_CB_STAT);
02702 if ( !(status & ATA_CB_STAT_BSY) ) break;
02703 }
02704
02705 if (status & ATA_CB_STAT_ERR) {
02706 BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
02707 return 2;
02708 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
02709 BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n", (unsigned) status);
02710 return 3;
02711 }
02712
02713
02714
02715 ASM_START
02716 sti ;; enable higher priority interrupts
02717 ASM_END
02718
02719 while (1) {
02720
02721 ASM_START
02722 push bp
02723 mov bp, sp
02724 mov si, _ata_cmd_data_out.offset + 2[bp]
02725 mov ax, _ata_cmd_data_out.segment + 2[bp]
02726 mov cx, _ata_cmd_data_out.blksize + 2[bp]
02727
02728 ;; adjust if there will be an overrun. 2K max sector size
02729 cmp si, #0xf800 ;;
02730 jbe ata_out_no_adjust
02731
02732 ata_out_adjust:
02733 sub si, #0x0800 ;; sub 2 kbytes from offset
02734 add ax, #0x0080 ;; add 2 Kbytes to segment
02735
02736 ata_out_no_adjust:
02737 mov es, ax ;; segment in es
02738
02739 mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port
02740
02741 mov ah, _ata_cmd_data_out.mode + 2[bp]
02742 cmp ah, #ATA_MODE_PIO32
02743 je ata_out_32
02744
02745 ata_out_16:
02746 seg ES
02747 rep
02748 outsw ;; CX words transfered from port(DX) to ES:[SI]
02749 jmp ata_out_done
02750
02751 ata_out_32:
02752 seg ES
02753 rep
02754 outsd ;; CX dwords transfered from port(DX) to ES:[SI]
02755
02756 ata_out_done:
02757 mov _ata_cmd_data_out.offset + 2[bp], si
02758 mov _ata_cmd_data_out.segment + 2[bp], es
02759 pop bp
02760 ASM_END
02761
02762 current++;
02763 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
02764 count--;
02765 status = inb(iobase1 + ATA_CB_STAT);
02766 if (count == 0) {
02767 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
02768 != ATA_CB_STAT_RDY ) {
02769 BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status);
02770 return 6;
02771 }
02772 break;
02773 }
02774 else {
02775 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
02776 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
02777 BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status);
02778 return 7;
02779 }
02780 continue;
02781 }
02782 }
02783
02784 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
02785 return 0;
02786 }
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797 Bit16u ata_cmd_packet(device, cmdlen, cmdseg, cmdoff, header, length, inout, bufseg, bufoff)
02798 Bit8u cmdlen,inout;
02799 Bit16u device,cmdseg, cmdoff, bufseg, bufoff;
02800 Bit16u header;
02801 Bit32u length;
02802 {
02803 Bit16u ebda_seg=read_word(0x0040,0x000E);
02804 Bit16u iobase1, iobase2;
02805 Bit16u lcount, lbefore, lafter, count;
02806 Bit8u channel, slave;
02807 Bit8u status, mode, lmode;
02808 Bit32u total, transfer;
02809
02810 channel = device / 2;
02811 slave = device % 2;
02812
02813
02814 if (inout == ATA_DATA_OUT) {
02815 BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n");
02816 return 1;
02817 }
02818
02819
02820 if (header & 1) {
02821 BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header);
02822 return 1;
02823 }
02824
02825 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
02826 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
02827 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
02828 transfer= 0L;
02829
02830 if (cmdlen < 12) cmdlen=12;
02831 if (cmdlen > 12) cmdlen=16;
02832 cmdlen>>=1;
02833
02834
02835 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
02836 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
02837
02838 status = inb(iobase1 + ATA_CB_STAT);
02839 if (status & ATA_CB_STAT_BSY) return 2;
02840
02841 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
02842
02843
02844
02845 outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
02846 outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
02847 outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
02848 outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
02849
02850
02851 while (1) {
02852 status = inb(iobase1 + ATA_CB_STAT);
02853 if ( !(status & ATA_CB_STAT_BSY) ) break;
02854 }
02855
02856 if (status & ATA_CB_STAT_ERR) {
02857 BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
02858 return 3;
02859 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
02860 BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status);
02861 return 4;
02862 }
02863
02864
02865 cmdseg += (cmdoff / 16);
02866 cmdoff %= 16;
02867
02868
02869 ASM_START
02870 sti ;; enable higher priority interrupts
02871
02872 push bp
02873 mov bp, sp
02874
02875 mov si, _ata_cmd_packet.cmdoff + 2[bp]
02876 mov ax, _ata_cmd_packet.cmdseg + 2[bp]
02877 mov cx, _ata_cmd_packet.cmdlen + 2[bp]
02878 mov es, ax ;; segment in es
02879
02880 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port
02881
02882 seg ES
02883 rep
02884 outsw ;; CX words transfered from port(DX) to ES:[SI]
02885
02886 pop bp
02887 ASM_END
02888
02889 if (inout == ATA_DATA_NO) {
02890 status = inb(iobase1 + ATA_CB_STAT);
02891 }
02892 else {
02893 while (1) {
02894
02895 status = inb(iobase1 + ATA_CB_STAT);
02896
02897
02898 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break;
02899
02900 if (status & ATA_CB_STAT_ERR) {
02901 BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
02902 return 3;
02903 }
02904
02905
02906 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
02907 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
02908 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", status);
02909 return 4;
02910 }
02911
02912
02913 bufseg += (bufoff / 16);
02914 bufoff %= 16;
02915
02916
02917 lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
02918
02919
02920 if(header>lcount) {
02921 lbefore=lcount;
02922 header-=lcount;
02923 lcount=0;
02924 }
02925 else {
02926 lbefore=header;
02927 header=0;
02928 lcount-=lbefore;
02929 }
02930
02931 if(lcount>length) {
02932 lafter=lcount-length;
02933 lcount=length;
02934 length=0;
02935 }
02936 else {
02937 lafter=0;
02938 length-=lcount;
02939 }
02940
02941
02942 count = lcount;
02943
02944 BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
02945 BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff);
02946
02947
02948 lmode = mode;
02949 if (lbefore & 0x03) lmode=ATA_MODE_PIO16;
02950 if (lcount & 0x03) lmode=ATA_MODE_PIO16;
02951 if (lafter & 0x03) lmode=ATA_MODE_PIO16;
02952
02953
02954 if (lcount & 0x01) {
02955 lcount+=1;
02956 if ((lafter > 0) && (lafter & 0x01)) {
02957 lafter-=1;
02958 }
02959 }
02960
02961 if (lmode == ATA_MODE_PIO32) {
02962 lcount>>=2; lbefore>>=2; lafter>>=2;
02963 }
02964 else {
02965 lcount>>=1; lbefore>>=1; lafter>>=1;
02966 }
02967
02968 ;
02969
02970 ASM_START
02971 push bp
02972 mov bp, sp
02973
02974 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port
02975
02976 mov cx, _ata_cmd_packet.lbefore + 2[bp]
02977 jcxz ata_packet_no_before
02978
02979 mov ah, _ata_cmd_packet.lmode + 2[bp]
02980 cmp ah, #ATA_MODE_PIO32
02981 je ata_packet_in_before_32
02982
02983 ata_packet_in_before_16:
02984 in ax, dx
02985 loop ata_packet_in_before_16
02986 jmp ata_packet_no_before
02987
02988 ata_packet_in_before_32:
02989 push eax
02990 ata_packet_in_before_32_loop:
02991 in eax, dx
02992 loop ata_packet_in_before_32_loop
02993 pop eax
02994
02995 ata_packet_no_before:
02996 mov cx, _ata_cmd_packet.lcount + 2[bp]
02997 jcxz ata_packet_after
02998
02999 mov di, _ata_cmd_packet.bufoff + 2[bp]
03000 mov ax, _ata_cmd_packet.bufseg + 2[bp]
03001 mov es, ax
03002
03003 mov ah, _ata_cmd_packet.lmode + 2[bp]
03004 cmp ah, #ATA_MODE_PIO32
03005 je ata_packet_in_32
03006
03007 ata_packet_in_16:
03008 rep
03009 insw ;; CX words transfered tp port(DX) to ES:[DI]
03010 jmp ata_packet_after
03011
03012 ata_packet_in_32:
03013 rep
03014 insd ;; CX dwords transfered to port(DX) to ES:[DI]
03015
03016 ata_packet_after:
03017 mov cx, _ata_cmd_packet.lafter + 2[bp]
03018 jcxz ata_packet_done
03019
03020 mov ah, _ata_cmd_packet.lmode + 2[bp]
03021 cmp ah, #ATA_MODE_PIO32
03022 je ata_packet_in_after_32
03023
03024 ata_packet_in_after_16:
03025 in ax, dx
03026 loop ata_packet_in_after_16
03027 jmp ata_packet_done
03028
03029 ata_packet_in_after_32:
03030 push eax
03031 ata_packet_in_after_32_loop:
03032 in eax, dx
03033 loop ata_packet_in_after_32_loop
03034 pop eax
03035
03036 ata_packet_done:
03037 pop bp
03038 ASM_END
03039
03040
03041 bufoff += count;
03042
03043
03044 transfer += count;
03045 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,transfer);
03046 }
03047 }
03048
03049
03050 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
03051 != ATA_CB_STAT_RDY ) {
03052 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status);
03053 return 4;
03054 }
03055
03056
03057 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
03058 return 0;
03059 }
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069 Bit16u
03070 atapi_get_sense(device)
03071 Bit16u device;
03072 {
03073 Bit8u atacmd[12];
03074 Bit8u buffer[16];
03075 Bit8u i;
03076
03077 memsetb(get_SS(),atacmd,0,12);
03078
03079
03080 atacmd[0]=0x03;
03081 atacmd[4]=0x20;
03082 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, get_SS(), buffer) != 0)
03083 return 0x0002;
03084
03085 if ((buffer[0] & 0x7e) == 0x70) {
03086 return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12];
03087 }
03088
03089 return 0;
03090 }
03091
03092 Bit16u
03093 atapi_is_ready(device)
03094 Bit16u device;
03095 {
03096 Bit8u atacmd[12];
03097 Bit8u buffer[];
03098
03099 memsetb(get_SS(),atacmd,0,12);
03100
03101
03102 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
03103 return 0x000f;
03104
03105 if (atapi_get_sense(device) !=0 ) {
03106 memsetb(get_SS(),atacmd,0,12);
03107
03108
03109 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
03110 return 0x000f;
03111
03112 return atapi_get_sense(device);
03113 }
03114 return 0;
03115 }
03116
03117 Bit16u
03118 atapi_is_cdrom(device)
03119 Bit8u device;
03120 {
03121 Bit16u ebda_seg=read_word(0x0040,0x000E);
03122
03123 if (device >= BX_MAX_ATA_DEVICES)
03124 return 0;
03125
03126 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI)
03127 return 0;
03128
03129 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].device) != ATA_DEVICE_CDROM)
03130 return 0;
03131
03132 return 1;
03133 }
03134
03135
03136
03137
03138
03139 #endif // BX_USE_ATADRV
03140
03141 #if BX_ELTORITO_BOOT
03142
03143
03144
03145
03146
03147 void
03148 cdemu_init()
03149 {
03150 Bit16u ebda_seg=read_word(0x0040,0x000E);
03151
03152
03153 write_byte(ebda_seg,&EbdaData->cdemu.active,0x00);
03154 }
03155
03156 Bit8u
03157 cdemu_isactive()
03158 {
03159 Bit16u ebda_seg=read_word(0x0040,0x000E);
03160
03161 return(read_byte(ebda_seg,&EbdaData->cdemu.active));
03162 }
03163
03164 Bit8u
03165 cdemu_emulated_drive()
03166 {
03167 Bit16u ebda_seg=read_word(0x0040,0x000E);
03168
03169 return(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive));
03170 }
03171
03172 static char isotag[6]="CD001";
03173 static char eltorito[24]="EL TORITO SPECIFICATION";
03174
03175
03176
03177 Bit16u
03178 cdrom_boot()
03179 {
03180 Bit16u ebda_seg=read_word(0x0040,0x000E);
03181 Bit8u atacmd[12], buffer[2048];
03182 Bit32u lba;
03183 Bit16u boot_segment, nbsectors, i, error;
03184 Bit8u device;
03185
03186
03187 for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
03188 if (atapi_is_cdrom(device)) break;
03189 }
03190
03191
03192 if(device >= BX_MAX_ATA_DEVICES) return 2;
03193
03194
03195 memsetb(get_SS(),atacmd,0,12);
03196 atacmd[0]=0x28;
03197 atacmd[7]=(0x01 & 0xff00) >> 8;
03198 atacmd[8]=(0x01 & 0x00ff);
03199 atacmd[2]=(0x11 & 0xff000000) >> 24;
03200 atacmd[3]=(0x11 & 0x00ff0000) >> 16;
03201 atacmd[4]=(0x11 & 0x0000ff00) >> 8;
03202 atacmd[5]=(0x11 & 0x000000ff);
03203 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
03204 return 3;
03205
03206
03207 if(buffer[0]!=0)return 4;
03208 for(i=0;i<5;i++){
03209 if(buffer[1+i]!=read_byte(0xf000,&isotag[i]))return 5;
03210 }
03211 for(i=0;i<23;i++)
03212 if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6;
03213
03214
03215 lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47];
03216
03217
03218 memsetb(get_SS(),atacmd,0,12);
03219 atacmd[0]=0x28;
03220 atacmd[7]=(0x01 & 0xff00) >> 8;
03221 atacmd[8]=(0x01 & 0x00ff);
03222 atacmd[2]=(lba & 0xff000000) >> 24;
03223 atacmd[3]=(lba & 0x00ff0000) >> 16;
03224 atacmd[4]=(lba & 0x0000ff00) >> 8;
03225 atacmd[5]=(lba & 0x000000ff);
03226 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
03227 return 7;
03228
03229
03230 if(buffer[0x00]!=0x01)return 8;
03231 if(buffer[0x01]!=0x00)return 9;
03232 if(buffer[0x1E]!=0x55)return 10;
03233 if(buffer[0x1F]!=0xAA)return 10;
03234
03235
03236 if(buffer[0x20]!=0x88)return 11;
03237
03238 write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]);
03239 if(buffer[0x21]==0){
03240
03241
03242 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0);
03243 }
03244 else if(buffer[0x21]<4)
03245 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00);
03246 else
03247 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x80);
03248
03249 write_byte(ebda_seg,&EbdaData->cdemu.controller_index,device/2);
03250 write_byte(ebda_seg,&EbdaData->cdemu.device_spec,device%2);
03251
03252 boot_segment=buffer[0x23]*0x100+buffer[0x22];
03253 if(boot_segment==0x0000)boot_segment=0x07C0;
03254
03255 write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment);
03256 write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000);
03257
03258 nbsectors=buffer[0x27]*0x100+buffer[0x26];
03259 write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors);
03260
03261 lba=buffer[0x2B]*0x1000000+buffer[0x2A]*0x10000+buffer[0x29]*0x100+buffer[0x28];
03262 write_dword(ebda_seg,&EbdaData->cdemu.ilba,lba);
03263
03264
03265 memsetb(get_SS(),atacmd,0,12);
03266 atacmd[0]=0x28;
03267 atacmd[7]=((1+(nbsectors-1)/4) & 0xff00) >> 8;
03268 atacmd[8]=((1+(nbsectors-1)/4) & 0x00ff);
03269 atacmd[2]=(lba & 0xff000000) >> 24;
03270 atacmd[3]=(lba & 0x00ff0000) >> 16;
03271 atacmd[4]=(lba & 0x0000ff00) >> 8;
03272 atacmd[5]=(lba & 0x000000ff);
03273 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0)
03274 return 12;
03275
03276
03277 switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
03278 case 0x01:
03279 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,15);
03280 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
03281 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
03282 break;
03283 case 0x02:
03284 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,18);
03285 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
03286 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
03287 break;
03288 case 0x03:
03289 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,36);
03290 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
03291 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
03292 break;
03293 case 0x04:
03294 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f);
03295 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,
03296 (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1);
03297 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1);
03298 break;
03299 }
03300
03301 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) {
03302
03303 if(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)==0x00)
03304 write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41);
03305 else
03306 write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1);
03307 }
03308
03309
03310
03311 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0)
03312 write_byte(ebda_seg,&EbdaData->cdemu.active,0x01);
03313
03314
03315 return (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)*0x100)+0;
03316 }
03317
03318
03319
03320
03321 #endif // BX_ELTORITO_BOOT
03322
03323 void
03324 int14_function(regs, ds, iret_addr)
03325 pusha_regs_t regs;
03326 Bit16u ds;
03327 iret_addr_t iret_addr;
03328 {
03329 Bit16u addr,timer,val16;
03330 Bit8u timeout;
03331
03332 ASM_START
03333 sti
03334 ASM_END
03335
03336 addr = read_word(0x0040, (regs.u.r16.dx << 1));
03337 timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx);
03338 if ((regs.u.r16.dx < 4) && (addr > 0)) {
03339 switch (regs.u.r8.ah) {
03340 case 0:
03341 outb(addr+3, inb(addr+3) | 0x80);
03342 if (regs.u.r8.al & 0xE0 == 0) {
03343 outb(addr, 0x17);
03344 outb(addr+1, 0x04);
03345 } else {
03346 val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5);
03347 outb(addr, val16 & 0xFF);
03348 outb(addr+1, val16 >> 8);
03349 }
03350 outb(addr+3, regs.u.r8.al & 0x1F);
03351 regs.u.r8.ah = inb(addr+5);
03352 regs.u.r8.al = inb(addr+6);
03353 ClearCF(iret_addr.flags);
03354 break;
03355 case 1:
03356 timer = read_word(0x0040, 0x006C);
03357 while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) {
03358 val16 = read_word(0x0040, 0x006C);
03359 if (val16 != timer) {
03360 timer = val16;
03361 timeout--;
03362 }
03363 }
03364 if (timeout) outb(addr, regs.u.r8.al);
03365 regs.u.r8.ah = inb(addr+5);
03366 if (!timeout) regs.u.r8.ah |= 0x80;
03367 ClearCF(iret_addr.flags);
03368 break;
03369 case 2:
03370 timer = read_word(0x0040, 0x006C);
03371 while (((inb(addr+5) & 0x01) == 0) && (timeout)) {
03372 val16 = read_word(0x0040, 0x006C);
03373 if (val16 != timer) {
03374 timer = val16;
03375 timeout--;
03376 }
03377 }
03378 if (timeout) {
03379 regs.u.r8.ah = 0;
03380 regs.u.r8.al = inb(addr);
03381 } else {
03382 regs.u.r8.ah = inb(addr+5);
03383 }
03384 ClearCF(iret_addr.flags);
03385 break;
03386 case 3:
03387 regs.u.r8.ah = inb(addr+5);
03388 regs.u.r8.al = inb(addr+6);
03389 ClearCF(iret_addr.flags);
03390 break;
03391 default:
03392 SetCF(iret_addr.flags);
03393 }
03394 } else {
03395 SetCF(iret_addr.flags);
03396 }
03397 }
03398
03399 void
03400 int15_function(regs, ES, DS, FLAGS)
03401 pusha_regs_t regs;
03402 Bit16u ES, DS, FLAGS;
03403 {
03404 Bit16u ebda_seg=read_word(0x0040,0x000E);
03405 bx_bool prev_a20_enable;
03406 Bit16u base15_00;
03407 Bit8u base23_16;
03408 Bit16u ss;
03409 Bit16u CX,DX;
03410
03411 Bit16u bRegister;
03412 Bit8u irqDisable;
03413
03414 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
03415
03416 switch (regs.u.r8.ah) {
03417 case 0x24:
03418 switch (regs.u.r8.al) {
03419 case 0x00:
03420 set_enable_a20(0);
03421 CLEAR_CF();
03422 regs.u.r8.ah = 0;
03423 break;
03424 case 0x01:
03425 set_enable_a20(1);
03426 CLEAR_CF();
03427 regs.u.r8.ah = 0;
03428 break;
03429 case 0x02:
03430 regs.u.r8.al = (inb(0x92) >> 1) & 0x01;
03431 CLEAR_CF();
03432 regs.u.r8.ah = 0;
03433 break;
03434 case 0x03:
03435 CLEAR_CF();
03436 regs.u.r8.ah = 0;
03437 regs.u.r16.bx = 3;
03438 break;
03439 default:
03440 BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) regs.u.r8.al);
03441 SET_CF();
03442 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03443 }
03444 break;
03445
03446 case 0x41:
03447 SET_CF();
03448 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03449 break;
03450
03451 case 0x4f:
03452
03453 #if BX_CPU < 2
03454 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03455 #else
03456
03457 #endif
03458 SET_CF();
03459 break;
03460
03461 case 0x52:
03462 CLEAR_CF();
03463 regs.u.r8.ah = 0;
03464 break;
03465
03466 case 0x83: {
03467 if( regs.u.r8.al == 0 ) {
03468
03469 if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) {
03470
03471 write_byte( 0x40, 0xA0, 1 );
03472 write_word( 0x40, 0x98, ES );
03473 write_word( 0x40, 0x9A, regs.u.r16.bx );
03474 write_word( 0x40, 0x9C, regs.u.r16.dx );
03475 write_word( 0x40, 0x9E, regs.u.r16.cx );
03476 CLEAR_CF( );
03477 irqDisable = inb( 0xA1 );
03478 outb( 0xA1, irqDisable & 0xFE );
03479 bRegister = inb_cmos( 0xB );
03480 outb_cmos( 0xB, bRegister | 0x40 );
03481 } else {
03482
03483 BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" );
03484 SET_CF();
03485 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03486 }
03487 } else if( regs.u.r8.al == 1 ) {
03488
03489 write_byte( 0x40, 0xA0, 0 );
03490 CLEAR_CF( );
03491 bRegister = inb_cmos( 0xB );
03492 outb_cmos( 0xB, bRegister & ~0x40 );
03493 } else {
03494 BX_DEBUG_INT15("int15: Func 83h, failed.\n" );
03495 SET_CF();
03496 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03497 regs.u.r8.al--;
03498 }
03499
03500 break;
03501 }
03502
03503 case 0x87:
03504 #if BX_CPU < 3
03505 # error "Int15 function 87h not supported on < 80386"
03506 #endif
03507
03508
03509
03510
03511 ASM_START
03512 cli
03513 ASM_END
03514
03515 prev_a20_enable = set_enable_a20(1);
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538 base15_00 = (ES << 4) + regs.u.r16.si;
03539 base23_16 = ES >> 12;
03540 if (base15_00 < (ES<<4))
03541 base23_16++;
03542 write_word(ES, regs.u.r16.si+0x08+0, 47);
03543 write_word(ES, regs.u.r16.si+0x08+2, base15_00);
03544 write_byte(ES, regs.u.r16.si+0x08+4, base23_16);
03545 write_byte(ES, regs.u.r16.si+0x08+5, 0x93);
03546 write_word(ES, regs.u.r16.si+0x08+6, 0x0000);
03547
03548
03549 write_word(ES, regs.u.r16.si+0x20+0, 0xffff);
03550 write_word(ES, regs.u.r16.si+0x20+2, 0x0000);
03551 write_byte(ES, regs.u.r16.si+0x20+4, 0x000f);
03552 write_byte(ES, regs.u.r16.si+0x20+5, 0x9b);
03553 write_word(ES, regs.u.r16.si+0x20+6, 0x0000);
03554
03555
03556 ss = get_SS();
03557 base15_00 = ss << 4;
03558 base23_16 = ss >> 12;
03559 write_word(ES, regs.u.r16.si+0x28+0, 0xffff);
03560 write_word(ES, regs.u.r16.si+0x28+2, base15_00);
03561 write_byte(ES, regs.u.r16.si+0x28+4, base23_16);
03562 write_byte(ES, regs.u.r16.si+0x28+5, 0x93);
03563 write_word(ES, regs.u.r16.si+0x28+6, 0x0000);
03564
03565 CX = regs.u.r16.cx;
03566 ASM_START
03567
03568
03569 mov bx, sp
03570 SEG SS
03571 mov cx, _int15_function.CX [bx]
03572
03573
03574
03575 push eax
03576 xor eax, eax
03577 mov ds, ax
03578 mov 0x0469, ss
03579 mov 0x0467, sp
03580
03581 SEG ES
03582 lgdt [si + 0x08]
03583 SEG CS
03584 lidt [pmode_IDT_info]
03585 ;; perhaps do something with IDT here
03586
03587 ;; set PE bit in CR0
03588 mov eax, cr0
03589 or al, #0x01
03590 mov cr0, eax
03591 ;; far jump to flush CPU queue after transition to protected mode
03592 JMP_AP(0x0020, protected_mode)
03593
03594 protected_mode:
03595 ;; GDT points to valid descriptor table, now load SS, DS, ES
03596 mov ax, #0x28 ;; 101 000 = 5th descriptor in table, TI=GDT, RPL=00
03597 mov ss, ax
03598 mov ax, #0x10 ;; 010 000 = 2nd descriptor in table, TI=GDT, RPL=00
03599 mov ds, ax
03600 mov ax, #0x18 ;; 011 000 = 3rd descriptor in table, TI=GDT, RPL=00
03601 mov es, ax
03602 xor si, si
03603 xor di, di
03604 cld
03605 rep
03606 movsw ;; move CX words from DS:SI to ES:DI
03607
03608 ;; make sure DS and ES limits are 64KB
03609 mov ax, #0x28
03610 mov ds, ax
03611 mov es, ax
03612
03613 ;; reset PG bit in CR0 ???
03614 mov eax, cr0
03615 and al, #0xFE
03616 mov cr0, eax
03617
03618 ;; far jump to flush CPU queue after transition to real mode
03619 JMP_AP(0xf000, real_mode)
03620
03621 real_mode:
03622 ;; restore IDT to normal real-mode defaults
03623 SEG CS
03624 lidt [rmode_IDT_info]
03625
03626
03627 xor ax, ax
03628 mov ds, ax
03629 mov ss, 0x0469
03630 mov sp, 0x0467
03631 pop eax
03632 ASM_END
03633
03634 set_enable_a20(prev_a20_enable);
03635
03636
03637 ASM_START
03638 sti
03639 ASM_END
03640
03641 regs.u.r8.ah = 0;
03642 CLEAR_CF();
03643 break;
03644
03645
03646 case 0x88:
03647
03648 #if BX_CPU < 2
03649 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03650 SET_CF();
03651 #else
03652 regs.u.r8.al = inb_cmos(0x30);
03653 regs.u.r8.ah = inb_cmos(0x31);
03654
03655
03656 if(regs.u.r16.ax > 0x3c00)
03657 regs.u.r16.ax = 0x3c00;
03658
03659 CLEAR_CF();
03660 #endif
03661 break;
03662
03663 case 0x90:
03664
03665 break;
03666
03667 case 0x91:
03668
03669 break;
03670
03671 case 0xbf:
03672 BX_INFO("*** int 15h function AH=bf not yet supported!\n");
03673 SET_CF();
03674 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03675 break;
03676
03677 case 0xC0:
03678 #if 0
03679 SET_CF();
03680 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03681 break;
03682 #endif
03683 CLEAR_CF();
03684 regs.u.r8.ah = 0;
03685 regs.u.r16.bx = BIOS_CONFIG_TABLE;
03686 ES = 0xF000;
03687 break;
03688
03689 case 0xc1:
03690 ES = ebda_seg;
03691 CLEAR_CF();
03692 break;
03693
03694 case 0xd8:
03695 bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n");
03696 SET_CF();
03697 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03698 break;
03699
03700 default:
03701 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
03702 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
03703 SET_CF();
03704 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03705 break;
03706 }
03707 }
03708
03709 #if BX_USE_PS2_MOUSE
03710 void
03711 int15_function_mouse(regs, ES, DS, FLAGS)
03712 pusha_regs_t regs;
03713 Bit16u ES, DS, FLAGS;
03714 {
03715 Bit16u ebda_seg=read_word(0x0040,0x000E);
03716 Bit8u mouse_flags_1, mouse_flags_2;
03717 Bit16u mouse_driver_seg;
03718 Bit16u mouse_driver_offset;
03719 Bit8u comm_byte, prev_command_byte;
03720 Bit8u ret, mouse_data1, mouse_data2, mouse_data3;
03721
03722 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
03723
03724 switch (regs.u.r8.ah) {
03725 case 0xC2:
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737 switch (regs.u.r8.al) {
03738 case 0:
03739 BX_DEBUG_INT15("case 0:\n");
03740 switch (regs.u.r8.bh) {
03741 case 0:
03742 BX_DEBUG_INT15("case 0: disable mouse\n");
03743 inhibit_mouse_int_and_events();
03744 ret = send_to_mouse_ctrl(0xF5);
03745 if (ret == 0) {
03746 ret = get_mouse_data(&mouse_data1);
03747 if ( (ret == 0) || (mouse_data1 == 0xFA) ) {
03748 CLEAR_CF();
03749 regs.u.r8.ah = 0;
03750 return;
03751 }
03752 }
03753
03754
03755 SET_CF();
03756 regs.u.r8.ah = ret;
03757 return;
03758 break;
03759
03760 case 1:
03761 BX_DEBUG_INT15("case 1: enable mouse\n");
03762 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
03763 if ( (mouse_flags_2 & 0x80) == 0 ) {
03764 BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n");
03765 SET_CF();
03766 regs.u.r8.ah = 5;
03767 return;
03768 }
03769 inhibit_mouse_int_and_events();
03770 ret = send_to_mouse_ctrl(0xF4);
03771 if (ret == 0) {
03772 ret = get_mouse_data(&mouse_data1);
03773 if ( (ret == 0) && (mouse_data1 == 0xFA) ) {
03774 enable_mouse_int_and_events();
03775 CLEAR_CF();
03776 regs.u.r8.ah = 0;
03777 return;
03778 }
03779 }
03780 SET_CF();
03781 regs.u.r8.ah = ret;
03782 return;
03783
03784 default:
03785 BX_DEBUG_INT15("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh);
03786 SET_CF();
03787 regs.u.r8.ah = 1;
03788 return;
03789 }
03790 break;
03791
03792 case 1:
03793 case 5:
03794 BX_DEBUG_INT15("case 1 or 5:\n");
03795 if (regs.u.r8.al == 5) {
03796 if (regs.u.r8.bh != 3) {
03797 SET_CF();
03798 regs.u.r8.ah = 0x02;
03799 return;
03800 }
03801 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
03802 mouse_flags_2 = (mouse_flags_2 & 0x00) | regs.u.r8.bh;
03803 mouse_flags_1 = 0x00;
03804 write_byte(ebda_seg, 0x0026, mouse_flags_1);
03805 write_byte(ebda_seg, 0x0027, mouse_flags_2);
03806 }
03807
03808 inhibit_mouse_int_and_events();
03809 ret = send_to_mouse_ctrl(0xFF);
03810 if (ret == 0) {
03811 ret = get_mouse_data(&mouse_data3);
03812
03813 if (mouse_data3 == 0xfe) {
03814 SET_CF();
03815 return;
03816 }
03817 if (mouse_data3 != 0xfa)
03818 BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3);
03819 if ( ret == 0 ) {
03820 ret = get_mouse_data(&mouse_data1);
03821 if ( ret == 0 ) {
03822 ret = get_mouse_data(&mouse_data2);
03823 if ( ret == 0 ) {
03824
03825 enable_mouse_int_and_events();
03826 CLEAR_CF();
03827 regs.u.r8.ah = 0;
03828 regs.u.r8.bl = mouse_data1;
03829 regs.u.r8.bh = mouse_data2;
03830 return;
03831 }
03832 }
03833 }
03834 }
03835
03836
03837 SET_CF();
03838 regs.u.r8.ah = ret;
03839 return;
03840
03841 case 2:
03842 BX_DEBUG_INT15("case 2:\n");
03843 switch (regs.u.r8.bh) {
03844 case 0: mouse_data1 = 10; break;
03845 case 1: mouse_data1 = 20; break;
03846 case 2: mouse_data1 = 40; break;
03847 case 3: mouse_data1 = 60; break;
03848 case 4: mouse_data1 = 80; break;
03849 case 5: mouse_data1 = 100; break;
03850 case 6: mouse_data1 = 200; break;
03851 default: mouse_data1 = 0;
03852 }
03853 if (mouse_data1 > 0) {
03854 ret = send_to_mouse_ctrl(0xF3);
03855 if (ret == 0) {
03856 ret = get_mouse_data(&mouse_data2);
03857 ret = send_to_mouse_ctrl(mouse_data1);
03858 ret = get_mouse_data(&mouse_data2);
03859 CLEAR_CF();
03860 regs.u.r8.ah = 0;
03861 } else {
03862
03863 SET_CF();
03864 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03865 }
03866 } else {
03867
03868 SET_CF();
03869 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03870 }
03871 break;
03872
03873 case 3:
03874 BX_DEBUG_INT15("case 3:\n");
03875
03876
03877
03878
03879
03880 CLEAR_CF();
03881 regs.u.r8.ah = 0;
03882 break;
03883
03884 case 4:
03885 BX_DEBUG_INT15("case 4:\n");
03886 inhibit_mouse_int_and_events();
03887 ret = send_to_mouse_ctrl(0xF2);
03888 if (ret == 0) {
03889 ret = get_mouse_data(&mouse_data1);
03890 ret = get_mouse_data(&mouse_data2);
03891 CLEAR_CF();
03892 regs.u.r8.ah = 0;
03893 regs.u.r8.bh = mouse_data2;
03894 } else {
03895
03896 SET_CF();
03897 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03898 }
03899 break;
03900
03901 case 6:
03902 BX_DEBUG_INT15("case 6:\n");
03903 switch (regs.u.r8.bh) {
03904 case 0:
03905 comm_byte = inhibit_mouse_int_and_events();
03906 ret = send_to_mouse_ctrl(0xE9);
03907 if (ret == 0) {
03908 ret = get_mouse_data(&mouse_data1);
03909 if (mouse_data1 != 0xfa)
03910 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
03911 if (ret == 0) {
03912 ret = get_mouse_data(&mouse_data1);
03913 if ( ret == 0 ) {
03914 ret = get_mouse_data(&mouse_data2);
03915 if ( ret == 0 ) {
03916 ret = get_mouse_data(&mouse_data3);
03917 if ( ret == 0 ) {
03918 CLEAR_CF();
03919 regs.u.r8.ah = 0;
03920 regs.u.r8.bl = mouse_data1;
03921 regs.u.r8.cl = mouse_data2;
03922 regs.u.r8.dl = mouse_data3;
03923 set_kbd_command_byte(comm_byte);
03924 return;
03925 }
03926 }
03927 }
03928 }
03929 }
03930
03931
03932 SET_CF();
03933 regs.u.r8.ah = ret;
03934 set_kbd_command_byte(comm_byte);
03935 return;
03936
03937 case 1:
03938 case 2:
03939 comm_byte = inhibit_mouse_int_and_events();
03940 if (regs.u.r8.bh == 1) {
03941 ret = send_to_mouse_ctrl(0xE6);
03942 } else {
03943 ret = send_to_mouse_ctrl(0xE7);
03944 }
03945 if (ret == 0) {
03946 get_mouse_data(&mouse_data1);
03947 ret = (mouse_data1 != 0xFA);
03948 }
03949 if (ret == 0) {
03950 CLEAR_CF();
03951 regs.u.r8.ah = 0;
03952 } else {
03953
03954 SET_CF();
03955 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
03956 }
03957 set_kbd_command_byte(comm_byte);
03958 break;
03959
03960 default:
03961 BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh);
03962 }
03963 break;
03964
03965 case 7:
03966 BX_DEBUG_INT15("case 7:\n");
03967 mouse_driver_seg = ES;
03968 mouse_driver_offset = regs.u.r16.bx;
03969 write_word(ebda_seg, 0x0022, mouse_driver_offset);
03970 write_word(ebda_seg, 0x0024, mouse_driver_seg);
03971 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
03972 if (mouse_driver_offset == 0 && mouse_driver_seg == 0) {
03973
03974 if ( (mouse_flags_2 & 0x80) != 0 ) {
03975 mouse_flags_2 &= ~0x80;
03976 inhibit_mouse_int_and_events();
03977 }
03978 }
03979 else {
03980
03981 mouse_flags_2 |= 0x80;
03982 }
03983 write_byte(ebda_seg, 0x0027, mouse_flags_2);
03984 CLEAR_CF();
03985 regs.u.r8.ah = 0;
03986 break;
03987
03988 default:
03989 BX_DEBUG_INT15("case default:\n");
03990 regs.u.r8.ah = 1;
03991 SET_CF();
03992 }
03993 break;
03994
03995 default:
03996 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
03997 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
03998 SET_CF();
03999 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
04000 break;
04001 }
04002 }
04003 #endif
04004
04005
04006 void set_e820_range(ES, DI, start, end, type)
04007 Bit16u ES;
04008 Bit16u DI;
04009 Bit32u start;
04010 Bit32u end;
04011 Bit16u type;
04012 {
04013 write_word(ES, DI, start);
04014 write_word(ES, DI+2, start >> 16);
04015 write_word(ES, DI+4, 0x00);
04016 write_word(ES, DI+6, 0x00);
04017
04018 end -= start;
04019 write_word(ES, DI+8, end);
04020 write_word(ES, DI+10, end >> 16);
04021 write_word(ES, DI+12, 0x0000);
04022 write_word(ES, DI+14, 0x0000);
04023
04024 write_word(ES, DI+16, type);
04025 write_word(ES, DI+18, 0x0);
04026 }
04027
04028 void
04029 int15_function32(regs, ES, DS, FLAGS)
04030 pushad_regs_t regs;
04031 Bit16u ES, DS, FLAGS;
04032 {
04033 Bit32u extended_memory_size=0;
04034 Bit16u CX,DX;
04035
04036 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
04037
04038 switch (regs.u.r8.ah) {
04039 case 0x86:
04040
04041
04042
04043 CX = regs.u.r16.cx;
04044 DX = regs.u.r16.dx;
04045
04046 ASM_START
04047 sti
04048
04049 ;; Get the count in eax
04050 mov bx, sp
04051 SEG SS
04052 mov ax, _int15_function.CX [bx]
04053 shl eax, #16
04054 SEG SS
04055 mov ax, _int15_function.DX [bx]
04056
04057 ;; convert to numbers of 15usec ticks
04058 mov ebx, #15
04059 xor edx, edx
04060 div eax, ebx
04061 mov ecx, eax
04062
04063 ;; wait for ecx number of refresh requests
04064 in al, #0x61
04065 and al,#0x10
04066 mov ah, al
04067
04068 or ecx, ecx
04069 je int1586_tick_end
04070 int1586_tick:
04071 in al, #0x61
04072 and al,#0x10
04073 cmp al, ah
04074 je int1586_tick
04075 mov ah, al
04076 dec ecx
04077 jnz int1586_tick
04078 int1586_tick_end:
04079 ASM_END
04080
04081 break;
04082
04083 case 0xe8:
04084 switch(regs.u.r8.al)
04085 {
04086 case 0x20:
04087 if(regs.u.r32.edx == 0x534D4150)
04088 {
04089 switch(regs.u.r16.bx)
04090 {
04091 case 0:
04092 set_e820_range(ES, regs.u.r16.di,
04093 0x0000000L, 0x0009fc00L, 1);
04094 regs.u.r32.ebx = 1;
04095 regs.u.r32.eax = 0x534D4150;
04096 regs.u.r32.ecx = 0x14;
04097 CLEAR_CF();
04098 return;
04099 break;
04100 case 1:
04101 set_e820_range(ES, regs.u.r16.di,
04102 0x0009fc00L, 0x000a0000L, 2);
04103 regs.u.r32.ebx = 2;
04104 regs.u.r32.eax = 0x534D4150;
04105 regs.u.r32.ecx = 0x14;
04106 CLEAR_CF();
04107 return;
04108 break;
04109 case 2:
04110 set_e820_range(ES, regs.u.r16.di,
04111 0x000e8000L, 0x00100000L, 2);
04112 regs.u.r32.ebx = 3;
04113 regs.u.r32.eax = 0x534D4150;
04114 regs.u.r32.ecx = 0x14;
04115 CLEAR_CF();
04116 return;
04117 break;
04118 case 3:
04119 extended_memory_size = inb_cmos(0x35);
04120 extended_memory_size <<= 8;
04121 extended_memory_size |= inb_cmos(0x34);
04122 extended_memory_size *= 64;
04123 if(extended_memory_size > 0x3bc000)
04124 {
04125 extended_memory_size = 0x3bc000;
04126 }
04127 extended_memory_size *= 1024;
04128 extended_memory_size += (16L * 1024 * 1024);
04129
04130 if(extended_memory_size <= (16L * 1024 * 1024))
04131 {
04132 extended_memory_size = inb_cmos(0x31);
04133 extended_memory_size <<= 8;
04134 extended_memory_size |= inb_cmos(0x30);
04135 extended_memory_size *= 1024;
04136 }
04137
04138 set_e820_range(ES, regs.u.r16.di,
04139 0x00100000L, extended_memory_size, 1);
04140 regs.u.r32.ebx = 4;
04141 regs.u.r32.eax = 0x534D4150;
04142 regs.u.r32.ecx = 0x14;
04143 CLEAR_CF();
04144 return;
04145 break;
04146 case 4:
04147
04148