~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/VBox/HostDrivers/Support/os2/SUPDrvA-os2.asm

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
; $Id: SUPDrvA-os2.asm 1197 2007-03-04 20:58:39Z vboxsync $
 
2
;; @file
 
3
; VBoxDrv - OS/2 assembly file, the first file in the link.
 
4
;
 
5
 
 
6
;
 
7
; Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
 
8
;
 
9
; Permission is hereby granted, free of charge, to any person
 
10
; obtaining a copy of this software and associated documentation
 
11
; files (the "Software"), to deal in the Software without
 
12
; restriction, including without limitation the rights to use,
 
13
; copy, modify, merge, publish, distribute, sublicense, and/or sell
 
14
; copies of the Software, and to permit persons to whom the
 
15
; Software is furnished to do so, subject to the following
 
16
; conditions:
 
17
;
 
18
; The above copyright notice and this permission notice shall be
 
19
; included in all copies or substantial portions of the Software.
 
20
;
 
21
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
22
; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 
23
; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
24
; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 
25
; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
26
; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
27
; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
28
; OTHER DEALINGS IN THE SOFTWARE.
 
29
;
 
30
 
 
31
 
 
32
;*******************************************************************************
 
33
;* Header Files                                                                *
 
34
;*******************************************************************************
 
35
%define RT_INCL_16BIT_SEGMENTS
 
36
%include "iprt/asmdefs.mac"
 
37
 
 
38
 
 
39
;*******************************************************************************
 
40
;* Structures and Typedefs                                                     *
 
41
;*******************************************************************************
 
42
;;
 
43
; Request packet header.
 
44
struc PKTHDR
 
45
    .cb     resb 1
 
46
    .unit   resb 1
 
47
    .cmd    resb 1
 
48
    .status resw 1
 
49
    .res1   resd 1
 
50
    .link   resd 1
 
51
endstruc
 
52
 
 
53
 
 
54
;;
 
55
; Init request packet - input.
 
56
struc PKTINITIN
 
57
    .cb     resb 1
 
58
    .unit   resb 1
 
59
    .cmd    resb 1
 
60
    .status resw 1
 
61
    .res1   resd 1
 
62
    .link   resd 1
 
63
 
 
64
    .data_1 resb 1
 
65
    .fpfnDevHlp resd 1
 
66
    .fpszArgs   resd 1
 
67
    .data_2 resb 1
 
68
endstruc
 
69
 
 
70
;;
 
71
; Init request packet - output.
 
72
struc PKTINITOUT
 
73
    .cb     resb 1
 
74
    .unit   resb 1
 
75
    .cmd    resb 1
 
76
    .status resw 1
 
77
    .res1   resd 1
 
78
    .link   resd 1
 
79
 
 
80
    .cUnits resb 1                      ; block devs only.
 
81
    .cbCode16 resw 1
 
82
    .cbData16 resw 1
 
83
    .fpaBPBs  resd 1                    ; block devs only.
 
84
    .data_2 resb 1
 
85
endstruc
 
86
 
 
87
;;
 
88
; Open request packet.
 
89
struc PKTOPEN
 
90
    .cb     resb 1
 
91
    .unit   resb 1
 
92
    .cmd    resb 1
 
93
    .status resw 1
 
94
    .res1   resd 1
 
95
    .link   resd 1
 
96
    .sfn    resw 1
 
97
endstruc
 
98
 
 
99
;;
 
100
; Close request packet.
 
101
struc PKTCLOSE
 
102
    .cb     resb 1
 
103
    .unit   resb 1
 
104
    .cmd    resb 1
 
105
    .status resw 1
 
106
    .res1   resd 1
 
107
    .link   resd 1
 
108
    .sfn    resw 1
 
109
endstruc
 
110
 
 
111
;;
 
112
; IOCtl request packet.
 
113
struc PKTIOCTL
 
114
    .cb     resb 1
 
115
    .unit   resb 1
 
116
    .cmd    resb 1
 
117
    .status resw 1
 
118
    .res1   resd 1
 
119
    .link   resd 1
 
120
 
 
121
    .cat    resb 1
 
122
    .fun    resb 1
 
123
    .pParm  resd 1
 
124
    .pData  resd 1
 
125
    .sfn    resw 1
 
126
    .cbParm resw 1
 
127
    .cbData resw 1
 
128
endstruc
 
129
 
 
130
;;
 
131
; Read/Write request packet
 
132
struc PKTRW
 
133
    .cb     resb 1
 
134
    .unit   resb 1
 
135
    .cmd    resb 1
 
136
    .status resw 1
 
137
    .res1   resd 1
 
138
    .link   resd 1
 
139
 
 
140
    .media  resb 1
 
141
    .PhysTrans resd 1
 
142
    .cbTrans resw 1
 
143
    .start  resd 1
 
144
    .sfn    resw 1
 
145
endstruc
 
146
 
 
147
 
 
148
 
 
149
;;
 
150
; The two device headers.
 
151
segment DATA16
 
152
 
 
153
; Some devhdr.inc stuff.
 
154
%define DEVLEV_3                0180h
 
155
%define DEV_30                  0800h
 
156
%define DEV_CHAR_DEV            8000h
 
157
%define DEV_16MB                0002h
 
