Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!wuarchive!rice!uupsi!cmcl2!lab!jai From: jai@lab.ultra.nyu.edu (Benchiao Jai) Newsgroups: comp.os.minix Subject: NYUMINIX:MPX88.ASM Message-ID: <1991Feb24.071511.7036@cmcl2.nyu.edu> Date: 24 Feb 91 07:15:11 GMT Sender: notes@cmcl2.nyu.edu (Notes Person) Organization: New York University Ultracomputer Research Lab Lines: 330 Nntp-Posting-Host: lab.ultra.nyu.edu ; This file is part of the lowest layer of the MINIX kernel. All processing ; switching and message handling is done here and in file "proc.c". This file ; is entered on every transition to the kernel, both for sending/receiving ; messages and for all interrupts. In all cases, the trap or interrupt ; routine first calls save() to store the machine state in the proc table. ; Then the stack is switched to k_stack. Finally, the real trap or interrupt ; handler (in C) is called. When it returns, the interrupt routine jumps to ; restart, to run the process or task whose number is in 'cur_proc'. ; ; The external entry points into this file are: ; s_call: process or task wants to send or receive a message ; tty_int: interrupt routine for each key depression and release ; rs232_int: interrupt routine for each rs232 interrupt on port 1 ; secondary: interrupt routine for each rs232 interrupt on port 2 ; lpr_int: interrupt routine for each line printer interrupt ; disk_int: disk interrupt routine ; clock_int: clock interrupt routine (HZ times per second) ; restart: start running a task or process ; reboot: reboot for CTRL-ALT-DEL ; wreboot: wait for character then reboot ; save_tty_vec: save tty interrupt vector 0x71 for PS/2 ; These symbols MUST agree with the values in ../h/com.h to avoid disaster. K_STACK_BYTES = 256 FLOPPY = -5 CLOCK = -3 IDLE = -999 DISKINT = 1 CLOCK_TICK = 2 ; The following procedures are defined in this file and called from outside it. public _tty_int, _rs232_int, _lpr_int, _clock_int, _disk_int public _s_call, _restart, _secondary_int public _reboot, _wreboot, _save_tty_vec ; The following external procedures are called in this file. extrn _main:near, _sys_call:near, _interupt:near, _keyboard:near extrn _panic:near, _pr_char:near, _rs232:near ; Variables, data structures and miscellaneous. extrn _cur_proc:word, _proc_ptr:word, _scan_code:word extrn _int_mess:byte, _k_stack:byte, splimit:word, _port_65:word, _ps:word extrn endtext:byte, enddata:byte, endbss:byte public _sizes, begtext, begdata, begbss public _vec_table ; The following constants are offsets into the proc table. esreg = 14 dsreg = 16 csreg = 18 ssreg = 20 SPr = 22 PC = 24 PSW = 28 SPLIM = 50 OFF = 18 ROFF = 12 DGROUP GROUP _TEXT, _DATA, _BSS _TEXT segment byte public 'CODE' assume cs:_TEXT, ds:DGROUP begtext: ;*===========================================================================* ;* MINIX * ;*===========================================================================* MINIX: ; this is the entry point for the MINIX kernel. jmp short M0 dw DGROUP:begdata dw DGROUP:endbss M0: cli mov ax,cs ; only one segment mov ds,ax mov _scan_code, 13 ; standard keyboard mov sssave,ss ; save old ss and sp for returning to MS-DOS mov spsave,sp mov ss,ax mov sp,offset _k_stack ; set sp to point to the top of the add sp, K_STACK_BYTES ; kernel stack sti call _main ; start the main program of MINIX M1: jmp M1 ; this should never be executed ;*===========================================================================* ;* s_call * ;*===========================================================================* _s_call: ; System calls are vectored here. call save ; save the machine state mov bp,_proc_ptr ; use bp to access sys call parameters push 2[bp] ; push(pointer to user message) (was bx) push [bp] ; push(src/dest) (was ax) push _cur_proc ; push caller push 4[bp] ; push(SEND/RECEIVE/BOTH) (was cx) call _sys_call ; sys_call(function, caller, src_dest, m_ptr) jmp _restart ; jump to code to restart proc/task running ;*===========================================================================* ;* tty_int * ;*===========================================================================* _tty_int: ; Interrupt routine for terminal input. call save ; save the machine state call _keyboard ; process a keyboard interrupt jmp _restart ; continue execution ;*============================================================================ ;* rs232_int * ;*============================================================================ _rs232_int: ; Interrupt routine for rs232 I/O. call save ; save the machine state mov ax, 1 ; which unit caused the interrupt push ax ; pass it as a parameter call _rs232 ; process a rs232 interrupt jmp _restart ; continue execution ;*============================================================================ ;* secondary_int * ;*============================================================================ _secondary_int: ; Interrupt routine for rs232 port 2 call save ; save the machine state mov ax, 2 ; which unit caused the interrupt push ax ; pass it as a parameter call _rs232 ; process a rs232 interrupt jmp _restart ; continue execution ;*===========================================================================* ;* lpr_int * ;*===========================================================================* _lpr_int: ; Interrupt routine for printer input. call save ; save the machine state call _pr_char ; process a line printer interrupt jmp _restart ; continue execution ;*===========================================================================* ;* disk_int * ;*===========================================================================* _disk_int: ; Interrupt routine for the floppy disk. call save ; save the machine state mov _int_mess+2, DISKINT; build message for disk task mov ax,offset _int_mess ; prepare to call interrupt(FLOPPY, &intmess) push ax ; push second parameter mov ax, FLOPPY ; prepare to push first parameter push ax ; push first parameter call _interupt ; this is the call jmp _restart ; continue execution ;*===========================================================================* ;* clock_int * ;*===========================================================================* _clock_int: ; Interrupt routine for the clock. call save ; save the machine state mov _int_mess+2, CLOCK_TICK ; build message for clock task mov ax,offset _int_mess ; prepare to call interrupt(CLOCK, &intmess) push ax ; push second parameter mov ax, CLOCK ; prepare to push first parameter push ax ; push first parameter call _interupt ; this is the call jmp _restart ; continue execution ;*===========================================================================* ;* save * ;*===========================================================================* save: ; save the machine state in the proc table. cld ; set direction flag to a known value mov cs:bx_save,bx ; save bx for later ; we need a free register mov cs:ds_save,ds ; stack: psw/cs/pc/ret addr mov bx,cs ; prepare to restore ds mov ds,bx ; ds has now been set to cs pop ret_save ; stack: psw/cs/pc mov bx,_proc_ptr ; start save set up; make bx point to save area add bx, OFF ; bx points to place to store cs pop PC-OFF[bx] ; store pc in proc table pop csreg-OFF[bx] ; store cs in proc table pop PSW-OFF[bx] ; store psw mov ssreg-OFF[bx],ss ; store ss mov SPr-OFF[bx],sp ; sp as it was prior to interrupt mov sp,bx ; now use sp to point into proc table/task save mov bx,ds ; about to set ss mov ss,bx ; set ss push ds_save ; start saving all the registers, sp first push es ; save es between sp and bp mov es,bx ; es now references kernel memory too push bp ; save bp push di ; save di push si ; save si push dx ; save dx push cx ; save cx push bx_save ; save original bx push ax ; all registers now saved mov sp,offset _k_stack ; temporary stack for interrupts add sp, K_STACK_BYTES ; set sp to top of temporary stack mov splimit,offset _k_stack ; limit for temporary stack add splimit, 8 ; splimit checks for stack overflow cld mov ax,ret_save ; ax = address to return to jmp ax ; return to caller; Note: sp points to saved ax ;*===========================================================================* ;* restart * ;*===========================================================================* _restart: ; This routine sets up and runs a proc or task. cmp _cur_proc, IDLE ; restart user; if cur_proc = IDLE, go idle je idl ; no user is runnable, jump to idle routine cli ; disable interrupts mov sp,_proc_ptr ; return to user, fetch regs from proc table pop ax ; start restoring registers pop bx ; restore bx pop cx ; restore cx pop dx ; restore dx pop si ; restore si pop di ; restore di mov lds_low,bx ; lds_low contains bx mov bx,sp ; bx points to saved bp register mov bp,SPLIM-ROFF[bx] ; splimit = p_splimit mov splimit,bp ; ditto mov bp,dsreg-ROFF[bx] ; bp = ds mov lds_low+2,bp ; lds_low+2 contains ds pop bp ; restore bp pop es ; restore es mov sp,SPr-ROFF[bx] ; restore sp mov ss,ssreg-ROFF[bx] ; restore ss using the value of ds push PSW-ROFF[bx] ; push psw push csreg-ROFF[bx] ; push cs push PC-ROFF[bx] ; push pc lds bx,dword ptr lds_low; restore ds and bx in one fell swoop iret ; return to user or task ;*===========================================================================* ;* idle * ;*===========================================================================* idl: ; executed when there is no work sti ; enable interrupts L3: wait ; just idle while waiting for interrupt jmp L3 ; loop until interrupt ;*===========================================================================* ;* reboot & wreboot * ;*===========================================================================* ; This code reboots the PC _reboot: cli ; disable interrupts mov ax, 20h ; re-enable interrupt controller out 20h,al call resvec ; restore the vectors in low core r0: mov al,36h ; reset the timer to IBM freq. out 43h,al xor al,al out 40h,al out 40h,al mov ss,sssave mov sp,spsave test _ps, 0FFFFh jz r1 mov ax,tty_vec1 ; Restore keyboard interrupt vector for PS/2 mov es:[452],ax mov ax,tty_vec2 mov es:[454],ax mov ax,_port_65 ; restore port 0x65 out 65h, al mov al, 0BCh out 21h, al r1: sti dummy proc far ret dummy endp _wreboot: cli ; disable interrupts mov ax, 20h ; re-enable interrupt controller out 20h,al call resvec ; restore the vectors in low core xor ax,ax ; wait for character before continuing int 16h ; get char jmp r0 ; Restore the interrupt vectors in low core. resvec: cld mov cx, 2*33 mov si,offset DGROUP:_vec_table xor di,di mov es,di rep movsw ret ;*===========================================================================* ;* save_tty_vec * ;*===========================================================================* ; Save the tty vector 0x71 (PS/2) _save_tty_vec: push es xor ax,ax mov es,ax mov ax,es:[452] mov tty_vec1,ax mov ax,es:[454] mov tty_vec2,ax pop es ret _TEXT ends ;*===========================================================================* ;* data * ;*===========================================================================* _DATA segment word public 'DATA' begdata label byte _sizes dw 8 dup (0) ; load uses this space bx_save dw 0 ; storage for bx ds_save dw 0 ; storage for ds ret_save dw 0 ; storage for return address lds_low dw 0,0 ; storage used for restoring bx _vec_table dw 66 dup(0) ; storage for interrupt vectors tty_vec1 dw 0 ; sorage for vector 0x71 (offset) tty_vec2 dw 0 ; sorage for vector 0x71 (segment) sssave dw 0 ; save ss for returning to MS-DOS spsave dw 0 ; save sp for returning to MS-DOS _DATA ends _BSS segment word public 'BSS' begbss label byte _BSS ends end Brought to you by Super Global Mega Corp .com