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

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