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

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

Changes:

  • Fixed what appears to be a mistake in EBIOS.inc
  • Added a 'release' option to the makefile of the Serial Server (invokes UPX)
  • Some very minor optimizations
  • Removed the eSEG macro and did some other cleanups (fixed typos etc)
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]
[150]99    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
100
[218]101    ; Check for errors in last block
102    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
103    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
104    jmp     SHORT ReturnWithTransferErrorInAH
[150]105
[218]106
[150]107;--------------------------------------------------------------------
[169]108; ReadFromDrive
[150]109;   Parameters:
110;       ES:DI:  Normalized ptr to buffer to recieve data
111;       DS:SI:  Ptr to DPT (in RAMVARS segment)
112;       SS:BP:  Ptr to PIOVARS
113;   Returns:
114;       DS:DI:  Ptr to DPT (in RAMVARS segment)
115;       AH:     BIOS Error code
[218]116;       CX:     Number of successfully transferred sectors
[150]117;       CF:     0 if transfer succesfull
118;               1 if any error
119;   Corrupts registers:
[218]120;       AL, BX, DX, SI, ES
[150]121;--------------------------------------------------------------------
122ALIGN JUMP_ALIGN
[169]123ReadFromDrive:
[150]124    ; Wait until drive is ready to transfer
125    xchg    di, si                              ; DS:DI now points DPT
126    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
[218]127    jc      SHORT ReturnWithTransferErrorInAH
[150]128    xchg    si, di                              ; ES:DI now points buffer
129
[218]130ALIGN JUMP_ALIGN
131.ReadNextBlockFromDrive:
132    mov     cx, [bp+PIOVARS.wWordsInBlock]
[150]133    mov     dx, [bp+PIOVARS.wDataPort]
[218]134    cmp     [bp+PIOVARS.wWordsLeft], cx
135    jbe     SHORT .ReadLastBlockFromDrive
136    call    [bp+PIOVARS.fnXfer]
[169]137
[218]138    ; Wait until ready for next block and check for errors
139    xchg    di, si                              ; DS:DI now points DPT
140    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
141    jc      SHORT ReturnWithTransferErrorInAH
142    xchg    si, di                              ; ES:DI now points buffer
[150]143
[218]144    ; Increment number of successfully read WORDs
145    mov     ax, [bp+PIOVARS.wWordsInBlock]
146    sub     [bp+PIOVARS.wWordsLeft], ax
147    add     [bp+PIOVARS.wWordsDone], ax
148    jmp     SHORT .ReadNextBlockFromDrive
[169]149
[150]150ALIGN JUMP_ALIGN
[218]151.ReadLastBlockFromDrive:
152    mov     cx, [bp+PIOVARS.wWordsLeft]
[150]153    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
[218]154
155    ; Check for errors in last block
[150]156    mov     di, si                              ; DS:DI now points DPT
157    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
[218]158    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[150]159
[218]160    ; Return number of successfully read sectors
161ReturnWithTransferErrorInAH:
162    mov     cx, [bp+PIOVARS.wWordsDone]
163    jc      SHORT .ConvertTransferredWordsInCXtoSectors
164    add     cx, [bp+PIOVARS.wWordsLeft]         ; Never sets CF
165.ConvertTransferredWordsInCXtoSectors:
166    xchg    cl, ch
167    ret
[150]168
[218]169
[150]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:
180;       AX, BX, CX, DX
181;--------------------------------------------------------------------
182ALIGN JUMP_ALIGN
[218]183InitializePiovarsInSSBPwithSectorCountInAH:
184    ; Store sizes
185    xor     al, al
186    mov     [bp+PIOVARS.wWordsLeft], ax
187    cbw
188    mov     [bp+PIOVARS.wWordsDone], ax         ; Zero
189    mov     ah, [di+DPT_ATA.bSetBlock]
190    mov     [bp+PIOVARS.wWordsInBlock], ax
[150]191
192    ; Get transfer function based on bus type
[158]193    xchg    ax, bx                              ; Lookup table offset to AX
[150]194    eMOVZX  bx, BYTE [di+DPT.bIdevarsOffset]    ; CS:BX now points to IDEVARS
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
198    mov     ax, [cs:bx]                         ; Load offset to transfer function
199    mov     [bp+PIOVARS.wDataPort], dx
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
213;       ES:DI:  Normalized ptr to buffer to recieve data
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
[152]236    shl     cx, 1       ; WORD count to BYTE count
[150]237    rep insb
238%else           ; If 8088/8086
[152]239    shr     cx, 1       ; WORD count to DWORD count
[150]240ALIGN JUMP_ALIGN
241.InsdLoop:
242    in      al, dx
[152]243    stosb               ; Store to [ES:DI]
[150]244    in      al, dx
245    stosb
246    in      al, dx
247    stosb
248    in      al, dx
249    stosb
250    loop    .InsdLoop
251%endif
252    ret
253
[152]254;----
255%ifndef USE_186
256ALIGN JUMP_ALIGN
257WordReadForXTIDEmod:
258    times 2 shr cx, 1   ; WORD count to QWORD count
259ALIGN JUMP_ALIGN
260.ReadNextQword:
261    in      ax, dx      ; Read 1st WORD
262    stosw               ; Store 1st WORD to [ES:DI]
263    in      ax, dx
264    stosw               ; 2nd
265    in      ax, dx
266    stosw               ; 3rd
267    in      ax, dx
268    stosw               ; 4th
269    loop    .ReadNextQword
270    ret
271%endif
[150]272
[152]273;----
274ALIGN JUMP_ALIGN
275WordReadForXTplusAndAT:
276    rep
277    db      6Dh         ; INSW (we want this in XT build)
278    ret
279
280;----
281ALIGN JUMP_ALIGN
282DWordRead:
283    shr     cx, 1       ; WORD count to DWORD count
284    rep
285    db      66h         ; Override operand size to 32-bit
286    db      6Dh         ; INSW/INSD
287    ret
288
289
[150]290;--------------------------------------------------------------------
[152]291; DualByteWriteForXtide     Dual port 8-bit XTIDE PIO write transfer
292; SingleByteWrite           Single port 8-bit PIO write transfer
293; WordWriteForXTIDEmod      8088/8086 compatible 16-bit IDE PIO read transfer
294; WordWrite                 Normal 16-bit IDE PIO write transfer
295; DWordWrite                VLB/PCI 32-bit IDE PIO write transfer
[150]296;   Parameters:
297;       CX:     Block size in WORDs
298;       DX:     IDE Data port address
299;       ES:SI:  Normalized ptr to buffer containing data
300;   Returns:
301;       Nothing
302;   Corrupts registers:
303;       AX, CX
304;--------------------------------------------------------------------
305ALIGN JUMP_ALIGN
[152]306DualByteWriteForXtide:
[150]307    push    ds
308    push    bx
[181]309    eSHR_IM cx, 2       ; Loop unrolling
[152]310    mov     bx, 8       ; Bit mask for toggling data low/high reg
311    push    es          ; Copy ES...
312    pop     ds          ; ...to DS
[150]313ALIGN JUMP_ALIGN
314.OutswLoop:
[152]315    XTIDE_OUTSW
316    XTIDE_OUTSW
317    XTIDE_OUTSW
318    XTIDE_OUTSW
[150]319    loop    .OutswLoop
320    pop     bx
321    pop     ds
322    ret
323
[152]324;----
[150]325ALIGN JUMP_ALIGN
326SingleByteWrite:
327%ifdef USE_186  ; OUTS instruction available
[152]328    shl     cx, 1       ; WORD count to BYTE count
[223]329    es                  ; Source is ES segment
[150]330    rep outsb
331%else           ; If 8088/8086
[152]332    shr     cx, 1       ; WORD count to DWORD count
333    push    ds          ; Store DS
334    push    es          ; Copy ES...
335    pop     ds          ; ...to DS
[150]336ALIGN JUMP_ALIGN
337.OutsdLoop:
[152]338    lodsb               ; Load from [DS:SI] to AL
[150]339    out     dx, al
340    lodsb
341    out     dx, al
342    lodsb
343    out     dx, al
344    lodsb
345    out     dx, al
346    loop    .OutsdLoop
[152]347    pop     ds          ; Restore DS
[150]348%endif
349    ret
350
[152]351;---
352ALIGN JUMP_ALIGN
353WordWriteForXTIDEmod:
354    push    ds
[181]355    eSHR_IM cx, 2       ; Loop unrolling
[152]356    push    es          ; Copy ES...
357    pop     ds          ; ...to DS
358ALIGN JUMP_ALIGN
359.WriteNextQword:
360    XTIDE_MOD_OUTSW
361    XTIDE_MOD_OUTSW
362    XTIDE_MOD_OUTSW
363    XTIDE_MOD_OUTSW
364    loop    .WriteNextQword
365    pop     ds
366    ret
[150]367
[152]368;----
369ALIGN JUMP_ALIGN
370WordWrite:
[223]371    es                  ; Source is ES segment
[152]372    rep
[155]373    db      6Fh         ; OUTSW (we want this in XT build)
[152]374    ret
375
376ALIGN JUMP_ALIGN
377DWordWrite:
378    shr     cx, 1       ; WORD count to DWORD count
[223]379    es                  ; Source is ES segment
[152]380    rep
381    db      66h         ; Override operand size to 32-bit
382    db      6Fh         ; OUTSW/OUTSD
383    ret
384
385
386
[150]387; Lookup tables to get transfer function based on bus type
388ALIGN WORD_ALIGN
389g_rgfnPioRead:
[152]390    dw      DualByteReadForXtide    ; DEVICE_8BIT_DUAL_PORT_XTIDE
391%ifdef USE_186
392    dw      WordReadForXTplusAndAT  ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
393%else
394    dw      WordReadForXTIDEmod
395%endif
396    dw      SingleByteRead          ; DEVICE_8BIT_SINGLE_PORT
397    dw      WordReadForXTplusAndAT  ; DEVICE_16BIT_ATA
398    dw      DWordRead               ; DEVICE_32BIT_ATA
399
[150]400g_rgfnPioWrite:
[152]401    dw      DualByteWriteForXtide   ; DEVICE_8BIT_DUAL_PORT_XTIDE
402    dw      WordWriteForXTIDEmod    ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
403    dw      SingleByteWrite         ; DEVICE_8BIT_SINGLE_PORT
404    dw      WordWrite               ; DEVICE_16BIT_ATA
405    dw      DWordWrite              ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.