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

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

Changes to XTIDE Universal BIOS:

  • ATA ID validation now compares heads to correct maximum number of heads.
  • Added XTCF 8-bit mode transfer functions.
File size: 12.9 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; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
231; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
232;   Parameters:
233;       CX:     Block size in 512 byte sectors
234;       DX:     IDE Data port address
235;       ES:DI:  Normalized ptr to buffer to receive data
236;   Returns:
237;       Nothing
238;   Corrupts registers:
239;       AX, BX, CX
240;--------------------------------------------------------------------
241%ifdef MODULE_8BIT_IDE
242
243ALIGN JUMP_ALIGN
244ReadBlockFromXtideRev1:
245    UNROLL_SECTORS_IN_CX_TO_QWORDS
246    mov     bl, 8       ; Bit mask for toggling data low/high reg
247ALIGN JUMP_ALIGN
248.InswLoop:
249    XTIDE_INSW
250    XTIDE_INSW
251    XTIDE_INSW
252    XTIDE_INSW
253    loop    .InswLoop
254    ret
255
256;--------------------------------------------------------------------
257%ifndef USE_186         ; 8086/8088 compatible WORD read
258ALIGN JUMP_ALIGN
259ReadBlockFromXtideRev2:
260    UNROLL_SECTORS_IN_CX_TO_QWORDS
261ALIGN JUMP_ALIGN
262.ReadNextQword:
263    in      ax, dx      ; Read 1st WORD
264    stosw               ; Store 1st WORD to [ES:DI]
265    in      ax, dx
266    stosw               ; 2nd
267    in      ax, dx
268    stosw               ; 3rd
269    in      ax, dx
270    stosw               ; 4th
271    loop    .ReadNextQword
272    ret
273%endif
274
275;--------------------------------------------------------------------
276ALIGN JUMP_ALIGN
277ReadBlockFromXTCF:
278    UNROLL_SECTORS_IN_CX_TO_DWORDS
279ALIGN JUMP_ALIGN
280.ReadNextDword:
281    in      al, dx      ; Read 1st BYTE
282    stosb               ; Store 1st BYTE to [ES:DI]
283    in      al, dx
284    stosb
285
286    in      al, dx
287    stosb
288    in      al, dx
289    stosb
290    loop    .ReadNextDword
291    ret
292
293%endif  ; MODULE_8BIT_IDE
294
295;--------------------------------------------------------------------
296%ifdef USE_186
297ALIGN JUMP_ALIGN
298ReadBlockFrom16bitDataPort:
299    xchg    cl, ch      ; Sectors to WORDs
300    rep
301    db      6Dh         ; INSW (we want this in XT build)
302    ret
303%endif
304
305;--------------------------------------------------------------------
306%ifdef USE_AT
307ALIGN JUMP_ALIGN
308ReadBlockFrom32bitDataPort:
309    db      0C1h        ; SHL
310    db      0E1h        ; CX
311    db      7           ; 7 (Sectors to DWORDs)
312    rep
313    db      66h         ; Override operand size to 32-bit
314    db      6Dh         ; INSW/INSD
315    ret
316%endif
317
318
319;--------------------------------------------------------------------
320; WriteBlockToXtideRev1         XTIDE rev 1
321; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
322; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
323; WriteBlockTo16bitDataPort     Normal 16-bit IDE
324; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
325;   Parameters:
326;       CX:     Block size in 512-byte sectors
327;       DX:     IDE Data port address
328;       ES:SI:  Normalized ptr to buffer containing data
329;   Returns:
330;       Nothing
331;   Corrupts registers:
332;       AX, BX, CX, DX
333;--------------------------------------------------------------------
334%ifdef MODULE_8BIT_IDE
335
336ALIGN JUMP_ALIGN
337WriteBlockToXtideRev1:
338    push    ds
339    UNROLL_SECTORS_IN_CX_TO_QWORDS
340    mov     bl, 8       ; Bit mask for toggling data low/high reg
341    push    es          ; Copy ES...
342    pop     ds          ; ...to DS
343ALIGN JUMP_ALIGN
344.OutswLoop:
345    XTIDE_OUTSW
346    XTIDE_OUTSW
347    XTIDE_OUTSW
348    XTIDE_OUTSW
349    loop    .OutswLoop
350    pop     ds
351    ret
352
353;--------------------------------------------------------------------
354ALIGN JUMP_ALIGN
355WriteBlockToXtideRev2:
356    UNROLL_SECTORS_IN_CX_TO_QWORDS
357    push    ds
358    push    es          ; Copy ES...
359    pop     ds          ; ...to DS
360ALIGN JUMP_ALIGN
361.WriteNextQword:
362    XTIDE_MOD_OUTSW
363    XTIDE_MOD_OUTSW
364    XTIDE_MOD_OUTSW
365    XTIDE_MOD_OUTSW
366    loop    .WriteNextQword
367    pop     ds
368    ret
369
370;--------------------------------------------------------------------
371ALIGN JUMP_ALIGN
372WriteBlockToXTCF:
373    UNROLL_SECTORS_IN_CX_TO_DWORDS
374    push    ds
375    push    es
376    pop     ds
377ALIGN JUMP_ALIGN
378.WriteNextDword:
379    lodsb               ; Load 1st BYTE from [DS:SI]
380    out     dx, al      ; Write 1st BYTE
381    lodsb
382    out     dx, al
383
384    lodsb
385    out     dx, al
386    lodsb
387    out     dx, al
388    loop    .WriteNextDword
389    pop     ds
390    ret
391%endif  ; MODULE_8BIT_IDE
392
393
394;--------------------------------------------------------------------
395%ifdef USE_AT
396ALIGN JUMP_ALIGN
397WriteBlockTo16bitDataPort:
398    xchg    cl, ch      ; Sectors to WORDs
399    es                  ; Source is ES segment
400    rep
401    db      6Fh         ; OUTSW (we want this in XT build)
402    ret
403
404;--------------------------------------------------------------------
405ALIGN JUMP_ALIGN
406WriteBlockTo32bitDataPort:
407    db      0C1h        ; SHL
408    db      0E1h        ; CX
409    db      7           ; 7 (Sectors to DWORDs)
410    es                  ; Source is ES segment
411    rep
412    db      66h         ; Override operand size to 32-bit
413    db      6Fh         ; OUTSW/OUTSD
414    ret
415%endif ; USE_AT
416
417
418
419; Lookup tables to get transfer function based on bus type
420ALIGN WORD_ALIGN
421g_rgfnPioRead:
422%ifdef MODULE_8BIT_IDE
423        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
424        dw      ReadBlockFromXTCF           ; 1, DEVICE_8BIT_XTCF
425    %ifdef USE_186
426        dw      ReadBlockFrom16bitDataPort  ; 2, DEVICE_8BIT_XTIDE_REV2
427    %else
428        dw      ReadBlockFromXtideRev2      ; 2, DEVICE_8BIT_XTIDE_REV2
429    %endif
430        dw      ReadBlockFromXtideRev1      ; 3, DEVICE_XTIDE_REV1
431
432%else
433        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
434%endif
435%ifdef USE_AT
436        dw      ReadBlockFrom16bitDataPort  ; 4, DEVICE_16BIT_ATA
437        dw      ReadBlockFrom32bitDataPort  ; 5, DEVICE_32BIT_ATA
438%endif
439
440
441g_rgfnPioWrite:
442%ifdef MODULE_8BIT_IDE
443        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
444        dw      WriteBlockToXTCF            ; 1, DEVICE_8BIT_XTCF
445        dw      WriteBlockToXtideRev2       ; 2, DEVICE_XTIDE_REV2
446        dw      WriteBlockToXtideRev1       ; 3, DEVICE_XTIDE_REV1
447
448%else
449        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
450%endif
451%ifdef USE_AT
452        dw      WriteBlockTo16bitDataPort   ; 4, DEVICE_16BIT_ATA
453        dw      WriteBlockTo32bitDataPort   ; 5, DEVICE_32BIT_ATA
454%endif
Note: See TracBrowser for help on using the repository browser.