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

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

AiR-BOOT v1.0.8-rc3 build-20120909 [2012-09-10]

With Git one can easily hop-skip-and-jump between branches.
So I use Git for my local repos and make use of this easy branching.
Because SVN can only handle lineair history, these branches had to be
rebased before committing them to Netlabs. So, this commit contains a
multitude of changes which makes it a bit hairy.

New

o Display LVM drive-letters in the main menu

A populair request was to show drive-letter information in the menu.
Drive-letters however, are OS specific and AiR-BOOT cannot
accurately predict what drive-letter other operating systems would
assign to what partition. eCS LVM drive-letters however are stored
in the LVM-record and can thus be displayed.

o Added 'Show LVM Drive Letters' option in SETUP/BASIC

This will toggle the display of LVM drive-letters in the main menu.
By default this option is enabled.

o Show popup message when BIOS INT13X extensions are not available

The system is halted.

o Show 'DEL to Power Off' in the bottom left corner

This tries to power-off the system, but it may not work for you.

o Simple interactive debugger

Outputs to the serial port with a few one-letter commands to dump
internal tables and state. (Only available in debug builds)

o Enhanced drive-letter feature

Enable multiple eCS installations using the same drive-letter.
This makes it possible to clone a system with the command
'XCOPY /h /o /t /s /e /r /v /e' to another drive and have that boot
from the same drive-letter.
(Or installing to the same drive by hiding the other system)

Changes

o Reduced MBR protection-image from 1024 to 768 bytes

Luckily the MBR Protection Image code does not exceed 768 bytes,
so that gives us another 256 bytes of precious code-space.
Now the non-EN versions are happy again.
Note that the alignment for the image changed from 512 to 256 bytes.
MBR-PROT.ASM, FIXCODE.C, PARTMAIN.ASM and AIR-BOOT.ASM have been
adjusted for this change.
The fight for code-space continues...

o Updating from v1.06 now also copies over drive-letters

When the user has forced drive-letters in v1.06 these will be copied
over to the v1.0.8 configuration when upgrading.
Because the drive-letter feature is broken in v1.07,
the drive-letter table does not get copied over when upgrading
from v1.07.

o Made FX-code optional to compile in

The FX-code supplies the shifting screen-effects when 'Cooper Bars'
is enabled in the setup. With the current enhancements made however,
there is a continuous lack of code-space, especially when debug-code
is included during development. The FX-code occupies some
1200 bytes, a space that can be put to better use. Therefore the
inclusion of the FX-code has been made conditional to make room for
either debugging or future new features.

o Also rewrite PBR on HPFS

Earlier, a fix was made to write a modified PBR back in case JFS was
used. This was done to enable the drive-letter feature on JFS, since
the PBR JFS-bootcode does not use the supplied PBR in memory.
With the enhancements in the drive-letter feature, the HPFS PBR
needs to be updated on disk also, to cope with zero drive-letters in
the HPFS PBR. This potentially fixes a missing drive-letter in the
PBR when the system is restored from an archive. You might need the
drive-letter feature to force the correct drive-letter on the first
boot, after which the feature can be disabled.

o Added extra MBR protection

When AiR-BOOT is active, it is only AiR-BOOT that writes to the MBR.
To protect the MBR from programming errors, like the one below,
any write to the MBR is now checked for validity.
In essence this is protecting your MBR from bad programming done
by me...

Fixes

o Fixed a minor bug with displaying LVM drive-letters

When more partitions that can be displayed were present, scrolling
the menu would not scroll the drive-letter. Fixed.

o Fixed a bug with regard to the drive-letter feature

When partitions were deleted, and some partitions above the deleted
partition(s) had a drive-letter forced, these partitions would lose
this assignment. This bug is also present in v1.06.

Note

The AIRBOOT.HIS file mentions a DOCU directory with the AiR-BOOT
documentation etc. However, this is not present in this commit and
will be provided at a later time.

File size: 51.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; 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
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.