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

Last change on this file since 90 was 84, checked in by Ben Rietbroek, 8 years ago

Changed the way to enable/disable debug-functions [v1.1.1-testing]

Instead of using named defines, now a simple 'IF' directive is used.
Any function local resources like strings are also conditionally enabled
or disabled.

CAUTION:
This is a testbuild !
AirBoot uses the BIOS to access disks and a small coding error can trash
partition tables or other vital disk structures. You are advised to make
backups of TRACK0 and EBRs before using this testbuild. More info at:
https://rousseaux.github.io/netlabs.air-boot/pdf/AirBoot-v1.1.0-manual.pdf

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