summaryrefslogtreecommitdiff
path: root/v4.0/src/DEV/XMA2EMS/PS2_5060.INC
blob: 96425f56b8d0aff738ad434715b0f84e448fab52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
;��������������������������������������������������������������������Ŀ
;� Include File: PS2_5060.INC					      �
;�								      �
;� Purpose: Initialization code for the Personal Systems/2	      �
;�	     models 50 and 60.				 	      �
;�								      �
;� Returns: INIT_ERR						      �
;�	      Flag indicating if an error was detected. 	      �
;�	      DX = ptr to error message string if error.	      �
;�								      �
;�    This procedure is called to initialize the XMO and/or XMA/A     �
;�  card(s) on a PS/2 mod 50 or 60.  Any mix of multiple XMA and      �
;�  XMO cards are supported.  The XMA cards will be used in	      �
;�  'real' mode, meaning the virtual mode ports providing bank        �
;�  swapping are not used (since this only works on 1 XMA card).      �
;�  This procedure is not called if WSP's XMA/A device driver         �
;�  (INDXMAA.SYS) is installed.  In this case only the single XMA     �
;�  card is used for EMS, and it is spoken to in 'virtual' mode.      �
;�    The procedure searches each adapter slot for the presence of    �
;�  an XMA or a XMO card by checking the card ID.  It checks	      �
;�  the configuration registers on the cards to determine the amount  �
;�  of memory they contain.					      �
;�    The procedure will then calculate for the /E parameter.  This   �
;�  states how much of the extended memory the user wants for EMS.    �
;�  Extended memory will come from the top of the address range,      �
;�  and EMS will come off the bottom (i.e. starting at 1M+384K).      �
;�  Memory kept as extended has to be marked unusable in the Page     �
;�  Allocation List.  Translate table entries in extended memory      �
;�  are disabled for memory used for EMS.			      �
;�    Note that the /E parameter is only valid within this	      �
;�  procedure, i.e. for PS/2 mod 50 and 60's.  On family 1 machines,  �
;�  only the XMA 1 card is supported, and it doesn't come up as       �
;�  extended memory.  On mod 50 or 60 with the XMA/A driver, the      �
;�  driver takes all of the (uppermost) XMA card and resets CMOS.     �
;�  On the mod 80 with the XMA emulator, this XMA/extended split      �
;�  must be specified on the Emulator's parm line.                    �
;�								      �
;����������������������������������������������������������������������

include SYSVAR.INC			;system variables structure		;an007; dms;


			     ;������������������������������������������������Ŀ
			     ;�   XMA/A declares			       �
			     ;��������������������������������������������������
HI6BIT_MASK	EQU  00000011b		;Mask for 2 bit bank descriptor
LO2BIT_FLIP	EQU  00000011b		;Reverses bottom 2 bits in bank des
					; gives # of 1/2M in that bank
NUM_CONFR_BANKS EQU 3			;Number of memory banks described
					; by the XMA/A config register
					; Bank 4 is on the control reg.
X_CONF_REG_VAL	   DB	?		;temporary holder for XMAA's
					; config (memory size) register
X_CTRL_REG_VAL	   DB	?		;temporary holder for XMAA's
					; control (mem size bank 4) reg.
X_BLKS_PER_HALFM   DB  128		;4K blocks per half meg of memory
XMAA_NUM_BLOCKS DW	?		;temp for # of 4K blocks on xmaa   @RH2
			     ;������������������������������������������������Ŀ
			     ;�   Expanded Memory Option (XMO) declares	       �
			     ;��������������������������������������������������
NUM_CINFO_BANKS EQU 3			;# of complete memory banks (4-2)
					; described by the XMO card info reg
					; Bank 1 - hi 1/2 bit - info, lo CC/P
H_CARD_INFO_VAL    DB	?		;temporary holder for XMO card's
					; info (memory size) register
H_BLKS_PER_HALFM   DB	32		;16K XMO card blocks per 1/2M of mem
HLST_NUM_BLOCKS DW	?		;temp for # of 16K blocks on hlstr @RH3
			     ;������������������������������������������������Ŀ
			     ;�   /E option declares			       �
			     ;�    (used to set extended memory)	       �
			     ;��������������������������������������������������
ems_pgs_parm   dw    0			;temp value for /E parameter
e_parm_def     equ   0FFFFh		;default...take all for ems
MIN_EXTMEM_H   EQU   (1024+384)/16	;Translate table pointer for the lowest
MIN_EXTMEM_X   EQU   (1024+384)/4	; addr extended memory can start at on
BASE_MEM       EQU   1024		;Base planer memory			;an007; dms;
					; a PS/2 (16K XMO and 4K XMA)
PREV_EXT_PGS   DW    0			;Extended memory claimed by previous
					; drivers
NEEDED_EMS_PGS DW    ?			;Pages that will go for EMS use
CARDS_PGS      DW    ?			;Number of pages on card being checked
CARD_EXT_S16K  DW    ?			; and where its extended memory starts
					; expressed in 16K blocks

INIT_MOD_50_60	PROC

	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	SI
	PUSH	DI

	MOV	INIT_ERR,NO_ERROR	;Initialize error flag		   @RH4
	MOV	TOTAL_SYS_PAGES,0	;Init total number of pages in the @RH2
	MOV	NUM_MEM_CARDS,0 	; system & # of memory cards found @RH2
	XOR	DI,DI			;Clear offset into mem card table  @RH2

			;�����������������������������������������������������Ŀ
			;� Search for XMO cards			  	       �
			;�������������������������������������������������������
	XOR	CX,CX			;Check all system slots starting   @RH2
					; at slot 0			    RH2
