Subversion Repositories Kolibri OS

Rev

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