Subversion Repositories Kolibri OS

Rev

Rev 6650 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6650 Rev 6842
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 6650 $
8
$Revision: 6842 $
9
 
9
 
10
; HDD driver
10
; HDD driver
11
 
11
 
12
struct HD_DATA
12
struct HD_DATA
13
hdbase  dw  ?
-
 
14
hdid    dw  ?
-
 
15
hdpos   dw  ?
13
hdpos   dw  ?
-
 
14
hdid    dw  ?
-
 
15
hdbase  dw  ?
16
hd48    dw  ?
16
hd48    dw  ?
-
 
17
sectors dq  ?
17
ends
18
ends
18
;-----------------------------------------------------------------
19
;-----------------------------------------------------------------
19
iglobal
20
iglobal
20
align 4
21
align 4
21
ide_callbacks:
22
ide_callbacks:
22
    dd  ide_callbacks.end - ide_callbacks
23
    dd  ide_callbacks.end - ide_callbacks
23
    dd  0   ; no close function
24
    dd  0   ; no close function
24
    dd  0   ; no closemedia function
25
    dd  0   ; no closemedia function
25
    dd  ide_querymedia
26
    dd  ide_querymedia
26
    dd  ide_read
27
    dd  ide_read
27
    dd  ide_write
28
    dd  ide_write
28
    dd  0   ; no flush function
29
    dd  0   ; no flush function
29
    dd  0   ; use default cache size
30
    dd  0   ; use default cache size
30
.end:
31
.end:
31
 
32
 
32
hd0_data    HD_DATA     ?,  0,  1, 0
33
hd0_data    HD_DATA     1,  0
33
hd1_data    HD_DATA     ?, 16,  2, 0
34
hd1_data    HD_DATA     2,  16
34
hd2_data    HD_DATA     ?,  0,  3, 0
35
hd2_data    HD_DATA     3,  0
35
hd3_data    HD_DATA     ?, 16,  4, 0
36
hd3_data    HD_DATA     4,  16
36
hd4_data    HD_DATA     ?,  0,  5, 0
37
hd4_data    HD_DATA     5,  0
37
hd5_data    HD_DATA     ?, 16,  6, 0
38
hd5_data    HD_DATA     6,  16
38
hd6_data    HD_DATA     ?,  0,  7, 0
39
hd6_data    HD_DATA     7,  0
39
hd7_data    HD_DATA     ?, 16,  8, 0
40
hd7_data    HD_DATA     8,  16
40
hd8_data    HD_DATA     ?,  0,  9, 0
41
hd8_data    HD_DATA     9,  0
41
hd9_data    HD_DATA     ?, 16, 10, 0
42
hd9_data    HD_DATA     10, 16
42
hd10_data   HD_DATA     ?,  0, 11, 0
43
hd10_data   HD_DATA     11, 0
43
hd11_data   HD_DATA     ?, 16, 12, 0
44
hd11_data   HD_DATA     12, 16
44
 
45
 
45
ide_mutex_table:
46
ide_mutex_table:
46
    dd  ide_channel1_mutex
47
    dd  ide_channel1_mutex
47
    dd  ide_channel2_mutex
48
    dd  ide_channel2_mutex
48
    dd  ide_channel3_mutex
49
    dd  ide_channel3_mutex
49
    dd  ide_channel4_mutex
50
    dd  ide_channel4_mutex
50
    dd  ide_channel5_mutex
51
    dd  ide_channel5_mutex
51
    dd  ide_channel6_mutex
52
    dd  ide_channel6_mutex
52
endg
53
endg
53
;-----------------------------------------------------------------
54
;-----------------------------------------------------------------
54
uglobal
55
uglobal
55
ide_mutex               MUTEX
56
ide_mutex               MUTEX
56
ide_channel1_mutex      MUTEX
57
ide_channel1_mutex      MUTEX
57
ide_channel2_mutex      MUTEX
58
ide_channel2_mutex      MUTEX
58
ide_channel3_mutex      MUTEX
59
ide_channel3_mutex      MUTEX
59
ide_channel4_mutex      MUTEX
60
ide_channel4_mutex      MUTEX
60
ide_channel5_mutex      MUTEX
61
ide_channel5_mutex      MUTEX
61
ide_channel6_mutex      MUTEX
62
ide_channel6_mutex      MUTEX
62
blockSize:
63
blockSize:
63
rb 4
64
rb 4
64
sector:
65
sector:
65
rb 6
66
rb 6
66
allow_dma_access        db ?
67
allow_dma_access        db ?
67
IDE_common_irq_param    db ?
68
IDE_common_irq_param    db ?
68
eventPointer            dd ?
69
eventPointer            dd ?
69
eventID                 dd ?
70
eventID                 dd ?
70
endg
71
endg
71
;-----------------------------------------------------------------
72
;-----------------------------------------------------------------
72
ide_read:
73
ide_read:
73
        mov     al, 25h     ; READ DMA EXT
