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

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

Its complement for writing to disk using INT13X [v1.1.1-testing]

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