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

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

merged last NCQ related changes with Watcom related changes

File size: 11.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 _end_of_data ; end of all data (label)
20 PUBLIC _end_of_code ; end of all code (label)
21
22; ----------------------------------------------------------------------------
23; Device Driver Header
24
25DEVHDR SEGMENT WORD PUBLIC 'DATA'
26_dev_hdr dd -1 ; no headers after this one
27 dw DEVLEV_3 + DEV_CHAR_DEV ; flags for ADD drivers
28 dw _asm_strat ; strategy routine
29 dw 0 ; no IDC routine
30 db "OS2AHCI$" ; name of character device
31 dq 0 ; 8 reserved bytes
32 dd DEV_ADAPTER_DD + DEV_INITCOMPLETE + 20h ; ADD flags
33 dw 0
34DEVHDR ENDS
35
36; ----------------------------------------------------------------------------
37; Segment Definitions. We need to reference all segments here, even if they
38; are not used, to allow proper grouping of all segments into one group for
39; data and one group for code as well as proper ordering of the segments
40; within each group to make sure the end of segment markers are at the end
41; of each group.
42
43; On top of that, we need to make sure that the end of segment marker is in
44; a data segment of class 'BSS' because BSS segments are always put towards
45; the end of the executable when linking with high-level language objects
46; such as C.
47
48_DATA SEGMENT WORD PUBLIC 'DATA'
49readl_dbg_fmt db "readl(%04x:%04x) = 0x%08lx [addr %% 0x80 = 0x%02x]"
50 db 10, 0
51writel_dbg_fmt db "writel(%04x:%04x, 0x%08lx) [addr %% 0x80 = 0x%02x]"
52 db 10, 0
53_DATA ENDS
54
55CONST SEGMENT WORD PUBLIC 'CONST'
56CONST ENDS
57
58_BSS SEGMENT WORD PUBLIC 'BSS'
59_BSS ENDS
60
61c_common SEGMENT WORD PUBLIC 'BSS'
62 EXTRN _debug : WORD ; global debug flag
63c_common ENDS
64
65_z_data SEGMENT WORD PUBLIC 'BSS'
66_end_of_data db 0
67_z_data ENDS
68
69_TEXT SEGMENT WORD PUBLIC 'CODE'
70 EXTRN _c_strat : NEAR ; C strategy routine
71 EXTRN _printf : NEAR ; C printf routine
72 EXTRN _restart_ctxhook : NEAR ; C restart context hook
73 EXTRN _reset_ctxhook : NEAR ; C reset context hook
74 EXTRN _engine_ctxhook : NEAR ; C engine context hook
75_TEXT ENDS
76
77CODE SEGMENT WORD PUBLIC 'CODE'
78CODE ENDS
79
80RMCode SEGMENT WORD PUBLIC 'CODE'
81RMCode ENDS
82
83LIBCODE SEGMENT WORD PUBLIC 'CODE'
84LIBCODE ENDS
85
86_z_text SEGMENT WORD PUBLIC 'CODE'
87_end_of_code LABEL NEAR
88_z_text ENDS
89
90DGROUP GROUP DEVHDR, _DATA, CONST, _BSS, c_common, _z_data
91TGROUP GROUP _TEXT, CODE, _z_text
92
93; ----------------------------------------------------------------------------
94; Start of code
95
96_TEXT SEGMENT WORD PUBLIC 'CODE'
97 ASSUME DS:DGROUP
98 ASSUME ES:NOTHING
99 ASSUME SS:NOTHING
100
101
102; Device driver main entry point (strategy routine)
103_asm_strat PROC FAR
104
105 ; push request packet address
106 PUSH ES
107 PUSH BX
108 CLD
109
110 ; call C strategy routine
111 CALL _c_strat
112
113 POP BX
114 POP ES
115 MOV WORD PTR ES:[BX+3], AX
116 RET
117_asm_strat ENDP
118
119 .386
120
121
122; Read long value from MMIO address; need to do this here to get real
123; 32-bit operations because at least the AHCI device in VirtualBox doesn't
124; seem to support reading 32-bit MMIO registers in two 16-bit steps.
125;
126; C prototype: u32 readl(void _far *addr);
127_readl PROC NEAR
128 ENTER 0, 0
129
130 ; load 'addr' into ES:EAX
131 LES AX, [BP+4]
132 AND EAX, 0000FFFFh
133
134 ; read MMIO register into EDX and return it in DX:AX
135 MOV EDX, ES:[EAX]
136
137 ; print debug message if debug level is 3+
138 CMP _debug, 3
139 JB no_debug
140 PUSH EDX ; save value read from MMIO port
141 MOV BX, AX ; addr & 0x7f (port reg index)
142 AND BX, 7FH
143 PUSH BX
144 PUSH EDX ; value read from MMIO address
145 PUSH AX ; offset of MMIO address
146 PUSH ES ; segment of MMIO address
147 PUSH OFFSET readl_dbg_fmt
148 CALL _printf
149 ADD SP, 12
150 POP EDX ; restore value read from MMIO port
151
152no_debug: MOV EAX, EDX
153 SHR EDX, 16
154
155 LEAVE
156 RET
157_readl ENDP
158
159
160; Write long value to MMIO address; need to do this here to get real
161; 32-bit operations because at least the AHCI device in VirtualBox doesn't
162; seem to support reading 32-bit MMIO registers in two 16-bit steps and the
163; assumption is that this is the same with writing 32-bit MMIO registers.
164;
165; C prototype: void writel(void _far *addr, u32 val);
166_writel PROC NEAR
167 ENTER 0, 0
168
169 ; load 'addr' into ES:EAX
170 LES AX, [BP+4]
171 AND EAX, 0000FFFFh
172
173 ; load 'val' into EDX, preserving the upper 16 bits of EBP
174 MOV EBX, EBP
175 AND EBP, 0000FFFFh
176 MOV EDX, [EBP+8]
177 MOV EBP, EBX
178
179 ; store 'val' at MMIO address in ES:EAX
180 MOV DWORD PTR ES:[EAX], EDX
181
182 ; print debug message if debug level is 3+
183 CMP _debug, 3
184 JB no_debug2
185 MOV BX, AX ; addr & 0x7f (port reg index)
186 AND BX, 7FH
187 PUSH BX
188 PUSH EDX ; value written to MMIO address
189 PUSH AX ; offset of MMIO address
190 PUSH ES ; segment of MMIO address
191 PUSH OFFSET writel_dbg_fmt
192 CALL _printf
193 ADD SP, 12
194
195no_debug2: LEAVE
196 RET
197_writel ENDP
198
199
200; Halfway-decent 32-bit implementation of memset().
201;
202; C prototype: void *memset(void _far *s, int c, size_t n);
203_memset PROC NEAR
204 ENTER 0, 0
205
206 PUSH DI
207
208 ; load 's' into ES:EDI
209 LES DI, [BP+4]
210 AND EDI, 0000FFFFh
211
212 ; load 'c' into EAX, replicating the low 8 bits all over
213 MOV BL, [BP+8]
214 MOV BH, BL
215 MOV AX, BX
216 SHL EAX, 16
217 MOV AX, BX
218
219 ; load 'n / 4' into ECX
220 MOV CX, [BP+10]
221 SHR CX, 2
222 AND ECX, 0000FFFFh
223
224 ; fill 's' with 32-bit chunks of EAX
225 REP STOSD
226
227 ; set remaining bytes (n % 4)'
228 MOV CX, [BP+10]
229 AND CX, 0003h
230 REP STOSB
231
232 ; return address of 's'
233 LES AX, [BP+4]
234 PUSH ES
235 POP DX
236
237 POP DI
238
239 LEAVE
240 RET
241_memset ENDP
242
243
244; Halfway-decent 32-bit implementation of memcpy().
245;
246; C prototype: void *memcpy(void _far *d, void _far *s, size_t n);
247_memcpy PROC NEAR
248 ENTER 0, 0
249
250 INT 3
251
252 PUSH SI
253 PUSH DI
254 PUSH DS
255
256 ; load 'd' into ES:EDI
257 LES DI, [BP+4]
258 AND EDI, 0000FFFFh
259
260 ; load 's' into DS:ESI
261 LDS SI, [BP+8]
262 AND ESI, 0000FFFFh
263
264 ; load 'n / 4' into ECX
265 MOV CX, [BP+12]
266 SHR CX, 2
267 AND ECX, 0000FFFFh
268
269 ; copy 's' to 'd' in 32-bit chunks
270 REP MOVSD
271
272 ; copy remaining bytes (n % 4)'
273 MOV CX, [BP+12]
274 AND CX, 0003h
275 REP MOVSB
276
277 ; return address of 'd'
278 LES AX, [BP+4]
279 PUSH ES
280 POP DX
281
282 POP DS
283 POP DI
284 POP SI
285
286 LEAVE
287 RET
288_memcpy ENDP
289
290
291; Port restart context hook; context hooks need to save all registers
292; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
293; we need a stub which calls the real context hook.
294_restart_hook PROC FAR
295 PUSHAD
296 PUSH EAX
297 CALL _restart_ctxhook
298 POP EAX
299 POPAD
300 RET
301_restart_hook ENDP
302
303
304; Port reset context hook; context hooks need to save all registers
305; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
306; we need a stub which calls the real context hook.
307_reset_hook PROC FAR
308 PUSHAD
309 PUSH EAX
310 CALL _reset_ctxhook
311 POP EAX
312 POPAD
313 RET
314_reset_hook ENDP
315
316
317; Engine trigger context hook; context hooks need to save all registers
318; and get the parameter passed to DevHelp_ArmCtxHook() in EAX, thus
319; we need a stub which calls the real context hook.
320_engine_hook PROC FAR
321 PUSHAD
322 PUSH EAX
323 CALL _engine_ctxhook
324 POP EAX
325 POPAD
326 RET
327_engine_hook ENDP
328
329 .286
330
331_TEXT ENDS
332
333 END
334
Note: See TracBrowser for help on using the repository browser.