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

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

Changes to XTIDE Universal BIOS:

  • Integrated XT-CFv3 support by James Pearce.
  • XT-CFv2 memory mapped I/O and DMA modes are no longer supported (but PIO mode is).
File size: 9.1 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
[526]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[400]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
30
31; Section containing code
32SECTION .text
33
34;--------------------------------------------------------------------
35; JrIdeTransfer_StartWithCommandInAL
36;   Parameters:
37;       AL:     IDE command that was used to start the transfer
38;               (all PIO read and write commands including Identify Device)
[480]39;       ES:SI:  Ptr to data buffer
[400]40;       DS:DI:  Ptr to DPT (in RAMVARS segment)
41;       SS:BP:  Ptr to IDEPACK
42;   Returns:
43;       AH:     INT 13h Error Code
44;       CX:     Number of successfully transferred sectors
45;       CF:     Cleared if success, Set if error
46;   Corrupts registers:
47;       AL, BX, DX, SI, ES
48;--------------------------------------------------------------------
49ALIGN JUMP_ALIGN
50JrIdeTransfer_StartWithCommandInAL:
[473]51    ; Initialize MEMPIOVARS
52    xchg    cx, ax          ; IDE command to CL
53    xor     ax, ax
54    mov     [bp+MEMPIOVARS.bSectorsDone], al
[538]55    mov     dh, [bp+IDEPACK.bSectorCount]
56    mov     [bp+MEMPIOVARS.bSectorsLeft], dh
[473]57    mov     al, [di+DPT_ATA.bBlockSize]
58    mov     [bp+MEMPIOVARS.wSectorsInBlock], ax
[400]59    mov     [bp+MEMPIOVARS.fpDPT], di
60    mov     [bp+MEMPIOVARS.fpDPT+2], ds
61
[480]62    ; Normalize pointer
63    call    IdeTransfer_NormalizePointerInESSI
[538]64%ifdef USE_AT
65    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
66%endif
[480]67
[473]68    ; Get far pointer to Sector Access Window
69    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
[545]70    mov     ds, [di+DPT.wBasePort]  ; Segment for JR-IDE/ISA and ADP50L
[536]71    mov     di, ADP50L_SECTOR_ACCESS_WINDOW_OFFSET
[545]72    eCMOVE  di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
[473]73
[400]74    ; Are we reading or writing?
[473]75.SectorAccessWindowLoadedToDSDI:
76    test    cl, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[400]77    jnz     SHORT WriteToSectorAccessWindow
[473]78    cmp     cl, COMMAND_WRITE_MULTIPLE
[400]79    je      SHORT WriteToSectorAccessWindow
80    ; Fall to ReadFromSectorAccessWindow
81
82;--------------------------------------------------------------------
83; ReadFromSectorAccessWindow
84;   Parameters:
[473]85;       DS:DI:  Ptr to Sector Access Window
[400]86;       ES:SI:  Normalized ptr to buffer to receive data
87;       SS:BP:  Ptr to MEMPIOVARS
88;   Returns:
89;       DS:DI:  Ptr to DPT (in RAMVARS segment)
90;       AH:     BIOS Error code
91;       CX:     Number of successfully transferred sectors
92;       CF:     0 if transfer successful
93;               1 if any error
94;   Corrupts registers:
[475]95;       AL, BX, DX, SI
[400]96;--------------------------------------------------------------------
97ReadFromSectorAccessWindow:
[473]98    xchg    si, di  ; DS:SI = source, ES:DI = Destination
[400]99    call    WaitUntilReadyToTransferNextBlock
100    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
101
[475]102    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears CH
[412]103    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
104    jbe     SHORT .ReadLastBlockFromDrive
[400]105
106ALIGN JUMP_ALIGN
107.ReadNextBlockFromDrive:
108    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
109    call    WaitUntilReadyToTransferNextBlock
110    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
111
[476]112    ; Update number of successfully read sectors and sectors left to transfer.
113    ; We cannot use SUB instruction as a comparison since it will not
114    ; work in this situation:
115    ; Before SUB we have 2 full blocks left to transfer. SUB command
116    ; then compares 2 full blocks against one full block and updates
117    ; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
118    ; since we have one full block left to transfer. After it has been
119    ; transferred, there will be a wait for next block but DRQ is never
120    ; set since all is transferred! Then we get timeout error.
[400]121    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]122    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]123    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]124    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]125    ja      SHORT .ReadNextBlockFromDrive
[400]126
127ALIGN JUMP_ALIGN
128.ReadLastBlockFromDrive:
129    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]130    push    cx
[400]131    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
132
133    ; Check for errors in last block
134CheckErrorsAfterTransferringLastMemoryMappedBlock:
135    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
[417]136    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[400]137    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]138    pop     cx  ; [bp+MEMPIOVARS.bSectorsLeft]
139    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
[400]140
[445]141    ; All sectors successfully transferred
[475]142    add     cl, [bp+MEMPIOVARS.bSectorsDone]    ; Never sets CF
[419]143    ret
144
[400]145    ; Return number of successfully transferred sectors
146ReturnWithMemoryIOtransferErrorInAH:
147    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
148%ifdef USE_386
[475]149    movzx   cx, BYTE [bp+MEMPIOVARS.bSectorsDone]
[400]150%else
[475]151    mov     ch, 0                               ; Preserve CF
[400]152    mov     cl, [bp+MEMPIOVARS.bSectorsDone]
153%endif
154    ret
155
156
157;--------------------------------------------------------------------
158; WriteToSectorAccessWindow
159;   Parameters:
[473]160;       DS:DI:  Ptr to Sector Access Window
[400]161;       ES:SI:  Normalized ptr to buffer containing data
162;       SS:BP:  Ptr to MEMPIOVARS
163;   Returns:
164;       DS:DI:  Ptr to DPT (in RAMVARS segment)
165;       AH:     BIOS Error code
166;       CX:     Number of successfully transferred sectors
167;       CF:     0 if transfer successful
168;               1 if any error
169;   Corrupts registers:
170;       AL, BX, DX, SI, ES
171;--------------------------------------------------------------------
172ALIGN JUMP_ALIGN
173WriteToSectorAccessWindow:
174    push    es
[473]175    push    ds
176    pop     es      ; ES:DI = Sector Access Window (destination)
177    pop     ds      ; DS:SI = Ptr to source buffer
[400]178
179    ; Always poll when writing first block (IRQs are generated for following blocks)
180    call    WaitUntilReadyToTransferNextBlock
181    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
182
183    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[412]184    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
185    jbe     SHORT .WriteLastBlockToDrive
[400]186
187ALIGN JUMP_ALIGN
188.WriteNextBlockToDrive:
189    call    WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
190    call    WaitUntilReadyToTransferNextBlock
191    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
192
193    ; Increment number of successfully written WORDs
194    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]195    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]196    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]197    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]198    ja      SHORT .WriteNextBlockToDrive
[400]199
200ALIGN JUMP_ALIGN
201.WriteLastBlockToDrive:
202    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]203    push    cx
[400]204    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
205    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
206
207;--------------------------------------------------------------------
208; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
209;   Parameters:
210;       CX:     Number of sectors in block
211;       DS:SI:  Normalized ptr to source buffer
212;       ES:DI:  Ptr to Sector Access Window
213;   Returns:
214;       CX, DX: Zero
215;       SI:     Updated
216;   Corrupts registers:
217;       BX
218;--------------------------------------------------------------------
219ALIGN JUMP_ALIGN
220WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
221    mov     bx, di
222    mov     dx, cx
[536]223    xor     cx, cx
[400]224ALIGN JUMP_ALIGN
[475]225.WriteNextSector:
[536]226    inc     ch
[400]227    rep movsw
228    mov     di, bx  ; Reset for next sector
229    dec     dx
[475]230    jnz     SHORT .WriteNextSector
[400]231    ret
232
233
234;--------------------------------------------------------------------
235; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
236;   Parameters:
[475]237;       CX      Number of sectors in full block or sectors in last partial block
[400]238;       ES:DI:  Normalized ptr to buffer to receive data (destination)
239;       DS:SI:  Ptr to Sector Access Window (source)
240;   Returns:
241;       CX, DX: Zero
242;       DI:     Updated
243;   Corrupts registers:
244;       BX
245;--------------------------------------------------------------------
246ALIGN JUMP_ALIGN
247ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
248    mov     bx, si
249    mov     dx, cx
[536]250    xor     cx, cx
[400]251ALIGN JUMP_ALIGN
[475]252.ReadNextSector:
[536]253    inc     ch
[400]254    rep movsw
255    mov     si, bx  ; Reset for next sector
256    dec     dx
[475]257    jnz     SHORT .ReadNextSector
[400]258    ret
259
260
261;--------------------------------------------------------------------
262; WaitUntilReadyToTransferNextBlock
263;   Parameters:
264;       SS:BP:  Ptr to MEMPIOVARS
265;   Returns:
266;       AH:     INT 13h Error Code
267;       CF:     Cleared if success, Set if error
268;   Corrupts registers:
269;       AL, BX, CX, DX
270;--------------------------------------------------------------------
271ALIGN JUMP_ALIGN
272WaitUntilReadyToTransferNextBlock:
273    push    ds
274    push    di
275    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
276    call    IdeWait_IRQorDRQ            ; Always polls
277    pop     di
278    pop     ds
279    ret
280
Note: See TracBrowser for help on using the repository browser.