source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/Common/HPIO.asm @ 26

Last change on this file since 26 was 26, checked in by aitotat, 14 years ago

Fixed a bug where Disk Parameter Table was accessed with wrong pointer register after writing last block
Cleaned AH=00h, Disk Controller Reset a bit

File size: 9.7 KB
Line 
1; File name     :   HPIO.asm
2; Project name  :   IDE BIOS
3; Created date  :   14.12.2007
4; Last update   :   14.4.2010
5; Author        :   Tomi Tilli
6; Description   :   PIO transfer functions.
7
8; Structure containing variables for PIO transfer functions
9struc PIOVARS
10    .fnXfer         resb    2   ; Offset to transfer function
11    .wBlockSize     resb    2   ; Block size in WORDs
12    .wWordsLeft     resb    2   ; Number of WORDs left to transfer
13                                ; (full sectors, can be partial block)
14endstruc
15
16
17; Section containing code
18SECTION .text
19
20;--------------------------------------------------------------------
21; Normalizes far pointer to that offset overflows won't happen
22; when transferring data using PIO.
23;
24; HPIO_NORMALIZE_PTR
25;   Parameters:
26;       %1:%2:      Far pointer to normalize
27;       %3:         Scratch register
28;       %4:         Scratch register
29;   Returns:
30;       %1:%2:      Normalized far pointer
31;   Corrupts registers:
32;       %3, %4
33;--------------------------------------------------------------------
34%macro HPIO_NORMALIZE_PTR 4
35    mov     %4, %2              ; Copy offset to scratch reg
36    and     %2, BYTE 0Fh        ; Clear offset bits 15...4
37    eSHR_IM %4, 4               ; Divide offset by 16
38    mov     %3, %1              ; Copy segment to scratch reg
39    add     %3, %4              ; Add shifted offset to segment
40    mov     %1, %3              ; Set normalized segment
41%endmacro
42
43
44;--------------------------------------------------------------------
45; Reads sectors from hard disk using PIO transfer mode.
46;
47; HPIO_ReadBlock
48;   Parameters:
49;       AL:     Number of sectors to read (1...255)
50;       ES:BX:  Pointer to buffer to recieve data
51;       DS:DI:  Ptr to Disk Parameter Table
52;   Returns:
53;       AH:     BIOS Error code
54;       CF:     0 if transfer succesfull
55;               1 if any error
56;   Corrupts registers:
57;       AL, BX, CX, DX
58;--------------------------------------------------------------------
59ALIGN JUMP_ALIGN
60HPIO_ReadBlock:
61    push    es
62
63    ; Create PIOVARS to stack
64    eENTER  PIOVARS_size, 0
65    sub     bp, BYTE PIOVARS_size           ; SS:BP now points to PIOVARS
66    push    si
67    mov     si, g_rgfnPioRead               ; Offset to read function lookup
68    call    HPIO_InitializePIOVARS          ; Store word count and block size
69    pop     si
70
71    ; Start to read data
72    xchg    bx, di                          ; DS:BX points DPT, ES:DI points buffer
73    mov     dx, [RAMVARS.wIdeBase]          ; Load IDE Base Port address
74    call    HPIO_ReadFromDrive
75
76    ; Destroy stack frame
77    rcl     al, 1                           ; CF to AL bit 0
78    add     bp, BYTE PIOVARS_size
79    eLEAVE
80    rcr     al, 1                           ; Restore CF
81    mov     di, bx                          ; Restore DI
82    pop     es
83    ret
84
85
86;--------------------------------------------------------------------
87; Initializes PIOVARS members.
88;
89; HPIO_InitializePIOVARS
90;   Parameters:
91;       AL:     Number of sectors to transfer (1...255)
92;       SI:     Offset to transfer function lookup table
93;       DS:DI:  Ptr to Disk Parameter Table
94;       ES:BX:  Ptr to source or destination data buffer
95;       SS:BP:  Ptr to PIOVARS
96;   Returns:
97;       ES:BX:  Normalized pointer to data buffer
98;   Corrupts registers:
99;       AX, CX
100;--------------------------------------------------------------------
101ALIGN JUMP_ALIGN
102HPIO_InitializePIOVARS:
103    ; Store number of WORDs to transfer
104    mov     ah, al                              ; Number of WORDs to transfer...
105    xor     al, al                              ; ...to AX
106    mov     [bp+PIOVARS.wWordsLeft], ax         ; Store WORD count
107
108    ; Store block size in WORDs
109    mov     ah, [di+DPT.bSetBlock]              ; AX = block size in WORDs
110    mov     [bp+PIOVARS.wBlockSize], ax         ; Store block size
111
112    ; Get transfer function based on bus type
113    xchg    ax, bx                              ; Backup BX
114    eMOVZX  bx, BYTE [di+DPT.bIdeOff]           ; CS:BX now points to IDEVARS
115    mov     bl, BYTE [cs:bx+IDEVARS.bBusType]   ; Load bus type to BX
116    mov     bx, [cs:bx+si]                      ; Load offset to transfer function
117    mov     [bp+PIOVARS.fnXfer], bx             ; Store offset to transfer function
118    xchg    bx, ax
119    ; Fall to HPIO_NormalizePtr
120
121;--------------------------------------------------------------------
122; Initializes PIOVARS members.
123;
124; HPIO_InitializePIOVARS
125;   Parameters:
126;       ES:BX:  Ptr to source or destination data buffer
127;   Returns:
128;       ES:BX:  Normalized pointer to data buffer
129;   Corrupts registers:
130;       AX, CX
131;--------------------------------------------------------------------
132;ALIGN JUMP_ALIGN
133HPIO_NormalizeDataPointer:
134    HPIO_NORMALIZE_PTR  es, bx, ax, cx
135    ret
136
137
138;--------------------------------------------------------------------
139; Reads blocks using PIO transfers.
140;
141; HPIO_ReadFromDrive
142;   Parameters:
143;       DX:     IDE Data port address
144;       DS:BX:  Ptr to DPT (in RAMVARS segment)
145;       ES:DI:  Normalized ptr to buffer to recieve data
146;       SS:BP:  Ptr to PIOVARS
147;   Returns:
148;       AH:     BIOS Error code
149;       CF:     0 if transfer succesfull
150;               1 if any error
151;   Corrupts registers:
152;       AL, CX, DX, DI
153;--------------------------------------------------------------------
154ALIGN JUMP_ALIGN
155HPIO_ReadFromDrive:
156    cld                                 ; INS to increment DI
157ALIGN JUMP_ALIGN
158.BlockLoop:
159    call    HStatus_WaitIrqOrDrq        ; Wait until ready to transfer
160    jc      SHORT .RetError             ; Return if error (code in AH)
161    mov     cx, [bp+PIOVARS.wBlockSize] ; Load block size
162    sub     [bp+PIOVARS.wWordsLeft], cx ; Transferring last (possibly partial) block?
163    jbe     SHORT .XferLastBlock        ;  If so, jump to transfer
164    call    [bp+PIOVARS.fnXfer]         ; Transfer full block
165    jmp     SHORT .BlockLoop            ; Loop while blocks left
166ALIGN JUMP_ALIGN
167.XferLastBlock:
168    add     cx, [bp+PIOVARS.wWordsLeft] ; CX to partial block size
169    call    [bp+PIOVARS.fnXfer]         ; Transfer possibly partial block
170    call    HStatus_ReadAndIgnoreAlternateStatus
171    jmp     HStatus_WaitBsyDefTime      ; Check for errors
172.RetError:
173    ret
174
175
176;--------------------------------------------------------------------
177; Writes sectors to hard disk using PIO transfer mode.
178;
179; HPIO_WriteBlock
180;   Parameters:
181;       AL:     Number of sectors to write (1...255)
182;       ES:BX:  Pointer to buffer containing data
183;       DS:DI:  Ptr to Disk Parameter Table
184;   Returns:
185;       AH:     BIOS Error code
186;       CF:     0 if transfer successfull
187;               1 if any error
188;   Corrupts registers:
189;       AL, BX, CX, DX
190;--------------------------------------------------------------------
191ALIGN JUMP_ALIGN
192HPIO_WriteBlock:
193    push    es
194    push    si
195
196    ; Create PIOVARS to stack
197    eENTER  PIOVARS_size, 0
198    sub     bp, BYTE PIOVARS_size           ; SS:BP now points to PIOVARS
199    mov     si, g_rgfnPioWrite              ; Offset to write function lookup
200    call    HPIO_InitializePIOVARS          ; Store word count and block size
201
202    ; Prepare pointers and start transfer
203    mov     si, bx                          ; ES:SI now points source buffer
204    mov     bx, di                          ; DS:BX now points DPT
205    call    HPIO_WriteToDrive
206
207    ; Destroy stack frame
208    rcl     al, 1                           ; CF to AL bit 0
209    add     bp, BYTE PIOVARS_size
210    eLEAVE
211    rcr     al, 1                           ; Restore CF
212    pop     si
213    pop     es
214    ret
215
216;--------------------------------------------------------------------
217; Writes blocks using PIO transfers.
218;
219; HPIO_WriteToDrive
220;   Parameters:
221;       DS:BX:  Ptr to DPT (in RAMVARS segment)
222;       ES:SI:  Normalized ptr to buffer containing data
223;       SS:BP:  Ptr to PIOVARS
224;   Returns:
225;       AH:     BIOS Error code
226;       CF:     0 if transfer succesfull
227;               1 if any error
228;   Corrupts registers:
229;       AL, CX, DX, SI
230;--------------------------------------------------------------------
231ALIGN JUMP_ALIGN
232HPIO_WriteToDrive:
233    cld                                     ; OUTS to increment SI
234    call    HStatus_WaitDrqDefTime          ; Always poll DRQ for first block, get data port to DX
235    jc      SHORT .RetError                 ; Return if error (code in AH)
236    sub     dx, BYTE REGR_IDE_ST            ; DX to Data Port address
237ALIGN JUMP_ALIGN
238.BlockLoop:
239    mov     cx, [bp+PIOVARS.wBlockSize]     ; Load block size
240    sub     [bp+PIOVARS.wWordsLeft], cx     ; Transferring last (possibly partial) block?
241    jbe     SHORT .XferLastBlock            ;  If so, jump to transfer
242    call    [bp+PIOVARS.fnXfer]             ; Transfer full block
243    call    HStatus_WaitIrqOrDrq            ; Wait until ready to transfer
244    jnc     SHORT .BlockLoop                ; If no error, loop while blocks left
245.RetError:
246    ret
247ALIGN JUMP_ALIGN
248.XferLastBlock:
249    add     cx, [bp+PIOVARS.wWordsLeft]     ; CX to partial block size
250    call    [bp+PIOVARS.fnXfer]             ; Transfer possibly partial block
251    jmp     HStatus_WaitIrqOrRdy            ; Check for errors
252
253
254;--------------------------------------------------------------------
255; Bus specific transfer functions and lookup table.
256;
257; HPIO_DualByteRead     Dual port 8-bit XTIDE PIO read transfer
258; HPIO_WordRead         Normal 16-bit IDE PIO read transfer
259; HPIO_DualByteWrite    Dual port 8-bit XTIDE PIO write transfer
260; HPIO_WordWrite        Normal 16-bit IDE PIO write transfer
261;   Parameters:
262;       CX:     Block size in WORDs
263;       DX:     IDE Data port address
264;       ES:DI:  Normalized ptr to buffer to recieve data (read only)
265;       ES:SI:  Normalized ptr to buffer containing data (write only)
266;   Returns:
267;       Nothing
268;   Corrupts registers:
269;       AX, CX
270;--------------------------------------------------------------------
271ALIGN JUMP_ALIGN
272HPIO_DualByteRead:
273    eREP_DUAL_BYTE_PORT_INSW
274    ret
275ALIGN JUMP_ALIGN
276HPIO_WordRead:
277    rep
278    db      6Dh         ; INSW
279    ret
280ALIGN JUMP_ALIGN
281HPIO_DWordRead:
282    shr     cx, 1       ; WORD count to DWORD count
283    rep
284    db      66h         ; Override operand size to 32-bit
285    db      6Dh         ; INSW/INSD
286    ret
287ALIGN JUMP_ALIGN
288HPIO_SingleByteRead:
289    eREP_SINGLE_BYTE_PORT_INSW
290    ret
291
292ALIGN JUMP_ALIGN
293HPIO_DualByteWrite:
294    eREP_DUAL_BYTE_PORT_OUTSW
295    ret
296ALIGN JUMP_ALIGN
297HPIO_WordWrite:
298    eSEG    es          ; Source is ES segment
299    rep
300    db      6Fh         ; OUTSW
301    ret
302ALIGN JUMP_ALIGN
303HPIO_DWordWrite:
304    shr     cx, 1       ; WORD count to DWORD count
305    eSEG    es          ; Source is ES segment
306    rep
307    db      66h         ; Override operand size to 32-bit
308    db      6Fh         ; OUTSW/OUTSD
309    ret
310ALIGN JUMP_ALIGN
311HPIO_SingleByteWrite:
312    eREP_SINGLE_BYTE_PORT_OUTSW
313    ret
314
315ALIGN WORD_ALIGN
316g_rgfnPioRead:
317    dw      HPIO_DualByteRead       ; 8-bit dual port reads
318    dw      HPIO_WordRead           ; 16-bit reads
319    dw      HPIO_DWordRead          ; 32-bit reads
320    dw      HPIO_SingleByteRead     ; 8-bit single port reads
321g_rgfnPioWrite:
322    dw      HPIO_DualByteWrite      ; 8-bit dual port writes
323    dw      HPIO_WordWrite          ; 16-bit writes
324    dw      HPIO_DWordWrite         ; 32-bit writes
325    dw      HPIO_SingleByteWrite    ; 8-bit single port writes
Note: See TracBrowser for help on using the repository browser.