source: trunk/src/os2ahci/init.asm@ 79

Last change on this file since 79 was 79, checked in by chris, 14 years ago
  • fixed debug print code in readl/writel (stack offset after printf() call was wrong after I removed the port offset token a few weeks ago and this was never tested)
  • added some logic to prevent PCI devices from being detected twice -- first by a thorough scan and then again by a class-based scan
  • still not working on ICH8 notebook; already found out that a port reset is required for this particular hardware (Dell D630) but the boot process is still hanging...
File size: 13.3 KB
Line 
1; ----------------------------------------------------------------------------
2; Initialization routines and segment mappings for os2ahci driver, plus
3; some low-level functions that were implemented in assembler
4
5include devhdr.inc
6
7; -----------------------------------------------------------------------------
8; Public symbols
9
10 PUBLIC _asm_strat ; low-level strategy routine
11 PUBLIC _readl ; MMIO read (32 bits)
12 PUBLIC _writel ; MMIO write (32 bits)
13 PUBLIC _memset ; C memset() implementation
14 PUBLIC _memcpy ; C memcpy() implementation
15 PUBLIC _restart_hook ; port restart context hook
16 PUBLIC _reset_hook ; port reset context hook
17 PUBLIC _engine_hook ; engine trigger context hook
18 PUBLIC _dev_hdr ; device driver header
19 PUBLIC __I4M ; 32bit signed multiply routine
20 PUBLIC __U4M ; 32bit unsigned multiply routine
21 PUBLIC __U4D ; 32bit unsigned divide routine
22 PUBLIC __I4D ; 32bit signed divide routine
23 PUBLIC _end_of_data ; end of all data (label)
24 PUBLIC _end_of_code ; end of all code (label)
25
26; ----------------------------------------------------------------------------
27; Device Driver Header
28
29DEVHDR SEGMENT WORD PUBLIC 'DATA'
30_dev_hdr dd -1 ; no headers after this one
31 dw DEVLEV_3 + DEV_CHAR_DEV ; flags for ADD drivers
32 dw _asm_strat ; strategy routine
33 dw 0 ; no IDC routine
34 db "OS2AHCI$" ; name of character device
35 dq 0 ; 8 reserved bytes
36 dd DEV_IOCTL2 + DEV_ADAPTER_DD + DEV_INITCOMPLETE + 20h ; ADD flags
37 dw 0
38DEVHDR ENDS
39
40; ----------------------------------------------------------------------------
41; Segment Definitions. We need to reference all segments here, even if they
42; are not used, to allow proper grouping of all segments into one group for
43; data and one group for code as well as proper ordering of the segments
44; within each group to make sure the end of segment markers are at the end
45; of each group.
46
47; On top of that, we need to make sure that the end of segment marker is in
48; a data segment of class 'BSS' because BSS segments are always put towards
49; the end of the executable when linking with high-level language objects
50; such as C.
51
52_DATA SEGMENT WORD PUBLIC 'DATA'
53readl_dbg_fmt db "readl(%04x:%04x) = 0x%08lx"
54 db 10, 0
55writel_dbg_fmt db "writel(%04x:%04x, 0x%08lx)"
56 db 10, 0
57_DATA ENDS
58
59CONST SEGMENT WORD PUBLIC 'CONST'
60CONST ENDS
61
62_BSS SEGMENT WORD PUBLIC 'BSS'
63_BSS ENDS
64
65c_common SEGMENT WORD PUBLIC 'BSS'
66 EXTRN _debug : WORD ; global debug flag
67c_common ENDS
68
69_z_data SEGMENT WORD PUBLIC 'BSS'
70_end_of_data db 0
71_z_data ENDS
72
73_TEXT SEGMENT WORD PUBLIC 'CODE'
74 EXTRN _c_strat : NEAR ; C strategy routine
75 EXTRN _printf : NEAR ; C printf routine
76 EXTRN _restart_ctxhook : NEAR ; C restart context hook
77 EXTRN _reset_ctxhook : NEAR ; C reset context hook
78 EXTRN _engine_ctxhook : NEAR ; C engine context hook
79_TEXT ENDS
80
81CODE SEGMENT WORD PUBLIC 'CODE'
82CODE ENDS
83
84RMCode SEGMENT WORD PUBLIC 'CODE'
85RMCode ENDS
86
87LIBCODE SEGMENT WORD PUBLIC 'CODE'
88LIBCODE ENDS
89
90_z_text SEGMENT WORD PUBLIC 'CODE'
91_end_of_code LABEL NEAR
92_z_text ENDS
93
94DGROUP GROUP DEVHDR, _DATA, CONST, _BSS, c_common, _z_data
95TGROUP GROUP _TEXT, CODE, _z_text
96
97; ----------------------------------------------------------------------------
98; Start of code
99
100_TEXT SEGMENT WORD PUBLIC 'CODE'
101 ASSUME DS:DGROUP
102 ASSUME ES:NOTHING
103 ASSUME SS:NOTHING
104
105
106; Device driver main entry point (strategy routine)
107_asm_strat PROC FAR
108
109 ; push request packet address
110 PUSH ES
111 PUSH BX
112 CLD
113
114 ; call C strategy routine
115 CALL _c_strat
116
117 POP BX
118 POP ES
119 MOV WORD PTR ES:[BX+3], AX
120 RET
121_asm_strat ENDP
122
123 .386
124
125
126; Read long value from MMIO address; need to do this here to get real
127; 32-bit operations because at least the AHCI device in VirtualBox doesn't
128; seem to support reading 32-bit MMIO registers in two 16-bit steps.
129;
130; C prototype: u32 readl(void _far *addr);
131_readl PROC NEAR
132 ENTER 0, 0
133
134 ; load 'addr' into ES:EAX
135 LES AX, [BP+4]
136 AND EAX, 0000FFFFh
137
138 ; read MMIO register into EDX and return it in DX:AX
139 MOV EDX, ES:[EAX]
140
141 ; print debug message if debug level is 3+
142 CMP _debug, 3
143 JB no_debug
144 PUSH EDX ; save value read from MMIO port
145 PUSH EDX ; value read from MMIO address
146 PUSH AX ; offset of MMIO address
147 PUSH ES ; segment of MMIO address
148 PUSH OFFSET readl_dbg_fmt
149 CALL _printf
150 ADD SP, 10
151 POP EDX ; restore value read from MMIO port
152
153no_debug: MOV EAX, EDX
154 SHR EDX, 16
155
156 LEAVE
157 RET
158_readl ENDP
159
160
161; Write long value to MMIO address; need to do this here to get real
162; 32-bit operations because at least the AHCI device in VirtualBox doesn't
163; seem to support reading 32-bit MMIO registers in two 16-bit steps and the
164; assumption is that this is the same with writing 32-bit MMIO registers.
165;
166; C prototype: void writel(void _far *addr, u32 val);
167_writel PROC NEAR
168 ENTER 0, 0
169
170 ; load 'addr' into ES:EAX
171 LES AX, [BP+4]
172 AND EAX, 0000FFFFh
173
174 ; load 'val' into EDX, preserving the upper 16 bits of EBP
175 MOV EBX, EBP
176 AND EBP, 0000FFFFh
177 MOV EDX, [EBP+8]
178 MOV EBP, EBX
179
180 ; store 'val' at MMIO address in ES:EAX
181 MOV DWORD PTR ES:[EAX], EDX
182
183 ; print debug message if debug level is 3+
184 CMP _debug, 3
185 JB no_debug2
186 PUSH EDX ; value written to MMIO address
187 PUSH AX ; offset of MMIO address
188 PUSH ES ; segment of MMIO address
189 PUSH OFFSET writel_dbg_fmt
190 CALL _printf
191 ADD SP, 10
192
193no_debug2: LEAVE
194 RET
195_writel ENDP
196
197
198; Halfway-decent 32-bit implementation of memset().
199;
200; C prototype: void *memset(void _far *s, int c, size_t n);
201_memset PROC NEAR
202 ENTER 0, 0
203
204 PUSH DI
205
206 ; load 's' into ES:EDI
207 LES DI, [BP+4]
208 AND EDI, 0000FFFFh
209
210 ; load 'c' into EAX, replicating the low 8 bits all over
211 MOV BL, [BP+8]
212 MOV BH, BL
213 MOV AX, BX
214 SHL EAX, 16
215 MOV AX, BX
216
217 ; load 'n / 4' into ECX
218 MOV CX, [BP+10]
219 SHR CX, 2
220 AND ECX, 0000FFFFh
221
222 ; fill 's' with 32-bit chunks of EAX
223 REP STOSD
224
225 ; set remaining bytes (n % 4)'
226 MOV CX, [BP+10]
227 AND CX, 0003h
228 REP STOSB
229
230 ; return address of 's'
231 LES AX, [BP+4]
232 PUSH ES
233 POP DX
234
235 POP DI
236
237 LEAVE
238 RET
239_memset ENDP
240
241
242; Halfway-decent 32-bit implementation of memcpy().
243;
244; C prototype: void *memcpy(void _far *d, void _far *s, size_t n);
245_memcpy PROC NEAR
246 ENTER 0, 0
247
248 PUSH SI
249 PUSH DI
250 PUSH DS
251
252 ; load 'd' into ES:EDI
253 LES DI, [BP+4]
254 AND EDI, 0000FFFFh
255
256 ; load 's' into DS:ESI
257 LDS SI, [BP+8]
258 AND ESI, 0000FFFFh
259
260 ; load 'n / 4' into ECX
261 MOV CX, [BP+12]
262 SHR CX, 2
263 AND ECX, 0000FFFFh
264
265 ; copy 's' to 'd' in 32-bit chunks
266 REP MOVSD
267
268 ; copy remaining bytes (n % 4)'
269 MOV CX, [BP+12]
270 AND CX, 0003h
271 REP MOVSB
272
273 ; return address of 'd'
274 LES AX, [BP+4]
275 PUSH ES
276 POP DX
277
278 POP DS
279 POP DI
280 POP SI
281
282 LEAVE
283 RET
284_memcpy ENDP
285
286
287; Port restart context hook; context hooks need to save all registers
288; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
289; we need a stub which calls the real context hook.
290_restart_hook PROC FAR
291 PUSHAD
292 PUSH EAX
293 CALL _restart_ctxhook
294 POP EAX
295 POPAD
296 RET
297_restart_hook ENDP
298
299
300; Port reset context hook; context hooks need to save all registers
301; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
302; we need a stub which calls the real context hook.
303_reset_hook PROC FAR
304 PUSHAD
305 PUSH EAX
306 CALL _reset_ctxhook
307 POP EAX
308 POPAD
309 RET
310_reset_hook ENDP
311
312
313; Engine trigger context hook; context hooks need to save all registers
314; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
315; we need a stub which calls the real context hook.
316_engine_hook PROC FAR
317 PUSHAD
318 PUSH EAX
319 CALL _engine_ctxhook
320 POP EAX
321 POPAD
322 RET
323_engine_hook ENDP
324
325
326; Unsigned long divide routine;
327; taken from OS/2 Uniaud project, original author: Timur Tabi
328__U4D proc near
329 shl edx,10h ;; Load dx:ax into eax
330 mov dx,ax
331 mov eax,edx
332 xor edx,edx ;; Zero extend eax into edx
333 shl ecx,10h ;; Load cx:bx into ecx
334 mov cx,bx
335 div ecx ;; Divide eax/ecx into eax
336 mov ecx,edx ;; Load edx into cx:bx
337 shr ecx,10h
338 mov bx,dx
339 mov edx,eax ;; Load eax into dx:ax
340 shr edx,10h
341 ret
342__U4D endp
343
344; Long multiply routine;
345; taken from OS/2 Uniaud project, original author: Timur Tabi
346__U4M proc near
347__I4M label near
348 shl edx,10h ;; Load dx:ax into eax
349 mov dx,ax
350 mov eax,edx
351 mov dx,cx ;; Load cx:bx into edx
352 shl edx,10h
353 mov dx,bx
354 mul edx ;; Multiply eax*edx into edx:eax
355 mov edx,eax ;; Load eax into dx:ax
356 shr edx,10h
357 ret
358__U4M endp
359
360
361; Signed long divide routine;
362; taken from OS/2 Uniaud project, original author: Timur Tabi
363__I4D proc near
364 shl edx,10h ;; Load dx:ax into eax
365 mov dx,ax
366 mov eax,edx
367 cdq ;; Sign extend eax into edx
368 shl ecx,10h ;; Load cx:bx into ecx
369 mov cx,bx
370 idiv ecx ;; Divide eax/ecx into eax
371 mov ecx,edx ;; Load edx into cx:bx
372 shr ecx,10h
373 mov bx,dx
374 mov edx,eax ;; Load eax into dx:ax
375 shr edx,10h
376 ret
377__I4D endp
378
379 .286
380
381_TEXT ENDS
382
383 END
384
Note: See TracBrowser for help on using the repository browser.