comparison level1/modules/clock.asm @ 2631:442795681807

o Fixed Atari SIO DWRead to timeout longer o Commented out call to InitVIRQ in dw3.sb for Atari due to issues o VTIO for Atari now properly handles IRQ shadow registers o Level 1 clock now merged to include Atari
author Boisy Pitre <boisy.pitre@nuance.com>
date Sun, 26 Feb 2012 21:39:44 -0600
parents b8c7b7fbf3c9
children 2ebf5e737ceb
comparison
equal deleted inserted replaced
2630:e310e8613606 2631:442795681807
1 ******************************************************************** 1 ********************************************************************
2 * Clock - NitrOS-9 System Clock 2 * Clock - NitrOS-9 System Clock
3 *
4 * CoCo 3 notes:
5 * Includes support for several different RTC chips, GIME Toggle
6 * IRQ fix, numerous minor changes.
7 * 3 *
8 * $Id$ 4 * $Id$
9 * 5 *
10 * Edt/Rev YYYY/MM/DD Modified by 6 * Edt/Rev YYYY/MM/DD Modified by
11 * Comment 7 * Comment
44 nam Clock 40 nam Clock
45 ttl NitrOS-9 System Clock 41 ttl NitrOS-9 System Clock
46 42
47 ifp1 43 ifp1
48 use defsfile 44 use defsfile
49 ifgt Level-1
50 use cocovtio.d
51 endc
52 endc 45 endc
53 46
54 tylg set Systm+Objct 47 tylg set Systm+Objct
55 atrv set ReEnt+rev 48 atrv set ReEnt+rev
56 rev set 8 49 rev set 8
65 58
66 name fcs "Clock" 59 name fcs "Clock"
67 fcb edition 60 fcb edition
68 61
69 62
70 ifeq Level-1
71 TkPerTS equ TkPerSec/10 ticks per time slice 63 TkPerTS equ TkPerSec/10 ticks per time slice
72 else
73 TkPerTS equ 2 ticks per time slice
74 endc
75 64
76 * 65 *
77 * Table to set up Service Calls 66 * Table to set up Service Calls
78 * 67 *
79 NewSvc fcb F$Time 68 NewSvc fcb F$Time
80 fdb FTime-*-2 69 fdb FTime-*-2
81 fcb F$VIRQ 70 fcb F$VIRQ
82 fdb FVIRQ-*-2 71 fdb FVIRQ-*-2
83 ifgt Level-1
84 fcb F$Alarm
85 fdb FALARM-*-2
86 endc
87 fcb F$STime 72 fcb F$STime
88 fdb FSTime-*-2 73 fdb FSTime-*-2
89 fcb $80 end of service call installation table 74 fcb $80 end of service call installation table
90 75
91 76
92 *------------------------------------------------------------ 77 *------------------------------------------------------------
93 * 78 *
94 * Handle F$STime system call 79 * Handle F$STime system call
95 * 80 *
96 * First, copy time packet from user address space to system time 81 * First, copy time packet from user address space to system time
97 * variables, then fall through to code to update RTC. 82 * variables, then fall through to code to update RTC.
98 * 83 *
99 FSTime equ * 84 FSTime equ *
100 ifgt Level-1
101 ldx <D.Proc caller's process descriptor
102 lda P$Task,x source is in user map
103 ldx R$X,u address of caller's time packet
104 ldu #D.Time destination address
105 ldb <D.SysTsk destination is in system map
106 lbsr STime.Mv get time packet (ignore errors)
107 else
108 ldx R$X,u 85 ldx R$X,u
109 ldd ,x 86 ldd ,x
110 std <D.Year 87 std <D.Year
111 ldd 2,x 88 ldd 2,x
112 std <D.Day 89 std <D.Day
113 ldd 4,x 90 ldd 4,x
114 std <D.Min 91 std <D.Min
115 endc
116 lda #TkPerSec reset to start of second 92 lda #TkPerSec reset to start of second
117 sta <D.Tick 93 sta <D.Tick
118 ldx <D.Clock2 get entry point to Clock2 94 ldx <D.Clock2 get entry point to Clock2
119 clra clear carry 95 clra clear carry
120 jmp $06,x and call SetTime entry point 96 jmp $06,x and call SetTime entry point
121 97
122
123 *-------------------------------------------------- 98 *--------------------------------------------------
124 * 99 *
125 * Clock Initialization 100 * Clock Initialization
126 * 101 *
127 * This vector is called by the kernel to service the first F$STime 102 * This vector is called by the kernel to service the first F$STime
131 * 106 *
132 * 107 *
133 108
134 Clock2 fcs "Clock2" 109 Clock2 fcs "Clock2"
135 110
136 init 111 init
137 ifeq Level-1
138 pshs dp,cc save DP and CC 112 pshs dp,cc save DP and CC
139 clra 113 clra
140 tfr a,dp set DP to zero 114 tfr a,dp set DP to zero
141 else
142 ldx <D.Proc save user proc
143 pshs x
144 ldx <D.SysPrc make sys for link
145 stx <D.Proc
146 endc
147
148 leax <Clock2,pcr 115 leax <Clock2,pcr
149 lda #Sbrtn+Objct 116 lda #Sbrtn+Objct
150 os9 F$Link 117 os9 F$Link
151
152 bcc LinkOk 118 bcc LinkOk
153
154 ifeq Level-1
155 jmp >$FFFE level 1: jump to reset vector 119 jmp >$FFFE level 1: jump to reset vector
156 else
157 lda #E$MNF
158 jmp <D.Crash level 2: jump to CRASH vector
159 endc
160 120
161 LinkOk 121 LinkOk
162 ifeq Level-1
163 puls cc,dp ; Restore saved dp and cc 122 puls cc,dp ; Restore saved dp and cc
164 else
165 puls x
166 stx <D.Proc restore user proc
167 endc
168
169 sty <D.Clock2 save entry point 123 sty <D.Clock2 save entry point
170 InitCont 124 InitCont
125 * Do not need to explicitly read RTC during initialization
126 ldd #59*256+$01 last second and last tick
127 std <D.Sec will prompt RTC read at next time slice
128 ldb #TkPerSec
129 stb <D.TSec set ticks per second
130 ldb #TkPerTS get ticks per time slice
131 stb <D.TSlice set ticks per time slice
132 stb <D.Slice set first time slice
133 IFNE atari
134 * Atari gets its clock source from the NMI
135 leax SvcIRQ,pcr set NMI handler
136 stx <D.NMI
137 ELSE
138 leax SvcIRQ,pcr set IRQ handler
139 stx <D.IRQ
140 ENDC
141
142 leay NewSvc,pcr insert syscalls
143 os9 F$SSvc
144
145 * Call Clock2 init routine
146 ldy <D.Clock2 get entry point to Clock2
147 jsr ,y call init entry point of Clock2
148
149 * Initialize clock hardware
150 IFNE atari
151 * Atari - Tell ANTIC to assert NMI on Vertical Blank
152 lda #$40
153 sta $D40E enable VBlank NMI
154 rts
155 ELSE
171 ldx #PIA0Base point to PIA0 156 ldx #PIA0Base point to PIA0
172 clra no error for return... 157 clra no error for return...
173 pshs cc save IRQ enable status (and Carry clear) 158 pshs cc save IRQ enable status (and Carry clear)
174 orcc #IntMasks stop interrupts 159 orcc #IntMasks stop interrupts
175
176 ifgt Level-1
177 * Note: this code can go away once we have a rel_50hz
178 ifeq TkPerSec-50
179 ldb <D.VIDMD get video mode register copy
180 orb #$08 set 50 Hz VSYNC bit
181 stb <D.VIDMD save video mode register copy
182 stb >$FF98 set 50 Hz VSYNC
183 endc
184 endc
185 160
186 sta 1,x enable DDRA 161 sta 1,x enable DDRA
187 sta ,x set port A all inputs 162 sta ,x set port A all inputs
188 sta 3,x enable DDRB 163 sta 3,x enable DDRB
189 coma 164 coma
190 sta 2,x set port B all outputs 165 sta 2,x set port B all outputs
191 166
192 ; ldd #$343C [A]=PIA0 CRA contents, [B]=PIA0 CRB contents 167 ; ldd #$343C [A]=PIA0 CRA contents, [B]=PIA0 CRB contents
193 168
194 ifgt Level-1
195 ldd #$3434 as per Robert Gault's suggestion
196 else
197 ldd #$3435 IRQ needs to be left enabled for Level1, as no GIME generated IRQ 169 ldd #$3435 IRQ needs to be left enabled for Level1, as no GIME generated IRQ
198 endif
199 170
200 sta 1,x CA2 (MUX0) out low, port A, disable HBORD high-to-low IRQs 171 sta 1,x CA2 (MUX0) out low, port A, disable HBORD high-to-low IRQs
201 stb 3,x CB2 (MUX1) out low, port B, disable VBORD low-to-high IRQs 172 stb 3,x CB2 (MUX1) out low, port B, disable VBORD low-to-high IRQs
202 173
203 ifgt Level-1
204 lda ,x clear possible pending PIA0 HBORD IRQ
205 endc
206 lda 2,x clear possible pending PIA0 VBORD IRQ 174 lda 2,x clear possible pending PIA0 VBORD IRQ
207 175 puls cc,pc recover IRQ enable status and return
208 * Don't need to explicitly read RTC during initialization 176 ENDC
209 ldd #59*256+$01 last second and last tick 177
210 std <D.Sec will prompt RTC read at next time slice
211 ifeq Level-1
212 ldb #TkPerSec
213 stb <D.TSec set ticks per second
214 endc
215 ldb #TkPerTS get ticks per time slice
216 stb <D.TSlice set ticks per time slice
217 stb <D.Slice set first time slice
218 leax SvcIRQ,pcr set IRQ handler
219 stx <D.IRQ
220
221 ifgt Level-1
222 leax SvcVIRQ,pcr set VIRQ handler
223 stx <D.VIRQ
224 endc
225
226 leay NewSvc,pcr insert syscalls
227 os9 F$SSvc
228
229 ifgt Level-1
230 ifne H6309
231 oim #$08,<D.IRQER
232 else
233 lda <D.IRQER get shadow GIME IRQ enable register
234 ora #$08 set VBORD bit
235 sta <D.IRQER save shadow register
236 endc
237 sta >IRQEnR enable GIME VBORD IRQs
238 endc
239
240 * Call Clock2 init routine
241 ldy <D.Clock2 get entry point to Clock2
242 jsr ,y call init entry point of Clock2
243 InitRts puls cc,pc recover IRQ enable status and return
244
245 ifeq Level-1
246 * 178 *
247 * Clock IRQ Entry Point 179 * Clock IRQ Entry Point
248 * 180 *
249 * For CoCo 1/2, called once every 16.667 milliseconds 181 * For CoCo 1/2, called once every 16.667 milliseconds
250 SvcIRQ 182 SvcIRQ
251 clra 183 clra
252 tfr a,dp set direct page to zero 184 tfr a,dp set direct page to zero
185 IFNE atari
186 sta $D40F clear NMI interrupt
187 ELSE
253 tst PIA0Base+3 get hw byte 188 tst PIA0Base+3 get hw byte
254 bmi L0032 branch if sync flag on 189 bmi L0032 branch if sync flag on
255 jmp [>D.SvcIRQ] else service other possible IRQ 190 jmp [>D.SvcIRQ] else service other possible IRQ
256 L0032 tst PIA0Base+2 clear interrupt 191 L0032 tst PIA0Base+2 clear interrupt
192 ENDC
257 dec <D.Tick decrement tick counter 193 dec <D.Tick decrement tick counter
258 bne L007F go around if not zero 194 bne L007F go around if not zero
259 ldb <D.Sec get minutes/seconds 195 ldb <D.Sec get minutes/seconds
260 * Seconds increment 196 * Seconds increment
261 incb increment seconds 197 incb increment seconds
289 bne L0087 if not zero, branch 225 bne L0087 if not zero, branch
290 lda ,s+ else get byte off stack 226 lda ,s+ else get byte off stack
291 beq GoAltIRQ branch if zero 227 beq GoAltIRQ branch if zero
292 ldx <D.Proc else get pointer to current process descriptor 228 ldx <D.Proc else get pointer to current process descriptor
293 beq L00AE branch if none 229 beq L00AE branch if none
294 tst P$State,x test process' state 230 tst P$State,x test process state
295 bpl UsrPoll branch if system state not set 231 bpl UsrPoll branch if system state not set
296 L00AE jsr [>D.Poll] poll ISRs 232 L00AE jsr [>D.Poll] poll ISRs
297 bcc L00AE keep polling until carry set 233 bcc L00AE keep polling until carry set
298 GoAltIRQ 234 GoAltIRQ
299 jmp [>D.AltIRQ] jump into an alternate IRQ if available 235 jmp [>D.AltIRQ] jump into an alternate IRQ if available
371 ldd <D.Min 307 ldd <D.Min
372 std 4,x 308 std 4,x
373 clrb 309 clrb
374 rts 310 rts
375 311
376
377
378
379 else
380
381
382
383
384 * NitrOS-9 Level 2 Clock
385
386 GI.Toggl equ %00000001 GIME CART* IRQ enable bit, for CC3
387
388 * TC9 needs to reset more interrupt sources
389 *GI.Toggl equ %00000111 GIME SERINT*, KEYINT*, CART* IRQ enable bits
390
391
392 *---------------------------------------------------------
393 * IRQ Handling starts here.
394 *
395 * Caveat: There may not be a stack at this point, so avoid using one.
396 * Stack is set up by the kernel between here and SvcVIRQ.
397 *
398 SvcIRQ lda >IRQEnR get GIME IRQ Status and save it.
399 ora <D.IRQS
400 sta <D.IRQS
401 bita #$08 check for clock interrupt
402 beq NoClock
403 anda #^$08 drop clock interrupt
404 sta <D.IRQS
405 ldx <D.VIRQ set VIRQ routine to be executed
406 clr <D.QIRQ ---x IS clock IRQ
407 bra ContIRQ
408
409 NoClock leax DoPoll,pcr if not clock IRQ, just poll IRQ source
410 ifne H6309
411 oim #$FF,<D.QIRQ ---x set flag to NOT clock IRQ
412 else
413 lda #$FF
414 sta <D.QIRQ
415 endc
416 ContIRQ stx <D.SvcIRQ
417 jmp [D.XIRQ] chain through Kernel to continue IRQ handling
418
419 *------------------------------------------------------------
420 *
421 * IRQ handling re-enters here on VSYNC IRQ.
422 *
423 * - Count down VIRQ timers, mark ones that are done
424 * - Call DoPoll/DoToggle to service VIRQs and IRQs and reset GIME
425 * - Call Keyboard scan
426 * - Update time variables
427 * - At end of minute, check alarm
428 *
429 SvcVIRQ clra flag if we find any VIRQs to service
430 pshs a
431 ldy <D.CLTb get address of VIRQ table
432 bra virqent
433
434 virqloop
435 ifgt Level-2
436 ldd 2,y get Level 3 extended map type
437 orcc #IntMasks
438 sta >$0643
439 stb >$0645
440 std >$FFA1
441 andcc #^IntMasks
442 endc
443
444 ldd Vi.Cnt,x decrement tick count
445 ifne H6309
446 decd --- subd #1
447 else
448 subd #$0001
449 endc
450 bne notzero is this one done?
451 lda Vi.Stat,x should we reset?
452 bmi doreset
453 lbsr DelVIRQ no, delete this entry
454 doreset ora #$01 mark this VIRQ as triggered.
455 sta Vi.Stat,x
456 lda #$80 add VIRQ as interrupt source
457 sta ,s
458 ldd Vi.Rst,x reset from Reset count.
459 notzero std Vi.Cnt,x
460 virqent ldx ,y++
461 bne virqloop
462
463 ifgt Level-2
464 puls d
465 orcc #Carry
466 stb >$0643
467 stb >$FFA1
468 incb
469 stb >$0645
470 stb >$FFA1
471 andcc #^IntMasks
472 else
473 puls a get VIRQ status flag: high bit set if VIRQ
474 endc
475
476 ora <D.IRQS Check to see if other hardware IRQ pending.
477 bita #%10110111 any V/IRQ interrupts pending?
478 beq toggle
479 ifgt Level-2
480 lbsr DoPoll yes, go service them.
481 else
482 bsr DoPoll yes, go service them.
483 endc
484 bra KbdCheck
485 toggle equ *
486 ifgt Level-2
487 lbsr DoToggle no, toggle GIME anyway
488 else
489 bsr DoToggle no, toggle GIME anyway
490 endc
491
492 KbdCheck
493 ifgt Level-2
494 lda >$0643 grab current map type
495 ldb >$0645
496 pshs d save it
497 orcc #IntMasks IRQs off
498 lda >$0660 SCF local memory ---x
499 sta >$0643 into DAT image ---x
500 sta >$FFA1 and into RAM ---x
501 inca
502 sta >$0645
503 sta >$FFA2 map in SCF, CC3IO, WindInt, etc.
504 endc
505
506 jsr [>D.AltIRQ] go update mouse, gfx cursor, keyboard, etc.
507
508 ifgt Level-2
509 puls d restore original map type ---x
510 orcc #IntMasks
511 sta >$0643 into system DAT image ---x
512 stb >$0645
513 std >$FFA1 and into RAM ---x
514 andcc #$AF
515 endc
516
517 dec <D.Tick end of second?
518 bne VIRQend no, skip time update and alarm check
519 lda #TkPerSec reset tick count
520 sta <D.Tick
521
522 * ATD: Modified to call real time clocks on every minute ONLY.
523 inc <D.Sec go up one second
524 lda <D.Sec grab current second
525 cmpa #60 end of minute?
526 blo VIRQend no, skip time update and alarm check
527 clr <D.Sec reset second count to zero
528
529 *
530 * Call GetTime entry point in Clock2
531 *
532 ldx <D.Clock2 get entry point to Clock2
533 jsr $03,x call GetTime entry point
534
535 NoGet ldd >WGlobal+G.AlPID
536 ble VIRQend Quit if no Alarm set
537 ldd >WGlobal+G.AlPckt+3 does Hour/Minute agree?
538 cmpd <D.Hour
539 bne VIRQend
540 ldd >WGlobal+G.AlPckt+1 does Month/Day agree?
541 cmpd <D.Month
542 bne VIRQend
543 ldb >WGlobal+G.AlPckt+0 does Year agree?
544 cmpb <D.Year
545 bne VIRQend
546 ldd >WGlobal+G.AlPID
547 cmpd #1
548 beq checkbel
549 os9 F$Send
550 bra endalarm
551 checkbel ldb <D.Sec sound bell for 15 seconds
552 andb #$F0
553 beq dobell
554 endalarm ldd #$FFFF
555 std >WGlobal+G.AlPID
556 bra VIRQend
557 dobell ldx >WGlobal+G.BelVec
558 beq VIRQend
559 jsr ,x
560 VIRQend jmp [>D.Clock] jump to kernel's timeslice routine
561
562 *------------------------------------------------------------
563 * Interrupt polling and GIME reset code
564 *
565
566 *
567 * Call [D.Poll] until all interrupts have been handled
568 *
569 DoPoll
570 ifgt Level-2
571 lda >$0643 Level 3: get map type
572 ldb >$0645
573 pshs d save for later
574 endc
575 d@ jsr [>D.Poll] call poll routine
576 bcc d@ until error (error -> no interrupt found)
577
578 ifgt Level-2
579 puls d
580 orcc #IntMasks
581 sta >$0643
582 stb >$0645
583 std >$FFA1
584 andcc #^IntMasks
585 endc
586
587 *
588 * Reset GIME to avoid missed IRQs
589 *
590 DoToggle
591 lda #^GI.Toggl mask off CART* bit
592 anda <D.IRQS
593 sta <D.IRQS
594 lda <D.IRQER get current enable register status
595 tfr a,b
596 anda #^GI.Toggl mask off CART* bit
597 orb #GI.Toggl --- ensure that 60Hz IRQ's are always enabled
598 sta >IRQEnR disable CART
599 stb >IRQEnR enable CART
600 clrb
601 rts
602
603
604 *------------------------------------------------------------
605 *
606 * Handle F$VIRQ system call
607 *
608 FVIRQ pshs cc
609 orcc #IntMasks disable interrupts
610 ldy <D.CLTb address of VIRQ table
611 ldx <D.Init address of INIT
612 ldb PollCnt,x number of polling table entries from INIT
613 ldx R$X,u zero means delete entry
614 beq RemVIRQ
615 ifgt Level-2
616 bra FindVIRQ ---x
617
618 v.loop leay 4,y ---x
619 endc
620 FindVIRQ
621 ldx ,y++ is VIRQ entry null?
622 beq AddVIRQ if yes, add entry here
623 decb
624 bne FindVIRQ
625 puls cc
626 comb
627 ldb #E$Poll
628 rts
629
630 AddVIRQ
631 ifgt Level-2
632 ldx R$Y,u
633 stx ,y
634 lda >$0643
635 ldb >$0645
636 std 2,y
637 else
638 leay -2,y point to first null VIRQ entry
639 ldx R$Y,u
640 stx ,y
641 endc
642 ldy R$D,u
643 sty ,x
644 bra virqexit
645
646 ifgt Level-2
647 v.chk leay 4,y
648 RemVIRQ ldx ,y
649 else
650 RemVIRQ ldx ,y++
651 endc
652 beq virqexit
653 cmpx R$Y,u
654 bne RemVIRQ
655 bsr DelVIRQ
656 virqexit puls cc
657 clrb
658 rts
659
660 DelVIRQ pshs x,y
661 DelVLup
662 IFEQ H6309-1
663 ldq ,y++ move entries up in table
664 leay 2,y
665 stq -8,y
666 bne DelVLup
667 puls x,y,pc
668 ELSE
669 ldx ,y++ move entries up in table
670 stx -4,y
671 bne DelVLup
672 puls x,y
673 leay -2,y
674 rts
675 ENDC
676
677 IFGT Level-1
678 *------------------------------------------------------------
679 *
680 * Handle F$Alarm call
681 *
682 FAlarm ldx #WGlobal+G.AlPckt
683 ldd R$D,u
684 bne DoAlarm
685 std G.AlPID-G.AlPckt,x erase F$Alarm PID, Signal.
686 rts
687
688 DoAlarm tsta if PID != 0, set alarm for this process
689 bne SetAlarm
690 cmpd #1 1 -> Set system-wide alarm
691 bne GetAlarm
692 SetAlarm
693 std G.AlPID-G.AlPckt,x
694 ldy <D.Proc
695 lda P$Task,y move from process task
696 ldb <D.SysTsk to system task
697 ldx R$X,u from address given in X
698 ldu #WGlobal+G.AlPckt
699 ldy #5 move 5 bytes
700 bra FMove
701
702 GetAlarm
703 cmpd #2
704 bne AlarmErr
705 ldd G.AlPID-G.AlPckt,x
706 std R$D,u
707 bra RetTime
708 AlarmErr
709 comb
710 ldb #E$IllArg
711 rts
712 endc
713
714 *------------------------------------------------------------
715 *
716 * Handle F$Time System call
717 *
718 FTime equ *
719 ifgt Level-1
720 ldx #D.Time address of system time packet
721 RetTime ldy <D.Proc get pointer to current proc descriptor
722 ldb P$Task,y process Task number
723 lda <D.SysTsk from System Task
724 ldu R$X,u
725 STime.Mv
726 ldy #6 move 6 bytes
727 FMove os9 F$Move
728 else
729 ldx R$X,u get pointer to caller's space
730 ldd <D.Year get year and month
731 std ,x
732 ldd <D.Day get day and hour
733 std 2,x
734 ldd <D.Min get minute and second
735 std 4,x
736 clrb
737 endc
738 rts
739
740 endc
741
742 emod 312 emod
743 len equ * 313 len equ *
744 end 314 end