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

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

Changes to XTIDE Universal BIOS:

  • Added XT-CF transfer functions for 80188/80186 and later.
  • XT-CF drive detection timeouts are now the same as for other controllers.
File size: 13.3 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    push    cx
111    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
112
113    ; Check for errors in last block
114    mov     di, si                              ; DS:DI now points DPT
115CheckErrorsAfterTransferringLastBlock:
116    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
117    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
118    pop     cx  ; [bp+PIOVARS.bSectorsLeft]
119    jc      SHORT ReturnWithTransferErrorInAH
120
121    ; All sectors succesfully transferred
122    add     cx, [bp+PIOVARS.bSectorsDone]       ; Never sets CF
123    ret
124
125    ; Return number of successfully read sectors
126ReturnWithTransferErrorInAH:
127%ifdef USE_386
128    movzx   cx, [bp+PIOVARS.bSectorsDone]
129%else
130    mov     cl, [bp+PIOVARS.bSectorsDone]
131    mov     ch, 0                               ; Preserve CF
132%endif
133    ret
134
135
136;--------------------------------------------------------------------
137; WriteToDrive
138;   Parameters:
139;       AH:     Number of sectors to transfer (1...128)
140;       DS:DI:  Ptr to DPT (in RAMVARS segment)
141;       ES:SI:  Normalized ptr to buffer containing data
142;       SS:BP:  Ptr to PIOVARS
143;   Returns:
144;       AH:     BIOS Error code
145;       CX:     Number of successfully transferred sectors
146;       CF:     0 if transfer successful
147;               1 if any error
148;   Corrupts registers:
149;       AL, BX, DX, SI, ES
150;--------------------------------------------------------------------
151ALIGN JUMP_ALIGN
152WriteToDrive:
153    ; Prepare to write data from ESSI
154    mov     bx, g_rgfnPioWrite
155    call    InitializePiovarsInSSBPwithSectorCountInAH
156
157    ; Always poll when writing first block (IRQs are generated for following blocks)
158    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
159    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
160    jc      SHORT ReturnWithTransferErrorInAH
161
162    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
163
164ALIGN JUMP_ALIGN
165.WriteNextBlockToDrive:
166    mov     dx, [bp+PIOVARS.wDataPort]
167    cmp     [bp+PIOVARS.bSectorsLeft], cl
168    jbe     SHORT .WriteLastBlockToDrive
169    call    [bp+PIOVARS.fnXfer]
170
171    ; Wait until ready for next block and check for errors
172    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
173    jc      SHORT ReturnWithTransferErrorInAH
174
175    ; Increment number of successfully written sectors
176    mov     cx, [bp+PIOVARS.wSectorsInBlock]
177    sub     [bp+PIOVARS.bSectorsLeft], cl
178    add     [bp+PIOVARS.bSectorsDone], cl
179    jmp     SHORT .WriteNextBlockToDrive
180
181ALIGN JUMP_ALIGN
182.WriteLastBlockToDrive:
183    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
184    push    cx
185%ifdef USE_186
186    push    CheckErrorsAfterTransferringLastBlock
187    jmp     [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
188%else
189    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
190    jmp     SHORT CheckErrorsAfterTransferringLastBlock
191%endif
192
193
194;--------------------------------------------------------------------
195; InitializePiovarsInSSBPwithSectorCountInAH
196;   Parameters:
197;       AH:     Number of sectors to transfer (1...128)
198;       BX:     Offset to transfer function lookup table
199;       DS:DI:  Ptr to DPT (in RAMVARS segment)
200;       SS:BP:  Ptr to PIOVARS
201;   Returns:
202;       Nothing
203;   Corrupts registers:
204;       AX, BX, DX
205;--------------------------------------------------------------------
206ALIGN JUMP_ALIGN
207InitializePiovarsInSSBPwithSectorCountInAH:
208    ; Store sizes
209    mov     [bp+PIOVARS.bSectorsLeft], ah
210    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
211    mov     [bp+PIOVARS.wSectorsInBlock], ax
212    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
213
214    ; Get transfer function based on bus type
215    xchg    ax, bx                              ; Lookup table offset to AX
216    mov     bl, [di+DPT.bIdevarsOffset]         ; CS:BX now points to IDEVARS
217    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
218    mov     bl, [di+DPT_ATA.bDevice]
219    add     bx, ax
220
221    mov     [bp+PIOVARS.wDataPort], dx
222    mov     ax, [cs:bx]                         ; Load offset to transfer function
223    mov     [bp+PIOVARS.fnXfer], ax
224    ret
225
226
227;--------------------------------------------------------------------
228; ReadBlockFromXtideRev1        XTIDE rev 1
229; ReadBlockFromXtideRev2        XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
230; ReadBlockFrom8bitDataPort     CF-XT when using 8-bit PIO
231; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
232; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
233;   Parameters:
234;       CX:     Block size in 512 byte sectors
235;       DX:     IDE Data port address
236;       ES:DI:  Normalized ptr to buffer to receive data
237;   Returns:
238;       Nothing
239;   Corrupts registers:
240;       AX, BX, CX
241;--------------------------------------------------------------------
242%ifdef MODULE_8BIT_IDE
243
244    ALIGN JUMP_ALIGN
245    ReadBlockFromXtideRev1:
246        UNROLL_SECTORS_IN_CX_TO_QWORDS
247        mov     bl, 8       ; Bit mask for toggling data low/high reg
248    ALIGN JUMP_ALIGN
249    .InswLoop:
250        XTIDE_INSW
251        XTIDE_INSW
252        XTIDE_INSW
253        XTIDE_INSW
254        loop    .InswLoop
255        ret
256
257    ;--------------------------------------------------------------------
258    %ifndef USE_186         ; 8086/8088 compatible WORD read
259        ALIGN JUMP_ALIGN
260        ReadBlockFromXtideRev2:
261            UNROLL_SECTORS_IN_CX_TO_QWORDS
262        ALIGN JUMP_ALIGN
263        .ReadNextQword:
264            in      ax, dx      ; Read 1st WORD
265            stosw               ; Store 1st WORD to [ES:DI]
266            in      ax, dx
267            stosw               ; 2nd
268            in      ax, dx
269            stosw               ; 3rd
270            in      ax, dx
271            stosw               ; 4th
272            loop    .ReadNextQword
273            ret
274    %endif
275
276    ;--------------------------------------------------------------------
277    %ifdef USE_186
278        ALIGN JUMP_ALIGN
279        ReadBlockFrom8bitDataPort:
280            shl     cx, 9       ; Sectors to BYTEs
281            rep insb
282            ret
283
284    %else ; If 8088/8086
285            ALIGN JUMP_ALIGN
286        ReadBlockFrom8bitDataPort:
287            UNROLL_SECTORS_IN_CX_TO_DWORDS
288        ALIGN JUMP_ALIGN
289        .ReadNextDword:
290            in      al, dx      ; Read 1st BYTE
291            stosb               ; Store 1st BYTE to [ES:DI]
292            in      al, dx
293            stosb
294
295            in      al, dx
296            stosb
297            in      al, dx
298            stosb
299            loop    .ReadNextDword
300            ret
301    %endif
302%endif  ; MODULE_8BIT_IDE
303
304;--------------------------------------------------------------------
305%ifdef USE_186
306    ALIGN JUMP_ALIGN
307    ReadBlockFrom16bitDataPort:
308        xchg    cl, ch      ; Sectors to WORDs
309        rep insw
310        ret
311%endif
312
313;--------------------------------------------------------------------
314%ifdef USE_AT
315    ALIGN JUMP_ALIGN
316    ReadBlockFrom32bitDataPort:
317        shl     cx, 7       ; Sectors to DWORDs
318        rep
319        db      66h         ; Override operand size to 32-bit
320        db      6Dh         ; INSW/INSD
321        ret
322%endif
323
324
325;--------------------------------------------------------------------
326; WriteBlockToXtideRev1         XTIDE rev 1
327; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
328; WriteBlockTo8bitDataPort      XT-CF when using 8-bit PIO
329; WriteBlockTo16bitDataPort     Normal 16-bit IDE
330; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
331;   Parameters:
332;       CX:     Block size in 512-byte sectors
333;       DX:     IDE Data port address
334;       ES:SI:  Normalized ptr to buffer containing data
335;   Returns:
336;       Nothing
337;   Corrupts registers:
338;       AX, BX, CX, DX
339;--------------------------------------------------------------------
340%ifdef MODULE_8BIT_IDE
341
342    ALIGN JUMP_ALIGN
343    WriteBlockToXtideRev1:
344        push    ds
345        UNROLL_SECTORS_IN_CX_TO_QWORDS
346        mov     bl, 8       ; Bit mask for toggling data low/high reg
347        push    es          ; Copy ES...
348        pop     ds          ; ...to DS
349    ALIGN JUMP_ALIGN
350    .OutswLoop:
351        XTIDE_OUTSW
352        XTIDE_OUTSW
353        XTIDE_OUTSW
354        XTIDE_OUTSW
355        loop    .OutswLoop
356        pop     ds
357        ret
358
359    ;--------------------------------------------------------------------
360    ALIGN JUMP_ALIGN
361    WriteBlockToXtideRev2:
362        UNROLL_SECTORS_IN_CX_TO_QWORDS
363        push    ds
364        push    es          ; Copy ES...
365        pop     ds          ; ...to DS
366    ALIGN JUMP_ALIGN
367    .WriteNextQword:
368        XTIDE_MOD_OUTSW
369        XTIDE_MOD_OUTSW
370        XTIDE_MOD_OUTSW
371        XTIDE_MOD_OUTSW
372        loop    .WriteNextQword
373        pop     ds
374        ret
375
376    ;--------------------------------------------------------------------
377    %ifdef USE_186
378        ALIGN JUMP_ALIGN
379        WriteBlockTo8bitDataPort:
380            shl     cx, 9       ; Sectors to BYTEs
381            es                  ; Source is ES segment
382            rep outsb
383            ret
384
385    %else ; If 8088/8086
386        ALIGN JUMP_ALIGN
387        WriteBlockTo8bitDataPort:
388            UNROLL_SECTORS_IN_CX_TO_DWORDS
389            push    ds
390            push    es
391            pop     ds
392        ALIGN JUMP_ALIGN
393        .WriteNextDword:
394            lodsb               ; Load 1st BYTE from [DS:SI]
395            out     dx, al      ; Write 1st BYTE
396            lodsb
397            out     dx, al
398
399            lodsb
400            out     dx, al
401            lodsb
402            out     dx, al
403            loop    .WriteNextDword
404            pop     ds
405            ret
406    %endif
407%endif  ; MODULE_8BIT_IDE
408
409;--------------------------------------------------------------------
410%ifdef USE_AT
411ALIGN JUMP_ALIGN
412WriteBlockTo16bitDataPort:
413    xchg    cl, ch      ; Sectors to WORDs
414    es                  ; Source is ES segment
415    rep outsw
416    ret
417
418;--------------------------------------------------------------------
419ALIGN JUMP_ALIGN
420WriteBlockTo32bitDataPort:
421    shl     cx, 7       ; Sectors to DWORDs
422    es                  ; Source is ES segment
423    rep
424    db      66h         ; Override operand size to 32-bit
425    db      6Fh         ; OUTSW/OUTSD
426    ret
427%endif ; USE_AT
428
429
430
431; Lookup tables to get transfer function based on bus type
432ALIGN WORD_ALIGN
433g_rgfnPioRead:
434%ifdef MODULE_8BIT_IDE
435        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
436        dw      ReadBlockFrom8bitDataPort   ; 1, DEVICE_8BIT_XTCF
437    %ifdef USE_186
438        dw      ReadBlockFrom16bitDataPort  ; 2, DEVICE_8BIT_XTIDE_REV2
439    %else
440        dw      ReadBlockFromXtideRev2      ; 2, DEVICE_8BIT_XTIDE_REV2
441    %endif
442        dw      ReadBlockFromXtideRev1      ; 3, DEVICE_XTIDE_REV1
443
444%else
445        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
446%endif
447%ifdef USE_AT
448        dw      ReadBlockFrom16bitDataPort  ; 4, DEVICE_16BIT_ATA
449        dw      ReadBlockFrom32bitDataPort  ; 5, DEVICE_32BIT_ATA
450%endif
451
452
453g_rgfnPioWrite:
454%ifdef MODULE_8BIT_IDE
455        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
456        dw      WriteBlockTo8bitDataPort    ; 1, DEVICE_8BIT_XTCF
457        dw      WriteBlockToXtideRev2       ; 2, DEVICE_XTIDE_REV2
458        dw      WriteBlockToXtideRev1       ; 3, DEVICE_XTIDE_REV1
459
460%else
461        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
462%endif
463%ifdef USE_AT
464        dw      WriteBlockTo16bitDataPort   ; 4, DEVICE_16BIT_ATA
465        dw      WriteBlockTo32bitDataPort   ; 5, DEVICE_32BIT_ATA
466%endif
Note: See TracBrowser for help on using the repository browser.