2 ;-------------------------------------------------------------------
4 ; Equates that are specific to LIM 4.0 functions go here
6 ;-------------------------------------------------------------------
8 null equ 0 ; null value, used everywhere
9 max_phys_pages equ 255 ; largest allowable phys page
11 sf_pm_get equ 0 ; 4f00 - get partial map
12 sf_pm_set equ 1 ; 4f01 - set partial map
13 sf_pm_size equ 2 ; 4f02 - get partial map size
15 mu_ppn equ 0 ; 5000 - map/unmap multiple
16 mu_seg equ 1 ; 5001 - map/unmap multiple
17 mu_max_fcn equ 1 ; 50 - map/unmap multiple
19 Hn_Attr_Max_Fcn equ 2 ; 52xx - max subfunction ;an000; dms;
21 sf_hn_get equ 0 ; 5300 - get handle name
22 sf_hn_set equ 1 ; 5301 - set handle name
23 hn_max_fcn equ 1 ; 53 - handle name sub-functions 00, 01
25 sf_hd_get equ 0 ; 5400 - get handle dir
26 sf_hd_search equ 1 ; 5401 - search for named handle
27 sf_hd_total equ 2 ; 5402 - get total number of handles
28 hd_max_fcn equ 2 ; 54 - get handle directory s-f's 00, 01, 02
30 Add_Get_Array equ 0 ; 5800 - Get Mappable Physical Address Array
31 Add_Get_Size equ 1 ; 5801 - Get Mappable Physical Address Array Entries
33 hi_info equ 0 ; 5900 - hardware info
34 hi_raw equ 1 ; 5901 - # raw pages
36 am_get equ 0 ; 5b00 - get alternate map register set
37 am_set equ 1 ; 5b01 - set alternate map register set
38 am_size equ 2 ; 5b02 - get alternate map save array size
39 am_alloc equ 3 ; 5b03 - allocate alternate map register set
40 am_dealloc equ 4 ; 5b04 - deallocate alternate map register set
41 am_dma_alloc equ 5 ; 5b05 - allocate DMA register set
42 am_dma_enable equ 6 ; 5b06 - enable DMA register set
43 am_dma_disable equ 7 ; 5b07 - disable DMA register set
44 am_dma_dealloc equ 8 ; 5b08 - deallocate DMA register set
46 os_enable equ 0 ; 5d00 - enable OS/E function
47 os_disable equ 1 ; 5d01 - disable OS/E function
48 os_access equ 2 ; 5d02 - "return" access key function
50 map_pages_fcn equ 44h ; function code used to map pages
51 get_free_pages equ 42h ; function code used to get free page count
53 read_clock equ 2ch ; function code to read clock
54 dos_int equ 21h ; interrupt 21
55 xor_mask equ 0ffffh ; mask used to confuse the random numbers a little
57 ppm_struct STRUC ; define the structure
58 phys_page_offset dw ? ; offsets into PPM entry
59 ppm_handle_offset dw ?
60 ppm_log_page_offset dw ?
64 ;-------------------------------------------------------------------
66 ; 4F - get/set partial page map
69 ; AL = 00, get partial page map pm_get
70 ; 01, set partial page map pm_set
71 ; 02, get partial page map size pm_size
74 ; See individual function headers
76 ;-------------------------------------------------------------------
79 ; use AL value to select sub-function
81 cmp al,sf_pm_get ; al = 00, get partial page map
84 cmp al,sf_pm_set ; al = 01, set partial page map
87 cmp al,sf_pm_size ; al = 02, get partial page map size
92 ; invalid sub-function, report the error
95 mov ah,ems_code8F ; invalid sub-function code
99 ;-------------------------------------------------------------------
101 ; 4F00 - get partial page map
104 ; DS:SI -> partial page map
106 ; dw ? ; segment count (number
107 ; ; of following entries)
108 ; dw ? ; segment address to save
109 ; : ; (repeats count times)
112 ; ES:DI -> user array for mapping info
113 ; size determined by function 4F02
118 ; 80H, Software error
119 ; 81H, Hardware error
120 ; 84H, Invalid function
121 ; 8FH, Invalid sub-function
122 ; A3H, Contents of control structure are invalid
124 ; ES:DI -> saved partial state array
125 ; format for this is un-disclosed to the user
128 ; ppm_count dw ? ; number of saved entries
129 ; ppm_phys_page dw ? ; physical page
130 ; ppm_handle dw ? ; handle
131 ; ppm_log_page dw ? ; logical page
132 ; : ; repeats for each requested page
136 ;-------------------------------------------------------------------
139 push bx ; save some regs
146 mov di,cs:[bp].IE_Saved_DI_Reg ; restore caller's DI, pointer to mapping control structure
149 ;-------------------------------------------------------------------
151 ; get count from caller's control structure
153 mov cx,ds:[si] ; the first word of the control
154 ; structure holds the # of entries
156 cmp cx,0 ; 0 pages requested? ;an000; dms;
157 je PM_Get_Error_A3 ; yes - flag an error ;an000; dms;
159 cmp cx,cs:Map_Count ; do some sanity checking
160 jbe pm_phys_ok ; requested number is ok, do the copies
162 ; They asked for more than we can possibly have. Sounds like trouble.
166 mov ah,ems_codea3 ; bad stuff in the control structure
167 jmp pm_exit00 ; return the error code
170 mov cx,DS:word ptr [si] ; get count from control structure
171 mov ES:word ptr [di],cx ; save count in save area
172 add di,2 ; increment save area pointer
174 ;-------------------------------------------------------------------
176 ; everything is OK so far, copy the entries requested
178 ;-------------------------------------------------------------------
182 add si,2 ; point to next segment number
183 mov ax,DS:word ptr [si] ; get segment value from control structure
185 push si ; save user's si
186 push ds ; save user's ds
187 push cx ; save counter for outer loop
189 ; ready to do the lookup and copy operation
191 push cs ; make DS:SI point to internal data area
195 mov cx,map_count ; number of mappable segments
198 cmp ax,ds:word ptr [si+phys_page_segment] ; is this entry the requested?
199 jne ppm_not_yet ; no, try again
201 mov cx,ppm_size ; number of bytes to copy
202 cld ; make sure direction flag is right
203 add si,2 ; point to phys_page_number
205 rep movsb ; copy the entry
209 jmp ppm_entry_done ; done with this copy, go on
212 add si,type mappable_phys_page_struct ; point to next entry
213 loop ppm_inner_copy_loop ; try some more
215 pop cx ; restore counter for outer loop
216 pop ds ; restore user's ds
217 pop si ; restore user's si
218 mov ah,EMS_Code8B ; we have an invalid segment specified ;an000; dms;
219 jmp PM_Exit00 ; exit the program
223 ; restore pointer to control structure
225 pop cx ; restore counter for outer loop
226 pop ds ; restore user's ds
227 pop si ; restore user's si
230 loop ppm_copies ; keep going until proper number of
231 ; entries have been copied
233 xor ah,ah ; good return code
234 ;-------------------------------------------------------------------
236 pop ds ; restore these registers
243 ret ; return to caller
248 ;-------------------------------------------------------------------
250 ; 4F01 - set partial page map
253 ; DS:SI -> source array
256 ; ppm_count dw ? ; number of saved entries
257 ; ppm_phys_page dw ? ; physical page
258 ; ppm_handle dw ? ; handle
259 ; ppm_log_page dw ? ; logical page
260 ; : ; repeats ppm_count times
266 ; 80H, Software error
267 ; 81H, Hardware error
268 ; 84H, Invalid function
269 ; 8FH, Invalid sub-function
270 ; A3H, Contents of source array invalid
272 ;-------------------------------------------------------------------
275 push bx ; save some regs
282 mov cx,DS:word ptr [si] ; get number of entries in save area
284 cmp cx,0 ; is the count zero?
285 je pm_set_error_A3 ; yes - error ;an000; dms;
287 cmp cx,cs:Map_Count ; greater than phys pages avail? ;an000; dms;
288 jbe count_ok ; no - data not corrupted ;an000; dms;
292 mov ah,EMS_CODEA3 ; control structure error
296 add si,2 ; point to first entry in save area
300 mov ax,DS:word ptr [si+phys_page_offset] ; set up regs for map_l_to_p
302 mov dx,DS:word ptr [si+ppm_handle_offset]
303 mov bx,DS:word ptr [si+ppm_log_page_offset]
305 cmp dx,0ffffh ; is there a real entry?
306 je no_map ; no, skip the call to map_l_to_p
308 call map_l_to_p ; make the mapping call
311 add si,type ppm_struct ; point to next entry
315 xor ah,ah ; good return code
318 pop ds ; restore these registers
325 ret ; return to caller
329 ;-------------------------------------------------------------------
331 ; 4F02 - get partial page map size
336 ; BX = number of pages in partial page map
340 ; 80H, Software error
341 ; 81H, Hardware error
342 ; 84H, Invalid function
343 ; 8FH, Invalid sub-function
345 ; AL = size of partial page map save array
346 ; number of bytes that will be needed
347 ; to save the requested number of pages
349 ;-------------------------------------------------------------------
354 cmp bx,0 ; 0 pages requested? ;an000; dms;
355 je PM_Size_Error_8B ; yes flag an error ;an000; dms;
357 cmp bx,cs:Map_Count ; page count > phys pages? ;an000; dms;
358 jbe PM_Size_Return ; no - continue ;an000; dms;
362 mov ah,EMS_Code8B ; signal page count exceeded ;an000; dms;
363 jmp PM_Exit02 ; exit routine ;an000; dms;
367 mov dx,bx ; number of pages times ...
368 mov ax,ppm_size ; * size of an entry ...
369 mul dx ; = number of bytes in save array
370 add ax,2 ; increase by 2 to include count word
372 xor ah,ah ; good return code
377 ret ; return to caller
383 ;-------------------------------------------------------------------
385 ; 50 - map/unmap multiple handle pages
388 ; AH = 00 physical page numbers
391 ;-------------------------------------------------------------------
394 cmp al,mu_ppn ; is this a map request?
395 je mu_ppn_fcn ; yes, go do it
397 cmp al,mu_seg ; no, is this an unmap request?
398 je mu_seg_fcn ; yes, go do it
400 xor al,al ; clear al, why not?
401 mov ah,ems_code8f ; no, return invalid sub-function code
402 ret ; return to caller
404 ;-------------------------------------------------------------------
406 ; 5000 - map/unmap multiple handle pages using physical page numbers
413 ; CX = num entries in control structure
415 ; DS:SI -> points to control structure
418 ; log_pg_num dw ? ; logical page number
419 ; phys_pg_num dw ? ; physical page number
420 ; : ; repeats CX times
426 ; 80H, Software error
427 ; 81H, Hardware error
428 ; 83H, Invalid handle
429 ; 84H, Invalid function
430 ; 8AH, Invalid logical page
431 ; 8BH, Invalid physical page
432 ; 8FH, Invalid sub-function
434 ;-------------------------------------------------------------------
438 push bx ; save regs ;an000; dms;
440 push dx ; ;an000; dms;
441 push si ; save pointer
443 xor ah,ah ; good return code
444 cmp cx,0 ; is count 0?
448 mov bx,ds:word ptr[si+0] ; get logical page number
449 mov ax,ds:word ptr[si+2] ; get physical page number
450 mov ah,map_pages_fcn ; fcn code for mapping
453 call map_l_to_p ; call the mapping routine
456 cmp ah,0 ; was return code OK
459 add si,4 ; point to next entry
461 loop mu_ppn_loop ; do it again
463 xor ah,ah ; good return code
468 pop si ; restore pointer
469 pop dx ; ;an000; dms;
470 pop cx ; restore count
471 pop bx ; restore regs ;an000; dms;
473 ret ; return to caller
476 ;-------------------------------------------------------------------
478 ; 5001 - map/unmap multiple handle pages using segment addresses
485 ; CX = num entries in control structure
487 ; DS:SI -> points to control structure
490 ; log_pg_num dw ? ; logical page number
491 ; seg_address dw ? ; physical segment address
492 ; : ; repeats CX times
498 ; 80H, Software error
499 ; 81H, Hardware error
500 ; 83H, Invalid handle
501 ; 84H, Invalid function
502 ; 8AH, Invalid logical page
503 ; 8BH, Invalid physical page
504 ; 8FH, Invalid sub-function
506 ;-------------------------------------------------------------------
510 push bx ; save regs ;an000; dms;
512 push dx ; ;an000; dms;
513 push si ; save pointer
515 xor ah,ah ; good return code
516 cmp cx,0 ; is count 0?
520 mov bx,ds:word ptr[si+0] ; get logical page number
522 push dx ; save handle
523 mov dx,ds:word ptr[si+2] ; get physical page number
524 call Get_Phys_Seg_Page ; convert to logical page circle
525 mov ax,dx ; must be in AX
526 pop dx ; restore handle
528 mov ah,map_pages_fcn ; fcn code for mapping
531 call map_l_to_p ; call the mapping routine
534 cmp ah,0 ; was return code OK
537 add si,4 ; point to next entry
539 loop mu_seg_loop ; do it again
541 xor ah,ah ; good return code
546 pop si ; restore pointer
547 pop dx ; ;an000; dms;
548 pop cx ; restore count
549 pop bx ; restore regs ;an000; dms;
551 ret ; return to caller
555 ;-------------------------------------------------------------------
557 ;-------------------------------------------------------------------
560 ;-------------------------------------------------------------------
562 ; 52 - get/set handle attributes
564 ; The LIM 4.0 spec strongly advises EMS implementers to avoid this
565 ; call. Our current implementation of this function is not to provide
566 ; support. Possibly in future releases it will be supported, if
567 ; the proper hardware becomes available.
571 ;-------------------------------------------------------------------
575 cmp al,Hn_Attr_Max_Fcn ;maximum subfunction number ;an000; dms;
576 jbe Handle_Attrib_Cont ;continue routine ;an000; dms;
577 mov ah,EMS_Code8F ;we have an invalid subfunction ;an000; dms;
578 jmp Handle_Attrib_Exit ; exit the routine ;an000; dms;
582 mov ah,EMS_Code91 ;this function is not supported ;an000; dms;
586 RET ; return to caller
591 ;-------------------------------------------------------------------
593 ; 53 - get/set handle name
595 ; Virtual Mode Note: The Handle Name functions (53 and 54) will @RH6
596 ; be handled differently when running on a system in virtual mode. @RH6
597 ; This is to accommadate the Workstation Program's bank switching. @RH6
598 ; In this case, handle names and ID's will only be returned for @RH6
599 ; handles allocated in the same PC bank, or for handles in bank 0. @RH6
600 ; Bank 0 is for device drivers, system extensions, or applications @RH6
601 ; that install resident before WSP loads. @RH6
602 ; When interfacing with handles in bank 0, one must be aware of @RH6
603 ; the problem of two PC applications running simultaneously that @RH6
604 ; get the handle ID of the resident program and map its pages. @RH6
605 ; Data corruption will occur if both map and write to the same page @RH6
606 ; at the same time. @RH6
607 ; While these new LIM 4.0 functions will return info only for @RH6
608 ; bank 0 and the current bank, the existing LIM 3.2 functions will @RH6
609 ; continue to return total system values. For example, function 4B @RH6
610 ; will return the number of active handles in all banks. @RH6
613 ; AL = sub-function code
614 ; 00 = get handle name hn_get
615 ; 01 = set handle name hn_set
619 ; ES:DI -> Get caller's name buffer (8 char's)
620 ; DS:SI -> Set caller's name buffer (8 char's)
625 ; 80H, Software error
626 ; 81H, Hardware error
627 ; 83H, Handle not found
628 ; 84H, Invalid function
629 ; 8FH, Invalid sub-function
636 ;-------------------------------------------------------------------
638 Null_Handle_Name db 8 dup(0) ;null handle value ;an000; dms;
642 push bx ; save some regs
649 PUSH CS ;Set addressability to our tables @RH8
650 POP DS ;Must restore DS for Set name @RH8
652 cmp al,hn_max_fcn ; al = 00 or 01, anything else = error
655 ; invalid sub-function, report the error
657 mov ah,ems_code8F ; invalid sub-function code
660 ; check the handle for valid range
664 cmp dx,num_handles-1 ; handle within range ?
665 jnae hn_range_ok ; yes, get down to business
667 mov ah,ems_code83 ; handle not found
670 ;------------------------
671 ; handle is within valid range, now see if it is valid handle (i.e. in use)
675 push ax ; save fcn code
676 push dx ; save handle
678 MOV AX,DX ;DX = handle id
679 MOV DX,TYPE H_LOOKUP_STRUC ;DI = entry's offset into
680 MUL DX ; the handle lookup table
682 POP DX ; restore handle
683 POP AX ; restore fcn code
685 CMP HANDLE_LOOKUP_TABLE.H_PAGES[DI],REUSABLE_HANDLE
686 JNE HN_IN_USE ;Is this handle valid (in use)?
688 mov ah,ems_code83 ; handle not found
689 jmp hn_exit ; return the error code
691 HN_IN_USE: ;Check bank ID if in virutal mode
693 mov bx,ax ;save ax ;an000; dms;
694 TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6
695 JZ HN_VALID ; (i.e. bank swapping), then read @RH6
696 MOV DX,IDREG ; the current bank ID. @RH6
698 CMP HANDLE_LOOKUP_TABLE.H_BANK[DI],AL ;If handle's bank ID @RH6
699 JE HN_VALID ; is 0 (resident) or @RH6
700 CMP HANDLE_LOOKUP_TABLE.H_BANK[DI],0 ; = requesters bank @RH6
701 JE HN_VALID ; then OK @RH6
702 ;Else invalid requester bank @RH6
703 MOV AH,EMS_CODE83 ;Indicate handle not found @RH6
706 ;------------------------
707 ; find out if get or set operation
710 mov ax,bx ;restore ax ;an000; dms;
711 cmp al,sf_hn_get ; al = 00 means GET
714 cmp al,sf_hn_set ; = 01 means SET
717 ; invalid sub-function, report the error
719 mov ah,ems_code8F ; invalid sub-function code
725 ;-------------------------------------------------------------------
727 ; 5300 - GET sub-function
728 ; ES:DI -> User's area where name is stored
729 ;-------------------------------------------------------------------
731 ;Here DI = offset into h lookup
732 LEA SI,HANDLE_LOOKUP_TABLE ;Set the source SI to the handle's
733 ADD SI,DI ; name field in the handle lookup
734 ADD SI,H_NAME ; lookup table
736 MOV DI,cs:[bp].IE_Saved_DI_Reg ;Restore the user's dest where
737 ; the handle name will be stored
739 MOV CX,8 ; want to copy 8 characters
740 CLD ; make sure direction flag is right
741 REP MOVSB ; copy the string
743 XOR AH,AH ; set good return code
748 ;-------------------------------------------------------------------
750 ; 5301 - SET sub-function
751 ; DS:SI -> User's area where name comes from
753 ;-------------------------------------------------------------------
757 POP DS ;Restore the user's source where @RH6
758 PUSH DS ; the handle name will come from
761 ;------------------------
762 push si ;save regs ;an000; dms;
763 push di ; ;an000; dms;
764 push cx ; ;an000; dms;
765 push es ; ;an000; dms;
767 push cs ;swap segs for compare ;an000; dms;
768 pop es ; ;an000; dms;
770 mov di,offset cs:Null_Handle_Name ;point to null handle name ;an000; dms;
771 mov cx,8 ;8 bytes to compare ;an000; dms;
773 cli ;ints off ;an000; dms;
774 rep cmpsb ;null string entered? ;an000; dms;
775 sti ;ints on ;an000; dms;
777 pop es ;restore regs ;an000; dms;
778 pop cx ; ;an000; dms;
779 pop di ; ;an000; dms;
780 pop si ; ;an000; dms;
781 je HN_Set_Null_Entered ;continue - don't look for match ;an000; dms;
784 call hd_named_handle ; find out if name is in use
787 cmp ah,0 ; is return code good
792 ;------------------------
793 ;Here DI = offset into h lookup
794 ADD DI,OFFSET HANDLE_LOOKUP_TABLE ;Set the dest. DI to the @RH6
795 ADD DI,OFFSET H_NAME ; handle's name field in @RH6
796 ; the handle lookup table @RH6
798 PUSH ES ;Make ES:DI -> destination in
799 PUSH CS ; the handle lookup table where
800 POP ES ; the name will be stored
802 mov cx,8 ; want to copy 8 characters
803 cld ; clear DF to auto-increment
804 rep movsb ; copy the string
806 ; all done with the SET function, set good return code and exit
808 pop es ; restore user's ES
809 xor ax,ax ; set good return code
813 ;------------------------
815 mov ah,ems_codea1 ; name is use error
819 pop ds ; restore these registers
833 ;-------------------------------------------------------------------
835 ; 54 - get handle directory
838 ; AL = 00, get handle directory hd_directory
839 ; 01, search for named handle hd_named_handle
840 ; 02, get total handles hd_total_handles
842 ;-------------------------------------------------------------------
845 cmp al,sf_hd_get ; 00 get handle dir
848 cmp al,sf_hd_search ; 01 search for named handle
851 cmp al,sf_hd_total ; 02 get total number of handles
852 jne hd_invalid_sfcn ; must be an invalid function code
854 jmp hd_total_handles ; go display total handles
857 ; invalid sub-function, report the error
860 mov ah,ems_code8F ; invalid sub-function code
862 ; invalid sub-function, fall through to exit
869 ;-------------------------------------------------------------------
870 ; 5400 - get handle directory
874 ; AL = 00, get handle directory
876 ; ES:DI -> caller's buffer for handle directory
880 ; 80H, software error
881 ; 81H, hardware error
882 ; 84H, invalid function
883 ; 8FH, invalid subfunction
885 ; AL = number of entries in handle directory
887 ; ES:DI -> handle directory
889 ; dw ? ; handle number
890 ; db 8 dup(?) ; handle name
892 ; : ; repeats AL times
894 ;-------------------------------------------------------------------
897 push bx ; save some regs
904 TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6
905 JZ HD_LOOP_INIT ; (i.e. bank swapping), then read @RH6
906 MOV DX,IDREG ; the current bank ID and save it. @RH6
911 ; initialize some things for the loop
913 mov di,cs:[bp].IE_Saved_DI_Reg ;restore users DI ;an000; dms;
914 xor al,al ; al = num entries
915 xor dx,dx ; dx = handle index
916 mov cx,NUM_HANDLES ; loop enough for all handles
917 cld ; make sure direction flag cleared
921 XOR SI,SI ; SI = offset into handle lookup @RH6
924 CMP HANDLE_LOOKUP_TABLE.h_pages[SI],REUSABLE_HANDLE
925 ; If handle not active, then @RH6
926 je hd_next_hndl ; loop and look again
927 ;-------------------------
928 ; Active handle...if in virtual mode check bank ID @RH6
929 ;-------------------------
931 TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6
932 JZ HD_ACTIVE ; (i.e. bank swapping), then check @RH6
933 MOV BL,cs:BANKID ; handle's bank id @RH6
934 CMP HANDLE_LOOKUP_TABLE.H_BANK[SI],BL ;If handle's bank ID @RH6
935 JE HD_Active ; is 0 (resident) or @RH6
936 CMP HANDLE_LOOKUP_TABLE.H_BANK[SI],0 ; = requesters bank @RH6
937 JE HD_Active ; then OK @RH6
938 jmp HD_Next_Hndl ;Else skip to next one @RH6
940 ;------------------------
941 ; found an active handle, copy info to directory
942 ;------------------------
944 mov es:word ptr[di],dx ; put handle number in directory
945 add di,2 ; move directory table pointer along,
946 ; must point to area for handle name now
948 push cx ; save counter for outer loop
949 push si ; save si for outer loop
951 mov cx,8 ; need to copy 8 chars
952 add si,offset Handle_LookUp_Table ;point to entry ;an000; dms;
953 add si,h_name ; make DS:SI -> handle name in lookup table
955 rep movsb ; copy the string
957 pop si ; restore si for outer loop
958 pop cx ; restore counter for outer loop
959 inc al ; increment entry count
961 ;------------------------
963 ;------------------------
966 inc dx ; update handle index
967 add si,type h_lookup_struc ; point to next entry in lookup table
968 loop hd_loop ; look for more
970 xor ah,ah ; good return code
972 ; all done, fall through to exit
976 pop ds ;restore these registers
988 ;-------------------------------------------------------------------
990 ; 5401 - Search for named handle sub-function
994 ; AL = 01, search for named handle
996 ; DS:SI = Pointer to handle name to search for
999 ; OUTPUT sub-fcn 01: Search for named handle
1001 ; AH = 00H, no error
1002 ; 80H, software error
1003 ; 81H, hardware error
1004 ; 84H, invalid function
1005 ; 8FH, invalid subfunction
1006 ; A0H, no matching handle found
1007 ; A1H, duplicate handle found
1009 ; DX = value of named handle
1011 ;-------------------------------------------------------------------
1015 push bx ; save some regs
1020 push es ;an000; dms;
1022 TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6
1023 JZ HD1_LOOP_INIT ; (i.e. bank swapping), then read @RH6
1024 MOV DX,IDREG ; the current bank ID and save it. @RH6
1029 ; initialize some things for the loop
1031 xor ah,ah ; good return code
1032 xor dx,dx ; dx = handle index
1033 mov cx,NUM_HANDLES ; loop enough for all handles
1034 cld ; make sure direction flag cleared
1038 XOR DI,DI ; DI = offset into handle lookup @RH6
1041 CMP ES:HANDLE_LOOKUP_TABLE.h_pages[DI],REUSABLE_HANDLE
1042 ; If handle not active, then @RH6
1043 je hd1_next_hndl ; loop and look again
1044 ;-------------------------
1045 ; Active handle...if in virtual mode check bank ID @RH6
1046 ;-------------------------
1048 TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6
1049 JZ HD1_ACTIVE ; (i.e. bank swapping), then check @RH6
1050 MOV BL,cs:BANKID ; handle's bank id @RH6
1051 CMP ES:HANDLE_LOOKUP_TABLE.H_BANK[DI],BL ;If handle's bank ID @RH6
1052 JE HD1_Active ; is 0 (resident) or @RH6
1053 CMP ES:HANDLE_LOOKUP_TABLE.H_BANK[DI],0 ; = requesters bank @RH6
1054 JE HD1_Active ; then OK @RH6
1055 jmp HD1_Next_Hndl ;Else skip to next one @RH6
1056 ;------------------------
1057 ; found an active handle, check the name
1058 ;------------------------
1061 push cx ; save counter for outer loop
1062 push si ; save si for outer loop
1063 push di ; save di for outer loop
1065 mov cx,8 ; need to compare 8 chars
1066 add di,offset Handle_LookUp_Table ;point to entry ;an000; dms;
1067 add di,offset H_Name ; must point to area for handle name now;an000; dms;
1069 rep cmpsb ; compare the strings
1071 pop di ; restore di for outer loop
1072 pop si ; restore si for outer loop
1073 pop cx ; restore counter for outer loop
1074 je hd_exit01 ; found a match, exit
1076 ;------------------------
1077 ; done with the check
1078 ;------------------------
1081 inc dx ; update handle index
1082 add di,type h_lookup_struc ; point to next entry in lookup table
1083 loop hd1_loop ; look for more
1087 ; all done, if we fall through loop without finding a match,
1088 ; must report the error
1090 mov ah,ems_codea0 ; no matching handle
1091 xor dx,dx ; invalid handle
1096 pop es ;restore these registers ;an000; dms;
1108 ;-------------------------------------------------------------------
1110 ; 5402 - Get total handles sub-function
1113 ; AL = 02, get total handles
1117 ; AH = 00H, no error
1118 ; 80H, software error
1119 ; 81H, hardware error
1120 ; 84H, invalid function
1121 ; 8FH, invalid subfunction
1123 ; BX = total number of handles (includes OS handle, 0)
1125 ;-------------------------------------------------------------------
1129 mov bx,NUM_HANDLES ; return number of handles
1130 xor ah,ah ; good return code
1132 ; all done, fall through to exit
1136 ret ; return to caller
1141 ;-------------------------------------------------------------------
1143 ; 58 - Get mappable physical address array
1149 ; ES:DI -> mappable physical array address
1153 ; 80H, software error
1154 ; 81H, hardware error
1155 ; 84H, invalid function
1156 ; 8FH, invalid subfunction
1158 ; CX = number of entries returned in the table below
1160 ; ES:DI -> DW ? ; phys_page_segment
1161 ; DW ? ; phys_page_number
1163 ; : ; repeats CX times
1165 ;-------------------------------------------------------------------
1168 cmp al,Add_Get_Array ; subfunction 00 Get Mappable Physical ;an000; dms;
1170 je Address_Get_Physical_Address
1172 cmp al,Add_Get_Size ; subfunction 01 Get Mappable Physical ;an000; dms;
1173 ; Address Array Entries
1174 je Address_Get_Size_Entries
1176 mov ah,EMS_Code8F ; none of the above - invalid sub parm ;an000; dms;
1181 Address_Get_Physical_Address:
1183 push si ; save some regs
1184 push di ; save di ;an000; dms;
1188 ; set up some things for the loop
1190 mov di,cs:[bp].IE_Saved_DI_Reg ; restore caller's DI, pointer to handle area
1192 mov cx,map_count ; number of entries in table
1194 push cs ; make DS:SI -> array
1199 cld ; make sure direction flag is right
1203 mov ax,DS:[si+phys_page_segment]
1205 add di,2 ; increment destination pointer
1206 mov ax,DS:[si+phys_page_number]
1209 add si,type mappable_phys_page_struct ; increment pointer
1210 add di,2 ; increment destination pointer
1212 loop copy_address_array
1214 mov cx,map_count ; number of entries
1215 xor ah,ah ; good return code
1221 RET ; return to caller
1223 Address_Get_Size_Entries:
1225 mov cx,cs:Map_Count ; return the number of pages allocated ;an000; dms;
1226 xor ax,ax ; clear error flag ;an000; dms;
1227 ret ; return to caller ;an000; dms;
1235 ;-------------------------------------------------------------------
1237 ; 59 - Get extended momory hardware information
1239 ;-------------------------------------------------------------------
1242 cmp ose_functions,ose_enabled ; first, check for fcns enabled
1246 mov ah,EMS_CODEA4 ; access denied
1250 cmp al,hi_info ; 5900 - hardware info fcn
1253 cmp al,hi_raw ; 5901 - unallocated raw page count
1256 mov ah,EMS_CODE8F ; invalid sub-function
1259 RET ; return to caller
1263 ;-------------------------------------------------------------------
1267 ;-------------------------------------------------------------------
1271 mov di,cs:[bp].IE_Saved_DI_Reg ; get di register
1273 mov es:word ptr[di+0],1024 ; raw page size = 16KB
1274 mov es:word ptr[di+2],0 ; number of alternate register sets
1275 mov es:word ptr[di+4],type H_SAVE_STRUC ; size of save array
1276 mov es:word ptr[di+6],0 ; number of DMA register sets
1277 mov es:word ptr[di+8],1 ; 1 = no special DMA register sets
1279 xor ah,ah ; good return code
1280 ret ; return to caller
1283 ;-------------------------------------------------------------------
1287 ;-------------------------------------------------------------------
1291 mov ah,get_free_pages ; function code to get free pages
1293 call q_pages ; pass this one through, since our
1295 ; this fcn returns exacly the same
1296 ; regs as are needed here
1298 ret ; return to caller
1303 ;-------------------------------------------------------------------
1305 ; 5B - alternate map register set
1307 ;-------------------------------------------------------------------
1309 AM_ES_Save dw 0 ;ES save variable ;an000; dms;
1310 AM_DI_Save dw 0 ;DI save variable ;an000; dms;
1311 AM_Set_Flag db 0 ;set called flag ;an000; dms;
1315 cmp ose_functions,ose_enabled ; first, check for fcns enabled
1319 mov ah,EMS_CODEA4 ; access denied
1323 cmp al,am_get ; 5b00 - get alternate map register set
1326 cmp al,am_set ; 5b01 - set alternate map register set
1329 cmp al,am_size ; 5b02 - get alternate map save array size
1332 cmp al,am_alloc ; 5b03 - allocate alternate map register set
1335 cmp al,am_dealloc ; 5b04 - deallocate alternate map register set
1338 cmp al,am_dma_alloc ; 5b05 - allocate DMA register set
1341 cmp al,am_dma_enable ; 5b06 - enable DMA register set
1344 cmp al,am_dma_disable ; 5b07 - disable DMA register set
1347 cmp al,am_dma_dealloc ; 5b08 - deallocate DMA register set
1350 mov ah,EMS_CODE8F ; invalid sub-function
1353 ret ; return to caller
1357 ;-------------------------------------------------------------------
1361 ;-------------------------------------------------------------------
1364 cmp cs:AM_Set_Flag,0 ;flag set? ;an000; dms;
1365 jne AM_Get_Continue ;yes ;an000; dms;
1366 xor di,di ;signal set has not ;an000; dms;
1367 mov es,di ; been performed ;an000; dms;
1368 xor ah,ah ;signal good exit ;an000; dms;
1369 jmp AM_Get_Exit ;exit routine ;an000; dms;
1373 mov di,cs:AM_DI_Save
1374 mov es,cs:AM_ES_Save
1375 mov cs:[bp].IE_Saved_DI_Reg,di;set instance table entry ;an000; dms;
1377 call GET_SUBFCN ; copy the save area info to user's buffer
1379 xor bl,bl ; bl = 0 for our implementation
1380 ; this indicates to user that ES:DI
1381 ; buffer has been filled in with save
1388 ;-------------------------------------------------------------------
1392 ;-------------------------------------------------------------------
1398 cmp bl,null ; bl must be 0 for us
1399 jne _am_set_error ; set error code and exit
1401 mov di,cs:[bp].IE_Saved_DI_Reg ; restore caller's DI, pointer to mapping control structure
1403 mov cs:AM_ES_Save,es ; save es value ;an000; dms;
1404 mov cs:AM_DI_Save,di ; save di value ;an000; dms;
1405 mov cs:AM_Set_Flag,01 ; flag indicates set performed ;an000; dms;
1406 mov si,di ; restore_pgfrm_map expects DS:SI to point to save area
1410 call RESTORE_PGFRM_MAP
1412 xor ah,ah ; good return code
1417 mov ah,EMS_CODE9C ; fast regs not supported and BL != 0
1427 ;-------------------------------------------------------------------
1431 ;-------------------------------------------------------------------
1434 mov dx,type h_save_struc ; get size requirements for save area
1436 xor ah,ah ; good return code
1441 ;-------------------------------------------------------------------
1445 ;-------------------------------------------------------------------
1449 xor bl,bl ; We don't support this function
1450 ; in hardware, so return 0.
1451 ; This indicates we will do software
1452 ; emulation of these register sets.
1454 xor ah,ah ; good return code
1459 ;-------------------------------------------------------------------
1461 ; _am_dealloc - 5b04
1463 ;-------------------------------------------------------------------
1466 xor ah,ah ; assume good return code
1468 cmp bl,0 ; is this a deallocate for 0?
1469 je _am_dealloc_exit ; yes, goo return code
1471 mov ah,EMS_CODE9C ; error code for dealloc of unsupported
1479 ;-------------------------------------------------------------------
1483 ;-------------------------------------------------------------------
1486 xor ah,ah ; good return code
1487 xor bl,bl ; no DMA sets available
1492 ;-------------------------------------------------------------------
1496 ;-------------------------------------------------------------------
1499 mov ah,EMS_CODE9E ; dedicated DMA not supported
1504 ;-------------------------------------------------------------------
1508 ;-------------------------------------------------------------------
1511 mov ah,EMS_CODE9E ; dedicated DMA not supported
1516 ;-------------------------------------------------------------------
1520 ;-------------------------------------------------------------------
1523 xor ah,ah ; assume good return code
1525 cmp bl,null ; is the DMA channel 0?
1528 mov ah,EMS_CODE9C ; DMA register sets are not
1529 ; supported and bl != 0
1538 ;-------------------------------------------------------------------
1540 ; 5D - enable/disable OS/E functions set functions
1542 ;-------------------------------------------------------------------
1545 cmp al,os_enable ; fcn code for enable
1548 cmp al,os_disable ; fcn code for disable
1551 cmp al,os_access ; fcn code for access key return
1554 mov ah,EMS_CODE8F ;invalid sub-function code error
1556 ret ; return to caller
1559 ;-------------------------------------------------------------------
1561 ; 5d00 - enable OS/E function set
1565 ; BX,CX = Access key
1569 ; AH = 00h, no error
1570 ; 80H, software error
1571 ; 81H, hardware error
1572 ; 84H, invalid function
1573 ; 8FH, invalid subfunction
1574 ; A4H, access denied, incorrect access key supplied
1576 ;-------------------------------------------------------------------
1579 ; find out if this is the first time
1581 cmp word ptr access_code[0],0 ; access_code = 0, means enabled
1582 jne ose_check_code ; not 0, must check access code
1584 cmp word ptr access_code[2],0 ; access_code = 0, means enabled
1585 jne ose_check_code ; not 0, must check access code
1587 call get_code ; get access code to return
1589 xor ah,ah ; good return code
1592 ; not the first time, must check access code
1596 cmp word ptr access_code[0],bx ; does it match?
1597 jne ose_bad ; no, return access denied error
1599 cmp word ptr access_code[2],cx ; get second word of access code
1600 jne ose_bad ; no, return access denied error
1602 ; access code was OK, enable functions and return no error condition
1604 mov word ptr ose_functions,ose_enabled ; reset enabled flag
1606 xor ah,ah ; good return code
1607 jmp ose_exit ; all done, exit
1610 mov ah,EMS_CODEA4 ; return access denied error code
1613 ret ; return to caller
1617 ;-------------------------------------------------------------------
1619 ; 5d01 - disable OS/E function set
1623 ; BX,CX = Access key
1627 ; AH = 00h, no error
1628 ; 80H, software error
1629 ; 81H, hardware error
1630 ; 84H, invalid function
1631 ; 8FH, invalid subfunction
1632 ; A4H, access denied, incorrect access key supplied
1634 ;-------------------------------------------------------------------
1637 ; find out if this is the first time
1639 cmp word ptr access_code[0],0 ; access_code = 0, means enabled
1640 jne osd_check_code ; not 0, must check access code
1642 cmp word ptr access_code[2],0 ; access_code = 0, means enabled
1643 jne osd_check_code ; not 0, must check access code
1645 ; yes, first time, must set access code and disable fcns
1647 call get_code ; get access code to return
1649 mov word ptr ose_functions,ose_disabled ; disable fcns
1651 xor ah,ah ; good return code
1654 ; not the first time, must check access code
1658 cmp word ptr access_code[0],bx ; does it match?
1659 jne osd_bad ; no, return access denied error
1661 cmp word ptr access_code[2],cx ; get second word of access code
1662 jne osd_bad ; no, return access denied error
1664 ; access code was OK, enable functions and return no error condition
1666 mov word ptr ose_functions,ose_disabled ; disable functions
1668 xor ah,ah ; good return code
1669 jmp osd_exit ; all done, exit
1672 mov ah,EMS_CODEA4 ; return access denied error code
1675 ret ; return to caller
1678 ;-------------------------------------------------------------------
1680 ; 5d02 - return OS/E function set access code
1684 ; BX,CX = Access key
1688 ; AH = 00h, no error
1689 ; 80H, software error
1690 ; 81H, hardware error
1691 ; 84H, invalid function
1692 ; 8FH, invalid subfunction
1693 ; A4H, access denied, incorrect access key supplied
1695 ;-------------------------------------------------------------------
1701 cmp word ptr access_code[0],bx ; does it match?
1702 jne osa_bad ; no, return access denied error
1704 cmp word ptr access_code[2],cx ; get second word of access code
1705 jne osa_bad ; no, return access denied error
1707 ; clear access code and return "no error" return code (AH = 00)
1709 xor ax,ax ; clear ax
1710 mov word ptr access_code[0],ax ; clear access code
1711 mov word ptr access_code[2],ax ; clear access code
1716 mov ah,ems_codeA4 ; access denied error code
1719 ret ; return to caller
1725 ;-------------------------------------------------------------------
1727 ; get_code - returns random access code in cx,dx and stores it in
1728 ; system variable access_code. Access_code is a double-word
1729 ; which is used to save the bx,cx combination making up the
1730 ; "password" for OS/E functions.
1732 ;-------------------------------------------------------------------
1738 ; get a "random" number for first word of access code
1741 call get_rand ; returns "random" num in dx
1742 xor dx,xor_mask ; confuse it a little
1744 cmp dx,0 ; make sure we didn't end up w/0
1747 mov word ptr access_code[0],dx ; save it away
1750 ; get another one for second word of access code
1754 add dx,dx ; confuse it a little
1757 cmp dx,0 ; make sure we didn't end up w/0
1760 mov word ptr access_code[2],dx ; save it away
1761 mov cx,dx ; put second word in cx
1765 ret ; return to caller
1768 ;-------------------------------------------------------------------
1770 ; get_rand - returns a "random" number in dx
1772 ;-------------------------------------------------------------------
1775 push ax ; save some regs
1779 mov ah,read_clock ; function code to read clock
1780 int dos_int ; read the time
1781 ; keep DX since it changes the most
1783 cmp dx,0 ; did we end up with 0?
1784 je redo ; yes, redo it ... never want 0
1786 pop cx ; restore some regs
1789 ret ; return to caller