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

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

Changes:

  • Added support for the Silicon Valley Computer ADP50L controller (and possibly other IDE controllers from SVC using memory mapped I/O). Please note that this has not been tested in any way since I don't have any of these cards myself (make backups before trying this on drives with important data). Also, *if* it works, make sure it works reliably (stress test the disk system). Some things you should know: 1) Autodetection for this controller has not been added to XTIDECFG, you need to manually select the "SVC ADP50L" controller (and possibly change the BIOS segment address if not using the default of C800h). 2) The memory mapped I/O window is inside the ROM address space of the controller. The XTIDE Universal BIOS currently do not support this so that means you need to use another ROM (for example, an XTIDE or XTCF card or the BOOT ROM of a NIC). This presents another problem, the original ADP50L BIOS needs to be disabled somehow to avoid conflicts. Either pull the ROM chip or disable the BIOS by removing jumper J3. Note, I have no idea if any of this will actually work. It's basically a shot in the dark.
File size: 9.4 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
55    mov     al, [bp+IDEPACK.bSectorCount]
56    mov     [bp+MEMPIOVARS.bSectorsLeft], al
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
64
[473]65    ; Get far pointer to Sector Access Window
66    mov     dx, [di+DPT.wBasePort]
67    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
[536]68    jb      SHORT .GetSectorAccessWindowForXTCF
[473]69
[536]70    ; Get Sector Access Window for JR-IDE/ISA and ADP50L
71    mov     ds, dx      ; Segment for JR-IDE/ISA and ADP50L
[473]72    mov     di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
[536]73    je      SHORT .SectorAccessWindowLoadedToDSDI
74    mov     di, ADP50L_SECTOR_ACCESS_WINDOW_OFFSET
[473]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
[536]233    xor     cx, cx
[400]234ALIGN JUMP_ALIGN
[475]235.WriteNextSector:
[536]236    inc     ch
[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
[536]260    xor     cx, cx
[400]261ALIGN JUMP_ALIGN
[475]262.ReadNextSector:
[536]263    inc     ch
[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
Note: See TracBrowser for help on using the repository browser.