158
%define DEV_IOCTL2              0001h
 
159
 
 
160
; Some dhcalls.h stuff.
 
161
%define DevHlp_VirtToLin        05bh
 
162
%define DevHlp_SAVE_MESSAGE     03dh
 
163
%define DevHlp_PhysToVirt       015h
 
164
 
 
165
; Fast IOCtl category, also defined in SUPDRVIOC.h
 
166
%define SUP_CTL_CATEGORY_FAST   0c1h
 
167
 
 
168
 
 
169
;*******************************************************************************
 
170
;* External Symbols                                                            *
 
171
;*******************************************************************************
 
172
extern KernThunkStackTo32
 
173
extern KernThunkStackTo16
 
174
extern DOS16OPEN
 
175
extern DOS16CLOSE
 
176
extern DOS16WRITE
 
177
extern NAME(VBoxDrvInit)
 
178
extern NAME(VBoxDrvOpen)
 
179
extern NAME(VBoxDrvClose)
 
180
extern NAME(VBoxDrvIOCtl)
 
181
extern NAME(VBoxDrvIOCtlFast)
 
182
 
 
183
 
 
184
;;
 
185
; Device headers. The first one is the one we'll be opening and the
 
186
; latter is only used for 32-bit initialization.
 
187
GLOBALNAME g_VBoxDrvHdr1
 
188
    dw  NAME(g_VBoxDrvHdr2) wrt DATA16  ; NextHeader.off
 
189
    dw  DATA16                          ; NextHeader.sel
 
190
    dw  DEVLEV_3 | DEV_30 | DEV_CHAR_DEV; SDevAtt
 
191
    dw  NAME(VBoxDrvEP) wrt CODE16      ; StrategyEP
 
192
    dw  0                               ; InterruptEP
 
193
    db  'vboxdrv$'                      ; DevName
 
194
    dw  0                               ; SDevProtCS
 
195
    dw  0                               ; SDevProtDS
 
196
    dw  0                               ; SDevRealCS
 
197
    dw  0                               ; SDevRealDS
 
198
    dd  DEV_16MB | DEV_IOCTL2           ; SDevCaps
 
199
 
 
200
align 4
 
201
GLOBALNAME g_VBoxDrvHdr2
 
202
    dd  0ffffffffh                      ; NextHeader (NIL)
 
203
    dw  DEVLEV_3 | DEV_30 | DEV_CHAR_DEV; SDevAtt
 
204
    dw  NAME(VBoxDrvInitEP) wrt CODE16  ; StrategyEP
 
205
    dw  0                               ; InterruptEP
 
206
    db  'vboxdr1$'                      ; DevName
 
207
    dw  0                               ; SDevProtCS
 
208
    dw  0                               ; SDevProtDS
 
209
    dw  0                               ; SDevRealCS
 
210
    dw  0                               ; SDevRealDS
 
211
    dd  DEV_16MB | DEV_IOCTL2           ; SDevCaps
 
212
 
 
213
 
 
214
;; Tristate 32-bit initialization indicator [0 = need init, -1 = init failed, 1 init succeeded].
 
215
; Check in the open path of the primary driver. The secondary driver will
 
216
; open the primary one during it's init and thereby trigger the 32-bit init.
 
217
GLOBALNAME g_fInitialized
 
218
    db 0
 
219
 
 
220
align 4
 
221
;; Pointer to the device helper service routine
 
222
; This is set during the initialization of the 2nd device driver.
 
223
GLOBALNAME g_fpfnDevHlp
 
224
    dd 0
 
225
 
 
226
 
 
227
;; Where we write to the log.
 
228
GLOBALNAME g_offLogHead
 
229
    dw 0
 
230
;; Where we read from the log.
 
231
GLOBALNAME g_offLogTail
 
232
    dw 0
 
233
;; The size of the log. (power of two!)
 
234
%define LOG_SIZE 16384
 
235
GLOBALNAME g_cchLogMax
 
236
    dw LOG_SIZE
 
237
;; The log buffer.
 
238
GLOBALNAME g_szLog
 
239
    times LOG_SIZE db 0
 
240
 
 
241
 
 
242
;
 
243
; The init data.
 
244
;
 
245
segment DATA16_INIT
 
246
GLOBALNAME g_InitDataStart
 
247
 
 
248
;; Far pointer to the device argument.
 
249
g_fpszArgs:
 
250
    dd      0
 
251
 
 
252
%if 0
 
253
;; Message table for the Save_Message device helper.
 
254
GLOBALNAME g_MsgTab
 
255
    dw  1178                                        ; MsgId - 'MSG_REPLACEMENT_STRING'.
 
256
    dw  1                                           ; cMsgStrings
 
257
    dw  NAME(g_szInitText)                          ; MsgStrings[0]
 
258
    dw  seg NAME(g_szInitText)
 
259
%else
 
260
;; Far pointer to DOS16WRITE (corrected set before called).
 
261
; Just a temporary hack to work around a wlink issue.
 
262
GLOBALNAME g_fpfnDos16Write
 
263
    dw  DOS16WRITE
 
264
    dw  seg DOS16WRITE
 
265
%endif
 
266
 
 
267
;; Size of the text currently in the g_szInitText buffer.
 
