0
|
1 ********************************************************************
|
|
2 * Clock - OS-9 Level Two V3.00 Clock part 1
|
|
3 *
|
|
4 * $Id$
|
|
5 *
|
|
6 * Ed. Comments Who YY/MM/DD
|
|
7 * ------------------------------------------------------------------
|
|
8 * Original version KKD 87/01/01
|
|
9 * Fixed labels KDM 87/05/22
|
|
10 * Break into 2 modules KKD 88/09/29
|
|
11 * Fixed GIME IRQ toggle BRI 88/10/05
|
|
12 * Changed to TSlice = 3 BRI 88/11/12
|
|
13 * Changed to TSlice = 2 BRI 88/11/16
|
|
14 * Added F$TPS, chopped size BRI 88/12/09
|
|
15 * 14 Added F$TPS, chopped size BRI 88/12/09
|
|
16 * 15 Fixed bug where F$Link to Clock2 BRI ??/??/??
|
|
17 * was being done without switching D.Proc to the
|
|
18 * system state D.SysPrc first. This bug caused
|
|
19 * crashes in certain situations.
|
|
20 * 16 The only change in this edition is that BRI 90/04/15
|
|
21 * Simmy's F$TimAlm call has been combined into
|
|
22 * the standard F$Alarm call, with a few enhancements.
|
|
23 * The best documentation for this (it would probably
|
|
24 * be a good start on a manual page) is the comments
|
|
25 * from the source code.
|
|
26 * 17 Fixed bug where jmp [D.Crash] should instead BGP 98/10/20
|
|
27 * jmp D.Crash
|
|
28
|
|
29
|
|
30 nam Clock
|
|
31 ttl OS-9 Level Two V3.00 Clock part 1
|
|
32
|
|
33 ifp1
|
|
34 use defsfile
|
|
35 endc
|
|
36
|
|
37 edition equ 17
|
|
38
|
|
39 *******************************************************
|
|
40
|
|
41 mod len,name,systm+objct,reent+1,Init,0
|
|
42
|
|
43 *******************************************************
|
|
44
|
|
45 TkPerSec equ 60 ticks per second
|
|
46
|
|
47 *******************************************************
|
|
48
|
|
49 name fcs "Clock"
|
|
50 fcb edition
|
|
51
|
|
52 * Svc Calls:
|
|
53
|
|
54 SvcTbl fcb F$Time
|
|
55 fdb FTime-*-2
|
|
56 fcb F$STime
|
|
57 fdb FSTime-*-2
|
|
58 fcb F$VIRQ
|
|
59 fdb FVIRQ-*-2
|
|
60 fcb F$Alarm
|
|
61 fdb FAlarm-*-2
|
|
62 fcb F$TPS *** new BRI ***
|
|
63 fdb FTPS-*-2 *** new BRI ***
|
|
64 * fcb $26
|
|
65 * fdb FUnk-*-2
|
|
66 fcb $80
|
|
67
|
|
68 *---------------------------------
|
|
69 * IRQ Handler:
|
|
70 * Note NO STACK HERE!
|
|
71
|
|
72 IRQChek lda >IRQEnR get GIME irq status
|
|
73 ora <D.IRQS save it
|
|
74 bita #$08 was it VBORD irq?
|
|
75 bne L0035 ..yes, increment time
|
|
76 sta <D.IRQS
|
|
77 ldd <D.GPoll set D.SvcIRQ to GIME polling
|
|
78 bra L0043 ..and jmp D.XIRQ
|
|
79
|
|
80 * WAS VBORD IRQ so increment Time Vars:
|
|
81 L0035 anda #^$08 drop vbord irq
|
|
82 sta <D.IRQS
|
|
83 dec <D.Tick ticks-1
|
|
84 bne L0041 ..skip if not yet
|
|
85 lda #TkPerSec reset ticks to start of second
|
|
86 sta <D.Tick (also F$Alarm check flag!!)
|
|
87 L0041 ldd <D.VIRQ set alternate IRQ
|
|
88 L0043 std <D.SvcIrq for system state
|
|
89 jmp [D.XIRQ] and finish irq handling.
|
|
90
|
|
91 *---------------------------------
|
|
92 * NEW GIME irq register reset:
|
|
93
|
|
94 GPoll jsr [>D.Poll] do regular polling
|
|
95 bcc GPoll
|
|
96 GFix lda #$FE get enabled bits
|
|
97 anda <D.IRQS
|
|
98 sta <D.IRQS
|
|
99 lda <D.IRQER
|
|
100 tfr a,b copy it for GIME IRQ re-trigger
|
|
101 anda #^$01 select GIME IRQ input(s) to toggle
|
|
102 sta >IrqEnR disable selected GIME input(s)
|
|
103 stb >IrqEnR trigger GIME again
|
|
104 clrb
|
|
105 rts
|
|
106
|
|
107 *------------------------------
|
|
108 * VIRQ Handler:
|
|
109
|
|
110 VIRQChek clr ,-s clear found flag
|
|
111 lda <D.IRQS check for other irqs
|
|
112 bita #$37 any others?
|
|
113 beq L006D ..no
|
|
114 inc ,s yes, set flag
|
|
115 L006D ldy <D.CLTb point to virqtable
|
|
116 bra L008A ..begin search
|
|
117
|
|
118 * Main Loop:
|
|
119
|
|
120 L0072 ldd ,x get virq counter
|
|
121 subd #$0001 decrement
|
|
122 bne L0088 ..skip if not ready
|
|
123 inc ,s
|
|
124 lda $04,x check kill flag
|
|
125 bne L0082 ..nope
|
|
126 lbsr L01D9 ..yep, delete entry
|
|
127 L0082 ora #$01 set software irq bit
|
|
128 sta $04,x
|
|
129 ldd $02,x reset counter
|
|
130 L0088 std ,x
|
|
131 L008A ldx ,y++ last entry?
|
|
132 bne L0072 ..no
|
|
133 lda ,s+ else any found?
|
|
134 beq L0092 ..no
|
|
135 bsr GPoll
|
|
136 bra L0094
|
|
137 L0092 bsr GFix
|
|
138 L0094 jsr [>D.AltIRQ] poll keyboard
|
|
139 lda #TkPerSec
|
|
140 cmpa <D.Tick new second starting?
|
|
141 bne L011D ..not yet
|
|
142 ldd #3 gettime vector
|
|
143 lbsr L0125
|
|
144 lda <$002D
|
|
145 cmpa #$10
|
|
146 bhi L011D
|
|
147 beq L00E5
|
|
148 ldx #$1016
|
|
149 ldb ,x
|
|
150 beq L011D
|
|
151 leay -$07,x
|
|
152 bsr L00CE
|
|
153 bne L011D
|
|
154 lda <$002D
|
|
155 cmpa #$0F
|
|
156 bcs L00C5
|
|
157 tstb
|
|
158 bpl L00C5
|
|
159 clr ,x
|
|
160 L00C5 ldx >$1017
|
|
161 beq L011D
|
|
162 jsr ,x
|
|
163 bra L011D
|
|
164 L00CE ldb #$04
|
|
165 pshs x,b
|
|
166 ldx #$0028
|
|
167 L00D5 lda b,y
|
|
168 bmi L00DF
|
|
169 dec ,s
|
|
170 cmpa b,x
|
|
171 bne L00E3
|
|
172 L00DF decb
|
|
173 bpl L00D5
|
|
174 clrb
|
|
175 L00E3 puls pc,x,b
|
|
176 L00E5 ldx <$0048
|
|
177 leax <$21,x
|
|
178 L00EA lda ,-x
|
|
179 beq L0119
|
|
180 ldb #$C3
|
|
181 tfr d,y
|
|
182 lda $06,y
|
|
183 beq L0119
|
|
184 bsr L00CE
|
|
185 bne L0119
|
|
186 pshs b
|
|
187 ldd $06,y
|
|
188 exg d,y
|
|
189 clrb
|
|
190 exg d,y
|
|
191 pshs x
|
|
192 ldx <D.Proc
|
|
193 sty <D.Proc
|
|
194 os9 F$Send
|
|
195 stx <D.Proc
|
|
196 puls x
|
|
197 tst ,s+
|
|
198 bpl L0119
|
|
199 clra
|
|
200 clrb
|
|
201 std $06,y
|
|
202 L0119 cmpx <$0048
|
|
203 bhi L00EA
|
|
204 L011D jmp [D.Clock] continue w/multitasking
|
|
205
|
|
206 *--------------------------------- new!
|
|
207 * F$STime
|
|
208
|
|
209 FSTime ldx #D.Time
|
|
210 bsr Copy6
|
|
211 ldd #06 do setime in clock2:
|
|
212
|
|
213 *---------------------------------
|
|
214 * CALL CLOCK2: D=offset
|
|
215 L0125 ldx <D.Clock2 else update time vars
|
|
216 jmp d,x do it and rts
|
|
217
|
|
218 *---------------------------------
|
|
219 * F$Time
|
|
220 * Note that time is already here
|
|
221 * from once/second clock polling!
|
|
222
|
|
223 FTime ldx #D.Time point to time packet Moved ****
|
|
224 L012C ldy <D.Proc user process
|
|
225 lda <D.SysTsk from sys map
|
|
226 ldb P$Task,y to user map
|
|
227 ldu R$X,u destination=user(X)
|
|
228 bra L015B
|
|
229
|
|
230 Copy6 ldy <D.Proc calling process *** changed BRI ***
|
|
231 lda P$Task,y from user map *** changed BRI ***
|
|
232 ldb <D.SysTsk
|
|
233 ldu R$X,u packet
|
|
234 exg x,u
|
|
235 L015B ldy #6 number bytes
|
|
236 os9 F$Move get them
|
|
237 rts
|
|
238
|
|
239
|
|
240
|
|
241 *--------------------------------------------
|
|
242 * F$Alarm
|
|
243 *
|
|
244 * Note: The time packet is standard F$Time format, except seconds are always
|
|
245 * set to zero and $80 through $FF are wild cards that will match any
|
|
246 * time constant. Use of wild cards to replace one or more time
|
|
247 * constants in a time packet results in a repetitive alarm. The BELL
|
|
248 * alarm sounds once per second up to and including the 15th second in
|
|
249 * the alarm minute. Signal alarms are sent on the 16th second of the
|
|
250 * alarm minute to avoid misses when using a real-time Clock2, which may
|
|
251 * be out of sync with the internal VBORD (60 Hz) tick count.
|
|
252 * EG1: X=>$5A0216000000 sets an alarm at midnight on Feb. 22, 1990.
|
|
253 * EG2: X=>$5AFFFF0D0000 sets an alarm at 1:00 PM every day in 1990.
|
|
254 * EG3: X=>$FFFFFFFFFF00 sets an alarm at every minute.
|
|
255 *
|
|
256 * INPUT: A = alarm type or process ID
|
|
257 * B = action or signal code (depending on A)
|
|
258 * X = pointer to caller's time packet (if alarm set or return)
|
|
259 *
|
|
260 * OUTPUT: Alarm set, cleared, or returned, as follows:
|
|
261 *
|
|
262 * - if A=0:
|
|
263 * - if B=0, clear alarm
|
|
264 * - if B=1, set "BELL" alarm
|
|
265 * - D = alarm info
|
|
266 * - X = pointer to caller's 6 byte time packet
|
|
267 * - if B=2, return alarm info
|
|
268 * - D = alarm info
|
|
269 * - X = pointer to caller's 6 byte time packet
|
|
270 *
|
|
271 * - if A<>0:
|
|
272 * - A = process ID to be signalled
|
|
273 * - B = signal code to be sent
|
|
274 * - X = pointer to caller's 6 byte time packet
|
|
275 *
|
|
276 * ERROR OUTPUT: CC = Carry set
|
|
277 * B = error code
|
|
278
|
|
279 FAlarm ldx <D.Proc
|
|
280 leax >$00C3,x
|
|
281 ldd $01,u
|
|
282 beq L0167
|
|
283 tsta
|
|
284 bne L017C
|
|
285 cmpb #$01
|
|
286 beq L0179
|
|
287 cmpb #$02
|
|
288 beq L0170
|
|
289 comb
|
|
290 ldb #$BB
|
|
291 rts
|
|
292 L0167 tst $06,x
|
|
293 bne L0188
|
|
294 ldx #$100F
|
|
295 bra L0188
|
|
296 L0170 ldx #$100F
|
|
297 ldd $06,x
|
|
298 std $01,u
|
|
299 bra L012C
|
|
300 L0179 ldx #$100F
|
|
301 L017C pshs x,b,a
|
|
302 clra
|
|
303 clrb
|
|
304 std $06,x
|
|
305 bsr Copy6
|
|
306 puls x,b,a
|
|
307 clr $05,x
|
|
308 L0188 std $06,x
|
|
309 clrb
|
|
310 rts
|
|
311
|
|
312 *--------------------------------- *** new ***
|
|
313 * get ticks per second:
|
|
314
|
|
315 FTPS ldd #TkPerSec number of ticks per second
|
|
316 std R$D,u save it to caller's reg stack
|
|
317 clrb no error...
|
|
318 rts
|
|
319
|
|
320 *---------------------------------
|
|
321 FVIRQ pshs cc save irq status
|
|
322 orcc #IntMasks stop irq/firqs
|
|
323 ldy <D.CLTb point to virq table
|
|
324 ldx <D.Init and Init module
|
|
325 ldb PollCnt,x get max devices
|
|
326 ldx R$X,u get X parameter
|
|
327 beq L01C3 ..remove entry
|
|
328 tst ,y first entry empty?
|
|
329 beq L01B9 ..yes
|
|
330 subb #$02 else point to last
|
|
331 lslb entry in table
|
|
332 leay b,y
|
|
333 tst ,y empty?
|
|
334 bne L01D3 ..no, error
|
|
335 L01B3 tst ,--y found spot?
|
|
336 beq L01B3 ..no, back up
|
|
337 leay $02,y yes, reset ptr
|
|
338 L01B9 ldx R$Y,u get packet ptr
|
|
339 stx ,y set entry
|
|
340 ldd R$D,u get first count *** changed BRI ***
|
|
341 std ,x set it *** changed BRI ***
|
|
342 bra L01CF return okay.
|
|
343 L01C3 ldx R$Y,u get entry
|
|
344 L01C5 tst ,y return if
|
|
345 beq L01CF no entries
|
|
346 cmpx ,y++ else search for
|
|
347 bne L01C5 this entry
|
|
348 bsr L01D9 then remove it
|
|
349 L01CF puls cc restore intrpt status
|
|
350 clrb ok
|
|
351 rts .
|
|
352 L01D3 puls cc retrieve CC reg
|
|
353 comb set error bit
|
|
354 ldb #E$Poll 'Polling Table Full'
|
|
355 rts .
|
|
356
|
|
357 *--------------------------
|
|
358 * delete virq entry:
|
|
359
|
|
360 L01D9 pshs y,x save regs
|
|
361 L01DB ldx ,y++ move entries
|
|
362 stx -$04,y up in table
|
|
363 bne L01DB until last one (0000)
|
|
364 puls y,x
|
|
365 leay -$02,y reset table ptr
|
|
366 rts
|
|
367
|
|
368
|
|
369 *---------------------------------
|
|
370 * Clock Init:
|
|
371
|
|
372 Init clrb necessary???
|
|
373 pshs cc save intpt status
|
|
374 ldd #(TkPerSec*256)+02
|
|
375 sta <D.Tick
|
|
376 stb <D.TSlice two ticks/time slice
|
|
377 stb <D.Slice and first slice
|
|
378 orcc #IntMasks stop interrupts
|
|
379 leax >IRQChek,pcr set IRQ handler
|
|
380 stx <D.IRQ
|
|
381 leax >VIRQChek,pcr set VIRQ handler
|
|
382 stx <D.VIRQ
|
|
383 leax >GPoll,pcr set GIME irq reset
|
|
384 stx <D.GPoll
|
|
385 * install system calls
|
|
386 leay >SvcTbl,pcr insert syscalls
|
|
387 os9 F$SSvc
|
|
388 clra
|
|
389 ldx #PIA0Base point to PIA0
|
|
390 sta $01,x dir register
|
|
391 sta ,x side A are inputs
|
|
392 sta $03,x dir register
|
|
393 coma
|
|
394 sta $02,x side B outputs
|
|
395 ldd #$343C reset D
|
|
396 sta $01,x control reg
|
|
397 stb $03,x set up irq from VBORD
|
|
398 lda $02,x dummy reset
|
|
399 lda #$08
|
|
400 ora <D.IRQER get GIME IRQ reg/enable VBord irqs
|
|
401 sta <D.IRQER save shadow reg
|
|
402 sta >IRQEnR set VBorder irqs
|
|
403
|
|
404 ldx <D.Proc save user proc
|
|
405 pshs x
|
|
406 ldx <D.SysPrc make sys for link
|
|
407 stx <D.Proc
|
|
408
|
|
409 leax <Clock2,pcr
|
|
410 lda #Systm+Objct
|
|
411 os9 F$Link
|
|
412
|
|
413 * And here, we restore the original D.Proc value
|
|
414 puls x
|
|
415 stx <D.Proc restore user proc
|
|
416
|
|
417 bcs err
|
|
418 sty <D.Clock2 save exec vector
|
|
419 jsr ,y do init of clock (ignore errs)
|
|
420 puls pc,cc
|
|
421
|
|
422 err ldb #5 "no clock2" err
|
|
423 jmp D.Crash tell user the booterr
|
|
424
|
|
425 Clock2 fcs "Clock2"
|
|
426
|
|
427 emod
|
|
428 len equ *
|
|
429 end
|
|
430
|