74
        mov     al, 25h     ; READ DMA EXT
74
        jmp     ide_read_write
75
        jmp     ide_read_write
75
 
76
 
76
ide_write:
77
ide_write:
77
        mov     al, 35h     ; WRITE DMA EXT
78
        mov     al, 35h     ; WRITE DMA EXT
78
proc ide_read_write stdcall uses esi edi ebx, \
79
proc ide_read_write stdcall uses esi edi ebx, \
79
        hd_data, buffer, startsector:qword, numsectors
80
        hd_data, buffer, startsector:qword, numsectors
80
        ; hd_data = pointer to hd*_data
81
        ; hd_data = pointer to hd*_data
81
        ; buffer = pointer to buffer with/for data
82
        ; buffer = pointer to buffer with/for data
82
        ; startsector = 64-bit start sector
83
        ; startsector = 64-bit start sector
83
        ; numsectors = pointer to number of sectors on input,
84
        ; numsectors = pointer to number of sectors on input,
84
        ;  must be filled with number of sectors really read/written
85
        ;  must be filled with number of sectors really read/written
85
locals
86
locals
86
sectors_todo    dd      ?
87
sectors_todo    dd      ?
87
channel_lock    dd      ?
88
channel_lock    dd      ?
88
endl
89
endl
89
        mov     bl, al
90
        mov     bl, al
90
; get number of requested sectors and say that no sectors were read yet
91
; get number of requested sectors and say that no sectors were read yet
91
        mov     ecx, [numsectors]
92
        mov     ecx, [numsectors]
92
        mov     eax, [ecx]
93
        mov     eax, [ecx]
93
        mov     dword [ecx], 0
94
        mov     dword [ecx], 0
94
        mov     [sectors_todo], eax
95
        mov     [sectors_todo], eax
95
; acquire the global lock
96
; acquire the global lock
96
        mov     ecx, ide_mutex
97
        mov     ecx, ide_mutex
97
        call    mutex_lock
98
        call    mutex_lock
98
        mov     ecx, [hd_data]
99
        mov     ecx, [hd_data]
99
        movzx   ecx, [ecx+HD_DATA.hdpos]
100
        movzx   ecx, [ecx+HD_DATA.hdpos]
100
        dec     ecx
101
        dec     ecx
101
        shr     ecx, 1
102
        shr     ecx, 1
102
        shl     ecx, 2
103
        shl     ecx, 2
103
        mov     ecx, [ecx + ide_mutex_table]
104
        mov     ecx, [ecx + ide_mutex_table]
104
        mov     [channel_lock], ecx
105
        mov     [channel_lock], ecx
105
        call    mutex_lock
106
        call    mutex_lock
106
; prepare worker procedures variables
107
; prepare worker procedures variables
107
        mov     esi, [buffer]
108
        mov     esi, [buffer]
108
        mov     edi, esi
109
        mov     edi, esi
109
        mov     ecx, [hd_data]
110
        mov     ecx, [hd_data]
110
        movzx   eax, [ecx+HD_DATA.hdbase]
111
        movzx   eax, [ecx+HD_DATA.hdbase]
111
        mov     [hdbase], eax
112
        mov     [hdbase], eax
112
        mov     ax, [ecx+HD_DATA.hdid]
113
        mov     ax, [ecx+HD_DATA.hdid]
113
        mov     [hdid], eax
114
        mov     [hdid], eax
114
        mov     eax, dword [startsector]
115
        mov     eax, dword [startsector]
115
        mov     [sector], eax
116
        mov     [sector], eax
116
        cmp     [ecx+HD_DATA.hd48], 0
117
        cmp     [ecx+HD_DATA.hd48], 0
117
        jz      .LBA28
118
        jz      .LBA28
118
        mov     ax, word [startsector+4]
119
        mov     ax, word [startsector+4]
119
        mov     [sector+4], ax
120
        mov     [sector+4], ax
120
        movzx   ecx, [ecx+HD_DATA.hdpos]
121
        movzx   ecx, [ecx+HD_DATA.hdpos]
121
        mov     [hdpos], ecx
122
        mov     [hdpos], ecx
122
        dec     ecx
123
        dec     ecx
123
        shr     ecx, 2
124
        shr     ecx, 2
124
        imul    ecx, sizeof.IDE_DATA
125
        imul    ecx, sizeof.IDE_DATA
125
        add     ecx, IDE_controller_1
126
        add     ecx, IDE_controller_1
126
        mov     [IDE_controller_pointer], ecx
127
        mov     [IDE_controller_pointer], ecx
127
        mov     eax, [hdpos]
128
        mov     eax, [hdpos]
128
        dec     eax
129
        dec     eax
129
        and     eax, 11b
130
        and     eax, 11b
130
        shr     eax, 1
131
        shr     eax, 1
131
        add     eax, ecx
132
        add     eax, ecx
132
        cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
