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

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

Changes to XTIDE Universal BIOS:

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