Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3742 clevermous 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 3870 $
9
 
10
 
11
; Low-level driver for HDD access
12
; DMA support by Mario79
13
; Access through BIOS by diamond
3712 mario79 14
; LBA48 support by Mario79
15
;-----------------------------------------------------------------------------
3742 clevermous 16
struct HD_DATA
17
hdbase  dd      ?
18
hdid    dd      ?
19
hdpos   dd      ?
20
ends
21
 
22
iglobal
2288 clevermous 23
align 4
3742 clevermous 24
ide_callbacks:
25
        dd      ide_callbacks.end - ide_callbacks       ; strucsize
26
        dd      0       ; no close function
27
        dd      0       ; no closemedia function
28
        dd      ide_querymedia
29
        dd      ide_read
30
        dd      ide_write
31
        dd      0       ; no flush function
32
        dd      0       ; use default cache size
33
.end:
2288 clevermous 34
 
3742 clevermous 35
bd_callbacks:
36
        dd      bd_callbacks.end - bd_callbacks         ; strucsize
37
        dd      0       ; no close function
38
        dd      0       ; no closemedia function
39
        dd      bd_querymedia
40
        dd      bd_read_interface
41
        dd      bd_write_interface
42
        dd      0       ; no flush function
43
        dd      0       ; use default cache size
44
.end:
2288 clevermous 45
 
3742 clevermous 46
hd0_data        HD_DATA         ?,    0, 1
47
hd1_data        HD_DATA         ?, 0x10, 2
48
hd2_data        HD_DATA         ?,    0, 3
49
hd3_data        HD_DATA         ?, 0x10, 4
50
endg
2288 clevermous 51
 
3742 clevermous 52
uglobal
53
ide_mutex               MUTEX
54
ide_channel1_mutex      MUTEX
55
ide_channel2_mutex      MUTEX
56
endg
2288 clevermous 57
 
3742 clevermous 58
proc ide_read stdcall uses edi, \
59
        hd_data, buffer, startsector:qword, numsectors
60
        ; hd_data = pointer to hd*_data
61
        ; buffer = pointer to buffer for data
62
        ; startsector = 64-bit start sector
63
        ; numsectors = pointer to number of sectors on input,
64
        ;  must be filled with number of sectors really read
65
locals
66
sectors_todo    dd      ?
67
channel_lock    dd      ?
68
endl
69
; 1. Initialize number of sectors: get number of requested sectors
70
; and say that no sectors were read yet.
71
        mov     ecx, [numsectors]
72
        mov     eax, [ecx]
73
        mov     dword [ecx], 0
74
        mov     [sectors_todo], eax
75
; 2. Acquire the global lock.
76
        mov     ecx, ide_mutex
77
        call    mutex_lock
78
        mov     ecx, ide_channel2_mutex
79
        mov     eax, [hd_data]
3774 mario79 80
        push    ecx
81
        mov     ecx, [hd_address_table]
82
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
83
        pop     ecx
3742 clevermous 84
        jne     .IDE_Channel_2
85
        mov     ecx, ide_channel1_mutex
86
.IDE_Channel_2:
87
        mov     [channel_lock], ecx
88
        call    mutex_lock
89
; 3. Convert parameters to the form suitable for worker procedures.
90
; Underlying procedures do not know about 64-bit sectors.
91
; Worker procedures use global variables and edi for [buffer].
92
        cmp     dword [startsector+4], 0
93
        jnz     .fail
94
        and     [hd_error], 0
95
        mov     ecx, [hd_data]
96
        mov     eax, [ecx+HD_DATA.hdbase]
97
        mov     [hdbase], eax
98
        mov     eax, [ecx+HD_DATA.hdid]
99
        mov     [hdid], eax
100
        mov     eax, [ecx+HD_DATA.hdpos]
101
        mov     [hdpos], eax
102
        mov     eax, dword [startsector]
103
        mov     edi, [buffer]
104
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
105
.sectors_loop:
2288 clevermous 106
; DMA read is permitted if [allow_dma_access]=1 or 2
107
        cmp     [allow_dma_access], 2
108
        ja      .nodma
109
        cmp     [dma_hdd], 1
110
        jnz     .nodma
111
        call    hd_read_dma
112
        jmp     @f
113
.nodma:
114
        call    hd_read_pio
115
@@:
116
        cmp     [hd_error], 0
3742 clevermous 117
        jnz     .fail
118
        mov     ecx, [numsectors]
119
        inc     dword [ecx]     ; one more sector is read
120
        dec     [sectors_todo]
121
        jz      .done
122
        inc     eax
123
        jnz     .sectors_loop
124
; 5. Loop is done, either due to error or because everything is done.
125
; Release the global lock and return the corresponding status.
126
.fail:
127
        mov     ecx, [channel_lock]
128
        call    mutex_unlock
129
        mov     ecx, ide_mutex
130
        call    mutex_unlock
131
        or      eax, -1
132
        ret
133
.done:
134
        mov     ecx, [channel_lock]
135
        call    mutex_unlock
136
        mov     ecx, ide_mutex
137
        call    mutex_unlock
138
        xor     eax, eax
139
        ret
140
endp
3712 mario79 141
 
3742 clevermous 142
proc ide_write stdcall uses esi edi, \
143
        hd_data, buffer, startsector:qword, numsectors
144
        ; hd_data = pointer to hd*_data
145
        ; buffer = pointer to buffer with data
146
        ; startsector = 64-bit start sector
147
        ; numsectors = pointer to number of sectors on input,
148
        ;  must be filled with number of sectors really written
149
locals
150
sectors_todo    dd      ?
151
channel_lock    dd      ?
152
endl
153
; 1. Initialize number of sectors: get number of requested sectors
154
; and say that no sectors were read yet.
155
        mov     ecx, [numsectors]
156
        mov     eax, [ecx]
157
        mov     dword [ecx], 0
158
        mov     [sectors_todo], eax
159
; 2. Acquire the global lock.
160
        mov     ecx, ide_mutex
161
        call    mutex_lock
162
        mov     ecx, ide_channel2_mutex
163
        mov     eax, [hd_data]
3774 mario79 164
        push    ecx
165
        mov     ecx, [hd_address_table]
166
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
167
        pop     ecx
3742 clevermous 168
        jne     .IDE_Channel_2
169
        mov     ecx, ide_channel1_mutex
170
.IDE_Channel_2:
171
        mov     [channel_lock], ecx
172
        call    mutex_lock
173
; 3. Convert parameters to the form suitable for worker procedures.
174
; Underlying procedures do not know about 64-bit sectors.
175
; Worker procedures use global variables and esi for [buffer].
176
        cmp     dword [startsector+4], 0
