Subversion Repositories Kolibri OS

Rev

Rev 3870 | Rev 4273 | 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: 3881 $
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 регистр команд
3711 clevermous 539
        jmp     .continue
3712 mario79 540
;--------------------------------------
3706 mario79 541
.lba48:
542
        pushfd
543
        cli
544
        xor     eax, eax
545
        mov     edx, [hdbase]
546
        inc     edx
547
        out     dx, al ; Features Previous Reserved
548
        out     dx, al ; Features Current Reserved
549
        inc     edx
550
        out     dx, al ; Sector Count Previous Sector count (15:8)
551
        inc     eax
552
        out     dx, al ; Sector Count Current Sector count (7:0)
553
        inc     edx
3742 clevermous 554
        mov     eax, [edi]
3711 clevermous 555
        rol     eax, 8
3706 mario79 556
        out     dx, al ; LBA Low Previous LBA (31:24)
3712 mario79 557
        xor     eax, eax ; because only 32 bit cache
3706 mario79 558
        inc     edx
559
        out     dx, al ; LBA Mid Previous LBA (39:32)
560
        inc     edx
561
        out     dx, al ; LBA High Previous LBA (47:40)
3711 clevermous 562
        sub     edx, 2
3742 clevermous 563
        mov     eax, [edi]
3706 mario79 564
        out     dx, al ; LBA Low Current LBA (7:0)
565
        shr     eax, 8
566
        inc     edx
567
        out     dx, al ; LBA Mid Current LBA (15:8)
568
        shr     eax, 8
569
        inc     edx
570
        out     dx, al ; LBA High Current LBA (23:16)
571
        inc     edx
572
        mov     al, byte [hdid]
573
        add     al, 128+64+32
3712 mario79 574
        out     dx, al ; номер головки/номер диска
3706 mario79 575
        inc     edx
3711 clevermous 576
        mov     al, 34h ; WRITE SECTOR(S) EXT
3712 mario79 577
        out     dx, al ; ATACommand регистр команд
578
;--------------------------------------
3706 mario79 579
.continue:
3881 mario79 580
        popfd
2288 clevermous 581
        call    wait_for_sector_buffer
582
 
583
        cmp     [hd_error], 0
584
        jne     hd_write_error
585
 
586
        push    ecx esi
587
 
3712 mario79 588
        pushfd
2288 clevermous 589
        cli
590
        mov     ecx, 256
591
        mov     edx, [hdbase]
592
        cld
593
        rep outsw
3712 mario79 594
        popfd
2288 clevermous 595
 
596
        pop     esi ecx
597
        ret
3712 mario79 598
;-----------------------------------------------------------------------------
599
align 4
2288 clevermous 600
save_hd_wait_timeout:
601
        push    eax
602
        mov     eax, [timer_ticks]
603
        add     eax, 300        ; 3 sec timeout
604
        mov     [hd_wait_timeout], eax
605
        pop     eax
606
        ret
3712 mario79 607
;-----------------------------------------------------------------------------
2288 clevermous 608
align 4
609
check_hd_wait_timeout:
610
        push    eax
611
        mov     eax, [hd_wait_timeout]
612
        cmp     [timer_ticks], eax
613
        jg      hd_timeout_error
3712 mario79 614
 
2288 clevermous 615
        pop     eax
616
        mov     [hd_error], 0
617
        ret
3712 mario79 618
;-----------------------------------------------------------------------------
2288 clevermous 619
hd_timeout_error:
3712 mario79 620
        if lang eq sp
621
        DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
622
        else
623
        DEBUGF 1,"K : FS - HD timeout\n"
624
        end if
2288 clevermous 625
        mov     [hd_error], 1
626
        pop     eax
627
        ret
3712 mario79 628
;-----------------------------------------------------------------------------
2288 clevermous 629
hd_read_error:
3712 mario79 630
        if lang eq sp
631
        DEBUGF 1,"K : FS - HD error de lectura\n"
632
        else
633
        DEBUGF 1,"K : FS - HD read error\n"
634
        end if
2288 clevermous 635
        pop     edx eax
636
        ret
3712 mario79 637
;-----------------------------------------------------------------------------
638
hd_write_error_dma:
639
        pop     esi
2288 clevermous 640
hd_write_error:
3309 esevece 641
        if lang eq sp
