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

Last change on this file since 38 was 38, checked in by Ben Rietbroek, 11 years ago

Converting to JWasm -- phase #1 (not working) [2012-02-15]

WARNING!!

All commits upto and including the commit of [2012-05-13] contain
a severe bug!! Building from these sources and then disabling
the 'force LBA' feature while also using the drive-letter feature or
editing the label can DESTROY THE MBR on ALL ATTACHED DISKS!!
DO NOT DISABLE 'FORCE LBA USAGE' WHEN BUILT FROM THE THESE COMMITS!!

Problems

o WLink generates an oversized image
o Only Tasm with TLink works correctly

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