177
        jnz     .fail
178
        and     [hd_error], 0
179
        mov     ecx, [hd_data]
180
        mov     eax, [ecx+HD_DATA.hdbase]
181
        mov     [hdbase], eax
182
        mov     eax, [ecx+HD_DATA.hdid]
183
        mov     [hdid], eax
184
        mov     eax, [ecx+HD_DATA.hdpos]
185
        mov     [hdpos], eax
186
        mov     esi, [buffer]
187
        lea     edi, [startsector]
188
        mov     [cache_chain_ptr], edi
189
; 4. Worker procedures take max 16 sectors per time,
190
; loop until all sectors will be processed.
191
.sectors_loop:
192
        mov     ecx, 16
193
        cmp     ecx, [sectors_todo]
194
        jbe     @f
195
        mov     ecx, [sectors_todo]
196
@@:
197
        mov     [cache_chain_size], cl
198
; DMA write is permitted only if [allow_dma_access]=1
199
        cmp     [allow_dma_access], 2
200
        jae     .nodma
201
        cmp     [dma_hdd], 1
202
        jnz     .nodma
203
        call    cache_write_dma
204
        jmp     .common
205
.nodma:
206
        mov     [cache_chain_size], 1
207
        call    cache_write_pio
208
.common:
209
        cmp     [hd_error], 0
210
        jnz     .fail
211
        movzx   ecx, [cache_chain_size]
212
        mov     eax, [numsectors]
213
        add     [eax], ecx
214
        sub     [sectors_todo], ecx
215
        jz      .done
216
        add     [edi], ecx
217
        jc      .fail
218
        shl     ecx, 9
219
        add     esi, ecx
220
        jmp     .sectors_loop
221
; 5. Loop is done, either due to error or because everything is done.
222
; Release the global lock and return the corresponding status.
223
.fail:
224
        mov     ecx, [channel_lock]
225
        call    mutex_unlock
226
        mov     ecx, ide_mutex
227
        call    mutex_unlock
228
        or      eax, -1
229
        ret
230
.done:
231
        mov     ecx, [channel_lock]
232
        call    mutex_unlock
233
        mov     ecx, ide_mutex
234
        call    mutex_unlock
235
        xor     eax, eax
236
        ret
237
endp
2288 clevermous 238
 
3742 clevermous 239
; This is a stub.
240
proc ide_querymedia stdcall, hd_data, mediainfo
241
        mov     eax, [mediainfo]
242
        mov     [eax+DISKMEDIAINFO.Flags], 0
243
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
244
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
245
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
246
        xor     eax, eax
247
        ret
248
endp
2288 clevermous 249
 
3742 clevermous 250
proc bd_read_interface stdcall uses edi, \
251
        userdata, buffer, startsector:qword, numsectors
252
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
253
        ; buffer = pointer to buffer for data
254
        ; startsector = 64-bit start sector
255
        ; numsectors = pointer to number of sectors on input,
256
        ;  must be filled with number of sectors really read
257
locals
258
sectors_todo    dd      ?
259
endl
260
; 1. Initialize number of sectors: get number of requested sectors
261
; and say that no sectors were read yet.
262
        mov     ecx, [numsectors]
263
        mov     eax, [ecx]
264
        mov     dword [ecx], 0
265
        mov     [sectors_todo], eax
266
; 2. Acquire the global lock.
267
        mov     ecx, ide_mutex
268
        call    mutex_lock
269
; 3. Convert parameters to the form suitable for worker procedures.
270
; Underlying procedures do not know about 64-bit sectors.
271
; Worker procedures use global variables and edi for [buffer].
272
        cmp     dword [startsector+4], 0
273
        jnz     .fail
274
        and     [hd_error], 0
275
        mov     eax, [userdata]
276
        mov     [hdpos], eax
277
        mov     eax, dword [startsector]
278
        mov     edi, [buffer]
279
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
280
.sectors_loop:
281
        call    bd_read
282
        cmp     [hd_error], 0
283
        jnz     .fail
284
        mov     ecx, [numsectors]
285
        inc     dword [ecx]     ; one more sector is read
286
        dec     [sectors_todo]
287
        jz      .done
288
        inc     eax
289
        jnz     .sectors_loop
290
; 5. Loop is done, either due to error or because everything is done.
291
; Release the global lock and return the corresponding status.
292
.fail:
293
        mov     ecx, ide_mutex
294
        call    mutex_unlock
295
        or      eax, -1
296
        ret
297
.done:
298
        mov     ecx, ide_mutex
299
        call    mutex_unlock
300
        xor     eax, eax
301
        ret
302
endp
3712 mario79 303
 
3742 clevermous 304
proc bd_write_interface stdcall uses esi edi, \
305
        userdata, buffer, startsector:qword, numsectors
306
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
307
        ; buffer = pointer to buffer with data
308
        ; startsector = 64-bit start sector
309
        ; numsectors = pointer to number of sectors on input,
310
        ;  must be filled with number of sectors really written
311
locals
312
sectors_todo    dd      ?
313
endl
314
; 1. Initialize number of sectors: get number of requested sectors
315
; and say that no sectors were read yet.
316
        mov     ecx, [numsectors]
317
        mov     eax, [ecx]
318
        mov     dword [ecx], 0
319
        mov     [sectors_todo], eax
320
; 2. Acquire the global lock.
321
        mov     ecx, ide_mutex
322
        call    mutex_lock
323
; 3. Convert parameters to the form suitable for worker procedures.
324
; Underlying procedures do not know about 64-bit sectors.
325
; Worker procedures use global variables and esi for [buffer].
326
        cmp     dword [startsector+4], 0
327
        jnz     .fail
328
        and     [hd_error], 0
329
        mov     eax, [userdata]
330
        mov     [hdpos], eax
331
        mov     esi, [buffer]
332
        lea     edi, [startsector]
333
        mov     [cache_chain_ptr], edi
334
; 4. Worker procedures take max 16 sectors per time,
335
; loop until all sectors will be processed.
336
.sectors_loop:
337
        mov     ecx, 16
338
        cmp     ecx, [sectors_todo]
339
        jbe     @f
340
        mov     ecx, [sectors_todo]
341
@@:
342
        mov     [cache_chain_size], cl
343
        call    bd_write_cache_chain
344
        cmp     [hd_error], 0
345
        jnz     .fail
346
        movzx   ecx, [cache_chain_size]
347
        mov     eax, [numsectors]
348
        add     [eax], ecx
349
        sub     [sectors_todo], ecx
350
        jz      .done
