Subversion Repositories Kolibri OS

Rev

Rev 4423 | Rev 5577 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4423 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
5565 serge 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4423 Serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 4420 $
9
 
10
 
11
; Access through BIOS by diamond
12
iglobal
13
align 4
14
bd_callbacks:
15
        dd      bd_callbacks.end - bd_callbacks         ; strucsize
16
        dd      0       ; no close function
17
        dd      0       ; no closemedia function
18
        dd      bd_querymedia
19
        dd      bd_read_interface
20
        dd      bd_write_interface
21
        dd      0       ; no flush function
22
        dd      0       ; use default cache size
23
.end:
24
endg
25
 
26
proc bd_read_interface stdcall uses edi, \
27
        userdata, buffer, startsector:qword, numsectors
28
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
29
        ; buffer = pointer to buffer for data
30
        ; startsector = 64-bit start sector
31
        ; numsectors = pointer to number of sectors on input,
32
        ;  must be filled with number of sectors really read
33
locals
34
sectors_todo    dd      ?
35
endl
36
; 1. Initialize number of sectors: get number of requested sectors
37
; and say that no sectors were read yet.
38
        mov     ecx, [numsectors]
39
        mov     eax, [ecx]
40
        mov     dword [ecx], 0
41
        mov     [sectors_todo], eax
42
; 2. Acquire the global lock.
43
        mov     ecx, ide_mutex
44
        call    mutex_lock
45
; 3. Convert parameters to the form suitable for worker procedures.
46
; Underlying procedures do not know about 64-bit sectors.
47
; Worker procedures use global variables and edi for [buffer].
48
        cmp     dword [startsector+4], 0
49
        jnz     .fail
50
        and     [hd_error], 0
51
        mov     eax, [userdata]
52
        mov     [hdpos], eax
53
        mov     eax, dword [startsector]
54
        mov     edi, [buffer]
55
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
56
.sectors_loop:
57
        call    bd_read
58
        cmp     [hd_error], 0
59
        jnz     .fail
60
        mov     ecx, [numsectors]
61
        inc     dword [ecx]     ; one more sector is read
62
        dec     [sectors_todo]
63
        jz      .done
64
        inc     eax
65
        jnz     .sectors_loop
66
; 5. Loop is done, either due to error or because everything is done.
67
; Release the global lock and return the corresponding status.
68
.fail:
69
        mov     ecx, ide_mutex
70
        call    mutex_unlock
71
        or      eax, -1
72
        ret
73
.done:
74
        mov     ecx, ide_mutex
75
        call    mutex_unlock
76
        xor     eax, eax
77
        ret
78
endp
79
 
80
proc bd_write_interface stdcall uses esi edi, \
81
        userdata, buffer, startsector:qword, numsectors
82
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
83
        ; buffer = pointer to buffer with data
84
        ; startsector = 64-bit start sector
85
        ; numsectors = pointer to number of sectors on input,
86
        ;  must be filled with number of sectors really written
87
locals
88
sectors_todo    dd      ?
89
endl
90
; 1. Initialize number of sectors: get number of requested sectors
91
; and say that no sectors were read yet.
92
        mov     ecx, [numsectors]
93
        mov     eax, [ecx]
94
        mov     dword [ecx], 0
95
        mov     [sectors_todo], eax
96
; 2. Acquire the global lock.
97
        mov     ecx, ide_mutex
98
        call    mutex_lock
99
; 3. Convert parameters to the form suitable for worker procedures.
100
; Underlying procedures do not know about 64-bit sectors.
101
; Worker procedures use global variables and esi for [buffer].
102
        cmp     dword [startsector+4], 0
103
        jnz     .fail
104
        and     [hd_error], 0
105
        mov     eax, [userdata]
106
        mov     [hdpos], eax
107
        mov     esi, [buffer]
108
        lea     edi, [startsector]
109
        mov     [cache_chain_ptr], edi
110
; 4. Worker procedures take max 16 sectors per time,
111
; loop until all sectors will be processed.
112
.sectors_loop:
113
        mov     ecx, 16
114
        cmp     ecx, [sectors_todo]
115
        jbe     @f
116
        mov     ecx, [sectors_todo]
117
@@:
118
        mov     [cache_chain_size], cl
119
        call    bd_write_cache_chain
120
        cmp     [hd_error], 0
121
        jnz     .fail
122
        movzx   ecx, [cache_chain_size]
123
        mov     eax, [numsectors]
124
        add     [eax], ecx
125
        sub     [sectors_todo], ecx
126
        jz      .done
127
        add     [edi], ecx
128
        jc      .fail
129
        shl     ecx, 9
130
        add     esi, ecx
131
        jmp     .sectors_loop
132
; 5. Loop is done, either due to error or because everything is done.
133
; Release the global lock and return the corresponding status.
134
.fail:
135
        mov     ecx, ide_mutex
136
        call    mutex_unlock
137
        or      eax, -1
138
        ret
139
.done:
140
        mov     ecx, ide_mutex
141
        call    mutex_unlock
142
        xor     eax, eax
143
        ret
144
endp
145
 
