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

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

Changes:

  • Update of the copyright notices to include the year 2013.
File size: 10.6 KB
RevLine 
[150]1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device transfer functions.
3
[376]4;
[445]5; XTIDE Universal BIOS and Associated Tools
[526]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[376]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.
[445]12;
[376]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
[445]16; GNU General Public License for more details.
[376]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[445]18;
[376]19
[150]20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
[414]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
[363]26    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
[218]27                            resb    1   ; 7, IDEPACK.bDeviceControl
[363]28    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
[150]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
[171]39;               (all PIO read and write commands including Identify Device)
[480]40;       ES:SI:  Ptr to data buffer
[150]41;       DS:DI:  Ptr to DPT (in RAMVARS segment)
42;       SS:BP:  Ptr to IDEPACK
43;   Returns:
44;       AH:     INT 13h Error Code
[218]45;       CX:     Number of successfully transferred sectors
[150]46;       CF:     Cleared if success, Set if error
47;   Corrupts registers:
[218]48;       AL, BX, DX, SI, ES
[150]49;--------------------------------------------------------------------
50ALIGN JUMP_ALIGN
51IdeTransfer_StartWithCommandInAL:
[157]52    ; Are we reading or writing?
[171]53    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[242]54    mov     ah, [bp+IDEPACK.bSectorCount]
55    jnz     SHORT WriteToDrive
[171]56    cmp     al, COMMAND_WRITE_MULTIPLE
[242]57    je      SHORT WriteToDrive
58    ; Fall to ReadFromDrive
[150]59
60;--------------------------------------------------------------------
[242]61; ReadFromDrive
[150]62;   Parameters:
[242]63;       AH:     Number of sectors to transfer (1...128)
[480]64;       ES:SI:  Ptr to buffer to receive data
[150]65;       DS:DI:  Ptr to DPT (in RAMVARS segment)
66;       SS:BP:  Ptr to PIOVARS
67;   Returns:
[242]68;       DS:DI:  Ptr to DPT (in RAMVARS segment)
[150]69;       AH:     BIOS Error code
[218]70;       CX:     Number of successfully transferred sectors
[294]71;       CF:     0 if transfer successful
[150]72;               1 if any error
73;   Corrupts registers:
[218]74;       AL, BX, DX, SI, ES
[150]75;--------------------------------------------------------------------
[242]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
[218]83    jc      SHORT ReturnWithTransferErrorInAH
[242]84    xchg    si, di                              ; ES:DI now points buffer
[218]85
[363]86    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
[242]87
[150]88ALIGN JUMP_ALIGN
[242]89.ReadNextBlockFromDrive:
[150]90    mov     dx, [bp+PIOVARS.wDataPort]
[363]91    cmp     [bp+PIOVARS.bSectorsLeft], cl
[242]92    jbe     SHORT .ReadLastBlockFromDrive
[218]93    call    [bp+PIOVARS.fnXfer]
[169]94
[218]95    ; Wait until ready for next block and check for errors
[242]96    xchg    di, si                              ; DS:DI now points DPT
[218]97    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
98    jc      SHORT ReturnWithTransferErrorInAH
[242]99    xchg    si, di                              ; ES:DI now points buffer
[169]100
[363]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
[242]105    jmp     SHORT .ReadNextBlockFromDrive
[150]106
107ALIGN JUMP_ALIGN
[242]108.ReadLastBlockFromDrive:
[363]109    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
[419]110    push    cx
[150]111    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
112
[242]113    ; Check for errors in last block
114    mov     di, si                              ; DS:DI now points DPT
115CheckErrorsAfterTransferringLastBlock:
[417]116    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[242]117    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]118    pop     cx  ; [bp+PIOVARS.bSectorsLeft]
119    jc      SHORT ReturnWithTransferErrorInAH
[150]120
[445]121    ; All sectors successfully transferred
[419]122    add     cx, [bp+PIOVARS.bSectorsDone]       ; Never sets CF
123    ret
124
[242]125    ; Return number of successfully read sectors
126ReturnWithTransferErrorInAH:
[370]127%ifdef USE_386
128    movzx   cx, [bp+PIOVARS.bSectorsDone]
129%else
[363]130    mov     cl, [bp+PIOVARS.bSectorsDone]
131    mov     ch, 0                               ; Preserve CF
[370]132%endif
[242]133    ret
134
135
[150]136;--------------------------------------------------------------------
[242]137; WriteToDrive
[150]138;   Parameters:
[242]139;       AH:     Number of sectors to transfer (1...128)
140;       DS:DI:  Ptr to DPT (in RAMVARS segment)
[480]141;       ES:SI:  Ptr to buffer containing data
[150]142;       SS:BP:  Ptr to PIOVARS
143;   Returns:
144;       AH:     BIOS Error code
[218]145;       CX:     Number of successfully transferred sectors
[294]146;       CF:     0 if transfer successful
[150]147;               1 if any error
148;   Corrupts registers:
[218]149;       AL, BX, DX, SI, ES
[150]150;--------------------------------------------------------------------
151ALIGN JUMP_ALIGN
[242]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
[218]160    jc      SHORT ReturnWithTransferErrorInAH
[150]161
[363]162    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
[242]163
[218]164ALIGN JUMP_ALIGN
[242]165.WriteNextBlockToDrive:
[150]166    mov     dx, [bp+PIOVARS.wDataPort]
[363]167    cmp     [bp+PIOVARS.bSectorsLeft], cl
[242]168    jbe     SHORT .WriteLastBlockToDrive
[218]169    call    [bp+PIOVARS.fnXfer]
[169]170
[218]171    ; Wait until ready for next block and check for errors
172    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
173    jc      SHORT ReturnWithTransferErrorInAH
[150]174
[363]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
[242]179    jmp     SHORT .WriteNextBlockToDrive
[169]180
[150]181ALIGN JUMP_ALIGN
[242]182.WriteLastBlockToDrive:
[363]183    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
[419]184    push    cx
[242]185%ifdef USE_186
186    push    CheckErrorsAfterTransferringLastBlock
187    jmp     [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
188%else
[150]189    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
[242]190    jmp     SHORT CheckErrorsAfterTransferringLastBlock
191%endif
[218]192
[150]193
194;--------------------------------------------------------------------
[218]195; InitializePiovarsInSSBPwithSectorCountInAH
[150]196;   Parameters:
[218]197;       AH:     Number of sectors to transfer (1...128)
[150]198;       BX:     Offset to transfer function lookup table
199;       DS:DI:  Ptr to DPT (in RAMVARS segment)
[480]200;       ES:SI:  Ptr to data buffer
[169]201;       SS:BP:  Ptr to PIOVARS
[167]202;   Returns:
[169]203;       Nothing
[150]204;   Corrupts registers:
[242]205;       AX, BX, DX
[150]206;--------------------------------------------------------------------
207ALIGN JUMP_ALIGN
[218]208InitializePiovarsInSSBPwithSectorCountInAH:
[473]209    ; Store sizes and Data Port
[363]210    mov     [bp+PIOVARS.bSectorsLeft], ah
[473]211    mov     ax, [di+DPT.wBasePort]
212    mov     [bp+PIOVARS.wDataPort], ax
[370]213    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
[363]214    mov     [bp+PIOVARS.wSectorsInBlock], ax
215    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
[150]216
217    ; Get transfer function based on bus type
[158]218    xchg    ax, bx                              ; Lookup table offset to AX
[400]219    mov     bl, [di+DPT_ATA.bDevice]
[493]220%ifdef MODULE_8BIT_IDE_ADVANCED
[480]221    mov     dl, bl
222%endif
[150]223    add     bx, ax
224    mov     ax, [cs:bx]                         ; Load offset to transfer function
225    mov     [bp+PIOVARS.fnXfer], ax
[480]226
227    ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
[493]228%ifdef MODULE_8BIT_IDE_ADVANCED
[480]229    cmp     dl, DEVICE_8BIT_XTCF_DMA
230    jb      SHORT IdeTransfer_NormalizePointerInESSI
231
232    ; Convert ES:SI to physical address
[491]233%ifdef USE_186          ; Bytes EU Cycles(286)
234    mov     ax, es      ; 2     2
235    rol     ax, 4       ; 3     9
236    mov     dx, ax      ; 2     2
237    and     ax, BYTE 0Fh; 3     3
238    xor     dx, ax      ; 2     2
239    add     si, dx      ; 2     2
240    adc     al, ah      ; 2     2
241    mov     es, ax      ; 2     2
242    ;------------------------------------
243                        ; 18    24
244%else ; 808x
245
246%if 0
247                        ; Bytes EU Cycles(808x)
248    mov     al, 4       ; 2     4
249    mov     dx, es      ; 2     2
250    xchg    cx, ax      ; 1     3
251    rol     dx, cl      ; 2     24
252    mov     cx, dx      ; 2     2
253    xchg    cx, ax      ; 1     3
254    and     ax, BYTE 0Fh; 3     4
255    xor     dx, ax      ; 2     3
256    add     si, dx      ; 2     3
257    adc     al, ah      ; 2     3
258    mov     es, ax      ; 2     2
259    ;------------------------------------
260                        ; 21    53
261;
262; Judging by the Execution Unit cycle count the above block of code is
263; apparently slower. However, the shifts and rotates in the block below
264; execute faster than the Bus Interface Unit on an 8088 can fetch them,
265; thus causing the EU to starve. The difference in true execution speed
266; (if any) might not be worth the extra 5 bytes.
267; In other words, we could use a real world test here.
268;
269%endif ; 0
270                        ; Bytes EU Cycles(808x/286)
271    xor     dx, dx      ; 2     3/2
272    mov     ax, es      ; 2     2/2
[480]273%rep 4
[491]274    shl     ax, 1       ; 8     8/8
275    rcl     dx, 1       ; 8     8/8
[480]276%endrep
[491]277    add     si, ax      ; 2     3/2
278    adc     dl, dh      ; 2     3/2
279    mov     es, dx      ; 2     2/2
280    ;------------------------------------
281%endif                  ; 26    29/26
[150]282    ret
[493]283%endif ; MODULE_8BIT_IDE_ADVANCED
[480]284    ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE
[150]285
286
[480]287;--------------------------------------------------------------------
288; IdeTransfer_NormalizePointerInESSI
289;   Parameters:
290;       ES:SI:  Ptr to be normalized
291;   Returns:
292;       ES:SI:  Normalized pointer (SI = 0...15)
293;   Corrupts registers:
294;       AX, DX
295;--------------------------------------------------------------------
296IdeTransfer_NormalizePointerInESSI:
297    NORMALIZE_FAR_POINTER   es, si, ax, dx
298    ret
[400]299
[480]300
[150]301; Lookup tables to get transfer function based on bus type
302ALIGN WORD_ALIGN
303g_rgfnPioRead:
[473]304        dw      IdePioBlock_ReadFrom16bitDataPort   ; 0, DEVICE_16BIT_ATA
305        dw      IdePioBlock_ReadFrom32bitDataPort   ; 1, DEVICE_32BIT_ATA
[400]306%ifdef MODULE_8BIT_IDE
[480]307        dw      IdePioBlock_ReadFrom8bitDataPort    ; 2, DEVICE_8BIT_ATA
[491]308        dw      IdePioBlock_ReadFromXtideRev1       ; 3, DEVICE_8BIT_XTIDE_REV1
[480]309        dw      IdePioBlock_ReadFromXtideRev2       ; 4, DEVICE_8BIT_XTIDE_REV2
[493]310%ifdef MODULE_8BIT_IDE_ADVANCED
[480]311        dw      IdePioBlock_ReadFrom8bitDataPort    ; 5, DEVICE_8BIT_XTCF_PIO8
312        dw      IdeDmaBlock_ReadFromXTCF            ; 6, DEVICE_8BIT_XTCF_DMA
[473]313%endif
[493]314%endif
[400]315
[480]316
[473]317g_rgfnPioWrite:
318        dw      IdePioBlock_WriteTo16bitDataPort    ; 0, DEVICE_16BIT_ATA
319        dw      IdePioBlock_WriteTo32bitDataPort    ; 1, DEVICE_32BIT_ATA
[400]320%ifdef MODULE_8BIT_IDE
[480]321        dw      IdePioBlock_WriteTo8bitDataPort     ; 2, DEVICE_8BIT_ATA
322        dw      IdePioBlock_WriteToXtideRev1        ; 3, DEVICE_8BIT_XTIDE_REV1
323        dw      IdePioBlock_WriteToXtideRev2        ; 4, DEVICE_8BIT_XTIDE_REV2
[526]324%ifdef MODULE_8BIT_IDE_ADVANCED
[480]325        dw      IdePioBlock_WriteTo8bitDataPort     ; 5, DEVICE_8BIT_XTCF_PIO8
326        dw      IdeDmaBlock_WriteToXTCF             ; 6, DEVICE_8BIT_XTCF_DMA
[361]327%endif
[493]328%endif
Note: See TracBrowser for help on using the repository browser.