351
        add     [edi], ecx
352
        jc      .fail
353
        shl     ecx, 9
354
        add     esi, ecx
355
        jmp     .sectors_loop
356
; 5. Loop is done, either due to error or because everything is done.
357
; Release the global lock and return the corresponding status.
358
.fail:
359
        mov     ecx, ide_mutex
360
        call    mutex_unlock
361
        or      eax, -1
362
        ret
363
.done:
364
        mov     ecx, ide_mutex
365
        call    mutex_unlock
366
        xor     eax, eax
367
        ret
368
endp
2288 clevermous 369
 
3742 clevermous 370
; This is a stub.
371
proc bd_querymedia stdcall, hd_data, mediainfo
372
        mov     eax, [mediainfo]
373
        mov     [eax+DISKMEDIAINFO.Flags], 0
374
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
375
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
376
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
377
        xor     eax, eax
378
        ret
379
endp
3712 mario79 380
 
381
;-----------------------------------------------------------------------------
2288 clevermous 382
align 4
3742 clevermous 383
; input: eax = sector, edi -> buffer
384
; output: edi = edi + 512
2288 clevermous 385
hd_read_pio:
386
        push    eax edx
387
 
3712 mario79 388
; Select the desired drive
3702 mario79 389
        mov     edx, [hdbase]
390
        add     edx, 6   ;адрес регистра головок
391
        mov     al, byte [hdid]
392
        add     al, 128+64+32
393
        out     dx, al; номер головки/номер диска
3711 clevermous 394
 
2288 clevermous 395
        call    wait_for_hd_idle
396
        cmp     [hd_error], 0
397
        jne     hd_read_error
3711 clevermous 398
 
3702 mario79 399
; ATA with 28 or 48 bit for sector number?
400
        mov     eax, [esp+4]
401
        cmp     eax, 0x10000000
3711 clevermous 402
        jae     .lba48
3712 mario79 403
;--------------------------------------
3702 mario79 404
.lba28:
3706 mario79 405
        pushfd
2288 clevermous 406
        cli
407
        xor     eax, eax
408
        mov     edx, [hdbase]
409
        inc     edx
3706 mario79 410
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 411
        inc     edx
412
        inc     eax
3706 mario79 413
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 414
        inc     edx
3706 mario79 415
        mov     eax, [esp+4+4]
416
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 417
        shr     eax, 8
418
        inc     edx
3706 mario79 419
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 420
        shr     eax, 8
421
        inc     edx
3706 mario79 422
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 423
        shr     eax, 8
424
        inc     edx
3706 mario79 425
        and     al, 1+2+4+8 ; LBA (27:24)
2288 clevermous 426
        add     al, byte [hdid]
427
        add     al, 128+64+32
3706 mario79 428
        out     dx, al ; номер головки/номер диска
2288 clevermous 429
        inc     edx
3711 clevermous 430
        mov     al, 20h ; READ SECTOR(S)
3706 mario79 431
        out     dx, al ; ATACommand регистр команд
432
        popfd
3711 clevermous 433
        jmp     .continue
3712 mario79 434
;--------------------------------------
3702 mario79 435
.lba48:
3706 mario79 436
        pushfd
3702 mario79 437
        cli
438
        xor     eax, eax
439
        mov     edx, [hdbase]
440
        inc     edx
441
        out     dx, al ; Features Previous Reserved
442
        out     dx, al ; Features Current Reserved
443
        inc     edx
444
        out     dx, al ; Sector Count Previous Sector count (15:8)
445
        inc     eax
446
        out     dx, al ; Sector Count Current Sector count (7:0)
447
        inc     edx
3706 mario79 448
        mov     eax, [esp+4+4]
3711 clevermous 449
        rol     eax, 8
3702 mario79 450
        out     dx, al ; LBA Low Previous LBA (31:24)
3712 mario79 451
        xor     eax, eax ; because only 32 bit cache
3702 mario79 452
        inc     edx
453
        out     dx, al ; LBA Mid Previous LBA (39:32)
454
        inc     edx
455
        out     dx, al ; LBA High Previous LBA (47:40)
3711 clevermous 456
        sub     edx, 2
3706 mario79 457
        mov     eax, [esp+4+4]
3702 mario79 458
        out     dx, al ; LBA Low Current LBA (7:0)
459
        shr     eax, 8
460
        inc     edx
461
        out     dx, al ; LBA Mid Current LBA (15:8)
462
        shr     eax, 8
463
        inc     edx
464
        out     dx, al ; LBA High Current LBA (23:16)
465
        inc     edx
466
        mov     al, byte [hdid]
467
        add     al, 128+64+32
3712 mario79 468
        out     dx, al ; номер головки/номер диска
3702 mario79 469
        inc     edx
3711 clevermous 470
        mov     al, 24h ; READ SECTOR(S) EXT
3712 mario79 471
        out     dx, al ; ATACommand регистр команд
3706 mario79 472
        popfd
3712 mario79 473
;--------------------------------------
3702 mario79 474
.continue:
2288 clevermous 475
        call    wait_for_sector_buffer
476
 
477
        cmp     [hd_error], 0
478
        jne     hd_read_error
479
 
3712 mario79 480
        pushfd
2288 clevermous 481
        cli
3712 mario79 482
 
2288 clevermous 483
        mov     ecx, 256
484
        mov     edx, [hdbase]
485
        cld
486
        rep insw
3712 mario79 487
        popfd
2288 clevermous 488
 
489
        pop     edx eax
490
        ret
3712 mario79 491
;-----------------------------------------------------------------------------
2288 clevermous 492
align 4
3742 clevermous 493
; edi -> sector, esi -> data
2288 clevermous 494
cache_write_pio:
3712 mario79 495
; Select the desired drive
3702 mario79 496
        mov     edx, [hdbase]
497
        add     edx, 6   ;адрес регистра головок
498
        mov     al, byte [hdid]
499
        add     al, 128+64+32
3712 mario79 500
        out     dx, al ; номер головки/номер диска
3702 mario79 501
 
2288 clevermous 502
        call    wait_for_hd_idle
503
        cmp     [hd_error], 0
504
        jne     hd_write_error
505
 
3706 mario79 506
; ATA with 28 or 48 bit for sector number?
3742 clevermous 507
        mov     eax, [edi]
3706 mario79 508
        cmp     eax, 0x10000000
509
        jae     .lba48
3712 mario79 510
;--------------------------------------
3706 mario79 511
.lba28:
512
        pushfd
2288 clevermous 513
        cli
514
        xor     eax, eax
515
        mov     edx, [hdbase]
516
        inc     edx
