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

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

Changes:

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