source: trunk/bootcode/regular/driveio.asm@ 65

Last change on this file since 65 was 57, checked in by Ben Rietbroek, 10 years ago

All source-files lowercased [v1.1.1-testing]

Some standard files like 'COPYING', 'LICENSE', etc. have not been
converted to lower case because they are usually distributed uppercased.

File size: 51.2 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 MODULE_NAMES
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 0 - 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
156 push si
157 push 0040h
158 pop ds
159 mov si, 0075h
160 mov dh, ds:[si] ; 40:75 -> POST: Total Harddiscs == DL
161 pop si
162 pop ds
163 mov [TotalHarddiscs], dh
164 ret
165DriveIO_GetHardDriveCount EndP
166
167
168; Fills our LBA-Usage table. It holds the LBA-address, where BIOS/CHS access is
169; stopped and BIOS/LBA access is started.
170; This is calculated by Sector*Heads. Comparing will get done with Bit 25-10
171; on LBA sectors, so we actually divide sector number by 1024.
172DriveIO_InitLBASwitchTable Proc Near Uses es di
173 mov di, offset LBASwitchTable
174 mov dh, [TotalHarddiscs]
175 mov dl, 80h
176 DIOILUT_DriveLoop:
177 push dx
178 push di
179 mov ah, 08h
180 int 13h ; DISK - GET DRIVE PARAMETERS
181 mov ah, 0FBh ; Assume 255 heads/63 sectors, if error
182 jc DIOILUT_Error
183 and cl, 111111b ; Isolate lower 6 bits of CL -> sector count
184
185 ;movzx ax, cl
186 mov al,cl
187 mov ah,0
188
189 mov bl, dh ; DH -> max head number
190 mul bl ; AX = Sectors*Heads
191 shl ah, 1
192 shl ah, 1 ; Shift 2 bits, so we are able to compare to
193 ; bit 16-23 of the LBA address
194 DIOILUT_Error:
195 pop di
196 pop dx
197 mov bptr ds:[di], ah ; Save that value
198 inc di ; Go to next BYTE
199 inc dl
200 dec dh
201 jnz DIOILUT_DriveLoop
202 ret
203DriveIO_InitLBASwitchTable EndP
204
205
206
207
208;FIXME: Only LBA gets updated, need to update CHS too !!!!!!!
209
210; Adjusts BX:AX / CX:DX to meet LVM sector location
211; BX:AX / CX:DX point to MBR or EBR !
212; Destroys SI
213; Rousseau: Enhanced to handle sector-numbers 127 and 255 besides 63 for LVM-info sectors.
214; Ugly, need to cleanup.
215DriveIO_LVMAdjustToInfoSector Proc Near
216 push cx ; Save Cyl/Sec part
217 xor ch,ch ; Clear low Cyl part
218 and cl,63 ; Clear high Cyl part
219 push bx ; We need BX...
220 push dx ; and DX temoraily
221 mov bx,offset [TrueSecs] ; Offset of sector table
222 xor dh,dh ; Clear DH because we use DL as index
223 and dl,01111111b ; Remove high bit of BIOS disk-nr
224 shl dx,2 ; Index to DWORD table
225 add bx,dx ; Point to TrueSecs for this disk
226 mov si,[bx] ; Get SPT for this disk
227 pop dx ; Restore DX...
228 pop bx ; and BX
229 ;~ sub si,cx ; Adjust offset !! INCORRECT FOR LBA (TP CX != 0 !!)
230 dec si
231 pop cx ; Restore Cyl/Sec part
232 add ax,si ; Add offset to low part...
233 adc bx,0 ; and high part of LBA address
234 or cl,63 ; Adjust CHS part !FIX ME for > 63! !! FIX HUGE DRIVE !!
235 ret
236
237
238;;jmp bliep
239;; pusha
240
241;; push dx
242;; push bx
243;; xor dh,dh
244;; and dl,01111111b
245;; shl dx,1
246;; shl dx,1
247;; mov bx, offset [TrueSecs]
248;; add bx,dx
249;; mov ax,word ptr [bx]
250;; pop bx
251;; pop dx
252
253
254 ;
255 ; AX now contains LVM secs
256 ;
257
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;; mov ax, word ptr[bx]
275
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;;bliep:
297
298 ;or bx,ax
299;; test byte ptr [ExtendedAbsPosSet],1
300;; jz pri
301
302
303;; push dx
304;; push bx
305
306;; xor dh,dh
307;; and dl,01111111b ; Strip high bit from disk
308;; shl dx,1 ; Convert to index
309;; shl dx,1 ; into TrueSecs table
310;; mov bx,offset [TrueSecs] ; Base of table
311;; add bx,dx ; Point to entry for disk
312;; mov dx,[bx] ; Get TrueSecs (LVM)
313;; dec dx
314;; add ax,dx
315
316;; pop bx
317;; pop dx
318;; adc bx,0
319
320
321;; jmp done
322
323
324
325;; pri:
326
327
328;; push ax
329;; push cx
330;; xor ch, ch ; Zero out upper-byte
331
332;; push dx
333;; xor dh,dh
334;; and dl,01111111b
335;; shl dx,1
336;; shl dx,1
337
338;; push bx
339;; mov bx,offset [TrueSecs]
340;; add bx,dx
341;; mov ax,[bx]
342 ;mov [ts2],ax
343;; pop bx
344;; pop dx
345
346
347
348 ;~ mov al, 63
349 ;~ call VideoIO_PrintByteDynamicNumber
350 ;~ self: jmp self
351
352
353
354 ; DEZE WERKT SOMS NIET GOED
355 ; ROMMELT MET CYLINDERS
356 ; ALLEEN TOEPASSEN ALS INT13X NIET ACTIEF !
357
358;; and cl, al ; Isolate lower bits, because upper
359;; mov ah, 0
360;; mov si, ax ; ones may be used for cylinder
361;; sub si, cx
362
363;; pop cx
364;; pop ax
365
366;; or cl, al ; Set sector to last sector
367;; add ax, si ; Adjust lower LBA
368;; adc bx, 0 ; Adjust LBA Sector (BX:AX)
369
370
371
372 ;~ push ax
373 ;~ call AuxIO_TeletypeHexWord
374 ;~ call AuxIO_TeletypeNL
375 ;~ mov ax,[ts]
376 ;~ call AuxIO_TeletypeHexWord
377 ;~ call AuxIO_TeletypeNL
378 ;~ mov ax,[ts2]
379 ;~ call AuxIO_TeletypeHexWord
380 ;~ call AuxIO_TeletypeNL
381 ;~ pop ax
382
383 ;~ and ax,[ts]
384
385;; jmp done
386
387
388
389;; done:
390
391 ;pusha
392 ;mov si,offset after_lvm_adjust
393 ;~ call AuxIO_Print
394 ; LBA
395 ;xchg dx,bx
396 ;~ call AuxIO_TeletypeHexDWord
397 ;~ call AuxIO_TeletypeNL
398 ;xchg bx,dx
399 ;popa
400
401 ;~ pusha
402 ;~ call AuxIO_TeletypeNL
403;~
404 ;~ ; CYL
405 ;~ mov al,ch
406 ;~ call AuxIO_TeletypeHexByte
407 ;~ call AuxIO_TeletypeNL
408;~
409 ;~ ; HEAD
410 ;~ mov al,dh
411 ;~ call AuxIO_TeletypeHexByte
412 ;~ call AuxIO_TeletypeNL
413;~
414 ;~ ; SEC
415 ;~ mov al,cl
416 ;~ call AuxIO_TeletypeHexByte
417 ;~ call AuxIO_TeletypeNL
418;~
419 ;~ ; DRIVE
420 ;~ mov al,dl
421 ;~ call AuxIO_TeletypeHexByte
422 ;~ call AuxIO_TeletypeNL
423 ;~ popa
424
425;; ret
426DriveIO_LVMAdjustToInfoSector EndP
427
428
429
430
431
432
433; #########################################################################
434; Routine: Loads partition to ExecBase and checks for validity
435; #########################################################################
436; Calling : bx:ax - Absolute sector
437; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
438; Returns : Carry Set if invalid partition encountered
439; Preserve: all registers
440; #########################################################################
441DriveIO_LoadPartition Proc Near Uses si
442 mov wptr cs:[CurPartition_Location+0], ax
443 mov wptr cs:[CurPartition_Location+2], bx
444 mov wptr cs:[CurPartition_Location+4], dx
445 mov wptr cs:[CurPartition_Location+6], cx ; Saves the location
446 mov si, offset PartitionSector ; DS:SI - ExecBase
447 call DriveIO_LoadSector
448 clc
449 cmp wptr [si+LocBR_Magic], 0AA55h
450 je DIOLP_Success
451 ; We check, if we are scanning partitions. In that case, if CHS is not 0/0/1
452 ; we will display a "bad partition table" message and halt the system.
453 cmp cx, 0001h
454 jne DIOLP_Failed
455 or dh, dh
456 jnz DIOLP_Failed
457 stc ; Set carry, so no partition table
458 DIOLP_Success:
459
460 IFDEF AUX_DEBUG
461 ; show current partition location
462 ;~ pushf
463 ;~ pusha
464 ;~ call AuxIO_TeletypeNL
465 ;~ mov si,offset db_curpartloc
466 ;~ call AuxIO_Print
467 ;~ mov dx,word ptr [CurPartition_Location+02]
468 ;~ mov ax,word ptr [CurPartition_Location+00]
469 ;~ call AuxIO_TeletypeHexDWord
470 ;~ call AuxIO_TeletypeNL
471 ;~ mov si,offset PartitionSector
472 ;~ call AuxIO_DumpSector
473 ;~ call AuxIO_TeletypeNL
474 ;~ popa
475 ;~ popf
476 ENDIF
477
478 ret
479 DIOLP_Failed:
480 jmp DriveIO_GotLoadError
481DriveIO_LoadPartition EndP
482
483; #########################################################################
484; Routine: Writes a partition from ExecBase to its original sector
485; #########################################################################
486; Calling : none
487; Returns : none
488; Preserve: all registers
489; #########################################################################
490DriveIO_SavePartition Proc Near Uses ax bx cx dx si
491 mov ax, wptr cs:[CurPartition_Location+0]
492 mov bx, wptr cs:[CurPartition_Location+2]
493 mov dx, wptr cs:[CurPartition_Location+4]
494 mov cx, wptr cs:[CurPartition_Location+6] ; Gets prev. saved location
495 mov si, offset PartitionSector ; DS:SI - ExecBase
496 cmp wptr [si+LocBR_Magic], 0AA55h ; Checks for signature, if not found
497 jne DIOSP_SevereError ; we assume a really bad error
498 call DriveIO_SaveSector
499 DIOSP_SevereError:
500 ret
501DriveIO_SavePartition EndP
502
503; Keeps DS:SI for caller
504DriveIO_LoadTmpSector Proc Near
505 mov si, offset TmpSector
506 call DriveIO_LoadSector
507 ret
508DriveIO_LoadTmpSector EndP
509
510; Keeps DS:SI for caller
511DriveIO_SaveTmpSector Proc Near
512 mov si, offset TmpSector
513 call DriveIO_SaveSector
514 ret
515DriveIO_SaveTmpSector EndP
516
517
518
519; Keeps DS:SI for caller, sets carry if valid LVM sector encountered
520DriveIO_LoadLVMSector Proc Near Uses ax bx cx dx
521 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
522 jnz DIOLLVMS_NoLVMSector ; don't load but declare as bad!
523 mov ax, wptr cs:[CurPartition_Location+0]
524 mov bx, wptr cs:[CurPartition_Location+2]
525 mov dx, wptr cs:[CurPartition_Location+4]
526 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
527
528 call DriveIO_LVMAdjustToInfoSector
529
530 mov si, offset LVMSector
531 call DriveIO_LoadSector
532
533 IFDEF AUX_DEBUG
534 ; show current partition location
535 ;~ pushf
536 ;~ pusha
537 ;~ call AuxIO_TeletypeNL
538 ;~ mov si,offset db_curlvmsec
539 ;~ call AuxIO_Print
540 ;~ mov dx,bx
541 ;~ call AuxIO_TeletypeHexDWord
542 ;~ call AuxIO_TeletypeNL
543 ;~ mov si,offset LVMSector
544 ;~ call AuxIO_DumpSector
545 ;~ call AuxIO_TeletypeNL
546 ;~ popa
547 ;~ popf
548 ENDIF
549
550 call LVM_CheckSectorSignature
551 jnc DIOLLVMS_NoLVMSector
552 call LVM_CheckSectorCRC
553 jnc DIOLLVMS_NoLVMSector
554 ret
555 ; This here is called, if an invalid (or no) LVM information sector is found
556 ; It will truncate the first byte of the sector, so all other routines
557 ; will notice it easily by just comparing the first byte.
558 DIOLLVMS_NoLVMSector:
559 mov bptr [si+LocLVM_SignatureStart], 0
560 ret
561DriveIO_LoadLVMSector EndP
562
563
564
565; Keeps DS:SI for caller, saves at anytime w/o checks (!)
566DriveIO_SaveLVMSector Proc Near Uses ax bx cx dx
567 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
568 jnz DIOSLVMS_SevereError ; don't save at anytime (security!)
569 mov ax, wptr cs:[CurPartition_Location+0]
570 mov bx, wptr cs:[CurPartition_Location+2]
571 mov dx, wptr cs:[CurPartition_Location+4]
572 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
573 call LVM_CheckSectorSignature
574 jnc DIOSLVMS_SevereError ; LVM Signature must be there
575
576 IFDEF AUX_DEBUG
577;~ dioatlvm db 'DriveIO_LVMAdjustToInfoSector',10,0
578 ;~ pushf
579 ;~ pusha
580 ;~ mov si,offset dioatlvm
581 ;~ call AuxIO_Print
582 ;~ popa
583 ;~ popf
584 call DEBUG_DumpRegisters
585 call DEBUG_DumpCHS
586 ENDIF
587
588 call DriveIO_LVMAdjustToInfoSector
589
590 IFDEF AUX_DEBUG
591 call DEBUG_DumpRegisters
592 call DEBUG_DumpCHS
593 ENDIF
594
595 mov si, offset LVMSector
596 call DriveIO_SaveSector
597 DIOSLVMS_SevereError:
598 ret
599DriveIO_SaveLVMSector EndP
600
601; Rousseau: Move this to BSS and merge with int13xbuf there.
602
603; Memory-Block that holds information for LBA-access via INT 13h
604DriveIO_DAP db 10h ; Size of paket
605 db 0 ; Reserved
606DriveIO_DAP_NumBlocks dw 0 ; Number of blocks
607DriveIO_DAP_Transfer dd 0 ; Transfer Adress
608DriveIO_DAP_Absolute dd 0 ; Absolute Sector
609 dd 0 ; Second Part of QWORD
610
611; Special error message instead of "LOAD ERROR" during partition scanning,
612; so users will notice that something is bad with their partition table(s)
613DriveIO_GotLoadError Proc Near
614 test byte ptr cs:[CurIO_Scanning], 1 ; Must be CS:, cause DS!=CS maybe here
615 jnz InScanMode
616 jmp MBR_LoadError
617 InScanMode:
618 mov si, offset TXT_BrokenPartitionTable
619 push cs
620 pop ds
621 call MBR_Teletype
622 mov si, offset BrokenHDD
623 sub dl, 50h ; 80h -> '0'
624 cmp dl, 39h
625 jbe DIOGLE_BelowA
626 add dl, 7 ; 3Ah -> 'A'
627 DIOGLE_BelowA:
628 mov bptr [si+5], dl
629 call MBR_Teletype
630
631 ; JWasm: cannot jump to local label in other procedure.
632 ; Changed to halt here.
633 ;jmp MBRLE_Halt
634 DriveIO_GotLoadError_halt:
635 jmp DriveIO_GotLoadError_halt
636DriveIO_GotLoadError EndP
637
638; #########################################################################
639; Routine: Loads a specified sector to DS:DI
640; #########################################################################
641; Calling : bx:ax - Absolute sector
642; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
643; ds:si - Destination-Adress
644; Returns : none
645; Preserve: all registers
646; #########################################################################
647DriveIO_LoadSector Proc Near Uses ax bx cx dx ds si es di
648 ; Is the drive not a harddrive?
649 cmp dl, 80h
650 jb DIOLS_UseNormal
651
652 test byte ptr cs:[CurIO_UseExtension], 1
653 jz DIOLS_UseNormal
654 ; Are we forced do use LBA via Setting?
655 jnz DIOLS_UseExtension
656
657 ; Upper 8 bits of LBA-address set?
658 ; Then use LBA (maximum boundary is 16320x16x63 = FB0400h)
659 or bh, bh
660 jnz DIOLS_UseExtension
661 ; Compare Switch-Table value to bit 16-23 of LBA-address
662 mov di, dx
663 and di, 007Fh
664 cmp bptr cs:[LBASwitchTable+di], bl
665 jbe DIOLS_UseExtension
666 DIOLS_UseNormal:
667 mov di, 3
668 DIOLS_ErrorLoop:
669 push ds
670 pop es
671 mov bx, si ; ES:BX - Destination
672 mov ax, 0201h ; Function 2 - Load Sector
673 int 13h
674 jnc DIOLS_Success
675 dec di
676 jnz DIOLS_ErrorLoop
677 ; Sector load failed...
678 jmp DriveIO_GotLoadError
679
680 DIOLS_UseExtension:
681 push cx
682 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
683 mov wptr cs:[DriveIO_DAP_Transfer+0], si
684 mov cx, ds
685 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
686 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
687 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
688 push cs
689 pop ds
690 mov si, offset DriveIO_DAP
691 mov ah, 42h ; Extended Read
692 int 13h
693 pop cx
694 jnc DIOLS_Success
695 ; Sector load failed...
696 jmp DriveIO_GotLoadError
697
698 DIOLS_Success:
699 ret
700DriveIO_LoadSector EndP
701
702
703
704;
705; ############################################################
706; # Load a specified sector from a disk using LBA addressing #
707; ############################################################
708;
709; In
710; --
711; DL = Physical Disk
712; BX:CX = LBA sector
713; DI:SI = Target buffer
714;
715; Out
716; ---
717; AX = Error code
718;
719DriveIO_LoadSectorLBA Proc Near Uses bx cx dx si di ds es
720 ; Get one sector
721 mov cs:[DriveIO_DAP_NumBlocks], 1
722
723 ; Setup buffer address
724 mov wptr cs:[DriveIO_DAP_Transfer+0], si
725 mov wptr cs:[DriveIO_DAP_Transfer+2], di
726
727 ; Setup LBA address of requested sector
728 mov wptr cs:[DriveIO_DAP_Absolute+0], cx
729 mov wptr cs:[DriveIO_DAP_Absolute+2], bx
730 mov wptr cs:[DriveIO_DAP_Absolute+4], 0
731 mov wptr cs:[DriveIO_DAP_Absolute+6], 0
732
733 ; Address of packet
734 mov si, offset DriveIO_DAP
735
736 ; Do the extended read
737 mov ah, 42h
738 int 13h
739
740 ; Looking good so far
741 jnc DriveIO_LoadSectorLBA_succes1
742
743 ; AH should not be zero, if it is then set to undefined and set carry
744 test ah,ah
745 jnz DriveIO_LoadSectorLBA_error1
746 mov ah, 0bbh ; Undefined error
747 DriveIO_LoadSectorLBA_error1:
748 stc
749 jmp DriveIO_LoadSectorLBA_exit
750
751 ; AL should be zero, if not then set to undefined and set carry
752 DriveIO_LoadSectorLBA_succes1:
753 test ah,ah
754 jz DriveIO_LoadSectorLBA_exit
755 stc
756 jmp DriveIO_LoadSectorLBA_exit
757
758 ; Return to caller
759 DriveIO_LoadSectorLBA_exit:
760 ret
761DriveIO_LoadSectorLBA EndP
762
763
764
765;
766; ############################################################
767; # Check for a valid MBR-sector to be written to disk #
768; ############################################################
769;
770; In
771; --
772; DL = Physical Disk
773; BX:CX = LBA sector
774; DI:SI = Source buffer
775;
776; Out
777; ---
778; CY = 1 if invalid MBR in source buffer, 0 if valid
779;
780; This routine is called when DriveIO_SaveSector attempts to write to the MBR.
781; It checks if the sector to be written has some sensible values in certain
782; places. In fact, if the sector is written to the boot-disk, the AiR-BOOT
783; signature should be present and the partition table should be the same
784; as the one at the start of the AiR-BOOT code in memory, except maybe for the
785; active flags.
786; For other disks, only the active flags are checked to be 00h or 80h and
787; the AA55h MBR signature.
788;
789DriveIO_ProtectMBR Proc Near
790 pusha ; Push all registers
791 push es ; Push ES because we need it for string instructions
792 push cs ; Make ES point...
793 pop es ; to CS
794
795 ; Save the pointer to the sector to write in BX
796 mov bx,si
797
798 ;
799 ; If the sector to be written is not the boot-disk, then skip
800 ; checking the AiR-BOOT MBR.
801 ;
802 cmp dl,80h
803 ja DriveIO_ProtectMBR_is_not_bootdisk
804
805 ;
806 ; The boot-disk is accessed so the sector to be written must be
807 ; the AiR-BOOT MBR. This is the same as the first 512 bytes
808 ; relocated to 8000:0000 and this the start of the AB-code.
809 ;
810 mov si,bx ; Get pointer to sector to write
811 xor di,di ; Point DI to start of AB-code (MBR)
812 mov cx, offset [MBR_PartTable] ; Bytes upto P-table must be same
813 cld ; Compare upwards
814 repe cmpsb ; Compare upto P-table
815
816 ; If not the same this is not the an AiR-BOOT boot-disk MBR !
817 jne DriveIO_ProtectMBR_not_valid_MBR ; SEVERE ERROR !
818
819 ; Continue with signature check
820 jmp DriveIO_ProtectMBR_check_signature
821
822
823 ;
824 ; The disk is not the boot-disk so we don't know what kind of MBR is on it.
825 ; Some sanity checks should be here.
826 ;
827 DriveIO_ProtectMBR_is_not_bootdisk:
828
829 ;
830 ; sanity checks...
831 ;
832
833 ; Continue with signature check
834 jmp DriveIO_ProtectMBR_check_signature
835
836
837 DriveIO_ProtectMBR_check_signature:
838 ; See if the sector to write contains a valid signature
839 mov si,bx ; Get pointer to sector to write
840 mov di, offset [MBR_Sig] ; Offset to MBR signature
841 add si,di ; Make SI point to it in sec to write
842 lodsw ; Load it
843 cmp ax,0aa55h ; See if it is valid
844
845 ; If no signature this cannot be a valid MBR !
846 jne DriveIO_ProtectMBR_not_valid_MBR ; SEVERE ERROR !
847
848
849 ;
850 ; The sector to be written seems to be valid.
851 ; Set CY=0 to indicate a valid MBR.
852 ;
853 DriveIO_ProtectMBR_is_valid_MBR:
854 clc
855 jmp DriveIO_ProtectMBR_end
856
857 ;
858 ; Something is terribly wrong; a non-MBR sector seems about to be written.
859 ; Set CY=1 and let the calling code handle this situation.
860 ;
861 DriveIO_ProtectMBR_not_valid_MBR:
862 stc
863 jmp DriveIO_ProtectMBR_end
864
865 ;
866 ; Return to the caller with no registers modyfied except FLAGS.
867 ;
868 DriveIO_ProtectMBR_end:
869 pop es
870 popa
871 ret
872DriveIO_ProtectMBR Endp
873
874
875
876; #########################################################################
877; Routine: Checks if the MBR is addressed by either CHS or LBA
878; #########################################################################
879; Calling : bx:ax - Absolute sector
880; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
881; Returns : ZF=1 if MBR is addressed, else ZF=0
882; Preserve: all registers
883; #########################################################################
884DriveIO_MBR_Addressed Proc
885 push ax
886 push bx
887
888 or bx,ax ; Results in 0 in BX if MBR is addressed by LBA
889 jz DriveIO_MBR_Addressed_done
890
891 mov ax,cx ; Results in 1 in AX if CYL 0, SEC 1 is addressed
892 add al,dh ; Results in 1 in AX if HEAD 0 is addressed
893 dec ax ; Results in 0 in AX if MBR is addressed by CHS
894
895 DriveIO_MBR_Addressed_done:
896 pop bx
897 pop ax
898 ret
899DriveIO_MBR_Addressed EndP
900
901
902
903
904; #########################################################################
905; Routine: Writes DS:SI to a specified sector
906; #########################################################################
907; Calling : bx:ax - Absolute sector
908; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
909; ds:si - Source-Adress
910; Returns : none
911; Preserve: all registers
912; #########################################################################
913DriveIO_SaveSector Proc Near Uses ax bx cx dx ds si es di
914
915
916 ;!
917 ;! DEBUG_BLOCK
918 ;! Force write to LBA0 to test interception routine.
919 ;! Do *NOT* enable unless you are debugging, will overwrite MBR !
920 ;!
921 ;~ __DIO_FORCE_LBA0_WRITE__ EQU
922 IFDEF AUX_DEBUG
923 IFDEF __DIO_FORCE_LBA0_WRITE__
924 xor ax,ax
925 xor bx,bx
926 xor cx,cx
927 inc cx
928 xor dh,dh
929 ENDIF
930 ENDIF
931
932
933 ;!
934 ;! DEBUG_BLOCK
935 ;! Check what is being written to disk.
936 ;! Uncomment below to activate.
937 ;!
938 __DIO_SS_DMP__ EQU
939 IFDEF AUX_DEBUG
940 IFDEF __DIO_SS_DMP__
941 pusha
942 push si
943 mov si,offset dioss
944 call AuxIO_Print
945 pop si
946 call DEBUG_DumpRegisters
947 call AuxIO_DumpSector
948 call AuxIO_TeletypeNL
949 popa
950 ENDIF
951 ENDIF
952
953 ;
954 ; Check if the MBR is the destination for the write.
955 ; ZF=1 if so.
956 ;
957 call DriveIO_MBR_Addressed
958 jnz DriveIO_SaveSector_continue_write
959
960
961 ; MBR is addressed, check the sector that is requested to be written.
962 ; For the bootdisk it should contain the AiR-BOOT signature, valid
963 ; partition-table entries and the AA55h signature.
964 ; If not, something is terribly wrong in some piece of the AB code.
965 ; For any other disk (80h+) at least a valid partition table should
966 ; be present together with the AA55h signature.
967 call DriveIO_ProtectMBR
968 jnc DriveIO_SaveSector_continue_write
969
970
971 ;
972 ; WE HAVE A SEVERE ERROR CONDITION !
973 ; SOME AB CODE TRIES TO WRITE A NON-MBR TO THE DISK !
974 ; ASK THE USER TO REPORT THIS !
975 ; HALT THE SYSTEM !
976 ;
977
978 ; Show error-box
979 mov cx, 0C04h
980 mov si, offset NonMBRwrite
981 call SETUP_ShowErrorBox
982 mov cx, 0C04h
983 mov si, offset NonMBRwrite_rep
984 call SETUP_ShowErrorBox
985
986
987 IFDEF AUX_DEBUG
988 pusha
989 mov si, offset NonMBRwrite
990 call AuxIO_TeletypeNL
991 call AuxIO_Print
992 call AuxIO_TeletypeNL
993 popa
994 ENDIF
995
996 ; Show popup and halt the system.
997 jmp HaltSystem
998
999
1000
1001 ;
1002 ; Continue the write if not MBR sector or MBR to write is validated.
1003 ;
1004 DriveIO_SaveSector_continue_write:
1005 test byte ptr cs:[CurIO_UseExtension], 1
1006 jz DIOSS_UseNormal
1007 ; Are we forced do use LBA via Setting?
1008 ; Always use INT13X on v1.0.8+.
1009 ;~ test byte ptr cs:[CFG_ForceLBAUsage], 1
1010 ;~ jnz DIOSS_UseExtension
1011 jmp DIOSS_UseExtension
1012 ; Is the drive not a harddrive?
1013 cmp dl, 80h
1014 jb DIOSS_UseNormal
1015 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
1016 or bh, bh
1017 jnz DIOSS_UseExtension
1018 ; Compare Switch-Table value to bit 16-23 of LBA-address
1019 mov di, dx
1020 and di, 007Fh
1021 cmp bptr cs:[LBASwitchTable+di], bl
1022 jbe DIOSS_UseExtension
1023 DIOSS_UseNormal:
1024 mov di, 3
1025 DIOSS_ErrorLoop:
1026 push ds
1027 pop es
1028 mov bx, si ; ES:BX - Destination
1029 mov ax, 0301h ; Function 3 - Write Sector
1030 int 13h
1031 jnc DIOSS_Success
1032 dec di
1033 jnz DIOSS_ErrorLoop
1034 call MBR_SaveError
1035
1036 DIOSS_UseExtension:
1037 push cx
1038 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
1039 mov wptr cs:[DriveIO_DAP_Transfer+0], si
1040 mov cx, ds
1041 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
1042 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
1043 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
1044 push cs
1045 pop ds
1046 mov si, offset DriveIO_DAP
1047 mov ax, 4300h ; Extended Write (No Verify)
1048 int 13h
1049 pop cx
1050 jnc DIOSS_Success
1051 call MBR_SaveError
1052
1053 DIOSS_Success:
1054 ret
1055DriveIO_SaveSector EndP
1056
1057
1058; See if a LVM-sector is valid.
1059; In : si, pointer to sector
1060; Out : CY if valid LVM sector, NC if not
1061DriveIO_LVMSectorValid Proc Near
1062 pusha
1063
1064 call LVM_CheckSectorSignature
1065 ; NC if no signature found
1066 jnc DriveIO_LVMSectorValid_End
1067
1068 call LVM_CheckSectorCRC
1069 ; Force valid !!!
1070 stc
1071
1072 DriveIO_LVMSectorValid_End:
1073 popa
1074 ret
1075DriveIO_LVMSectorValid EndP
1076
1077; ------------------------------------------------------
1078; Rousseau: # Load the master LVM-sector if one exists #
1079; ------------------------------------------------------
1080; Load the master LVM-sector to get the number of sectors per track as
1081; eCS views the drive. If no master LVM-sector is found it is assumed eCS
1082; is not installed. The master LVM-sector can be located at three different
1083; places depending on drive size and partitioning scheme and driver used.
1084; When DANIS506.ADD is used, the eCS extended geometry will be 255/127 for
1085; drives >502GiB but <1TiB. Then the location will be sector 127 which
1086; is LBA 126 (7Eh).
1087; IBM1S506.ADD will always use 255/255 for the extended eCS geometry.
1088; DANIS506.ADD will use 255/255 for drives >1TiB.
1089; Then the location of the master LVM-sector will be 255 which is LBA 254 (FEh).
1090; When eCS is installed on a huge drive that alread had a system on it, eCS
1091; will be confined to the lower 502GiB of the drive.
1092; In this case the normal geometry from Int13X will be used.
1093; This is also the case when no valid master LVM-sector can be found.
1094;
1095; Return CF when valid master LVM sector found, NC if not.
1096; Loads sector at [LVMSector] !
1097DriveIO_LoadMasterLVMSector Proc Near
1098 pusha
1099
1100 ;~ mov si,offset db_lmlvm
1101 ;~ call AuxIO_Print
1102
1103 ;~ ; Physical disk
1104 ;~ mov al,'<'
1105 ;~ call VideoIO_PrintSingleChar
1106 ;~ mov al,dl
1107 ;~ call VideoIO_PrintHexByte
1108 ;~ mov al,'>'
1109 ;~ call VideoIO_PrintSingleChar
1110;~
1111 ;~ call AuxIO_TeletypeHexByte
1112 ;~ call AuxIO_TeletypeNL
1113
1114
1115 ; Loop over the sector-translation table,
1116 ; process the first three values from high (255) to low.
1117 ; (bios spt, most likely 63)
1118 mov cx,3
1119 DriveIO_LoadMasterLVMSector_NextTry:
1120 ; Number of sectors to read
1121 mov [DriveIO_DAP_NumBlocks],1
1122
1123 ; Setup destination address
1124 mov si, offset [LVMSector]
1125 mov word ptr [DriveIO_DAP_Transfer+0],si
1126 mov ax, ds
1127 mov word ptr [DriveIO_DAP_Transfer+2],ax
1128
1129 ; Get the sector-number of the next possible LVM sector (255,127,63)
1130 ; using the translation table and the counter as the index
1131 mov bx,offset secs_per_track_table
1132 mov ax,cx
1133 dec ax
1134 xlatb
1135 dec al
1136
1137 ;
1138 ; AX now contains the LBA address of the sector
1139 ; that could be an LVM sector.
1140 ; This is all in track0 so the address will not exceed 64kiB sectors.
1141 ;
1142
1143 ;~ push ax
1144 ;~ push ax
1145 ;~ mov al,'$'
1146 ;~ call VideoIO_PrintSingleChar
1147 ;~ pop ax
1148 ;~ call VideoIO_PrintHexByte
1149 ;~ mov al,'$'
1150 ;~ call VideoIO_PrintSingleChar
1151 ;~ pop ax
1152
1153 IFDEF AUX_DEBUG
1154 ; Dump the value
1155 ;~ call AuxIO_TeletypeHexByte
1156 ;~ call AuxIO_TeletypeNL
1157 ENDIF
1158
1159 ; Setup the requested LBA sector number
1160 mov word ptr [DriveIO_DAP_Absolute+0],ax ; LBA low NORMAL I/O GEBRUIKEN !
1161 mov word ptr [DriveIO_DAP_Absolute+2],00h ; LBA high
1162 mov si, offset DriveIO_DAP ; address request packet
1163 mov ah, 42h
1164 int 13h ; do the i/o
1165 cmc ; Complement carry so we can exit imm. on error
1166 jnc DriveIO_LoadMasterLVMSector_End ; oops, return with NC
1167
1168
1169 mov si,offset [LVMSector]
1170
1171 ; See if this is a valid LVM-sector
1172 ; CY=1 if valid
1173 call DriveIO_LVMSectorValid
1174
1175; pushf
1176; mov ah,0
1177; rcl ah,1
1178; mov al,'|'
1179; call VideoIO_PrintSingleChar
1180; mov al,ah
1181; call VideoIO_PrintHexByte
1182; mov al,'|'
1183; call VideoIO_PrintSingleChar
1184; popf
1185
1186
1187 ; Yep, we found the master LVM-sector
1188 jc DriveIO_LoadMasterLVMSector_Found
1189 ; Try next location
1190 loop DriveIO_LoadMasterLVMSector_NextTry
1191
1192 ; No master LVM-sector found, set CF=false
1193 clc
1194
1195 DriveIO_LoadMasterLVMSector_Found:
1196 ; Store the address for later use.
1197 mov ax, word ptr [DriveIO_DAP_Absolute]
1198 mov word ptr [MasterLVMLBA], ax
1199
1200 DriveIO_LoadMasterLVMSector_End:
1201 popa
1202 ret
1203DriveIO_LoadMasterLVMSector Endp
1204
1205
1206
1207
1208; ---------------------------------------------------
1209; Rousseau ## Large drives, (eCS) geometry and LBA ##
1210; ---------------------------------------------------
1211; A sector size of 512 bytes is assumed in the below calculations.
1212; Note that this scheme changes when the sector size will be 4096 or larger,
1213; like with modern drives that do not translate to 512 bytes per sector anymore.
1214; These drives will have a capacity above the 2TiB LBA32 boundary.
1215; For now, we assume drives <=2TiB with a sector size of 512 bytes.
1216
1217; There are a few boundaries that are of importance.
1218; Note that these are disk-boundaries and not partition boundaries.
1219; Even with a small partition, like <502GiB, OS/2 will use extended geometry on
1220; an empty huge disk.
1221; These boundaries are (from high to low):
1222
1223; (code 5)
1224; 2^32 = 4294967296 = 100000000 sectors = 2048 GiB
1225; This is the LBA32 2TiB boundary.
1226; Everything above it must be addressed using LBA48.
1227; OS/2 can currently not address this space above.
1228
1229; (code4)
1230; 65536*255*255 = 4261478400 = FE010000 sectors ~ 2032 GiB
1231; This is the max OS/2 boundary using 255/255 extended geometry.
1232; OS/2 can currently not address this space above.
1233
1234; (code 3)
1235; 2^31 = 2147483648 = 80000000 sectors = 1024 GiB
1236; This is the LBA32 1TiB boundary.
1237; OS/2 can address this space and will use 255/255 extended geometry.
1238
1239; (code 2)
1240; 65536*255*127 = 2122383360 = 7E810000 sectors ~ 1012 GiB
1241; This is the DANI 1TiB boundary.
1242; OS/2 can address this space and will use 255/255 extended geometry.
1243; Below this DANI will use 255/127 extended geometry.
1244; This matters on where the LVM-sectors are located !
1245
1246; (code 1)
1247; 65536*255*63 = 1052835840 = 3EC10000 sectors ~ 502 GiB
1248; This is the current OS/2 limit using this geometry because OS/2 can
1249; currently not address more than 65536 cylinders.
1250; DANI will address space above with 255/127 extended geometry up until
1251; the DANI 1TiB boundary (code 2)
1252
1253; (code 0)
1254; Everything below 65536*255*63 will be addressed using standard geometry.
1255
1256
1257;
1258; This function will return the following values:
1259;
1260
1261; 5 = This drive is above the 2^32 LBA32 (2TB) boundary and has more
1262; than 4294967296 sectors.
1263; LBA48 addressing is needed to access the complete capacity of the drive.
1264; OS/2 is currently unable to do so.
1265
1266; 4 = This drive is above the 65536*255*255 (4261478400) boundary but below 2^32.
1267; This is an OS/2 boundary and OS/2 is not able to access the drive above
1268; this boundary.
1269
1270; 3 = This drive is above the 2^31 (1TB) boundary and has more than
1271; 2147483648 sectors.
1272; OS/2 is able to access the drive using it's extended geometry.
1273; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
1274
1275; 2 = This drive is above the 65536*255*127 (2122383360) boundary but below 2^31.
1276; OS/2 is able to access the drive using it's extended geometry.
1277; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
1278
1279; 1 = This drive is above the 65536*255*63 (1052835840) boundary but
1280; below 65536*255*127.
1281; OS/2 is able to access the drive using it's extended geometry.
1282; Note that DANIS506 will use 255/127 and IBM1S506 will use 255/255 geometry !
1283; Using DANI or IBM influences the location of the LVM info-sectors !
1284
1285; 0 = This drive is below the 65536*255*63 (1052835840) boundary.
1286; OS/2 is able to access this drive using the standard 255/63 geometry.
1287
1288; So, any return value >0 means OS/2 extended geometry will be used.
1289; Value 1 will use 255/127 with DANIS506 but 255/255 with IBM1S506.
1290; Values 2 and 3 will use 255/255 on both drivers.
1291; You can or with 0x01 and check for 3 in this case.
1292; Any value above 3 will be a drive who's capacity cannot be fully used by OS/2
1293; The upper limit of 65536*255*255 will be in effect here.
1294
1295; Note this function currently handles the boot-drive only !
1296; It should be extended and use dl for the drive-number as a parameter.
1297; Because we use this function to get this info in a number of places,
1298; all regs and flags except AX are saved and restored.
1299
1300; DL contains BIOS disk-number; 80h for first, 81h for second, etc.
1301DriveIO_GatherDiskInfo Proc Near
1302 pushf
1303 push bx
1304 push cx
1305 push dx
1306 push si
1307 push di
1308 push es
1309
1310 ; Set ES to CS for buffer clearing
1311 push cs
1312 pop es
1313
1314 ; Clear the buffer
1315 ; Also setup the buffer size.
1316 ; Old Phoenix BIOSses require word (flags) at 02 to be zero,
1317 ; so we clear the whole buffer to be sure.
1318 mov cx, i13xbuf_size ; Dynamically calculated by assembler.
1319 mov di, offset i13xbuf ; Points to size field.
1320 mov [di],cx ; Setup buffer-size.
1321 inc di
1322 inc di ; Now pointing at actual buffer.
1323 xor ah,ah ; Fill value.
1324 cld ; Direction up.
1325 rep stosb ; Clear buffer.
1326
1327 ; Get the drive parameters
1328 mov ah, 48h ; Get Drive Parameters (extended version)
1329 ;mov dl, 80h ; Drive number
1330 mov si, offset i13xbuf ; Buffer for result-info
1331 push dx
1332 int 13h ; Call the BIOS-function
1333 pop dx
1334
1335 ; Do some error-checking
1336 or ah,ah ; AH is zero if no error (ZF=1 if no error)
1337 mov ax,0 ; Setup code for non-huge drive (does not influence ZF)
1338 jz DriveIO_GatherDiskInfo_ok ; Return if error (AL<>0 thus ZF=0) but CY not set, assuming non-huge drive
1339 jnc DriveIO_GatherDiskInfo_ok ; Return if error (CY=1), assuming non-huge drive
1340 jmp DriveIO_GatherDiskInfo_ret
1341
1342
1343 DriveIO_GatherDiskInfo_ok:
1344
1345 ;
1346 ; Store the drive geometry
1347 ;
1348
1349 mov si, offset i13xbuf
1350
1351 xor dh,dh
1352 and dl,01111111b
1353 shl dx,1
1354 shl dx,1
1355
1356 ; Store number of cylinders on disk
1357 mov bx, offset BIOS_Cyls
1358 add bx,dx
1359 mov ax,[si+04h]
1360
1361 mov word ptr [bx+00],ax
1362 mov ax,[si+06]
1363 mov word ptr [bx+02],ax
1364
1365 ; Store number of heads per cylinder
1366 mov bx, offset BIOS_Heads
1367 add bx,dx
1368 mov ax,[si+08h]
1369 mov word ptr [bx+00],ax
1370 mov ax,[si+0ah]
1371 mov word ptr [bx+02],ax
1372
1373 ; Store number of sectors per track
1374 mov bx, offset BIOS_Secs
1375 add bx,dx
1376 mov ax,[si+0ch]
1377 mov word ptr [bx+00],ax
1378
1379 ; Update first byte of translation-table to conform to BIOS SPT
1380 mov byte ptr [secs_per_track_table], al
1381
1382 mov ax,[si+0eh]
1383 mov word ptr [bx+02],ax
1384
1385 ; Store total secs
1386 mov bx, offset BIOS_TotalSecs
1387 add bx,dx
1388 add bx,dx
1389 mov ax,[si+10h]
1390
1391 mov word ptr [bx+00],ax
1392 mov ax,[si+12h]
1393 mov word ptr [bx+02],ax
1394 mov ax,[si+14h]
1395 mov word ptr [bx+04],ax
1396 mov ax,[si+18h]
1397 mov word ptr [bx+06],ax
1398
1399 ; Store number of bytes per sector
1400 mov bx, offset BIOS_Bytes
1401 add bx,dx
1402 mov ax,[si+18h]
1403 mov [bx],ax
1404
1405
1406 ;
1407 ; See of it's a huge drive of not
1408 ;
1409
1410 ; Drive is larger than 2TiB
1411 mov ax,5 ; Drive code (5)
1412 mov bx, [si+14h] ; Low word of high dword of sector-count
1413 or bx, [si+16h] ; High word of high dword of sector-count
1414 jnz DriveIO_GatherDiskInfo_ret ; If non-zero we have a drive with >2^32 sectors and thus LBA48 addressing
1415
1416 ; Drive is larger than max OS/2 capacity
1417 dec ax ; Drive code (4)
1418 mov bx, [si+12h] ; High word of low dword of sector-count
1419 cmp bx, 0fe01h ; Boundary
1420 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1421 ; we have a drive larger than to 65536*255*255 = FE010000 sectors
1422
1423 ; Drive can be completely utilized by OS/2
1424 dec ax ; Drive code (3)
1425 cmp bx, 8000h ; Boundary
1426 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1427 ; we have a drive larger than 2^31 sectors but smaller than 65536*255*255
1428
1429 ; This is the small area between DANI 1TiB and LBA 1TiB
1430 dec ax ; Drive code (2)
1431 cmp bx, 7e81h ; Boundary
1432 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1433 ; we have a drive larger than 65536*255*127 but <65536*255*255
1434 ; DANIS506.ADD will use 255/255 extended geometry
1435
1436 ; DANI will use 255/127 in this area, this could impact the location of LVM-sectors ! (last sec on track)
1437 dec ax ; Drive code (1)
1438 cmp bx, 3ec1h ; Boundary
1439 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1440 ; we have a drive larger than 65536*255*63 sectors (OS/2 502GiB Limit!)
1441 ; DANIS506.ADD will use 255/127 extended geometry !
1442 ; IBM1S506.ADD will use 255/255 extended geometry !
1443
1444 ; We have a drive that can be addressed using standard 255/63 geometry
1445 dec ax ; Drive code (0)
1446 ; We have a drive smaller than 65536*255*63 = 3EC10000 sectors
1447
1448 DriveIO_GatherDiskInfo_ret:
1449 pop es
1450 pop di
1451 pop si
1452 pop dx
1453 pop cx
1454 pop bx
1455
1456 mov byte ptr [CurIO_UseExtension],1
1457
1458 popf
1459 ret
1460DriveIO_GatherDiskInfo EndP
1461
1462
1463
1464; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value.
1465secs_per_track_table db 63,127,255,255,255,255
1466
1467;db_lmlvm: db 'Load Master LVM -- disk: ',0
Note: See TracBrowser for help on using the repository browser.