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