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 |