146
; This is a stub.
147
proc bd_querymedia stdcall, hd_data, mediainfo
148
        mov     eax, [mediainfo]
149
        mov     [eax+DISKMEDIAINFO.Flags], 0
150
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
151
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
152
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
153
        xor     eax, eax
154
        ret
155
endp
156
 
157
;-----------------------------------------------------------------------------
158
; \begin{diamond}
159
uglobal
160
bios_hdpos      dd 0       ; 0 is invalid value for [hdpos]
161
bios_cur_sector dd ?
162
bios_read_len   dd ?
163
endg
164
;-----------------------------------------------------------------------------
165
align 4
166
bd_read:
167
        push    eax
168
        push    edx
169
        mov     edx, [bios_hdpos]
170
        cmp     edx, [hdpos]
171
        jne     .notread
172
        mov     edx, [bios_cur_sector]
173
        cmp     eax, edx
174
        jb      .notread
175
        add     edx, [bios_read_len]
176
        dec     edx
177
        cmp     eax, edx
178
        ja      .notread
179
        sub     eax, [bios_cur_sector]
180
        shl     eax, 9
181
        add     eax, (OS_BASE+0x9A000)
182
        push    ecx esi
183
        mov     esi, eax
184
        mov     ecx, 512/4
185
        cld
186
        rep movsd
187
        pop     esi ecx
188
        pop     edx
189
        pop     eax
190
        ret
191
.notread:
192
        push    ecx
193
        mov     dl, 42h
194
        mov     ecx, 16
195
        call    int13_call
196
        pop     ecx
197
        test    eax, eax
198
        jnz     .v86err
199
        test    edx, edx
200
        jz      .readerr
201
        mov     [bios_read_len], edx
202
        mov     edx, [hdpos]
203
        mov     [bios_hdpos], edx
204
        pop     edx
205
        pop     eax
206
        mov     [bios_cur_sector], eax
207
        jmp     bd_read
208
.readerr:
209
.v86err:
210
        mov     [hd_error], 1
211
        jmp     hd_read_error
212
;-----------------------------------------------------------------------------
213
align 4
214
bd_write_cache_chain:
215
        pusha
216
        mov     edi, OS_BASE + 0x9A000
217
        movzx   ecx, [cache_chain_size]
218
        push    ecx
219
        shl     ecx, 9-2
220
        rep movsd
221
        pop     ecx
222
        mov     dl, 43h
223
        mov     eax, [cache_chain_ptr]
224
        mov     eax, [eax]
225
        call    int13_call
226
        test    eax, eax
227
        jnz     .v86err
228
        cmp     edx, ecx
229
        jnz     .writeerr
230
        popa
231
        ret
232
.v86err:
233
.writeerr:
234
        popa
235
        mov     [hd_error], 1
236
        jmp     hd_write_error
237
;-----------------------------------------------------------------------------
238
uglobal
239
int13_regs_in   rb sizeof.v86_regs
240
int13_regs_out  rb sizeof.v86_regs
241
endg
242
;-----------------------------------------------------------------------------
243
align 4
244
int13_call:
245
; Because this code uses fixed addresses,
246
; it can not be run simultaniously by many threads.
247
; In current implementation it is protected by common mutex 'ide_status'
248
        mov     word [OS_BASE + 510h], 10h             ; packet length
249
        mov     word [OS_BASE + 512h], cx              ; number of sectors
250
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
251
        mov     dword [OS_BASE + 518h], eax
252
        and     dword [OS_BASE + 51Ch], 0
253
        push    ebx ecx esi edi
254
        mov     ebx, int13_regs_in
255
        mov     edi, ebx
256
        mov     ecx, sizeof.v86_regs/4
257
        xor     eax, eax
258
        rep stosd
259
        mov     byte [ebx+v86_regs.eax+1], dl
260
        mov     eax, [hdpos]
261
        lea     eax, [BiosDisksData+(eax-80h)*4]
262
        mov     dl, [eax]
263
        mov     byte [ebx+v86_regs.edx], dl
264
        movzx   edx, byte [eax+1]
265
;        mov     dl, 5
266
        test    edx, edx
267
        jnz     .hasirq
268
        dec     edx
269
        jmp     @f
270
.hasirq:
271
        pushad
272
        stdcall enable_irq, edx
273
        popad
274
@@:
275
        mov     word [ebx+v86_regs.esi], 510h
276
        mov     word [ebx+v86_regs.ss], 9000h
277
        mov     word [ebx+v86_regs.esp], 0A000h
278
        mov     word [ebx+v86_regs.eip], 500h
279
        mov     [ebx+v86_regs.eflags], 20200h
280
        mov     esi, [sys_v86_machine]
281
        mov     ecx, 0x502
282
        push    fs
283
        call    v86_start
284
        pop     fs
285
        and     [bios_hdpos], 0
286
        pop     edi esi ecx ebx
287
        movzx   edx, byte [OS_BASE + 512h]
288
        test    byte [int13_regs_out+v86_regs.eflags], 1
289
        jnz     @f
290
        mov     edx, ecx
291
@@:
292
        ret
293
; \end{diamond}