268
GLOBALNAME g_cchInitText
 
269
    dw      0
 
270
;; The max size of text that can fit into the g_szInitText buffer.
 
271
GLOBALNAME g_cchInitTextMax
 
272
    dw      512
 
273
;; The init text buffer.
 
274
GLOBALNAME g_szInitText
 
275
    times 512 db 0
 
276
 
 
277
;
 
278
; The 16-bit code segment.
 
279
;
 
280
segment CODE16
 
281
 
 
282
 
 
283
;;
 
284
; The strategy entry point (vboxdrv$).
 
285
;
 
286
; ss:bx -> request packet
 
287
; ds:si -> device header
 
288
;
 
289
; Can clobber any registers it likes except SP.
 
290
;
 
291
BEGINPROC VBoxDrvEP
 
292
    push    ebp
 
293
    mov     ebp, esp
 
294
    push    es                                      ; bp - 2
 
295
    push    bx                                      ; bp - 4
 
296
    and     sp, 0fffch
 
297
 
 
298
    ;
 
299
    ; Check for the most frequent first.
 
300
    ;
 
301
    cmp     byte [es:bx + PKTHDR.cmd], 10h          ; Generic IOCtl
 
302
    jne near VBoxDrvEP_NotGenIOCtl
 
303
 
 
304
 
 
305
    ;
 
306
    ; Generic I/O Control Request.
 
307
    ;
 
308
VBoxDrvEP_GenIOCtl:
 
309
 
 
310
    ; Fast IOCtl?
 
311
    cmp     byte [es:bx + PKTIOCTL.cat], SUP_CTL_CATEGORY_FAST
 
312
    jne     VBoxDrvEP_GenIOCtl_Other
 
313
 
 
314
    ;
 
315
    ; Fast IOCtl.
 
316
    ;   DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction, uint16_t *pcbParm)
 
317
    ;
 
318
VBoxDrvEP_GenIOCtl_Fast:
 
319
    mov     ax, [es:bx + PKTIOCTL.pData + 2]        ; LDT selector to flat address.
 
320
    shr     ax, 3
 
321
    shl     eax, 16
 
322
    mov     ax, [es:bx + PKTIOCTL.pData]
 
323
    push    eax                                     ; 08h - pointer to the rc buffer.
 
324
 
 
325
    ; function.
 
326
    movzx   edx, byte [es:bx + PKTIOCTL.fun]
 
327
    push    edx                                     ; 04h
 
328
 
 
329
    ; system file number.
 
330
    movzx   eax, word [es:bx + PKTIOCTL.sfn]
 
331
    push    eax                                     ; 00h
 
332
 
 
333
    ; go to the 32-bit code
 
334
    ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Fast_32) wrt FLAT
 
335
    db      066h
 
336
    db      0eah
 
337
    dd      NAME(VBoxDrvEP_GenIOCtl_Fast_32) ;wrt FLAT
 
338
    dw      TEXT32 wrt FLAT
 
339
segment TEXT32
 
340
GLOBALNAME VBoxDrvEP_GenIOCtl_Fast_32
 
341
 
 
342
    ; switch stack to 32-bit.
 
343
    mov     ax, DATA32 wrt FLAT
 
344
    mov     ds, ax
 
345
    mov     es, ax
 
346
    call    KernThunkStackTo32
 
347
 
 
348
    ; call the C code (don't cleanup the stack).
 
349
    call    NAME(VBoxDrvIOCtlFast)
 
350
 
 
351
    ; switch back the stack.
 
352
    push    eax
 
353
    call    KernThunkStackTo16
 
354
    pop     eax
 
355
 
 
356
    ; jump back to the 16-bit code.
 
357
    ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Fast_16) wrt CODE16
 
358
    db      066h
 
359
    db      0eah
 
360
    dw      NAME(VBoxDrvEP_GenIOCtl_Fast_16) wrt CODE16
 
361
    dw      CODE16
 
362
segment CODE16
 
363
GLOBALNAME VBoxDrvEP_GenIOCtl_Fast_16
 
364
    les     bx, [bp - 4]                            ; Reload the packet pointer.
 
365
    or      eax, eax
 
366
    jnz near VBoxDrvEP_GeneralFailure
 
367
 
 
368
    ; setup output stuff.
 
369
    mov     edx, esp
 
370
    mov     eax, [ss:edx + 0ch]                     ; output sizes.
 
371
    mov     [es:bx + PKTIOCTL.cbParm], eax          ; update cbParm and cbData.
 
372
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
373
 
 
374
    mov     sp, bp
 
375
    pop     ebp
 
376
    retf
 
377
 
 
378
    ;
 
379
    ; Other IOCtl (slow)
 
380
    ;
 
381
VBoxDrvEP_GenIOCtl_Other:
 
382
    mov     eax, [es:bx +  PKTIOCTL.cbParm]         ; Load cbParm and cbData
 
383
    push    eax                                     ; 1eh - in/out data size.
 
384
                                                    ; 1ch - in/out parameter size.
 
385
    push    edx                                     ; 18h - pointer to data size (filled in later).
 
386
    push    ecx                                     ; 14h - pointer to param size (filled in later).
 