133
        cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
133
        jz      .next
134
        jz      .next
134
        dec     ebx     ; READ/WRITE SECTOR(S) EXT
135
        dec     ebx     ; READ/WRITE SECTOR(S) EXT
135
; LBA48 supports max 10000h sectors per time
136
; LBA48 supports max 10000h sectors per time
136
; loop until all sectors will be processed
137
; loop until all sectors will be processed
137
.next:
138
.next:
138
        mov     ecx, 8000h
139
        mov     ecx, 8000h
139
        cmp     ecx, [sectors_todo]
140
        cmp     ecx, [sectors_todo]
140
        jbe     @f
141
        jbe     @f
141
        mov     ecx, [sectors_todo]
142
        mov     ecx, [sectors_todo]
142
@@:
143
@@:
143
        mov     [blockSize], ecx
144
        mov     [blockSize], ecx
144
        push    ecx
145
        push    ecx
145
        call    IDE_transfer
146
        call    IDE_transfer
146
        pop     ecx
147
        pop     ecx
147
        jc      .out
148
        jc      .out
148
        mov     eax, [numsectors]
149
        mov     eax, [numsectors]
149
        add     [eax], ecx
150
        add     [eax], ecx
150
        sub     [sectors_todo], ecx
151
        sub     [sectors_todo], ecx
151
        jz      .out
152
        jz      .out
152
        add     [sector], ecx
153
        add     [sector], ecx
153
        adc     word [sector+4], 0
154
        adc     word [sector+4], 0
154
        jmp     .next
155
        jmp     .next
155
 
156
 
156
.LBA28:
157
.LBA28:
157
        add     eax, [sectors_todo]
158
        add     eax, [sectors_todo]
158
        add     eax, 0xF0000000
159
        add     eax, 0xF0000000
159
        jc      .out
160
        jc      .out
160
        sub     bl, 5   ; READ/WRITE SECTOR(S)
161
        sub     bl, 5   ; READ/WRITE SECTOR(S)
161
; LBA28 supports max 256 sectors per time
162
; LBA28 supports max 256 sectors per time
162
; loop until all sectors will be processed
163
; loop until all sectors will be processed
163
.next28:
164
.next28:
164
        mov     ecx, 256
165
        mov     ecx, 256
165
        cmp     ecx, [sectors_todo]
166
        cmp     ecx, [sectors_todo]
166
        jbe     @f
167
        jbe     @f
167
        mov     ecx, [sectors_todo]
168
        mov     ecx, [sectors_todo]
168
@@:
169
@@:
169
        mov     [blockSize], ecx
170
        mov     [blockSize], ecx
170
        push    ecx
171
        push    ecx
171
        call    IDE_transfer.LBA28
172
        call    IDE_transfer.LBA28
172
        pop     ecx
173
        pop     ecx
173
        jc      .out
174
        jc      .out
174
        mov     eax, [numsectors]
175
        mov     eax, [numsectors]
175
        add     [eax], ecx
176
        add     [eax], ecx
176
        sub     [sectors_todo], ecx
177
        sub     [sectors_todo], ecx
177
        jz      .out
178
        jz      .out
178
        add     [sector], ecx
179
        add     [sector], ecx
179
        jmp     .next28
180
        jmp     .next28
180
 
181
 
181
; loop is done, either due to error or because everything is done
182
; loop is done, either due to error or because everything is done
182
; release the global lock and return the corresponding status
183
; release the global lock and return the corresponding status
183
.out:
184
.out:
184
        sbb     eax, eax
185
        sbb     eax, eax
185
        push    eax
186
        push    eax
186
        mov     ecx, [channel_lock]
187
        mov     ecx, [channel_lock]
187
        call    mutex_unlock
188
        call    mutex_unlock
188
        mov     ecx, ide_mutex
189
        mov     ecx, ide_mutex
189
        call    mutex_unlock
190
        call    mutex_unlock
190
        pop     eax
191
        pop     eax
191
        ret
192
        ret
192
endp
193
endp
193
;-----------------------------------------------------------------
194
;-----------------------------------------------------------------
194
; this is a stub
-
 
195
proc ide_querymedia stdcall, hd_data, mediainfo
195
proc ide_querymedia stdcall, hd_data, mediainfo
196
        mov     eax, [mediainfo]
196
        mov     eax, [mediainfo]
-
 
197
        mov     edx, [hd_data]
197
        mov     [eax+DISKMEDIAINFO.Flags], 0
198
        mov     [eax+DISKMEDIAINFO.Flags], 0
198
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
199
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
-
 
200
        mov     ecx, dword[edx+HD_DATA.sectors]
199
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
201
        mov     dword[eax+DISKMEDIAINFO.Capacity], ecx
-
 
202
        mov     ecx, dword[edx+HD_DATA.sectors+4]
200
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
203
        mov     dword[eax+DISKMEDIAINFO.Capacity+4], ecx
