Subversion Repositories Kolibri OS

Rev

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

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