source: trunk/BOOTCODE/REGULAR/DRIVEIO.ASM@ 30

Last change on this file since 30 was 30, checked in by Ben Rietbroek, 14 years ago

AiR-BOOT v1.07 -- As released with eCS v2.1. [2011-05-06]
Signature-date: 2006-03-13. (incorrect)
Trunk contains buildable v1.07 version as distributed with eCS v2.1.
Directory 'tags' contains v1.06 & v1.07 reference versions
built for all languages. Note that language ID for 'Dutch' changed
from 'DT' to 'NL' in v1.07 and that the v1.06 reference version also
uses 'NL' for 'Dutch'.
Also note that helper programs like the installer and setaboot are
are only modified for the OS/2 versions in v1.07.
The signature-date for v1.07 incorrectly states the same
date as for v1.06. The signature-version is correct.
Removed other binaries. (cd-rom images, old releases, etc.)
The tags serve as reference versions:

  • v1.06: rebuilt from source. (tags/v1.06r)
  • v1.07: built as released with eCS v2.1. (tags/v1.07r)
File size: 40.0 KB
Line 
1; AiR-BOOT (c) Copyright 1998-2008 M. Kiewitz
2;
3; This file is part of AiR-BOOT
4;
5; AiR-BOOT is free software: you can redistribute it and/or modify it under
6; the terms of the GNU General Public License as published by the Free
7; Software Foundation, either version 3 of the License, or (at your option)
8; any later version.
9;
10; AiR-BOOT is distributed in the hope that it will be useful, but WITHOUT ANY
11; WARRANTY: without even the implied warranty of MERCHANTABILITY or FITNESS
12; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13; details.
14;
15; You should have received a copy of the GNU General Public License along with
16; AiR-BOOT. If not, see <http://www.gnu.org/licenses/>.
17;
18;---------------------------------------------------------------------------
19; AiR-BOOT / DRIVE I/O
20;---------------------------------------------------------------------------
21
22
23
24IFDEF ModuleNames
25DB 'DRIVEIO',0
26ENDIF
27
28; Note: Some routines set DS/ES to CS or even address via CS, even if its not
29; needed. This was done for SECURITY. So DO NOT remove it.
30; Its there to make sure the correct data is loaded/written to/from
31; harddrive.
32;
33; IF YOU MODIFY ANYTHING IN HERE, YOU MAY EASILY BREAK YOUR HARDDRIVE!
34
35; Will only load base-configuration, will NOT load IPT nor Hide-Config
36; Those are originally loaded on startup and will NOT get reloaded.
37DriveIO_LoadConfiguration Proc Near Uses ax bx cx dx es
38 mov ax, cs
39 mov es, ax
40 mov bx, offset Configuration
41 mov dx, 0080h ; First harddrive, Sector 55...
42 mov cx, 0037h
43 mov ax, 0201h ; Function 02, read 1 sector...
44 int 13h
45 jnc DIOLC_NoError
46 call MBR_LoadError ; Will Abort BootUp
47 DIOLC_NoError:
48 ret
49DriveIO_LoadConfiguration EndP
50
51DriveIO_SaveConfiguration Proc Near Uses ax bx cx dx ds es si
52 mov ax, cs
53 mov ds, ax
54 mov es, ax ; Safety first (CS==DS==ES)
55 ; --- Overwrite Floppy-Name with "FloppyDrive"
56 mov si, offset TXT_Floppy_Drive
57 mov di, offset PartitionTable
58 sub di, 30 ; Adjust to Floppy-Name
59 mov cx, 11
60 rep movsb
61 mov si, offset Configuration ; Calculate new checksum
62 xor bx, bx
63 mov cx, 5 ; Total of 5 Config-Sectors
64 mov dx, [CFG_CheckConfig]
65 mov [CFG_CheckConfig], bx
66 DIOSC_Loop:
67 call MBR_GetCheckOfSector
68 loop DIOSC_Loop
69 mov [CFG_CheckConfig], bx
70 ; --------------------------------------------------------------------
71 ; ES == CS
72 mov bx, offset Configuration
73 mov dx, 0080h ; First harddrive, Sector 55...
74 mov cx, 0037h
75 mov ax, 0305h ; Function 03, 5 sectors to write
76 int 13h
77 jnc DIOSC_NoError
78 call MBR_SaveError ; Will Abort BootUp
79 DIOSC_NoError:
80 ret
81DriveIO_SaveConfiguration EndP
82
83DriveIO_UpdateFloppyName Proc Near Uses bx cx dx ds si es di
84 mov ax, cs
85 mov ds, ax
86 mov es, ax
87
88 mov ah, 00h ; Function 2 - Reset Drive
89 xor dl, dl
90 int 13h
91 xor dx, dx ; Cylinder=0, Head=0
92 mov cx, 1 ; Sector=1, Drive=0
93 mov bx, offset TmpSector ; ES:BX - TmpSector
94 mov ax, 0201h ; Function 2 - Load Sector
95 int 13h
96 jnc DIOUFN_AllFine
97
98 ; --- Overwrite Floppy-Name with "No Disc"
99 mov si, offset TXT_Floppy_NoDisc
100 xor ax, ax
101 DIOUFN_WriteFloppyName:
102 mov di, offset PartitionTable
103 sub di, 30 ; Adjust to Floppy-Name
104 mov cl, 11
105 rep movsb
106 ret ; AX=-1 -> GotDisc, =0 -> NoDisc
107
108 ; --- Floppy found and read, data in TempSector
109 DIOUFN_AllFine:
110 mov ax, -1
111 mov si, offset TXT_Floppy_NoName
112 cmp wptr es:[bx+54], 'AF'
113 jne DIOUFN_WriteFloppyName
114 cmp wptr es:[bx+56], '1T'
115 jne DIOUFN_WriteFloppyName
116 cmp bptr es:[bx+58], '2'
117 jne DIOUFN_WriteFloppyName
118 mov si, bx
119 add si, 43 ; FAT12 - Volume Label Location
120 jmp DIOUFN_WriteFloppyName
121DriveIO_UpdateFloppyName EndP
122
123; =============================================================================
124; HARDDRIVE / GENERAL ACCESS
125; =============================================================================
126; The following routines are used for harddisc/floppy access.
127; The access is done via INT 13h/CHS or INT 13h/LBA.
128; Access will be done prefered by INT 13h/CHS, because it's (I wonder!) much
129; faster, than the LBA-method. I don't know, why LBA is so slow. Perhaps BIOS.
130;
131; Internal access (to AiR-BOOT) is always done via INT 13h/CHS.
132
133DriveIO_GetHardDriveCount Proc Near Uses ds si
134 push ds si
135 push 0040h
136 pop ds
137 mov si, 0075h
138 mov dh, ds:[si] ; 40:75 -> POST: Total Harddiscs == DL
139 pop si ds
140 mov TotalHarddiscs, dh
141 ret
142DriveIO_GetHardDriveCount EndP
143
144
145; Fills our LBA-Usage table. It holds the LBA-address, where BIOS/CHS access is
146; stopped and BIOS/LBA access is started.
147; This is calculated by Sector*Heads. Comparing will get done with Bit 25-10
148; on LBA sectors, so we actually divide sector number by 1024.
149DriveIO_InitLBASwitchTable Proc Near Uses es di ; Rousseau: LBA !
150 mov di, offset LBASwitchTable
151 mov dh, TotalHarddiscs
152 mov dl, 80h
153 DIOILUT_DriveLoop:
154 push dx di
155 mov ah, 08h
156 int 13h ; DISK - GET DRIVE PARAMETERS
157 mov ah, 0FBh ; Assume 255 heads/63 sectors, if error
158 jc DIOILUT_Error
159 and cl, 111111b ; Isolate lower 6 bits of CL -> sector count
160
161 ; huge disk 127 sec/track on <1TB using DANI
162; mov cl, 07Fh
163
164 ;movzx ax, cl
165 mov al,cl
166 mov ah,0
167
168 mov bl, dh ; DH -> head count ; Rousseau: nope, it's max head number !
169 mul bl ; AX = Sectors*Heads
170 shl ah, 1
171 shl ah, 1 ; Shift 2 bits, so we are able to compare to
172 ; bit 16-23 of the LBA address
173 DIOILUT_Error:
174 pop di dx
175 mov bptr ds:[di], ah ; Save that value
176 inc di ; Go to next BYTE
177 inc dl
178 dec dh
179 jnz DIOILUT_DriveLoop
180 ret
181DriveIO_InitLBASwitchTable EndP
182
183
184
185
186; Adjusts BX:AX / CX:DX to meet LVM sector location
187; Destroys SI
188; Rousseau: Enhanced to handle sector-numbers 127 and 255 besides 63 for LVM-info sectors.
189; Ugly, need to cleanup.
190DriveIO_LVMAdjustToInfoSector Proc Near Uses ; Rousseau: LVM stuff !
191
192
193
194; pusha
195; call AuxIO_TeletypeNL
196
197 ; LBA
198; xchg dx,bx
199; call AuxIO_TeletypeHexDWord
200; call AuxIO_TeletypeNL
201; xchg bx,dx
202
203 ; CYL
204; mov al,ch
205; call AuxIO_TeletypeHexByte
206; call AuxIO_TeletypeNL
207
208 ; HEAD
209; mov al,dh
210; call AuxIO_TeletypeHexByte
211; call AuxIO_TeletypeNL
212
213 ; SEC
214; mov al,cl
215; call AuxIO_TeletypeHexByte
216; call AuxIO_TeletypeNL
217
218 ; DRIVE
219; mov al,dl
220; call AuxIO_TeletypeHexByte
221; call AuxIO_TeletypeNL
222
223; popa
224
225
226 ;local ts:word
227 ;local ts2:word
228
229 pusha
230
231 ; Dump drive
232 mov si,offset drive
233 call AuxIO_Print
234 xchg al,dl
235 call AuxIO_TeletypeHexByte
236 call AuxIO_TeletypeNL
237 xchg dl,al
238
239 ; Dump SPT
240 mov si,offset spt_used
241 call AuxIO_Print
242 push dx
243 push bx
244 xor dh,dh
245 and dl,01111111b
246 shl dx,1
247 shl dx,1
248 mov bx, offset TrueSecs
249 add bx,dx
250 mov ax,word ptr [bx]
251
252 ;mov [ts],ax
253
254 call AuxIO_TeletypeHexWord
255 call AuxIO_TeletypeNL
256 pop bx
257 pop dx
258
259 pusha
260 push dx
261 ; Location of extended position
262 mov dx,word ptr [ExtendedAbsPos+02]
263 mov ax,word ptr [ExtendedAbsPos+00]
264 call AuxIO_TeletypeHexDWord
265 call AuxIO_TeletypeNL
266 pop dx
267
268 xor dh,dh
269 and dl,01111111b
270 shl dx,1
271 shl dx,1
272 mov bx, offset TrueSecs
273 add bx,dx
274
275 mov ax, word ptr[bx]
276 call AuxIO_TeletypeHexWord
277 call AuxIO_TeletypeNL
278 mov al,[ExtendedAbsPosSet] ; if true -> 1st sector of extpart (EBR), not logpart(BPB)
279 call AuxIO_TeletypeHexByte
280 call AuxIO_TeletypeNL
281 ; mov si,offset PartitionSector
282 ; call AuxIO_DumpSector
283 popa
284
285 ; LBA
286 mov si,offset before_lvm_adjust
287 call AuxIO_Print
288
289 xchg dx,bx
290 call AuxIO_TeletypeHexDWord
291 call AuxIO_TeletypeNL
292 xchg bx,dx
293 popa
294
295
296 ;or bx,ax
297 test [ExtendedAbsPosSet],1
298 jz pri
299
300
301
302
303 pusha
304 mov si,offset before_lvm_adjust_log
305 call AuxIO_Print
306 ; LBA
307 xchg dx,bx
308 call AuxIO_TeletypeHexDWord
309 call AuxIO_TeletypeNL
310 xchg bx,dx
311 popa
312
313
314 push dx
315 push bx
316 xor dh,dh
317 and dl,01111111b
318 shl dx,1
319 shl dx,1
320 mov bx,offset TrueSecs
321 add bx,dx
322 mov dx,[bx]
323 dec dx
324 add ax,dx
325 pop bx
326 pop dx
327 adc bx,0
328
329
330 pusha
331 mov si,offset after_lvm_adjust_log
332 call AuxIO_Print
333 ; LBA
334 xchg dx,bx
335 call AuxIO_TeletypeHexDWord
336 call AuxIO_TeletypeNL
337 xchg bx,dx
338 popa
339
340 jmp done
341
342
343
344
345pri:
346
347
348 push ax
349 push cx
350 xor ch, ch ; Zero out upper-byte
351
352 push dx
353 xor dh,dh
354 and dl,01111111b
355 shl dx,1
356 shl dx,1
357 push bx
358 mov bx,offset TrueSecs
359 add bx,dx
360 mov ax,[bx]
361 ;mov [ts2],ax
362 pop bx
363 pop dx
364
365
366
367 ;mov al, 63
368 ;call VideoIO_PrintByteDynamicNumber
369 ;self: jmp self
370
371
372
373 ; DEZE WERKT SOMS NIET GOED
374 ; ROMMELT MET CYLINDERS
375 ; ALLEEN TOEPASSEN ALS INT13X NIET ACTIEF !
376
377 and cl, al ; Isolate lower bits, because upper
378 mov ah, 0
379 mov si, ax ; ones may be used for cylinder
380 sub si, cx
381
382 pop cx
383 pop ax
384
385 or cl, al ; Set sector to last sector
386
387 add ax, si ; Adjust lower LBA
388 adc bx, 0 ; Adjust LBA Sector (BX:AX)
389
390
391
392 ;push ax
393 ;call AuxIO_TeletypeHexWord
394 ;call AuxIO_TeletypeNL
395 ;mov ax,[ts]
396 ;call AuxIO_TeletypeHexWord
397 ;call AuxIO_TeletypeNL
398 ;mov ax,[ts2]
399 ;call AuxIO_TeletypeHexWord
400 ;call AuxIO_TeletypeNL
401 ;pop ax
402
403 ;and ax,[ts]
404
405 jmp done
406
407
408
409done:
410
411
412
413 pusha
414 mov si,offset after_lvm_adjust
415 call AuxIO_Print
416 ; LBA
417 xchg dx,bx
418 call AuxIO_TeletypeHexDWord
419 call AuxIO_TeletypeNL
420 xchg bx,dx
421 popa
422
423
424
425; pusha
426; call AuxIO_TeletypeNL
427
428 ; CYL
429; mov al,ch
430; call AuxIO_TeletypeHexByte
431; call AuxIO_TeletypeNL
432
433 ; HEAD
434; mov al,dh
435; call AuxIO_TeletypeHexByte
436; call AuxIO_TeletypeNL
437
438 ; SEC
439; mov al,cl
440; call AuxIO_TeletypeHexByte
441; call AuxIO_TeletypeNL
442
443 ; DRIVE
444; mov al,dl
445; call AuxIO_TeletypeHexByte
446; call AuxIO_TeletypeNL
447
448; popa
449
450
451
452 ret
453DriveIO_LVMAdjustToInfoSector EndP
454
455drive: db 'drive : ',0
456before_lvm_adjust: db 'before lvm adjust : ',0
457after_lvm_adjust: db 'after lvm adjust : ',0
458before_lvm_adjust_log: db 'before lvm logical adjust: ',0
459after_lvm_adjust_log: db 'after lvm logical adjust : ',0
460spt_used: db 'spt used : ',0
461
462
463
464; #########################################################################
465; Routine: Loads partition to ExecBase and checks for validity
466; #########################################################################
467; Calling : bx:ax - Absolute sector
468; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
469; Returns : Carry Set if invalid partition encountered
470; Preserve: all registers
471; #########################################################################
472DriveIO_LoadPartition Proc Near Uses si
473 mov wptr cs:[CurPartition_Location+0], ax
474 mov wptr cs:[CurPartition_Location+2], bx
475 mov wptr cs:[CurPartition_Location+4], dx
476 mov wptr cs:[CurPartition_Location+6], cx ; Saves the location
477 mov si, offset PartitionSector ; DS:SI - ExecBase
478 call DriveIO_LoadSector
479 clc
480 cmp wptr [si+LocBR_Magic], 0AA55h
481 je DIOLP_Success
482 ; We check, if we are scanning partitions. In that case, if CHS is not 0/0/1
483 ; we will display a "bad partition table" message and halt the system.
484 cmp cx, 0001h
485 jne DIOLP_Failed
486 or dh, dh
487 jnz DIOLP_Failed
488 stc ; Set carry, so no partition table
489 DIOLP_Success:
490
491IFDEF AuxDebug
492 ; show current partition location
493 pushf
494 pusha
495 call AuxIO_TeletypeNL
496 mov si,offset db_curpartloc
497 call AuxIO_Print
498 mov dx,word ptr [CurPartition_Location+02]
499 mov ax,word ptr [CurPartition_Location+00]
500 call AuxIO_TeletypeHexDWord
501 call AuxIO_TeletypeNL
502 mov si,offset PartitionSector
503 call AuxIO_DumpSector
504 call AuxIO_TeletypeNL
505 popa
506 popf
507ENDIF
508
509 ret
510 DIOLP_Failed:
511 jmp DriveIO_GotLoadError
512DriveIO_LoadPartition EndP
513
514; #########################################################################
515; Routine: Writes a partition from ExecBase to its original sector
516; #########################################################################
517; Calling : none
518; Returns : none
519; Preserve: all registers
520; #########################################################################
521DriveIO_SavePartition Proc Near Uses ax bx cx dx si
522 mov ax, wptr cs:[CurPartition_Location+0]
523 mov bx, wptr cs:[CurPartition_Location+2]
524 mov dx, wptr cs:[CurPartition_Location+4]
525 mov cx, wptr cs:[CurPartition_Location+6] ; Gets prev. saved location
526 mov si, offset PartitionSector ; DS:SI - ExecBase
527 cmp wptr [si+LocBR_Magic], 0AA55h ; Checks for signature, if not found
528 jne DIOSP_SevereError ; we assume a really bad error
529 call DriveIO_SaveSector
530 DIOSP_SevereError:
531 ret
532DriveIO_SavePartition EndP
533
534; Keeps DS:SI for caller
535DriveIO_LoadTmpSector Proc Near Uses
536 mov si, offset TmpSector
537 call DriveIO_LoadSector ; Uses INT13X if needed
538 ret
539DriveIO_LoadTmpSector EndP
540
541; Keeps DS:SI for caller
542DriveIO_SaveTmpSector Proc Near Uses
543 mov si, offset TmpSector
544 call DriveIO_SaveSector
545 ret
546DriveIO_SaveTmpSector EndP
547
548; Keeps DS:SI for caller, sets carry if valid LVM sector encountered
549DriveIO_LoadLVMSector Proc Near Uses ax bx cx dx
550 test [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
551 jnz DIOLLVMS_NoLVMSector ; don't load but declare as bad!
552 mov ax, wptr cs:[CurPartition_Location+0]
553 mov bx, wptr cs:[CurPartition_Location+2]
554 mov dx, wptr cs:[CurPartition_Location+4]
555 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
556
557 call DriveIO_LVMAdjustToInfoSector ; Rousseau: LVM stuff !
558
559 mov si, offset LVMSector
560 call DriveIO_LoadSector
561
562IFDEF AuxDebug
563 ; show current partition location
564 pushf
565 pusha
566 call AuxIO_TeletypeNL
567 mov si,offset db_curlvmsec
568 call AuxIO_Print
569 mov dx,bx
570 call AuxIO_TeletypeHexDWord
571 call AuxIO_TeletypeNL
572 mov si,offset LVMSector
573 call AuxIO_DumpSector
574 call AuxIO_TeletypeNL
575 popa
576 popf
577ENDIF
578
579 ; Rousseau
580 ;pushf
581 ;pusha
582 ;mov si, offset MyText4
583 ;call VideoIO_Print
584 ;mov si, offset LVMSector
585 ;mov al, [si+LocLVM_VolumeLetter2]
586 ;call VideoIO_PrintByteDynamicNumber
587 ;mov al, [si+LocLVM_Startable]
588 ;call VideoIO_PrintByteDynamicNumber
589 ;mov al, [si+LocLVM_OnBootMenu]
590 ;call VideoIO_PrintByteDynamicNumber
591 ;;self: jmp self
592 ;popa
593 ;popf
594
595 call LVM_CheckSectorSignature ; Rousseau: LVM stuff !
596 jnc DIOLLVMS_NoLVMSector
597 call LVM_CheckSectorCRC ; Rousseau: LVM stuff !
598 jnc DIOLLVMS_NoLVMSector
599 ret
600 ; This here is called, if an invalid (or no) LVM information sector is found
601 ; It will truncate the first byte of the sector, so all other routines
602 ; will notice it easily by just comparing the first byte.
603 DIOLLVMS_NoLVMSector:
604 mov bptr [si+LocLVM_SignatureStart], 0
605 ret
606DriveIO_LoadLVMSector EndP
607
608; Keeps DS:SI for caller, saves at anytime w/o checks (!)
609DriveIO_SaveLVMSector Proc Near Uses ax bx cx dx
610 test [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
611 jnz DIOSLVMS_SevereError ; don't save at anytime (security!)
612 mov ax, wptr cs:[CurPartition_Location+0]
613 mov bx, wptr cs:[CurPartition_Location+2]
614 mov dx, wptr cs:[CurPartition_Location+4]
615 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
616 call LVM_CheckSectorSignature
617 jnc DIOSLVMS_SevereError ; LVM Signature must be there
618 call DriveIO_LVMAdjustToInfoSector
619 mov si, offset LVMSector
620 call DriveIO_SaveSector
621 DIOSLVMS_SevereError:
622 ret
623DriveIO_SaveLVMSector EndP
624
625; Memory-Block that holds information for LBA-access via INT 13h
626DriveIO_DAP: db 10h ; Size of paket
627 db 0 ; Reserved
628DriveIO_DAP_NumBlocks dw 0 ; Number of blocks
629DriveIO_DAP_Transfer dd 0 ; Transfer Adress
630DriveIO_DAP_Absolute dd 0 ; Absolute Sector
631 dd 0 ; Second Part of QWORD
632
633; Special error message instead of "LOAD ERROR" during partition scanning,
634; so users will notice that something is bad with their partition table(s)
635DriveIO_GotLoadError Proc Near
636 test cs:CurIO_Scanning, 1 ; Must be CS:, cause DS!=CS maybe here
637 jnz InScanMode
638 jmp MBR_LoadError
639 InScanMode:
640 mov si, offset TXT_BrokenPartitionTable
641 push cs
642 pop ds
643 call MBR_Teletype
644 mov si, offset BrokenHDD
645 sub dl, 50h ; 80h -> '0'
646 cmp dl, 39h
647 jbe DIOGLE_BelowA
648 add dl, 7 ; 3Ah -> 'A'
649 DIOGLE_BelowA:
650 mov bptr [si+5], dl
651 call MBR_Teletype
652 jmp MBRLE_Halt
653DriveIO_GotLoadError EndP
654
655; #########################################################################
656; Routine: Loads a specified sector to DS:DI
657; #########################################################################
658; Calling : bx:ax - Absolute sector
659; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
660; ds:si - Destination-Adress
661; Returns : none
662; Preserve: all registers
663; #########################################################################
664DriveIO_LoadSector Proc Near Uses ax bx ds si es di ; Rousseau: Disk IO
665 test cs:[CurIO_UseExtension], 1
666 jz DIOLS_UseNormal
667 ; Are we forced do use LBA via Setting?
668 test cs:[CFG_ForceLBAUsage], 1 ; Rousseau: LBA
669 jnz DIOLS_UseExtension
670 ; Is the drive not a harddrive?
671 cmp dl, 80h
672 jb DIOLS_UseNormal
673 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
674 or bh, bh
675 jnz DIOLS_UseExtension
676 ; Compare Switch-Table value to bit 16-23 of LBA-address
677 mov di, dx
678 and di, 007Fh
679 cmp bptr cs:[LBASwitchTable+di], bl
680 jbe DIOLS_UseExtension
681 DIOLS_UseNormal:
682 mov di, 3
683 DIOLS_ErrorLoop:
684 push ds
685 pop es
686 mov bx, si ; ES:BX - Destination
687 mov ax, 0201h ; Function 2 - Load Sector ; Rousseau: Disk IO -- legacy BIOS call
688 int 13h
689 jnc DIOLS_Success
690 dec di
691 jnz DIOLS_ErrorLoop
692 ; Sector load failed...
693 jmp DriveIO_GotLoadError
694
695 DIOLS_UseExtension:
696 push cx
697 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
698 mov wptr cs:[DriveIO_DAP_Transfer+0], si
699 mov cx, ds
700 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
701 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
702 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
703 push cs
704 pop ds
705 mov si, offset DriveIO_DAP
706 mov ah, 42h ; Extended Read ; Rousseau: Disk IO -- extended BIOS call
707 int 13h
708 pop cx
709 jnc DIOLS_Success
710 ; Sector load failed...
711 jmp DriveIO_GotLoadError
712
713 DIOLS_Success:
714 ret
715DriveIO_LoadSector EndP
716
717; #########################################################################
718; Routine: Writes DS:SI to a specified sector
719; #########################################################################
720; Calling : bx:ax - Absolute sector
721; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
722; ds:si - Source-Adress
723; Returns : none
724; Preserve: all registers
725; #########################################################################
726DriveIO_SaveSector Proc Near Uses ax bx cx ds si es di
727 test cs:[CurIO_UseExtension], 1
728 jz DIOSS_UseNormal
729 ; Are we forced do use LBA via Setting?
730 test cs:[CFG_ForceLBAUsage], 1 ; Rousseau: LBA
731 jnz DIOSS_UseExtension
732 ; Is the drive not a harddrive?
733 cmp dl, 80h
734 jb DIOSS_UseNormal
735 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
736 or bh, bh
737 jnz DIOSS_UseExtension
738 ; Compare Switch-Table value to bit 16-23 of LBA-address
739 mov di, dx
740 and di, 007Fh
741 cmp bptr cs:[LBASwitchTable+di], bl
742 jbe DIOSS_UseExtension
743 DIOSS_UseNormal:
744 mov di, 3
745 DIOSS_ErrorLoop:
746 push ds
747 pop es
748 mov bx, si ; ES:BX - Destination
749 mov ax, 0301h ; Function 3 - Write Sector
750 int 13h
751 jnc DIOSS_Success
752 dec di
753 jnz DIOSS_ErrorLoop
754 call MBR_SaveError
755
756 DIOSS_UseExtension:
757 push cx
758 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
759 mov wptr cs:[DriveIO_DAP_Transfer+0], si
760 mov cx, ds
761 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
762 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
763 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
764 push cs
765 pop ds
766 mov si, offset DriveIO_DAP
767 mov ax, 4300h ; Extended Write (No Verify)
768 int 13h
769 pop cx
770 jnc DIOSS_Success
771 call MBR_SaveError
772
773 DIOSS_Success:
774 ret
775DriveIO_SaveSector EndP
776
777
778; See if a LVM-sector is valid.
779; In : si, pointer to sector
780; Out : ZF=true, not valid; ZF=false, valid
781DriveIO_LVMSectorValid Proc Near
782 pusha
783
784 call LVM_CheckSectorSignature
785 mov al,0
786 rcl al,1 ; Move CY to AL.0
787 call AuxIO_TeletypeHexByte
788 call AuxIO_TeletypeNL
789 or al,al ; Zero if not a valid sector
790 jz DriveIO_LVMSectorValid_End ; Not a valid sector
791
792 call LVM_CheckSectorCRC
793 stc
794 mov al,0
795 rcl al,1 ; Move CY to AL.0
796 call AuxIO_TeletypeHexByte
797 call AuxIO_TeletypeNL
798 or al,al ; Zero if not a valid sector
799
800 DriveIO_LVMSectorValid_End:
801
802 popa
803 ret
804DriveIO_LVMSectorValid EndP
805
806; ------------------------------------------------------
807; Rousseau: # Load the master LVM-sector is one exists #
808; ------------------------------------------------------
809; Load the master LVM-sector to get the number of sectors per track as eCS views the drive.
810; If no master LVM-sector is found it is assumed eCS is not installed.
811; The master LVM-sector can be located at three different places according to drive size
812; and partitioning scheme and driver used.
813; When DANIS506.ADD is used, the eCS extended geometry will be 255/127 for drives >502GiB but <1TiB.
814; Then the location will be sector 127 which is LBA 126 (7Eh).
815; IBM1S506.ADD will always use 255/255 for the extended eCS geometry.
816; DANIS506.ADD will use 255/255 for drives >1TiB.
817; Then the location of the master LVM-sector will be 255 which is LBA 254 (FEh).
818; When eCS is installed on a huge drive that alread had a system on it, eCS will be confined to the
819; lower 502GiB of the drive. In this case the normal geometry from Int13X will be used.
820; This is also the case when no valid master LVM-sector can be found.
821;
822; Return ZF=true if not found, ZF=false when valid master LVM-sector found.
823DriveIO_LoadMasterLVMSector Proc Near
824 pusha
825
826 mov si,offset db_lmlvm
827 ;call AuxIO_Print
828
829 mov al,dl
830 ;call AuxIO_TeletypeHexByte
831 ;call AuxIO_TeletypeNL
832
833
834 ; Loop over the sector-translation table,
835 ; process the first three values from high (255) to low (bios spt, most likely 63)
836 mov cx,3
837DriveIO_LoadMasterLVMSector_NextTry:
838 mov bx,offset secs_per_track_table ; sector translation table that corresponds with IsHugeDrive
839 mov si, offset LVMSector ; space to load the master LVM-sector
840 mov [DriveIO_DAP_NumBlocks],1 ; number of sectors to read
841 mov wptr [DriveIO_DAP_Transfer+0],si ; low part of transfer address
842 mov ax, ds
843 mov wptr [DriveIO_DAP_Transfer+2],ax ; high part of transfer address
844 mov ax,cx ; use the counter...
845 dec ax ; as an index into the table
846 xlatb ; translate to number of sectors
847 dec al ; LBA is zero-based, so adjust
848
849IFDEF AuxDebug
850 ; Dump the value
851 ;call AuxIO_TeletypeHexByte
852 ;call AuxIO_TeletypeNL
853ENDIF
854
855 mov wptr [DriveIO_DAP_Absolute+0],ax ; LBA low ;
856 mov wptr [DriveIO_DAP_Absolute+2],00h ; LBA high
857 mov si, offset DriveIO_DAP ; address request packet
858 mov ah, 42h
859 int 13h ; do the i/o
860 jc DriveIO_LoadMasterLVMSector_NotFound ; oops, there was an error
861
862IFDEF AuxDebug
863 ; Dump title
864 mov si,offset db_masterlvm
865 ;call AuxIO_Print
866
867 ; Dum sector
868 mov si, offset LVMSector
869 ;call AuxIO_DumpSector
870 ;call AuxIO_TeletypeNL
871ENDIF
872 ; See is this is a valid LVM-sector
873 call DriveIO_LVMSectorValid
874
875IFDEF AuxDebug
876 pushf
877 ;call AuxIO_TeletypeNL
878 popf
879ENDIF
880 ; Yep, we found the master LVM-sector
881 jnz DriveIO_LoadMasterLVMSector_Found
882 ; Try next location
883 loop DriveIO_LoadMasterLVMSector_NextTry
884
885 ; No master LVM-sector found, set ZF=true
886 DriveIO_LoadMasterLVMSector_NotFound:
887 xor ax,ax
888
889 ; Jump here with ZF=false if found
890 DriveIO_LoadMasterLVMSector_Found:
891
892 popa
893 ret
894DriveIO_LoadMasterLVMSector Endp
895
896
897
898
899; ---------------------------------------------------
900; Rousseau ## Large drives, (eCS) geometry and LBA ##
901; ---------------------------------------------------
902; A sector size of 512 bytes is assumed in the below calculations.
903; Note that this scheme changes when the sector size will be 4096 or larger,
904; like with modern drives that do not translate to 512 bytes per sector anymore.
905; These drives will have a capacity above the 2TiB LBA32 boundary.
906; For now, we assume drives <=2TiB with a sector size of 512 bytes.
907
908; There are a few boundaries that are of importance.
909; Note that these are disk-boundaries and not partition boundaries.
910; Even with a small partition, like <502GiB, OS/2 will use extended geometry on an
911; empty huge disk.
912; These boundaries are (from high to low):
913
914; (code 5)
915; 2^32 = 4294967296 = 100000000 sectors = 2048 GiB
916; This is the LBA32 2TiB boundary.
917; Everything above it must be addressed using LBA48.
918; OS/2 can currently not address this space above.
919
920; (code4)
921; 65536*255*255 = 4261478400 = FE010000 sectors ~ 2032 GiB
922; This is the max OS/2 boundary using 255/255 extended geometry.
923; OS/2 can currently not address this space above.
924
925; (code 3)
926; 2^31 = 2147483648 = 80000000 sectors = 1024 GiB
927; This is the LBA32 1TiB boundary.
928; OS/2 can address this space and will use 255/255 extended geometry.
929
930; (code 2)
931; 65536*255*127 = 2122383360 = 7E810000 sectors ~ 1012 GiB
932; This is the DANI 1TiB boundary.
933; OS/2 can address this space and will use 255/255 extended geometry.
934; Below this DANI will use 255/127 extended geometry.
935; This matters on where the LVM-sectors are located !
936
937; (code 1)
938; 65536*255*63 = 1052835840 = 3EC10000 sectors ~ 502 GiB
939; This is the current OS/2 limit using this geometry because OS/2 can currently
940; not address more than 65536 cylinders.
941; DANI will address space above with 255/127 extended geometry up until the DANI 1TiB boundary (code 2)
942
943; (code 0)
944; Everything below 65536*255*63 will be addressed using standard geometry.
945
946
947;
948; This function will return the following values:
949;
950
951; 5 = This drive is above the 2^32 LBA32 (2TB) boundary and has more than 4294967296 sectors.
952; LBA48 addressing is needed to access the complete capacity of the drive.
953; OS/2 is currently unable to do so.
954
955; 4 = This drive is above the 65536*255*255 (4261478400) boundary but below 2^32.
956; This is an OS/2 boundary and OS/2 is not able to access the drive above this boundary.
957
958; 3 = This drive is above the 2^31 (1TB) boundary and has more than 2147483648 sectors.
959; OS/2 is able to access the drive using it's extended geometry.
960; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
961
962; 2 = This drive is above the 65536*255*127 (2122383360) boundary but below 2^31.
963; OS/2 is able to access the drive using it's extended geometry.
964; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
965
966; 1 = This drive is above the 65536*255*63 (1052835840) boundary but below 65536*255*127.
967; OS/2 is able to access the drive using it's extended geometry.
968; Note that DANIS506 will use 255/127 and IBM1S506 will use 255/255 geometry !
969; Using DANI or IBM influences the location of the LVM info-sectors !
970
971; 0 = This drive is below the 65536*255*63 (1052835840) boundary.
972; OS/2 is able to access this drive using the standard 255/63 geometry.
973
974; So, any return value >0 means OS/2 extended geometry will be used.
975; Value 1 will use 255/127 with DANIS506 but 255/255 with IBM1S506.
976; Values 2 and 3 will use 255/255 on both drivers.
977; You can or with 0x01 and check for 3 in this case.
978; Any value above 3 will be a drive who's capacity cannot be fully used by OS/2
979; The upper limit of 65536*255*255 will be in effect here.
980
981; Note this function currently handles the boot-drive only !
982; It should be extended and use dl for the drive-number as a parameter.
983; Because we use this function to get this info in a number of places,
984; all regs and flags except AX are saved and restored.
985
986; DL contains BIOS disk-number; 80h for first, 81h for second, etc.
987DriveIO_GatherDiskInfo Proc Near
988 pushf
989 push bx
990 push cx
991 push dx
992 push si
993 push di
994 push es
995
996 ; Set ES to CS for buffer clearing
997 push cs
998 pop es
999
1000 ; Clear the buffer
1001 ; Don't overwrite the word of the buffersize at index 0 !
1002 ; Old Phoenix BIOSses require word (flags) at 02 to be zero,
1003 ; so we clear the whole buffer to be sure.
1004 mov cx, i13xbuf_size
1005 mov di, offset i13xbuf
1006 mov [di],cx
1007 inc di
1008 inc di
1009 xor ah,ah
1010 cld
1011 rep stosb
1012
1013 ; Get the drive parameters
1014 mov ah, 48h ; Get Drive Parameters (extended version)
1015 ;mov dl, 80h ; Drive number
1016 mov si, offset i13xbuf ; Buffer for result-info
1017 push dx
1018 int 13h ; Call the BIOS-function
1019 pop dx
1020
1021 ; Do some error-checking
1022 or ah,ah ; AH is zero if no error (ZF=1 if no error)
1023 mov ax,0 ; Setup code for non-huge drive (does not influence ZF)
1024 jz DriveIO_GatherDiskInfo_ok ; Return if error (AL<>0 thus ZF=0) but CY not set, assuming non-huge drive
1025 jnc DriveIO_GatherDiskInfo_ok ; Return if error (CY=1), assuming non-huge drive
1026 jmp DriveIO_GatherDiskInfo_ret
1027
1028
1029 DriveIO_GatherDiskInfo_ok:
1030
1031 ;
1032 ; Store the drive geometry
1033 ;
1034
1035 mov si, offset i13xbuf
1036
1037 xor dh,dh
1038 and dl,01111111b
1039 shl dx,1
1040 shl dx,1
1041
1042 ; Store number of cylinders on disk
1043 mov bx, offset BIOS_Cyls
1044 add bx,dx
1045 mov ax,[si+04h]
1046
1047 mov word ptr [bx+00],ax
1048 mov ax,[si+06]
1049 mov word ptr [bx+02],ax
1050
1051 ; Store number of heads per cylinder
1052 mov bx, offset BIOS_Heads
1053 add bx,dx
1054 mov ax,[si+08h]
1055 mov word ptr [bx+00],ax
1056 mov ax,[si+0ah]
1057 mov word ptr [bx+02],ax
1058
1059 ; Store number of sectors per track
1060 mov bx, offset BIOS_Secs
1061 add bx,dx
1062 mov ax,[si+0ch]
1063 mov word ptr [bx+00],ax
1064
1065 ; Update first byte of translation-table to conform to BIOS SPT
1066 mov byte ptr [secs_per_track_table], al
1067
1068 mov ax,[si+0eh]
1069 mov word ptr [bx+02],ax
1070
1071 ; Store total secs
1072 mov bx, offset BIOS_TotalSecs
1073 add bx,dx
1074 add bx,dx
1075 mov ax,[si+10h]
1076
1077 mov word ptr [bx+00],ax
1078 mov ax,[si+12h]
1079 mov word ptr [bx+02],ax
1080 mov ax,[si+14h]
1081 mov word ptr [bx+04],ax
1082 mov ax,[si+18h]
1083 mov word ptr [bx+06],ax
1084
1085 ; Store number of bytes per sector
1086 mov bx, offset BIOS_Bytes
1087 add bx,dx
1088 mov ax,[si+18h]
1089 mov [bx],ax
1090
1091
1092 ;
1093 ; See of it's a huge drive of not
1094 ;
1095
1096 ; Drive is larger than 2TiB
1097 mov ax,5 ; Drive code (5)
1098 mov bx, [si+14h] ; Low word of high dword of sector-count
1099 or bx, [si+16h] ; High word of high dword of sector-count
1100 jnz DriveIO_GatherDiskInfo_ret ; If non-zero we have a drive with >2^32 sectors and thus LBA48 addressing
1101
1102 ; Drive is larger than max OS/2 capacity
1103 dec ax ; Drive code (4)
1104 mov bx, [si+12h] ; High word of low dword of sector-count
1105 cmp bx, 0fe01h ; Boundary
1106 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1107 ; we have a drive larger than to 65536*255*255 = FE010000 sectors
1108
1109 ; Drive can be completely utilized by OS/2
1110 dec ax ; Drive code (3)
1111 cmp bx, 8000h ; Boundary
1112 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1113 ; we have a drive larger than 2^31 sectors but smaller than 65536*255*255
1114
1115 ; This is the small area between DANI 1TiB and LBA 1TiB
1116 dec ax ; Drive code (2)
1117 cmp bx, 7e81h ; Boundary
1118 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1119 ; we have a drive larger than 65536*255*127 but <65536*255*255
1120 ; DANIS506.ADD will use 255/255 extended geometry
1121
1122 ; DANI will use 255/127 in this area, this could impact the location of LVM-sectors ! (last sec on track)
1123 dec ax ; Drive code (1)
1124 cmp bx, 3ec1h ; Boundary
1125 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1126 ; we have a drive larger than 65536*255*63 sectors (OS/2 502GiB Limit!)
1127 ; DANIS506.ADD will use 255/127 extended geometry !
1128 ; IBM1S506.ADD will use 255/255 extended geometry !
1129
1130 ; We have a drive that can be addressed using standard 255/63 geometry
1131 dec ax ; Drive code (0)
1132 ; We have a drive smaller than 65536*255*63 = 3EC10000 sectors
1133
1134 DriveIO_GatherDiskInfo_ret:
1135 pop es
1136 pop di
1137 pop si
1138 pop dx
1139 pop cx
1140 pop bx
1141
1142 mov [CurIO_UseExtension],1
1143
1144 popf
1145 ret
1146DriveIO_GatherDiskInfo EndP
1147
1148
1149
1150; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value.
1151secs_per_track_table: db 63,127,255,255,255,255
1152
1153db_lmlvm: db 'Load Master LVM -- disk: ',0
Note: See TracBrowser for help on using the repository browser.