H_SLOT_SCAN:
	MOV	AL,CL			;Enable the specific slot by ORing @RH2
	OR	AL,SLOT_SETUP		; the slot (bits 0-2) with the	   @RH2
	OUT	96h,AL			; setup flag (bit 3).		   @RH2

	MOV	DX,CARD_ID_LO		;Read the signature ID of the card @RH2
	IN	AL,DX			;				   @RH2
	XCHG	AL,AH			;				   @RH2
	MOV	DX,CARD_ID_HI		;				   @RH2
	IN	AL,DX			;				   @RH2
HLST_CHECK:
	CMP	AX,HLST_CARD_ID 	;If it's a XMO card then 	   @RH3
	JNE	H_NEXT_SLOT		; calculate the amount of memory   @RH3
	CALL	HLST_MEM_ADD		; on the card			   @RH3
	MOV	WTT_CARD_SLOT,CL	;Set default slot # and card type  @RH5
	MOV	MEMCARD_MODE,HOLS_REAL	; for single card support	   @RH5

	MOV	BX,HLST_NUM_BLOCKS	;1 XMO card block = an EMS page

				       ;��������������������������������������Ŀ
				       ;� Save info in the memory card table   �
				       ;����������������������������������������
	MOV	MEM_CARD_TABLE.CARD_ID[DI],AX	   ;Save the card ID and   @RH5
	MOV	MEM_CARD_TABLE.CARD_SLOT[DI],CL    ; slot # of this card   @RH5
	MOV	AX,TOTAL_SYS_PAGES		   ;Set # of the 1st EMS   @RH5
	MOV	MEM_CARD_TABLE.START_PG_NUM[DI],AX ; page this card maps   @RH5
	ADD	AX,BX				   ;Last page mapped =	   @RH5
	DEC	AX				   ; 1st pg + pages on	   @RH5
	MOV	MEM_CARD_TABLE.END_PG_NUM[DI],AX   ;  this card - 1.	   @RH5

	ADD	TOTAL_SYS_PAGES,BX		   ;Add card's pgs to tot. @RH5
	INC	NUM_MEM_CARDS			   ;Inc # of cards found   @RH5
	ADD	DI,TYPE MEM_CARD_STRUC		   ;Next entry in card	   @RH5
						   ; descriptor table	    RH5

H_NEXT_SLOT:
	INC	CL				 ;Check next adapter slot  @RH2
	CMP	CL,NUM_OF_SLOTS 		 ;Is it <= system slots?   @RH2
	JB	H_SLOT_SCAN			 ;Yes..check next slot		;ac000; dms;
						 ;No fall through loop	    RH2

			;�����������������������������������������������������Ŀ
			;� Search for XMA/A cards			       �
			;�������������������������������������������������������
	XOR	CX,CX			;Check all slots starting at 0	   @RH2
X_SLOT_SCAN:
	MOV	AL,CL			;Enable the specific slot by ORing @RH2
	OR	AL,SLOT_SETUP		; the slot (bits 0-2) with the	   @RH2
	OUT	96h,AL			; setup flag (bit 3).		   @RH2

	MOV	DX,CARD_ID_LO		;Read the signature ID of the card @RH2
	IN	AL,DX			;				   @RH2
	XCHG	AL,AH			;				   @RH2
	MOV	DX,CARD_ID_HI		;				   @RH2
	IN	AL,DX			;				   @RH2
XMAA_CHECK:
	CMP	AX,XMAA_CARD_ID 	;If it's an XMA/A card then        @RH2
	JNE	X_NEXT_SLOT		; calculate the amount of memory   @RH2
	CALL	XMAA_MEM_ADD		; on the card			   @RH2
	MOV	WTT_CARD_SLOT,CL	;Set default slot # and card type  @RH5
	MOV	MEMCARD_MODE,XMAA_REAL	; for single card support	   @RH5

	MOV	BX,XMAA_NUM_BLOCKS	;Divide the # of 4K XMA/A blocks   @RH2
	SHR	BX,1			; by 4 to get number or 16K EMS    @RH2
	SHR	BX,1			; pages on this card		   @RH2

				       ;��������������������������������������Ŀ
				       ;� Save info in the memory card table   �
				       ;����������������������������������������
	MOV	MEM_CARD_TABLE.CARD_ID[DI],AX	   ;Save the card ID and   @RH5
	MOV	MEM_CARD_TABLE.CARD_SLOT[DI],CL    ; slot # of this card   @RH5
	MOV	AX,TOTAL_SYS_PAGES		   ;Set # of the 1st EMS   @RH5
	MOV	MEM_CARD_TABLE.START_PG_NUM[DI],AX ; page this card maps   @RH5
	ADD	AX,BX				   ;Last page mapped =	   @RH5
	DEC	AX				   ; 1st pg + pages on	   @RH5
	MOV	MEM_CARD_TABLE.END_PG_NUM[DI],AX   ;  this card - 1.	   @RH5

	ADD	TOTAL_SYS_PAGES,BX		   ;Add card's pgs to tot. @RH5
	INC	NUM_MEM_CARDS			   ;Inc # of cards found   @RH5
	ADD	DI,TYPE MEM_CARD_STRUC		   ;Next entry in card	   @RH5
						   ; descriptor table	    RH5

