home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-01-26 | 138.1 KB | 4,923 lines |
- ; INIT.A86
- title 'XIOS Initialization'
- pagesize 60+11
- ;********************************************************
- ;* *
- ;* XIOS INITIALIZATION ROUTINE *
- ;* CDOS 6.x/2.x XIOS *
- ;* DRI OS ENGR, JMB, GMS, JW *
- ;* *
- ;********************************************************
- ; Modifications:
- ; V 6.2/3.0
- ; 23 Jan 89 -- More XPC checks - IJ
- ; 1 Dec 88 -- add support for model 30-286 - JW
- ; 28 Nov 88 -- double check XPC settings - IJ
- ; 18 Nov 88 -- allow LOADSYS from drive D: - GMS
- ; 7 NOV 88 -- modified PS/2 check - JW
- ; 27 Oct 88 -- fix_crt now ignores inactive VGA - IJ
- ; 26 SEP 88 -- print digit of 10,000 or more fix - GMS
- ; 1 AUG 88 -- mark unused LCB's as unavailable - GMS
- ; 29 Jul 88 -- build_pin removed - IJ
- ; 29 JUL 88 -- call alloc_tmp to allocate TMP banked window - GMS
- ; 28 JUL 88 -- fix for empty DOS extended partitions - JW
- ; 21 Jul 88 -- intercept int 14 - IJ
- ; 13 Jul 88 -- add XPC protocol support - IJ
- ; 13 Jul 88 -- use PC Terminal Aux port as a printer - IJ
- ; 1 JUL 88 -- removed support for internal MDISK (use VDISK.SYS) GMS
- ; 29 JUN 88 -- Big fix in io_mem_alloc with alignment - GMS
- ; 24 JUN 88 -- Align VC buffers on 4k page for SunRiver - GMS
- ; 21 JUN 88 -- move hard disk param tables if below screen - GMS
- ; 17 JUN 88 -- display printer numbers < 9 - GMS
- ; 15 JUN 88 -- setup int17 and int14 tables per VC - GMS
- ; 15 JUN 88 -- mark unused ACB's as unavailable - GMS
- ; 6 APR 88 -- added support for Sun River system - GMS
- ; 17 Feb 88 -- Use ROS to read Time and Disk Parameters - JC/JW
- ; 27 JAN 88 -- support loadable Aux device drivers - JW
- ; 27 JAN 88 -- check for 12 bit FAT - JW
- ; 13 JAN 88 -- support Compaq DOS 3.31 big partitions - GMS
- ; 11 JAN 88 -- save_equip$ now setup for XM and saved in VS_ - GMS
- ; 10 DEC 87 -- mcga/ega/vga no longer initialise vector table. - GMS
- ; 10 DEC 87 -- video_init replaced with screen_set_only - GMS
- ; 7 DEC 87 -- initialise current monitor only - GMS
- ; 2 DEC 87 -- introduced new flag video$ for monitor types - GMS
- ; 22 NOV 87 -- don't use Sprite ROS as RAM, now like COMPAQ - JW
- ;
- ; 6.0/2.0
- ; =======
- ; 18 NOV 87 -- set flag for AST color card - GMS
- ; 17 NOV 87 -- re-map ega/vga rom, based on rom size value COMPAQ.GMS
- ; 16 NOV 87 -- change INT 10h to callf for compaq's sake in fix_ega GMS
- ; 13 NOV 87 -- bug fix for compaq ega test - GMS
- ; 11 NOV 87 -- save ROS keyboard data params for 386 - GMS
- ; 10 NOV 87 -- change COMPAQ test to use ega rom at C000h on 386 GMS
- ; 9 NOV 87 -- set some ROS keyboard variables for clones - GMS
- ; 7 NOV 87 -- do one video mode init only if VGA - JW
- ; 6 NOV 87 -- MDISK now allocated from next available TPA slot - GMS
- ; hi memory on XM EMM or 386 if available.
- ; 5 NOV 87 -- disable page 1 on hercules before color check - GMS
- ; 3 NOV 87 -- disable INT 14 for com1/com2 if serial console - GMS
- ; 1 NOV 87 -- join 386 hi partitions, split in MEM_ALLOC(0h) - JW
- ; 31 Oct 87 -- HI_MFL_START renamed XIOS_MFL, moved into SYSDAT - JW
- ; 30 OCT 87 -- XIOS no longer patches Int 1Bh vector - GMS
- ; 29 OCT 87 -- move hi_mfl_root onto hi_mfl_start after io_protect - GMS
- ; 28 OCT 87 -- relocate PS/2 BIOS data before MP_CHECK - JW
- ; 27 OCT 87 -- link INIT code into HI_MFL_START - JW
- ; write protect RAM BIOS on COMPAQ & Sprite (386)
- ; check for 80386 CPU for CDOS 386
- ; 20 OCT 87 -- set disk change mask for model 30 - GMS
- ; 19 OCT 87 -- mem_alloc made public for XM as well as 386 - GMS
- ; 18 OCT 87 -- mem_alloc function searches mfl and mwd - GMS
- ; if 386 all segment based allocations done
- ; after protected mode initialisised.
- ; if XM MMU then seg based allocations done
- ; after MWD setup.
- ; 15 OCT 87 -- use high end of SYSDAT for hd login buffer - JW
- ; just set buffer variables, BDOS will allocate
- ; let BDOS take care of DOS media hash setup
- ; 21 SEP 87 -- insert dummy DPB offset in floppy DPH's - GMS
- ; 16 SEP 87 -- logical to physical console mapping included - GMS
- ; 9 SEP 87 -- test setup bit before checking for EEMS boards - GMS
- ; 28 AUG 87 -- Zero DDSC area - GMS
- ; 6 AUG 87 -- added code for CDOS 386 version 2.0 support - GMS
- ; 5 AUG 87 -- TMPS' now spawn themselves so do not build - GMS
- ; 4 AUG 87 -- IO_PROTECT added for Cdos 386 init - GMS
- ; 3 AUG 87 -- change # of buffers based on sector size - JW
- ; 3 AUG 87 -- Bug fix for multi port cards init. - SAC
- ; 17 JUL 87 -- small model XIOS conversion - JW
- ; 21 JUN 87 -- use Q buffer space for login local_buffer$ - JW
- ; 18 JUN 87 -- check for COMPAQ & SPRITE shadowed 256 K - JW
- ; 13 JUN 87 -- support for PS/2 Model 30 + MCGA, VGA modes - JW
- ; 12 JUN 87 -- enabled INT 15 flag stuff - - JW
- ; only do one flag wait per INT 13h
- ; 10 JUN 87 -- support for RAM at E000-F000 in COMPAQ 386 - JW
- ; also added test for IBM PS/2 Model 80
- ; 9 JUN 87 -- support for RAM at E000-F000 in Sprite 386 - JW
- ;
- ; 5.2
- ; ===
- ; 20 MAY 87 -- if COMPAQ test if 9*14 CGA present. - GMS
- ; 14 MAY 87 -- read real time clock uses ROS int 1ah - GMS
- ; also called from statline not TICK routine.
- ; 5.2 beta 1
- ; 29 APR 87 -- "set_time" moved to safe area for use by TICK - GMS
- ; 13 APR 87 -- fix bug re hardcard which writes to monitor - GMS
- ; 6 APR 87 -- Olivetti 640*400 graphics modes support - GMS
- ; 2 APR 87 -- Get hard disk sectors_per_track from BPB - GMS
- ; 2 APR 87 -- Leave NMI vector if not pointing at ROS seg - GMS
- ; (autoswitch ega's)
- ; 2 MAR 87 -- Pallette save area fixed in VS structure - GMS
- ; 27 FEB 87 -- If compaq 386 set mode to FAST....... - GMS
- ; 9 FEB 87 -- Apricot 1.4meg 3.5inch drive is type 4 - GMS
- ; 5 FEB 87 -- skip buggy_string test re pc_at -- to be cleaned up !!
- ; 28 JAN 87 -- MEM_ALLOC moved before INIT code for V386 - GMS
- ; 27 JAN 87 -- Test for EGA changed to use int 10h - GMS
- ; 27 JAN 87 -- do_video inits both primary and secondary monitors GMS
- ;
- ; 5.1
- ; ===
- ; 16 JAN 87 -- Prevent the Boot Part on Drive 1 being Boot DRV - GMS
- ; 13 JAN 87 -- Fix uart reset - GMS
- ; 8 JAN 87 -- Bug fix for hard disk sizes > 32meg - GMS
- ; 10 DEC 86 -- Test byte in SETUP buffer for EGA autoswitch cards GMS
- ; 1 DEC 86 -- Restore var_cursor value for EGA's on COMPAQ - GMS
- ; 11 NOV 86 -- Bug fix for old ros kb/buffer on old COMPAQ machines - GMS
- ; 13 NOV 86 -- Test byte in SETUP buffer to enable hercules check GMS
- ; 13 NOV 86 -- Changed hercules check, problem on Philips P3200 - GMS
- ; 29 OCT 86 -- 19.2 & 38.4 Kb for serial consoles added - JW
- ; 27 OCT 86 -- Add retrace timing for hercules - PAR
- ; 15 OCT 86 -- Bug fix for HP vectra machine - GMS
- ; 14 OCT 86 -- Amstrad support added - GMS
- ; 7 OCT 86 -- European Keyboard support added - GMS
- ; 28 AUG 86 -- collapse parallel printer numbers
- ; 21 AUG 86 -- Large sector size support for DOS partition - GMS
- ; sizes greater than 32 megabytes.
- ; 18 AUG 86 -- Multiple DOS partition support added - GMS
- ; 30 JUL 86 -- reinstall interrupt-driven serial output (thx AS)
- ; ?? JUL 86 -- dynamic DPB setup for 96 TPI & Sony support - JW
- ; 18 JUL 86 -- set default printer in rsps to first actually present
- ; 18 JUL 86 -- support Olivetti M24 RTC - JW
- ;
- ; 5.0
- ; ===
- ; 10 JUL 86 -- if debug, don't init int 3
- ; 27 JUN 86 -- add presence test for QXM
- ; 24 JUN 86 -- rework patch_mem to fix 64k wrap problem - ddb
- ; 20 JUN 86 -- conditional unexpected int. vector setup
- ; 17 JUN 86 -- point int 3 at iret
- ; 16 JUN 86 -- set parity-checking port as function of at or pc/xt
- ; 10 JUN 86 -- correct memory sizing for old PC's w/ int 12h bug
- ; 10 JUN 86 -- zero dph entries for non-existent partitions
- ; 3 JUN 86 -- support keyboard vector switching
- ; 28 MAY 86 -- change sign-on version if QXM
- ; 27 MAY 86 -- initialize cntl-break isr
- ; 14 MAY 86 -- wait for update bit in AT CMOS/tod before reading (thx JC)
- ; 12 MAY 86 -- new INIT signon plus color
- ; 29 APR 86 -- fix bus float on RAM check for ZDS (thx Mark Foster)
- ; 23 APR 86 -- save vectors (for LOADCCPM) before poking 1E
- ; 22 APR 86 -- fix do_one_port bug (thx JC)
- ; 15 APR 86 -- set up process-terminating isr address for seg overrun int (286)
- ; 16 APR 86 -- same for invalid-opcode int (286)
- ; 3 APR 86 -- explicitly mask a non-existent serial port at the PIC (thx JC)
- ; 24 MAR 86 -- remove JW DOS hash experiment
- ; 11 FEB 86 -- add JW DOS hash experiment ;;**
- ; 5 FEB 86 -- only use optimized XIOS hard disk driver if SETUP instructs
- ; 19 DEC 85 -- make screen buffers last-allocated non-SYSDAT for 4.0 group
- ; 18 DEC 85 -- allocate space for the EGA bit_plane save if EGA
- ; 18 DEC 85 -- force the default diskette EOT to 9
- ; 6 NOV 85 -- do or don't customize fdc based on su_fdc_check
- ; 24 OCT 85 -- support diskette int 1E + setup diskette parms
- ; 27 SEP 85 -- add Dev. Driver/SETUP SYSDAT space routine
- ; 20 SEP 85 -- add low memory space allocation routines, for
- ; SYSDAT space and non-sysdat space, use for HASH,
- ; HD ALV (CPM), data buffs, AUX buffs and screen buffs
- ; 17 SEP 85 -- remove previously installed AT HD POST/WAIT code
- ; 4 SEP 85 -- handle interrupt-driven hard disk code
- ; 28 AUG 85 -- handle Enhanced Graphics Adaptor
- ; 12 JUL 85 -- program the UARTS for ints. only on data-received
- ; 9 JUL 85 -- insert debug flag to control timer PIC mask
- ; 1 JUL 85 -- initialize the ROS interface vectors (ROSIF.A86)
- ; 6 JUN 85 -- update 4.1 ASM86 to 4.2 RASM86
-
- ; include COPYRITE.TXT
-
- nolist
- include CDOS.EQU
- include XIOS.EQU
- include PCHW.EQU
- include ASCII.EQU
- include ROSDATA.EQU
- if SR
- include SR.EQU
- endif
- list
- ; These have been included:
- ; include CDOS.EQU
- ; include XIOS.EQU
- ; include PCHW.EQU
- ; include ASCII.EQU
- ; include ROSDATA.EQU
-
- CGROUP group init_cseg
- DGROUP group init_dseg
-
- public init@ ; for HEADER.A86
- public INIT_START, XIOS_END ; for FIDD.A86
-
- public io_mem_alloc@ ; for HEADER.A86
- public mem_alloc_i@ ; for V386.A86 and EMM
- public hi_on$, hi_off$
- public init_reuse@ ; for EMM.A86
- if SR
- public current_pc$
- public pic_mask_image$
- public put_in_s_o
- public conv_digit@
- endif
-
- eject
-
- init_dseg dseg
-
- extrn genccpm_buf$ :word
- extrn dph_tbl$ :word, nvcns$ :byte
-
- extrn su_md_size$ :word, su_verf$ :byte
- extrn su_mmp$ :word, su_cf$ :byte
- extrn su_scroll$ :byte, su_hdst$ :byte
- extrn su_config$ :word, su_prot$ :byte
- extrn su_pfk_tbl$ :byte, su_ser_con$ :word
- extrn su_check$ :word, su_pf$ :byte
- extrn su_sysdat$ :word, su_hard_driver$:byte
- extrn su_timer_count$ :word, su_fdc_check$ :byte
- extrn su_fdc_spec1$ :byte, su_fdc_spec2$ :byte
- extrn su_fdc_settle$ :byte, su_fdc_spinup$ :byte
- extrn su_flag_bits$ :word
- extrn su_mu_data$ :word
- extrn su_mu_vs$ :byte
- extrn mu_com_type$ :byte
-
- extrn ndp_control$ :word, num_ndp$ :word ; in ISRS.A86
- extrn parity_chk$ :word
- extrn pfk_tbl0$ :byte ; in CONIN.A86
- extrn sl_attrib$ :byte ; in STATLINE.A86
-
- extrn list_data$ :word, list_stat$ :word ; in LISTAUX.A86
- extrn list_out$ :word, auxout_blk_ptr$:word
- extrn aux_in_vector$ :word, aux_out_vector$:word
- extrn auxin_stat_vector$:word, auxout_stat_vector$:word
- extrn ser_conin_vec$ :word, ser_conout_vec$:word, ser_conout_stat_vec$:word
- extrn auxin_blk_ptr$ :word
- extrn port2pc_table$ :byte, pc2port_table$:byte
- extrn serdrv_vector$ :word
-
- extrn ccb_list$ :word, acb_list$:word, dummy_cb$:word ; in PUBDATA.A86
- extrn lcb_list$ :word
- extrn dph_md$ :word
- extrn pcdpb9D$ :word
- extrn next_flag$ :byte
- extrn int14_ptr$ :byte, int17_ptr$ :byte
- extrn save_equip$ :word
-
- extrn num_flop$ :word, num_flop_des$ :word
- extrn num_print$ :word, num_hard$ :word
- extrn num_port$ :word
- extrn num_mmkb$ :word
- extrn iattrib$ :byte, blank$ :word
-
- extrn disk_int_off$ :word, disk_int_seg$ :word
- extrn timer_count$ :word
-
- extrn lo_mem_top$ :word, hi_mem_start$ :word
- extrn hi_mem_top$ :word
- extrn aux_prot_blk$ :word
- extrn dsm_md$ :word
- extrn nfatrecs_md$ :word
- extrn nclust_md$ :word
-
- extrn ros_vectors$ :byte
- extrn cloneflag$ :byte
- extrn retrace$ :word
-
- if V386
- extrn hi_xmem_addr$ :word, hi_xmem_size$ :word ; in V386.A86
- extrn num_pages$:word
- extrn pc_kbd_save$:word ; in PCTERM.A86/SRTERM.A86
- extrn save_kbdata$:word ; in KEYBOARD.A86
- endif
-
- if SR
- extrn sr_vs_table$:byte, sr_pc_table$:byte ; in PUBDATA.A86
- extrn sr_table_vs$:word, SR_VS_TLEN:abs
- extrn vc_seg_save$:word ; in SRTERM.A86
- extrn ptbl_bit_plane$:word ,ptbl_vc_save$:word
- endif
-
- if XM
- extrn num_pgkb$ :word ; in EMM.A86
- endif
-
- extrn alpha_str_80$ :word, compaq_str$ :byte ; in WINDOWS1.A86
- extrn mono_table$ :word, video$ :byte
- extrn ast_flag$ :byte
- extrn mode_vector$ :word, oli_vector$ :word
- extrn bit_plane_seg$ :word
- extrn local_ptr$ :word
-
- extrn var_cursor$ :word, var_sync$ :byte ; in WINDOWS3.A86
- extrn table_vs$ :word, scroll_mode$ :byte
- extrn vc_map_seg$ :word, vc_priority$ :byte
-
- extrn read_tbl$ :word, write_tbl$ :word ; in DISK.A86
- extrn select_tbl$ :word
-
- extrn drive_type$ :byte, data_rate$ :byte ; in FLOPPY.A86
- extrn motor_flags$ :byte,disk_chng_mask$:byte
- extrn verify_flag$ :byte, pc_at$ :byte
- extrn int_1e_parms$ :byte
- extrn settle_1e$ :byte
- extrn dos_dpbs$ :word
-
- extrn hd_rom_seg$ :word, hd_rom_ofs$ :word ; in HDISK.A86
- extrn hd_disk_info$ :byte, hdinf_ptr$ :word
- extrn hd_rom_entry$ :dword
-
- if XM
- extrn hd_cmd_blk$ :byte ; not in CDOS 386
- endif
-
- extrn local_buffer$ :word
- extrn hd_boot_flag$ :byte, hd_init_flag$ :byte
-
- extrn sysdat_buff_base$ :word ; in FIDDS.A86
- extrn sysdat_buff_length$ :word, sysdat_buff_link$ :word
- extrn prog_hist_base$ :word, comm_hist_base$ :word
- extrn ser_hist_base$ :word
-
- init_cseg cseg
-
- extrn sysdat$ :word ; in HEADER.A86
- extrn supervisor_o$ :word, supervisor_s$ :word ; in HEADER.A86
- extrn disp_offset$ :word, disp_segment$ :word
- extrn i_ndp@ :near, i_unexpected@ :near ; in ISRS.A86
- extrn i_divide@ :near, i_nmi@ :near
- extrn i_clock@ :near, i_tick@ :near
- extrn i_overflow@ :near
- extrn i_seg_ovr@ :near, i_bad_opcode@ :near
-
- extrn i_keyboard@ :near ; in KEYBOARD.A86
- extrn NX_init@ :near ;
- extrn keyboard_isr$ :dword ; in KEYBOARD.A86
- extrn z_sl_mono@ :near, z_sl_color@ :near ; in STATLINE.A86
-
- extrn point_aux@ :near, aux_port_in@ :near ; in LISTAUX.A86
- extrn aux_null@ :near, parallel_out@ :near
- extrn aux_port_out@ :near,parallel_stat@ :near
- extrn aux_in@ :near, aux_out@ :near, term_auxout_stat@ :near
- extrn i_aux_0@ :near, i_aux_1@ :near
-
- extrn select_flop@ :near, read_flop@ :near ; in FLOPPY.A86
- extrn write_flop@ :near
- extrn flop_specify@ :near, i_disk@:near
-
- extrn hd_dummy_int@ :near ; in HDISK.A86
- extrn pc_select_hd@ :near, pc_read_hd@ :near
- extrn pc_write_hd@ :near
- if XM
- extrn hd_isr@ :near, xt_driver@ :near
- endif
-
- extrn hd_rom@ :near, int15_isr@ :near
-
- extrn i_dummy_fidds@ :near, i_fidds_flag@ :near ; in FIDDS.A86
- extrn check_init_reuse@:near
-
- extrn set_mono@:near, set_color@:near ; in WINDOWS1.A86
- extrn io_conout@:near, screen_set_only@:near
- extrn bw_640_400@:near, bw_640_400_t@:near
-
- extrn point_vs@ :near, new_monitor@ :near ; in WINDOWS2.A86
- extrn video_int@ :near ; in PCVIDEO.A86
- extrn async_int@ :near ; in LISTAUX.A86
-
- extrn vector_table$ :word, NUM_VECTORS :abs ; in ROSIF.A86
- extrn int10_isr$:word
-
- extrn old_int15$ :word ; in HDISK.A86
-
- public set_time@ ; for STATLINE.A86
-
- if XM
- extrn mp_check@ :near, mp_config@ :near ; in EMM.A86
- endif
-
- if V386
- extrn init_386@:near ; in V386.A86
- extrn alloc_tmp@:near
- public io_protect@
- endif
- if SR
- extrn sr_init@:near ; in SRTERM.A86
- extrn sr_fix_crt@:near
- endif
- eject
-
- init_cseg cseg
- hard8087
-
- ; The following routine is used to initialize any required
- ; data areas, and alter any peripheral chip programming when
- ; starting up CPCDOS. This code is called once from the
- ; SUP(ERVISOR) after the SUP has called the RTM, CIO, MEM and
- ; BDOS initialization routines, and before SUP has created
- ; the RSP processes.
-
- ; We are again hoping that the DL register is preserved through
- ; the init process, because we are setting sysdisk to A: when
- ; we boot from floppy to ease the installation procedures.
-
- ; Read real time clock and set sysdat TOD
- set_time@:
- ;---------
- or cx,0ffffh ; Invalidate Hours and Minutes
- mov ah,02h ; and RESET the carry flag
- int TOD_INT ; get Time of day from ROS
- jc bad_time ; Bad function or clock inoperative
- cmp ch,24h ; Check for a Valid BCD Hour
- jae bad_time
- cmp cl,60h ; Check for a Valid BCD Minute
- jae bad_time
- mov tod_sec$,dh ; Real Time Clock Function
- mov tod_min$,cl
- mov tod_hour$,ch
-
- mov ah,04
- int TOD_INT ; get date from ROS
- push cx ; save CL
- mov al,dl ; day in bcd
- call conv_bcd
- mov tod_day$,ax ; initial set
- mov al,dh ; month in bcd
- call conv_bcd
- mov ch,0 ; assume march-dec
- cmp al,3 ; and if true
- jae check_286_leap ; skip
-
- mov ch,1 ; jan-feb leap correct
- check_286_leap:
- dec ax ! shl ax,1 ; zero base and word index
- xchg ax,bx
- mov ax,month_length[bx] ; days in prior months
- add tod_day$,ax ; add days up to now
-
- pop ax ; saved year into al
- call conv_bcd
- sub al,78 ; cpm base year
- push ax
- mov dx,365
- mul dx ; convert to days
- add tod_day$,ax ; here's the biggie
- pop ax
- add al,2 ; 78 -> 80
- sub al,ch ; dec if jan or feb
- shr ax,1 ! shr ax,1 ; every 4 years
- add tod_day$,ax ; gives us a day
- bad_time:
- ret
-
-
- conv_bcd:
- ; convert bcd in AL to binary in AX:
-
- mov ah,al
- mov cl,4
- shr ah,cl ; ms nib to ah
- and al,0Fh ; ls nib in al
- aad ; ax = 10*ah + al
- ret
-
-
-
- io_mem_alloc@: ; entry point from HEADER.A86
- ;------------- ; used during initialisation
- ; Entry: DX = <> 0 - paragraphs required
- ; = 0 no further mem_alloc calls
- ; CX = 0 no alignment
- ; <> alignment mask
- ; Exit: AX = segment base freed for caller
-
- test dx,dx ; test for final allocation
- jnz do_mem_alloc ; skip if normal allocation
- mem_cleanup1:
- mov bx,xios_mfl ; get first entry in XIOS_MFL or 0000h
- test bx,bx ; test if XIOS_MFL empty
- jz mem_cleanup5 ; done if empty
- mov ax,MD_LINK[bx] ; else get remainder of list
- mov xios_mfl,ax ; remove this item from the list
- mov dx,MD_START[bx] ; get base of this block
- mov cx,MD_LENGTH[bx] ; get size of this block
- mov ax,mdul
- mov MD_LINK[bx],ax ; release this item into MDUL
- mov mdul,bx
- mem_cleanup2: ; DX = base, CX = size
- cmp cx,MIN_PART_LEN ; remaining size too small to bother
- jb mem_cleanup1 ; drop it, try next block
- mov bx,mdul ; else get an unused MD from MDUL
- mov ax,MD_LINK[bx]
- mov mdul,ax
-
- mov di,offset mfl ; find end of MFL
- mem_cleanup3:
- mov si,di ; save previous item
- mov di,MD_LINK[si] ; get next item
- test di,di ; end of MFL found yet?
- jnz mem_cleanup3 ; no, try next one
- mov MD_LINK[si],bx ; link new MD to current end of MFL
-
- mov si,cx ; assume we use up whole block
- cmp si,400h ; compare with normal size
- jbe mem_cleanup4 ; if less than normal, use it
- mov si,400h ; else chop it up into 16K blocks
- mem_cleanup4:
- sub ax,ax
- mov MD_LINK[bx],ax ; make us the last entry
- mov MD_START[bx],dx ; set base address of block
- mov MD_LENGTH[bx],si ; set size of this block
- mov 6[bx],ax ; reserved = 0000h
- mov 8[bx],ax ; reserved = 0000h
- add dx,si ; increment the base address
- sub cx,si ; decrement the block sizethe
- jmps mem_cleanup2 ; check if more space in block
-
- mem_cleanup5: ; all blocks moved to MFL
- mov bx,mfl$
- or bx,bx
- jz mem_clean_exit
- cmp MD_LENGTH[bx],MIN_PART_LEN
- jae mem_clean_exit
- mov bx,MD_LINK[bx] ; if first entry too small
- mov mfl$,bx ; remove from mfl
- mem_clean_exit:
- sub ax,ax ; return O.K. code
- ret
-
-
- do_mem_alloc: ; real memory allocation
-
- if V386 ; aligned allocations on 386 only
- jcxz mem_alloc_i@ ; skip if unaliged
- mov si,offset xios_mfl
- align_hi:
- mov si,MD_LINK[si] ; get next entry
- test si,si
- jz no_hi_mem ; align high MFL
- cmp dx,MD_LENGTH[si] ; will this block fit?
- ja align_hi ; no, check next one
- mov ax,MD_START[si] ; check aligned
- add ax,MD_LENGTH[si]
- test ax,cx
- jnz align_hi
- sub MD_LENGTH[si],dx ; else allocate it from top end
- mov ax,MD_START[si] ; to leave end page aligned
- add ax,MD_LENGTH[si] ; AX = base of allocated block
- ret
-
- no_hi_mem: ; if no high memory partition
- mov si,mfl$ ; then check low mem alignment
- or si,si
- jz mem_alloc_i@ ; only banked memory left
- mov ax,MD_LENGTH[si]
- and ax,cx
- add MD_START[si],ax
- sub MD_LENGTH[si],ax
- jnz mem_alloc_i@
- mov ax,MD_LINK[si] ; not enough aligned memory in
- mov mfl$,ax ; partition, so waste it
- jmps mem_alloc1
- endif
-
- mem_alloc_i@:
- ;------------
- ; Internal entry point to do memory trimming
- ; first from high memory free list (if available)
- ; and then from bottom of TPA first from MFL and then
- ; MWD list.
- ; hi_mfl contains entries of discontiguous memory
- ; of varying length which can be used for segment
- ; based buffer allocations.
- ; Entry: DX = paragraphs wanted from base of TPA list
- ; Exit: AX = segment base freed for caller
- ; DX = preserved
- ; BX = preserved
- ; AX = 0ffffh no memory available
- ; No error checking.
- push bx
- mov bx,offset xios_mfl
- mem_alloc1a:
- mov di,bx ; DI = previous
- mov bx,MD_LINK[bx]
- test bx,bx ; end of list ?
- jz end_hi_mfl
- cmp dx,MD_LENGTH[bx] ; is entry big enough
- ja mem_alloc1a ; no try next
- mov ax,MD_START[bx] ; start segment to AX
- sub MD_LENGTH[bx],dx ; reduce partition size
- jz mem_alloc1b ; completely used
- add MD_START[bx],dx ; else increase start seg
- jmps mem_ret
- mem_alloc1b:
- mov si,MD_LINK[bx] ; remove entry when all used
- mov MD_LINK[di],si ; link next into previous
- mem_ret:
- pop bx ; restore bx
- ret ; and return
-
- end_hi_mfl:
- pop bx
- mem_alloc1:
- push bx
- push dx ; save
- mov bx,mfl$
- or bx,bx
- jz get_mwd
- mov si,MD_START[bx] ; save it for below
- mov bp,si ; save for exit
- call common_trim ; returns ax=0000 MFL exhausted
- or ax,ax
- jnz trim_exit
- jmps do_mwd
- get_mwd:
- mov bx,mwdr$
- mov si,MD_START[bx] ; start seg off MWD list
- mov bp,si ; start seg for exit
- do_mwd:
- mov bx,mwdr$
- mov si,MD_START[bx] ; start seg for trim
- call trim_mwd
- or ax,ax
- jnz err_exit
- trim_exit:
- mov ax,bp ; return seg. addr.
- err_exit:
- pop dx ; restore input params
- pop bx
-
- ret
-
-
- common_trim:
- ;-----------
- ; Entry: DX = paragraphs wanted
- ; SI = start buffer paragraph.
- ; BX = root MD.
- ; Exit: MD and mfl$ updated
- ; No error checking.
-
- ; Init for trim algorithm:
- mov bx,offset mfl$ ; init for algorithm below
- ; sub bx,MD_LINK ; (MD_LINK equ 0)
- sub ax,ax ; init cumulative length
-
- chop_loop:
- mov bx,MD_LINK[bx]
- or bx,bx
- jz exit_mfl_loop ; mfl exhausted
- add ax,MD_LENGTH[bx]
- cmp ax,dx
- jb chop_loop
-
- sub ax,dx ; sub. requested from cum.
- mov MD_LENGTH[bx],ax ; and adjust MD
- add dx,si ; add start to total length
- mov MD_START[bx],dx ; gives new start
- mov mfl$,bx
-
- ; One final check:
- test ax,ax
- jnz length_ok
- mov bx,MD_LINK[bx] ; then skip to next MD
- mov mfl$,bx ; and bump root
- length_ok:
-
- mov al,0ffh
- ret
-
- exit_mfl_loop:
- mov mfl$,0000 ; remove completely
- sub dx,ax ; DX = remaining paragraphs
- sub ax,ax ; return state
- ret
-
-
- trim_mwd:
- ;--------
- ; Entry: DX = paragraphs wanted
- ; SI = start buffer paragraph.
- ; BX = root MD.
- ; Exit: MD , mwd$ and mfl$ updated
- ; AX = 0ffffh if no memory left
-
- mov bx,offset mwdr$ ; init for algorithm below
- sub ax,ax ; init cumulative length
-
- mwd_loop:
- mov bx,MD_LINK[bx]
- or bx,bx ; we should never
- jz mwd_error ; get zero
- add ax,MD_LENGTH[bx]
- cmp ax,dx
- jb mwd_loop
-
- sub ax,dx ; sub. requested from cum.
- mov MD_LENGTH[bx],ax ; and adjust MD
- add dx,si ; add start to total length
- mov MD_START[bx],dx ; gives new start
- mov mwdr$,bx ; place in root pointer
- cmp ax,400h ; 16k block ?
- je mwd_done ; yes .. leave all on MWD list
- cmp ax,MIN_PART_LEN ; else check if big enough
- ja put_mfl ; for entry on MFL
- mov bx,MD_LINK[bx] ; if not then add to next entry
- add MD_LENGTH[bx],ax
- mov MD_START[bx],dx
- put_mfl:
- mov mfl$,bx ; new mfl start
- xor di,di ; with one entry only
- xchg di,MD_LINK[bx] ; so terminate link get next
- mov mwdr$,di ; as start of MWD
- mwd_done:
- xor ax,ax
- ret
- mwd_error:
- mov ax,0ffffh
- ret
-
-
- eject
-
- INITCODE_START equ $ ; start of reusable code space
-
- init@:
- ;-----
-
- if V386
- ; We need to check for an 386 CPU as our XIOS assumes
- ; that processor even before MEM has a chance to check
- ; for its presence...
-
- push sp
- pop ax ; AX != SP if 8086/88/186/V20/30/...
- cmp ax,sp ; AX == SP if 80286 or 80386
- jne need_386 ; skip if not even 286
- pushf ; save current CPU state
- pop ax ; AX = default flags
- or ah,30h ; try to set IOPL == 3
- push ax ; push image back on stack
- popf ; try to change IOPL in flags
- pushf ; push current flags
- pop ax ; AX == 3xxx if 386 or 0xxx if 286
- and ah,30h ; isolate IOPL bits in flags
- cmp ah,30h ; could be set IOPL = 3?
- je got_386 ; yes, must have 386 (or 486?)
- need_386:
- mov si,offset need_386_msg ; else print error message
- need_386_loop:
- lods cs:al ; get next character
- test al,al
- jz need_386_done ; skip if message done
- mov bl,07h ; normal attribute
- mov ah,14 ; write TTY
- int VIDEO_INT ; call ROS
- jmps need_386_loop ; get next character
- need_386_done:
- sti ; turn on ints for keyboard
- jmps need_386_done ; hang for Ctl/Alt/Del
-
- need_386_msg db 13,10,'Requires Intel 80386 to run.'
- db 13,10,' Press Ctrl/Alt/Del. ', 0
-
- got_386: ; O.K. if we've got one
- endif
- cli
- push es
- call set_sys_vars ; set up system variables
- call do_ros_ints ; store some vectors
- call set_ros_data ; set some ros data variables
- call check_286 ; see if we're AT or clone
- call equip_check ; see what we've got
- if XM
- call reloc_disk_params ; reloc fixed disk table if not ROM
- call reloc_ext_BIOS ; relocate PS/2 extended BIOS data
- test su_flag_bits$, EEMS_ENABLE_BIT
- jz no_mpcheck
- call mp_check@ ; check for EEMS boards
- no_mpcheck:
- endif
- call check_hi_mem ; from C000 up
- call ndp_init ; check for an 8087
- call compaq ; do before any video setup
- if V386
- call sprite386 ; check for Jarogate machine
- endif
- if XM ; non-386 only...
- call amstrad ; check for Amstrad 1512
- call check_8530 ; check for The Orphan (Model 30)
- call olivetti ; check for Olivetti M24
- endif
- call fix_crt ; mono/color vs_ variables
- call get_dph_seg ; get temp SEG address for DPH's
- call fix_disk_tables ; match disk tables to equip
- call do_int_1e ; dos support
- call printer_init ; reset the parallel printers
- call do_setup ; customize XIOS
- call flop_off ; turn off the floppy motors
- call find_dskbuf ; find SYSDAT buffer for HD_INIT
- call hd_init ; get hard disk partitions
- call alloc_dskbuf ; find SYSDAT buffer for deblocking
- call trim_memory ; fix up the partition list
-
- call alloc_setup_buff ; get user-requested buffer for FIDDS
-
-
- ;********** last SYSDAT allocation **********
-
- if V386 ; switch into protected mode and continue
- ; XIOS init on return through io_protect
- call init_386@ ; prepare for switch into virtual mode
- pop es ; restore Init UDA
- sti
- retf ; Part 1 initialization done
-
-
- io_protect@: ; Re-enter in protected mode
- ;---------- ; for all segment based allocations
- pop ax ; clean return offset
- push es ; for common exit from INIT
- ; ; continue with initialisation
-
- call align_dskbuf ; align deblocking buffer
- ; (in case we've relocated SYSDAT)
- call alloc_tmp@ ; find TMP window
- cmp ega_remap,FALSE
- je not_remap
- call compaq_protect ; map 32 bit EGA copy over 8 bit
- not_remap:
- endif
-
- if XM ; create MWDR if resident EEMS
- call mp_config@ ; done before all segment based
- ; allocations
-
- else ; if MMU, we've done this earlier on
- call reloc_disk_params ; reloc fixed disk table if not ROM
- call reloc_ext_BIOS ; relocate PS/2 extended BIOS data
- endif
- call fix_ega_pal ; setup local save area for palettes
- call do_aux_ports ; serial port int init
- if SR
- call sr_init@ ; initialise SUN RIVER cygna card
- endif
- call alloc_tmp_buffs ; allocate space for history buffers
- call alloc_non_sysdat ; get hash tables, etc.
- call floppy_hash ; get floppy hash tables/FAT buffers
- call alloc_fat_buffs ; allocate FAT buffers
- call alloc_ser_rsps ; make serial PCTmps and PINs
- call alloc_virt_screens ; do it ourselves (no GENCCPM)
- if SR
- call sr_fix_crt@ ; fix up VS_ variables
- endif
- call do_interrupts ; do all of the int stuff
- call NX_init@ ; Initialise international keyboard
- call do_video ; initial mode setup
- call sign_on ; print signon message
- call default_prnt ; poke default printers
- call enable_ints ; interrupts back on
- call herc_check ; check for hercules
-
- init_ret:
- ; move built DPH's into SYSDAT Segment
- ; must be last function before returning from INIT
- ; as the INIT code area is overwritten..
-
- push ds ! push es
- push ds ! pop es ; move to SYSDAT
- mov cx,dph_count ; total number of bytes allocated to DPH's
- jcxz no_hd_dos_dph ; no hard disk DOS partitions ......
- mov di,pc_hd_dph_start ; pointer to first hard disk DPH entry
- mov si,dph_tbl$[di] ; get offset of drive DPH
- mov di,si ; same offset in both segments
- mov ax,dph_seg ; temp seg. address
- mov ds,ax
- cld
- rep movsb
- no_hd_dos_dph:
- pop es ! pop ds
-
- ;; clear out DDSC for all drives
- push es
- mov cx,16 ; all drives
- mov bx,offset dph_tbl$ ; DPH table
- zero_loop:
- push cx
- mov si,[bx] ; point to the dph
- test si,si ; DPH ??
- jz next_dph
- mov es,DPH_HSTBL[si] ; hash table seg
- sub di,di
- mov cx,32/2 ; clear two paras
- xor ax,ax
- rep stosw
- next_dph:
- pop cx
- inc bx ! inc bx ; point to next dph
- loop zero_loop ; and do another
- pop es
-
-
- ; Build memory descriptor for XIOS init code and
- ; link it into high memory list so it can be reused
- ; for Q buffers, disk buffers and hash tables.
- ; Note that this assumes the code segment is not
- ; write protected, which may change in future versions.
-
- mov si,offset INITCODE_START
- mov di,offset INITCODE_END ; DI = address of 1st resident byte
- call init_reuse@
- pop es ; restore Init UDA
- sti
- retf ; initialization done
-
-
- init_reuse@:
- ;-----------
- ; entry: SI -> first reusable byte code segment
- ; DI -> first resident byte in code segment
-
- mov bx,mdul ; steal MD from MD unused list
- mov ax,MD_LINK[bx] ; (no CLI/STI as we're the only
- mov mdul,ax ; process running here)
-
- mov dx,cs ; DX = paragraph address of XIOS code
- mov cl,4
- add si,15
- shr si,cl ; SI = paragraph offset
- add si,dx ; SI = address of reuseable space
- mov MD_START[bx],si
- shr di,cl
- add di,dx ; DI = address of resident code
- sub di,si ; DI = # of reusable paragraphs
- mov MD_LENGTH[bx],di
-
- mov ax,xios_mfl ; link us into high memory free list
- mov MD_LINK[bx],ax ; for use by future IO_MEMALLOCs
- mov xios_mfl,bx
-
- ret
-
-
- dph_count dw 0 ; leave here before INIT_START
- dph_seg rw 1
-
-
- get_dph_seg:
- ;-----------
- mov ax,memory_top
- mov dx,(8*(PC_HD_DPH_SIZE+PC_HD_DPB_SIZE)/16) + 1
- ; reserved space for max 8 drives
- ; in paras.
- sub ax,dx
- mov dx,XIOS_END
- mov cl,3
- shr dx,cl ; div by 16
- inc dx ; round up
- sub ax,dx
- mov dph_seg,ax ; temp SAFE seg address for building
- ret ; DOS hard disk DPH's
-
- eject
-
- ; Allocate a couple of F_DOS deblocking buffers
-
- ; Currently, we use about 8 Kb for buffers,
- ; which gives a variable # of buffers depending
- ; on the maximum sector size to support.
-
- alloc_fat_buffs:
- mov ax,16 shl 2 ; give us 16*512 bytes of buffers
- mov cl,maxpsh ; (2 = 512, 3 = 1024, 4 = 2048, ...)
- shr ax,cl ; AX = 16, 8, 4, etc.
- cmp ax,5 ; check if minimum for performance
- jae alloc_fat1 ; O.K. if at least 5 buffers
- mov ax,5 ; else get us at least minimum #
- alloc_fat1:
- cmp ax,nbuffers$ ; less than what's configured already?
- jb alloc_fat2 ; no, s.o. wants more than default
- mov nbuffers$,ax ; set SYSDAT variable
- alloc_fat2:
- mov ax,128 ; bytes in basic sector size
- mov cl,maxpsh ; adjust for physical sector size
- shl ax,cl ; AX = sector size in bytes
- cmp ax,sec_size$ ; less than what's configured already?
- jb alloc_fat3 ; no, s.o. wants more than defult
- mov sec_size$,ax ; set sector size for buffer alloc
- alloc_fat3:
- ret
-
-
- do_int_1e:
- ;---------
- ; Copy and point int 1Eh:
-
- ; The 11 disk-parm. bytes pointed to by int 1E are copied to our
- ; local XIOS string. The initialized values in the XIOS correspond to
- ; DOS 2.1 parms.
-
- push ds
- xor ax,ax ; point to vectors
- mov ds,ax ; source
- lds si,dword ptr .INT_1E_VEC_OFF ; possibly ROM
- pop es ! push es ; destination
- mov di,offset int_1e_parms$ ; in XIOS RAM
- mov cx,11
- cld
- rep movsb ; to our local area
-
- mov es:byte ptr MIN_7[di],18 ; force EOT to 18
-
- mov ds,ax ; = 0
- mov word ptr .INT_1E_VEC_SEG,es ; new vector
- mov word ptr .INT_1E_VEC_OFF,offset int_1e_parms$
- pop ds
- ret
-
-
- set_sys_vars:
- ;------------
- ; Set up initial system variables:
-
- mov boot_drive,dl ; back to this old trick
- cld ; Sup saves DS,ES on INIT call
- in al,PIC_MASK ; get the current interrupt mask
- mov pic_mask_image$,al ; and save it for restoration
- mov al,0FFh
- out PIC_MASK,al ; mask off all interrupts
-
- ; mov sysdat$,ds ; save System Data Segment
- ; mov bx,offset supmod$ ; save Sup entry double word
- ; mov ax,[bx] ; get offset from Sys Data Seg
- ; mov supervisor_o$,ax ; save it
- ; mov ax,2[bx] ; get the segment
- ; mov supervisor_s$,ax ; save it
-
- mov si,offset dispatcher$ ; get dispatcher double word
- lodsw
- mov disp_offset$,ax ; get offset
- lodsw
- mov disp_segment$,ax ; get segment
-
- mov owner_8087$,0FFFFh ; 8087's owner's pd
- ret
- eject
- check_286:
- ;---------
- ; Check to see if we're running on the PC-AT or compatible:
-
- mov ax,0FFFFh ; top of rom
- mov es,ax
- mov al,es:.0Eh ; get IBM model byte
- cmp al,0FCh ; AT clone (incl. XT 286 + PS/2 50/60)
- je yes_at ; yes, read CMOS RAM
- cmp al,0F8h ; also check for PS/2 Model 70/80
- jne check_286_done ; no, return
- yes_at: ; AT or clone, XT286, PS/2 50/60/70/80
- mov ah,0C0h ; get machine architecture info
- int 15H ; via the ROM BIOS
- jc not_ps2 ; skip if old ROM BIOS version
- cmp es:word ptr 2[bx],09FCh ; is it PS/2 model 30 - 286
- jne test_ps2
- mov disk_chng_mask$,80h ; set disk change polarity mask
- test_ps2:
- test es:byte ptr 5[bx],2 ; test if MCA implemented
- jz not_ps2 ; skip if not
- or pc_at$,02h ; indicate it is a PS/2
- mov hi_off$,000ffh ; nothing above E000 on PS/2 range
- ; mov hi_on$, 00000h ; no "guaranteed good" areas
-
- not_ps2:
- or pc_at$,01h ; we are with a member of AT family...
-
- mov al,not 04h
- out PIC_MASK,al ; enable slave PIC for HP VECTRA
-
- ; Now check to see if we are running on an at with the buggy hard disk
- ; code which has prevented us from doing multi-sector i/o on an AT:
- if XM
- push es
- mov ax,AT_HDROS_SEG
- mov es,ax
- mov di,AT_HDROS_OFF
- mov si,offset buggy_string
- mov cx,length buggy_string
-
- repe cmpsb ; z flag will be reset if no match
- pop es
- jnz no_match
- endif
-
- ; Since we matched the bytes, indicate by setting the bit:
- match:
- or pc_at$,80h
- no_match:
- ;
- ; Set up the vector for the segment overrun interrupt on a 286,
- ; and the Invalid Opcode int:
- ; (Ints are CLIed at the top of INIT)
- T1 equ 13*4 ! T2 equ T1 + 2 ; int. # 13(d)
- O1 equ 6*4 ! O2 equ O1 + 2 ; int. # 6(d)
- sub ax,ax ; point at vectors
- push ds
- mov ds,ax
- mov .T1,offset i_seg_ovr@
- mov .T2,cs
- mov .O1,offset i_bad_opcode@
- mov .O2,cs
- pop ds
-
- ;Change the port to detect parity errors:
- mov parity_chk$,PORT_B ; 61h on ATs, 62h on pcs.
- check_286_done:
- ret
-
-
- ; Read PC AT cmos ram port in al:
-
- read_286_cmos:
- out CMOS_ADDR,al ; set address
- jmps $ + 2 ; pause
- in al,CMOS_DATA ; read the rom
- ret
-
-
- eject
- ; set ROS data variables
- ; some clones don't do this
- ; and save Keyboard data area locally
- ; for CDOS 386
- set_ros_data:
- push ds
- push ds ! pop es
- mov ax,PC_SEGMENT
- mov ds,ax ; point to the nether region
- mov buffer_start_40,1eh ; setup these pointers for the
- mov buffer_end_40,3eh ; sake of the old COMPAQ ROS
- mov ax,equip_flag_40
- mov es:save_equip$,ax ; save equipment flag for PC terminals
- pop ds
- if V386
- push ds
- mov ax,PC_SEGMENT ;* in buffer
- mov ds,ax ;* point to the nether region
- mov si,offset kb_flag_40 ; save ROS params for PC terminals
- mov di,offset pc_kbd_save$
- mov cx,39
- rep movsb
- mov si,offset kb_flag_40 ; save ROS params for main terminal
- mov di,offset save_kbdata$
- mov cx,39
- rep movsb
- pop ds
- endif
- ret
-
-
- equip_check:
- ;-----------
- ; Check IBM equipment word, set number variables:
-
- int EQUIP_INT ; return equip word
- mov dx,ax
-
- mov cl,4
- shr dx,cl ; shift down init_video
- mov al,dl
- and al,03h
- mov init_video_mode,al ; save for crt setup
-
- mov cl,2
- shr dx,cl ; shift down floppy bits
- mov ax,dx
- and ax,03h ; mask for floppy
- inc ax ; correct 0 based code
- mov num_flop$,ax
-
- cmp al,1 ; if there is only one floppy
- jnz equip_check_des ; then use 2 designators
-
- mov al,2 ; this fakes a B: drive
-
- equip_check_des: ; in single drive systems
- mov num_flop_des$,ax
-
- mov cl,3
- shr dx,cl ; shift down port bits
- mov ax,dx
- and ax,07h ; mask for serial ports
- mov num_port$,ax
-
- mov cl,5
- shr dx,cl ; shift down printer bits
- mov ax,dx
- and ax,03h ; mask for printer
- mov num_print$,ax
-
- mov ah,8 ; XT param check
- mov dl,80h ; first hard disk code
- int DISK_INT
- jnc equip_ch1 ; skip if dl good
- mov dl,0 ; else no hard disks
- equip_ch1:
- mov dh,0
- mov num_hard$,dx
-
- sub dx,dx ; start off with first floppy
- equip_loop:
- mov si,dx ; SI = DX = drive type
- push dx ; save drive number
- mov ah,8 ; get drive parameters (supported if
- int DISK_INT ; ROS handles 3.5" Sony drives)
- pop dx ; restore drive number
- jc equip_ft_change ; ROS doesn't support 3.5", check hyper
- cmp ch,TOP_CYLIN_48 ; is this a 48 TPI 5.25" drive?
- je equip_ft_next ; yes, this is the default
- cmp cl,EOT_HYPER_96 ; check for 5.25" hyper drives (1.2 Mb)
- je equip_ft_hyper ; yes, this is a hyper drive
- mov drive_type$[si],SONY_DRIVE
- jmps equip_ft_next ; must be 720K or 1.44Mb 3.5" drive
-
- equip_ft_change: ; ROS version doesn't support 3.5"
- mov ah,15H ; maybe hyper, read DASD type
- int DISK_INT ; call floppy ROM BIOS
- jc equip_ft_next ; must be 360 K if hyper not supported
- cmp ah,2 ; disk change line available?
- jne equip_ft_next ; must be 360 K if no change line
-
- equip_ft_hyper: ; this drive is a hyper drive (1.2 Mb)
- mov drive_type$[si],HYPER_DRIVE
- mov data_rate$[si],RATE_HYPER_48
-
- equip_ft_next:
- inc dx ; next physical drive
- cmp dx,num_flop$ ; all floppy drives checked?
- jb equip_loop ; repeat until all floppies done
-
- call set_time@ ; get the time and date
-
- ; Check RAM size. Int 12h (MEM_INT) is reliable except for old 64k PCs.
- ; The ROS in those machines had a wrap problem, where if you set the DIPS
- ; to say 576, 608, or 640k, int 12 returned that minus 512k. The ROS would
- ; never initialize that 96k above 544, and parity errors could result, since
- ; the memory needs to be written with something prior to reading.
-
- int MEM_INT ; check total memory size
-
- if XM ; skip this for 386's
- push ds ; check machine type
- mov cx,0FFFFh
- mov ds,cx
- cmp byte ptr .0Eh,PC_TYPE
- pop ds
- jne not_pc
-
- ; If ax = 544k, or ax = 64, 96, or 128 k, play the special memory tricks:
- cmp ax,128
- jbe patch_mem
- cmp ax,544
- jb not_problem
-
- ; Look for memory from 544 to 640 and initialize it if found
- patch_mem:
- push es ; use to reach more than 64k
- mov ax,544 shl 6 ; starting segment = 544k
- mov es,ax
- mov bx,640 - 544 ; number of Kbytes to check
- mov dx,0DBDBh ; ancient druidic tradition
- sub ax,ax ; fill word
-
- hi_tpa_lp:
- sub di,di ; start of 1K block
- mov es:[di],dx ; set the test pattern
- push ax ; wipe out bus float
- pop ax
- cmp es:[di],dx ; see if memory is real
- jnz ram_done ; and skip if it isn't
-
- mov cx,512 ; words per Kbyte
- rep stosw ; zero a 1K block
- mov cx,es ; now, bump the es register
- add cx,1024 shr 4 ; to let us get to more
- mov es,cx ; than 64k of memory
- dec bx ; Kbyte count
- jnz hi_tpa_lp ; continue up to 640k
-
- ; bx = # kbs to subtract from 640kb to get our total ram:
- ram_done:
- mov ax,640
- sub ax,bx
- pop es
-
- not_problem:
- not_pc:
-
- endif ; endif XM
-
- ; On the IBM PS/2 range, handle extended BIOS data
- ; at the top of the first (usually) 640 Kb:
- ; (Otherwise, we'd have problems with paging on a 639 K machine)
-
- mov cx,PC_SEGMENT ; DS:0000 -> ROM BIOS data segment
- push ds
- mov ds,cx
- mov cx,extended_BIOS_40 ; get extended BIOS segment
- jcxz no_ext_BIOS ; skip if no extended BIOS data
- mov ds,cx ; else DS:0 -> extended data segment
- add al,.0 ; add extended BIOS into memory size
- adc ah,0 ; (in case there ever is a carry)
- no_ext_BIOS:
- pop ds
-
- xor cx,cx
- mov es,cx
- mov si,HD_PARAM_INTERRUPT*4
- mov cx,es:2[si] ; get pointer segment
- cmp cx,08000h
- jbe no_disk_reloc ; too low
- mov dx,0A000h
- cmp cx,dx
- jae no_disk_reloc ; not in TPA
- sub dx,cx ; dx = number of paras to move
- mov reloc_disk$,dx ; save number for move
- mov cl,6
- shr dx,cl ; DL= size in 1k blocks
- add al,dl
- adc ah,0
- no_disk_reloc:
-
- mov num_mmkb$,ax ; save kilobytes
- mov cl,6
- shl ax,cl ; change to paragraph count
- mov memory_top,ax ; save for memory trim
- mov lo_mem_top$,ax ; keep a permanent copy
- ret
-
-
- crt_check:
- ;---------
- ; Do a memory check on the crt ram:
-
- mov es,ax ; crt segment
- mov cx,1234h ; dummy pattern for ..
- mov ax,0DDB2h ; bit pattern
- mov es:[bx],ax ; store it
- push cx ; ... bus float protection
- pop cx
- sub ax,es:[bx] ; check it
- jnz crt_chk1 ; and skip if not there
-
- mov ax,blank$ ; once more for
- mov es:[bx],ax ; good measure
- push cx
- pop cx
- sub ax,es:[bx]
- jnz crt_chk1
-
- inc ax ; only one
- ret
- crt_chk1:
- sub ax,ax ; nobody home
- ret
-
-
-
- herc_check:
- ;----------
- ; Get hercules card text retrace timing
-
- test video$,MONO
- jz no_check ; only check if we have mono
- test word ptr su_flag_bits$, HERC_ENABLE_BIT ; retrace timing enabled ??
- jnz herc_check1
- no_check:
- jmp no_herc_exit ; not enabled
- herc_check1:
- mov cx,20 ; 20 times to find min value
- herc_check_loop:
- push cx
- mov si,2 ; outer timeout counter
- mov cx,0
- herc_check2:
- mov dx,MONO_PORT+6 ; status port
- mov di,0 ; timeout count
- herc_check_active:
- sti
- nop ; interrupt window
- cli
- in al,dx
- rol al,1 ; wait for active (bit 7 set)
- jnc herc_next_check
- in al,dx
- rol al,1 ; wait for retrace (bit 7 clr)
- jc herc_next_check
-
- ;read timer at start of retrace
- mov al,0
- out TIMER_CMND_REG,al ; latch timer 0
- in al,TIMER_0_REG ; lsb
- mov ah,al
- in al,TIMER_0_REG ; msb
- xchg al,ah ; swap to word value
- mov bx,ax ; save value
- herc_retrace_wait:
- in al,dx
- rol al,1 ; wait for active ( bit 7 set)
- jc herc_retrace
- loop herc_retrace_wait
- jmp no_herc ; this is taking too long.... exit
-
- herc_retrace: ;read timer at end of retrace
- mov al,0
- out TIMER_CMND_REG,al ; latch timer 0
- in al,TIMER_0_REG ; lsb
- mov ah,al
- in al,TIMER_0_REG ; msb
- xchg al,ah ; swap to word value
- sti
- ; BX = old value...
- sub bx,ax ; BX = time difference
- jc herc_next_check ; oops.. looped try again
- cmp word ptr retrace$,0eeeeh
- je set_retrace
- mov ax,retrace$
- mov dx,bx ; new value
- sub dx,ax ; lets do a range check
- jnc test_range ; new value < or > 20h previous value
- neg dx
- test_range:
- cmp dx,20h ; if values wildly different
- jg no_herc ; then something is not quite right
- cmp bx,retrace$ ; else compare with previous
- jnb herc_next_try ; if this time is smaller....
- set_retrace:
- mov retrace$,bx ; then update LOWEST value
- herc_next_try:
- pop cx
- loop herc_check_loop ; and try again...
- sub retrace$,8 ; based on experiment
- sti ; of hercules & clones
- ret
-
- herc_next_check:
- inc di
- jnz herc_check_active ; else try again
- dec si
- jnz herc_check2
- no_herc:
- pop cx
- no_herc_exit:
- mov retrace$,0EEEEh ; no hercules...
- sti
- ret
-
-
-
-
- check_hi_mem:
- ;------------
- ; Check for memory at or above C000:0000:
-
- mov dx,0C000h ; starting segment
- mov cx,(0F000h-0C000h)/400h ; 16k block count
- test pc_at$,0FFh ; test up to F000 on PC's
- jz ch_hi_mem0
- mov cx,(0E000h-0C000h)/400h ; above E000 taboo for RAM on AT's
- ch_hi_mem0:
- mov ax,0DDB2h ; check pattern
- mov bx,1234h ; dummy for bus float
- ch_hi_mem1:
- call ch_hi_word ; is there RAM ?
- jz ch_hi_mem2 ; if so, skip
- add dx,400h ; check next 16k
- loop ch_hi_mem1 ; up to F000
- ret ; if none there, return
-
- ch_hi_mem2:
- mov hi_mem_start$,dx ; there is some memory
- ch_hi_mem3:
- add dx,400h ; up 16k
- call ch_hi_word ; as long as it's good
- jz ch_hi_mem3 ; keep on going
- mov hi_mem_top$,dx ; and save the top
- ret
-
- ch_hi_word:
- sub si,si ; zero index
- mov es,dx ; set check segment
- mov bp,es:[si] ; save data
- push bx ! pop bx ; bus float
- mov es:[si],ax ; store check pattern
- push bx ! pop bx
- cmp es:[si],ax ; and see if it matches
- mov es:[si],bp ; restore data
- ret ; return with zf set
- eject
-
- ndp_init:
- ;--------
- ; 8087 Numeric Data Processor initiation routine:
-
- test pc_at$,0ffh ; find 287 differently
- jz no_286
- int 11h ; equipment determination
- test ax,2 ; 2nd bit set means present
- jnz found_ndp ; show it
- jmps ndp_init_done
-
- no_286:
- FNINIT ; init and check for 8087
- xor ax,ax ; stall for time
- mov ndp_control$,ax ; and clear control word
- FNSTCW ndp_control$ ; get 8087 control word
- or ax,ndp_control$ ; test for 8087 presence
- jz ndp_init_done ; if not there, skip
-
- found_ndp:
- mov num_ndp$,1 ; we've got one!
- mov owner_8087$,0 ; tell the system about it
-
- mov ndp_int_off$,NMI_INTERRUPT * 4
- mov ndp_int_seg$,0 ; save the vector location
- mov ndp_vec_off$,offset i_ndp@
- mov ndp_vec_seg$,cs ; and the interrupt vector
- ndp_init_done:
- ret
-
-
-
- eject
-
- compaq:
- ;------
- ; If this is the compaq, change cursor, sync and sl_attrib$:
-
- mov ax,0F000h
- mov es,ax ; ROM segment
- mov di,0FFEAh ; ID offset
- mov si,offset compaq_name
- mov cx,length compaq_name
- repz cmpsb ; look for a match
- je compaq1
- ret ; no, ain't a COMPAQ
- compaq1:
- mov cloneflag$,IS_COMPAQ ; remember, it's a COMPAQ
- push ds
- sub bx,bx
- mov ds,bx ; point to int vectors
- lds bx,VIDEO_PARMS_INTERRUPT*4[bx] ; ds:bx = param table start
- cmp word ptr 1ah[bx],0706h ; is it 8*8 CGA mode
- pop ds
- je not_cmpq_cga ; yes - do not set special
- mov var_cursor$,COMPAQ_CURSOR ; Compaq values
- mov var_sync$,0 ; no retrace sync on dual mode CGA
- mov sl_attrib$,0Fh ; enhanced white
- mov alpha_str_80$,offset compaq_str$
- not_cmpq_cga:
-
- if V386
- mov ega_remap,TRUE ; allow EGA remap from E000 to C000
-
- mov hi_off$,00fffh ; nothing above F000 on COMPAQ
- mov hi_on$, 00f00h ; always enable E000-EFFF
-
- mov dx,00FAh ; initialize memory at 00FA0000h
- call xmem_256k ; try to find extra memory up there
- endif
-
- compaq_done:
- ret ; all for now
-
- if V386
- compaq_protect:
- ;#IJ test video$,EGA+VGA ; do we have EGA
- ;#IJ jz not_ega_compaq ; (we may have an inactive one !)
-
- cmp int10_isr$+2,0e000h ; (CODE SEG) was it pointing to RAM copy
- jne not_ega_compaq ; no leave well alone
- mov ax,0c000h
- mov es,ax ; Rom address
- mov int10_isr$+2,ax ; (CODE SEG) point back to 8 bit rom
- push ds ; in our copy
- xor dx,dx ; and interrupt vectors
- mov ds,dx
- mov bx,((1fh*4)+2)
- mov [bx],ax
- mov bx,((43h*4)+2)
- mov [bx],ax
- pop ds
-
- xor ah,ah
- mov al,es:.02h ; get # of 512 byte pages in ROM
- add al,((16384/512)-1)
- shr al,5 ; AL = # of 16 Kb pages
- shl al,2 ; 4 page table entries per 16 kb page
- mov cx,ax ; cx = number of page table entries
-
- mov bx,v386_ptr ; get page table address thru table
- mov es,ptbl_seg
- mov bx,(0c000h shr 6)+1 ; get entry for 8 bit EGA rom
- mov ax,0e00h ; and replace with new linear address
- ega_rom_loop:
- mov es:[bx],ax
- add bx,4 ; next page table entry
- add ax,10h ; and address
- loop ega_rom_loop
-
- not_ega_compaq:
- ret
- endif
-
-
- eject
-
- if V386
- sprite386:
- ;---------
- mov ax,0F000h
- mov es,ax ; ROM segment
- mov di,0E076h ; ID offset
- mov si,offset sprite_name
- mov cx,length sprite_name
- repe cmpsb ; look for a match
- jnz sprite_done
-
- push ds
- mov si,0C000h ; copy EGA ROM in case there is one
- mov ds,si ; move from C000:0000 to E000:0000
- sub si,si
- mov di,0E000h ; copy to E000h:0000h
- mov es,di
- sub di,di
- mov cx,32*(1024/WORD)
- call rom_to_ram ; copy 32 Kb of EGA/VGA ROM
-
- mov si,0F000h
- mov ds,si
- mov es,si
- sub si,si
- sub di,di
- mov cx,64*(1024/WORD) ; copy 64 Kb of Phoenix ROM BIOS
- call rom_to_ram ; from ROM to RAM at same address
- pop ds
-
- cmp int10_isr$+2,0C000h ; is it pointing at EGA ROM?
- jne fix_sprite_ega ; skip if not EGA ROM at usual place
- push ds
- mov si,0C000h
- mov ds,si ; test if we could relocate EGA
- mov di,0E000h
- mov es,di ; to COMPAQ compatible address
- sub si,si
- sub di,di ; compare C000:0000 to E000:0000
- mov cx,(16*1024)/2 ; compare first 16 K
- repe cmpsw ; check if ROM copied alright
- pop ds
- jne fix_sprite_ega ; skip if ROM copy failed
- mov int10_isr$+2,0E000h ; point it to where COMPAQ has it
- mov ega_remap,TRUE ; allow EGA remapping
- fix_sprite_ega:
-
- ;; mov dx,0F800h
- ;; mov cx,00800h ; write protect last 32K
- ;; call write_protect
-
- mov hi_off$,03fffh ; nothing above F800 on Sprite 386
- mov hi_on$, 03f00h ; always enable E000-F800
-
- mov dx,00CAh ; initialize memory at 00CA0000h
- call xmem_256k ; try to find extra memory up there
-
- sprite_done:
- ret
-
-
-
- ; Entry: DS:SI -> source of ROM block
- ; ES:DI -> destination of ROM block
- ; CX = # of words to move
- ; Exit: SI, DI updated
- ; ROM copied to RAM
-
- rom_to_ram:
- mov dx,0318h ; standard Sprite ROM switch port
- rom_to_ram_lp:
- mov al,1 ; select ROM
- out dx,al
- jmps $+2 ; i/o delay
- lodsw ; read a word from ROM
- push ax ; save word
- mov es:[di],ax
- mov al,2 ; select RAM
- out dx,al
- pop ax ; get data word
- stosw ; write it to RAM
- loop rom_to_ram_lp ; repeat for entire ROM
- ret
-
-
- xmem_256k:
- ;---------
- ; Check for 256 K of RAM shadowed out from A000-E000
- ; to allow for video memory and adapter space. On some
- ; 386 ATs (eg. COMPAQ) this memory is relocated to one
- ; of the top megabytes and can be put to good use by CDOS 386.
-
- ; Entry: DX = A16..A31 where memory might reside
- ; Exit: hi_xmem_size$ updated if memory found
-
- mov ah,88h ; extended memory size determine
- int 15H ; AX = Kb of extended memory
- add ax,1024h ; AX = Kb address of end of RAM
- shr ax,6 ; AX = A16..A31 of end of linear RAM
- cmp ax,dx ; RAM higher than 256K extension?
- jae xmem_256k_done ; skip 256K test if yes
-
- mov hi_xmem_addr$,dx ; set potential high memory
- mov cx,256/64 ; 4 banks of 64K (256K total)
- xmem_256k_lp1:
- push cx ! push dx ; save count, base address
- sub bx,bx
- mov es,bx ; move from ES:BX -> 0000:0000
- sub ax,ax ; to DX*10000h
- mov cx,8000h ; move 64 Kb to initialize parity
- call xmem_write ; move to high memory
- pop dx ! pop cx ; restore address, count
- inc dx ; next 64K bank
- loop xmem_256k_lp1 ; repeat for all banks
-
- mov dx,hi_xmem_addr$ ; get potential high memory
- mov cx,256/64 ; now check banks for presence
- xmem_256k_lp2:
- push cx ! push dx ; save count, address
- mov ax,055AAh ; get test pattern #1
- call test_256k ; perform read/write test
- jnz xmem_256k_bad ; give up if no RAM
- mov ax,0AA55h ; get test pattern #2
- call test_256k ; perform read/write test
- jnz xmem_256k_bad ; give up if no RAM
- add hi_xmem_size$,(64/16) ; number of extra pages up there
- cmp ax,ax ; set ZF = 1 for good test
- xmem_256k_bad:
- pop dx ! pop cx ; restore address, count
- jnz xmem_256k_done ; break out if test failed
- inc dx ; next 64K bank to test
- loop xmem_256k_lp2 ; repeat for all banks
- xmem_256k_done: ; high memory test done
- ret
-
-
- test_256k:
- ; Entry: AX = 16 bit test pattern
- ; DX = A16-A31 for memory block to test
- ; Exit: ZF = 1 if test succeeded
- ; AX, DX preserved
-
- push ax ! push dx ; save pattern, address
- mov int15_config,ax ; save store for move
- call int15_setup ; setup pointers for move
- call xmem_write ; move pattern to extended memory
- not int15_config ; negate pattern in case move fails
- pop dx ! push dx ; recover & save value A16-A31
- call int15_setup ; setup pointers for move
- call xmem_read ; read back test pattern
- pop dx ! pop ax ; restore address, original pattern
- cmp ax,int15_config ; check if read back O.K.
- ret ; ZF = 1 if memory O.K.
-
- int15_setup:
- ; Entry: DX = A16..A31 for extended move
- ; Exit: AX/DX = 32 bit address
- ; ES:BX = 8086 address
- ; CX = 1
-
- sub ax,ax ; A0..A16 = 0000h
- push ds ! pop es
- mov bx,offset int15_config ; ES:BX -> int15_config
- mov cx,1 ; CX = word count
- ret
-
- xmem_read:
- ;---------
- ; Entry: ES:BX -> destination (1st Mb)
- ; AX/DX = 32 bit source address (anywhere)
- ; CX = word count for block move
-
- mov si,offset int15_gdt+10h ; source selector
- mov di,offset int15_gdt+18h ; destination selector
- jmps xmem_rw ; make a move...
-
- xmem_write:
- ;----------
- ; Entry: AX/DX = 32 bit destination address (anywhere)
- ; ES:BX -> source (1st Mb)
-
- mov di,offset int15_gdt+10h ; source selector
- mov si,offset int15_gdt+18h ; destination descriptor
- ; jmps xmem_rw ; make a move
-
- xmem_rw:
- mov 2[si],ax ; set A0-A15
- mov 4[si],dl ; set A15-A23
- mov 7[si],dh ; set A24-A31
-
- mov ax,es ; get segment in 1st Mb
- mov dx,16 ; bytes per paragraph
- mul dx ; AX/DX = 32 bit address of ES
- add ax,bx ; add in the offset within segment
- adc dx,0 ; add in the carry
- mov 2[di],ax ; set A0-A15
- mov 4[di],dl ; set A15-A23
- mov 7[di],dh ; set A14-A31
-
- mov ah,87H ; extended memory move function
- push ds ! pop es
- mov si,offset int15_gdt ; ES:SI -> GDT for ROS use
- int 15H ; call AT compatible ROS
- ret
-
- write_protect:
- ;-------------
- ; entry: DX = segment address to protect
- ; CX = # of paragraphs to protect
- ; (both must be multiple of 100h)
-
- mov bx,mdul ; steal entry from MDUL
- mov ax,MD_LINK[bx] ; (no CLI/STI as we're only process
- mov mdul,ax ; running here)
-
- mov MD_START[bx],dx ; set start of block to protect
- mov MD_LENGTH[bx],cx ; set length of block to protect
- mov si,v386_ptr ; get 386 structure
- mov ax,ro_mem_root[si] ; get current R/O list
- mov MD_LINK[bx],ax ; append it to our entry
- mov ro_mem_root[si],bx ; link us into R/O list
-
- ret ; MEM will make these pages R/O
-
- endif
-
- eject
-
- if XM
- ; Now check for a couple of 8086-2 machines (XM only, not 386)
- ; to make use of any useful special features (RTC, etc.)
-
- amstrad:
- ;-------
- mov ax,0F000h
- mov es,ax ; ROM segment
- mov si, offset amstrad_name
- mov di, 0C016h ; ID offset
- mov cx, 7
- repz cmpsb ; look for a match
- jnz amstrad_done
-
- mov cloneflag$, IS_AMSTRAD ; is Amstrad so
- call set_time@ ; set the system time from RTC
- mov var_sync$,0 ; no retrace syncing - wide open
-
- ; Get Default Attributes from the RTC
- mov al,RTC_VDU
- call read_286_cmos
- mov iattrib$,al ; save initial attribute
-
- amstrad_done:
- ret
-
- eject
- check_8530: ; check for PS/2 model 30
- ;----------
- ; Check to see if we're running on the PS/2 Model 30
-
- mov ax,0FFFFh ; top of rom
- mov es,ax
- mov al,es:.0Eh ; get IBM model byte
- cmp al,0FAh ; check if on PS/2 model 30
- jne not_8530
-
- mov var_sync$,0 ; no syncing w/ MCGA
- or video$,MCGA ; yes, we've got MCGA
-
- mov disk_chng_mask$,80h ; disk change mask
- mov dx,FDC_RATE ; initialize the data rate to 250 Kbit
- mov al,RATE_SLOW_48 ; as our disk code won't
- out dx,al ; set it up on non-AT machines
-
- jmp set_time@ ; set current time & date
-
- not_8530:
- ret
-
-
- eject
-
- olivetti: ; check for Olivetti M24 or M24SP
- ;--------
- mov ax,0F000h
- mov es,ax ; ROM segment
- mov di,0C050H ; ID offset
- mov si,offset olivetti_name
- mov cx,8
- repz cmpsb ; look for a match
- jnz olivetti_done
-
- mov si,offset oli_vector$ ; setup extra video modes
- mov [si],offset bw_640_400@ ; ROS mode 64
- mov 1*2[si],offset bw_640_400_t@ ; ROS mode 72
- mov cloneflag$, IS_M24 ; support video modes on M24/M28
-
- cmp pc_at$,0 ; treat M28 like an IBM AT
- jne olivetti_done ; not like an M24...
- mov ax,0FFFFh ; top of rom
- mov es,ax
- mov al,es:.0Eh ; get model byte
- cmp al,0FBh ; XT with 640k = M240
- je oli_48_tpi
- in al,67h ; read the motherboard switches
- test al,01h ; test SW1: 96 TPI option installed
- jz oli_48_tpi ; skip if normal 48 TPI drives
- mov al,HYPER_DRIVE ; else 80 tracks, double step magic
- mov drive_type$+0,al ; required for reading 48 TPI media
- mov drive_type$+1,al ; on both A: and B: (if we have both)
- oli_48_tpi:
-
- ; M24 has battery backed up real time clock
-
- mov ah,0FEh ; get time in clock chip
- int TOD_INT ; read battery backed up time
-
- push ds ! pop es ; point ES to SYSDAT for string op's
-
- mov di,offset tod_day$ ; point to SYSDAT time
- add bx,365*5+366 ; days from 1/1/78 to 1/1/84
- inc bx ; rel to 1
- mov ax,bx
- stosw
-
- push cx
- mov al,ch
- call o_mk_bcd
- pop cx
-
- mov al,cl
- call o_mk_bcd
-
- mov al,dh
- ; call o_mk_bcd
- ; ret
-
-
- o_mk_bcd:
- ;--------
- ; entry: AL = binary
- ; exit: BCD equivalent stored at DI
-
- xor ah,ah ;0 tens count
- mb_tens:
- cmp al,15
- jbe mb_aaa
- sub al,10
- inc ah
- jmps mb_tens
- mb_aaa:
- add al,0 ;make into packed BCD
- aaa
- mov cl,4
- shl ah,cl
- or al,ah
- stosb ;and save it
-
- olivetti_done:
- ret
-
- endif ; endif XM
-
- eject
-
- fix_crt:
- ;-------
- ; Set up the mono/color vs_ variables and test for EGA:
-
- ; These things need to be determined for EGA support:
- ; 1. Is an EGA present?
- ; 2. Is it the "primary" display (default on boot)?
- ; 3. Is it acting as a color card or a mono card?
- ; 4. Is the Enhanced Color Display attached if in color card mode?
-
- ; An EGA is present if int 10 function 12h does not alter BX.
-
- ; An EGA is the "primary" display if an int 10h (alternate select)
- ; returns cl > 5 on bl = 10h.
- ; and EGA type = MONO if BH = 1, COLOR if BH = 0.
-
-
- ; Get EGA information
- mov ax,1Ah*256+0 ; get display type combination
- int VIDEO_INT
- cmp al,1Ah ; 0 if not implemented, 1Ah if OK
- jne check_ega ; skip if not PS/2 video adapter
- cmp bl,2
- jbe no_ega ; if primary = MDA or CGA, ignore VGA
- check_ega:
-
- mov bh,0ffh
- mov ax,1200h ; alternate select
- mov bl,10h ; return EGA info
- int VIDEO_INT ; BH = 0 color, 1 mono
- ; BH unchanged = no EGA
- ; BL = memsize
- ; CH = feature bits
- ; CL = switch settings
- cmp bh,0ffh
- jne ega_here
- jmp no_ega
-
- ; Here if we've got an EGA. See if it's color or mono:
- ega_here:
- or video$,EGA ; set video flag
-
- ; First replace the "mode_not_supported" vectors in the mode vector table
- ; with the routines for the ega modes:
- mov var_cursor$,COLOR_CURSOR ; overwrite COMPAQ value
- mov al,MONO ; assume mono
- cmp bh,1
- je ega_mono ; Mono monitor EGA
- mov al,COLOR ; indicate color
- mov var_sync$,0 ; no syncing w/ ega
- ega_mono:
- or video$,al ; byte now set up
-
- ; If the ega is mono, skip the ECD stuff:
- test video$,MONO
- jnz ecd_done
-
- ; Check for the enhanced modes:
- cmp cl,0010b ! je ecd ; bit set (1) = SW off
- cmp cl,0011b ! je ecd
- cmp cl,1000b ! je ecd
- cmp cl,1001b ! jne ecd_done
- ecd:
- ; Here if the Enhanced Color Display is attached:
- or video$,ECD ; set bit
-
- ecd_done:
- mov ax,1Ah*256+0 ; get display type combination
- int VIDEO_INT
- cmp al,1Ah ; 0 if not implemented, 1Ah if OK
- jne no_ega ; skip if not PS/2 video adapter
- cmp bl,7 ; PS/2 w/ VGA and mono monitor
- je vga_here
- cmp bl,8 ; PS/2 w/ VGA and color monitor
- jne no_ega ; else we can't cope...
- vga_here:
- or video$,VGA ; set VGA bit
-
- no_ega:
- mov si,offset set_mono@ ; assume monochrome
- mov di,offset z_sl_mono@ ; for status line too
- cmp init_video_mode,03h ; if mono switched on
- jnz fix_color
- test video$,EGA
- jnz fix_crt1
- or video$,MONO ; set mono bit
- jmps fix_crt1 ; then skip
-
- fix_color:
- mov si,offset set_color@ ; else color
- mov di,offset z_sl_color@ ; and color status
- test video$,EGA
- jnz fix_crt1
- or video$,COLOR ; set color bit
- fix_crt1:
- push si
- call di ; set status line
- pop si
- sub dl,dl ; first vc number
- fix_crt2:
- push dx ! push si
- call point_vs@ ; bx -> structure
- call si ; mono or color
- pop si ! pop dx
- inc dx ; next vc
- cmp dl,NUM_VIR_CONS ; through the last
- jb fix_crt2
-
- test video$,EGA+VGA+MCGA+MONO ; make sure it is possibly AST COLOR
- jnz not_ast
- mov ast_flag$,0ffh ; set AST colorcard possible flag
- not_ast:
- ret
-
-
- fix_ega_pal:
- test video$,EGA+VGA
- jz no_ega1
- push ds
- push ds ! pop es
- mov ax,PC_SEGMENT
- mov ds,ax
- lds si,dword ptr .0a8h ; get pointer to save_ptr in EGA ROS
- mov di,offset local_ptr$
- mov cx,16
- push di
- cld
- rep movsw ; move table locally
- pop di
- mov ds,ax
- mov .0a8h,di ; save our pointer in ROS data
- mov .0a8h + 2,es
- pop ds
- mov dx,256/16 ; ega spec specifies 256
- call mem_alloc_i@ ; for pallette save area
- mov local_ptr$+6,ax ; save segment save area in local ptr
- mov local_ptr$+4,0000
- mov ax,0f00h ; get current video mode
- pushf
- callf cs:dword ptr int10_isr$
-
- mov ah,0
- or al,80h ; reset mode without clearing screen
- pushf
- callf cs:dword ptr int10_isr$ ; to initialise palette save area
- ; into our local table
-
- xor bx,bx ; start with virtual console 0
- mov cx,NUM_VIR_CONS
- init_pal:
- push bx ! push cx
- mov bx,table_vs$[bx]
- lea di,VS_PALLETTE ; get save area
- xor si,si
- push ds
- mov ds,local_ptr$+6 ; get pallette segment save area
- mov cx,17
- rep movsb
- pop ds
- pop cx ! pop bx
- add bx,2 ; next VC_
- loop init_pal ; save for all vs's
-
- no_ega1:
- ret
-
-
- eject
-
- fix_disk_tables:
- ;---------------
- ; Correct the disk tables to match physical configuration:
-
- sub bx,bx ; start with 1st drive
- dos_dpb_alloc:
- push bx ; save the drive index
- mov dx,29 ; allocate one DPB/drive
- call sysdat_mem_alloc ; returns offset in AX
- pop bx ; restore drive index
- mov si,bx ; make bx+si = 2*bx
- mov dos_dpbs$[bx+si],ax ; save DPB for dynamic DPBs
- inc bx ; point to next drive
- cmp bx,num_flop$ ; all floppies done?
- jne dos_dpb_alloc ; loop back if more
-
- sub ax,ax ; ax = 0; al = A:
- mov temp_disk$,al ; tempory disk default
-
- push ds ! pop es ; local extra segment
- mov di,offset dph_tbl$ ; first we must zap the
- mov cx,num_flop$
- alloc_flop_dphs:
- push cx ! push di
- mov dx,DPH_SIZE+8 ; allocate DPH plus some extra data
- call sysdat_ext_alloc ; grow SYSDAT by DX bytes, return in AX
- pop di ; restore address of next DPH
- stosw ; save address of DPH in DPH table
- push di ; save address of next DPH table entry
- xchg ax,di ; DI -> new DPH
- push di
- sub ax,ax ; get a zero to initialize it
- mov cx,(DPH_SIZE+8)/WORD ; size of DPH in byte
- rep stosw ; zero out new DPH
- pop di ; start of DPH
- mov ax,offset pcdpb9D$ ; insert temp DPB pointer into DPH
- mov DPH_DPB[di],ax
- pop di ! pop cx ; restore DPH pointer, loop count
- loop alloc_flop_dphs ; do next disk parameter header
- mov cx,8
- sub cx,num_flop$ ; number of drives remaining
- sub ax,ax ; get a zero to initialize it
- rep stosw ; zero out all other DPHs
-
-
- ; Now, set up the true dph and branch vector tables:
-
- sub di,di ; di = 0, first entry
- mov cx,num_flop$ ; first the floppies
- mov bx,offset dph_tbl$ ; list of floppy dph's
- fix_flops:
- mov si,offset flop_vectors ; select, read, write flops
- call fix_one_disk ; set dph and vectors
- loop fix_flops
-
- cmp num_flop$,1 ; now, if only one floppy
- jnz fix_flop_done ; then we special case
- inc di ! inc di ; by skipping B:
-
- fix_flop_done:
-
- ; Hard disk setup moved to hd_init
- mov pc_hd_dph_start,di ; save pointer to first DOS partition DPH
-
- ret
-
- ; Set up table entries for one disk:
-
- fix_one_disk:
- mov ax,[bx] ; get the dph offset
- mov dph_tbl$[di],ax ; set dph
- lodsw ; fetch the select vector
- mov select_tbl$[di],ax
- lodsw ; fetch the read vector
- mov read_tbl$[di],ax
- lodsw ; fetch the write vector
- mov write_tbl$[di],ax
- inc bx ! inc bx ; to next dph entry
- inc di ! inc di ; to next vector entry
- ret
-
-
- eject
-
- printer_init:
- ;------------
- ; Reset all parallel printer ports:
- ; Set up list_out$ and list_stat$ tables:
- ; Collapse parallels:
-
- cmp num_print$,0 ; test count
- mov cx,3 ; total number
- jne pr_par_loop
- xor di,di
- pr_loop:
- mov bx,lcb_list$[di] ; get pointer to LCB
- mov LCB_ATTACH[bx],UNAVAILABLE ; mark for TMP
- inc di ! inc di
- loop pr_loop
- jmp pr_par_done
-
- pr_par_loop:
- sub dx,dx ; first is zero
- pr_par_loop1:
- mov ah,1 ; reset code
- int PRINT_INT
- inc dx ; next printer
- loop pr_par_loop1
-
- mov ax,40h ; look into base page
- mov es,ax
- mov si,8 ; printer address list
- mov di,0 ; logical number index
- mov bx,0
- mov cx,3
- pr_par_loop2:
- push cx
- push bx
- mov ax,es:[si] ; fetch printer address
- or ax,ax ; anything there?
- jnz pr_par_set
- mov bx,lcb_list$[bx] ; get pointer to LCB
- mov LCB_ATTACH[bx],UNAVAILABLE ; mark for TMP
- jmps pr_par_next
-
- pr_par_set:
- mov list_data$[di],ax
- mov list_out$[di],offset parallel_out@
- mov list_stat$[di],offset parallel_stat@
-
- mov ax,di
- shr al,1
- call conv_digit@
- call put_in_s_o ; put in sign-on
-
- inc di ! inc di ; next logical number
- pr_par_next:
- inc si
- inc si ; next list entry
- pop bx
- inc bx
- inc bx
- pop cx
- loop pr_par_loop2
-
- ; We don't do this for serial printers any more...
- ; Do_aux_ports takes care of it for us.
-
- pr_par_done:
- ret
-
-
- put_in_s_o:
- ; al,ah = ascii printer number
- push bx
- mov bx,offset sign_on_prnum
- mov dx,bx
- mov cx,8*3 ; 8 per line
- call find_lp
- cmp ch,0ffh
- jne put_done
- mov bx,offset sign_on_prnum1
- mov dx,bx
- mov cx,8 ; 8 per line
- call find_lp
- put_done:
- pop bx
- ret
-
- find_lp:
- cmp byte ptr [bx],' '
- je find_lp1 ; try next if already taken
- inc bx
- loop find_lp
- mov ch,0ffh ; error exit
- ret
- find_lp1:
- cmp bx,dx ; is this the first number ?
- je find_lp5 ; yes, just get on with it
- call test_next_in_seq ; is it the next in a sequence ?
- jne find_lp3 ; no, we add a ","
- call rewind_if_dash ; have we already got a "-" ?
- mov byte ptr [bx],'-' ; is so rewind, then do this one
- jmps find_lp4
- find_lp3:
- mov byte ptr [bx],','
- find_lp4:
- inc bx
- find_lp5:
- mov [bx],al
- or ah,ah ; two digit number
- jz find_lp6 ; no exit all done
- mov 1[bx],ah
- find_lp6:
- ret
-
- test_next_in_seq:
- ; on entry BX = 1st space, DX = start, AX = number
- ; on exit we set Z flag if the previous number is the immediately
- ; preceeding one in the sequence
- push ax
- push bx
- push cx
- mov cx,ax ; save the number (in ASCII form)
- dec bx
- mov al,[bx] ; get the number
- sub al,'0' ; do the ascii adjust
- cmp bx,dx ; at the start yet ?
- jle test_next_in_seq1 ; yes, no dash use old BX
- dec bx
- cmp byte ptr [bx],'0'
- jl test_next_in_seq1 ; are we looking at a number
- cmp byte ptr [bx],'9' ; if not, we already have the whole lot
- jg test_next_in_seq1 ; otherwise we need to add a digit
- mov bl,[bx]
- xchg al,bl
- sub al,'0'
- mov ah,10
- mul ah
- add al,bl ; the lot
- test_next_in_seq1:
- inc al ; this is the next in the sequence
- call conv_digit@ ; see what the ascii is
- cmp ax,cx ; does it match our number ?
- pop cx
- pop bx
- pop ax
- ret
-
- rewind_if_dash:
- ; on entry BX = 1st space, DX = start
- ; on exit BX = where we want to start writing
- ; we have already determined the previous number immediately preceeds
- ; the one we are doing, but here we check to see if it is already part
- ; of a sequence.
- ; we look before the previous number to see if it has a "-", if so we rewind
- ; BX to point at it ready to overwrite with the new number.
- push ax ; save it...
- mov ax,bx ; old BX here
- rewind1:
- dec bx
- cmp bx,dx ; before the start yet ?
- jl rewind3 ; yes, no dash use old BX
- cmp byte ptr [bx],'0'
- jl rewind2 ; are we looking at a number
- cmp byte ptr [bx],'9' ; if not, check for the '-'
- jg rewind2 ; otherwise go back another
- jmps rewind1
- rewind2:
- cmp byte ptr[bx],'-' ; have we found a dash ?
- je rewind4 ; bingo - use new BX value
- rewind3:
- mov bx,ax ; restore old BX value
- rewind4:
- pop ax ; restore it
- ret
-
- ; convert hex number in al to ascii in ah and al
- ; return tens in AL if AH<>0
- conv_digit@:
- xor ah,ah
- do_tens:
- cmp al,9
- jbe do_digit
- sub al,10
- inc ah ; increment tens
- jmps do_tens
- do_digit:
- or al,'0' ; convert to ascii
- or ah,ah
- jz do_al
- or ah,'0'
- xchg al,ah ; make al tens
- do_al:
- ret
-
-
- eject
-
- do_video:
- ;--------
- ; Initialise primary monitor
-
- test video$,COLOR
- jnz do_color ; skip mono if in color mode
- do_mono:
- sub dl,dl
- call point_vs@ ; point bx at top structure
- mov cl,7 ; ROS mode 7 (mono 80)
- call screen_set_only@ ; set default mode
- jmps do_vid_done
-
- do_color:
- sub dl,dl
- call point_vs@ ; point bx at top structure
- mov cl,3 ; ROS mode 3 (color 80)
- call screen_set_only@ ; set default mode
-
- do_vid_done:
- ret
-
- eject
-
- RSPH_LINK equ es:word ptr .00h
- RSPH_NCP equ es:byte ptr .04h
- RSPH_CGSIZE equ es:word ptr .0Ch
- RSPH_DGSIZE equ es:word ptr .0Eh
- RSPH_PDNAM equ es:byte ptr .18h
- RSPH_PCNS equ es:byte ptr .30h
- RSPH_INITDS equ es:word ptr .92h
- RSPH_INITES equ es:word ptr .94h
- RSPH_INITSS equ es:word ptr .96h
-
-
- alloc_ser_rsps: ; allocate serial TMPs and PINs
- ;--------------
- mov cl,NUM_VIR_CONS ; default start
- mov ncondev$,cl ; update # of virtual consoles
- mov nvcons$,cl ; update SYSDAT
- mov nvcns$,cl ; update XIOS header
- mov npcons$,1 ; master console
- sub di,di ; physical port number
-
- alloc_ser_loop:
- mov dl,port2pc_table$[di] ; physical console number
- cmp dl,0ffh ; allocated
- jne alloc_ser1
- jmp alloc_ser_next ; no get next possible
- alloc_ser1:
- inc npcons$ ; number of physical consoles
- ;#IJ call build_pin ; build a PIN RSP
- mov al,1 ; default 1 virtual console
- ; per physical console
-
- if not SR ; *** do not allow PCTERM and SRTERM for now ***
- if V386
- test su_mu_vs$[di],PCTERM_EMU ; test setup bit for installed port
- jz no_pcterm ; to see if pcterm emulation required
- call build_flush ; if yes then build FLUSH RSP and
- mov al,su_mu_vs$[di] ; get number of virtuals per physical
- and al,07h ; mask number of virtuals
- no_pcterm:
- endif
- endif
-
- if SR
- test su_mu_vs$[di],VTERM_EMU ; test setup bit for installed port
- jz no_vterm ; to see if sun river emulation required
- mov al,su_mu_vs$[di] ; get number of virtuals per physical
- and al,07h ; mask number of virtuals
- push ax
- push cx
-
- mov bx,offset sr_pc_table$-1 ; Sun River physical console table
- find_free_pc:
- inc bx
- cmp byte ptr[bx],0ffh ; free ?
- jne find_free_pc
- mov [bx],dl ; current PC number
-
- mov bx,offset sr_vs_table$-1 ; Sun River virtual console table
- find_free_vs:
- inc bx
- cmp byte ptr[bx],0ffh ; free ?
- jne find_free_vs
- insert_vs:
- mov [bx],cl ; current VS number
- inc cl
- inc bx
- dec al ; number of virtual per physical
- jnz insert_vs
- pop cx
- pop ax
-
- no_vterm:
- endif
-
- build_ccb: ; re-allocate the CCB's
- mov bl,cl ; current VS number to assign
- xor bh,bh
- shl bx,1
- mov si,ccb_list$[bx] ; get free CCB
- mov C_PC[si],dl ; insert physical console number
- mov C_VC[si],cl ; and virtual console number
- if V386
- ; If PCTERM or SunRiver then setup CCBs
- test su_mu_vs$[di],PCTERM_EMU or VTERM_EMU
- ; test setup bit for installed port
- jz no_pcterm1 ; to see if pcterm emulation required
- mov C_ATTR[si],CA_25LINES + CA_ANSI+ CA_ROS + CA_HARDWARE
- push si
- push ax
- mov al,int17_ptr$ ; get count of LPT's
- mul cl ; * VS number
- mov si,offset int17_ptr$
- inc si
- add si,ax ; point to table for VS
- mov ax,di ; current port number
- add al,3 ; main box parallel printer numbers
- mov [si],al ; LPT1 = parallel on terminal
- test su_mu_vs$[di],VTERM_EMU ; test if SR terminal
- jz pcterm1a ; no leave COM settings
-
- mov al,int14_ptr$ ; get count of COM's
- mul cl ; * VS number
- mov si,offset int14_ptr$ ; COM table
- inc si
- add si,ax ; point to table for VS
- mov ax,di ; current port number
- inc al ; next port number
- mov [si],al ; COM1
- inc si ! inc al
- mov [si],al ; COM2
- pcterm1a:
- pop ax
- pop si
-
- no_pcterm1:
- endif
- inc cl ; next VS
- inc ncondev$ ; update # of virtual consoles
- inc nvcons$ ; update SYSDAT
- inc nvcns$ ; update XIOS header
- dec al ; number of virtuals
- jz term_ccb ; no more...
- inc bx ! inc bx ; pointer to next free CCB
- mov bx,ccb_list$[bx] ; offset of next free CCB
- mov C_LINK[si],bx ; and link to current
- mov C_STATE[bx],CSM_BACKGROUND ; set to background
- jmps build_ccb
-
- term_ccb:
- mov C_LINK[si],0000h ; terminate CCB
- alloc_ser_next:
- inc di ; pointer to next serial port
-
- if SR
- cmp di,NUM_AUX_PORTS + NUM_SR_PORTS ; for SUN RIVER system
- else
- cmp di,NUM_AUX_PORTS
- endif
- je alloc_ser_end
- jmp alloc_ser_loop ; do more
- alloc_ser_end:
- ret
-
- if V386
- build_flush:
- push di
- mov bx,offset flushstr
- call make_rsp ; create flush process for this console
- pop di
- ret
- endif
-
- if 0 ;#IJ
- build_pin:
- push di
- mov bx,offset pinstr
- call make_rsp ; use common V5.x code
- pop di
- ret
- endif
-
- make_rsp:
- ;--------
- ; entry: BX = offset of RSP name string
- ; DL = physical console number
- ; CL = virtual console number
- ; note: This code only works for up to 10 copies
- ; of an RSP (as it uses single digit #'s).
-
- push es
- push cx ; save virtual
- push dx ; and physical
- add dl,'0' ; convert to ASCII digit
- mov si,bx ; find copy number in RSP name
- make_rsp1:
- lodsb ; get character from RSP name
- cmp al,'0' ; is it a digit?
- jb make_rsp1 ; get next one if not
- cmp al,'9' ; is it a digit?
- ja make_rsp1 ; get next one if not
- dec si ; SI -> digit in name
- mov [si],dl ; update the name with copy #
- call find_rsp ; does the RSP exist already?
- jnc make_rsp9 ; don't create if already exists
-
- mov byte ptr [si],'0' ; look for 1st copy of RSP in system
- call find_rsp ; locate "<rsp>0"
- jnc found_rsp ; if no RSP 0 then try RSP 1
-
- mov byte ptr [si],'1' ; look for 1st copy of RSP in system
- call find_rsp ; locate "<rsp>1"
- jc make_rsp9 ; if no RSP 1 then exit
-
- found_rsp:
- ; Concurrent 6.0 GENSYS stores the group sizes
- ; in the RSP header. Much more convenient...
-
- push es
- mov es,ax ; AX = base of 1st RSP
- mov dx,RSPH_DGSIZE ; DX = size of RSP data segment
- pop es
- sub si,bx ; SI = offset of number in name
- push si ; save ASCII digit index
-
- push dx ! push ax ; save size & base of RSP
- call mem_alloc_i@ ; allocate one RSP (DX paragraphs)
- mov es,ax ; ES -> space for new RSP image
- pop dx ! pop cx ; restore base & size of RSP
-
- push ds ; save our data segment
- mov ds,dx ; DS = existing RSP
- shl cx,1 ; copy 8 words per paragraphs
- shl cx,1
- shl cx,1
- sub si,si ; copy from beginning of segment
- sub di,di ; to beginning of segment
- rep movsw ; make an identical copy of the RSP
- pop ds
-
- pop si ; restore ASCII digit address
- pop ax ; AX = physical console number
- pop cx ; and virtual console number
- push cx
- push ax ; and resave
- mov RSPH_NCP,al ; set NCP field to physical console #
- mov RSPH_PCNS,cl ; put VC number in RSP
- add al,'0' ; ASCII console #
- mov RSPH_PDNAM[si],al ; set physical console # in PD name
- mov ax,es ; get RSP data segment
- mov RSPH_INITDS,ax ; set initial DS in UDA
- mov RSPH_INITES,ax ; set initial ES in UDA
- mov RSPH_INITSS,ax ; set initial SS in UDA
- mov ax,rspseg$
- mov RSPH_LINK,ax ; link RSP into linked list
- mov rspseg$,es
- make_rsp9:
- pop dx ! pop cx ; retore physical and virtual consoles
- pop es
- ret
-
- find_rsp: ; BX = modified name
- ;--------
- ; entry: BX -> 8 byte RSP name to locate
- ; exit: AX = data segment of RSP, CY = 0
- ; or CY = 1, RSP not found
- ; note: BX,SI preserved
-
- mov cx,rspseg$ ; search through RSP list
- call find_rsp2 ; try to locate RSP in phase 2
- jc find_rsp1 ; skip if not in phase 2 list
- ret ; else return with AX = RSP seg
- find_rsp1:
- mov cx,phase1_root$ ; search trough phase 1 RSPs
- ; call find_rsp2 ; try to locate RSP in phase 1
- ; ret ; return with AX = RSP or CY on
-
- find_rsp2: ; locate RSP name BX in list CX
- jcxz find_rsp4 ; RSP not found
- mov es,cx ; ES = next RSP to check
- push si
- mov si,bx ; DS:SI = name
- mov di,offset RSPH_PDNAM ; ES:DI -> RSP name
- mov cx,4 ; check if 8 byte match
- repe cmpsw ; is this the name we want?
- pop si
- je find_rsp3 ; yes, found the RSP
- mov cx,RSPH_LINK ; else get the next one
- jmps find_rsp2 ; and try again
- find_rsp3:
- mov ax,es ; return RSP segment in ES & AX
- clc
- ret
- find_rsp4: ; RSP not found
- stc
- ret
-
- eject
-
- alloc_virt_screens:
- ;------------------
- test video$,EGA+VGA+MCGA ; do we have MCGA/EGA or VGA?
- jz init_v0 ; skip if no EGA/VGA
- ; We want a buffer to save the
- ; 2nd bit plane on screen
- ; switches...allocate:
- mov dx,PLANE2_LENGTH/16 ; get size required - 8k
- if SR
- mov cx,(PAGE_SIZE)/16 -1 ; align on 4k boundary
- call io_mem_alloc@ ; to allow SR pc's to be mapped
- mov cx,ax
- shr cx,6 ; (/100h*4) - page table entry
- mov ptbl_bit_plane$,cx ; save in SRTERM.A86
-
- else
- call mem_alloc_i@
- endif
- mov bit_plane_seg$,ax ; save segment for IO_SWITCH
- init_v0:
-
- ; Set up the virtual screen structures (one per virtual console)
- ; and blank out their screen save areas.
- ; We now call the low-mem allocator at INIT time rather than letting
- ; GENCCPM put the buffers at the end of the system image.
-
- xor bx,bx ; 1st VC
- mov cx,NUM_VIR_CONS
- if SR
- xor di,di
- endif
- init_v1:
- push cx ! push bx
- if V386
- push di
- mov dx,1024*4/16 ; allocate 4k VC buffer
- mov cx,(1 shl 12)/16 -1 ;(PAGE_SIZE)/16 -1
- ; align on 4k boundary for mapping
- call io_mem_alloc@
- pop di
- if SR
- mov cx,ax
- shr cx,6 ; (/100h*4) - page table entry
- mov ptbl_vc_save$[di],cx ; save in SRTERM.A86
- mov vc_seg_save$[di],ax ; save for SRTERM.A86
- add di,2
- endif
- else
- mov dx,((CRT_ROWS_P*CRT_COLS+15) shr 4) * 2 ; segment size
- call mem_alloc_i@
- endif
- pop bx ! push bx
- mov bx,table_vs$[bx] ; get VS_
- mov VS_VC_SEG,ax ; tell each vs_ where to find
- pop bx ! pop cx ; its buffer segment
- add bx,2 ; next VC_
- cmp cx,NUM_VIR_CONS
- jne init_v2 ; skip if not first VC
- mov genccpm_buf$,ax ; in case someone wants it
- init_v2:
- loop init_v1
-
-
- mov dx,((CRT_ROWS_P*CRT_COLS+15) shr 4) * 1 ; for vc_map_seg
- call mem_alloc_i@
- mov vc_map_seg$,ax ; ownership map segment
-
- mov es,ax ; now set up the initial map
- sub di,di ; top left corner
- mov cx,CRT_ROWS_P*CRT_COLS
- mov al,(1 shl NUM_VIR_CONS)-1 ; all bits on
- cld
- rep stosb ; fill the map
-
- xor bx,bx ; 1st VC
- mov cx,NUM_VIR_CONS
- mov ah,iattrib$ ; get default atribute
- mov dx,save_equip$ ; get PC equipment flag
- init_v3:
- push bx ! push cx
- mov bx,table_vs$[bx] ; get VS_
- mov VS_ATTRIB,ah ; Save the default attribute
- mov VS_PC_EQUIP,dx ; save power up equipment word
- mov es,VS_VC_SEG ; point to image
- sub di,di
- mov cx,CRT_ROWS_P*CRT_COLS
- mov al,' ' ; default attribute + space
- rep stosw ; fill with blanks
- pop cx ! pop bx
- add bx,2 ; next virtual console
- loop init_v3
-
- push ds ! pop es ; local extra segment
- mov di,offset vc_priority$ ; vc priority list
- mov al,NUM_VIR_CONS-1
- init_v4:
- stosb ; lowest priority first
- dec al
- jns init_v4 ; do through zero
- jmp new_monitor@ ; set up initial windows
- eject
- do_setup:
- ;--------
- ; Do the SETUP customizing of the XIOS:
- cmp su_check$,0DDB2h ; check for secret code
- jmpnz setup_done ; if bad, bag it
-
- ; At this point, the SETUP block is a winner.
- mov ax,su_timer_count$
- mov timer_count$,ax ; for a dif. clock
- mov al,su_verf$
- mov verify_flag$,al ; whether to verf after write
- mov ax,su_mmp$ ; max mem per process
- mov mmp$,ax ; tell the system
- mov al,su_scroll$
- mov scroll_mode$,al ; for the color monitor
- mov ax,su_ser_con$
- mov word ptr term_data,ax ; for COM1/COM2 consoles
-
- ; Serial com setup is done in do_aux_ports.
-
- ; Adjust the floppy parameter string from the setup info.
-
- test su_fdc_check$,0ffh ; did the user change it?
- jz fdc_done ; no...don't use them
- mov dl,su_fdc_spec1$ ; head step code
- mov dh,su_fdc_spec2$
- mov cl,su_fdc_settle$ ; head settle
- mov ch,su_fdc_spinup$
-
- push es
- sub ax,ax
- mov es,ax
- les si,es:dword ptr.INT_1E_VEC_OFF
- mov es:[si],dx ; store specify bytes
- mov es:9[si],cx ; and timing bytes
- pop es
-
- call flop_specify@ ; set head step speed
-
- fdc_done:
- cmp su_cf$,0 ; check the config flag
- jz setup_pfks ; if not saved, skip
-
- mov ax,su_config$
- mov config_data,ax ; save both codes
-
- ; Move the SETUP protocol bytes to the aux blocks:
- push ds ! pop es ; local move
- mov cx,4 ; bytes to move
- mov bx,0
- mov si,offset su_prot$
- setup_prot:
- mov di,aux_prot_blk$[bx] ; get block prot pointer
- movsb ; put the byte
- dec di
- ;; test byte ptr [di],XON_XOFF ; software protocol ?
- ;; jz setup_prot1
- mov word ptr (AUX_ON - AUX_PROT)[di], XON + 256*XOFF
- push di ; if not a PCTERM then we
- mov di,bx ; leave XON/XOFF, else
- shr di,1 ; we want XPC protocols
- and di,1
- test mu_com_type$[di],1 ; is it a terminal ?
- jz setup_port2
- test su_mu_vs$[di],PCTERM_EMU ; is it a PC terminal ?
- setup_port2:
- pop di
- jz setup_prot1 ; then we use XPC protocols
- mov word ptr (AUX_ON - AUX_PROT)[di], XPCON + 256*XPCOFF
- setup_prot1:
- inc bx ! inc bx ; next pointer
- loop setup_prot ; next block
-
- setup_pfks:
- cmp su_pf$,0 ; check the pfk flag
- jz setup_done ; if not saved, finished
-
- push ds ! pop es ; local es
- mov di,offset pfk_tbl0$ ; first pfk
- mov bx,NUM_VIR_CONS ; number of pfk tables
- setup_pfk_loop:
- mov si,offset su_pfk_tbl$ ; the saved values
- mov cx,180 ; words per pfk table
- rep movsw ; copy 'em
- dec bx
- jnz setup_pfk_loop ; for each console
- setup_done:
- ret
- eject
-
- flop_off:
- ;--------
- ; Turn off the floppy motors before taking over interrupts:
-
- mov dx,FDC_PORT
- mov al,FDC_ON ; turn off floppy motors
- mov motor_flags$,al ; or they may stay on forever
- out dx,al
- ret
-
-
- eject
-
- floppy_hash:
- ;-----------
- ; Allocate hash tables/FAT buffers/DDSC structures for the real floppies:
-
- mov cx,num_flop$ ; how many are there
- jcxz flop_hash_done ; skip if nobody
-
- mov bx,offset dph_tbl$ ; floppies are first here
- flop_hash_loop:
- push bx ! push cx ; preserve loop variables
- mov si,[bx] ; point to the dph
- ; sectors_per_track * nheads * ntracks
- ; / sectors_per_clusters
- ; / (sectors_size/2)
- ; / (words_per_paragraph)
- ; + 3 extra paragraphs
- mov dx,(18*2*80/1/256/8)+3 ; big enough for 1.44 Mb drives
- push si
- call mem_alloc_i@ ; allocate block for hash table (CP/M)
- pop si ; or FAT image (DOS) or DDSC (6.0)
- mov DPH_HSTBL[si],ax
- mov dx,(9*2+224/4+15)/16 ; max = 9 FAT sects, 224 dir entries
- push si
- call mem_alloc_i@ ; allocate check sum vector
- pop si
- mov DPH_CSV[si],ax ; CSVs are segment based in 6.0
- pop cx ! pop bx ; restore loop variables
- inc bx ! inc bx ; point to next dph
- loop flop_hash_loop ; and do another
- flop_hash_done:
- ret
-
-
- pc_hash_alloc:
- ;-------------
- ; Subroutine to allocate a hash table for a pc hard disk partition
- ; Entry: es:si -> dph
-
- mov di,es:DPH_DPB[si] ; point to dpb
- mov ax,es:PCDPB_NCLSTRS[di] ; get number of clusters
- mov cl,es:PCDPB_PSH[di] ; get sector shift
- add cl,6+3 ; log2(words/sect) + log2(word/para)
- shr ax,cl ; AX = # of words
- add ax,3 ; round up + DDSC
- ; jmps hash_alloc ; fall through
-
- hash_alloc:
- ; Subroutine to allocate one hash table at top of available memory:
- ; That's what the 4 commented instructions would do. Now we (eventually)
- ; call the allocator to put them low. More buggy programs destroy high memory
- ; than low. (Thx GP) Here we just store the addresses and sizes to be
- ; actually allocated at the END of INIT, when all allocations which require
- ; SYSDAT space have hopefully been done.
-
- ; entry: es:si -> dph
- ; ax = hash table size in paragraphs
-
- push bx
- mov bx,offset alloc_table - 6 ; 1st find space in the table
- lph:
- add bx,6
- test word ptr [bx],0ffffh ; anyone there?
- jnz lph
-
- mov 4[bx],ax ; store size required
- lea ax,DPH_HSTBL[si] ; where will it go
- mov 2[bx],es ; segment
- mov [bx],ax ; and offset
- pop bx
- ret
-
-
-
- eject
-
- ; The following function locates a 512 byte block in SYSDAT which
- ; can be used as a temporary buffer for logging in hard disks. Any
- ; such buffer must not cross a 64K boundary in case the ROM BIOS
- ; doesn't support disk transfers across 64K banks (e.g. IBM XT).
-
- ; After the XIOS initialization is done, local_buffer$ will be
- ; pointing at reused space inside the INIT module. Therefore,
- ; local_buffer$ has to point to a temporary buffer at INIT time for
- ; any code that might reference local_buffer$, such as the hard
- ; disk login code.
-
- find_dskbuf:
- ;-----------
-
- mov bx,62*1024 ; use high end of SYSDAT segment
- ; we normally only use the 1st half
- mov ax,ds
- mov cl,4
- shl ax,cl ; AX = offset of SYSDAT in 64 K bank
- add ax,bx ; AX = offset of buffer in 64 K bank
- cmp ax,(-512) ; will one physical sector fit?
- jb find_buf1 ; no, try next buffer
- neg ax ; AX = # of bytes til 64K boundary
- add bx,ax ; move BX up to 64K boundary
- find_buf1:
- mov local_buffer$,bx ; set pointer to local buffer
- ret
-
-
- alloc_dskbuf:
- ;------------
- if V386
- mov dx,local_bsize ; 1 Kb/2 Kb deblocking buffer
- shl dx,1 ; make it twice as large
- add dx,16 ; and a bit more
- ; as we might move SYSDAT on 386
- ; and we could then have to move
- ; LOCAL_BUFFER$ to avoid DMA trouble
- call sysdat_mem_alloc ; allocate in SYSDAT
- mov local_buffer$,ax ; save for FLOPPY/HDISK code
- endif
- if XM
- mov dx,local_bsize ; 1 Kb local deblocking buffer
- call sysdat_mem_alloc ; allocate in SYSDAT
- mov local_buffer$,ax ; save for FLOPPY/HDISK code
- mov dx,ds
- mov cl,4
- shl dx,cl ; DX = offset of SYSDAT in 64K bank
- add ax,dx ; AX = offset of buffer in 64K bank
- add ax,local_bsize ; check for DMA boundary problem
- jc alloc_dskbuf ; if any problem, redo it
- endif
- ret
-
-
- if V386
- align_dskbuf:
- ;------------
- mov ax,ds
- mov cl,4
- shl ax,cl ; AX = A0..A15 of DS base address
- add ax,local_buffer$ ; AX = A0..A15 of local_buffer base
- or ax,0C000h ; make any 16K boundary look like 64K
- not ax ; AX = # of bytes left in 16K page
- cmp ax,local_bsize ; enough space in page for DMA?
- jae align_dskbuf1 ; yes, use current buffer offset
- inc ax
- and ax,-2 ; else round up to next even number
- add local_buffer$,ax ; move buffer past the DMA boundary
- align_dskbuf1:
- mov ax,ds ; get XIOS data segment
- push ds
- sub cx,cx
- mov ds,cx ; DS -> 8086 interrupt vectors
- mov .INT_1E_VEC_SEG,ax ; relocate ROS floppy paramters
- pop ds ; in case we've been moved
- ret
- endif
-
-
- hd_init:
- ;-------
-
- ; Cold start setup for XT hard disk driver;
- ; needs to do these things:
- ; 0) setup int 15 vector if AT (int POST and WAIT)
- ; .5) setup hd hard interrupt if XT
- ; 1) setup floppy interrupt trap
- ; 2) save disk interrupt vector for far call usage
- ; 2.5) or insert our own XT driver
- ; 3) initialize HDINF vectors about physical drive char.
- ; 4) try to login both hard disks
- ; 5) decide who will be system disk and temp disk
- ;
- ; ALSO builds hard disk DPH's and DPB's dynamically
- ; and disk table setup moved from fix_disk_tables routine.
- ;
- ; This code assumes that it is running in XIOS codeseg and that
- ; the floppy initialization has already been done.
-
- push ds
- push es
- xor ax,ax
- mov es,ax ;point to vector seg
-
- ;hd_patch_step_rate: ;step option bits off
- ; and es:byte ptr .HD_CONTROL_BYTE,0F8h or (not SLOW_SEEK)
- ; Why the and w/ FF instruction above?
-
- les ax,es:.HD_PTR ;get hard disk sw int ptr
- mov hd_rom_seg$,es
- mov hd_rom_ofs$,ax ;to local link address
-
- mov disk_int_off$,ax ;save for dskmaint too
- mov disk_int_seg$,es
-
- ; See if we have any hard disks at all:
-
- mov cx,num_hard$
- or cx,cx
- jnz fix_hd
- jmp hd_init_done
-
- fix_hd:
- mov al,0 ; first hard disk
- mov di,pc_hd_dph_start ; pointer to DPH next entry
- fix_disk_loop:
- mov drive_num,al ; store current drive number
- push cx ; save number of disks
- push di ; and DPH pointer
-
- mov dl,al
- or dl,80h ;ask about 1st drive
- mov ah,8
- push ax
- ; pushf ! callf hd_rom_entry$ ;if a drive is present
- int DISK_INT
- pop ax
- jnc hd_init_pc0 ; then try to log pc part
- pop di
- jmp fix_disk1 ; else try next drive
-
- ; Now try to log in first pc dos partition:
-
- hd_init_pc0:
- mov dl,HDINF_SIZE
- xor ah,ah
- mul dl
- lea si,hd_disk_info$ ; if drive is there then
- add si,ax
- call hd_init_hdinf ; set its info vector
-
- call read_sector0 ; read master partition table
- pop di
- or al,al ; physical disk error ?
- jnz fix_disk1 ; yes, skip the drive
- mov bx,local_buffer$
- cmp XTLBL_ID[bx],IBM_SYS_ID ; does it have IBM label?
- jnz fix_disk1
- lea bx,XTLBL_PART1[bx] ; setup to scan for DOS partition
- mov cx,4 ; four partitions possible
- do_all_parts:
- mov al,XT_PT_SYSTEM[bx] ; fetch SYS ID
- cmp al,HD_DOS_ID1 ; type 1
- je pc_hd_dos_found
- cmp al,HD_DOS_ID4 ; type 4
- je pc_hd_dos_found
- cmp al,HD_DOS_ID6 ; type 6
- je pc_hd_dos_found
- jmps next_pc_part ; go search next partition
- pc_hd_dos_found: ; found a DOS partition
- mov hd_dos_sys_id,al ; save for extflag
- mov al,XT_PT_BOOTFL[bx] ; get boot flag
- cmp al,80h ; is it a bootable partition
- jne setup_pt ; no
- cmp drive_num,0 ; Check that only partitions
- jne setup_pt ; on drive zero are made the
- mov ax,di ; boot drive.
- shr al,1 ; DI = word pointer to current drive
- mov hd_boot_flag$,al ; save boot drive so
- ; init can pick up sysdisk
- setup_pt:
- push cx
- call fix_pc_hd ; set dph, dpb and vectors
- push bx ! push di
- call read_sector0 ; re-read sector 0 into local_b
- pop di ! pop bx
- pop cx ; restore partition count
- or al,al ; physical disk error ?
- jnz fix_disk1 ; yes, done with drive
- ; login drive DPB and alloc hash
- next_pc_part:
- add bx,XT_PT_REC_SIZE ; point to next partition entry
- loop do_all_parts ; repeat for all partitions
-
- call do_ext_part ; handle extended partitions
- fix_disk1:
- pop cx ; restore drive count
- mov al,1 ; second drive number
- dec cx
- jz fix_done
- jmp fix_disk_loop ; setup second Hard disk
-
- ;*****
- fix_done:
- mov al,hd_boot_flag$ ; save the boot drive in case we
- mov pc_pt_bootable,al ; want to override cp/m sysdisk
- mov dsrchdisk$,al ; SYS and TEMP disks now
- mov temp_disk$,al ; point to boot dos partition
-
- mov hd_dph_start,di ; pointer to DPH next entry
-
-
- hd_init_done:
- mov hd_init_flag$,0ffh ; set XIOS initialized flag
- pop es ; (which enables error handler)
- pop ds
-
- test boot_drive,80h ; if we booted from hard disk
- jnz hd_init_vect ; then skip sys_disk poke
- mov al,boot_drive
- mov dsrchdisk$,al ; system disk = entry drive
-
- hd_init_vect:
- push es
- sub ax,ax
- mov es,ax
-
- if XM ; -not on CDOS 386-
- test pc_at$,01h ; if XT, not AT, stick in
- jnz at_int15 ; our own hd hw interrupt
- cmp su_hard_driver$,0 ; but only if our SETUP
- je at_int15 ; option tells us so
-
- ; mov es:word ptr .HD_HARD_INTERRUPT*4, offset hd_isr@ ; handler
- ; mov es:word ptr .HD_HARD_INTERRUPT*4 +2,cs
- TARGET equ HD_HARD_INTERRUPT * 4
- TARGET1 equ TARGET + 2 ; thanks RASM
-
- mov es:word ptr .TARGET,offset hd_isr@
- mov es:.TARGET1,cs
-
- mov al,es:control_byte_40 + 400h ; and get the step bits
- mov hd_cmd_blk$ + 5,al ; into our command string
-
- mov hd_rom_seg$,cs ; we now have our own driver
- mov hd_rom_ofs$,offset xt_driver@
- ; jmps hd_init_quit
- endif ; endif XM
-
- at_int15:
- ; Here we must save and set the int 15h vector. This int is used on
- ; the AT for the hard disk device-post/wait idea.
- ; Removed: 17 SEP 85
- ; Reenabled: 12 JUN 87
-
- TARGET2 equ 15h*4
- TARGET3 equ TARGET2 + 2
- mov ax,es:.TARGET2 ; save int 15 address
- mov word ptr old_int15$,ax
- mov ax,es:.TARGET3
- mov word ptr old_int15$ +2,ax
-
- mov es:word ptr .TARGET2,offset int15_isr@
- mov es:.TARGET3,cs
-
- hd_init_quit:
- pop es
- ret
-
-
-
- ; Handle extended partitioning scheme in DOS 3.3:
- ; Entry: local_buffer$ contains master partition table
-
- do_ext_part:
- ;-----------
- ; now check for 3.3 extended partitions
- ; local_buffer$ contains either
- ; the master partition table (1st time)
- ; or an extended partition table
- mov bx,local_buffer$ ; get local deblocking buffer
- lea bx,XTLBL_PART1[bx] ; setup to scan through table
- mov cx,4 ; scan up to four entries
- extscn_lp1:
- mov al,XT_PT_SYSTEM[bx] ; fetch SYS ID
- cmp al,5 ; 3.3 extended partition?
- jne extscn_nxt2 ; no, go & check next one
- mov cl,XT_PT_START_SECTOR[bx]
- mov ch,XT_PT_START_CYLINDER[bx]
- mov dh,XT_PT_START_HEAD[bx] ; starting head (<> 0)
- push cx ! push dx ; save this for re-reading sector
- ; after logging in DOS partition
- push bx ! push di
- call read_sector ; read 1st sector of extended partition
- pop di ! pop bx
- ; now scan for DOS partition in there:
- mov bx,local_buffer$ ; get local deblocking buffer
- lea bx,XTLBL_PART1[bx] ; setup to scan through table
- mov cx,4 ; scan up to four entries
- extscn_lp2:
- mov al,XT_PT_SYSTEM[bx] ; fetch SYS ID
- cmp al,HD_DOS_ID1 ; type 1 (12 bit FAT)
- je extscn_dos ; yes, log in the partition
- cmp al,HD_DOS_ID4 ; type 4 (16 bit FAT)
- je extscn_dos ; yes, log in the partition
- cmp al,HD_DOS_ID6 ; type 6 (16 bit FAT)
- jne extscn_nxt1 ; no, try next table entry
- extscn_dos: ; DOS partition in extended partition
- mov hd_dos_sys_id,al ; save for extflag
- call fix_pc_hd ; set dph, dpb and vectors
- pop dx ! pop cx ; restore extended system
- push di
- call read_sector ; read extended partition table
- pop di ; might have another type 5 in there...
- jmps do_ext_part ; so go and scan it again
-
- extscn_nxt1: ; entry in ext.part. is not DOS
- add bx,XT_PT_REC_SIZE ; next partition
- loop extscn_lp2 ; until all partitions done
- pop dx ! pop cx ; discard address of ext. part.
- jmps do_ext_part ; so go and scan it again
-
- extscn_nxt2:
- add bx,XT_PT_REC_SIZE ; next partition
- loop extscn_lp1 ; until all partitions done
-
- ret
-
-
- ; Setup table entries for 1 Hard disk DOS partition
- ; build the DPH, DPB and allocate FAT space.
- ; Entry: BX -> partition table entry for DOS partition
- ; DI = logical drive*2 (e.g. 2=C:, 3=D:, etc.)
-
- fix_pc_hd:
- push di ! push bx
- mov dx,PC_HD_DPH_SIZE+PC_HD_DPB_SIZE
- add dph_count,dx ; total amount reserved
- call sysdat_mem_alloc ; reserve space in sysdat for
- pop bx ; DPH + partition info + DPB
- ;; or ax,ax ;; hope it never rains...
- ;; jnz alloc_ok
- ;; jmp go_no_more ; HALT no sysdat space
- ;;alloc_ok:
- mov si,dph_tbl$ ; drive A: DPH - use for copy
- mov di,ax ; DPH offset in ES:
- mov es,dph_seg ; temp DPH segment address
- cld
- mov cx,DPH_SIZE ; size of A: DPH to copy
- rep movsb ; copy A: DPH to share buffers
- mov si,bx ; SI -> part entry in local buffer
- mov cx,XT_PT_REC_SIZE ; size of one entry in partition table
- rep movsb ; save partition entry for later
- pop di ; restore table pointer (drive*2)
- mov si,offset pc_hd_vectors ; select, read, write pc part
- push es ! push bx
- mov es,dph_seg ; get DPH temp Seg
- mov dph_tbl$[di],ax ; set dph in header
- lodsw ; fetch the select vector
- mov select_tbl$[di],ax
- lodsw ; fetch the read vector
- mov read_tbl$[di],ax
- lodsw ; fetch the write vector
- mov write_tbl$[di],ax
-
- ; Now build the DPH
- push di
- mov di,dph_tbl$[di] ; get dph offset
- sub ax,ax
- mov es:DPH_CSV[di],ax ; no checksum vectors - fixed
- mov es:DPH_ALV[di],ax ; no allocation vectors - DOS media
- lea ax,PC_HD_DPH_SIZE[di] ; AX -> DPB address (after part info)
- mov es:DPH_DPB[di],ax ; save DPB offset in DPH
-
- ; Log in the drive DPB
- push di ; save DPH ->
- call pc_hd_login ; Build DPB
- pop si ; restore DPH ->
- or al,al
- jz login_ok
- pop di ; login error so
- mov dph_tbl$[di],0000 ; reset DPH table for drive
- jmps login_exit
-
- ; Login is successful, allocate the hash table (for FAT):
- login_ok:
- mov es,dph_seg ; get DPH temp Seg
- call pc_hash_alloc ; save some hash space es:si->DPH
- pop di
-
- mov bx,di ; current pointer
- mov si,pc_hd_dph_start ; pointer to first HD DPH entry
- sub bx,si ; make zero relative table pointer
- mov dl,HDINF_SIZE
- xor ah,ah
- mov al,drive_num ; current physical drive number
- mul dl
- lea si,hd_disk_info$ ;if drive is there then
- add si,ax ; setup info vector pointer
- mov hdinf_ptr$[bx],si ; for logical drive number
-
- inc di ! inc di ; to next vector entry
- login_exit:
- pop bx ! pop es
- ret
-
-
- pc_hd_login:
- ;-----------
- ; Builds dpb for DOS partition
-
- ; ENTRY: ES:DI -> PC DPH + partition data + DPB
- ; EXIT: AL = 0 if success, else NZ
-
- mov si,di ; save DPH ->
- add di,DPH_SIZE ; point to start of saved partition info
- mov bx,offset pc_part_table_iopb ; make boot record IOPB
- mov cl,es:XT_PT_START_SECTOR[di]
- mov ch,es:XT_PT_START_CYLINDER[di]
- mov dh,es:XT_PT_START_HEAD[di] ; starting head (<> 0)
- push bx ! push di ! push si
- call read_sector ; read boot record
- pop si ! pop di ! pop bx
- or al,al
- jnz pc_hd_login_fail
- mov di,local_buffer$ ; di -> boot record
- cmp word ptr 510[di],IBM_SYS_ID ; check for signature
- jne pc_hd_login_fail ; abort if not found
-
- mov bx,es:DPH_DPB[si] ; point es:bx -> dpb
-
- mov es:PCDPB_EXTFLAG[bx],EXTFLAG1 ; assume 1.5 bytes per
- cmp hd_dos_sys_id,HD_DOS_ID1
- je pc_hd_build ; if its a 2 byte per
- mov es:PCDPB_EXTFLAG[bx],EXTFLAG2 ; entry fat, flag it
-
- pc_hd_build:
- mov al,PC_BR_NFATS[di]
- sub ah,ah ; build the dpb
- mov es:PCDPB_NFAT[bx],ax
-
- mov ax,PC_BR_FATSEC[di]
- mov es:PCDPB_FATREC[bx],ax ; size factor
-
- mov ax,PC_BR_RESERVED[di]
- mov es:PCDPB_FATADD[bx],ax
-
- call pc_hd_cluster_count ; calculate # of clstrs
-
- cmp es:PCDPB_NCLSTRS[bx],0FF6h ; max. size for 12 bit
- jbe pc_hd_is12 ; if its a 2 byte per
- mov es:PCDPB_EXTFLAG[bx],EXTFLAG2 ; entry fat, flag it
- pc_hd_is12:
- mov ax,PC_BR_SECS[di] ; get sectors per track
- mov es:PCDPB_SPT[bx],ax ; from DOS BPB
- mov ax,PC_BR_DIRMAX[di]
- dec ax
- mov es:PCDPB_DIRSIZ[bx],ax
- mov es:PCDPB_CKSIZ[bx],PERM ; fixed disk only
-
- call pc_hd_dpb_fix ; patch up for show
-
- sub ax,ax
- jmps pc_hd_login_exit
- pc_hd_login_fail:
- mov ax,-1
- pc_hd_login_exit:
- ret
-
-
- pc_hd_cluster_count:
- ; Calculate number of clusters:
- ; Enter : ES:BX = DPB ->
- ; calculate # of clstrs
-
- mov ax,32 ; bytes per directory entry
- mul PC_BR_DIRMAX[di]
- div PC_BR_SECSIZ[di]
- test dx,dx ; test if incomplete sector
- jz pc_hd_clu1 ; skip if even sector number
- inc ax ; round up to next full sector
- pc_hd_clu1:
- xchg ax,cx ; CX = sectors in directory
- mov ax,PC_BR_FATSEC[di] ; assume < 256
- mul PC_BR_NFATS[di] ; AX = sectors of fats
- add cx,ax ; CX = sectors in FATs + directories
- add cx,PC_BR_RESERVED[di] ; + boot
-
- xor dx,dx
- mov ax,PC_BR_TOTSEC[di] ; get total
- or ax,ax ; is it valid ?
- jnz calc_clusters
- mov ax,PC_BR_BTOTSEC[di] ; no must be >32meg partition
- mov dx,PC_BR_BTOTSEC+2[di] ; so use big total sectors value
-
- calc_clusters: ; DX:AX = total # of sectors
- sub ax,cx ; minus directory, FATs and boot
- jnc calc_1
- dec dx
- calc_1:
- mov cl,PC_BR_ALLOCSIZ[di] ; sectors per cluster
- xor ch,ch ; shift mask
- get_mask:
- shr cl,1
- jc end_mask
- inc ch ; mask
- jmps get_mask
- end_mask:
- mov cl,ch
- xor ch,ch ; cx = divide loop count
-
- calc_2:
- clc
- rcr dx,1
- rcr ax,1
- loop calc_2
- inc ax ! inc ax ; + 2 (rsvd clusters)
- mov es:PCDPB_NCLSTRS[bx],ax ; set num of clusters
-
-
- mov cl,PC_BR_ALLOCSIZ[di] ; sectors per cluster
- xor ch,ch
- mov ax,PC_BR_SECSIZ[di]
- mul cx
- mov es:PCDPB_CLSIZE[bx],ax ; and clustersize
-
- mov ax,0302h ; assume 512 byte default values
- mov cx,PC_BR_SECSIZ[di] ; get logical sector size
- pc_hd_clu2:
- cmp cx,BYTES_PER_SECTOR ; logical = physical sector size?
- je pc_hd_clu3 ; yes, continue
- add ah,ah ; else ...
- add ax,0101h ; PSH++, PRM = PRM*2+1
- shr cx,1 ; halve the logical size
- jmps pc_hd_clu2 ; until it matches physical size
- pc_hd_clu3:
- mov es:PCDPB_PSH[bx],al ; AL = log2 (sectorsize/128)
- mov es:PCDPB_PRM[bx],ah ; AH = (sectorsize/128) - 1
- cmp al,maxpsh ; check if new maximum
- jbe pc_hd_clu4 ; skip if same or smaller
- mov maxpsh,al ; else save new max. sector size
- pc_hd_clu4:
- ret
- eject
-
- pc_hd_dpb_fix:
- ; Fix up the pc partitions dpb for show dsk:
- ; Enter : ES:BX = -> DPB
- push si ; save for indexing
- mov ax,es:PCDPB_CLSIZE[bx]
- dec ax ; align msb
- mov cx,6 ; to shift out > 1024
- pd_hd_fix_loop:
- shl ax,1 ; march the msb out
- jc pc_hd_fix_it ; skip when out
- loop pd_hd_fix_loop ; fall through if < 1024
- pc_hd_fix_it:
- mov si,cx
- shl si,1 ; block size index
-
- mov cx,pc_blk_size[si] ; get the block size
- mov ax,es:PCDPB_NCLSTRS[bx]
- mul es:PCDPB_CLSIZE[bx]
- div cx ; number of allocation blocks
- dec ax ; calculated dsm
-
- cmp cx,1024 ; if the block size is 1k and
- jne pc_hd_fix_ok ; we've more than 255 blocks,
- cmp ax,255 ; then pretend that we've got
- jbe pc_hd_fix_ok ; 2k blocks
-
- inc si ! inc si ; move our index to 2k
- shr ax,1 ; and correct dsm
- pc_hd_fix_ok:
- mov es:PCDPB_DSM[bx],ax ; fill in DSM value
-
- mov ax,pc_bsh_blm[si] ; fetch both
- mov es:PCDPB_BSH[bx],al ; block shift
- mov es:PCDPB_BLM[bx],ah ; block mask
-
- mov es:PCDPB_EXM[bx],0 ; build remainder of
- mov es:PCDPB_OFF[bx],0 ; DPB paramaters...
- pop si ; restore index
- ret
-
-
-
- ; Read first sector from a hard disk
- ; into local_buffer area
- ; Enter : drive_num = drive number
- ; Exit : AL = return error code
- read_sector0:
- mov cx,1 ; CH: cylinder 0, CL: sector 1
- mov dh,0 ; DH: head 0 of current drive
- ; jmps read_sector ; read one sector via ROM BIOS
-
- ; Read one sector into local buffer
- ; Entry: CH = cylinder
- ; CL = sector (bits 0-5)/hi cyl (bits 6-7)
- ; DH = head
- ; drive_num = 0 or 1 for 1st/2nd hd
- ; Exit: AL = return error code
- read_sector:
- mov bx,offset pc_part_table_iopb
- mov IBM_HEAD[bx],dh ; not equal zero
- mov al,cl
- and al,3fh ; bottom 5 bits are sector #
- mov IBM_SECTOR[bx],al ; set sector number
- mov al,ch ; bits 0-7 of cylinder #
- mov ah,cl ; bits 8-9 of cylinder #
- rol ah,1 ! rol ah,1 ; shift them into place
- and ah,3 ; isolate MSB cylinder #
- mov IBM_CYLINDER[bx],ax ; 16 bit cylinder #
- mov ax,local_buffer$
- mov IBM_XFER_OFS[bx],ax ; read to local buffer
- mov IBM_XFER_SEG[bx],ds
- mov al,drive_num
- mov IBM_LUN[bx],al ; set logical unit #
- jmp hd_rom@
-
- hd_init_hdinf:
- ; Subroutine sets up physical information vector about a drive:
- ; entry: registers as returned from ROM call
-
- mov HDINF_EXISTS[si],0ffh ; it at least exists
- inc dh ; change last hd to # of hds
- mov HDINF_HEADS[si],dh
- mov al,3fh
- and al,cl ; sectors is already # of spt
- mov HDINF_SPT[si],al
- rol cl,1
- rol cl,1
- and cl,3
- xchg ch,cl ; unpack max cyl address
- mov HDINF_CYL[si],cx ; and save it
- mov cl,drive_num
- mov HDINF_PC_DRIVE[si],cl ; save physical drive number
- ret
- eject
-
- trim_memory:
- ;-----------
- ; Trim the memory partion list to match physical memory:
-
- mov cx,memory_top ; top segment address
- lea bx,mfl$ ; memory free list root
- trim_next:
- mov si,bx ; save previous link
- mov bx,MD_LINK[bx] ; link to next
- test bx,bx
- jz trim_done ; 0 => end of list
-
- mov ax,MD_START[bx] ; memory block start seg
- cmp ax,cx ; is start past mem top?
- jae trim_clip ; if yes, end the list
-
- add ax,MD_LENGTH[bx] ; get to the end
- cmp ax,cx ; is end past mem top?
- jbe trim_next ; if not, link to next
-
- mov ax,cx
- sub ax,MD_START[bx] ; ax=usable memory left
- mov MD_LENGTH[bx],ax ; shorten up this block
- jmps trim_next ; and link to next
-
- trim_clip:
- mov MD_LINK[si],0 ; previous is now the last
- mov si,bx ; save start of severed list
-
- trim_scan:
- mov di,bx ; save last link
- mov bx,MD_LINK[bx] ; look for the end of the
- test bx,bx ; severed list
- jnz trim_scan
-
- mov ax,mdul$ ; save md unused root
- mov mdul$,si ; redo the root
- mov MD_LINK[di],ax ; and re-attach original
- trim_done:
- ret
- eject
-
- do_aux_ports:
- ;------------
- ; Set up the auxiliary ports:
-
- call check_multi_port ; try to find multi-port board
-
- sub dx,dx ; start with 1st serial port
- do_aux_lp1:
- mov bx,dx
- mov al,config0_data[bx] ; get config data (if COM1 or COM2)
- call point_aux@ ; get auxiliary port structure
- mov cx,AUX_PORT_ADDR[bx] ; get hardware base port
- test ch,ch ; no card (0000) or generic (00xx)?
- jz do_aux_p2 ; skip if no hardware setup
- push dx ! push ds
- mov bx,PC_SEGMENT
- mov ds,bx ; trick the ROS into using our port #
- xchg cx,rs232_base_40 ; get their #, give them ours
- sub dx,dx ; dx -> port 0
- mov ah,0 ; init code
- int ASYNC_INT ; through the ROS
- mov rs232_base_40,cx ; restore ROS port number
- pop ds ! pop dx
- do_aux_p2:
- inc dx ; next serial port
- cmp dx,NUM_AUX_PORTS ; all possible ports done?
- jne do_aux_lp1 ; loop back for more ports
-
- ; Now we set up for interrupt driven auxin auxout:
-
- cli ; best not be disturbed
- ; First turn both off (thx JC & JW):
- or pic_mask_image$,(not (AUX_PIC0 and AUX_PIC1)) and 0ffh
- sub dx,dx ; dx = 0
- mov cl,AUX_PIC0 ; port 0 pic mask
- do_aux_lp2:
- push dx
- call do_one_port ; if existent, enable ints
- mov cl,AUX_PIC1 ; port 2 pic mask
- pop dx
- inc dx ; next port
- cmp dx,NUM_AUX_PORTS ; try all possible ports
- jne do_aux_lp2 ; repeat if more ports
- ret
-
-
- do_one_port:
- ; Set up interrupts for one aux port:
- ; entry: dx = port number (0..NUM_AUX_PORTS-1)
- ; cl = pic mask
-
- ; Same test that ROS does:
- call point_aux@ ; bx -> aux block
- mov ax,AUX_PORT_ADDR[bx] ; get serial port address
- test ax,ax ; was serial port card found?
- je erase_port ; no, none of the ports there
- test ah,ah ; test if generic card
- jz do_one_gen ; yes, skip hardware setup
- push dx
- mov dx,AUX_PORT_INT_ID
- call aux_port_in@ ; get test int ident
- test al,0F8h ; zf set if present
- pop dx
- jnz erase_port ; hardware is absent
-
- call do_one_alloc ; allocate i/o buffers
- call do_aux_int ; set up port hardware
- do_one_gen:
- mov bx,dx ; bx = port number
- cmp term_data[bx],0FFh ; if serial console..
- jz y_con ; jump
- add_printer:
- mov al,bl
- add al,3 ; start w/ 3 for ser printers
- call conv_digit@
- jmp put_in_s_o ; show it
- ; we're finished
-
- ; According to setup data, dedicate this port to a serial console:
- y_con:
- if V386
- test su_mu_vs$[bx],PCTERM_EMU ; test setup bit for PCTerm
- jz y_con1
- push dx ; it's a PCTerminal
- call add_printer ; so we can have a printer on
- pop dx ; its aux port
- y_con1:
- endif
- call erase_port ; dx=port,wipe out the aux vectors
- jmp set_ser_con ; set up serial console vectors
-
-
- erase_port:
- ; If port is not present, wipe out this port's branch vectors:
- ; entry: dx = port number
-
- mov bx,dx
- shl bx,1 ; bx = port word index
- mov ax,offset aux_null@ ; address of null aux routine
- mov aux_in_vector$[bx],ax ; zap auxin calls
- mov aux_out_vector$[bx],ax ; zap auxout calls
- mov auxin_stat_vector$[bx],ax ; zap input status
- mov auxout_stat_vector$[bx],ax ; zap output status
- mov bx,acb_list$[bx] ; get pointer to ACB
- mov LCB_ATTACH[bx],UNAVAILABLE ; mark for TMP
- ret ; that's it
-
-
- check_multi_port: ; check if multi-port card is installed
- ;----------------
- ; Note: If the base port address configured by SETUP
- ; is 00xxh (0000-00FFh) then the actual I/O routines
- ; will be provided by an external device driver
- ; installed after the XIOS initialization. In this
- ; case, all hardware setup is skipped in the XIOS
- ; and only RSP duplication & other data setup is performed.
- ; Otherwise, the port address is the address of the
- ; first of several 8250 chips on a multi-port card.
-
- mov serdrv_vector$+2,cs ; point default to XIOS handler
-
- mov bx,offset su_mu_data$ ; BX -> SETUP info for card
- ; first initialize the card
- ; in case it needs a reset
- mov dx,MU_RESET[bx] ; does the card need reset?
- test dx,dx ; no reset port otherwise
- jz chk_mp_nores ; skip read/write from/to reset port
- mov ax,MU_RESDAT[bx] ; get reset r/w flag and data
- test ah,ah ; AH = 0 if read, AH = FF if write
- jz chk_mp_in ; skip if read from port req'd
- chk_mp_out: ; else need to write to it
- out dx,al ; write reset value
- jmps chk_mp_nores ; done it
- chk_mp_in: ; else read from port required
- in al,dx ; to initialize board
- chk_mp_nores: ; card reset completed
- ; now check for presence of card
- mov dx,MU_PORT[bx] ; get base address
- test dx,dx ; any card configured?
- jz chk_mp_ret ; skip if not
- test dh,dh ; generic port card (dummy addr 00xx)?
- jz chk_mp_init ; yes, assume ports are there
- mov cx,MU_NPORTS[bx] ; there should be 1-8 8250 UARTs
- add dx,AUX_PORT_INT_ID ; check interrupt ID as for COM1/COM2
- chk_mp_lp1:
- in al,dx ; 00000xxxb if 8250 chip responds
- test al,0F8h ; zf set if present
- jnz chk_mp_ret ; hardware is absent
- add dx,8 ; 8250s must be at every 8 i/o ports
- loop chk_mp_lp1
- jmps chk_mp_init
-
- chk_mp_ret: ; return if card not present
- ret
-
- chk_mp_init:
- cmp num_port$,2 ; can't have COM2 (cos of IRQ3) & AST
- jb chk_mp_com2 ; installed together - too messy for us
- dec num_port$
- chk_mp_com2:
- mov ax,MU_NPORTS[bx] ; get # of ports on card (4 or 8)
- add num_port$,ax ; add in all the ports on our card
-
- mov dx,MU_PORT[bx] ; get base port address
- test dh,dh ; generic multi-port card?
- jz chk_mp_gen ; yes, don't check for latch
- cmp MU_LATCH[bx],0 ; do we have an IRQ latch port
- jnz chk_mp_gen
- jmp chk_mp_nolatch ; skip if not (req'd if NPORTS > 1)
- chk_mp_gen:
- mov cx,MU_NPORTS[bx] ; get # of ports on board (4 or 8)
- mov di,1*WORD ; skip COM1, modify remaining ports
- chk_mp_lp2:
- lea ax,MU_LATCH[bx] ; get IRQ info for multi-port card
- mov si,MU_NPORTS[bx]
- sub si,cx ; SI = relative port index
- push bx
- mov bl,MU_PROT[bx+si] ; BL = protocol for our port
- mov bh,bl
- shr bl,1 ! shr bl,1 ; 4 MSB = input protocol
- shr bl,1 ! shr bl,1
- and bh,0Fh ; 4 LSB = output protocol
- mov si,auxin_blk_ptr$[di]
- mov AUX_PORT_ADDR[si],dx ; fill in port address (input)
- mov AUX_LATCH[si],ax ; fill in IRQ latch data
- mov AUX_PROT[si],bl ; input protocol
- test bl,XON_XOFF ; software protocol ?
- jz chk_mp_lp3
- mov word ptr AUX_ON[si], XON + 256*XOFF
- push di ; if a PCTERM then we
- shr di,1 ; we want XPC protocols
- test mu_com_type$[di],1 ; is it a terminal ?
- jz chk_mp_lp2a
- test su_mu_vs$[di],PCTERM_EMU ; is it a PC terminal ?
- chk_mp_lp2a:
- pop di
- jz chk_mp_lp3 ; to see if pcterm emulation required
- mov word ptr AUX_ON[si], XPCON + 256*XPCOFF
- chk_mp_lp3:
- mov si,auxout_blk_ptr$[di]
- mov AUX_PORT_ADDR[si],dx ; fill in port address (output)
- mov AUX_LATCH[si],ax ; fill in IRQ latch data
- mov AUX_PROT[si],bh ; output protocol
- test bh,XON_XOFF ; software protocol ?
- jz chk_mp_lp4
- mov word ptr AUX_ON[si], XON + 256*XOFF
- push di ; if a PCTERM then we
- shr di,1 ; we want XPC protocols
- test mu_com_type$[di],1 ; is it a terminal ?
- jz chk_mp_lp3a
- test su_mu_vs$[di],PCTERM_EMU ; is it a PC terminal ?
- chk_mp_lp3a:
- pop di
- jz chk_mp_lp4 ; to see if pcterm emulation required
- mov word ptr AUX_ON[si], XPCON + 256*XPCOFF
- chk_mp_lp4:
- pop bx
- inc di ! inc di
- add dx,8 ; next 8250A/B-16450 chip on board
- loop chk_mp_lp2 ; repeat for all comms chips
-
- lea si,MU_CONFIG[bx] ; SI -> baud rate table for our ports
- lea di,config1_data ; DI -> baud rates for initialization
- mov cx,MU_NPORTS[bx] ; number of ports that we support
- push es
- push ds ! pop es
- rep movsb ; copy SETUP info across
- pop es
-
- chk_mp_nolatch:
- mov cx,MU_NPORTS[bx] ; # of serial terminals
- mov si,1 ; skip COM1 port
- mov dl,MU_CONAUX[bx] ; get console/printer bit map
- cmp_mp_lp3: ; is next port console or printer?
- shr dx,1 ; shift next bit in CY flag
- sbb al,al ; AL = FF if CY on, 00 if CY off
- mov term_data[si],al ; update the flag (FF = terminal)
- inc si ; next port
- loop cmp_mp_lp3 ; repeat for all of them
- ret
-
- eject
-
- do_one_alloc: ; allocate I/O buffers for serial port
- ;------------
- ; entry: DX = port number
- ; Setup output buffers:
- call point_aux@ ; BX -> I buf ctl, DI -> O buf ctl
- xchg bx,di ; BX -> output buffer control structure
- ;; mov AUX_PROT[bx],PROT_T_INIT; default protocol unless SETUP
- mov si,dx
- cmp term_data[si],0
- mov ax,AUXOUT_BUF_SIZE/16 ; # of paragraphs for buffer
- jz do_one_alloc1
- mov ax,CONOUT_BUF_SIZE/16 ; # of paragraphs for buffer
- do_one_alloc1:
- call do_one_alloc3 ; allocate buffer, setup ctrl structure
- ; Setup input buffers:
- call point_aux@ ; BX -> I buf ctl, DI -> O buf ctl
- ;; mov AUX_PROT[bx],PROT_R_INIT; default protocol unless SETUP
- mov si,dx
- cmp term_data[si],0
- mov ax,AUXIN_BUF_SIZE/16 ; # of paragraphs for buffer
- jz do_one_alloc2
- mov ax,CONIN_BUF_SIZE/16 ; # of paragraphs for buffer
- do_one_alloc2:
- ; call do_one_alloc3 ; allocate buffer, setup ctrl structure
- ; ret
-
- do_one_alloc3: ; allocate input or output buffer
- ;-------------
- ; entry: AX = # of paragraphs to allocate for buffer
- ; BX -> buffer control structure
- ;
- ; saved: BX,CX,DX
-
- push cx ! push dx ; save CX, DX for caller
- push bx ; preserve control block
- xchg ax,dx ; DX = # of paragraphs wanted
- call mem_alloc_i@ ; allocate memory block
- mov cl,4 ; AX = segment of new buffer
- shl dx,cl ; convert buffer size to bytes
- dec dx ; make it offset of last byte
- pop bx
-
- mov AUX_BUF_BASE[bx],ax ; setup buffer segment
- mov AUX_BUF_TOP[bx],dx ; offset of last byte in buffer
-
- sub ax,ax
- mov AUX_IN_PTR[bx],ax ; reset input & output pointers
- mov AUX_OUT_PTR[bx],ax
- mov AUX_BUF_COUNT[bx],ax ; & buffer count
-
- call alloc_flag@ ; get an unused flag
- mov AUX_FLAG[bx],al ; save this flag for syncronization
-
- pop dx ! pop cx ; restore DX, CX for caller
- ret
-
-
- do_aux_int:
- ; Set up the aux interrupt hardware:
- ; entry: BX -> buffer structure
- ; CL = PIC mask
- ; DX = port number
-
- call point_aux@ ; set BX, DI = input/output structures
-
- push dx
- and pic_mask_image$,cl ; mask in our interrupt
-
- mov dx,AUX_PORT_INT_EN ; here we enable interrupts
- mov al,R_ERR_MASK ; for rcv and errors
- call aux_port_out@
-
- mov dx,AUX_PORT_M_CTRL ; now we set the modem control
- mov al,I_EN + DTR_BIT + RTS_BIT ; register to enable ints
- cmp AUX_PORT_ADDR[bx],AUX_PORT1 ; if COM0 or COM1
- jae set_prot ; enable I_EN bit
- mov al,DTR_BIT + RTS_BIT ; else leave for multi-port cards
- set_prot: ; as it screws some cards up.(AST)
- call aux_port_out@ ; with all protocol on.
-
- mov dx,AUX_PORT_INT_ID ; reading the int ident reg
- call aux_port_in@ ; clears pending xmit ints
- pop dx
- ret
-
- set_ser_con:
- ; Set up the serial console jump vectors:
- ; entry: dx = port number
-
- mov bx,dx ; BX = port index (0..8)
- inc current_pc$ ; first serial is physical console 1
- mov al,current_pc$ ; get next physical console to use
- mov port2pc_table$[bx],al ; save console # for this serial port
- cbw ; make console # a word
- xchg ax,di ; DI = physical console #
- mov pc2port_table$[di],dl ; save port # for this console
- shl bx,1 ; bx = port word index
- mov ser_conin_vec$[bx],offset aux_in@
- mov ser_conout_vec$[bx],offset aux_out@
- mov ser_conout_stat_vec$[bx],offset term_auxout_stat@
- mov di,auxout_blk_ptr$[bx] ; di -> auxout block
- push dx ; save port index
- mov dx,AUX_PORT_ADDR[di] ; get the 8250 port address
- test dh,dh ; generic serial port?
- jz set_ser_serdrv ; yes, skip baud rate setup
- ; else do high baud rate kludge
- add dx,3 ; DX = line control port
- in al,dx ; read line control values
- jmps $+2 ; I/O delay (just in case)
- xchg ax,cx ; save them in CL
- mov al,80h
- out dx,al ; DLAB = 1 to set baud rate
- jmps $+2 ; I/O delay (just in case)
- sub dx,2 ; DX = divisor latch high (DLM)
- in al,dx ; read back DLM
- jmps $+2 ; I/O delay (just in case)
- mov ah,al ; save in AH
- dec dx ; DX = didvisor latch low (DLL)
- in al,dx ; AX = baud rate divisor value
- jmps $+2 ; I/O delay (just in case)
- ; 110bd=1047 150bd=768 300bd=384
- cmp ax,500 ; very low baud rate (110, 150)?
- jb set_ser_con_new ; don't modify if > 150 baud
- cmp ax,800 ; < 800 => 150 baud => 19.2 KBd
- mov ax,6 ; 1.8432 Mhz/(16 * 6) = 19.2 KBd
- jae set_ser_con_new ; skip if 19.2 requested
- mov ax,3 ; 1.8432 Mhz/(16 * 3) = 38.4 KBd
- set_ser_con_new:
- out dx,al ; LSB of divisor for baud rate
- jmps $+2 ; I/O delay (just in case)
- inc dx ; DX = divisor latch high
- mov al,ah ; divisor value high
- out dx,al
- jmps $+2 ; I/O delay (just in case)
- add dx,2 ; DX = line control port
- xchg ax,cx ; AL = orig. line control value
- out dx,al ; DLAB in line control port = 0
-
- set_ser_serdrv: ; baud rate fixed up
- pop dx ; restore port index
-
- cmp dl,9 ; above range of AUX devices?
- jae skip_acb_init ; yes, don't touch ACBs then
- mov di,dx
- test su_mu_vs$[di],PCTERM_EMU ; look at setup byte for serial port
- jz skip_acb_init ; if not PCTERM leave as UNAVAILABLE
- shl di,1
- push di
- mov di,acb_list$[di] ; get pointer to ACB
- mov LCB_ATTACH[di],0 ; it's available after all
- pop di ; now point acb at a dummy
- mov acb_list$[di], offset dummy_cb$
- skip_acb_init:
- ret ; that's it
-
- eject
-
- do_ros_ints:
- ;-----------
- ; Store several of the initial ROS entry points to allow the XIOS to
- ; use the ROS drivers:
- mov ax,ds
- mov es,ax ; point ES here
- push ds
- sub ax,ax
- mov ds,ax ; point DS at int. vectors
-
- push es
- push cs ! pop es ; vector_table$ in CS
- mov di,offset vector_table$ ; table of ints to save
- mov cx,NUM_VECTORS ; loop count
- cld
- ros_lp:
- mov si,es:[di] ; get vector address
- inc di ! inc di ; point to save area
- movsw ! movsw ; move segment and offset
- loop ros_lp ; do them all
- pop es
-
- ; The required vectors have now been stored.
-
- ; One more special case:
- TARGETT equ KEYBOARD_INTERRUPT * 4
- mov ax,.TARGETT ; offset
- mov word ptr keyboard_isr$,ax
- mov ax,.TARGETT+2
- mov word ptr keyboard_isr$+2,ax
-
- ; Now, although redundant, save another set for LOADCCPM:
- sub si,si
- mov di,offset ros_vectors$
- mov cl,es:[di] ; get count
- inc di
- sub ch,ch
- shl cx,1 ; 2 words per vector
- rep movsw ; and move into place
-
- pop DS ; point it back here
- ret
-
-
- alloc_non_sysdat:
- ;----------------
- ; Routine to trim memory from low TPA and give it to whoever requested:
- ; alloc_table dw ptr_addr_offset, ptr_addr_segment, paras_req'd
- ; ... ...
- ; where ptr_addr is a word containing the offset in SYSDAT which must
- ; receive the segment address of the allocated space.
-
- push es
- mov bx,offset alloc_table
- alp:
- mov dx,4[bx] ; get amount requested
- or dx,dx ; end of table?
- jz aret ; jump if so
- push bx
- call mem_alloc_i@ ; else get the mem.
- pop bx
- les di,[bx] ; get segment & offset
- stosw ; put returned seg address
- add bx,6 ; in place
- jmps alp
- aret:
- pop es
-
- ret
-
- reloc_ext_BIOS: ; relocate PS/2 extended BIOS data
- ;--------------
- push ds
- mov cx,PC_SEGMENT
- mov ds,cx
- mov cx,extended_BIOS_40 ; get extended BIOS data segment
- jcxz reloc_ret ; skip if none (non-PS/2 ROS)
- mov ds,cx ; DS:0 -> extended BIOS data
- sub dx,dx
- mov dl,.0 ; size of data in 1 K blocks
- mov cl,6
- shl dx,cl ; DX = # of paragraphs in extended data
- push ds
- mov ds,sysdat$ ; restore data segment
- call mem_alloc_i@ ; allocate segment address
- mov es,ax ; ES = alternate BIOS segment
- pop ds ; DS = current extended data
- mov cl,3
- shl dx,cl ; size of data segment in words
- mov cx,dx ; CX = # of words to move
- sub si,si
- sub di,di
- rep movsw ; relocate BIOS segment to low memory
- mov ax,PC_SEGMENT
- mov ds,ax ; DS = ROM BIOS data segment
- mov extended_BIOS_40,es ; set new BIOS data segment address
-
- reloc_ret:
- pop ds ; restore data segment
- ret
-
- reloc_disk_params: ; relocate hard disk parameter tables
- ;----------------- ; if in TPA space
- push ds
- cmp word ptr reloc_disk$,00 ; do we have to move tables
- je reloc_ret1
- xor ax,ax
- mov es,ax
- mov si,HD_PARAM_INTERRUPT*4
- mov ax,es:2[si] ; get pointer segment
- push ax ; ax = tables segment
- mov dx,reloc_disk$ ; dx = number of paras to move
- if XM
- mov cx,4
- shl dx,cl ; size in bytes
- call sysdat_ext_alloc ; allocate para aligned buffer in sysdat
- mov cl,4 ; ax= offset of buffer
- shr ax,cl
- mov cx,ds
- add ax,cx
- endif
- if V386
- call mem_alloc_i@ ; allocate segment address- non sysdat
- endif
- mov es,ax ; ES = alternate segment
- pop ds ; DS = current tables segment
- mov cl,3
- shl dx,cl ; size of data segment in words
- mov cx,dx ; CX = # of words to move
- sub si,si
- sub di,di
- rep movsw ; relocate segment to low/hi memory
- xor ax,ax
- mov ds,ax
- mov si,HD_PARAM_INTERRUPT*4
- mov ax,2[si] ; get original
- mov 2[si],es ; set new pointer segment
- mov si,HD_PARAM_INTERRUPT1*4 ; second hard disk pointer
- cmp 2[si],ax
- jne reloc_ret0 ; also moved ?
- mov 2[si],es ; set new pointer segment
- reloc_ret0:
- mov cx,PC_SEGMENT
- mov ds,cx
- ;; cmp [si],ax
- ;; jne reloc_ret1
- mov hd_param_40,es ; used so update
- reloc_ret1:
- pop ds ; restore data segment
- ret
-
-
- sysdat_ext_alloc:
- ;----------------
- ; Routine to trim the low end of the TPA to return the offset of a SYSDAT-
- ; inclusive buffer to the caller.
- ;
- ; Entry: DX = # bytes wanted
- ; Exit: AX = offset of area freed for caller;
- ; = 0 if some SYSDAT space left, but < DX
- ; = FFFF if no SYSDAT space left at all
- ; Assumptions:
- ; MD chain goes from low addresses to high w/ no gaps.
- ; SYSDAT < TPA.
-
- mov bp,dx ; copy requested size in bytes
- add dx,15 ; round up to
- mov cl,4 ; nearest paragraph
- shr dx,cl
- jmps sysdat_mem_chop
-
- sysdat_mem_alloc:
- ;----------------
- ; Routine to trim the low end of the TPA to return the offset of a SYSDAT-
- ; inclusive buffer to the caller.
- ;
- ; Entry: DX = # bytes wanted
- ; Exit: AX = offset of area freed for caller;
- ; = 0 if some SYSDAT space left, but < DX
- ; = FFFF if no SYSDAT space left at all
- ; Assumptions:
- ; MD chain goes from low addresses to high w/ no gaps.
- ; SYSDAT < TPA.
-
- mov bp,dx ; copy requested size in bytes
- add dx,15 ; round up to
- mov cl,4 ; nearest paragraph
- shr dx,cl
-
- ; First try to reuse the init space:
- call check_init_reuse@
- jnc good_ret ; then we got it
-
- ; Get start of chain:
-
- sysdat_mem_chop:
- mov bx,mfl$ ; root
- mov si,MD_START[bx] ; save for below
-
- ; Is lowest TPA partition already out of reach?
- mov ax,ds
- add ax,1000h ; ax = 64k away
- cmp ax,si
- jbe ffff_ret
-
- ; Check for start + requested length in sysdat:
- mov di,dx ; DI = scratch
- add di,si
- cmp ax,di
- jb zero_ret
-
- ; Trim the MDs:
- call common_trim
-
- ; Return offset of base paragraph:
- mov ax,si ; start paragraph
- mov si,ds
- sub ax,si
- ; mov cl,4
- shl ax,cl ; start byte
-
- good_ret:
- mov dx,bp ; restore req. bytes
- ret
-
- ffff_ret:
- mov dx,bp ; restore req. bytes
- mov ax,0FFFFh
- ret
- zero_ret:
- mov dx,bp ; restore req. bytes
- sub ax,ax
- ret
-
-
- eject
-
- alloc_tmp_buffs:
- ;---------------
- ; Allocate the history buffers for the tmps.
- ; This system uses common buffers for the 4 virtual screens, and
- ; separate buffers for each serial terminal.
-
- mov dx,HIST_PROG_SIZE
- call hist_init
- mov prog_hist_base$,ax
-
- mov dx,HIST_COMM_SIZE
- call hist_init
- mov comm_hist_base$,ax
-
- sub di,di ; physical port number
- ser_hist_loop:
- cmp port2pc_table$[di],0ffh ; physical console number allocated ?
- je ser_hist_next ; no get next possible
- push di
- mov dx,HIST_SER_SIZE ; allocate & initialize buffer
- call hist_init
- pop di
- mov bl,port2pc_table$[di] ; get logical console number
- dec bl ; zero relative
- xor bh,bh
- shl bx,1
- mov ser_hist_base$[bx],ax ; save serial history buffer
- ser_hist_next:
- inc di ; next port number
-
- if SR
- cmp di,NUM_AUX_PORTS + NUM_SR_PORTS ; for SUN RIVER system
- else
- cmp di,NUM_AUX_PORTS ; all console ports done?
- endif
- jne ser_hist_loop ; loop back if more
- ret
-
-
- hist_init:
- ;---------
- ; entry: DX = # of paragraphs for history buffer
- ; exit: AX = segment address of history buffer
-
- call mem_alloc_i@ ; allocate DX paragraphs
- push es
- sub bx,bx
- mov es,ax ; set up segment
- mov es:word ptr [bx],bx
- mov es:byte ptr 4[bx],bl
- shl dx,1 ! shl dx,1
- shl dx,1 ! shl dx,1 ; para. to bytes
- sub dx,5 ; size of header
- mov es:word ptr 2[bx],dx
- pop es
- ret
-
- alloc_setup_buff:
- ;----------------
- ; This routine looks in the setup buffer for amount of SYSDAT space
- ; requested for device drivers, etc., allocates it, and updates the
- ; variables for the XIOS sysdat_alloc call:
- cmp su_check$,0DDB2h ; is the buffer valid?
- jne asb_done
- mov dx,su_sysdat$ ; get BYTES requested
- or dx,dx ; anything?
- jz asb_done ; jump if no
- asb_retry:
- call sysdat_mem_alloc
- inc ax ; FFFF -> 0 if none at all
- jz asb_done
- dec ax
- cmp ax,0 ; some?
- jnz store_addr ; jump if a good alloc
- sub dx,10h ; drop down a para and retry
- jbe asb_done ; if negative or 0, leave
- jmps asb_retry
-
- store_addr:
- mov sysdat_buff_base$,ax ; initted to 0
- mov sysdat_buff_length$,dx
- mov si,sysdat_mem$ ; sysdat memory allocation block
- mov sysdat_buff_link$,si ; and store in our block
- mov sysdat_mem$,offset sysdat_buff_link$ ; set link to free block
- asb_done:
- ret
- eject
-
- do_interrupts:
- ;-------------
- ; Take care of all of the interrupt stuff...
- ; if an interrupt vector is currently zero (uninitialized)
- ; then set it to the unexpected interrupt handler:
- ; 20 JUN 86--to support some more dumb apps, set up our unexpected handler
- ; only if a developer has tweeked the patch byte:
-
- cli ; an interrupt now would be bad
-
- sub di,di ; int vector pointer
- mov es,di ; int vector base address
- cmp unexp_byte,0BBh ; do we put in our handler?
- je int_setup1 ; if different, don't skip
- mov cx,256 ; number of interrupts
- int_save_loop:
- mov ax,es:[di] ; fetch the current vector
- or ax,es:2[di] ; and if it has a value
- jnz int_save_next ; then leave it alone
-
- mov es:[di],offset i_unexpected@
- mov es:2[di],cs ; if not, fill it in
- int_save_next:
- add di,4 ; to the next vector
- loop int_save_loop ; through the whole table
-
- ; Now set up our particular interrupts:
-
- int_setup1:
- mov si,offset int_tbl ; offsets and vectors
- mov cx,INT_TBL_LEN ; number of entries
- mov ax,ds
- cmp ax,3000h ; debug sys?
- jb no_int3_fix
- dec cx
- no_int3_fix:
- cld
- lodsw ; first check if NMI ->
- mov di,ax ; to ROS. If not then leave
- lodsw ; well alone (autoswitch cards)
- cmp es:word ptr 2[di],0e000h ; ROS segment ?? watch 386's
- jb int_setup_dec ; not pointing to ROS
- jmps int_store
- int_setup_loop:
- lodsw ; get destination
- mov di,ax ; and stash it
- lodsw ; get vector
- int_store:
- stosw ; and store it
- mov ax,cs ; all vectors to sysdat
- stosw
- int_setup_dec:
- loop int_setup_loop ; through the table
-
- ; Now set up timer interrupt:
- mov ax,timer_count$ ; variable timer count
- out TIMER_0_REG,al
- xchg ah,al
- out TIMER_0_REG,al
- ret ; to main line
-
- unexp_byte db 0BBh ; anything else, we'll install
- ; the unexpected handler
- eject
-
- sign_on:
- ;-------
- ; Print the sign on message with equipment configuration:
-
- mov dl,0 ; console 0
- call point_vs@
- push word ptr VS_ATTRIB ; save initial one
- push bx ; save vs_pointer
- mov al,iattrib$
- mov VS_ATTRIB,al
-
- mov si,offset banner
- call print_msg ; name, copyright, etc.
-
- pop bx ; restore vs_pointer
- pop word ptr VS_ATTRIB ; restore original attribute
-
- if XM
- mov si,offset num_pgkb$ ; address of paged memory count
- cmp word ptr [si],0 ; any paged memory?
- je sign_on_conv ; no, all conventional
- mov emm_fix,si ; "paged" instead of "main"
- push es
- push ds ! pop es
- mov si,offset emm_pag ; print different message
- mov di,offset emm_fix+4
- mov cx,length emm_pag
- rep movsb
- pop es
- sign_on_conv:
- endif
- mov si,offset hdware ; Hardware supported:
- call print_msg
- sign_on_loop:
- cmp word ptr [si],0 ; if next equip ptr = 0
- jz sign_on_done ; then we're done
- push si
- call print_equip ; print one item
- pop si
- add si,EQUIP_RECORD_LEN
- jmps sign_on_loop ; back for another
- sign_on_done:
- lodsw ; clear the pointer
- call print_msg ; cr,lf,lf
-
- ; Help 'em out by printing legal printer numbers:
- cmp byte ptr sign_on_prnum1,' ' ; space in second line
- jne print_2line
- mov byte ptr end_prnum,0 ; terminate after first line
- print_2line:
- mov si,offset prnt_num_msg
- call print_msg ; and return
- ret
-
-
- print_equip:
- lodsw
- xchg ax,bx ; bx -> equip count
- mov ax,[bx] ; ax = equip count
- test ax,ax ; if count = 0
- jz pr_equip_done ; then don't print
- push ax ; save the count
- call print_msg ; print the name first
- pop ax
- call print_num ; and then the count
- pr_equip_done:
- ret
-
- print_msg:
- lodsb ; fetch a character
- pr_msg_loop:
- push si
- call print_char ; print just one
- pop si
- lodsb ; fetch another
- test al,al
- jnz pr_msg_loop ; when char = 0, done
- ret
-
- print_num:
- sub dx,dx ; for 16-bit divide
- div ten_thousand
- push dx ; save remainder
- sub dh,dh ; yes, zero blanking
- call print_digit
- pop ax ; restore thou,hun,ten,ones
- mov cx,dx ; save leading digit's flag
- sub dx,dx ; for 16-bit divide
- div one_thousand
- push dx ; save remainder
- mov dx,cx ; restore leading digit's flag
- call print_digit
- pop ax ; restore hun,ten,ones
- div one_hundred ; al = hund's, ah = rem
- call print_digit ; print hundred's place
- mov al,ah
- cbw ; ready for divide
- div ten
- call print_digit ; print ten's place
- mov al,ah
- ; jmps print_digit ; print one's place
-
- print_digit:
- push ax ; save the number
- or dh,al ; have we started printing
- jz pr_digit_done ; skip if 0 and no
- push dx
- or al,'0' ; make into ascii
- call print_char ; and print it
- pop dx
- pr_digit_done:
- pop ax ; restore number
- ret
-
- print_char:
- mov cl,al ; char to cl
- mov dl,0
- jmp io_conout@ ; print it
- eject
-
- eject
-
- default_prnt:
- ;------------
- ; Find lowest existing printer number and stick in the PDs of all
- ; phase1 and phase2 RSPs.
-
- mov bx,offset sign_on_prnum
- mov cx,5
- dp_lp:
- mov al,[bx]
- cmp al,' '
- jne found_prnt
- add bx,2
- loop dp_lp
- ret
-
- found_prnt:
- and al,0fh ; make binary
- push es
- mov bx,ds
- mov es,bx
- mov bx,rspseg$
- call poke_prnt
- mov bx,phase1_root$
- call poke_prnt
- pop es
- ret
-
- poke_prnt:
- ; Entry: BX = RSP header segment
- or bx,bx
- jz end_poke
- mov es,bx
- mov es:.10h + P_LIST,al ; skip RSP header.
- mov bx,es:.0 ; get link
- jmps poke_prnt
- end_poke:
- ret
-
-
- alloc_flag@:
- ;-----------
- mov al,next_flag$
- inc next_flag$
- ret
-
-
- enable_ints:
- ;-----------
- ; Finally, enable the interrupts:
-
- mov dx,AUX_PORT0 ; clear pending ones
- call reset_uarts
- mov dx,AUX_PORT1
- call reset_uarts
-
- mov al,pic_mask_image$ ; restore the pic mask
- out PIC_MASK,al
- sti ; now we can handle ints
- ret ; to main line
-
- reset_uarts:
- ; add dx,AUX_PORT_DATA ; get any pending received
- in al,dx ; data
- jmps $+2
- add dx,2 ; IIR
- in al,dx ; reset trans-rdy int
- jmps $+2
- add dx,3 ; line status
- in al,dx ; reset error interrupt
- jmps $+2
- inc dx ; modem status
- in al,dx ; reset protocol interrupt
- ret
- eject
-
- INITCODE_END equ $
-
- ;************************************************
- ;* *
- ;* INITIALIZATION DATA AREA *
- ;* *
- ;************************************************
-
- init_dseg dseg
-
- INIT_START equ offset $
-
- hi_on$ dw 00000h ; on if high memory always OK
- hi_off$ dw 0FFFFh ; off if high memory never OK
-
- alloc_table rw 0
- dw 0,0,0,0,0,0,0,0,0,0 ; 30 entries
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
- dw 0,0,0,0,0,0,0,0,0,0
-
-
- memory_top rw 1 ; for memory_trim
-
- config0_data db 43h ; 300 baud, 1, none, 8
- config1_data db 43h ; same here
- config_data equ word ptr config0_data
- rb NUM_AUX_PORTS-2 ; all other serial ports go here
-
- term_data rb NUM_AUX_PORTS ; 0=LST/AUX, FF=CON (up to 9 ports)
- current_pc$ db 0 ; current physical console number assigned
- ; only used during INIT
- if V386
- ega_remap db FALSE ; flag if we've moved the EGA ROS
- endif
-
- init_video_mode rb 1 ; which crt to default
- pic_mask_image$ rb 1 ; set at the top of init
- pc_pt_bootable db 0 ; <> 0 if pc partition bootable
- boot_drive rb 1 ; ROS code for the boot drive
- reloc_disk$ dw 0 ; size of hard disk param table if moved
-
- ; some pc hard disk data - moved from HDISK.A86
-
- pc_blk_size dw 0400h,0800h,1000h,2000h,4000h,4000h,4000h
- pc_bsh_blm dw 0703h,0F04h,1F05h,3F06h,7F07h,7F07h,7F07h
- pc_hd_dph_start rw 1
- hd_dph_start rw 1
- hd_dos_sys_id db 0 ; temporarily save system id code
- drive_num db 0 ; temp drive number storage
- maxpsh db 2 ; max. sector size (2 = 512)
- local_bsize dw 2*512 ; 1 Kb unless CP/M hard disks
-
- pc_part_table_iopb:
- db HD_ROS_READ,0,0,0 ; fn,err,lun,head
- dw 0 ; cyl
- db 0,1 ; sector, count
- dw 0,0 ; must be preset to ds
-
- ; String to look for at AT_HDROS_SEG:AT_HDROS_OFF to identify the
- ; multi-sector bug:
-
- buggy_string db 47h,0E2h,0F9h,0E8h,2Dh,1,75h,7,0F6h,6,8Ch,0,80h,75h,0CDh,0C3h
-
- ; Lists of dph offsets:
-
-
- ; Lists of branch vector offsets:
-
- flop_vectors dw select_flop@, read_flop@, write_flop@
- pc_hd_vectors dw pc_select_hd@, pc_read_hd@, pc_write_hd@
- eject
-
- ; The following structure is used to write to the COMPAQ
- ; memory configuration register in order to permit writing
- ; to COMPAQ 32-bit RAM at E000:0-FFFF:0
-
- if V386
- ;-----------------------;
- int15_gdt rb 8 ; null entry - dummy
- ;-----------------------;
- rb 8 ; GDT entry - filled in by ROS
- ;-----------------------;
- dw -1 ; segment limit = 64K
- db 0,0,0,93H ; base address, attribute
- db 0, 0 ; 386 extension
- ;-----------------------;
- dw -1 ; segment limit = 64K
- db 0,0,0,93H ; base address, attribute
- db 0, 0 ; 386 extension
- ;-----------------------;
- rb 8 ; BIOS CS entry - filled in by ROS
- ;-----------------------;
- rb 8 ; BIOS SS entry - filled in by ROS
- ;-----------------------;
-
- ; Compaq memory control port value:
- int15_config dw 0FEFEh ; map RAM, don't write protect
-
- endif
-
- LUC equ 201 ! LLC equ 200 ! RUC equ 187 ! RLC equ 188
- HU equ 205 ! HL equ 205
- VVR equ 186 ! VVL equ 186
-
- banner db ESC,'H' ; home cursor
- db LUC
- db HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU ;20
- db HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU ;20
- db HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU,HU ;15
- db RUC,CR,LF
-
-
- ;banner db '-----------------------------------------------------',CR,LF
- if XM
- db VVL,' Concurrent DOS XM for the IBM PC, XT, AT 9-Jan-89 ',VVR,CR,LF
- endif
- if V386
- db VVL,' Concurrent DOS 386 for Intel 386 based PC''s 9-Jan-89 ',VVR,CR,LF
- endif
- db VVL,' Copyright(C) 1982-89 All Rights Reserved ',VVR,CR,LF
- db VVL,' Digital Research, Inc. Monterey, California, USA ',VVR,CR,LF
-
- db LLC
- db HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL ;20
- db HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL ;20
- db HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL,HL ;15
- db RLC,CR,LF;LF
-
- db 0
- hdware:
- db ' Hardware Supported :',CR,LF,0
-
- dw num_flop$
- db CR,LF,' Diskette Drive(s) : ',0
- dw num_hard$
- db CR,LF,' Hard Disk(s) : ',0
- dw num_print$
- db CR,LF,' Parallel Printer Port(s) : ',0
- dw num_port$
- db CR,LF,' Serial Port(s) : ',0
- dw num_ndp$
- db CR,LF,' Numeric Data Processor : ',0
- last_eq rw 0
- if XM
- emm_fix dw num_mmkb$
- db CR,LF,' Main Memory (Kb) : ',0
- endif
- if V386
- dw num_pages$
- db CR,LF,' 386 Paged Memory (Kb) : ', 0
- endif
-
- EQUIP_RECORD_LEN equ offset $ - offset last_eq
- dw 0 ; equipment end
- db CR,LF,0 ; last message
-
- prnt_num_msg rb 0
- db ' Printer Numbers : '
- sign_on_prnum db ' ' ; printers + spaces
- db CR,LF
- end_prnum db ' ' ; padding
- sign_on_prnum1 db ' ' ; printers + spaces
- db CR,LF,0
-
- ; db CR,LF,' Main Memory (Kb) : ',0
- ; db CR,LF,' EEMS Paged Memory (Kb) : ',0
- emm_pag db ' EEMS Paged' ; remainder same as "Main Memory (Kb)"
-
-
- ten_thousand dw 10000 ; for print_number divisions
- one_thousand dw 1000
- one_hundred db 100
- ten db 10
- eject
-
- ; Interrupt setup table
-
- int_tbl dw NMI_INTERRUPT*4, i_nmi@ ; MUST be first in list
- dw DIVIDE_INTERRUPT*4, i_divide@
- dw OVERFLOW_INTERRUPT*4, i_overflow@
- dw CLOCK_INTERRUPT*4, i_clock@
- dw TICK_INTERRUPT*4, i_tick@
- dw KEYBOARD_INTERRUPT*4, i_keyboard@
- dw AUX1_INTERRUPT*4, i_aux_1@
- dw AUX0_INTERRUPT*4, i_aux_0@
- dw DISK_INTERRUPT*4, i_disk@
- dw HD_CODE_INTERRUPT*4, hd_dummy_int@
- ;; dw BREAK_INTERRUPT*4, i_cntl_brk@
- dw VIDEO_INT*4, video_int@
- dw ASYNC_INT*4, async_int@
- dw FLAG_INTERRUPT*4, i_fidds_flag@
- dw FIDDS_INTERRUPT*4, i_dummy_fidds@
- dw ONE_BYTE_INTERRUPT*4, iret_op@ ; must be last!
-
- INT_TBL_LEN equ (offset $ - offset int_tbl) / 4
-
- month_length dw 0,31,59,90,120,151 ; days in prior months
- dw 181,212,243,273,304,334
-
- if 0 ;#IJ
- pctmpstr db 'PCTmp0 ' ; PCTmp0 - PCTmp#
- pinstr db 'PIN0 ' ; PIN0 - PIN#
- endif
-
- if V386
- flushstr db 'Flush1 ' ; Flush1 - Flush#
- endif
-
- compaq_name db 'COMPAQ'
- if V386
- sprite_name db 'JAROGATE'
- endif
- if XM
- amstrad_name db 'Amstrad'
- olivetti_name db 'OLIVETTI'
- endif
-
-
-
- XIOS_END equ offset $
-
- end
- ;END OF INIT.A86
-