642
        DEBUGF 1,"K : FS - HD error de escritura\n"
643
        else
644
        DEBUGF 1,"K : FS - HD write error\n"
645
        end if
2288 clevermous 646
        ret
3712 mario79 647
;-----------------------------------------------------------------------------
2288 clevermous 648
hd_lba_error:
3712 mario79 649
        if lang eq sp
650
        DEBUGF 1,"K : FS - HD error en LBA\n"
651
        else
652
        DEBUGF 1,"K : FS - HD LBA error\n"
653
        end if
2288 clevermous 654
        jmp     LBA_read_ret
3712 mario79 655
;-----------------------------------------------------------------------------
2288 clevermous 656
align 4
657
wait_for_hd_idle:
658
        push    eax edx
659
 
660
        call    save_hd_wait_timeout
661
 
662
        mov     edx, [hdbase]
663
        add     edx, 0x7
3712 mario79 664
;--------------------------------------
665
align 4
666
wfhil1:
2288 clevermous 667
        call    check_hd_wait_timeout
668
        cmp     [hd_error], 0
669
        jne     @f
670
 
671
        in      al, dx
672
        test    al, 128
673
        jnz     wfhil1
674
 
3712 mario79 675
@@:
2288 clevermous 676
        pop     edx eax
677
        ret
3712 mario79 678
;-----------------------------------------------------------------------------
2288 clevermous 679
align 4
680
wait_for_sector_buffer:
681
        push    eax edx
682
 
683
        mov     edx, [hdbase]
684
        add     edx, 0x7
685
 
686
        call    save_hd_wait_timeout
3712 mario79 687
;--------------------------------------
688
align 4
689
hdwait_sbuf:                  ; wait for sector buffer to be ready
2288 clevermous 690
        call    check_hd_wait_timeout
691
        cmp     [hd_error], 0
692
        jne     @f
693
 
694
        in      al, dx
695
        test    al, 8
696
        jz      hdwait_sbuf
697
 
698
        mov     [hd_error], 0
699
 
700
        cmp     [hd_setup], 1   ; do not mark error for setup request
701
        je      buf_wait_ok
702
 
703
        test    al, 1           ; previous command ended up with an error
704
        jz      buf_wait_ok
3712 mario79 705
@@:
2288 clevermous 706
        mov     [hd_error], 1
707
 
3712 mario79 708
buf_wait_ok:
2288 clevermous 709
        pop     edx eax
710
        ret
3712 mario79 711
;-----------------------------------------------------------------------------
3762 mario79 712
irq14_num equ byte 14
713
irq15_num equ byte 15
714
;-----------------------------------------------------------------------------
2288 clevermous 715
align 4
716
wait_for_sector_dma_ide0:
717
        push    eax
718
        push    edx
719
        call    save_hd_wait_timeout
3712 mario79 720
;--------------------------------------
721
align 4
2288 clevermous 722
.wait:
723
        call    change_task
3870 mario79 724
        cmp     [IDE_common_irq_param], 0
725
        jz      .done
3762 mario79 726
 
2288 clevermous 727
        call    check_hd_wait_timeout
728
        cmp     [hd_error], 0
729
        jz      .wait
3881 mario79 730
; clear Bus Master IDE Command register
3870 mario79 731
        pushfd
732
        cli
3762 mario79 733
        mov     [IDE_common_irq_param], 0
2288 clevermous 734
        mov     dx, [IDEContrRegsBaseAddr]
735
        mov     al, 0
736
        out     dx, al
3870 mario79 737
        popfd
3881 mario79 738
;--------------------------------------
739
align 4
2288 clevermous 740
.done:
741
        pop     edx
742
        pop     eax
743
        ret
3712 mario79 744
;-----------------------------------------------------------------------------
2288 clevermous 745
align 4
746
wait_for_sector_dma_ide1:
747
        push    eax
748
        push    edx
749
        call    save_hd_wait_timeout
3712 mario79 750
;--------------------------------------
751
align 4
2288 clevermous 752
.wait:
753
        call    change_task
3870 mario79 754
        cmp     [IDE_common_irq_param], 0
755
        jz      .done
3762 mario79 756
 
2288 clevermous 757
        call    check_hd_wait_timeout
758
        cmp     [hd_error], 0
759
        jz      .wait
