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

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

Changes to XTIDE Universal BIOS:

  • ATA ID validation now compares heads to correct maximum number of heads.
  • Added XTCF 8-bit mode transfer functions.
File size: 12.9 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)
230; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
231; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
[150]232;   Parameters:
[363]233;       CX:     Block size in 512 byte sectors
[150]234;       DX:     IDE Data port address
[242]235;       ES:DI:  Normalized ptr to buffer to receive data
[150]236;   Returns:
237;       Nothing
238;   Corrupts registers:
239;       AX, BX, CX
240;--------------------------------------------------------------------
[400]241%ifdef MODULE_8BIT_IDE
242
[150]243ALIGN JUMP_ALIGN
[361]244ReadBlockFromXtideRev1:
[363]245    UNROLL_SECTORS_IN_CX_TO_QWORDS
[370]246    mov     bl, 8       ; Bit mask for toggling data low/high reg
[150]247ALIGN JUMP_ALIGN
248.InswLoop:
[152]249    XTIDE_INSW
250    XTIDE_INSW
251    XTIDE_INSW
252    XTIDE_INSW
[150]253    loop    .InswLoop
254    ret
255
[361]256;--------------------------------------------------------------------
257%ifndef USE_186         ; 8086/8088 compatible WORD read
[150]258ALIGN JUMP_ALIGN
[361]259ReadBlockFromXtideRev2:
[363]260    UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]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
[150]274
[442]275;--------------------------------------------------------------------
276ALIGN JUMP_ALIGN
277ReadBlockFromXTCF:
278    UNROLL_SECTORS_IN_CX_TO_DWORDS
279ALIGN JUMP_ALIGN
280.ReadNextDword:
281    in      al, dx      ; Read 1st BYTE
282    stosb               ; Store 1st BYTE to [ES:DI]
283    in      al, dx
284    stosb
285
286    in      al, dx
287    stosb
288    in      al, dx
289    stosb
290    loop    .ReadNextDword
291    ret
292
[400]293%endif  ; MODULE_8BIT_IDE
294
[361]295;--------------------------------------------------------------------
[401]296%ifdef USE_186
[152]297ALIGN JUMP_ALIGN
[361]298ReadBlockFrom16bitDataPort:
[363]299    xchg    cl, ch      ; Sectors to WORDs
[152]300    rep
301    db      6Dh         ; INSW (we want this in XT build)
302    ret
[401]303%endif
[152]304
[361]305;--------------------------------------------------------------------
[401]306%ifdef USE_AT
[152]307ALIGN JUMP_ALIGN
[361]308ReadBlockFrom32bitDataPort:
[363]309    db      0C1h        ; SHL
310    db      0E1h        ; CX
311    db      7           ; 7 (Sectors to DWORDs)
[152]312    rep
313    db      66h         ; Override operand size to 32-bit
314    db      6Dh         ; INSW/INSD
315    ret
[401]316%endif
[152]317
318
[150]319;--------------------------------------------------------------------
[361]320; WriteBlockToXtideRev1         XTIDE rev 1
321; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
322; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
323; WriteBlockTo16bitDataPort     Normal 16-bit IDE
324; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
[150]325;   Parameters:
[363]326;       CX:     Block size in 512-byte sectors
[150]327;       DX:     IDE Data port address
328;       ES:SI:  Normalized ptr to buffer containing data
329;   Returns:
330;       Nothing
331;   Corrupts registers:
[417]332;       AX, BX, CX, DX
[150]333;--------------------------------------------------------------------
[400]334%ifdef MODULE_8BIT_IDE
335
[150]336ALIGN JUMP_ALIGN
[361]337WriteBlockToXtideRev1:
[150]338    push    ds
[363]339    UNROLL_SECTORS_IN_CX_TO_QWORDS
[370]340    mov     bl, 8       ; Bit mask for toggling data low/high reg
[152]341    push    es          ; Copy ES...
342    pop     ds          ; ...to DS
[150]343ALIGN JUMP_ALIGN
344.OutswLoop:
[152]345    XTIDE_OUTSW
346    XTIDE_OUTSW
347    XTIDE_OUTSW
348    XTIDE_OUTSW
[150]349    loop    .OutswLoop
350    pop     ds
351    ret
352
[361]353;--------------------------------------------------------------------
[150]354ALIGN JUMP_ALIGN
[361]355WriteBlockToXtideRev2:
[363]356    UNROLL_SECTORS_IN_CX_TO_QWORDS
[152]357    push    ds
358    push    es          ; Copy ES...
359    pop     ds          ; ...to DS
360ALIGN JUMP_ALIGN
361.WriteNextQword:
362    XTIDE_MOD_OUTSW
363    XTIDE_MOD_OUTSW
364    XTIDE_MOD_OUTSW
365    XTIDE_MOD_OUTSW
366    loop    .WriteNextQword
367    pop     ds
368    ret
[150]369
[361]370;--------------------------------------------------------------------
[152]371ALIGN JUMP_ALIGN
[442]372WriteBlockToXTCF:
373    UNROLL_SECTORS_IN_CX_TO_DWORDS
[361]374    push    ds
375    push    es
376    pop     ds
377ALIGN JUMP_ALIGN
[442]378.WriteNextDword:
379    lodsb               ; Load 1st BYTE from [DS:SI]
380    out     dx, al      ; Write 1st BYTE
381    lodsb
382    out     dx, al
383
384    lodsb
385    out     dx, al
386    lodsb
387    out     dx, al
388    loop    .WriteNextDword
[361]389    pop     ds
390    ret
[400]391%endif  ; MODULE_8BIT_IDE
392
[421]393
[361]394;--------------------------------------------------------------------
[402]395%ifdef USE_AT
[361]396ALIGN JUMP_ALIGN
397WriteBlockTo16bitDataPort:
[363]398    xchg    cl, ch      ; Sectors to WORDs
[223]399    es                  ; Source is ES segment
[152]400    rep
[155]401    db      6Fh         ; OUTSW (we want this in XT build)
[152]402    ret
403
[361]404;--------------------------------------------------------------------
[152]405ALIGN JUMP_ALIGN
[361]406WriteBlockTo32bitDataPort:
[363]407    db      0C1h        ; SHL
408    db      0E1h        ; CX
409    db      7           ; 7 (Sectors to DWORDs)
[223]410    es                  ; Source is ES segment
[152]411    rep
412    db      66h         ; Override operand size to 32-bit
413    db      6Fh         ; OUTSW/OUTSD
414    ret
[421]415%endif ; USE_AT
[152]416
417
[361]418
[150]419; Lookup tables to get transfer function based on bus type
420ALIGN WORD_ALIGN
421g_rgfnPioRead:
[400]422%ifdef MODULE_8BIT_IDE
[401]423        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
[442]424        dw      ReadBlockFromXTCF           ; 1, DEVICE_8BIT_XTCF
[400]425    %ifdef USE_186
[401]426        dw      ReadBlockFrom16bitDataPort  ; 2, DEVICE_8BIT_XTIDE_REV2
[400]427    %else
[401]428        dw      ReadBlockFromXtideRev2      ; 2, DEVICE_8BIT_XTIDE_REV2
[400]429    %endif
[401]430        dw      ReadBlockFromXtideRev1      ; 3, DEVICE_XTIDE_REV1
[400]431
[152]432%else
[400]433        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
[152]434%endif
[401]435%ifdef USE_AT
436        dw      ReadBlockFrom16bitDataPort  ; 4, DEVICE_16BIT_ATA
437        dw      ReadBlockFrom32bitDataPort  ; 5, DEVICE_32BIT_ATA
438%endif
[152]439
[400]440
[150]441g_rgfnPioWrite:
[400]442%ifdef MODULE_8BIT_IDE
[401]443        dw      0                           ; 0, DEVICE_8BIT_JRIDE_ISA
[442]444        dw      WriteBlockToXTCF            ; 1, DEVICE_8BIT_XTCF
[401]445        dw      WriteBlockToXtideRev2       ; 2, DEVICE_XTIDE_REV2
446        dw      WriteBlockToXtideRev1       ; 3, DEVICE_XTIDE_REV1
[400]447
[361]448%else
[400]449        times   COUNT_OF_8BIT_IDE_DEVICES   dw  0
[361]450%endif
[401]451%ifdef USE_AT
452        dw      WriteBlockTo16bitDataPort   ; 4, DEVICE_16BIT_ATA
453        dw      WriteBlockTo32bitDataPort   ; 5, DEVICE_32BIT_ATA
454%endif
Note: See TracBrowser for help on using the repository browser.