X_NEXT_SLOT:
	INC	CL				 ;Check next adapter slot  @RH2
	CMP	CL,NUM_OF_SLOTS 		 ;Is it <= system slots?   @RH2
	JB	X_SLOT_SCAN			 ;Yes..check next slot		;ac000; dms;
						 ;No fall through loop	    RH2

	CMP	TOTAL_SYS_PAGES,0	;If one or more cards are found    @RH4
	JA	CALC_EXTENDED		; then everythang's cool so far    @RH4
	    MOV     INIT_ERR,ERROR		 ;Else no card...set	   @RH4
	    MOV     DX,OFFSET NOT_FOUND_MSG	 ; 1st part of error msg   @RH4
	    JMP     INIT_50_60_RET		 ; for no card found	   @RH4

			;�����������������������������������������������������Ŀ
			;� Calculate /E parameter - amount of memory for EMS   �
			;�������������������������������������������������������
					;������������������������������������Ŀ
					;� Find ext mem addr of bottom card   �
					;� in case card memory ever starts at �
					;� something other than 1M + 384K     �
					;� (i.e. if more planar memory is     �
					;�  added or a new unsupported card   �
					;�  comes in below XMO card)	      �
					;��������������������������������������
CALC_EXTENDED:
	push	es			;this call kills these regs		;an007; dms;
	push	bx			;					;an007; dms;

	mov	ah,52h			;get the sysvars ptr			;an007; dms;
	int	21h			; to get total ext. memory at boot	;an007; dms;
	mov	ax,word ptr es:[bx].SYSI_Ext_Mem	;			;an007; dms;

	pop	bx			;restore regs				;an007; dms;
	pop	es			;					;an007; dms;

	add	ax,Base_Mem		; + base memory 			;an007; dms;
	MOV	CL,4			; convert to 16Kb pages 		;an007; dms;
	SHR	AX,CL			;					;an007; dms;
	sub	ax,cs:Total_Sys_Pages	;get page where card begins		;an007; dms;

	xor	di,di			;init. index value			;an008; dms
	CMP	MEM_CARD_TABLE.CARD_ID[DI],HLST_CARD_ID ;If 1st card holst @RH4
	JE	FIND_H_1ST_TT				; then get hlst TT @RH4
FIND_X_1ST_TT:				;XMAA is 1st card (lowest ext mem) @RH4
;;;;;	MOV	AX,MIN_EXTMEM_X 	;Set XMAA TT ptr at 1.384M and	   @RH4
	shl	ax,1			;					;an000; dms;
	shl	ax,1			;					;an000; dms;
FIND_X_1ST_LOOP:			; search for start of ext mem	   @RH4
	CALL	X_READ_TT		;Read trans tbl data at this addr  @RH4
	CMP	BX,XMA_TT_INHIBIT	;If not inhibitted then mem here.  @RH4
	JE	FIND_X_1ST_NEXT 	;Divide the 4K translate table ptr @RH4
	MOV	CL,2			; by 4 to convert it to 16K format @RH4
	SHR	AX,CL			; AX = start of ext mem (in 16K)   @RH4
	JMP	FIRST_EXT_FOUND 	;				   @RH4
FIND_X_1ST_NEXT:			;				   @RH4
	INC	AX			;Else no mem...inc TT ptr and see  @RH4
	JMP	FIND_X_1ST_LOOP 	; if ext mem starts at next 4K	   @RH4

FIND_H_1ST_TT:				;XMO is 1st card (lowest ext mem)  @RH4
;;;;;	MOV	AX,MIN_EXTMEM_H 	;Set hlst TT ptr at 1.384M and	   @RH4
FIND_H_1ST_LOOP:			; search for start of ext mem	   @RH4
	CALL	H_READ_TT		;Read trans tbl data at this addr  @RH4
	CMP	BL,H_TT_INHIBIT 	;If not inhibitted then mem here.  @RH4
	JNE	FIRST_EXT_FOUND 	; found start of card ext mem	   @RH4
	INC	AX			;Else no mem...inc TT ptr and see  @RH4
	JMP	FIND_H_1ST_LOOP 	; if ext mem starts at next 16K    @RH4
FIRST_EXT_FOUND:
	MOV	CARD_EXT_S16K,AX	;Save the start of ext mem ptr	   @RH4
					;������������������������������������Ŀ
					;� Calc pages for extended memory     �
					;��������������������������������������
	MOV	AH,88H			;Go to BIOS and find amount of	   @RH4
	INT	15H			; extended memory (assume previous @RH4
	MOV	CL,4			; drivers have hooked INT 15h)	   @RH4
	SHR	AX,CL			;Get # of 16k pages		   @RH4

	MOV	BX,CARD_EXT_S16K	;Pages of extended memory used	   @RH4
	ADD	BX,TOTAL_SYS_PAGES	; by previous drivers = 	   @RH4
	SUB	BX,1024/16		; what we know is the # of ext	   @RH4
	SUB	BX,AX			; pages minus what BIOS tells us   @RH4
	MOV	PREV_EXT_PGS,BX 	;				   @RH4

	CMP	EMS_PGS_PARM,E_PARM_DEF ;If no /E parm specified then	   @RH4
	JNE	CHECK_E_PARM		; use the remaining pages for EMS  @RH4
	MOV	AX,TOTAL_SYS_PAGES	; (total on cards minus previously @RH4
	cmp	Prev_Ext_Pgs,ax 	;Previous ext pages >= avail on cards?	;an000; dms;
	jae	Default_Mem_Err_Exit	;yes - we have used the whole card	;an000; dms;
	SUB	AX,PREV_EXT_PGS 	; used for extended memory)	   @RH4
	MOV	NEEDED_EMS_PGS,AX	;Set counter for marking PAL and TT@RH4
	JMP	SHORT MARK_EXT_IN_PAL