201
        xor     eax, eax
204
        xor     eax, eax
202
        ret
205
        ret
203
endp
206
endp
204
;-----------------------------------------------------------------
207
;-----------------------------------------------------------------
205
; input: esi -> buffer, bl = command, [sector], [blockSize]
208
; input: esi -> buffer, bl = command, [sector], [blockSize]
206
; output: esi -> next block in buffer
209
; output: esi -> next block in buffer
207
; for pio read esi equal edi
210
; for pio read esi equal edi
208
IDE_transfer:
211
IDE_transfer:
209
        mov     edx, [hdbase]
212
        mov     edx, [hdbase]
210
        add     edx, 6
213
        add     edx, 6
211
        mov     al, byte [hdid]
214
        mov     al, byte [hdid]
212
        add     al, 224
215
        add     al, 224
213
        out     dx, al  ; select the desired drive
216
        out     dx, al  ; select the desired drive
214
        call    save_hd_wait_timeout
217
        call    save_hd_wait_timeout
215
        inc     edx
218
        inc     edx
216
@@:
219
@@:
217
        call    check_hd_wait_timeout
220
        call    check_hd_wait_timeout
218
        jc      .hd_error
221
        jc      .hd_error
219
        in      al, dx
222
        in      al, dx
220
        test    al, 128 ; ready for command?
223
        test    al, 128 ; ready for command?
221
        jnz     @b
224
        jnz     @b
222
        pushfd          ; fill the ports
225
        pushfd          ; fill the ports
223
        cli
226
        cli
224
        mov     edx, [hdbase]
227
        mov     edx, [hdbase]
225
        inc     edx
228
        inc     edx
226
        inc     edx
229
        inc     edx
227
        mov     al, [blockSize+1]
230
        mov     al, [blockSize+1]
228
        out     dx, al  ; Sector count (15:8)
231
        out     dx, al  ; Sector count (15:8)
229
        inc     edx
232
        inc     edx
230
        mov     eax, [sector+3]
233
        mov     eax, [sector+3]
231
        out     dx, al  ; LBA (31:24)
234
        out     dx, al  ; LBA (31:24)
232
        inc     edx
235
        inc     edx
233
        shr     eax, 8
236
        shr     eax, 8
234
        out     dx, al  ; LBA (39:32)
237
        out     dx, al  ; LBA (39:32)
235
        inc     edx
238
        inc     edx
236
        shr     eax, 8
239
        shr     eax, 8
237
        out     dx, al  ; LBA (47:40)
240
        out     dx, al  ; LBA (47:40)
238
        sub     edx, 3
241
        sub     edx, 3
239
        mov     al, [blockSize]
242
        mov     al, [blockSize]
240
        out     dx, al  ; Sector count (7:0)
243
        out     dx, al  ; Sector count (7:0)
241
        inc     edx
244
        inc     edx
242
        mov     eax, [sector]
245
        mov     eax, [sector]
243
        out     dx, al  ; LBA (7:0)
246
        out     dx, al  ; LBA (7:0)
244
        inc     edx
247
        inc     edx
245
        shr     eax, 8
248
        shr     eax, 8
246
        out     dx, al  ; LBA (15:8)
249
        out     dx, al  ; LBA (15:8)
247
        inc     edx
250
        inc     edx
248
        shr     eax, 8
251
        shr     eax, 8
249
        out     dx, al  ; LBA (23:16)
252
        out     dx, al  ; LBA (23:16)
250
        inc     edx
253
        inc     edx
251
        mov     al, byte [hdid]
254
        mov     al, byte [hdid]
252
        add     al, 224
255
        add     al, 224
253
        out     dx, al
256
        out     dx, al
254
        test    bl, 1
257
        test    bl, 1
255
        jz      .PIO
258
        jz      .PIO
256
; DMA
259
; DMA
257
        mov     dword [esp], 0x1000
260
        mov     dword [esp], 0x1000
258
        call    kernel_alloc
261
        call    kernel_alloc
259
        mov     edi, eax
262
        mov     edi, eax
260
        push    eax
263
        push    eax
261
        shl     dword [blockSize], 9
264
        shl     dword [blockSize], 9
262
        mov     eax, esi
265
        mov     eax, esi
263
        add     eax, [blockSize]
266
        add     eax, [blockSize]
264
        push    eax
267
        push    eax
265
; check buffer pages physical addresses and fill the scatter-gather list
268
; check buffer pages physical addresses and fill the scatter-gather list
266
; buffer may be not aligned and may have size not divisible by page size
269
; buffer may be not aligned and may have size not divisible by page size
267
; [edi] = block physical address, [edi+4] = block size in bytes
270
; [edi] = block physical address, [edi+4] = block size in bytes
268
; block addresses can not cross 10000h borders
271
; block addresses can not cross 10000h borders
269
        mov     ecx, esi
272
        mov     ecx, esi
270
        and     ecx, 0xFFF
