source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/JrIdeTransfer.asm @ 488

Last change on this file since 488 was 488, checked in by gregli@…, 11 years ago

Removed unused '4' entry from Strings.asm and recompressed. Added 8x multiplier value for serial drives. Wrapped some preprocessor symbol references so that 'make xt_unused' analysis continues to work.

File size: 9.6 KB
RevLine 
[400]1; Project name  :   XTIDE Universal BIOS
2; Description   :   Memory mapped IDE Device transfer functions.
3
4;
[412]5; XTIDE Universal BIOS and Associated Tools
[400]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
7;
8; This program is free software; you can redistribute it and/or modify
9; it under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2 of the License, or
11; (at your option) any later version.
[412]12;
[400]13; This program is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
[412]16; GNU General Public License for more details.
[400]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[412]18;
[400]19
20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
[414]22struc MEMPIOVARS    ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23    .wSectorsInBlock        resb    2   ; 0-1, Block size in sectors
24    .fpDPT                  resb    4   ; 2-5, Far pointer to DPT
25    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
[400]26                            resb    1   ; 7, IDEPACK.bDeviceControl
[414]27    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
[400]28endstruc
29
[473]30SECTOR_ACCESS_WINDOW_SIZE   EQU     512 ; 512 bytes
[400]31
[473]32
[400]33; Section containing code
34SECTION .text
35
36;--------------------------------------------------------------------
37; JrIdeTransfer_StartWithCommandInAL
38;   Parameters:
39;       AL:     IDE command that was used to start the transfer
40;               (all PIO read and write commands including Identify Device)
[480]41;       ES:SI:  Ptr to data buffer
[400]42;       DS:DI:  Ptr to DPT (in RAMVARS segment)
43;       SS:BP:  Ptr to IDEPACK
44;   Returns:
45;       AH:     INT 13h Error Code
46;       CX:     Number of successfully transferred sectors
47;       CF:     Cleared if success, Set if error
48;   Corrupts registers:
49;       AL, BX, DX, SI, ES
50;--------------------------------------------------------------------
51ALIGN JUMP_ALIGN
52JrIdeTransfer_StartWithCommandInAL:
[473]53    ; Initialize MEMPIOVARS
54    xchg    cx, ax          ; IDE command to CL
55    xor     ax, ax
56    mov     [bp+MEMPIOVARS.bSectorsDone], al
57    mov     al, [bp+IDEPACK.bSectorCount]
58    mov     [bp+MEMPIOVARS.bSectorsLeft], al
59    mov     al, [di+DPT_ATA.bBlockSize]
60    mov     [bp+MEMPIOVARS.wSectorsInBlock], ax
[400]61    mov     [bp+MEMPIOVARS.fpDPT], di
62    mov     [bp+MEMPIOVARS.fpDPT+2], ds
63
[480]64    ; Normalize pointer
65    call    IdeTransfer_NormalizePointerInESSI
66
[473]67    ; Get far pointer to Sector Access Window
68    mov     dx, [di+DPT.wBasePort]
69    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
70    jne     SHORT .GetSectorAccessWindowForXTCF
71
72    ; Get Sector Access Window for JR-IDE/ISA
73    mov     di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
74    mov     ds, dx      ; Segment for JR-IDE/ISA
75    jmp     SHORT .SectorAccessWindowLoadedToDSDI
76
77.GetSectorAccessWindowForXTCF:
78    xor     di, di
79    add     dl, XTCF_CONTROL_REGISTER
80    in      al, dx                  ; Read high byte for Sector Access Window segment
81    xchg    ah, al
82    mov     ds, ax
83
[400]84    ; Are we reading or writing?
[473]85.SectorAccessWindowLoadedToDSDI:
86    test    cl, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[400]87    jnz     SHORT WriteToSectorAccessWindow
[473]88    cmp     cl, COMMAND_WRITE_MULTIPLE
[400]89    je      SHORT WriteToSectorAccessWindow
90    ; Fall to ReadFromSectorAccessWindow
91
92;--------------------------------------------------------------------
93; ReadFromSectorAccessWindow
94;   Parameters:
[473]95;       DS:DI:  Ptr to Sector Access Window
[400]96;       ES:SI:  Normalized ptr to buffer to receive data
97;       SS:BP:  Ptr to MEMPIOVARS
98;   Returns:
99;       DS:DI:  Ptr to DPT (in RAMVARS segment)
100;       AH:     BIOS Error code
101;       CX:     Number of successfully transferred sectors
102;       CF:     0 if transfer successful
103;               1 if any error
104;   Corrupts registers:
[475]105;       AL, BX, DX, SI
[400]106;--------------------------------------------------------------------
107ReadFromSectorAccessWindow:
[473]108    xchg    si, di  ; DS:SI = source, ES:DI = Destination
[400]109    call    WaitUntilReadyToTransferNextBlock
110    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
111
[475]112    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears CH
[412]113    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
114    jbe     SHORT .ReadLastBlockFromDrive
[400]115
116ALIGN JUMP_ALIGN
117.ReadNextBlockFromDrive:
118    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
119    call    WaitUntilReadyToTransferNextBlock
120    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
121
[476]122    ; Update number of successfully read sectors and sectors left to transfer.
123    ; We cannot use SUB instruction as a comparison since it will not
124    ; work in this situation:
125    ; Before SUB we have 2 full blocks left to transfer. SUB command
126    ; then compares 2 full blocks against one full block and updates
127    ; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
128    ; since we have one full block left to transfer. After it has been
129    ; transferred, there will be a wait for next block but DRQ is never
130    ; set since all is transferred! Then we get timeout error.
[400]131    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]132    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]133    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]134    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]135    ja      SHORT .ReadNextBlockFromDrive
[400]136
137ALIGN JUMP_ALIGN
138.ReadLastBlockFromDrive:
139    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]140    push    cx
[400]141    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
142
143    ; Check for errors in last block
144CheckErrorsAfterTransferringLastMemoryMappedBlock:
145    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
[417]146    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[400]147    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]148    pop     cx  ; [bp+MEMPIOVARS.bSectorsLeft]
149    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
[400]150
[445]151    ; All sectors successfully transferred
[475]152    add     cl, [bp+MEMPIOVARS.bSectorsDone]    ; Never sets CF
[419]153    ret
154
[400]155    ; Return number of successfully transferred sectors
156ReturnWithMemoryIOtransferErrorInAH:
157    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
158%ifdef USE_386
[475]159    movzx   cx, BYTE [bp+MEMPIOVARS.bSectorsDone]
[400]160%else
[475]161    mov     ch, 0                               ; Preserve CF
[400]162    mov     cl, [bp+MEMPIOVARS.bSectorsDone]
163%endif
164    ret
165
166
167;--------------------------------------------------------------------
168; WriteToSectorAccessWindow
169;   Parameters:
[473]170;       DS:DI:  Ptr to Sector Access Window
[400]171;       ES:SI:  Normalized ptr to buffer containing data
172;       SS:BP:  Ptr to MEMPIOVARS
173;   Returns:
174;       DS:DI:  Ptr to DPT (in RAMVARS segment)
175;       AH:     BIOS Error code
176;       CX:     Number of successfully transferred sectors
177;       CF:     0 if transfer successful
178;               1 if any error
179;   Corrupts registers:
180;       AL, BX, DX, SI, ES
181;--------------------------------------------------------------------
182ALIGN JUMP_ALIGN
183WriteToSectorAccessWindow:
184    push    es
[473]185    push    ds
186    pop     es      ; ES:DI = Sector Access Window (destination)
187    pop     ds      ; DS:SI = Ptr to source buffer
[400]188
189    ; Always poll when writing first block (IRQs are generated for following blocks)
190    call    WaitUntilReadyToTransferNextBlock
191    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
192
193    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[412]194    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
195    jbe     SHORT .WriteLastBlockToDrive
[400]196
197ALIGN JUMP_ALIGN
198.WriteNextBlockToDrive:
199    call    WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
200    call    WaitUntilReadyToTransferNextBlock
201    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
202
203    ; Increment number of successfully written WORDs
204    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]205    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]206    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]207    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]208    ja      SHORT .WriteNextBlockToDrive
[400]209
210ALIGN JUMP_ALIGN
211.WriteLastBlockToDrive:
212    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]213    push    cx
[400]214    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
215    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
216
217;--------------------------------------------------------------------
218; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
219;   Parameters:
220;       CX:     Number of sectors in block
221;       DS:SI:  Normalized ptr to source buffer
222;       ES:DI:  Ptr to Sector Access Window
223;   Returns:
224;       CX, DX: Zero
225;       SI:     Updated
226;   Corrupts registers:
227;       BX
228;--------------------------------------------------------------------
229ALIGN JUMP_ALIGN
230WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
231    mov     bx, di
232    mov     dx, cx
233    xor     cl, cl
234ALIGN JUMP_ALIGN
[475]235.WriteNextSector:
[473]236    mov     ch, SECTOR_ACCESS_WINDOW_SIZE >> 9
[400]237    rep movsw
238    mov     di, bx  ; Reset for next sector
239    dec     dx
[475]240    jnz     SHORT .WriteNextSector
[400]241    ret
242
243
244;--------------------------------------------------------------------
245; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
246;   Parameters:
[475]247;       CX      Number of sectors in full block or sectors in last partial block
[400]248;       ES:DI:  Normalized ptr to buffer to receive data (destination)
249;       DS:SI:  Ptr to Sector Access Window (source)
250;   Returns:
251;       CX, DX: Zero
252;       DI:     Updated
253;   Corrupts registers:
254;       BX
255;--------------------------------------------------------------------
256ALIGN JUMP_ALIGN
257ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
258    mov     bx, si
259    mov     dx, cx
260    xor     cl, cl
261ALIGN JUMP_ALIGN
[475]262.ReadNextSector:
[473]263    mov     ch, SECTOR_ACCESS_WINDOW_SIZE >> 9
[400]264    rep movsw
265    mov     si, bx  ; Reset for next sector
266    dec     dx
[475]267    jnz     SHORT .ReadNextSector
[400]268    ret
269
270
271;--------------------------------------------------------------------
272; WaitUntilReadyToTransferNextBlock
273;   Parameters:
274;       SS:BP:  Ptr to MEMPIOVARS
275;   Returns:
276;       AH:     INT 13h Error Code
277;       CF:     Cleared if success, Set if error
278;   Corrupts registers:
279;       AL, BX, CX, DX
280;--------------------------------------------------------------------
281ALIGN JUMP_ALIGN
282WaitUntilReadyToTransferNextBlock:
283    push    ds
284    push    di
285    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
286    call    IdeWait_IRQorDRQ            ; Always polls
287    pop     di
288    pop     ds
289    ret
290
291
[488]292%ifndef CHECK_FOR_UNUSED_ENTRYPOINTS       
[473]293%if SECTOR_ACCESS_WINDOW_SIZE <> 512
294    %error "SECTOR_ACCESS_WINDOW_SIZE is no longer equal to 512. JrIdeTransfer.asm needs changes."
[400]295%endif
[488]296%endif
Note: See TracBrowser for help on using the repository browser.