source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm @ 170

Last change on this file since 170 was 170, checked in by krille_n_@…, 13 years ago

Changes to all parts of the project:

  • Minor size optimizations
  • Commented away some ALIGN JUMP_ALIGN directives in the Int13h handler (they are either in init procedures, procedures that are rarely called or are unnecessary due to conditional assembly)
  • Fixed what appears to be a typo in EBIOS.inc
File size: 11.5 KB
RevLine 
[150]1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device transfer functions.
3
4; Structure containing variables for PIO transfer functions.
5; This struct must not be larger than IDEPACK without INTPACK.
6struc PIOVARS
[169]7    .wBlocksLeft            resb    2
[150]8    .wBlockSize             resb    2   ; Block size in WORDs (256...32768)
9    .wDataPort              resb    2
[169]10    .bSectorsInLastBlock:   resb    1
[150]11                            resb    1   ; Offset 7 = IDEPACK.bDeviceControl
12    .fnXfer                 resb    2   ; Offset to transfer function
13endstruc
14
15
16; Section containing code
17SECTION .text
18
19;--------------------------------------------------------------------
20; IdeTransfer_StartWithCommandInAL
21;   Parameters:
22;       AL:     IDE command that was used to start the transfer
23;       ES:SI:  Ptr to destination buffer or source data
24;       DS:DI:  Ptr to DPT (in RAMVARS segment)
25;       SS:BP:  Ptr to IDEPACK
26;   Returns:
27;       AH:     INT 13h Error Code
28;       CF:     Cleared if success, Set if error
29;   Corrupts registers:
30;       AL, BX, CX, DX, SI, ES
31;--------------------------------------------------------------------
32ALIGN JUMP_ALIGN
33IdeTransfer_StartWithCommandInAL:
[169]34    mov     ah, [bp+IDEPACK.bSectorCountHighExt]
35
[157]36    ; Are we reading or writing?
[170]37    test    al, 11001b
38    jpo     SHORT .PrepareToWriteDataFromESSI
[150]39
40    ; Prepare to read data to ESSI
41    mov     bx, g_rgfnPioRead
[169]42    mov     al, [bp+IDEPACK.bSectorCount]
43    call    InitializePiovarsInSSBPwithSectorCountInAX
[150]44    xchg    si, di
45    call    Registers_NormalizeESDI
[169]46    jmp     SHORT ReadFromDrive
[150]47
48ALIGN JUMP_ALIGN
49.PrepareToWriteDataFromESSI:
50    mov     bx, g_rgfnPioWrite
[169]51    mov     al, [bp+IDEPACK.bSectorCount]
52    call    InitializePiovarsInSSBPwithSectorCountInAX
[150]53    call    Registers_NormalizeESSI
[169]54    ; Fall to WriteToDrive
[150]55
56
57;--------------------------------------------------------------------
[169]58; WriteToDrive
[150]59;   Parameters:
60;       DS:DI:  Ptr to DPT (in RAMVARS segment)
61;       ES:SI:  Normalized ptr to buffer containing data
62;       SS:BP:  Ptr to PIOVARS
63;   Returns:
64;       AH:     BIOS Error code
65;       CF:     0 if transfer succesfull
66;               1 if any error
67;   Corrupts registers:
68;       AL, BX, CX, DX, SI, ES
69;--------------------------------------------------------------------
[169]70WriteToDrive:
[150]71    ; Always poll when writing first block (IRQs are generated for following blocks)
72    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
73    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
74    jc      SHORT .ReturnWithTransferErrorInAH
75ALIGN JUMP_ALIGN
76.WriteNextBlock:
77    mov     dx, [bp+PIOVARS.wDataPort]
[169]78    dec     WORD [bp+PIOVARS.wBlocksLeft]       ; Transferring last (possibly partial) block?
[150]79    jz      SHORT .XferLastBlock                ;  If so, jump to transfer
80    mov     cx, [bp+PIOVARS.wBlockSize]         ; Load block size in WORDs
81    call    [bp+PIOVARS.fnXfer]                 ; Transfer full block
[169]82
83    ; Normalize pointer when necessary
84    mov     ax, si
85    shr     ax, 1                               ; WORD offset
86    add     ax, [bp+PIOVARS.wBlockSize]
87    jns     SHORT .WaitUntilReadyToTransferNextBlock
88    call    Registers_NormalizeESSI
89
90ALIGN JUMP_ALIGN
91.WaitUntilReadyToTransferNextBlock:
[150]92%ifdef USE_186
93    push    .WriteNextBlock
94    jmp     IdeWait_IRQorDRQ
95%else
96    call    IdeWait_IRQorDRQ
97    jnc     SHORT .WriteNextBlock
98%endif
99.ReturnWithTransferErrorInAH:
100    ret
101
102ALIGN JUMP_ALIGN
103.XferLastBlock:
104    xor     cx, cx
105    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
106    mov     ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
107%ifdef USE_186
108    push    IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
109    jmp     [bp+PIOVARS.fnXfer]
110%else
111    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
112    jmp     IdeWait_IRQorStatusFlagInBLwithTimeoutInBH  ; Check for errors
113%endif
114
115
116;--------------------------------------------------------------------
[169]117; ReadFromDrive
[150]118;   Parameters:
119;       ES:DI:  Normalized ptr to buffer to recieve data
120;       DS:SI:  Ptr to DPT (in RAMVARS segment)
121;       SS:BP:  Ptr to PIOVARS
122;   Returns:
123;       DS:DI:  Ptr to DPT (in RAMVARS segment)
124;       AH:     BIOS Error code
125;       CF:     0 if transfer succesfull
126;               1 if any error
127;   Corrupts registers:
128;       AL, BX, CX, DX, SI, ES
129;--------------------------------------------------------------------
130ALIGN JUMP_ALIGN
[169]131ReadFromDrive:
[150]132    ; Wait until drive is ready to transfer
133    xchg    di, si                              ; DS:DI now points DPT
134    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
[169]135    jc      SHORT WriteToDrive.ReturnWithTransferErrorInAH
[150]136    xchg    si, di                              ; ES:DI now points buffer
137
138    ; Transfer full or last (possible partial) block
139    mov     dx, [bp+PIOVARS.wDataPort]
[169]140    dec     WORD [bp+PIOVARS.wBlocksLeft]
[150]141    jz      SHORT .XferLastBlock
142    mov     cx, [bp+PIOVARS.wBlockSize]         ; Load block size in WORDs
[169]143    call    [bp+PIOVARS.fnXfer]                 ; Transfer full block
144
145    ; Normalize pointer when necessary
146    mov     ax, di
147    shr     ax, 1                               ; WORD offset
148    add     ax, [bp+PIOVARS.wBlockSize]
149    jns     SHORT ReadFromDrive
[167]150%ifdef USE_186
[169]151    push    ReadFromDrive
152    jmp     Registers_NormalizeESDI
[167]153%else
[169]154    call    Registers_NormalizeESDI
155    jmp     SHORT ReadFromDrive                 ; Loop while blocks left
[167]156%endif
[150]157
[169]158
[150]159ALIGN JUMP_ALIGN
160.XferLastBlock:
161    xor     cx, cx
162    mov     ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
163    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
164    mov     di, si                              ; DS:DI now points DPT
165    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
166    jmp     IdeWait_PollStatusFlagInBLwithTimeoutInBH
167
168
169;--------------------------------------------------------------------
[169]170; InitializePiovarsInSSBPwithSectorCountInAX
[150]171;   Parameters:
[169]172;       AX:     Number of sectors to transfer (1...65535)
[150]173;       BX:     Offset to transfer function lookup table
174;       DS:DI:  Ptr to DPT (in RAMVARS segment)
[169]175;       SS:BP:  Ptr to PIOVARS
[167]176;   Returns:
[169]177;       Nothing
[150]178;   Corrupts registers:
179;       AX, BX, CX, DX
180;--------------------------------------------------------------------
181ALIGN JUMP_ALIGN
[169]182InitializePiovarsInSSBPwithSectorCountInAX:
[150]183    ; Store number of blocks to transfer
[169]184    eMOVZX  cx, BYTE [di+DPT_ATA.bSetBlock]     ; Block size in sectors
185    xor     dx, dx      ; DX:AX = Sectors to transfer (1...65535)
186    div     cx          ; AX = Full blocks to transfer
187    test    dx, dx
188    mov     dh, cl      ; DH = Full block size if no partial blocks to transfer
[150]189    jz      SHORT .NoPartialBlocksToTransfer
[169]190    inc     ax          ; Partial block
191    mov     dh, dl      ; DH = Size of partial block in sectors
[150]192.NoPartialBlocksToTransfer:
[169]193    mov     [bp+PIOVARS.wBlocksLeft], ax
194    mov     [bp+PIOVARS.bSectorsInLastBlock], dh
[150]195
196    ; Store block size in WORDs
197    xchg    ch, cl      ; CX = Block size in WORDs
198    mov     [bp+PIOVARS.wBlockSize], cx
199
200    ; Get transfer function based on bus type
[158]201    xchg    ax, bx                              ; Lookup table offset to AX
[150]202    eMOVZX  bx, BYTE [di+DPT.bIdevarsOffset]    ; CS:BX now points to IDEVARS
203    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
204    mov     bl, [cs:bx+IDEVARS.bDevice]         ; Load device type to BX
205    add     bx, ax
206    mov     ax, [cs:bx]                         ; Load offset to transfer function
207    mov     [bp+PIOVARS.wDataPort], dx
208    mov     [bp+PIOVARS.fnXfer], ax
209    ret
210
211
212;--------------------------------------------------------------------
[152]213; DualByteReadForXtide      Dual port 8-bit XTIDE PIO read transfer
214; SingleByteRead            Single port 8-bit PIO read transfer
215; WordReadForXTIDEmod       8088/8086 compatible 16-bit IDE PIO read transfer
216; WordReadForXTplusAndAT    Normal 16-bit IDE PIO read transfer
217; DWordRead                 VLB/PCI 32-bit IDE PIO read transfer
[150]218;   Parameters:
219;       CX:     Block size in WORDs
220;       DX:     IDE Data port address
221;       ES:DI:  Normalized ptr to buffer to recieve data
222;   Returns:
223;       Nothing
224;   Corrupts registers:
225;       AX, BX, CX
226;--------------------------------------------------------------------
227ALIGN JUMP_ALIGN
[152]228DualByteReadForXtide:
[161]229%ifdef USE_186
230    shr     cx, 2       ; Smaller but slower on 186/286
231%else
[152]232    times 2 shr cx, 1   ; Loop unrolling
[161]233%endif
[152]234    mov     bx, 8       ; Bit mask for toggling data low/high reg
[150]235ALIGN JUMP_ALIGN
236.InswLoop:
[152]237    XTIDE_INSW
238    XTIDE_INSW
239    XTIDE_INSW
240    XTIDE_INSW
[150]241    loop    .InswLoop
242    ret
243
[152]244;----
[150]245ALIGN JUMP_ALIGN
246SingleByteRead:
247%ifdef USE_186  ; INS instruction available
[152]248    shl     cx, 1       ; WORD count to BYTE count
[150]249    rep insb
250%else           ; If 8088/8086
[152]251    shr     cx, 1       ; WORD count to DWORD count
[150]252ALIGN JUMP_ALIGN
253.InsdLoop:
254    in      al, dx
[152]255    stosb               ; Store to [ES:DI]
[150]256    in      al, dx
257    stosb
258    in      al, dx
259    stosb
260    in      al, dx
261    stosb
262    loop    .InsdLoop
263%endif
264    ret
265
[152]266;----
267%ifndef USE_186
268ALIGN JUMP_ALIGN
269WordReadForXTIDEmod:
270    times 2 shr cx, 1   ; WORD count to QWORD count
271ALIGN JUMP_ALIGN
272.ReadNextQword:
273    in      ax, dx      ; Read 1st WORD
274    stosw               ; Store 1st WORD to [ES:DI]
275    in      ax, dx
276    stosw               ; 2nd
277    in      ax, dx
278    stosw               ; 3rd
279    in      ax, dx
280    stosw               ; 4th
281    loop    .ReadNextQword
282    ret
283%endif
[150]284
[152]285;----
286ALIGN JUMP_ALIGN
287WordReadForXTplusAndAT:
288    rep
289    db      6Dh         ; INSW (we want this in XT build)
290    ret
291
292;----
293ALIGN JUMP_ALIGN
294DWordRead:
295    shr     cx, 1       ; WORD count to DWORD count
296    rep
297    db      66h         ; Override operand size to 32-bit
298    db      6Dh         ; INSW/INSD
299    ret
300
301
[150]302;--------------------------------------------------------------------
[152]303; DualByteWriteForXtide     Dual port 8-bit XTIDE PIO write transfer
304; SingleByteWrite           Single port 8-bit PIO write transfer
305; WordWriteForXTIDEmod      8088/8086 compatible 16-bit IDE PIO read transfer
306; WordWrite                 Normal 16-bit IDE PIO write transfer
307; DWordWrite                VLB/PCI 32-bit IDE PIO write transfer
[150]308;   Parameters:
309;       CX:     Block size in WORDs
310;       DX:     IDE Data port address
311;       ES:SI:  Normalized ptr to buffer containing data
312;   Returns:
313;       Nothing
314;   Corrupts registers:
315;       AX, CX
316;--------------------------------------------------------------------
317ALIGN JUMP_ALIGN
[152]318DualByteWriteForXtide:
[150]319    push    ds
320    push    bx
[161]321%ifdef USE_186
322    shr     cx, 2       ; Smaller but slower on 186/286
323%else
[152]324    times 2 shr cx, 1   ; Loop unrolling
[161]325%endif
[152]326    mov     bx, 8       ; Bit mask for toggling data low/high reg
327    push    es          ; Copy ES...
328    pop     ds          ; ...to DS
[150]329ALIGN JUMP_ALIGN
330.OutswLoop:
[152]331    XTIDE_OUTSW
332    XTIDE_OUTSW
333    XTIDE_OUTSW
334    XTIDE_OUTSW
[150]335    loop    .OutswLoop
336    pop     bx
337    pop     ds
338    ret
339
[152]340;----
[150]341ALIGN JUMP_ALIGN
342SingleByteWrite:
343%ifdef USE_186  ; OUTS instruction available
[152]344    shl     cx, 1       ; WORD count to BYTE count
345    eSEG    es          ; Source is ES segment
[150]346    rep outsb
347%else           ; If 8088/8086
[152]348    shr     cx, 1       ; WORD count to DWORD count
349    push    ds          ; Store DS
350    push    es          ; Copy ES...
351    pop     ds          ; ...to DS
[150]352ALIGN JUMP_ALIGN
353.OutsdLoop:
[152]354    lodsb               ; Load from [DS:SI] to AL
[150]355    out     dx, al
356    lodsb
357    out     dx, al
358    lodsb
359    out     dx, al
360    lodsb
361    out     dx, al
362    loop    .OutsdLoop
[152]363    pop     ds          ; Restore DS
[150]364%endif
365    ret
366
[152]367;---
368ALIGN JUMP_ALIGN
369WordWriteForXTIDEmod:
370    push    ds
[161]371%ifdef USE_186
372    shr     cx, 2       ; Smaller but slower on 186/286
373%else
[152]374    times 2 shr cx, 1   ; Loop unrolling
[161]375%endif
[152]376    push    es          ; Copy ES...
377    pop     ds          ; ...to DS
378ALIGN JUMP_ALIGN
379.WriteNextQword:
380    XTIDE_MOD_OUTSW
381    XTIDE_MOD_OUTSW
382    XTIDE_MOD_OUTSW
383    XTIDE_MOD_OUTSW
384    loop    .WriteNextQword
385    pop     ds
386    ret
[150]387
[152]388;----
389ALIGN JUMP_ALIGN
390WordWrite:
391    eSEG    es          ; Source is ES segment
392    rep
[155]393    db      6Fh         ; OUTSW (we want this in XT build)
[152]394    ret
395
396ALIGN JUMP_ALIGN
397DWordWrite:
398    shr     cx, 1       ; WORD count to DWORD count
399    eSEG    es          ; Source is ES segment
400    rep
401    db      66h         ; Override operand size to 32-bit
402    db      6Fh         ; OUTSW/OUTSD
403    ret
404
405
406
[150]407; Lookup tables to get transfer function based on bus type
408ALIGN WORD_ALIGN
409g_rgfnPioRead:
[152]410    dw      DualByteReadForXtide    ; DEVICE_8BIT_DUAL_PORT_XTIDE
411%ifdef USE_186
412    dw      WordReadForXTplusAndAT  ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
413%else
414    dw      WordReadForXTIDEmod
415%endif
416    dw      SingleByteRead          ; DEVICE_8BIT_SINGLE_PORT
417    dw      WordReadForXTplusAndAT  ; DEVICE_16BIT_ATA
418    dw      DWordRead               ; DEVICE_32BIT_ATA
419
[150]420g_rgfnPioWrite:
[152]421    dw      DualByteWriteForXtide   ; DEVICE_8BIT_DUAL_PORT_XTIDE
422    dw      WordWriteForXTIDEmod    ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
423    dw      SingleByteWrite         ; DEVICE_8BIT_SINGLE_PORT
424    dw      WordWrite               ; DEVICE_16BIT_ATA
425    dw      DWordWrite              ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.