Default_Mem_Err_Exit:

	mov	Init_Err,Error		;flag an error occurred 		;an000; dms;
	lea	dx,No_EMS_Memory	;no memory on cards left		;an000; dms;
	jmp	Init_50_60_Ret		;exit routine				;an000; dms;

CHECK_E_PARM:				;Else test user specified # EMS pgs@RH4
	MOV	BX,EMS_PGS_PARM 	;Set counter for marking Page	   @RH4
	MOV	NEEDED_EMS_PGS,BX	; Allocation List and TT entries   @RH4
	MOV	AX,TOTAL_SYS_PAGES	;If the requested EMS pages are    @RH4
	SUB	AX,PREV_EXT_PGS 	; more than what's left            @RH4
	CMP	AX,EMS_PGS_PARM 	; (total pages minus pages	   @RH4
	JGE	MARK_EXT_IN_PAL 	; used by other drivers) then set  @RH4
	    MOV     INIT_ERR,ERROR	; an error condition flag	   @RH4
	    LEA     DX,REQ_EMS_ERR_MSG	; Set first part of error message  @RH4
	    JMP     INIT_50_60_RET	;				   @RH4

					;������������������������������������Ŀ
					;� Mark PAL for extended memory pages �
					;��������������������������������������
MARK_EXT_IN_PAL:
	xor	di,di			;start at bottom of PAL to init EXT	;an002; dms;
MARK_NEW_IN_PAL:
	MOV	CX,TOTAL_SYS_PAGES	;Loop for the 'new' extended pages @RH4
	SUB	CX,NEEDED_EMS_PGS	; (left over from /E parm and not  @RH4
	SUB	CX,PREV_EXT_PGS 	; reserved by a previous driver)   @RH4
	MOV	RESR_EXT_PGS,CX 	;				   @RH4
	CMP	CX,0			; This assumes that others anyone  @RH4
	JE	MARK_PREV_IN_PAL	; using extended memory after us   @RH4
MARK_NEW_LP:				; will take it from the top	   @RH4
	MOV	PAGE_ALLOC_LIST[DI],RESR_EXT	 ;Place a 'RE' in the PAL  @RH4
	ADD	DI,TYPE PAGE_ALLOC_LIST 	 ; (Reserved Extended) for @RH4
	LOOP	MARK_NEW_LP			 ; these entries	   @RH4

MARK_PREV_IN_PAL:
	MOV	AX,NEEDED_EMS_PGS	;Set offset into Page Alloc List   @RH4
	add	ax,Resr_Ext_Pgs 	;get end of area for EMS pages		;an002; dms;
	MOV	DX,TYPE PAGE_ALLOC_LIST ; for the page where extended mem  @RH4
	MUL	DX			; starts.  This is done by skipping@RH4
	MOV	DI,AX			; over the EMS pages on bottom	   @RH4
	MOV	CX,PREV_EXT_PGS 	;Loop for the previous extended    @RH4
	CMP	CX,0			; memory pages (if any).  This is  @RH4
	JE	DIS_EMS_TT		; ext mem claimed before we load   @RH4
MARK_PREV_LP:				;				   @RH4
	MOV	PAGE_ALLOC_LIST[DI],PREV_EXT	 ;Place a 'PE' in the PAL  @RH4
	ADD	DI,TYPE PAGE_ALLOC_LIST 	 ; (Previous Extended) for @RH4
	LOOP	MARK_PREV_LP			 ; these entries	   @RH4
					;������������������������������������Ŀ
					;� Disable translate table entries    �
					;� in extended memory for memory      �
					;� used as EMS			      �
					;��������������������������������������

DIS_EMS_TT:

	mov	cx,Resr_Ext_Pgs 		;get extended page count	;ac008; dms;
						;1 based page count

	xor	di,di				;set mem card table ptr 	;an002; dms;

Card_Find_Chk:

	cmp	cx,Mem_Card_Table.End_Pg_Num[di];page > ending page on card?	;ac008; dms;
	ja	Card_Find_Loop			;yes - next card please 	;an002; dms;
	add	Card_Ext_S16K,cx		;get 1st. avail page		;an008; dms;
	mov	cx,Mem_Card_Table.End_Pg_Num[di];Calc # pages remaining on card ;an002; dms;
	sub	cx,Resr_Ext_Pgs 		;				;ac008; dms;
	inc	cx				;				;an002; dms;
	jmp	Calc_Cards_EMS			;				;an002; dms;

Card_Find_Loop:

	add	di,Type Mem_Card_Struc		;next pointer			;an002; dms;
	jmp	Card_Find_Chk			;continue loop			;an002; dms;


