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

Last change on this file since 493 was 493, checked in by gregli@…, 11 years ago

Separated MODULE_8BIT_IDE into the basic part used by XTIDE rev 1 and rev 2 which is PIO based, and MODULE_8BIT_IDE_ADVANCED for JRIDE and XTCF support which requires memory mapping and/or DMA. This allows for creating an 8KB image with boot menu support (but no hotkeys) for the XTIDE rev 1. Cleaned up how we reset the drive translation information, ensuring it is properly set between boot attempt on a primary and secondary drive - as a result we clean it when needed, rather than trying to always keep it clean. Also fixed translation bugs in int13h.asm where I had previously missed converting some MODULE_HOTKEYS into MODULE_DRIVEXLATE.

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
[376]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.
[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
[493]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.