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

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

Changes to XTIDE Universal BIOS:

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