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