273
        and     ecx, 0xFFF
271
        jz      .aligned
274
        jz      .aligned
272
        mov     eax, esi
275
        mov     eax, esi
273
        call    get_pg_addr
276
        call    get_pg_addr
274
        add     eax, ecx
277
        add     eax, ecx
275
        neg     ecx
278
        neg     ecx
276
        add     ecx, 0x1000
279
        add     ecx, 0x1000
277
        mov     [edi], eax
280
        mov     [edi], eax
278
        cmp     ecx, [blockSize]
281
        cmp     ecx, [blockSize]
279
        jnc     .end
282
        jnc     .end
280
        mov     [edi+4], ecx
283
        mov     [edi+4], ecx
281
        add     esi, 0x1000
284
        add     esi, 0x1000
282
        add     edi, 8
285
        add     edi, 8
283
        sub     [blockSize], ecx
286
        sub     [blockSize], ecx
284
.aligned:
287
.aligned:
285
        mov     eax, esi
288
        mov     eax, esi
286
        call    get_pg_addr
289
        call    get_pg_addr
287
        mov     ecx, eax
290
        mov     ecx, eax
288
        mov     [edi], eax
291
        mov     [edi], eax
289
        and     ecx, 0xFFFF
292
        and     ecx, 0xFFFF
290
        neg     ecx
293
        neg     ecx
291
        add     ecx, 0x10000
294
        add     ecx, 0x10000
292
        cmp     [blockSize], ecx
295
        cmp     [blockSize], ecx
293
        jnc     @f
296
        jnc     @f
294
        mov     ecx, [blockSize]
297
        mov     ecx, [blockSize]
295
        and     ecx, 0xF000
298
        and     ecx, 0xF000
296
        jz      .end
299
        jz      .end
297
@@:
300
@@:
298
        push    ecx
301
        push    ecx
299
@@:
302
@@:
300
        add     esi, 0x1000
303
        add     esi, 0x1000
301
        add     eax, 0x1000
304
        add     eax, 0x1000
302
        sub     ecx, 0x1000
305
        sub     ecx, 0x1000
303
        jz      @f
306
        jz      @f
304
        mov     edx, eax
307
        mov     edx, eax
305
        mov     eax, esi
308
        mov     eax, esi
306
        call    get_pg_addr
309
        call    get_pg_addr
307
        cmp     eax, edx
310
        cmp     eax, edx
308
        jz      @b
311
        jz      @b
309
@@:
312
@@:
310
        pop     edx
313
        pop     edx
311
        sub     edx, ecx
314
        sub     edx, ecx
312
        mov     [edi+4], edx
315
        mov     [edi+4], edx
313
        add     edi, 8
316
        add     edi, 8
314
        sub     [blockSize], edx
317
        sub     [blockSize], edx
315
        jnz     .aligned
318
        jnz     .aligned
316
        sub     edi, 8
319
        sub     edi, 8
317
        jmp     @f
320
        jmp     @f
318
 
321
 
319
.end:
322
.end:
320
        mov     ecx, [blockSize]
323
        mov     ecx, [blockSize]
321
        mov     [edi+4], ecx
324
        mov     [edi+4], ecx
322
@@:
325
@@:
323
        mov     byte [edi+7], 80h   ; list end
326
        mov     byte [edi+7], 80h   ; list end
324
        pop     esi
327
        pop     esi
325
        pop     edi
328
        pop     edi
326
; select controller Primary or Secondary
329
; select controller Primary or Secondary
327
        mov     ecx, [IDE_controller_pointer]
330
        mov     ecx, [IDE_controller_pointer]
328
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
331
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
329
        mov     eax, [hdpos]
332
        mov     eax, [hdpos]
330
        dec     eax
333
        dec     eax
331
        test    eax, 10b
334
        test    eax, 10b
332
        jz      @f
335
        jz      @f
333
        add     edx, 8
336
        add     edx, 8
334
@@:
337
@@:
335
        add     edx, 2      ; Bus Master IDE Status register
338
        add     edx, 2      ; Bus Master IDE Status register
336
        mov     al, 6
339
        mov     al, 6
337
        out     dx, al      ; clear Error bit and Interrupt bit
340
        out     dx, al      ; clear Error bit and Interrupt bit
338
 
341
 
339
        add     edx, 2      ; Bus Master IDE PRD Table Address
342
        add     edx, 2      ; Bus Master IDE PRD Table Address
340
        mov     eax, edi
343
        mov     eax, edi
341
        call    get_pg_addr
344
        call    get_pg_addr
342
        out     dx, eax     ; send scatter-gather list physical address
345
        out     dx, eax     ; send scatter-gather list physical address
343
 
346
 
344
        push    edx
347
        push    edx
345
        mov     edx, [hdbase]
348
        mov     edx, [hdbase]
346
        add     edx, 7      ; ATACommand
349
        add     edx, 7      ; ATACommand
