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

Last change on this file since 601 was 601, checked in by krille_n_, 5 years ago

Changes:

  • Building the BIOS now works again.
  • Added a new IDE device type/transfer mode for use only with XT-IDE rev 2+ (or Chuck(G)-modded rev 1) cards installed in any of the following machines: Olivetti M24, AT&T PC6300, Xerox 6060 and Logabax Persona 1600. This new transfer mode is slightly faster than the regular XT-IDE rev 1 device type and requires that the card is configured for High Speed mode (or, in case of the card being a rev 1 card, has the Chuck(G) mod done). The new device type is called "XTIDE rev 2 (Olivetti M24)" in XTIDECFG.
  • Made some minor improvements to the library code that handles 'Drive Not Ready' errors in XTIDECFG.
  • Optimizations.
File size: 9.0 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
[601]102    mov     dx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears DH
103    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
[412]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.
[601]121    mov     dx, [bp+MEMPIOVARS.wSectorsInBlock]
122    sub     [bp+MEMPIOVARS.bSectorsLeft], dl
123    add     [bp+MEMPIOVARS.bSectorsDone], dl
124    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
[412]125    ja      SHORT .ReadNextBlockFromDrive
[400]126
127ALIGN JUMP_ALIGN
128.ReadLastBlockFromDrive:
[601]129    mov     dl, [bp+MEMPIOVARS.bSectorsLeft]
130    push    dx
[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
[592]149    movzx   cx, [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
[601]183    mov     dx, [bp+MEMPIOVARS.wSectorsInBlock]
184    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
[412]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
[601]194    mov     dx, [bp+MEMPIOVARS.wSectorsInBlock]
195    sub     [bp+MEMPIOVARS.bSectorsLeft], dl
196    add     [bp+MEMPIOVARS.bSectorsDone], dl
197    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
[412]198    ja      SHORT .WriteNextBlockToDrive
[400]199
200ALIGN JUMP_ALIGN
201.WriteLastBlockToDrive:
[601]202    mov     dl, [bp+MEMPIOVARS.bSectorsLeft]
203    push    dx
[400]204    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
205    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
206
207;--------------------------------------------------------------------
208; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
209;   Parameters:
[601]210;       DX:     Number of sectors in block
[400]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
[536]222    xor     cx, cx
[400]223ALIGN JUMP_ALIGN
[475]224.WriteNextSector:
[536]225    inc     ch
[400]226    rep movsw
227    mov     di, bx  ; Reset for next sector
228    dec     dx
[475]229    jnz     SHORT .WriteNextSector
[400]230    ret
231
232
233;--------------------------------------------------------------------
234; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
235;   Parameters:
[601]236;       DX:     Number of sectors in block
237;       ES:DI:  Normalized ptr to destination buffer
238;       DS:SI:  Ptr to Sector Access Window
[400]239;   Returns:
240;       CX, DX: Zero
241;       DI:     Updated
242;   Corrupts registers:
243;       BX
244;--------------------------------------------------------------------
245ALIGN JUMP_ALIGN
246ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
247    mov     bx, si
[536]248    xor     cx, cx
[400]249ALIGN JUMP_ALIGN
[475]250.ReadNextSector:
[536]251    inc     ch
[400]252    rep movsw
253    mov     si, bx  ; Reset for next sector
254    dec     dx
[475]255    jnz     SHORT .ReadNextSector
[400]256    ret
257
258
259;--------------------------------------------------------------------
260; WaitUntilReadyToTransferNextBlock
261;   Parameters:
262;       SS:BP:  Ptr to MEMPIOVARS
263;   Returns:
264;       AH:     INT 13h Error Code
265;       CF:     Cleared if success, Set if error
266;   Corrupts registers:
267;       AL, BX, CX, DX
268;--------------------------------------------------------------------
269ALIGN JUMP_ALIGN
270WaitUntilReadyToTransferNextBlock:
271    push    ds
272    push    di
273    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
274    call    IdeWait_IRQorDRQ            ; Always polls
275    pop     di
276    pop     ds
277    ret
278
Note: See TracBrowser for help on using the repository browser.