3881 mario79 760
; clear Bus Master IDE Command register
3870 mario79 761
        pushfd
762
        cli
3762 mario79 763
        mov     [IDE_common_irq_param], 0
2288 clevermous 764
        mov     dx, [IDEContrRegsBaseAddr]
765
        add     dx, 8
766
        mov     al, 0
767
        out     dx, al
3870 mario79 768
        popfd
3881 mario79 769
;--------------------------------------
770
align 4
2288 clevermous 771
.done:
772
        pop     edx
773
        pop     eax
774
        ret
3712 mario79 775
;-----------------------------------------------------------------------------
2288 clevermous 776
iglobal
777
align 4
778
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
779
IDE_descriptor_table:
3712 mario79 780
        dd IDE_DMA
781
        dw 0x2000
782
        dw 0x8000
2288 clevermous 783
 
3712 mario79 784
dma_cur_sector  dd not 40h
785
dma_hdpos       dd 0
3762 mario79 786
IDE_common_irq_param db 0
2288 clevermous 787
endg
3712 mario79 788
;-----------------------------------------------------------------------------
2288 clevermous 789
uglobal
790
; all uglobals are zeroed at boot
3712 mario79 791
dma_process         dd 0
792
dma_slot_ptr        dd 0
793
cache_chain_pos     dd 0
794
cache_chain_ptr     dd 0
795
cache_chain_size    db 0
796
cache_chain_started db 0
797
dma_task_switched   db 0
798
dma_hdd             db 0
799
allow_dma_access    db 0
2288 clevermous 800
endg
3712 mario79 801
;-----------------------------------------------------------------------------
2288 clevermous 802
align 4
3870 mario79 803
IDE_irq_14_handler:
804
        cmp     [IDE_common_irq_param], irq14_num
805
        jne     .exit
806
 
2288 clevermous 807
        pushfd
808
        cli
809
        pushad
3881 mario79 810
; clear Bus Master IDE Command register
3870 mario79 811
        mov     [IDE_common_irq_param], 0
2288 clevermous 812
        mov     dx, [IDEContrRegsBaseAddr]
813
        mov     al, 0
814
        out     dx, al
3881 mario79 815
; clear Bus Master IDE Status register
816
; clear Interrupt bit
817
        add     edx, 2
818
        mov     al, 4 ; 100b
819
        out     dx, al
3870 mario79 820
 
821
        popad
822
        popfd
3881 mario79 823
;--------------------------------------
824
align 4
3870 mario79 825
.exit:
826
        mov     al, 1
827
        ret
828
;-----------------------------------------------------------------------------
2288 clevermous 829
align 4
3870 mario79 830
IDE_irq_15_handler:
831
        cmp     [IDE_common_irq_param], irq15_num
832
        jne     .exit
833
 
834
        pushfd
835
        cli
836
        pushad
3881 mario79 837
; clear Bus Master IDE Command register
3870 mario79 838
        mov     [IDE_common_irq_param], 0
2288 clevermous 839
        mov     dx, [IDEContrRegsBaseAddr]
840
        add     dx, 8
841
        mov     al, 0
842
        out     dx, al
3881 mario79 843
; clear Bus Master IDE Status register
844
; clear Interrupt bit
845
        add     edx, 2
846
        mov     al, 4 ; 100b
847
        out     dx, al
3870 mario79 848
 
849
        popad
850
        popfd
3881 mario79 851
;--------------------------------------
852
align 4
3870 mario79 853
.exit:
854
        mov     al, 1
855
        ret
856
;-----------------------------------------------------------------------------
857
align 4
858
IDE_common_irq_handler:
859
        cmp     [IDE_common_irq_param], 0
860
        je      .exit
861
 
862
        pushfd
863
        cli
864
        pushad
3881 mario79 865
; clear Bus Master IDE Command register
3870 mario79 866
        xor     ebx, ebx
867
        mov     dx, [IDEContrRegsBaseAddr]
868
        mov     eax, IDE_common_irq_param
869
        cmp     [eax], irq14_num
870
        mov     [eax], bl
871
        xor     eax, eax
872
        je      @f
873
 
874
        add     dx, 8
3762 mario79 875
;--------------------------------------
876
align 4
3870 mario79 877
@@:
878
        out     dx, al