3706 mario79 517
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 518
        inc     edx
519
        inc     eax
3706 mario79 520
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 521
        inc     edx
3742 clevermous 522
        mov     eax, [edi]      ; eax = sector to write
3706 mario79 523
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 524
        shr     eax, 8
525
        inc     edx
3706 mario79 526
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 527
        shr     eax, 8
528
        inc     edx
3706 mario79 529
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 530
        shr     eax, 8
531
        inc     edx
3706 mario79 532
        and     al, 1+2+4+8 ; LBA (27:24)
2288 clevermous 533
        add     al, byte [hdid]
534
        add     al, 128+64+32
3706 mario79 535
        out     dx, al ; номер головки/номер диска
2288 clevermous 536
        inc     edx
3706 mario79 537
        mov     al, 30h ; WRITE SECTOR(S)
538
        out     dx, al ; ATACommand регистр команд
539
        popfd
3711 clevermous 540
        jmp     .continue
3712 mario79 541
;--------------------------------------
3706 mario79 542
.lba48:
543
        pushfd
544
        cli
545
        xor     eax, eax
546
        mov     edx, [hdbase]
547
        inc     edx
548
        out     dx, al ; Features Previous Reserved
549
        out     dx, al ; Features Current Reserved
550
        inc     edx
551
        out     dx, al ; Sector Count Previous Sector count (15:8)
552
        inc     eax
553
        out     dx, al ; Sector Count Current Sector count (7:0)
554
        inc     edx
3742 clevermous 555
        mov     eax, [edi]
3711 clevermous 556
        rol     eax, 8
3706 mario79 557
        out     dx, al ; LBA Low Previous LBA (31:24)
3712 mario79 558
        xor     eax, eax ; because only 32 bit cache
3706 mario79 559
        inc     edx
560
        out     dx, al ; LBA Mid Previous LBA (39:32)
561
        inc     edx
562
        out     dx, al ; LBA High Previous LBA (47:40)
3711 clevermous 563
        sub     edx, 2
3742 clevermous 564
        mov     eax, [edi]
3706 mario79 565
        out     dx, al ; LBA Low Current LBA (7:0)
566
        shr     eax, 8
567
        inc     edx
568
        out     dx, al ; LBA Mid Current LBA (15:8)
569
        shr     eax, 8
570
        inc     edx
571
        out     dx, al ; LBA High Current LBA (23:16)
572
        inc     edx
573
        mov     al, byte [hdid]
574
        add     al, 128+64+32
3712 mario79 575
        out     dx, al ; номер головки/номер диска
3706 mario79 576
        inc     edx
3711 clevermous 577
        mov     al, 34h ; WRITE SECTOR(S) EXT
3712 mario79 578
        out     dx, al ; ATACommand регистр команд
3706 mario79 579
        popfd
3712 mario79 580
;--------------------------------------
3706 mario79 581
.continue:
2288 clevermous 582
        call    wait_for_sector_buffer
583
 
584
        cmp     [hd_error], 0
585
        jne     hd_write_error
586
 
587
        push    ecx esi
588
 
3712 mario79 589
        pushfd
2288 clevermous 590
        cli
591
        mov     ecx, 256
592
        mov     edx, [hdbase]
593
        cld
594
        rep outsw
3712 mario79 595
        popfd
2288 clevermous 596
 
597
        pop     esi ecx
598
        ret
3712 mario79 599
;-----------------------------------------------------------------------------
600
align 4
2288 clevermous 601
save_hd_wait_timeout:
602
        push    eax
603
        mov     eax, [timer_ticks]
604
        add     eax, 300        ; 3 sec timeout
605
        mov     [hd_wait_timeout], eax
606
        pop     eax
607
        ret
3712 mario79 608
;-----------------------------------------------------------------------------
2288 clevermous 609
align 4
610
check_hd_wait_timeout:
611
        push    eax
612
        mov     eax, [hd_wait_timeout]
613
        cmp     [timer_ticks], eax
614
        jg      hd_timeout_error
3712 mario79 615
 
2288 clevermous 616
        pop     eax
617
        mov     [hd_error], 0
618
        ret
3712 mario79 619
;-----------------------------------------------------------------------------
2288 clevermous 620
hd_timeout_error:
3712 mario79 621
        if lang eq sp
622
        DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
623
        else
624
        DEBUGF 1,"K : FS - HD timeout\n"
625
        end if
2288 clevermous 626
        mov     [hd_error], 1
627
        pop     eax
628
        ret
3712 mario79 629
;-----------------------------------------------------------------------------
2288 clevermous 630
hd_read_error:
3712 mario79 631
        if lang eq sp
632
        DEBUGF 1,"K : FS - HD error de lectura\n"
633
        else
634
        DEBUGF 1,"K : FS - HD read error\n"
635
        end if
2288 clevermous 636
        pop     edx eax
637
        ret
3712 mario79 638
;-----------------------------------------------------------------------------
639
hd_write_error_dma:
640
        pop     esi
2288 clevermous 641
hd_write_error:
3309 esevece 642
        if lang eq sp
643
        DEBUGF 1,"K : FS - HD error de escritura\n"
644
        else
645
        DEBUGF 1,"K : FS - HD write error\n"
646
        end if
2288 clevermous 647
        ret
3712 mario79 648
;-----------------------------------------------------------------------------
2288 clevermous 649
hd_lba_error:
3712 mario79 650
        if lang eq sp
651
        DEBUGF 1,"K : FS - HD error en LBA\n"
652
        else
653
        DEBUGF 1,"K : FS - HD LBA error\n"
654
        end if
2288 clevermous 655
        jmp     LBA_read_ret
3712 mario79 656
;-----------------------------------------------------------------------------
2288 clevermous 657
align 4
658
wait_for_hd_idle:
659
        push    eax edx
660
 
661
        call    save_hd_wait_timeout
662
 
663
        mov     edx, [hdbase]
664
        add     edx, 0x7
3712 mario79 665
;--------------------------------------
666
align 4
667
wfhil1:
2288 clevermous 668
        call    check_hd_wait_timeout
669
        cmp     [hd_error], 0
670
        jne     @f
671
 
672
        in      al, dx
673
        test    al, 128
674
        jnz     wfhil1
675
 
3712 mario79 676
@@:
2288 clevermous 677
        pop     edx eax
678
        ret
3712 mario79 679
;-----------------------------------------------------------------------------
2288 clevermous 680
align 4
681
wait_for_sector_buffer:
682
        push    eax edx
683
 
684
        mov     edx, [hdbase]
685
        add     edx, 0x7
686
 
687
        call    save_hd_wait_timeout
