title 'Olympia "PEOPLE" XIOS' ; program: concurrent ccp/m-86 xios for version 2.0 ; dated: 7/5/83 ; author: douglas w. goodall ; the following program is an XIOS for Concurrent Version 2.0 ; to integrate this code into a useable CCPM.SYS it is necessary ; to assemble it using RASM version 1.0A which is only available ; in the native code version (RASM86.CMD). after the assembly is ; complete, the xios must be linked with LINK0.CMD which is a ; special version of the linker which is distributed inside ; the OS group. after the linker creates a .cmd file, this ; file must be renamed XIOS.CON per the system guide. cgroup group code,data include ccpmxios.equ public supervisor_o ; let int rtns do fast flagset public flagwait,flagset public nvcns public screen_struct_addrs public foreground_screen public io_statline public poll public sysdat public tick public i_nmi public console_owner ; pic extrn pic_disable:near ; ask pic to disable extrn pic_enable:near ; ask pic to enable extrn pic_vectors:near ; ask pic to setup vectors ; clock extrn clock_init:near ; timer hardware module extrn clock_baudset:near ; set baudrate per caller's ax ; tick extrn tick_init:near ; timer int rtn setup ; pdisk extrn pdio_init:near ; read sector from TMP: disk extrn pdio_rd:near ; read sector extrn pdio_wr:near ; write sector extrn dst1:near ; polling status routine extrn dst2:near ; polling status routine extrn hst_dsk:byte ; primitive disk module extrn hst_trk:word ; paramters extrn hst_sec:byte extrn hst_seg:word extrn hst_off:word ; console extrn io_const:near ; function target extrn io_conin:near ; function target extrn io_conout:near ; function target extrn co_no_escape:near ; escape handler extrn normal_const:near ; const handler (default) extrn normal_conin:near ; conin handler (default) extrn erase_screen:near ; utility routine extrn crt_rfrsh:word ; regen addr extrn enable_cursor:near ; utility routine extrn disable_cursor:near ; utility routine extrn set_physical_cursor:near; utility routine extrn video_status_line:word ; regen addr of status line extrn public_crt_init_attr:byte ; crt initial attribute extrn console_0_function_table:byte extrn console_1_function_table:byte extrn console_2_function_table:byte extrn console_3_function_table:byte extrn conin_shunt_stat:near if default_z19 extrn z19_special_char_tab:byte extrn z19_special_func_tab:byte extrn z19_esc_tab:byte extrn z19_esc_func_tab:word endif ; default_z19 if default_oly extrn oly_special_char_tab:byte extrn oly_special_func_tab:byte extrn oly_esc_tab:byte extrn oly_esc_func_tab:word endif ; default_oly ; list extrn io_listst:near extrn io_list:near extrn lcb_tab:byte extrn listst:near ; serial extrn serial_init:near ; serial module extrn serial_inp_stat:near extrn serial_out_stat:near extrn serial_output:near extrn serial_input:near CSEG ORG 0C00h-5 ;8080 model XIOS base ;CCP/M-86 entry points to XIOS: jmp init ;called once at system boot jmp entry ;subsequent calls go through here EJECT ; the following code is in the code segment because danny's was that way sysdat dw 0 supervisor_o rw 1 supervisor_s rw 1 supervisor equ dword ptr supervisor_o tick db true ticks_sec db 20 ; OLYMPIA "PEOPLE" door db false rb 2 nvcns db num_vir_cons ;4 virtual consoles nccb db 4 ;total number of ccbs nlcb db 1 ;1 list device ccb dw offset ccb_tab ;pointer to the first ccb lcb dw offset lcb_tab ;pointer to the first lcb dph_tbl dw offset dph1 dw offset dph2 rw 14 ; If Mdisk memory is not present, INIT: 0's DPH_M_ADR ; We put this DPHM in now so GENCCPM will perform ; DPH fixups for us. genccpm_buf dw screens_size ;GENCCPM will alloc screens_size ;# of paragraphs and put the ;segment address of the buffer in ;the variable genccpm_buf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; genccpm_buf is the last of the data items in this area which ; ; are defined in the system guide and therefore the last of the ; ; invariant header data items. implementation specific data items ; ; may be defined following this point ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; in order that the function key programming utility may find the ; screen structures, a pointer to the screen structures list may be ; found here. ss_ptr dw screen_struct_addrs console_owner db 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; debug db 0ffh ;debug mode - only set up the ;interrupt vectors we need ;leave the rest pointing to CP/M-86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; eject ;************************************************************************ ;* * ;* XIOS INITIALIZATION ROUTINE * ;* * ;************************************************************************ ; The following routine is used to initialize any required ; data areas and alter any peripheral chip programming when ; starting up CCP/M-86. This code is called once from the ; SUP(ERVISOR) after calling the SUP has called the RTM, ; RTM, CIO, MEM, BDOS initialization routines and before the ; SUP has created the RSP processes. ; This code can be placed in an XIOS data area if the XIOS is ; 8080 model (mixed code and data). Usually, overlaying the ; initialization code with a data area is done after the XIOS ; has been debugged. ; ********************************************************* ; * * ; * INIT * ; * * ; ********************************************************* init: cli ! cld push es ;save the UDA call pic_disable ; ask pic module to disable all call clock_init ; init tick period call serial_init ; init serial if necessary call tick_init xor ax,ax mov es,ax mov al,debug and al,al jnz no_wipe ; chuck's int wiper mov cx,256 mov di,10h mov ax,offset i_unexpected wipel: stosw push ax mov ax,cs stosw pop ax inc ax loop wipel no_wipe: call pic_vectors ; set up vectors for pic call pic_enable ; ask pic to enable eject ; ********************************************************* ; * * ; * initialize virtual screen structures * ; * * ; ********************************************************* ; Set up the virtual screen structures (one per virtual console) ; and blank out their screen save areas. ; initialize the screen structure's initial crt attribute mov al,public_crt_init_attr mov ss0a,al mov ss1a,al mov ss2a,al mov ss3a,al mov dx,genccpm_buf ;paragraph address of buffer ;space allocated by GENCCPM. ;this area is not part of the ;CCPM.SYS file, and is located ;with GENCCPM allocated disk ;data buffers at the end of ;the system image. xor ah,ah ;CX = screen we are initializing ;and param to erase_screen mov bx,offset screen_structures init_screen_structures: mov ss_screen_seg[bx],dx ;RAM storage segment for this virtual ;console push ax ! push dx ;save screen # ; test ah,ah ; jz no_erase ;don't erase screen 0 call erase_screen ;erase screen AH no_erase: pop dx ! pop ax ;screen # add dx,(screen_siz*2 + 15)/16 ;next virtual screen storage area add bx,ss_len ;next screen_structure inc ah ! cmp ah,nvcns ;do for each virtual console jb init_screen_structures eject ; ********************************************************* ; * * ; * ISSUE SIGNON MESSAGE * ; * ( WE ARE GETTING CLOSE NOW ) * ; * * ; ********************************************************* mov si,offset sign_on ; SI ==> MESSAGE STRING call print_msg ; ACTUALLY ISSUE TO CRT pop es ;restore the UDA sti retf ;initializaiton done ; end of init routine ; biosrw.a86 3/6/83 dwg/jn ;======= io_read: ; Function 10: Read sector ;======= ; Reads the sector on the current disk, track and ; sector into the current dma buffer. ; input: parameters on stack ; output: AL = 000h if no error occured ; AL = 001h if an error occured ; = 0ffh if media density has changed mov bx, offset io_read_es mov ax, path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov bp,sp mov al,drive cmp al,16! jb rdsk_ok ;check for valid drive mov al,1 ;return error if not ret rdsk_ok: mov idrive,al ;save DPH index in local variable xor ah,ah ;Index into the physical driver mov si,ax shl si,1 jmp read_tbl[si] ;jump to physical driver read routine eject ;======== io_write: ; Function 11: Write disk ;======== ; Write the sector in the current Dma buffer ; to the current disk on the current ; track in the current sector. ; input: CL = 0 - Defered Writes ; 1 - non-defered writes ; 2 - def-wrt 1st sect unalloc blk ; output: AL = 000h if no error occured ; = 001h if error occured ; = 002h if read only disk ; = 0ffh if media density has changed mov bx, offset io_write_es mov ax, path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov bp,sp ;set BP for indexing into IOPB mov al,drive cmp al,16! jb wdsk_ok ;check if valid drive mov al,1 ;return error if not ret wdsk_ok: mov idrive,al ;save DPH index in local variable xor ah,ah ;Index into the physical driver mov si,ax shl si,1 jmp write_tbl[si] ;jump to physical driver write routine eject read_write: ;unskews and reads or writes multi sectors ;---------- ; input: SI = read or write routine address ; output: AX = return code mov bx, offset read_write_es mov ax, path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov cl, idrive mov dl, FIRST_CALL_FLAG ; this is not the first select call io_seldsk ;get DPH address or bx,bx! jnz dsk_ok ;check if valid ret_error: mov al,1 ; return error if not ret dsk_ok: mov ax,xlt[bx] mov xltbl,ax ;save translation table address mov bx,dpb[bx] mov ax,spt[bx] mov maxsec,ax ;save maximum sector per track mov cl,psh[bx] mov ax,128 shl ax,cl ;compute physical record size mov secsiz,ax ; and save it call initdmatbl ;initialize dma offset table cmp mcnt,0 je rw_sects rw_1: mov ax,sector ;is sector < max sector/track cmp ax,maxsec! jb same_trk call rw_sects ; no - read/write sectors on track call initdmatbl ; reinitialize dma offset table inc track ; next track xor ax,ax mov sector,ax ; initialize sector to 0 same_trk: mov bx,xltbl ;get translation table address or bx,bx! jz no_trans ;if xlt <> 0 xlat al ; translate sector number no_trans: xor bh,bh mov bl,al ;sector # is used as the index shl bx,1 ; into the dma offset table mov ax,rwdmaoff mov dmatbl[bx],ax ;save dma offset in table add ax,secsiz ;increment dma offset by the mov rwdmaoff,ax ; physical sector size inc sector ;next sector dec mcnt ;decrement multi sector count jnz rw_1 ;if mcnt <> 0 store next sector dma rw_sects: ;read/write sectors in dma table mov al,1 ;preset error code xor bx,bx ;initialize sector index rw_s1: cmp current_reskew, 0 je no_reskew push bx! push ax mov ax, bx mov bx, current_reskew mov ah, 0 xlat al mov di, ax pop ax! pop bx jmps re_skew_1 no_reskew: mov di,bx re_skew_1: shl di,1 ;compute index into dma table cmp word ptr dmatbl[di],0ffffh je no_rw ;nop if invalid entry push bx! push si ;save index and routine address mov ax,track ;get track # from IOPB mov itrack,ax mov ax,di ;sector # is index value shr ax, 1 mov isector,al mov ax,dmatbl[di] ;get dma offset from table mov idmaoff,ax mov ax,rwdmaseg ;get dma segment from IOPB mov idmaseg,ax call si ;call read/write routine pop si! pop bx ;restore routine address and index or al,al! jnz err_ret ;if error occured return no_rw: inc bx ;next sector index cmp bx,maxsec ;if not end of table jb rw_s1 ; go read/write next sector err_ret: pushf! push ax! push bx push ax mov bx, offset read_write_es mov ax, path_counter mov PATH_EXIT[bx], ax inc path_counter pop ax mov LAST_RETURN[bx], ax pop bx! pop ax! popf ret ;return with error code in AL eject initdmatbl: ;initialize DMA offset table mov di,offset dmatbl mov cx,maxsec ;length = maxsec + 1 sectors may inc cx ; index relative to 0 or 1 mov ax,0ffffh push es ;save UDA push ds! pop es rep stosw ;initialize table to 0ffffh pop es ;restore UDA ret eject io_seldsk: ; ; ENTRY: cl = disk to select ; ; EXIT: ax = bx = offset dph[cl] ; current_reskew = address of reskew table for this drive mov ch,0 shl cx, 1 ; get the rekew word set up mov bx, offset re_skew_tbl add bx, cx mov ax, [bx] mov current_reskew, ax ; get the dph's offset to send back to the BDOS mov bx, offset dph_tbl add bx,cx mov ax,[bx] mov bx,ax ret eject read: ; ; calls the de-skewing routine mov bx, offset read_es mov ax,path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov si, offset read1 jmp read_write read1: ; ; get a local copy of the current floppy mode byte mov bx, offset read1_es mov ax, path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov al,idrive ! mov hst_dsk,al ; drive code mov ax,itrack ! mov hst_trk,ax ; track number mov al,isector ! mov hst_sec,al ; sector number mov ax,idmaoff ! mov hst_off,ax ; offset mov ax,idmaseg ! mov hst_seg,ax ; segment call pdio_rd ; use olympia read rd_exit: pushf! push ax! push bx push ax mov bx, offset read1_es mov ax, path_counter mov PATH_EXIT[bx], ax inc path_counter pop ax mov LAST_RETURN[bx], ax pop bx! pop ax! popf ret eject write: ; ; calls the de-skewing routine mov bx, offset write_es mov ax,path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov si, offset write1 jmp read_write write1: mov bx, offset write1_es mov ax, path_counter mov PATH_ENTRY[bx], ax inc path_counter inc USE[bx] mov al,idrive ! mov hst_dsk,al ; drive code mov ax,itrack ! mov hst_trk,ax ; track number mov al,isector ! mov hst_sec,al ; sector number mov ax,idmaoff ! mov hst_off,ax ; offset mov ax,idmaseg ! mov hst_seg,ax ; segment call pdio_wr ; use olympia write wt_exit: pushf! push ax! push bx push ax mov bx, offset write1_es mov ax, path_counter mov PATH_EXIT[bx], ax inc path_counter pop ax mov LAST_RETURN[bx], ax pop bx! pop ax! popf ret eject ; ; no deblocking in xios ; io_flushbuf: xor ax,ax ; thanks ray... ret EJECT ;************************************************************************ ;* * ;* INTERFACE TO CCP/M O.S. * ;* * ;************************************************************************ entry: ;arrive here from JMP at ; entry: AL = function number ; CX, DX parameters ; exit: AX = BX = return ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call ; Note: no alteration of stack is allowed during entry except ; for the return address caused by the "call function_table[bx]" ; instruction. ; the following code ASSuMEs that no bad calls(function # to great) ; will be issued because only the kernel calls here cld ;set the direction flag xor ah,ah shl al,1 ;multiply by 2 mov bx,ax ;put in pointer register call function_table[bx] ;no range checking needed mov bx,ax ;only called by O.S. retf ;return to O.S. kernel EJECT ; ********************************************************* ; * * ; * AUXILLIARY INPUT * ; * (NOT IMPLEMENTED AT THIS TIME * ; * * ; ********************************************************* io_auxin: ; entry: none ; exit: AL = character input ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call ret ; ********************************************************* ; * * ; * AUXILLIARY OUTPUT * ; * (NOT IMPLEMENTED AT THIS TIME) * * ; * * ; ********************************************************* io_auxout: ; entry: CL character to output ; exit: none ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call ret EJECT ;************************************************************************ ;* * ;* SWITCH SCREEN * ;* * ;************************************************************************ io_switch: ; entry: DL = Screen to switch to ; exit: None ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call ; PIN process does range checking of DL push es ;save UDA xor ax,ax mov al,dl mov bl,dl mov cx,ccblen mul cx add ax,ccb ;compute new foreground CCB mov foreground_ccb,ax xchg bl,foreground_screen ;save destination screen ;and get screen to save xor bh,bh ;index into screen structure array shl bx,1 ;word pointer mov bx,screen_struct_addrs[bx] ;get pointer to old envionrment mov cx,screen_siz ;in words mov es,ss_screen_seg[bx] ;destination segment xor si,si ! mov di,si mov ax,CRT_RFRSH ; PEOPLE push ds ;save DS mov ds,ax ;source segment rep movsw ;do the copy pop ds ;restore DS mov bl,foreground_screen xor bh,bh ;requested one shl bx,1 mov bx,screen_struct_addrs[bx] mov foreground_ss,bx ;new foreground screen SS address xor si,si mov di,si mov ax,CRT_RFRSH ; PEOPLE mov es,ax mov cx,screen_siz ;in words push ds mov ds,ss_screen_seg[bx] rep movsw pop ds pop es ;restore UDA mov ah,foreground_screen ;param to set_physical_cursor push ax ;save AH = foreground screen test ss_mode[bx],ssm_no_cursor ;turn on/off cursor ? jnz sw_no_cursor call enable_cursor jmps sw_done sw_no_cursor: call disable_cursor sw_done:pop ax ;restore AH = foreground screen jmp set_physical_cursor ret EJECT ; ********************************************************* ; * * ; * UPDATE STATUS LINE * ; * * ; ********************************************************* io_statline: ; entry: DX, CX = 0 ; exit: none ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call mov al,true xchg sline_locked,al ;is in io_statline at time cmp al,true ;sline_locked = 0ffh if locked jne sl_free ;sline_locked = 0 if not ret ;another process is in the code sl_free: push es ;save UDA mov dx,ds ! mov es,dx mov di,offset status_msg_start mov al,' ' mov cx,columns_per_screen rep stosb ;blank out local status string mov si,offset constr ;put in 'Console=' mov di,offset smsg_con mov cx,length constr rep movsb mov si,offset prnstr ;put in 'Printer=' mov di,offset smsg_prn mov cx,length prnstr rep movsb mov al,foreground_screen add al,'0' mov smsg_cnum,al ;set console number mov bx,foreground_ccb ;get process which owns the mov si,c_owner[bx] ;foreground console test si,si ! jz s_nopd ;make sure its non-zero mov al,p_list[si] add al,'0' ! mov smsg_pnum,al lea si,p_name[si] ;offset of process name mov di,offset smsg_pd mov cx,4 ! rep movsw s_nopd: s_ctrlS: mov ax,c_state[bx] test ax,csm_ctrlS ! jz s_ctrlO mov smsg_ctrlS,'S^' ! jmps s_ctrlP s_ctrlO: test ax,csm_ctrlO ! jz s_ctrlP ;ctrl S and ctrl O are mutally mov smsg_ctrlS,'O^' ;exclusive print one of ^S or ^O s_ctrlP: test ax,csm_ctrlP ! jz s_mode mov smsg_ctrlP,'P^' mov dl,'=' ! mov dh,c_mimic[bx] add dh,'0' ! mov smsg_ctrlP_num,dx s_mode: mov di,offset smsg_mode mov cx,length dynstr mov si,offset nosstr ;test for noswitch test ax,csm_noswitch ! jnz s_movmode mov si,offset dynstr test ax,csm_buffered ! jz s_movmode ;lsb bit=0: dynamic mov si,offset bufstr ;lsb bit=1:buffered test ax,csm_purging ! jz s_movmode ;check for purging mov si,offset purstr s_movmode: rep movsb s_getopenvec: ;display a letter for each drive ;with open files mov cx,16 ;loop count - 16 bits to check mov al,'A' ;A through P mov ah,6 ;count of drive letters displayed mov dx,open_vec ;BDOS sets this vector in SYSDAT mov di,offset smsg_openvec open_nxt: shr dx,1 ;lowest bit is A drive, highest is P jnc s_open_nxt ;no carry then no open files stosb ;store letter, incr DI dec ah ;count letters displayed, 6 max jz s_capslock ;used up drive display field s_open_nxt: inc al ;next letter loop open_nxt ;tested all 16 drive bits ? s_capslock: mov bx,foreground_ss mov al,ss_mode[bx] test al,ssm_capslock ! jz s_numlock mov si,offset capstr mov di,offset smsg_capslock mov cx,length capstr rep movsb s_numlock: test al,ssm_numlock ! jz s_wrap mov si,offset numstr mov di,offset smsg_numlock mov cx,length numstr rep movsb s_wrap: ;BX=foreground_ss test al,ssm_no_wrap ;if bit is set leave WRAP jnz s_display ;field blank mov si,offset wrpstr mov di,offset smsg_wrap mov cx,length wrpstr rep movsb s_display: mov si,offset status_msg_start mov di,video_status_line mov ax,CRT_RFRSH ; PEOPLE mov es,ax mov ah,public_crt_init_attr ; s/b underlined/enhanced mov cx,columns_per_screen s_dloop: lodsb ;get character stosw ;display character and attribute loop s_dloop mov sline_locked,0 pop es ;restore UDA ret EJECT ;************************************************************************ ;* * ;* POLL ROUTINES * ;* * ;************************************************************************ ; Check device for ready status, call dev_poll if not ready poll: ;poll device ; entry: DL = device number ; exit: AL = 0ffh device ready ; AL = 0 if not ready ; BX = device# * 2 call io_poll ;check hardware first test ax,ax ! jz p_os ;AX=0 if not ready ret ;BX=device# * 2 set by io_poll p_os: ;DL=device# push bx ;save device# * 2 mov cl,dev_poll ;give up the CPU resource call supif pop bx ;device# * 2 ret ; io_poll is called from the dispatcher after a process makes ; a dev_poll call to the O.S. During system dispatches, a ; a call to io_poll is made for each polling process. ;********************************************************************** io_poll: ; entry: DL = device # ; exit: AL = 0 if not ready, 0FFH if ready ; BX = device# * 2 ; ALL SEGMENT REGISTERS PRESERVED: ; CS,DS,ES,SS must be preserved though call xor bx,bx mov bl,dl shl bx,1 jmp poll_table[bx] ;ret ;********************************************************************* ; each of these functions must preserve bx and dx ; the relationship between the order of the elements ; in the poll_table and the poll numbers in the equates ; following must be preserved. EJECT ; ********************************************************* ; * * ; * SUPERVISOR MODULER * ; * * ; ********************************************************* supif: ; entry: CL = function number ; CH = 0 ; DX parameter ; ES = user data area ; exit: AX = BX = return ; CX = error code from O.S. ; ES = UDA or return value xor ch,ch ;ensure CH is 0 callf supervisor ret EJECT ; ********************************************************* ; * * ; * PRINT MESSAGE UNTIL ZERO BYTE * ; * * ; ********************************************************* print_msg: ; entry: SI = address of string to print until 0 byte ; on foreground console ; exit: None mov dl,foreground_screen p_msg_l: mov cl,[si] test cl,cl jz p_done push dx push si call io_conout pop si pop dx inc si jmps p_msg_l p_done: ret EJECT ; ********************************************************* ; * * ; * FLAG SET ROUTINE FOR INTERRUPT ROUTINES * ; * * ; ********************************************************* ; entry: DL = flag number ; exit: AX = BX = return flagset: mov cl,dev_flagset jmps supif ; ********************************************************* ; * * ; * FLAG WAIT ROUTINE * ; * * ; ********************************************************* ; entry: DL = flag number ; exit: AX = BX = return flagwait: mov cl,dev_flagwait jmps supif eject ;************************************************************************ ;* * ;* UNEXPECTED INTERRUPT HANDLER * ;* * ;************************************************************************ i_unexpected: ;unknown interrupts go here ; Display on the console the interrupt vector number that caused ; the CPU to be here. We will terminate the process that caused ; the unknown interrupt, even if its keep flag is on. mov ax,sysdat ;don't save registers, going to terminate mov ds,ax mov es,ax ;ES,DS = SYSDAT SEGMENT mov di,offset unex_msg_pd mov si,rlr ;PD offset lea si,p_name[si] mov di,offset unex_msg_pd mov cx,4 rep movsw ;get PD name into message string mov si,offset unex_msg call print_msg ;print unexpected interrupt message mov bx,rlr ;terminate the running process and p_flag[bx],not (pf_keep + pf_tempkeep) mov cx,p_term mov dx,0ffffh jmp supif ;process is terminated, interrupts ;are forced on when next process to ;run is brought into context eject i_nmi: int 3 eject dseg EJECT ; ; screen structures for everyone ; public ss0,ss1,ss2,ss3 screen_structures rb 0 eject ss0 dw 0,0 ;cursor, old cursor dw offset co_no_escape ;initially not in an escape sequence dw 0 ;screen_seg - set by INIT: db 0,0 ;row,column db 0,0 ;old row, old column ss0a db 0 ;initialized by init: db 0 ;mode - initialize wrap,cursor,reverse off, ;no data logging dw offset normal_const ; ss_const[bx] dw offset normal_conin ; ss_conin[bx] dw 0 ; ss_pfk_offset[bx] dw console_0_function_table if default_z19 dw offset z19_special_char_tab dw offset z19_special_func_tab dw offset z19_esc_tab dw offset z19_esc_func_tab endif ; default_z19 if default_oly dw offset oly_special_char_tab dw offset oly_special_func_tab dw offset oly_esc_tab dw offset oly_esc_func_tab endif ; default_oly dw 0 ; ss_fpgm_off[bx] db 0 ; ss_fpgm_count[bx] db 0 ; ss_shunt[bx] db 0 ; ss_fun_wrt_lock[bx] eject ss1 dw 0,0 ;cursor, old cursor dw offset co_no_escape ;initially not in an escape sequence dw 0 ;screen_seg - set by INIT: db 0,0 ;row,column db 0,0 ;old row, old column ss1a db 0 ; initialized by init: db 0 ;mode - initialize wrap,cursor,reverse off, ;no data logging dw offset normal_const ; ss_const[bx] dw offset normal_conin ; ss_conin[bx] dw 0 ; ss_pfk_offset[bx] dw console_1_function_table if default_z19 dw offset z19_special_char_tab dw offset z19_special_func_tab dw offset z19_esc_tab dw offset z19_esc_func_tab endif ; default_z19 if default_oly dw offset oly_special_char_tab dw offset oly_special_func_tab dw offset oly_esc_tab dw offset oly_esc_func_tab endif ; default_oly dw 0 ; ss_fpgm_off[bx] db 0 ; ss_fpgm_count[bx] db 0 ; ss_shunt[bx] db 0 ; ss_fun_wrt_lock[bx] eject ss2 dw 0,0 ;cursor, old cursor dw offset co_no_escape ;initially not in an escape sequence dw 0 ;screen_seg - set by INIT: db 0,0 ;row,column db 0,0 ;old row, old column ss2a db 0 ; initialized by init: db 0 ;mode - initialize wrap,cursor,reverse off ;no data logging dw offset normal_const ; ss_const[bx] dw offset normal_conin ; ss_conin[bx] dw 0 ; ss_pfk_offset[bx] dw console_2_function_table if default_z19 dw offset z19_special_char_tab dw offset z19_special_func_tab dw offset z19_esc_tab dw offset z19_esc_func_tab endif ; default_z19 if default_oly dw offset oly_special_char_tab dw offset oly_special_func_tab dw offset oly_esc_tab dw offset oly_esc_func_tab endif ; default_oly dw 0 ; ss_fpgm_off[bx] db 0 ; ss_fpgm_count[bx] db 0 ; ss_shunt[bx] db 0 ; ss_fun_wrt_lock[bx] eject ss3 dw 0,0 ;cursor, old cursor dw offset co_no_escape ;initially not in an escape sequence dw 0 ;screen_seg - set by INIT: db 0,0 ;row,column db 0,0 ;old row, old column ss3a db 0 ; initialized by init: db 0 ;mode - initialize wrap,cursor,reverse off ;no data logging dw offset normal_const ; ss_const[bx] dw offset normal_conin ; ss_conin[bx] dw 0 ; ss_pfk_offset[bx] dw console_3_function_table if default_z19 dw offset z19_special_char_tab dw offset z19_special_func_tab dw offset z19_esc_tab dw offset z19_esc_func_tab endif ; default_z19 if default_oly dw offset oly_special_char_tab dw offset oly_special_func_tab dw offset oly_esc_tab dw offset oly_esc_func_tab endif ; default_oly dw 0 ; ss_fpgm_off[bx] db 0 ; ss_fpgm_count[bx] db 0 ; ss_shunt[bx] db 0 ; ss_fun_wrt_lock[bx] screen_struct_addrs dw offset ss0 dw offset ss1 dw offset ss2 dw offset ss3 eject function_table: dw io_const ; 0 console status dw io_conin ; 1 console input dw io_conout ; 2 console output dw io_listst ; 3 list status dw io_list ; 4 list output dw io_auxin ; 5 auxillary input dw io_auxout ; 6 auxillary out dw io_switch ; 7 switch screen dw io_statline ; 8 update or print new status dw io_seldsk ; 9 select disk dw io_read ;10 read logical sector dw io_write ;11 write logical sector dw io_flushbuf ;12 flush buffers dw io_poll ;13 poll device EJECT ; ********************************************************* ; * * ; * SIGNON MESSAGE TEXT * ; * * ; ********************************************************* sign_on: db 0dh,0ah db '--------------------------------------------------',0dh,0ah db 'Olympia "PEOPLE" CCP/M-86 XIOS 6/29/83 version 1.0',0dh,0ah db 'Serial No. xxx-0000-162534 All Rights Reserved',0dh,0ah db 'Copyright (C) 1983 Digital Research, Inc.',0dh,0ah db '--------------------------------------------------',0dh,0ah db 0 eject ;***************************************************** ;* ;* IOPB for disk I/O ;* ;***************************************************** opcode db 0 ;operation code idrive db 0 ;disk drive id itrack dw 0 ;track for I/O head db 0 ;head for I/O isector db 0 ;sector for I/O count db 0 ;number of sectors for I/O retcode db 0 ;return code from operation retmask db 0 ;return code mask retries db 0 ;number of error retries idmaoff dw 0 ;DMA offset address idmaseg dw 0 ;DMA segment address seclen dw 0 ;sector length dw 0,0,0 ;work area eject ;***************************************************** ;* ;* DISK DATA AREA ;* ;***************************************************** xltbl dw 0 ;translation table address maxsec dw 0 ;max sectors per track secsiz dw 0 ;sector size dmatbl rw 50 ;dma address table read_tbl dw offset read dw offset read dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error write_tbl dw offset write dw offset write dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error dw offset ret_error eject path_counter dw 0 io_read_es rs PATH_RETRY_HIST io_write_es rs PATH_RETRY_HIST read_write_es rs PATH_RETRY_HIST read_es rs PATH_RETRY_HIST read1_es rs PATH_RETRY_HIST write_es rs PATH_RETRY_HIST write1_es rs PATH_RETRY_HIST ; floppy disk 0 dph1 dw xlts, 0000h ; translate table dw 0000h, 0000h ; scratch area dw dpbd1 ; disk paramater table dw 0ffffh, 0ffffh ; check, alloc vectors dw 0ffffh ; dir buf control block dw 0ffffh ; data buff cntrl block dw 0ffffh ; hash table segment ; floppy disk 1 dph2 dw xlts, 0000h ; translate table dw 0000h, 0000h ; scratch area dw dpbd1 ; disk paramater table dw 0ffffh, 0ffffh ; check, alloc vectors dw 0ffffh ; dir buf control block dw 0ffffh ; data buff cntrl block dw 0ffffh ; hash table segment eject ; THESE ARE THE SKEW TABLES ; sector translation tables (for floppy disks) xtable DW (Offset xlts ) ; no skew at all xlts DB 0,1,2,3,4,5,6,7,8 db 9,10,11,12,13,14,15 db 16,17,18,19,20,21,22,23 db 24,25,26,27,28,29,30,31 ; THIS IS THE RE-SKEW TABLE current_reskew dw 0 re_skew_tbl dw offset re_skew_32_2 ; D.D. 256 bytes/sec dw offset re_skew_32_2 re_skew_32_2 db 0,2,4,6 db 8,10,12,14 db 16,18,20,22 db 24,26,28,30 db 1,3,5,7 db 9,11,13,15 db 17,19,21,23 db 25,27,29,31 dpbd1: ; double density, double sided 256 bytes/sec. DW 32 ; physical sectors per track db 4 ; BSH - 2048 byte blocks db 15 ; BLM db 0 ; EXM dw 311 ; Disk Size - 1 dw 127 ; Directory Max db 192 ; Alloc 0 db 0 ; Alloc 1 dw 32 ; Check Sum Size dw 2 ; number of physical tracks offset db 1 ; Phys Sec Shift db 1 ; Phys Sec Mask EJECT unex_msg db cr,lf,'terminating ' unex_msg_pd rw 4 db ' process ,received unexpected interrupt',cr,lf,0 EJECT ;************************************************************************ ;* * ;* STATUS LINE ROUTINE * ;* * ;************************************************************************ ; Display status line on 25th line of IBM PC monochrome ; screen. First gather information into local string ; and then copy to the video display RAM. ; The format of the status line is: ;Console=1 Buffered GENCCPM ABCDEF ^S^P=0 Printer=2 CapsLock NumLock Wrap ; ^O status_msg_start rb 0 smsg_con rb 8 ;0-7 (Console=) smsg_cnum rb 1 ;8 db ' ' ;9 smsg_mode rb 8 ;10-17 db ' ' ;18 smsg_pd rb 8 ;19-26 db ' ' ;27 smsg_openvec rb 6 ;28-33 db ' ' ;34 smsg_ctrlS rw 1 ;35-36 smsg_ctrlO rw 0 ;overlays ctrlS db ' ' ;37 smsg_ctrlP rw 1 ;38-39 smsg_ctrlP_num rw 1 ;40-41 db ' ' ;42 smsg_prn rb 8 ;43-50 (Printer=) smsg_pnum rb 1 ;51 db ' ' ;52 smsg_capslock rb 8 ;53-60 db ' ' ;61 smsg_numlock rb 7 ;62-68 db ' ' ;69 smsg_wrap rb 4 ;70-73 rb 6 ;74-79 eject ; String constants for status line dynstr db 'Dynamic ' ;these bufstr db 'Buffered' ;messages must purstr db 'Purging ' ;be the same length nosstr db 'NoSwitch' constr db 'Console=' prnstr db 'Printer=' capstr db 'CapsLock' numstr db 'NumLock' wrpstr db 'Wrap' eject sline_locked db 0 ;semaphore for status line code EJECT poll_table dw listst ; 0 - list device status dw io_const ; 1 - console status dw dst1 ; 2 - disk status 1 dw dst2 ; 3 - disk status 2 dw 0 ; 4 - was conout status dw serial_inp_stat ; 5 - rda dw serial_out_stat ; 6 - tbre dw conin_shunt_stat; 7 - shunt available status ; eincl EJECT ;************************************************************************ ;* * ;* CONSOLE CONTROL BLOCKS * ;* * ;************************************************************************ foreground_screen db 0 ;console 0 is initial foreground_ccb dw offset ccb0 ;foreground console foreground_ss dw offset ss0 ccb_tab rb 0 ccb0 dw 0 ;owner dw 0,0,0 db 0ffh, 0ffh ;mimic, msource db 0 db 0 ;virtual console number dw 0 dw 0 ;foreground and dynamic ;be the foreground console dw 10h ;max buffer file size dw 0,0,0,0,0,0 dw 0,0,0,0,0,0 dw 0 ccb1 dw 0 ;owner dw 0,0,0 db 0ffh, 0ffh ;mimic, msource db 0 db 1 ;virtual console number dw 0 dw csm_background ;background and dynamic dw 10h ;max buffer file size dw 0,0,0,0,0,0 dw 0,0,0,0,0,0 dw 0 eject ccb2 dw 0 ;owner dw 0,0,0 db 0ffh, 0ffh ;mimic, msource db 0 db 2 ;virtual console number dw 0 dw csm_background ;background and dynamic dw 10h ;max buffer file size dw 0,0,0,0,0,0 dw 0,0,0,0,0,0 dw 0 ccb3 dw 0 ;owner dw 0,0,0 db 0ffh, 0ffh ;mimic, msource db 0 db 3 ;virtual console number dw 0 dw csm_background ;background and dynamic dw 10h ;max buffer file size dw 0,0,0,0,0,0 dw 0,0,0,0,0,0 dw 0 ; serial port console ccb4 dw 0 ;owner dw 0,0,0 db 0ffh, 0ffh ;mimic, msource db 0 db 0 ;virtual console number dw 0 dw 0 dw 0 ;max buffer file size dw 0,0,0,0,0,0 dw 0,0,0,0,0,0 dw 0 ; end of main.a86