Subversion Repositories Kolibri OS

Rev

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