387
 
 
388
    ; pData (convert to flat 32-bit)
 
389
    mov     ax,  word [es:bx + PKTIOCTL.pData + 2]  ; selector
 
390
    cmp     ax, 3                                   ; <= 3 -> nil selector...
 
391
    jbe     .no_data
 
392
    movzx   esi, word [es:bx + PKTIOCTL.pData]      ; offset
 
393
    mov     dl, DevHlp_VirtToLin
 
394
    call far [NAME(g_fpfnDevHlp)]
 
395
    jc near VBoxDrvEP_GeneralFailure
 
396
    jmp     .finish_data
 
397
.no_data:
 
398
    xor     eax, eax
 
399
.finish_data:
 
400
    push    eax                                     ; 10h
 
401
 
 
402
    ; pParm (convert to flat 32-bit)
 
403
    mov     ax,  word [es:bx + PKTIOCTL.pParm + 2]  ; selector
 
404
    cmp     ax, 3                                   ; <= 3 -> nil selector...
 
405
    jbe     .no_parm
 
406
    movzx   esi, word [es:bx + PKTIOCTL.pParm]      ; offset
 
407
    mov     dl, DevHlp_VirtToLin
 
408
    call far [NAME(g_fpfnDevHlp)]
 
409
    jc near VBoxDrvEP_GeneralFailure
 
410
    jmp     .finish_parm
 
411
.no_parm:
 
412
    xor     eax, eax
 
413
.finish_parm:
 
414
    push    eax                                     ; 0ch
 
415
 
 
416
    ; function.
 
417
    movzx   edx, byte [es:bx + PKTIOCTL.fun]
 
418
    push    edx                                     ; 08h
 
419
 
 
420
    ; category.
 
421
    movzx   ecx, byte [es:bx + PKTIOCTL.cat]
 
422
    push    ecx                                     ; 04h
 
423
 
 
424
    ; system file number.
 
425
    movzx   eax, word [es:bx + PKTIOCTL.sfn]
 
426
    push    eax                                     ; 00h
 
427
 
 
428
    ; go to the 32-bit code
 
429
    ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Other_32) wrt FLAT
 
430
    db      066h
 
431
    db      0eah
 
432
    dd      NAME(VBoxDrvEP_GenIOCtl_Other_32) ;wrt FLAT
 
433
    dw      TEXT32 wrt FLAT
 
434
segment TEXT32
 
435
GLOBALNAME VBoxDrvEP_GenIOCtl_Other_32
 
436
 
 
437
    ; switch stack to 32-bit.
 
438
    mov     ax, DATA32 wrt FLAT
 
439
    mov     ds, ax
 
440
    mov     es, ax
 
441
    call    KernThunkStackTo32
 
442
 
 
443
    ; update in/out parameter pointers
 
444
    lea     eax, [esp + 1ch]
 
445
    mov     [esp + 14h], eax
 
446
    lea     edx, [esp + 1eh]
 
447
    mov     [esp + 18h], edx
 
