source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AccessDPT.asm @ 324

Last change on this file since 324 was 324, checked in by aitotat@…, 12 years ago

Changes to XTIDE Universal BIOS:

  • Boot Menu now displays correct capacity when using user defined LBA.
File size: 7.7 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   Functions for accessing DPT data.
3
4; Section containing code
5SECTION .text
6
7;--------------------------------------------------------------------
8; AccessDPT_GetDriveSelectByteToAL
9;   Parameters:
10;       DS:DI:  Ptr to Disk Parameter Table
11;   Returns:
12;       AL:     Drive Select Byte
13;   Corrupts registers:
14;       Nothing
15;--------------------------------------------------------------------
16ALIGN JUMP_ALIGN
17AccessDPT_GetDriveSelectByteToAL:
18    mov     al, [di+DPT.wFlags]
19    and     al, FLG_DRVNHEAD_LBA | FLG_DRVNHEAD_DRV
20    or      al, MASK_DRVNHEAD_SET   ; Bits set to 1 for old drives
21    ret
22
23
24;--------------------------------------------------------------------
25; AccessDPT_GetDeviceControlByteToAL
26;   Parameters:
27;       DS:DI:  Ptr to Disk Parameter Table
28;   Returns:
29;       AL:     Device Control Byte
30;   Corrupts registers:
31;       Nothing
32;--------------------------------------------------------------------
33ALIGN JUMP_ALIGN
34AccessDPT_GetDeviceControlByteToAL:
35    xor     al, al
36    test    BYTE [di+DPT.bFlagsLow], FLGL_DPT_ENABLE_IRQ
37    jnz     SHORT .EnableDeviceIrq
38    or      al, FLG_DEVCONTROL_nIEN ; Disable IRQ
39.EnableDeviceIrq:
40    ret
41
42
43;--------------------------------------------------------------------
44; AccessDPT_GetLCHStoAXBLBH
45;   Parameters:
46;       DS:DI:  Ptr to Disk Parameter Table
47;   Returns:
48;       AX:     Number of L-CHS cylinders
49;       BL:     Number of L-CHS heads
50;       BH:     Number of L-CHS sectors per track
51;   Corrupts registers:
52;       CX, DX
53;--------------------------------------------------------------------
54AccessDPT_GetLCHStoAXBLBH:
55    ; Return LBA-assisted CHS if LBA addressing used
56    test    BYTE [di+DPT.bFlagsLow], FLG_DRVNHEAD_LBA
57    jz      SHORT .ConvertPchsToLchs
58
59    call    AccessDPT_GetLbaSectorCountToBXDXAX
60    call    AccessDPT_ConvertSectorCountFromBXDXAXtoLbaAssistedCHSinDXAXBLBH
61    test    dx, dx
62    jnz     SHORT .LimitAXtoMaxLCHScylinders
63    cmp     ax, MAX_LCHS_CYLINDERS
64    jb      SHORT .returnLCHS
65.LimitAXtoMaxLCHScylinders:
66    mov     ax, MAX_LCHS_CYLINDERS
67.returnLCHS:
68    ret
69
70.ConvertPchsToLchs:
71    mov     ax, [di+DPT.wPchsCylinders]
72    mov     bx, [di+DPT.wPchsHeadsAndSectors]
73    ; Fall to AccessDPT_ShiftPCHinAXBLtoLCH
74
75
76;--------------------------------------------------------------------
77; AccessDPT_ShiftPCHinAXBLtoLCH
78;   Parameters:
79;       AX:     P-CHS cylinders (1...16383)
80;       BL:     P-CHS heads (1...16)
81;   Returns:
82;       AX:     Number of L-CHS cylinders (1...1024)
83;       BL:     Number of L-CHS heads (1...255)
84;       CX:     Number of bits shifted (4 at most)
85;   Corrupts registers:
86;       Nothing
87;--------------------------------------------------------------------
88AccessDPT_ShiftPCHinAXBLtoLCH:
89    xor     cx, cx
90.ShiftLoop:
91    cmp     ax, MAX_LCHS_CYLINDERS      ; Need to shift?
92    jbe     SHORT .Return               ;  If not, return
93    inc     cx                          ; Increment shift count
94    shr     ax, 1                       ; Halve cylinders
95    shl     bl, 1                       ; Double heads
96    jnz     SHORT .ShiftLoop            ; Falls through only on the last (4th) iteration and only if BL was 16 on entry
97    dec     bl                          ; DOS doesn't support drives with 256 heads so we limit heads to 255
98    ; We can save a byte here by using DEC BX if we don't care about BH
99.Return:
100    ret
101
102
103;--------------------------------------------------------------------
104; AccessDPT_GetLbaSectorCountToBXDXAX
105;   Parameters:
106;       DS:DI:  Ptr to Disk Parameter Table
107;   Returns:
108;       BX:DX:AX:   48-bit sector count
109;   Corrupts registers:
110;       Nothing
111;--------------------------------------------------------------------
112AccessDPT_GetLbaSectorCountToBXDXAX:
113    mov     ax, [di+DPT.twLbaSectors]
114    mov     dx, [di+DPT.twLbaSectors+2]
115    mov     bx, [di+DPT.twLbaSectors+4]
116    ret
117
118
119;--------------------------------------------------------------------
120; Returns pointer to DRVPARAMS for master or slave drive.
121;
122; AccessDPT_GetPointerToDRVPARAMStoCSBX
123;   Parameters:
124;       DS:DI:  Ptr to Disk Parameter Table
125;   Returns:
126;       CS:BX:  Ptr to DRVPARAMS
127;   Corrupts registers:
128;       Nothing
129;--------------------------------------------------------------------
130ALIGN JUMP_ALIGN
131AccessDPT_GetPointerToDRVPARAMStoCSBX:
132    eMOVZX  bx, [di+DPT.bIdevarsOffset]         ; CS:BX points to IDEVARS
133    add     bx, BYTE IDEVARS.drvParamsMaster    ; CS:BX points to Master Drive DRVPARAMS
134    test    BYTE [di+DPT.bFlagsLow], FLGL_DPT_SLAVE
135    jz      SHORT .ReturnPointerToDRVPARAMS
136    add     bx, BYTE DRVPARAMS_size             ; CS:BX points to Slave Drive DRVPARAMS
137.ReturnPointerToDRVPARAMS:
138    ret
139
140;--------------------------------------------------------------------
141; AccessDPT_GetUnshiftedAddressModeToALZF
142;   Parameters:
143;       DS:DI:  Ptr to Disk Parameter Table
144;   Returns:
145;       AL:     Addressing Mode (L-CHS, P-CHS, LBA28, LBA48)
146;               unshifted (still shifted where it is in bFlagsLow)
147;       ZF:     Set based on value in AL
148;   Corrupts registers:
149;       AL
150;--------------------------------------------------------------------
151;
152; Converted to a macro since only called in two places, and the call/ret overhead
153; is not worth it for these two instructions (4 bytes total)
154;
155%macro AccessDPT_GetUnshiftedAddressModeToALZF 0
156    mov     al, [di+DPT.bFlagsLow]
157    and     al, MASKL_DPT_ADDRESSING_MODE
158%endmacro
159
160
161;--------------------------------------------------------------------
162; LBA assist calculation:
163; this is how to fit a big drive into INT13's skimpy size requirements,
164; with a maximum of 8.4G available.
165;
166; total LBAs (as obtained by words 60+61)
167; divided by 63 (sectors per track) (save as value A)
168; Sub 1 from A
169; divide A by 1024 + truncate.
170; == total number of heads to use.
171; add 1
172; this value must be either 16, 32, 64, 128, or 256 (round up)
173; then take the value A above and divide by # of heads
174; to get the # of cylinders to use.
175;
176;
177; so a LBA28 drive will have 268,435,456 as maximum LBAs
178;
179; 10000000h / 63   = 410410h (total cylinders or tracks)
180;   410410h / 1024 = 1041h, which is way more than 256 heads, but 256 is max.
181;   410410h / 256  = 4104h cylinders
182;
183; there's a wealth of information at: http://www.mossywell.com/boot-sequence
184; they show a slightly different approach to LBA assist calulations, but
185; the method here provides compatibility with phoenix BIOS
186;
187; we're using the values from 60+61 here because we're topping out at 8.4G
188; anyway, so there's no need to use the 48bit LBA values.
189;
190; AccessDPT_ConvertSectorCountFromBXDXAXtoLbaAssistedCHStoDXAXBLBH:
191;   Parameters:
192;       BX:DX:AX:   Total number of sectors
193;   Returns:
194;       DX:AX:  Number of cylinders
195;       BH:     Number of sectors per track (always 63)
196;       BL:     Number of heads (16, 32, 64, 128 or 255)
197;   Corrupts registers:
198;       CX
199;--------------------------------------------------------------------
200AccessDPT_ConvertSectorCountFromBXDXAXtoLbaAssistedCHSinDXAXBLBH:
201    push    bp
202    push    si
203
204    ; Value A = Total sector count / 63
205    xor     cx, cx
206    push    cx      ; Push zero for bits 48...63
207    push    bx
208    push    dx
209    push    ax                      ; 64-bit sector count now in stack
210    mov     cl, LBA_ASSIST_SPT
211    mov     bp, sp                  ; SS:BP now points sector count
212    call    Math_DivQWatSSBPbyCX    ; Temporary value A now in stack
213
214    ; BX = Number of heads =  A / 1024
215    mov     ax, [bp]
216    mov     dx, [bp+2]
217    mov     bx, [bp+4]
218    call    Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
219
220    ; Heads must be 16, 32, 64, 128 or 256 (round up)
221    mov     bx, 256                     ; Max number of heads
222    test    dx, dx                      ; 65536 or more heads?
223    jnz     SHORT .GetNumberOfCylinders
224    mov     cx, 128                     ; Half BX for rounding up
225.FindMostSignificantBitForHeadSize:
226    cmp     ax, cx
227    jae     SHORT .GetNumberOfCylinders
228    shr     cx, 1
229    shr     bx, 1                       ; Halve number of heads
230    jmp     SHORT .FindMostSignificantBitForHeadSize
231
232    ; DX:AX = Number of cylinders = A / number of heads
233.GetNumberOfCylinders:
234    mov     cx, bx
235    call    Math_DivQWatSSBPbyCX
236    mov     ax, [bp]
237    mov     dx, [bp+2]                  ; Cylinders now in DX:AX
238
239    ; Return LBA assisted CHS
240    add     sp, BYTE 8                  ; Clean stack
241    sub     bl, bh                      ; Limit heads to 255
242    mov     bh, LBA_ASSIST_SPT
243    pop     si
244    pop     bp
245    ret
Note: See TracBrowser for help on using the repository browser.