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

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

Changes to XTIDE Universal BIOS:

  • AT builds now relocate INT 13h stack to top of stolen conventional memory.
  • Some small fixes here and there.
File size: 12.5 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device transfer functions.
3
4;
5; XTIDE Universal BIOS and Associated Tools 
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.
12; 
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
16; GNU General Public License for more details.     
17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18;       
19
20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
22struc PIOVARS   ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23    .wDataPort              resb    2   ; 0-1, IDE Data Port
24    .fnXfer                 resb    2   ; 2-3, Offset to transfer function
25    .wSectorsInBlock        resb    2   ; 4-5, Block size in sectors
26    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
27                            resb    1   ; 7, IDEPACK.bDeviceControl
28    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
29endstruc
30
31
32; Section containing code
33SECTION .text
34
35;--------------------------------------------------------------------
36; IdeTransfer_StartWithCommandInAL
37;   Parameters:
38;       AL:     IDE command that was used to start the transfer
39;               (all PIO read and write commands including Identify Device)
40;       ES:SI:  Ptr to normalized data buffer
41;       DS:DI:  Ptr to DPT (in RAMVARS segment)
42;       SS:BP:  Ptr to IDEPACK
43;   Returns:
44;       AH:     INT 13h Error Code
45;       CX:     Number of successfully transferred sectors
46;       CF:     Cleared if success, Set if error
47;   Corrupts registers:
48;       AL, BX, DX, SI, ES
49;--------------------------------------------------------------------
50ALIGN JUMP_ALIGN
51IdeTransfer_StartWithCommandInAL:
52    ; Are we reading or writing?
53    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
54    mov     ah, [bp+IDEPACK.bSectorCount]
55    jnz     SHORT WriteToDrive
56    cmp     al, COMMAND_WRITE_MULTIPLE
57    je      SHORT WriteToDrive
58    ; Fall to ReadFromDrive
59
60;--------------------------------------------------------------------
61; ReadFromDrive
62;   Parameters:
63;       AH:     Number of sectors to transfer (1...128)
64;       ES:SI:  Normalized ptr to buffer to receive data
65;       DS:DI:  Ptr to DPT (in RAMVARS segment)
66;       SS:BP:  Ptr to PIOVARS
67;   Returns:
68;       DS:DI:  Ptr to DPT (in RAMVARS segment)
69;       AH:     BIOS Error code
70;       CX:     Number of successfully transferred sectors
71;       CF:     0 if transfer successful
72;               1 if any error
73;   Corrupts registers:
74;       AL, BX, DX, SI, ES
75;--------------------------------------------------------------------
76ReadFromDrive:
77    ; Prepare to read data to ESSI
78    mov     bx, g_rgfnPioRead
79    call    InitializePiovarsInSSBPwithSectorCountInAH
80
81    ; Wait until drive is ready to transfer
82    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
83    jc      SHORT ReturnWithTransferErrorInAH
84    xchg    si, di                              ; ES:DI now points buffer
85
86    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
87
88ALIGN JUMP_ALIGN
89.ReadNextBlockFromDrive:
90    mov     dx, [bp+PIOVARS.wDataPort]
91    cmp     [bp+PIOVARS.bSectorsLeft], cl
92    jbe     SHORT .ReadLastBlockFromDrive
93    call    [bp+PIOVARS.fnXfer]
94
95    ; Wait until ready for next block and check for errors
96    xchg    di, si                              ; DS:DI now points DPT
97    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
98    jc      SHORT ReturnWithTransferErrorInAH
99    xchg    si, di                              ; ES:DI now points buffer
100
101    ; Increment number of successfully read sectors
102    mov     cx, [bp+PIOVARS.wSectorsInBlock]
103    sub     [bp+PIOVARS.bSectorsLeft], cl
104    add     [bp+PIOVARS.bSectorsDone], cl
105    jmp     SHORT .ReadNextBlockFromDrive
106
107ALIGN JUMP_ALIGN
108.ReadLastBlockFromDrive:
109    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
110    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
111
112    ; Check for errors in last block
113    mov     di, si                              ; DS:DI now points DPT
114CheckErrorsAfterTransferringLastBlock:
115    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
116    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
117
118    ; Return number of successfully read sectors
119ReturnWithTransferErrorInAH:
120%ifdef USE_386
121    movzx   cx, [bp+PIOVARS.bSectorsDone]
122%else
123    mov     cl, [bp+PIOVARS.bSectorsDone]
124    mov     ch, 0                               ; Preserve CF
125%endif
126    ret
127
128
129;--------------------------------------------------------------------
130; WriteToDrive
131;   Parameters:
132;       AH:     Number of sectors to transfer (1...128)
133;       DS:DI:  Ptr to DPT (in RAMVARS segment)
134;       ES:SI:  Normalized ptr to buffer containing data
135;       SS:BP:  Ptr to PIOVARS
136;   Returns:
137;       AH:     BIOS Error code
138;       CX:     Number of successfully transferred sectors
139;       CF:     0 if transfer successful
140;               1 if any error
141;   Corrupts registers:
142;       AL, BX, DX, SI, ES
143;--------------------------------------------------------------------
144ALIGN JUMP_ALIGN
145WriteToDrive:
146    ; Prepare to write data from ESSI
147    mov     bx, g_rgfnPioWrite
148    call    InitializePiovarsInSSBPwithSectorCountInAH
149
150    ; Always poll when writing first block (IRQs are generated for following blocks)
151    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
152    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
153    jc      SHORT ReturnWithTransferErrorInAH
154
155    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
156
157ALIGN JUMP_ALIGN
158.WriteNextBlockToDrive:
159    mov     dx, [bp+PIOVARS.wDataPort]
160    cmp     [bp+PIOVARS.bSectorsLeft], cl
161    jbe     SHORT .WriteLastBlockToDrive
162    call    [bp+PIOVARS.fnXfer]
163
164    ; Wait until ready for next block and check for errors
165    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
166    jc      SHORT ReturnWithTransferErrorInAH
167
168    ; Increment number of successfully written sectors
169    mov     cx, [bp+PIOVARS.wSectorsInBlock]
170    sub     [bp+PIOVARS.bSectorsLeft], cl
171    add     [bp+PIOVARS.bSectorsDone], cl
172    jmp     SHORT .WriteNextBlockToDrive
173
174ALIGN JUMP_ALIGN
175.WriteLastBlockToDrive:
176    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
177%ifdef USE_186
178    push    CheckErrorsAfterTransferringLastBlock
179    jmp     [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
180%else
181    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
182    jmp     SHORT CheckErrorsAfterTransferringLastBlock
183%endif
184
185
186;--------------------------------------------------------------------
187; InitializePiovarsInSSBPwithSectorCountInAH
188;   Parameters:
189;       AH:     Number of sectors to transfer (1...128)
190;       BX:     Offset to transfer function lookup table
191;       DS:DI:  Ptr to DPT (in RAMVARS segment)
192;       SS:BP:  Ptr to PIOVARS
193;   Returns:
194;       Nothing
195;   Corrupts registers:
196;       AX, BX, DX
197;--------------------------------------------------------------------
198ALIGN JUMP_ALIGN
199InitializePiovarsInSSBPwithSectorCountInAH:
200    ; Store sizes
201    mov     [bp+PIOVARS.bSectorsLeft], ah
202    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
203    mov     [bp+PIOVARS.wSectorsInBlock], ax
204    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
205
206    ; Get transfer function based on bus type
207    xchg    ax, bx                              ; Lookup table offset to AX
208    mov     bl, [di+DPT.bIdevarsOffset]         ; CS:BX now points to IDEVARS
209    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
210    mov     bl, [di+DPT_ATA.bDevice]
211    add     bx, ax
212
213    mov     [bp+PIOVARS.wDataPort], dx
214    mov     ax, [cs:bx]                         ; Load offset to transfer function
215    mov     [bp+PIOVARS.fnXfer], ax
216    ret
217
218
219;--------------------------------------------------------------------
220; ReadBlockFromXtideRev1        XTIDE rev 1
221; ReadBlockFromXtideRev2        XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
222; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
223; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
224;   Parameters:
225;       CX:     Block size in 512 byte sectors
226;       DX:     IDE Data port address
227;       ES:DI:  Normalized ptr to buffer to receive data
228;   Returns:
229;       Nothing
230;   Corrupts registers:
231;       AX, BX, CX
232;--------------------------------------------------------------------
233%ifdef MODULE_8BIT_IDE
234
235ALIGN JUMP_ALIGN
236ReadBlockFromXtideRev1:
237    UNROLL_SECTORS_IN_CX_TO_QWORDS
238    mov     bl, 8       ; Bit mask for toggling data low/high reg
239ALIGN JUMP_ALIGN
240.InswLoop:
241    XTIDE_INSW
242    XTIDE_INSW
243    XTIDE_INSW
244    XTIDE_INSW
245    loop    .InswLoop
246    ret
247
248;--------------------------------------------------------------------
249%ifndef USE_186         ; 8086/8088 compatible WORD read
250ALIGN JUMP_ALIGN
251ReadBlockFromXtideRev2:
252    UNROLL_SECTORS_IN_CX_TO_QWORDS
253ALIGN JUMP_ALIGN
254.ReadNextQword:
255    in      ax, dx      ; Read 1st WORD
256    stosw               ; Store 1st WORD to [ES:DI]
257    in      ax, dx
258    stosw               ; 2nd
259    in      ax, dx
260    stosw               ; 3rd
261    in      ax, dx
262    stosw               ; 4th
263    loop    .ReadNextQword
264    ret
265%endif
266
267%endif  ; MODULE_8BIT_IDE
268
269;--------------------------------------------------------------------
270%ifdef USE_186
271ALIGN JUMP_ALIGN
272ReadBlockFrom16bitDataPort:
273    xchg    cl, ch      ; Sectors to WORDs
274    rep
275    db      6Dh         ; INSW (we want this in XT build)
276    ret
277%endif
278
279;--------------------------------------------------------------------
280%ifdef USE_AT
281ALIGN JUMP_ALIGN
282ReadBlockFrom32bitDataPort:
283    db      0C1h        ; SHL
284    db      0E1h        ; CX
285    db      7           ; 7 (Sectors to DWORDs)
286    rep
287    db      66h         ; Override operand size to 32-bit
288    db      6Dh         ; INSW/INSD
289    ret
290%endif
291
292
293;--------------------------------------------------------------------
294; WriteBlockToXtideRev1         XTIDE rev 1
295; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
296; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
297; WriteBlockTo16bitDataPort     Normal 16-bit IDE
298; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
299;   Parameters:
300;       CX:     Block size in 512-byte sectors
301;       DX:     IDE Data port address
302;       ES:SI:  Normalized ptr to buffer containing data
303;   Returns:
304;       Nothing
305;   Corrupts registers:
306;       AX, BX, CX, DX
307;--------------------------------------------------------------------
308%ifdef MODULE_8BIT_IDE
309
310ALIGN JUMP_ALIGN
311WriteBlockToXtideRev1:
312    push    ds
313    UNROLL_SECTORS_IN_CX_TO_QWORDS
314    mov     bl, 8       ; Bit mask for toggling data low/high reg
315    push    es          ; Copy ES...
316    pop     ds          ; ...to DS
317ALIGN JUMP_ALIGN
318.OutswLoop:
319    XTIDE_OUTSW
320    XTIDE_OUTSW
321    XTIDE_OUTSW
322    XTIDE_OUTSW
323    loop    .OutswLoop
324    pop     ds
325    ret
326
327;--------------------------------------------------------------------
328ALIGN JUMP_ALIGN
329WriteBlockToXtideRev2:
330    UNROLL_SECTORS_IN_CX_TO_QWORDS
331    push    ds
332    push    es          ; Copy ES...
333    pop     ds          ; ...to DS
334ALIGN JUMP_ALIGN
335.WriteNextQword:
336    XTIDE_MOD_OUTSW
337    XTIDE_MOD_OUTSW
338    XTIDE_MOD_OUTSW
339    XTIDE_MOD_OUTSW
340    loop    .WriteNextQword
341    pop     ds
342    ret
343
344;--------------------------------------------------------------------
345ALIGN JUMP_ALIGN
346WriteBlockToFastXtide:
347    UNROLL_SECTORS_IN_CX_TO_QWORDS
348    push    ds
349    push    es
350    pop     ds
351    or      dl, (1<<4)  ; Writes need A4 set
352ALIGN JUMP_ALIGN
353.ReadNextQword:
354    lodsw               ; Load 1st WORD from [DS:SI]
355    out     dx, ax      ; Write 1st WORD
356    lodsw
357    out     dx, ax      ; 2nd
358    lodsw
359    out     dx, ax      ; 3rd
360    lodsw
361    out     dx, ax      ; 4th
362    loop    .ReadNextQword
363    pop     ds
364    ret
365
366%endif  ; MODULE_8BIT_IDE
367
368;--------------------------------------------------------------------
369%ifdef USE_AT
370ALIGN JUMP_ALIGN
371WriteBlockTo16bitDataPort:
372    xchg    cl, ch      ; Sectors to WORDs
373    es                  ; Source is ES segment
374    rep
375    db      6Fh         ; OUTSW (we want this in XT build)
376    ret
377
378;--------------------------------------------------------------------
379ALIGN JUMP_ALIGN
380WriteBlockTo32bitDataPort:
381    db      0C1h        ; SHL
382    db      0E1h        ; CX
383    db      7           ; 7 (Sectors to DWORDs)
384    es                  ; Source is ES segment
385    rep
386    db      66h         ; Override operand size to 32-bit
387    db      6Fh         ; OUTSW/OUTSD
388    ret
389%endif
390
391
392
393; Lookup tables to get transfer function based on bus type
394ALIGN WORD_ALIGN
395g_rgfnPioRead:
396%ifdef MODULE_8BIT_IDE
397        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
398    %ifdef USE_186
399        dw      ReadBlockFrom16bitDataPort  ; 1, DEVICE_FAST_XTIDE
400        dw      ReadBlockFrom16bitDataPort  ; 2, DEVICE_8BIT_XTIDE_REV2
401    %else
402        dw      ReadBlockFromXtideRev2      ; 1, DEVICE_FAST_XTIDE
403        dw      ReadBlockFromXtideRev2      ; 2, DEVICE_8BIT_XTIDE_REV2
404    %endif
405        dw      ReadBlockFromXtideRev1      ; 3, DEVICE_XTIDE_REV1
406
407%else
408        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
409%endif
410%ifdef USE_AT
411        dw      ReadBlockFrom16bitDataPort  ; 4, DEVICE_16BIT_ATA
412        dw      ReadBlockFrom32bitDataPort  ; 5, DEVICE_32BIT_ATA
413%endif
414
415
416g_rgfnPioWrite:
417%ifdef MODULE_8BIT_IDE
418        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
419        dw      WriteBlockToFastXtide       ; 1, DEVICE_FAST_XTIDE
420        dw      WriteBlockToXtideRev2       ; 2, DEVICE_XTIDE_REV2
421        dw      WriteBlockToXtideRev1       ; 3, DEVICE_XTIDE_REV1
422
423%else
424        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
425%endif
426%ifdef USE_AT
427        dw      WriteBlockTo16bitDataPort   ; 4, DEVICE_16BIT_ATA
428        dw      WriteBlockTo32bitDataPort   ; 5, DEVICE_32BIT_ATA
429%endif
Note: See TracBrowser for help on using the repository browser.