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

Last change on this file since 16 was 16, checked in by markus, 15 years ago

Changed wmakefile to use link.exe and alp.exe (Assembler) from DDK, now it compiles.

File size: 14.1 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 multiply 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_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 [addr %% 0x80 = 0x%02x]"
54 db 10, 0
55writel_dbg_fmt db "writel(%04x:%04x, 0x%08lx) [addr %% 0x80 = 0x%02x]"
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 MOV BX, AX ; addr & 0x7f (port reg index)
146 AND BX, 7FH
147 PUSH BX
148 PUSH EDX ; value read from MMIO address
149 PUSH AX ; offset of MMIO address
150 PUSH ES ; segment of MMIO address
151 PUSH OFFSET readl_dbg_fmt
152 CALL _printf
153 ADD SP, 12
154 POP EDX ; restore value read from MMIO port
155
156no_debug: MOV EAX, EDX
157 SHR EDX, 16
158
159 LEAVE
160 RET
161_readl ENDP
162
163
164; Write long value to MMIO address; need to do this here to get real
165; 32-bit operations because at least the AHCI device in VirtualBox doesn't
166; seem to support reading 32-bit MMIO registers in two 16-bit steps and the
167; assumption is that this is the same with writing 32-bit MMIO registers.
168;
169; C prototype: void writel(void _far *addr, u32 val);
170_writel PROC NEAR
171 ENTER 0, 0
172
173 ; load 'addr' into ES:EAX
174 LES AX, [BP+4]
175 AND EAX, 0000FFFFh
176
177 ; load 'val' into EDX, preserving the upper 16 bits of EBP
178 MOV EBX, EBP
179 AND EBP, 0000FFFFh
180 MOV EDX, [EBP+8]
181 MOV EBP, EBX
182
183 ; store 'val' at MMIO address in ES:EAX
184 MOV DWORD PTR ES:[EAX], EDX
185
186 ; print debug message if debug level is 3+
187 CMP _debug, 3
188 JB no_debug2
189 MOV BX, AX ; addr & 0x7f (port reg index)
190 AND BX, 7FH
191 PUSH BX
192 PUSH EDX ; value written to MMIO address
193 PUSH AX ; offset of MMIO address
194 PUSH ES ; segment of MMIO address
195 PUSH OFFSET writel_dbg_fmt
196 CALL _printf
197 ADD SP, 12
198
199no_debug2: LEAVE
200 RET
201_writel ENDP
202
203
204; Halfway-decent 32-bit implementation of memset().
205;
206; C prototype: void *memset(void _far *s, int c, size_t n);
207_memset PROC NEAR
208 ENTER 0, 0
209
210 PUSH DI
211
212 ; load 's' into ES:EDI
213 LES DI, [BP+4]
214 AND EDI, 0000FFFFh
215
216 ; load 'c' into EAX, replicating the low 8 bits all over
217 MOV BL, [BP+8]
218 MOV BH, BL
219 MOV AX, BX
220 SHL EAX, 16
221 MOV AX, BX
222
223 ; load 'n / 4' into ECX
224 MOV CX, [BP+10]
225 SHR CX, 2
226 AND ECX, 0000FFFFh
227
228 ; fill 's' with 32-bit chunks of EAX
229 REP STOSD
230
231 ; set remaining bytes (n % 4)'
232 MOV CX, [BP+10]
233 AND CX, 0003h
234 REP STOSB
235
236 ; return address of 's'
237 LES AX, [BP+4]
238 PUSH ES
239 POP DX
240
241 POP DI
242
243 LEAVE
244 RET
245_memset ENDP
246
247
248; Halfway-decent 32-bit implementation of memcpy().
249;
250; C prototype: void *memcpy(void _far *d, void _far *s, size_t n);
251_memcpy PROC NEAR
252 ENTER 0, 0
253
254 INT 3
255
256 PUSH SI
257 PUSH DI
258 PUSH DS
259
260 ; load 'd' into ES:EDI
261 LES DI, [BP+4]
262 AND EDI, 0000FFFFh
263
264 ; load 's' into DS:ESI
265 LDS SI, [BP+8]
266 AND ESI, 0000FFFFh
267
268 ; load 'n / 4' into ECX
269 MOV CX, [BP+12]
270 SHR CX, 2
271 AND ECX, 0000FFFFh
272
273 ; copy 's' to 'd' in 32-bit chunks
274 REP MOVSD
275
276 ; copy remaining bytes (n % 4)'
277 MOV CX, [BP+12]
278 AND CX, 0003h
279 REP MOVSB
280
281 ; return address of 'd'
282 LES AX, [BP+4]
283 PUSH ES
284 POP DX
285
286 POP DS
287 POP DI
288 POP SI
289
290 LEAVE
291 RET
292_memcpy ENDP
293
294
295; Port restart context hook; context hooks need to save all registers
296; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
297; we need a stub which calls the real context hook.
298_restart_hook PROC FAR
299 PUSHAD
300 PUSH EAX
301 CALL _restart_ctxhook
302 POP EAX
303 POPAD
304 RET
305_restart_hook ENDP
306
307
308; Port reset context hook; context hooks need to save all registers
309; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
310; we need a stub which calls the real context hook.
311_reset_hook PROC FAR
312 PUSHAD
313 PUSH EAX
314 CALL _reset_ctxhook
315 POP EAX
316 POPAD
317 RET
318_reset_hook ENDP
319
320
321; Engine trigger context hook; context hooks need to save all registers
322; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
323; we need a stub which calls the real context hook.
324_engine_hook PROC FAR
325 PUSHAD
326 PUSH EAX
327 CALL _engine_ctxhook
328 POP EAX
329 POPAD
330 RET
331_engine_hook ENDP
332
333
334; Unsigned long divide routine;
335; taken from OS/2 Uniaud project, original author: Timur Tabi
336__U4D proc near
337 shl edx,10h ;; Load dx:ax into eax
338 mov dx,ax
339 mov eax,edx
340 xor edx,edx ;; Zero extend eax into edx
341 shl ecx,10h ;; Load cx:bx into ecx
342 mov cx,bx
343 div ecx ;; Divide eax/ecx into eax
344 mov ecx,edx ;; Load edx into cx:bx
345 shr ecx,10h
346 mov bx,dx
347 mov edx,eax ;; Load eax into dx:ax
348 shr edx,10h
349 ret
350__U4D endp
351
352; Long multiply routine;
353; taken from OS/2 Uniaud project, original author: Timur Tabi
354__U4M proc near
355 shl edx,10h ;; Load dx:ax into eax
356 mov dx,ax
357 mov eax,edx
358 mov dx,cx ;; Load cx:bx into edx
359 shl edx,10h
360 mov dx,bx
361 mul edx ;; Multiply eax*edx into edx:eax
362 mov edx,eax ;; Load eax into dx:ax
363 shr edx,10h
364 ret
365__U4M endp
366
367__I4M proc near
368 shl edx,10h ;; Load dx:ax into eax
369 mov dx,ax
370 mov eax,edx
371 mov dx,cx ;; Load cx:bx into edx
372 shl edx,10h
373 mov dx,bx
374 mul edx ;; Multiply eax*edx into edx:eax
375 mov edx,eax ;; Load eax into dx:ax
376 shr edx,10h
377 ret
378__I4M endp
379
380
381; Signed long divide routine;
382; taken from OS/2 Uniaud project, original author: Timur Tabi
383__I4D proc near
384 shl edx,10h ;; Load dx:ax into eax
385 mov dx,ax
386 mov eax,edx
387 cdq ;; Sign extend eax into edx
388 shl ecx,10h ;; Load cx:bx into ecx
389 mov cx,bx
390 idiv ecx ;; Divide eax/ecx into eax
391 mov ecx,edx ;; Load edx into cx:bx
392 shr ecx,10h
393 mov bx,dx
394 mov edx,eax ;; Load eax into dx:ax
395 shr edx,10h
396 ret
397__I4D endp
398
399 .286
400
401_TEXT ENDS
402
403 END
404
Note: See TracBrowser for help on using the repository browser.