3712 mario79 688
;--------------------------------------
689
align 4
690
hdwait_sbuf:                  ; wait for sector buffer to be ready
2288 clevermous 691
        call    check_hd_wait_timeout
692
        cmp     [hd_error], 0
693
        jne     @f
694
 
695
        in      al, dx
696
        test    al, 8
697
        jz      hdwait_sbuf
698
 
699
        mov     [hd_error], 0
700
 
701
        cmp     [hd_setup], 1   ; do not mark error for setup request
702
        je      buf_wait_ok
703
 
704
        test    al, 1           ; previous command ended up with an error
705
        jz      buf_wait_ok
3712 mario79 706
@@:
2288 clevermous 707
        mov     [hd_error], 1
708
 
3712 mario79 709
buf_wait_ok:
2288 clevermous 710
        pop     edx eax
711
        ret
3712 mario79 712
;-----------------------------------------------------------------------------
3762 mario79 713
irq14_num equ byte 14
714
irq15_num equ byte 15
715
;-----------------------------------------------------------------------------
2288 clevermous 716
align 4
717
wait_for_sector_dma_ide0:
718
        push    eax
719
        push    edx
720
        call    save_hd_wait_timeout
3712 mario79 721
;--------------------------------------
722
align 4
2288 clevermous 723
.wait:
724
        call    change_task
3870 mario79 725
        cmp     [IDE_common_irq_param], 0
726
        jz      .done
3762 mario79 727
 
2288 clevermous 728
        call    check_hd_wait_timeout
729
        cmp     [hd_error], 0
730
        jz      .wait
3762 mario79 731
 
3870 mario79 732
        pushfd
733
        cli
3762 mario79 734
        mov     [IDE_common_irq_param], 0
2288 clevermous 735
        mov     dx, [IDEContrRegsBaseAddr]
736
        mov     al, 0
737
        out     dx, al
3870 mario79 738
        popfd
2288 clevermous 739
.done:
740
        pop     edx
741
        pop     eax
742
        ret
3712 mario79 743
;-----------------------------------------------------------------------------
2288 clevermous 744
align 4
745
wait_for_sector_dma_ide1:
746
        push    eax
747
        push    edx
748
        call    save_hd_wait_timeout
3712 mario79 749
;--------------------------------------
750
align 4
2288 clevermous 751
.wait:
752
        call    change_task
3870 mario79 753
        cmp     [IDE_common_irq_param], 0
754
        jz      .done
3762 mario79 755
 
2288 clevermous 756
        call    check_hd_wait_timeout
757
        cmp     [hd_error], 0
758
        jz      .wait
3762 mario79 759
 
3870 mario79 760
        pushfd
761
        cli
3762 mario79 762
        mov     [IDE_common_irq_param], 0
2288 clevermous 763
        mov     dx, [IDEContrRegsBaseAddr]
764
        add     dx, 8
765
        mov     al, 0
766
        out     dx, al
3870 mario79 767
        popfd
2288 clevermous 768
.done:
769
        pop     edx
770
        pop     eax
771
        ret
3712 mario79 772
;-----------------------------------------------------------------------------
2288 clevermous 773
iglobal
774
align 4
775
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
776
IDE_descriptor_table:
3712 mario79 777
        dd IDE_DMA
778
        dw 0x2000
779
        dw 0x8000
2288 clevermous 780
 
3712 mario79 781
dma_cur_sector  dd not 40h
782
dma_hdpos       dd 0
3762 mario79 783
IDE_common_irq_param db 0
2288 clevermous 784
endg
3712 mario79 785
;-----------------------------------------------------------------------------
2288 clevermous 786
uglobal
787
; all uglobals are zeroed at boot
3712 mario79 788
dma_process         dd 0
789
dma_slot_ptr        dd 0
790
cache_chain_pos     dd 0
791
cache_chain_ptr     dd 0
792
cache_chain_size    db 0
793
cache_chain_started db 0
794
dma_task_switched   db 0
795
dma_hdd             db 0
796
allow_dma_access    db 0
2288 clevermous 797
endg
3712 mario79 798
;-----------------------------------------------------------------------------
2288 clevermous 799
align 4
3870 mario79 800
IDE_irq_14_handler:
801
        cmp     [IDE_common_irq_param], irq14_num
802
        jne     .exit
803
 
2288 clevermous 804
        pushfd
805
        cli
806
        pushad
3762 mario79 807
 
3870 mario79 808
        mov     [IDE_common_irq_param], 0
2288 clevermous 809
        mov     dx, [IDEContrRegsBaseAddr]
810
        mov     al, 0
811
        out     dx, al
3870 mario79 812
 
813
        popad
814
        popfd
815
.exit:
816
        mov     al, 1
817
        ret
818
;-----------------------------------------------------------------------------
2288 clevermous 819
align 4
3870 mario79 820
IDE_irq_15_handler:
821
        cmp     [IDE_common_irq_param], irq15_num
822
        jne     .exit
823
 
824
        pushfd
825
        cli
826
        pushad
827
 
828
        mov     [IDE_common_irq_param], 0
2288 clevermous 829
        mov     dx, [IDEContrRegsBaseAddr]
830
        add     dx, 8
831
        mov     al, 0
832
        out     dx, al
3870 mario79 833
 
834
        popad
835
        popfd
836
.exit:
837
        mov     al, 1
838
        ret
839
;-----------------------------------------------------------------------------
840
align 4
841
IDE_common_irq_handler:
842
        cmp     [IDE_common_irq_param], 0
843
        je      .exit
844
 
845
        pushfd
846
        cli
847
        pushad
848
 
849
        xor     ebx, ebx
850
        mov     dx, [IDEContrRegsBaseAddr]
851
        mov     eax, IDE_common_irq_param
852
        cmp     [eax], irq14_num
853
        mov     [eax], bl
854
        xor     eax, eax
855
        je      @f
856
 
857
        add     dx, 8
3762 mario79 858
;--------------------------------------
859
align 4
3870 mario79 860
@@:
861
        out     dx, al
862
 
2288 clevermous 863
        popad
864
        popfd
3870 mario79 865
.exit:
3762 mario79 866
        mov     al, 1
2288 clevermous 867
        ret
3712 mario79 868
;-----------------------------------------------------------------------------
2288 clevermous 869
align 4
870
hd_read_dma:
871
        push    eax
872
        push    edx
873
        mov     edx, [dma_hdpos]
874
        cmp     edx, [hdpos]
875
        jne     .notread
876
        mov     edx, [dma_cur_sector]
877
        cmp     eax, edx
878
        jb      .notread
879
        add     edx, 15