448
 
 
449
    ; call the C code (don't cleanup the stack).
 
450
    call    NAME(VBoxDrvIOCtl)
 
451
 
 
452
    ; switch back the stack.
 
453
    push    eax
 
454
    call    KernThunkStackTo16
 
455
    pop     eax
 
456
 
 
457
    ; jump back to the 16-bit code.
 
458
    ;jmp far dword NAME(VBoxDrvEP_GenIOCtl_Other_16) wrt CODE16
 
459
    db      066h
 
460
    db      0eah
 
461
    dw      NAME(VBoxDrvEP_GenIOCtl_Other_16) wrt CODE16
 
462
    dw      CODE16
 
463
segment CODE16
 
464
GLOBALNAME VBoxDrvEP_GenIOCtl_Other_16
 
465
    les     bx, [bp - 4]                            ; Reload the packet pointer.
 
466
    or      eax, eax
 
467
    jnz near VBoxDrvEP_GeneralFailure
 
468
 
 
469
    ; setup output stuff.
 
470
    mov     edx, esp
 
471
    mov     eax, [ss:edx + 1ch]                     ; output sizes.
 
472
    mov     [es:bx + PKTIOCTL.cbParm], eax          ; update cbParm and cbData.
 
473
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
474
 
 
475
    mov     sp, bp
 
476
    pop     ebp
 
477
    retf
 
478
 
 
479
 
 
480
    ;
 
481
    ; Less Performance Critical Requests.
 
482
    ;
 
483
VBoxDrvEP_NotGenIOCtl:
 
484
    cmp     byte [es:bx + PKTHDR.cmd], 0dh          ; Open
 
485
    je      VBoxDrvEP_Open
 
486
    cmp     byte [es:bx + PKTHDR.cmd], 0eh          ; Close
 
487
    je      VBoxDrvEP_Close
 
488
    cmp     byte [es:bx + PKTHDR.cmd], 00h          ; Init
 
489
    je      VBoxDrvEP_Init
 
490
    cmp     byte [es:bx + PKTHDR.cmd], 04h          ; Read
 
491
    je near VBoxDrvEP_Read
 
492
    jmp near VBoxDrvEP_NotSupported
 
493
 
 
494
 
 
495
    ;
 
496
    ; Open Request. w/ ring-0 init.
 
497
    ;
 
498
VBoxDrvEP_Open:
 
499
    cmp     byte [NAME(g_fInitialized)], 1
 
500
    jne     VBoxDrvEP_OpenOther
 
501
 
 
502
    ; First argument, the system file number.
 
503
    movzx   eax, word [es:bx + PKTOPEN.sfn]
 
504
    push    eax
 
505
 
 
506
    ; go to the 32-bit code
 
507
    ;jmp far dword NAME(VBoxDrvEP_Open_32) wrt FLAT
 
508
    db      066h
 
509
    db      0eah
 
510
    dd      NAME(VBoxDrvEP_Open_32) ;wrt FLAT
 
511
    dw      TEXT32 wrt FLAT
 
512
segment TEXT32
 
513
GLOBALNAME VBoxDrvEP_Open_32
 
514
 
 
515
    ; switch stack to 32-bit.
 
516
    mov     ax, DATA32 wrt FLAT
 
517
    mov     ds, ax
 
518
    mov     es, ax
 
519
    call    KernThunkStackTo32
 
520
 
 
521
    ; call the C code.
 
522
    call    NAME(VBoxDrvOpen)
 
523
 
 
524
    ; switch back the stack.
 
525
    push    eax
 
526
    call    KernThunkStackTo16
 
527
    pop     eax
 
528
 
 
529
    ; jump back to the 16-bit code.
 
530
    ;jmp far dword NAME(VBoxDrvEP_Open_32) wrt CODE16
 
531
    db      066h
 
532
    db      0eah
 
533
    dw      NAME(VBoxDrvEP_Open_16) wrt CODE16
 
534
    dw      CODE16
 
535
segment CODE16
 
536
GLOBALNAME VBoxDrvEP_Open_16
 
537
    les     bx, [bp - 4]                            ; Reload the packet pointer.
 
538
    or      eax, eax
 
539
    jnz near VBoxDrvEP_GeneralFailure
 
540
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
541
    jmp near VBoxDrvEP_Done
 
542
 
 
543
    ; Initializing or failed init?
 
544
VBoxDrvEP_OpenOther:
 
545
    cmp     byte [NAME(g_fInitialized)], 0
 
546
    jne     VBoxDrvEP_OpenFailed
 
547
 
 
548
    mov     byte [NAME(g_fInitialized)], -1
 
549
    call    NAME(VBoxDrvRing0Init)
 
550
    cmp     byte [NAME(g_fInitialized)], 1
 
551
    je      VBoxDrvEP_Open
 
552
 
 
553
VBoxDrvEP_OpenFailed:
 
554
    mov     word [es:bx + PKTHDR.status], 0810fh    ; error, done, init failed.
 
555
    jmp near VBoxDrvEP_Done
 
556
 
 
557
 
 
558
    ;
 
559
    ; Close Request.
 
560
    ;
 
561
VBoxDrvEP_Close:
 
562
    ; First argument, the system file number.
 
563
    movzx   eax, word [es:bx + PKTOPEN.sfn]
 
564
    push    eax
 
565
 
 
566
    ; go to the 32-bit code
 
567
    ;jmp far dword NAME(VBoxDrvEP_Close_32) wrt FLAT
 
568
    db      066h
 
569
    db      0eah
 
570
    dd      NAME(VBoxDrvEP_Close_32) ;wrt FLAT
 
571
    dw      TEXT32 wrt FLAT
 
572
segment TEXT32
 
573
GLOBALNAME VBoxDrvEP_Close_32
 
574
 
 
575
    ; switch stack to 32-bit.
 
576
    mov     ax, DATA32 wrt FLAT
 
577
    mov     ds, ax
 
578
    mov     es, ax
 
579
    call    KernThunkStackTo32
 
580
 
 
581
    ; call the C code.
 
582
    call    NAME(VBoxDrvClose)
 
583
 
 
584
    ; switch back the stack.
 
585
    push    eax
 
586
    call    KernThunkStackTo16
 
587
    pop     eax
 
588
 
 
589
    ; jump back to the 16-bit code.
 
590
    ;jmp far dword NAME(VBoxDrvEP_Close_32) wrt CODE16
 
591
    db      066h
 
592
    db      0eah
 
593
    dw      NAME(VBoxDrvEP_Close_16) wrt CODE16
 
594
    dw      CODE16
 
595
segment CODE16
 
596
GLOBALNAME VBoxDrvEP_Close_16
 
597
    les     bx, [bp - 4]                            ; Reload the packet pointer.
 
598
    or      eax, eax
 
599
    jnz near VBoxDrvEP_GeneralFailure
 
600
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
601
    jmp near VBoxDrvEP_Done
 
602
 
 
603
 
 
604
    ;
 
605
    ; Init Request.
 
606
    ; The other driver header will do this.
 
607
    ;
 
608
VBoxDrvEP_Init:
 
609
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
610
    mov     byte [es:bx + PKTINITOUT.cUnits], 0
 
611
    mov     word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16
 
612
    mov     word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16
 
613
    mov     dword [es:bx + PKTINITOUT.fpaBPBs], 0
 
614
    jmp near VBoxDrvEP_Done
 
615
 
 
616
 
 
617
    ;
 
618
    ; Read Request.
 
619
    ; Return log data.
 
620
    ;
 
621
VBoxDrvEP_Read:
 
622
    ; Any log data available?
 
623
    xor     dx, dx
 
624
    mov     ax, [NAME(g_offLogTail)]
 
625
    cmp     ax, [NAME(g_offLogHead)]
 
626
    jz near .log_done
 
627
 
 
628
    ; create a temporary mapping of the physical buffer. Docs claims it trashes nearly everything...
 
629
    push    ebp
 
630
    mov     cx, [es:bx + PKTRW.cbTrans]
 
631
    push    cx
 
632
    mov     ax, [es:bx + PKTRW.PhysTrans + 2]
 
633
    mov     bx, [es:bx + PKTRW.PhysTrans]
 
634
    mov     dh, 1
 
635
    mov     dl, DevHlp_PhysToVirt
 
636
    call far [NAME(g_fpfnDevHlp)]
 
637
    pop     bx                                      ; bx = cbTrans
 
638
    pop     ebp
 
639
    jc near .log_phystovirt_failed
 
640
                                                    ; es:di -> the output buffer.
 
641
 
 
642
    ; setup the copy operation.
 
643
    mov     ax, [NAME(g_offLogTail)]
 
644
    xor     dx, dx                                  ; dx tracks the number of bytes copied.
 
645
.log_loop:
 
646
    mov     cx, [NAME(g_offLogHead)]
 
647
    cmp     ax, cx
 
648
    je      .log_done
 
649
    jb      .log_loop_before
 
650
    mov     cx, LOG_SIZE
 
651
.log_loop_before:                                   ; cx = end offset
 
652
    sub     cx, ax                                  ; cx = sequential bytes to copy.
 
653
    cmp     cx, bx
 
654
    jbe     .log_loop_min
 
655
    mov     cx, bx                                  ; output buffer is smaller than available data.
 
656
.log_loop_min:
 
657
    mov     si, NAME(g_szLog)
 
658
    add     si, ax                                  ; ds:si -> the log buffer.
 
659
    add     dx, cx                                  ; update output counter
 
660
    add     ax, cx                                  ; calc new offLogTail
 
661
    and     ax, LOG_SIZE - 1
 
662
    rep movsb                                       ; do the copy
 
663
    mov     [NAME(g_offLogTail)], ax                ; commit the read.
 
664
    jmp     .log_loop
 
665
 
 
666
.log_done:
 
667
    les     bx, [bp - 4]                            ; Reload the packet pointer.
 
668
    mov     word [es:bx + PKTRW.cbTrans], dx
 
669
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
670
    jmp near VBoxDrvEP_Done
 
671
 
 
672
.log_phystovirt_failed:
 
673
    les     bx, [bp - 4]                            ; Reload the packet pointer.
 
674
    jmp     VBoxDrvEP_GeneralFailure
 
675
 
 
676
 
 
677
    ;
 
678
    ; Return 'unknown command' error.
 
679
    ;
 
680
VBoxDrvEP_NotSupported:
 
681
    mov     word [es:bx + PKTHDR.status], 08103h    ; error, done, unknown command.
 
682
    jmp     VBoxDrvEP_Done
 
683
 
 
684
    ;
 
685
    ; Return 'general failure' error.
 
686
    ;
 
687
VBoxDrvEP_GeneralFailure:
 
688
    mov     word [es:bx + PKTHDR.status], 0810ch    ; error, done, general failure.
 
689
    jmp     VBoxDrvEP_Done
 
690
 
 
691
    ;
 
692
    ; Non-optimized return path.
 
693
    ;
 
694
VBoxDrvEP_Done:
 
695
    mov     sp, bp
 
696
    pop     ebp
 
697
    retf
 
698
ENDPROC VBoxDrvEP
 
699
 
 
700
 
 
701
;;
 
702
; The helper device entry point.
 
703
;
 
704
; This is only used to do the DosOpen on the main driver so we can
 
705
; do ring-3 init and report failures.
 
706
;
 
707
GLOBALNAME VBoxDrvInitEP
 
708
    ; The only request we're servicing is the 'init' one.
 
709
    cmp     word [es:bx + PKTHDR.cmd], 0
 
710
    je near NAME(VBoxDrvInitEPServiceInitReq)
 
711
 
 
712
    ; Ok, it's not the init request, just fail it.
 
713
    mov     word [es:bx + PKTHDR.status], 08103h    ; error, done, unknown command.
 
714
    retf
 
715
 
 
716
 
 
717
;
 
718
; The 16-bit init code.
 
719
;
 
720
segment CODE16_INIT
 
721
GLOBALNAME g_InitCodeStart
 
722
 
 
723
;; The device name for DosOpen.
 
724
g_szDeviceName:
 
725
    db  '\DEV\vboxdrv$', 0
 
726
 
 
727
; icsdebug can't see where stuff starts otherwise. (kDevTest)
 
728
int3
 
729
int3
 
730
int3
 
731
int3
 
732
int3
 
733
int3
 
734
 
 
735
;;
 
736
; The Ring-3 init code.
 
737
;
 
738
BEGINPROC VBoxDrvInitEPServiceInitReq
 
739
    push    ebp
 
740
    mov     ebp, esp
 
741
    push    es                                      ; bp - 2
 
742
    push    sp                                      ; bp - 4
 
743
    push    -1                                      ; bp - 6: hfOpen
 
744
    push    0                                       ; bp - 8: usAction
 
745
    and     sp, 0fffch
 
746
 
 
747
    ; check for the init package.
 
748
    cmp     word [es:bx + PKTHDR.cmd], 0
 
749
    jne near .not_init
 
750
 
 
751
    ;
 
752
    ; Copy the data out of the init packet.
 
753
    ;
 
754
    mov     eax, [es:bx + PKTINITIN.fpfnDevHlp]
 
755
    mov     [NAME(g_fpfnDevHlp)], eax
 
756
    mov     edx, [es:bx + PKTINITIN.fpszArgs]
 
757
    mov     [g_fpszArgs], edx
 
758
 
 
759
    ;
 
760
    ; Open the first driver, close it, and check status.
 
761
    ;
 
762
 
 
763
    ; APIRET _Pascal DosOpen(PSZ pszFname, PHFILE phfOpen, PUSHORT pusAction,
 
764
    ;                        ULONG ulFSize, USHORT usAttr, USHORT fsOpenFlags,
 
765
    ;                        USHORT fsOpenMode, ULONG ulReserved);
 
766
    push    seg g_szDeviceName                      ; pszFname
 
767
    push    g_szDeviceName
 
768
    push    ss                                      ; phfOpen
 
769
    lea     dx, [bp - 6]
 
770
    push    dx
 
771
    push    ss                                      ; pusAction
 
772
    lea     dx, [bp - 8]
 
773
    push    dx
 
774
    push    dword 0                                 ; ulFSize
 
775
    push    0                                       ; usAttr = FILE_NORMAL
 
776
    push    1                                       ; fsOpenFlags = FILE_OPEN
 
777
    push    00040h                                  ; fsOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY
 
778
    push    dword 0                                 ; ulReserved
 
779
    call far DOS16OPEN
 
780
 
 
781
    push    ax                                      ; Quickly flush any text.
 
782
    call    NAME(VBoxDrvInitFlushText)
 
783
    pop     ax
 
784
 
 
785
    or      ax, ax
 
786
    jnz     .done_err
 
787
 
 
788
    ; APIRET  APIENTRY DosClose(HFILE hf);
 
789
    mov     cx, [bp - 6]
 
790
    push    cx
 
791
    call far DOS16CLOSE
 
792
    or      ax, ax
 
793
    jnz     .done_err                               ; This can't happen (I hope).
 
794
 
 
795
    ;
 
796
    ; Ok, we're good.
 
797
    ;
 
798
    mov     word [es:bx + PKTHDR.status], 00100h    ; done, ok.
 
799
    mov     byte [es:bx + PKTINITOUT.cUnits], 0
 
800
    mov     word [es:bx + PKTINITOUT.cbCode16], NAME(g_InitCodeStart) wrt CODE16
 
801
    mov     word [es:bx + PKTINITOUT.cbData16], NAME(g_InitDataStart) wrt DATA16
 
802
    mov     dword [es:bx + PKTINITOUT.fpaBPBs], 0
 
803
    jmp     .done
 
804
 
 
805
    ;
 
806
    ; Init failure.
 
807
    ;
 
808
.done_err:
 
809
    mov     word [es:bx + PKTHDR.status], 0810fh    ; error, done, init failed.
 
810
    mov     byte [es:bx + PKTINITOUT.cUnits], 0
 
811
    mov     word [es:bx + PKTINITOUT.cbCode16], 0
 
812
    mov     word [es:bx + PKTINITOUT.cbData16], 0
 
813
    mov     dword [es:bx + PKTINITOUT.fpaBPBs], 0
 
814
    jmp     .done
 
815
 
 
816
    ;
 
817
    ; Not init, return 'unknown command'.
 
818
    ;
 
819
.not_init:
 
820
    mov     word [es:bx + PKTHDR.status], 08103h    ; error, done, unknown command.
 
821
    jmp     .done
 
822
 
 
823
    ;
 
824
    ; Request done.
 
825
    ;
 
826
.done:
 
827
    mov     sp, bp
 
828
    pop     ebp
 
829
    retf
 
830
ENDPROC VBoxDrvInitEPServiceInitReq
 
831
 
 
832
 
 
833
;;
 
834
; The Ring-0 init code.
 
835
;
 
836
BEGINPROC VBoxDrvRing0Init
 
837
    push    es
 
838
    push    esi
 
839
    push    ebp
 
840
    mov     ebp, esp
 
841
    and     sp, 0fffch
 
842
 
 
843
    ;
 
844
    ; Thunk the argument string pointer first.
 
845
    ;
 
846
    movzx   esi, word [g_fpszArgs]                  ; offset
 
847
    mov     ax, [g_fpszArgs + 2]                    ; selector
 
848
    mov     dl, DevHlp_VirtToLin
 
849
    call far [NAME(g_fpfnDevHlp)]
 
850
    jc near VBoxDrvRing0Init_done                   ; eax is non-zero on failure (can't happen)
 
851
    push    eax                                     ; 00h - pszArgs (for VBoxDrvInit).
 
852
 
 
853
    ;
 
854
    ; Do 16-bit init?
 
855
    ;
 
856
 
 
857
 
 
858
    ;
 
859
    ; Do 32-bit init
 
860
    ;
 
861
    ;jmp far dword NAME(VBoxDrvRing0Init_32) wrt FLAT
 
862
    db      066h
 
863
    db      0eah
 
864
    dd      NAME(VBoxDrvRing0Init_32) ;wrt FLAT
 
865
    dw      TEXT32 wrt FLAT
 
866
segment TEXT32
 
867
GLOBALNAME VBoxDrvRing0Init_32
 
868
 
 
869
    ; switch stack to 32-bit.
 
870
    mov     ax, DATA32 wrt FLAT
 
871
    mov     ds, ax
 
872
    mov     es, ax
 
873
    call    KernThunkStackTo32
 
874
 
 
875
    ; call the C code.
 
876
    call    NAME(VBoxDrvInit)
 
877
 
 
878
    ; switch back the stack and reload ds.
 
879
    push    eax
 
880
    call    KernThunkStackTo16
 
881
    pop     eax
 
882
 
 
883
    mov     dx, seg NAME(g_fInitialized)
 
884
    mov     ds, dx
 
885
 
 
886
    ; jump back to the 16-bit code.
 
887
    ;jmp far dword NAME(VBoxDrvRing0Init_16) wrt CODE16
 
888
    db      066h
 
889
    db      0eah
 
890
    dw      NAME(VBoxDrvRing0Init_16) wrt CODE16
 
891
    dw      CODE16_INIT
 
892
segment CODE16_INIT
 
893
GLOBALNAME VBoxDrvRing0Init_16
 
894
 
 
895
    ; check the result and set g_fInitialized on success.
 
896
    or      eax, eax
 
897
    jnz     VBoxDrvRing0Init_done
 
898
    mov     byte [NAME(g_fInitialized)], 1
 
899
 
 
900
VBoxDrvRing0Init_done:
 
901
    mov     sp, bp
 
902
    pop     ebp
 
903
    pop     esi
 
904
    pop     es
 
905
    ret
 
906
ENDPROC VBoxDrvRing0Init
 
907
 
 
908
 
 
909
;;
 
910
; Flush any text in the text buffer.
 
911
;
 
912
BEGINPROC VBoxDrvInitFlushText
 
913
    push    bp
 
914
    mov     bp, sp
 
915
 
 
916
    ; Anything in the buffer?
 
917
    mov     ax, [NAME(g_cchInitText)]
 
918
    or      ax, ax
 
919
    jz      .done
 
920
 
 
921
%if 1
 
922
    ; Write it to STDOUT.
 
923
    ; APIRET  _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
 
924
    push    ax                                      ; bp - 2 : cbBytesWritten
 
925
    mov     cx, sp
 
926
    push    1                                       ; STDOUT
 
927
    push    seg NAME(g_szInitText)                  ; pvBuf
 
928
    push    NAME(g_szInitText)
 
929
    push    ax                                      ; cbBuf
 
930
    push    ss                                      ; pcbBytesWritten
 
931
    push    cx
 
932
%if 0 ; wlink generates a non-aliased fixup here which results in 16-bit offset with the flat 32-bit selector.
 
933
    call far DOS16WRITE
 
934
%else
 
935
    ; convert flat pointer to a far pointer using the tiled algorithm.
 
936
    push    ds
 
937
    mov     ax, DATA32 wrt FLAT
 
938
    mov     ds, ax
 
939
    mov     eax, g_pfnDos16Write wrt FLAT
 
940
    movzx   eax, word [eax + 2]                     ; High word of the flat address (in DATA32).
 
941
    shl     ax, 3
 
942
    or      ax, 0007h
 
943
    pop     ds
 
944
    mov     [NAME(g_fpfnDos16Write) + 2], ax        ; Update the selector (in DATA16_INIT).
 
945
    ; do the call
 
946
    call far [NAME(g_fpfnDos16Write)]
 
947
%endif
 
948
 
 
949
%else ; alternative workaround for the wlink issue.
 
950
    ; Use the save message devhlp.
 
951
    push    esi
 
952
    push    ebx
 
953
    xor     bx, bx
 
954
    mov     si, NAME(g_MsgTab)
 
955
    mov     dx, seg NAME(g_MsgTab)
 
956
    mov     ds, dx
 
957
    mov     dl, DevHlp_SAVE_MESSAGE
 
958
    call far [NAME(g_fpfnDevHlp)]
 
959
    pop     ebx
 
960
    pop     esi
 
961
%endif
 
962
 
 
963
    ; Empty the buffer.
 
964
    mov     word [NAME(g_cchInitText)], 0
 
965
    mov     byte [NAME(g_szInitText)], 0
 
966
 
 
967
.done:
 
968
    mov     sp, bp
 
969
    pop     bp
 
970
    ret
 
971
ENDPROC VBoxDrvInitFlushText
 
972
 
 
973
 
 
974
 
 
975
;;
 
976
; This must be present
 
977
segment DATA32
 
978
g_pfnDos16Write:
 
979
    dd  DOS16WRITE  ; flat
 
980
 
 
981