3881 mario79 879
; clear Bus Master IDE Status register
880
; clear Interrupt bit
881
        add     edx, 2
882
        mov     al, 4 ; 100b
883
        out     dx, al
3870 mario79 884
 
2288 clevermous 885
        popad
886
        popfd
3881 mario79 887
;--------------------------------------
888
align 4
3870 mario79 889
.exit:
3762 mario79 890
        mov     al, 1
2288 clevermous 891
        ret
3712 mario79 892
;-----------------------------------------------------------------------------
2288 clevermous 893
align 4
894
hd_read_dma:
895
        push    eax
896
        push    edx
897
        mov     edx, [dma_hdpos]
898
        cmp     edx, [hdpos]
899
        jne     .notread
900
        mov     edx, [dma_cur_sector]
901
        cmp     eax, edx
902
        jb      .notread
903
        add     edx, 15
904
        cmp     [esp+4], edx
905
        ja      .notread
906
        mov     eax, [esp+4]
907
        sub     eax, [dma_cur_sector]
908
        shl     eax, 9
909
        add     eax, (OS_BASE+IDE_DMA)
3742 clevermous 910
        push    ecx esi
2288 clevermous 911
        mov     esi, eax
3712 mario79 912
 
2288 clevermous 913
        mov     ecx, 512/4
914
        cld
915
        rep movsd
3742 clevermous 916
        pop     esi ecx
2288 clevermous 917
        pop     edx
918
        pop     eax
919
        ret
920
.notread:
3870 mario79 921
; set data for PRD Table
2288 clevermous 922
        mov     eax, IDE_descriptor_table
923
        mov     dword [eax], IDE_DMA
924
        mov     word [eax+4], 0x2000
925
        sub     eax, OS_BASE
3870 mario79 926
; select controller Primary or Secondary
2288 clevermous 927
        mov     dx, [IDEContrRegsBaseAddr]
3774 mario79 928
        push    eax
929
        mov     eax, [hd_address_table]
930
        cmp     [hdbase], eax ; 0x1F0
931
        pop     eax
2288 clevermous 932
        jz      @f
933
        add     edx, 8
934
@@:
935
        push    edx
3870 mario79 936
; Bus Master IDE PRD Table Address
2288 clevermous 937
        add     edx, 4
3870 mario79 938
; save IDE_descriptor_table
2288 clevermous 939
        out     dx, eax
940
        pop     edx
3870 mario79 941
; clear Bus Master IDE Command register
2288 clevermous 942
        mov     al, 0
943
        out     dx, al
3870 mario79 944
; clear Bus Master IDE Status register
945
; clear Error bit and Interrupt bit
2288 clevermous 946
        add     edx, 2
3870 mario79 947
        mov     al, 6 ; 110b
2288 clevermous 948
        out     dx, al
3712 mario79 949
; Select the desired drive
950
        mov     edx, [hdbase]
951
        add     edx, 6   ; адрес регистра головок
952
        mov     al, byte [hdid]
953
        add     al, 128+64+32
954
        out     dx, al ; номер головки/номер диска
955
 
2288 clevermous 956
        call    wait_for_hd_idle
957
        cmp     [hd_error], 0
958
        jnz     hd_read_error
3712 mario79 959
 
960
; ATA with 28 or 48 bit for sector number?
961
        mov     eax, [esp+4]
962
; -10h because the PreCache hits the boundary between lba28 and lba48
963
; 10h = 16  - size of PreCache
964
        cmp     eax, 0x10000000-10h
965
        jae     .lba48
966
;--------------------------------------
967
.lba28:
968
        pushfd
969
        cli
2288 clevermous 970
        xor     eax, eax
971
        mov     edx, [hdbase]
972
        inc     edx
3712 mario79 973
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 974
        inc     edx
3712 mario79 975
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
976
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 977
        inc     edx
3712 mario79 978
        mov     eax, [esp+4+4]
979
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 980
        shr     eax, 8
981
        inc     edx
3712 mario79 982
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 983
        shr     eax, 8
984
        inc     edx
3712 mario79 985
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 986
        shr     eax, 8
987
        inc     edx
3712 mario79 988
        and     al, 0xF ; LBA (27:24)
2288 clevermous 989
        add     al, byte [hdid]
990
        add     al, 11100000b
3712 mario79 991
        out     dx, al ; номер головки/номер диска
