.nolist .include "io.s" .include "section.s" .include "lcd_const.s" .list DEBUG = 0 ERASE_PROCS = 1 PID_NUM = 8 STACK_SIZE = 512 DEFAULT_PRIO = 16 .pushsection .data .globl pid .type pid,@object pid: .byte 0 .size pid, . - pid .globl procdata .type procdata,@object JIFFIES = 0 PRIO = 1 STACK_PTR = 2 SLEEP_UNTIL = 4 SLEEP_UNTIL_H = 4 SLEEP_UNTIL_L = 6 PROCDATA_SIZE = 8 procdata: .fill PID_NUM * PROCDATA_SIZE ; jiffies + prio + stack_ptr + sleep_until _end_procdata: .size procdata, . - procdata .globl userstacks .type userstacks,@object userstacks: .fill PID_NUM * STACK_SIZE _end_userstacks: .size userstacks, . - userstacks .type idlethread,@object idlethread: .word 0 ; addr .word 0 ; Y .word 0 ; X .word 0 ; D .byte 0 ; CCR .size idlethread, . - idlethread .popsection .pushsection .text .globl k_sched_init .type k_sched_init,@function k_sched_init: CLRA LDX #procdata _k_sched_init_loop: ; do { CLRB .if ERASE_PROCS STD 0,X ; jiffies = 0; prio = 0; STD 2,X ; stack_ptr = 0; .else STAA 0,X ; jiffies = 0; .endif STD 4,X ; sleep_until STD 6,X ; = 0; LDAB #8 ; pid++ ABX CMPX #_end_procdata BLO _k_sched_init_loop ; loop if pid < PID_NUM ; pid = 0 CLR pid ; procdata[pid].jiffies = DEFAULT_PRIO; LDX #procdata LDAA #DEFAULT_PRIO STAA JIFFIES,X ; procdata[pid].prio = DEFAULT_PRIO; STAA PRIO,X ; procdata[pid].sleep_until = 0; CLRA CLRB STD SLEEP_UNTIL_H,X STD SLEEP_UNTIL_L,X XGDX ; stick X into D PULX ; return pointer PULY ; k_stack return pointer LDS #userstacks + STACK_SIZE PSHY ; k_stack return pointer PSHX ; return pointer XGDX ; restore D from X TSY ; save stack pointer into array STY STACK_PTR,X LDAB #'p' JSR k_putc RTS .size k_sched_init, . - k_sched_init .pushsection .k_stacks.init JSR k_sched_init .popsection .type k_sched_intr,@function k_sched_intr: ; if (pid < PID_NUM) LDAA pid CMPA #PID_NUM BHS _find_next_pid ; procdata[pid].jiffies--; LDX #procdata TAB LSLB LSLB LSLB ABX LDAB JIFFIES,X SUBB #1 STAB JIFFIES,X ; procdata[pid].stack_ptr = ustack; LDD ustack STD STACK_PTR,X _find_next_pid: ; A = pid LDAA pid TAB LSLB LSLB LSLB LDX #procdata ABX LDAB #PROCDATA_SIZE _find_loop: ; A++ INCA ABX ; if (A >= PID_NUM) CMPA #PID_NUM BLO _nowrap ; A = 0; LDAA #0 LDX #procdata _nowrap: ; if (procdata[A].jiffies) TST JIFFIES,X ; goto _got_process BNE _got_process ; if (A != pid) CMPA pid ; goto _find_loop BNE _find_loop ; if we get here, no processes have jiffies CLRA LDX #procdata LDY #time _assign_jiffies_loop: ; time stuff PSHA LDD SLEEP_UNTIL_H,X CMPD 0,Y BHI _no_jiffy BLO _give_jiffy LDD SLEEP_UNTIL_L,X CMPD 2,Y BHI _no_jiffy _give_jiffy: LDAB PRIO,X BRA _next_jiffy _no_jiffy: CLRB _next_jiffy: PULA STAB JIFFIES,X ; end time stuff ABA LDAB #PROCDATA_SIZE ABX CPX #_end_procdata BLO _assign_jiffies_loop ;LDAB #PID_NUM ;STAB pid ; if (A == 0) TSTA ; goto _no_procs BEQ _no_procs ; A = pid ;LDAA pid LDAA #PID_NUM - 1 ; force wrap ; X = &procdata[A] ;LDX #procdata ;TAB ;LSLB ;LSLB ;LSLB ;ABX ;LDAB #8 ; goto _find_loop BRA _find_loop _no_procs: ; if we get here, no processes are running ; default to pid 0 even if it has no prio CLRA LDX #procdata _got_process: ; A == newpid, X = &procdata[pid] ; if (pid == last_pid) LDAB pid CMPA pid BNE _update_stack ; return RTS _update_stack: ; pid = A STAA pid .if DEBUG ; debug PSHB PSHA .endif ; ustack = procdata[pid].stack_ptr LDD STACK_PTR,X STD ustack .if DEBUG ; debug (if pid != last_pid) ; lcd_goto 0 ;LDD #(command_mode << 8) + lcd_setdispaddr + 0 ;JSR lcd_putchar LDAB #0 JSR k_lcd_goto ; k_print_int ((uint *) ustack)[4] LDX ustack ; stack = .CBAXXYYRR LDD 8,X JSR k_print_int CLRA LDAB #'P' JSR k_putc CLRA PULB ; old pid JSR k_print_int CLRA LDAB #'>' JSR k_putc CLRA PULB ; new pid JSR k_print_int CLRA LDAB #'.' JSR k_putc ;STOP ;LDAA #129 ;STAA k_debug_counter .endif ; return RTS .size k_sched_intr, . - k_sched_intr .pushsection .k_stacks.tovr JSR k_sched_intr .popsection ; now for some process related functions .globl msleep .type msleep,@function msleep: PSHY PSHX ; divide by 7.8125 ( ticks = ms * 16 / 125 ) LSLD LSLD LSLD LSLD LDX #125 IDIV XGDX PSHB LDAB pid LDX #procdata LDY #time LSLB LSLB LSLB ABX PULB SEI ; procdata[pid].sleep_until = time.l + (uint32) D; ADDD 2,Y STD SLEEP_UNTIL_L,X ; can't CLRA;CLRB because that clears carry too :/ LDD #0 ADCB 1,Y ADCA 0,Y STD SLEEP_UNTIL_H,X ; procdata[pid].jiffies = 0; CLRA STAA JIFFIES,X ;CLI PULX PULY ;WAI ;RTS ; tail return, fall through to defer() .size msleep, . - msleep .globl defer .type defer,@function defer: SEI PSHY PSHX PSHA PSHB TPA ANDA #~I. ; mask out interrupt bit PSHA STS ustack LDS #kernelstack JSR k_sched_intr LDS ustack RTI .size defer, . - defer .globl exit .type exit,@function exit: ; procdata[pid].jiffies = 1; procdata[pid].prio = 0; LDAB pid LDX #procdata LSLB LSLB LSLB ABX LDAA #1 CLRB STD JIFFIES,X ; defer(); BRA defer WAI .size exit, . - exit .globl fork .type fork,@function fork: ; D = PULB PULA PSHB PSHA JSR create_process RTS .size fork, . - fork .globl kill .type kill,@function kill: LDX #procdata LSLB LSLB LSLB ABX CLRA CLRB STD JIFFIES,X RTS .size kill, . - kill .globl create_process .type create_process,@function create_process: PSHY PSHX PSHB PSHA CLRA LDAB #8 LDX #procdata _fork_loop: ; if (procdata[A].prio == 0) TST PRIO,X ; goto _found_free_pid BEQ _found_free_pid ; A++ INCA ABX ; if (A < PID_NUM) CPX #procdata + (PID_NUM * PROCDATA_SIZE) ; goto _fork_loop BLO _fork_loop ; return -1 LDD #0x00FF RTS _found_free_pid: ; start_atomic() SEI ; newpid = A PSHA ; Y = &procdata[pid]; LDAB pid LDY #procdata LSLB LSLB LSLB ABY ; procdata[newpid].prio = procdata[pid].prio; LDAA PRIO,Y STAA PRIO,X ; procdata[newpid].jiffies = 0; CLRA STAA JIFFIES,X ; procdata[newpid].sleep_until = 0; CLRA CLRB STD SLEEP_UNTIL_H,X STD SLEEP_UNTIL_L,X ; Y = &userstacks[newpid] + STACK_SIZE - 11 PULA PSHA LSLA CLRB ADDD #userstacks + STACK_SIZE - 12 XGDY ; procdata[newpid].stack_ptr = Y :: &userstacks[newpid] + STACK_SIZE - 11 STY STACK_PTR,X ; userstacks[pid][STACK_SIZE - 2] = &exit LDD #exit STD 10,Y ; userstacks[pid][STACK_SIZE - 4] = func_address TSX ; stack = AFFXXYYRRDD LDD 1,X ; return address STD 8,Y ; debug ;JSR k_print_int ;STOP ; userstacks[pid][STACK_SIZE - 6] = 0; // Y CLRA CLRB STD 6,Y ; userstacks[pid][STACK_SIZE - 8] = 0; // X STD 4,Y ; userstacks[pid][STACK_SIZE - 10] = 0; // D LDD 9,X STD 2,Y ; userstacks[pid][STACK_SIZE - 11] = 0; // CCR CLRA STAA 1,Y ; end_atomic(); CLI ; D = newpid CLRA PULB PULX PULX PULY ; return(newpid); RTS .size create_process, . - create_process .popsection