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

Last change on this file since 162 was 160, checked in by David Azarewicz, 12 years ago

fixed trap dump kernel exit, some work on suspend/resume routines

File size: 16.4 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; Constants
9 DEV_IDC EQU 0400h ; IDC bit for ADD flags
10
11; -----------------------------------------------------------------------------
12; Public symbols
13
14 PUBLIC _asm_strat ; low-level strategy routine
15 PUBLIC _asm_idc_entry ; low-level IDC entry point
16 PUBLIC _asm_krnl_exit ; low-level kernel exit routine
17 PUBLIC _readl ; MMIO read (32 bits)
18 PUBLIC _writel ; MMIO write (32 bits)
19 PUBLIC _memset ; C memset() implementation
20 PUBLIC _memcpy ; C memcpy() implementation
21 PUBLIC _restart_hook ; port restart context hook
22 PUBLIC _reset_hook ; port reset context hook
23 PUBLIC _engine_hook ; engine trigger context hook
24 PUBLIC _dev_hdr ; device driver header
25 PUBLIC __I4M ; 32bit signed multiply routine
26 PUBLIC __U4M ; 32bit unsigned multiply routine
27 PUBLIC __U4D ; 32bit unsigned divide routine
28 PUBLIC __I4D ; 32bit signed divide routine
29 PUBLIC _end_of_data ; end of all data (label)
30 PUBLIC _end_of_code ; end of all code (label)
31 PUBLIC _udelay ; spin for microseconds
32 EXTRN DOSIODELAYCNT:ABS
33
34; ----------------------------------------------------------------------------
35; Device Driver Header
36
37DEVHDR SEGMENT WORD PUBLIC 'DATA'
38_dev_hdr dd _next_hdr ; next device header
39 dw DEVLEV_3 + DEV_CHAR_DEV + DEV_IDC ; flags for ADD drivers
40 dw OFFSET _asm_strat ; strategy routine
41 dw OFFSET _asm_idc_entry ; IDC entry point
42 db "OS2AHCI$" ; name of character device
43 dq 0 ; 8 reserved bytes
44 dd DEV_IOCTL2 + DEV_ADAPTER_DD + DEV_INITCOMPLETE + DEV_SAVERESTORE ; ADD flags
45 dw 0
46
47if 1
48; This is here to support old SMART tools. This is a really bad thing to do as it will
49; cause problems in the future. The SMART tools should be fixed instead.
50_next_hdr dd -1 ; no headers after this one
51 dw DEVLEV_3 + DEV_CHAR_DEV ; flags for ADD drivers
52 dw OFFSET _asm_strat ; strategy routine
53 dw 0 ; IDC entry point
54 db "IBMS506$" ; name of character device
55 dq 0 ; 8 reserved bytes
56 dd 0
57 dw 0
58else
59_next_hdr equ -1
60endif
61
62DEVHDR ENDS
63
64; ----------------------------------------------------------------------------
65; Segment Definitions. We need to reference all segments here, even if they
66; are not used, to allow proper grouping of all segments into one group for
67; data and one group for code as well as proper ordering of the segments
68; within each group to make sure the end of segment markers are at the end
69; of each group.
70
71; On top of that, we need to make sure that the end of segment marker is in
72; a data segment of class 'BSS' because BSS segments are always put towards
73; the end of the executable when linking with high-level language objects
74; such as C.
75
76; When using the Watcom Linker, the segment ordering can be overridden in
77; the Watcom Makefile (wmakefile) where the Linker response-file is generated
78; containing statements for segment ordering. First you can order by class and
79; for each class you can specify the order of the segments within that class.
80; See the ORDER directive in the wlink documentation.
81_DATA SEGMENT WORD PUBLIC 'DATA'
82readl_dbg_fmt db "readl(%04x:%04x) = 0x%08lx"
83 db 10, 0
84writel_dbg_fmt db "writel(%04x:%04x, 0x%08lx)"
85 db 10, 0
86_DATA ENDS
87
88LIBDATA SEGMENT WORD PUBLIC 'DATA'
89LIBDATA ENDS
90
91CONST SEGMENT WORD PUBLIC 'CONST'
92CONST ENDS
93
94_BSS SEGMENT WORD PUBLIC 'BSS'
95_BSS ENDS
96
97c_common SEGMENT WORD PUBLIC 'BSS'
98 EXTRN _debug : WORD ; global debug flag
99c_common ENDS
100
101_z_data SEGMENT WORD PUBLIC 'BSS'
102_end_of_data db ?
103_z_data ENDS
104
105_TEXT SEGMENT WORD PUBLIC 'CODE'
106 EXTRN _c_strat : NEAR ; C strategy routine
107 EXTRN _printf : NEAR ; C printf routine
108 EXTRN _restart_ctxhook : NEAR ; C restart context hook
109 EXTRN _reset_ctxhook : NEAR ; C reset context hook
110 EXTRN _engine_ctxhook : NEAR ; C engine context hook
111 EXTRN _shutdown_driver : NEAR ; C routine for INT13 IO enable
112_TEXT ENDS
113
114CODE SEGMENT WORD PUBLIC 'CODE'
115CODE ENDS
116
117LIBCODE SEGMENT WORD PUBLIC 'CODE'
118LIBCODE ENDS
119
120RMCode SEGMENT WORD PUBLIC 'CODE'
121RMCode ENDS
122
123_z_text SEGMENT WORD PUBLIC 'CODE'
124_end_of_code LABEL NEAR
125_z_text ENDS
126
127
128; The Watcom Linker behaves differently than the IBM/MS Linkers when segments
129; are defined but not added to the corresponding group. So when you define a
130; a new (logical) segment and want it to be part of a physical segment (group)
131; then don't forget to add it below or unresolvable or miscalculated
132; relocations can be the result.
133DGROUP GROUP DEVHDR, _DATA, LIBDATA, _BSS, c_common, _z_data
134TGROUP GROUP _TEXT, CODE, LIBCODE, RMCode, _z_text
135
136 .386
137
138; ----------------------------------------------------------------------------
139; Start of code
140
141_TEXT SEGMENT WORD PUBLIC 'CODE'
142 ASSUME DS:DGROUP
143 ASSUME ES:NOTHING
144 ASSUME SS:NOTHING
145
146
147; Device driver main entry point (strategy routine)
148_asm_strat PROC FAR
149
150 ; push request packet address
151 PUSH ES
152 PUSH BX
153 CLD
154
155 ; call C strategy routine
156 CALL _c_strat
157
158 POP BX
159 POP ES
160 MOV WORD PTR ES:[BX+3], AX
161 RET
162_asm_strat ENDP
163
164
165; IDC entry point (Assembler stub)
166_asm_idc_entry PROC FAR
167
168 ; push request packet address
169 PUSH ES
170 PUSH BX
171 CLD
172
173 ; call C IDC entry point - which is the strategy routine
174 CALL _c_strat
175
176 POP BX
177 POP ES
178 MOV WORD PTR ES:[BX+3], AX
179 RET
180_asm_idc_entry ENDP
181
182; Kernel exit routine to enable INT13 I/O (called before a trap dump occurrs)
183_asm_krnl_exit PROC FAR
184 PUSH ES
185 PUSH DS
186 MOV AX,DGROUP
187 MOV DS,AX
188 CLD
189
190 ; call C routine
191 CALL _shutdown_driver
192
193 POP DS
194 POP ES
195
196 RET
197_asm_krnl_exit ENDP
198
199
200 .386
201
202; void udelay(u16 microseconds);
203_udelay PROC NEAR
204 enter 0, 0
205 mov cx, word ptr [bp+4]
206@OuterLoop:
207 mov ax, DOSIODELAYCNT
208 shl ax, 1
209@InnerLoop:
210 dec ax
211 jnz short @InnerLoop
212 loop @OuterLoop
213
214 leave
215 ret
216_udelay ENDP
217
218; Read long value from MMIO address; need to do this here to get real
219; 32-bit operations because at least the AHCI device in VirtualBox doesn't
220; seem to support reading 32-bit MMIO registers in two 16-bit steps.
221;
222; C prototype: u32 readl(void _far *addr);
223_readl PROC NEAR
224 ENTER 0, 0
225
226 ; load 'addr' into ES:EAX
227 LES AX, [BP+4]
228 AND EAX, 0000FFFFh
229
230 ; read MMIO register into EDX and return it in DX:AX
231 MOV EDX, ES:[EAX]
232
233 ; print debug message if debug level is 3+
234 CMP _debug, 3
235 JB no_debug
236 PUSH EDX ; save value read from MMIO port
237 PUSH EDX ; value read from MMIO address
238 PUSH AX ; offset of MMIO address
239 PUSH ES ; segment of MMIO address
240 PUSH OFFSET readl_dbg_fmt
241 CALL _printf
242 ADD SP, 10
243 POP EDX ; restore value read from MMIO port
244
245no_debug: MOV EAX, EDX
246 SHR EDX, 16
247
248 LEAVE
249 RET
250_readl ENDP
251
252
253; Write long value to MMIO address; need to do this here to get real
254; 32-bit operations because at least the AHCI device in VirtualBox doesn't
255; seem to support reading 32-bit MMIO registers in two 16-bit steps and the
256; assumption is that this is the same with writing 32-bit MMIO registers.
257;
258; C prototype: void writel(void _far *addr, u32 val);
259_writel PROC NEAR
260 ENTER 0, 0
261
262 ; load 'addr' into ES:EAX
263 LES AX, [BP+4]
264 AND EAX, 0000FFFFh
265
266 ; load 'val' into EDX, preserving the upper 16 bits of EBP
267 MOV EBX, EBP
268 AND EBP, 0000FFFFh
269 MOV EDX, [EBP+8]
270 MOV EBP, EBX
271
272 ; store 'val' at MMIO address in ES:EAX
273 MOV DWORD PTR ES:[EAX], EDX
274
275 ; print debug message if debug level is 3+
276 CMP _debug, 3
277 JB no_debug2
278 PUSH EDX ; value written to MMIO address
279 PUSH AX ; offset of MMIO address
280 PUSH ES ; segment of MMIO address
281 PUSH OFFSET writel_dbg_fmt
282 CALL _printf
283 ADD SP, 10
284
285no_debug2: LEAVE
286 RET
287_writel ENDP
288
289
290; Halfway-decent 32-bit implementation of memset().
291;
292; C prototype: void *memset(void _far *s, int c, size_t n);
293_memset PROC NEAR
294 ENTER 0, 0
295
296 PUSH DI
297
298 ; load 's' into ES:EDI
299 LES DI, [BP+4]
300 AND EDI, 0000FFFFh
301
302 ; load 'c' into EAX, replicating the low 8 bits all over
303 MOV BL, [BP+8]
304 MOV BH, BL
305 MOV AX, BX
306 SHL EAX, 16
307 MOV AX, BX
308
309 ; load 'n / 4' into ECX
310 MOV CX, [BP+10]
311 SHR CX, 2
312 AND ECX, 0000FFFFh
313
314 ; fill 's' with 32-bit chunks of EAX
315 REP STOSD
316
317 ; set remaining bytes (n % 4)'
318 MOV CX, [BP+10]
319 AND CX, 0003h
320 REP STOSB
321
322 ; return address of 's'
323 LES AX, [BP+4]
324 PUSH ES
325 POP DX
326
327 POP DI
328
329 LEAVE
330 RET
331_memset ENDP
332
333
334; Halfway-decent 32-bit implementation of memcpy().
335;
336; C prototype: void *memcpy(void _far *d, void _far *s, size_t n);
337_memcpy PROC NEAR
338 ENTER 0, 0
339
340 PUSH SI
341 PUSH DI
342 PUSH DS
343
344 ; load 'd' into ES:EDI
345 LES DI, [BP+4]
346 AND EDI, 0000FFFFh
347
348 ; load 's' into DS:ESI
349 LDS SI, [BP+8]
350 AND ESI, 0000FFFFh
351
352 ; load 'n / 4' into ECX
353 MOV CX, [BP+12]
354 SHR CX, 2
355 AND ECX, 0000FFFFh
356
357 ; copy 's' to 'd' in 32-bit chunks
358 REP MOVSD
359
360 ; copy remaining bytes (n % 4)'
361 MOV CX, [BP+12]
362 AND CX, 0003h
363 REP MOVSB
364
365 ; return address of 'd'
366 LES AX, [BP+4]
367 PUSH ES
368 POP DX
369
370 POP DS
371 POP DI
372 POP SI
373
374 LEAVE
375 RET
376_memcpy ENDP
377
378
379; Port restart context hook; context hooks need to save all registers
380; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
381; we need a stub which calls the real context hook.
382_restart_hook PROC FAR
383 PUSHAD
384 PUSH EAX
385 CALL _restart_ctxhook
386 POP EAX
387 POPAD
388 RET
389_restart_hook ENDP
390
391
392; Port reset context hook; context hooks need to save all registers
393; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
394; we need a stub which calls the real context hook.
395_reset_hook PROC FAR
396 PUSHAD
397 PUSH EAX
398 CALL _reset_ctxhook
399 POP EAX
400 POPAD
401 RET
402_reset_hook ENDP
403
404
405; Engine trigger context hook; context hooks need to save all registers
406; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
407; we need a stub which calls the real context hook.
408_engine_hook PROC FAR
409 PUSHAD
410 PUSH EAX
411 CALL _engine_ctxhook
412 POP EAX
413 POPAD
414 RET
415_engine_hook ENDP
416
417
418; Unsigned long divide routine;
419; taken from OS/2 Uniaud project, original author: Timur Tabi
420__U4D proc near
421 shl edx,10h ;; Load dx:ax into eax
422 mov dx,ax
423 mov eax,edx
424 xor edx,edx ;; Zero extend eax into edx
425 shl ecx,10h ;; Load cx:bx into ecx
426 mov cx,bx
427 div ecx ;; Divide eax/ecx into eax
428 mov ecx,edx ;; Load edx into cx:bx
429 shr ecx,10h
430 mov bx,dx
431 mov edx,eax ;; Load eax into dx:ax
432 shr edx,10h
433 ret
434__U4D endp
435
436; Long multiply routine;
437; taken from OS/2 Uniaud project, original author: Timur Tabi
438__U4M proc near
439__I4M label near
440 shl edx,10h ;; Load dx:ax into eax
441 mov dx,ax
442 mov eax,edx
443 mov dx,cx ;; Load cx:bx into edx
444 shl edx,10h
445 mov dx,bx
446 mul edx ;; Multiply eax*edx into edx:eax
447 mov edx,eax ;; Load eax into dx:ax
448 shr edx,10h
449 ret
450__U4M endp
451
452
453; Signed long divide routine;
454; taken from OS/2 Uniaud project, original author: Timur Tabi
455__I4D proc near
456 shl edx,10h ;; Load dx:ax into eax
457 mov dx,ax
458 mov eax,edx
459 cdq ;; Sign extend eax into edx
460 shl ecx,10h ;; Load cx:bx into ecx
461 mov cx,bx
462 idiv ecx ;; Divide eax/ecx into eax
463 mov ecx,edx ;; Load edx into cx:bx
464 shr ecx,10h
465 mov bx,dx
466 mov edx,eax ;; Load eax into dx:ax
467 shr edx,10h
468 ret
469__I4D endp
470
471_TEXT ENDS
472
473 END
474
Note: See TracBrowser for help on using the repository browser.