347
        mov     al, bl
350
        mov     al, bl
348
        out     dx, al      ; Start hard drive
351
        out     dx, al      ; Start hard drive
349
        pop     edx
352
        pop     edx
350
 
353
 
351
        sub     edx, 4      ; Bus Master IDE Command register
354
        sub     edx, 4      ; Bus Master IDE Command register
352
        mov     al, 1       ; set direction
355
        mov     al, 1       ; set direction
353
        cmp     bl, 35h     ; write
356
        cmp     bl, 35h     ; write
354
        jz      @f
357
        jz      @f
355
        add     al, 8       ; read
358
        add     al, 8       ; read
356
@@:
359
@@:
357
        out     dx, al      ; Start Bus Master
360
        out     dx, al      ; Start Bus Master
358
        mov     [IDE_common_irq_param], 14
361
        mov     [IDE_common_irq_param], 14
359
        mov     eax, [hdpos]
362
        mov     eax, [hdpos]
360
        dec     eax
363
        dec     eax
361
        test    eax, 10b
364
        test    eax, 10b
362
        jz      @f
365
        jz      @f
363
        inc     [IDE_common_irq_param]
366
        inc     [IDE_common_irq_param]
364
@@:
367
@@:
365
        push    edi esi ebx
368
        push    edi esi ebx
366
        xor     ecx, ecx
369
        xor     ecx, ecx
367
        xor     esi, esi
370
        xor     esi, esi
368
        call    create_event
371
        call    create_event
369
        mov     [eventPointer], eax
372
        mov     [eventPointer], eax
370
        mov     [eventID], edx
373
        mov     [eventID], edx
371
        sti
374
        sti
372
        mov     ebx, edx
375
        mov     ebx, edx
373
        mov     ecx, 300
376
        mov     ecx, 300
374
        call    wait_event_timeout
377
        call    wait_event_timeout
375
        test    eax, eax
378
        test    eax, eax
376
        jnz     @f
379
        jnz     @f
377
        dbgstr 'IDE DMA IRQ timeout'
380
        dbgstr 'IDE DMA IRQ timeout'
378
        mov     [IDE_common_irq_param], 0
381
        mov     [IDE_common_irq_param], 0
379
        mov     eax, [eventPointer]
382
        mov     eax, [eventPointer]
380
        mov     ebx, [eventID]
383
        mov     ebx, [eventID]
381
        call    destroy_event
384
        call    destroy_event
382
        mov     [eventPointer], 0
385
        mov     [eventPointer], 0
383
@@:
386
@@:
384
        pop     ebx esi
387
        pop     ebx esi
385
        call    kernel_free
388
        call    kernel_free
386
        cmp     [eventPointer], 0
389
        cmp     [eventPointer], 0
387
        jz      .hd_error
390
        jz      .hd_error
388
        ret
391
        ret
389
 
392
 
390
.LBA28:
393
.LBA28:
391
        mov     edx, [hdbase]
394
        mov     edx, [hdbase]
392
        add     edx, 6
395
        add     edx, 6
393
        mov     al, byte [hdid]
396
        mov     al, byte [hdid]
394
        add     al, 224
397
        add     al, 224
395
        out     dx, al  ; select the desired drive
398
        out     dx, al  ; select the desired drive
396
        call    save_hd_wait_timeout
399
        call    save_hd_wait_timeout
397
        inc     edx
400
        inc     edx
398
@@:
401
@@:
399
        call    check_hd_wait_timeout
402
        call    check_hd_wait_timeout
400
        jc      .hd_error
403
        jc      .hd_error
401
        in      al, dx
404
        in      al, dx
402
        test    al, 128 ; ready for command?
405
        test    al, 128 ; ready for command?
403
        jnz     @b
406
        jnz     @b
404
        pushfd          ; fill the ports
407
        pushfd          ; fill the ports
405
        cli
408
        cli
406
        mov     edx, [hdbase]
409
        mov     edx, [hdbase]
407
        inc     edx
410
        inc     edx
408
        inc     edx
411
        inc     edx
409
        mov     al, [blockSize]
412
        mov     al, [blockSize]
410
        out     dx, al  ; Sector count (7:0)
413
        out     dx, al  ; Sector count (7:0)
411
        inc     edx
414
        inc     edx
412
        mov     eax, [sector]
415
        mov     eax, [sector]
413
        out     dx, al  ; LBA (7:0)
416
        out     dx, al  ; LBA (7:0)
414
        inc     edx
417
        inc     edx
415
        shr     eax, 8
418
        shr     eax, 8
416
        out     dx, al  ; LBA (15:8)
419
        out     dx, al  ; LBA (15:8)
417
        inc     edx
420
        inc     edx
418
        shr     eax, 8
421
        shr     eax, 8
419
        out     dx, al  ; LBA (23:16)
422
        out     dx, al  ; LBA (23:16)
420
        inc     edx
423
        inc     edx
