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

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

Changes to XTIDE Universal BIOS:

  • Added XT-CF transfer functions for 80188/80186 and later.
  • XT-CF drive detection timeouts are now the same as for other controllers.
File size: 13.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.
[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)
[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
[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
[421]121    ; All sectors succesfully 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)
141;       ES:SI:  Normalized 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)
[169]200;       SS:BP:  Ptr to PIOVARS
[167]201;   Returns:
[169]202;       Nothing
[150]203;   Corrupts registers:
[242]204;       AX, BX, DX
[150]205;--------------------------------------------------------------------
206ALIGN JUMP_ALIGN
[218]207InitializePiovarsInSSBPwithSectorCountInAH:
208    ; Store sizes
[363]209    mov     [bp+PIOVARS.bSectorsLeft], ah
[370]210    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
[363]211    mov     [bp+PIOVARS.wSectorsInBlock], ax
212    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
[150]213
214    ; Get transfer function based on bus type
[158]215    xchg    ax, bx                              ; Lookup table offset to AX
[242]216    mov     bl, [di+DPT.bIdevarsOffset]         ; CS:BX now points to IDEVARS
[150]217    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
[400]218    mov     bl, [di+DPT_ATA.bDevice]
[150]219    add     bx, ax
[363]220
[242]221    mov     [bp+PIOVARS.wDataPort], dx
[150]222    mov     ax, [cs:bx]                         ; Load offset to transfer function
223    mov     [bp+PIOVARS.fnXfer], ax
224    ret
225
226
227;--------------------------------------------------------------------
[361]228; ReadBlockFromXtideRev1        XTIDE rev 1
229; ReadBlockFromXtideRev2        XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
[444]230; ReadBlockFrom8bitDataPort     CF-XT when using 8-bit PIO
[361]231; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
232; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
[150]233;   Parameters:
[363]234;       CX:     Block size in 512 byte sectors
[150]235;       DX:     IDE Data port address
[242]236;       ES:DI:  Normalized ptr to buffer to receive data
[150]237;   Returns:
238;       Nothing
239;   Corrupts registers:
240;       AX, BX, CX
241;--------------------------------------------------------------------
[400]242%ifdef MODULE_8BIT_IDE
243
[444]244    ALIGN JUMP_ALIGN
245    ReadBlockFromXtideRev1:
246        UNROLL_SECTORS_IN_CX_TO_QWORDS
247        mov     bl, 8       ; Bit mask for toggling data low/high reg
248    ALIGN JUMP_ALIGN
249    .InswLoop:
250        XTIDE_INSW
251        XTIDE_INSW
252        XTIDE_INSW
253        XTIDE_INSW
254        loop    .InswLoop
255        ret
[150]256
[444]257    ;--------------------------------------------------------------------
258    %ifndef USE_186         ; 8086/8088 compatible WORD read
259        ALIGN JUMP_ALIGN
260        ReadBlockFromXtideRev2:
261            UNROLL_SECTORS_IN_CX_TO_QWORDS
262        ALIGN JUMP_ALIGN
263        .ReadNextQword:
264            in      ax, dx      ; Read 1st WORD
265            stosw               ; Store 1st WORD to [ES:DI]
266            in      ax, dx
267            stosw               ; 2nd
268            in      ax, dx
269            stosw               ; 3rd
270            in      ax, dx
271            stosw               ; 4th
272            loop    .ReadNextQword
273            ret
274    %endif
[150]275
[444]276    ;--------------------------------------------------------------------
277    %ifdef USE_186
278        ALIGN JUMP_ALIGN
279        ReadBlockFrom8bitDataPort:
280            shl     cx, 9       ; Sectors to BYTEs
281            rep insb
282            ret
[442]283
[444]284    %else ; If 8088/8086
285            ALIGN JUMP_ALIGN
286        ReadBlockFrom8bitDataPort:
287            UNROLL_SECTORS_IN_CX_TO_DWORDS
288        ALIGN JUMP_ALIGN
289        .ReadNextDword:
290            in      al, dx      ; Read 1st BYTE
291            stosb               ; Store 1st BYTE to [ES:DI]
292            in      al, dx
293            stosb
[442]294
[444]295            in      al, dx
296            stosb
297            in      al, dx
298            stosb
299            loop    .ReadNextDword
300            ret
301    %endif
[400]302%endif  ; MODULE_8BIT_IDE
303
[361]304;--------------------------------------------------------------------
[401]305%ifdef USE_186
[444]306    ALIGN JUMP_ALIGN
307    ReadBlockFrom16bitDataPort:
308        xchg    cl, ch      ; Sectors to WORDs
309        rep insw
310        ret
[401]311%endif
[152]312
[361]313;--------------------------------------------------------------------
[401]314%ifdef USE_AT
[444]315    ALIGN JUMP_ALIGN
316    ReadBlockFrom32bitDataPort:
317        shl     cx, 7       ; Sectors to DWORDs
318        rep
319        db      66h         ; Override operand size to 32-bit
320        db      6Dh         ; INSW/INSD
321        ret
[401]322%endif
[152]323
324
[150]325;--------------------------------------------------------------------
[361]326; WriteBlockToXtideRev1         XTIDE rev 1
327; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
[444]328; WriteBlockTo8bitDataPort      XT-CF when using 8-bit PIO
[361]329; WriteBlockTo16bitDataPort     Normal 16-bit IDE
330; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
[150]331;   Parameters:
[363]332;       CX:     Block size in 512-byte sectors
[150]333;       DX:     IDE Data port address
334;       ES:SI:  Normalized ptr to buffer containing data
335;   Returns:
336;       Nothing
337;   Corrupts registers:
[417]338;       AX, BX, CX, DX
[150]339;--------------------------------------------------------------------
[400]340%ifdef MODULE_8BIT_IDE
341
[444]342    ALIGN JUMP_ALIGN
343    WriteBlockToXtideRev1:
344        push    ds
345        UNROLL_SECTORS_IN_CX_TO_QWORDS
346        mov     bl, 8       ; Bit mask for toggling data low/high reg
347        push    es          ; Copy ES...
348        pop     ds          ; ...to DS
349    ALIGN JUMP_ALIGN
350    .OutswLoop:
351        XTIDE_OUTSW
352        XTIDE_OUTSW
353        XTIDE_OUTSW
354        XTIDE_OUTSW
355        loop    .OutswLoop
356        pop     ds
357        ret
[150]358
[444]359    ;--------------------------------------------------------------------
360    ALIGN JUMP_ALIGN
361    WriteBlockToXtideRev2:
362        UNROLL_SECTORS_IN_CX_TO_QWORDS
363        push    ds
364        push    es          ; Copy ES...
365        pop     ds          ; ...to DS
366    ALIGN JUMP_ALIGN
367    .WriteNextQword:
368        XTIDE_MOD_OUTSW
369        XTIDE_MOD_OUTSW
370        XTIDE_MOD_OUTSW
371        XTIDE_MOD_OUTSW
372        loop    .WriteNextQword
373        pop     ds
374        ret
[150]375
[444]376    ;--------------------------------------------------------------------
377    %ifdef USE_186
378        ALIGN JUMP_ALIGN
379        WriteBlockTo8bitDataPort:
380            shl     cx, 9       ; Sectors to BYTEs
381            es                  ; Source is ES segment
382            rep outsb
383            ret
[442]384
[444]385    %else ; If 8088/8086
386        ALIGN JUMP_ALIGN
387        WriteBlockTo8bitDataPort:
388            UNROLL_SECTORS_IN_CX_TO_DWORDS
389            push    ds
390            push    es
391            pop     ds
392        ALIGN JUMP_ALIGN
393        .WriteNextDword:
394            lodsb               ; Load 1st BYTE from [DS:SI]
395            out     dx, al      ; Write 1st BYTE
396            lodsb
397            out     dx, al
398
399            lodsb
400            out     dx, al
401            lodsb
402            out     dx, al
403            loop    .WriteNextDword
404            pop     ds
405            ret
406    %endif
[400]407%endif  ; MODULE_8BIT_IDE
408
[361]409;--------------------------------------------------------------------
[402]410%ifdef USE_AT
[361]411ALIGN JUMP_ALIGN
412WriteBlockTo16bitDataPort:
[363]413    xchg    cl, ch      ; Sectors to WORDs
[223]414    es                  ; Source is ES segment
[444]415    rep outsw
[152]416    ret
417
[361]418;--------------------------------------------------------------------
[152]419ALIGN JUMP_ALIGN
[361]420WriteBlockTo32bitDataPort:
[444]421    shl     cx, 7       ; Sectors to DWORDs
[223]422    es                  ; Source is ES segment
[152]423    rep
424    db      66h         ; Override operand size to 32-bit
425    db      6Fh         ; OUTSW/OUTSD
426    ret
[421]427%endif ; USE_AT
[152]428
429
[361]430
[150]431; Lookup tables to get transfer function based on bus type
432ALIGN WORD_ALIGN
433g_rgfnPioRead:
[400]434%ifdef MODULE_8BIT_IDE
[401]435        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
[444]436        dw      ReadBlockFrom8bitDataPort   ; 1, DEVICE_8BIT_XTCF
[400]437    %ifdef USE_186
[401]438        dw      ReadBlockFrom16bitDataPort  ; 2, DEVICE_8BIT_XTIDE_REV2
[400]439    %else
[401]440        dw      ReadBlockFromXtideRev2      ; 2, DEVICE_8BIT_XTIDE_REV2
[400]441    %endif
[401]442        dw      ReadBlockFromXtideRev1      ; 3, DEVICE_XTIDE_REV1
[400]443
[152]444%else
[400]445        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
[152]446%endif
[401]447%ifdef USE_AT
448        dw      ReadBlockFrom16bitDataPort  ; 4, DEVICE_16BIT_ATA
449        dw      ReadBlockFrom32bitDataPort  ; 5, DEVICE_32BIT_ATA
450%endif
[152]451
[400]452
[150]453g_rgfnPioWrite:
[400]454%ifdef MODULE_8BIT_IDE
[401]455        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
[444]456        dw      WriteBlockTo8bitDataPort    ; 1, DEVICE_8BIT_XTCF
[401]457        dw      WriteBlockToXtideRev2       ; 2, DEVICE_XTIDE_REV2
458        dw      WriteBlockToXtideRev1       ; 3, DEVICE_XTIDE_REV1
[400]459
[361]460%else
[400]461        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
[361]462%endif
[401]463%ifdef USE_AT
464        dw      WriteBlockTo16bitDataPort   ; 4, DEVICE_16BIT_ATA
465        dw      WriteBlockTo32bitDataPort   ; 5, DEVICE_32BIT_ATA
466%endif
Note: See TracBrowser for help on using the repository browser.