2288 clevermous 992
        inc     edx
3712 mario79 993
        mov     al, 0xC8 ; READ DMA
994
        out     dx, al ; ATACommand регистр команд
995
        jmp     .continue
996
;--------------------------------------
997
.lba48:
998
        pushfd
999
        cli
1000
        xor     eax, eax
1001
        mov     edx, [hdbase]
1002
        inc     edx
1003
        out     dx, al ; Features Previous Reserved
1004
        out     dx, al ; Features Current Reserved
1005
        inc     edx
1006
        out     dx, al ; Sector Count Previous Sector count (15:8)
1007
        mov     eax, 10h ; Sector Counter = 16 PreCache
1008
        out     dx, al ; Sector Count Current Sector count (7:0)
1009
        inc     edx
1010
        mov     eax, [esp+4+4]
1011
        rol     eax, 8
1012
        out     dx, al ; LBA Low Previous LBA (31:24)
1013
        xor     eax, eax ; because only 32 bit cache
1014
        inc     edx
1015
        out     dx, al ; LBA Mid Previous LBA (39:32)
1016
        inc     edx
1017
        out     dx, al ; LBA High Previous LBA (47:40)
1018
        sub     edx, 2
1019
        mov     eax, [esp+4+4]
1020
        out     dx, al ; LBA Low Current LBA (7:0)
1021
        shr     eax, 8
1022
        inc     edx
1023
        out     dx, al ; LBA Mid Current LBA (15:8)
1024
        shr     eax, 8
1025
        inc     edx
1026
        out     dx, al ; LBA High Current LBA (23:16)
1027
        inc     edx
1028
        mov     al, byte [hdid]
1029
        add     al, 128+64+32
1030
        out     dx, al ; номер головки/номер диска
1031
        inc     edx
1032
        mov     al, 25h ; READ DMA EXT
1033
        out     dx, al ; ATACommand регистр команд
1034
;--------------------------------------
1035
.continue:
3870 mario79 1036
; select controller Primary or Secondary
2288 clevermous 1037
        mov     dx, [IDEContrRegsBaseAddr]
3712 mario79 1038
        mov     eax, [hd_address_table]
1039
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1040
        jz      @f
1041
        add     dx, 8
1042
@@:
3870 mario79 1043
; set write to memory and Start Bus Master
2288 clevermous 1044
        mov     al, 9
1045
        out     dx, al
3870 mario79 1046
 
2288 clevermous 1047
        mov     eax, [CURRENT_TASK]
1048
        mov     [dma_process], eax
3870 mario79 1049
 
2288 clevermous 1050
        mov     eax, [TASK_BASE]
1051
        mov     [dma_slot_ptr], eax
3870 mario79 1052
 
3712 mario79 1053
        mov     eax, [hd_address_table]
1054
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1055
        jnz     .ide1
3762 mario79 1056
 
1057
        mov     [IDE_common_irq_param], irq14_num
2288 clevermous 1058
        jmp     @f
1059
.ide1:
3762 mario79 1060
        mov     [IDE_common_irq_param], irq15_num
2288 clevermous 1061
@@:
3712 mario79 1062
        popfd
3870 mario79 1063
; wait for interrupt
3712 mario79 1064
        mov     eax, [hd_address_table]
1065
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1066
        jnz     .wait_ide1
1067
        call    wait_for_sector_dma_ide0
1068
        jmp     @f
1069
.wait_ide1:
1070
        call    wait_for_sector_dma_ide1
1071
@@:
1072
        cmp     [hd_error], 0
1073
        jnz     hd_read_error
1074
        mov     eax, [hdpos]
1075
        mov     [dma_hdpos], eax
1076
        pop     edx
1077
        pop     eax
1078
        mov     [dma_cur_sector], eax
1079
        jmp     hd_read_dma
3712 mario79 1080
;-----------------------------------------------------------------------------
3742 clevermous 1081
cache_write_dma:
3881 mario79 1082
        mov     eax, [cache_chain_ptr] ; for what?
2288 clevermous 1083
        push    esi
3881 mario79 1084
; set data for PRD Table
2288 clevermous 1085
        mov     eax, IDE_descriptor_table
1086
        mov     edx, eax
1087
        pusha
1088
        mov     edi, (OS_BASE+IDE_DMA)
