Subversion Repositories Kolibri OS

Rev

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