880
        cmp     [esp+4], edx
881
        ja      .notread
882
        mov     eax, [esp+4]
883
        sub     eax, [dma_cur_sector]
884
        shl     eax, 9
885
        add     eax, (OS_BASE+IDE_DMA)
3742 clevermous 886
        push    ecx esi
2288 clevermous 887
        mov     esi, eax
3712 mario79 888
 
2288 clevermous 889
        mov     ecx, 512/4
890
        cld
891
        rep movsd
3742 clevermous 892
        pop     esi ecx
2288 clevermous 893
        pop     edx
894
        pop     eax
895
        ret
896
.notread:
3870 mario79 897
; set data for PRD Table
2288 clevermous 898
        mov     eax, IDE_descriptor_table
899
        mov     dword [eax], IDE_DMA
900
        mov     word [eax+4], 0x2000
901
        sub     eax, OS_BASE
3870 mario79 902
; select controller Primary or Secondary
2288 clevermous 903
        mov     dx, [IDEContrRegsBaseAddr]
3774 mario79 904
        push    eax
905
        mov     eax, [hd_address_table]
906
        cmp     [hdbase], eax ; 0x1F0
907
        pop     eax
2288 clevermous 908
        jz      @f
909
        add     edx, 8
910
@@:
911
        push    edx
3870 mario79 912
; Bus Master IDE PRD Table Address
2288 clevermous 913
        add     edx, 4
3870 mario79 914
; save IDE_descriptor_table
2288 clevermous 915
        out     dx, eax
916
        pop     edx
3870 mario79 917
; clear Bus Master IDE Command register
2288 clevermous 918
        mov     al, 0
919
        out     dx, al
3870 mario79 920
; set write to memory
921
;        mov     al, 8 ; 1000b
922
;        out     dx, al
923
; clear Bus Master IDE Status register
924
; clear Error bit and Interrupt bit
2288 clevermous 925
        add     edx, 2
3870 mario79 926
        mov     al, 6 ; 110b
2288 clevermous 927
        out     dx, al
3712 mario79 928
 
929
; Select the desired drive
930
        mov     edx, [hdbase]
931
        add     edx, 6   ; адрес регистра головок
932
        mov     al, byte [hdid]
933
        add     al, 128+64+32
934
        out     dx, al ; номер головки/номер диска
935
 
2288 clevermous 936
        call    wait_for_hd_idle
937
        cmp     [hd_error], 0
938
        jnz     hd_read_error
3712 mario79 939
 
940
; ATA with 28 or 48 bit for sector number?
941
        mov     eax, [esp+4]
942
; -10h because the PreCache hits the boundary between lba28 and lba48
943
; 10h = 16  - size of PreCache
944
        cmp     eax, 0x10000000-10h
945
        jae     .lba48
946
;--------------------------------------
947
.lba28:
948
        pushfd
949
        cli
2288 clevermous 950
        xor     eax, eax
951
        mov     edx, [hdbase]
952
        inc     edx
3712 mario79 953
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 954
        inc     edx
3712 mario79 955
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
956
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 957
        inc     edx
3712 mario79 958
        mov     eax, [esp+4+4]
959
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 960
        shr     eax, 8
961
        inc     edx
3712 mario79 962
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 963
        shr     eax, 8
964
        inc     edx
3712 mario79 965
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 966
        shr     eax, 8
967
        inc     edx
3712 mario79 968
        and     al, 0xF ; LBA (27:24)
2288 clevermous 969
        add     al, byte [hdid]
970
        add     al, 11100000b
3712 mario79 971
        out     dx, al ; номер головки/номер диска
2288 clevermous 972
        inc     edx
3712 mario79 973
        mov     al, 0xC8 ; READ DMA
974
        out     dx, al ; ATACommand регистр команд
975
        jmp     .continue
976
;--------------------------------------
977
.lba48:
978
        pushfd
979
        cli
980
        xor     eax, eax
981
        mov     edx, [hdbase]
982
        inc     edx
983
        out     dx, al ; Features Previous Reserved
984
        out     dx, al ; Features Current Reserved
985
        inc     edx
986
        out     dx, al ; Sector Count Previous Sector count (15:8)
987
        mov     eax, 10h ; Sector Counter = 16 PreCache
988
        out     dx, al ; Sector Count Current Sector count (7:0)
989
        inc     edx
990
        mov     eax, [esp+4+4]
991
        rol     eax, 8
992
        out     dx, al ; LBA Low Previous LBA (31:24)
993
        xor     eax, eax ; because only 32 bit cache
994
        inc     edx
995
        out     dx, al ; LBA Mid Previous LBA (39:32)
996
        inc     edx
997
        out     dx, al ; LBA High Previous LBA (47:40)
998
        sub     edx, 2
999
        mov     eax, [esp+4+4]
1000
        out     dx, al ; LBA Low Current LBA (7:0)
1001
        shr     eax, 8
1002
        inc     edx
1003
        out     dx, al ; LBA Mid Current LBA (15:8)
1004
        shr     eax, 8
1005
        inc     edx
1006
        out     dx, al ; LBA High Current LBA (23:16)
1007
        inc     edx
1008
        mov     al, byte [hdid]
1009
        add     al, 128+64+32
1010
        out     dx, al ; номер головки/номер диска
1011
        inc     edx
1012
        mov     al, 25h ; READ DMA EXT
1013
        out     dx, al ; ATACommand регистр команд
1014
;--------------------------------------
1015
.continue:
3870 mario79 1016
; select controller Primary or Secondary
2288 clevermous 1017
        mov     dx, [IDEContrRegsBaseAddr]
3712 mario79 1018
        mov     eax, [hd_address_table]
1019
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1020
        jz      @f
1021
        add     dx, 8
1022
@@:
3870 mario79 1023
; set write to memory and Start Bus Master
2288 clevermous 1024
        mov     al, 9
1025
        out     dx, al
3870 mario79 1026
 
2288 clevermous 1027
        mov     eax, [CURRENT_TASK]
1028
        mov     [dma_process], eax
3870 mario79 1029
 
2288 clevermous 1030
        mov     eax, [TASK_BASE]
1031
        mov     [dma_slot_ptr], eax
3870 mario79 1032
 
3712 mario79 1033
        mov     eax, [hd_address_table]
1034
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1035
        jnz     .ide1
3762 mario79 1036
 
1037
        mov     [IDE_common_irq_param], irq14_num
2288 clevermous 1038
        jmp     @f
1039
.ide1:
3762 mario79 1040
        mov     [IDE_common_irq_param], irq15_num
2288 clevermous 1041
@@:
3712 mario79 1042
        popfd