1089
        mov     dword [edx], IDE_DMA
1090
        movzx   ecx, [cache_chain_size]
1091
        shl     ecx, 9
1092
        mov     word [edx+4], cx
1093
        shr     ecx, 2
1094
        cld
1095
        rep movsd
1096
        popa
1097
        sub     eax, OS_BASE
3881 mario79 1098
; select controller Primary or Secondary
2288 clevermous 1099
        mov     dx, [IDEContrRegsBaseAddr]
3774 mario79 1100
        push    eax
1101
        mov     eax, [hd_address_table]
1102
        cmp     [hdbase], eax ; 0x1F0
1103
        pop     eax
2288 clevermous 1104
        jz      @f
1105
        add     edx, 8
1106
@@:
1107
        push    edx
3881 mario79 1108
; Bus Master IDE PRD Table Address
2288 clevermous 1109
        add     edx, 4
3881 mario79 1110
; save IDE_descriptor_table
2288 clevermous 1111
        out     dx, eax
1112
        pop     edx
3881 mario79 1113
; clear Bus Master IDE Command register
2288 clevermous 1114
        mov     al, 0
1115
        out     dx, al
3881 mario79 1116
; clear Bus Master IDE Status register
1117
; clear Error bit and Interrupt bit
2288 clevermous 1118
        add     edx, 2
1119
        mov     al, 6
1120
        out     dx, al
3712 mario79 1121
; Select the desired drive
1122
        mov     edx, [hdbase]
1123
        add     edx, 6   ; адрес регистра головок
1124
        mov     al, byte [hdid]
1125
        add     al, 128+64+32
1126
        out     dx, al ; номер головки/номер диска
1127
 
2288 clevermous 1128
        call    wait_for_hd_idle
1129
        cmp     [hd_error], 0
1130
        jnz     hd_write_error_dma
3712 mario79 1131
 
1132
; ATA with 28 or 48 bit for sector number?
1133
        mov     esi, [cache_chain_ptr]
1134
        mov     eax, [esi]
1135
; -40h because the PreCache hits the boundary between lba28 and lba48
1136
; 40h = 64  - the maximum number of sectors to be written for one command
1137
        cmp     eax, 0x10000000-40h
1138
        jae     .lba48
1139
;--------------------------------------
1140
.lba28:
1141
        pushfd
1142
        cli
2288 clevermous 1143
        xor     eax, eax
1144
        mov     edx, [hdbase]
1145
        inc     edx
3712 mario79 1146
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 1147
        inc     edx
3712 mario79 1148
        mov     al, [cache_chain_size] ; Sector Counter
1149
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 1150
        inc     edx
1151
        mov     eax, [esi]
3712 mario79 1152
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 1153
        shr     eax, 8
1154
        inc     edx
3712 mario79 1155
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 1156
        shr     eax, 8
1157
        inc     edx
3712 mario79 1158
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 1159
        shr     eax, 8
1160
        inc     edx
3712 mario79 1161
        and     al, 0xF ; LBA (27:24)
2288 clevermous 1162
        add     al, byte [hdid]
1163
        add     al, 11100000b
3712 mario79 1164
        out     dx, al ; номер головки/номер диска
2288 clevermous 1165
        inc     edx
3712 mario79 1166
        mov     al, 0xCA ; WRITE DMA
1167
        out     dx, al ; ATACommand регистр команд
1168
        jmp     .continue
1169
;--------------------------------------
1170
.lba48:
1171
        pushfd
1172
        cli
1173
        xor     eax, eax
1174
        mov     edx, [hdbase]
1175
        inc     edx
1176
        out     dx, al ; Features Previous Reserved
1177
        out     dx, al ; Features Current Reserved
1178
        inc     edx
1179
        out     dx, al ; Sector Count Previous Sector count (15:8)
1180
        mov     al, [cache_chain_size] ; Sector Counter
1181
        out     dx, al ; Sector Count Current Sector count (7:0)
1182
        inc     edx
1183
        mov     eax, [esi]
1184
        rol     eax, 8
1185
        out     dx, al ; LBA Low Previous LBA (31:24)
1186
        xor     eax, eax ; because only 32 bit cache
1187
        inc     edx
1188
        out     dx, al ; LBA Mid Previous LBA (39:32)
1189
        inc     edx
