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

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

Changes to XTIDE Universal BIOS:

  • Addressing modes are now NORMAL, LARGE and LBA.
  • L-CHS parameters are now generated differently for drives with 8192 or less cylinders.
File size: 12.7 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%endif  ; MODULE_8BIT_IDE
276
277;--------------------------------------------------------------------
278%ifdef USE_186
279ALIGN JUMP_ALIGN
280ReadBlockFrom16bitDataPort:
281    xchg    cl, ch      ; Sectors to WORDs
282    rep
283    db      6Dh         ; INSW (we want this in XT build)
284    ret
285%endif
286
287;--------------------------------------------------------------------
288%ifdef USE_AT
289ALIGN JUMP_ALIGN
290ReadBlockFrom32bitDataPort:
291    db      0C1h        ; SHL
292    db      0E1h        ; CX
293    db      7           ; 7 (Sectors to DWORDs)
294    rep
295    db      66h         ; Override operand size to 32-bit
296    db      6Dh         ; INSW/INSD
297    ret
298%endif
299
300
301;--------------------------------------------------------------------
302; WriteBlockToXtideRev1         XTIDE rev 1
303; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
304; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
305; WriteBlockTo16bitDataPort     Normal 16-bit IDE
306; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
307;   Parameters:
308;       CX:     Block size in 512-byte sectors
309;       DX:     IDE Data port address
310;       ES:SI:  Normalized ptr to buffer containing data
311;   Returns:
312;       Nothing
313;   Corrupts registers:
314;       AX, BX, CX, DX
315;--------------------------------------------------------------------
316%ifdef MODULE_8BIT_IDE
317
318ALIGN JUMP_ALIGN
319WriteBlockToXtideRev1:
320    push    ds
321    UNROLL_SECTORS_IN_CX_TO_QWORDS
322    mov     bl, 8       ; Bit mask for toggling data low/high reg
323    push    es          ; Copy ES...
324    pop     ds          ; ...to DS
325ALIGN JUMP_ALIGN
326.OutswLoop:
327    XTIDE_OUTSW
328    XTIDE_OUTSW
329    XTIDE_OUTSW
330    XTIDE_OUTSW
331    loop    .OutswLoop
332    pop     ds
333    ret
334
335;--------------------------------------------------------------------
336ALIGN JUMP_ALIGN
337WriteBlockToXtideRev2:
338    UNROLL_SECTORS_IN_CX_TO_QWORDS
339    push    ds
340    push    es          ; Copy ES...
341    pop     ds          ; ...to DS
342ALIGN JUMP_ALIGN
343.WriteNextQword:
344    XTIDE_MOD_OUTSW
345    XTIDE_MOD_OUTSW
346    XTIDE_MOD_OUTSW
347    XTIDE_MOD_OUTSW
348    loop    .WriteNextQword
349    pop     ds
350    ret
351
352;--------------------------------------------------------------------
353ALIGN JUMP_ALIGN
354WriteBlockToFastXtide:
355    UNROLL_SECTORS_IN_CX_TO_QWORDS
356    push    ds
357    push    es
358    pop     ds
359    or      dl, (1<<4)  ; Writes need A4 set
360ALIGN JUMP_ALIGN
361.ReadNextQword:
362    lodsw               ; Load 1st WORD from [DS:SI]
363    out     dx, ax      ; Write 1st WORD
364    lodsw
365    out     dx, ax      ; 2nd
366    lodsw
367    out     dx, ax      ; 3rd
368    lodsw
369    out     dx, ax      ; 4th
370    loop    .ReadNextQword
371    pop     ds
372    ret
373%endif  ; MODULE_8BIT_IDE
374
375
376;--------------------------------------------------------------------
377%ifdef USE_AT
378ALIGN JUMP_ALIGN
379WriteBlockTo16bitDataPort:
380    xchg    cl, ch      ; Sectors to WORDs
381    es                  ; Source is ES segment
382    rep
383    db      6Fh         ; OUTSW (we want this in XT build)
384    ret
385
386;--------------------------------------------------------------------
387ALIGN JUMP_ALIGN
388WriteBlockTo32bitDataPort:
389    db      0C1h        ; SHL
390    db      0E1h        ; CX
391    db      7           ; 7 (Sectors to DWORDs)
392    es                  ; Source is ES segment
393    rep
394    db      66h         ; Override operand size to 32-bit
395    db      6Fh         ; OUTSW/OUTSD
396    ret
397%endif ; USE_AT
398
399
400
401; Lookup tables to get transfer function based on bus type
402ALIGN WORD_ALIGN
403g_rgfnPioRead:
404%ifdef MODULE_8BIT_IDE
405        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
406    %ifdef USE_186
407        dw      ReadBlockFrom16bitDataPort  ; 1, DEVICE_FAST_XTIDE
408        dw      ReadBlockFrom16bitDataPort  ; 2, DEVICE_8BIT_XTIDE_REV2
409    %else
410        dw      ReadBlockFromXtideRev2      ; 1, DEVICE_FAST_XTIDE
411        dw      ReadBlockFromXtideRev2      ; 2, DEVICE_8BIT_XTIDE_REV2
412    %endif
413        dw      ReadBlockFromXtideRev1      ; 3, DEVICE_XTIDE_REV1
414
415%else
416        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
417%endif
418%ifdef USE_AT
419        dw      ReadBlockFrom16bitDataPort  ; 4, DEVICE_16BIT_ATA
420        dw      ReadBlockFrom32bitDataPort  ; 5, DEVICE_32BIT_ATA
421%endif
422
423
424g_rgfnPioWrite:
425%ifdef MODULE_8BIT_IDE
426        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
427        dw      WriteBlockToFastXtide       ; 1, DEVICE_FAST_XTIDE
428        dw      WriteBlockToXtideRev2       ; 2, DEVICE_XTIDE_REV2
429        dw      WriteBlockToXtideRev1       ; 3, DEVICE_XTIDE_REV1
430
431%else
432        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
433%endif
434%ifdef USE_AT
435        dw      WriteBlockTo16bitDataPort   ; 4, DEVICE_16BIT_ATA
436        dw      WriteBlockTo32bitDataPort   ; 5, DEVICE_32BIT_ATA
437%endif
Note: See TracBrowser for help on using the repository browser.