CALC_CARDS_EMS:

	MOV	CARDS_PGS,CX			      ; 		   @RH4

					;Calc # of pages to inhibit for.   @RH4
	CMP	CX,NEEDED_EMS_PGS	;If the card has less pgs than	   @RH4
	JBE	ADJUST_NEEDED_EMS	; # needed for EMS then just loop  @RH4
	MOV	CX,NEEDED_EMS_PGS	; for card.  Else loop for needed. @RH4

ADJUST_NEEDED_EMS:
	SUB	NEEDED_EMS_PGS,CX	;Remaining EMS pages to inhibit    @RH4
					; after this card is taken care of @RH4

	MOV	AL,MEM_CARD_TABLE.CARD_SLOT[DI]  ;Activate the slot of	   @RH4
	OR	AL,SLOT_SETUP			 ; the card and set ptr    @RH4
	OUT	96h,AL				 ; to where it's ext mem   @RH4
	MOV	AX,CARD_EXT_S16K		 ; starts		   @RH4

	CMP	MEM_CARD_TABLE.CARD_ID[DI],HLST_CARD_ID    ;Test card type @RH4
	JE	H_INHIBIT_EMS				   ;		   @RH4
X_INHIBIT_EMS:				;Inhibit TT on XMA/A for EMS	   @RH4
	PUSH	CX			;Save ctr for # EMS on this card   @RH4
	MOV	CL,2			;Convert 16K start of EMS ptr to   @RH4
	SHL	AX,CL			; 4K XMA/A translate table format  @RH4
	POP	CX			;Restore # EMS pages counter	   @RH4
X_INH_EMS_PGS:				;----Loop for all XMA EMS pages----@RH4
	PUSH	CX			;Save # EMS pages ctr		   @RH4
	MOV	CX,BLOCKS_PER_PAGE	;Loop for all XMA blocks in a pg   @RH4
X_INH_ONE_PAGE: 			;----Loop for one XMA EMS page-----@RH4
	CALL	X_INH_FOR_EMS		;Inhibit TT entry (AX = 4K ptr)    @RH4
	INC	AX			;Next XMA block 		   @RH4
	LOOP	X_INH_ONE_PAGE		;				   @RH4
	POP	CX			;Restore ctr for # EMS pgs on card @RH4
	LOOP	X_INH_EMS_PGS		;Loop for # EMS pgs on card	   @RH4
	JMP	short next_card_ems	;Now go fix that page alloc table  @RH4

H_INHIBIT_EMS:				;Inhibit TT on XMO for EMS	   @RH4
	CALL	H_INH_FOR_EMS		;Inhibit one TT entry per EMS page @RH4
	INC	AX			;Next 16K pointer		   @RH4
	LOOP	H_INHIBIT_EMS		; and do it again yahoooooo	   @RH4

NEXT_CARD_EMS:
	CMP	NEEDED_EMS_PGS,0	;If this card had the rest of the  @RH4
	JE	INIT_50_60_RET		; EMS pages then done disabling TT @RH4
					;Else EMS on next card.  Set ptr   @RH4
	MOV	AX,CARDS_PGS		; to where next card's ext mem     @RH4
	ADD	CARD_EXT_S16K,AX	; starts (in units of 16K) and save@RH4

	ADD	DI,TYPE MEM_CARD_STRUC	;Next entry in the memory card	   @RH4

	mov	cx,Mem_Card_Table.End_Pg_Num[di]	;calc pages on		;an002; dms;
	sub	cx,Mem_Card_Table.Start_Pg_Num[di]	;card			;an002; dms;
	inc	cx					;			;an002; dms;

	JMP	CALC_CARDS_EMS		; table.			   @RH4

INIT_50_60_RET:

	MOV	AX,TOTAL_SYS_PAGES	;Total EMS pages in the system =   @RH4
	SUB	AX,PREV_EXT_PGS 	; pages on cards - amount used	   @RH4
	SUB	AX,RESR_EXT_PGS 	; as extended memory		   @RH4
	MOV	TOTAL_SYS_PAGES,AX	;Initialize values for: 	   @RH4
	MOV	TOTAL_EMS_PAGES,AX	; EMS pages - pages to back planar @RH4
	MOV	FREE_PAGES,AX		; EMS pages free for applications  @RH4

	MOV	AL,0			;Reset the slot ID		   @RH5
	OUT	96h,AL			;				   @RH5

	POP	DI
	POP	SI
	POP	CX
	POP	BX
	POP	AX
	RET
INIT_MOD_50_60	ENDP