421
        shr     eax, 8
424
        shr     eax, 8
422
        add     al, byte [hdid]
425
        add     al, byte [hdid]
423
        add     al, 224
426
        add     al, 224
424
        out     dx, al  ; LBA (27:24)
427
        out     dx, al  ; LBA (27:24)
425
.PIO:
428
.PIO:
426
        inc     edx     ; ATACommand
429
        inc     edx     ; ATACommand
427
        mov     al, bl
430
        mov     al, bl
428
        out     dx, al  ; Start hard drive
431
        out     dx, al  ; Start hard drive
429
        popfd
432
        popfd
430
.sectorTransfer:
433
.sectorTransfer:
431
        call    save_hd_wait_timeout
434
        call    save_hd_wait_timeout
432
        in      al, dx
435
        in      al, dx
433
        in      al, dx
436
        in      al, dx
434
        in      al, dx
437
        in      al, dx
435
        in      al, dx
438
        in      al, dx
436
@@:
439
@@:
437
        call    check_hd_wait_timeout
440
        call    check_hd_wait_timeout
438
        jc      .hd_error
441
        jc      .hd_error
439
        in      al, dx
442
        in      al, dx
440
        test    al, 8   ; ready for transfer?
443
        test    al, 8   ; ready for transfer?
441
        jz      @b
444
        jz      @b
442
        cmp     [hd_setup], 1   ; do not mark error for setup request
445
        cmp     [hd_setup], 1   ; do not mark error for setup request
443
        jz      @f
446
        jz      @f
444
        test    al, 1   ; previous command ended up with an error
447
        test    al, 1   ; previous command ended up with an error
445
        jnz     .pio_error
448
        jnz     .pio_error
446
@@:
449
@@:
447
        pushfd
450
        pushfd
448
        cli
451
        cli
449
        cld
452
        cld
450
        mov     ecx, 256
453
        mov     ecx, 256
451
        mov     edx, [hdbase]
454
        mov     edx, [hdbase]
452
        cmp     bl, 30h
455
        cmp     bl, 30h
453
        jnc     .write
456
        jnc     .write
454
        rep insw
457
        rep insw
455
        jmp     @f
458
        jmp     @f
456
 
459
 
457
.write:
460
.write:
458
        rep outsw
461
        rep outsw
459
@@:
462
@@:
460
        popfd
463
        popfd
461
        add     edx, 7
464
        add     edx, 7
462
        dec     dword [blockSize]
465
        dec     dword [blockSize]
463
        jnz     .sectorTransfer
466
        jnz     .sectorTransfer
464
        ret
467
        ret
465
 
468
 
466
.pio_error:
469
.pio_error:
467
        dbgstr 'IDE PIO transfer error'
470
        dbgstr 'IDE PIO transfer error'
468
.hd_error:
471
.hd_error:
469
        cmp     bl, 30h
472
        cmp     bl, 30h
470
        jnc     hd_write_error
473
        jnc     hd_write_error
471
;-----------------------------------------------------------------
474
;-----------------------------------------------------------------
472
hd_read_error:
475
hd_read_error:
473
        dbgstr 'HD read error'
476
        dbgstr 'HD read error'
474
        stc
477
        stc
475
        ret
478
        ret
476
;-----------------------------------------------------------------
479
;-----------------------------------------------------------------
477
hd_write_error:
480
hd_write_error:
478
        dbgstr 'HD write error'
481
        dbgstr 'HD write error'
479
        stc
482
        stc
480
        ret
483
        ret
481
;-----------------------------------------------------------------
484
;-----------------------------------------------------------------
482
save_hd_wait_timeout:
485
save_hd_wait_timeout:
483
        mov     eax, [timer_ticks]
486
        mov     eax, [timer_ticks]
484
        add     eax, 300        ; 3 sec timeout
487
        add     eax, 300        ; 3 sec timeout
485
        mov     [hd_wait_timeout], eax
488
        mov     [hd_wait_timeout], eax
486
        ret
489
        ret
487
;-----------------------------------------------------------------
490
;-----------------------------------------------------------------
488
check_hd_wait_timeout:
491
check_hd_wait_timeout:
489
        mov     eax, [timer_ticks]
492
        mov     eax, [timer_ticks]
490
        cmp     [hd_wait_timeout], eax
493
        cmp     [hd_wait_timeout], eax
491
        jc      @f
494
        jc      @f
492
        ret
495
        ret
493
 
496
 
494
@@:
497
@@:
495
        dbgstr 'IDE device timeout'
498
        dbgstr 'IDE device timeout'
496
        stc
499
        stc
497
        ret
500
        ret