3870 mario79 1043
; wait for interrupt
3712 mario79 1044
        mov     eax, [hd_address_table]
1045
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1046
        jnz     .wait_ide1
1047
        call    wait_for_sector_dma_ide0
1048
        jmp     @f
1049
.wait_ide1:
1050
        call    wait_for_sector_dma_ide1
1051
@@:
1052
        cmp     [hd_error], 0
1053
        jnz     hd_read_error
1054
        mov     eax, [hdpos]
1055
        mov     [dma_hdpos], eax
1056
        pop     edx
1057
        pop     eax
1058
        mov     [dma_cur_sector], eax
1059
        jmp     hd_read_dma
3712 mario79 1060
;-----------------------------------------------------------------------------
3742 clevermous 1061
cache_write_dma:
2288 clevermous 1062
        mov     eax, [cache_chain_ptr]
1063
        push    esi
1064
        mov     eax, IDE_descriptor_table
1065
        mov     edx, eax
1066
        pusha
1067
        mov     edi, (OS_BASE+IDE_DMA)
1068
        mov     dword [edx], IDE_DMA
1069
        movzx   ecx, [cache_chain_size]
1070
        shl     ecx, 9
1071
        mov     word [edx+4], cx
1072
        shr     ecx, 2
1073
        cld
1074
        rep movsd
1075
        popa
1076
        sub     eax, OS_BASE
1077
        mov     dx, [IDEContrRegsBaseAddr]
3774 mario79 1078
        push    eax
1079
        mov     eax, [hd_address_table]
1080
        cmp     [hdbase], eax ; 0x1F0
1081
        pop     eax
2288 clevermous 1082
        jz      @f
1083
        add     edx, 8
1084
@@:
1085
        push    edx
1086
        add     edx, 4
1087
        out     dx, eax
1088
        pop     edx
1089
        mov     al, 0
1090
        out     dx, al
1091
        add     edx, 2
1092
        mov     al, 6
1093
        out     dx, al
3712 mario79 1094
 
1095
; Select the desired drive
1096
        mov     edx, [hdbase]
1097
        add     edx, 6   ; адрес регистра головок
1098
        mov     al, byte [hdid]
1099
        add     al, 128+64+32
1100
        out     dx, al ; номер головки/номер диска
1101
 
2288 clevermous 1102
        call    wait_for_hd_idle
1103
        cmp     [hd_error], 0
1104
        jnz     hd_write_error_dma
3712 mario79 1105
 
1106
; ATA with 28 or 48 bit for sector number?
1107
        mov     esi, [cache_chain_ptr]
1108
        mov     eax, [esi]
1109
; -40h because the PreCache hits the boundary between lba28 and lba48
1110
; 40h = 64  - the maximum number of sectors to be written for one command
1111
        cmp     eax, 0x10000000-40h
1112
        jae     .lba48
1113
;--------------------------------------
1114
.lba28:
1115
        pushfd
1116
        cli
2288 clevermous 1117
        xor     eax, eax
1118
        mov     edx, [hdbase]
1119
        inc     edx
3712 mario79 1120
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 1121
        inc     edx
3712 mario79 1122
        mov     al, [cache_chain_size] ; Sector Counter
1123
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 1124
        inc     edx
1125
        mov     eax, [esi]
3712 mario79 1126
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 1127
        shr     eax, 8
1128
        inc     edx
3712 mario79 1129
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 1130
        shr     eax, 8
1131
        inc     edx
3712 mario79 1132
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 1133
        shr     eax, 8
1134
        inc     edx
3712 mario79 1135
        and     al, 0xF ; LBA (27:24)
2288 clevermous 1136
        add     al, byte [hdid]
1137
        add     al, 11100000b
3712 mario79 1138
        out     dx, al ; номер головки/номер диска
2288 clevermous 1139
        inc     edx
3712 mario79 1140
        mov     al, 0xCA ; WRITE DMA
1141
        out     dx, al ; ATACommand регистр команд
1142
        jmp     .continue
1143
;--------------------------------------
1144
.lba48:
1145
        pushfd
1146
        cli
1147
        xor     eax, eax
1148
        mov     edx, [hdbase]
1149
        inc     edx
1150
        out     dx, al ; Features Previous Reserved
1151
        out     dx, al ; Features Current Reserved
1152
        inc     edx
1153
        out     dx, al ; Sector Count Previous Sector count (15:8)
1154
        mov     al, [cache_chain_size] ; Sector Counter
1155
        out     dx, al ; Sector Count Current Sector count (7:0)
1156
        inc     edx
1157
        mov     eax, [esi]
1158
        rol     eax, 8
1159
        out     dx, al ; LBA Low Previous LBA (31:24)
1160
        xor     eax, eax ; because only 32 bit cache
1161
        inc     edx
1162
        out     dx, al ; LBA Mid Previous LBA (39:32)
1163
        inc     edx
1164
        out     dx, al ; LBA High Previous LBA (47:40)
1165
        sub     edx, 2
1166
        mov     eax, [esi]
1167
        out     dx, al ; LBA Low Current LBA (7:0)
1168
        shr     eax, 8
1169
        inc     edx
1170
        out     dx, al ; LBA Mid Current LBA (15:8)
1171
        shr     eax, 8
1172
        inc     edx
1173
        out     dx, al ; LBA High Current LBA (23:16)
1174
        inc     edx
1175
        mov     al, byte [hdid]
1176
        add     al, 128+64+32
1177
        out     dx, al ; номер головки/номер диска
1178
        inc     edx
1179
        mov     al, 35h ; WRITE DMA EXT
1180
        out     dx, al ; ATACommand регистр команд
1181
;--------------------------------------
1182
.continue:
2288 clevermous 1183
        mov     dx, [IDEContrRegsBaseAddr]
3712 mario79 1184
        mov     eax, [hd_address_table]
1185
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1186
        jz      @f
1187
        add     dx, 8
1188
@@:
1189
        mov     al, 1
1190
        out     dx, al
1191
        mov     eax, [CURRENT_TASK]
1192
        mov     [dma_process], eax
1193
        mov     eax, [TASK_BASE]
1194
        mov     [dma_slot_ptr], eax
3712 mario79 1195
        mov     eax, [hd_address_table]
1196
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1197
        jnz     .ide1
3762 mario79 1198
 
1199
        mov     [IDE_common_irq_param], irq14_num
2288 clevermous 1200
        jmp     @f
1201
.ide1:
3762 mario79 1202
        mov     [IDE_common_irq_param], irq15_num
2288 clevermous 1203
@@:
3712 mario79 1204
        popfd
