Version:
~
[ 2.3.5 ] ~
[ 2.3 ] ~
** Warning: Cannot open xref database.
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: rombios.c,v 1.183 2007/09/10 20:00:29 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
12 //
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
17 //
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26
27 // ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
28
29
30 // ROM BIOS compatability entry points:
31 // ===================================
32 // $e05b ; POST Entry Point
33 // $e2c3 ; NMI Handler Entry Point
34 // $e3fe ; INT 13h Fixed Disk Services Entry Point
35 // $e401 ; Fixed Disk Parameter Table
36 // $e6f2 ; INT 19h Boot Load Service Entry Point
37 // $e6f5 ; Configuration Data Table
38 // $e729 ; Baud Rate Generator Table
39 // $e739 ; INT 14h Serial Communications Service Entry Point
40 // $e82e ; INT 16h Keyboard Service Entry Point
41 // $e987 ; INT 09h Keyboard Service Entry Point
42 // $ec59 ; INT 13h Diskette Service Entry Point
43 // $ef57 ; INT 0Eh Diskette Hardware ISR Entry Point
44 // $efc7 ; Diskette Controller Parameter Table
45 // $efd2 ; INT 17h Printer Service Entry Point
46 // $f045 ; INT 10 Functions 0-Fh Entry Point
47 // $f065 ; INT 10h Video Support Service Entry Point
48 // $f0a4 ; MDA/CGA Video Parameter Table (INT 1Dh)
49 // $f841 ; INT 12h Memory Size Service Entry Point
50 // $f84d ; INT 11h Equipment List Service Entry Point
51 // $f859 ; INT 15h System Services Entry Point
52 // $fa6e ; Character Font for 320x200 & 640x200 Graphics (lower 128 characters)
53 // $fe6e ; INT 1Ah Time-of-day Service Entry Point
54 // $fea5 ; INT 08h System Timer ISR Entry Point
55 // $fef3 ; Initial Interrupt Vector Offsets Loaded by POST
56 // $ff53 ; IRET Instruction for Dummy Interrupt Handler
57 // $ff54 ; INT 05h Print Screen Service Entry Point
58 // $fff0 ; Power-up Entry Point
59 // $fff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
60 // $fffe ; System Model ID
61
62 // NOTES for ATA/ATAPI driver (cbbochs@free.fr)
63 // Features
64 // - supports up to 4 ATA interfaces
65 // - device/geometry detection
66 // - 16bits/32bits device access
67 // - pchs/lba access
68 // - datain/dataout/packet command support
69 //
70 // NOTES for El-Torito Boot (cbbochs@free.fr)
71 // - CD-ROM booting is only available if ATA/ATAPI Driver is available
72 // - Current code is only able to boot mono-session cds
73 // - Current code can not boot and emulate a hard-disk
74 // the bios will panic otherwise
75 // - Current code also use memory in EBDA segement.
76 // - I used cmos byte 0x3D to store extended information on boot-device
77 // - Code has to be modified modified to handle multiple cdrom drives
78 // - Here are the cdrom boot failure codes:
79 // 1 : no atapi device found
80 // 2 : no atapi cdrom found
81 // 3 : can not read cd - BRVD
82 // 4 : cd is not eltorito (BRVD)
83 // 5 : cd is not eltorito (ISO TAG)
84 // 6 : cd is not eltorito (ELTORITO TAG)
85 // 7 : can not read cd - boot catalog
86 // 8 : boot catalog : bad header
87 // 9 : boot catalog : bad platform
88 // 10 : boot catalog : bad signature
89 // 11 : boot catalog : bootable flag not set
90 // 12 : can not read cd - boot image
91 //
92 // ATA driver
93 // - EBDA segment.
94 // I used memory starting at 0x121 in the segment
95 // - the translation policy is defined in cmos regs 0x39 & 0x3a
96 //
97 // TODO :
98 //
99 // int74
100 // - needs to be reworked. Uses direct [bp] offsets. (?)
101 //
102 // int13:
103 // - f04 (verify sectors) isn't complete (?)
104 // - f02/03/04 should set current cyl,etc in BDA (?)
105 // - rewrite int13_relocated & clean up int13 entry code
106 //
107 // NOTES:
108 // - NMI access (bit7 of addr written to 70h)
109 //
110 // ATA driver
111 // - should handle the "don't detect" bit (cmos regs 0x3b & 0x3c)
112 // - could send the multiple-sector read/write commands
113 //
114 // El-Torito
115 // - Emulate a Hard-disk (currently only diskette can be emulated) see "FIXME ElTorito Harddisk"
116 // - Implement remaining int13_cdemu functions (as defined by El-Torito specs)
117 // - cdrom drive is hardcoded to ide 0 device 1 in several places. see "FIXME ElTorito Hardcoded"
118 // - int13 Fix DL when emulating a cd. In that case DL is decremented before calling real int13.
119 // This is ok. But DL should be reincremented afterwards.
120 // - Fix all "FIXME ElTorito Various"
121 // - should be able to boot any cdrom instead of the first one
122 //
123 // BCC Bug: find a generic way to handle the bug of #asm after an "if" (fixed in 0.16.7)
124
125 #include "rombios.h"
126
127 #define DEBUG_ATA 0
128 #define DEBUG_INT13_HD 0
129 #define DEBUG_INT13_CD 0
130 #define DEBUG_INT13_ET 0
131 #define DEBUG_INT13_FL 0
132 #define DEBUG_INT15 0
133 #define DEBUG_INT16 0
134 #define DEBUG_INT1A 0
135 #define DEBUG_INT74 0
136 #define DEBUG_APM 0
137
138 #define BX_CPU 3
139 #define BX_USE_PS2_MOUSE 1
140 #define BX_CALL_INT15_4F 1
141 #define BX_USE_EBDA 1
142 #define BX_SUPPORT_FLOPPY 1
143 #define BX_FLOPPY_ON_CNT 37 /* 2 seconds */
144 #define BX_PCIBIOS 1
145 #define BX_APM 1
146
147 #define BX_USE_ATADRV 1
148 #define BX_ELTORITO_BOOT 1
149
150 #define BX_MAX_ATA_INTERFACES 4
151 #define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2)
152
153 #define BX_VIRTUAL_PORTS 1 /* normal output to Bochs ports */
154 #define BX_DEBUG_SERIAL 0 /* output to COM1 */
155
156 /* model byte 0xFC = AT */
157 #define SYS_MODEL_ID 0xFC
158 #define SYS_SUBMODEL_ID 0x00
159 #define BIOS_REVISION 1
160 #define BIOS_CONFIG_TABLE 0xe6f5
161
162 #ifndef BIOS_BUILD_DATE
163 # define BIOS_BUILD_DATE "06/23/99"
164 #endif
165
166 // 1K of base memory used for Extended Bios Data Area (EBDA)
167 // EBDA is used for PS/2 mouse support, and IDE BIOS, etc.
168 #define EBDA_SEG 0x9FC0
169 #define EBDA_SIZE 1 // In KiB
170 #define BASE_MEM_IN_K (640 - EBDA_SIZE)
171
172 // Define the application NAME
173 #if defined(BX_QEMU)
174 # define BX_APPNAME "QEMU"
175 #elif defined(PLEX86)
176 # define BX_APPNAME "Plex86"
177 #else
178 # define BX_APPNAME "Bochs"
179 #endif
180
181 // Sanity Checks
182 #if BX_USE_ATADRV && BX_CPU<3
183 # error The ATA/ATAPI Driver can only to be used with a 386+ cpu
184 #endif
185 #if BX_USE_ATADRV && !BX_USE_EBDA
186 # error ATA/ATAPI Driver can only be used if EBDA is available
187 #endif
188 #if BX_ELTORITO_BOOT && !BX_USE_ATADRV
189 # error El-Torito Boot can only be use if ATA/ATAPI Driver is available
190 #endif
191 #if BX_PCIBIOS && BX_CPU<3
192 # error PCI BIOS can only be used with 386+ cpu
193 #endif
194 #if BX_APM && BX_CPU<3
195 # error APM BIOS can only be used with 386+ cpu
196 #endif
197
198 // define this if you want to make PCIBIOS working on a specific bridge only
199 // undef enables PCIBIOS when at least one PCI device is found
200 // i440FX is emulated by Bochs and QEMU
201 #define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge
202
203 // #20 is dec 20
204 // #$20 is hex 20 = 32
205 // #0x20 is hex 20 = 32
206 // LDA #$20
207 // JSR $E820
208 // LDD .i,S
209 // JSR $C682
210 // mov al, #$20
211
212 // all hex literals should be prefixed with '0x'
213 // grep "#[0-9a-fA-F][0-9a-fA-F]" rombios.c
214 // no mov SEG-REG, #value, must mov register into seg-reg
215 // grep -i "mov[ ]*.s" rombios.c
216
217 // This is for compiling with gcc2 and gcc3
218 #define ASM_START #asm
219 #define ASM_END #endasm
220
221 ASM_START
222 .rom
223
224 .org 0x0000
225
226 #if BX_CPU >= 3
227 use16 386
228 #else
229 use16 286
230 #endif
231
232 MACRO HALT
233 ;; the HALT macro is called with the line number of the HALT call.
234 ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
235 ;; to print a BX_PANIC message. This will normally halt the simulation
236 ;; with a message such as "BIOS panic at rombios.c, line 4091".
237 ;; However, users can choose to make panics non-fatal and continue.
238 #if BX_VIRTUAL_PORTS
239 mov dx,#PANIC_PORT
240 mov ax,#?1
241 out dx,ax
242 #else
243 mov dx,#0x80
244 mov ax,#?1
245 out dx,al
246 #endif
247 MEND
248
249 MACRO JMP_AP
250 db 0xea
251 dw ?2
252 dw ?1
253 MEND
254
255 MACRO SET_INT_VECTOR
256 mov ax, ?3
257 mov ?1*4, ax
258 mov ax, ?2
259 mov ?1*4+2, ax
260 MEND
261
262 ASM_END
263
264 typedef unsigned char Bit8u;
265 typedef unsigned short Bit16u;
266 typedef unsigned short bx_bool;
267 typedef unsigned long Bit32u;
268
269
270 void memsetb(seg,offset,value,count);
271 void memcpyb(dseg,doffset,sseg,soffset,count);
272 void memcpyd(dseg,doffset,sseg,soffset,count);
273
274 // memset of count bytes
275 void
276 memsetb(seg,offset,value,count)
277 Bit16u seg;
278 Bit16u offset;
279 Bit16u value;
280 Bit16u count;
281 {
282 ASM_START
283 push bp
284 mov bp, sp
285
286 push ax
287 push cx
288 push es
289 push di
290
291 mov cx, 10[bp] ; count
292 cmp cx, #0x00
293 je memsetb_end
294 mov ax, 4[bp] ; segment
295 mov es, ax
296 mov ax, 6[bp] ; offset
297 mov di, ax
298 mov al, 8[bp] ; value
299 cld
300 rep
301 stosb
302
303 memsetb_end:
304 pop di
305 pop es
306 pop cx
307 pop ax
308
309 pop bp
310 ASM_END
311 }
312
313 // memcpy of count bytes
314 void
315 memcpyb(dseg,doffset,sseg,soffset,count)
316 Bit16u dseg;
317 Bit16u doffset;
318 Bit16u sseg;
319 Bit16u soffset;
320 Bit16u count;
321 {
322 ASM_START
323 push bp
324 mov bp, sp
325
326 push ax
327 push cx
328 push es
329 push di
330 push ds
331 push si
332
333 mov cx, 12[bp] ; count
334 cmp cx, #0x0000
335 je memcpyb_end
336 mov ax, 4[bp] ; dsegment
337 mov es, ax
338 mov ax, 6[bp] ; doffset
339 mov di, ax
340 mov ax, 8[bp] ; ssegment
341 mov ds, ax
342 mov ax, 10[bp] ; soffset
343 mov si, ax
344 cld
345 rep
346 movsb
347
348 memcpyb_end:
349 pop si
350 pop ds
351 pop di
352 pop es
353 pop cx
354 pop ax
355
356 pop bp
357 ASM_END
358 }
359
360 // memcpy of count dword
361 void
362 memcpyd(dseg,doffset,sseg,soffset,count)
363 Bit16u dseg;
364 Bit16u doffset;
365 Bit16u sseg;
366 Bit16u soffset;
367 Bit16u count;
368 {
369 ASM_START
370 push bp
371 mov bp, sp
372
373 push ax
374 push cx
375 push es
376 push di
377 push ds
378 push si
379
380 mov cx, 12[bp] ; count
381 cmp cx, #0x0000
382 je memcpyd_end
383 mov ax, 4[bp] ; dsegment
384 mov es, ax
385 mov ax, 6[bp] ; doffset
386 mov di, ax
387 mov ax, 8[bp] ; ssegment
388 mov ds, ax
389 mov ax, 10[bp] ; soffset
390 mov si, ax
391 cld
392 rep
393 movsd
394
395 memcpyd_end:
396 pop si
397 pop ds
398 pop di
399 pop es
400 pop cx
401 pop ax
402
403 pop bp
404 ASM_END
405 }
406
407 // read_dword and write_dword functions
408 static Bit32u read_dword();
409 static void write_dword();
410
411 Bit32u
412 read_dword(seg, offset)
413 Bit16u seg;
414 Bit16u offset;
415 {
416 ASM_START
417 push bp
418 mov bp, sp
419
420 push bx
421 push ds
422 mov ax, 4[bp] ; segment
423 mov ds, ax
424 mov bx, 6[bp] ; offset
425 mov ax, [bx]
426 inc bx
427 inc bx
428 mov dx, [bx]
429 ;; ax = return value (word)
430 ;; dx = return value (word)
431 pop ds
432 pop bx
433
434 pop bp
435 ASM_END
436 }
437
438 void
439 write_dword(seg, offset, data)
440 Bit16u seg;
441 Bit16u offset;
442 Bit32u data;
443 {
444 ASM_START
445 push bp
446 mov bp, sp
447
448 push ax
449 push bx
450 push ds
451 mov ax, 4[bp] ; segment
452 mov ds, ax
453 mov bx, 6[bp] ; offset
454 mov ax, 8[bp] ; data word
455 mov [bx], ax ; write data word
456 inc bx
457 inc bx
458 mov ax, 10[bp] ; data word
459 mov [bx], ax ; write data word
460 pop ds
461 pop bx
462 pop ax
463
464 pop bp
465 ASM_END
466 }
467
468 // Bit32u (unsigned long) and long helper functions
469 ASM_START
470
471 ;; and function
472 landl:
473 landul:
474 SEG SS
475 and ax,[di]
476 SEG SS
477 and bx,2[di]
478 ret
479
480 ;; add function
481 laddl:
482 laddul:
483 SEG SS
484 add ax,[di]
485 SEG SS
486 adc bx,2[di]
487 ret
488
489 ;; cmp function
490 lcmpl:
491 lcmpul:
492 and eax, #0x0000FFFF
493 shl ebx, #16
494 add eax, ebx
495 shr ebx, #16
496 SEG SS
497 cmp eax, dword ptr [di]
498 ret
499
500 ;; sub function
501 lsubl:
502 lsubul:
503 SEG SS
504 sub ax,[di]
505 SEG SS
506 sbb bx,2[di]
507 ret
508
509 ;; mul function
510 lmull:
511 lmulul:
512 and eax, #0x0000FFFF
513 shl ebx, #16
514 add eax, ebx
515 SEG SS
516 mul eax, dword ptr [di]
517 mov ebx, eax
518 shr ebx, #16
519 ret
520
521 ;; dec function
522 ldecl:
523 ldecul:
524 SEG SS
525 dec dword ptr [bx]
526 ret
527
528 ;; or function
529 lorl:
530 lorul:
531 SEG SS
532 or ax,[di]
533 SEG SS
534 or bx,2[di]
535 ret
536
537 ;; inc function
538 lincl:
539 lincul:
540 SEG SS
541 inc dword ptr [bx]
542 ret
543
544 ;; tst function
545 ltstl:
546 ltstul:
547 and eax, #0x0000FFFF
548 shl ebx, #16
549 add eax, ebx
550 shr ebx, #16
551 test eax, eax
552 ret
553
554 ;; sr function
555 lsrul:
556 mov cx,di
557 jcxz lsr_exit
558 and eax, #0x0000FFFF
559 shl ebx, #16
560 add eax, ebx
561 lsr_loop:
562 shr eax, #1
563 loop lsr_loop
564 mov ebx, eax
565 shr ebx, #16
566 lsr_exit:
567 ret
568
569 ;; sl function
570 lsll:
571 lslul:
572 mov cx,di
573 jcxz lsl_exit
574 and eax, #0x0000FFFF
575 shl ebx, #16
576 add eax, ebx
577 lsl_loop:
578 shl eax, #1
579 loop lsl_loop
580 mov ebx, eax
581 shr ebx, #16
582 lsl_exit:
583 ret
584
585 idiv_:
586 cwd
587 idiv bx
588 ret
589
590 idiv_u:
591 xor dx,dx
592 div bx
593 ret
594
595 ldivul:
596 and eax, #0x0000FFFF
597 shl ebx, #16
598 add eax, ebx
599 xor edx, edx
600 SEG SS
601 mov bx, 2[di]
602 shl ebx, #16
603 SEG SS
604 mov bx, [di]
605 div ebx
606 mov ebx, eax
607 shr ebx, #16
608 ret
609
610 ASM_END
611
612 // for access to RAM area which is used by interrupt vectors
613 // and BIOS Data Area
614
615 typedef struct {
616 unsigned char filler1[0x400];
617 unsigned char filler2[0x6c];
618 Bit16u ticks_low;
619 Bit16u ticks_high;
620 Bit8u midnight_flag;
621 } bios_data_t;
622
623 #define BiosData ((bios_data_t *) 0)
624
625 #if BX_USE_ATADRV
626 typedef struct {
627 Bit16u heads; // # heads
628 Bit16u cylinders; // # cylinders
629 Bit16u spt; // # sectors / track
630 } chs_t;
631
632 // DPTE definition
633 typedef struct {
634 Bit16u iobase1;
635 Bit16u iobase2;
636 Bit8u prefix;
637 Bit8u unused;
638 Bit8u irq;
639 Bit8u blkcount;
640 Bit8u dma;
641 Bit8u pio;
642 Bit16u options;
643 Bit16u reserved;
644 Bit8u revision;
645 Bit8u checksum;
646 } dpte_t;
647
648 typedef struct {
649 Bit8u iface; // ISA or PCI
650 Bit16u iobase1; // IO Base 1
651 Bit16u iobase2; // IO Base 2
652 Bit8u irq; // IRQ
653 } ata_channel_t;
654
655 typedef struct {
656 Bit8u type; // Detected type of ata (ata/atapi/none/unknown)
657 Bit8u device; // Detected type of attached devices (hd/cd/none)
658 Bit8u removable; // Removable device flag
659 Bit8u lock; // Locks for removable devices
660 // Bit8u lba_capable; // LBA capable flag - always yes for bochs devices
661 Bit8u mode; // transfert mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA
662 Bit16u blksize; // block size
663
664 Bit8u translation; // type of translation
665 chs_t lchs; // Logical CHS
666 chs_t pchs; // Physical CHS
667
668 Bit32u sectors; // Total sectors count
669 } ata_device_t;
670
671 typedef struct {
672 // ATA channels info
673 ata_channel_t channels[BX_MAX_ATA_INTERFACES];
674
675 // ATA devices info
676 ata_device_t devices[BX_MAX_ATA_DEVICES];
677 //
678 // map between (bios hd id - 0x80) and ata channels
679 Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES];
680
681 // map between (bios cd id - 0xE0) and ata channels
682 Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES];
683
684 // Buffer for DPTE table
685 dpte_t dpte;
686
687 // Count of transferred sectors and bytes
688 Bit16u trsfsectors;
689 Bit32u trsfbytes;
690
691 } ata_t;
692
693 #if BX_ELTORITO_BOOT
694 // ElTorito Device Emulation data
695 typedef struct {
696 Bit8u active;
697 Bit8u media;
698 Bit8u emulated_drive;
699 Bit8u controller_index;
700 Bit16u device_spec;
701 Bit32u ilba;
702 Bit16u buffer_segment;
703 Bit16u load_segment;
704 Bit16u sector_count;
705
706 // Virtual device
707 chs_t vdevice;
708 } cdemu_t;
709 #endif // BX_ELTORITO_BOOT
710
711 // for access to EBDA area
712 // The EBDA structure should conform to
713 // http://www.frontiernet.net/~fys/rombios.htm document
714 // I made the ata and cdemu structs begin at 0x121 in the EBDA seg
715 // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot
716 // device tables are at 0x9ff00 -- 0x9ffff
717 typedef struct {
718 unsigned char filler1[0x3D];
719
720 // FDPT - Can be splitted in data members if needed
721 unsigned char fdpt0[0x10];
722 unsigned char fdpt1[0x10];
723
724 unsigned char filler2[0xC4];
725
726 // ATA Driver data
727 ata_t ata;
728
729 #if BX_ELTORITO_BOOT
730 // El Torito Emulation data
731 cdemu_t cdemu;
732 #endif // BX_ELTORITO_BOOT
733
734 } ebda_data_t;
735
736 #define EbdaData ((ebda_data_t *) 0)
737
738 // for access to the int13ext structure
739 typedef struct {
740 Bit8u size;
741 Bit8u reserved;
742 Bit16u count;
743 Bit16u offset;
744 Bit16u segment;
745 Bit32u lba1;
746 Bit32u lba2;
747 } int13ext_t;
748
749 #define Int13Ext ((int13ext_t *) 0)
750
751 // Disk Physical Table definition
752 typedef struct {
753 Bit16u size;
754 Bit16u infos;
755 Bit32u cylinders;
756 Bit32u heads;
757 Bit32u spt;
758 Bit32u sector_count1;
759 Bit32u sector_count2;
760 Bit16u blksize;
761 Bit16u dpte_segment;
762 Bit16u dpte_offset;
763 Bit16u key;
764 Bit8u dpi_length;
765 Bit8u reserved1;
766 Bit16u reserved2;
767 Bit8u host_bus[4];
768 Bit8u iface_type[8];
769 Bit8u iface_path[8];
770 Bit8u device_path[8];
771 Bit8u reserved3;
772 Bit8u checksum;
773 } dpt_t;
774
775 #define Int13DPT ((dpt_t *) 0)
776
777 #endif // BX_USE_ATADRV
778
779 typedef struct {
780 union {
781 struct {
782 Bit16u di, si, bp, sp;
783 Bit16u bx, dx, cx, ax;
784 } r16;
785 struct {
786 Bit16u filler[4];
787 Bit8u bl, bh, dl, dh, cl, ch, al, ah;
788 } r8;
789 } u;
790 } pusha_regs_t;
791
792 typedef struct {
793 union {
794 struct {
795 Bit32u edi, esi, ebp, esp;
796 Bit32u ebx, edx, ecx, eax;
797 } r32;
798 struct {
799 Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4;
800 Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8;
801 } r16;
802 struct {
803 Bit32u filler[4];
804 Bit8u bl, bh;
805 Bit16u filler1;
806 Bit8u dl, dh;
807 Bit16u filler2;
808 Bit8u cl, ch;
809 Bit16u filler3;
810 Bit8u al, ah;
811 Bit16u filler4;
812 } r8;
813 } u;
814 } pushad_regs_t;
815
816 typedef struct {
817 union {
818 struct {
819 Bit16u flags;
820 } r16;
821 struct {
822 Bit8u flagsl;
823 Bit8u flagsh;
824 } r8;
825 } u;
826 } flags_t;
827
828 #define SetCF(x) x.u.r8.flagsl |= 0x01
829 #define SetZF(x) x.u.r8.flagsl |= 0x40
830 #define ClearCF(x) x.u.r8.flagsl &= 0xfe
831 #define ClearZF(x) x.u.r8.flagsl &= 0xbf
832 #define GetCF(x) (x.u.r8.flagsl & 0x01)
833
834 typedef struct {
835 Bit16u ip;
836 Bit16u cs;
837 flags_t flags;
838 } iret_addr_t;
839
840
841
842 static Bit8u inb();
843 static Bit8u inb_cmos();
844 static void outb();
845 static void outb_cmos();
846 static Bit16u inw();
847 static void outw();
848 static void init_rtc();
849 static bx_bool rtc_updating();
850
851 static Bit8u read_byte();
852 static Bit16u read_word();
853 static void write_byte();
854 static void write_word();
855 static void bios_printf();
856
857 static Bit8u inhibit_mouse_int_and_events();
858 static void enable_mouse_int_and_events();
859 static Bit8u send_to_mouse_ctrl();
860 static Bit8u get_mouse_data();
861 static void set_kbd_command_byte();
862
863 static void int09_function();
864 static void int13_harddisk();
865 static void int13_cdrom();
866 static void int13_cdemu();
867 static void int13_eltorito();
868 static void int13_diskette_function();
869 static void int14_function();
870 static void int15_function();
871 static void int16_function();
872 static void int17_function();
873 static void int19_function();
874 static void int1a_function();
875 static void int70_function();
876 static void int74_function();
877 static Bit16u get_CS();
878 static Bit16u get_SS();
879 static unsigned int enqueue_key();
880 static unsigned int dequeue_key();
881 static void get_hd_geometry();
882 static void set_diskette_ret_status();
883 static void set_diskette_current_cyl();
884 static void determine_floppy_media();
885 static bx_bool floppy_drive_exists();
886 static bx_bool floppy_drive_recal();
887 static bx_bool floppy_media_known();
888 static bx_bool floppy_media_sense();
889 static bx_bool set_enable_a20();
890 static void debugger_on();
891 static void debugger_off();
892 static void keyboard_init();
893 static void keyboard_panic();
894 static void shutdown_status_panic();
895 static void nmi_handler_msg();
896
897 static void print_bios_banner();
898 static void print_boot_device();
899 static void print_boot_failure();
900 static void print_cdromboot_failure();
901
902 # if BX_USE_ATADRV
903
904 // ATA / ATAPI driver
905 void ata_init();
906 void ata_detect();
907 void ata_reset();
908
909 Bit16u ata_cmd_non_data();
910 Bit16u ata_cmd_data_in();
911 Bit16u ata_cmd_data_out();
912 Bit16u ata_cmd_packet();
913
914 Bit16u atapi_get_sense();
915 Bit16u atapi_is_ready();
916 Bit16u atapi_is_cdrom();
917
918 #endif // BX_USE_ATADRV
919
920 #if BX_ELTORITO_BOOT
921
922 void cdemu_init();
923 Bit8u cdemu_isactive();
924 Bit8u cdemu_emulated_drive();
925
926 Bit16u cdrom_boot();
927
928 #endif // BX_ELTORITO_BOOT
929
930 static char bios_cvs_version_string[] = "$Revision: 1.183 $ $Date: 2007/09/10 20:00:29 $";
931
932 #define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
933
934 #if DEBUG_ATA
935 # define BX_DEBUG_ATA(a...) BX_DEBUG(a)
936 #else
937 # define BX_DEBUG_ATA(a...)
938 #endif
939 #if DEBUG_INT13_HD
940 # define BX_DEBUG_INT13_HD(a...) BX_DEBUG(a)
941 #else
942 # define BX_DEBUG_INT13_HD(a...)
943 #endif
944 #if DEBUG_INT13_CD
945 # define BX_DEBUG_INT13_CD(a...) BX_DEBUG(a)
946 #else
947 # define BX_DEBUG_INT13_CD(a...)
948 #endif
949 #if DEBUG_INT13_ET
950 # define BX_DEBUG_INT13_ET(a...) BX_DEBUG(a)
951 #else
952 # define BX_DEBUG_INT13_ET(a...)
953 #endif
954 #if DEBUG_INT13_FL
955 # define BX_DEBUG_INT13_FL(a...) BX_DEBUG(a)
956 #else
957 # define BX_DEBUG_INT13_FL(a...)
958 #endif
959 #if DEBUG_INT15
960 # define BX_DEBUG_INT15(a...) BX_DEBUG(a)
961 #else
962 # define BX_DEBUG_INT15(a...)
963 #endif
964 #if DEBUG_INT16
965 # define BX_DEBUG_INT16(a...) BX_DEBUG(a)
966 #else
967 # define BX_DEBUG_INT16(a...)
968 #endif
969 #if DEBUG_INT1A
970 # define BX_DEBUG_INT1A(a...) BX_DEBUG(a)
971 #else
972 # define BX_DEBUG_INT1A(a...)
973 #endif
974 #if DEBUG_INT74
975 # define BX_DEBUG_INT74(a...) BX_DEBUG(a)
976 #else
977 # define BX_DEBUG_INT74(a...)
978 #endif
979
980 #define SET_AL(val8) AX = ((AX & 0xff00) | (val8))
981 #define SET_BL(val8) BX = ((BX & 0xff00) | (val8))
982 #define SET_CL(val8) CX = ((CX & 0xff00) | (val8))
983 #define SET_DL(val8) DX = ((DX & 0xff00) | (val8))
984 #define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8))
985 #define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8))
986 #define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8))
987 #define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8))
988
989 #define GET_AL() ( AX & 0x00ff )
990 #define GET_BL() ( BX & 0x00ff )
991 #define GET_CL() ( CX & 0x00ff )
992 #define GET_DL() ( DX & 0x00ff )
993 #define GET_AH() ( AX >> 8 )
994 #define GET_BH() ( BX >> 8 )
995 #define GET_CH() ( CX >> 8 )
996 #define GET_DH() ( DX >> 8 )
997
998 #define GET_ELDL() ( ELDX & 0x00ff )
999 #define GET_ELDH() ( ELDX >> 8 )
1000
1001 #define SET_CF() FLAGS |= 0x0001
1002 #define CLEAR_CF() FLAGS &= 0xfffe
1003 #define GET_CF() (FLAGS & 0x0001)
1004
1005 #define SET_ZF() FLAGS |= 0x0040
1006 #define CLEAR_ZF() FLAGS &= 0xffbf
1007 #define GET_ZF() (FLAGS & 0x0040)
1008
1009 #define UNSUPPORTED_FUNCTION 0x86
1010
1011 #define none 0
1012 #define MAX_SCAN_CODE 0x58
1013
1014 static struct {
1015 Bit16u normal;
1016 Bit16u shift;
1017 Bit16u control;
1018 Bit16u alt;
1019 Bit8u lock_flags;
1020 } scan_to_scanascii[MAX_SCAN_CODE + 1] = {
1021 { none, none, none, none, none },
1022 { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */
1023 { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */
1024 { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */
1025 { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */
1026 { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */
1027 { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */
1028 { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */
1029 { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */
1030 { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */
1031 { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */
1032 { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */
1033 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */
1034 { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */
1035 { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */
1036 { 0x0f09, 0x0f00, none, none, none }, /* tab */
1037 { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 }, /* Q */
1038 { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 }, /* W */
1039 { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 }, /* E */
1040 { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 }, /* R */
1041 { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 }, /* T */
1042 { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 }, /* Y */
1043 { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 }, /* U */
1044 { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 }, /* I */
1045 { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 }, /* O */
1046 { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 }, /* P */
1047 { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */
1048 { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */
1049 { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */
1050 { none, none, none, none, none }, /* L Ctrl */
1051 { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 }, /* A */
1052 { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 }, /* S */
1053 { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 }, /* D */
1054 { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 }, /* F */
1055 { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 }, /* G */
1056 { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 }, /* H */
1057 { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 }, /* J */
1058 { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 }, /* K */
1059 { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 }, /* L */
1060 { 0x273b, 0x273a, none, none, none }, /* ;: */
1061 { 0x2827, 0x2822, none, none, none }, /* '" */
1062 { 0x2960, 0x297e, none, none, none }, /* `~ */
1063 { none, none, none, none, none }, /* L shift */
1064 { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */
1065 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 }, /* Z */
1066 { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 }, /* X */
1067 { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 }, /* C */
1068 { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 }, /* V */
1069 { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 }, /* B */
1070 { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 }, /* N */
1071 { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 }, /* M */
1072 { 0x332c, 0x333c, none, none, none }, /* ,< */
1073 { 0x342e, 0x343e, none, none, none }, /* .> */
1074 { 0x352f, 0x353f, none, none, none }, /* /? */
1075 { none, none, none, none, none }, /* R Shift */
1076 { 0x372a, 0x372a, none, none, none }, /* * */
1077 { none, none, none, none, none }, /* L Alt */
1078 { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */
1079 { none, none, none, none, none }, /* caps lock */
1080 { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */
1081 { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */
1082 { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */
1083 { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */
1084 { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */
1085 { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */
1086 { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */
1087 { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */
1088 { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */
1089 { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */
1090 { none, none, none, none, none }, /* Num Lock */
1091 { none, none, none, none, none }, /* Scroll Lock */
1092 { 0x4700, 0x4737, 0x7700, none, 0x20 }, /* 7 Home */
1093 { 0x4800, 0x4838, none, none, 0x20 }, /* 8 UP */
1094 { 0x4900, 0x4939, 0x8400, none, 0x20 }, /* 9 PgUp */
1095 { 0x4a2d, 0x4a2d, none, none, none }, /* - */
1096 { 0x4b00, 0x4b34, 0x7300, none, 0x20 }, /* 4 Left */
1097 { 0x4c00, 0x4c35, none, none, 0x20 }, /* 5 */
1098 { 0x4d00, 0x4d36, 0x7400, none, 0x20 }, /* 6 Right */
1099 { 0x4e2b, 0x4e2b, none, none, none }, /* + */
1100 { 0x4f00, 0x4f31, 0x7500, none, 0x20 }, /* 1 End */
1101 { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */
1102 { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */
1103 { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */
1104 { 0x5300, 0x532e, none, none, 0x20 }, /* Del */
1105 { none, none, none, none, none },
1106 { none, none, none, none, none },
1107 { 0x565c, 0x567c, none, none, none }, /* \| */
1108 { 0x5700, 0x5700, none, none, none }, /* F11 */
1109 { 0x5800, 0x5800, none, none, none } /* F12 */
1110 };
1111
1112 Bit8u
1113 inb(port)
1114 Bit16u port;
1115 {
1116 ASM_START
1117 push bp
1118 mov bp, sp
1119
1120 push dx
1121 mov dx, 4[bp]
1122 in al, dx
1123 pop dx
1124
1125 pop bp
1126 ASM_END
1127 }
1128
1129 #if BX_USE_ATADRV
1130 Bit16u
1131 inw(port)
1132 Bit16u port;
1133 {
1134 ASM_START
1135 push bp
1136 mov bp, sp
1137
1138 push dx
1139 mov dx, 4[bp]
1140 in ax, dx
1141 pop dx
1142
1143 pop bp
1144 ASM_END
1145 }
1146 #endif
1147
1148 void
1149 outb(port, val)
1150 Bit16u port;
1151 Bit8u val;
1152 {
1153 ASM_START
1154 push bp
1155 mov bp, sp
1156
1157 push ax
1158 push dx
1159 mov dx, 4[bp]
1160 mov al, 6[bp]
1161 out dx, al
1162 pop dx
1163 pop ax
1164
1165 pop bp
1166 ASM_END
1167 }
1168
1169 #if BX_USE_ATADRV
1170 void
1171 outw(port, val)
1172 Bit16u port;
1173 Bit16u val;
1174 {
1175 ASM_START
1176 push bp
1177 mov bp, sp
1178
1179 push ax
1180 push dx
1181 mov dx, 4[bp]
1182 mov ax, 6[bp]
1183 out dx, ax
1184 pop dx
1185 pop ax
1186
1187 pop bp
1188 ASM_END
1189 }
1190 #endif
1191
1192 void
1193 outb_cmos(cmos_reg, val)
1194 Bit8u cmos_reg;
1195 Bit8u val;
1196 {
1197 ASM_START
1198 push bp
1199 mov bp, sp
1200
1201 mov al, 4[bp] ;; cmos_reg
1202 out 0x70, al
1203 mov al, 6[bp] ;; val
1204 out 0x71, al
1205
1206 pop bp
1207 ASM_END
1208 }
1209
1210 Bit8u
1211 inb_cmos(cmos_reg)
1212 Bit8u cmos_reg;
1213 {
1214 ASM_START
1215 push bp
1216 mov bp, sp
1217
1218 mov al, 4[bp] ;; cmos_reg
1219 out 0x70, al
1220 in al, 0x71
1221
1222 pop bp
1223 ASM_END
1224 }
1225
1226 void
1227 init_rtc()
1228 {
1229 outb_cmos(0x0a, 0x26);
1230 outb_cmos(0x0b, 0x02);
1231 inb_cmos(0x0c);
1232 inb_cmos(0x0d);
1233 }
1234
1235 bx_bool
1236 rtc_updating()
1237 {
1238 // This function checks to see if the update-in-progress bit
1239 // is set in CMOS Status Register A. If not, it returns 0.
1240 // If it is set, it tries to wait until there is a transition
1241 // to 0, and will return 0 if such a transition occurs. A 1
1242 // is returned only after timing out. The maximum period
1243 // that this bit should be set is constrained to 244useconds.
1244 // The count I use below guarantees coverage or more than
1245 // this time, with any reasonable IPS setting.
1246
1247 Bit16u count;
1248
1249 count = 25000;
1250 while (--count != 0) {
1251 if ( (inb_cmos(0x0a) & 0x80) == 0 )
1252 return(0);
1253 }
1254 return(1); // update-in-progress never transitioned to 0
1255 }
1256
1257
1258 Bit8u
1259 read_byte(seg, offset)
1260 Bit16u seg;
1261 Bit16u offset;
1262 {
1263 ASM_START
1264 push bp
1265 mov bp, sp
1266
1267 push bx
1268 push ds
1269 mov ax, 4[bp] ; segment
1270 mov ds, ax
1271 mov bx, 6[bp] ; offset
1272 mov al, [bx]
1273 ;; al = return value (byte)
1274 pop ds
1275 pop bx
1276
1277 pop bp
1278 ASM_END
1279 }
1280
1281 Bit16u
1282 read_word(seg, offset)
1283 Bit16u seg;
1284 Bit16u offset;
1285 {
1286 ASM_START
1287 push bp
1288 mov bp, sp
1289
1290 push bx
1291 push ds
1292 mov ax, 4[bp] ; segment
1293 mov ds, ax
1294 mov bx, 6[bp] ; offset
1295 mov ax, [bx]
1296 ;; ax = return value (word)
1297 pop ds
1298 pop bx
1299
1300 pop bp
1301 ASM_END
1302 }
1303
1304 void
1305 write_byte(seg, offset, data)
1306 Bit16u seg;
1307 Bit16u offset;
1308 Bit8u data;
1309 {
1310 ASM_START
1311 push bp
1312 mov bp, sp
1313
1314 push ax
1315 push bx
1316 push ds
1317 mov ax, 4[bp] ; segment
1318 mov ds, ax
1319 mov bx, 6[bp] ; offset
1320 mov al, 8[bp] ; data byte
1321 mov [bx], al ; write data byte
1322 pop ds
1323 pop bx
1324 pop ax
1325
1326 pop bp
1327 ASM_END
1328 }
1329
1330 void
1331 write_word(seg, offset, data)
1332 Bit16u seg;
1333 Bit16u offset;
1334 Bit16u data;
1335 {
1336 ASM_START
1337 push bp
1338 mov bp, sp
1339
1340 push ax
1341 push bx
1342 push ds
1343 mov ax, 4[bp] ; segment
1344 mov ds, ax
1345 mov bx, 6[bp] ; offset
1346 mov ax, 8[bp] ; data word
1347 mov [bx], ax ; write data word
1348 pop ds
1349 pop bx
1350 pop ax
1351
1352 pop bp
1353 ASM_END
1354 }
1355
1356 Bit16u
1357 get_CS()
1358 {
1359 ASM_START
1360 mov ax, cs
1361 ASM_END
1362 }
1363
1364 Bit16u
1365 get_SS()
1366 {
1367 ASM_START
1368 mov ax, ss
1369 ASM_END
1370 }
1371
1372 #if BX_DEBUG_SERIAL
1373 /* serial debug port*/
1374 #define BX_DEBUG_PORT 0x03f8
1375
1376 /* data */
1377 #define UART_RBR 0x00
1378 #define UART_THR 0x00
1379
1380 /* control */
1381 #define UART_IER 0x01
1382 #define UART_IIR 0x02
1383 #define UART_FCR 0x02
1384 #define UART_LCR 0x03
1385 #define UART_MCR 0x04
1386 #define UART_DLL 0x00
1387 #define UART_DLM 0x01
1388
1389 /* status */
1390 #define UART_LSR 0x05
1391 #define UART_MSR 0x06
1392 #define UART_SCR 0x07
1393
1394 int uart_can_tx_byte(base_port)
1395 Bit16u base_port;
1396 {
1397 return inb(base_port + UART_LSR) & 0x20;
1398 }
1399
1400 void uart_wait_to_tx_byte(base_port)
1401 Bit16u base_port;
1402 {
1403 while (!uart_can_tx_byte(base_port));
1404 }
1405
1406 void uart_wait_until_sent(base_port)
1407 Bit16u base_port;
1408 {
1409 while (!(inb(base_port + UART_LSR) & 0x40));
1410 }
1411
1412 void uart_tx_byte(base_port, data)
1413 Bit16u base_port;
1414 Bit8u data;
1415 {
1416 uart_wait_to_tx_byte(base_port);
1417 outb(base_port + UART_THR, data);
1418 uart_wait_until_sent(base_port);
1419 }
1420 #endif
1421
1422 void
1423 wrch(c)
1424 Bit8u c;
1425 {
1426 ASM_START
1427 push bp
1428 mov bp, sp
1429
1430 push bx
1431 mov ah, #0x0e
1432 mov al, 4[bp]
1433 xor bx,bx
1434 int #0x10
1435 pop bx
1436
1437 pop bp
1438 ASM_END
1439 }
1440
1441 void
1442 send(action, c)
1443 Bit16u action;
1444 Bit8u c;
1445 {
1446 #if BX_DEBUG_SERIAL
1447 if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
1448 uart_tx_byte(BX_DEBUG_PORT, c);
1449 #endif
1450 #if BX_VIRTUAL_PORTS
1451 if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c);
1452 if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);
1453 #endif
1454 if (action & BIOS_PRINTF_SCREEN) {
1455 if (c == '\n') wrch('\r');
1456 wrch(c);
1457 }
1458 }
1459
1460 void
1461 put_int(action, val, width, neg)
1462 Bit16u action;
1463 short val, width;
1464 bx_bool neg;
1465 {
1466 short nval = val / 10;
1467 if (nval)
1468 put_int(action, nval, width - 1, neg);
1469 else {
1470 while (--width > 0) send(action, ' ');
1471 if (neg) send(action, '-');
1472 }
1473 send(action, val - (nval * 10) + '');
1474 }
1475
1476 void
1477 put_uint(action, val, width, neg)
1478 Bit16u action;
1479 unsigned short val;
1480 short width;
1481 bx_bool neg;
1482 {
1483 unsigned short nval = val / 10;
1484 if (nval)
1485 put_uint(action, nval, width - 1, neg);
1486 else {
1487 while (--width > 0) send(action, ' ');
1488 if (neg) send(action, '-');
1489 }
1490 send(action, val - (nval * 10) + '');
1491 }
1492
1493 void
1494 put_luint(action, val, width, neg)
1495 Bit16u action;
1496 unsigned long val;
1497 short width;
1498 bx_bool neg;
1499 {
1500 unsigned long nval = val / 10;
1501 if (nval)
1502 put_luint(action, nval, width - 1, neg);
1503 else {
1504 while (--width > 0) send(action, ' ');
1505 if (neg) send(action, '-');
1506 }
1507 send(action, val - (nval * 10) + '');
1508 }
1509
1510 void put_str(action, s)
1511 Bit16u action;
1512 Bit8u *s;
1513 {
1514 Bit8u c;
1515 if (!s)
1516 s = "<NULL>";
1517
1518 while (c = read_byte(get_CS(), s)) {
1519 send(action, c);
1520 s++;
1521 }
1522 }
1523
1524 //--------------------------------------------------------------------------
1525 // bios_printf()
1526 // A compact variable argument printf function which prints its output via
1527 // an I/O port so that it can be logged by Bochs/Plex.
1528 // Currently, only %x is supported (or %02x, %04x, etc).
1529 //
1530 // Supports %[format_width][format]
1531 // where format can be d,x,c,s
1532 //--------------------------------------------------------------------------
1533 void
1534 bios_printf(action, s)
1535 Bit16u action;
1536 Bit8u *s;
1537 {
1538 Bit8u c, format_char;
1539 bx_bool in_format;
1540 short i;
1541 Bit16u *arg_ptr;
1542 Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width;
1543
1544 arg_ptr = &s;
1545 arg_seg = get_SS();
1546
1547 in_format = 0;
1548 format_width = 0;
1549
1550 if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) {
1551 #if BX_VIRTUAL_PORTS
1552 outb(PANIC_PORT2, 0x00);
1553 #endif
1554 bios_printf (BIOS_PRINTF_SCREEN, "FATAL: ");
1555 }
1556
1557 while (c = read_byte(get_CS(), s)) {
1558 if ( c == '%' ) {
1559 in_format = 1;
1560 format_width = 0;
1561 }
1562 else if (in_format) {
1563 if ( (c>='') && (c<='9') ) {
1564 format_width = (format_width * 10) + (c - '');
1565 }
1566 else {
1567 arg_ptr++; // increment to next arg
1568 arg = read_word(arg_seg, arg_ptr);
1569 if (c == 'x') {
1570 if (format_width == 0)
1571 format_width = 4;
1572 for (i=format_width-1; i>=0; i--) {
1573 nibble = (arg >> (4 * i)) & 0x000f;
1574 send (action, (nibble<=9)? (nibble+'') : (nibble-10+'A'));
1575 }
1576 }
1577 else if (c == 'u') {
1578 put_uint(action, arg, format_width, 0);
1579 }
1580 else if (c == 'l') {
1581 s++;
1582 arg_ptr++; /* increment to next arg */
1583 hibyte = read_word(arg_seg, arg_ptr);
1584 put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
1585 }
1586 else if (c == 'd') {
1587 if (arg & 0x8000)
1588 put_int(action, -arg, format_width - 1, 1);
1589 else
1590 put_int(action, arg, format_width, 0);
1591 }
1592 else if (c == 's') {
1593 put_str(action, arg);
1594 }
1595 else if (c == 'c') {
1596 send(action, arg);
1597 }
1598 else
1599 BX_PANIC("bios_printf: unknown format\n");
1600 in_format = 0;
1601 }
1602 }
1603 else {
1604 send(action, c);
1605 }
1606 s ++;
1607 }
1608
1609 if (action & BIOS_PRINTF_HALT) {
1610 // freeze in a busy loop.
1611 ASM_START
1612 cli
1613 halt2_loop:
1614 hlt
1615 jmp halt2_loop
1616 ASM_END
1617 }
1618 }
1619
1620 //--------------------------------------------------------------------------
1621 // keyboard_init
1622 //--------------------------------------------------------------------------
1623 // this file is based on LinuxBIOS implementation of keyboard.c
1624 // could convert to #asm to gain space
1625 void
1626 keyboard_init()
1627 {
1628 Bit16u max;
1629
1630 /* ------------------- Flush buffers ------------------------*/
1631 /* Wait until buffer is empty */
1632 max=0xffff;
1633 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
1634
1635 /* flush incoming keys */
1636 max=0x2000;
1637 while (--max > 0) {
1638 outb(0x80, 0x00);
1639 if (inb(0x64) & 0x01) {
1640 inb(0x60);
1641 max = 0x2000;
1642 }
1643 }
1644
1645 // Due to timer issues, and if the IPS setting is > 15000000,
1646 // the incoming keys might not be flushed here. That will
1647 // cause a panic a few lines below. See sourceforge bug report :
1648 // [ 642031 ] FATAL: Keyboard RESET error:993
1649
1650 /* ------------------- controller side ----------------------*/
1651 /* send cmd = 0xAA, self test 8042 */
1652 outb(0x64, 0xaa);
1653
1654 /* Wait until buffer is empty */
1655 max=0xffff;
1656 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00);
1657 if (max==0x0) keyboard_panic(00);
1658
1659 /* Wait for data */
1660 max=0xffff;
1661 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01);
1662 if (max==0x0) keyboard_panic(01);
1663
1664 /* read self-test result, 0x55 should be returned from 0x60 */
1665 if ((inb(0x60) != 0x55)){
1666 keyboard_panic(991);
1667 }
1668
1669 /* send cmd = 0xAB, keyboard interface test */
1670 outb(0x64,0xab);
1671
1672 /* Wait until buffer is empty */
1673 max=0xffff;
1674 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10);
1675 if (max==0x0) keyboard_panic(10);
1676
1677 /* Wait for data */
1678 max=0xffff;
1679 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11);
1680 if (max==0x0) keyboard_panic(11);
1681
1682 /* read keyboard interface test result, */
1683 /* 0x00 should be returned form 0x60 */
1684 if ((inb(0x60) != 0x00)) {
1685 keyboard_panic(992);
1686 }
1687
1688 /* Enable Keyboard clock */
1689 outb(0x64,0xae);
1690 outb(0x64,0xa8);
1691
1692 /* ------------------- keyboard side ------------------------*/
1693 /* reset kerboard and self test (keyboard side) */
1694 outb(0x60, 0xff);
1695
1696 /* Wait until buffer is empty */
1697 max=0xffff;
1698 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20);
1699 if (max==0x0) keyboard_panic(20);
1700
1701 /* Wait for data */
1702 max=0xffff;
1703 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21);
1704 if (max==0x0) keyboard_panic(21);
1705
1706 /* keyboard should return ACK */
1707 if ((inb(0x60) != 0xfa)) {
1708 keyboard_panic(993);
1709 }
1710
1711 /* Wait for data */
1712 max=0xffff;
1713 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x31);
1714 if (max==0x0) keyboard_panic(31);
1715
1716 if ((inb(0x60) != 0xaa)) {
1717 keyboard_panic(994);
1718 }
1719
1720 /* Disable keyboard */
1721 outb(0x60, 0xf5);
1722
1723 /* Wait until buffer is empty */
1724 max=0xffff;
1725 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40);
1726 if (max==0x0) keyboard_panic(40);
1727
1728 /* Wait for data */
1729 max=0xffff;
1730 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41);
1731 if (max==0x0) keyboard_panic(41);
1732
1733 /* keyboard should return ACK */
1734 if ((inb(0x60) != 0xfa)) {
1735 keyboard_panic(995);
1736 }
1737
1738 /* Write Keyboard Mode */
1739 outb(0x64, 0x60);
1740
1741 /* Wait until buffer is empty */
1742 max=0xffff;
1743 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50);
1744 if (max==0x0) keyboard_panic(50);
1745
1746 /* send cmd: scan code convert, disable mouse, enable IRQ 1 */
1747 outb(0x60, 0x61);
1748
1749 /* Wait until buffer is empty */
1750 max=0xffff;
1751 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60);
1752 if (max==0x0) keyboard_panic(60);
1753
1754 /* Enable keyboard */
1755 outb(0x60, 0xf4);
1756
1757 /* Wait until buffer is empty */
1758 max=0xffff;
1759 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70);
1760 if (max==0x0) keyboard_panic(70);
1761
1762 /* Wait for data */
1763 max=0xffff;
1764 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71);
1765 if (max==0x0) keyboard_panic(70);
1766
1767 /* keyboard should return ACK */
1768 if ((inb(0x60) != 0xfa)) {
1769 keyboard_panic(996);
1770 }
1771
1772 outb(0x80, 0x77);
1773 }
1774
1775 //--------------------------------------------------------------------------
1776 // keyboard_panic
1777 //--------------------------------------------------------------------------
1778 void
1779 keyboard_panic(status)
1780 Bit16u status;
1781 {
1782 // If you're getting a 993 keyboard panic here,
1783 // please see the comment in keyboard_init
1784
1785 BX_PANIC("Keyboard error:%u\n",status);
1786 }
1787
1788 //--------------------------------------------------------------------------
1789 // shutdown_status_panic
1790 // called when the shutdown statsu is not implemented, displays the status
1791 //--------------------------------------------------------------------------
1792 void
1793 shutdown_status_panic(status)
1794 Bit16u status;
1795 {
1796 BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
1797 }
1798
1799 //--------------------------------------------------------------------------
1800 // print_bios_banner
1801 // displays a the bios version
1802 //--------------------------------------------------------------------------
1803 void
1804 print_bios_banner()
1805 {
1806 printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
1807 BIOS_BUILD_DATE, bios_cvs_version_string);
1808 printf(
1809 #if BX_APM
1810 "apmbios "
1811 #endif
1812 #if BX_PCIBIOS
1813 "pcibios "
1814 #endif
1815 #if BX_ELTORITO_BOOT
1816 "eltorito "
1817 #endif
1818 #if BX_ROMBIOS32
1819 "rombios32 "
1820 #endif
1821 "\n\n");
1822 }
1823
1824 //--------------------------------------------------------------------------
1825 // BIOS Boot Specification 1.0.1 compatibility
1826 //
1827 // Very basic support for the BIOS Boot Specification, which allows expansion
1828 // ROMs to register themselves as boot devices, instead of just stealing the
1829 // INT 19h boot vector.
1830 //
1831 // This is a hack: to do it properly requires a proper PnP BIOS and we aren't
1832 // one; we just lie to the option ROMs to make them behave correctly.
1833 // We also don't support letting option ROMs register as bootable disk
1834 // drives (BCVs), only as bootable devices (BEVs).
1835 //
1836 // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
1837 //--------------------------------------------------------------------------
1838
1839 /* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
1840 #define IPL_SEG 0x9ff0
1841 #define IPL_TABLE_OFFSET 0x0000
1842 #define IPL_TABLE_ENTRIES 8
1843 #define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */
1844 #define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */
1845
1846 struct ipl_entry {
1847 Bit16u type;
1848 Bit16u flags;
1849 Bit32u vector;
1850 Bit32u description;
1851 Bit32u reserved;
1852 };
1853
1854 static void
1855 init_boot_vectors()
1856 {
1857 struct ipl_entry e;
1858 Bit16u count = 0;
1859 Bit16u ss = get_SS();
1860
1861 /* Clear out the IPL table. */
1862 memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, 0xff);
1863
1864 /* Floppy drive */
1865 e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
1866 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
1867 count++;
1868
1869 /* First HDD */
1870 e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
1871 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
1872 count++;
1873
1874 #if BX_ELTORITO_BOOT
1875 /* CDROM */
1876 e.type = 3; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
1877 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
1878 count++;
1879 #endif
1880
1881 /* Remember how many devices we have */
1882 write_word(IPL_SEG, IPL_COUNT_OFFSET, count);
1883 /* Not tried booting anything yet */
1884 write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
1885 }
1886
1887 static Bit8u
1888 get_boot_vector(i, e)
1889 Bit16u i; struct ipl_entry *e;
1890 {
1891 Bit16u count;
1892 Bit16u ss = get_SS();
1893 /* Get the count of boot devices, and refuse to overrun the array */
1894 count = read_word(IPL_SEG, IPL_COUNT_OFFSET);
1895 if (i >= count) return 0;
1896 /* OK to read this device */
1897 memcpyb(ss, e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e));
1898 return 1;
1899 }
1900
1901
1902 //--------------------------------------------------------------------------
1903 // print_boot_device
1904 // displays the boot device
1905 //--------------------------------------------------------------------------
1906
1907 static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
1908
1909 void
1910 print_boot_device(type)
1911 Bit16u type;
1912 {
1913 /* NIC appears as type 0x80 */
1914 if (type == 0x80 ) type = 0x4;
1915 if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
1916 printf("Booting from %s...\n", drivetypes[type]);
1917 }
1918
1919 //--------------------------------------------------------------------------
1920 // print_boot_failure
1921 // displays the reason why boot failed
1922 //--------------------------------------------------------------------------
1923 void
1924 print_boot_failure(type, reason)
1925 Bit16u type; Bit8u reason;
1926 {
1927 if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
1928
1929 printf("Boot from %s failed", drivetypes[type]);
1930 if (type < 4) {
1931 /* Report the reason too */
1932 if (reason==0)
1933 printf(": not a bootable disk");
1934 else
1935 printf(": could not read the boot disk");
1936 }
1937 printf("\n");
1938 }
1939
1940 //--------------------------------------------------------------------------
1941 // print_cdromboot_failure
1942 // displays the reason why boot failed
1943 //--------------------------------------------------------------------------
1944 void
1945 print_cdromboot_failure( code )
1946 Bit16u code;
1947 {
1948 bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code);
1949
1950 return;
1951 }
1952
1953 void
1954 nmi_handler_msg()
1955 {
1956 BX_PANIC("NMI Handler called\n");
1957 }
1958
1959 void
1960 int18_panic_msg()
1961 {
1962 BX_PANIC("INT18: BOOT FAILURE\n");
1963 }
1964
1965 void
1966 log_bios_start()
1967 {
1968 #if BX_DEBUG_SERIAL
1969 outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */
1970 #endif
1971 BX_INFO("%s\n", bios_cvs_version_string);
1972 }
1973
1974 bx_bool
1975 set_enable_a20(val)
1976 bx_bool val;
1977 {
1978 Bit8u oldval;
1979
1980 // Use PS2 System Control port A to set A20 enable
1981
1982 // get current setting first
1983 oldval = inb(0x92);
1984
1985 // change A20 status
1986 if (val)
1987 outb(0x92, oldval | 0x02);
1988 else
1989 outb(0x92, oldval & 0xfd);
1990
1991 return((oldval & 0x02) != 0);
1992 }
1993
1994 void
1995 debugger_on()
1996 {
1997 outb(0xfedc, 0x01);
1998 }
1999
2000 void
2001 debugger_off()
2002 {
2003 outb(0xfedc, 0x00);
2004 }
2005
2006 #if BX_USE_ATADRV
2007
2008 // ---------------------------------------------------------------------------
2009 // Start of ATA/ATAPI Driver
2010 // ---------------------------------------------------------------------------
2011
2012 // Global defines -- ATA register and register bits.
2013 // command block & control block regs
2014 #define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0
2015 #define ATA_CB_ERR 1 // error in pio_base_addr1+1
2016 #define ATA_CB_FR 1 // feature reg out pio_base_addr1+1
2017 #define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2
2018 #define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3
2019 #define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4
2020 #define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5
2021 #define ATA_CB_DH 6 // device head in/out pio_base_addr1+6
2022 #define ATA_CB_STAT 7 // primary status in pio_base_addr1+7
2023 #define ATA_CB_CMD 7 // command out pio_base_addr1+7
2024 #define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6
2025 #define ATA_CB_DC 6 // device control out pio_base_addr2+6
2026 #define ATA_CB_DA 7 // device address in pio_base_addr2+7
2027
2028 #define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
2029 #define ATA_CB_ER_BBK 0x80 // ATA bad block
2030 #define ATA_CB_ER_UNC 0x40 // ATA uncorrected error
2031 #define ATA_CB_ER_MC 0x20 // ATA media change
2032 #define ATA_CB_ER_IDNF 0x10 // ATA id not found
2033 #define ATA_CB_ER_MCR 0x08 // ATA media change request
2034 #define ATA_CB_ER_ABRT 0x04 // ATA command aborted
2035 #define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found
2036 #define ATA_CB_ER_NDAM 0x01 // ATA address mark not found
2037
2038 #define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask)
2039 #define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request
2040 #define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort
2041 #define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media
2042 #define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication
2043
2044 // ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
2045 #define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask)
2046 #define ATA_CB_SC_P_REL 0x04 // ATAPI release
2047 #define ATA_CB_SC_P_IO 0x02 // ATAPI I/O
2048 #define ATA_CB_SC_P_CD 0x01 // ATAPI C/D
2049
2050 // bits 7-4 of the device/head (CB_DH) reg
2051 #define ATA_CB_DH_DEV0 0xa0 // select device 0
2052 #define ATA_CB_DH_DEV1 0xb0 // select device 1
2053
2054 // status reg (CB_STAT and CB_ASTAT) bits
2055 #define ATA_CB_STAT_BSY 0x80 // busy
2056 #define ATA_CB_STAT_RDY 0x40 // ready
2057 #define ATA_CB_STAT_DF 0x20 // device fault
2058 #define ATA_CB_STAT_WFT 0x20 // write fault (old name)
2059 #define ATA_CB_STAT_SKC 0x10 // seek complete
2060 #define ATA_CB_STAT_SERV 0x10 // service
2061 #define ATA_CB_STAT_DRQ 0x08 // data request
2062 #define ATA_CB_STAT_CORR 0x04 // corrected
2063 #define ATA_CB_STAT_IDX 0x02 // index
2064 #define ATA_CB_STAT_ERR 0x01 // error (ATA)
2065 #define ATA_CB_STAT_CHK 0x01 // check (ATAPI)
2066
2067 // device control reg (CB_DC) bits
2068 #define ATA_CB_DC_HD15 0x08 // bit should always be set to one
2069 #define ATA_CB_DC_SRST 0x04 // soft reset
2070 #define ATA_CB_DC_NIEN 0x02 // disable interrupts
2071
2072 // Most mandtory and optional ATA commands (from ATA-3),
2073 #define ATA_CMD_CFA_ERASE_SECTORS 0xC0
2074 #define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
2075 #define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87
2076 #define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
2077 #define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
2078 #define ATA_CMD_CHECK_POWER_MODE1 0xE5
2079 #define ATA_CMD_CHECK_POWER_MODE2 0x98
2080 #define ATA_CMD_DEVICE_RESET 0x08
2081 #define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
2082 #define ATA_CMD_FLUSH_CACHE 0xE7
2083 #define ATA_CMD_FORMAT_TRACK 0x50
2084 #define ATA_CMD_IDENTIFY_DEVICE 0xEC
2085 #define ATA_CMD_IDENTIFY_DEVICE_PACKET 0xA1
2086 #define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1
2087 #define ATA_CMD_IDLE1 0xE3
2088 #define ATA_CMD_IDLE2 0x97
2089 #define ATA_CMD_IDLE_IMMEDIATE1 0xE1
2090 #define ATA_CMD_IDLE_IMMEDIATE2 0x95
2091 #define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
2092 #define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
2093 #define ATA_CMD_NOP 0x00
2094 #define ATA_CMD_PACKET 0xA0
2095 #define ATA_CMD_READ_BUFFER 0xE4
2096 #define ATA_CMD_READ_DMA 0xC8
2097 #define ATA_CMD_READ_DMA_QUEUED 0xC7
2098 #define ATA_CMD_READ_MULTIPLE 0xC4
2099 #define ATA_CMD_READ_SECTORS 0x20
2100 #define ATA_CMD_READ_VERIFY_SECTORS 0x40
2101 #define ATA_CMD_RECALIBRATE 0x10
2102 #define ATA_CMD_SEEK 0x70
2103 #define ATA_CMD_SET_FEATURES 0xEF
2104 #define ATA_CMD_SET_MULTIPLE_MODE 0xC6
2105 #define ATA_CMD_SLEEP1 0xE6
2106 #define ATA_CMD_SLEEP2 0x99
2107 #define ATA_CMD_STANDBY1 0xE2
2108 #define ATA_CMD_STANDBY2 0x96
2109 #define ATA_CMD_STANDBY_IMMEDIATE1 0xE0
2110 #define ATA_CMD_STANDBY_IMMEDIATE2 0x94
2111 #define ATA_CMD_WRITE_BUFFER 0xE8
2112 #define ATA_CMD_WRITE_DMA 0xCA
2113 #define ATA_CMD_WRITE_DMA_QUEUED 0xCC
2114 #define ATA_CMD_WRITE_MULTIPLE 0xC5
2115 #define ATA_CMD_WRITE_SECTORS 0x30
2116 #define ATA_CMD_WRITE_VERIFY 0x3C
2117
2118 #define ATA_IFACE_NONE 0x00
2119 #define ATA_IFACE_ISA 0x00
2120 #define ATA_IFACE_PCI 0x01
2121
2122 #define ATA_TYPE_NONE 0x00
2123 #define ATA_TYPE_UNKNOWN 0x01
2124 #define ATA_TYPE_ATA 0x02
2125 #define ATA_TYPE_ATAPI 0x03
2126
2127 #define ATA_DEVICE_NONE 0x00
2128 #define ATA_DEVICE_HD 0xFF
2129 #define ATA_DEVICE_CDROM 0x05
2130
2131 #define ATA_MODE_NONE 0x00
2132 #define ATA_MODE_PIO16 0x00
2133 #define ATA_MODE_PIO32 0x01
2134 #define ATA_MODE_ISADMA 0x02
2135 #define ATA_MODE_PCIDMA 0x03
2136 #define ATA_MODE_USEIRQ 0x10
2137
2138 #define ATA_TRANSLATION_NONE 0
2139 #define ATA_TRANSLATION_LBA 1
2140 #define ATA_TRANSLATION_LARGE 2
2141 #define ATA_TRANSLATION_RECHS 3
2142
2143 #define ATA_DATA_NO 0x00
2144 #define ATA_DATA_IN 0x01
2145 #define ATA_DATA_OUT 0x02
2146
2147 // ---------------------------------------------------------------------------
2148 // ATA/ATAPI driver : initialization
2149 // ---------------------------------------------------------------------------
2150 void ata_init( )
2151 {
2152 Bit16u ebda_seg=read_word(0x0040,0x000E);
2153 Bit8u channel, device;
2154
2155 // Channels info init.
2156 for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
2157 write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE);
2158 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0);
2159 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2,0x0);
2160 write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
2161 }
2162
2163 // Devices info init.
2164 for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
2165 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
2166 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE);
2167 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable,0);
2168 write_byte(ebda_seg,&EbdaData->ata.devices[device].lock,0);
2169 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_NONE);
2170 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,0);
2171 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation,ATA_TRANSLATION_NONE);
2172 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads,0);
2173 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders,0);
2174 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt,0);
2175 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0);
2176 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
2177 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
2178
2179 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L);
2180 }
2181
2182 // hdidmap and cdidmap init.
2183 for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
2184 write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
2185 write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
2186 }
2187
2188 write_byte(ebda_seg,&EbdaData->ata.hdcount,0);
2189 write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
2190 }
2191
2192 // ---------------------------------------------------------------------------
2193 // ATA/ATAPI driver : device detection
2194 // ---------------------------------------------------------------------------
2195
2196 void ata_detect( )
2197 {
2198 Bit16u ebda_seg=read_word(0x0040,0x000E);
2199 Bit8u hdcount, cdcount, device, type;
2200 Bit8u buffer[0x0200];
2201
2202 #if BX_MAX_ATA_INTERFACES > 0
2203 write_byte(ebda_seg,&EbdaData->ata.channels[0].iface,ATA_IFACE_ISA);
2204 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase1,0x1f0);
2205 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase2,0x3f0);
2206 write_byte(ebda_seg,&EbdaData->ata.channels[0].irq,14);
2207 #endif
2208 #if BX_MAX_ATA_INTERFACES > 1
2209 write_byte(ebda_seg,&EbdaData->ata.channels[1].iface,ATA_IFACE_ISA);
2210 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase1,0x170);
2211 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase2,0x370);
2212 write_byte(ebda_seg,&EbdaData->ata.channels[1].irq,15);
2213 #endif
2214 #if BX_MAX_ATA_INTERFACES > 2
2215 write_byte(ebda_seg,&EbdaData->ata.channels[2].iface,ATA_IFACE_ISA);
2216 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase1,0x1e8);
2217 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase2,0x3e0);
2218 write_byte(ebda_seg,&EbdaData->ata.channels[2].irq,12);
2219 #endif
2220 #if BX_MAX_ATA_INTERFACES > 3
2221 write_byte(ebda_seg,&EbdaData->ata.channels[3].iface,ATA_IFACE_ISA);
2222 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase1,0x168);
2223 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase2,0x360);
2224 write_byte(ebda_seg,&EbdaData->ata.channels[3].irq,11);
2225 #endif
2226 #if BX_MAX_ATA_INTERFACES > 4
2227 #error Please fill the ATA interface informations
2228 #endif
2229
2230 // Device detection
2231 hdcount=cdcount=0;
2232
2233 for(device=0; device<BX_MAX_ATA_DEVICES; device++) {
2234 Bit16u iobase1, iobase2;
2235 Bit8u channel, slave, shift;
2236 Bit8u sc, sn, cl, ch, st;
2237
2238 channel = device / 2;
2239 slave = device % 2;
2240
2241 iobase1 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1);
2242 iobase2 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2);
2243
2244 // Disable interrupts
2245 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
2246
2247 // Look for device
2248 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
2249 outb(iobase1+ATA_CB_SC, 0x55);
2250 outb(iobase1+ATA_CB_SN, 0xaa);
2251 outb(iobase1+ATA_CB_SC, 0xaa);
2252 outb(iobase1+ATA_CB_SN, 0x55);
2253 outb(iobase1+ATA_CB_SC, 0x55);
2254 outb(iobase1+ATA_CB_SN, 0xaa);
2255
2256 // If we found something
2257 sc = inb(iobase1+ATA_CB_SC);
2258 sn = inb(iobase1+ATA_CB_SN);
2259
2260 if ( (sc == 0x55) && (sn == 0xaa) ) {
2261 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN);
2262
2263 // reset the channel
2264 ata_reset(device);
2265
2266 // check for ATA or ATAPI
2267 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
2268 sc = inb(iobase1+ATA_CB_SC);
2269 sn = inb(iobase1+ATA_CB_SN);
2270 if ((sc==0x01) && (sn==0x01)) {
2271 cl = inb(iobase1+ATA_CB_CL);
2272 ch = inb(iobase1+ATA_CB_CH);
2273 st = inb(iobase1+ATA_CB_STAT);
2274
2275 if ((cl==0x14) && (ch==0xeb)) {
2276 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI);
2277 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
2278 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA);
2279 } else if ((cl==0xff) && (ch==0xff)) {
2280 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
2281 }
2282 }
2283 }
2284
2285 type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
2286
2287 // Now we send a IDENTIFY command to ATA device
2288 if(type == ATA_TYPE_ATA) {
2289 Bit32u sectors;
2290 Bit16u cylinders, heads, spt, blksize;
2291 Bit8u translation, removable, mode;
2292
2293 //Temporary values to do the transfer
2294 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
2295 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
2296
2297 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, get_SS(),buffer) !=0 )
2298 BX_PANIC("ata-detect: Failed to detect ATA device\n");
2299
2300 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
2301 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
2302 blksize = read_word(get_SS(),buffer+10);
2303
2304 cylinders = read_word(get_SS(),buffer+(1*2)); // word 1
2305 heads = read_word(get_SS(),buffer+(3*2)); // word 3
2306 spt = read_word(get_SS(),buffer+(6*2)); // word 6
2307
2308 sectors = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
2309
2310 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
2311 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
2312 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
2313 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
2314 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);
2315 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders);
2316 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
2317 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors);
2318 BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
2319
2320 translation = inb_cmos(0x39 + channel/2);
2321 for (shift=device%4; shift>0; shift--) translation >>= 2;
2322 translation &= 0x03;
2323
2324 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation, translation);
2325
2326 switch (translation) {
2327 case ATA_TRANSLATION_NONE:
2328 BX_INFO("none");
2329 break;
2330 case ATA_TRANSLATION_LBA:
2331 BX_INFO("lba");
2332 break;
2333 case ATA_TRANSLATION_LARGE:
2334 BX_INFO("large");
2335 break;
2336 case ATA_TRANSLATION_RECHS:
2337 BX_INFO("r-echs");
2338 break;
2339 }
2340 switch (translation) {
2341 case ATA_TRANSLATION_NONE:
2342 break;
2343 case ATA_TRANSLATION_LBA:
2344 spt = 63;
2345 sectors /= 63;
2346 heads = sectors / 1024;
2347 if (heads>128) heads = 255;
2348 else if (heads>64) heads = 128;
2349 else if (heads>32) heads = 64;
2350 else if (heads>16) heads = 32;
2351 else heads=16;
2352 cylinders = sectors / heads;
2353 break;
2354 case ATA_TRANSLATION_RECHS:
2355 // Take care not to overflow
2356 if (heads==16) {
2357 if(cylinders>61439) cylinders=61439;
2358 heads=15;
2359 cylinders = (Bit16u)((Bit32u)(cylinders)*16/15);
2360 }
2361 // then go through the large bitshift process
2362 case ATA_TRANSLATION_LARGE:
2363 while(cylinders > 1024) {
2364 cylinders >>= 1;
2365 heads <<= 1;
2366
2367 // If we max out the head count
2368 if (heads > 127) break;
2369 }
2370 break;
2371 }
2372 // clip to 1024 cylinders in lchs
2373 if (cylinders > 1024) cylinders=1024;
2374 BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
2375
2376 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);
2377 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders);
2378 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt);
2379
2380 // fill hdidmap
2381 write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device);
2382 hdcount++;
2383 }
2384
2385 // Now we send a IDENTIFY command to ATAPI device
2386 if(type == ATA_TYPE_ATAPI) {
2387
2388 Bit8u type, removable, mode;
2389 Bit16u blksize;
2390
2391 //Temporary values to do the transfer
2392 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM);
2393 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
2394
2395 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, get_SS(),buffer) != 0)
2396 BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
2397
2398 type = read_byte(get_SS(),buffer+1) & 0x1f;
2399 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
2400 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
2401 blksize = 2048;
2402
2403 write_byte(ebda_seg,&EbdaData->ata.devices[device].device, type);
2404 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
2405 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
2406 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
2407
2408 // fill cdidmap
2409 write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device);
2410 cdcount++;
2411 }
2412
2413 {
2414 Bit32u sizeinmb;
2415 Bit16u ataversion;
2416 Bit8u c, i, version, model[41];
2417
2418 switch (type) {
2419 case ATA_TYPE_ATA:
2420 sizeinmb = read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors);
2421 sizeinmb >>= 11;
2422 case ATA_TYPE_ATAPI:
2423 // Read ATA/ATAPI version
2424 ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
2425 for(version=15;version>0;version--) {
2426 if((ataversion&(1<<version))!=0)
2427 break;
2428 }
2429
2430 // Read model name
2431 for(i=0;i<20;i++){
2432 write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
2433 write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
2434 }
2435
2436 // Reformat
2437 write_byte(get_SS(),model+40,0x00);
2438 for(i=39;i>0;i--){
2439 if(read_byte(get_SS(),model+i)==0x20)
2440 write_byte(get_SS(),model+i,0x00);
2441 else break;
2442 }
2443 break;
2444 }
2445
2446 switch (type) {
2447 case ATA_TYPE_ATA:
2448 printf("ata%d %s: ",channel,slave?" slave":"master");
2449 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
2450 printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
2451 break;
2452 case ATA_TYPE_ATAPI:
2453 printf("ata%d %s: ",channel,slave?" slave":"master");
2454 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
2455 if(read_byte(ebda_seg,&EbdaData->ata.devices[device].device)==ATA_DEVICE_CDROM)
2456 printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version);
2457 else
2458 printf(" ATAPI-%d Device\n",version);
2459 break;
2460 case ATA_TYPE_UNKNOWN:
2461 printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
2462 break;
2463 }
2464 }
2465 }
2466
2467 // Store the devices counts
2468 write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
2469 write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount);
2470 write_byte(0x40,0x75, hdcount);
2471
2472 printf("\n");
2473
2474 // FIXME : should use bios=cmos|auto|disable bits
2475 // FIXME : should know about translation bits
2476 // FIXME : move hard_drive_post here
2477
2478 }
2479
2480 // ---------------------------------------------------------------------------
2481 // ATA/ATAPI driver : software reset
2482 // ---------------------------------------------------------------------------
2483 // ATA-3
2484 // 8.2.1 Software reset - Device 0
2485
2486 void ata_reset(device)
2487 Bit16u device;
2488 {
2489 Bit16u ebda_seg=read_word(0x0040,0x000E);
2490 Bit16u iobase1, iobase2;
2491 Bit8u channel, slave, sn, sc;
2492 Bit16u max;
2493
2494 channel = device / 2;
2495 slave = device % 2;
2496
2497 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
2498 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
2499
2500 // Reset
2501
2502 // 8.2.1 (a) -- set SRST in DC
2503 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
2504
2505 // 8.2.1 (b) -- wait for BSY
2506 max=0xff;
2507 while(--max>0) {
2508 Bit8u status = inb(iobase1+ATA_CB_STAT);
2509 if ((status & ATA_CB_STAT_BSY) != 0) break;
2510 }
2511
2512 // 8.2.1 (f) -- clear SRST
2513 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
2514
2515 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_NONE) {
2516
2517 // 8.2.1 (g) -- check for sc==sn==0x01
2518 // select device
2519 outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0);
2520 sc = inb(iobase1+ATA_CB_SC);
2521 sn = inb(iobase1+ATA_CB_SN);
2522
2523 if ( (sc==0x01) && (sn==0x01) ) {
2524
2525 // 8.2.1 (h) -- wait for not BSY
2526 max=0xff;
2527 while(--max>0) {
2528 Bit8u status = inb(iobase1+ATA_CB_STAT);
2529 if ((status & ATA_CB_STAT_BSY) == 0) break;
2530 }
2531 }
2532 }
2533
2534 // 8.2.1 (i) -- wait for DRDY
2535 max=0xfff;
2536 while(--max>0) {
2537 Bit8u status = inb(iobase1+ATA_CB_STAT);
2538 if ((status & ATA_CB_STAT_RDY) != 0) break;
2539 }
2540
2541 // Enable interrupts
2542 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
2543 }
2544
2545 // ---------------------------------------------------------------------------
2546 // ATA/ATAPI driver : execute a non data command
2547 // ---------------------------------------------------------------------------
2548
2549 Bit16u ata_cmd_non_data()
2550 {return 0;}
2551
2552 // ---------------------------------------------------------------------------
2553 // ATA/ATAPI driver : execute a data-in command
2554 // ---------------------------------------------------------------------------
2555 // returns
2556 // 0 : no error
2557 // 1 : BUSY bit set
2558 // 2 : read error
2559 // 3 : expected DRQ=1
2560 // 4 : no sectors left to read/verify
2561 // 5 : more sectors to read/verify
2562 // 6 : no sectors left to write
2563 // 7 : more sectors to write
2564 Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, segment, offset)
2565 Bit16u device, command, count, cylinder, head, sector, segment, offset;
2566 Bit32u lba;
2567 {
2568 Bit16u ebda_seg=read_word(0x0040,0x000E);
2569 Bit16u iobase1, iobase2, blksize;
2570 Bit8u channel, slave;
2571 Bit8u status, current, mode;
2572
2573 channel = device / 2;
2574 slave = device % 2;
2575
2576 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
2577 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
2578 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
2579 blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
2580 if (mode == ATA_MODE_PIO32) blksize>>=2;
2581 else blksize>>=1;
2582
2583 // sector will be 0 only on lba access. Convert to lba-chs
2584 if (sector == 0) {
2585 sector = (Bit16u) (lba & 0x000000ffL);
2586 lba >>= 8;
2587 cylinder = (Bit16u) (lba & 0x0000ffffL);
2588 lba >>= 16;
2589 head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
2590 }
2591
2592 // Reset count of transferred data
2593 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
2594 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
2595 current = 0;
2596
2597 status = inb(iobase1 + ATA_CB_STAT);
2598 if (status & ATA_CB_STAT_BSY) return 1;
2599
2600 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
2601 outb(iobase1 + ATA_CB_FR, 0x00);
2602 outb(iobase1 + ATA_CB_SC, count);
2603 outb(iobase1 + ATA_CB_SN, sector);
2604 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
2605 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
2606 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
2607 outb(iobase1 + ATA_CB_CMD, command);
2608
2609 while (1) {
2610 status = inb(iobase1 + ATA_CB_STAT);
2611 if ( !(status & ATA_CB_STAT_BSY) ) break;
2612 }
2613
2614 if (status & ATA_CB_STAT_ERR) {
2615 BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
2616 return 2;
2617 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
2618 BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n", (unsigned) status);
2619 return 3;
2620 }
2621
2622 // FIXME : move seg/off translation here
2623
2624 ASM_START
2625 sti ;; enable higher priority interrupts
2626 ASM_END
2627
2628 while (1) {
2629
2630 ASM_START
2631 push bp
2632 mov bp, sp
2633 mov di, _ata_cmd_data_in.offset + 2[bp]
2634 mov ax, _ata_cmd_data_in.segment + 2[bp]
2635 mov cx, _ata_cmd_data_in.blksize + 2[bp]
2636
2637 ;; adjust if there will be an overrun. 2K max sector size
2638 cmp di, #0xf800 ;;
2639 jbe ata_in_no_adjust
2640
2641 ata_in_adjust:
2642 sub di, #0x0800 ;; sub 2 kbytes from offset
2643 add ax, #0x0080 ;; add 2 Kbytes to segment
2644
2645 ata_in_no_adjust:
2646 mov es, ax ;; segment in es
2647
2648 mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port
2649
2650 mov ah, _ata_cmd_data_in.mode + 2[bp]
2651 cmp ah, #ATA_MODE_PIO32
2652 je ata_in_32
2653
2654 ata_in_16:
2655 rep
2656 insw ;; CX words transfered from port(DX) to ES:[DI]
2657 jmp ata_in_done
2658
2659 ata_in_32:
2660 rep
2661 insd ;; CX dwords transfered from port(DX) to ES:[DI]
2662
2663 ata_in_done:
2664 mov _ata_cmd_data_in.offset + 2[bp], di
2665 mov _ata_cmd_data_in.segment + 2[bp], es
2666 pop bp
2667 ASM_END
2668
2669 current++;
2670 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
2671 count--;
2672 status = inb(iobase1 + ATA_CB_STAT);
2673 if (count == 0) {
2674 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
2675 != ATA_CB_STAT_RDY ) {
2676 BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status);
2677 return 4;
2678 }
2679 break;
2680 }
2681 else {
2682 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
2683 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
2684 BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status);
2685 return 5;
2686 }
2687 continue;
2688 }
2689 }
2690 // Enable interrupts
2691 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
2692 return 0;
2693 }
2694
2695 // ---------------------------------------------------------------------------
2696 // ATA/ATAPI driver : execute a data-out command
2697 // ---------------------------------------------------------------------------
2698 // returns
2699 // 0 : no error
2700 // 1 : BUSY bit set
2701 // 2 : read error
2702 // 3 : expected DRQ=1
2703 // 4 : no sectors left to read/verify
2704 // 5 : more sectors to read/verify
2705 // 6 : no sectors left to write
2706 // 7 : more sectors to write
2707 Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, segment, offset)
2708 Bit16u device, command, count, cylinder, head, sector, segment, offset;
2709 Bit32u lba;
2710 {
2711 Bit16u ebda_seg=read_word(0x0040,0x000E);
2712 Bit16u iobase1, iobase2, blksize;
2713 Bit8u channel, slave;
2714 Bit8u status, current, mode;
2715
2716 channel = device / 2;
2717 slave = device % 2;
2718
2719 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
2720 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
2721 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
2722 blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
2723 if (mode == ATA_MODE_PIO32) blksize>>=2;
2724 else blksize>>=1;
2725
2726 // sector will be 0 only on lba access. Convert to lba-chs
2727 if (sector == 0) {
2728 sector = (Bit16u) (lba & 0x000000ffL);
2729 lba >>= 8;
2730 cylinder = (Bit16u) (lba & 0x0000ffffL);
2731 lba >>= 16;
2732 head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
2733 }
2734
2735 // Reset count of transferred data
2736 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
2737 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
2738 current = 0;
2739
2740 status = inb(iobase1 + ATA_CB_STAT);
2741 if (status & ATA_CB_STAT_BSY) return 1;
2742
2743 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
2744 outb(iobase1 + ATA_CB_FR, 0x00);
2745 outb(iobase1 + ATA_CB_SC, count);
2746 outb(iobase1 + ATA_CB_SN, sector);
2747 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
2748 outb(iobase1 + ATA_CB_CH, cylinder >> 8);
2749 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
2750 outb(iobase1 + ATA_CB_CMD, command);
2751
2752 while (1) {
2753 status = inb(iobase1 + ATA_CB_STAT);
2754 if ( !(status & ATA_CB_STAT_BSY) ) break;
2755 }
2756
2757 if (status & ATA_CB_STAT_ERR) {
2758 BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
2759 return 2;
2760 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
2761 BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n", (unsigned) status);
2762 return 3;
2763 }
2764
2765 // FIXME : move seg/off translation here
2766
2767 ASM_START
2768 sti ;; enable higher priority interrupts
2769 ASM_END
2770
2771 while (1) {
2772
2773 ASM_START
2774 push bp
2775 mov bp, sp
2776 mov si, _ata_cmd_data_out.offset + 2[bp]
2777 mov ax, _ata_cmd_data_out.segment + 2[bp]
2778 mov cx, _ata_cmd_data_out.blksize + 2[bp]
2779
2780 ;; adjust if there will be an overrun. 2K max sector size
2781 cmp si, #0xf800 ;;
2782 jbe ata_out_no_adjust
2783
2784 ata_out_adjust:
2785 sub si, #0x0800 ;; sub 2 kbytes from offset
2786 add ax, #0x0080 ;; add 2 Kbytes to segment
2787
2788 ata_out_no_adjust:
2789 mov es, ax ;; segment in es
2790
2791 mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port
2792
2793 mov ah, _ata_cmd_data_out.mode + 2[bp]
2794 cmp ah, #ATA_MODE_PIO32
2795 je ata_out_32
2796
2797 ata_out_16:
2798 seg ES
2799 rep
2800 outsw ;; CX words transfered from port(DX) to ES:[SI]
2801 jmp ata_out_done
2802
2803 ata_out_32:
2804 seg ES
2805 rep
2806 outsd ;; CX dwords transfered from port(DX) to ES:[SI]
2807
2808 ata_out_done:
2809 mov _ata_cmd_data_out.offset + 2[bp], si
2810 mov _ata_cmd_data_out.segment + 2[bp], es
2811 pop bp
2812 ASM_END
2813
2814 current++;
2815 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
2816 count--;
2817 status = inb(iobase1 + ATA_CB_STAT);
2818 if (count == 0) {
2819 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
2820 != ATA_CB_STAT_RDY ) {
2821 BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status);
2822 return 6;
2823 }
2824 break;
2825 }
2826 else {
2827 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
2828 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
2829 BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status);
2830 return 7;
2831 }
2832 continue;
2833 }
2834 }
2835 // Enable interrupts
2836 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
2837 return 0;
2838 }
2839
2840 // ---------------------------------------------------------------------------
2841 // ATA/ATAPI driver : execute a packet command
2842 // ---------------------------------------------------------------------------
2843 // returns
2844 // 0 : no error
2845 // 1 : error in parameters
2846 // 2 : BUSY bit set
2847 // 3 : error
2848 // 4 : not ready
2849 Bit16u ata_cmd_packet(device, cmdlen, cmdseg, cmdoff, header, length, inout, bufseg, bufoff)
2850 Bit8u cmdlen,inout;
2851 Bit16u device,cmdseg, cmdoff, bufseg, bufoff;
2852 Bit16u header;
2853 Bit32u length;
2854 {
2855 Bit16u ebda_seg=read_word(0x0040,0x000E);
2856 Bit16u iobase1, iobase2;
2857 Bit16u lcount, lbefore, lafter, count;
2858 Bit8u channel, slave;
2859 Bit8u status, mode, lmode;
2860 Bit32u total, transfer;
2861
2862 channel = device / 2;
2863 slave = device % 2;
2864
2865 // Data out is not supported yet
2866 if (inout == ATA_DATA_OUT) {
2867 BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n");
2868 return 1;
2869 }
2870
2871 // The header length must be even
2872 if (header & 1) {
2873 BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header);
2874 return 1;
2875 }
2876
2877 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
2878 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
2879 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
2880 transfer= 0L;
2881
2882 if (cmdlen < 12) cmdlen=12;
2883 if (cmdlen > 12) cmdlen=16;
2884 cmdlen>>=1;
2885
2886 // Reset count of transferred data
2887 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0);
2888 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L);
2889
2890 status = inb(iobase1 + ATA_CB_STAT);
2891 if (status & ATA_CB_STAT_BSY) return 2;
2892
2893 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
2894 // outb(iobase1 + ATA_CB_FR, 0x00);
2895 // outb(iobase1 + ATA_CB_SC, 0x00);
2896 // outb(iobase1 + ATA_CB_SN, 0x00);
2897 outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
2898 outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
2899 outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
2900 outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
2901
2902 // Device should ok to receive command
2903 while (1) {
2904 status = inb(iobase1 + ATA_CB_STAT);
2905 if ( !(status & ATA_CB_STAT_BSY) ) break;
2906 }
2907
2908 if (status & ATA_CB_STAT_ERR) {
2909 BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
2910 return 3;
2911 } else if ( !(status & ATA_CB_STAT_DRQ) ) {
2912 BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status);
2913 return 4;
2914 }
2915
2916 // Normalize address
2917 cmdseg += (cmdoff / 16);
2918 cmdoff %= 16;
2919
2920 // Send command to device
2921 ASM_START
2922 sti ;; enable higher priority interrupts
2923
2924 push bp
2925 mov bp, sp
2926
2927 mov si, _ata_cmd_packet.cmdoff + 2[bp]
2928 mov ax, _ata_cmd_packet.cmdseg + 2[bp]
2929 mov cx, _ata_cmd_packet.cmdlen + 2[bp]
2930 mov es, ax ;; segment in es
2931
2932 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port
2933
2934 seg ES
2935 rep
2936 outsw ;; CX words transfered from port(DX) to ES:[SI]
2937
2938 pop bp
2939 ASM_END
2940
2941 if (inout == ATA_DATA_NO) {
2942 status = inb(iobase1 + ATA_CB_STAT);
2943 }
2944 else {
2945 while (1) {
2946
2947 status = inb(iobase1 + ATA_CB_STAT);
2948
2949 // Check if command completed
2950 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break;
2951
2952 if (status & ATA_CB_STAT_ERR) {
2953 BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
2954 return 3;
2955 }
2956
2957 // Device must be ready to send data
2958 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
2959 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
2960 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", status);
2961 return 4;
2962 }
2963
2964 // Normalize address
2965 bufseg += (bufoff / 16);
2966 bufoff %= 16;
2967
2968 // Get the byte count
2969 lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
2970
2971 // adjust to read what we want
2972 if(header>lcount) {
2973 lbefore=lcount;
2974 header-=lcount;
2975 lcount=0;
2976 }
2977 else {
2978 lbefore=header;
2979 header=0;
2980 lcount-=lbefore;
2981 }
2982
2983 if(lcount>length) {
2984 lafter=lcount-length;
2985 lcount=length;
2986 length=0;
2987 }
2988 else {
2989 lafter=0;
2990 length-=lcount;
2991 }
2992
2993 // Save byte count
2994 count = lcount;
2995
2996 BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter);
2997 BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff);
2998
2999 // If counts not dividable by 4, use 16bits mode
3000 lmode = mode;
3001 if (lbefore & 0x03) lmode=ATA_MODE_PIO16;
3002 if (lcount & 0x03) lmode=ATA_MODE_PIO16;
3003 if (lafter & 0x03) lmode=ATA_MODE_PIO16;
3004
3005 // adds an extra byte if count are odd. before is always even
3006 if (lcount & 0x01) {
3007 lcount+=1;
3008 if ((lafter > 0) && (lafter & 0x01)) {
3009 lafter-=1;
3010 }
3011 }
3012
3013 if (lmode == ATA_MODE_PIO32) {
3014 lcount>>=2; lbefore>>=2; lafter>>=2;
3015 }
3016 else {
3017 lcount>>=1; lbefore>>=1; lafter>>=1;
3018 }
3019
3020 ; // FIXME bcc bug
3021
3022 ASM_START
3023 push bp
3024 mov bp, sp
3025
3026 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port
3027
3028 mov cx, _ata_cmd_packet.lbefore + 2[bp]
3029 jcxz ata_packet_no_before
3030
3031 mov ah, _ata_cmd_packet.lmode + 2[bp]
3032 cmp ah, #ATA_MODE_PIO32
3033 je ata_packet_in_before_32
3034
3035 ata_packet_in_before_16:
3036 in ax, dx
3037 loop ata_packet_in_before_16
3038 jmp ata_packet_no_before
3039
3040 ata_packet_in_before_32:
3041 push eax
3042 ata_packet_in_before_32_loop:
3043 in eax, dx
3044 loop ata_packet_in_before_32_loop
3045 pop eax
3046
3047 ata_packet_no_before:
3048 mov cx, _ata_cmd_packet.lcount + 2[bp]
3049 jcxz ata_packet_after
3050
3051 mov di, _ata_cmd_packet.bufoff + 2[bp]
3052 mov ax, _ata_cmd_packet.bufseg + 2[bp]
3053 mov es, ax
3054
3055 mov ah, _ata_cmd_packet.lmode + 2[bp]
3056 cmp ah, #ATA_MODE_PIO32
3057 je ata_packet_in_32
3058
3059 ata_packet_in_16:
3060 rep
3061 insw ;; CX words transfered tp port(DX) to ES:[DI]
3062 jmp ata_packet_after
3063
3064 ata_packet_in_32:
3065 rep
3066 insd ;; CX dwords transfered to port(DX) to ES:[DI]
3067
3068 ata_packet_after:
3069 mov cx, _ata_cmd_packet.lafter + 2[bp]
3070 jcxz ata_packet_done
3071
3072 mov ah, _ata_cmd_packet.lmode + 2[bp]
3073 cmp ah, #ATA_MODE_PIO32
3074 je ata_packet_in_after_32
3075
3076 ata_packet_in_after_16:
3077 in ax, dx
3078 loop ata_packet_in_after_16
3079 jmp ata_packet_done
3080
3081 ata_packet_in_after_32:
3082 push eax
3083 ata_packet_in_after_32_loop:
3084 in eax, dx
3085 loop ata_packet_in_after_32_loop
3086 pop eax
3087
3088 ata_packet_done:
3089 pop bp
3090 ASM_END
3091
3092 // Compute new buffer address
3093 bufoff += count;
3094
3095 // Save transferred bytes count
3096 transfer += count;
3097 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,transfer);
3098 }
3099 }
3100
3101 // Final check, device must be ready
3102 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
3103 != ATA_CB_STAT_RDY ) {
3104 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status);
3105 return 4;
3106 }
3107
3108 // Enable interrupts
3109 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
3110 return 0;
3111 }
3112
3113 // ---------------------------------------------------------------------------
3114 // End of ATA/ATAPI Driver
3115 // ---------------------------------------------------------------------------
3116
3117 // ---------------------------------------------------------------------------
3118 // Start of ATA/ATAPI generic functions
3119 // ---------------------------------------------------------------------------
3120
3121 Bit16u
3122 atapi_get_sense(device)
3123 Bit16u device;
3124 {
3125 Bit8u atacmd[12];
3126 Bit8u buffer[16];
3127 Bit8u i;
3128
3129 memsetb(get_SS(),atacmd,0,12);
3130
3131 // Request SENSE
3132 atacmd[0]=0x03;
3133 atacmd[4]=0x20;
3134 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, get_SS(), buffer) != 0)
3135 return 0x0002;
3136
3137 if ((buffer[0] & 0x7e) == 0x70) {
3138 return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12];
3139 }
3140
3141 return 0;
3142 }
3143
3144 Bit16u
3145 atapi_is_ready(device)
3146 Bit16u device;
3147 {
3148 Bit8u atacmd[12];
3149 Bit8u buffer[];
3150
3151 memsetb(get_SS(),atacmd,0,12);
3152
3153 // Test Unit Ready
3154 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
3155 return 0x000f;
3156
3157 if (atapi_get_sense(device) !=0 ) {
3158 memsetb(get_SS(),atacmd,0,12);
3159
3160 // try to send Test Unit Ready again
3161 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
3162 return 0x000f;
3163
3164 return atapi_get_sense(device);
3165 }
3166 return 0;
3167 }
3168
3169 Bit16u
3170 atapi_is_cdrom(device)
3171 Bit8u device;
3172 {
3173 Bit16u ebda_seg=read_word(0x0040,0x000E);
3174
3175 if (device >= BX_MAX_ATA_DEVICES)
3176 return 0;
3177
3178 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI)
3179 return 0;
3180
3181 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].device) != ATA_DEVICE_CDROM)
3182 return 0;
3183
3184 return 1;
3185 }
3186
3187 // ---------------------------------------------------------------------------
3188 // End of ATA/ATAPI generic functions
3189 // ---------------------------------------------------------------------------
3190
3191 #endif // BX_USE_ATADRV
3192
3193 #if BX_ELTORITO_BOOT
3194
3195 // ---------------------------------------------------------------------------
3196 // Start of El-Torito boot functions
3197 // ---------------------------------------------------------------------------
3198
3199 void
3200 cdemu_init()
3201 {
3202 Bit16u ebda_seg=read_word(0x0040,0x000E);
3203
3204 // the only important data is this one for now
3205 write_byte(ebda_seg,&EbdaData->cdemu.active,0x00);
3206 }
3207
3208 Bit8u
3209 cdemu_isactive()
3210 {
3211 Bit16u ebda_seg=read_word(0x0040,0x000E);
3212
3213 return(read_byte(ebda_seg,&EbdaData->cdemu.active));
3214 }
3215
3216 Bit8u
3217 cdemu_emulated_drive()
3218 {
3219 Bit16u ebda_seg=read_word(0x0040,0x000E);
3220
3221 return(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive));
3222 }
3223
3224 static char isotag[6]="CD001";
3225 static char eltorito[24]="EL TORITO SPECIFICATION";
3226 //
3227 // Returns ah: emulated drive, al: error code
3228 //
3229 Bit16u
3230 cdrom_boot()
3231 {
3232 Bit16u ebda_seg=read_word(0x0040,0x000E);
3233 Bit8u atacmd[12], buffer[2048];
3234 Bit32u lba;
3235 Bit16u boot_segment, nbsectors, i, error;
3236 Bit8u device;
3237
3238 // Find out the first cdrom
3239 for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
3240 if (atapi_is_cdrom(device)) break;
3241 }
3242
3243 // if not found
3244 if(device >= BX_MAX_ATA_DEVICES) return 2;
3245
3246 // Read the Boot Record Volume Descriptor
3247 memsetb(get_SS(),atacmd,0,12);
3248 atacmd[0]=0x28; // READ command
3249 atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors
3250 atacmd[8]=(0x01 & 0x00ff); // Sectors
3251 atacmd[2]=(0x11 & 0xff000000) >> 24; // LBA
3252 atacmd[3]=(0x11 & 0x00ff0000) >> 16;
3253 atacmd[4]=(0x11 & 0x0000ff00) >> 8;
3254 atacmd[5]=(0x11 & 0x000000ff);
3255 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
3256 return 3;
3257
3258 // Validity checks
3259 if(buffer[0]!=0)return 4;
3260 for(i=0;i<5;i++){
3261 if(buffer[1+i]!=read_byte(0xf000,&isotag[i]))return 5;
3262 }
3263 for(i=0;i<23;i++)
3264 if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6;
3265
3266 // ok, now we calculate the Boot catalog address
3267 lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47];
3268
3269 // And we read the Boot Catalog
3270 memsetb(get_SS(),atacmd,0,12);
3271 atacmd[0]=0x28; // READ command
3272 atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors
3273 atacmd[8]=(0x01 & 0x00ff); // Sectors
3274 atacmd[2]=(lba & 0xff000000) >> 24; // LBA
3275 atacmd[3]=(lba & 0x00ff0000) >> 16;
3276 atacmd[4]=(lba & 0x0000ff00) >> 8;
3277 atacmd[5]=(lba & 0x000000ff);
3278 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
3279 return 7;
3280
3281 // Validation entry
3282 if(buffer[0x00]!=0x01)return 8; // Header
3283 if(buffer[0x01]!=0x00)return 9; // Platform
3284 if(buffer[0x1E]!=0x55)return 10; // key 1
3285 if(buffer[0x1F]!=0xAA)return 10; // key 2
3286
3287 // Initial/Default Entry
3288 if(buffer[0x20]!=0x88)return 11; // Bootable
3289
3290 write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]);
3291 if(buffer[0x21]==0){
3292 // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
3293 // Win2000 cd boot needs to know it booted from cd
3294 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0);
3295 }
3296 else if(buffer[0x21]<4)
3297 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00);
3298 else
3299 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x80);
3300
3301 write_byte(ebda_seg,&EbdaData->cdemu.controller_index,device/2);
3302 write_byte(ebda_seg,&EbdaData->cdemu.device_spec,device%2);
3303
3304 boot_segment=buffer[0x23]*0x100+buffer[0x22];
3305 if(boot_segment==0x0000)boot_segment=0x07C0;
3306
3307 write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment);
3308 write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000);
3309
3310 nbsectors=buffer[0x27]*0x100+buffer[0x26];
3311 write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors);
3312
3313 lba=buffer[0x2B]*0x1000000+buffer[0x2A]*0x10000+buffer[0x29]*0x100+buffer[0x28];
3314 write_dword(ebda_seg,&EbdaData->cdemu.ilba,lba);
3315
3316 // And we read the image in memory
3317 memsetb(get_SS(),atacmd,0,12);
3318 atacmd[0]=0x28; // READ command
3319 atacmd[7]=((1+(nbsectors-1)/4) & 0xff00) >> 8; // Sectors
3320 atacmd[8]=((1+(nbsectors-1)/4) & 0x00ff); // Sectors
3321 atacmd[2]=(lba & 0xff000000) >> 24; // LBA
3322 atacmd[3]=(lba & 0x00ff0000) >> 16;
3323 atacmd[4]=(lba & 0x0000ff00) >> 8;
3324 atacmd[5]=(lba & 0x000000ff);
3325 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0)
3326 return 12;
3327
3328 // Remember the media type
3329 switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
3330 case 0x01: // 1.2M floppy
3331 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,15);
3332 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
3333 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
3334 break;
3335 case 0x02: // 1.44M floppy
3336 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,18);
3337 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
3338 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
3339 break;
3340 case 0x03: // 2.88M floppy
3341 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,36);
3342 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80);
3343 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2);
3344 break;
3345 case 0x04: // Harddrive
3346 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f);
3347 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,
3348 (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1);
3349 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1);
3350 break;
3351 }
3352
3353 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) {
3354 // Increase bios installed hardware number of devices
3355 if(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)==0x00)
3356 write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41);
3357 else
3358 write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1);
3359 }
3360
3361
3362 // everything is ok, so from now on, the emulation is active
3363 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0)
3364 write_byte(ebda_seg,&EbdaData->cdemu.active,0x01);
3365
3366 // return the boot drive + no error
3367 return (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)*0x100)+0;
3368 }
3369
3370 // ---------------------------------------------------------------------------
3371 // End of El-Torito boot functions
3372 // ---------------------------------------------------------------------------
3373 #endif // BX_ELTORITO_BOOT
3374
3375 void
3376 int14_function(regs, ds, iret_addr)
3377 pusha_regs_t regs; // regs pushed from PUSHA instruction
3378 Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper
3379 iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call
3380 {
3381 Bit16u addr,timer,val16;
3382 Bit8u timeout;
3383
3384 ASM_START
3385 sti
3386 ASM_END
3387
3388 addr = read_word(0x0040, (regs.u.r16.dx << 1));
3389 timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx);
3390 if ((regs.u.r16.dx < 4) && (addr > 0)) {
3391 switch (regs.u.r8.ah) {
3392 case 0:
3393 outb(addr+3, inb(addr+3) | 0x80);
3394 if (regs.u.r8.al & 0xE0 == 0) {
3395 outb(addr, 0x17);
3396 outb(addr+1, 0x04);
3397 } else {
3398 val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5);
3399 outb(addr, val16 & 0xFF);
3400 outb(addr+1, val16 >> 8);
3401 }
3402 outb(addr+3, regs.u.r8.al & 0x1F);
3403 regs.u.r8.ah = inb(addr+5);
3404 regs.u.r8.al = inb(addr+6);
3405 ClearCF(iret_addr.flags);
3406 break;
3407 case 1:
3408 timer = read_word(0x0040, 0x006C);
3409 while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) {
3410 val16 = read_word(0x0040, 0x006C);
3411 if (val16 != timer) {
3412 timer = val16;
3413 timeout--;
3414 }
3415 }
3416 if (timeout) outb(addr, regs.u.r8.al);
3417 regs.u.r8.ah = inb(addr+5);
3418 if (!timeout) regs.u.r8.ah |= 0x80;
3419 ClearCF(iret_addr.flags);
3420 break;
3421 case 2:
3422 timer = read_word(0x0040, 0x006C);
3423 while (((inb(addr+5) & 0x01) == 0) && (timeout)) {
3424 val16 = read_word(0x0040, 0x006C);
3425 if (val16 != timer) {
3426 timer = val16;
3427 timeout--;
3428 }
3429 }
3430 if (timeout) {
3431 regs.u.r8.ah = 0;
3432 regs.u.r8.al = inb(addr);
3433 } else {
3434 regs.u.r8.ah = inb(addr+5);
3435 }
3436 ClearCF(iret_addr.flags);
3437 break;
3438 case 3:
3439 regs.u.r8.ah = inb(addr+5);
3440 regs.u.r8.al = inb(addr+6);
3441 ClearCF(iret_addr.flags);
3442 break;
3443 default:
3444 SetCF(iret_addr.flags); // Unsupported
3445 }
3446 } else {
3447 SetCF(iret_addr.flags); // Unsupported
3448 }
3449 }
3450
3451 void
3452 int15_function(regs, ES, DS, FLAGS)
3453 pusha_regs_t regs; // REGS pushed via pusha
3454 Bit16u ES, DS, FLAGS;
3455 {
3456 Bit16u ebda_seg=read_word(0x0040,0x000E);
3457 bx_bool prev_a20_enable;
3458 Bit16u base15_00;
3459 Bit8u base23_16;
3460 Bit16u ss;
3461 Bit16u CX,DX;
3462
3463 Bit16u bRegister;
3464 Bit8u irqDisable;
3465
3466 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
3467
3468 switch (regs.u.r8.ah) {
3469 case 0x24: /* A20 Control */
3470 switch (regs.u.r8.al) {
3471 case 0x00:
3472 set_enable_a20(0);
3473 CLEAR_CF();
3474 regs.u.r8.ah = 0;
3475 break;
3476 case 0x01:
3477 set_enable_a20(1);
3478 CLEAR_CF();
3479 regs.u.r8.ah = 0;
3480 break;
3481 case 0x02:
3482 regs.u.r8.al = (inb(0x92) >> 1) & 0x01;
3483 CLEAR_CF();
3484 regs.u.r8.ah = 0;
3485 break;
3486 case 0x03:
3487 CLEAR_CF();
3488 regs.u.r8.ah = 0;
3489 regs.u.r16.bx = 3;
3490 break;
3491 default:
3492 BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) regs.u.r8.al);
3493 SET_CF();
3494 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3495 }
3496 break;
3497
3498 case 0x41:
3499 SET_CF();
3500 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3501 break;
3502
3503 case 0x4f:
3504 /* keyboard intercept */
3505 #if BX_CPU < 2
3506 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3507 #else
3508 // nop
3509 #endif
3510 SET_CF();
3511 break;
3512
3513 case 0x52: // removable media eject
3514 CLEAR_CF();
3515 regs.u.r8.ah = 0; // "ok ejection may proceed"
3516 break;
3517
3518 case 0x83: {
3519 if( regs.u.r8.al == 0 ) {
3520 // Set Interval requested.
3521 if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) {
3522 // Interval not already set.
3523 write_byte( 0x40, 0xA0, 1 ); // Set status byte.
3524 write_word( 0x40, 0x98, ES ); // Byte location, segment
3525 write_word( 0x40, 0x9A, regs.u.r16.bx ); // Byte location, offset
3526 write_word( 0x40, 0x9C, regs.u.r16.dx ); // Low word, delay
3527 write_word( 0x40, 0x9E, regs.u.r16.cx ); // High word, delay.
3528 CLEAR_CF( );
3529 irqDisable = inb( 0xA1 );
3530 outb( 0xA1, irqDisable & 0xFE );
3531 bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through.
3532 outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer
3533 } else {
3534 // Interval already set.
3535 BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" );
3536 SET_CF();
3537 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3538 }
3539 } else if( regs.u.r8.al == 1 ) {
3540 // Clear Interval requested
3541 write_byte( 0x40, 0xA0, 0 ); // Clear status byte
3542 CLEAR_CF( );
3543 bRegister = inb_cmos( 0xB );
3544 outb_cmos( 0xB, bRegister & ~0x40 ); // Turn off the Periodic Interrupt timer
3545 } else {
3546 BX_DEBUG_INT15("int15: Func 83h, failed.\n" );
3547 SET_CF();
3548 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3549 regs.u.r8.al--;
3550 }
3551
3552 break;
3553 }
3554
3555 case 0x87:
3556 #if BX_CPU < 3
3557 # error "Int15 function 87h not supported on < 80386"
3558 #endif
3559 // +++ should probably have descriptor checks
3560 // +++ should have exception handlers
3561
3562 // turn off interrupts
3563 ASM_START
3564 cli
3565 ASM_END
3566
3567 prev_a20_enable = set_enable_a20(1); // enable A20 line
3568
3569 // 128K max of transfer on 386+ ???
3570 // source == destination ???
3571
3572 // ES:SI points to descriptor table
3573 // offset use initially comments
3574 // ==============================================
3575 // 00..07 Unused zeros Null descriptor
3576 // 08..0f GDT zeros filled in by BIOS
3577 // 10..17 source ssssssss source of data
3578 // 18..1f dest dddddddd destination of data
3579 // 20..27 CS zeros filled in by BIOS
3580 // 28..2f SS zeros filled in by BIOS
3581
3582 //es:si
3583 //eeee0
3584 //0ssss
3585 //-----
3586
3587 // check for access rights of source & dest here
3588
3589 // Initialize GDT descriptor
3590 base15_00 = (ES << 4) + regs.u.r16.si;
3591 base23_16 = ES >> 12;
3592 if (base15_00 < (ES<<4))
3593 base23_16++;
3594 write_word(ES, regs.u.r16.si+0x08+0, 47); // limit 15:00 = 6 * 8bytes/descriptor
3595 write_word(ES, regs.u.r16.si+0x08+2, base15_00);// base 15:00
3596 write_byte(ES, regs.u.r16.si+0x08+4, base23_16);// base 23:16
3597 write_byte(ES, regs.u.r16.si+0x08+5, 0x93); // access
3598 write_word(ES, regs.u.r16.si+0x08+6, 0x0000); // base 31:24/reserved/limit 19:16
3599
3600 // Initialize CS descriptor
3601 write_word(ES, regs.u.r16.si+0x20+0, 0xffff);// limit 15:00 = normal 64K limit
3602 write_word(ES, regs.u.r16.si+0x20+2, 0x0000);// base 15:00
3603 write_byte(ES, regs.u.r16.si+0x20+4, 0x000f);// base 23:16
3604 write_byte(ES, regs.u.r16.si+0x20+5, 0x9b); // access
3605 write_word(ES, regs.u.r16.si+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16
3606
3607 // Initialize SS descriptor
3608 ss = get_SS();
3609 base15_00 = ss << 4;
3610 base23_16 = ss >> 12;
3611 write_word(ES, regs.u.r16.si+0x28+0, 0xffff); // limit 15:00 = normal 64K limit
3612 write_word(ES, regs.u.r16.si+0x28+2, base15_00);// base 15:00
3613 write_byte(ES, regs.u.r16.si+0x28+4, base23_16);// base 23:16
3614 write_byte(ES, regs.u.r16.si+0x28+5, 0x93); // access
3615 write_word(ES, regs.u.r16.si+0x28+6, 0x0000); // base 31:24/reserved/limit 19:16
3616
3617 CX = regs.u.r16.cx;
3618 ASM_START
3619 // Compile generates locals offset info relative to SP.
3620 // Get CX (word count) from stack.
3621 mov bx, sp
3622 SEG SS
3623 mov cx, _int15_function.CX [bx]
3624
3625 // since we need to set SS:SP, save them to the BDA
3626 // for future restore
3627 push eax
3628 xor eax, eax
3629 mov ds, ax
3630 mov 0x0469, ss
3631 mov 0x0467, sp
3632
3633 SEG ES
3634 lgdt [si + 0x08]
3635 SEG CS
3636 lidt [pmode_IDT_info]
3637 ;; perhaps do something with IDT here
3638
3639 ;; set PE bit in CR0
3640 mov eax, cr0
3641 or al, #0x01
3642 mov cr0, eax
3643 ;; far jump to flush CPU queue after transition to protected mode
3644 JMP_AP(0x0020, protected_mode)
3645
3646 protected_mode:
3647 ;; GDT points to valid descriptor table, now load SS, DS, ES
3648 mov ax, #0x28 ;; 101 000 = 5th descriptor in table, TI=GDT, RPL=00
3649 mov ss, ax
3650 mov ax, #0x10 ;; 010 000 = 2nd descriptor in table, TI=GDT, RPL=00
3651 mov ds, ax
3652 mov ax, #0x18 ;; 011 000 = 3rd descriptor in table, TI=GDT, RPL=00
3653 mov es, ax
3654 xor si, si
3655 xor di, di
3656 cld
3657 rep
3658 movsw ;; move CX words from DS:SI to ES:DI
3659
3660 ;; make sure DS and ES limits are 64KB
3661 mov ax, #0x28
3662 mov ds, ax
3663 mov es, ax
3664
3665 ;; reset PG bit in CR0 ???
3666 mov eax, cr0
3667 and al, #0xFE
3668 mov cr0, eax
3669
3670 ;; far jump to flush CPU queue after transition to real mode
3671 JMP_AP(0xf000, real_mode)
3672
3673 real_mode:
3674 ;; restore IDT to normal real-mode defaults
3675 SEG CS
3676 lidt [rmode_IDT_info]
3677
3678 // restore SS:SP from the BDA
3679 xor ax, ax
3680 mov ds, ax
3681 mov ss, 0x0469
3682 mov sp, 0x0467
3683 pop eax
3684 ASM_END
3685
3686 set_enable_a20(prev_a20_enable);
3687
3688 // turn back on interrupts
3689 ASM_START
3690 sti
3691 ASM_END
3692
3693 regs.u.r8.ah = 0;
3694 CLEAR_CF();
3695 break;
3696
3697
3698 case 0x88:
3699 // Get the amount of extended memory (above 1M)
3700 #if BX_CPU < 2
3701 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3702 SET_CF();
3703 #else
3704 regs.u.r8.al = inb_cmos(0x30);
3705 regs.u.r8.ah = inb_cmos(0x31);
3706
3707 // According to Ralf Brown's interrupt the limit should be 15M,
3708 // but real machines mostly return max. 63M.
3709 if(regs.u.r16.ax > 0xffc0)
3710 regs.u.r16.ax = 0xffc0;
3711
3712 CLEAR_CF();
3713 #endif
3714 break;
3715
3716 case 0x90:
3717 /* Device busy interrupt. Called by Int 16h when no key available */
3718 break;
3719
3720 case 0x91:
3721 /* Interrupt complete. Called by Int 16h when key becomes available */
3722 break;
3723
3724 case 0xbf:
3725 BX_INFO("*** int 15h function AH=bf not yet supported!\n");
3726 SET_CF();
3727 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3728 break;
3729
3730 case 0xC0:
3731 #if 0
3732 SET_CF();
3733 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3734 break;
3735 #endif
3736 CLEAR_CF();
3737 regs.u.r8.ah = 0;
3738 regs.u.r16.bx = BIOS_CONFIG_TABLE;
3739 ES = 0xF000;
3740 break;
3741
3742 case 0xc1:
3743 ES = ebda_seg;
3744 CLEAR_CF();
3745 break;
3746
3747 case 0xd8:
3748 bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n");
3749 SET_CF();
3750 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3751 break;
3752
3753 default:
3754 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
3755 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
3756 SET_CF();
3757 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3758 break;
3759 }
3760 }
3761
3762 #if BX_USE_PS2_MOUSE
3763 void
3764 int15_function_mouse(regs, ES, DS, FLAGS)
3765 pusha_regs_t regs; // REGS pushed via pusha
3766 Bit16u ES, DS, FLAGS;
3767 {
3768 Bit16u ebda_seg=read_word(0x0040,0x000E);
3769 Bit8u mouse_flags_1, mouse_flags_2;
3770 Bit16u mouse_driver_seg;
3771 Bit16u mouse_driver_offset;
3772 Bit8u comm_byte, prev_command_byte;
3773 Bit8u ret, mouse_data1, mouse_data2, mouse_data3;
3774
3775 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
3776
3777 switch (regs.u.r8.ah) {
3778 case 0xC2:
3779 // Return Codes status in AH
3780 // =========================
3781 // 00: success
3782 // 01: invalid subfunction (AL > 7)
3783 // 02: invalid input value (out of allowable range)
3784 // 03: interface error
3785 // 04: resend command received from mouse controller,
3786 // device driver should attempt command again
3787 // 05: cannot enable mouse, since no far call has been installed
3788 // 80/86: mouse service not implemented
3789
3790 switch (regs.u.r8.al) {
3791 case 0: // Disable/Enable Mouse
3792 BX_DEBUG_INT15("case 0:\n");
3793 switch (regs.u.r8.bh) {
3794 case 0: // Disable Mouse
3795 BX_DEBUG_INT15("case 0: disable mouse\n");
3796 inhibit_mouse_int_and_events(); // disable IRQ12 and packets
3797 ret = send_to_mouse_ctrl(0xF5); // disable mouse command
3798 if (ret == 0) {
3799 ret = get_mouse_data(&mouse_data1);
3800 if ( (ret == 0) || (mouse_data1 == 0xFA) ) {
3801 CLEAR_CF();
3802 regs.u.r8.ah = 0;
3803 return;
3804 }
3805 }
3806
3807 // error
3808 SET_CF();
3809 regs.u.r8.ah = ret;
3810 return;
3811 break;
3812
3813 case 1: // Enable Mouse
3814 BX_DEBUG_INT15("case 1: enable mouse\n");
3815 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
3816 if ( (mouse_flags_2 & 0x80) == 0 ) {
3817 BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n");
3818 SET_CF(); // error
3819 regs.u.r8.ah = 5; // no far call installed
3820 return;
3821 }
3822 inhibit_mouse_int_and_events(); // disable IRQ12 and packets
3823 ret = send_to_mouse_ctrl(0xF4); // enable mouse command
3824 if (ret == 0) {
3825 ret = get_mouse_data(&mouse_data1);
3826 if ( (ret == 0) && (mouse_data1 == 0xFA) ) {
3827 enable_mouse_int_and_events(); // turn IRQ12 and packet generation on
3828 CLEAR_CF();
3829 regs.u.r8.ah = 0;
3830 return;
3831 }
3832 }
3833 SET_CF();
3834 regs.u.r8.ah = ret;
3835 return;
3836
3837 default: // invalid subfunction
3838 BX_DEBUG_INT15("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh);
3839 SET_CF(); // error
3840 regs.u.r8.ah = 1; // invalid subfunction
3841 return;
3842 }
3843 break;
3844
3845 case 1: // Reset Mouse
3846 case 5: // Initialize Mouse
3847 BX_DEBUG_INT15("case 1 or 5:\n");
3848 if (regs.u.r8.al == 5) {
3849 if (regs.u.r8.bh != 3) {
3850 SET_CF();
3851 regs.u.r8.ah = 0x02; // invalid input
3852 return;
3853 }
3854 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
3855 mouse_flags_2 = (mouse_flags_2 & 0x00) | regs.u.r8.bh;
3856 mouse_flags_1 = 0x00;
3857 write_byte(ebda_seg, 0x0026, mouse_flags_1);
3858 write_byte(ebda_seg, 0x0027, mouse_flags_2);
3859 }
3860
3861 inhibit_mouse_int_and_events(); // disable IRQ12 and packets
3862 ret = send_to_mouse_ctrl(0xFF); // reset mouse command
3863 if (ret == 0) {
3864 ret = get_mouse_data(&mouse_data3);
3865 // if no mouse attached, it will return RESEND
3866 if (mouse_data3 == 0xfe) {
3867 SET_CF();
3868 return;
3869 }
3870 if (mouse_data3 != 0xfa)
3871 BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3);
3872 if ( ret == 0 ) {
3873 ret = get_mouse_data(&mouse_data1);
3874 if ( ret == 0 ) {
3875 ret = get_mouse_data(&mouse_data2);
3876 if ( ret == 0 ) {
3877 // turn IRQ12 and packet generation on
3878 enable_mouse_int_and_events();
3879 CLEAR_CF();
3880 regs.u.r8.ah = 0;
3881 regs.u.r8.bl = mouse_data1;
3882 regs.u.r8.bh = mouse_data2;
3883 return;
3884 }
3885 }
3886 }
3887 }
3888
3889 // error
3890 SET_CF();
3891 regs.u.r8.ah = ret;
3892 return;
3893
3894 case 2: // Set Sample Rate
3895 BX_DEBUG_INT15("case 2:\n");
3896 switch (regs.u.r8.bh) {
3897 case 0: mouse_data1 = 10; break; // 10 reports/sec
3898 case 1: mouse_data1 = 20; break; // 20 reports/sec
3899 case 2: mouse_data1 = 40; break; // 40 reports/sec
3900 case 3: mouse_data1 = 60; break; // 60 reports/sec
3901 case 4: mouse_data1 = 80; break; // 80 reports/sec
3902 case 5: mouse_data1 = 100; break; // 100 reports/sec (default)
3903 case 6: mouse_data1 = 200; break; // 200 reports/sec
3904 default: mouse_data1 = 0;
3905 }
3906 if (mouse_data1 > 0) {
3907 ret = send_to_mouse_ctrl(0xF3); // set sample rate command
3908 if (ret == 0) {
3909 ret = get_mouse_data(&mouse_data2);
3910 ret = send_to_mouse_ctrl(mouse_data1);
3911 ret = get_mouse_data(&mouse_data2);
3912 CLEAR_CF();
3913 regs.u.r8.ah = 0;
3914 } else {
3915 // error
3916 SET_CF();
3917 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3918 }
3919 } else {
3920 // error
3921 SET_CF();
3922 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3923 }
3924 break;
3925
3926 case 3: // Set Resolution
3927 BX_DEBUG_INT15("case 3:\n");
3928 // BH:
3929 // 0 = 25 dpi, 1 count per millimeter
3930 // 1 = 50 dpi, 2 counts per millimeter
3931 // 2 = 100 dpi, 4 counts per millimeter
3932 // 3 = 200 dpi, 8 counts per millimeter
3933 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
3934 if (regs.u.r8.bh < 4) {
3935 ret = send_to_mouse_ctrl(0xE8); // set resolution command
3936 if (ret == 0) {
3937 ret = get_mouse_data(&mouse_data1);
3938 if (mouse_data1 != 0xfa)
3939 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
3940 ret = send_to_mouse_ctrl(regs.u.r8.bh);
3941 ret = get_mouse_data(&mouse_data1);
3942 if (mouse_data1 != 0xfa)
3943 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
3944 CLEAR_CF();
3945 regs.u.r8.ah = 0;
3946 } else {
3947 // error
3948 SET_CF();
3949 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3950 }
3951 } else {
3952 // error
3953 SET_CF();
3954 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3955 }
3956 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
3957 break;
3958
3959 case 4: // Get Device ID
3960 BX_DEBUG_INT15("case 4:\n");
3961 inhibit_mouse_int_and_events(); // disable IRQ12 and packets
3962 ret = send_to_mouse_ctrl(0xF2); // get mouse ID command
3963 if (ret == 0) {
3964 ret = get_mouse_data(&mouse_data1);
3965 ret = get_mouse_data(&mouse_data2);
3966 CLEAR_CF();
3967 regs.u.r8.ah = 0;
3968 regs.u.r8.bh = mouse_data2;
3969 } else {
3970 // error
3971 SET_CF();
3972 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
3973 }
3974 break;
3975
3976 case 6: // Return Status & Set Scaling Factor...
3977 BX_DEBUG_INT15("case 6:\n");
3978 switch (regs.u.r8.bh) {
3979 case 0: // Return Status
3980 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
3981 ret = send_to_mouse_ctrl(0xE9); // get mouse info command
3982 if (ret == 0) {
3983 ret = get_mouse_data(&mouse_data1);
3984 if (mouse_data1 != 0xfa)
3985 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
3986 if (ret == 0) {
3987 ret = get_mouse_data(&mouse_data1);
3988 if ( ret == 0 ) {
3989 ret = get_mouse_data(&mouse_data2);
3990 if ( ret == 0 ) {
3991 ret = get_mouse_data(&mouse_data3);
3992 if ( ret == 0 ) {
3993 CLEAR_CF();
3994 regs.u.r8.ah = 0;
3995 regs.u.r8.bl = mouse_data1;
3996 regs.u.r8.cl = mouse_data2;
3997 regs.u.r8.dl = mouse_data3;
3998 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
3999 return;
4000 }
4001 }
4002 }
4003 }
4004 }
4005
4006 // error
4007 SET_CF();
4008 regs.u.r8.ah = ret;
4009 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
4010 return;
4011
4012 case 1: // Set Scaling Factor to 1:1
4013 case 2: // Set Scaling Factor to 2:1
4014 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
4015 if (regs.u.r8.bh == 1) {
4016 ret = send_to_mouse_ctrl(0xE6);
4017 } else {
4018 ret = send_to_mouse_ctrl(0xE7);
4019 }
4020 if (ret == 0) {
4021 get_mouse_data(&mouse_data1);
4022 ret = (mouse_data1 != 0xFA);
4023 }
4024 if (ret == 0) {
4025 CLEAR_CF();
4026 regs.u.r8.ah = 0;
4027 } else {
4028 // error
4029 SET_CF();
4030 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
4031 }
4032 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
4033 break;
4034
4035 default:
4036 BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh);
4037 }
4038 break;
4039
4040 case 7: // Set Mouse Handler Address
4041 BX_DEBUG_INT15("case 7:\n");
4042 mouse_driver_seg = ES;
4043 mouse_driver_offset = regs.u.r16.bx;
4044 write_word(ebda_seg, 0x0022, mouse_driver_offset);
4045 write_word(ebda_seg, 0x0024, mouse_driver_seg);
4046 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
4047 if (mouse_driver_offset == 0 && mouse_driver_seg == 0) {
4048 /* remove handler */
4049 if ( (mouse_flags_2 & 0x80) != 0 ) {
4050 mouse_flags_2 &= ~0x80;
4051 inhibit_mouse_int_and_events(); // disable IRQ12 and packets
4052 }
4053 }
4054 else {
4055 /* install handler */
4056 mouse_flags_2 |= 0x80;
4057 }
4058 write_byte(ebda_seg, 0x0027, mouse_flags_2);
4059 CLEAR_CF();
4060 regs.u.r8.ah = 0;
4061 break;
4062
4063 default:
4064 BX_DEBUG_INT15("case default:\n");
4065 regs.u.r8.ah = 1; // invalid function
4066 SET_CF();
4067 }
4068 break;
4069
4070 default:
4071 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
4072 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
4073 SET_CF();
4074 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
4075 break;
4076 }
4077 }
4078 #endif
4079
4080
4081 void set_e820_range(ES, DI, start, end, type)
4082 Bit16u ES;
4083 Bit16u DI;
4084 Bit32u start;
4085 Bit32u end;
4086 Bit16u type;
4087 {
4088 write_word(ES, DI, start);
4089 write_word(ES, DI+2, start >> 16);
4090 write_word(ES, DI+4, 0x00);
4091 write_word(ES, DI+6, 0x00);
4092
4093 end -= start;
4094 write_word(ES, DI+8, end);
4095 write_word(ES, DI+10, end >> 16);
4096 write_word(ES, DI+12, 0x0000);
4097 write_word(ES, DI+14, 0x0000);
4098
4099 write_word(ES, DI+16, type);
4100 write_word(ES, DI+18, 0x0);
4101 }
4102
4103 void
4104 int15_function32(regs, ES, DS, FLAGS)
4105 pushad_regs_t regs; // REGS pushed via pushad
4106 Bit16u ES, DS, FLAGS;
4107 {
4108 Bit32u extended_memory_size=0; // 64bits long
4109 Bit16u CX,DX;
4110
4111 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
4112
4113 switch (regs.u.r8.ah) {
4114 case 0x86:
4115 // Wait for CX:DX microseconds. currently using the
4116 // refresh request port 0x61 bit4, toggling every 15usec
4117
4118 CX = regs.u.r16.cx;
4119 DX = regs.u.r16.dx;
4120
4121 ASM_START
4122 sti
4123
4124 ;; Get the count in eax
4125 mov bx, sp
4126 SEG SS
4127 mov ax, _int15_function32.CX [bx]
4128 shl eax, #16
4129 SEG SS
4130 mov ax, _int15_function32.DX [bx]
4131
4132 ;; convert to numbers of 15usec ticks
4133 mov ebx, #15
4134 xor edx, edx
4135 div eax, ebx
4136 mov ecx, eax
4137
4138 ;; wait for ecx number of refresh requests
4139 in al, #0x61
4140 and al,#0x10
4141 mov ah, al
4142
4143 or ecx, ecx
4144 je int1586_tick_end
4145 int1586_tick:
4146 in al, #0x61
4147 and al,#0x10
4148 cmp al, ah
4149 je int1586_tick
4150 mov ah, al
4151 dec ecx
4152 jnz int1586_tick
4153 int1586_tick_end:
4154 ASM_END
4155
4156 break;
4157
4158 case 0xe8:
4159 switch(regs.u.r8.al)
4160 {
4161 case 0x20: // coded by osmaker aka K.J.
4162 if(regs.u.r32.edx == 0x534D4150)
4163 {
4164 extended_memory_size = inb_cmos(0x35);
4165 extended_memory_size <<= 8;
4166 extended_memory_size |= inb_cmos(0x34);
4167 extended_memory_size *= 64;
4168 // greater than EFF00000???
4169 if(extended_memory_size > 0x3bc000) {
4170 extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
4171 }
4172 extended_memory_size *= 1024;
4173 extended_memory_size += (16L * 1024 * 1024);
4174
4175 if(extended_memory_size <= (16L * 1024 * 1024)) {
4176 extended_memory_size = inb_cmos(0x31);
4177 extended_memory_size <<= 8;
4178 extended_memory_size |= inb_cmos(0x30);
4179 extended_memory_size *= 1024;
4180 }
4181
4182 switch(regs.u.r16.bx)
4183 {
4184 case 0:
4185 set_e820_range(ES, regs.u.r16.di,
4186 0x0000000L, 0x0009fc00L, 1);
4187 regs.u.r32.ebx = 1;
4188 regs.u.r32.eax = 0x534D4150;
4189 regs.u.r32.ecx = 0x14;
4190 CLEAR_CF();
4191 return;
4192 break;
4193 case 1:
4194 set_e820_range(ES, regs.u.r16.di,
4195 0x0009fc00L, 0x000a0000L, 2);
4196 regs.u.r32.ebx = 2;
4197 regs.u.r32.eax = 0x534D4150;
4198 regs.u.r32.ecx = 0x14;
4199 CLEAR_CF();
4200 return;
4201 break;
4202 case 2:
4203 set_e820_range(ES, regs.u.r16.di,
4204 0x000e8000L, 0x00100000L, 2);
4205 regs.u.r32.ebx = 3;
4206 regs.u.r32.eax = 0x534D4150;
4207 regs.u.r32.ecx = 0x14;
4208 CLEAR_CF();
4209 return;
4210 break;
4211 case 3:
4212 set_e820_range(ES, regs.u.r16.di,
4213 0x00100000L,
4214 extended_memory_size - ACPI_DATA_SIZE, 1);
4215 regs.u.r32.ebx = 4;
4216 regs.u.r32.eax = 0x534D4150;
4217 regs.u.r32.ecx = 0x14;
4218 CLEAR_CF();
4219 return;
4220 break;
4221 case 4:
4222 set_e820_range(ES, regs.u.r16.di,
4223 extended_memory_size - ACPI_DATA_SIZE,
4224 extended_memory_size, 3); // ACPI RAM
4225 regs.u.r32.ebx = 5;
4226 regs.u.r32.eax = 0x534D4150;
4227 regs.u.r32.ecx = 0x14;
4228 CLEAR_CF();
4229 return;
4230 break;
4231 case 5:
4232 /* 256KB BIOS area at the end of 4 GB */
4233 set_e820_range(ES, regs.u.r16.di,
4234 0xfffc0000L, 0x00000000L, 2);
4235 regs.u.r32.ebx = 0;
4236 regs.u.r32.eax = 0x534D4150;
4237 regs.u.r32.ecx = 0x14;
4238 CLEAR_CF();
4239 return;
4240 default: /* AX=E820, DX=534D4150, BX unrecognized */
4241 goto int15_unimplemented;
4242 break;
4243 }
4244 } else {
4245 // if DX != 0x534D4150)
4246 goto int15_unimplemented;
4247 }
4248 break;
4249
4250 case 0x01:
4251 // do we have any reason to fail here ?
4252 CLEAR_CF();
4253
4254 // my real system sets ax and bx to 0
4255 // this is confirmed by Ralph Brown list
4256 // but syslinux v1.48 is known to behave
4257 // strangely if ax is set to 0
4258 // regs.u.r16.ax = 0;
4259 // regs.u.r16.bx = 0;
4260
4261 // Get the amount of extended memory (above 1M)
4262 regs.u.r8.cl = inb_cmos(0x30);
4263 regs.u.r8.ch = inb_cmos(0x31);
4264
4265 // limit to 15M
4266 if(regs.u.r16.cx > 0x3c00)
4267 {
4268 regs.u.r16.cx = 0x3c00;
4269 }
4270
4271 // Get the amount of extended memory above 16M in 64k blocs
4272 regs.u.r8.dl = inb_cmos(0x34);
4273 regs.u.r8.dh = inb_cmos(0x35);
4274
4275 // Set configured memory equal to extended memory
4276 regs.u.r16.ax = regs.u.r16.cx;
4277 regs.u.r16.bx = regs.u.r16.dx;
4278 break;
4279 default: /* AH=0xE8?? but not implemented */
4280 goto int15_unimplemented;
4281 }
4282 break;
4283 int15_unimplemented:
4284 // fall into the default
4285 default:
4286 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
4287 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
4288 SET_CF();
4289 regs.u.r8.ah = UNSUPPORTED_FUNCTION;
4290 break;
4291 }
4292 }
4293
4294 void
4295 int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
4296 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS;
4297 {
4298 Bit8u scan_code, ascii_code, shift_flags, led_flags, count;
4299 Bit16u kbd_code, max;
4300
4301 BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
4302
4303 shift_flags = read_byte(0x0040, 0x17);
4304 led_flags = read_byte(0x0040, 0x97);
4305 if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) {
4306 ASM_START
4307 cli
4308 ASM_END
4309 outb(0x60, 0xed);
4310 while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
4311 if ((inb(0x60) == 0xfa)) {
4312 led_flags &= 0xf8;
4313 led_flags |= ((shift_flags >> 4) & 0x07);
4314 outb(0x60, led_flags & 0x07);
4315 while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
4316 inb(0x60);
4317 write_byte(0x0040, 0x97, led_flags);
4318 }
4319 ASM_START
4320 sti
4321 ASM_END
4322 }
4323
4324 switch (GET_AH()) {
4325 case 0x00: /* read keyboard input */
4326
4327 if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
4328 BX_PANIC("KBD: int16h: out of keyboard input\n");
4329 }
4330 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4331 else if (ascii_code == 0xE0) ascii_code = 0;
4332 AX = (scan_code << 8) | ascii_code;
4333 break;
4334
4335 case 0x01: /* check keyboard status */
4336 if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
4337 SET_ZF();
4338 return;
4339 }
4340 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4341 else if (ascii_code == 0xE0) ascii_code = 0;
4342 AX = (scan_code << 8) | ascii_code;
4343 CLEAR_ZF();
4344 break;
4345
4346 case 0x02: /* get shift flag status */
4347 shift_flags = read_byte(0x0040, 0x17);
4348 SET_AL(shift_flags);
4349 break;
4350
4351 case 0x05: /* store key-stroke into buffer */
4352 if ( !enqueue_key(GET_CH(), GET_CL()) ) {
4353 SET_AL(1);
4354 }
4355 else {
4356 SET_AL(0);
4357 }
4358 break;
4359
4360 case 0x09: /* GET KEYBOARD FUNCTIONALITY */
4361 // bit Bochs Description
4362 // 7 0 reserved
4363 // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support)
4364 // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support)
4365 // 4 1 INT 16/AH=0Ah supported
4366 // 3 0 INT 16/AX=0306h supported
4367 // 2 0 INT 16/AX=0305h supported
4368 // 1 0 INT 16/AX=0304h supported
4369 // 0 0 INT 16/AX=0300h supported
4370 //
4371 SET_AL(0x30);
4372 break;
4373
4374 case 0x0A: /* GET KEYBOARD ID */
4375 count = 2;
4376 kbd_code = 0x0;
4377 outb(0x60, 0xf2);
4378 /* Wait for data */
4379 max=0xffff;
4380 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00);
4381 if (max>0x0) {
4382 if ((inb(0x60) == 0xfa)) {
4383 do {
4384 max=0xffff;
4385 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00);
4386 if (max>0x0) {
4387 kbd_code >>= 8;
4388 kbd_code |= (inb(0x60) << 8);
4389 }
4390 } while (--count>0);
4391 }
4392 }
4393 BX=kbd_code;
4394 break;
4395
4396 case 0x10: /* read MF-II keyboard input */
4397
4398 if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
4399 BX_PANIC("KBD: int16h: out of keyboard input\n");
4400 }
4401 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4402 AX = (scan_code << 8) | ascii_code;
4403 break;
4404
4405 case 0x11: /* check MF-II keyboard status */
4406 if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
4407 SET_ZF();
4408 return;
4409 }
4410 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4411 AX = (scan_code << 8) | ascii_code;
4412 CLEAR_ZF();
4413 break;
4414
4415 case 0x12: /* get extended keyboard status */
4416 shift_flags = read_byte(0x0040, 0x17);
4417 SET_AL(shift_flags);
4418 shift_flags = read_byte(0x0040, 0x18) & 0x73;
4419 shift_flags |= read_byte(0x0040, 0x96) & 0x0c;
4420 SET_AH(shift_flags);
4421 BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX);
4422 break;
4423
4424 case 0x92: /* keyboard capability check called by DOS 5.0+ keyb */
4425 SET_AH(0x80); // function int16 ah=0x10-0x12 supported
4426 break;
4427
4428 case 0xA2: /* 122 keys capability check called by DOS 5.0+ keyb */
4429 // don't change AH : function int16 ah=0x20-0x22 NOT supported
4430 break;
4431
4432 case 0x6F:
4433 if (GET_AL() == 0x08)
4434 SET_AH(0x02); // unsupported, aka normal keyboard
4435
4436 default:
4437 BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
4438 }
4439 }
4440
4441 unsigned int
4442 dequeue_key(scan_code, ascii_code, incr)
4443 Bit8u *scan_code;
4444 Bit8u *ascii_code;
4445 unsigned int incr;
4446 {
4447 Bit16u buffer_start, buffer_end, buffer_head, buffer_tail;
4448 Bit16u ss;
4449 Bit8u acode, scode;
4450
4451 #if BX_CPU < 2
4452 buffer_start = 0x001E;
4453 buffer_end = 0x003E;
4454 #else
4455 buffer_start = read_word(0x0040, 0x0080);
4456 buffer_end = read_word(0x0040, 0x0082);
4457 #endif
4458
4459 buffer_head = read_word(0x0040, 0x001a);
4460 buffer_tail = read_word(0x0040, 0x001c);
4461
4462 if (buffer_head != buffer_tail) {
4463 ss = get_SS();
4464 acode = read_byte(0x0040, buffer_head);
4465 scode = read_byte(0x0040, buffer_head+1);
4466 write_byte(ss, ascii_code, acode);
4467 write_byte(ss, scan_code, scode);
4468
4469 if (incr) {
4470 buffer_head += 2;
4471 if (buffer_head >= buffer_end)
4472 buffer_head = buffer_start;
4473 write_word(0x0040, 0x001a, buffer_head);
4474 }
4475 return(1);
4476 }
4477 else {
4478 return(0);
4479 }
4480 }
4481
4482 static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n";
4483
4484 Bit8u
4485 inhibit_mouse_int_and_events()
4486 {
4487 Bit8u command_byte, prev_command_byte;
4488
4489 // Turn off IRQ generation and aux data line
4490 if ( inb(0x64) & 0x02 )
4491 BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse");
4492 outb(0x64, 0x20); // get command byte
4493 while ( (inb(0x64) & 0x01) != 0x01 );
4494 prev_command_byte = inb(0x60);
4495 command_byte = prev_command_byte;
4496 //while ( (inb(0x64) & 0x02) );
4497 if ( inb(0x64) & 0x02 )
4498 BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse");
4499 command_byte &= 0xfd; // turn off IRQ 12 generation
4500 command_byte |= 0x20; // disable mouse serial clock line
4501 outb(0x64, 0x60); // write command byte
4502 outb(0x60, command_byte);
4503 return(prev_command_byte);
4504 }
4505
4506 void
4507 enable_mouse_int_and_events()
4508 {
4509 Bit8u command_byte;
4510
4511 // Turn on IRQ generation and aux data line
4512 if ( inb(0x64) & 0x02 )
4513 BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse");
4514 outb(0x64, 0x20); // get command byte
4515 while ( (inb(0x64) & 0x01) != 0x01 );
4516 command_byte = inb(0x60);
4517 //while ( (inb(0x64) & 0x02) );
4518 if ( inb(0x64) & 0x02 )
4519 BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse");
4520 command_byte |= 0x02; // turn on IRQ 12 generation
4521 command_byte &= 0xdf; // enable mouse serial clock line
4522 outb(0x64, 0x60); // write command byte
4523 outb(0x60, command_byte);
4524 }
4525
4526 Bit8u
4527 send_to_mouse_ctrl(sendbyte)
4528 Bit8u sendbyte;
4529 {
4530 Bit8u response;
4531
4532 // wait for chance to write to ctrl
4533 if ( inb(0x64) & 0x02 )
4534 BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse");
4535 outb(0x64, 0xD4);
4536 outb(0x60, sendbyte);
4537 return(0);
4538 }
4539
4540
4541 Bit8u
4542 get_mouse_data(data)
4543 Bit8u *data;
4544 {
4545 Bit8u response;
4546 Bit16u ss;
4547
4548 while ( (inb(0x64) & 0x21) != 0x21 ) {
4549 }
4550
4551 response = inb(0x60);
4552
4553 ss = get_SS();
4554 write_byte(ss, data, response);
4555 return(0);
4556 }
4557
4558 void
4559 set_kbd_command_byte(command_byte)
4560 Bit8u command_byte;
4561 {
4562 if ( inb(0x64) & 0x02 )
4563 BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm");
4564 outb(0x64, 0xD4);
4565
4566 outb(0x64, 0x60); // write command byte
4567 outb(0x60, command_byte);
4568 }
4569
4570 void
4571 int09_function(DI, SI, BP, SP, BX, DX, CX, AX)
4572 Bit16u DI, SI, BP, SP, BX, DX, CX, AX;
4573 {
4574 Bit8u scancode, asciicode, shift_flags;
4575 Bit8u mf2_flags, mf2_state;
4576
4577 //
4578 // DS has been set to F000 before call
4579 //
4580
4581
4582 scancode = GET_AL();
4583
4584 if (scancode == 0) {
4585 BX_INFO("KBD: int09 handler: AL=0\n");
4586 return;
4587 }
4588
4589
4590 shift_flags = read_byte(0x0040, 0x17);
4591 mf2_flags = read_byte(0x0040, 0x18);
4592 mf2_state = read_byte(0x0040, 0x96);
4593 asciicode = 0;
4594
4595 switch (scancode) {
4596 case 0x3a: /* Caps Lock press */
4597 shift_flags ^= 0x40;
4598 write_byte(0x0040, 0x17, shift_flags);
4599 mf2_flags |= 0x40;
4600 write_byte(0x0040, 0x18, mf2_flags);
4601 break;
4602 case 0xba: /* Caps Lock release */
4603 mf2_flags &= ~0x40;
4604 write_byte(0x0040, 0x18, mf2_flags);
4605 break;
4606
4607 case 0x2a: /* L Shift press */
4608 shift_flags |= 0x02;
4609 write_byte(0x0040, 0x17, shift_flags);
4610 break;
4611 case 0xaa: /* L Shift release */
4612 shift_flags &= ~0x02;
4613 write_byte(0x0040, 0x17, shift_flags);
4614 break;
4615
4616 case 0x36: /* R Shift press */
4617 shift_flags |= 0x01;
4618 write_byte(0x0040, 0x17, shift_flags);
4619 break;
4620 case 0xb6: /* R Shift release */
4621 shift_flags &= ~0x01;
4622 write_byte(0x0040, 0x17, shift_flags);
4623 break;
4624
4625 case 0x1d: /* Ctrl press */
4626 if ((mf2_state & 0x01) == 0) {
4627 shift_flags |= 0x04;
4628 write_byte(0x0040, 0x17, shift_flags);
4629 if (mf2_state & 0x02) {
4630 mf2_state |= 0x04;
4631 write_byte(0x0040, 0x96, mf2_state);
4632 } else {
4633 mf2_flags |= 0x01;
4634 write_byte(0x0040, 0x18, mf2_flags);
4635 }
4636 }
4637 break;
4638 case 0x9d: /* Ctrl release */
4639 if ((mf2_state & 0x01) == 0) {
4640 shift_flags &= ~0x04;
4641 write_byte(0x0040, 0x17, shift_flags);
4642 if (mf2_state & 0x02) {
4643 mf2_state &= ~0x04;
4644 write_byte(0x0040, 0x96, mf2_state);
4645 } else {
4646 mf2_flags &= ~0x01;
4647 write_byte(0x0040, 0x18, mf2_flags);
4648 }
4649 }
4650 break;
4651
4652 case 0x38: /* Alt press */
4653 shift_flags |= 0x08;
4654 write_byte(0x0040, 0x17, shift_flags);
4655 if (mf2_state & 0x02) {
4656 mf2_state |= 0x08;
4657 write_byte(0x0040, 0x96, mf2_state);
4658 } else {
4659 mf2_flags |= 0x02;
4660 write_byte(0x0040, 0x18, mf2_flags);
4661 }
4662 break;
4663 case 0xb8: /* Alt release */
4664 shift_flags &= ~0x08;
4665 write_byte(0x0040, 0x17, shift_flags);
4666 if (mf2_state & 0x02) {
4667 mf2_state &= ~0x08;
4668 write_byte(0x0040, 0x96, mf2_state);
4669 } else {
4670 mf2_flags &= ~0x02;
4671 write_byte(0x0040, 0x18, mf2_flags);
4672 }
4673 break;
4674
4675 case 0x45: /* Num Lock press */
4676 if ((mf2_state & 0x03) == 0) {
4677 mf2_flags |= 0x20;
4678 write_byte(0x0040, 0x18, mf2_flags);
4679 shift_flags ^= 0x20;
4680 write_byte(0x0040, 0x17, shift_flags);
4681 }
4682 break;
4683 case 0xc5: /* Num Lock release */
4684 if ((mf2_state & 0x03) == 0) {
4685 mf2_flags &= ~0x20;
4686 write_byte(0x0040, 0x18, mf2_flags);
4687 }
4688 break;
4689
4690 case 0x46: /* Scroll Lock press */
4691 mf2_flags |= 0x10;
4692 write_byte(0x0040, 0x18, mf2_flags);
4693 shift_flags ^= 0x10;
4694 write_byte(0x0040, 0x17, shift_flags);
4695 break;
4696
4697 case 0xc6: /* Scroll Lock release */
4698 mf2_flags &= ~0x10;
4699 write_byte(0x0040, 0x18, mf2_flags);
4700 break;
4701
4702 default:
4703 if (scancode & 0x80) {
4704 break; /* toss key releases ... */
4705 }
4706 if (scancode > MAX_SCAN_CODE) {
4707 BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode);
4708 return;
4709 }
4710 if (shift_flags & 0x08) { /* ALT */
4711 asciicode = scan_to_scanascii[scancode].alt;
4712 scancode = scan_to_scanascii[scancode].alt >> 8;
4713 } else if (shift_flags & 0x04) { /* CONTROL */
4714 asciicode = scan_to_scanascii[scancode].control;
4715 scancode = scan_to_scanascii[scancode].control >> 8;
4716 } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) {
4717 /* extended keys handling */
4718 asciicode = 0xe0;
4719 scancode = scan_to_scanascii[scancode].normal >> 8;
4720 } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
4721 /* check if lock state should be ignored
4722 * because a SHIFT key are pressed */
4723
4724 if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
4725 asciicode = scan_to_scanascii[scancode].normal;
4726 scancode = scan_to_scanascii[scancode].normal >> 8;
4727 } else {
4728 asciicode = scan_to_scanascii[scancode].shift;
4729 scancode = scan_to_scanascii[scancode].shift >> 8;
4730 }
4731 } else {
4732 /* check if lock is on */
4733 if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
4734 asciicode = scan_to_scanascii[scancode].shift;
4735 scancode = scan_to_scanascii[scancode].shift >> 8;
4736 } else {
4737 asciicode = scan_to_scanascii[scancode].normal;
4738 scancode = scan_to_scanascii[scancode].normal >> 8;
4739 }
4740 }
4741 if (scancode==0 && asciicode==0) {
4742 BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n");
4743 }
4744 enqueue_key(scancode, asciicode);
4745 break;
4746 }
4747 if ((scancode & 0x7f) != 0x1d) {
4748 mf2_state &= ~0x01;
4749 }
4750 mf2_state &= ~0x02;
4751 write_byte(0x0040, 0x96, mf2_state);
4752 }
4753
4754 unsigned int
4755 enqueue_key(scan_code, ascii_code)
4756 Bit8u scan_code, ascii_code;
4757 {
4758 Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail;
4759
4760 #if BX_CPU < 2
4761 buffer_start = 0x001E;
4762 buffer_end = 0x003E;
4763 #else
4764 buffer_start = read_word(0x0040, 0x0080);
4765 buffer_end = read_word(0x0040, 0x0082);
4766 #endif
4767
4768 buffer_head = read_word(0x0040, 0x001A);
4769 buffer_tail = read_word(0x0040, 0x001C);
4770
4771 temp_tail = buffer_tail;
4772 buffer_tail += 2;
4773 if (buffer_tail >= buffer_end)
4774 buffer_tail = buffer_start;
4775
4776 if (buffer_tail == buffer_head) {
4777 return(0);
4778 }
4779
4780 write_byte(0x0040, temp_tail, ascii_code);
4781 write_byte(0x0040, temp_tail+1, scan_code);
4782 write_word(0x0040, 0x001C, buffer_tail);
4783 return(1);
4784 }
4785
4786
4787 void
4788 int74_function(make_farcall, Z, Y, X, status)
4789 Bit16u make_farcall, Z, Y, X, status;
4790 {
4791 Bit16u ebda_seg=read_word(0x0040,0x000E);
4792 Bit8u in_byte, index, package_count;
4793 Bit8u mouse_flags_1, mouse_flags_2;
4794
4795 BX_DEBUG_INT74("entering int74_function\n");
4796 make_farcall = 0;
4797
4798 in_byte = inb(0x64);
4799 if ( (in_byte & 0x21) != 0x21 ) {
4800 return;
4801 }
4802 in_byte = inb(0x60);
4803 BX_DEBUG_INT74("int74: read byte %02x\n", in_byte);
4804
4805 mouse_flags_1 = read_byte(ebda_seg, 0x0026);
4806 mouse_flags_2 = read_byte(ebda_seg, 0x0027);
4807
4808 if ( (mouse_flags_2 & 0x80) != 0x80 ) {
4809 return;
4810 }
4811
4812 package_count = mouse_flags_2 & 0x07;
4813 index = mouse_flags_1 & 0x07;
4814 write_byte(ebda_seg, 0x28 + index, in_byte);
4815
4816 if ( (index+1) >= package_count ) {
4817 BX_DEBUG_INT74("int74_function: make_farcall=1\n");
4818 status = read_byte(ebda_seg, 0x0028 + 0);
4819 X = read_byte(ebda_seg, 0x0028 + 1);
4820 Y = read_byte(ebda_seg, 0x0028 + 2);
4821 Z = 0;
4822 mouse_flags_1 = 0;
4823 // check if far call handler installed
4824 if (mouse_flags_2 & 0x80)
4825 make_farcall = 1;
4826 }
4827 else {
4828 mouse_flags_1++;
4829 }
4830 write_byte(ebda_seg, 0x0026, mouse_flags_1);
4831 }
4832
4833 #define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
4834
4835 #if BX_USE_ATADRV
4836
4837 void
4838 int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
4839 Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
4840 {
4841 Bit32u lba;
4842 Bit16u ebda_seg=read_word(0x0040,0x000E);
4843 Bit16u cylinder, head, sector;
4844 Bit16u segment, offset;
4845 Bit16u npc, nph, npspt, nlc, nlh, nlspt;
4846 Bit16u size, count;
4847 Bit8u device, status;
4848
4849 BX_DEBUG_INT13_HD("int13_harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
4850
4851 write_byte(0x0040, 0x008e, 0); // clear completion flag
4852
4853 // basic check : device has to be defined
4854 if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) {
4855 BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
4856 goto int13_fail;
4857 }
4858
4859 // Get the ata channel
4860 device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
4861
4862 // basic check : device has to be valid
4863 if (device >= BX_MAX_ATA_DEVICES) {
4864 BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
4865 goto int13_fail;
4866 }
4867
4868 switch (GET_AH()) {
4869
4870 case 0x00: /* disk controller reset */
4871 ata_reset (device);
4872 goto int13_success;
4873 break;
4874
4875 case 0x01: /* read disk status */
4876 status = read_byte(0x0040, 0x0074);
4877 SET_AH(status);
4878 SET_DISK_RET_STATUS(0);
4879 /* set CF if error status read */
4880 if (status) goto int13_fail_nostatus;
4881 else goto int13_success_noah;
4882 break;
4883
4884 case 0x02: // read disk sectors
4885 case 0x03: // write disk sectors
4886 case 0x04: // verify disk sectors
4887
4888 count = GET_AL();
4889 cylinder = GET_CH();
4890 cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300;
4891 sector = (GET_CL() & 0x3f);
4892 head = GET_DH();
4893
4894 segment = ES;
4895 offset = BX;
4896
4897 if ((count > 128) || (count == 0) || (sector == 0)) {
4898 BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH());
4899 goto int13_fail;
4900 }
4901
4902 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
4903 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
4904 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
4905
4906 // sanity check on cyl heads, sec
4907 if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) {
4908 BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector);
4909 goto int13_fail;
4910 }
4911
4912 // FIXME verify
4913 if ( GET_AH() == 0x04 ) goto int13_success;
4914
4915 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
4916 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
4917
4918 // if needed, translate lchs to lba, and execute command
4919 if ( (nph != nlh) || (npspt != nlspt)) {
4920 lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
4921 sector = 0; // this forces the command to be lba
4922 }
4923
4924 if ( GET_AH() == 0x02 )
4925 status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba, segment, offset);
4926 else
4927 status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, segment, offset);
4928
4929 // Set nb of sector transferred
4930 SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
4931
4932 if (status != 0) {
4933 BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
4934 SET_AH(0x0c);
4935 goto int13_fail_noah;
4936 }
4937
4938 goto int13_success;
4939 break;
4940
4941 case 0x05: /* format disk track */
4942 BX_INFO("format disk track called\n");
4943 goto int13_success;
4944 return;
4945 break;
4946
4947 case 0x08: /* read disk drive parameters */
4948
4949 // Get logical geometry from table
4950 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
4951 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
4952 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
4953 count = read_byte(ebda_seg, &EbdaData->ata.hdcount);
4954
4955 nlc = nlc - 2; /* 0 based , last sector not used */
4956 SET_AL(0);
4957 SET_CH(nlc & 0xff);
4958 SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f));
4959 SET_DH(nlh - 1);
4960 SET_DL(count); /* FIXME returns 0, 1, or n hard drives */
4961
4962 // FIXME should set ES & DI
4963
4964 goto int13_success;
4965 break;
4966
4967 case 0x10: /* check drive ready */
4968 // should look at 40:8E also???
4969
4970 // Read the status from controller
4971 status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT);
4972 if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) {
4973 goto int13_success;
4974 }
4975 else {
4976 SET_AH(0xAA);
4977 goto int13_fail_noah;
4978 }
4979 break;
4980
4981 case 0x15: /* read disk drive size */
4982
4983 // Get physical geometry from table
4984 npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders);
4985 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
4986 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
4987
4988 // Compute sector count seen by int13
4989 lba = (Bit32u)(npc - 1) * (Bit32u)nph * (Bit32u)npspt;
4990 CX = lba >> 16;
4991 DX = lba & 0xffff;
4992
4993 SET_AH(3); // hard disk accessible
4994 goto int13_success_noah;
4995 break;
4996
4997 case 0x41: // IBM/MS installation check
4998 BX=0xaa55; // install check
4999 SET_AH(0x30); // EDD 3.0
5000 CX=0x0007; // ext disk access and edd, removable supported
5001 goto int13_success_noah;
5002 break;
5003
5004 case 0x42: // IBM/MS extended read
5005 case 0x43: // IBM/MS extended write
5006 case 0x44: // IBM/MS verify
5007 case 0x47: // IBM/MS extended seek
5008
5009 count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
5010 segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
5011 offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
5012
5013 // Can't use 64 bits lba
5014 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
5015 if (lba != 0L) {
5016 BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH());
5017 goto int13_fail;
5018 }
5019
5020 // Get 32 bits lba and check
5021 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
5022 if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) {
5023 BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
5024 goto int13_fail;
5025 }
5026
5027 // If verify or seek
5028 if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
5029 goto int13_success;
5030
5031 // Execute the command
5032 if ( GET_AH() == 0x42 )
5033 status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba, segment, offset);
5034 else
5035 status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset);
5036
5037 count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
5038 write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
5039
5040 if (status != 0) {
5041 BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
5042 SET_AH(0x0c);
5043 goto int13_fail_noah;
5044 }
5045
5046 goto int13_success;
5047 break;
5048
5049 case 0x45: // IBM/MS lock/unlock drive
5050 case 0x49: // IBM/MS extended media change
5051 goto int13_success; // Always success for HD
5052 break;
5053
5054 case 0x46: // IBM/MS eject media
5055 SET_AH(0xb2); // Volume Not Removable
5056 goto int13_fail_noah; // Always fail for HD
5057 break;
5058
5059 case 0x48: // IBM/MS get drive parameters
5060 size=read_word(DS,SI+(Bit16u)&Int13DPT->size);
5061
5062 // Buffer is too small
5063 if(size < 0x1a)
5064 goto int13_fail;
5065
5066 // EDD 1.x
5067 if(size >= 0x1a) {
5068 Bit16u blksize;
5069
5070 npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders);
5071 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
5072 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
5073 lba = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors);
5074 blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
5075
5076 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
5077 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
5078 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
5079 write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
5080 write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
5081 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba); // FIXME should be Bit64
5082 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);
5083 write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
5084 }
5085
5086 // EDD 2.x
5087 if(size >= 0x1e) {
5088 Bit8u channel, dev, irq, mode, checksum, i, translation;
5089 Bit16u iobase1, iobase2, options;
5090
5091 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
5092
5093 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
5094 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
5095
5096 // Fill in dpte
5097 channel = device / 2;
5098 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
5099 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
5100 irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
5101 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
5102 translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation);
5103
5104 options = (translation==ATA_TRANSLATION_NONE?0:1<<3); // chs translation
5105 options |= (1<<4); // lba translation
5106 options |= (mode==ATA_MODE_PIO32?1:0<<7);
5107 options |= (translation==ATA_TRANSLATION_LBA?1:0<<9);
5108 options |= (translation==ATA_TRANSLATION_RECHS?3:0<<9);
5109
5110 write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
5111 write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
5112 write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
5113 write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
5114 write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
5115 write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
5116 write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
5117 write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
5118 write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
5119 write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
5120 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
5121
5122 checksum=0;
5123 for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i);
5124 checksum = ~checksum;
5125 write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
5126 }
5127
5128 // EDD 3.x
5129 if(size >= 0x42) {
5130 Bit8u channel, iface, checksum, i;
5131 Bit16u iobase1;
5132
5133 channel = device / 2;
5134 iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
5135 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
5136
5137 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
5138 write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
5139 write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
5140 write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
5141 write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
5142
5143 if (iface==ATA_IFACE_ISA) {
5144 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
5145 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
5146 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
5147 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
5148 }
5149 else {
5150 // FIXME PCI
5151 }
5152 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
5153 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
5154 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
5155 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
5156
5157 if (iface==ATA_IFACE_ISA) {
5158 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
5159 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
5160 write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
5161 }
5162 else {
5163 // FIXME PCI
5164 }
5165 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
5166 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
5167 write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
5168 write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
5169
5170 checksum=0;
5171 for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
5172 checksum = ~checksum;
5173 write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
5174 }
5175
5176 goto int13_success;
5177 break;
5178
5179 case 0x4e: // // IBM/MS set hardware configuration
5180 // DMA, prefetch, PIO maximum not supported
5181 switch (GET_AL()) {
5182 case 0x01:
5183 case 0x03:
5184 case 0x04:
5185 case 0x06:
5186 goto int13_success;
5187 break;
5188 default :
5189 goto int13_fail;
5190 }
5191 break;
5192
5193 case 0x09: /* initialize drive parameters */
5194 case 0x0c: /* seek to specified cylinder */
5195 case 0x0d: /* alternate disk reset */
5196 case 0x11: /* recalibrate */
5197 case 0x14: /* controller internal diagnostic */
5198 BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH());
5199 goto int13_success;
5200 break;
5201
5202 case 0x0a: /* read disk sectors with ECC */
5203 case 0x0b: /* write disk sectors with ECC */
5204 case 0x18: // set media type for format
5205 case 0x50: // IBM/MS send packet command
5206 default:
5207 BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
5208 goto int13_fail;
5209 break;
5210 }
5211
5212 int13_fail:
5213 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
5214 int13_fail_noah:
5215 SET_DISK_RET_STATUS(GET_AH());
5216 int13_fail_nostatus:
5217 SET_CF(); // error occurred
5218 return;
5219
5220 int13_success:
5221 SET_AH(0x00); // no error
5222 int13_success_noah:
5223 SET_DISK_RET_STATUS(0x00);
5224 CLEAR_CF(); // no error
5225 return;
5226 }
5227
5228 // ---------------------------------------------------------------------------
5229 // Start of int13 for cdrom
5230 // ---------------------------------------------------------------------------
5231
5232 void
5233 int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
5234 Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
5235 {
5236 Bit16u ebda_seg=read_word(0x0040,0x000E);
5237 Bit8u device, status, locks;
5238 Bit8u atacmd[12];
5239 Bit32u lba;
5240 Bit16u count, segment, offset, i, size;
5241
5242 BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
5243
5244 SET_DISK_RET_STATUS(0x00);
5245
5246 /* basic check : device should be 0xE0+ */
5247 if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
5248 BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
5249 goto int13_fail;
5250 }
5251
5252 // Get the ata channel
5253 device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
5254
5255 /* basic check : device has to be valid */
5256 if (device >= BX_MAX_ATA_DEVICES) {
5257 BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
5258 goto int13_fail;
5259 }
5260
5261 switch (GET_AH()) {
5262
5263 // all those functions return SUCCESS
5264 case 0x00: /* disk controller reset */
5265 case 0x09: /* initialize drive parameters */
5266 case 0x0c: /* seek to specified cylinder */
5267 case 0x0d: /* alternate disk reset */
5268 case 0x10: /* check drive ready */
5269 case 0x11: /* recalibrate */
5270 case 0x14: /* controller internal diagnostic */
5271 case 0x16: /* detect disk change */
5272 goto int13_success;
5273 break;
5274
5275 // all those functions return disk write-protected
5276 case 0x03: /* write disk sectors */
5277 case 0x05: /* format disk track */
5278 case 0x43: // IBM/MS extended write
5279 SET_AH(0x03);
5280 goto int13_fail_noah;
5281 break;
5282
5283 case 0x01: /* read disk status */
5284 status = read_byte(0x0040, 0x0074);
5285 SET_AH(status);
5286 SET_DISK_RET_STATUS(0);
5287
5288 /* set CF if error status read */
5289 if (status) goto int13_fail_nostatus;
5290 else goto int13_success_noah;
5291 break;
5292
5293 case 0x15: /* read disk drive size */
5294 SET_AH(0x02);
5295 goto int13_fail_noah;
5296 break;
5297
5298 case 0x41: // IBM/MS installation check
5299 BX=0xaa55; // install check
5300 SET_AH(0x30); // EDD 2.1
5301 CX=0x0007; // ext disk access, removable and edd
5302 goto int13_success_noah;
5303 break;
5304
5305 case 0x42: // IBM/MS extended read
5306 case 0x44: // IBM/MS verify sectors
5307 case 0x47: // IBM/MS extended seek
5308
5309 count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
5310 segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
5311 offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
5312
5313 // Can't use 64 bits lba
5314 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
5315 if (lba != 0L) {
5316 BX_PANIC("int13_cdrom: function %02x. Can't use 64bits lba\n",GET_AH());
5317 goto int13_fail;
5318 }
5319
5320 // Get 32 bits lba
5321 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
5322
5323 // If verify or seek
5324 if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
5325 goto int13_success;
5326
5327 memsetb(get_SS(),atacmd,0,12);
5328 atacmd[0]=0x28; // READ command
5329 atacmd[7]=(count & 0xff00) >> 8; // Sectors
5330 atacmd[8]=(count & 0x00ff); // Sectors
5331 atacmd[2]=(lba & 0xff000000) >> 24; // LBA
5332 atacmd[3]=(lba & 0x00ff0000) >> 16;
5333 atacmd[4]=(lba & 0x0000ff00) >> 8;
5334 atacmd[5]=(lba & 0x000000ff);
5335 status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset);
5336
5337 count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
5338 write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
5339
5340 if (status != 0) {
5341 BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
5342 SET_AH(0x0c);
5343 goto int13_fail_noah;
5344 }
5345
5346 goto int13_success;
5347 break;
5348
5349 case 0x45: // IBM/MS lock/unlock drive
5350 if (GET_AL() > 2) goto int13_fail;
5351
5352 locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
5353
5354 switch (GET_AL()) {
5355 case 0 : // lock
5356 if (locks == 0xff) {
5357 SET_AH(0xb4);
5358 SET_AL(1);
5359 goto int13_fail_noah;
5360 }
5361 write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
5362 SET_AL(1);
5363 break;
5364 case 1 : // unlock
5365 if (locks == 0x00) {
5366 SET_AH(0xb0);
5367 SET_AL(0);
5368 goto int13_fail_noah;
5369 }
5370 write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
5371 SET_AL(locks==0?0:1);
5372 break;
5373 case 2 : // status
5374 SET_AL(locks==0?0:1);
5375 break;
5376 }
5377 goto int13_success;
5378 break;
5379
5380 case 0x46: // IBM/MS eject media
5381 locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
5382
5383 if (locks != 0) {
5384 SET_AH(0xb1); // media locked
5385 goto int13_fail_noah;
5386 }
5387 // FIXME should handle 0x31 no media in device
5388 // FIXME should handle 0xb5 valid request failed
5389
5390 // Call removable media eject
5391 ASM_START
5392 push bp
5393 mov bp, sp
5394
5395 mov ah, #0x52
5396 int 15
5397 mov _int13_cdrom.status + 2[bp], ah
5398 jnc int13_cdrom_rme_end
5399 mov _int13_cdrom.status, #1
5400 int13_cdrom_rme_end:
5401 pop bp
5402 ASM_END
5403
5404 if (status != 0) {
5405 SET_AH(0xb1); // media locked
5406 goto int13_fail_noah;
5407 }
5408
5409 goto int13_success;
5410 break;
5411
5412 case 0x48: // IBM/MS get drive parameters
5413 size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
5414
5415 // Buffer is too small
5416 if(size < 0x1a)
5417 goto int13_fail;
5418
5419 // EDD 1.x
5420 if(size >= 0x1a) {
5421 Bit16u cylinders, heads, spt, blksize;
5422
5423 blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
5424
5425 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
5426 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media change, lockable, max values
5427 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff);
5428 write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
5429 write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
5430 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); // FIXME should be Bit64
5431 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
5432 write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
5433 }
5434
5435 // EDD 2.x
5436 if(size >= 0x1e) {
5437 Bit8u channel, dev, irq, mode, checksum, i;
5438 Bit16u iobase1, iobase2, options;
5439
5440 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
5441
5442 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
5443 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
5444
5445 // Fill in dpte
5446 channel = device / 2;
5447 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
5448 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
5449 irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
5450 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
5451
5452 // FIXME atapi device
5453 options = (1<<4); // lba translation
5454 options |= (1<<5); // removable device
5455 options |= (1<<6); // atapi device
5456 options |= (mode==ATA_MODE_PIO32?1:0<<7);
5457
5458 write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
5459 write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
5460 write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
5461 write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
5462 write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
5463 write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
5464 write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
5465 write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
5466 write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
5467 write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
5468 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
5469
5470 checksum=0;
5471 for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i);
5472 checksum = ~checksum;
5473 write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
5474 }
5475
5476 // EDD 3.x
5477 if(size >= 0x42) {
5478 Bit8u channel, iface, checksum, i;
5479 Bit16u iobase1;
5480
5481 channel = device / 2;
5482 iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
5483 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
5484
5485 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
5486 write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
5487 write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
5488 write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
5489 write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
5490
5491 if (iface==ATA_IFACE_ISA) {
5492 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
5493 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
5494 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
5495 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
5496 }
5497 else {
5498 // FIXME PCI
5499 }
5500 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
5501 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
5502 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
5503 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
5504
5505 if (iface==ATA_IFACE_ISA) {
5506 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
5507 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
5508 write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
5509 }
5510 else {
5511 // FIXME PCI
5512 }
5513 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
5514 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
5515 write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
5516 write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
5517
5518 checksum=0;
5519 for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
5520 checksum = ~checksum;
5521 write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
5522 }
5523
5524 goto int13_success;
5525 break;
5526
5527 case 0x49: // IBM/MS extended media change
5528 // always send changed ??
5529 SET_AH(06);
5530 goto int13_fail_nostatus;
5531 break;
5532
5533 case 0x4e: // // IBM/MS set hardware configuration
5534 // DMA, prefetch, PIO maximum not supported
5535 switch (GET_AL()) {
5536 case 0x01:
5537 case 0x03:
5538 case 0x04:
5539 case 0x06:
5540 goto int13_success;
5541 break;
5542 default :
5543 goto int13_fail;
5544 }
5545 break;
5546
5547 // all those functions return unimplemented
5548 case 0x02: /* read sectors */
5549 case 0x04: /* verify sectors */
5550 case 0x08: /* read disk drive parameters */
5551 case 0x0a: /* read disk sectors with ECC */
5552 case 0x0b: /* write disk sectors with ECC */
5553 case 0x18: /* set media type for format */
5554 case 0x50: // ? - send packet command
5555 default:
5556 BX_INFO("int13_cdrom: unsupported AH=%02x\n", GET_AH());
5557 goto int13_fail;
5558 break;
5559 }
5560
5561 int13_fail:
5562 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
5563 int13_fail_noah:
5564 SET_DISK_RET_STATUS(GET_AH());
5565 int13_fail_nostatus:
5566 SET_CF(); // error occurred
5567 return;
5568
5569 int13_success:
5570 SET_AH(0x00); // no error
5571 int13_success_noah:
5572 SET_DISK_RET_STATUS(0x00);
5573 CLEAR_CF(); // no error
5574 return;
5575 }
5576
5577 // ---------------------------------------------------------------------------
5578 // End of int13 for cdrom
5579 // ---------------------------------------------------------------------------
5580
5581 #if BX_ELTORITO_BOOT
5582 // ---------------------------------------------------------------------------
5583 // Start of int13 for eltorito functions
5584 // ---------------------------------------------------------------------------
5585
5586 void
5587 int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
5588 Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS;
5589 {
5590 Bit16u ebda_seg=read_word(0x0040,0x000E);
5591
5592 BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
5593 // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI);
5594
5595 switch (GET_AH()) {
5596
5597 // FIXME ElTorito Various. Should be implemented
5598 case 0x4a: // ElTorito - Initiate disk emu
5599 case 0x4c: // ElTorito - Initiate disk emu and boot
5600 case 0x4d: // ElTorito - Return Boot catalog
5601 BX_PANIC("Int13 eltorito call with AX=%04x. Please report\n",AX);
5602 goto int13_fail;
5603 break;
5604
5605 case 0x4b: // ElTorito - Terminate disk emu
5606 // FIXME ElTorito Hardcoded
5607 write_byte(DS,SI+0x00,0x13);
5608 write_byte(DS,SI+0x01,read_byte(ebda_seg,&EbdaData->cdemu.media));
5609 write_byte(DS,SI+0x02,read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive));
5610 write_byte(DS,SI+0x03,read_byte(ebda_seg,&EbdaData->cdemu.controller_index));
5611 write_dword(DS,SI+0x04,read_dword(ebda_seg,&EbdaData->cdemu.ilba));
5612 write_word(DS,SI+0x08,read_word(ebda_seg,&EbdaData->cdemu.device_spec));
5613 write_word(DS,SI+0x0a,read_word(ebda_seg,&EbdaData->cdemu.buffer_segment));
5614 write_word(DS,SI+0x0c,read_word(ebda_seg,&EbdaData->cdemu.load_segment));
5615 write_word(DS,SI+0x0e,read_word(ebda_seg,&EbdaData->cdemu.sector_count));
5616 write_byte(DS,SI+0x10,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.cylinders));
5617 write_byte(DS,SI+0x11,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.spt));
5618 write_byte(DS,SI+0x12,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.heads));
5619
5620 // If we have to terminate emulation
5621 if(GET_AL() == 0x00) {
5622 // FIXME ElTorito Various. Should be handled accordingly to spec
5623 write_byte(ebda_seg,&EbdaData->cdemu.active, 0x00); // bye bye
5624 }
5625
5626 goto int13_success;
5627 break;
5628
5629 default:
5630 BX_INFO("int13_eltorito: unsupported AH=%02x\n", GET_AH());
5631 goto int13_fail;
5632 break;
5633 }
5634
5635 int13_fail:
5636 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
5637 SET_DISK_RET_STATUS(GET_AH());
5638 SET_CF(); // error occurred
5639 return;
5640
5641 int13_success:
5642 SET_AH(0x00); // no error
5643 SET_DISK_RET_STATUS(0x00);
5644 CLEAR_CF(); // no error
5645 return;
5646 }
5647
5648 // ---------------------------------------------------------------------------
5649 // End of int13 for eltorito functions
5650 // ---------------------------------------------------------------------------
5651
5652 // ---------------------------------------------------------------------------
5653 // Start of int13 when emulating a device from the cd
5654 // ----------------------------