498
;-----------------------------------------------------------------
501
;-----------------------------------------------------------------
499
align 4
502
align 4
500
IDE_irq_14_handler:
503
IDE_irq_14_handler:
501
IDE_irq_15_handler:
504
IDE_irq_15_handler:
502
IDE_common_irq_handler:
505
IDE_common_irq_handler:
503
; Most of the time, we are here because we have requested
506
; Most of the time, we are here because we have requested
504
; a DMA transfer for the corresponding drive.
507
; a DMA transfer for the corresponding drive.
505
; However,
508
; However,
506
; a) we can be here because IDE IRQ is shared with some other device,
509
; a) we can be here because IDE IRQ is shared with some other device,
507
;    that device has actually raised IRQ,
510
;    that device has actually raised IRQ,
508
;    it has nothing to do with IDE;
511
;    it has nothing to do with IDE;
509
; b) we can be here because IDE controller just does not want
512
; b) we can be here because IDE controller just does not want
510
;    to be silent and reacts to something even though
513
;    to be silent and reacts to something even though
511
;    we have, in theory, disabled IRQs.
514
;    we have, in theory, disabled IRQs.
512
; If the interrupt corresponds to our current request,
515
; If the interrupt corresponds to our current request,
513
; remove the interrupt request and raise the event for the waiting code.
516
; remove the interrupt request and raise the event for the waiting code.
514
; In the case a), just return zero - not our interrupt.
517
; In the case a), just return zero - not our interrupt.
515
; In the case b), remove the interrupt request and hope for the best.
518
; In the case b), remove the interrupt request and hope for the best.
516
; DEBUGF 1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
519
; DEBUGF 1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
517
        mov     ecx, [esp+4]
520
        mov     ecx, [esp+4]
518
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
521
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
519
        add     edx, 2  ; Bus Master IDE Status register
522
        add     edx, 2  ; Bus Master IDE Status register
520
        in      al, dx
523
        in      al, dx
521
        test    al, 4
524
        test    al, 4
522
        jnz     .interrupt_from_primary
525
        jnz     .interrupt_from_primary
523
        add     edx, 8
526
        add     edx, 8
524
        in      al, dx
527
        in      al, dx
525
        test    al, 4
528
        test    al, 4
526
        jnz     .interrupt_from_secondary
529
        jnz     .interrupt_from_secondary
527
        xor     eax, eax ; not our interrupt
530
        xor     eax, eax ; not our interrupt
528
        ret
531
        ret
529
 
532
 
530
.interrupt_from_primary:
533
.interrupt_from_primary:
531
        out     dx, al  ; clear Interrupt bit
534
        out     dx, al  ; clear Interrupt bit
532
        sub     edx, 2
535
        sub     edx, 2
533
        xor     eax, eax
536
        xor     eax, eax
534
        out     dx, al  ; clear Bus Master IDE Command register
537
        out     dx, al  ; clear Bus Master IDE Command register
535
        mov     dx, [ecx+IDE_DATA.BAR0_val]
538
        mov     dx, [ecx+IDE_DATA.BAR0_val]
536
        add     edx, 7
539
        add     edx, 7
537
        in      al, dx  ; read status register
540
        in      al, dx  ; read status register
538
        cmp     [IDE_common_irq_param], 14
541
        cmp     [IDE_common_irq_param], 14
539
        jz      .raise
542
        jz      .raise
540
.exit_our:
543
.exit_our:
541
        mov     al, 1
544
        mov     al, 1
542
        ret
545
        ret
543
 
546
 
544
.interrupt_from_secondary:
547
.interrupt_from_secondary:
545
        out     dx, al  ; clear Interrupt bit
548
        out     dx, al  ; clear Interrupt bit
546
        sub     edx, 2
549
        sub     edx, 2
547
        xor     eax, eax
550
        xor     eax, eax
548
        out     dx, al  ; clear Bus Master IDE Command register
551
        out     dx, al  ; clear Bus Master IDE Command register
549
        mov     dx, [ecx+IDE_DATA.BAR2_val]
552
        mov     dx, [ecx+IDE_DATA.BAR2_val]
550
        add     edx, 7
553
        add     edx, 7
551
        in      al, dx  ; read status register
554
        in      al, dx  ; read status register
552
        cmp     [IDE_common_irq_param], 15
555
        cmp     [IDE_common_irq_param], 15
553
        jnz     .exit_our
556
        jnz     .exit_our
554
.raise:
557
.raise:
555
        cmp     ecx, [IDE_controller_pointer]
558
        cmp     ecx, [IDE_controller_pointer]
556
        jnz     .exit_our
559
        jnz     .exit_our
557
        pushad
560
        pushad
558
        mov     eax, [eventPointer]
561
        mov     eax, [eventPointer]
559
        mov     ebx, [eventID]
562
        mov     ebx, [eventID]
560
        xor     edx, edx
563
        xor     edx, edx
561
        xor     esi, esi
564
        xor     esi, esi
562
        call    raise_event
565
        call    raise_event
563
        popad
566
        popad
564
        mov     al, 1   ; remove the interrupt request
567
        mov     al, 1   ; remove the interrupt request
565
        ret
568
        ret