1190
        out     dx, al ; LBA High Previous LBA (47:40)
1191
        sub     edx, 2
1192
        mov     eax, [esi]
1193
        out     dx, al ; LBA Low Current LBA (7:0)
1194
        shr     eax, 8
1195
        inc     edx
1196
        out     dx, al ; LBA Mid Current LBA (15:8)
1197
        shr     eax, 8
1198
        inc     edx
1199
        out     dx, al ; LBA High Current LBA (23:16)
1200
        inc     edx
1201
        mov     al, byte [hdid]
1202
        add     al, 128+64+32
1203
        out     dx, al ; номер головки/номер диска
1204
        inc     edx
1205
        mov     al, 35h ; WRITE DMA EXT
1206
        out     dx, al ; ATACommand регистр команд
1207
;--------------------------------------
1208
.continue:
3881 mario79 1209
; select controller Primary or Secondary
2288 clevermous 1210
        mov     dx, [IDEContrRegsBaseAddr]
3712 mario79 1211
        mov     eax, [hd_address_table]
1212
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1213
        jz      @f
1214
        add     dx, 8
1215
@@:
3881 mario79 1216
; set write to device and Start Bus Master
2288 clevermous 1217
        mov     al, 1
1218
        out     dx, al
1219
        mov     eax, [CURRENT_TASK]
1220
        mov     [dma_process], eax
1221
        mov     eax, [TASK_BASE]
1222
        mov     [dma_slot_ptr], eax
3712 mario79 1223
        mov     eax, [hd_address_table]
1224
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1225
        jnz     .ide1
3762 mario79 1226
 
1227
        mov     [IDE_common_irq_param], irq14_num
2288 clevermous 1228
        jmp     @f
1229
.ide1:
3762 mario79 1230
        mov     [IDE_common_irq_param], irq15_num
2288 clevermous 1231
@@:
3712 mario79 1232
        popfd
3881 mario79 1233
; wait for interrupt
2288 clevermous 1234
        mov     [dma_cur_sector], not 0x40
3712 mario79 1235
        mov     eax, [hd_address_table]
1236
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1237
        jnz     .wait_ide1
1238
        call    wait_for_sector_dma_ide0
1239
        jmp     @f
1240
.wait_ide1:
1241
        call    wait_for_sector_dma_ide1
1242
@@:
1243
        cmp     [hd_error], 0
1244
        jnz     hd_write_error_dma
1245
        pop     esi
1246
        ret
3712 mario79 1247
;-----------------------------------------------------------------------------
2288 clevermous 1248
uglobal
3881 mario79 1249
align 4
3762 mario79 1250
IDE_Interrupt   dw ?
3712 mario79 1251
IDEContrRegsBaseAddr         dw ?
1252
IDEContrProgrammingInterface dw ?
3711 clevermous 1253
IDE_BAR0_val    dw ?
1254
IDE_BAR1_val    dw ?
1255
IDE_BAR2_val    dw ?
1256
IDE_BAR3_val    dw ?
2288 clevermous 1257
endg
3712 mario79 1258
;-----------------------------------------------------------------------------
2288 clevermous 1259
; \begin{diamond}
1260
uglobal
3712 mario79 1261
bios_hdpos      dd 0       ; 0 is invalid value for [hdpos]
1262
bios_cur_sector dd ?
1263
bios_read_len   dd ?
2288 clevermous 1264
endg
3712 mario79 1265
;-----------------------------------------------------------------------------
1266
align 4
2288 clevermous 1267
bd_read:
1268
        push    eax
1269
        push    edx
1270
        mov     edx, [bios_hdpos]
1271
        cmp     edx, [hdpos]
1272
        jne     .notread
1273
        mov     edx, [bios_cur_sector]
1274
        cmp     eax, edx
1275
        jb      .notread
1276
        add     edx, [bios_read_len]
1277
        dec     edx
1278
        cmp     eax, edx
1279
        ja      .notread
1280
        sub     eax, [bios_cur_sector]
1281
        shl     eax, 9
1282
        add     eax, (OS_BASE+0x9A000)
3742 clevermous 1283
        push    ecx esi
2288 clevermous 1284
        mov     esi, eax
1285
        mov     ecx, 512/4
1286
        cld
1287
        rep movsd
3742 clevermous 1288
        pop     esi ecx