;��������������������������������������������������������������������Ŀ
;� HLST_MEM_ADD subprocedure					      �
;�   Calculates the amount of memory on the XMO card		      �
;�     on entry: (CL) = card slot #				      �
;�		 card is in setup mode				      �
;�								      �
;�  The following describes how to read memory size, where the 2 bit  �
;�   pattern indicates SIP size.  There are 2 SIPs per bank.	      �
;�								      �
;�   Reg:   Card Info			      Channel Check, Presence �
;�   Port:   102h			       105h		      �
;�   SIPS:   bank 4  bank 3  bank 2  bank 1    bank 1		      �
;�   Bit:     7  6    5  4    3  2    1 	   0		      �
;�   -----------------------------------------------------------------�
;�	      1  1    1  1    1  1    1 	   1  No memory,error �
;�	      1  0    1  0    1  0    1 	   0  256K	      �
;�	      0  1    0  1    0  1    0 	   1  512K	      �
;�	      0  0    0  0    0  0    0 	   0  1M	      �
;�								      �
;� Note that for bank 0, 102's bit 1 forms the upper bit and          �
;�  105's bit 0 forms the lower of the 2 bit presence pattern.        �
;�  Therefore, if the pattern is '10'B, then the bank has 256K.       �
;�								      �
;����������������������������������������������������������������������
HLST_MEM_ADD  PROC
	PUSH	DX			;				   @RH3
	PUSH	CX			;				   @RH3
	PUSH	AX			;				   @RH3

	MOV	HLST_NUM_BLOCKS,0	;Init # of 16K blocks on card	   @RH3

	MOV	DX,H_CARD_INFO		;Read & store card info reg (102h) @RH3
	IN	AL,DX			; bits 7-2 describe banks 4-2	   @RH3
	AND	AL,11111110B		; bit 1 upper half of bank 1 descr @RH3
	MOV	H_CARD_INFO_VAL,AL	; (don't care about sleep bit 0)   @RH3
	MOV	DX,H_CC_PRES		;Read chan. check & presence (105) @RH3
	IN	AL,DX			; for bit 0 - lower half of bank 1 @RH3
	AND	AL,00000001B		; Turn off all other bits	   @RH3
	OR	AL,H_CARD_INFO_VAL	;Join 2 bits - bank 1 descriptor   @RH3

	XOR	AL,LO2BIT_FLIP		;Flip these 2 to get # of 1/2 Megs @RH3
					; in bank 1 of XMO card		   @RH3
	AND	AL,HI6BIT_MASK		;Clear other bits		   @RH3
	CMP	AL,LO2BIT_FLIP		;Are both bits on (i.e. 1M sips)?  @RH3
	JNE	H_B1_HMEG_OK		;No  # of 1/2 M for bank OK (0,1,2)@RH3
	INC	AL			;Yes # of 1/2 M should be 4 not 3  @RH3
H_B1_HMEG_OK:
	MUL	H_BLKS_PER_HALFM	;Multiply by # of 16k Blocks per   @RH3
					; half meg to get bank's blocks    @RH3
	ADD	HLST_NUM_BLOCKS,AX	;Add bank 1 to the total	   @RH3

	SHR	H_CARD_INFO_VAL,1	;Shift bank 4-2 descriptors to	   @RH3
	SHR	H_CARD_INFO_VAL,1	; bits 0-5			   @RH3

	MOV	CX,NUM_CINFO_BANKS	; Loop for banks accounted for by  @RH3
					; the XMO card info register	   @RH3
HLST_MEM_LOOP:
	MOV	AL,H_CARD_INFO_VAL	;Get 2 bit bank descriptor & flip  @RH3
	XOR	AL,LO2BIT_FLIP		; the 2 bits.  Bits now indicate   @RH3
					; the # of 1/2 meg in the bank	   @RH3
	AND	AL,HI6BIT_MASK		;Ignore other banks		   @RH3
	CMP	AL,LO2BIT_FLIP		;Are both bits on (i.e. 1M sips)?  @RH3
	JNE	H_B42_HMEG_OK		;No  # of 1/2 M for bank OK (0,1,2)@RH3
	INC	AL			;Yes # of 1/2 M should be 4 not 3  @RH3
H_B42_HMEG_OK:
	MUL	H_BLKS_PER_HALFM	;Multiply by # of 4k blocks per    @RH3
					; half meg to get bank's blocks    @RH3
	ADD	HLST_NUM_BLOCKS,AX	;Add XMO banks 4-2 to total	   @RH3
	SHR	H_CARD_INFO_VAL,1	;Get next bank			   @RH3
	SHR	H_CARD_INFO_VAL,1	;				   @RH3
	LOOP	HLST_MEM_LOOP		;				   @RH3

	POP	AX			;				   @RH3
	POP	CX			;				   @RH3
	POP	DX			;				   @RH3

	RET
HLST_MEM_ADD  ENDP

;��������������������������������������������������������������������Ŀ
;� XMAA_MEM_ADD subprocedure					      �
;�   Calculates the amount of memory on the XMAA card		      �
;�     on entry: (CL) = card slot #				      �
;�		 card is in setup mode				      �
;�								      �
;�  The following describes how to read memory size, where the 2 bit  �
;�   pattern indicates SIP size.  There are 2 SIPs per bank.	      �
;�								      �
;�   Reg:   Control Reg    Config, Channel Check reg		      �
;�   Port:   102h	    105h				      �
;�   SIPS:   bank 4	    bank 3  bank 2  bank 1		      �
;�   Bit:     7  6	     5	4    3	2    1	0		      �
;�   -------------------------------------------------		      �
;�	      1  1	     1	1    1	1    1	1  No memory or error �
;�	      1  0	     1	0    1	0    1	0  256K 	      �
;�	      0  1	     0	1    0	1    0	1  512K 	      �
;�	      0  0	     0	0    0	0    0	0  1M		      �
;�								      �
;����������������������������������������������������������������������
XMAA_MEM_ADD  PROC
	PUSH	DX			;				   @RH2
	PUSH	CX			;				   @RH2
	PUSH	AX			;				   @RH2

					;Insure XMA/A init ROM is disabled @RH2
					;When the high byte of the TT data @RH2
	MOV	DX,X_CTRL_REG
	IN	AL,DX			; is read or written using port    @RH2
	MOV	X_CTRL_REG_VAL,AL	  ;  SAVE FOR MEM COUNT
	AND	AL,CR_ROMSLEEP_DIS	; 104h (real mode), the upper	   @RH2
	OUT	DX,AL			; nibble has info for setting the  @RH2
					; initialization ROM addresses. To @RH2
					; insure this causes no problems,  @RH2
					; disable XMA/A ROM by clearing    @RH2
					; ROM sleep bit in the control reg @RH2

	MOV	XMAA_NUM_BLOCKS,0	;				   @RH2

	MOV	AL,X_CTRL_REG_VAL	;Get bits 6&7 of control register  @RH2
	MOV	CL,6			; to get memory configuration of   @RH2
	SHR	AL,CL			; bank 4			   @RH2
	XOR	AL,LO2BIT_FLIP		;Flip these 2 to get # of 1/2M	   @RH2
					; in bank 4 of XMA/A card	   @RH2
	AND	AL,HI6BIT_MASK		;Clear other bits		   @RH2
	CMP	AL,LO2BIT_FLIP		;Are both bits on (i.e. 1M sips)?  @RH2
	JNE	CTRL_HMEG_OK		;No  # of 1/2 M for bank OK (0,1,2)@RH2
	INC	AL			;Yes # of 1/2 M should be 4 not 3  @RH2
CTRL_HMEG_OK:
	MUL	X_BLKS_PER_HALFM	;Multiply by # of 4k blocks per    @RH2
					; half meg to get bank's blocks    @RH2
	ADD	XMAA_NUM_BLOCKS,AX


	MOV	DX,X_CONF_REG		;Read the config, channel check    @RH2
	IN	AL,DX			; register to get mem size of	   @RH2
	MOV	X_CONF_REG_VAL,AL	; banks 1-3			   @RH2

	MOV	CX,NUM_CONFR_BANKS	; Loop for banks accounted for by  @RH2
					; the config register		   @RH2
XMAA_MEM_LOOP:
	MOV	AL,X_CONF_REG_VAL	;Get 2 bit bank descriptor & flip  @RH2
	XOR	AL,LO2BIT_FLIP		; the 2 bits.  Bits now indicate   @RH2
					; the # of 1/2 meg in the bank	   @RH2
	AND	AL,HI6BIT_MASK		;Ignore other banks		   @RH2
	CMP	AL,LO2BIT_FLIP		;Are both bits on (i.e. 1M sips)?  @RH2
	JNE	CONF_HMEG_OK		;No  # of 1/2 M for bank OK (0,1,2)@RH2
	INC	AL			;Yes # of 1/2 M should be 4 not 3  @RH2
CONF_HMEG_OK:
	MUL	X_BLKS_PER_HALFM	;Multiply by # of 4k blocks per    @RH2
					; half meg to get bank's blocks    @RH2
	ADD	XMAA_NUM_BLOCKS,AX	;				   @RH2
	SHR	X_CONF_REG_VAL,1	;Get next bank			   @RH2
	SHR	X_CONF_REG_VAL,1	;				   @RH2
	LOOP	XMAA_MEM_LOOP		;				   @RH2

	POP	AX			;				   @RH2
	POP	CX			;				   @RH2
	POP	DX			;				   @RH2

	RET
XMAA_MEM_ADD  ENDP

;��������������������������������������������������������������������Ŀ
;� H_READ_TT subprocedure					      �
;�   Reads the contents of a translate table entry on a XMO card      �
;�     on entry: (AX) = Translate table pointer 		      �
;�     on exit:  (BL) = Data (byte) at that entry		      �
;�								      �
;����������������������������������������������������������������������
H_READ_TT	PROC
	PUSH	AX			;Save the TT pointer		   @RH4
	MOV	DX,H_TTPTR_LO		;Set the low and high bytes of	   @RH4
	OUT	DX,AL			; the XMO translate table	   @RH4
	XCHG	AL,AH			; pointer, then read the value	   @RH4
	MOV	DX,H_TTPTR_HI		; of the data for that entry	   @RH4
	OUT	DX,AL			;				   @RH4
	MOV	DX,H_TTDATA		;				   @RH4
	IN	AL,DX			;Read the data into AL		   @RH4
	MOV	BL,AL			; and store it in BL		   @RH4
	POP	AX			;Restore TT pointer		   @RH4
	RET				;				   @RH4
H_READ_TT	ENDP

;��������������������������������������������������������������������Ŀ
;� X_READ_TT subprocedure					      �
;�   Reads the contents of a translate table entry on an XMA/A card   �
;�     on entry: (AX) = Translate table pointer 		      �
;�     on exit:  (BX) = Data (12 bits) at that entry		      �
;�								      �
;����������������������������������������������������������������������
X_READ_TT	PROC
	PUSH	AX			;Save the TT pointer		   @RH4
	MOV	DX,RM_TTPTR_LO		;Set the low and high bytes of	   @RH4
	OUT	DX,AL			; the XMA/A translate table	   @RH4
	XCHG	AL,AH			; pointer, then read the value	   @RH4
	MOV	DX,RM_TTPTR_HI		; of the data for that entry	   @RH4
	OUT	DX,AL			;				   @RH4

	MOV	DX,RM_TTDATA_HI 	;Read 12 bit TT data high byte	   @RH4
	IN	AL,DX			; first, then read low byte.	   @RH4
	XCHG	AL,AH			;				   @RH4
	MOV	DX,RM_TTDATA_LO 	;				   @RH4
	IN	AL,DX			;				   @RH4
	MOV	BX,AX			;Store result in BX		   @RH4
	AND	BX,XMA_TT_MASK		;Turn off useless upper 4 bits	   @RH4
	POP	AX			;Restore TT pointer		   @RH4
	RET				;				   @RH4
X_READ_TT	ENDP

;��������������������������������������������������������������������Ŀ
;� H_INH_FOR_EMS subprocedure					      �
;�   Inhibits a single translate table entry of extended memory       �
;�   on a XMO card.  This entry (16K) is for use by EMS.	      �
;�     on entry: (AX) = XMO Translate table pointer (# of K / 16)     �
;�								      �
;����������������������������������������������������������������������
H_INH_FOR_EMS	PROC
	PUSH	AX			;Save the TT pointer		   @RH4
	MOV	DX,H_TTPTR_LO		;Set the low and high bytes of	   @RH4
	OUT	DX,AL			; the XMO translate table	   @RH4
	XCHG	AL,AH			; pointer,			   @RH4
	MOV	DX,H_TTPTR_HI		;				   @RH4
	OUT	DX,AL			;				   @RH4

	MOV	AL,H_TT_INHIBIT 	;AL = XMO TT inhibit data	   @RH4
	MOV	DX,H_TTDATA		;Inhibit this TT entry so that	   @RH4
	OUT	DX,AL			; it is no longer extended memory  @RH4
	POP	AX			;Restore TT pointer		   @RH4
	RET				;				   @RH4
H_INH_FOR_EMS	ENDP

;��������������������������������������������������������������������Ŀ
;� X_INH_FOR_EMS subprocedure					      �
;�   Inhibits a single translate table entry of extended memory       �
;�   on a XMA/A card.  This entry (4K) is for use by EMS.	      �
;�     on entry: (AX) = XMA/A Translate table pointer (# of K / 4)    �
;�								      �
;����������������������������������������������������������������������
X_INH_FOR_EMS	PROC
	PUSH	AX			;Save the TT pointer		   @RH4
	MOV	DX,RM_TTPTR_LO		;Set the low and high bytes of	   @RH4
	OUT	DX,AL			; the XMA/A translate table	   @RH4
	XCHG	AL,AH			; pointer, then read the value	   @RH4
	MOV	DX,RM_TTPTR_HI		; of the data for that entry	   @RH4
	OUT	DX,AL			;				   @RH4

	MOV	AX,XMA_TT_INHIBIT	;AX = XMA 12 bit TT inhibit data   @RH4
	MOV	DX,RM_TTDATA_LO 	;Write 12 bit TT data low byte	   @RH4
	OUT	DX,AL			; first, then write high byte.	   @RH4
	XCHG	AL,AH			;				   @RH4
	MOV	DX,RM_TTDATA_HI 	;				   @RH4
	OUT	DX,AL			;				   @RH4
	POP	AX			;Restore TT pointer		   @RH4
	RET				;				   @RH4
X_INH_FOR_EMS	ENDP

;��������������������������������������������������������������������Ŀ
;� ADJUST_CMOS subprocedure					      �
;�   Reset the CMOS value for amount of extended memory.  The	      �
;�   memory off the 'top' (upper addresses) is used by EMS.           �
;�     on entry:						      �
;�	CARD_EXT_S16K = First 16K translate table pointer past the    �
;�			top of the last card.  Example - One 2M card  �
;�			that started at 1M+384K, AX = 58h + 80H = D8h �
;�								      �
;�								      �
;����������������������������������������������������������������������
ADJUST_CMOS	PROC
CMOS_LO EQU  70h			;Port addrs of CMOS controller
CMOS_HI EQU  71h

	MOV	BX,CARD_EXT_S16K	;Convert to 1st 16K TT ptr past    @RH4
	SUB	BX,ems_pgs_parm 	; entries reserved for ext mem	   @RH4
	SUB	BX,1024/16		;Convert to # of 16K above 1M
	MOV	CL,4			;Multiply by 16 to get # of K
	SHL	BX,CL			; above 1 Megabyte

	MOV	AX,8800h		;Get BIOS' current value for #
	INT	15h			; of K extended (above 1M)

	CMP	AX,BX			;If already set below what we think
	JBE	CMOS_RET		; think then don't adjust it

	PUSHF				;Else adjust CMOS...save state of
	CLI				; interrupts and disable
	MOV	AL,0B5h 		;Select NMI off byte 35
	OUT	CMOS_LO,AL		;Write to CMOS controller
	JMP	$+2			;		  delay
	MOV	AL,BL			;Write low data byte to CMOS
	OUT	CMOS_HI,AL		;
	JMP	$+2			;

	MOV	AL,0B6h 		;Select NMI off byte 36
	OUT	CMOS_LO,AL		;Write to CMOS controller
	JMP	$+2			;		  delay
	MOV	AL,BH			;Write high data byte to CMOS
	OUT	CMOS_HI,AL		;
	JMP	$+2			;

	MOV	AL,0Fh			;Select NMI on byte 0f
	OUT	CMOS_LO,AL		;Write to CMOS controller
	JMP	$+2			;		   delay
	IN	AL,CMOS_HI		;Reset CMOS like BIOS does
	POPF				;Restore interrupt state
CMOS_RET:
	RET				;				   @RH4
ADJUST_CMOS	ENDP