IMD 1.17: 1/01/1998 2:42:16 SLICER BIOS 40 Trk   SLICERCBp sņఅ..ņంQ<.3Ҿ3ņ YthrȎЎؼ&p &36 t@pnpp33ņQPSR Z[XYt3 t  uln33ņQPSR Z[XYuF&iU&]Iȋn3ҋņQPSR Z[XYu pc.6 t.& 3.6 t@IO SYSMSDOS SYSNot System diskError loading systemdBË..O`  @`! #@%`')+-/1 3@5`79;=?A C@E`GKMOQ S@oWY[]_a c@e`gikmoqs@u`wy{}@o @ ` @ ` @ ` ` ǀ ɠ @ ` ׀ ٠  @` @`!Aa   !Aa!!#A%a')-//35a79;=?A!CAEaGIKMOQ!SAUaWY[]_aO`  @`! #@%`')+-/1 3@5`79;=?A C@E`GKMOQ S@oWY[]_a c@e`gikmoqs@u`wy{}@o @ ` @ ` @ ` ` ǀ ɠ @ ` ׀ ٠  @` @`!Aa   !Aa!!#A%a')-//35a79;=?A!CAEaGIKMOQ!SAUaWY[]_a8087MAC ASM X$0BIOS ASM )BIOSDATAASM 0IBOMB ASM ԝxPDBG ASM yY=UrEPROM EXE fr r=HDBOOT ASM [k KIBMBIOS ASM B!%IBMPRN ASM qTINIT EXE {/ j/INIT IN sd LD4 CMD T LOADER3 EXE L" iMEMTEST ASM {b NEWCALL ASM ky~NEWKEY ASM OY=?NEWVIDEOASM !OLDCALL ASM +A`.RESET ASM *SETPORT BAT H/ +SOURCE DOC i(,SPRN ASM rX .RSTEAL210ASM S 1SU EXE {/ 4TABLES ASM o X&  ;8087 MACRO FOR MICROSOFT DUMB ASSEMBLER V4.0 FINIT MACRO ;INITIALIZE 8087 WAIT ;CLEARS THE REGISTER STACK DB 0DBH,0EBH ENDM FLDPI MACRO ;PUSH THE VALUE OF PI WAIT ;ONTO THE REGISTER STACK DB 0D9H,0EBH ENDM FILD MACRO IVAR ;LOADS SHORT INTEGER ONTO THE WAIT ;REGISTER STACK ESC 18H,IVAR ENDM FDIV MACRO STI ;FDIV ST,ST(i) WAIT DB 0D8H,0F0H+STI ENDM FMUL MACRO STI ;FMUL ST,ST(i) WAIT DB 0D8H,0C8H+STI ENDM FST MACRO RVAR ;FST RVAR WAIT ;STORES SHORT REAL FORMAT ESC 0AH,RVAR WAIT ENDM ! #@%`')+-/1 3@5`79;=?A C@EGIKOQ S@U`WY[_a c@e`gikmoq s@u`wy{@` ` @ o @ ` @ ` ɠ @ ` ׀ ٠  @` O`Aa   !Aa/#%a')+-/1!3A5a79;=/CAG if2 %out Pass 2. endif .286c page 60,132 name core title Slicer Concurrnet BIOS Version 1.0A ;-------------------------------------------------------------------------------- ; Concurrent BIOS for the Slicer. (C) Slicer Computers Inc.,1985 ; ; Version 1.0A April 4, 1985 ; By David Daney 1985 ; ; ;-------------------------------------------------------------------------------- subttl Equates page ;---------------------------------------------------------------- ; E Q U A T E S ;---------------------------------------------------------------- b equ byte ptr w equ word ptr ; ; byte definition ; disk type uninitialized equ 10000000b mini equ 00010000b double_density equ 00100000b double_track equ 01000000b sector_size_m equ 00001100b step_rate_m equ 00000011b ;---------------------------------------------------------------- ; disk_flags ;---------------------------------------------------------------- disk_in_service equ 00000001b fop_waiting equ 00000010b ;floppy done f_nest equ 00000100b write_status equ 00001000b interuptable equ 00010000b sop_waiting equ 00100000b ;sasi done sasi_nest equ 01000000b sasi_in_service equ 10000000b ;---------------------------------------------------------------- ; com_flags ;---------------------------------------------------------------- com1_waiting equ 00000001b com2_waiting equ 00000010b com3_waiting equ 00000100b com4_waiting equ 00001000b com5_waiting equ 00010000b com6_waiting equ 00100000b ;---------------------------------------------------------------- ; Hardware I/O port definition ;---------------------------------------------------------------- keyboard_port equ 300h ;CAN BE 60 WITH BOARD CHANGES aux_timer_int equ 01ch ibm_timer0_int equ 08h concurrent_int equ 0f9h aux_int13_int equ 0fch mini_sel equ 010ch dbl_den_sel equ 010eh sasi_reset_port equ 102h sasi_sel_port equ 100h sasi_data_port equ 180h sasi_stat_port equ 184  h sasi_reset_port equ 102h sasi_sel_port equ 100h ;---------------------------------------------------------------- ; sasi status port definitions ;---------------------------------------------------------------- status_mask equ 1011100000000000b selected equ 0000100000000000b request equ 0100000000000000b command_block1 equ 0010100000000000b data_block_fro equ 0000100000000000b data_block_to equ 1000100000000000b status_byte equ 1010100000000000b message_byte equ 1011100000000000b ; ; ; 2681 EQUATES ; ; uart_base2 equ 200h uart_base equ 80h mode_rega equ uart_base stat_reg equ 2 stat_rega equ uart_base+stat_reg clock_reg equ 2 command_reg equ 4 command_rega equ uart_base+command_reg clock_rega equ uart_base+clock_reg tx_rega equ 6+uart_base rx_rega equ 6+uart_base aux_cr equ 8+uart_base int_reg equ 0ah+uart_base mode_regb equ mode_rega+10h stat_regb equ stat_rega+10h command_regb equ command_rega+10h clock_regb equ clock_rega+10h tx_regb equ tx_rega+10h rx_regb equ rx_rega+10h out_cr equ uart_base+1ah in_reg equ uart_base+1ah sio_out_set equ uart_base+1ch sio_out_clr equ uart_base+1eh ; reset_rx equ 00100000b reset_tx equ 00110000b disable_channel equ 00001010b enable_channel equ 00000101b reset_mr_ptr equ 00010000b mode1 equ 10010011b mode2 equ 00011111b auxa equ 10000000b enable_all equ 00100010b enable_1 equ 00000010b enable_2 equ 00100000b rx_rdy equ 1b tx_rdy equ 100b enable_ctsa equ 1b enable_ctsb equ 10b enable_dtra equ 100b enable_dtrb equ 1000b out_config equ 0 xoff equ 13h jump96 equ 40h baudb equ 66h ;1200 baud ; ; 8250 EQUATES ; ; com_port equ 3f0h line_control equ com_port+0bh divisor_latchl equ com_port+08h ;dlab = 1 divisor_latchm equ com_port+09h ;dlab = 1 line_status equ com_port+0dh interrupt_id equ com_port+0ah interrupt_enable equ com_port+09h ;dlab = 0 modem_control equ com_port+0ch modem_status equ com_port+0eh receiver_buffer equ com_port+08h ; dlab = 0 READ transmitter_holding equ com_port+08h ; dlab = 0 WRITE ; ; ; Z8530 EQUATES ; ; scc_base equ 240h port4_control equ scc_base port3_control equ scc_base+4 port4_data equ scc_base+2 port3_data equ scc_base+6 reset3 equ 080h reset4 equ 040h reset_scc equ 0c0h mie equ 08h wr1 equ 12h wr11 equ 01010101b wr14d equ 2 wr14e equ 3 wr15 equ 0 reset_txip equ 00101000b channela_txip equ 00010000b channela_rxip equ 00100000b channelb_txip equ 00000010b channelb_rxip equ 00000100b ;---------------------------------------------------------------- ; Meg board equates ;---------------------------------------------------------------- switch_port equ 261h smem_mask equ 4 vmem_mask equ 2 meg_mask equ 00001001b switch_mask equ 11111001b uart2_base equ 200h mode_reg2a equ uart2_base stat_reg2a equ uart2_base+stat_reg command_reg2a equ uart2_base+command_reg clock_reg2a equ uart2_base+clock_reg tx_reg2a equ 6+uart2_base rx_reg2a equ 6+uart2_base aux_cr2 equ 8+uart2_base int_reg2 equ 0ah+uart2_base mode_reg2b equ mode_reg2a+10h stat_reg2b equ stat_reg2a+10h command_reg2b equ command_reg2a+10h clock_reg2b equ clock_reg2a+10h tx_reg2b equ tx_reg2a+10h rx_reg2b equ rx_reg2a+10h out_cr2 equ uart2_base+1ah sio2_out_set equ uart2_base+1ch sio2_out_clr equ uart2_base+1eh ; ; ; ; fdc_status equ 0h fdc_command equ 0h fdc_track equ 2h fdc_sector equ 4h fdc_data equ 6h dma_cr0 equ 0ffcah dma_sl0 equ 0ffc0h dma_sh0 equ 0ffc2h dma_dl0 equ 0ffc4h dma_dh0 equ 0ffc6h dma_tc0 equ 0ffc8h dma_cr1 equ 0ffdah dma_sl1 equ 0ffd0h dma_sh1 equ 0ffd2h dma_dl1 equ 0ffd4h dma_dh1 equ 0ffd6h dma_tc1 equ 0ffd8h timer0_control equ 0ff56h timer1_control equ 0ff5eh timer2_control equ 0ff66h timer2_max_ct equ 0ff62h timer2cw equ 1110000000000001b ;enable timer2 continous counting ;generating interupts timer1cw equ 0100000000000000b ;disabled timer0cw equ 0100000000000000b ;disabled timer2_divisor equ 40000 ;50 times a sec at 8mHz. ;---------------------------------------------------------------- ; Interupt registers ;---------------------------------------------------------------- int0_int_cr equ 0ff38h int1_int_cr equ 0ff3ah int2_int_cr equ 0ff3ch int3_int_cr equ 0ff3eh dma0_int_cr equ 0ff34h dma1_int_cr equ 0ff36h timer_int_cr equ 0ff32h is_reg equ 0ff2ch priority_maskr equ 0ff2ah int_maskr equ 0ff28h eoi_reg equ 0ff22h ;---------------------------------------------------------------- ; Interupt priorities These priorities should be observed when ; 0-dma0   using external service routines ; 1-fdc ; 2-dma1(if used) ; 3-onboard serial ports ; 4-offboard serial ports(if installed) ; 5-IBM keyboard(if installed) ; 6-timer ; 7-unused interupts ;---------------------------------------------------------------- timer_int_cw equ 6 dma0_int_cw equ 0 dma1_int_cw equ 2 int0_int_cw equ 0fh int1_int_cw equ 1 ;edge triggered (fdc) int2_int_cw equ 0fh int3_int_cw equ 0fh com_int_cw equ 13h ;level triggered com2_int_cw equ 14h ;level triggered priority_mask equ 6 int_is_mask equ 11111101b ;mask out non inservice bits ; eoi_cmd equ 8000h dma0_int_mask equ 00000100b dma1_int_mask equ 00001000b int0_int_mask equ 00010000b int1_int_mask equ 00100000b int2_int_mask equ 01000000b int3_int_mask equ 10000000b timer_int_mask equ 00000001b ;---------------------------------------------------------------- ; Chip select registers ;---------------------------------------------------------------- umcsr equ 0ffa0h lmcsr equ 0ffa2h pacsr equ 0ffa4h mmcsr equ 0ffa6h mpcsr equ 0ffa8h umcsv equ 0f838h ;32k no wait states lmcsv equ 03ff8h ;256k no wait states pacsv equ 03ah ;i/o starts at 0, 2 wait states mpcsv equ 090bbh ;io io space 7pcs lines 3 waits 32k wide mcs mmcsv equ 0c1fbh ;mcs lines start at c0000h ;---------------------------------------------------------------- ; Command and status definitions ;---------------------------------------------------------------- motor_ctl equ 080h terminate_ni equ 11010000b terminate_wi equ 11011000b restore_cmd equ 00001000b seek_cmd equ 00011000b fatal_error equ 2 non_fatal_error equ 1 time_out equ 80h not_ready_error equ 80h bad_seek equ 40h bad_crc equ 10h record_not_fnd equ 04h write_protect equ 03h bad_addr_mark equ 02h bad_cmd equ 01h sasi_time_out equ 0ffh disable_dma equ 0110111000000101b ;stop channel no int. dma_read equ 1010111101100110b ;dest inc, source nochg, stop on tc ;int on tc high priority no timer int  ;start channel byte transfers dma_write equ 0111011110100110b ;dest nochg,source inc, stop on tc ;int on tc high priority no timer int ;start channel byte transfers sasi_dma equ 1111111110100110b ;used only to generate an interupt ;after 1 transfer dma1_int equ 0bh run_monitor equ 4 ; subttl Data Areas page + include biosdata.asm include 8087mac.asm subttl Externals and Publics page + ;---------------------------------------------------------------- ; Externals and Publics ;---------------------------------------------------------------- extrn new_call_init:near extrn old_call_init:near extrn ibm_call_init:near extrn video_init:near extrn keyboard_init:near extrn bootstrap:near ; extrn memory_debug:near extrn bomb_init:near extrn bomb_c:near extrn memtest:near extrn moninit:near ;ADDED FOR MAP public timer,cal_address,disk_op,int_dma0 public disk_pseudo_int,check_8087 public disk_read,disk_read1 public disk_write,disk_write1 public disk_reset public port1_write,port2_write,port3_write,port4_write public port1_status,port2_status,port3_status,port4_status public set_up_port1,set_up_port2,set_up_port3,set_up_port4 public ibm_serial public initialize public drive_mask public sasi_io,sasi_io1 subttl Initialization Code page + ;---------------------------------------------------------------- ; Setup all internal and external peripheral registers, and low ; memory locations.  ;---------------------------------------------------------------- cgroup group code code segment byte public 'code' assume cs:cgroup,ds:data org 0h initialize proc far cli mov dx,lmcsr mov ax,lmcsv out dx,ax mov dx,pacsr mov ax,pacsv out dx,ax mov dx,mpcsr mov ax,mpcsv out dx,ax mov dx,mmcsr mov ax,mmcsv out dx,ax ;activate mmcs lines mov dx,out_cr mov al,out_config out dx,al mov al,motor_ctl out sio_out_set,al ;turn off floppy motors  mov ax,data mov ds,ax mov ax,stack mov ss,ax assume ss:stack mov sp,offset stack_top cmp reset_location,1234h jne i17 jmp i13 ;warm start skip baud rate i17: ;---------------------------------------------------------------- mov dx,command_rega mov al,reset_rx+disable_channel out dx,al mov al,reset_tx out dx,al mov al,reset_mr_ptr out dx,al mov al,enable_ctsa+enable_ctsb+enable_dtra+enable_dtrb mov dx,sio_out_set out dx,al BAUD: MOV AL,100  10011B ;8 bits ; no parity ; Rx controls RTS OUT mode_rega,AL MOV AL,00011111B ;CTS controls XMTR ; 2 stops OUT mode_rega,AL IN AL,in_reg ;Jumper decides whether TEST AL,JUMP96 ;baud rate is set by JNZ GETBAUD ;CR typed at console MOV AL,0BBH ;or just set to 9600 OUT clock_rega,AL JMP i13 GETBAUD: MOV CX,3 ;Retries BAUD0: JCXZ ECHO DEC CX ;Try again MOV BX,-1 BAUD1: INC BX ;Count breaks MOV AX,0CC00H ;38.4K MOV DI,OFFSET BAUD2 ;Set baud JMP BAUD6 ;and get char BAUD2: OR AL,AL ;Break? JZ BAUD1 ;Get another char CMP AL,0dh ;If CR then 38.4K baud JZ BAUD9 ;is correct CMP BL,0 ;First char? JZ BAUD3 MOV AL,BL ;If not use break count. BAUD3: MOV BX,OFFSET BAUDTABLE BAUD4: MOV DX,cs:[BX] ;Search table CMP DH,0 ;Error? JZ BAUD0 CMP DL,0 ;End of table? JZ BAUD5 ;Use default baud ADD BX,2 CMP AL,DL ;Test. JNZ BAUD4 BAUD5: MOV AH,DH ;Have it. Set baud MOV DI,OFFSET BAUD9 MOV AL,80H BAUD6: MOV BP,AX OUT aux_cr,AL MOV AL,00100001B ;Reset OUT command_rega,AL MOV AL,AH ;Set baud OUT clock_rega,AL MOV AL,00010101B ;Tx enable ; Rx enable OUT command_rega,AL BAUD7: IN AL,stat_rega ;Get a char. TEST AL,rx_rdy JZ BAUD7 IN AL,rx_rega JMP DI ;RAMless return BAUD9: JMP i13 ;Couldn't determine baud rate. Set baud to 1200 and go ;into continuous echo mode. ECHO: MOV AL,66H OUT clock_rega,AL ECHO0: MOV AL,AH OUT tx_rega,AL ECHO1: IN AL,stat_rega TEST AL,tx_rdy JNZ ECHO0 TEST AL,rx_rdy JZ ECHO1 IN AL,rx_rega MOV AH,AL JMP ECHO1 BAUDTABLE: DB 0E6H,0CCH ;19.2K DB 78H,0BBH ;9600 DB 80H,99H ;4800 DB 1,88H ;2400 DB 3,66H ;1200 DB 6,55H,7,55H ;600 DB 12,44H,13,44H,14,44H ;300 DB 0,0 ;Put default baud here. ;---------------------------------------------------------------- i13: mov equip_flag,40cdh ;1 printer ,no game,no rs232 ;4 disk drives, 64k ram call ibm_call_init call video_init ;initialize video to get bomb messages call memory_check mov ax,vectors mov es,ax assume es:vectors call bomb_init ;WILD INTERRUPT call old_call_init ;MONITOR set macro num,val mov w num,offset val mov w num+2,seg val endm set vector_3,dummy_int ;break use by PD set vector_1c,dummy_int set vector_8,dummy_int ;ibm timer set vector_f9,flag_int set vector_33,dummy_int ;microsoft mouse int set vector_67,dummy_int ; init_int: mov dx,priority_maskr mov ax,priority_mask out dx,ax mov dx,is_reg mov ax,0 ;clear all in service bits out dx,ax mov dx,int_maskr ;mask all interupts. they will be mov ax,0ffh ;unmasked as they are initialized out dx,ax mov dx,int0_int_cr mov ax,int0_int_cw out dx,ax mov dx,int2_int_cr mov ax,int2_int_cw out dx,ax mov dx,int3_int_cr mov ax,int3_int_cw out dx,ax ; mov dx,sasi_stat_port+1 in al,dx and al,3 cmp al,2 ;checks for rev E board mov bl,al ;save in bl also mov ax,com_int_cw jnz init_int0 set vector_f,com_int mov dx,int3_int_cr out dx,ax jmp i2 init_int0: set vector_c,com_int mov dx,int0_int_cr out dx,ax i2: mov dx,command_reg2a ;check for expansion board ports mov al,reset_mr_ptr out dx,al mov al,055h mov dx,mode_reg2a out dx,al mov dx,command_reg2a mov al,reset_mr_ptr out dx,al mov dx,mode_reg2a in al,dx cmp al,055h je i5 jmp i3 ;no expansion ports i5: cmp bl,2 ;checks for rev E board mov ax,com2_int_cw jnz init_int2 set vector_c,com2_int mov dx,int0_int_cr out dx,ax jmp i4 init_int2: set vector_f,com2_int mov dx,int3_int_cr out dx,ax i4: mov dx,command_reg2a mov al,reset_rx+disable_channel out dx,al mov al,reset_tx out dx,al mov al,reset_mr_ptr out dx,al mov dx,mode_reg2a mov al,mode1 out dx,al mov al,mode2 out dx,al mov al,baudb mov dx,clock_reg2a out dx,al mov dx,aux_cr2 mov al,0 out dx,al mov al,enable_all mov com2_int_status,al mov dx,int_reg2 out dx,al mov dx,out_cr2 mov al,out_config out dx,al mov al,enable_ctsa+enable_ctsb+enable_dtra+enable_dtrb mov dx,sio2_out_set out dx,al mov dx,command_reg2a mov al,enable_channel out dx,al mov dx,command_reg2b mov al,reset_rx+disable_channel out dx,al mov al,reset_tx out dx,al mov al,reset_mr_ptr out dx,al mov dx,mode_reg2b mov al,mode1 out dx,al mov al,mode2 out dx,al mov al,baudb mov dx,clock_re  g2b out dx,al mov dx,command_reg2b mov al,enable_channel out dx,al i3: mov dx,command_rega mov al,reset_rx+disable_channel out dx,al mov al,reset_tx out dx,al mov al,reset_mr_ptr out dx,al mov dx,mode_rega mov al,mode1 out dx,al mov al,mode2 out dx,al mov al,enable_all mov com1_int_status,al mov dx,int_reg out dx,al mov dx,out_cr mov al,out_config out dx,al mov al,enable_ctsa+enable_ctsb+enable_dtra+enable_dtrb mov dx,sio_out_set  out dx,al mov dx,command_rega mov al,enable_channel out dx,al mov dx,command_regb mov al,reset_rx+disable_channel out dx,al mov al,reset_tx out dx,al mov al,reset_mr_ptr out dx,al mov dx,mode_regb mov al,mode1 out dx,al mov al,mode2 out dx,al mov al,baudb mov dx,clock_regb out dx,al mov dx,command_regb mov al,enable_channel out dx,al init_dma: mov dx,dma_cr0 mov ax,disable_dma out dx,ax mov dx,dma_cr1 out dx,ax mov dx,dma0_int_cr mov ax,dma0_int_cw out dx,ax mov dx,dma1_int_cr mov ax,dma1_int_cw out dx,ax set vector_a,int_dma0 set vector_b,int_dma1 init_timers: mov dx,timer0_control mov ax,timer0cw ;turn off timers 0,1 out dx,ax ;turn on timer 2 mov ax,timer1cw mov dx,timer1_control out dx,ax mov dx,timer2_control mov ax,timer2cw out dx,ax mov dx,timer2_max_ct mov ax,timer2_divisor out dx,ax mov dx,timer_int_cr mov ax,timer_int_cw out dx,ax set vector_13,timer set vector_fd,disk_pseudo_int ;Jonathan 10-8-86 mov motor_count,500 mov select_count,100 ;**************************************************************** mov disk_time_out,25 ; mov hdisk_time_out,0ffffh ;**************************************************************** mov motor_count1,0 mov select_count1,0 mov disk_time_out1,0 init_fdc: mov dx,fdc_command mov al,terminate_ni out dx,al mov dx,int1_int_cr mov ax,(int1_int_cw or 8) out dx,ax set vector_d,int_fdc and disk_flags,not disk_in_service xor bx,bx mov cx,4 xor ax,ax ifloop: mov w wait_flags[bx],ax add bx,2 loop ifloop call disk_reset call ibm_call_init mov al,0ffh mov dx,keyboard_port out dx,al ;set video to text display ;initialize video to get bomb messages call ibm_com1_init call new_call_init call keyboard_init call keyboard_init ;do it twice to make sure we find keyboard call video_init ;initialize ibm com1 if present call check_8087 sti ; cmp reset_location,4321h ;monitor start code jne i15 jmp moninit ;goto monitor i15: mov al,79h ;BIT IN FLOPPY CONTROLLER FOR HEAD DEBOUNCE mov bx,1 ;turn on head settle mov cx,0ffffh ;spin up time in biosdata.asm mov ah,0 int 0f8h ;floppy control mov printer_stat,0 ;used to initialize ack signal mov dsknum,0 jmp bootstrap initialize endp ;---------------------------------------------------------------- ; Misc. functions ;---------------------------------------------------------------- memory_check proc near ; ; cmp reset_location,1234h jne mc13 mov reset_location,4321h ;goto monitor code jmp short mc14 mc13: mov reset_location,0 ;cold boot on next reset mc14: mov dx,sio2_out_set ;signal is inverted mov al,0ffh out dx,al ;set meg board to map 0 xor ax,ax ;ax has current memory size in k-bytes mc1: mov bx,ax shl bx,6 ;move to bx and convert to segment mov es,bx xor bx,bx mc2: mov cx,es:[bx] mov dx,es:[bx+2] mov es:[bx],05555h mov es:[bx+2],0ffffh cmp es:[bx],05555h mov es:[bx],cx jne mc3 mov es:[bx],0aaaah mov es:[bx+2],0ffffh cmp es:[bx],0aaaah mov es:[bx+2],dx mov es:[bx],cx jne mc3 add bx,2 cmp bx,400h jl mc2 inc ax jmp mc1 mc3: cmp ax,64 jae mc4 jmp memtest mc4: mov bx,ax ;save value in bx mov dx,switch_port in al,dx ;check for meg board and adjust size mov dl,al and dl,switch_mask ;mask out 3 high bits cmp dl,meg_mask jne mc5 test al,smem_mask jnz mc6 cmp bx,832 jle mc6 mov bx,832 mc6: test al,vmem_mask jnz mc5 cmp bx,640 jle mc5 mov bx,640 mc5: mov memory_size,bx ;ibm monitor size mov memsize,bx ;old monitor size cmp reset_location,4321h ;goto monitor code je mc15 mov reset_location,1234h ;warm boot on next reset mc15: ret memory_check endp subttl Concurrent Flags page + ;--------------------------------------------------------  -------- ; Flag Int ; ah=function ; 0=wait until flag set then clear flag and return ; 1=set flag ; 2=clear flag (used only for initialization) ; 3=pop ax and return ; al=flag number (0-63) ; functions 0-2 destroy ax,and bx ;---------------------------------------------------------------- flag_int proc far sti or ah,ah jz wait_flag dec ah jz set_flag dec ah jz clear_flag add sp,6 ;pop off callers return address and flags pop ax ;pop ax  iret set_flag: push ds mov bx,data xor ah,ah mov ds,bx mov bl,8 div bl xchg ah,al mov bx,offset drive_mask xlat cs:drive_mask mov bl,ah xor bh,bh or wait_flags[bx],al pop ds iret clear_flag: push ds mov bx,data mov ds,bx xor ah,ah mov bl,8 div bl xchg ah,al mov bx,offset drive_mask xlat cs:drive_mask mov bl,ah xor bh,bh not al and wait_flags[bx],al pop ds iret wait_flag: push ds mov bx,data mov ds,bx xor ah,ah  mov bl,8 div bl xchg ah,al mov bx,offset drive_mask xlat cs:drive_mask mov bl,ah xor bh,bh wf_loop: test wait_flags[bx],al jz wf_loop not al and wait_flags[bx],al pop ds iret flag_int endp subttl Serial Ports page + ;---------------------------------------------------------------- ; Serial port write functions. ; Reads will just access the buffers ;---------------------------------------------------------------- port1_write proc near ;char in al to port1 push ax ;wait for transmitter ready ; ; test com_hold_enable,1 jz p1w3 p1w4: test com_hold,1 jnz p1w4 ;wait for hold to clear p1w3: mov dx,stat_rega p1w1: in al,dx test al,tx_rdy jz p1w1 ; ; pop ax mov dx,tx_rega ;output byte out dx,al ret port1_status: test com_hold_enable,1 jz p1w5 test com_hold,1 jnz p1w6 ;hold p1w5: mov dx,stat_rega in al,dx test al,tx_rdy mov al,0 jnz p1w2 p1w6: mov al,not_ready_error p1w2: ret port1_write endp port2_write proc near ;char in al to port1 push ax ;wait for transmitter ready ; ; test com_hold_enable,10b jz p2w3 p2w4: test com_hold,10b jnz p2w4 ;wait for hold to clear p2w3: mov dx,stat_regb p2w1: in al,dx test al,tx_rdy jz p2w1 ; ; pop ax mov dx,tx_regb ;output byte out dx,al ret port2_status: test com_hold_enable,10b jz p2w5 test com_hold,10b jnz p2w6 ;hold p2w5: mov dx,stat_regb in al,dx test al,tx_rdy mov al,0 jnz p2w2 p2w6: mov al,not_ready_error p2w2: ret port2_write endp port3_write proc near ;char in al to port1 push ax ;wait for transmitter ready ; ; test com_hold_enable,100b jz p3w3 p3w4: test com_hold,100b jnz p3w4 ;wait for hold to clear p3w3: mov dx,stat_reg2a p3w1: in al,dx test al,tx_rdy jz p3w1 ; ; pop ax mov dx,tx_reg2a ;output byte out dx,al ret port3_status: test com_hold_enable,100b jz p3w5 test com_hold,100b jnz p3w6 ;hold p3w5: mov dx,stat_reg2a in al,dx test al,tx_rdy mov al,0 jnz p3w2 p3w6: mov al,not_ready_error p3w2: ret port3_write endp port4_write proc near ;char in al to port1 push ax ;wait for transmitter ready ; ; test com_hold_enable,1000b jz p4w3 p4w4: test com_hold,1000b jnz p4w4 ;wait for hold to clear p4w3: mov dx,stat_reg2b p4w1: in al,dx test al,tx_rdy jz p4w1 ; ; pop ax mov dx,tx_reg2b ;output byte out dx,al ret port4_status: test com_hold_enable,1000b jz p4w5 test com_hold,1000b jnz p4w6 ;hold p4w5: mov dx,stat_reg2b in al,dx test al,tx_rdy mov al,0 jnz p4w2 p4w6: mov al,not_ready_error p4w2: ret port4_write endp set_up_port1 proc near mov duart_base,uart_base ;porta on slicer call set_up_port ret set_up_port1 endp set_up_port2 proc near mov duart_base,uart_base+10h ;port b on slicer call set_up_port ret set_up_port2 endp set_up_port3 proc near mov duart_base,uart_base2 ;porta expansion call set_up_port ret set_up_port3 endp set_up_port4 proc near mov duart_base,uart_base2+10h ;portb expansion call set_up_port ret set_up_port4 endp ; ; bl contains setup info as given in newcall.asm ; routine called from there set_up_port proc near mov dx,duart_base add dx,4 mov al,1ah out dx,al ;reset mr pointer disable rx tx mov al,2ah out dx,al mov al,3ah out dx,al ;port now reset & disabled ;set mr1 character length and parity mov bh,bl and bh,03 ;  number of bits per char correct test bl,8 jz no_parity or bh,8 ;force parity jmp set_parity no_parity: or bh,10h ;no parity jmp setmr1 set_parity: test bl,10h jnz setmr1 ;even leave bit set to 0 or bh,4 ;set odd parity bit setmr1: mov dx,duart_base in al,dx and al,0e0h ;save rx control, rx int, err mode or bh,al mov al,10h mov dx,duart_base add dx,4 out dx,al ;reset mr pointer mov al,bh ; new mr1 mov dx,duart_base out dx,al ;set new mr1 ;now set stop bits test bl,4 jz one_stop mov bh,0fh ;two stop bits jmp setmr2 one_stop: mov bh,7 setmr2: in al,dx and al,0f0h or al,bh out dx,al ;set baud rate xor bh,bh shr bl,5 push ds mov ax,cs mov ds,ax mov si,offset baud_table add bx,si mov bl,[bx] pop ds mov dx,duart_base add dx,2 mov al,bl out dx,al ;set baud rate ;enable communications mov dx,duart_base add dx,4  mov al,15h out dx,al ret baud_table db 11h,22h,44h,55h,66h,88h,99h,0bbh set_up_port endp ibm_com1_init proc near push bx push cx mov bx,offset ser_addr mov cx,8 com1_init1: mov word ptr [bx],0 ;init 40:0-40:f add bx,2 ;as IBM would loop com1_init1 mov dx,modem_control ;modem control reg mov al,0Bh out dx,al mov dx,line_control ;7bits/word no parity dlab=1 mov al,82h out dx,al mov dx,modem_control in al,dx cmp al,0Bh  jz tst_com1 jmp no_com1 tst_com1: mov dx,line_control in al,dx cmp al,82h jnz no_com1 ;THERE IS A IBM SERIAL CARD INITIALIZE or equip_flag,200h ;com1 is present mov ser_addr,3f8h mov ax,0ch mov dx,divisor_latchl ;divisor latch out dx,al ;9600 baud mov al,0 mov dx,divisor_latchm out dx,al mov dx,line_control mov al,3 ;8 bits/char no parity dlab=0 out dx,al mov dx,interrupt_enable mov al,0 ; no interrupts out dx,al  mov dx,sasi_stat_port+1 in al,dx ;REV D BOARD and al,3 ;INTERRUPT NOT SUPPORTED cmp al,2 jnz no_com1 ;don't steal interrupt mov dx,0ff3eh ;disable int3 mov ax,0fh out dx,ax mov dx,88h ;acr & IPCR register on 2681 in al,dx in al,dx or al,4 out dx,al mov dx,8ah ; INTERRUPT MASK ON 2681 mov al,0a2h out dx,al push es mov ax,0 mov es,ax push si mov si,offset bomb_c mov bx,30h mov ax,es:[bx] cmp ax,si jnz ex_present mov es:[bx],7ffdh ;IRET INSTUCTION ex_present: pop si mov bx,3ch ;int3 vector mov dx,offset ibm_com_int mov ax,cs ;reset vector for int3 mov es:[bx],dx mov es:[bx+2],ax pop es mov dx,0ff3eh mov ax,14h ;enable int3 out dx,ax no_com1: pop cx pop bx ret ibm_com1_init endp ibmb_table dw 417h ;110 dw 300h ;150 dw 180h ;300 dw 0c0h ;600 dw 60h ;1200 dw 30h ;2400 dw 18h ;4800 dw 0ch ;9600 command dw receive dw send dw in_status dw out_status dw bad_command dw init_ibm_port ibm_serial proc far push ds push ax mov ax,cs mov ds,ax pop ax cmp al,5 ja bad_command push cx mov di,offset command push bx mov bl,al xor bh,bh shl bx,1 add di,bx jmp word ptr [di] exit: pop bx sub bx,cx mov cx,bx ;characters sent al last char sent xor bl,bl ;for printer status bad_command: pop ds ret ibm_serial endp init_ibm_port: pop bx mov cl,bl mov al,cl and cl,0e0h shr cl,4 xor ch,ch and al,1fh or al,80h ;set dlab = 1 mov dx,line_control out dx,al ;set parity and word length mov bx,offset ibmb_table add bx,cx mov ax,[bx] mov dx,divisor_latchl out dx,ax ;set baud rate mov dx,line_control in al,dx and al,7fh out dx,al ;set dlab = 0 mov dx,interrupt_enable xor al,al out dx,al pop cx push cx jmp exit send: pop bx send1: mov dx,modem_control mov al,1 out dx,al mov dx,modem_status mov bl,10h mov di,offset cts push di jmp t_out cts: mov dx,line_status mov bl,20h mov di,offset trans_ready push di jmp t_out trans_ready: mov dx,transmitter_holding lods byte ptr es:[si] out dx,al loop send1 jmp exit receive: pop bx receive1: mov dx,modem_control mov al,3 out dx,al mov dx,line_status in al,dx test al,1 jnz get_char jmp receive1 get_char: mov dx  ,receiver_buffer in al,dx mov es:[si],al inc si loop receive1 xor al,al ;status on charatcer writes jmp exit out_status: pop bx mov dx,line_status in al,dx test al,20h ;test trans holding 1 = empty jz not_r xor al,al not_r: jmp exit in_status: pop bx mov dx,line_status in al,dx test al,1 jnz rdy mov al,80h jmp exit rdy: mov al,0 jmp exit t_out proc near push cx xor cx,cx wait1: in al,dx test al,bl jnz got_it loop wait1 pop cx pop bx mov al,80 jmp exit got_it: pop cx ret t_out endp check_8087 proc near push bx mov bx,offset area mov w [bx],0 ;set resslt of test to zero mov w [bx+2],0 mov bx,offset radius mov w [bx],56419 mov w [bx+2],0 mov bx,offset scale mov w [bx],10000 mov w [bx+2],0 finit ;initialize 8087 fldpi ;load pi on stack fild scale ;scale factor fild radius fdiv 1 ;radius/scale fmul 0 ;square it fmul 2 ;multiply by pi  fst area ;store it in test result area mov bx,area or bx,bx jz no_8087 or equip_flag,2 ;8087 present cmp bx,13h jz good1 call bad8087 jmp short no_8087 good1: mov bx,area+2 cmp bx,42c8h jz good2 call bad8087 jmp short no_8087 good2: call g8087 no_8087: pop bx ret check_8087 endp badmess db '8087 gave bad answer',0dh,0ah db ' ' goodmess db '8087 present and working',0dh,0ah db 'bring her up to warp speed Scotty',0dh,0ah db ' ' bad8087 proc near pusha push es mov si,offset badmess mov ax,cs mov es,ax mov cx,23 mov ax,601h int 0f8h pop es popa ret bad8087 endp g8087 proc near pusha push es set vector_2,dummy_int ;NMI mov ax,0 mov es,ax mov dx,0a0h ;NMI mask register mov al,80h out dx,al ;enable NMI interrupts mov si,offset goodmess mov ax,cs mov es,ax mov cx,62 mov ax,601h int 0f8h pop es popa ret g8087 endp ;---------------------------------------------------------------- ; Serial port interupt ; Gets charecter from uart and puts it in the appropriate buffer. ;---------------------------------------------------------------- ;SLICER BOARD INTERRUPT SERVICE ROUTINE ibm_com_int proc far push dx push ax mov dx,88h ;change port register on port 1 in al,dx test al,4 ;check input pin ip2 jz not_ibm_com pop ax ;it is ibm com 1 interrupt pop dx sti int 0ch ;do ibm com 1 interrupt push dx push ax mov dx,3fch in al,dx or al,8 out dx,al mov dx,0ff22h mov ax,8000h out dx,ax pop ax pop dx iret not_ibm_com: pop ax pop dx ibm_com_int endp com_int proc far sti push ax push bx push dx push ds mov ax,data mov ds,ax mov dx,stat_rega in al,dx test al,rx_rdy ;was it porta on slicer jz com_int_8 ;if not check portb ; mov dx,rx_rega in al,dx ;input char from porta test com_hold,1 ;was last char xoff jz com_int_7 ;if not jump and com_hold,not 1 ;if so clear hold this int jmp com_int_8 ;go check portb com_int_7: test com_hold_enable,1 ;are we looking for xoff on this port jz com_int_6 ;jump if not cmp al,xoff ;was char xoff jne com_int_6 or com_hold,1 ;yes set hold this port jmp com_int_8 ;go check portb com_int_6: mov bl,port1_head ;not xoff save char in buffer xor bh,bh mov port1_buf[bx],al inc bl and bl,0fh mov port1_head,bl ;update buffer pointer com_int_9: test com_flags,com1_waiting jz com_int_8 mov ax,102h ;set flag 2 int concurrent_int and com_flags,not com1_waiting com_int_8: mov dx,stat_regb ;same as port a in al,dx test al,rx_rdy jz com_int_91 ; mov dx,rx_regb in al,dx ; test com_hold,10b jz com_int_17 and com_hold,not 10b jmp com_int_91 com_int_17: test com_hold_enable,10b jz com_int_16 cmp al,xoff jne com_int_16 or com_hold,10b jmp com_int_91 com_int_16: mov bl,port2_head xor bh,bh mov port2_buf[bx],al inc bl and bl,0fh mov port2_head,bl com_int_19: test com_flags,com2_waiting jz com_int_91 mov ax,103h ;set flag 3; int concurrent_int and com_flags,not com2_waiting com_int_91: mov dx,eoi_reg mov ax,eoi_cmd cli out dx,ax mov dx,is_reg in ax,dx and ax,int_is_mask or ax,ax jz com_int_92 ; pop ds pop dx pop bx pop ax iret com_int_92: pop ds pop dx pop bx mov ax,300h int concurrent_int ;  pop ax/iret com_int endp ; EXPANSION BOARD SERIAL INTERRUPT SERVIVE ROUTINE com2_int proc far sti push ax push bx push dx push ds mov ax,data mov ds,ax mov dx,stat_reg2a in al,dx test al,rx_rdy jz com2_int_8 ;go check port b on 2681 ; mov dx,rx_reg2a in al,dx ;input char from port a 2681 test com_hold,100b ;was last char xoff jz com2_int_7 and com_hold,not 100b ;it was xoff disasble hold jmp com2_int_8 ;go check next port com2_int_7: test com_hold_enable,100b ;are we looking for xoff on this port jz com2_int_6 cmp al,xoff ;is character xoff jne com2_int_6 or com_hold,100b ;yes set hold this port jmp com2_int_8 ;go check next port com2_int_6: mov bl,port3_head ;put char in port 3 buffer xor bh,bh mov port3_buf[bx],al inc bl and bl,0fh mov port3_head,bl ;adjust circular buffer com2_int_9: test com_flags,com3_waiting jz com2_int_8 mov ax,104h ;set flag 4; int concurrent_int and com_flags,not com3_waiting com2_int_8: mov dx,stat_reg2b in al,dx test al,rx_rdy jz com2_int_93 ;go check sio chip ; mov dx,rx_reg2b in al,dx ;get char port b 2681 ; test com_hold,1000b jz com2_int_17 and com_hold,not 1000b jmp com2_int_91 com2_int_17: test com_hold_enable,1000b jz com2_int_16 cmp al,xoff jne com2_int_16 or com_hold,1000b jmp com2_int_91 com2_int_16: mov bl,port4_head ;put char in buffer xor bh,bh mov port4_buf[bx],al inc bl and bl,0fh mov port4_head,bl ; move head to next byte in buffer com2_int_19: test com_flags,com4_waiting jz com2_int_91 mov ax,105h ;set flag 5; int concurrent_int and com_flags,not com4_waiting com2_int_91: ;check for Z8530 ready com2_int_93: mov dx,eoi_reg ;END OF INTERRUPT mov ax,eoi_cmd cli out dx,ax mov dx,is_reg in ax,dx and ax,int_is_mask or ax,ax jz com2_int_92 ; pop ds pop dx pop bx pop ax iret com2_int_92: pop ds pop dx pop bx mov ax,300h int concurrent_int ;pop ax/iret com2_int endp subttl Timer page + ;---------------------------------------------------------------- ; Timer interupt ; Increments time of day counters. Decrements time_out counters. ; Turns off disk Drives ;---------------------------------------------------------------- timer proc far sti push ax push dx mov dx,is_reg ;check if interupt came from the in ax,dx ;timer if it didn't pass it to an test ax,timer_int_mask ;auxiliary handler. jnz t1 pop dx pop ax int aux_int13_int ret 2 t1: push ds mov ax,data mov ds,ax add hundredth,2 inc ibm_timer_cnt cmp ibm_timer_cnt,3 jl t5 mov ibm_timer_cnt,0 int ibm_timer0_int t5: cmp hundredth,100 jl timer_cont17 mov hundredth,0 inc seconds cmp seconds,60 jl timer_cont17 mov seconds,0 inc min cmp min,60 jl timer_cont17 mov min,0 inc hours cmp hours,24 jl timer_cont17 mov hours,0 inc day timer_cont17: test disk_flags,disk_in_service jnz timer_cont19 cmp motor_count1,0 je timer_cont18 dec motor_count1 jnz timer_cont18 call motor_off call deselect timer_cont18: cmp select_count1,0 jz t2 dec select_count1 jnz t2 call deselect jmp t2 timer_cont19: cmp disk_time_out1,0 je t2 dec disk_time_out1 jnz t2 inc disk_time_out1 ;so we can try again if disk can't cli ;be interupted test disk_flags,interuptable ;terminate disk operation if ok jz not_interuptable ;set proper termination address mov disk_time_out1,0 cmp f_state,offset disk_op_end je t3 mov f_state,offset disk_op_22 t3: or diskette_status,time_out mov dx,fdc_command mov al,terminate_wi out dx,al not_interuptable: sti t2: test disk_flags,sasi_in_service jz timer_end cli cmp hdisk_time_out1,0 je timer_end dec hdisk_time_out1 jnz timer_end or sasi_status,sasi_time_out int dma1_int ;interupt process timer_end: int aux_timer_int mov dx,eoi_reg mov ax,eoi_cmd cli out dx,ax mov dx,is_reg in ax,dx and ax,int_is_mask or ax,ax jz t4 ;interupts not nested pop ds pop dx pop ax dummy_int: iret t4: pop ds pop dx mov ax,300h int concurrent_int ;pop ax/ iret timer endp subttl Floppy Disk I/O page + ;---------------------------------------------------------------- ; Floppy disk I/O ; destroys ax, bx, cx, and dx al  l others unchanged. ; interupt driven to run concurrently with other programs ; ;---------------------------------------------------------------- ds0 dw 010ah ;drive select addresses ds1 dw 0108h ds2 dw 0106h ds3 dw 0104h drive_mask db 001h db 002h db 004h db 008h db 010h db 020h db 040h db 080h disk_pseudo_int proc far ;so disk opperations can sti cmp al,0c0h jz pseudo_int1 test al,20h ;be intercepted by MS-DOS 3.2 jz pseudo_int1 ;in the print command this is call disk_write ;interrupt 0fdh Jonathan 10-8-86 jmp short pseudo_intout pseudo_int1: call disk_read pseudo_intout: ret 2 disk_pseudo_int endp cal_address proc near ;es:bx -> ax = high 4 bits bx = low 16 bits mov ax,es mov dx,ax shl dx,4 shr ax,12 add bx,dx adc ax,0 ret cal_address endp ; disk_reset proc near and disk_flags,not fop_waiting disk_reset1: mov recal_required,0ffh mov dx,fdc_command mov al,terminate_ni out dx,al mov diskette_status,0 ret disk_reset endp ; disk_read proc near ;general pourpose read. pop f_return ;command in al es:bx->data ;save return address and disk_flags,not f_nest disk_read1: mov fdc_cmd,al ;entry point for composite commands mov al,head_number and al,1 shl al,1 or fdc_cmd,al call cal_address mov dx,dma_dh0 out dx,ax mov dx,dma_dl0 mov ax,bx out dx,ax xor ax,ax mov dx,dma_sh0 out dx,ax mov ax,fdc_data mov dx,dma_sl0  out dx,ax mov f_dma_cmd,dma_read and disk_flags,not write_status jmp disk_op disk_read endp disk_write proc near ;general pourpose write command pop f_return ;command in al es:bx->data ;save return address and disk_flags,not f_nest disk_write1: mov fdc_cmd,al ;entry point for composite commands mov al,head_number and al,1 shl al,1 or fdc_cmd,al call cal_address mov dx,dma_sh0 out dx,ax mov dx,dma_sl0 mov ax,bx out dx,ax xor ax,ax mov dx,dma_dh0 out dx,ax mov ax,fdc_data mov dx,dma_dl0 out dx,ax mov f_dma_cmd,dma_write or disk_flags,write_status ; jmp disk_op disk_write endp ; disk_op proc near mov dx,fdc_command mov al,terminate_ni out dx,al mov cx,10 ;must delay 10us before reading status reg do13: loop do13 mov dx,fdc_status in al,dx ;reset fdc mov dx,int1_int_cr ;enable fdc interupts disable others mov ax,int1_int_cw out dx,ax ; mov dx,0ff2ah ; mask ; mov ax,1 ; out dx,ax ;---------------------------------------------------------------- ;preform command in bl at specified location. DMA cmd in di ;---------------------------------------------------------------- cli ;has to run with out interuption or disk_flags,disk_in_service ;until first wait so it will not and disk_flags,not interuptable mov ax,disk_time_out ;time out if it is prempted mov disk_time_out1,ax mov diskette_status,0 cmp num_of_sectors,0 jnz disk_op_15 jmp disk_op_end disk_op_15: call motor_on mov bl,drive_number ;recal if needed xor bh,bh call drive_select mov al,disk_track test d_type_0[bx],double_track jz disk_op_16 shl al,1 disk_op_16: mov drive_track,al mov al,drive_mask[bx] test recal_required,al jz no_recal jmp restore ;---------------------------------------------------------------- ; seek to current track ;---------------------------------------------------------------- no_recal: mov bl,drive_number xor bh,bh mov al,track_0[bx] mov dx,fdc_track out dx,al cmp al,drive_track ;already there ? je no_seek mov al,drive_track ;save where we will be. mov track_0[bx],al jmp seek ;seek to new track only ;if needed ;---------------------------------------------------------------- ; ok, now we are over the right track. ; perform desired operations. ;---------------------------------------------------------------- no_seek: mov f_state,offset disk_op_done mov bl,drive_number xor bh,bh mov dx,mini_sel ;switch to 5" or 8" mode mov al,1 test d_type_0[bx],mini jnz is_mini mov al,0 is_mini: out dx,al mov dx,dbl_den_sel mov al,1 test d_type_0[bx],double_density jz not_dbl_den mov al,0 not_dbl_den: out dx,al mov cl,d_type_0[bx] and cl,sector_size_m shr cl,2 mov ax,80h shl ax,cl mov sector_size,ax call wait_fdc_ready mov dx,fdc_track mov al,disk_track out dx,al mov dx,fdc_sector mov al,sector_number    out dx,al mov al,num_of_sectors xor ah,ah mul sector_size mov dx,dma_tc0 out dx,ax mov ax,f_dma_cmd mov dx,dma_cr0 out dx,ax mov al,fdc_cmd mov dx,fdc_command cli out dx,al jmp wait_done ;wait for operation to finish disk_op_done: mov dx,dma_tc0 ;compleation entry point in ax,dx xor dx,dx div sector_size or dx,dx jz disk_op_21 inc al disk_op_21: sub num_of_sectors,al ;number of sectors transfered jmp short disk_op_23 ;---------------------------------------------------------------- ; test error codes ;---------------------------------------------------------------- disk_op_22: mov num_of_sectors,0 ;alternate compleation entry point disk_op_23: mov al,temp ;fdc status into al test disk_flags,write_status jz j9 ;only set for write operations test al,40h jz j9 or diskette_status,write_protect j9: test al,001000b jz j6 or diskette_status,bad_crc j6: test al,80h jz j8 or diskette_status,time_out j8: test al,10h jz disk_op_end or diskette_status,record_not_fnd disk_op_end: and disk_flags,not disk_in_service mov disk_time_out1,0 mov dx,int1_int_cr mov ax,(int1_int_cw or 8) ;disable fdc interupts out dx,ax ; mov dx,0ff2ah ;unmask keyboard if present ; mov ax,6h ;interrupts ; out dx,ax ;no_keyboard: jmp [f_return] disk_op endp ;---------------------------------------------------------------- ; DMA interupt handler. ; Disables DMA transfers, interupts FDC, and returns ;---------------------------------------------------------------- int_dma0 proc far push ax push dx push ds mov ax,data mov ds,ax mov dx,dma_cr0 mov ax,disable_dma out dx,ax ;delay added 7/12/84 00:54:23 JPS push cx ;delay insures 192 us. delay so crc bytes mov cx,90 ;can be written self: loop self pop cx ; mov dx,fdc_command mov al,terminate_wi out dx,al mov dx,eoi_reg mov ax,eoi_cmd out dx,ax pop ds pop dx pop ax iret int_dma0 endp ;---------------------------------------------------------------- ;FDC interupt handler. ; Gets status into temp, enables FDC, disables DMA, and starts ; the next phase of the disk operation. If the operation is finished ; does a set flag call and return through the flag wait return. ;---------------------------------------------------------------- int_fdc proc far push ax push bx push cx push dx push ds mov dx,fdc_status in al,dx mov cl,al ;save status in cl mov dx,fdc_command mov al,terminate_ni out dx,al mov ax,data mov ds,ax ;must read status again to clear interrupt mov temp,cl ;save original status in temp mov cx,29 ;must delay 56us before reading status reg if13: loop if13 mov dx,fdc_status in al,dx mov dx,dma_cr0 mov ax,disable_dma out dx,ax mov dx,eoi_reg mov ax,eoi_cmd out dx,ax and disk_flags,not interuptable simulate_fdc_int: test disk_flags,f_nest jnz if1 cmp f_state,offset disk_op_done je if2 cmp f_state,offset disk_op_22 jne if1 if2: and disk_flags,not fop_waiting mov ax,100h int concurrent_int ;set flag 0 mov dx,is_reg in ax,dx and ax,int_is_mask or ax,ax jz wd1 ;interupts not nested pop ds pop dx pop cx pop bx mov ax,300h int concurrent_int ;pop ax iret ; if1: sti jmp [f_state] ;start next phase of disk op ; wd1: pop ds pop dx pop cx pop bx pop ax iret int_fdc endp ;---------------------------------------------------------------- ; Wait done checks to see if a floppy operation is in progress. ; If it is it does a return from interupt sequence. If it is not ; it does a wait flag call. ;---------------------------------------------------------------- wait_done proc near ;interupts disabled on entry or disk_flags,interuptable ;allow disk time out to happen test disk_flags,fop_waiting jnz wd1 ;wd1 is in int_fdc or disk_flags,fop_waiting sti mov ax,0 ;wait for flag 0  int concurrent_int jmp [f_state] ;has termination address wait_done endp wait_fdc_ready proc near mov dx,fdc_status busy_loop: in al,dx test al,1 jnz busy_loop ret wait_fdc_ready endp ;---------------------------------------------------------------- ; Restore R/W head to track 0 ;---------------------------------------------------------------- restore proc near ;si has drive # mov f_state,offset r1 call wait_fdc_ready mov dx,mini_sel ;switch to 8" mode to enable   3ms mov al,0 ;step time. out dx,al ; mov dx,fdc_command mov al,d_type_0[bx] and al,step_rate_m or al,restore_cmd cli out dx,al jmp wait_done ; r1: mov al,temp test al,0100b jnz r2 or diskette_status,bad_seek mov f_state,offset disk_op_22 jmp simulate_fdc_int r2: ;CHANGED BY JONATHAN 5/21/86 mov bl,drive_number xor bh,bh mov al,drive_mask[bx] not al and recal_required,bl mov track_0[bx],0 ;current track number. jmp no_recal restore endp ;---------------------------------------------------------------- ; Seeks R/W heads to track in al ;---------------------------------------------------------------- seek proc near ;al has new track # si has drive mov f_state,offset no_seek push ax call wait_fdc_ready mov dx,mini_sel ;switch to 8" mode to enable 3ms mov al,0 ;step time. out dx,al ; mov dx,fdc_data pop ax out dx,al mov dx,fdc_command mov al,d_type_0[bx] and al,step_rate_m or al,seek_cmd cli out dx,al jmp wait_done seek endp ;---------------------------------------------------------------- ; Turn on disk motors. ;---------------------------------------------------------------- motor_on proc near mov ax,motor_count mov motor_count1,ax mov al,motor_ctl out sio_out_clr,al test settle,80h ;is motor on jnz motor_go ;jump if on push cx mov cx,spin_up motor_lp: nop ;about 4 tenth of a second nop ; if cx = ffff like on boot nop nop nop nop nop nop nop loop motor_lp ;might want concourent interrupt or settle,80h ;no spin up until after motor off pop cx motor_go: ret motor_on endp ;---------------------------------------------------------------- ; Turn off disk motors. ;---------------------------------------------------------------- motor_off proc near mov al,motor_ctl out sio_out_set,al and settle,7fh ;reset to spin up next time  ret motor_off endp ;---------------------------------------------------------------- ; Select disk drive (disk number in bx). ;---------------------------------------------------------------- drive_select proc near mov ax,select_count mov select_count1,ax call deselect shl bx,1 mov dx,ds0[bx] shr bx,1 mov al,1 out dx,al ret drive_select endp ;---------------------------------------------------------------- ; Deselect all disk drives. ;---------------------------------------------------------------- deselect proc near mov al,0 mov dx,ds0 out dx,al mov dx,ds1 out dx,al mov dx,ds2 out dx,al mov dx,ds3 out dx,al ret deselect endp subttl Hard Disk I/O page + ;------------------------------------------------------------- ; Sasi I/O ; ah=0 reset system ; ah=1 read blocks into memory ; ah=2 write blocks from memory ; bp:si=command block ; es:bx=data blocks ; cx=block count ; dx=block size ; ;************************************************************** ; RETURNS ; ; al=status ; 0=no error ; 1=op error (error occoured during operation) ; 2=fatal error (controler out of sync) ; ff=time out ; cx=number of blocks xfered ; ; ; ;------------------------------------------------------------ sasi_io proc near pop sasi_return ;save return address and disk_flags,not sasi_nest sasi_io1: mov sasi_xfer_count,cx mov sasi_xfer_count1,cx mov sasi_cmd,ah or ah,ah jnz sio1 call hd_reset and disk_flags,not sop_waiting jmp sio_end1 sio1: call hd_select or al,al jz sio2 mov al,0ffh ;time out has occoured or sasi_status,time_out xor cx,cx jmp sio_end1 sio2: mov sasi_status,0 mov sasi_block_size,dx mov ax,es ;adjusts es:bx for no wraparound mov dx,bx and bx,0fh shr dx,4 add ax,dx mov sasi_es_temp,ax mov sasi_bx_temp,bx mov sasi_bp_temp,bp mov sasi_si_temp,si mov ax,0ffffh ;dummy address mov dx,dma_dh1 out dx,ax mov dx,dma_dl1 out dx,ax mov dx,dma_sh1 out dx,ax mov dx,dma_sl1 out dx,ax mov dx,dma_tc1 mov ax,1 cli out dx,ax ;count of 1 to interupt on first ;request mov dx,dma_cr1 mov s_state,offset send_command mov ax,hdisk_time_out mov hdisk_time_out1,ax mov ax,sasi_dma or disk_flags,sasi_in_service out dx,ax test disk_flags,sop_waiting jz sio4 jmp si2 ;already waiting must be n  ested operation ;restore registers and iret sio4: or disk_flags,sop_waiting mov ax,1 int concurrent_int ;wait for flag 1 jmp sio16 ;exit sio send_command: cld mov es,sasi_bp_temp ;setup segment from bp mov si,sasi_si_temp mov cx,6 sc_loop: mov dx,sasi_stat_port in ax,dx test ax,request jz sc_loop ;wait for request and ax,status_mask cmp ax,command_block1 je sc1 or sasi_status,fatal_error jmp sc_end sc1: lods b es:[si] mov dx,sasi_data_port out dx,al loop sc_loop sc_end: cmp sasi_xfer_count1,0 jne sio13 ;no transfers jmp sio5 sio13: mov al,sasi_cmd dec al jz sasi_read dec al jz sasi_write mov sasi_xfer_count1,0 mov sasi_xfer_count,0 or sasi_status,fatal_error jmp sio_end1 sasi_read: mov dx,dma_tc1 mov ax,1 cli out dx,ax ;count of 1 to interupt on first ;request mov dx,dma_cr1 mov s_state,offset sio6 mov ax,sasi_dma out dx,ax jmp si2 ;wait for interupt sio6: mov di,sasi_bx_temp ;interupt activated mov es,sasi_es_temp mov cx,sasi_block_size sasi_read_loop: mov dx,sasi_stat_port in ax,dx test ax,request jz sasi_read_loop and ax,status_mask cmp ax,data_block_to jne sio5 mov dx,sasi_data_port ins b [di],dx loop sasi_read_loop mov sasi_bx_temp,di dec sasi_xfer_count jz sio5 jmp sasi_read sasi_write: mov dx,dma_tc1 mov ax,1 cli out dx,ax ;count of 1 to interupt on first ;request  mov dx,dma_cr1 mov s_state,offset sio66 mov ax,sasi_dma out dx,ax jmp si2 ;wait for interupt sio66: mov si,sasi_bx_temp ;interupt activated mov es,sasi_es_temp mov cx,sasi_block_size sasi_write_loop: mov dx,sasi_stat_port in ax,dx test ax,request jz sasi_write_loop and ax,status_mask cmp ax,data_block_fro jne sio5 mov dx,sasi_data_port outs dx,b es:[si] loop sasi_write_loop mov sasi_bx_temp,si dec sasi_xfer_count jz sio5 jmp sasi_write  sio5: mov dx,dma_tc1 mov ax,1 cli out dx,ax ;count of 1 to interupt on first ;request mov dx,dma_cr1 mov s_state,offset sio55 mov ax,sasi_dma out dx,ax jmp si2 ;wait for interupt sio55: call hd_wait_req ;finish hand shaking and ax,status_mask cmp ax,status_byte je sio11 or sasi_status,fatal_error jmp short sio_end sio11: mov dx,sasi_data_port in al,dx test al,010b jz sio12 or sasi_status,non_fatal_error sio12: mov dx,dma_tc1 mov ax,1 cli out dx,ax ;count of 1 to interupt on first ;request mov dx,dma_cr1 mov s_state,offset sio122 mov ax,sasi_dma out dx,ax jmp si2 ;wait for interupt sio122: call hd_wait_req and ax,status_mask cmp ax,message_byte je sio14 or sasi_status,fatal_error jmp short sio_end sio14: mov dx,sasi_data_port in al,dx sio_end: call hd_deselect test disk_flags,sasi_nest jnz sio16 and disk_flags,not sop_waiting mov ax,101h int concurrent_int ;set flag 1 jmp si5 sio16: mov cx,sasi_xfer_count1 sub cx,sasi_xfer_count sio_end1: and disk_flags,not sasi_in_service mov al,sasi_status jmp [sasi_return] sasi_io endp ;---------------------------------------------------------------- ; DMA1 Interupt ; disables dma1 sets sop_waiting ;---------------------------------------------------------------- int_dma1 proc far sti cld push ax push bx push cx push dx push si push bp push es push ds mov ax,data  mov ds,ax mov dx,dma_cr1 mov ax,disable_dma out dx,ax mov dx,is_reg in ax,dx test ax,dma1_int_mask jz simulate_sasi_int ;must have timed out mov dx,eoi_reg mov ax,eoi_cmd out dx,ax simulate_sasi_int: cmp sasi_status,0ffh jne si6 call hd_reset jmp sio16 si6: jmp s_state ; ; si5: mov dx,is_reg in ax,dx and ax,int_is_mask or ax,ax jnz si2 ;nested int just do an iret pop ds pop es pop bp pop si pop dx pop cx pop bx mov ax,300h int concurrent_int ;pop ax iret ; si2: pop ds pop es pop bp pop si pop dx pop cx pop bx pop ax iret int_dma1 endp hd_reset proc near call hd_deselect mov dx,sasi_reset_port mov al,0 out dx,al mov al,0ffh out dx,al mov dx,dma_cr1 mov ax,disable_dma out dx,ax ret hd_reset endp hd_wait_req proc near mov dx,sasi_stat_port in ax,dx test ax,request jz hd_wait_req ret hd_wait_req endp hd_select proc near push dx    push cx push ax mov ax,0001h mov dx,sasi_stat_port out dx,ax mov al,0 mov dx,sasi_sel_port out dx,al mov dx,sasi_stat_port mov cx,1000 sel_loop: in ax,dx test ax,selected loopz sel_loop pop ax xor al,al or cx,cx jnz hds1 mov al,sasi_time_out hds1: pop cx pop dx ret hd_select endp hd_deselect proc near mov al,0ffh mov dx,sasi_sel_port out dx,al ret hd_deselect endp code ends end zRECOVER COM uS!bios.obj: bios.asm biosdata.asm masm bios; ibmbios.obj: ibmbios.asm biosdata.asm masm ibmbios; newcall.obj: newcall.asm biosdata.asm masm newcall; oldcall.obj: oldcall.asm biosdata.asm masm oldcall; newvideo.obj: newvideo.asm biosdata.asm tables.asm masm newvideo; newkey.obj: newkey.asm biosdata.asm masm newkey; bomb.obj: bomb.asm biosdata.asm masm bomb; sprn.obj: sprn.asm biosdata.asm masm sprn; dbg.obj: dbg.asm biosdata.asm masm dbg; ibmprn.obj: ibmprn.asm biosdata.asm masm ibmprn; memtest.obj: memtest.asm biosdata.asm masm memtest; reset.bin: reset.asm masm reset; link reset; exe2bin reset command /c erase reset.exe bios.bin: bios.obj ibmbios.obj newcall.obj oldcall.obj newvideo.obj newkey.obj bomb.obj sprn.obj dbg.obj memtest.obj link bios+ibmbios+newcall+oldcall+newvideo+newkey+sprn+bomb+dbg+memtest+ibmprn,,bios/m; exe3bin bios.exe bios.bin 0f800 command /c erase bios.exe epbios.bin: reset.bin bios.bin biosadj command /c erase bios.bin  @`! #@%`')+-/1 3@5`79;=?A C@EGIKOQ S@U`WY[_a c@e`gikmoq s@u`wy{@` ` @ o @ ` @ ` ɠ @ ` ׀ ٠  @` O`Aa   !Aa/#%a')+-/1!3A5a79;=/CAGMZ } ظ}м0! u\>|'&,n t>l3u uG>p& 2$F&>}<t<=tA< t< uI3u:2ItF&< t< t GĀ tͺ;3It.F&< t&< t",0|(< $r rrr2r t늺rpہwr'&+u r;w؎ЌQã`d&+vϱË%fhR uZ3P>l>p|&5\&lnڋʃ+6cG6 G&6FG6&P>|L!˴ !>|L!3Pˡ-ື !>|L!ˀ>| FL!-Ur;&wPPEFuPW ]øPP FuP2 ]øPPFu"P ]F vDHDx 0 v؃^ t,F vDHDx 0vv _먋F F =},vDHDx0vP(ɋvDHDx 0 v؃^ t)vDHDx 0vv vvv]U:>: }nv0@H0%tFv0tI::  F<v0Ft@H0%uFߋvFF0u0=|P|PP:0>FtP~P:PfF PP;PPF PPP<F u P~uv PbP6PvvD0%D~ tv P$PIn3Jt3F z^ˠQNx0 %t 0 <P6:3P]U츴F^;sG0tFF=u3]vv v ]UvDt0%t VPovD 0P!塘v\0Fv FFF btatv D0=+t33Cv0^ F F~ t^ ؁PSvF@u3]øP3P3Sv~ tF~ t3^ Sv5F@u3]Â~ tFf~ t^ ؁PSvF@u3]Â~ tF3]=wt=rui=auF*OtNF vDvDFvD D3DDFDƃ]UvD0%t VPvD0% u| t t t)3vDD DD 0P-]U F^hf~i0=}3 ]ËF^^ F3 t3 ]ùF ^S^t3 ]ËF ^fhbËNb)f^hF ]UF 3SPKFt]ø]U 0=}b+^3ۅyKfhZ^F3 t ]ùF^S^zt ]ËF^hf^b3 ]Uv D0%0t]Ëv | uD0%uVt]Ëv D0%tF)v D0%t]Ëv D0 DD Fv D 0vtP?Fyv D0 D~uv D0 DF~ v DDv D0%0t]Ëv DHDx 0 v ؋Ã]U Fv\00Ft ]Ëv| ujD0%u`~u3 ]vt ]ËvD0 DD DHDx^0 vvv؋à ]ËvD0%t8~u3 ]ËFv\ 0F v NQSFFFvD0%t ]ËvD0 D~t2|~,DHDx^0 vvFv+DF tD 0v tPhFF~uvD0 DF;F tvD0 DvD DDF=t \K\x 0 vvCvD0%0t ]Ã~u3 ]ËF ]Uv| tD0%u3]6N vDu ]ávD D0%D3DD]Uv F 0Ft)Kۉx60ԸPvwơHx6 0 P PM]UFv F 0Ft(v\K\x 0 vv FNjF]Uv6~u3]ËvD0%D0 DFDD 3]UVN!s]U^NV?!s3]U^NV@!s3]UF B^NV!s؋]UVA!s]UVFCN!s]U^D!]UV~V!s]3]UFx;L}*N0%u  3]ËF*N]U FFL;~*N0tFߋF;Lu ]ËF*NJ%^3ÉF%v t3 v F%`v 0 @cF%t3 v 0 ؈DF%t3 `v 0 ؈%v  ]=t=t=tۋv0uv DF ]FF=}7 @Pv uF ~ EF ]Fv D0=F%tvF%tF%Pv>v D>t4F%t3Pvv D>t>v  ]ËF%=uv tv  ]ËF ]UF % ^ SPv ]UFy]vyFu]ËvD0F==~FS FF0^;~FFFF0= u Fv #F0=uFFFvF뮸 P F]øF^ F^v0%t-FF;F}FF^؉^VvF]FF;F|VF0 PV PVFF@vv F]Ã~tPV PVPV띸 PV PV3]ËFFvF0= }^PVF0@PVSF0PVE l l .;u.y뛋F]3]à0=~#vvvtF>t]Ëv0%tF]3FF F^;~UFvF08F+FH3ۅyKQSPvvF ]뿋F F vF= t=t~ u ~tIF ]ø]Fm? ?s. UFy]vFu]ËvD0FFFFF^;~6FvF0= uv0%u PVF0PVF]Ëv0%tP3P3SvW0=~4v0%t(vvtF>t]ËF]F3FF F F^;FvF0= uF0= tF NF F@v^=F ^|0=~0v Pvt;F Ft3]Ã>t]F p~ t:0=~0v PvtB;F Ft3]Ã>t  ]ËF]ËF]]dlt s. UvFu ]ËvD0t 33ۃ]à0=~2vvvvtF^>t]Ã~urF Ftjv0%u^F-^F ^ F x33Pv v vM tPFPv/u n ^ ƋF ^ ]ËF^]Uv Fu]3v\0ۉFu0=~t>tFvF]U(0=~v,>t(]3(]Ã(]Uv]UN0=~vTvRN]ÃN]U@BۣDFu]Ë6D3FD3]U3P]UF y]@BF3PSFu]ËF^@BF HF t3PSjt FBC3]UF3ۓ]UF 3SPF^]UF^33=3]ËF^-FË^3ɺD FN^ v~tnvD3ۉFÉ^^NV |A;u;u vvD3+F ^DFF3+F ^^FÃ]ËFF^댹F^ PSHF t@>Bu ^ @B%B@؋F ;É^uB3F ^BF ]3]UF3SPv F^]UF^33]ËF^NF 3ɺ^N ˋF3^оDFNVFvFu\؋N;ȉ^sv FDƋv3]ËF;Fu)~ D3ۋNȋVӉMNjv3]ËF ;FsF3+F^F]ËF ;FuUvt^;vF3+F^F]ËvD3F^Dt^;u GD3]ËF^ FN^ F v3ۋFDÃ]U`+\jV`+rSZJ![r j3]ã]U+\j+Fu!j^rZSJ![r j3]ã]P3XPx+u3;twH XUFF=}P9FF~} vFv v]Uvvo]UPT]UP@]UvP,F]UP]UvPF]UvPF]Uv <t(~=t F F0 0+ˉNt׋]Ëv <t]Ëv<t]3]U~t5v <t-~=t%F F0 0+ˉNt]NŃ~t v <t]Ëv<t]3]UN u33F u33NFyy 333o3v3yڃux ;r+COu3ɋ!;r u;r+COu΋3FtFtڃ]UV !]UvD0%t3]Ëv| tD0%u t t$F vDD0 D3D DD]UfFV!]Lattice C 2.10Invalid stack size $Invalid I/O redirection $Insufficient memory $*** STACK OVERFLOW *** $bios.binrbCan't open Bios.bin. epbios.binwbCan't open Epbios.bin. reset.binCan't open Reset.bin. rwaCan't open stdin file Can't open stdout file con:CON:prn:PRN:lst:LST:lpt:LPT:lpt1:LPT1:aux:AUX:com:COM:com1:COM1:rdr:RDR:pun:PUN:nul:NUL:null:NULL: ((((( H  ((((( H   ;---------------------------------------------------------------- ; Structures ;---------------------------------------------------------------- dpb struc sectors_per_trk db ? number_of_heads db ? dpb ends hdpb struc db 8 dup (?) step_rate db ? hdpb ends ;---------------------------------------------------------------- ; Interupt vector space definition ;---------------------------------------------------------------- vectors segment at 0 vector_0 dd ? vector_1 dd ? vector_2 dd ? vector_3 dd ? vector_4 dd ? vector_5 dd ? vector_6 dd ? vector_7 dd ? vector_8 dd ? vector_9 dd ? vector_a dd ? vector_b dd ? vector_c dd ? vector_d dd ? vector_e dd ? vector_f dd ? vector_10 dd ? vector_11 dd ? vector_12 dd ? vector_13 dd ? vector_14 dd ? vector_15 dd ? vector_16 dd ? vector_17 dd ? vector_18 dd ? vector_19 dd ? vector_1a dd ? vector_1b dd ? vector_1c dd ? vector_1d dd ? vector_1e dd ? vector_1f dd ? org 033h*4 vector_33 dd ? org 03bh*4 vector_3b dd ? org 067h*4 vector_67 dd ? org 0f8h*4 vector_f8 dd ? vector_f9 dd ? vector_fa dd ? vector_fb dd ? vector_fc dd ? vector_fd dd ? vector_fe dd ? vector_ff dd ? kludge label word kludge1 label word org 7c00h ibm_boot label far vectors ends ;---------------------------------------------------------------- ; Data for BIOS ;---------------------------------------------------------------- data segment at 40h ser_addr dw 4 dup(?) pport_addr dw 4 dup(?) equip_flag dw ? function_cmd db ? org 13h memory_size dw ? old_temp_char label byte ibm_temp_char db ? nd_error_flag db ? org 17h shift_status db 0 shift_status1 db 0 alt_input db 0 buffer_head dw 0 buffer_tail dw 0 kb_buffer dw 10h dup (0) ;buffer kb_buffer_end label word nd_sector_count dw ? dpb0 dpb <,> dpb1 dpb <,> dpb2 dpb <,> dpb3 dpb <,> temp db ? ;status after fdc_int org 49h crt_mode db ? ;current mode num_columns db ? ;number of columns for mode db ? page_size dw ? ;page size in bytes for mode buffer_seg dw ? ;segment of current video buffer cursor_posn dw 8 dup (?) ;position for each of 8 pages cursor_mode dw ? ;start and stop line of cursor cur_page db ? ;current page adr_6845 dw ? ;address of current video board crt_mode_set db ? crt_pallette db ? page_seg dw ? ;segment of current video page temp_ax dw ? com_flags db ? com_hold db ? com_hold_enable db ? com1_int_status db ? com2_int_status db ? sector_size dw ? ;sector size in bytes for current transfer d_type_0 db ? ;definition of disk in each drive d_type_1 db ? d_type_2 db ? d_type_3 db ? track_0 db ? ;current track for each drive track_1 db ? track_2 db ? track_3 db ? recal_required db ? ;bits 0-3 set to home disk head on each drive diskette_status db ? drive_number db ? head_number db ? drive_track db ? disk_track db ? sector_number db ? num_of_sectors db ? disk_flags db ? ;disk in service, op done, write status fdc_cmd db ? even f_dma_cmd dw ? f_state dw ? f_return dw ? s_state dw ? sasi_return dw ? sasi_block_size dw ? sasi_xfer_count dw ? sasi_xfer_count1 dw ? sasi_bx_temp dw ? sasi_es_temp dw ? sasi_bp_temp dw ? sasi_si_temp dw ? sasi_cmd db ? sasi_status db ? wait_flags db 8 dup (?) ;---------------------------------------------------------------- ; Data for new function dispatcher ;---------------------------------------------------------------- device_numbers dw 20h dup (?) ;high byte is input driver# for the channel ;low byte is output driver# if bit 8 is set ;the driver is external external_limit db ? ;number of external drivers function_ptr dw ? spb struc db 10h dup (?) head db ? tail db ? spb ends org 0eeh ;locations for old monitor memsize dw ? duout db ? duimr db ? settle db ? ;ADDED BY JONATHAN OFFSET 0F2H dskseg dw ? dskmem dw ? dsknum db ? dsktrack dw ? dsksector db ? ;---------------------------------------------------------------- ; more keyboard data ;---------  ------------------------------------------------------- port_status db ? byte_flag db ? key_int_enable db ? reset_location dw ? ;set to 1234 for warm boot port1_buf db 10h dup (?) port1_head db 0 port1_tail db 0 port2_buf db 10h dup (?) port2_head db ? port2_tail db ? port3_buf db 10h dup (?) port3_head db ? port3_tail db ? port4_buf db 10h dup (?) port4_head db ? port4_tail db ? day dw ? day1 dw ? ;for ibm tod call min db ? hours db ? hundredth db ? seconds db ? ;---------------------------------------------------------------- ; terminal emulator data ;---------------------------------------------------------------- vid_temp db ? esc_flag db ? ;---------------------------------------------------------------- ; Data for new disk io ;---------------------------------------------------------------- am_buffer label byte am_track db ? ;address mark buffer for disk io am_side db ? am_sector db ? am_size db ? am_crc db 2 dup (?) hdpb0 hdpb <> hdpb1 hdpb <> hd_command db 6 dup (?) hd_last_drive db ? hd_ax_temp dw ? hd_bx_temp dw ? hd_cx_temp dw ? hd_cx_temp1 dw ? hd_dx_temp dw ? hd_si_temp dw ? hd_es_temp dw ? even hdisk_time_out dw ? hdisk_time_out1 dw ? prn_countl dw ? prn_counth dw ? axsave dw ? bxsave dw ? cxsave dw ? dxsave dw ? bpsave dw ? sisave dw ? disave dw ? spsave dw ? cssave dw ? dssave dw ? sssave dw ? essave dw ? ipsave dw ? fsave dw ? word1 dw ? word2 dw ? seg1 dw ? seg2 dw ? monsp dw ? mem1 dw ? mem2 dw ? mem3 dw ? port1 dw ? break1 dw 3 dup (?) break2 dw 3 dup (?) bits db ? seccnt db ? trksize db ? linbuf db 50h dup (?) motor_count dw ? ;time out value for motor select_count dw ? ;value for select disk_time_out dw ? motor_count1 dw ? ;current time out counts select_count1 dw ? ;this was moved from 40:8 disk_time_out1 dw ? external_table dd ? ;pointer to table of pointers to drivers tty_on db ? ;some bytes needed by jonathan printer_stat db ? spin_up dw ? ;word count duart_base dw ? ;for int 14h key_status2 db ? ;bit 1 ctrl num ibm_timer_cnt db ? bits2 db ? radius dw ? ;three variables for 8087 dw ? ;check out scale dw ? dw ? area dw ? dw ? data ends ;---------------------------------------------------------------- ; Stack for initialization ;---------------------------------------------------------------- stack segment at 064h db 0100h dup (?) stack_top label word stack ends  if2 %out Pass 2. endif .286c page 60,132 name BOMB title Slicer BIOS Version 2.0A (Bomb Routine) ;-------------------------------------------------------------------------------- ; BIOS for the Slicer. (C) Slicer Computers Inc., 1985 ; ; Version 2.0 April 4, 1985 ; By David Daney 1985 ; ; ;-------------------------------------------------------------------------------- subttl Equates page ;---------------------------------------------------------------- ; E Q U A T E S ;---------------------------------------------------------------- b equ byte ptr w equ word ptr subttl Data Areas page + include biosdata.asm subttl Externals and Publics page + ;---------------------------------------------------------------- ; Externals and Publics ;---------------------------------------------------------------- public bomb_init extrn print:near extrn print_al:near,number_table:byte extrn conout2:near  public bomb_0,bomb_c extrn monitor:near extrn bomb:near subttl Initialization Code page + cgroup group code code segment byte public 'code' assume cs:cgroup,ds:data,es:nothing debug proc near mov ax,[bp+22] call print_ax1 mov al,':' mov ah,6 ;console device call conout2 mov ax,[bp+20] call print_ax1 pop es pop ds popa jmp bomb debug endp print_ax1 proc near xchg ah,al call print_al xchg ah,al call print_al ret print_ax1 end   p assume es:vectors bomb_init proc near mov cx,100h xor di,di set_loop: mov ax,offset bomb1 stos w [di] mov ax,seg bomb1 stos w [di] loop set_loop ; set macro num,val mov w num,offset val mov w num+2,seg val endm ; set vector_0,bomb_0 set vector_1,bomb_1 set vector_2,bomb_2 set vector_3,bomb_3 set vector_4,bomb_4 set vector_5,bomb_5 set vector_6,bomb_6 set vector_7,bomb_7 set vector_8,bomb_8 set vector_9,bomb_9 set vector_a,bomb_a set vector_b,bomb_b set vector_c,bomb_c set vector_d,bomb_d set vector_e,bomb_e set vector_f,bomb_f ret assume es:nothing bomb_init endp bomb1 proc far pusha push ds push es mov si,offset gen_bomb_mess call print mov bp,sp les si,[bp+20] ;cs:ip mov dx,es:[si-2] ;should be cd xx mov ax,data mov ds,ax mov es,ax cmp dl,0cdh jne bomb13 mov al,dh shr al,4 mov bx,offset number_table xlat cgroup:number_table push dx mov ah,6 call conout2 pop dx mov al,dh and al,0fh mov bx,offset number_table xlat cgroup:number_table mov ah,6 call conout2 mov si,offset crlf call print jmp debug bomb13: mov si,offset wild_int_mess call print jmp debug bomb1 endp bomb_0 proc far pusha push ds push es mov di,offset bomb_0_mess jmp short bomb_cont bomb_1: pusha push ds push es mov di,offset bomb_1_mess jmp short bomb_cont bomb_2: pusha push ds push es mov di,offset bomb_2_mess jmp short bomb_cont bomb_3: pusha push ds push es mov di,offset bomb_3_mess jmp short bomb_cont bomb_4: pusha push ds push es mov di,offset bomb_4_mess jmp short bomb_cont bomb_5: pusha push ds push es mov di,offset bomb_5_mess jmp short bomb_cont bomb_6: pusha push ds push es mov di,offset bomb_6_mess jmp short bomb_cont bomb_7: pusha push ds push es mov di,offset bomb_7_mess jmp short bomb_cont bomb_8: pusha  push ds push es mov di,offset bomb_8_mess jmp short bomb_cont bomb_9: pusha push ds push es mov di,offset bomb_9_mess jmp short bomb_cont bomb_a: pusha push ds push es mov di,offset bomb_a_mess jmp short bomb_cont bomb_b: pusha push ds push es mov di,offset bomb_b_mess jmp short bomb_cont bomb_c: pusha push ds push es mov di,offset bomb_c_mess jmp short bomb_cont bomb_d: pusha push ds push es mov di,offset bomb_d_mess jmp short bomb_cont bomb_e: pusha push ds push es mov di,offset bomb_e_mess jmp short bomb_cont bomb_f: pusha push ds push es mov di,offset bomb_f_mess bomb_cont: mov ax,data mov ds,ax mov es,ax mov bp,sp mov si,offset gen_bomb_mess push di call print pop di mov si,di call print mov si,offset crlf call print jmp debug bomb_0 endp gen_bomb_mess db 0dh,0ah,"Wild interupt through vector ",0 wild_int_mess db 0dh,0ah,"Wild interupt can't determine vector",0dh,0ah,0 bomb_0_mess db "0",0 bomb_1_mess db "1",0 bomb_2_mess db "2",0 bomb_3_mess db "3",0 bomb_4_mess db "4",0 bomb_5_mess db "5",0 bomb_6_mess db "6",0 bomb_7_mess db "7",0 bomb_8_mess db "8",0 bomb_9_mess db "9",0 bomb_a_mess db "a",0 bomb_b_mess db "b",0 bomb_c_mess db "c",0 bomb_d_mess db "d",0 bomb_e_mess db "e",0 bomb_f_mess db "f",0 crlf db 0dh,0ah,0 code ends end !!#A%a')-//35a79;=?A!CAEaGIKMOQ!SAUa .286c .xlist include biosdata.asm .list ;********************************************************** ;********************************************************** ;********************************************************** ;*** *** ;*** *** ;*** SLICER DEBUGGER I.3 *** ;*** =================== *** ;*** *** ;*** *** ;********************************************************** ;********************************************************** b equ byte ptr w equ word ptr home equ 7 read equ 8 write equ 9 dskcheck equ 11h message equ 14h hexword equ 15h hexbyte equ 16h decdisp equ 17h conout equ 3 conin equ 2 const equ 1 function_call equ 0fbh cr equ 0dh lf equ 0ah bs equ 8 cntl equ 1-'A' brkcode equ 0cch inline equ 1 ; *** INITIALIZATION *** ; ====================== extrn bootstrap1:near,bootstrap2:near,memtest:near extrn old_load:near public monitor,bomb,moninit cgroup group code code segment byte public 'code'   assume cs:cgroup,ds:data,ss:stack,es:nothing MONINIT: mov ax,data mov ds,ax mov bx,message int function_call DB CR,LF,LF,LF,'SLICER Monitor 2.1E-1 SEPT 29, 1987',CR,LF,' ',0 MOV AX,MEMSIZE mov bx,decdisp int function_call mov bx,message int function_call DB 'K RAM installed',0 JMP monitor ;********************************************************** ;*** *** ;*** MONITOR SUBROUTINE *** ;*** *** ;********************************************************** ; *** OUTPUT ROUTINES *** ; ======================= ;Output CR, LF combination to console CRLF: PUSH AX push bx MOV AL,CR mov bx,conout int function_call MOV AL,LF mov bx,conout int function_call pop bx POP AX RET ;Output a space to the console SPACE: PUSH AX push bx MOV AL,' ' mov bx,conout int function_call pop bx POP AX RET ;Erase a character on the console BACKSP: PUSH AX push bx MOV AL,BS mov bx,conout int function_call CALL SPACE mov bx,conout int function_call pop bx POP AX RET REGNAMES DB 'AXBXCXDXBPSIDISPCSDSSSESIPF ' ;Display register name on console. ; AX contains register name, two bytes. ; A space is added. ;In REGOUT0, BX points to register save area REGOUT0: MOV AX,w cs:REGNAMES[BX] REGOUT: PUSH AX push bx mov bx,conout int function_call MOV AL,AH mov bx,conout int function_call CALL SPACE pop bx POP AX RET ;Get users register value.  ;IN: AX=Register name ;OUT: BX=Pointer to register value. REGVALUE: PUSH CX MOV CX,14 xor bx,bx REG0: CMP AX,w cs:regnames[BX] JZ REG2 ADD BX,2 LOOP REG0 STC REG2: POP CX RET ;Print header for register display REGHEAD: CALL CRLF PUSH BX PUSH CX MOV CX,14 ;Number of registers MOV BX,OFFSET REGNAMES ;Names REG4: CALL SPACE ;Get name MOV AX,cs:[BX] CALL REGOUT ;Print it. CALL SPACE ADD BX,2 LOOP REG4 ;And loop. POP CX POP BX RET ;Print register values. REGDISP: CALL CRLF PUSH BX PUSH CX MOV CX,14 ;Number of registers. MOV BX,OFFSET AXSAVE REG5: MOV AX,[BX] ;Display values. push bx mov bx,hexword int function_call pop bx CALL SPACE ADD BX,2 LOOP REG5 POP CX POP BX RET ; *** CONSOLE INPUT *** ; ===================== ;Check for user break ; If no character ready return AL=0,Z,NC ; If control-S then wait for another character ; If control-C then return AL=3,Z,C ; Otherwise return AL=ASCII,NZ,NC CNTLCHK:push bx mov bx,const int function_call pop bx JZ CNT2 push bx mov bx,conin int function_call pop bx CMP AL,CNTL+'S' ;Control S JNZ CNT0 push bx mov bx,conin int function_call pop bx CNT0: CMP AL,CNTL+'C' ;Control-C JC CNT1 JNZ CNT2 AND BITS,NOT INLINE CNT1: CMC CNT2: RET ;Input a line of text from console. BS may be used for ;editing. CR marks the end of the line. Other control ;characters are not allowed. Characters typed pass the ;Maximum line width are ignored. ;IN: CX=Max length (must be less than LEN LINBUF) ;OUT: CX=Length (including CR) ; SI=Pointer to start of line. ;Any routine that takes characters from input can assume ;that SI points to the next character. These routines ;must update SI after using an input character. LININ: AND BITS,NOT INLINE PUSH AX PUSH BX PUSH DI MOV DI,OFFSET LINBUF ;Set DI and SI MOV SI,DI ;to the start of the input ;buffer. MOV BX,CX ;BX holds max length ;CX holds current length LIN0: push bx mov bx,conin int function_call pop bx CMP AL,BS ;Check for BS. JNZ LIN2 CMP CX,BX ;Empty line? JNZ LIN4 LIN1: MOV AL,7 ;If so, ignore it push bx mov bx,conout int function_call pop bx jmp short LIN0 LIN2: CMP AL,CR ;Check for end of line. JZ LIN3 CMP AL,' ' ;Ignore other controls JC LIN1 push bx mov bx,conout int function_call ;Echo character. pop bx LIN3: STOSB ;Put it in buffer LOOPNZ LIN0 JZ LIN5 ;Exit because of CR? MOV AL,7 ;If not, line too long push bx mov bx,conout int function_call pop bx LIN4: DEC DI ;Erase a character INC CX CALL BACKSP jmp short LIN0 LIN5: CALL CRLF ;All done SUB BX,CX ;Compute length MOV CX,BX POP DI POP BX POP AX RET ; *** INPUT PROCESSING *** ; ======================== ;These routines aid in the processing of the command line. ;SI always points to the next character to be processed. ;Registers which do not hold return values are saved. ;Syntax erro   rs in the command line are flagged by setting ;C. ;Convert possible lower case in AL to upper case. UCONVERT: CMP AL,'a' JC UCON0 CMP AL,'z' JA UCON0 SUB AL,20H UCON0: RET ;Convert hex character in AL to binary. HEXCHR: CALL UCONVERT SUB AL,'0' JC HEX1 CMP AL,10 JC HEX0 SUB AL,7 CMP AL,10 JC HEX1 CMP AL,16 HEX0: CMC HEX1: RET ;Convert ascii hex string to binary. If string contains more ;than four digits then only the lowest four are used. String ;ends with comma or CR. Non-hex characters cause errors. ;(/// MAY WANT TO ALLOW SPACES) ;IN: AX=Default value ;OUT: AX=Conversion result HEXSTRING: PUSH BX PUSH DX MOV DX,AX ;Move default MOV BX,0 ;Start with 0 HEX4: shl BX,4 LODSB ;Get next char in string CMP AL,',' ;End of string? JZ HEX6 CMP AL,CR JZ HEX5 CMP AL,' ' JZ HEX5 CALL HEXCHR ;Convert char JC HEX6 ADD BL,AL ;Move char into result MOV DX,BX jmp short HEX4 HEX5: DEC SI ;Do not swallow CR or space HEX6: MOV AX,DX POP DX POP BX RET ;Address strings are in the form SEGMENT:OFFSET where ;SEGMENT and OFFSET are 16 bit hex strings ;SEGMENT can be a segment register. ;IN: AX=Default offset ; BX=Default segment ;OUT: AX=Offset ; BX=Segment ADRSTRING: PUSH DX MOV DX,AX ;Save default offset CMP WORD PTR 1[SI],':S' ;Segment override. JNZ ADR2 LODSW CALL REGVALUE JC ADR4 MOV BX,[BX] INC SI jmp short ADR3 ADR2: CALL HEXSTRING ;Maybe, get value JNC ADR4 CMP BYTE PTR (-1)[SI],':' ;Then check for colon STC JNZ ADR4 ;If not then error exit MOV BX,AX ADR3: MOV AX,DX CALL HEXSTRING ;Get offset ADR4: POP DX RET ;Get code address. ;OUT: AX=Offset ; BX=Offset (same as AX) ; DX=Segment CODESTRING: MOV AX,IPSAVE MOV BX,CSSAVE jmp short DAT0 ;Get address in data segment, defaults in MEM1,DSSAVE ;OUT: AX=Offset ; BX=Offset (same as AX) ; DX=Segment DATASTRING: MOV AX,MEM1 MOV BX,DSSAVE DAT0: CALL ADRSTRING MOV DX,BX MOV BX,AX RET ;Pull a break point out of the input. ;IN: DS:[DI]=Break point area ;OUT: AX=Messed up ; BX=Offset ; DX=Segment ;Break point area is updated to show that the break point ;is active. The break point area consists of 6 bytes. ;0: ACTIVE If bit 7 is set the break point is set. ;1: OP CODE Op code that the break is replacing. ;2,3: OFFSET ;4,5: SEGMENT BRKSTRING: MOV AL,[SI] CMP AL,CR JZ BRK0 ;If CR then no break. CMP AL,' ' JZ BRK0 INC SI CMP AL,',' JZ BRK0 ;If , don't set break CMP AL,'.' JZ BRK2 ;If . use defaults DEC SI ;Otherwise break in input BRK2: MOV AX,2[DI] MOV BX,CSSAVE CALL DAT0 ;Get break points from input. JC BRK0 MOV 2[DI],BX ;Store them. MOV 4[DI],DX MOV BYTE PTR [DI],80H ;Activate break. CALL GETDXBX MOV 1[DI],AL MOV AL,BRKCODE CALL PUTDXBX BRK0: RET ;Get parameters for disk operation. ;Get number of sectors, SECCNT, and sectors per ;track, TRKSIZE. Default for seccnt is 1. ;IN: NONE ;OUT: AX=TRKSIZE=Sectors/track ; SECCNT=Number of sectors. DSKSTRING: MOV AL,1 ;Number of sectors CALL HEXSTRING JC DSK6 MOV SECCNT,AL MOV AL,TRKSIZE ;Sectors/track. CALL HEXSTRING JC DSK6 MOV TRKSIZE,AL DSK6: RET ;Get parameters for a from/to pair in the data segement ;(Ex. D(ump) from,to) ;IN: CX=Default length ;OUT: AX=To offset ; BX=From offset ; CX=Length (AX-BX) ; DX=Segment ; MEM3=To offset ; SEG1=Segment FROMTO: CALL DATASTRING JC FRM1 ADD AX,CX JNC FRM0 MOV AX,-1 FRM0: CALL HEXSTRING JC FRM1 MOV CX,AX SUB CX,BX JC FRM1 MOV MEM3,AX MOV SEG1,DX FRM1: RET ;Get from/to/with parameters. (Ex. C(ompare) from,to,with). ;From and with may be in different segments ;IN: CX=Default length ;OUT: AX=With offset ; BX=From offset ; CX=Length ; DX=With segment ; MEM1=From offset ; MEM3=To offset ; SEG1=From segment ; SEG3=With segment FRMTOTO: CALL FROMTO JC FRM2 MOV MEM1,BX MOV AX,MEM2 MOV BX,ESSAVE CALL ADRSTRING JC FRM2 MOV SEG2,BX MOV BX,MEM1 FRM2: RET ; OTHER USEFUL SUBROUTINES ; ------------------------ ;Pretend that DX is a segment register GETDXBX: PUSH DS MOV DS,DX MOV AL,[BX] POP DS RET PUTDXBX: PUSH DS MOV DS,DX MOV [BX],AL POP DS RET ;Dump the next CX bytes at BX to the console in ascii. ;Convert controls and negatives to periods. ASCDMP: PUSH AX PUSH BX PUSH CX ASC0: MOV AL,[BX] CMP AL,' ' JC ASC1 OR AL,AL JNS ASC2 ASC1: MOV AL,'.' ASC2: p  ush bx mov bx,conout int function_call pop bx INC BX LOOP ASC0 POP CX POP BX POP AX RET ;Dump the next CX bytes at BX to the console in hex. HEXDMP: PUSH AX PUSH BX PUSH CX HEX3: MOV AL,[BX] INC BX push bx mov bx,hexbyte int function_call pop bx CALL SPACE LOOP HEX3 POP CX POP BX POP AX RET ;Execute user program. ;STEP does one step, GO goes until break. assume es:vectors STEP: push es push ax xor ax,ax mov es,ax MOV w es:vector_1+2,CS ;Set single step vector MOV w es:vector_1,OFFSET RETURN OR FSAVE,100H ;and trace flag. jmp short go1 GO: push es push ax xor ax,ax mov es,ax MOV w es:vector_3+2,CS ;Set up break vector. MOV w es:vector_3,OFFSET RETURN go1: pop ax pop es assume es:nothing PUSHF ;Save my registers. PUSHA MOV MONSP,SP MOV SS,SSSAVE MOV SP,SPSAVE PUSH FSAVE PUSH CSSAVE PUSH IPSAVE PUSH DSSAVE MOV AX,AXSAVE ;Set user registers. MOV BX,BXSAVE MOV CX,CXSAVE MOV DX,DXSAVE MOV BP,BPSAVE MOV SI,SISAVE MOV DI,DISAVE MOV ES,ESSAVE POP DS IRET ;Return from user program. BOMB is for unexpected returns. BOMB: STC jmp short RET1 RETURN: CLC RET1: push ds push ax MOV AX,data ;Set my DS. MOV DS,AX pop ax MOV AXSAVE,AX pop ax MOV DSSAVE,ax MOV BXSAVE,BX ;Save users registers MOV CXSAVE,CX MOV DXSAVE,DX MOV BPSAVE,BP MOV SISAVE,SI MOV DISAVE,DI MOV SSSAVE,SS MOV ESSAVE,ES POP IPSAVE POP CSSAVE POP FSAVE MOV SPSAVE,SP MOV AX,DS ;Set my segments MOV ES,AX mov ax,stack MOV SS,AX JC RET2 MOV SP,MONSP ;And stack POPA ;And registers POPF sti RET RET2: MOV SP,OFFSET stack_top ;Program bombed. sti mov bx,message int function_call DB CR,LF,'Welcome to the Error Recovery Routine (Or Rats!)',0 JMP MONINIT ; *** COMMAND FLOW CONTROL *** ; ============================ ;Get command from command line and branch to proper routine. ;Pointer to branch table is at TOS. Grab a character from the ;command line, locate it in the table, and jump to the ;corresponding routine (note that its a jump, not a call). ;A 0 at the end of the table will catch everything that ;falls through. BRANCH: POP AX ;Get table pointer PUSH BX MOV BX,AX LODSB ;Get command letter. CALL UCONVERT BR0: MOV AH,cs:[BX] ;Search. INC BX CMP AL,AH ;Found it? JZ BR1 CMP AH,0 JZ BR1 ;End of table? INC BX INC BX jmp short BR0 BR1: MOV AX,cs:[BX] ;Get routine. POP BX JMP AX ;A macro to help build branch tables. BNCH macro BITE,ROUTINE DB BITE DW ROUTINE ENDM ; BRANCH TABLES ; ------------- ;Branch on first letter of command. MAINBRANCH: CALL BRANCH BNCH 'D',DBRANCH BNCH 'S',SBRANCH BNCH 'X',EXAMINE BNCH 'G',GOTO BNCH 'F',FILL BNCH 'M',MBRANCH BNCH 'R',RBRANCH BNCH 'C',COMPARE BNCH 'H',HEXMATH BNCH 'I',IBRANCH BNCH 'O',OUTPUT BNCH 'P',PUTTEXT BNCH 'B',bbranch BNCH 'T',TRACE BNCH 'U',UNTRACE BNCH 'W',WAIT BNCH 'Z',SLEEP BNCH ' ',MAINBRANCH BNCH ',',MAINBRANCH BNCH '&',REPEAT BNCH CR,ROMRET BNCH 0,WHAT ;These branch on second letter of command. DBRANCH: CALL BRANCH BNCH 'Q',DMPASC BNCH 'I',DMPIO BNCH 'M',DSKMEMORY BNCH 'N',SETDSKNUM BNCH 'T',SETDSKTRK BNCH 'S',SETDSKSEC BNCH 'R',DSKREAD BNCH 'W',DSKWRITE BNCH 'P',DSKPARAMS BNCH 'Z',DSKZERO BNCH '?',DISKSET BNCH 0,DMPHEX bbranch: CALL BRANCH BNCH 'I',ibmboot BNCH 'O',OLD_LOADER BNCH 0,boot SBRANCH: CALL BRANCH BNCH 'M',SRCHBYTE BNCH 'W',SRCHWORD BNCH 'S',SHOWSEGS BNCH 0,SUBSTITUTE RBRANCH: CALL BRANCH BNCH 'M',REVMOVE BNCH 0,WHAT MBRANCH: CALL BRANCH BNCH 'T',MEMTEST BNCH 0,MOVE IBRANCH: CALL BRANCH BNCH 'S',SILENTIP BNCH 0,INPUT ;********************************************************** ;*** *** ;*** MONITOR COMMAND ROUTINES *** ;*** *** ;********************************************************** ;These routines save all registers except AX (which was destroyed ;by BRANCH anyway), and SI which is left pointing to the end of ;the command line, or after the character which caused an error. ;Since these routines are close to the top level, it is probably ;not necessary to save registers (although it is nice). ;Hex dump command ; Df,t ;Display memory from f to t. DMPHEX: DEC SI ;Back up one character PUSH BX PUSH CX PUSH DX MOV CX,0ffh ;Defalut is 256 bytes CALL FROMTO JC DMP3 PUSH DS MOV DS,DX ;Segment to DS.    MOV DX,CX ;Length in DX. DMP0: MOV AX,BX ;Compute length of line AND AL,0F0H ;Line ends at the next ADD AX,10H ;multiple of 10H, SUB AX,BX MOV CX,AX MOV AX,DX ;or at DX. INC AX JZ DMP1 CMP AX,CX ;Whichever is less JNC DMP1 XCHG AX,CX DMP1: CALL CRLF MOV AX,BX push bx mov bx,hexword int function_call pop bx CALL SPACE CALL HEXDMP ;Have start in BX, CALL ASCDMP ;and length in CX. ADD BX,CX ;New starting point. SUB DX,CX JC DMP2 CALL CNTLCHK JNC DMP0 DMP2: POP DS JMP EXIT2 DMP3: JMP SAYWHAT ;ASCII dump routine ;DQf,t DMPASC: PUSH BX PUSH CX PUSH DX MOV CX,1279 ;Default is 1280 chars. CALL FROMTO JC DMP3 PUSH DS MOV DS,DX ;Data segment to DS. MOV DX,CX ;Length to DX DMP4: MOV CX,64 ;Length is either 64, MOV AX,DX ;or all the rest. INC AX JZ DMP5 CMP AX,CX ;Whichever is less JNC DMP5 XCHG AX,CX DMP5: CALL CRLF MOV AX,BX push bx mov bx,hexword int function_call pop bx CALL SPACE CALL ASCDMP ADD BX,CX ;New start SUB DX,CX JC DMP2 CALL CNTLCHK JC DMP2 JNC DMP4 ;Substitute memory values ;Sf,v1,v2,...,vn ;This command may extend over several lines. Replace ;one of the v's with a period to exit SUBSTITUTE: DEC SI ;Back up one character PUSH BX PUSH CX PUSH DX CALL DATASTRING ;Get memory location JC SUB3 CMP BYTE PTR [SI],' ' JA SUB1 MOV MEM1,BX MOV SEG1,DX SUB0: MOV AX,BX ;Start another line push bx mov bx,hexword int function_call ;Display current location. pop bx CALL SPACE CALL GETDXBX push bx mov bx,hexbyte int function_call ;Display old value pop bx CALL SPACE MOV CX,64 CALL LININ ;Get new line SUB1: CMP BYTE PTR [SI],'.' ;Time to quit? JZ SUB2 CALL GETDXBX ;Get old value, and CALL HEXSTRING ;use as default JC SUB3 CALL PUTDXBX INC BX MOV MEM1,BX CMP BYTE PTR [SI],' ' ;End of line? JNA SUB0 JNZ SUB1 SUB2: JMP EXIT3 SUB3: JMP SAYWHAT ;Put ascii into memory ; Pf,text PUTTEXT: PUSH BX PUSH CX PUSH DX CALL DATASTRING JC PUT2 PUSH DI PUSH ES MOV DI,BX ;Set up destination MOV ES,DX ;Source already set PUT0: CMP BYTE PTR [SI],CR ;(command line) JZ PUT1 MOVSB ;Move string jmp short PUT0 PUT1: JMP EXIT1 PUT2: JMP SAYWHAT ;Fill memory with byte ; Ff,t,b ;Default for t is 0FFFFH (rest of segment) FILL: PUSH BX PUSH CX PUSH DX MOV CX,-1 CALL FROMTO JC FILL0 MOV AL,0 ;Get byte to fill in CALL HEXSTRING JC FILL0 PUSH DI PUSH ES MOV DI,BX MOV ES,DX STOSB REP STOSB JMP EXIT1 FILL0: JMP SAYWHAT ;Move memory ; Mf,t1,t2 ;Move memory from f to t1 to t2. f and t1 are in the same ;segment, t2 may be in a different segment ; RMf,t1,t2 ;does the move from the top down. This may be needed to avoid ;destroying data during the move. It may also be used to ;repeat a pattern in memory. REVMOVE: PUSH BX PUSH CX PUSH DX MOV CX,-1 CALL FRMTOTO JC MOV1 STD ;Reverse direction ADD BX,CX ;Adjust pointers ADD AX,CX jmp short MOV0 MOVE: DEC SI PUSH BX PUSH CX PUSH DX MOV CX,-1 CALL FRMTOTO JC MOV1 MOV0: PUSH DI ;Set registers to PUSH ES ;use string instructions PUSH SI PUSH DS MOV DI,AX MOV ES,SEG2 MOV SI,BX MOV DS,SEG1 MOVSB REP MOVSB ;Move them JMP EXIT0 MOV1: JMP SAYWHAT ;Compare two memory areas. ; Cf,t1,t2 COMPARE: PUSH BX PUSH CX PUSH DX MOV CX,-1 CALL FRMTOTO JC CMP2 PUSH DI ;Set up registers for PUSH ES ;String compare  PUSH SI PUSH DS MOV DI,AX MOV ES,SEG2 MOV SI,BX MOV DS,SEG1 CMPSB JNZ CMP3 CMP0: REPZ CMPSB ;Do string compare JZ CMP1 ;CX=0 means all done CMP3: CALL CRLF MOV AX,SI ;Otherwise show error DEC AX push bx mov bx,hexword int function_call pop bx CALL SPACE MOV AL,(-1)[SI] push bx mov bx,hexbyte int function_call pop bx CALL SPACE MOV AL,ES:(-1)[DI] push bx mov bx,hexbyte int function_call pop bx CALL SPACE MOV AX,DI DEC AX push bx mov bx,hexword int function_call pop bx POP DS CALL CNTLCHK PUSH DS MOV DS,SEG1 JNC CMP0 CMP1: JMP EXIT0 CMP2: JMP SAYWHAT ;Input command, displays input data ; Ip INPUT: DEC SI CALL CRLF PUSH BX PUSH CX PUSH DX MOV AX,PORT1 CALL HEXSTRING JC INP0 push bx mov bx,hexword int function_call pop bx CALL SPACE MOV DX,AX IN AX,DX push bx mov bx,hexword int function_call pop bx JMP EXIT4 INP0: JMP SAYWHAT ;Silent input, does not display data ; ISp    SILENTIP: PUSH BX PUSH CX PUSH DX MOV AX,PORT1 ;Get default value CALL HEXSTRING JC SIP0 MOV DX,AX IN AX,DX JMP EXIT4 SIP0: JMP SAYWHAT ;Output ; Op,w OUTPUT: PUSH BX PUSH CX PUSH DX MOV AX,PORT1 ;Get port CALL HEXSTRING JC OUT0 MOV DX,AX MOV AX,WORD1 ;Get word CALL HEXSTRING JC OUT0 MOV WORD1,AX OUT DX,AX JMP EXIT4 OUT0: JMP SAYWHAT ;Wait, gives a delay of n milliseconds ; Wn WAIT: PUSH BX PUSH CX PUSH DX MOV AX,1 CALL HEXSTRING JC WT0 DEC AX JZ WT1 WTLP1: PUSH AX MOV AX,494 WTLP2: DEC AX JNZ WTLP2 POP AX DEC AX JNZ WTLP1 WT1: PUSH AX MOV AX,120 ;Fill up routine overhead WTLP3: DEC AX ; to make up the last millisec JNZ WTLP3 POP AX JMP EXIT3 WT0: JMP SAYWHAT ;Hexmath ; Hw1,w2 HEXMATH: CALL CRLF PUSH BX PUSH CX PUSH DX XOR AX,AX CALL HEXSTRING ;Get first operand JC HEX7 MOV BX,AX XOR AX,AX CALL HEXSTRING ;Get second operand JC HEX7 XCHG AX,BX MOV WORD1,AX MOV WORD2,BX ADD AX,BX push bx mov bx,hexword int function_call ;Display sum pop bx MOV AL,'+' push bx mov bx,conout int function_call pop bx CALL SPACE MOV AX,WORD1 SUB AX,BX push bx mov bx,hexword int function_call ;Display difference pop bx MOV AL,'-' push bx mov bx,conout int function_call pop bx JMP EXIT3 HEX7: JMP SAYWHAT ;Examine and modify registers ;Xr ;X ;First form is examine & modify register ;Second is examine all. EXAMINE: PUSH BX  PUSH CX PUSH DX LODSW CMP AL,'F' ;Have name in AX JNZ EXM0 MOV AH,' ' ;Only one letter for flags EXM0: CALL REGVALUE JC EXM2 ;Did not find it. EXM1: CALL CRLF EXM6: CALL REGOUT0 ;Display register name. MOV AX,axsave[BX] push bx mov bx,hexword int function_call ;And value. pop bx CALL SPACE MOV CX,60 CALL LININ ;Get new value CMP BYTE PTR [SI],'.' JZ EXM4 CALL HEXSTRING JC EXM5 MOV axsave[BX],AX ;And put it. ADD BX,2 CMP BX,offset fsave - offset axsave JBE EXM6 jmp short EXM4 EXM2: SUB SI,2 CALL REGHEAD CALL REGDISP EXM4: JMP EXIT3 EXM5: JMP SAYWHAT ;Goto with breaks ;Gg,b1,b2 GOTO: PUSH BX PUSH CX PUSH DX CALL CODESTRING ;Get goto address JC GT4 MOV IPSAVE,AX ;Put into user registers MOV CSSAVE,DX PUSH DI MOV DI, OFFSET BREAK1 MOV CX,2 GT0: CALL BRKSTRING ;Get break points JC GT1 ADD DI,6 LOOP GT0 GT1: POP DI JC GT4 AND FSAVE,NOT 100H ;Shut off single step CALL GO ;And go. DEC IPSAVE PUSH DI MOV CX,2 MOV DI,OFFSET BREAK2 GT2: TEST BYTE PTR [DI],80H ;Remove breaks JZ GT3 MOV AL,1[DI] MOV BX,2[DI] MOV DX,4[DI] CALL PUTDXBX MOV BYTE PTR [DI],0 GT3: SUB DI,6 LOOP GT2 POP DI JMP EXIT3 GT4: JMP SAYWHAT ;Untrace ;Uw ;Execute w steps, instructions which modify segment ;registers are not counted. UNTRACE: PUSH BX PUSH CX PUSH DX MOV AX,1 CALL HEXSTRING ;Get number. JC UN0 MOV CX,AX UN1: CALL STEP ;Do step. LOOP UN1 JMP EXIT3 UN0: JMP SAYWHAT  ;Trace ;Tw ;Execute W steps, display registers after each step. ;A check is made for control-C or control-S after ;each step. ;Instructions which modify the segment registers are not ;counted as steps. TRACE: PUSH BX PUSH CX PUSH DX MOV AX,1 CALL HEXSTRING ;Get step count. JC TR0 MOV CX,AX CALL REGHEAD ;Print header. TR1: CALL STEP ;Do step. CALL REGDISP ;Display registers CALL CNTLCHK ;Check for exit or stop. JC TR2 LOOP TR1 TR2: JMP EXIT3 TR0: JMP SAYWHAT  ;Set memory area for disk transfers. ;DMs:m DSKMEMORY: PUSH BX PUSH CX PUSH DX MOV AX,DSKMEM MOV BX,DSKSEG CALL DAT0 JC DSK5 MOV DSKSEG,DX MOV DSKMEM,AX JMP EXIT3 DSK5: JMP SAYWHAT ;Set sector for disk transfers. ;DSs SETDSKSEC: CMP WORD PTR [SI],':S' JNZ DS0 JMP DMPHEX DS0: PUSH BX PUSH CX PUSH DX MOV AL,DSKSECTOR CALL HEXSTRING JC DSK5 MOV DSKSECTOR,AL JMP EXIT3 ;Set drive number for disk transfer. ;DNn SETDSKNUM: PUSH BX PUSH CX PUSH DX MOV AL,DSKNUM CALL HEXSTRING JC DSK5 MOV DSKNUM,AL JMP EXIT3 ;Set track for disk transfer. ;DTn SETDSKTRK: PUSH BX PUSH CX PUSH DX MOV AX,DSKTRACK CALL HEXSTRING JC DSK5 MOV DSKTRACK,AX JMP EXIT3 ;Display current disk parameters. ;DP DSKPARAMS: PUSH BX PUSH CX PUSH DX mov bx,message int function_call DB CR,LF,LF,' DISK PARAMETERS' DB CR,LF,LF,'MEMORY (DM) ',0 MOV AX,DSKSEG mov bx,hexword int function_call MOV AL,':' mov b   x,conout int function_call MOV AX,DSKMEM mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'LOGICAL DISK (DN) ',0 MOV AL,DSKNUM mov bx,hexbyte int function_call mov bx,message int function_call DB CR,LF,'TRACK (DT) ',0 MOV AX,DSKTRACK mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'LOGICAL SECTOR (DS) ',0 MOV AL,DSKSECTOR mov bx,hexbyte int function_call mov bx,message int function_call DB CR,LF,'DISK DISCRIPTOR (D?) ',0 mov bl,dsknum xor bh,bh mov al,d_type_0[bx] mov bx,hexbyte int function_call DSK10: JMP EXIT3 ;Determine disk type. DISKSET: PUSH BX PUSH CX PUSH DX PUSH DI mov bx,dskcheck int function_call JZ DSK16 CALL SELERR DSK16: POP DI JMP EXIT3 ;Zero disk. ;Set lsttrk so that drive looks uncalibrated. ;DZ DSKZERO: PUSH BX PUSH CX PUSH DX PUSH DI mov bx,home int function_call POP DI JC DSK12 ;Disk exists? JMP EXIT3 DSK12: JMP DSK7 ;Read disk sector. ;DRb1,b2 ;Read b1 sectors from disk, assume b2 sectors per track. DSKREAD: PUSH BX PUSH CX PUSH DX CALL DSKSTRING JC DSK11 CALL REPREAD JZ DSK8 DSK9: CALL DSKERR DSK8: JMP EXIT3 DSK7: mov bx,message int function_call DB CR,LF,'BAD DISK SELECT',0 jmp short DSK8 DSK11: JMP SAYWHAT ;Write to disk. ;DWb1,b2 ;Write b1 setors to the disk, assume b2 sectors per track. DSKWRITE: PUSH BX PUSH CX PUSH DX CALL DSKSTRING JC DSK11 CALL REPWRITE JZ DSK8 JNZ DSK9 ; READ/WRITE A RANGE OF SECTORS ; ----------------------------- REPREAD: PUSH DI PUSH SI ;Put read routine in SI MOV SI,READ JMP short REP3 REPWRITE: PUSH DI PUSH SI ;Put write routine in SI MOV SI,WRITE REP3: REP2: push bx mov bx,si int function_call ;Read or write pop bx JNZ REP0 ;Quit if error MOV AL,SECCNT DEC AL ;Or if done. JZ REP0 MOV SECCNT,AL mov ax,200h cmp dsknum,4 jae rep10 mov ax,sector_size rep10: ADD DSKMEM,AX MOV AL,DSKSECTOR CMP AL,TRKSIZE JNZ REP1 INC DSKTRACK ;and track MOV AL,0 REP1: INC AL MOV DSKSECTOR,AL ;and sector. JMP short REP2 ;Then repeat REP0: POP SI POP DI RET ibmboot: int 19h ;boot ibm disk in drive 0 BOOT: dec si xor ax,ax CALL HEXSTRING cmp al,4 ;this should be made call to dskchk to varify floppy jae boot1 call bootstrap1 ;boot floppy jmp booterr boot1: jmp bootstrap2 ;boot harddisk OLD_LOADER: call old_load ; DISK ERRORS ; =========== ;select error SELERR: AND AL,80H JNZ DSKERR MOV AL,0F9H ;disk error, code in al DSKERR: PUSH AX mov bx,message int function_call DB CR,LF,'DISK ERROR CODE ',0 DSK15: POP AX mov bx,hexbyte int function_call ret ;boot error, code in ah BOOTERR: MOV AL,AH mov bx,message int function_call DB CR,LF,'BOOT ERROR CODE ',0 mov bx,hexbyte int function_call ret ;Show current default segments. ;SS SHOWSEGS: CMP WORD PTR [SI],':S' JNZ SS0 JMP SUBSTITUTE SS0: PUSH BX PUSH CX PUSH DX mov bx,message int function_call DB CR,LF,LF,' SEGMENTS' DB CR,LF,LF,'DATA ',0 MOV AX,DSSAVE mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'EXTRA ',0 MOV AX,ESSAVE mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'CODE ',0 MOV AX,CSSAVE mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'STACK ',0 MOV AX,SSSAVE mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'GOTO ',0 MOV AX,IPSAVE mov bx,hexword int function_call mov bx,message int function_call DB CR,LF,'IO PORT ',0 MOV AX,PORT1 mov bx,hexword int function_call JMP EXIT3 REPEAT: CALL CNTLCHK JC REP4 MOV SI,OFFSET LINBUF REP4: RET SLEEP: mov bx,conin int function_call CMP AL,'C'-40H JNZ SLP0 AND BITS,NOT INLINE SLP0: RET ; THINGS TO DO YET ; ---------------- DMPIO: SRCHBYTE: SRCHWORD: JMP WHAT ;Exits for the monitor routines all look pretty ;much the same, so they are grouped together here. ;The beginnings of these routines also have some ;similarities, maybe these could also be combined ;to save space (some other day). EXIT0: CLD ;Set string direction MOV MEM2,SI POP DS POP SI EXIT1: MOV BX,DI POP ES POP DI EXIT2: MOV MEM1,BX EXIT3: POP DX POP CX POP BX RET EXIT4:    MOV PORT1,DX JMP EXIT3 ;These are for errors SAYWHAT: POP DX POP CX POP BX WHAT: AND BITS,NOT INLINE mov bx,message int function_call DB ' what?',0 romret: RET ; **** MAIN MONITOR LOOP *** ; ========================== MONITOR: mov ax,data mov ds,ax mov es,ax mov ax,stack mov ss,ax mov sp,offset stack_top monitor1: sti CALL CRLF MOV AL,'+' ;Monitor prompt mov bx,conout int function_call MOV CX,78 ;Maximum line length CALL LININ OR BITS,INLINE MON0: CALL MAINBRANCH CMP BYTE PTR[SI],CR JZ monitor1 TEST BITS,INLINE JNZ MON0 jmp monitor1 code ends end SM 0IBOMB ASM ԝxPDBG ASM yY=UrEPROM EXE fr r=HDBOOT ASM [k KIBMBIOS ASM B!%IBMPRN ASM qTINIT EXE {/ j/INIT IN sd LD4 CMD T LOADER3 EXE L" iMEMTEST ASM {b MZ ֓ !ظм0! u\>|'&,n t>l3u uG>p& 2$F&>}<t<=tA< t< uI3u:2ItF&< t< t GĀ tͺ;3It.F&< t&< t",0|(< $r rrr2r t늺rpہwr'&+u r;w؎ЌQã`d&+vϱË%fh uZ3P>l>p|&5\&lnڋʃ+6cG6 G&6FG6&P;>|L!˴ !>|L!3Pˡ-ື !>|L!ˀ>| FL!-ULr;&wPo vRtP~PPQ L]ø-PvRtFuvRt0PL]øHPDPFuJP|L]F ~ ~3P3P3Sv ~ u0^P wP FP F0=YFte=yt`vDHDx 0 v9 ؉^CuPl wPc FP F0=YFt=ytrvP vP 帱P$ 帳P FPe vPs vP P 帳P FP2 F F3FF~}BvF@t4FFPPFDP FDPFPFvF@uPFP%tqFFFF ^^ ہSFPv vPv$FFFF ^^ ہSFPv vP~tF #v P^ vP v P F L]Uv D0%t VPv ~uv D3ۅyK)F ^v D3DDD0䩀Ft%Dv D 0vvv Pu=u]Ëv D0%D3]U vD 0S3S3QPmu=F^t v| u F^ ]ËvD0%t+D3ۅyKNȋVӋ‹ك ]ËvD3ۅyKN+ȋVӋ‹ك ]U> }nv0@$0%tFv0tIFv0Ft@$0%uFߋvFF0u0=|PXPP:0>FtPZP:PF P\P;PF P\P^P}F u P9%~uv _P P$6 sPvvD0%D~ tv vPP$n 3&t3F h^ˠQ<f%t 0 P6R3P $]Uv ^ ؉^vF~FuF ]Uv ^ ؉^FN~v F ~tFvF ]Uv <t(~=t F F0 0+ˉNt׋]Ëv <t]Ëv<t]3]U~t5v <t-~=t%F F0 0+ˉNt]NŃ~t v <t]Ëv<t]3]U츐F^;sG0tFF=u3]vv v ]UvDt0%t VPvD 0P_塆 v\0Fv FFF btatv D0=+t33Cv0^ F F~ t^ ؁PSv F@u3]øP3P3Sv~ tF~ t3^ Svs F@u3]Â~ tFf~ t^ ؁PSv+ F@u3]Â~ tF3]=wt=rui=auF*=tNF vDvDFvD D3DDFDƃ]UvD0%t VPvD0% u| t t tg3vDD DD 0Pk]U썆F 0uƉF@0%^t0%u20䋶\K\ۉFx    0vp뛍FPF PFPF u|FF^;f\K\xC0vB0P F뾋DHDx^0v]U F^hf~i0=}3 ]ËF^^ F3 t3 ]ùF ^S^t3 ]ËF ^fhbËNb)f^hF ]UF 3SPKFt]ø]U 0=}b+^3ۅyKfhZ  ^F3 t ]ùF^S^t ]ËF^hf^b3 ]UFHx60 P;=Ft'= uFFv FFv F믃~u3]ËF v]UFFH^;}AvDHDx 0 v؉^CtFFv F= uFv u3]ËF ]U썆F^0uƉF@0%^u`0%u뾍F PFPFPF tFF^ ;~CF⋶Fk+FF ]Uv F 0Ft)Kۉx60ԸPvơHx6 0 P P_]UFv F 0Ft(v\K\x 0 vvFNjF]Uv D0%0t]Ëv | uD0%uVt]Ëv D0%tF)v D0%t]Ëv D0 DD Fv D 0vtPFyv D0 D~uv D0 DF~ v DDv D0%0t]Ëv DHDx 0 v ؋Ã]U Fv\00Ft ]Ëv| ujD0%u`~u3 ]vt ]ËvD0 DD DHDx^0 vvv؋à ]ËvD0%t8~u3 ]ËFv\ 0F v NQSF FFvD0%t ]ËvD0 D~t2|~,DHDx^0 vvFv+DF tD 0v tP- FF~uvD0 DF;F tvD0 DvD DDF=t \K\x 0 vvCvD0%0t ]Ã~u3 ]ËF ]Uv| tD0%u3]6  vDu ]á vD D0%D3DD]UvDHDx 0 v؋Ã]Uv DHDx^0F0v PS؋Ã]U썆F 0uƉF@0%^t0%u40KۉFx60맸Pv뙍FPF PFPvF uzFF^;dKۉx6C0vB0仞SPnF뼡Hx6F0Pv@]Uv=~u3]ËvD0%D0 DFD D 3]UVN!s]U^NV?!s3]U^NV@!s3]UF B^NV!s؋]UVA!s]UVFCN!s]U^D!]UV~V!s]3]UFx;:}*<0%u  3]ËF*<]U FF:;~*<0tFߋF;:u  ]ËF*<&%^3ÉF%v t3 v F%`v 0 @cF%t3 v 0 ؈DF%t3 `v 0 ؈%v   ]=t=t=tۋv0uv DF ]FF=}7 @Pv_uF ~ EF ]Fv D0=F%tvF%tF%Pv>v D>t4F%t3Pvv D>t> v  ]ËF%=uv t v  ]ËF ]UF % ^ SPv ]UFy ]vyFu]ËvD0F==~FS"FF0^;~FFFF0= u Fv #F0=uFFFvF뮸 PF]øY,,F^ ,,F^v0%t-FF;F}FF^؉^VvF]FF;F|VF0 PV PVFF@vv F]Ã~tPV PVPV띸 PV PV3]ËFFvF0= }^PVF0@PVSF0PVEq G G .;u.y뛋F]3]à0=~#vvvtF>t]Ëv0%tF]3FF F^;~UFvF08F+FH3ۅyKQSPvvF ]뿋F F vF= t=t~ u ~tIF ]ø]!Hs.UFy ]vFu]ËvD0,F,F,FFF^;~6FvF0= uv0%u PVF0PVF]Ëv0%tP3P3SvW0=~4v0%t(vvtF>t]ËF]F3FF F F^;FvF0= uF0= tF NF F@v^=F ^|0=~0v Pvt;F Ft3]Ã>t]F p~ t:0=~0v PvtB;F Ft3]Ã>t]ËF]ËF] ]â?G  Os.UvFu ]ËvD0t 33ۃ]à0=~2vvvvtF^>t ]Ã~urF Ftjv0%u^F-^F ^ F x33Pv v vM tPFPv/u n ^ ƋF ^ ]ËF^]Uv Fu]3v\0ۉFu0=~t>tFvF]U(0=~v,>t(]3(]Ã(]Uv]UN0=~vTvRN]ÃN]Uۣ "u]Ë6 3"D3]U3P]UF y]F3PSrFu]ËF^F HF t3PS?t FC3]U"3ۓ]UF 3SPF^]UF^33 3]ËF^-FË^3ɺ  FN^ v~tnvD3ۉFÉ^^NV |A;u;u vvD3+F ^DF"3+F ^^"Ã]ËFF^댹F^ PSF t@>u ^ %؋F ;É^u3F ^F ]3]UF3SPv F^]UF^33 ]ËF^NF 3ɺ ^N ˋ"3^о FNV"vFu\؋N;ȉ^sv FDƋv3]ËF;Fu)~ D3ۋNȋVӉMNjv3]ËF ;Fs"3+F^"]ËF ;FuUvt^;v"3+F^"]ËvD3F^Dt^;u GD3]ËF^ FN^ F v3ۋFDÃ]U`+\jV`+rSZJ![r j3]ã]U+\j+Fu!j^rZSJ![r j3]ã]UFvv0tFF]U63FF v:0-F FFFu F:F v:0F@$0%tJ~0uF0v:F:0%Fv:0@$0%tF F:0ÉFыv:0=.u7F:Fv:0@$0%tF F:0ÉFыv:0=lu F:FFv:0~tv>\ N^ v>3ɅyIN ^F yBV ^^ F1~tv>\ N^ v>3F ^F FHFF ^3ɺ v0vR"F ^3ɺ F ^F Fu~u FHB"-FF"^ظ +FF ^~tv>\ N^ v>3F ^FFH^ N3ہ(Z"^ V^ FV^ F FuF"^ظ+FF ^G~tv>\ N^ v>3F ^F FH^ N3ہ0J"^ V^ FV^ F FuF"^ظ +FF ^~uFv>ۉ^u8FF F ^;v0tuF F"F v>FN"VFOFHFA36]f'e'g'c'sD'o&x&&u%d6% .;'u.'y뿃~uFt;F }F FF )FF~ t?F HF xFFv<~FދFHFxQFFv<FFHFxFFv<FF HF xFFv<~FދFv@F:@6]Ã~uF~|FF @~t33CN"QNQNQSPv>4v>^"NɉF N^y^~u~ t ~|33@F~ tN3F~tF~t!F@^Ë^ۉFx^~t1F,FFFyF=cF~F~~F~ u)F;F~!F)FFHFxvFuNF txvN }F ϋFxA=7FF^NV ֊͊ߊĿOu% F 3333ҋv4Ft D\Lv2F(]þ@3^NV~ = r- GNu^NV~ ËF F FЉFFЉFFЉFË3Ã3ɿCK[ÃCOOyËF^NV NuF^NV Ã~,t F,F,V0FN.uNFtUV !]UvD0%t3]Ëv| tD0%u t tF vDD0 D3D DD]UfFV!]Lattice C 2.10 Invalid stack size $Invalid I/O redirection $Insufficient memory $*** STACK OVERFLOW *** $Intel hex converter for programming Eproms Programming file: %s Error no file specified. rbError opening %s . prnwError opening prn. Programming even bytes. Do you wish to continue (y or n) Programming odd bytes. IPress return to continue. T%02xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:%02x%04x00%s%02x :00000001FF rwaCan't open stdin file Can't open stdout file con:CON:prn:PRN:lst:LST:lpt:LPT:lpt1:LPT1:aux:AUX:com:COM:com1:COM1:rdr:RDR:pun:PUN:nul:NUL:null:NULL: ((((( H ((((( H 0123456789ABCDEFLD4 CMD T LOADER3 EXE L" iMEMTEST ASM {b  .286c function_int equ 0f8h boot_seg segment at 1000h org 0 boot_location label far boot_seg ends code segment assume cs:code,ds:code org 0h ;---------------------------------------------------------------- ; on entry bp has either 4 or 5 disk 0 or 1 ;---------------------------------------------------------------- boot proc far jmp boot_code our_name db 'SLICERCB' ;slicer concurrent bios cylinders dw 306 heads db 4 rw_cyliner dw 0 wp_cylinder dw 0 error_burst db 5 step_rate db 7 sectors dd ? drives db 0 p_ptr dw partition1 dw partition2 dw partition3 dw partition4 boot_code: mov cx,1 ;number of sectors in boot sector xor bx,bx xor dx,dx mov si,0fd0h mov es,si xor si,si mov ax,bp xchg ah,al mov al,0 int function_int ;read entire boot to seg fd0h or al,al jz b2 jmp boot_error b2: push es push offset boot_continue ret boot endp dos_sector dw ? dir_sector dw ? boot_continue proc near push cs pop ds x  or si,si bc1: mov di,p_ptr[si] cmp byte ptr [di].boot_indicator,80h je boot_it add si,2 cmp si,8 jae boot_error jmp bc1 boot_it: mov si,boot_seg mov es,si xor si,si mov ax,bp mov ah,al xor al,al mov cx,1 mov bx,word ptr[di].rel_sector mov dx,word ptr[di+2].rel_sector int function_int ;read secondary boot record or al,al jnz boot_error jmp boot_location boot_error: mov si,offset message push cs pop es mov ax,601h mov cx,message_length int function_int cli hlt boot_continue endp message db 0dh,0ah,'Error Loading secondary boot record.',0dh,0ah message_length equ (this byte - message) pr struc boot_indicator db ? begin_head db ? begin_sector db ? begin_cylinder db ? sys_indicator db ? end_head db ? end_sector db ? end_cylinder db ? rel_sector dd ? num_sectors dd ? pr ends org 1beh partition1 pr <80h,0,2,0,0,0,0,0,1,0ffffh> partition2 pr <0,0,2,0,0,0,0,0,1,0ffffh> partition3 pr <0,0,2,0,0,0,0,0,1,0ffffh> partition4 pr <0,0,2,0,0,0,0,0,1,0ffffh> dw 0aa55h code ends end  if2 %out Pass 2. endif .286c page 60,132 name ibm title Slicer BIOS Version 2.0A (IBM emulation) .xlist subttl Data Areas page + include biosdata.asm page + .list ;-------------------------------------------------------------------------------- ; BIOS for the Slicer. (C) Slicer Computers Inc., 1985 ; ; Version 2.0 April 4, 1985 ; By David Daney 1985 ; ; ;-------------------------------------------------------------------------------- subttl Equates page ;---------------------------------------------------------------- ; E Q U A T E S ;---------------------------------------------------------------- b equ byte ptr w equ word ptr ; byte definition ; disk type uninitialized equ 10000000b mini equ 00010000b double_density equ 00100000b double_track equ 01000000b sector_size_m equ 00001100b step_rate_m equ 00000011b disk_read_cmd equ 10011000b disk_write_cmd equ 10111000b ; console equ 6 output equ 1 function_call equ 0f8h ;---------------------------------------------------------------- ; S T R U C T U R E S ;---------------------------------------------------------------- dpb11 struc db ? db ? db ? ibm_sector_size db ? dpb11 ends subttl Externals and Publics page + ;---------------------------------------------------------------- ; Externals and Publics ;---------------------------------------------------------------- public ibm_call_init public rs_232_send public print extrn disk_read:near extrn disk_write:near extrn disk_reset:near extrn port1_write:near,port2_write:near extrn moninit:near subttl Initialization Code page + boot_seg segment at 0 org 7c00h boot_location label far boot_seg ends cgroup group code code segment byte public 'code' assume cs:cgroup,ds:data ibm_call_init proc near ; set macro num,val mov w num,offset val mov w num+2,seg val endm ; mov ax,vectors mov es,ax assume es:vectors set vector_10,vidio_io set vector_16,keyboard_io set vector_11,equipment_check set vector_12,memory_size_d set vector_14,rs_232 set vector_15,cassette_io set vector_17,printer set vector_19,bootstrap mov ax,offset kb_buffer mov buffer_head,ax mov buffer_tail,ax set vector_1a,time_of_day set vector_1e,disk_base set vector_fc,disk_io mov al,uninitialized mov d_type_0,al mov d_type_1,al mov d_type_2,al mov d_type_3,al mov ax,day mov day1  ,ax ret assume es:nothing ibm_call_init endp number_table db '0123456789ABCDEF' print proc near cld mov dx,cs mov es,dx mov di,si mov al,0 mov cx,0ffffh repne scas b [di] not cx dec cx mov ah,console mov al,output int function_call ret print endp assume ds:nothing,es:data keyboard_io proc far sti push es push si mov si,data mov es,si or ah,ah jz get_char cmp ah,-1 je get_char dec ah jz keyboard_status dec ah jz shift_atatus2 pop si pop es iret get_char: mov si,offset ibm_temp_char push cx mov cx,1 mov ax,600h ;read one char int 0f8h mov al,es:[si] xor ah,ah pop cx pop si pop es iret keyboard_status: mov si,offset ibm_temp_char mov ax,602h ;read status int 0f8h or al,al ;set zero flag lahf xor ah,40h sahf ;invert zero flag mov al,es:[si] mov ah,0 pop si pop es ret 2 shift_atatus2: mov al,shift_status pop si pop es iret keyboard_io endp vidio_io proc far sti push si push es push cx mov cx,data mov es,cx cmp ah,14 je vi1 cmp ah,-1 jne viend vi1: mov si,offset ibm_temp_char mov es:[si],al mov cx,1 mov ax,601h ;write 1 char int 0f8h viend: pop cx pop es pop si iret vidio_io endp cassette_io proc far mov ah,080h stc ret 2 cassette_io endp assume ds:data ;---------------------------------------------------------------- ;Diskette i/o ; ;input ; (ah)=0 reset disk system ; (ah)=1 read status of disk system into (al) ; (ah)=2 read sectors into memory ; (ah)=3 write sectors to disk ; (ah)=4 verify sectors on disk ; ; (dl) - drive number (0-3) ; (dh) - head number ; (ch) - track number ; (cl) - sector number ; (al) - number of sectors to transfer ; (es:bx) - data buffer ; ;output ; (ah) - status of operation ; (cy)=0 no error ; (cy)=1 error ; ;---------------------------------------------------------------- disk_io proc far sti push ds push es push bx push cx push dx push bp push si push di mov si,data mov ds,si cmp dl,3 ja hd_io mov drive_number,dl mov head_number,dh mov disk_track,ch mov sector_number,cl mov num_of_sectors,al push es mov si,vectors mov es,si assume es:vectors les si,vector_1e mov al,es:[si].ibm_sector_size and al,011b shl al,2 mov si,dx and si,3 and d_type_0[si],not sector_size_m or d_type_0[si],al ;set sector size pop es assume es:nothing or ah,ah jnz dio1 call disk_reset mov ah,0 jmp dio2 dio1: dec ah jnz dio3 mov ah,diskette_status jmp dio2 dio3: dec ah jnz dio4 mov al,settle and al,4 or al,disk_read_cmd int 0fdh ;file bios.asm disk_read mov al,num_of_sectors mov ah,diskette_status jmp dio2 dio4: dec ah jnz dio5 mov al,settle and al,4 or al,disk_write_cmd int 0fdh ;file bios.asm disk_write mov al,num_of_sectors mov ah,diskette_status jmp dio2 dio5: hd_io: mov ax,100h dio2: cmp ah,1 cmc pop di pop si pop bp pop dx pop cx pop bx pop es pop ds ret 2 ;kill the flags disk_io endp disk_base dpb11 <0,0,0,2> memory_size_d proc far sti push ds mov ax,data mov ds,ax mov ax,memory_size pop ds iret memory_size_d endp equipment_check proc far sti push ds mov ax,40h mov ds,ax mov ax,equip_flag pop ds iret equipment_check endp rs_232 proc far  sti push bx push cx push dx push si push es push ds mov bx,data mov ds,bx mov es,bx cmp ah,0 je rs_232_setup cmp ah,3 je rs_232_status push dx cmp ah,1 je rs_232_send mov ah,dl add ah,0ah xor al,al mov si,offset ibm_temp_char mov cx,1 int 0f8h mov al,ibm_temp_char xor ah,ah pop dx jmp rs_232_exit rs_232_send: mov ibm_temp_char,al mov si,offset ibm_temp_char mov cx,1 mov ah,dl add ah,0ah mov al,1 int 0f8h pop dx mov ah,61h jmp rs_232_exit rs_232_setup: push ax mov bl,al ;set up incoded in al mov ah,dl add ah,0ah ;port 1-4 newcall.asm mov al,5 ;write setup call int 0f8h pop ax ;only thing that could have changed rs_232_status: mov ah,dl add ah,0ah ;port to ah push ax mov al,2 ;read status int 0f8h mov si,ax pop ax mov al,3 ;write status int 0f8h xor ah,ah or al,al jnz rs_232s1 mov ah,01100000b rs_232s1: and si,0ffh jnz rs_23  2s2 or ah,1 rs_232s2: mov al,11110000b rs_232_exit: pop ds pop es pop si pop dx pop cx pop bx iret rs_232 endp printer proc far sti push bx push cx push dx push si push es push ds mov bx,data mov ds,bx mov es,bx mov si,offset ibm_temp_char or ah,ah jz prn_out dec ah jz prn_init mov ah,7 ;prn or dx,dx jz po1 inc ah ;aux po1: mov al,3 ;status int 0f8h xor ah,ah test al,80h jnz prn_bad mov ah,80h jmp short prn_good prn_out: mov cx,1 mov ibm_temp_char,al mov ah,7 ;prn or dx,dx jz po2 inc ah ;aux po2: mov al,1 ;out put a char int 0f8h mov ah,bl ;al test ah,80h jz prn_good prn_bad: mov ah,1 ;time out jmp short prn_done prn_init: mov ah,0 prn_good: or ah,90h prn_done: pop ds pop es pop si pop dx pop cx pop bx iret printer endp time_of_day proc far sti push ds push dx push cx push bx push si mov bx,data ;returns seconds*18 mov ds,bx or ah,ah jz tod2 dec al jz tod3 jmp tod4 tod2: cli mov al,hours xor ah,ah mov bx,64800 ;3600*18 mul bx mov si,dx mov cx,ax mov al,min xor ah,ah mov bx,1080 mul bx add cx,ax adc si,0 mov al,seconds xor ah,ah mov bl,18 mul bl add cx,ax adc si,0 mov dx,cx mov cx,si xor al,al mov bx,day sti cmp bx,day1 je tod1 inc al tod1: mov day1,bx jmp tod4 tod3: mov ax,dx mov dx,cx mov bx,1080 ;60*18 div bx mov cx,dx mov bl,60 div bl cli mov min,ah mov hours,al mov ax,cx mov bl,18 div bl mov seconds,al mov bx,day sti mov day1,bx tod4: pop si pop bx pop cx pop dx pop ds iret time_of_day endp bootstrap proc far xor ax,ax ;drive 0 mov al,84h int 0f8h ;getparameters from drive or al,al je boot2 jmp boot_error boot2: mov bl,1 mov cl,1 xor ax,ax mov al,82h int 0f8h ;set parameters boot3: mov cx,1  xor dx,dx xor bx,bx mov si,boot_seg mov es,si mov si,offset boot_location xor ax,ax mov al,0 int 0f8h ;read first sector or al,al jnz boot_error xor dx,dx ;drive 0 jmp boot_location boot_error: jmp moninit bootstrap endp code ends end  .286C page 60,132 .xlist include biosdata.asm .list ;------------------------------------------------------------ ; Slicer drivers for the System Expansion Board ; This driver provides an I/O channel for the printer ; port on the Slicer System Expansion Board. ; ;------------------------------------------------------------ ; ; E Q U A T E S ; ; ; w equ word ptr b equ byte ptr ; printer_status equ 1 printer_data equ 0 printer_control equ 2 strobe_on equ 0feh strobe_off equ 1 busy equ 80h fault equ 020h fault_error equ 20h not_ready equ 80h bad_command equ 1 cgroup group code public ibm_parallel ; code segment public byte 'code' assume cs:cgroup,es:nothing,ds:data ; ibm_parallel proc far dec al jz prn_out dec al dec al jz prn_stat mov al,bad_command ret prn_out: push cx ;save character count jcxz po_end po_loop: mov dx,pport_addr mov prn_countl,0 mov prn_counth,0ah add dx,printer_status  ack_wait: in al,dx test al,fault jz po1 mov al,fault_error ;out of paper jmp po_end po1: test al,busy jnz po2 ;jump if printer ready dec prn_countl jnz ack_wait dec prn_counth jnz ack_wait mov al,not_ready ; time out printer not ready jmp po_end po2: lods b es:[si] call send loop po_loop ;loop for multiple characters xor al,al xor bl,bl po_end: pop di ;return number of characters sent sub di,cx mov cx,di ret send proc   near mov dx,pport_addr po9: out dx,al ;output data add dx,printer_control in al,dx and al,strobe_on out dx,al ;send strobe low or al,strobe_off ;send strobe high again out dx,al ret send endp ; ; ; S T A T U S ; ; prn_stat: mov dx,pport_addr add dx,printer_status statlp: in al,dx test al,busy mov al,0 jnz pos_end ;jump if ready mov al,printer_stat ;test if printer was used test al,8 jnz stat1 ;jump if printer was used or printer_stat,8 mov al,0h call send ;send break for first ack mov al,0 jmp pos_end stat1: mov al,not_ready pos_end: ret ibm_parallel endp code ends end Y=UrMZj ddO  USSW^SSF^R SvF=t#~t~uS Sr =uĻ%S S[ =t+SPBS?SvZR SvF=tU~t~tvv9HS S =t SOSv SRSv뒻VS S =t ]SAvvS]Uv ^FFPuF~t~t ^F]NF=~1v^FFP0F~t~tvv^K]U~a|~z~ ~A| ~Z]~0| ~9]F]]UFF wSqS*^R SvF=u~t ~tyS SP=uF|S S6=uFF~t~uXR SvF=tv6 SF~u F    F5v]Uv tЬ]U  =tv ؋ ӃFF;}DF ؋%=t)F ؁ÎS3F Fv]U> }  ؋v ]ø]U^G%=u~vE^wwF^^_ ۸tt^G%=t@5=t$^G%=t ^G ^w^GF]ø]U^=| ^O@^wGF%] vv7]]U~ u^G%=u v Rvv]U^u^G%=t^_v \^G%=t#^_Fv=u]ËF]v=u]vv]U^?rt^?wt^?at ]û^ .ދv;s^G%=uF ջ .ދv;r ]F+Rv tF^?wu~uFN ^?au~uFNRvvF~u]Ë^FG^^G^G^?ru^?au^ GbRv_t^O+RvEt^O;Fu^O;Fu^O^]U^ ^Sv S]U6 v]U^G%=t]Ë^=|^wG%] v=]]UvF^G%=tF]Ã~ tF^?^G%=tvnFCFFFR^S^w=tFR66^w~ t~t~t vv`F ~u vFF]Ã~u ^OF~uF%]U^Sv>S1]UFFFFF~t^v7~|~$~ F^]Ë^P =tF^?-u FF ^?+uF~u,F ^?0u^GPG=xuFF~u$^?0u^GP=xu ^^^P =tN^-0;F}:vvFRP FFvv^F-0RPFFF^P  tt ^P -a~ ;Ǹ|H =tDvvFRPFFvv  ^FPC -a RPFFF^ ۸tt F t=t^v7~tvvZFFF^]U~u]Ë^G%=t0^v_;\v"^?|^O_F^]]]Uv~<ttrtH]ð:&+؁vЋ-Á+؎J!؎  + t3PU^GFF%=t F%=t]Ë^uBPPRv\^twt^O^]]v]U^G%D=u^G%=t^?u FF]^?}^^+FF^F^g^v_\~tv^w^w]Ë^G%=t^^v_\]U^G%=t^G%=t]Ë^uN^G%=t^_v \,PP v\|u ^O^O멋^v_\^G%=tP^w^w9 ^^G%=t^O^=}&^?u ^O^O ^]Ë^wG%]UD^^^^^F^?u ^?%tFFFFFFFFFދFމFFF^Pv ^t^+^ù^ʍJ^^?0uFF^S^SF^?.uF^S^SlF^?luFF^FQFd~t^Fw7v^FRPvrF*F#F ~t^Fw7vPA~tv^Fw7v^v^F3RPvx^^~su ^F^~u vF(^FvF^~tFF^Pvv^Fwww7JSK ~uFq^^F^[=gt=ft=et=Et=Gt=suA=cu9=uu=xu=Xu=ou=duc=iuV돃~su^J^SF~su~|F;F~FFFFE^v=d}v=g~~t,^?-u^F^FN ^F+F0~t*^?-u^F^FN ^F F~t!r]ã]YXL!^[ZYXPQRSVB!rãUFt"FtV=!r*ش>! ]ËVF=!r!FtNV" uRQ$ ?!YZr $ uU~F=t uuK]<t]UNVNV ]>%=u@D!€u D!€u UPS^Ff ȋFȋFʉN F[X]U+ҋ+VNVN]UFfFP^~tvRvh ^]UFF~uFv v vvvy F~~]Ë^^?-uFv*~}v~H =tF@Pv1^^C^F=.t@^FF tu F t=t^. ^^^N~u~u^K?.u ^N^Fe~| ^F+F؉F^F-~ } ^F0vv4n~u+vvv`^?.tFF؋vF^^~|F؉F=~F+FF^^F؋vvFFFN=t^^N^N0܋^;^t ^N0vv  v^^FFF=}vvv^C^^?.tF^^^.~~FFFF+FFFN=t^F^FFN=t ^F0+FF=}FF+FF=} FFF~t ^F.FN=tFFN=t ^F0^~t~up.RvtKv؋vNvv =gu^?0u ^N~u^?.u^~t Sv0=u=fu=u=eu=u=gu]UF؋vFvv^N?4^@^?9~ ^N0^?/ud^F1F tu F t=t ^F.FF0F;F}^F^FFFFFً^]U~a}H t ~z~H ]U~A}H t ~Z~H ]U~ uFvv66XZFvv66FF66vvFFu~ uFvv66{XZFvv66;FF66vvNFF)vvF RPXZFvvF RP?FFF Ftv vvv"^~}F؉F~ ~ aF- 0F^F^]U^^vv66_s?vvFF^F-vv664sSv`^]ú Rvvvz^^^]U^^ RvvvK^^^]UFRPvA]U~a}H t ~z~H =t F-aAF]ZXPR++v+r ûZRRU~+-]U^VN;t<t9tB!^VN@Q!Y;u]ã]ËڸPSQ!Y[XC@] uU^^^?tF^F^F?t^]Z_WRËDu-. 00EG+@naninfinityindefinite y-Gd+%=u4T  T TuDtDuO!. þ!!trhs.DdL-t $TTTRDT\U, DT\,,\TD0%G*װE]ZR y-ڋ™0d0 Ę00*Xû D;G sD;G rWRttt4www7DDDZÊd2gDy;G;GuD;Gu D;Gu;U~FN^]Uv~<t^]UNV!N!V ]UUSVWPR u^ v^v uZ`UU u V~V ~ u Z-U3 +sӋ]Z t߉v^ X_^[]UV ;Vt 2vy V+V]UN tn ^]tUF v^ ]2t tt ut ut ut+r v rQS=+ҋF V ^vV+F^vV yF^vV VV VVV[YYUWVPSv~ ff ֋NJԁ F F F F uF F F Fu tN} tN vvtNuIt=< u=u=u =sߊF FFFFFFF jފcttЋ% tFu tVuFt+FuF t+F FFFF t Cw@F% À F[X^_]fV VVV+ۉ^^^^ ػ+FFFF 뭵+FFF FtUF N^ ]M2 uGt t uFt txut{}]~dQS+ɋًF fF fʋF fڋF f ؃V FfʃV FfڃV FfV FFsFf F VFfڃV VFfV VFfF VFFsFf FVFfV VVFfF VVFfFVFf FZr*u% t!tXJFFFF F^ YVv G|uuuOFVv^ YtF FFJutUF f^ ]ettt ;tUF F^ ]"tt t to ut u t2y* ut;trVtFjtG2uuiCw y^F F F Ftf*n^^^ ^^ ^ ^ ^n ^^^^ ^ ^ ^ ^n^^^ ^V VVV+FF FFFÊF FFF FFFFF FF ÊF (FFF FFFFF FS.INrS.OUTwidataidataError in file S.IN %sidata00000H%s%s 00000HError in file S.IN S.OUTrDWDB-+ #.2147483648$ P 8 urm.&%ZR]jp2A0M[w9!FFFg<@C& .> Ah㈵>@MbP?P@{Gz? @??$@Y@?@?חA@>7yAC<nF@9?O8M230HwZP%>sOuE {/ j/INIT IN sd LD4 CMD T LOADER3 EXE L" iMEMTEST ASM {b   MODE PROMPT OFF TOLERATE OFF HARDWARE DUART A_INPUT state on baud_rate 9600 stops 2.0 char_size 8 parity none interrupt off A_OUTPUT state on baud_rate 9600 stops 2.0 char_size 8 parity none interrupt off B_INPUT state on baud_rate 300 stops 2.0 char_size 8 parity none interrupt off B_OUTPUT state on baud_rate 300 stops 2.0  char_size 8 parity none interrupt off EX_DUART A_INPUT state on baud_rate 1200 stops 1.0 char_size 7 parity odd interrupt on A_OUTPUT state on baud_rate 1200 stops 1.0 char_size 7 parity odd interrupt off B_INPUT state on baud_rate 9600 stops 2.0 char_size 8 parity none interrupt on buffer 100 B_OUTPUT state on baud_rate 9600 stops 2.0 char_size 8 parity none interrupt off buffer 100 EX_SIO A_INPUT state on baud_rate 1200 stops 1.0 char_size 7 parity odd interrupt on A_OUTPUT state on baud_rate 1200 stops 1.0 char_size 7 parity odd interrupt off B_INPUT state on baud_rate 9600 stops 2.0 char_size 8 parity none interrupt on buffer 100 B_OUTPUT state on baud_rate 9600 stops 2.0 char_size 8 parity none interrupt off buffer 100 MODE PROMPT ON TOLERATE ON WRITE yY=UrEPROM EXE fr r=HDBOOT ASM [k Kdd SLICER Ȏ؎м ;; SLICER loader program December 12,1984 Vers. 3.1 Copyright Slicer Computers Inc., 1983, 1984 DUfD.&A.C.CtD &‹\D ut'uQ&ɀOr&Y&.&;uD&.Có; Disk read error.ADd.?D +.6?Q&&.A8.?Q G$.9u.:!.:-uYY.6AS&.G&*GD t#G t .A.>9u :.9 r&.G[.AȎ++ghˌȎ؎QV.Eء .=.E.G=s^Yó;% ;t;Unknown disk format .E.G.=.;%.9.E.;Gu6.9.;{.E.;Gu;No system file .G.E+Q Q++YY++.9u.6E.6;.=ÌȎؿA%&?% .8%tи b.6+һ.I+һ@+@Ѓ.K.I t(+s+.I@.K< Rk Z.Kþ< u<sV\ *LHDLȈD&>e%|D@|&c%D%&>e%ۃ&A%? D@        @ @ @ @   @           CPM SYSCCPM SYS.9 r&.G[.AȎ++ghˌȎ؎QV.Eء .=.E.G=s^Yó;% ;t;Unknown disk format .E.G.=.;%.9.E.;Gu6.9.;{.E.;Gu;No system file .MZiC TU                LD4.CMDHANDLE NOT OPEN FOR READING $HANDLE NOT OPEN OR INVALID $FILE LD4.CMD NOT FOUND $TOO MANY OPEN FILES $PATH SPECIFIES A VOLUME-ID OR READONLY OR DIRECTORY $BAD ACCESS CODE $TRANSFER TO DISK UNSUCCESSFUL $ENTER THE NUMBER OF SECTORS PER TRACK OF OUR DISK IN DECIMAL$ENTER DRIVE TO PUT LOADER ON 0 - 3 $PUT CPM DISK IN DRIVE if you wish to continue type y$ENTRY ERROR $ $=uP !=ui !=u != tw !m=u !=tY3 !Oغ=!r?!r% ! !,0 !瀴 !Q !< t#,0Yu !uAآAYu & !K ! !entry? CMP AL,'A'-'0' JB WRD1 ;not hex? SUB AL,'A'-10-'0' CMP AL,0FH JA WRD1 ;not hex? WRD4: MOV CL,4 SHL BP,CL OR BP,AX WRD5: IN AL,stat_rega AND AL,tx_rdy JZ WRD5 MOV AL,CH OUT tx_rega,AL JMP WRD1    ;Print Word in SI PWRD: MOV CH,4 ;print 4 nibbles PWRD1: IN AL,stat_rega AND AL,tx_rdy JZ PWRD1 ;port not ready? MOV CL,4 ROL SI,CL ;get the right nibble MOV AX,SI AND AL,0FH ADD AL,'0' CMP AL,'9' JBE PWRD2 ;ascii ok? ADD AL,7 PWRD2: OUT tx_rega,AL DEC CH JNZ PWRD1 ;more to do? ;now print a space PWRD3: IN AL,stat_rega AND AL,tx_rdy JZ PWRD3 MOV AL,' ' OUT tx_rega,AL JMP DI SIGNON1: MOV SI,OFFSET MESG1 PROMPT: MOV DI,OFFSET CMNDS JMP TXTOUT MESG1 DB 0CH,0AH,0DH DB ' SLICER memory test',0ah,0ah,0dh DB ' Ddddd enter data dddd',0dh,0ah DB ' Aaaaa enter address aaaa',0ah,0dh DB ' Sssss set segment register to ssss',0dh,0ah DB ' R read from location ssss:aaaa',0dh,0ah DB ' W Write dddd to location ssss:aaaa',0dh,0ah DB ' T test memory segment ssss',0dh,0ah DB ' E exit to main monitor',0ah,0dh MESG2 DB 0DH,0AH,'>'+80h PROMPT1: JMP PROMPT CMNDS: MOV DI,OFFSET CMDTST JMP CHRIN CMDTST: MOV AH,AL CMND0: IN AL,stat_rega AND AL,tx_rdy JZ CMND0 MOV AL,AH OUT tx_rega,AL ;echo character back to terminal CMP AL,'A' ;command option ? JZ GETADR CMP AL,'D' JZ GETDAT CMP AL,'E' JNZ NOTEE mov ax,data mov ds,ax assume ds:data mov reset_location,1234h jmp initialize assume ds:nothing NOTEE: CMP AL,'R' JZ DRAMRD CMP AL,'S' JZ DTSEG CMP AL,'T' JZ DRAMTST CMP AL,'W' jmp short DRAMWR CMND1: MOV SI,OFFSET MESG2 jmp short PROMPT1 ;D RAM write cycle DRAMWR: MOV AX,DX MOV [BX],AX IN AL,stat_rega AND AL,rx_rdy JZ DRAMWR jmp short CMND1 ;D RAM read cycle DRAMRD: MOV AX,DX MOV [BX],AX RDCYCL: MOV AX,[BX] IN AL,stat_rega AND AL,rx_rdy JZ RDCYCL jmp short CMND1 ;Get Address into bx GETADR: MOV SP,OFFSET ADR1 JMP WRD ADR1: MOV BX,BP jmp short CMND1 ;GET Data into dx GETDAT: MOV SP,OFFSET DAT1 JMP WRD DAT1: MOV DX,BP jmp short CMND1 ;Set data segment register DTSEG: MOV SP,OFFSET DTSEG1 JMP WRD DTSEG1: MOV DS,BP jmp short CMND1 ;D RAM test DRAMTST: MOV CX,SS XOR CX,-1 MOV SS,CX MOV BX,0 MOV BP,BX MTST1: MOV AX,CS:[BX] XOR AX,CX MOV DS:[BP],AX ;move data to ram CMP BX,4000h ;0FFFEH AND OFFSET MONTOP JNE MTST2 ;not at end of test pattern? MOV BX,-2 ;restart test pattern MTST2: INC BX INC BX INC BP INC BP JNZ MTST1 ;ram not full? MTST6: MOV BX,BP MTST3: MOV AX,DS:[BP] XOR AX,CX CMP AX,CS:[BX] JNZ MERROR MTST4: CMP BX,4000h ;0FFFEH AND OFFSET MONTOP JNE MTST5 ;not at end of test pattern? MOV BX,-2 ;restart test pattern MTST5: INC BX INC BX INC BP INC BP JNZ MTST3 ;not all tested? MTST9: IN AL,stat_rega TEST AL,tx_rdy JZ MTST9 MOV AL,'.' OUT tx_rega,AL IN AL,stat_rega AND AL,rx_rdy JZ MTSTA IN AL,rx_rega CMP AL,0DH JNZ MTST8 JMP CMND1 MTST8: CMP AL,'S'-40H JNZ MTSTA ;Continue testing? ;no, suspend test until console sends a ^S MTST7: IN AL,stat_rega AND AL,rx_rdy JZ MTST7 IN AL,rx_rega CMP AL,'S'-40H JNZ MTST7 ;no ^S? MTSTA: IN AL,in_reg ;read sense inputs on duart TEST AL,JUMP96 JZ MTST6 ;write once, then read only? jmp short DRAMTST ;write each cycle ;Show D Ram Error MERROR: XOR AX,CX MOV DX,AX ;save ref data MERR1: IN AL,stat_rega AND AL,tx_rdy JZ MERR1 MOV AL,0DH ;carriage return OUT tx_rega,AL MERR2: IN AL,stat_rega AND AL,tx_rdy JZ MERR2 MOV AL,0AH ;line feed OUT tx_rega,AL MERR3: MOV DI,OFFSET MERR4 MOV SI,BP ;ram address JMP PWRD MERR4: MOV DI,OFFSET MERR5 MOV SI,DX ;bad data JMP PWRD MERR5: MOV AX,CS:[BX] MOV CX,SS XOR AX,CX MOV SI,AX ;bad data MOV DI,OFFSET MERR6 JMP PWRD MERR6: MOV CX,SS IN AL,stat_rega AND AL,rx_rdy JNZ MERRA JMP MTST4 ;continue MERRA: IN AL,rx_rega CMP AL,0DH JNZ MERR7 JMP CMND1 MERR7: MOV DI,OFFSET MERR8 JMP CHRIN MERR8: MOV CX,SS CMP AL,0DH JNZ MERR9 JMP CMND1 MERR9: JMP MTST4 code ends end 35a79;=?A!CAEaGIKMOQ!SAUa   .286c page 60,132 name new_interface title Slicer Concurrnet BIOS Version 1.0A New Interface subttl Data areas .xlist page + include biosdata.asm subttl Macros page + .list ;---------------------------------------------------------------- ; Macros ;---------------------------------------------------------------- dp macro a dw offset a dw seg a endm set macro num,val mov w num,offset val mov w num+2,seg val endm boot_struc struc db 3 dup (?) our_name db 8 dup (?) cylinders dw ? heads db ? rw_cylinder dw ? wp_cylinder dw ? error_burst db ? step_rate1 db ? sectors dd ? drives db ? boot_struc ends subttl Function dispatcher page + ;---------------------------------------------------------------- ; Error codes ;---------------------------------------------------------------- bad_command equ 1 write_protect equ 3 record_not_fnd equ 4 dev_out_of_rng equ 8h crc_error equ 10h hardware_error equ 20h bad_seek equ 40h not_ready_error equ 080h d equ dword ptr w equ word ptr b equ byte ptr ;---------------------------------------------------------------- ; disk_flags ;---------------------------------------------------------------- disk_in_service equ 00000001b fop_waiting equ 00000010b ;floppy done f_nest equ 00000100b write_status equ 00001000b interuptable equ 00010000b sop_waiting equ 00100000b ;sasi done sasi_nest equ 01000000b disk_read_cmd equ 10011000b disk_write_cmd equ 10111000b ram_command equ 11000000b ; hd_control equ 01000000b ;enable retrys immediate error correction hd_read_cmd equ 8 hd_write_cmd equ 0ah ; disk type uninitialized equ 10000000b mini equ 00010000b double_density equ 00100000b double_track equ 01000000b sector_size_m equ 00001100b step_rate_m equ 00000011b concurrent_int equ 0f9h ;---------------------------------------------------------------- ; com_flags ;---------------------------------------------------------------- com1_waiting equ 00000001b com2_waiting equ 00000010b com3_waiting equ 00000100b com4_waiting equ 00001000b com5_waiting equ 00010000b com6_waiting equ 00100000b public new_call_init,new_hdisk public bootstrap,bootstrap1,bootstrap2 extrn old_load:near extrn port1_write:near,port2_write:near extrn port1_status:near,port2_status:near extrn port3_write:near,port4_write:near extrn port3_status:near,port4_status:near extrn set_up_port1:near,set_up_port2:near extrn set_up_port3:near,set_up_port4:near  extrn ibm_serial:far extrn disk_read:near,disk_write:near extrn disk_read1:near,disk_write1:near extrn sasi_io:near,sasi_io1:near extrn disk_reset:near extrn drive_mask:byte extrn new_video:far,new_keyboard:far extrn new_parallel:far,ibm_parallel:far extrn moninit:near boot_seg segment at 01200h org 0 boot_location label far boot_seg ends rom_seg segment at 0c800h org 0 rom_id label word page_sel dw ? rom_entry label far rom_seg ends cgroup group code code  segment byte public 'code' assume cs:cgroup ;---------------------------------------------------------------- ; Function dispatcher ; Dispatches calls to all new BIOS functions ; input: ; ah = channel # ; al = function # ; cx = transfer count ; dx:bx = starting block for disk and disk like devices ; es:si = buffer for all functions ; ; returns: ; al = status ; 0 = no error ; 1 = bad command ; 3 = write protect ; 4 = record not found ; 8 = device out of range(bad pointer in jump table) ; 10= crc error ; 20= hardware error ; 40= bad seek ; 80= not ready or time out ; ; cx = blocks successfully transfered ; bl = status on return On printer output ONLY ; ah,bx,dx destroyed unless data explicitly returned in register ; di,si,sp,bp,ds,es,ss unchanged ;---------------------------------------------------------------- internal_table label dword dp new_disk ;channel 0 dp new_hdisk ; " 1  dp new_port0_out ; " 2 dp new_port0_in ; " 3 dp new_port1_out ; " 4 dp new_port1_in ; " 5 dp new_video ; " 6 dp new_keyboard ; " 7 dp new_port2_out ; " 8 dp new_port2_in ; " 9 dp new_port3_out ; " a dp new_port3_in ; " b ; dp new_port4_out ; dp new_port4_in ; dp new_port5_out ; dp new_port5_in dp new_parallel ; " c ; dp new_time dp equipment ; " d dp ibm_parallel ; " e dp ibm_seria  l ; " f ; dp ibm_serial_in ; " 10 internal_limit equ (this byte - internal_table)/4 dpb_ptr dw dpb0 dw dpb1 dw dpb2 dw dpb3 new_call_init proc near assume ds:data,es:vectors set vector_f8,dispatch mov al,(uninitialized or step_rate_m) mov d_type_0,al ;15ms step rate to boot with mov d_type_1,al mov d_type_2,al mov d_type_3,al xor al,al mov port1_head,al mov port1_tail,al mov port2_head,al mov port2_tail,al mov port3_head,al mov port3_tail,al mov port4_head,al mov port4_tail,al mov com_hold_enable,0ffh ;enable hold on all channels mov com_hold,0 ;clear holds on all channels mov external_limit,0 mov device_numbers,0 ;floppy 1 mov device_numbers+(2*1),0 ;floppy 2 mov device_numbers+(2*2),0 ;floppy 3 mov device_numbers+(2*3),0 ;floppy 4 mov device_numbers+(2*4),101h ;hard 1 mov device_numbers+(2*5),101h ;hard 2 mov device_numbers+(2*6),203h ;console mov device_numbers+(2*7),405h ;printer mov device_numbers+(2*8),203h ;aux mov device_numbers+(2*9),0d0dh ;equipment mov device_numbers+(2*0ah),203h ;port 1 mov device_numbers+(2*0bh),405h ;port 2 mov device_numbers+(2*0ch),809h ;port 3 mov device_numbers+(2*0dh),0a0bh ;port 4 mov device_numbers+(2*11h),0c0ch ;parallel printer ;---------------------------------------------------------------- ; get parameters from hard_disk ;---------------------------------------------------------------- mov ax,484h ;reset sasi int 0f8h  mov hdpb0.step_rate,0ffh mov hdpb1.step_rate,0ffh mov cx,5000 test_rdy_loop: push cx mov ax,480h ;sasi write mov bp,cgroup mov si,offset test_0_ready mov cx,0 int 0f8h pop cx cmp al,not_ready_error jne nns jmp no_sasi nns: or al,al jz hd0_ready loop test_rdy_loop mov cx,1 jmp no_sasi ;not ready hd0_ready: mov bp,cgroup mov si,offset recal_0 mov cx,0 mov ax,480h int 0f8h or al,al je nns3 jmp no_sasi ;not ready nns3: mov hd_last_drive,0 ;don't send invalid parameters mov cx,1 mov bx,0 mov dx,0 mov si,0 mov ax,1000h mov es,ax mov ax,400h ;load first sector from drive 0 int 0f8h ;to get disk parameters or al,al jz nns4 jmp no_sasi nns4: mov di,1000h mov ax,es:[si].cylinders xchg ah,al stos b [di] xchg ah,al stos b [di] mov al,es:[si].heads stos b [di] mov ax,es:[si].rw_cylinder xchg ah,al stos b [di] xchg ah,al stos b [di] mov ax,es:[si].wp_cylinder  xchg ah,al stos b [di] xchg ah,al stos b [di] mov al,es:[si].error_burst stos b [di] mov bl,es:[si].step_rate1 mov di,si mov si,1000h mov ax,482h int 0f8h ;set parameters cmp es:[di].drives,2 je nns6 jmp no_sasi ;only one disk nns6: mov cx,5000 test_rdy_loop1: push cx mov ax,480h ;sasi write mov bp,cgroup mov si,offset test_1_ready mov cx,0 int 0f8h pop cx cmp al,not_ready_error jne nns1 jmp no_sasi nns1: or al,al jz hd1_ready loop test_rdy_loop1 mov cx,1 jmp no_sasi ;not ready hd1_ready: mov bp,cgroup mov si,offset recal_1 mov cx,0 mov ax,480h int 0f8h or al,al jne no_sasi ;not ready mov hd_last_drive,1 ;don't send invalid parameters mov cx,1 mov bx,0 mov dx,0 mov si,0 mov ax,1000h mov es,ax mov ax,500h ;load first sector from drive 1 int 0f8h ;to get disk parameters or al,al jnz no_sasi mov di,1000h mov ax,es:[si].cylinders xchg ah,al stos b [di] xchg ah,al stos b [di] mov al,es:[si].heads stos b [di] mov ax,es:[si].rw_cylinder xchg ah,al stos b [di] xchg ah,al stos b [di] mov ax,es:[si].wp_cylinder xchg ah,al stos b [di] xchg ah,al stos b [di] mov al,es:[si].error_burst stos b [di] mov bl,es:[si].step_rate1 mov si,1000h mov ax,582h int 0f8h ;set parameters ; no_sasi: get_param_done: ret assume es:nothing,ds:data new_call_init endp bootstrap proc near call old_load xor ax,ax call bootstrap1 ;boot drive 0 mov disk_time_out,100 ;change time out longer call bootstrap2 ;boot hard drive call romboot jmp moninit bootstrap endp romboot proc near push ds mov ax,rom_seg mov ds,ax assume ds:rom_seg mov page_sel,0 ;select page 0 of rom cmp rom_id,0aa55h ;is it valid jne no_rom jmp rom_entry no_rom: pop ds assume ds:data ret romboot endp bootstrap1 proc near xor ah,ah mov bp,ax ;drive to boot from mov ah,al m  ov al,84h int 0f8h ;getparameters from drive or al,al je boot2 jmp boot_error boot2: mov bl,1 mov cl,1 mov ax,bp mov ah,al mov al,82h int 0f8h ;set parameters boot3: mov cx,1 xor dx,dx xor bx,bx mov si,boot_seg mov es,si mov si,offset boot_location mov ax,bp mov ah,al mov al,0 int 0f8h ;read first sector or al,al jnz boot_error mov disk_time_out,100 ;change time out longer jmp boot_location boot_error: ret bootstrap1 endp bootstrap2 proc near mov cx,4 boot13: push cx mov cx,1 xor dx,dx xor bx,bx mov si,boot_seg mov es,si mov si,offset boot_location mov ax,400h int 0f8h ;read first sector or al,al jz boot14 pop cx loop boot13 mov si,cs mov es,si mov si,offset boot_mess mov cx,boot_mess_len mov ax,601h int 0f8h ;write mess ret boot14: mov bp,4 jmp boot_location boot_mess db 'Boot Failure.',0dh,0ah boot_mess_len equ (this byte - boot_mess) bootstrap2 endp dispatch proc far sti cld push ds push es push bp push si push di push bx mov bx,data mov ds,bx assume ds:data cmp ah,0feh jae c_maintain ;update dispatch jump tables mov di,ax shr di,7 and di,not 1b ;channel #*2 in di mov bx,device_numbers[di] ;bx has channel descriptor test al,1 je d1 xchg bh,bl d1: xor bh,bh ;bl has device # cmp bl,080h jae external_call cmp bl,internal_limit jae dev_out_of_range shl bx,2 mov di,bx ;di is offset into jump table pop bx call internal_table[di] ;call internal function jmp dispatch_done external_call: sub bl,080h cmp bl,external_limit jae dev_out_of_range shl bx,2 lds di,external_table add di,bx pop bx call d ds:[di] ;call external function jmp dispatch_done ;---------------------------------------------------------------- ; To reassign device numbers to a channel a call should be made ; to channel FF. ; ; Entry: ; al: channel number ;  bl: new input device ; bh: new output device ; Exit ; bl: old input device ; bh: old output device ; ; ;---------------------------------------------------------------- c_maintain: cmp ah,0feh je c_maintain1 pop bx ;al has channel number xchg ax,bx ;bh bl have new device numbers xor bh,bh ;for input and output shl bx,1 ;returns bx old device numbers xchg device_numbers[bx],ax mov bx,ax jmp short dispatch_done ;---------------------------------------------------------------- ; To install external devices A call should be made to ; channel FE. ; ; Entry: ; es:si A buffer big enough to hold 4-byte pointers to all ; external functions. ; dx:bx A pointer to the Entry point of the function. ; Exit: ; bl: device number assigned to the device. ;---------------------------------------------------------------- c_maintain1: pop bx push ds mov bp,si mov cl,external_limit xor ch,ch cld lds di,external_table mov ax,ds or ax,di xchg si,di jz c_m1_new shl cx,1 rep movs w [di],w [si] ;copy old table to new table c_m1_new: pop ds mov ax,bx stos w [di] mov ax,dx stos w [di] ;put new pointer in table mov w external_table,bp mov w external_table+2,es mov bl,external_limit inc external_limit add bl,080h jmp short dispatch_done dev_out_of_range: mov al,dev_out_of_rng d_end: pop bx dispatch_done: pop di pop si pop bp pop es pop ds iret dispatch endp subttl New Disk function calls page + ;---------------------------------------------------------------- ; New Disk function calls ; ; input: ; al = function # ; 0 = read logical sectors from disk ; 1 = write logical sectors to disk ; cx = block count ; bx = starting block ; es:si = buffer ; ; 80= general purpose read ; 81= general purpose write ; bl = head number ; cl = number of blocks to transfer ; ch = sector number ; dl = track number ; dh = command for 1797 fdc ; ; 82= set disk parameters marked with * ; 83= set all disk parameters ; 84= get disk parameters from disk (analyse format) ; 85= get current disk parameters ; bl = number of heads * ; cl = sectors per track * ; dl = disk type byte ; uninitialized 10000000b ; mini 00010000b ;    double_density 00100000b * ; double_track 01000000b * ; sector_size 00001100b * ; step_rate 00000011b ; ; 86= set time out values ; bx = select count ; cx = motor count ; dx = contorller count ; ; 87= reset disk system ; stops current operation and forces a restore before ; next operation ; ; 79h= set or reset head settle bit and spinup time for ; motor on routine for floppy disk drives ; bx = 0 turn off head settle bit else turn on ; cx = length of spin up loop set long on boot ; ; output ; al = status ;---------------------------------------------------------------- new_disk proc far mov drive_number,ah cmp al,1 jbe ndrw cmp al,080h jb nd3 jmp nddp nd3: cmp al,79h jnz badcont jmp disk_speed ;change head settle and spinup time badcont: mov al,bad_command ;bad command ret ndrw: mov function_ptr,offset disk_read1 mov function_cmd,disk_read_cmd or al,al ;setup pointer to function jz nd1 mov function_ptr,offset disk_write1 mov function_cmd,disk_write_cmd nd1: mov al,settle ;JONATHAN ADDED THIS 3/26 and al,4 ;and out garbage or function_cmd,al mov nd_error_flag,0 mov al,ah mov di,ax and di,3h shl di,1 mov di,dpb_ptr[di] ;di points to dpb for drive mov ax,bx ;ax starting sector div [di].sectors_per_trk inc ah mov sector_number,ah xor ah,ah div [di].number_of_heads mov disk_track,al mov head_number,ah mov bp,cx ;store count in bp instead of cx mov nd_sector_count,cx ;save count so it can be returned to caller nd_xfer_loop: mov bx,si ;buffer address to bx mov al,[di].sectors_per_trk sub al,sector_number inc al ;ax has number of sectors that can be transfered xor ah,ah cmp ax,bp jae last_xfer mov num_of_sectors,al mov f_return,offset nd_cont or disk_flags,f_nest mov temp_ax,ax ;save ax mov al,function_cmd jmp [function_ptr] nd_cont: mov ax,temp_ax ;restore ax cmp al,num_of_sectors jne nd_error ; cmp diskette_status,0 jne nd_error sub bp,ax ;adjust sector count mul sector_size ;sector size is set by preceding disk op add si,ax ;adjust buffer pointer jnc nd2 mov ax,es add ax,1000h ;if carry set inc es mov es,ax nd2: inc head_number mov al,head_number cmp al,[di].number_of_heads jl no_track_increment inc disk_track mov head_number,0 no_track_increment: mov sector_number,1 jmp nd_xfer_loop last_xfer: and disk_flags,not f_nest mov ax,bp mov num_of_sectors,al mov f_return,offset nd_cont1 mov al,function_cmd jmp [function_ptr] nd_cont1: cmp nd_error_flag,0 ;if error has occoured handle differently jne nd9 mov al,num_of_sectors xor ah,ah sub bp,ax mov cx,nd_sector_count sub cx,bp mov al,diskette_status ret nd9: mov cx,nd_sector_count sub cx,bp ;bp has block count from before error mov al,nd_error_flag ;status from error ret nd_error: mov al,num_of_sectors xor ah,ah sub bp,ax ;adjust block count mov al,diskette_status mov nd_error_flag,al ;save status and flag error mov function_cmd,ram_command mov function_ptr,offset disk_read1 mov bx,0fffeh mov es,bx ;set transfer address to point to rom so ;we won't destroy anything important jmp last_xfer ;read address mark is just a dummy command ;to get us out of the interupt driven structure ;of this part of the code nddp: sub al,080h jnz nd11 jmp nd_gpr ;general purpose read nd11: dec al jnz nd12 jmp nd_gpw ;general purpose write nd12: dec al jz nd_sdp ;set disk parameters dec al jz nd_sdp1 ;set all disk parameters dec al jnz nd10 jmp nd_gdp ;get disk parameters from disk nd10: dec al jz nd_gcdp dec al jz nd_sto dec al jz nd_reset ;disk reset mov al,bad_command ret nd_sto: mov motor_count,cx mov select_count,bx mov disk_time_out,dx mov al,0 ret nd_gcdp: mov al,ah xor ah,ah mov di,ax mov dl,d_type_0[di] ;get disk type shl di,1 mov di,dpb_ptr[di] ;di points to dpb for drive mov bl,[di].number_of_heads mov cl,[di].sectors_per_trk mov al,0 ret nd_sdp: and dl,not (mini or uninitialized or step_rate_m) mov al,ah ;clear unwanted bits xor ah,ah mov di,ax and d_type_0[di],mini or uninitialized or step_rate_m ;clear bits to be   set or d_type_0[di],dl ;set disk type shl di,1 mov di,dpb_ptr[di] ;di points to dpb for drive mov [di].number_of_heads,bl mov [di].sectors_per_trk,cl mov al,0 ret nd_sdp1: mov al,ah xor ah,ah mov di,ax mov d_type_0[di],dl ;set disk type shl di,1 mov di,dpb_ptr[di] ;di points to dpb for drive mov [di].number_of_heads,bl mov [di].sectors_per_trk,cl mov al,0 ret nd_reset: call disk_reset mov al,0 ret nd_gpr: mov disk_track,dl mov head_number,bl mov sector_number,ch mov num_of_sectors,cl mov al,settle and al,4 ;ADDED BY JONATHAN or dh,al mov al,dh mov bx,si int 0fdh ;file bios.ams disk_read mov cl,num_of_sectors mov al,diskette_status ret nd_gpw: mov disk_track,dl mov head_number,bl mov sector_number,ch mov num_of_sectors,cl mov al,settle and al,4 ;ADDED BY JONATHAN or dh,al mov al,dh mov bx,si int 0fdh ;file bios.asm disk_write mov cl,num_of_sectors mov al,diskette_status ret ; nd_gdp: mov drive_number,ah mov bl,ah xor bh,bh mov di,bx mov al,cgroup:drive_mask[di] or recal_required,al ;force recal on drive mov num_of_sectors,1 mov disk_track,2 mov head_number,1 and d_type_0[di],not double_track test d_type_0[di],uninitialized jz nd7 ;set double density mini if uninitialized or d_type_0[di],mini or double_density nd7: mov ax,data mov es,ax mov al,ram_command mov bx,offset am_buffer int 0fdh ; call disk_read ;read address mark from track 2 head 1 ;of a dbl density 5 inch disk cmp diskette_status,0 jne nd4 jmp found_it nd4: mov head_number,0 ;try head 0 mov num_of_sectors,1 mov bx,offset am_buffer mov al,ram_command int 0fdh ; call disk_read cmp diskette_status,0 jne nd5 jmp found_it nd5: mov head_number,1 mov num_of_sectors,1 xor d_type_0[di],double_density mov bx,offset am_buffer mov al,ram_command ;try other density head 1 int 0fdh ; call disk_read cmp diskette_status,0 jne nd6 jmp found_it nd6: mov head_number,0 ;try head 0 mov num_of_sectors,1 mov bx,offset am_buffer mov al,ram_command int 0fdh ; call disk_read cmp diskette_status,0 je found_it test d_type_0[di],uninitialized jz not_found mov head_number,1 mov num_of_sectors,1 xor d_type_0[di],mini mov bx,offset am_buffer mov al,ram_command ;try other size head 1 int 0fdh ; call disk_read cmp diskette_status,0 je found_it mov head_number,0 mov num_of_sectors,1 mov bx,offset am_buffer mov al,ram_command ;try head 0 int 0fdh ; call disk_read cmp diskette_status,0 je found_it mov head_number,1 mov num_of_sectors,1 xor d_type_0[di],double_density mov bx,offset am_buffer mov al,ram_command ;try other density head 1 int 0fdh ; call disk_read cmp diskette_status,0 je found_it mov head_number,0 mov num_of_sectors,1 mov bx,offset am_buffer mov al,ram_command ;try head 0 int 0fdh ; call disk_read cmp diskette_status,0 je found_it not_found: mov al,not_ready_error ret found_it: and d_type_0[di],not uninitialized mov al,am_size shl al,2 and al,sector_size_m and d_type_0[di],not sector_size_m or d_type_0[di],al ;set sector size and d_type_0[di],not double_track cmp am_track,2 je nd8 or d_type_0[di],double_track nd8: mov dl,d_type_0[di] mov bl,head_number inc bl mov al,0 ret ;***************************************************** disk_speed: mov spin_up,cx cmp bx,0 jz setle_off or settle,4 ;head settle on jmp spdone setle_off: and settle,0fbh ;head settle off spdone: and settle,7fh ;high bit flag need to spin up ret new_disk endp subttl New Hard Disk function calls page + ;---------------------------------------------------------------- ; New Hard Disk function calls ; ; al = function # ; 0 = read logical sectors from disk ; 1 = write logical sectors to disk ; cx = block count ; dl:bx = starting block ; es:si = buffer ; ; 80= general purpose sasi read ; 81= general purpose sasi write ; es:bx = buffer ; bp:si = control block ; cx = block count ; dx = block size ; ; 82 = set all disk parameters ; 83 = get disk parameters ; es:si = 8 byte area to fill with: ; msb number of sectors ; lsb nu  mber of sectors ; number of heads ; msb starting reduced write cylinder ; lsb starting reduced write cylinder ; msb starting write precomp cylinder ; lsb starting write precomp cylinder ; maximum length of error burst to be corrected ; bl = step rate byte ; ; 84= reset sasi system ;---------------------------------------------------------------- hdpb_ptr dw hdpb0 dw hdpb1 new_hdisk proc far sub ah,4 cmp ah,1 jbe hd1 mov al,dev_out_of_rng xor cx,cx ret hd1: cmp al,1 jbe hd2 cmp al,80h jb hd10 jmp nhd_ef hd10: mov al,bad_command xor cx,cx ret hd2: mov hd_ax_temp,ax cmp hd_last_drive,ah je hd_do_op mov hd_last_drive,ah mov hd_si_temp,si mov hd_bx_temp,bx mov hd_cx_temp,cx mov hd_dx_temp,dx mov hd_es_temp,es ;this was a poor fix on a problem running two hard disks and should ;be changed some day jonathan 12-10-86 ; push ax ; mov al,0ffh ; mov dx,100h ;sasi select port ; out dx,al ;deselect drive ; ; mov al,0 ; mov dx,102h ;sasi reset port ; out dx,al ;pulse reset pin ; mov al,0ffh ;on controller ; out dx,al ; ; pop ax ;********************************************* mov di,ax shr di,7 and di,10b mov bx,data mov es,bx mov bx,hdpb_ptr[di] mov ax,200h ;write 1 block of 8 bytes to controler mov cx,1 mov dx,8 mov bp,cgroup mov si,offset set_parameters or disk_flags,sasi_nest mov sasi_return,offset hd3 jmp sasi_io1 hd3: or al,al mov si,hd_si_temp mov dx,hd_dx_temp mov cx,hd_cx_temp mov bx,hd_bx_temp mov ax,hd_ax_temp mov es,hd_es_temp jz hd_do_op jmp hd_error hd_do_op: mov di,ax shr di,7 and di,10b mov di,hdpb_ptr[di] and dl,00011111b shl ah,5 and ah,0100000b or ah,dl or al,al jz hd_read_13 mov hd_command,hd_write_cmd mov al,2 ;write disk jmp short hd_do_op1 hd_read_13: mov hd_command,hd_read_cmd mov al,1 ;read from disk hd_do_op1: mov hd_command+1,ah ;starting block mov hd_command+2,bh mov hd_command+3,bl mov hd_command+4,cl ;block count mov bl,[di].step_rate and bl,0fh or bl,hd_control mov hd_command+5,bl mov bp,data mov bx,si mov si,offset hd_command mov dx,200h ;block size and disk_flags,not sasi_nest mov sasi_return,offset hd6 mov ah,al ;command to ah jmp sasi_io1 hd6: or al,al jz hd19 jmp hd_error hd19: ret  hd_error: op_error: mov bp,cgroup mov ax,hd_ax_temp or ah,ah jnz hde1 mov si,offset req_status_0 jmp short hde2 hde1: mov si,offset req_status_1 hde2: mov ax,data mov es,ax mov bx,offset hd_command mov cx,1 mov dx,4 mov ah,1 and disk_flags,not sasi_nest mov sasi_return,offset hd7 jmp sasi_io1 hd7: or al,al jz hd8 jmp hard_error hd8: mov al,hd_command ;has status byte from controler status_xlat macro a,b local c cmp al,a jne c  or sasi_status,b c: nop endm status_xlat 1,not_ready_error status_xlat 2,bad_seek status_xlat 3,not_ready_error status_xlat 4,not_ready_error status_xlat 6,bad_seek status_xlat 11h,crc_error status_xlat 12h,record_not_fnd status_xlat 15h,bad_seek status_xlat 19h,not_ready_error status_xlat 1ah,not_ready_error status_xlat 20h,not_ready_error status_xlat 21h,not_ready_error status_xlat 30h,not_ready_error status_xlat 31h,not_ready_error status_xlat 32h,not_ready_error ret hard_error: or sasi_status,hardware_error ret nhd_ef: sub al,80h jz sasi_read dec al jz sasi_write dec al jz set_hdp dec al jz get_hdp dec al jz sasi_reset mov al,bad_command xor cx,cx ret sasi_read: mov ah,1 call sasi_io ret sasi_write: mov ah,2 call sasi_io ret set_hdp: mov di,ax mov hd_last_drive,0ffh shr di,7 and di,10b mov di,hdpb_ptr[di] mov [di].step_rate,bl mov ax,es mov bx,ds mov es,bx mov ds,ax mov cx,4 rep movsw ret get_hdp: mov di,ax shr di,7 and di,10b mov di,hdpb_ptr[di] mov bl,[di].step_rate xchg si,di mov cx,4 rep movsw ret sasi_reset: mov ah,0 mov hd_last_drive,0ffh ;neither drive was last used call sasi_io ret new_hdisk endp set_parameters db 0ch,0,0,0,0,0 ;sasi set parameters command req_status_0 db 3,0,0,0,0,0 ;sasi reqest status command req_status_1 db 3,20h,0,0,0,0 ;sasi reqest status command recal_0 db 1,0,0,0,0,0 ;sasi   recal drive 0 recal_1 db 1,20h,0,0,0,0 ;sasi recal drive 1 test_0_ready db 0,0,0,0,0,0 ;test drive 0 ready test_1_ready db 0,20h,0,0,0,0 ;test drive 1 ready subttl New Serial port calls page + ;---------------------------------------------------------------- ; New Serial Port function calls ; ; input: ; al = function # ; 0 = input characters ; 1 = output characters ; cx = count ; es:si = buffer ; ; 2 = input status ; 3 = output status ; es:si = buffer (next charecter to be read for input) ; ; 5 = setup serial port ; bl bits 7,6,5 baud rate 4,3 parity 2 stopbit 1 0 char length ; 0=110 x0 = none 0 =1 10 = 7 ; 1=150 01 = odd 1 = 2 11 = 8 ; 2=300 11 = even ; 3=600 ; 4=1200 ; 5=2400 ; 6=4800 ; 7=9600 ; ; 81= change hold enable (XON XOFF) ; bl= 0 enable holds else disable ; ; output ; al = status ;---------------------------------------------------------------- new_port0_in proc far mov di,offset port1_buf mov dl,2 ;flag #2 mov dh,com1_waiting jmp short npi1 new_port1_in: mov di,offset port2_buf mov dl,3 ;flag #3 mov dh,com2_waiting npi1: or al,al jnz npi_status jcxz npi_done npi2: mov bl,[di].tail cmp bl,[di].head jne npi_got_char mov al,dl ;dl has flag number mov ah,0 or com_flags,dh ;com_waiting int concurrent_int ;wait for charecter jmp npi2 npi_got_char: xor bh,bh mov al,[di][bx] mov es:[si],al inc si inc bl and bl,0fh mov [di].tail,bl loop npi2 mov al,0 npi_done: ret npi_status: mov al,0 mov bl,[di].tail cmp bl,[di].head jne npis_done mov al,not_ready_error npis_done: xor bh,bh ;JONATHAN 4,1,86 mov ah,[di][bx] mov es:[si],ah ret new_port0_in endp new_port2_in proc far mov di,offset port3_buf mov dl,4 ;flag #4 mov dh,com3_waiting jmp short npi21 new_port3_in: mov di,offset port4_buf  mov dl,5 ;flag #5 mov dh,com4_waiting npi21: or al,al jnz npi2_status jcxz npi2_done npi22: mov bl,[di].tail cmp bl,[di].head jne npi2_got_char mov al,dl ;dl has flag number mov ah,0 or com_flags,dh ;com_waiting int concurrent_int ;wait for charecter jmp npi22 npi2_got_char: xor bh,bh mov al,[di][bx] mov es:[si],al inc si inc bl and bl,0fh ;JONATHAN 7-16-86 mov [di].tail,bl loop npi22 mov al,0 npi2_done: ret npi2_status: mov al,0  mov bl,[di].tail cmp bl,[di].head jne npis2_done mov al,not_ready_error npis2_done: mov ah,[di][bx] mov es:[si],ah ret new_port2_in endp new_port0_out proc far cmp al,81h je npo4 cmp al,1 jne npo1 cld jcxz npo2 npo3: lods b es:[si] call port1_write loop npo3 xor bl,bl jmp short npo2 npo1: cmp al,3 je npo50 cmp al,5 jne npo2 call set_up_port1 npo50: call port1_status npo2: ret npo4: or bl,bl jz npo5 and com_hold_enable,not 1 ret npo5: or com_hold_enable,1 ret new_port0_out endp new_port1_out proc far cmp al,81h je npo14 cmp al,1 jne npo11 cld jcxz npo12 npo13: lods b es:[si] call port2_write loop npo13 xor bl,bl jmp short npo12 npo11: cmp al,3 je npo51 cmp al,5 jne npo12 call set_up_port2 npo51: call port2_status npo12: ret npo14: or bl,bl jz npo15 and com_hold_enable,not 10b ret npo15: or com_hold_enable,10b ret new_port1_out endp new_port2_out proc far cmp al,81h je npo24 cmp al,1 jne npo21 cld jcxz npo22 npo23: lods b es:[si] call port3_write loop npo23 xor bl,bl jmp short npo22 npo21: cmp al,3 je npo52 cmp al,5 jne npo22 call set_up_port3 npo52: call port3_status npo22: ret npo24: or bl,bl jz npo25 and com_hold_enable,not 100b ret npo25: or com_hold_enable,100b ret new_port2_out endp new_port3_out proc far cmp al,81h je npo34 cmp al,1 jne npo31 cld  jcxz npo32 npo33: lods b es:[si] call port4_write loop npo33 xor bl,bl jmp short npo32 npo31: cmp al,3 je npo53 cmp al,5 jne npo32 call set_up_port4 npo53: call port4_status npo32: ret npo34: or bl,bl jz npo35 and com_hold_enable,not 1000b ret npo35: or com_hold_enable,1000b ret new_port3_out endp ;---------------------------------------------------------------- ; Equipment ; returns bx = memory size (k bytes) ;---------------------------------  ------------------------------- equipment proc far mov bx,memory_size ret equipment endp code ends end interrupt off buffer 100 MODE PROMPT ON TOLERATE ON WRITE yY=UrEPROM EXE fr r=HDBOOT ASM [k K .286c .xlist include biosdata.asm .list ;********************************************************************* ; ; K E Y B O A R D I / O ; ; ; These routines provide the keyboard interfice for the Slicer ; using the the Slicer PC expansion board, and are accessed using ; INT 16H. ; ; AH = 0: Read next ASCII charecter from keyboard. ; Return result in AL, with scan code in AH. ; ; AH = 1: Set Z flag to indicate if an ascii character is ; available to be read. ; ZF = 1 No code ready ; ZF = 0 code ready and in ax. ; ; AH = 2: Return shift status in AL. ; ; AH = FF: Return 8 bit charecter in AL. ; If non-ASCII zero is returned then on next call the scan code ; ; AH = FE: Set bits on port 300h. ; AL = mask of bits to set. ; ; AH = FD: Clear bits on port 300h. ; AL = Mask of bits to clear. ;********************************************************************* b equ byte ptr w equ word ptr uart_base equ 80h uart_input equ uart_base+1ah use_keyboard equ 20h port_status_v equ 11110111b ;set ibm io channel to b0000 keyboard_port equ 300h ;CAN BE CHANGED TO 60 WITH BIOS.ASM clock_line equ 40h data_line equ 80h num_key equ 69 scroll_key equ 70 alt_key equ 56 ctl_key equ 29 caps_key equ 58 left_shift equ 42 right_shift equ 54 ins_key equ 82 del_key equ 83 reset_code equ 0aah alt_key_rel equ alt_key+80h ctl_key_rel equ ctl_key+80h left_shift_rel equ left_shift+80h right_shift_rel equ right_shift+80h ins_mask equ 80h caps_mask equ 40h num_mask equ 20h scroll_mask equ 10h alt_mask equ 8 ctl_mask equ 4 left_mask equ 2 right_mask equ 1 nshiftkey_mask equ 1 ; ; intcr equ 0ff3ch eoir equ 0ff22h eoiv equ 8000h intcrv equ 15h ;priority 5 level trigered intcr_mask equ 0fh break_int equ 01bh ; ; extrn initialize:near public new_keyboard public keyboard_init set1 macro num,val mov w num,offset val mov w num+2,seg val endm cgroup group code code segment public byte 'code' assume cs:cgroup,es:vectors,ds:data ; ; Install is called on power up to initialize the interupt vectors, ; and initialize the keyboard. ; keyboard_init proc near xor ax,ax mov es,ax set1 vector_9,interupt set1 vector_e,interupt2 set1 vector_1b,interupt1 ;iret mov buffer_tail,offset kb_buffer mov buffer_head,offset kb_buffer mov byte_flag,0  mov dx,intcr mov ax,intcrv out dx,ax mov port_status,port_status_v mov dx,keyboard_port mov al,port_status or al,data_line and al,not clock_line ;data line high clock line low out dx,al mov port_status,al mov cx,30000 delay: loop delay ;20 ms delay(actually quite a bit more) mov al,port_status or al,clock_line and al,not data_line ;data line low clock line high out dx,al or al,data_line ;data line high out dx,al mov port_status,al mov shift_status,left_mask ;left_shift_rel=0aah mov key_int_enable,0ffh ;let only one interupt happen xor cx,cx sti reset_loop: test shift_status,left_mask loopnz reset_loop jnz no_install mov key_int_enable,0 ;let all interupts through mov dx,intcr mov ax,intcrv out dx,ax ;re enable interupts set1 vector_16,keyboard_io mov b device_numbers+(2*010h),7 in al,uart_input ;install keyboard in new call system test al,use_keyboard jz no_install1 mov b device_numbers+(2*6),7 ;install keyboard as con inupt mov key_status2,0 ;Jonathan for ctrl numlock pause no_install1: ret no_install: mov dx,intcr mov ax,intcr_mask out dx,ax ret keyboard_init endp assume es:nothing ; ; ; Function dispatcher for int 16h ; Int 16h. ; keyboard_io proc far sti ;intrupts back on push ds push bx push dx mov dx,data mov ds,dx or ah,ah jnz k_io1 jmp read_char16 k_io1: cmp ah,1 je read_status cmp ah,2   je read_shift cmp ah,0ffh je read_char8 cmp ah,0feh je set_bits cmp ah,0fdh je reset_bits exit: pop dx pop bx pop ds iret read_status: cli mov bx,buffer_head cmp bx,buffer_tail ;set z flag for status mov ax,[bx] sti pop dx pop bx pop ds ret 2 keyboard_io endp read_shift: mov al,shift_status jmp exit read_char8 proc near rc8_poll: sti nop cli mov bx,buffer_head cmp bx,buffer_tail je rc8_poll mov ax,[bx]  or al,al jnz rc8_ascii cmp byte_flag,0ffh je rc8_high_byte mov byte_flag,0ffh jmp short rc8_exit rc8_high_byte: mov al,ah rc8_ascii: inc bx ;check for rollover inc bx cmp bx,offset kb_buffer_end jne rc8_inc_buf mov bx,offset kb_buffer ;reset buffer to start rc8_inc_buf: mov buffer_head,bx mov byte_flag,0 ;clear hi lo read flag rc8_exit: sti jmp exit read_char8 endp set_bits: cli or al,port_status mov port_status,al mov dx,keyboard_port out dx,al sti jmp exit reset_bits: cli not al and al,port_status mov port_status,al mov dx,keyboard_port out dx,al sti jmp exit read_char16 proc near sti nop cli mov bx,buffer_head cmp bx,buffer_tail je read_char16 mov ax,[bx] inc bx inc bx cmp bx,offset kb_buffer_end jne rc16_inc_buf mov bx,offset kb_buffer rc16_inc_buf: mov buffer_head,bx mov byte_flag,0 ;clear hi lo read flag sti jmp exit read_char16 endp ;---------------------------------------------------------------- ; New keyboard function calls ; ; input: ; al = function # ; 0 = input characters ; cx = count ; es:si = buffer ; ; 2 = input status ; es:si = buffer (next charecter to be read for input) ; output ; al = status ;---------------------------------------------------------------- new_keyboard proc far mov di,si or al,al ;read characters jnz nk1 jcxz nk5  push cx nk4: mov ah,-1 int 16h ;read 8 bit char cld stos b [di] loop nk4 pop cx nk5: mov al,0 ret nk1: cmp al,2 ;status jne nk2 mov ah,1 int 16h ;status call pushf cli ;changed 3 - 9 - 87 cmp byte_flag,0 sti je nk12 mov al,ah ;end change 3 - 9 - 87 nk12: stos b [di] mov al,0 popf jnz nk9 mov al,80h ;not ready nk9: ret nk2: mov al,1 ;bad command ret new_keyboard endp shift_keys db 0 db right_shift ;look up for shift key scan codes db left_shift db ctl_key db alt_key db scroll_key db num_key db caps_key db ins_key db right_shift_rel db left_shift_rel db ctl_key_rel db alt_key_rel sk_len equ this byte - shift_keys - 1 set equ 0 clear equ 2 toggle equ 4 bit_functions dw set_function ;jump table for shift mask functions dw clear_function dw toggle_function shift_functions db 0,0 db right_mask,set ;action taken for corresponding db left_mask,set ;values in shift keys db ctl_mask,set db alt_mask,set db scroll_mask,toggle db num_mask,toggle db caps_mask,toggle db ins_mask,toggle db right_mask,clear db left_mask,clear db ctl_mask,clear db alt_mask,clear ;look up tables for non-shift keys ;format for table is ascii code,(1, or scan_code if ascii code is 0) ;normal n_table db 27,1,'1',1,'2',1,'3',1,'4',1,'5',1,'6',1,'7',1 db '8',1,'9',1,'0',1,'-',1,'=',1,8,1,9,1,'q',1,'w',1,'e',1 db 'r',1,'t',1,'y',1,'u',1,'i',1,'o',1,'p',1,'[',1,']',1 db 13,1,0,0,'a',1,'s',1,'d',1,'f',1,'g',1,'h',1,'j',1 db 'k',1,'l',1,';',1,39,1,'`',1,0,0,'\',1,'z',1,'x',1 db 'c',1,'v',1,'b',1,'n',1,'m',1,',',1,'.',1,'/',1,0,0 db '*',1,0,0,32,1,0,0,0,59,0,60,0,61,0,62,0,63,0,64,0,65 db 0,66,0,67,0,68,0,0,0,0,0,71,0,72,0,73,'-',1,0,75,0,0 db 0,77,'+',1,0,79,0,80,0,81,0,82,0,83 ;shift s_table db 27,1,'!',1,'@',1,'#',1,'$',1,'%',1,'^',1,'&',1,'*',1 db '(',1,')',1,'_',1,'+',1,8,1,0,15,'Q',1,'W',1,'E',1 db 'R',1,'T',1,'Y',1,'U',1,'I',1,'O',1,'P',1,'{',1,'}',1 db 13,1,0,0,'A',1,'S',1,'D',1,'F',1,'G',1,'H',1,'J',1,'K',1 db 'L',1,':',1,'"',1,'~',1,0,0,'|',1,'Z',1,'X',1,'C',1 db 'V',1,'B',1,'N',1,'M',1,'<',1,'>',1,'?',1,0,0,0,0,0,0 db 32,1,0,0,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92 db 0,93,0,0,0,0,'7',1,'8',1,'9',1,'-',1,'4',1,'5',1,'6',1 db '+',1,'1',1,'2',1,'3',1,'0',1,'.',1 ;normal w/ caps nc_table db 27,1,'1',1,'2',1,'3',1,'4',1,'5',1,'6',1,'7',1 db '8',1,'9',1,'0',1,'-',1,'=',1,8,1,9,1,'Q',1,'W',  1,'E',1 db 'R',1,'T',1,'Y',1,'U',1,'I',1,'O',1,'P',1,'[',1,']',1 db 13,1,0,0,'A',1,'S',1,'D',1,'F',1,'G',1,'H',1,'J',1 db 'K',1,'L',1,';',1,39,1,'`',1,0,0,'\',1,'Z',1,'X',1 db 'C',1,'V',1,'B',1,'N',1,'M',1,',',1,'.',1,'/',1,0,0 db '*',1,0,0,32,1,0,0,0,59,0,60,0,61,0,62,0,63,0,64,0,65 db 0,66,0,67,0,68,0,0,0,0,0,71,0,72,0,73,'-',1,0,75,0,0 db 0,77,'+',1,0,79,0,80,0,81,0,82,0,83 ;shift w/ caps sc_table db 27,1,'!',1,'@',1,'#',1,'$',1,'%',1,'^',1,'&',1,'*',1 db '(',1,')',1,'_',1,'+',1,8,1,0,15,'q',1,'w',1,'e',1 db 'r',1,'t',1,'y',1,'u',1,'i',1,'o',1,'p',1,'{',1,'}',1 db 13,1,0,0,'a',1,'s',1,'d',1,'f',1,'g',1,'h',1,'j',1,'k',1 db 'l',1,':',1,'"',1,'~',1,0,0,'|',1,'z',1,'x',1,'c',1 db 'v',1,'b',1,'n',1,'m',1,'<',1,'>',1,'?',1,0,0,0,0,0,0 db 32,1,0,0,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92 db 0,93,0,0,0,0,'7',1,'8',1,'9',1,'-',1,'4',1,'5',1,'6',1 db '+',1,'1',1,'2',1,'3',1,'0',1,'.',1 ;normal w/ num nn_table db 27,1,'1',1,'2',1,'3',1,'4',1,'5',1,'6',1,'7',1 db '8',1,'9',1,'0',1,'-',1,'=',1,8,1,9,1,'q',1,'w',1,'e',1 db 'r',1,'t',1,'y',1,'u',1,'i',1,'o',1,'p',1,'[',1,']',1 db 13,1,0,0,'a',1,'s',1,'d',1,'f',1,'g',1,'h',1,'j',1 db 'k',1,'l',1,';',1,39,1,'`',1,0,0,'\',1,'z',1,'x',1 db 'c',1,'v',1,'b',1,'n',1,'m',1,',',1,'.',1,'/',1,0,0 db '*',1,0,0,32,1,0,0,0,59,0,60,0,61,0,62,0,63,0,64,0,65 db 0,66,0,67,0,68,0,0,0,0,'7',1,'8',1,'9',1,'-',1,'4',1 db '5',1,'6',1,'+',1,'1',1,'2',1,'3',1,'0',1,'.',1 ;shifted w/ num sn_table db 27,1,'!',1,'@',1,'#',1,'$',1,'%',1,'^',1,'&',1,'*',1 db '(',1,')',1,'_',1,'+',1,8,1,0,15,'Q',1,'W',1,'E',1 db 'R',1,'T',1,'Y',1,'U',1,'I',1,'O',1,'P',1,'{',1,'}',1 db 13,1,0,0,'A',1,'S',1,'D',1,'F',1,'G',1,'H',1,'J',1,'K',1 db 'L',1,':',1,'"',1,'~',1,0,0,'|',1,'Z',1,'X',1,'C',1 db 'V',1,'B',1,'N',1,'M',1,'<',1,'>',1,'?',1,0,0,0,0,0,0 db 32,1,0,0,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92 db 0,93,0,0,0,0,0,71,0,72,0,73,'-',1,0,75,0,0 db 0,77,'+',1,0,79,0,80,0,81,0,82,0,83 ;num and caps ncn_table db 27,1,'1',1,'2',1,'3',1,'4',1,'5',1,'6',1,'7',1 db '8',1,'9',1,'0',1,'-',1,'=',1,8,1,9,1,'Q',1,'W',1,'E',1 db 'R',1,'T',1,'Y',1,'U',1,'I',1,'O',1,'P',1,'[',1,']',1 db 13,1,0,0,'A',1,'S',1,'D',1,'F',1,'G',1,'H',1,'J',1 db 'K',1,'L',1,';',1,39,1,'`',1,0,0,'\',1,'Z',1,'X',1 db 'C',1,'V',1,'B',1,'N',1,'M',1,',',1,'.',1,'/',1,0,0 db '*',1,0,0,32,1,0,0,0,59,0,60,0,61,0,62,0,63,0,64,0,65 db 0,66,0,67,0,68,0,0,0,0,'7',1,'8',1,'9',1,'-',1,'4',1 db '5',1,'6',1,'+',1,'1',1,'2',1,'3',1,'0',1,'.',1 ;shifted num and caps scn_table db 27,1,'!',1,'@',1,'#',1,'$',1,'%',1,'^',1,'&',1,'*',1 db '(',1,')',1,'_',1,'+',1,8,1,0,15,'q',1,'w',1,'e',1 db 'r',1,'t',1,'y',1,'u',1,'i',1,'o',1,'p',1,'{',1,'}',1 db 13,1,0,0,'a',1,'s',1,'d',1,'f',1,'g',1,'h',1,'j',1,'k',1 db 'l',1,':',1,'"',1,'~',1,0,0,'|',1,'z',1,'x',1,'c',1 db 'v',1,'b',1,'n',1,'m',1,'<',1,'>',1,'?',1,0,0,0,0,0,0 db 32,1,0,0,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,92 db 0,93,0,0,0,0,0,71,0,72,0,73,'-',1,0,75,0,0 db 0,77,'+',1,0,79,0,80,0,81,0,82,0,83 ;control c_table db 27,1,0,0,0,1,0,0,0,0,0,0,30,1,0,0,0,0,0,0,0,0,31,1,0,0 db 127,1,0,0,17,1,23,1,5,1,18,1,20,1,25,1,21,1,9,1,15,1 db 16,1,27,1,29,1,10,1,0,0,1,1,19,1,4,1,6,1,7,1,8,1,10,1 db 11,1,12,1,0,0,0,0,0,0,0,0,28,1,26,1,24,1,3,1,22,1,2,1 db 14,1,13,1,0,0,0,0,0,0,0,0,0,114,0,0,32,1,0,0,0,94,0,95 db 0,96,0,97,0,98,0,99,0,100,0,101,0,102,0,103,0,0,3,1 db 0,119,0,0,0,132,0,0,0,115,0,0,0,116,0,0,0,117,0,0,0,118 db 0,0,0,0 ;alt a_table db 0,0,0,120,0,121,0,122,0,123,0,124,0,125,0,126,0,127 db 0,128,0,129,0,130,0,131,0,0,0,0,0,16,0,17,0,18,0,19 db 0,20,0,21,0,22,0,23,0,24,0,25,0,0,0,0,0,0,0,0,0,30 db 0,31,0,32,0,33,0,34,0,35,0,36,0,37,0,38,0,0,0,0,0,0 db 0,0,0,0,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,0,0,0 db 0,0,0,0,0,0,0,0,32,1,0,0,0,104,0,105,0,106,0,107,0,108 db 0,109,0,110,0,111,0,112,0,113,0,0,0,0,0,0,0,0,0,0 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 interupt2 proc far sti cld int 9 ;go do keyboard int push ax push dx push ds mov ax,data mov ds,ax cli mov dx,keyboard_port mov al,port_status and al,not data_line out dx,al or al,data_line out dx,al mov port_status,al sti mov dx,eoir mov ax,eoiv out dx,ax pop ds pop dx pop ax iret interupt2 endp interupt proc far sti cld push ds push si push ax push bx push cx push dx mov ax,data mov ds,ax z1: mov dx,keyboard_port in al,dx MOV BL,AL cli mov dx,  keyboard_port mov al,port_status and al,not data_line out dx,al or al,data_line out dx,al mov port_status,al MOV AL,BL STI test shift_status,ctl_mask jz z2 test shift_status,alt_mask jz z3 cmp al,del_key jne z3 mov reset_location,1234h ;warm boot jmp initialize z3: cmp al,scroll_key jne z2 ;ctl break was pressed xor ax,ax ;clear buffer return 0000 mov kb_buffer,ax mov buffer_head,offset kb_buffer mov buffer_tail,offset kb_buffer+2 mov byte_flag,0 int break_int jmp interupt_done z2: mov si,offset shift_keys xor bx,bx mov cx,sk_len sk_loop: inc bx ;is it a shift key? cmp al,cs:[bx][si] loopne sk_loop jne not_shift shl bx,1 mov ah,shift_functions[bx] mov bl,shift_functions[bx]+1 xor bh,bh jmp bit_functions[bx] ;adjust shift status set_function: or shift_status,ah jmp short sk_cont clear_function: not ah and shift_status,ah jmp short sk_cont toggle_function: xor shift_status,ah sk_cont: cmp al,ins_key je not_shift and key_status2,not nshiftkey_mask jmp interupt_done not_shift: ;not shift key get table for i1: cmp al,80h ;current shift status jb i2 jmp interupt_done i2: or key_status2, nshiftkey_mask mov ah,shift_status test ah,alt_mask jz i17 mov bx,offset a_table jmp look_up i17: test ah,ctl_mask jz i18 mov bx,offset c_table jmp look_up i18: test ah,caps_mask jz i3 test ah,num_mask jz i4 test ah,right_mask or left_mask jz i16 mov bx,offset scn_table jmp look_up i16: mov bx,offset ncn_table jmp look_up i4: test ah,right_mask or left_mask jz i26 mov bx,offset sc_table jmp look_up i26: mov bx,offset nc_table jmp look_up i3: test ah,num_mask jz i5 test ah,right_mask or left_mask jz i36 mov bx,offset sn_table jmp look_up i36: mov bx,offset nn_table jmp look_up i5: test ah,right_mask or left_mask jz i6 mov bx,offset s_table  jmp look_up i6: mov bx,offset n_table look_up: xor ah,ah mov si,ax dec si mov ah,al ;scan code to ah shl si,1 mov al,cs:[bx][si] ;ascii to al or al,al jnz lu1 mov ah,cs:[bx][si]+1 ;ascii is 0 adjusted scan code to ah or ax,ax jz interupt_done ;illegal key discard it lu1: cli mov bx,buffer_tail mov si,bx inc bx inc bx cmp bx,offset kb_buffer_end jne lu2 mov bx,offset kb_buffer lu2: cmp bx,buffer_head je error_beep mov [si],ax mov buffer_tail,bx error_beep: interupt_done: mov dx,eoir mov ax,eoiv out dx,ax pop dx pop cx pop bx pop ax pop si ctl_num_loop: sti test shift_status,num_mask ;should call concurrent int jz i23 test shift_status,ctl_mask jz i23 test key_status2,nshiftkey_mask jnz i23 jmp short ctl_num_loop i23: pop ds interupt1: iret interupt endp code ends end T LOADER3 EXE L" i .286c .xlist include biosdata.asm .list ;********************************************************************* ; ; V I D I O I / O ; ; ; These routines provide the video interfice for the Slicer ; using the the Slicer video board, and are accesed using ; INT 10H. Modes 0, 1, 2, 3, 4, 5, and 6 reequire an IBM comptable ; color graphics board. The functions provided are: ; ; AH = 0: Set video mode in AL ; AL = 0: 40x25 b&w text ; AL = 1: 40x25 color text ; AL = 2: 80x25 b&w text ; AL = 3: 80x25 color text ; Graphics modes ; AL = 4: 320x200 color ; AL = 5: 320x200 b&w ; AL = 6: 640x200 b&w ; Modes on Slicer pc board ; AL = 7: 80x25 text ; AL = 80:640x200 b&w ; ; AH = 1: Set cursor type ; CH = Starting line of cursor (bits 0 - 4) ; CL = Lase line of cursor (bits 0 - 4) ; ; AH = 2: Set cursor position ; DH = Row (0 is the top row) ; DL = Column (0 is the leftmost) ; BH = Page number ; ; AH = 3: Read cusor position ; BH = Page number ; Returns: ; DH = Row ; DL = Column ; CH = Starting line ; CL = End line ; ; AH = 4: Nop ; ; AH = 5: Select active display page ; AL = New page ; ; AH = 6: Scroll active page up    ; AL = Number of lines to scroll (0 = Blank entire window) ; CH, CL = Upper left corner of window ; DH, DL = Lower right corner of window ; BH = Attribute of blanked lines ; ; AH = 7: Scroll active page down ; AL = Number of lines to scroll (0 = Blank entire window) ; CH, CL = Upper left corner of window ; DH, DL = Lower right corner of window ; BH = Attribute of blanked lines ; ; ; AH = 8: Read charecter and attribute at cursor ; BH = Page ; Returns: ; AH = Attrribute ; AL = Charecter ; ; AH = 9: Write charecter and attribute to cursor ; BH = Page ; BL = Attribute ; AL = Charecter ; CX = Number of charecters to write ; ; AH = A: Write charecter to cursor ; BH = Page ; AL = Charecter ; CX = Number of charecters to write ; ; AH = B: Set color palette ; BH = Pallette id ; 0 = Background ; 1 = Pallette ; BL = Valus ; ; AH = C: Write dot. ; DX = Row ; CX = Column ; AL = Color ; ; AH = D: Read dot. ; AL = Dot read ; ; AH = E: Write teletype to current page ; AL = Charecter to write ; BL = Forground color in graphics mode ; ; AH = F: Return current video state ;  Returns: ; AL = Mode ; AH = Number of columns on screen ; BH = Active page ;--------------------------------------------------------------------- ; ; AH = 80: Fill window with charecter and attribute ; AL = Charecter ; BL = Attribute ; CH = Upper row ; CL = Left column ; DH = Lower row ; DL = Right column ; ; ; AH = FB: Turn on TTY Extended ; AH = FC: Turn off TTY Extended ; AH = FD: Write TTY Extended ; AH = FE: Get video buffer ( returns for now ) ; AH = FF: Set video buffer ( returns for now ) ; ;********************************************************************* public new_video,video_init,set_mode,get_mode,set_page b equ byte ptr w equ word ptr uart_base equ 80h uart_input equ uart_base+1ah use_video equ 20h bw_base equ 03b4h _data equ 01h _control equ 04h _status equ 06h color_base equ 03d4h _color equ 05h ; b_space equ 8 c_return equ 0dh l_feed equ 0ah bell equ 7 color_card equ 2 herc equ 1 ; ; xxx struc temp1 dw ? pointer1 dw ? pointer2 dw ? rdi dw ? rsi dw ? rbp dw ? rsp dw ? rbx dw ? rdx dw ? rcx dw ? rax dw ? xxx ends size_temp_data equ rdi ;used to alocate temporary data space ; ; ; cgroup group code code segment public byte 'code' assume cs:cgroup,es:vectors,ds:data include tables.asm ; CHANGED 9-5-86 JONATHAN FOR TESTING HURCULESS CARD card_index db 1,1,1,1,1,1,1,0 ;video board used in each mode ;1=color card, 0=bw board param_index db 0,0,1,1,2,2,2,3 ;index into parameter table ;for each mode color_reg db 0h,0h,0h,0h,0h,0h,03fh control_reg db 02ch,028h,02dh,029h,02ah,02eh,01eh,029h columns db 40,40,80,80,40,40,80,80 p_size dw 2048,2048,4096,4096,16384,16384,16384,4096 parameters db 038h,028h,02dh,00ah,01fh,006h,019h db 01ch,002h,007h,006h,007h db 0,0,0,0 params_len equ this byte-parameters db 071h,050h,05ah,00ah,01fh,006h,019h db 01ch,002h,007h,006h,007h db 0,0,0,0 ; db 038h,028h,02dh,00ah,07fh,006h,064h db 070h,002h,001h,006h,007h db 0,0,0,0 ; db 061h,050h,052h,00fh,019h,006h,019h db 019h,002h,00dh,0bh,00ch db 0h,0h,0,0 ; ; low_table dw set_mode dw set_c_type dw set_c_pos dw get_c_pos dw read_lpen dw set_page dw scroll_up dw scroll_down dw read_char dw write_achar dw write_char dw set_pallette dw write_dot dw read_dot dw write_tty dw get_mode dw no_op ; ; high_table dw fill_window dw draw_line dw draw_box dw fill_box dw no_op set macro num,val mov w num,offset val mov w num+2,seg val endm ; ; ; ; Install is called on power up to initialize the interupt vectors, ; and initialize the video boards. ; video_init proc near xor ax,ax mov es,ax ; Jonathan 2-24-86 mov tty_on,0 ;turn off extended tty and bits,not color_card and bits2,not herc in al,uart_input ;install vi  deo in new call system test al,40h jnz no_herc test al,10h jnz no_herc or bits2,herc no_herc: or equip_flag,30h mov dx,color_base mov ax,550fh ;check to see if color video is present out dx,ax ;by outputting values to register out dx,al ;reading them back and checking if inc dx ;they are the same in al,dx dec dx cmp al,55h jne no_color mov ax,0aa0fh out dx,ax out dx,al inc dx in al,dx cmp al,0aah jne no_color or bits,color_card ;this is in biosdata.asm set vector_10,video_io set vector_1d,parameters mov ax,0003h ;init color board int 10h mov b device_numbers+(2*010h)+1,6 in al,uart_input ;install video in new call system test al,use_video jz no_color mov b device_numbers+(2*6)+1,6 ;install video as con output device no_color: ;no color board test for bw board ;*********************************** mov dx,bw_base mov ax,550fh ;check to see if video is present out dx,ax ;by outputting values to register out dx,al ;reading them back and checking if inc dx ;they are the same in al,dx dec dx cmp al,55h jne no_video mov ax,0aa0fh out dx,ax out dx,al inc dx in al,dx cmp al,0aah jne no_video set vector_10,video_io set vector_1d,parameters mov ax,0007h ;init bw board. int 10h test bits,color_card jz install and equip_flag,0ffefh ;clear color mov ax,3 int 10h mov cx,607h call set_c_type install: mov b device_numbers+(2*010h)+1,6 in al,uart_input ;install video in new call system test al,use_video jz no_video mov b device_numbers+(2*6)+1,6 ;install video as con output device no_video: push bx mov bx,offset pport_addr test bits,color_card jz no_lpt1 mov [bx],378h ;printer port on color add bx,2 no_lpt1: test bits2,herc jz no_lpt mov [bx],3bch ;printer port on herc no_lpt: pop bx ret video_init endp assume es:nothing ; ; ; Function dispatcher for int 10h ; Int 10h is reentrent so that intrupt driven clocks ect. can use it ; video_io proc far sti ;intrupts back on cld ;string operations forward push es push ds pusha sub sp,offset size_temp_data mov bp,sp ;temp data referenced off bp ; mov al,ah xor ah,ah vi1: cmp al,80h vi0: jae high_functions ; mov si,offset low_table cmp al,15 jbe dispatch mov al,16 jmp dispatch high_functions: sub al,80h mov si,offset high_table cmp al,4 jbe dispatch cmp al,07ah ;7f 6/6/86 jna vi13 ;jne cmp al,7bh ;add jnz vi15 call extty_on jmp short vi14 vi15: cmp al,7ch jnz vi16 call extty_off jmp short vi14 ;end add 6/6/86 vi16: cmp al,7dh jnz vi14 call terminal_out jmp short vi14 vi13: mov al,5 dispatch: shl ax,1 add si,ax ;si has index into jump table mov ax,data mov ds,ax call cs:word ptr[si] ; vi14: add sp,offset size_temp_data popa pop ds pop es iret video_io endp ;---------------------------------------------------------------- ; New video function calls ; ; input: ; al = function # ; 1 = output charecters ; cx = count ; es:si = buffer ; ; 3 = output status ; output ; al = status ;---------------------------------------------------------------- new_video proc far cmp al,1 ;write charecters jne nv1 jcxz nv5 push cx nv4: lods b es:[si] push si push cx and tty_on,1 jnz nv6 mov ah,0eh ;tty output jmp nv7 nv6: mov ah,0fdh ;extended tty output nv7: int 10h pop cx pop si loop nv4 pop cx nv5: mov al,0 ret nv1: cmp al,3 ;status jne nv2 mov al,0 ret nv2: mov al,1 ;bad command ret new_video endp ; ; scroll_up proc near assume es:vectors ;makes movs work mov cx,rax[bp] xor ch,ch cmp cl,0 ;number of rows to scroll in cx jne su1 mov cx,rcx[bp] mov dx,rdx[bp] mov ah,080h ;fill window cx,dx with mov al,' ' ;spaces and attribute mov bx,rbx[bp] mov bl,bh int 10h ret su1: cmp crt_mode,7 je su_cont cmp crt_mode,4 jb su_cont jmp gscroll_up su_cont: mov ax,page_seg mov es,ax ;es has segment of video buffer ; mov bx,rdx[bp] mov bl,bh xor bh,bh ;ending row to bx mov ax,rcx[bp] mov al,ah xor ah,ah ;starting row to ax sub bx,ax ;number of rows in window to bx inc bx sub bx,cx ;#of rows - rows to scroll=#of mov temp1[  bp],bx ;rows to move to temp1 mov bx,ax ;starting row to bx also mov dl,num_columns ;words per line of text xor dh,dh shl dx,1 ;bytes per line of text mul dl mov pointer2[bp],ax ;address to move first line to mov ax,bx ;restore starting row to ax add ax,cx mul dl mov pointer1[bp],ax ;address to move first line from mov ax,rcx[bp] xor ah,ah ;starting column of window to ax shl ax,1 ;convert to words add pointer1[bp],ax ;increment pointers to to add pointer2[bp],ax ;starting column shr ax,1 ;back to columns mov bx,rdx[bp] xor bh,bh sub bx,ax ;width of window to bx inc bx scroll_up_loop: mov cx,bx mov si,pointer1[bp] mov di,pointer2[bp] add pointer1[bp],dx add pointer2[bp],dx ;increment pointers one row rep movs kludge,kludge1 ;move one row up dec temp1[bp] jnz scroll_up_loop ;repeat for all rows mov cx,rcx[bp] mov dx,rdx[bp] mov ch,dh mov ax,rax[bp] dec al ;erases number of lines sub ch,al ;at bottom of window mov ah,080h ;fill window cx,dx with mov al,' ' ;spaces and attribute mov bx,rbx[bp] mov bl,bh int 10h ret scroll_up endp ; ; scroll_down proc near mov cx,rax[bp] xor ch,ch cmp cl,0 ;number of rows to scroll in cx jne sd1 mov cx,rcx[bp] mov dx,rdx[bp] mov ah,080h ;fill window cx,dx with mov al,' ' ;spaces and attribute mov bx,rbx[bp] mov bl,bh int 10h ret ; sd1: cmp crt_mode,7 je sd_cont cmp crt_mode,4 jb sd_cont jmp gscroll_dn sd_cont: mov ax,page_seg mov es,ax ;es has segment of video buffer ; mov bx,rdx[bp] mov bl,bh xor bh,bh ;ending row to bx mov dx,bx ;save in dx for now mov ax,rcx[bp] mov al,ah xor ah,ah ;starting row to ax sub bx,ax ;number of rows in window to bx inc bx sub bx,cx ;#of rows - rows to scroll=#of mov temp1[bp],bx ;rows to move to temp1 mov ax,dx ;get last row back to ax mov bx,ax ;starting row to bx also mov dl,num_columns ;words per line of text xor dh,dh shl dx,1 ;bytes per line of text mul dl mov pointer2[bp],ax ;address to move first line to mov ax,bx ;restore ending row to ax sub ax,cx mul dl mov pointer1[bp],ax ;address to move first line from mov ax,rcx[bp] xor ah,ah ;starting column of window to ax shl ax,1 ;convert to words add pointer1[bp],ax ;increment pointers to to add pointer2[bp],ax ;starting column shr ax,1 ;back to columns mov bx,rdx[bp] xor bh,bh sub bx,ax ;width of window to bx inc bx scroll_dn_loop: mov cx,bx mov si,pointer1[bp] mov di,pointer2[bp] sub pointer1[bp],dx sub pointer2[bp],dx ;increment pointers one row rep movs kludge,kludge1 ;move one row down dec temp1[bp] jnz scroll_dn_loop ;repeat for all rows mov cx,rcx[bp] mov dx,rdx[bp] mov dh,ch mov ax,rax[bp] dec al ;erases number of lines add dh,al ;at top of window mov ah,080h ;fill window cx,dx with mov al,' ' ;spaces and attribute mov bx,rbx[bp] mov bl,bh int 10h ret scroll_down endp ; read_char proc near mov ax,buffer_seg mov es,ax mov bx,rbx[bp] mov bl,bh ;page to bl mov ax,page_size xor bh,bh mul bx mov si,bx ;si has page # for cursor shl si,1 ;address look up mov bx,ax ;base of page into bx mov al,num_columns shl al,1 ;mul by 2 for word address mov cx,cursor_posn[si] mul ch add bx,ax ;address of row in bx xor ch,ch shl cl,1 ;mul by 2 for word address add bx,cx ;address of cursor in bx mov ax,es:[bx] ;read char mov rax[bp],ax ;save to be restored to ax ret read_char endp ; ; write_achar proc near cmp crt_mode,7 je wac_cont cmp crt_mode,3 jbe wac_cont jmp near ptr graphics_write wac_cont: mov ax,buffer_seg mov es,ax mov bx,rbx[bp] mov bl,bh ;page to bl mov ax,page_size xor bh,bh mul bx mov si,bx ;si has page # for cursor shl si,1 ;address look up mov di,ax ;base of page into di mov al,num_columns shl al,1 ;mul by 2 for word address mov cx,cursor_posn[si] mul ch add di,ax ;address of row in di xor ch,ch shl cx,1 ;mul by 2 for word address add di,cx ;address of cursor in di mov ax,rax[bp] mov bx,rbx[bp] mov ah,bl ;char, and attribute in ax mov cx,rcx[bp] ;count to write to cx rep stosw ;store to es:di+=2 ret write_achar endp ; ; write_char proc near cmp crt_mode,7 je wc_cont cmp crt_mode,3 jbe wc_cont   jmp near ptr graphics_write wc_cont: mov ax,buffer_seg mov es,ax mov bx,rbx[bp] mov bl,bh ;page to bl mov ax,page_size xor bh,bh mul bx mov si,bx ;si has page # for cursor shl si,1 ;address look up mov di,ax ;base of page into di mov al,num_columns shl al,1 ;mul by 2 for word address mov cx,cursor_posn[si] mul ch add di,ax ;address of row in di xor ch,ch shl cx,1 ;mul by 2 for word address add di,cx ;address of cursor in di mov ax,rax[bp] mov cx,rcx[bp] ;count to write to cx jcxz wc_stop wc_loop: stosb inc di ;store to es:di+=2 loop wc_loop wc_stop: ret write_char endp ; ; fill_window proc near cmp crt_mode,7 je fw_cont cmp crt_mode,4 jb fw_cont jmp gfill_window fw_cont: ; mov ax,page_seg mov es,ax ;es has segment of video buffer ; mov bx,rdx[bp] mov bl,bh xor bh,bh ;ending row to bx mov ax,rcx[bp] mov al,ah xor ah,ah ;starting row to ax sub bx,ax inc bx  ;number of rows in window to bx mov temp1[bp],bx ;rows to clear to temp1 mov dl,num_columns ;words per line of text xor dh,dh shl dx,1 ;bytes per line of text mul dl mov bx,rcx[bp] xor bh,bh ;starting column of window to bx shl bx,1 ;convert to words add ax,bx mov pointer1[bp],ax ;address of first line to clear shr bx,1 ;back to columns mov ax,bx ;starting column to ax mov bx,rdx[bp] xor bh,bh sub bx,ax ;width of window to bx inc bx mov ax,rax[bp] mov cx,rbx[bp] mov ah,cl ;charecter and attribute in ax fill_loop: mov cx,bx mov di,pointer1[bp] add pointer1[bp],dx rep stos word ptr [di] ;move one row up dec temp1[bp] jnz fill_loop ;repeat for all rows ret fill_window endp gfill_window proc near mov ah,3 mov bh,0 int 10h ;get cursor position mov temp1[bp],dx ;and save it mov dx,rcx[bp] mov ah,2 int 10h mov cx,rdx[bp] mov bl,ch ;bl has ending column sub cl,dl inc cl xor ch,ch  ;cx has count to write mov ax,rax[bp] gfill_loop: mov ah,2 mov bh,0 int 10h ;position cursor mov ah,10 int 10h ;write cx chars inc dh cmp dh,bl jbe gfill_loop mov dx,temp1[bp] mov ah,2 int 10h ;restore cursor ret gfill_window endp ; set_mode proc near mov di,rax[bp] and di,00ffh ;mode into di cmp di,080h jb smcont1 jmp extended_mode smcont1: cmp di,8 jb smcont2 jmp illegal_mode smcont2: ;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Jonathan 2-24-86 cmp di,4 ;if mode is 6 or less ja smcont3 ;a color board must be test bits,color_card ;installed or default jnz smcont3 ;to slicer mode mov di,7 ; mov rax[bp],7 ;change callers mode smcont3: ;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ mov si,offset cursor_posn xor ax,ax mov cx,8 cur_zero_loop: mov [si],ax ;zero all cursors add si,2 loop cur_zero_loop mov dx,bw_base mov buffer_seg,0b000h cmp card_index[di],0 je sm1 test bits,color_card je sm1 mov dx,color_base mov buffer_seg,0b800h sm1: mov adr_6845,dx ;save 6845 base mov al,params_len mul param_index[di] ;ax has offset to parameters xor cx,cx mov es,cx assume es:vectors les si,vector_1d add si,ax ;si points to 6845 parameters ;for this mode mov cx,params_len ;number of parameters to set mov al,0 smloop: mov ah,byte ptr es:[si] ;mov next parameter into ah inc si out dx,ax inc al loop smloop mov dx,adr_6845 mov bx,dx add dx,_control ;setup control and color registers mov al,control_reg[di] out dx,al mov dx,bx add dx,_color mov al,color_reg[di] out dx,al mov crt_pallette,al ;Jonathan 1-7-86 mov dx,bx add dx,_status st_check: in al,dx ;the quad ram color baord test al,1 ;seems to require this jz st_check mov al,columns[di] mov num_columns,al shl di,1 mov ax,p_size[di] mov page_size,ax mov cx,rax[bp] mov crt_mode,cl mov ah,5 ;must set window before other mov al,0 ;operations !!!!!!!!!!!! ;this sets up the pointer to the ;page base int 10h ; mov cx,0 mov dh,24 ;(0,0)-(width,24) mov dl,num_columns dec dl mov al,' ' mov bl,7 mov ah,080h int 10h ;fill screen extended_mode: illegal_mode: ret assume es:nothing set_mode endp ; get_mode proc near mov bx,rbx[bp] ;get bx so bl can be preserved mov bh,cur_page ;set approprate registers for mov rbx[bp],bx ;restore with popa    mov al,crt_mode mov ah,num_columns mov rax[bp],ax ret get_mode endp ; set_c_type proc near mov dx,adr_6845 mov al,0ah mov ah,ch out dx,ax mov al,0bh mov ah,cl out dx,ax mov cursor_mode,cx ret set_c_type endp ; set_c_pos proc near mov bx,rbx[bp] mov bl,bh xor bh,bh ;offset into cursor position shl bx,1 ;table mov ax,rdx[bp] mov cursor_posn[bx],ax ;save position in table shr bx,1 ;back to page # cmp crt_mode,7 je scp_cont cmp crt_mode,4 jae scp_done ;do nothing for grapics modes scp_cont: cmp bl,cur_page jne scp_done ;need to update actual position? mov cx,ax ;position to cx mov ax,page_size shr ax,1 ;div by 2 for 6845 mul bx ;base of page into bx mov bx,ax mov al,num_columns mul ch add bx,ax ;address of row in bx xor ch,ch add cx,bx ;address of cursor in cx mov dx,adr_6845 mov al,0eh mov ah,ch out dx,ax mov al,0fh mov ah,cl out dx,ax scp_done: ret set_c_pos endp ; get_c_pos proc near mov bx,rbx[bp] mov bl,bh xor bh,bh shl bx,1 ;page in bx mov ax,cursor_posn[bx] ;save cursor_posn, and mov rdx[bp],ax ;curcor_mode so they mov ax,cursor_mode ;will be rewstored with mov rcx[bp],ax ;the popa ret get_c_pos endp ; set_page proc near cmp crt_mode,7 je sp_cont cmp crt_mode,4 jae spg_done ;do nothing for grapics modes sp_cont: mov ax,rax[bp] mov cur_page,al mov bl,al mov ax,page_size xor bh,bh mul bx mov si,bx ;si has page # for cursor shl si,1 ;address look up mov bx,ax ;base of page into bx shr bx,1 ;div by 2 for byte address mov temp1[bp],ax ;save in temp1 also mov al,num_columns mov cx,cursor_posn[si] mul ch add bx,ax ;address of row in bx xor ch,ch add cx,bx ;address of cursor in cx mov dx,adr_6845 ;set cursor address in 6845 mov al,0eh mov ah,ch out dx,ax mov al,0fh mov ah,cl out dx,ax mov cx,temp1[bp] ;retrieve base of page shr cx,1 ;divide by 2 for 6845 address mov ax,adr_6845 cmp ax,bw_base jne sp_around1 ;decrement by 1 for 6845 test bits2,herc jnz sp_around1 dec cx ;only if b and w board sp_around1: mov ah,ch ;set base address in 6845 mov al,0ch out dx,ax mov al,0dh mov ah,cl out dx,ax mov ax,adr_6845 cmp ax,bw_base jne sp_around2 ;increment by 1 for 6845 test bits2,herc jnz sp_around2 inc cx ;only if b and w board to sp_around2: ;counter act the preceeding dec shr cx,3 ;segment value of base ;shift only 3 times because ;already shifted once above ; mov ax,buffer_seg add ax,cx mov page_seg,ax spg_done: ret set_page endp ; graphics_write proc near mov ax,cursor_posn mov dl,al xor dh,dh ;dx has column mov al,ah shl ax,1 ;mul by 2 for word index mov cl,8 mul cl mov bx,ax ;bx has base row for charecter cmp crt_mode,5 ja gw_cont1 shl dx,1 gw_cont1: mov ax,rax[bp] ;dx has offset for char write mul cl mov si,ax ;si points to char lea si,cs:char_gen[si] mov temp1[bp],8 gw_loop: lods cs:char_gen[si] cmp crt_mode,5 ja gw_cont4 mov cx,8 gw_loop1: shr al,1 rcr di,1 sar di,1 loop gw_loop1 ;expand into a word mov ax,di xchg al,ah mov cx,rax[bp] cmp ch,9 jne gw_cont4 ;write with out color mov di,rbx[bp] ;color and di,3 shl di,1 and ax,cs:color_mask[di] ;and with color mask gw_cont4: mov es,cs:base_table1[bx] add bx,2 ;inc to next column mov di,dx mov cx,rcx[bp] cmp crt_mode,5 ja gw_cont2 rep stosw jmp gw_cont3 gw_cont2: rep stosb gw_cont3: dec temp1[bp] jnz gw_loop ret graphics_write endp gscroll_up proc near ;cx has number of rows to scroll ; shl cx,3 mov bx,rdx[bp] mov bl,bh xor bh,bh ;multiply by 8 shl bx,3 ;ending row to bx add bx,7 mov ax,rcx[bp] mov al,ah xor ah,ah ;starting row to ax shl ax,3 sub bx,ax ;number of rows in window to bx inc bx sub bx,cx ;#of rows - rows to scroll=#of mov temp1[bp],bx ;rows to move to temp1 mov bx,ax ;starting row to bx also shl ax,1 mov pointer2[bp],ax ;address to move first line to mov ax,bx ;restore starting row to ax add ax,cx shl ax,1 mov pointer1[bp],ax ;address to move first line from mov ax,rcx[bp] xor ah,ah ;starting column of window to ax mov bx,rdx[bp] xor bh,bh sub bx,ax ;width of window to bx inc bx xor dx,dx cmp   crt_mode,5 ja gscrl_up_loop not dx ;dx is word move flag shl ax,1 gscrl_up_loop: mov cx,bx mov si,pointer1[bp] mov di,pointer2[bp] mov ds,cs:base_table1[si] mov es,cs:base_table1[di] mov si,ax mov di,ax add pointer1[bp],2 add pointer2[bp],2 ;increment pointers one row or dx,dx je gsu2 rep movsw ;move one row up jmp gsu3 gsu2: rep movsb gsu3: dec temp1[bp] jnz gscrl_up_loop ;repeat for all rows mov cx,rcx[bp] mov dx,rdx[bp] mov ch,dh mov ax,rax[bp] dec al ;erases number of lines sub ch,al ;at bottom of window mov ah,080h ;fill window cx,dx with mov al,' ' ;spaces and attribute mov bx,rbx[bp] mov bl,bh int 10h ret gscroll_up endp gscroll_dn proc near ;cx has number of rows to scroll ; shl cx,3 mov bx,rdx[bp] mov bl,bh xor bh,bh ;multiply by 8 shl bx,3 ;ending row to bx add bx,7 mov dx,bx ;save in dx for now mov ax,rcx[bp] mov al,ah xor ah,ah ;starting row to ax shl ax,3 sub bx,ax ;number of rows in window to bx inc bx sub bx,cx ;#of rows - rows to scroll=#of add bx,8 ;this seems to fix a bug who knows why????? mov temp1[bp],bx ;rows to move to temp1 mov ax,dx mov bx,ax ;ending row to bx also shl ax,1 mov pointer2[bp],ax ;address to move first line to mov ax,bx ;restore ending row to ax add ax,cx shl ax,1 mov pointer1[bp],ax ;address to move first line from mov ax,rcx[bp] xor ah,ah ;starting column of window to ax mov bx,rdx[bp] xor bh,bh sub bx,ax ;width of window to bx inc bx xor dx,dx cmp crt_mode,5 ja gscrl_dn_loop not dx ;dx is word move flag shl ax,1 gscrl_dn_loop: mov cx,bx mov si,pointer1[bp] mov di,pointer2[bp] mov ds,cs:base_table1[di] mov es,cs:base_table1[si] mov si,ax mov di,ax sub pointer1[bp],2 sub pointer2[bp],2 ;increment pointers one row or dx,dx je gsd2 rep movsw ;move one row up jmp gsd3 gsd2: rep movsb gsd3: dec temp1[bp] jnz gscrl_dn_loop ;repeat for all rows mov cx,rcx[bp] mov dx,rdx[bp] mov dh,ch mov ax,rax[bp] dec al ;erases number of lines add dh,al ;at top of window mov ah,080h ;fill window cx,dx with mov al,' ' ;spaces and attribute mov bx,rbx[bp] mov bl,bh int 10h ret gscroll_dn endp write_dot proc near cmp crt_mode,6 jne wd1 jmp wd_hr wd1: mov ax,rcx[bp] mov bl,4 div bl mov bl,ah xor ah,ah xor bh,bh mov si,ax mov al,dot_mask[bx] mov bx,rdx[bp] mov es,base_table1[bx] test rax[bp],80h jnz wdxor mov ah,es:[si] not al and ah,al not al mov bx,rax[bp] and bx,3 and al,color_mask1[bx] or ah,al mov es:[si],ah ret wdxor: mov bx,rax[bp] and bx,3 and al,color_mask1[bx] xor es:[si],al ret wd_hr: mov ax,rcx[bp] mov bl,8 div bl mov bl,ah xor ah,ah xor bh,bh mov si,ax mov al,dot_mask1[bx] mov bx,rdx[bp] mov es,base_table1[bx] test rax[bp],80h jnz wdhrxor mov ah,es:[si] or ah,al mov es:[si],ah ret wdhrxor: mov bx,rax[bp] xor es:[si],al ret write_dot endp read_dot proc near cmp crt_mode,6 jne rd1 jmp rd_hr rd1: mov ax,rcx[bp] mov bl,4 div bl mov cl,ah mov bl,ah add cl,cl xor ah,ah xor bh,bh mov si,ax mov al,dot_mask[bx] mov bx,rdx[bp] mov es,base_table1[bx] mov ah,es:[si] and ah,al shr ah,cl mov al,ah mov rax[bp],ax ret rd_hr: mov ax,rcx[bp] mov bl,8 div bl mov cl,ah mov bl,ah xor ah,ah xor bh,bh mov si,ax mov al,dot_mask1[bx] mov bx,rdx[bp] mov es,base_table1[bx] mov ah,es:[si] and ah,al shr ah,cl mov al,ah mov rax[bp],ax ret read_dot endp set_pallette proc near cmp crt_mode,4 jnz sp_end mov bx,rbx[bp] or bh,bh je sp1 mov al,crt_pallette and al,0e0h and bl,01fh or al,bl jmp short sp2 sp1: mov al,crt_pallette and al,not 100000b shr bl,1 jnc sp2 or al,100000b sp2:  mov crt_pallette,al mov dx,color_base+_color sp3: out dx,al sp_end: ret set_pallette endp esc equ 1bh f_char db 'Y' db 'A' db 'B' db 'C' db 'D' db 'E' db 'H' db 'I' db 'J' db 'K' db 'd' db 'l' db 'o' db 'L' db 'M' f_char_len equ (this byte - f_char) function dw position dw up dw down dw right dw left dw erase_scrn dw home dw reverse_lf dw erase_eos dw erase_eol dw erase_bos dw erase_line dw erase_bol dw i  nsert_line dw delete_line terminal_out proc near mov ax,[bp].rax test esc_flag,1 jnz i1 ;in esc sequence cmp al,esc jne i99 ;send it through or esc_flag,1 ;set flag and return ret i99: jmp write_tty i1: test esc_flag,10b ;cursor position flag jz i11 jmp position1 i11: xor bx,bx i2: cmp al,f_char[bx] je i3 inc bx cmp bx,f_char_len jbe i2 and esc_flag,not 1 ;bad esc seq throw it out ret i3: shl bx,1 jmp function[bx] ;goto desired function terminal_out endp home proc near mov bh,cur_page mov dx,0 ;cursor at (0,0) mov ah,2 int 10h and esc_flag,not 1 ;clear esc flag ret home endp position proc near mov vid_temp,0 or esc_flag,10b ;in cursor position ret position endp position1 proc near cmp vid_temp,0 jne p1 ;already have row sub al,32 mov vid_temp,al ;store row ret p1: mov bh,cur_page mov dh,vid_temp ;row mov dl,al sub dl,32 ;column mov ah,2 int 10h ;position cursor and esc_flag,(not 11b) ret position1 endp erase_scrn proc near mov cx,0 mov dh,24 ;(0,0)-(width,24) mov dl,num_columns dec dl mov al,' ' mov bl,7 mov ah,080h int 10h ;fill screen mov bh,cur_page mov dx,0 ;cursor at (0,0) mov ah,2 int 10h and esc_flag,not 1 ;clear esc flag ret erase_scrn endp erase_eos proc near mov bh,cur_page mov ah,3 int 10h mov cx,dx cmp ch,24 jae erase_eol inc ch mov cl,0 mov dh,24  mov dl,num_columns dec dl mov al,' ' mov bl,7 mov ah,80h ;fill box just below cursor int 10h ;then erase eol erase_eol: mov bh,cur_page mov ah,3 int 10h mov cx,dx mov dl,num_columns dec dl mov al,' ' mov bl,7 mov ah,80h ;fill box just to end of line int 10h and esc_flag,not 1 ;clear esc flag ret erase_eos endp erase_line proc near mov bh,cur_page mov ah,3 int 10h mov cx,dx mov dl,num_columns dec dl mov cl,0 mov al,' ' mov bl,7 mov ah,80h ;fill just the line int 10h and esc_flag,not 1 ;clear esc flag ret erase_line endp erase_bos proc near mov bh,cur_page mov ah,3 int 10h mov cx,0 cmp dh,0 je erase_bol dec dh mov dl,num_columns dec dl mov al,' ' mov bl,7 mov ah,80h ;fill box just below cursor int 10h ;then erase eol erase_bol: mov bh,cur_page mov ah,3 int 10h mov cx,dx mov cl,0 mov al,' ' mov bl,7 mov ah,80h ;fill box just to end of line int 10h and esc_flag,not 1 ;clear esc flag ret erase_bos endp reverse_lf proc near mov bh,cur_page mov ah,3 int 10h cmp dh,0 jne up jmp insert_line reverse_lf endp up proc near mov bh,cur_page mov ah,3 int 10h sub dh,1 jb u1 mov ah,2 int 10h u1: and esc_flag,not 1 ;clear esc flag ret up endp down proc near mov bh,cur_page mov ah,3 int 10h inc dh cmp dh,24 ja d1 mov ah,2 int 10h d1: and esc_flag,not 1 ;clear esc flag ret down endp left proc near mov bh,cur_page mov ah,3 int 10h sub dl,1 jb l1 mov ah,2 int 10h l1: and esc_flag,not 1 ;clear esc flag ret left endp right proc near mov bh,cur_page mov ah,3 int 10h inc dl cmp dl,num_columns jae r1 mov ah,2 int 10h r1: and esc_flag,not 1 ;clear esc flag ret right endp insert_line proc near mov bh,cur_page mov ah,3 ;position int 10h mov ah,8 int 10h ;attribute mov cx,dx xor cl,cl ;top corner mov dl,num_columns mov dh,24 mov ax,701h int 10h ;scroll down and esc_flag,not 1 ;clear esc flag ret insert_line endp delete_line proc near mov bh,cur_page mov ah,3 ;position int 10h mov ah,8 int 10h ;attribute mov cx,dx xor cl,cl ;top corner mov dl,num_columns mov dh,24 mov ax,601h int 10h ;scroll up and esc_flag,not 1 ;clear esc flag ret delete_line endp ; write_tty proc near mov bh,cur_page mov ah,3 ;get cursor position for all int 10h ;functions mov ax,rax[bp] ;char into al jump to special cmp al,b_space ;case je wb_space cmp al,c_return je wc_return cmp al,l_feed je wl_feed cmp al,bell je wbell ; mov ah,10 ;not special case mov cx,1 ;write a charecter to cursor int 10h ;on active page bh has page ; inc dl ;move to right one position cmp dl,num_columns ;off screen??? jb on_screen xor dl,dl ;set column to 0 inc dh ;goto next row cmp   dh,24 jbe on_screen mov ah,8 ;must scroll screen. get int 10h ;attribute for fill to bh mov bh,ah ;bh still had page mov ax,0601h ;scroll one line mov cx,0 ;upper left = (0,0) mov dl,num_columns dec dl mov dh,24 ;lower right = (24,num_columns) int 10h mov dx,1800h ;position of cursor 18h=24d on_screen: mov bh,cur_page mov ah,2 int 10h ;reposition cursor wbell: ret ;no op for bell ; wc_return: mov dl,0 ;mov to column 0 mov ah,2 int 10h ;set cursor ret ; wl_feed: cmp dh,24 mov temp1[bp],dx ;save position in temp1 jb wl_no_scroll mov ah,8 int 10h mov bh,ah ;attribute fo fill new line with mov cx,0 ;upper left (0, 0) mov dh,24 ;lower right (24, num_columns) mov dl,num_columns dec dl mov ax,0601h ;scroll screen up 1 line int 10h mov dx,temp1[bp] ;restore cursor position mov dh,23 ;incremented to 24 on next line wl_no_scroll: inc dh mov ah,2 int 10h ;set cursor position ret ; wb_space: cmp dl,0 je wb_up ;must move up to next line dec dl ;back space jmp wb_writes ;write a space wb_up: mov dl,num_columns cmp dh,0 je wb_do_nothing ;already at (0,0) do nothing dec dh jmp wb_writes wb_do_nothing: mov dx,0 ;keep at (0, 0) wb_writes: mov ah,2 ;set cursor position bh=page int 10h mov ax,0a20h ;write a space to cursor mov cx,1 int 10h ret ; ; no_op: read_lpen: draw_line: draw_box: fill_box: ret write_tty endp ; extty_on proc near assume ds:data mov ax,data mov ds,ax mov tty_on,1 ret extty_on endp extty_off proc near assume ds:data mov ax,data mov ds,ax mov tty_on,0 ret extty_off endp ; code ends end ASM rX .RSTEAL210ASM S 1SU EXE {/ 4TABLES ASM o X& if2 %out Pass 2. endif .286c page 60,132 name ibm title Slicer BIOS Version 2.0A (Monitor 1.3 emulation) .xlist subttl Data Areas page + include biosdata.asm page + .list ;-------------------------------------------------------------------------------- ; BIOS for the Slicer. (C) Slicer Computers Inc., 1985 ; ; Version 2.0 April 4, 1985 ; By David Daney 1985 ; ; ;-------------------------------------------------------------------------------- subttl Equates page ;---------------------------------------------------------------- ; E Q U A T E S ;---------------------------------------------------------------- b equ byte ptr w equ word ptr hd0 equ 4 console equ 6 aux_dev equ 8 prn_dev equ 7 input equ 0 output equ 1 in_status equ 2 out_status equ 3 function_call equ 0f8h disk_read_cmd equ 10011000b disk_write_cmd equ 10111000b time_out equ 80h not_ready_error equ 80h bad_seek equ 40h bad_crc equ 10h record_not_fnd equ 04h write_protect equ 03h bad_addr_mark equ 02h bad_cmd equ 01h int_stat equ 8ah ;CHANGE int_stat2 equ 9ah du_out equ 9ch dureset equ 9dh subttl Externals and Publics page + ;---------------------------------------------------------------- ; Externals and Publics ;---------------------------------------------------------------- public old_call_init public number_table public print_al public print_ax public conout2 public old_load ;Jonathan ;ADDED FOR MAP public read,write,old_dispatch extrn disk_read:near extrn disk_write:near extrn disk_reset:near extrn drive_mask:byte subttl Initialization Code page + cgroup group code code segment byte public 'code' assume cs:cgroup old_call_init proc near ; set macro num,val mov w num,offset val mov w num+2,seg val endm ; assume es:vectors set vector_fb,old_dispatch set vector_3b,old_dispatch assume es:nothing ;initialize duout and duimr for old monitor calls were bl = 0ah, 0bh, 0ch, 0dh push dx push ax push ds mov ax,data mov ds,ax assume ds:data mov duout,0 ;assumming all outputs resset fix later mov dx,int_stat ;interrupt status register on slicer board in al,dx ;read it mov duimr,al ;save it if people call this through monitor it won't be screwed up pop ds pop ax pop dx ret old_call_init endp number_table db '0123456789ABCDEF' old_table dw dispatch_end ;0 dw const     ;1 dw conin ;2 dw conout ;3 dw dubin ;4 dw dubout ;5 dw dispatch_end dw home ;6 dw read ;7 dw write ;8 dw duon ;9 dw duoff ;10 dw duhigh ;11 dw dulow ;12 dw lstout ;13 dw lstst ;14 dw dispatch_end ;15 dw dskcheck ;16 dw dispatch_end dw dolmess ;17 dw message ;18 dw hexword ;19 dw hexbyte ;20 dw decdisp ;21 dw clrscr ;22 dw crtset ;23 dw old_load ;24 added by jonathan old_dispatch proc far sti cld push bp mov bp,sp push es push ds push si push di push cx push dx push ax mov cx,data mov es,cx assume es:data cmp bl,21h jae dispatch_end xor bh,bh shl bx,1 jmp old_table[bx] dispatch_end1: pop dx ;discard old ax jmp short de3 dispatch_end: pop ax de3: pop dx pop cx pop di pop si pop ds pop es pop bp ret 2 old_dispatch endp const proc near ;console input status mov ah,console mov al,in_status  jmp short const1 lstst: mov ah,prn_dev ;printer status mov al,out_status const1: mov si,offset old_temp_char int function_call or al,al jz const_rdy xor al,al jmp dispatch_end1 const_rdy: mov al,0ffh or al,al jmp dispatch_end1 const endp conin proc near ;console input mov ah,console jmp short conin1 dubin: mov ah,aux_dev ;aux input conin1: mov al,input mov si,offset old_temp_char mov cx,1 int function_call mov al,es:[si] jmp dispatch_end1 conin endp conout2 proc near ;output al to device in ah push ax mov si,offset old_temp_char mov es:[si],al mov al,output mov cx,1 int function_call pop ax ret conout2 endp conout proc near ;console output mov ah,console jmp short conout1 lstout: mov ah,prn_dev ;printer output jmp short conout1 dubout: mov ah,aux_dev ;aux output conout1: call conout2 jmp dispatch_end conout endp home proc near ;home disk drive heads mov bl,dsknum and bx,03h  ;mask for floppy disks only mov al,cgroup:drive_mask[bx] or recal_required,al jmp dispatch_end home endp read proc near mov bx,es mov ds,bx assume ds:data mov al,dsknum cmp al,3 ;this means a disk greater than 3 must be a hard disk ja hd_read ;that is not good it should be check with dskcheck call call disk_setup mov al,settle and al,4 or al,disk_read_cmd ;ADDED BY JONATHAN ;FOR HEAD DEBOUNCE call disk_read r0: mov ah,diskette_status r00: xor al,al test ah,write_protect jz r1 or al,040h r1: test ah,bad_crc jz r2 or al,8 r2: test ah,time_out jz r3 or al,080h r3: test ah,record_not_fnd jz r4 or al,010h r4: jmp dispatch_end1 hd_read: cmp al,4 je r5 cmp al,5 je r7 r6: mov al,0ffh ;drive does not exist jmp r4 r5: cmp hdpb0.step_rate,0ffh ;drive does not exist je r6 jmp r8 r7: cmp hdpb1.step_rate,0ffh je r6 r8: push ax mov ax,dsktrack mov bx,17 mul bx sub ax,1  sbb dx,0 add al,dsksector adc ah,0 adc dx,0 mov bx,ax ;sector number in dx:bx mov cx,1 mov si,dskmem mov es,dskseg pop ax mov ah,al mov al,input int function_call mov ah,al ;status to ah jmp r00 ;xlat status and exit read endp write proc near mov bx,es mov ds,bx mov al,dsknum cmp al,3 ja hd_write call disk_setup mov al,settle and al,4 or al,disk_write_cmd ;ADDED BY JONATHAN ;FOR HEAD DEBOUNCE call disk_write jmp r0 hd_write: cmp al,4 je w5 cmp al,5 je w7 w6: mov al,0ffh ;drive does not exist jmp r4 w5: cmp hdpb0.step_rate,0ffh ;drive does not exist je w6 jmp w8 w7: cmp hdpb1.step_rate,0ffh je w6 w8: push ax mov ax,dsktrack mov bx,17 mul bx sub ax,1 sbb dx,0 add al,dsksector adc ah,0 adc dx,0 mov bx,ax ;sector number in dx:bx mov cx,1 mov si,dskmem mov es,dskseg pop ax mov ah,al mov al,output int function_call mov ah,al ;status to ah jmp r00 ;xlat status and exit write endp disk_setup proc near mov es,dskseg mov bx,dskmem mov drive_number,al mov ax,dsktrack mov disk_track,al mov al,dsksector mov ah,al and al,07fh ;mask out side mov sector_number,al shr ah,7 ;head number in bit 7 mov head_number,ah mov num_of_sectors,1 ret disk_setup endp duon proc near mov cl,al mov dx,int_stat2 ;interrupt stat on slicer board serial in al,dx or al,cl out dx,al ;s!  et requested bits mov duimr,al ret duon endp duoff proc near mov cl,al not cl mov dx,int_stat2 ;interrupt stat on slicer serial in al,dx and al,cl out dx,al mov duimr,al ret duoff endp duhigh proc near mov dx,du_out ;set outputs reg on slicer serial out dx,al or duout,al mov al,duout ret duhigh endp dulow proc near mov dx,dureset ;reset outputs seg on slicer serial out dx,al not al and duout,al mov al,duout ret  dulow endp dskcheck proc near mov ax,es mov ds,ax mov ah,dsknum cmp ah,3 jae dc1 mov al,84h ;analyse format int function_call or al,al jnz dc2 ;read error mov al,dl shr al,2 ;sector size in bits 0,1 and al,3 cmp bl,2 jne dc3 or al,4 ;2 sides dc3: mov ah,8 ;disk is floppy shr dl,4 and dl,7 or ah,dl ;mini,d'density,half track xor bx,bx ;set zero flag jmp dispatch_end1 dc1: mov ax,1002h ;hard disk 512 byte sector xor bx,bx  jmp dispatch_end1 dc2: or al,80h jmp dispatch_end1 assume ds:nothing dskcheck endp dolmess proc near mov si,ds mov es,si mov di,dx mov al,'$' mov cx,0ffffh repne scas b [di] not cx dec cx mov si,dx mov ah,console mov al,output int function_call jmp dispatch_end dolmess endp message proc near mov es,[bp+4] mov di,[bp+2] mov al,0 mov cx,0ffffh repne scas b [di] not cx mov si,[bp+2] add [bp+2],cx dec cx mov ah,console mov al,output int function_call jmp dispatch_end message endp print_al proc near ;print al in hex ax not destroyed mov bx,offset number_table mov di,ax shr al,4 and al,0fh xlat number_table[bx] mov ah,console call conout2 mov bx,offset number_table mov ax,di and al,0fh xlat number_table[bx] mov ah,console call conout2 mov ax,di ret print_al endp print_ax proc near ;print ax in decimal mov bx,10 xor dx,dx div bx add dl,'0' or ax,ax jz got_it push dx call print_ax pop dx got_it: mov ah,console mov al,dl call conout2 ret print_ax endp hexword proc near xchg ah,al call print_al xchg ah,al call print_al jmp dispatch_end hexword endp hexbyte proc near call print_al jmp dispatch_end hexbyte endp decdisp proc near push ax call print_ax pop ax jmp dispatch_end decdisp endp clrscr proc near mov al,crt_mode mov ah,0 int 10h jmp dispatch_end clrscr endp  crtset proc near mov bh,0 ;page # may change this mov bl,dh ;dh has column mov dh,dl ;dl has row need to flop for int 10h mov dl,bl mov ax,200h int 10h jmp dispatch_end crtset endp old_boot equ 8800h return equ 12h timer equ 70h romseg equ 0f800h intret equ 7ffdh boot_info struc load_offset dw ? ;this is address to load loader load_segment dw ? run_offset dw ? ;this is address to jump to once loader is loaded run_segment dw ? num_of_sec dw ? ;number of sectors to load bytes_per_sec dw ? sec_per_track db ? boot_info ends old_load proc near mov ax,87h ;reset disk system int function_call or al,al jz old_l1 jmp boot_error old_l1: mov ax,84h ;analyse format int function_call or al,al jz old_l2 jmp boot_error old_l2: mov bl,1 mov cl,1 mov ax,82h int function_call mov cx,1 ;number of sectors mov bx,0 ;sector number 1 mov ax,80h mov es,ax ;load segment mov si,0 ;load offset mov ax,0 int function_call ;read in first sector of disk to 80:0 or al,al jz old_l3 jmp boot_error old_l3: mov al,es:return ;look for ret instruction in old loader cmp al,0c3h jne not_cpm ;if no ret instruction not cpm disk push offset old_l4 push old_boot ret old_l4: cmp al,1 jnz not_cpm ;bx points to boot info off disk in ld4.a86 push bx mov ax,85h ;get current disk prams int function_call pop si push si mov ax,84h ;get disk prams int function_call xor ch,ch mov cl,es:[si.sec_per_track] mov ax,82h ;set disk prams int function_call pop bx push bx mov cx,es:[bx.num_of_sec] mov si,es:[bx.load_offset] mov es,es:[bx.load_segment] mov ax,0 mov bx,0 int function_call ;load loader at proper address pop bx or al,al jnz boot_error mov bx,es:[bx.run_offset] call far ptr go boot_error: not_cpm: ret old_load endp go proc far push es ;se!  gment to jump to push bx ;offset to jump to ret go endp code ends end OLDCALL ASM +A`.RESET ASM *SETPORT BAT H/ +SOURCE DOC i(,SPRN ASM rX .RSTEAL210ASM S 1SU EXE {/ 4TABLES ASM o X& .286c page 60,132 name reset title Slicer BIOS Version 2.1 subttl Reset code umcsr equ 0ffa0h umcsv equ 0f838h ;32k no wait states bios segment at 0f800h org 0 initialize label far bios ends code segment assume cs:code reset proc far mov dx,umcsr mov ax,umcsv out dx,ax jmp initialize ret iret db '1E ' reset endp code ends end SU S.IN init @`! #@%`')+-/1 3@5`79;=?A C@E`GKMOQ S@oWY[]_a c@e`gikmoqs@u`wy{}@o @ ` @ ` @ ` ` ǀ ɠ @ ` ׀ ٠  @` @`!Aa   !Aa!!#A%a')-//35a79;=?A!CAEaGIKMOQ!SAUa D O C U M E N T A T I O N F O R B I O S S O U R C E C O D E F I L E S N E E D E D F R O M S O U R C E D I S K RESET.ASM BIOSDATA.ASM BIOS.ASM IBMBIOS.ASM NEWCALL.ASM OLDCALL.ASM NEWVIDEO.ASM NEWKEY.ASM BOMB.ASM SPRN.ASM DBG.ASM TABLES.ASM MEMTEST.ASM HDBOOT.ASM 8087MAC.ASM IBMPRN.ASM ****************************************************************** FILES OTHER THAN BIOS NEEDED TO ASSEMBLE THE BIOS EPROM.EXE ( not supplied ) LINK.EXE MASM.EXE ( not supplied ) EXE2BIN.EXE BIOSADJ.EXE BIOS.MAK ( not needed but very nice ) MAKE.EXE ( not supplied not needed but nice ) ******************************************************************** The editor used on these files is PMATE-86 V#3.37. This editor has no end of file marker. If an end of file marker is needed for your editor use debug to put cntl Z at the end of the file. The assembler used was microsofts MASM version 4.0. The version is important because previous versions have a bug with push immediate command. The linker was also microsoft. The MAKE file is also used from the micosoft assembler as a way to save time and reduce error in assembling the bios. The file BIOS.MAK is given as an example for you, it is the one used at Slicer when the bios is assembled. If you follow the steps in this file you will have a binary file that starts with reset located at F800:7FF0. The file then needs to be put in Intel hex format, split into odd and even halves and downloaded to your eprom burner THEN UPPY DUPPY WE HAVE FUN!! IF ANY FIXES ARE MADE PLEASE LET US KNOW!  0f800h org 0 initialize label far bios ends code segment assume cs:code reset proc far mov dx,umcsr mov ax,umcsv out dx,ax jmp initialize ret iret db '1E ' reset endp code ends end "   .286C page 60,132 .xlist include biosdata.asm .list ;------------------------------------------------------------ ; Slicer drivers for the System Expansion Board ; This driver provides an I/O channel for the printer ; port on the Slicer System Expansion Board. ; ;------------------------------------------------------------ ; ; E Q U A T E S ; ; ; w equ word ptr b equ byte ptr ; base equ 200h parport equ base+60h stbon equ base+1ch stboff equ base+1eh inport equ base+1ah ready equ 08h fault equ 040h fault_error equ 20h not_ready equ 80h bad_command equ 1 cgroup group code public new_parallel ; code segment public byte 'code' assume cs:cgroup,es:nothing,ds:data ; new_parallel proc far dec al jz prn_out dec al dec al jz prn_stat mov al,bad_command ret prn_out: push cx ;save character count jcxz po_end po_loop: mov prn_countl,0 mov prn_counth,0ah mov dx,inport ack_wait: in al,dx test al,fault jz po1 mov al,fault_error ;out of paper jmp po_end po1: test al,ready jz po2 ;jump if ack dec prn_countl jnz ack_wait dec prn_counth jnz ack_wait mov al,not_ready ; time out no ack jmp po_end po2: lods b es:[si] call send loop po_loop ;loop for multiple characters xor al,al xor bl,bl po_end: pop di ;return number of characters sent sub di,cx mov cx,di ret send proc near mov dx,parport po9: out dx,al ;output data mov dx,stbon mov al,80h out dx,al ;send strobe low mov dx,stboff ;send strobe high again out dx,al ret send endp ; ; ; S T A T U S ; ; prn_stat: mov dx,inport statlp: in al,dx test al,ready mov al,0 jz pos_end ;jump if ready mov al,printer_stat ;test if printer was used test al,8 jnz stat1 ;jump if printer was used or printer_stat,8 mov al,0h call send ;send break for first ack mov al,0 jmp pos_end stat1: mov al,not_ready pos_end: ret new_parallel endp code ends end !OLDCALL ASM +A`.RESET ASM *SETPORT BAT H/ +SOURCE DOC i(,SPRN ASM rX .RSTEAL210ASM S 1SU EXE {/ 4TABLES ASM o X&.186 ;This program steels vector 21h. The reason is so that the two MS-DOS calls ;set vector and get vector can not change the vector for int 13h. ;*************************************************************** ;MACROS data segment dw 100 dup(?) stack_top dw ? data ends GET_VECTOR MACRO INTERRUPT MOV AL,INTERRUPT MOV AH,35h INT 21H ENDM ;*********************************************************** ;EQUATES DOS_INT EQU 21H ;****************************************************** code segment assume cs:code,ds:data,es:nothing,ss:nothing steel21 proc far ;*************************************************************** ;GET NEEDED INTERRUPT VECTORS AND SAVE START: mov ax, data mov ss, ax mov sp, offset stack_top GET_VECTOR DOS_INT MOV DI,OFFSET DOS_VECTOR_21 ;GET OLD INTERRUPT 21H MOV CS:[DI],BX ;SAVE IT MOV CS:[DI+2],ES ;********************************************************************* ;STEAL NEEDED VECTORS  cli mov ax,0 mov es,ax MOV AX,CS ;STEAL INTERRUPT 21H MOV DX,OFFSET NEW_21 mov bx,84h ;INTERRUPT 21H mov es:[bx],dx mov es:[bx+2],ax mov cx,ax sti ;************************************************************* ;EXIT AND STAY_RESIDENT MOV DX,OFFSET FINISH MOV BX,OFFSET START SUB DX,BX mov cX,4 SHR DX,cl ADD DX,20H MOV AH,31H mov al, 0 INT 21H ;***************************************"  ************************ ;OLD INTERRUPT VECTORS AND NEW SEVICE ROUTINES DOS_VECTOR_21 DD ? NEW_21: cmp ah,25H ;2513 JNZ TEST_2 CALL TEST JMP SHORT OUT TEST_2: CMP AH,35H JNZ OUT call test OUT: JMP DOS_VECTOR_21 TEST PROC NEAR CMP AL,13h ;THIS IS SLICER TIMER JNZ TEST3 ;BESIDES IBM DRIVES MOV AL,0FDH ;THIS IS MORE LIKE DRIVES JMP SHORT TEST_DONE TEST3: CMP AL,24H ;DRIVES FATAL ERROR SAVE JZ NO_NO JNZ TEST_DONE NO_NO: POPF ;RETURN IRET TEST_DONE: RET TEST ENDP ;************************ ;END OF PROGRAM DW 10H DUP(?) FINISH: DB ? steel21 endp code ends end start H/ +SOURCE DOC i(,SPRN ASM rX .RSTEAL210ASM S 1SU EXE {/ 4TABLES ASM o X&MZH Y, dO277U5S^w}-]U>+t]Ë^?;tSJ)R2SJ)R2vSJ)R2]U>+tJ)Rv1F%PSJ)R2]U>+tvFPvSJ)RS2]á+6=t SJ)R82Rá+\6=tRSJ)R2U5 ^6SF ^w1HSF ^wUSF ^w-`SF ^wqS]6\( lKûqSIS+ûSO3U ^F ^G^F vGD^F vGD^F vGD^F vGD^F vG D^F vG D]U ^F ^vGF ^vGDF ^vGDF ^vGDF ^vGDF ^vGD F ^vGD ]U^GF؁ô+^vS^w*vB]U^w;S^wx*]U ^F ^vGF ^vGD]U ^^F vD^F vGD]U\,^v^wS^w)vk]U ^F ^vG]U ^^F vD]U`,^v^wS^wk)v]US^wK)]U>+tv5v8~@u~Dtvv, SJ)R.vvB SJ)Rw.]U^vG;Dt SK0P,^vG;Dt S)0P,^vG;Dt S0Pv,]UF^^^?tvF^?tv vFP~u]Ã~u v8^G؋^ߋWFP^G؋PFP^G؋^ߋWFPd^t ^uRF%P;]U^(1=t1^G1=t#^G 1=t^G*0=t]û? SFF؋F RFP0RFPRFPRFPvv=FP^S)^G ^ ^G Nj^* W FP"RFP]U^/=t1^G/=t#^G/=t^G*/=t]Ë^ tt^G t=t v^G tt^G* t=t ^S@ S)6A SF RFFP1B SRFFPN S RFFPW SRFFPc S]U^. tt^G. t=t]áFRFFPl SE^G؋vD4 JPFFPNx S^?t@RFFP+ S^G:FFP S^t@RFFP S^GBFFP SRFFP SeRFFP SJRFFPl S/RFFPQ S#   RFFP6 S RFFP, S RFFP= SRFFPJ S RFFPO SVRFFP\ Sr^,=t*^G؋F^G؋$F"^G؋F^G؋$F RFFP; SvFFP! S RFFP SvFFP SRFFP SRFFP SyRFFP S^RFFP SCRFFPe& S(RFFPJ2 S RFFP/= SRFFPI SRFFPT SRFFPa SRFFPm SRFFP Sk RFFP SP RFFPr S5RFFPW S^G tu^G t=u^G tt^G t=tRFFP SA^ tRFFP SRFFP SkRFFP SN]û S=R+R.R+R R$,R<6 S R$,R_= SR@,RGD SR>UE SFRF SR]UF%FFgF@PP SR+FPX S;R_ S'F؋FPo SF?z SF؋FPP SF S]UF%FF SFP+FP SaR SMF؋FP S.Fe SR S FPj SRVS~ t@5F P5S]U'SFF؋FF؋FF~}kF^؋&=t vDF^؃ t%F^w FFPvvc vv}F돋]UF%FFF@P(SF%FF 0SR 7SF؋PFPGSlFhRSQF؋XFP_S2FhilS]UF%FFySFP$FSR/SF؋PFPSF`SsRS_F؋XFPS@RS,~t@5FPS ]USFF؋FF~}dF^؋#=t v=F^؃ tF^w vvl vvyF떋]ûS[>/ t!RS@R~Rq SR](S Ry/S`Re?S R!JSR=WSRdSûqS>`,t4RRSwRScRRûSB>\,t Ry RmRcúR+R`R+RRR$,RDR%UF~}^^~ ؉F݋]UvvS]U컍vS]U커vS]U컻vSw]UvS`]UvRSS]û\S2SzûSSkU< ^^F vGD^F vGD^F vGD^F vGD^F vG D^F vG D^F vGD^F vGD]U< ^F ^vGDF ^vGDF ^vGDF ^vGDF ^vGD F ^vGD F ^vGDF ^vGD]U ^^F=uFF ^FG^F vGD^F vGD^F vGD^F vGD^F vG D^F vG D^F vGD^SP ^F~}^F ؊G(F ^GFF~}^F@؊G(F ^GFދ^G/F ^G^GF\ ^^F vGD^F vGDF ^?t^G #F=H ^G؋]U ^F ^vGF ^vGDF ^vGDF ^vGDF ^vGDF ^vGD F ^vGD F ^vGDF~}F ؋vvDF޻ ^F~}F ^vF GD(FF~}F ^vF@GD(F߃F ^vGD7D7^G0G0^G/G/^G(F\ ^F ^vGDF ^vGDF ^?t^t ^G F^FG]Uʃ>c} S]Ë^-0F~| F;e~3>e |H eFFeF؁"/^^cF؁"/^^7vS^SPv?R<S^Sv]U֋^-0F~| F;c~>c |H cFFcF8؁,SvS^SS^SF8؁,S5]U֋^-0F~| F;g~>g |H gFFgF؋/vS^SFS^SF#  /]UFF;e}F؋"/;FuF]FػS]UvFFFF؋"/;Fu F;e}ߋF+F]Uv^F7PFPPSUv^F7PRtFPS$^F=uFHFvvUPv6PkS]UFFF~}$F#F=tF؋"FFFF֋F]UF8؁,^S~^7 SiR SU^w S?^w{( S)^we7 SvFPHK Sv5Z S^wOd S^wFP/t SR SvP S SuF~}^^GPF^?u^?uR S*^GF^G nF^G nFPz Svg SvT SR@ S^?u?R! S!SF~}^^G(PFR!S`v^wPRFP)!S2FFP^wpPvfPvGP|>!S߃v)PvF_ljFQ!S߃F;F}vFF؁(/S)vFa!S߃F;F}vFF؁./Sۋ]UFF;c}vF]Us!S:߃^F8؁,^F~uFvS߃!S߃v@߃!Sރ~u^G F^G F^GFFnnP2߃!SރR߃!SރR ߃!Sރ~u)Rރ!Snރvރ!S[ރ&vރ!SFރvރ!S3ރ^wރ"Sރ^wރ"Sރ]UFF;e}F؁"/SF݋]U%"S݃^7ރ]UFF;g}F؁/SF]û-"S~݃cc=} F"S6c݃["ST݃ee=} x"S6e|݃"S*݃ggPd݃"S݃ >g~KcegU$^^F^G^F vGD^F vGD^F vGD~uj,b,^^F vD^F vGD^F vGD^F vGD]U$^^vGFF ^vGDF ^vGDF ^vGD~uj,b,^F ^vGF ^vGDF ^vGDF ^vGD]U^PX -AF~|~~>a|H aFFaF؁r,SpAFP@$S^Se$S^SF؁r,S]UR^7N PSۃ$SۃR^w- P2ۃ%SڃR^w Pۃ$%SڃR^w Pڃ2%Sڃ]UFR%Sڃ~})F؃r,tF؃r,tFу~} 6b,' RڃFf%S-ڃ~}F؃r,tF~} 6j, R<ڃ]Ux%Sكv"ڃ%SكR>ڃ%SكR*ڃRكFt,ك%SكRك%SuكFx,ك%SVك]UF؋v,RPFFvv6'6'v@ F%SكvRك%SكRnك%S؃RZكR كRكR ك &S؃&S؃Rك%&S؃R؃;&S؃R؃R؃vv6'6'6'6'؃J&SH؃F P؃V&S-؃FPc؃i&S؃RO؃Ru؃|&S׃6'a؃&S׃'RPvvXZ'R ؃&S׃R׃Fx,׃&S׃]U&S}׃v׃&Sj׃R׃&SV׃R׃R׃R׃Rv׃&S$׃R׃&S׃RN׃'SփR:׃R0׃F؋v,HPC׃'Sփ?R/׃)'SփRփ<'SփRփRփO'S{փRփ_'SgփRփm'SSփRփFx,|փ'S*փ]UF~}GF؋r,F=u v ~u v~u vKF볺R փ]Uv'S )) =t'S u 'Sz ]UF ^؃?t*F ^wvG=tF]Fĸ]URvvF=}]ËF@Pvv=~]ËF]U^?u]vvF=|F]Ã~u 'S]'~u (S]v(S P]U^w/(Sg ^w^w3(SQ v](S@)R ]U^w`(S+ ^w^wd(S ^S(S@)R ]U^F~u^_^vvv^Ӄ ~u\v^wF=|)^_ nމ^^S(Sv^S^w^w~u^vG~uF^S(Sv=t!^F;G|^F;G  ^FG ^SJ~uD^S(Sv=t!^F;G|^F;G  ^FG ^S]U^_^^?t$^G;Fu^w(S]F Ի(S~]UĂ>)uv(S_^^^F=u^GF^w(S0~|~t~u^F;t (S $  N~uvv9:~uv(S%~uv(S~u (S^w(SF J(S'R^S ^^^S^S(S^S)S^S=u)S)SA^SvOF=|v^SF ^S^?u]]U~A}H t ~Z~H ]U~a}H t ~z~H ]U~0}H t ~9~H ]U~ t@5u ~ t@5u ~ t@5]Uvj tuvt t]Uv\=tF- F]Uv=t FF]U^FFFP^F;u~tҊF ]Uv0Fv$F]U~ t@5u ~ t@5u ~ t@5]UFF=u^]Ã~uv=t{~ u$^F R7 R-^]Ã~u,~~$NR  RRNF;F}F^FFvY]UF;F~FF]UF;F}FF]U//=tv/؋/ӃFF;:*}DF ؋F)%=t)F ؁@)SF H)Fv]U>/ }//؋v/]ø]U^=| ^O@^wGF%] vv7]]U~ u^G%=u v Rvv]U^u^G%=t^_v0\^G%=t#^_Fv=u]ËF]v=u]vv]U^0^Sv.3S2]U60v+]U^G%=t]Ë^=|^wG%] v]]UvF^G%=tF]Ã~ tF^?^G%=tvnFCFFFR^S^w0=tFR6>)6<)^w~ t~t~t vvF ~u vFF]Ã~u ^OF~uF%]URRR+FF PRR@)RF~u @)OFvRR~uFF%]ú@)RU^Sv5SE]UJ)Rv=]U^0^Sv]5SF0F]U00F%]U@)0^Sv5S5Sf ]U^0^Sv5S5SF ]U^0^Sv6S5S& ]60U60v0]U00F=tF]U~t00F0F]Uv~<ttrtH]ð:UNVNV ]UUSVWPR u^ v^v uZUU u V~V ~ u ZWŀt 3+ƋËt 3+Nj‹UQ3 +sӋY]Z t2ŀt 3+ƋË؉v^ X_^[] uUPS^Ff ȋFȋFʉN F[X]UV ;Vt 2vy V+V]&+؁vЋ-Á+؎J!؎+0+ t3PU^GFF%=t F%=t]Ë^uBPPv\^twt^O^]]v]U^G%D=u^G%=t^?u FF]^?}^^+FF^F^g^v_\~tv^w^w]Ë^G%=t^^v_\]U^G%=t^G%=t]Ë^uN^G%=t^_v 0\,PPrv\|u ^O^O멋^v_\^G%=tP^w^w+^^G%=t^O^=}&^?u ^O^O ^]Ë^wG%]UD<*^^^^^F^?u ^?%tFFFFFFFFFދFމFFF^Pv^t^+^ù^ʍJ^^?0uFF^S^SF^?.uF^S^SlF^?luFF^FQFd~t^Fw7va^FRPvJrF*F#F ~t^Fw7vA~tv^Fw7v^v^F3RPv^^~su ^F^~u vqF(^FvF^~tFF^Pvv^Fwww7JS~uFq^^F^[=gt=ft=et=Et=Gt=suA=cu9=uu=xu=Xu=ou=duc=iuV돃~su^J^SF~su~|F;F~FFFFE^v=d}v=g~~t,^?-u^F^FN ^F+F0~t*^?-u^F^FN ^F F~t~u5v>=t^FF^ӉF80F띃~.uWF tu F t=tv^Ӄ80F^FF^ӉF80F@vO=euB~tv^Ӄ80Fv$^F^ӉF80F~+t ~-t~ uG~t~tv^Ӄ80-F~-u ^FF^ӉF80F^~tv^Ӄ80~uF]~u~tF]Ã~u@~t^SrRQSP^GGG^STRQSP^w GF~uF]3~%uE^ӉF~u~tF]80F;Ftv^Ӄ80F]^ӉF80~u~tF]ËF;Ftv^Ӄ80F]F]U^ӉF80v=tF]U^?^u FFFF N =u*^ӉF80FF^^?]u ~t~t^^?]uF tt^^=-t@5=tJFH^؊~G^ߗ;}-FH^؊~;|F@^؊~;F^^~;uFM~t ^^?]tF~t~u~ u ^FF'~u~u~ u ^FFv^Ӄ80~ u^F^?]tF^]U~u]Ë^G%=t0^v_;\v"^?|^O_F^]]]U^*t9*tDŽ*;T*uT*;V*uV*>!r]ã*]YXL!U^FD<u!r*]<uV!r~u ^ :0]ø*]^[ZYXPQRSVB!rã*X[ZYQRSP;T*t?!rã*á0 t3;~Pȋ600<00X+0Q6060Xû>:0uRQ<0?!YZr0<00 u>%=u@R*D!€u T*F)D!€u V*P)USv] ]UFfFP^~tvRv4 ^]UFF~uFv v vvvE F~~]Ë^^?-uFvL*~}v~H =tF@Pv1^^C^F=.t@^FF tu F t=t^. ^^^N~u~u^K?.u ^N^Fe~| ^F+F؉F^F-~ } ^F0vvn~u+vvv`^?.tFF؋vF^^~|F؉F=~F+FF^^F؋vvFFFN=t^^N^N0܋^;^t ^N0vvv^^FFF=}vvv^C^^?.tF^^^.~~FFFF+FFFN=t^F^FFN=t ^F0+FF=}FF+FF=} FFF~t ^F.FN=tFFN=t ^F0^~t~up.RvFtKv؋vNvvb߃=gu^?0u ^N~u^?.u^~t X*Svq0=u=fu=u=eu=u=gu]UF؋vFvv^N?4^@^?9~ ^N0^?/ud^F1F tu F t=t ^F.FF0F;F}^F^FFFFFً^]U~ uFvv6g*6e*XZFvv6k*6i* FF6o*6m*vvF%  Fu~ uFvv6s*6q*XZFvv6w*6u* FF6{*6y*vvZFF)vvF RPXZFvvF RPKFFF Ftv vvv"^~}F؉F~ ~ aF- 0F^F^]U^^vv6*6}*s?vvFF^F-vv6*6}*lsZ*Svl^]ú Rvvvz^^^]U^^ RvvvK^^^]UFRPvA]U~+-]U~F=t uuK]<t]U^VN;V*t<*t9*tB!^VN@Q!Y;u]ã*]ËڸPSQ!Y[XC@]UR*t F^]PSF ȀV~ٱu=w=~w-y@+ҋڰs@=w߀ ňF V ~[X]U+ҋ+VNVN]UNV)NV ]Uv]UFH3@F0^u0^000^^^F;rl^F;u ^v;F؋v^7^F+^^v4^FG^^0^]Ë^;0uFP'^u]Ë^^^^T]UFH3FFPK^~u]Ë^^^FG^^S 0]U^^^?t]Ë0^^;^wH t^v;7rH =t(^v;7r^;^w ^v;7s ^^밋^G؋v^;7u^vGD^v ^v^G؋v;vu^vGD^v^v7^0]U^^^?tF^F^F?t^]U^P׃=tF^Svg^~t^v7F^NV]Z_WRËDu-. 00EG+@naninfinityindefinite y-Gd+%=u4T  T TuDtDuOW. þWW<+r,+s.DdL-t $TTTRDT\U, DT\,,\TD0%G*װE]ZR y-ڋ™0d0 Ę00*Xû* D;G s+D;G rWRttt4www7DDDZÊd2gDy;G;GuD;Gu D;Gu;U~FN^]Uv~<t^]UNV!N!V ]UUSVWPR u^ v^v uZ`UU u V~V ~ u Z-U3 +sӋ]Z t߉v^ X_^[]YUWVPSv~ ff ֋NJԁ F F F F uF F F Fu tN} tN vvtNuIt=< u=u=u =sߊF FFFFFFF jފcttЋ% tFu tVuFt+FuF t+F FFFF t Cw@F% À F[X^_]fV VVV+ۉ^^^^ ػ+FFFF 뭵+FFF FUN tn ^]Z^_WVRNU+҉UUUʋ¬<+t<-u<.uu+G<0r <:sg+