2288 clevermous 1289
        pop     edx
1290
        pop     eax
1291
        ret
1292
.notread:
1293
        push    ecx
1294
        mov     dl, 42h
1295
        mov     ecx, 16
1296
        call    int13_call
1297
        pop     ecx
1298
        test    eax, eax
1299
        jnz     .v86err
1300
        test    edx, edx
1301
        jz      .readerr
1302
        mov     [bios_read_len], edx
1303
        mov     edx, [hdpos]
1304
        mov     [bios_hdpos], edx
1305
        pop     edx
1306
        pop     eax
1307
        mov     [bios_cur_sector], eax
1308
        jmp     bd_read
1309
.readerr:
1310
.v86err:
1311
        mov     [hd_error], 1
1312
        jmp     hd_read_error
3712 mario79 1313
;-----------------------------------------------------------------------------
1314
align 4
2288 clevermous 1315
bd_write_cache_chain:
1316
        pusha
1317
        mov     edi, OS_BASE + 0x9A000
1318
        movzx   ecx, [cache_chain_size]
1319
        push    ecx
1320
        shl     ecx, 9-2
1321
        rep movsd
1322
        pop     ecx
1323
        mov     dl, 43h
1324
        mov     eax, [cache_chain_ptr]
1325
        mov     eax, [eax]
1326
        call    int13_call
1327
        test    eax, eax
1328
        jnz     .v86err
1329
        cmp     edx, ecx
1330
        jnz     .writeerr
1331
        popa
1332
        ret
1333
.v86err:
1334
.writeerr:
1335
        popa
1336
        mov     [hd_error], 1
1337
        jmp     hd_write_error
3712 mario79 1338
;-----------------------------------------------------------------------------
2288 clevermous 1339
uglobal
3712 mario79 1340
int13_regs_in   rb sizeof.v86_regs
1341
int13_regs_out  rb sizeof.v86_regs
2288 clevermous 1342
endg
3712 mario79 1343
;-----------------------------------------------------------------------------
1344
align 4
2288 clevermous 1345
int13_call:
1346
; Because this code uses fixed addresses,
1347
; it can not be run simultaniously by many threads.
3742 clevermous 1348
; In current implementation it is protected by common mutex 'ide_status'
2288 clevermous 1349
        mov     word [OS_BASE + 510h], 10h             ; packet length
1350
        mov     word [OS_BASE + 512h], cx              ; number of sectors
1351
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
1352
        mov     dword [OS_BASE + 518h], eax
1353
        and     dword [OS_BASE + 51Ch], 0
1354
        push    ebx ecx esi edi
1355
        mov     ebx, int13_regs_in
1356
        mov     edi, ebx
2384 hidnplayr 1357
        mov     ecx, sizeof.v86_regs/4
2288 clevermous 1358
        xor     eax, eax
1359
        rep stosd
1360
        mov     byte [ebx+v86_regs.eax+1], dl
1361
        mov     eax, [hdpos]
1362
        lea     eax, [BiosDisksData+(eax-80h)*4]
1363
        mov     dl, [eax]
1364
        mov     byte [ebx+v86_regs.edx], dl
1365
        movzx   edx, byte [eax+1]
1366
;        mov     dl, 5
1367
        test    edx, edx
1368
        jnz     .hasirq
1369
        dec     edx
1370
        jmp     @f
1371
.hasirq:
1372
        pushad
1373
        stdcall enable_irq, edx
1374
        popad
1375
@@:
1376
        mov     word [ebx+v86_regs.esi], 510h
1377
        mov     word [ebx+v86_regs.ss], 9000h
1378
        mov     word [ebx+v86_regs.esp], 0A000h
1379
        mov     word [ebx+v86_regs.eip], 500h
1380
        mov     [ebx+v86_regs.eflags], 20200h
1381
        mov     esi, [sys_v86_machine]
1382
        mov     ecx, 0x502
1383
        push    fs
1384
        call    v86_start
1385
        pop     fs
1386
        and     [bios_hdpos], 0
1387
        pop     edi esi ecx ebx
1388
        movzx   edx, byte [OS_BASE + 512h]
1389
        test    byte [int13_regs_out+v86_regs.eflags], 1
1390
        jnz     @f
1391
        mov     edx, ecx
1392
@@:
1393
        ret
1394
; \end{diamond}