2288 clevermous 1205
        mov     [dma_cur_sector], not 0x40
3712 mario79 1206
        mov     eax, [hd_address_table]
1207
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1208
        jnz     .wait_ide1
1209
        call    wait_for_sector_dma_ide0
1210
        jmp     @f
1211
.wait_ide1:
1212
        call    wait_for_sector_dma_ide1
1213
@@:
1214
        cmp     [hd_error], 0
1215
        jnz     hd_write_error_dma
1216
        pop     esi
1217
        ret
3712 mario79 1218
;-----------------------------------------------------------------------------
2288 clevermous 1219
uglobal
3762 mario79 1220
IDE_Interrupt   dw ?
3712 mario79 1221
IDEContrRegsBaseAddr         dw ?
1222
IDEContrProgrammingInterface dw ?
3711 clevermous 1223
IDE_BAR0_val    dw ?
1224
IDE_BAR1_val    dw ?
1225
IDE_BAR2_val    dw ?
1226
IDE_BAR3_val    dw ?
2288 clevermous 1227
endg
3712 mario79 1228
;-----------------------------------------------------------------------------
2288 clevermous 1229
; \begin{diamond}
1230
uglobal
3712 mario79 1231
bios_hdpos      dd 0       ; 0 is invalid value for [hdpos]
1232
bios_cur_sector dd ?
1233
bios_read_len   dd ?
2288 clevermous 1234
endg
3712 mario79 1235
;-----------------------------------------------------------------------------
1236
align 4
2288 clevermous 1237
bd_read:
1238
        push    eax
1239
        push    edx
1240
        mov     edx, [bios_hdpos]
1241
        cmp     edx, [hdpos]
1242
        jne     .notread
1243
        mov     edx, [bios_cur_sector]
1244
        cmp     eax, edx
1245
        jb      .notread
1246
        add     edx, [bios_read_len]
1247
        dec     edx
1248
        cmp     eax, edx
1249
        ja      .notread
1250
        sub     eax, [bios_cur_sector]
1251
        shl     eax, 9
1252
        add     eax, (OS_BASE+0x9A000)
3742 clevermous 1253
        push    ecx esi
2288 clevermous 1254
        mov     esi, eax
1255
        mov     ecx, 512/4
1256
        cld
1257
        rep movsd
3742 clevermous 1258
        pop     esi ecx
2288 clevermous 1259
        pop     edx
1260
        pop     eax
1261
        ret
1262
.notread:
1263
        push    ecx
1264
        mov     dl, 42h
1265
        mov     ecx, 16
1266
        call    int13_call
1267
        pop     ecx
1268
        test    eax, eax
1269
        jnz     .v86err
1270
        test    edx, edx
1271
        jz      .readerr
1272
        mov     [bios_read_len], edx
1273
        mov     edx, [hdpos]
1274
        mov     [bios_hdpos], edx
1275
        pop     edx
1276
        pop     eax
1277
        mov     [bios_cur_sector], eax
1278
        jmp     bd_read
1279
.readerr:
1280
.v86err:
1281
        mov     [hd_error], 1
1282
        jmp     hd_read_error
3712 mario79 1283
;-----------------------------------------------------------------------------
1284
align 4
2288 clevermous 1285
bd_write_cache_chain:
1286
        pusha
1287
        mov     edi, OS_BASE + 0x9A000
1288
        movzx   ecx, [cache_chain_size]
1289
        push    ecx
1290
        shl     ecx, 9-2
1291
        rep movsd
1292
        pop     ecx
1293
        mov     dl, 43h
1294
        mov     eax, [cache_chain_ptr]
1295
        mov     eax, [eax]
1296
        call    int13_call
1297
        test    eax, eax
1298
        jnz     .v86err
1299
        cmp     edx, ecx
1300
        jnz     .writeerr
1301
        popa
1302
        ret
1303
.v86err:
1304
.writeerr:
1305
        popa
1306
        mov     [hd_error], 1
1307
        jmp     hd_write_error
3712 mario79 1308
;-----------------------------------------------------------------------------
2288 clevermous 1309
uglobal
3712 mario79 1310
int13_regs_in   rb sizeof.v86_regs
1311
int13_regs_out  rb sizeof.v86_regs
2288 clevermous 1312
endg
3712 mario79 1313
;-----------------------------------------------------------------------------
1314
align 4
2288 clevermous 1315
int13_call:
1316
; Because this code uses fixed addresses,
1317
; it can not be run simultaniously by many threads.
3742 clevermous 1318
; In current implementation it is protected by common mutex 'ide_status'
2288 clevermous 1319
        mov     word [OS_BASE + 510h], 10h             ; packet length
1320
        mov     word [OS_BASE + 512h], cx              ; number of sectors
1321
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
1322
        mov     dword [OS_BASE + 518h], eax
1323
        and     dword [OS_BASE + 51Ch], 0
1324
        push    ebx ecx esi edi
1325
        mov     ebx, int13_regs_in
1326
        mov     edi, ebx
2384 hidnplayr 1327
        mov     ecx, sizeof.v86_regs/4
2288 clevermous 1328
        xor     eax, eax
1329
        rep stosd
1330
        mov     byte [ebx+v86_regs.eax+1], dl
1331
        mov     eax, [hdpos]
1332
        lea     eax, [BiosDisksData+(eax-80h)*4]
1333
        mov     dl, [eax]
1334
        mov     byte [ebx+v86_regs.edx], dl
1335
        movzx   edx, byte [eax+1]
1336
;        mov     dl, 5
1337
        test    edx, edx
1338
        jnz     .hasirq
1339
        dec     edx
1340
        jmp     @f
1341
.hasirq:
1342
        pushad
1343
        stdcall enable_irq, edx
1344
        popad
1345
@@:
1346
        mov     word [ebx+v86_regs.esi], 510h
1347
        mov     word [ebx+v86_regs.ss], 9000h
1348
        mov     word [ebx+v86_regs.esp], 0A000h
1349
        mov     word [ebx+v86_regs.eip], 500h
1350
        mov     [ebx+v86_regs.eflags], 20200h
1351
        mov     esi, [sys_v86_machine]
1352
        mov     ecx, 0x502
1353
        push    fs
1354
        call    v86_start
1355
        pop     fs
1356
        and     [bios_hdpos], 0
1357
        pop     edi esi ecx ebx
1358
        movzx   edx, byte [OS_BASE + 512h]
1359
        test    byte [int13_regs_out+v86_regs.eflags], 1
1360
        jnz     @f
1361
        mov     edx, ecx
1362
@@:
1363
        ret
1364
; \end{diamond}