OpenCores
URL https://opencores.org/ocsvn/rf68000/rf68000/trunk

Subversion Repositories rf68000

[/] [rf68000/] [trunk/] [software/] [examples/] [boot.asm] - Blame information for rev 4

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 robfinch
;-------------------------------------------------------------------------------
2
;
3
; system memory map
4
;
5
;
6
; 00000000 +----------------+      <+
7
;          | startup sp,pc  | 8 B   |
8
; 00000008 +----------------+       |
9
;                                        |    vectors     | pair shared+
10
; 00000400 +----------------+       |
11
;                                        |   bios mem     |       |
12
; 00001000 +----------------+       |
13
;                                        |   bios code    |       |
14
; 00008000 +----------------+      <+
15
;                                        |    unused      |
16
; 00040000 +----------------+
17
;                                        |   local ram    |
18
; 00042000 +----------------+
19
;                                        |    unused      |
20
; 00100000 +----------------+
21
;                                        |   global ram   |
22
; 00101000 +----------------+
23
;                                        | serial rcvbuf  |
24
; 00102000 +----------------+
25
;                                        |    unused      |
26
; 20000000 +----------------+
27
;          |                |
28
;          |                |
29
;          |                |
30
;          :  dram memory   : 512 MB
31
;          |                |
32
;          |                |
33
;          |                |
34
; 40000000 +----------------+
35
;          |                |
36
;          :     unused     :
37
;          |                |
38
; FD000000 +----------------+
39
;          |                |
40
;          :    I/O area    : 1.0 M
41
;          |                |
42
; FFE00000 +----------------+
43
;          |                |
44
;          :     unused     :
45
;          |                |
46
; FFFFFFFF +----------------+
47
;
48
;-------------------------------------------------------------------------------
49
;
50 3 robfinch
HAS_MMU equ 0
51
 
52 2 robfinch
CTRLC   EQU             $03
53
CTRLH   EQU             $08
54
CTRLS   EQU             $13
55
CTRLX   EQU             $18
56
CTRLZ   EQU             $1A
57
LF              EQU             $0A
58
CR              EQU             $0D
59
XON             EQU             $11
60
XOFF    EQU             $13
61
 
62
SC_F12  EQU    $07
63
SC_C    EQU    $21
64
SC_T    EQU    $2C
65
SC_Z    EQU    $1A
66
SC_KEYUP        EQU             $F0
67
SC_EXTEND   EQU         $E0
68
SC_CTRL         EQU             $14
69
SC_RSHIFT       EQU             $59
70
SC_NUMLOCK      EQU             $77
71
SC_SCROLLLOCK   EQU     $7E
72
SC_CAPSLOCK             EQU     $58
73
SC_ALT          EQU             $11
74
SC_LSHIFT       EQU             $12
75
SC_DEL          EQU             $71             ; extend
76
SC_LCTRL        EQU             $58
77
SC_TAB      EQU         $0D
78
 
79 3 robfinch
        if HAS_MMU
80 2 robfinch
TEXTREG         EQU     $1E3FF00        ; virtual addresses
81
txtscreen       EQU     $1E00000
82
semamem         EQU     $1E50000
83
ACIA                    EQU     $1E60000
84
ACIA_RX         EQU     0
85
ACIA_TX         EQU     0
86
ACIA_STAT       EQU     4
87
ACIA_CMD        EQU     8
88
ACIA_CTRL       EQU     12
89 3 robfinch
I2C2                    equ $01E69000
90
I2C_PREL        equ 0
91
I2C_PREH        equ 1
92
I2C_CTRL        equ 2
93
I2C_RXR         equ 3
94
I2C_TXR         equ 3
95
I2C_CMD         equ 4
96
I2C_STAT        equ 4
97 2 robfinch
PLIC                    EQU     $1E90000
98
MMU                             EQU $FDC00000   ; physical address
99
leds                    EQU     $1EFFF00        ; virtual addresses
100
keybd                   EQU     $1EFFE00
101
KEYBD                   EQU     $1EFFE00
102
RAND                    EQU     $1EFFD00
103
RAND_NUM        EQU     $1EFFD00
104
RAND_STRM       EQU     $1EFFD04
105
RAND_MZ         EQU $1EFFD08
106
RAND_MW         EQU     $1EFFD0C
107
RST_REG         EQU     $1EFFC00
108
IO_BITMAP       EQU $1F00000
109 3 robfinch
        else
110
TEXTREG         EQU     $FD03FF00       ; virtual addresses
111
txtscreen       EQU     $FD000000
112
semamem         EQU     $FD050000
113
ACIA                    EQU     $FD060000
114
ACIA_RX         EQU     0
115
ACIA_TX         EQU     0
116
ACIA_STAT       EQU     4
117
ACIA_CMD        EQU     8
118
ACIA_CTRL       EQU     12
119
I2C2                    equ $FD069000
120
I2C_PREL        equ 0
121
I2C_PREH        equ 1
122
I2C_CTRL        equ 2
123
I2C_RXR         equ 3
124
I2C_TXR         equ 3
125
I2C_CMD         equ 4
126
I2C_STAT        equ 4
127
PLIC                    EQU     $FD090000
128
MMU                             EQU $FDC00000   ; physical address
129
leds                    EQU     $FD0FFF00       ; virtual addresses
130
keybd                   EQU     $FD0FFE00
131
KEYBD                   EQU     $FD0FFE00
132
RAND                    EQU     $FD0FFD00
133
RAND_NUM        EQU     $FD0FFD00
134
RAND_STRM       EQU     $FD0FFD04
135
RAND_MZ         EQU $FD0FFD08
136
RAND_MW         EQU     $FD0FFD0C
137
RST_REG         EQU     $FD0FFC00
138
IO_BITMAP       EQU $FD100000
139
        endif
140 2 robfinch
 
141
SERIAL_SEMA     EQU     2
142
KEYBD_SEMA      EQU     3
143
RAND_SEMA               EQU     4
144
SCREEN_SEMA     EQU     5
145
MEMORY_SEMA EQU 6
146
TCB_SEMA                EQU     7
147
 
148
        data
149
        dc.l            $00040FFC
150
        dc.l            start
151
        dc.l            bus_err
152
        dc.l            0
153
        dc.l            illegal_trap            * ILLEGAL instruction
154
        dc.l            0
155
        dc.l            EXCEPTION_6                     * CHK
156
        dc.l            EXCEPTION_7                     * TRAPV
157
        dc.l            0
158
        dc.l            0
159
 
160
        ; 10
161
        dc.l            0
162
        dc.l            0
163
        dc.l            0
164
        dc.l            0
165
        dc.l            0
166
        dc.l            0
167
        dc.l            0
168
        dc.l            0
169
        dc.l            0
170
        dc.l            0
171
 
172
        ; 20
173
        dc.l            0
174
        dc.l            0
175
        dc.l            0
176
        dc.l            0
177
        dc.l            SpuriousIRQ
178
        dc.l            0
179
        dc.l            0
180
        dc.l            irq3_rout
181
        dc.l            0
182
        dc.l            0
183
 
184
        ; 30
185
        dc.l            TickIRQ                                         ; IRQ 30 - timer / keyboard
186
        dc.l            nmi_rout
187
        dc.l            0
188
        dc.l            0
189
        dc.l            0
190
        dc.l            trap3                                                   ; breakpoint
191
        dc.l            0
192
        dc.l            0
193
        dc.l            0
194
        dc.l            0
195
 
196
        ; 40
197
        dc.l            0
198
        dc.l            0
199
        dc.l            0
200
        dc.l            0
201
        dc.l            0
202
        dc.l            0
203
        dc.l            0
204
        dc.l            TRAP15
205
        dc.l            0
206
        dc.l            0
207
 
208
        ; 50
209
        dc.l            0
210
        dc.l            0
211
        dc.l            0
212
        dc.l            0
213
        dc.l            0
214
        dc.l            0
215
        dc.l            0
216
        dc.l            0
217
        dc.l            0
218
        dc.l            io_irq
219
 
220
        ; 60
221
        dc.l            KeybdIRQ
222
        dc.l            SerialIRQ
223
        dc.l            0
224
        dc.l            brdisp_trap
225
        dc.l            0
226
        dc.l            0
227
        dc.l            0
228
        dc.l            0
229
        dc.l            0
230
        dc.l            0
231
 
232
        org                     $400
233
 
234
InstalledIRQ:
235
        dc.l            0
236
        dc.l            0
237
        dc.l            0
238
        dc.l            0
239
        dc.l            0
240
        dc.l            0
241
        dc.l            0
242
        dc.l            0
243
 
244
        dc.l            0
245
        dc.l            0
246
        dc.l            0
247
        dc.l            0
248
        dc.l            0
249
        dc.l            0
250
        dc.l            0
251
        dc.l            0
252
 
253
        dc.l            0
254
        dc.l            0
255
        dc.l            0
256
        dc.l            0
257
        dc.l            0
258
        dc.l            0
259
        dc.l            0
260
        dc.l            0
261
 
262
        dc.l            0
263
        dc.l            0
264
        dc.l            0
265
        dc.l            0
266
        dc.l            0
267
        dc.l            0
268
        dc.l            0
269
        dc.l            0
270
 
271
        dc.l            0
272
        dc.l            0
273
        dc.l            0
274
        dc.l            0
275
        dc.l            0
276
        dc.l            0
277
        dc.l            0
278
        dc.l            0
279
 
280
        dc.l            0
281
        dc.l            0
282
        dc.l            0
283
        dc.l            0
284
        dc.l            0
285
        dc.l            0
286
        dc.l            0
287
        dc.l            0
288
 
289
        dc.l            0
290
        dc.l            0
291
        dc.l            0
292
        dc.l            0
293
        dc.l            0
294
        dc.l            0
295
        dc.l            0
296
        dc.l            0
297
 
298
        dc.l            0
299
        dc.l            0
300
        dc.l            0
301
        dc.l            0
302
        dc.l            0
303
        dc.l            0
304
        dc.l            0
305
        dc.l            0
306
 
307
        org                     $500
308
 
309
;-------------------------------------------------------------------------------
310
;-------------------------------------------------------------------------------
311
 
312
; BIOS variables which must be local (not shared) to each core
313
 
314
CursorRow       equ             $40000
315
CursorCol       equ             $40001
316
TextPos         equ             $40002
317
TextCurpos      equ     $40002
318
TextScr                 equ     $40004
319
S19StartAddress equ     $40008
320
KeybdEcho               equ     $4000C
321
KeybdWaitFlag   equ     $4000D
322
CmdBuf                  equ $40040
323
CmdBufEnd               equ     $40080
324
fgColor                 equ     $40084
325
bkColor                 equ     $40088
326
TextRows                equ     $4008C
327
TextCols                equ     $4008D
328
Regsave                 equ     $40100
329
numBreakpoints  equ             8
330
BreakpointFlag  equ             $40200
331
NumSetBreakpoints       equ     $40202  ; to $40203
332
Breakpoints                     equ             $40220  ; to $40240
333
BreakpointWords equ             $40280  ; to $402A0
334
;RunningTCB  equ $40300
335
TimerStack      equ     $40BFC
336
 
337
; Keyboard buffer is in shared memory
338 3 robfinch
IOFocus                 EQU     $00100000
339 2 robfinch
memend                  equ $00100004
340
KeybdLEDs               equ     $0010000E
341
_KeyState1      equ     $0010000F
342
_KeyState2      equ     $00100010
343
_KeybdHead      equ     $00100011
344
_KeybdTail      equ     $00100012
345
_KeybdCnt               equ     $00100013
346
KeybdID                 equ     $00100016
347
_KeybdBuf               equ     $00100020
348
S19Checksum     equ     $00100150
349
SerTailRcv      equ     $00100160
350
SerHeadRcv      equ     $00100162
351
SerRcvXon               equ     $00100164
352
SerRcvXoff      equ     $00100165
353
SerRcvBuf               equ     $00101000
354 3 robfinch
RTCBuf                  equ $00100200   ; to $0010023F
355 2 robfinch
 
356
        include "..\Femtiki\source\kernel\Femtiki_vars.x68"
357
 
358
        code
359
        align           2
360
start:
361 3 robfinch
;       fadd (a0)+,fp2
362 2 robfinch
        move.w #$2700,sr                                        ; enable level 6 and higher interrupts
363
        moveq #0,d0                                                             ; set address space zero
364
        movec d0,asid
365 3 robfinch
        ; Setup circuit select signals
366
        move.l #MMU,d0
367
        movec d0,mmus
368
        if HAS_MMU
369
                move.l #$01F00000,d0                    ; set virtual address for iop bitmap
370
                movec d0,iops
371
                move.l #$01E00000,d0                    ; set virtual address for io block
372
                movec d0,ios
373
        else
374
                move.l #$FD100000,d0                    ; set virtual address for iop bitmap
375
                movec d0,iops
376
                move.l #$FD000000,d0                    ; set virtual address for io block
377
                movec d0,ios
378
        endif
379
        movec coreno,d0                                                 ; set initial value of thread register
380
        swap d0                                                                                 ; coreno in high eight bits
381
        lsl.l #8,d0
382
        movec d0,tr
383 2 robfinch
        ; Prepare local variable storage
384
        move.w #1023,d0                                         ; 1024 longs to clear
385
        lea     $40000,a0                                                       ; non shared local memory address
386
.0111:
387
        clr.l   (a0)+                                                           ; clear the memory area
388
        dbra d0,.0111
389
        move.l #$1fffff,fgColor         ; set foreground / background color
390
        move.l #$00003f,bkColor
391
        movec.l coreno,d0                                       ; get core number (2 to 9)
392
        subi.b #2,d0                                                    ; adjust (0 to 7)
393
        mulu #16384,d0                                          ; compute screen location
394 3 robfinch
        if HAS_MMU
395
                addi.l #$01E00000,d0
396
        else
397
                addi.l #$FD000000,d0
398
        endif
399 2 robfinch
        move.l d0,TextScr
400
        move.b #64,TextCols                             ; set rows and columns
401
        move.b #32,TextRows
402
        movec.l coreno,d0                                       ; get core number
403
        cmpi.b #2,d0
404
        bne     start_other
405
        move.b d0,IOFocus                                       ; Set the IO focus in global memory
406 3 robfinch
        if HAS_MMU
407
                bsr InitMMU                                                     ; Can't access anything till this is done
408
        endif
409
        bsr     InitIOPBitmap                                   ; not going to get far without this
410 2 robfinch
        bsr     InitSemaphores
411
        bsr     InitRand
412
        bsr     Delay3s                                         ; give devices time to reset
413
        bsr     clear_screen
414
 
415
        bsr     _KeybdInit
416
;       bsr     InitIRQ
417
        bsr     SerialInit
418 3 robfinch
        bsr init_i2c
419
;       bsr rtc_read
420 2 robfinch
 
421
        ; Write startup message to screen
422
 
423
        lea     msg_start,a1
424
        bsr     DisplayString
425
;       bsr     FemtikiInit
426
        movec   coreno,d0
427
        swap d0
428
        moveq   #1,d1
429
        bsr     UnlockSemaphore ; allow another cpu access
430
        moveq   #0,d1
431
        bsr     UnlockSemaphore ; allow other cpus to proceed
432
        move.w #$A4A4,leds                      ; diagnostics
433
        bsr     init_plic                               ; initialize platform level interrupt controller
434
        bra     StartMon
435
        bsr     cpu_test
436
;       lea     brdisp_trap,a0  ; set brdisp trap vector
437
;       move.l  a0,64*4
438
 
439
loop2:
440
        move.l  #-1,d0
441
loop1:
442
        move.l  d0,d1
443
        lsr.l           #8,d1
444
        lsr.l           #8,d1
445
        move.b  d1,leds
446
        dbra            d0,loop1
447
        bra                     loop2
448
 
449
start_other:
450
        bsr                     Delay3s2                                                ; need time for system setup (io_bitmap etc.)
451 3 robfinch
        bsr                     Delay3s2                                                ; need time for system setup (io_bitmap etc.)
452 2 robfinch
        bsr                     clear_screen
453
        movec           coreno,d1
454
        bsr                     DisplayByte
455
        lea                     msg_core_start,a1
456
        bsr                     DisplayString
457
;       bsr                     FemtikiInitIRQ
458
do_nothing:
459
        bra                     StartMon
460
        bra                     do_nothing
461
 
462
;------------------------------------------------------------------------------
463
; Initialize the MMU to allow thread #0 access to IO
464
;------------------------------------------------------------------------------
465 3 robfinch
        if HAS_MMU
466 2 robfinch
        align 2
467
mmu_adrtbl:     ; virtual address[24:16], physical address[31:16] bytes reversed!
468
        dc.l    $0010,$10000300 ; global scratch pad
469
        dc.l    $01E0,$00FD0300
470
        dc.l    $01E1,$01FD0300
471
        dc.l    $01E2,$02FD0300
472
        dc.l  $01E3,$03FD0300
473
        dc.l    $01E5,$05FD0300
474
        dc.l    $01E6,$06FD0300
475
        dc.l    $01E9,$09FD0300
476
        dc.l    $01EF,$0FFD0300
477
        dc.l    $01F0,$10FD0300
478 3 robfinch
        dc.l  $01FF,$FFFF0300   ; all ones output for IRQ ack needed
479 2 robfinch
 
480
        even
481
InitMMU:
482
        lea MMU+8,a0                            ; first 128kB is local RAM
483
        move.l #$32000,d2               ; map all pages to DRAM
484
        move.l #510,d0                  ; then override for IO later
485
.0002
486
        move.l d2,d1
487
        bsr rbo
488
        move.l d1,(a0)+
489
        addi.w #1,d2                            ; increment DRAM page number
490
        dbra d0,.0002
491
        lea MMU,a0                                      ; now program IO access
492
        lea mmu_adrtbl,a1
493 3 robfinch
        moveq #10,d0
494 2 robfinch
.0001
495
        move.l (a1)+,d2
496
        lsl.l #2,d2
497
        move.l (a1)+,(a0,d2.w)
498
        dbra d0,.0001
499
        rts
500 3 robfinch
        endif
501 2 robfinch
 
502
;------------------------------------------------------------------------------
503
; The IO bitmap needs to be initialized to allow access to IO.
504
;------------------------------------------------------------------------------
505
 
506 3 robfinch
InitIOPBitmap:
507
        moveq #0,d3                             ; d3 = asid value
508
        move.w #63,d0                   ; 64 bitmaps to setup
509
        movec iops,a0                   ; a0 = IOP bitmap address
510
        movea.l a0,a1                   ; a1 = table address
511
.0004
512
        tst.b d3
513
        seq d1                                          ; set entire bitmap for asid 0, otherwise clear entire bitmap
514
        ext.w   d1                                      ; make into a long value
515
        ext.l d1
516
        move.w #127,d4
517 2 robfinch
.0001
518 3 robfinch
        move.l d1,(a1)+         ; set or clear entire table
519
        dbra d4,.0001
520 2 robfinch
        moveq #-1,d1
521 3 robfinch
        move.l d1,160(a0)       ; all cores have access to semaphores
522
        move.l d1,164(a0)
523
        move.l d1,168(a0)
524
        move.l d1,172(a0)
525 2 robfinch
        swap d0
526 3 robfinch
        move.w #31,d0                   ; 32 long words for the screen area per bitmap
527 2 robfinch
.0003
528 3 robfinch
        move.l d1,(a0)+         ; all cores have access to a screen
529 2 robfinch
        dbra d0,.0003
530
        swap d0
531 3 robfinch
        addi.b #1,d3                    ; do next address space
532
        movea.l a1,a0                   ; a0 points to area for next address space
533 2 robfinch
        dbra d0,.0004
534
        rts
535
 
536
;------------------------------------------------------------------------------
537
; RandInit
538
;       Initialize random number generator.
539
;
540
; Modifies:
541
;               none
542
; Parameters:
543
;               none
544
;       Returns:
545
;               none
546
;------------------------------------------------------------------------------
547
 
548
InitRand:
549
RandInit:
550
        movem.l d0/d1,-(a7)
551 3 robfinch
        moveq #37,d0                                                            ; lock semaphore
552
        moveq   #RAND_SEMA,d1
553
        trap #15
554
        movec coreno,d0                                                 ; d0 = core number
555
        lsl.l   #6,d0                                                                   ; allow 64 streams per core
556
        move.l d0,RAND_STRM                                     ; select the stream
557
        move.l #$12345678,RAND_MZ               ; initialize to some value
558
        move.l #$98765432,RAND_MW
559
        move.l #777777777,RAND_NUM      ; generate first number
560
        moveq #38,d0                                                            ; unlock semaphore
561
        moveq   #RAND_SEMA,d1
562
        trap #15
563 2 robfinch
        movem.l (a7)+,d0/d1
564
        rts
565
 
566
;------------------------------------------------------------------------------
567
;------------------------------------------------------------------------------
568
 
569
RandGetNum:
570
        movem.l d0/d2,-(a7)
571 3 robfinch
        moveq #37,d0                                                            ; lock semaphore
572
        moveq   #RAND_SEMA,d1
573
        trap #15
574
        movec   coreno,d0
575
        lsl.l   #6,d0
576
        move.l d0,RAND_STRM                                     ; select the stream
577
        move.l RAND_NUM,d2                                      ; d2 = random number
578
        clr.l   RAND_NUM                                                        ; generate next number
579
        moveq #38,d0                                                            ; unlock semaphore
580
        moveq   #RAND_SEMA,d1
581
        trap #15
582
        move.l d2,d1
583 2 robfinch
        movem.l (a7)+,d0/d2
584
        rts
585
 
586
;------------------------------------------------------------------------------
587
; RandWait
588
;    Wait some random number of clock cycles before returning.
589
;------------------------------------------------------------------------------
590
 
591
RandWait:
592
        movem.l d0/d1,-(a7)
593
        bsr                     RandGetNum
594
        andi.w  #15,d1
595
.0001:
596
        nop
597
        dbra            d1,.0001
598
        movem.l (a7)+,d0/d1
599
        rts
600
 
601
;------------------------------------------------------------------------------
602
; Initialize semaphores
603
; - all semaphores are set to unlocked except the first one, which is locked
604
; for core #2.
605
;
606
; Parameters:
607
;               
608
; Modifies:
609
;               
610
; Returns:
611
;               
612
;------------------------------------------------------------------------------
613
 
614
InitSemaphores:
615
        movem.l d1/a0,-(a7)
616
        lea                     semamem,a0
617
        move.l  #$20000,$2000(a0)       ; lock the first semaphore for core #2, thread #0
618
        move.w  #254,d1
619
.0001:
620
        lea                     4(a0),a0
621
        clr.l           $2000(a0)                                       ; write zeros to unlock
622
        dbra            d1,.0001
623
        movem.l (a7)+,d1/a0
624
        rts
625
 
626
; -----------------------------------------------------------------------------
627
; Parameters:
628
;               d1 semaphore number
629
;
630
; Side Effects:
631
;               increments semaphore, saturates at 255
632
;
633
; Returns:
634
;       z flag set if semaphore was zero
635
; -----------------------------------------------------------------------------
636
 
637
;IncrementSemaphore:
638
;       movem.l d1/a0,-(a7)                     ; save registers
639
;       lea                     semamem,a0                      ; point to semaphore memory
640
;       ext.w           d1                                                      ; make d1 word value
641
;       asl.w           #4,d1                                           ; align to memory
642
;       tst.b           1(a0,d1.w)                      ; read (test) value for zero
643
;       movem.l (a7)+,a0/d1                     ; restore regs
644
;       rts
645
 
646
; -----------------------------------------------------------------------------
647
; Parameters:
648
;               d1 semaphore number
649
;
650
; Side Effects:
651
;               decrements semaphore, saturates at zero
652
;
653
; Returns:
654
;       z flag set if semaphore was zero
655
; -----------------------------------------------------------------------------
656
 
657
;DecrementSemaphore:
658
;       movem.l d1/a0,-(a7)                     ; save registers
659
;       lea                     semamem,a0                      ; point to semaphore memory
660
;       andi.w  #255,d1                                 ; make d1 word value
661
;       asl.w           #4,d1                                           ; align to memory
662
;       tst.b           1(a0,d1.w)                      ; read (test) value for zero
663
;       movem.l (a7)+,a0/d1                     ; restore regs
664
;       rts
665
 
666
; -----------------------------------------------------------------------------
667
; Lock a semaphore
668
;
669
; Parameters:
670
;               d0 = key
671
;               d1 = semaphore number
672
; -----------------------------------------------------------------------------
673
 
674
LockSemaphore:
675 3 robfinch
        rts
676 2 robfinch
        movem.l d1/a0,-(a7)                     ; save registers
677
        lea                     semamem,a0                      ; point to semaphore memory lock area
678
        andi.w  #255,d1                                 ; make d1 word value
679
        lsl.w           #2,d1                                           ; align to memory
680 3 robfinch
.0001
681 2 robfinch
        move.l  d0,(a0,d1.w)            ; try and write the semaphore
682
        cmp.l           (a0,d1.w),d0            ; did it lock?
683
        bne.s           .0001                                           ; no, try again
684
        movem.l (a7)+,a0/d1                     ; restore regs
685
        rts
686
 
687
; -----------------------------------------------------------------------------
688
; Unlocks a semaphore even if not the owner.
689
;
690
; Parameters:
691
;               d1 semaphore number
692
; -----------------------------------------------------------------------------
693
 
694
ForceUnlockSemaphore:
695
        movem.l d1/a0,-(a7)                             ; save registers
696
        lea                     semamem+$3000,a0        ; point to semaphore memory read/write area
697
        andi.w  #255,d1                                         ; make d1 word value
698
        lsl.w           #2,d1                                                   ; align to memory
699
        clr.l           (a0,d1.w)                                       ; write zero to unlock
700
        movem.l (a7)+,a0/d1                             ; restore regs
701
        rts
702
 
703
; -----------------------------------------------------------------------------
704
; Unlocks a semaphore. Must be the owner to have effect.
705
; Three cases:
706
;       1) the owner, the semaphore will be reset to zero
707
;       2) not the owner, the write will be ignored
708
; 3) already unlocked, the write will be ignored
709
;
710
; Parameters:
711
;               d0 = key
712
;               d1 = semaphore number
713
; -----------------------------------------------------------------------------
714
 
715
UnlockSemaphore:
716 3 robfinch
        bra ForceUnlockSemaphore
717 2 robfinch
        movem.l d1/a0,-(a7)                             ; save registers
718
        lea                     semamem+$1000,a0        ; point to semaphore memory unlock area
719
        andi.w  #255,d1                                         ; make d1 word value
720
        lsl.w           #2,d1                                                   ; align to memory
721
        move.l  d0,(a0,d1.w)                    ; write matching value to unlock
722
        movem.l (a7)+,a0/d1                             ; restore regs
723
        rts
724
 
725
; -----------------------------------------------------------------------------
726
; Parameters:
727
;               d1 = semaphore to lock / unlock
728
; -----------------------------------------------------------------------------
729
 
730
T15LockSemaphore:
731 3 robfinch
        movec tr,d0
732 2 robfinch
        bra LockSemaphore
733
 
734
T15UnlockSemaphore:
735 3 robfinch
        movec tr,d0
736 2 robfinch
        bra UnlockSemaphore
737
 
738
; -----------------------------------------------------------------------------
739
; Delay for a few seconds to allow some I/O reset operations to take place.
740
; -----------------------------------------------------------------------------
741
 
742
Delay3s:
743
        move.l  #3000000,d0             ; this should take a few seconds to loop
744
        lea                     leds,a0                         ; a0 = address of LED output register
745
        bra                     dly3s1                          ; branch to the loop
746
dly3s2:
747
        swap            d0                                              ; loop is larger than 16-bits
748
dly3s1:
749
        move.l  d0,d1                                   ; the counter cycles fast, so use upper bits for display
750
        rol.l           #8,d1                                   ; could use swap here, but lets test rol
751
        rol.l           #8,d1
752
        move.b  d1,(a0)                         ; set the LEDs
753
        dbra            d0,dly3s1                       ; decrement and branch back
754
        swap            d0
755
        dbra            d0,dly3s2
756
        rts
757
 
758
Delay3s2:
759
        movec           coreno,d0                       ; vary delay by core to stagger startup
760
        lsl.l           #8,d0
761
        addi.l  #3000000,d0             ; this should take a few seconds to loop
762
        bra                     .0001                                   ; branch to the loop
763
.0002
764
        swap            d0                                              ; loop is larger than 16-bits
765
.0001
766
        dbra            d0,.0001                        ; decrement and branch back
767
        swap            d0
768
        dbra            d0,.0002
769
        rts
770
 
771
        include "cputest.asm"
772
        include "TinyBasic.asm"
773
        include "..\Femtiki\source\kernel\Femtiki.x68"
774
 
775
; -----------------------------------------------------------------------------
776
; Gets the screen color in d0 and d1.
777
; -----------------------------------------------------------------------------
778
 
779
get_screen_color:
780
        move.l  fgColor,d0                      ; get foreground color
781
        asl.l           #5,d0                                           ; shift into position
782
        ori.l           #$40000000,d0           ; set priority
783
        move.l  bkColor,d1
784
        lsr.l           #8,d1
785
        lsr.l           #8,d1
786
        andi.l  #31,d1                                  ; mask off extra bits
787
        or.l            d1,d0                                           ; set background color bits in upper long word
788
        move.l  bkColor,d1                      ; get background color
789
        asl.l           #8,d1                                           ; shift into position for display ram
790
        asl.l           #8,d1
791
        rts
792
 
793
; -----------------------------------------------------------------------------
794
; -----------------------------------------------------------------------------
795
 
796
get_screen_address:
797
        move.l  TextScr,a0
798
        rts
799
 
800
; -----------------------------------------------------------------------------
801
; -----------------------------------------------------------------------------
802
 
803
clear_screen:
804
        movem.l d0/d1/d2/a0,-(a7)
805
        movec           coreno,d0
806
        swap            d0
807
        moveq           #SCREEN_SEMA,d1
808
        bsr                     LockSemaphore
809
        bsr                     get_screen_address      ; a0 = pointer to screen area
810
        move.b  TextRows,d0                                     ; d0 = rows
811
        move.b  TextCols,d2                                     ; d2 = cols
812
        ext.w           d0                                                                      ; convert to word
813
        ext.w           d2                                                                      ; convert to word
814
        mulu            d0,d2                                                           ; d2 = number of character cells to clear
815
        bsr                     get_screen_color                ; get the color bits
816
        ori.w           #32,d1                                                  ; load space character
817
        rol.w           #8,d1                                                           ; swap endian, text controller expects little endian
818
        swap            d1
819
        rol.w           #8,d1
820
        rol.w           #8,d0                                                           ; swap endian
821
        swap            d0
822
        rol.w           #8,d0
823
loop3:
824
        move.l  d1,(a0)+                                                ; copy char plus bkcolor to cell
825
        move.l  d0,(a0)+                                        ; copy fgcolor to cell
826
        dbra            d2,loop3
827
        movec           coreno,d0
828
        swap            d0
829
        moveq           #SCREEN_SEMA,d1
830
        bsr                     UnlockSemaphore
831
        movem.l (a7)+,d0/d1/d2/a0
832
        rts
833
 
834
CRLF:
835
        move.l  d1,-(a7)
836
        move.b  #13,d1
837
        bsr                     DisplayChar
838
        move.b  #10,d1
839
        bsr                     DisplayChar
840
        move.l  (a7)+,d1
841
        rts
842
 
843
;------------------------------------------------------------------------------
844
;------------------------------------------------------------------------------
845
 
846
UpdateTextPos:
847
        move.b  CursorRow,d0            ; compute screen location
848
        andi.w  #$7f,d0
849
        move.b  TextCols,d2
850
        ext.w           d2
851
        mulu.w  d2,d0
852
        move.l  d0,d3
853
        move.b  CursorCol,d2
854
        andi.w  #$ff,d2
855
        add.w           d2,d0
856
        move.w  d0,TextPos                      ; save cursor pos
857
        rts
858
 
859
;------------------------------------------------------------------------------
860
; Calculate screen memory location from CursorRow,CursorCol.
861
; Destroys d0,d2,a0
862
;------------------------------------------------------------------------------
863
 
864
CalcScreenLoc:
865
        bsr                     UpdateTextPos
866
        ext.l           d0                                                              ; make it into a long
867
        asl.l           #3,d0                                                   ; 8 bytes per char
868
        bsr                     get_screen_address
869
        add.l           d0,a0                                                   ; a0 = screen location
870
        rts
871
 
872
;------------------------------------------------------------------------------
873
; Display a character on the screen
874
; d1.b = char to display
875
;------------------------------------------------------------------------------
876
 
877
DisplayChar:
878
        movem.l d1/d2/d3,-(a7)
879
        movec           coreno,d2
880
        cmpi.b  #2,d2
881
;       bne.s           .0001
882
;       bsr                     SerialPutChar
883
.0001:
884
        andi.l  #$ff,d1                         ; zero out upper bytes of d1
885
        cmpi.b  #13,d1                          ; carriage return ?
886
        bne                     dccr
887
        clr.b           CursorCol                       ; just set cursor column to zero on a CR
888
dcx14:
889
        bsr                     SyncCursor              ; set position in text controller
890
dcx7:
891
        movem.l (a7)+,d1/d2/d3
892
        rts
893
dccr:
894
        cmpi.b  #$91,d1                 ; cursor right ?
895
        bne.s   dcx6
896
        move.b  TextCols,d2
897
        sub.b           #1,d2
898
        sub.b           CursorCol,d2
899
        beq.s           dcx7
900
        addi.b  #1,CursorCol
901
        bra.s           dcx14
902
dcx6:
903
        cmpi.b  #$90,d1                 ; cursor up ?
904
        bne.s           dcx8
905
        cmpi.b  #0,CursorRow
906
        beq.s           dcx7
907
        subi.b  #1,CursorRow
908
        bra.s           dcx14
909
dcx8:
910
        cmpi.b  #$93,d1                 ; cursor left?
911
        bne.s           dcx9
912
        cmpi.b  #0,CursorCol
913
        beq.s           dcx7
914
        subi.b  #1,CursorCol
915
        bra.s           dcx14
916
dcx9:
917
        cmpi.b  #$92,d1                 ; cursor down ?
918
        bne.s           dcx10
919
        move.b  TextRows,d2
920
        sub.b           #1,d2
921
        cmp.b           CursorRow,d2
922
        beq.s           dcx7
923
        addi.b  #1,CursorRow
924
        bra.s           dcx14
925
dcx10:
926
        cmpi.b  #$94,d1                 ; cursor home ?
927
        bne.s           dcx11
928
        cmpi.b  #0,CursorCol
929
        beq.s           dcx12
930
        clr.b           CursorCol
931
        bra                     dcx14
932
dcx12:
933
        clr.b           CursorRow
934
        bra                     dcx14
935
dcx11:
936
        movem.l d0/d1/d2/a0,-(a7)
937
        cmpi.b  #$99,d1                 ; delete ?
938
        beq.s           doDelete
939
        cmpi.b  #CTRLH,d1                       ; backspace ?
940
        beq.s   doBackspace
941
        cmpi.b  #CTRLX,d1                       ; delete line ?
942
        beq                     doCtrlX
943
        cmpi.b  #10,d1          ; linefeed ?
944
        beq.s           dclf
945
 
946
        ; regular char
947
        bsr                     CalcScreenLoc   ; a0 = screen location
948
        move.l  d1,d2                                   ; d2 = char
949
        bsr                     get_screen_color        ; d0,d1 = color
950
        or.l            d2,d1                                   ; d1 = char + color
951
        rol.w           #8,d1                                   ; text controller expects little endian data
952
        swap            d1
953
        rol.w           #8,d1
954
        move.l  d1,(a0)
955
        rol.w           #8,d0                                   ; swap bytes
956
        swap            d0                                              ; swap halfs
957
        rol.w           #8,d0                                   ; swap remaining bytes
958
        move.l  d0,4(a0)
959
        bsr                     IncCursorPos
960
        bsr                     SyncCursor
961
        bra                     dcx4
962
dclf:
963
        bsr                     IncCursorRow
964
dcx16:
965
        bsr                     SyncCursor
966
dcx4:
967
        movem.l (a7)+,d0/d1/d2/a0               ; get back a0
968
        movem.l (a7)+,d1/d2/d3
969
        rts
970
 
971
        ;---------------------------
972
        ; CTRL-H: backspace
973
        ;---------------------------
974
doBackspace:
975
        cmpi.b  #0,CursorCol            ; if already at start of line
976
        beq.s   dcx4                                            ; nothing to do
977
        subi.b  #1,CursorCol            ; decrement column
978
 
979
        ;---------------------------
980
        ; Delete key
981
        ;---------------------------
982
doDelete:
983
        movem.l d0/d1/a0,-(a7)  ; save off screen location
984
        bsr               CalcScreenLoc         ; a0 = screen location
985
        move.b  CursorCol,d0
986
.0001:
987
        move.l  8(a0),(a0)              ; pull remaining characters on line over 1
988
        move.l  12(a0),4(a0)    ; pull remaining characters on line over 1
989
        lea                     8(a0),a0
990
        addi.b  #1,d0
991
        cmp.b           TextCols,d0
992
        blo.s           .0001
993
        bsr                     get_screen_color
994
        move.w  #' ',d1                         ; terminate line with a space
995
        rol.w           #8,d1
996
        swap            d1
997
        rol.w           #8,d1
998
        move.l  d1,-8(a0)
999
        movem.l (a7)+,d0/d1/a0
1000
        bra.s           dcx16                           ; finished
1001
 
1002
        ;---------------------------
1003
        ; CTRL-X: erase line
1004
        ;---------------------------
1005
doCtrlX:
1006
        clr.b           CursorCol                       ; Reset cursor to start of line
1007
        move.b  TextCols,d0                     ; and display TextCols number of spaces
1008
        ext.w           d0
1009
        ext.l           d0
1010
        move.b  #' ',d1                         ; d1 = space char
1011
.0001:
1012
        ; DisplayChar is called recursively here
1013
        ; It's safe to do because we know it won't recurse again due to the
1014
        ; fact we know the character being displayed is a space char
1015
        bsr             DisplayChar
1016
        subq    #1,d0
1017
        bne.s   .0001
1018
        clr.b   CursorCol                       ; now really go back to start of line
1019
        bra.s   dcx16                           ; we're done
1020
 
1021
;------------------------------------------------------------------------------
1022
; Increment the cursor position, scroll the screen if needed.
1023
;------------------------------------------------------------------------------
1024
 
1025
IncCursorPos:
1026
        addi.w  #1,TextCurpos
1027
        addi.b  #1,CursorCol
1028
        move.b  TextCols,d0
1029
        cmp.b           CursorCol,d0
1030
        bhs.s           icc1
1031
        clr.b           CursorCol
1032
IncCursorRow:
1033
        addi.b  #1,CursorRow
1034
        move.b  TextRows,d0
1035
        cmp.b           CursorRow,d0
1036
        bhi.s           icc1
1037
        move.b  TextRows,d0
1038
        move.b  d0,CursorRow            ; in case CursorRow is way over
1039
        subi.b  #1,CursorRow
1040
        ext.w           d0
1041
        asl.w           #1,d0
1042
        sub.w           d0,TextCurpos
1043
        bsr                     ScrollUp
1044
icc1:
1045
        rts
1046
 
1047
;------------------------------------------------------------------------------
1048
; Scroll screen up.
1049
;------------------------------------------------------------------------------
1050
 
1051
ScrollUp:
1052
        movem.l d0/d1/a0/a5,-(a7)               ; save off some regs
1053
        movec           coreno,d0
1054
        swap            d0
1055
        moveq           #SCREEN_SEMA,d1
1056
        bsr                     LockSemaphore
1057
        bsr                     get_screen_address
1058
        move.l  a0,a5                                                           ; a5 = pointer to text screen
1059
.0003:
1060
        move.b  TextCols,d0                                     ; d0 = columns
1061
        move.b  TextRows,d1                                     ; d1 = rows
1062
        ext.w           d0                                                                      ; make cols into a word value
1063
        ext.w           d1                                                                      ; make rows into a word value
1064
        asl.w           #3,d0                                                           ; make into cell index
1065
        lea                     0(a5,d0.w),a0                           ; a0 = pointer to second row of text screen
1066
        lsr.w           #3,d0                                                           ; get back d0
1067
        subq            #1,d1                                                           ; number of rows-1
1068
        mulu            d1,d0                                                           ; d0 = count of characters to move
1069
.0001:
1070
        move.l  (a0)+,(a5)+                                     ; each char is 64 bits
1071
        move.l  (a0)+,(a5)+
1072
        dbra            d0,.0001
1073
        movec           coreno,d0
1074
        swap            d0
1075
        moveq           #SCREEN_SEMA,d1
1076
        bsr                     UnlockSemaphore
1077
        movem.l (a7)+,d0/d1/a0/a5
1078
        ; Fall through into blanking out last line
1079
 
1080
;------------------------------------------------------------------------------
1081
; Blank out the last line on the screen.
1082
;------------------------------------------------------------------------------
1083
 
1084
BlankLastLine:
1085
        movem.l d0/d1/d2/a0,-(a7)
1086
        movec           coreno,d0
1087
        swap            d0
1088
        moveq           #SCREEN_SEMA,d1
1089
        bsr                     LockSemaphore
1090
        bsr                     get_screen_address
1091
        move.b  TextRows,d0                                     ; d0 = rows
1092
        move.b  TextCols,d1                                     ; d1 = columns
1093
        ext.w           d0
1094
        ext.w           d1
1095
        subq            #1,d0                                                           ; last row = #rows-1
1096
        mulu            d1,d0                                                           ; d0 = index of last line
1097
        lsl.w           #3,d0                                                           ; *8 bytes per char
1098
        lea                     (a0,d0.w),a0                            ; point a0 to last row
1099
        move.b  TextCols,d2                                     ; number of text cells to clear
1100
        ext.w           d2
1101
        subi.w  #1,d2                                                           ; count must be one less than desired
1102
        bsr                     get_screen_color                ; d0,d1 = screen color
1103
        move.w  #32,d1                                                  ; set the character for display in low 16 bits
1104
        bsr                     rbo                                                                     ; reverse the byte order
1105
        rol.w           #8,d0
1106
        swap            d0
1107
        rol.w           #8,d0
1108
.0001:
1109
        move.l  d0,(a0)+
1110
        move.l  d1,(a0)+
1111
        dbra            d2,.0001
1112
        movec           coreno,d0
1113
        swap            d0
1114
        moveq           #SCREEN_SEMA,d1
1115
        bsr                     UnlockSemaphore
1116
        movem.l (a7)+,d0/d1/d2/a0
1117
        rts
1118
 
1119
;------------------------------------------------------------------------------
1120
; Display a string on the screen.
1121
;------------------------------------------------------------------------------
1122
 
1123
DisplayString:
1124
        movem.l d0/d1/a1,-(a7)
1125
dspj1:
1126
        clr.l           d1                                              ; clear upper bits of d1
1127
        move.b  (a1)+,d1                        ; move string char into d1
1128
        beq.s           dsret                                   ; is it end of string ?
1129
        bsr                     DisplayChar             ; display character
1130
        bra.s           dspj1                                   ; go back for next character
1131
dsret:
1132
        movem.l (a7)+,d0/d1/a1
1133
        rts
1134
 
1135
;------------------------------------------------------------------------------
1136
; Display a string on the screen followed by carriage return / linefeed.
1137
;------------------------------------------------------------------------------
1138
 
1139
DisplayStringCRLF:
1140
        bsr             DisplayString
1141
        bra             CRLF
1142
 
1143
;------------------------------------------------------------------------------
1144
; Display a string on the screen limited to 255 chars max.
1145
;------------------------------------------------------------------------------
1146
 
1147
DisplayStringLimited:
1148
        movem.l d0/d1/d2/a1,-(a7)
1149
        move.w  d1,d2                                   ; d2 = max count
1150
        andi.w  #$00FF,d2                       ; limit to 255 chars
1151
        bra.s           .0003                                   ; enter loop at bottom
1152
.0001:
1153
        clr.l           d1                                              ; clear upper bits of d1
1154
        move.b  (a1)+,d1                        ; move string char into d1
1155
        beq.s           .0002                                   ; is it end of string ?
1156
        bsr                     DisplayChar             ; display character
1157
.0003:
1158
        dbra            d2,.0001                        ; go back for next character
1159
.0002:
1160
        movem.l (a7)+,d0/d1/d2/a1
1161
        rts
1162
 
1163
DisplayStringLimitedCRLF:
1164
        bsr             DisplayStringLimited
1165
        bra             CRLF
1166
 
1167
;------------------------------------------------------------------------------
1168
; Set cursor position to top left of screen.
1169
;
1170
; Parameters:
1171
;               
1172
; Returns:
1173
;               
1174
; Registers Affected:
1175
;               
1176
;------------------------------------------------------------------------------
1177
 
1178
HomeCursor:
1179
        clr.b           CursorRow
1180
        clr.b           CursorCol
1181
        clr.w           TextPos
1182
        ; fall through
1183
 
1184
;------------------------------------------------------------------------------
1185
; SyncCursor:
1186
;
1187
; Sync the hardware cursor's position to the text cursor position but only for
1188
; the core with the IO focus.
1189
;
1190
; Parameters:
1191
;               
1192
; Returns:
1193
;               
1194
; Registers Affected:
1195
;               
1196
;------------------------------------------------------------------------------
1197
 
1198
SyncCursor:
1199
        movem.l d0/d2,-(a7)
1200
        bsr                     UpdateTextPos
1201
        movec           coreno,d2
1202
        cmp.b           IOFocus,d2
1203
        bne.s           .0001
1204
        subi.w  #2,d2                                           ; factor in location of screen in controller
1205
        mulu            #2048,d2                                ; 2048 cells per screen
1206
        add.w           d2,d0
1207
        rol.w           #8,d0                                           ; swap byte order
1208
        move.w  d0,TEXTREG+$24
1209
.0001:
1210
        movem.l (a7)+,d0/d2
1211
        rts
1212
 
1213
;==============================================================================
1214
; TRAP #15 handler
1215
;
1216
; Parameters:
1217
;               d0.w = function number to perform
1218
;==============================================================================
1219
 
1220
TRAP15:
1221
        movem.l d0/a0,-(a7)
1222
        lea                     T15DispatchTable,a0
1223
        asl.l           #2,d0
1224
        move.l  (a0,d0.w),a0
1225
        jsr                     (a0)
1226
        movem.l (a7)+,d0/a0
1227
        rte
1228
 
1229
                align   2
1230
T15DispatchTable:
1231
        dc.l    DisplayStringLimitedCRLF
1232
        dc.l    DisplayStringLimited
1233
        dc.l    StubRout
1234
        dc.l    StubRout
1235
        dc.l    StubRout
1236
        dc.l    GetKey
1237
        dc.l    DisplayChar
1238
        dc.l    CheckForKey
1239
        dc.l    StubRout
1240
        dc.l    StubRout
1241
        ; 10
1242
        dc.l    StubRout
1243
        dc.l    Cursor1
1244
        dc.l    SetKeyboardEcho
1245
        dc.l    DisplayStringCRLF
1246
        dc.l    DisplayString
1247
        dc.l    StubRout
1248
        dc.l    StubRout
1249
        dc.l    StubRout
1250
        dc.l    StubRout
1251
        dc.l    StubRout
1252
        ; 20
1253
        dc.l    StubRout
1254
        dc.l    StubRout
1255
        dc.l    StubRout
1256
        dc.l    StubRout
1257
        dc.l    StubRout
1258
        dc.l    StubRout
1259
        dc.l    StubRout
1260
        dc.l    StubRout
1261
        dc.l    StubRout
1262
        dc.l    StubRout
1263
        ; 30
1264
        dc.l    StubRout
1265
        dc.l    StubRout
1266
        dc.l    rotate_iofocus
1267
        dc.l    SerialPeekCharDirect
1268
        dc.l    SerialPutChar
1269
        dc.l    SerialPeekChar
1270
        dc.l    SerialGetChar
1271
        dc.l    T15LockSemaphore
1272
        dc.l    T15UnlockSemaphore
1273
        dc.l    StubRout
1274
 
1275
;------------------------------------------------------------------------------
1276
; Cursor positioning / Clear screen
1277
; - out of range settings are ignored
1278
;
1279
; Parameters:
1280
;               d1.w cursor position, bits 0 to 7 are row, bits 8 to 15 are column.
1281
;       Returns:
1282
;               none
1283
;------------------------------------------------------------------------------
1284
 
1285
Cursor1:
1286
        move.l          d1,-(a7)
1287
        cmpi.w          #$FF00,d1
1288
        bne.s                   .0002
1289
        bsr                             clear_screen
1290
        bra                             HomeCursor
1291
.0002:
1292
        cmp.b                   TextRows,d1             ; if cursor pos out of range, ignore setting
1293
        bhs.s                   .0003
1294
        move.b          d1,CursorRow
1295
.0003:
1296
        ror.w                   #8,d1
1297
        cmp.b                   TextCols,d1
1298
        bhs.s                   .0001
1299
        move.b          d1,CursorCol
1300
.0001:
1301
        bsr                             SyncCursor              ; update hardware cursor
1302
        move.l          (a7)+,d1
1303
        rts
1304
 
1305
;------------------------------------------------------------------------------
1306
; Stub routine for unimplemented functionality.
1307
;------------------------------------------------------------------------------
1308
 
1309
StubRout:
1310
        rts
1311
 
1312
;------------------------------------------------------------------------------
1313
; Select a specific IO focus.
1314
;------------------------------------------------------------------------------
1315
 
1316
select_iofocus:
1317
        cmpi.b  #2,d1
1318
        blo.s           .0001
1319
        cmpi.b  #9,d1
1320
        bhi.s           .0001
1321
        move.l  d1,d0
1322
        bra.s           select_focus1
1323
.0001:
1324
        rts
1325
 
1326
;------------------------------------------------------------------------------
1327
; Rotate the IO focus, done when ALT-Tab is pressed.
1328
;
1329
; Modifies:
1330
;               d0, IOFocus BIOS variable
1331
;------------------------------------------------------------------------------
1332
 
1333
rotate_iofocus:
1334
        move.b  IOFocus,d0                              ; d0 = focus, we can trash d0
1335
        add.b           #1,d0                                                   ; increment the focus
1336
        cmp.b           #9,d0                                                   ; limit to 2 to 9
1337
        bls.s           .0001
1338
        move.b  #2,d0
1339
.0001:
1340
select_focus1:
1341
        move.b  d0,IOFocus                              ; set IO focus
1342
        subi.b  #2,d0                                                   ; screen is 0 to 7, focus is 2 to 9
1343
        ext.w           d0                                                              ; make into long value
1344
        mulu            #2048,d0                                        ; * 2048        cells per screen
1345
        rol.w           #8,d0                                                   ; swap byte order
1346
        move.w  d0,TEXTREG+$28          ; update screen address in text controller
1347
        bra                     SyncCursor                              ; set cursor position
1348
 
1349
;==============================================================================
1350
; PLIC - platform level interrupt controller
1351
;
1352
; Register layout:
1353
;   bits 0 to 7  = cause code to issue (vector number)
1354
;   bits 8 to 11 = irq level to issue
1355
;   bit 16 = irq enable
1356
;   bit 17 = edge sensitivity
1357
;   bit 18 = 0=vpa, 1=inta
1358
;               bit 24 to 29 target core
1359
;
1360
; Note byte order must be reversed for PLIC.
1361
;==============================================================================
1362
 
1363
init_plic:
1364
        lea             PLIC,a0                                         ; a0 points to PLIC
1365
        lea             $80+4*29(a0),a1         ; point to timer registers (29)
1366
        move.l  #$0006033F,(a1) ; initialize, core=63,edge sensitive,enabled,irq6,vpa
1367
        lea                     4(a1),a1                                ; point to keyboard registers (30)
1368
        move.l  #$3C060502,(a1) ; core=2,level sensitive,enabled,irq6,inta
1369
        lea                     4(a1),a1                                ; point to nmi button register (31)
1370
        move.l  #$00070302,(a1) ; initialize, core=2,edge sensitive,enabled,irq7,vpa
1371
        lea             $80+4*16(a0),a1         ; a1 points to ACIA register
1372
        move.l  #$3D030502,(a1) ; core=2,level sensitive,enabled,irq3,inta
1373
        lea             $80+4*4(a0),a1          ; a1 points to io_bitmap irq
1374
        move.l  #$3B060702,(a1) ; core=2,edge sensitive,enabled,irq6,inta
1375
        rts
1376
 
1377
;==============================================================================
1378
; Keyboard stuff
1379
;
1380
; KeyState2_
1381
; 876543210
1382
; ||||||||+ = shift
1383
; |||||||+- = alt
1384
; ||||||+-- = control
1385
; |||||+--- = numlock
1386
; ||||+---- = capslock
1387
; |||+----- = scrolllock
1388
; ||+------ =
1389
; |+------- =
1390
; +-------- = extended
1391
;
1392
;==============================================================================
1393
 
1394
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1395
; Get ID - get the keyboards identifier code.
1396
;
1397
; Parameters: none
1398
; Returns: d = $AB83, $00 on fail
1399
; Modifies: d, KeybdID updated
1400
; Stack Space: 2 words
1401
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1402
 
1403
KeybdGetID:
1404
        move.w  #$F2,d1
1405
        bsr                     KeybdSendByte
1406
        bsr                     KeybdWaitTx
1407
        bsr                     KeybdRecvByte
1408
        btst            #7,d1
1409
        bne                     kgnotKbd
1410
        cmpi.b  #$AB,d1
1411
        bne                     kgnotKbd
1412
        bsr                     KeybdRecvByte
1413
        btst            #7,d1
1414
        bne                     kgnotKbd
1415
        cmpi.b  #$83,d1
1416
        bne                     kgnotKbd
1417
        move.l  #$AB83,d1
1418
kgid1:
1419
        move.w  d1,KeybdID
1420
        rts
1421
kgnotKbd:
1422
        moveq           #0,d1
1423
        bra                     kgid1
1424
 
1425
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1426
; Set the LEDs on the keyboard.
1427
;
1428
; Parameters:
1429
;               d1.b = LED state
1430
;       Modifies:
1431
;               none
1432
; Returns:
1433
;               none
1434
; Stack Space:
1435
;               1 long word
1436
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1437
 
1438
KeybdSetLED:
1439
        move.l  d1,-(a7)
1440
        move.b  #$ED,d1
1441
        bsr                     KeybdSendByte
1442
        bsr                     KeybdWaitTx
1443
        bsr                     KeybdRecvByte
1444
        tst.b           d1
1445
        bmi                     .0001
1446
        cmpi.b  #$FA,d1
1447
        move.l  (a7),d1
1448
        bsr                     KeybdSendByte
1449
        bsr                     KeybdWaitTx
1450
        bsr                     KeybdRecvByte
1451
.0001:
1452
        move.l  (a7)+,d1
1453
        rts
1454
 
1455
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1456
; Initialize the keyboard.
1457
;
1458
; Parameters:
1459
;               none
1460
;       Modifies:
1461
;               none
1462
; Returns:
1463
;               none
1464
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1465
 
1466
_KeybdInit:
1467
KeybdInit:
1468
;       movem.l d0/d1/d3/a1,-(a7)
1469
        clr.b   _KeyState1              ; records key up/down state
1470
        clr.b   _KeyState2              ; records shift,ctrl,alt state
1471
        rts
1472
 
1473
        bsr                     Wait300ms
1474
        bsr                     _KeybdGetStatus ; wait for response from keyboard
1475
        tst.b           d1
1476
        bpl                     .0001                                   ; is input buffer full ? no, branch
1477
        bsr                     _KeybdGetScancode
1478
        cmpi.b  #$AA,d1                         ; keyboard Okay
1479
        beq                     kbdi0005
1480
.0001:
1481
        moveq           #10,d3
1482
kbdi0002:
1483
        bsr                     Wait10ms
1484
        clr.b           KEYBD+1                         ; clear receive register (write $00 to status reg)
1485
        moveq           #-1,d1                          ; send reset code to keyboard
1486
        move.b  d1,KEYBD+1              ; write $FF to status reg to clear TX state
1487
        bsr                     KeybdSendByte   ; now write ($FF) to transmit register for reset
1488
        bsr                     KeybdWaitTx             ; wait until no longer busy
1489
        tst.l           d1
1490
        bmi                     kbdiXmitBusy
1491
        bsr                     KeybdRecvByte   ; look for an ACK ($FA)
1492
        cmpi.b  #$FA,d1
1493
        bne                     .0001
1494
        bsr                     KeybdRecvByte   ; look for BAT completion code ($AA)
1495
.0001:
1496
        cmpi.b  #$FC,d1                         ; reset error ?
1497
        beq                     kbdiTryAgain
1498
        cmpi.b  #$AA,d1                         ; reset complete okay ?
1499
        bne                     kbdiTryAgain
1500
 
1501
        ; After a reset, scan code set #2 should be active
1502
.config:
1503
        move.w  #$F0,d1                 ; send scan code select
1504
        move.b  d1,leds
1505
        bsr                     KeybdSendByte
1506
        bsr                     KeybdWaitTx
1507
        tst.l           d1
1508
        bmi                     kbdiXmitBusy
1509
        bsr                     KeybdRecvByte   ; wait for response from keyboard
1510
        tst.w           d1
1511
        bmi                     kbdiTryAgain
1512
        cmpi.b  #$FA,d1                         ; ACK
1513
        beq                     kbdi0004
1514
kbdiTryAgain:
1515
        dbra            d3,kbdi0002
1516
.keybdErr:
1517
        lea                     msgBadKeybd,a1
1518
        bsr                     DisplayStringCRLF
1519
        bra                     ledxit
1520
kbdi0004:
1521
        moveq           #2,d1                   ; select scan code set #2
1522
        bsr                     KeybdSendByte
1523
        bsr                     KeybdWaitTx
1524
        tst.l           d1
1525
        bmi                     kbdiXmitBusy
1526
        bsr                     KeybdRecvByte   ; wait for response from keyboard
1527
        tst.w           d1
1528
        bmi                     kbdiTryAgain
1529
        cmpi.b  #$FA,d1
1530
        bne                     kbdiTryAgain
1531
kbdi0005:
1532
        bsr                     KeybdGetID
1533
ledxit:
1534
        moveq           #$07,d1
1535
        bsr                     KeybdSetLED
1536
        bsr                     Wait300ms
1537
        moveq           #$00,d1
1538
        bsr                     KeybdSetLED
1539
        movem.l (a7)+,d0/d1/d3/a1
1540
        rts
1541
kbdiXmitBusy:
1542
        lea                     msgXmitBusy,a1
1543
        bsr                     DisplayStringCRLF
1544
        movem.l (a7)+,d0/d1/d3/a1
1545
        rts
1546
 
1547
msgBadKeybd:
1548
        dc.b            "Keyboard error",0
1549
msgXmitBusy:
1550
        dc.b            "Keyboard transmitter stuck",0
1551
 
1552
        even
1553
_KeybdGetStatus:
1554
        moveq           #0,d1
1555
        move.b  KEYBD+1,d1
1556
        rts
1557
 
1558
; Get the scancode from the keyboard port
1559
 
1560
_KeybdGetScancode:
1561
        moveq           #0,d1
1562
        move.b  KEYBD,d1                                ; get the scan code
1563
        move.b  #0,KEYBD+1                      ; clear receive register
1564
        rts
1565
 
1566
; Recieve a byte from the keyboard, used after a command is sent to the
1567
; keyboard in order to wait for a response.
1568
;
1569
KeybdRecvByte:
1570
        move.l  d3,-(a7)
1571
        move.w  #100,d3         ; wait up to 1s
1572
.0003:
1573
        bsr                     _KeybdGetStatus ; wait for response from keyboard
1574
        tst.b           d1
1575
        bmi                     .0004                   ; is input buffer full ? yes, branch
1576
        bsr                     Wait10ms        ; wait a bit
1577
        dbra            d3,.0003        ; go back and try again
1578
        move.l  (a7)+,d3
1579
        moveq           #-1,d1          ; return -1
1580
        rts
1581
.0004:
1582
        bsr                     _KeybdGetScancode
1583
        move.l  (a7)+,d3
1584
        rts
1585
 
1586
 
1587
; Wait until the keyboard transmit is complete
1588
; Returns -1 if timedout, 0 if transmit completed
1589
;
1590
KeybdWaitTx:
1591
        movem.l d2/d3,-(a7)
1592
        moveq           #100,d3         ; wait a max of 1s
1593
.0001:
1594
        bsr                     _KeybdGetStatus
1595
        btst            #6,d1                           ; check for transmit complete bit
1596
        bne         .0002                               ; branch if bit set
1597
        bsr                     Wait10ms                ; delay a little bit
1598
        dbra            d3,.0001                ; go back and try again
1599
        movem.l (a7)+,d2/d3
1600
        moveq           #-1,d1                  ; return -1
1601
        rts
1602
.0002:
1603
        movem.l (a7)+,d2/d3
1604
        moveq   #0,d1           ; return 0
1605
        rts
1606
 
1607
;------------------------------------------------------------------------------
1608
; d1.b 0=echo off, non-zero = echo on
1609
;------------------------------------------------------------------------------
1610
 
1611
SetKeyboardEcho:
1612
        move.b  d1,KeybdEcho
1613
        rts
1614
 
1615
;------------------------------------------------------------------------------
1616
; Get key pending status into d1.b
1617
;
1618
; Returns:
1619
;               d1.b = 1 if a key is available, otherwise zero.
1620
;------------------------------------------------------------------------------
1621
 
1622
CheckForKey:
1623
        moveq.l #0,d1                                   ; clear high order bits
1624
;       move.b  KEYBD+1,d1              ; get keyboard port status
1625
;       smi.b           d1                                              ; set true/false
1626
;       andi.b  #1,d1                                   ; return true (1) if key available, 0 otherwise
1627
        tst.b           _KeybdCnt
1628
        sne.b           d1
1629
        rts
1630
 
1631
;------------------------------------------------------------------------------
1632
; GetKey
1633
;       Get a character from the keyboard.
1634
;
1635
; Modifies:
1636
;               d1
1637
; Returns:
1638
;               d1 = -1 if no key available or not in focus, otherwise key
1639
;------------------------------------------------------------------------------
1640
 
1641
GetKey:
1642
        move.l  d0,-(a7)                                        ; push d0
1643
        move.b  IOFocus,d1                              ; Check if the core has the IO focus
1644
        movec.l coreno,d0
1645
        cmp.b           d0,d1
1646
        bne.s           .0004                                                   ; go return no key available, if not in focus
1647
        bsr                     KeybdGetCharNoWait      ; get a character
1648
        tst.l           d1                                              ; was a key available?
1649
        bmi.s           .0004
1650
        tst.b           KeybdEcho                                       ; is keyboard echo on ?
1651
        beq.s           .0003                                                   ; no echo, just return the key
1652
        cmpi.b  #CR,d1                                          ; convert CR keystroke into CRLF
1653
        bne.s           .0005
1654
        bsr                     CRLF
1655
        bra.s           .0003
1656
.0005:
1657
        bsr                     DisplayChar
1658
.0003:
1659
        move.l  (a7)+,d0                                        ; pop d0
1660
        rts                                                                                             ; return key
1661
; Return -1 indicating no char was available
1662
.0004:
1663
        move.l  (a7)+,d0                                        ; pop d0
1664
        moveq           #-1,d1                                          ; return no key available
1665
        rts
1666
 
1667
CheckForCtrlC:
1668
        bsr                     KeybdGetCharNoWait
1669
        cmpi.b  #CTRLC,d1
1670
        beq                     Monitor
1671
        rts
1672
 
1673
;------------------------------------------------------------------------------
1674
;------------------------------------------------------------------------------
1675
 
1676
KeybdGetCharNoWait:
1677
        clr.b   KeybdWaitFlag
1678
        bra             KeybdGetChar
1679
 
1680
KeybdGetCharWait:
1681
        move.b  #-1,KeybdWaitFlag
1682
 
1683
KeybdGetChar:
1684
        movem.l d0/d2/d3/a0,-(a7)
1685
.0003:
1686
        movec           coreno,d0
1687
        swap            d0
1688
        moveq           #KEYBD_SEMA,d1
1689
        bsr                     LockSemaphore
1690
        move.b  _KeybdCnt,d2            ; get count of buffered scan codes
1691
        beq.s           .0015                                           ;
1692
        move.b  _KeybdHead,d2           ; d2 = buffer head
1693
        ext.w           d2
1694
        lea                     _KeybdBuf,a0            ; a0 = pointer to keyboard buffer
1695
        clr.l           d1
1696
        move.b  (a0,d2.w),d1            ; d1 = scan code from buffer
1697
        addi.b  #1,d2                                           ; increment keyboard head index
1698
        andi.b  #31,d2                                  ; and wrap around at buffer size
1699
        move.b  d2,_KeybdHead
1700
        subi.b  #1,_KeybdCnt            ; decrement count of scan codes in buffer
1701
        exg                     d1,d2                                           ; save scancode value in d2
1702
        movec           coreno,d0
1703
        swap            d0
1704
        moveq           #KEYBD_SEMA,d1
1705
        bsr                     UnlockSemaphore
1706
        exg                     d2,d1                                           ; restore scancode value
1707
        bra                     .0001                                           ; go process scan code
1708
.0014:
1709
        bsr             _KeybdGetStatus         ; check keyboard status for key available
1710
        bmi             .0006                                                   ; yes, go process
1711
.0015:
1712
        movec           coreno,d0
1713
        swap            d0
1714
        moveq           #KEYBD_SEMA,d1
1715
        bsr                     UnlockSemaphore
1716
        tst.b           KeybdWaitFlag                   ; are we willing to wait for a key ?
1717
        bmi                     .0003                                                   ; yes, branch back
1718
        movem.l (a7)+,d0/d2/d3/a0
1719
        moveq           #-1,d1                                          ; flag no char available
1720
        rts
1721
.0006:
1722
        bsr             _KeybdGetScancode
1723
.0001:
1724
        move.w  #1,leds
1725
        cmp.b   #SC_KEYUP,d1
1726
        beq             .doKeyup
1727
        cmp.b   #SC_EXTEND,d1
1728
        beq             .doExtend
1729
        cmp.b   #SC_CTRL,d1
1730
        beq             .doCtrl
1731
        cmp.b   #SC_LSHIFT,d1
1732
        beq             .doShift
1733
        cmp.b   #SC_RSHIFT,d1
1734
        beq             .doShift
1735
        cmp.b   #SC_NUMLOCK,d1
1736
        beq             .doNumLock
1737
        cmp.b   #SC_CAPSLOCK,d1
1738
        beq             .doCapsLock
1739
        cmp.b   #SC_SCROLLLOCK,d1
1740
        beq             .doScrollLock
1741
        cmp.b   #SC_ALT,d1
1742
        beq     .doAlt
1743
        move.b  _KeyState1,d2                   ; check key up/down
1744
        move.b  #0,_KeyState1                   ; clear keyup status
1745
        tst.b   d2
1746
        bne         .0003                                       ; ignore key up
1747
        cmp.b   #SC_TAB,d1
1748
        beq     .doTab
1749
.0013:
1750
        move.b  _KeyState2,d2
1751
        bpl             .0010                                   ; is it extended code ?
1752
        and.b   #$7F,d2                                 ; clear extended bit
1753
        move.b  d2,_KeyState2
1754
        move.b  #0,_KeyState1                   ; clear keyup
1755
        lea             _keybdExtendedCodes,a0
1756
        move.b  (a0,d1.w),d1
1757
        bra             .0008
1758
.0010:
1759
        btst    #2,d2                                   ; is it CTRL code ?
1760
        beq             .0009
1761
        and.w   #$7F,d1
1762
        lea             _keybdControlCodes,a0
1763
        move.b  (a0,d1.w),d1
1764
        bra             .0008
1765
.0009:
1766
        btst    #0,d2                                   ; is it shift down ?
1767
        beq     .0007
1768
        lea             _shiftedScanCodes,a0
1769
        move.b  (a0,d1.w),d1
1770
        bra             .0008
1771
.0007:
1772
        lea             _unshiftedScanCodes,a0
1773
        move.b  (a0,d1.w),d1
1774
        move.w  #$0202,leds
1775
.0008:
1776
        move.w  #$0303,leds
1777
        movem.l (a7)+,d0/d2/d3/a0
1778
        rts
1779
.doKeyup:
1780
        move.b  #-1,_KeyState1
1781
        bra             .0003
1782
.doExtend:
1783
        or.b    #$80,_KeyState2
1784
        bra             .0003
1785
.doCtrl:
1786
        move.b  _KeyState1,d1
1787
        clr.b   _KeyState1
1788
        tst.b   d1
1789
        bpl.s   .0004
1790
        bclr    #2,_KeyState2
1791
        bra             .0003
1792
.0004:
1793
        bset    #2,_KeyState2
1794
        bra             .0003
1795
.doAlt:
1796
        move.b  _KeyState1,d1
1797
        clr.b   _KeyState1
1798
        tst.b   d1
1799
        bpl             .0011
1800
        bclr    #1,_KeyState2
1801
        bra             .0003
1802
.0011:
1803
        bset    #1,_KeyState2
1804
        bra             .0003
1805
.doTab:
1806
        move.l  d1,-(a7)
1807
  move.b  _KeyState2,d1
1808
  btst  #1,d1                 ; is ALT down ?
1809
  beq     .0012
1810
;       inc     _iof_switch
1811
  move.l        (a7)+,d1
1812
  bra     .0003
1813
.0012:
1814
  move.l        (a7)+,d1
1815
  bra     .0013
1816
.doShift:
1817
        move.b  _KeyState1,d1
1818
        clr.b   _KeyState1
1819
        tst.b   d1
1820
        bpl.s   .0005
1821
        bclr    #0,_KeyState2
1822
        bra             .0003
1823
.0005:
1824
        bset    #0,_KeyState2
1825
        bra             .0003
1826
.doNumLock:
1827
        bchg    #4,_KeyState2
1828
        bsr             KeybdSetLEDStatus
1829
        bra             .0003
1830
.doCapsLock:
1831
        bchg    #5,_KeyState2
1832
        bsr             KeybdSetLEDStatus
1833
        bra             .0003
1834
.doScrollLock:
1835
        bchg    #6,_KeyState2
1836
        bsr             KeybdSetLEDStatus
1837
        bra             .0003
1838
 
1839
KeybdSetLEDStatus:
1840
        movem.l d2/d3,-(a7)
1841
        clr.b           KeybdLEDs
1842
        btst            #4,_KeyState2
1843
        beq.s           .0002
1844
        move.b  #2,KeybdLEDs
1845
.0002:
1846
        btst            #5,_KeyState2
1847
        beq.s           .0003
1848
        bset            #2,KeybdLEDs
1849
.0003:
1850
        btst            #6,_KeyState2
1851
        beq.s           .0004
1852
        bset            #0,KeybdLEDs
1853
.0004:
1854
        move.b  KeybdLEDs,d1
1855
        bsr                     KeybdSetLED
1856
        movem.l (a7)+,d2/d3
1857
        rts
1858
 
1859
KeybdSendByte:
1860
        move.b  d1,KEYBD
1861
        rts
1862
 
1863
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1864
; Wait for 10 ms
1865
;
1866
; Parameters: none
1867
; Returns: none
1868
; Modifies: none
1869
; Stack Space: 2 long words
1870
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1871
 
1872
Wait10ms:
1873
        movem.l d0/d1,-(a7)
1874
        movec           tick,d0
1875
        addi.l  #400000,d0                      ; 400,000 cycles at 40MHz
1876
.0001:
1877
        movec           tick,d1
1878
        cmp.l           d1,d0
1879
        bhi                     .0001
1880
        movem.l (a7)+,d0/d1
1881
        rts
1882
 
1883
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1884
; Wait for 300 ms
1885
;
1886
; Parameters: none
1887
; Returns: none
1888
; Modifies: none
1889
; Stack Space: 2 long words
1890
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1891
 
1892
Wait300ms:
1893
        movem.l d0/d1,-(a7)
1894
        movec           tick,d0
1895
        addi.l  #12000000,d0                    ; 12,000,000 cycles at 40MHz
1896
.0001:
1897
        movec           tick,d1
1898
        cmp.l           d1,d0
1899
        bhi                     .0001
1900
        movem.l (a7)+,d0/d1
1901
        rts
1902
 
1903
;--------------------------------------------------------------------------
1904
; Keyboard IRQ routine.
1905
;
1906
; Returns:
1907
;       d1 = -1 if keyboard routine handled interrupt, otherwise positive.
1908
;--------------------------------------------------------------------------
1909
 
1910
KeybdIRQ:
1911
        move.w  #$2600,sr                                       ; disable lower interrupts
1912
        movem.l d0/d1/a0,-(a7)
1913
        bsr                     _KeybdGetStatus         ; check if keyboard
1914
        tst.b           d1
1915
        bpl                     .0001                                                   ; branch if not keyboard
1916
        movec           coreno,d0
1917
        swap            d0
1918
        moveq           #KEYBD_SEMA,d1
1919
        bsr                     LockSemaphore
1920
        btst            #1,_KeyState2                   ; Is Alt down?
1921
        beq.s           .0003
1922
        move.b  KEYBD,d0                                        ; get scan code
1923
        cmpi.b  #SC_TAB,d0                              ; is Alt-Tab?
1924
        bne.s           .0003
1925
        bsr                     _KeybdGetScancode       ; grab the scan code (clears interrupt)
1926
        bsr                     rotate_iofocus
1927
        clr.b           _KeybdHead                              ; clear keyboard buffer
1928
        clr.b           _KeybdTail
1929
        clr.b           _KeybdCnt
1930
        bra                     .0002                                                   ; do not store Alt-Tab
1931
.0003:
1932
        ; Insert keyboard scan code into raw keyboard buffer
1933
        bsr                     _KeybdGetScancode       ; grab the scan code (clears interrupt)
1934
        cmpi.b  #32,_KeybdCnt                   ; see if keyboard buffer full
1935
        bhs.s           .0002
1936
        move.b  _KeybdTail,d0                   ; keyboard buffer not full, add to tail
1937
        ext.w           d0
1938
        lea                     _KeybdBuf,a0                    ; a0 = pointer to buffer
1939
        move.b  d1,(a0,d0.w)                    ; put scancode in buffer
1940
        addi.b  #1,d0                                                   ; increment tail index
1941
        andi.b  #31,d0                                          ; wrap at buffer limit
1942
        move.b  d0,_KeybdTail                   ; update tail index
1943
        addi.b  #1,_KeybdCnt                    ; increment buffer count
1944
.0002:
1945
        movec           coreno,d0
1946
        swap            d0
1947
        moveq           #KEYBD_SEMA,d1
1948
        bsr                     UnlockSemaphore
1949
.0001:
1950
        movem.l (a7)+,d0/d1/a0          ; return
1951
        rte
1952
 
1953
;--------------------------------------------------------------------------
1954
; PS2 scan codes to ascii conversion tables.
1955
;--------------------------------------------------------------------------
1956
;
1957
_unshiftedScanCodes:
1958
        dc.b    $2e,$a9,$2e,$a5,$a3,$a1,$a2,$ac
1959
        dc.b    $2e,$aa,$a8,$a6,$a4,$09,$60,$2e
1960
        dc.b    $2e,$2e,$2e,$2e,$2e,$71,$31,$2e
1961
        dc.b    $2e,$2e,$7a,$73,$61,$77,$32,$2e
1962
        dc.b    $2e,$63,$78,$64,$65,$34,$33,$2e
1963
        dc.b    $2e,$20,$76,$66,$74,$72,$35,$2e
1964
        dc.b    $2e,$6e,$62,$68,$67,$79,$36,$2e
1965
        dc.b    $2e,$2e,$6d,$6a,$75,$37,$38,$2e
1966
        dc.b    $2e,$2c,$6b,$69,$6f,$30,$39,$2e
1967
        dc.b    $2e,$2e,$2f,$6c,$3b,$70,$2d,$2e
1968
        dc.b    $2e,$2e,$27,$2e,$5b,$3d,$2e,$2e
1969
        dc.b    $ad,$2e,$0d,$5d,$2e,$5c,$2e,$2e
1970
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$08,$2e
1971
        dc.b    $2e,$95,$2e,$93,$94,$2e,$2e,$2e
1972
        dc.b    $98,$7f,$92,$2e,$91,$90,$1b,$af
1973
        dc.b    $ab,$2e,$97,$2e,$2e,$96,$ae,$2e
1974
 
1975
        dc.b    $2e,$2e,$2e,$a7,$2e,$2e,$2e,$2e
1976
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1977
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1978
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1979
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1980
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1981
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1982
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1983
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1984
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1985
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1986
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1987
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1988
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1989
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1990
        dc.b    $2e,$2e,$fa,$2e,$2e,$2e,$2e,$2e
1991
 
1992
_shiftedScanCodes:
1993
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
1994
        dc.b    $2e,$2e,$2e,$2e,$2e,$09,$7e,$2e
1995
        dc.b    $2e,$2e,$2e,$2e,$2e,$51,$21,$2e
1996
        dc.b    $2e,$2e,$5a,$53,$41,$57,$40,$2e
1997
        dc.b    $2e,$43,$58,$44,$45,$24,$23,$2e
1998
        dc.b    $2e,$20,$56,$46,$54,$52,$25,$2e
1999
        dc.b    $2e,$4e,$42,$48,$47,$59,$5e,$2e
2000
        dc.b    $2e,$2e,$4d,$4a,$55,$26,$2a,$2e
2001
        dc.b    $2e,$3c,$4b,$49,$4f,$29,$28,$2e
2002
        dc.b    $2e,$3e,$3f,$4c,$3a,$50,$5f,$2e
2003
        dc.b    $2e,$2e,$22,$2e,$7b,$2b,$2e,$2e
2004
        dc.b    $2e,$2e,$0d,$7d,$2e,$7c,$2e,$2e
2005
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$08,$2e
2006
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2007
        dc.b    $2e,$7f,$2e,$2e,$2e,$2e,$1b,$2e
2008
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2009
 
2010
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2011
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2012
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2013
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2014
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2015
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2016
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2017
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2018
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2019
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2020
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2021
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2022
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2023
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2024
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2025
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2026
 
2027
; control
2028
_keybdControlCodes:
2029
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2030
        dc.b    $2e,$2e,$2e,$2e,$2e,$09,$7e,$2e
2031
        dc.b    $2e,$2e,$2e,$2e,$2e,$11,$21,$2e
2032
        dc.b    $2e,$2e,$1a,$13,$01,$17,$40,$2e
2033
        dc.b    $2e,$03,$18,$04,$05,$24,$23,$2e
2034
        dc.b    $2e,$20,$16,$06,$14,$12,$25,$2e
2035
        dc.b    $2e,$0e,$02,$08,$07,$19,$5e,$2e
2036
        dc.b    $2e,$2e,$0d,$0a,$15,$26,$2a,$2e
2037
        dc.b    $2e,$3c,$0b,$09,$0f,$29,$28,$2e
2038
        dc.b    $2e,$3e,$3f,$0c,$3a,$10,$5f,$2e
2039
        dc.b    $2e,$2e,$22,$2e,$7b,$2b,$2e,$2e
2040
        dc.b    $2e,$2e,$0d,$7d,$2e,$7c,$2e,$2e
2041
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$08,$2e
2042
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2043
        dc.b    $2e,$7f,$2e,$2e,$2e,$2e,$1b,$2e
2044
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2045
 
2046
_keybdExtendedCodes:
2047
        dc.b    $2e,$2e,$2e,$2e,$a3,$a1,$a2,$2e
2048
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2049
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2050
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2051
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2052
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2053
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2054
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2055
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2056
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2057
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2058
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2059
        dc.b    $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
2060
        dc.b    $2e,$95,$2e,$93,$94,$2e,$2e,$2e
2061
        dc.b    $98,$99,$92,$2e,$91,$90,$2e,$2e
2062
        dc.b    $2e,$2e,$97,$2e,$2e,$96,$2e,$2e
2063
 
2064
;==============================================================================
2065
;==============================================================================
2066
; Monitor
2067
;==============================================================================
2068
;==============================================================================
2069
 
2070
cmdString:
2071
        dc.b    '?'+$80                                         ; ? display help
2072
        dc.b    'L'+$80                                         ; L load S19 file
2073
        dc.b    'F','B'+$80                             ; FB fill with byte
2074
        dc.b    'F','W'+$80                             ; FW fill with wyde
2075
        dc.b    'F','L'+$80                             ; FL fill with long wyde
2076
        dc.b    'B','A'+$80                             ; BA start Tiny Basic
2077
        dc.b    'B','R'+$80                             ; BR breakpoint
2078
        dc.b    'D','R'+$80                             ; DR dump registers
2079
        dc.b    'D'+$80                                         ; D dump memory
2080
        dc.b    'J'+$80                                         ; J jump to code
2081
        dc.b    ':'+$80                                         ; : edit memory
2082
        dc.b    "CL",'S'+$80                    ; CLS clear screen
2083
        dc.b    "COR",'E'+$80                   ; CORE  switch to core
2084
        dc.b  "TRA",'M'+$80                     ; TRAM test RAM
2085
        dc.b    'T','R'+$80                             ; TR test serial receive
2086
        dc.b    'T'+$80                                         ; T test CPU
2087
        dc.b    'S'+$80                                         ; S send serial
2088
        dc.b    "RESE",'T'+$80          ; RESET 
2089
        dc.b    "CLOC",'K'+$80          ; CLOCK 
2090
        dc.b    'R'+$80                                         ; R receive serial
2091
 
2092
        align   2
2093
cmdTable:
2094
        dc.w    cmdHelp
2095
        dc.w    cmdLoadS19
2096
        dc.w    cmdFillB
2097
        dc.w    cmdFillW
2098
        dc.w    cmdFillL
2099
        dc.w    cmdTinyBasic
2100
        dc.w    cmdBreakpoint
2101
        dc.w    cmdDumpRegs
2102
        dc.w    cmdDumpMemory
2103
        dc.w    cmdJump
2104
        dc.w    cmdEditMemory
2105
        dc.w    cmdClearScreen
2106
        dc.w    cmdCore
2107
        dc.w  cmdTestRAM
2108
        dc.w    cmdTestSerialReceive
2109
        dc.w    cmdTestCPU
2110
        dc.w    cmdSendSerial
2111
        dc.w    cmdReset
2112
        dc.w    cmdClock
2113
        dc.w    cmdReceiveSerial
2114
        dc.w    cmdMonitor
2115
 
2116
; Get a word from screen memory and swap byte order
2117
 
2118
FromScreen:
2119
        move.l  (a0),d1
2120
        bsr                     rbo
2121
        lea                     8(a0),a0        ; increment screen pointer
2122
        rts
2123
 
2124
StartMon:
2125
        clr.w           NumSetBreakpoints
2126
        bsr                     ClearBreakpointList
2127
cmdMonitor:
2128
Monitor:
2129
        ; Reset the stack pointer on each entry into the monitor
2130
        move.l  #$40FFC,sp      ; reset core's stack
2131
        move.w  #$2200,sr               ; enable level 2 and higher interrupts
2132
        movec           coreno,d0
2133
        swap            d0
2134
        moveq           #1,d1
2135
        bsr                     UnlockSemaphore
2136
        clr.b           KeybdEcho               ; turn off keyboard echo
2137
PromptLn:
2138
        bsr                     CRLF
2139
        move.b  #'$',d1
2140
        bsr                     DisplayChar
2141
 
2142
; Get characters until a CR is keyed
2143
;
2144
Prompt3:
2145
        bsr                     GetKey
2146
        cmpi.b  #-1,d1
2147
        beq.s           Prompt3
2148
        cmpi.b  #CR,d1
2149
        beq.s           Prompt1
2150
        bsr                     DisplayChar
2151
        bra.s           Prompt3
2152
 
2153
; Process the screen line that the CR was keyed on
2154
 
2155
Prompt1:
2156
        clr.b           CursorCol                       ; go back to the start of the line
2157
        bsr                     CalcScreenLoc   ; a0 = screen memory location
2158
.0001:
2159
        bsr                     FromScreen              ; grab character off screen
2160
        cmpi.b  #'$',d1                         ; skip over '$' prompt character
2161
        beq.s           .0001
2162
 
2163
; Dispatch based on command string
2164
 
2165
cmdDispatch:
2166
        lea                     cmdString,a2
2167
        clr.l           d4                                              ; command counter
2168
        lea                     -8(a0),a0                       ; backup a character
2169
        move.l  a0,a3                                   ; a3 = start of command on screen
2170
.checkNextCmd:
2171
        bsr                     FromScreen              ; d1 = char from input screen
2172
        move.b  (a2)+,d5
2173
        eor.b           d5,d1                                   ; does it match with command string?
2174
        beq.s           .checkNextCmd   ; If it does, keep matching for longest match
2175
        cmpi.b  #$80,d1                         ; didn't match, was it the end of the command?
2176
        beq.s           .foundCmd
2177
        tst.b           -1(a2)                          ; was end of table hit?
2178
        beq.s           .endOfTable
2179
        addi.w  #2,d4                                   ; increment command counter
2180
        move.l  a3,a0                                   ; reset input pointer
2181
        tst.b           -1(a2)                          ; were we at the end of the command?
2182
        bmi.s           .checkNextCmd   ; if were at end continue, otherwise scan for enf of cmd
2183
.scanToEndOfCmd
2184
        tst.b           (a2)+                                   ; scan to end of command
2185
        beq.s           .endOfTable
2186
        bpl.s           .scanToEndOfCmd
2187
        bmi.s           .checkNextCmd
2188
.endOfTable
2189
        lea                     msgUnknownCmd,a1
2190
        bsr                     DisplayStringCRLF
2191
        bra                     Monitor
2192
.foundCmd:
2193
        lea                     cmdTable,a1             ; a1 = pointer to command address table
2194
        move.w  (a1,d4.w),a1    ; fetch command routine address from table
2195
        jmp                     (a1)                                    ; go execute command
2196
 
2197
cmdBreakpoint:
2198
        bsr                     ignBlanks
2199
        bsr                     FromScreen
2200
        cmpi.b  #'+',d1
2201
        beq                     ArmBreakpoint
2202
        cmpi.b  #'-',d1
2203
        beq                     DisarmBreakpoint
2204
        cmpi.b  #'L',d1
2205
        beq                     ListBreakpoints
2206
        bra                     Monitor
2207
 
2208
cmdTinyBasic:
2209
        bra                     CSTART
2210
 
2211
cmdTestCPU:
2212
        bsr                     cpu_test
2213
        lea                     msg_test_done,a1
2214
        bsr                     DisplayStringCRLF
2215
        bra                     Monitor
2216
 
2217
cmdClearScreen:
2218
        bsr                     ClearScreen
2219
        bsr                     HomeCursor
2220
        bra                     Monitor
2221
 
2222
cmdCore:
2223
        bsr                     ignBlanks
2224
        bsr                     FromScreen
2225
        cmpi.b  #'2',d1                                 ; check range
2226
        blo                     Monitor
2227
        cmpi.b  #'9',d1
2228
        bhi                     Monitor
2229
        subi.b  #'0',d1                                 ; convert ascii to binary
2230
        bsr                     select_iofocus
2231
        bra                     Monitor
2232
 
2233
;-------------------------------------------------------------------------------
2234
; CLOCK 
2235
;    Set the clock register to n which will turn off or on clocks to the CPUs.
2236
;-------------------------------------------------------------------------------
2237
 
2238
cmdClock:
2239
        bsr                     ignBlanks
2240
        bsr                     GetHexNumber
2241
        tst.b           d0                                                      ; was there a number?
2242
        beq                     Monitor
2243
        ori.w           #4,d0                                           ; primary core's clock cannot be turned off
2244
        rol.w           #8,d1                                           ; switch byte order
2245
        move.w  d1,RST_REG+2
2246
        bra                     Monitor
2247
 
2248
;-------------------------------------------------------------------------------
2249
; RESET 
2250
;    Reset the specified core. Resetting the core automatically turns on the
2251
; core's clock.
2252
;-------------------------------------------------------------------------------
2253
 
2254
cmdReset:
2255
        bsr                     ignBlanks
2256
        bsr                     FromScreen
2257
        cmpi.b  #'2',d1                                 ; check range
2258
        blo                     Monitor
2259
        cmpi.b  #'9',d1
2260
        bhi                     Monitor
2261
        subi.b  #'0',d1                                 ; convert ascii to binary
2262
        lsl.w           #1,d1                                           ; make into index
2263
        lea                     tblPow2,a1
2264
        move.w  (a1,d1.w),d1
2265
        rol.w           #8,d1                                           ; reverse byte order
2266
        move.w  d1,RST_REG
2267
        bra                     Monitor
2268
 
2269
tblPow2:
2270
        dc.w            1
2271
        dc.w            2
2272
        dc.w            4
2273
        dc.w            8
2274
        dc.w            16
2275
        dc.w            32
2276
        dc.w            64
2277
        dc.w            128
2278
        dc.w            256
2279
        dc.w            512
2280
        dc.w            1024
2281
        dc.w            2048
2282
        dc.w            4096
2283
        dc.w            8192
2284
        dc.w            16384
2285
        dc.w            32768
2286
        even
2287
 
2288
cmdHelp:
2289
DisplayHelp:
2290
        lea                     HelpMsg,a1
2291
        bsr                     DisplayString
2292
        bra                     Monitor
2293
 
2294
HelpMsg:
2295
        dc.b    "? = Display help",LF,CR
2296
        dc.b  "CORE n = switch to core n, n = 2 to 7",LF,CR
2297
        dc.b  "RESET n = reset core n",LF,CR
2298
        dc.b    "CLS = clear screen",LF,CR
2299
        dc.b    ": = Edit memory bytes",LF,CR
2300
        dc.b    "FB = Fill memory bytes, FW, FL",LF,CR
2301
        dc.b    "L = Load S19 file",LF,CR
2302
        dc.b    "D = Dump memory, DR = dump registers",LF,CR
2303
        dc.b    "BA = start tiny basic",LF,CR
2304
        dc.b  "BR = set breakpoint",LF,CR
2305
        dc.b    "J = Jump to code",LF,CR
2306
        dc.b  "S = send to serial port",LF,CR
2307
        dc.b    "T = cpu test program",LF,CR
2308
        dc.b    "TRAM = test RAM",LF,CR,0
2309
 
2310
msgUnknownCmd:
2311
        dc.b    "command unknown",0
2312
 
2313
msgHello:
2314
        dc.b    LF,CR,"Hello World!",LF,CR,0
2315
        even
2316
 
2317
;------------------------------------------------------------------------------
2318
; This routine borrowed from Gordo's Tiny Basic interpreter.
2319
; Used to fetch a command line. (Not currently used).
2320
;
2321
; d0.b  - command prompt
2322
;------------------------------------------------------------------------------
2323
 
2324
GetCmdLine:
2325
                bsr             DisplayChar             ; display prompt
2326
                move.b  #' ',d0
2327
                bsr             DisplayChar
2328
                lea             CmdBuf,a0
2329
.0001:
2330
                bsr             GetKey
2331
                cmp.b   #CTRLH,d0
2332
                beq.s   .0003
2333
                cmp.b   #CTRLX,d0
2334
                beq.s   .0004
2335
                cmp.b   #CR,d0
2336
                beq.s   .0002
2337
                cmp.b   #' ',d0
2338
                bcs.s   .0001
2339
.0002:
2340
                move.b  d0,(a0)
2341
                lea                     8(a0),a0
2342
                bsr             DisplayChar
2343
                cmp.b   #CR,d0
2344
                beq             .0007
2345
                cmp.l   #CmdBufEnd-1,a0
2346
                bcs.s   .0001
2347
.0003:
2348
                move.b  #CTRLH,d0
2349
                bsr             DisplayChar
2350
                move.b  #' ',d0
2351
                bsr             DisplayChar
2352
                cmp.l   #CmdBuf,a0
2353
                bls.s   .0001
2354
                move.b  #CTRLH,d0
2355
                bsr             DisplayChar
2356
                subq.l  #1,a0
2357
                bra.s   .0001
2358
.0004:
2359
                move.l  a0,d1
2360
                sub.l   #CmdBuf,d1
2361
                beq.s   .0006
2362
                subq    #1,d1
2363
.0005:
2364
                move.b  #CTRLH,d0
2365
                bsr             DisplayChar
2366
                move.b  #' ',d0
2367
                bsr             DisplayChar
2368
                move.b  #CTRLH,d0
2369
                bsr             DisplayChar
2370
                dbra    d1,.0005
2371
.0006:
2372
                lea             CmdBuf,a0
2373
                bra             .0001
2374
.0007:
2375
                move.b  #LF,d0
2376
                bsr             DisplayChar
2377
                rts
2378
 
2379
;------------------------------------------------------------------------------
2380
; S 
2381
; Send data buffer to serial port
2382
; S 40000 40
2383
;------------------------------------------------------------------------------
2384
 
2385
cmdSendSerial:
2386
        bsr                     ignBlanks
2387
        bsr                     GetHexNumber
2388
        beq                     Monitor
2389
        move.l  d1,d6                                   ; d6 points to buffer
2390
        bsr                     ignBlanks
2391
        bsr                     GetHexNumber
2392
        bne.s           .0003
2393
        moveq           #16,d1
2394
.0003:
2395
        move.l  d6,a1                                   ; a1 points to buffer
2396
        move.l  d1,d2                                   ; d2 = count of bytes to send
2397
        bra.s           .0002                                   ; enter loop at bottom
2398
.0001:
2399
        move.b  (a1)+,d1
2400
        move.w  #34,d0                          ; serial putchar
2401
        trap            #15
2402
.0002:
2403
        dbra            d2,.0001
2404
        bra                     Monitor
2405
 
2406
;------------------------------------------------------------------------------
2407
; R 
2408
; Send data buffer to serial port
2409
; R 10000 40
2410
;------------------------------------------------------------------------------
2411
 
2412
cmdReceiveSerial:
2413
        bsr                     ignBlanks
2414
        bsr                     GetHexNumber
2415
        beq                     Monitor
2416
        move.l  d1,d6                                   ; d6 points to buffer
2417
        bsr                     ignBlanks
2418
        bsr                     GetHexNumber
2419
        bne.s           .0003
2420
        moveq           #16,d1
2421
.0003:
2422
        move.l  d6,a1                                   ; a1 points to buffer
2423
        move.l  d1,d2                                   ; d2 = count of bytes to send
2424
        bra.s           .0002                                   ; enter loop at bottom
2425
.0001:
2426
        move.w  #36,d0                          ; serial peek char
2427
        trap            #15
2428
        tst.l           d1
2429
        bmi.s           .0001
2430
        move.b  d1,(a1)+
2431
.0002:
2432
        dbra            d2,.0001
2433
        bra                     Monitor
2434
 
2435
;------------------------------------------------------------------------------
2436
; Fill memory
2437
;
2438
; FB = fill bytes               FB 00000010 100 FF      ; fill starting at 10 for 256 bytes
2439
; FW = fill words
2440
; FL = fill longs
2441
; F = fill bytes
2442
;------------------------------------------------------------------------------
2443
 
2444
cmdFillB:
2445
        bsr                     ignBlanks
2446
        bsr                     GetHexNumber
2447
        move.l  d1,a1                                   ; a1 = start
2448
        bsr                     ignBlanks
2449
        bsr                     GetHexNumber
2450
        move.l  d1,d3                                   ; d3 = count
2451
        beq                     Monitor
2452
        bsr                     ignBlanks
2453
        bsr                     GetHexNumber    ; fill value
2454
.fmem:
2455
        move.b  d1,(a1)+
2456
        sub.l           #1,d3
2457
        bne.s           .fmem
2458
        bra                     Monitor
2459
 
2460
cmdFillW:
2461
        bsr                     ignBlanks
2462
        bsr                     GetHexNumber
2463
        move.l  d1,a1                                   ; a1 = start
2464
        bsr                     ignBlanks
2465
        bsr                     GetHexNumber
2466
        move.l  d1,d3                                   ; d3 = count
2467
        beq                     Monitor
2468
        bsr                     ignBlanks
2469
        bsr                     GetHexNumber    ; fill value
2470
.fmem:
2471
        move.w  d1,(a1)+
2472
        sub.l           #1,d3
2473
        bne.s           .fmem
2474
        bra                     Monitor
2475
 
2476
cmdFillL:
2477
        bsr                     ignBlanks
2478
        bsr                     GetHexNumber
2479
        move.l  d1,a1                                   ; a1 = start
2480
        bsr                     ignBlanks
2481
        bsr                     GetHexNumber
2482
        move.l  d1,d3                                   ; d3 = count
2483
        beq                     Monitor
2484
        bsr                     ignBlanks
2485
        bsr                     GetHexNumber    ; fill value
2486
.fmem:
2487
        move.l  d1,(a1)+
2488
        sub.l           #1,d3
2489
        bne.s           .fmem
2490
        bra                     Monitor
2491
 
2492
;------------------------------------------------------------------------------
2493
; Modifies:
2494
;       a0      - text pointer
2495
;------------------------------------------------------------------------------
2496
 
2497
ignBlanks:
2498
        move.l  d1,-(a7)
2499
.0001:
2500
        bsr                     FromScreen
2501
        cmpi.b  #' ',d1
2502
        beq.s           .0001
2503
        lea                     -8(a0),a0
2504
        move.l  (a7)+,d1
2505
        rts
2506
 
2507
;------------------------------------------------------------------------------
2508
; Edit memory byte.
2509
;    Bytes are built into long words in case the memory is only longword
2510
; accessible.
2511
;------------------------------------------------------------------------------
2512
 
2513
cmdEditMemory:
2514
        bsr                     ignBlanks
2515
        bsr                     GetHexNumber
2516
        move.l  d1,a1
2517
edtmem1:
2518
        clr.l           d2
2519
        bsr                     ignBlanks
2520
        bsr                     GetHexNumber
2521
        move.b  d1,d2
2522
;       move.b  d1,(a1)+
2523
        bsr                     ignBlanks
2524
        bsr                     GetHexNumber
2525
        lsl.l           #8,d2
2526
        move.b  d1,d2
2527
;       move.b  d1,(a1)+
2528
        bsr                     ignBlanks
2529
        bsr                     GetHexNumber
2530
        lsl.l           #8,d2
2531
        move.b  d1,d2
2532
;       move.b  d1,(a1)+
2533
        bsr                     ignBlanks
2534
        bsr                     GetHexNumber
2535
        lsl.l           #8,d2
2536
        move.b  d1,d2
2537
        move.l  d2,(a1)+
2538
;       move.b  d1,(a1)+
2539
        clr.l           d2
2540
        bsr                     ignBlanks
2541
        bsr                     GetHexNumber
2542
        move.b  d1,d2
2543
;       move.b  d1,(a1)+
2544
        bsr                     ignBlanks
2545
        bsr                     GetHexNumber
2546
        lsl.l           #8,d2
2547
        move.b  d1,d2
2548
;       move.b  d1,(a1)+
2549
        bsr                     ignBlanks
2550
        bsr                     GetHexNumber
2551
        lsl.l           #8,d2
2552
        move.b  d1,d2
2553
;       move.b  d1,(a1)+
2554
        bsr                     ignBlanks
2555
        bsr                     GetHexNumber
2556
        lsl.l           #8,d2
2557
        move.b  d1,d2
2558
;       move.b  d1,(a1)+
2559
        move.l  d2,(a1)+
2560
        bra                     Monitor
2561
 
2562
;------------------------------------------------------------------------------
2563
; Execute code at the specified address.
2564
;------------------------------------------------------------------------------
2565
 
2566
cmdJump:
2567
ExecuteCode:
2568
        bsr                     ignBlanks
2569
        bsr                     GetHexNumber
2570
        move.l  d1,a0
2571
        jsr                     (a0)
2572
        bra     Monitor
2573
 
2574
;------------------------------------------------------------------------------
2575
; Do a memory dump of the requested location.
2576
; D 0800 0850
2577
;------------------------------------------------------------------------------
2578
 
2579
cmdDumpMemory:
2580
        bsr                     ignBlanks
2581
        bsr                     GetHexNumber
2582
        beq                     Monitor                 ; was there a number ? no, other garbage, just ignore
2583
        move.l  d1,d3                           ; save off start of range
2584
        bsr                     ignBlanks
2585
        bsr                     GetHexNumber
2586
        bne.s           DumpMem1
2587
        move.l  d3,d1
2588
        addi.l  #64,d1                  ; no end specified, just dump 64 bytes
2589
DumpMem1:
2590
        move.l  d3,a0
2591
        move.l  d1,a1
2592
        bsr                     CRLF
2593
.0001:
2594
        cmpa.l  a0,a1
2595
        bls                     Monitor
2596
        bsr                     DisplayMem
2597
        bra.s           .0001
2598
 
2599
;------------------------------------------------------------------------------
2600
; Display memory dump in a format suitable for edit.
2601
;
2602
;       :12345678 00 11 22 33 44 55 66 77  "........"
2603
;
2604
; Modifies:
2605
;               d1,d2,a0
2606
;------------------------------------------------------------------------------
2607
 
2608
DisplayMem:
2609
        move.b  #':',d1
2610
        bsr                     DisplayChar
2611
        move.l  a0,d1
2612
        bsr                     DisplayTetra
2613
        moveq           #7,d2
2614
dspmem1:
2615
        move.b  #' ',d1
2616
        bsr                     DisplayChar
2617
        move.b  (a0)+,d1
2618
        bsr                     DisplayByte
2619
        dbra            d2,dspmem1
2620
        bsr                     DisplayTwoSpaces
2621
        move.b  #34,d1
2622
        bsr                     DisplayChar
2623
        lea                     -8(a0),a0
2624
        moveq           #7,d2
2625
.0002:
2626
        move.b  (a0)+,d1
2627
        cmp.b           #' ',d1
2628
        blo.s           .0003
2629
        cmp.b           #127,d1
2630
        bls.s           .0001
2631
.0003:
2632
        move.b  #'.',d1
2633
.0001:
2634
        bsr                     DisplayChar
2635
        dbra            d2,.0002
2636
        move.b  #34,d1
2637
        bsr                     DisplayChar
2638
        bsr                     CheckForCtrlC
2639
        bra                     CRLF
2640
 
2641
;------------------------------------------------------------------------------
2642
; Dump Registers
2643
;    The dump is in a format that allows the register value to be edited.
2644
;
2645
; RegD0 12345678
2646
; RegD1 77777777
2647
;       ... etc
2648
;------------------------------------------------------------------------------
2649
 
2650
cmdDumpRegs:
2651
        bsr                     CRLF
2652
        move.w  #15,d0                                  ; number of registers-1
2653
        lea                     msg_reglist,a0  ;
2654
        lea                     msg_regs,a1
2655
        lea                     Regsave,a2                      ; a2 points to register save area
2656
.0001:
2657
        bsr                     DisplayString
2658
        move.b  (a0)+,d1
2659
        bsr                     DisplayChar
2660
        move.b  (a0)+,d1
2661
        bsr                     DisplayChar
2662
        bsr                     DisplaySpace
2663
        move.l  (a2)+,d1
2664
        bsr                     DisplayTetra
2665
        bsr                     CRLF
2666
        dbra            d0,.0001
2667
        bsr                     DisplayString
2668
        move.b  (a0)+,d1
2669
        bsr                     DisplayChar
2670
        move.b  (a0)+,d1
2671
        bsr                     DisplayChar
2672
        bsr                     DisplaySpace
2673
        move.l  Regsave+$44,d1
2674
        bsr                     DisplayTetra
2675
        bsr                     CRLF
2676
        bsr                     DisplayString
2677
        move.b  (a0)+,d1
2678
        bsr                     DisplayChar
2679
        move.b  (a0)+,d1
2680
        bsr                     DisplayChar
2681
        bsr                     DisplaySpace
2682
        move.w  Regsave+$40,d1
2683
        bsr                     DisplayWyde
2684
        bsr                     CRLF
2685
        bra                     Monitor
2686
 
2687
msg_regs:
2688
        dc.b    "Reg",0
2689
msg_reglist:
2690
        dc.b    "D0D1D2D3D4D5D6D7A0A1A2A3A4A5A6A7PCSR",0
2691
 
2692
        align   1
2693
 
2694
;------------------------------------------------------------------------------
2695
;------------------------------------------------------------------------------
2696
 
2697
cmdTestSerialReceive:
2698
.0002:
2699
        moveq           #36,d0                          ; serial get char from buffer
2700
        trap            #15
2701
;       bsr                     SerialPeekCharDirect
2702
        tst.w           d1
2703
        bmi.s           .0001
2704
        cmpi.b  #CTRLZ,d1
2705
        beq                     .0003
2706
        bsr                     DisplayChar
2707
.0001:
2708
        bsr                     CheckForCtrlC
2709
        bra                     .0002
2710
.0003:
2711
        bsr                     _KeybdInit
2712
        bra                     Monitor
2713
 
2714
;------------------------------------------------------------------------------
2715
; Get a hexidecimal number. Maximum of eight digits.
2716
;
2717
; Returns:
2718
;               d0 = number of digits
2719
;               d1 = value of number
2720
;               zf = number of digits == 0
2721
;------------------------------------------------------------------------------
2722
 
2723
GetHexNumber:
2724
        move.l  d2,-(a7)
2725
        clr.l           d2
2726
        moveq           #0,d0
2727
.0002:
2728
        bsr                     FromScreen
2729
        bsr                     AsciiToHexNybble
2730
        cmp.b           #$ff,d1
2731
        beq.s           .0001
2732
        lsl.l           #4,d2
2733
        andi.l  #$0f,d1
2734
        or.l            d1,d2
2735
        addq            #1,d0
2736
        cmpi.b  #8,d0
2737
        blo.s           .0002
2738
.0001:
2739
        move.l  d2,d1
2740
        move.l  (a7)+,d2
2741
        tst.b           d0
2742
        rts
2743
 
2744
;------------------------------------------------------------------------------
2745
; Convert ASCII character in the range '0' to '9', 'a' tr 'f' or 'A' to 'F'
2746
; to a hex nybble.
2747
;------------------------------------------------------------------------------
2748
 
2749
AsciiToHexNybble:
2750
        cmpi.b  #'0',d1
2751
        blo.s           gthx3
2752
        cmpi.b  #'9',d1
2753
        bhi.s           gthx5
2754
        subi.b  #'0',d1
2755
        rts
2756
gthx5:
2757
        cmpi.b  #'A',d1
2758
        blo.s           gthx3
2759
        cmpi.b  #'F',d1
2760
        bhi.s           gthx6
2761
        addi.b  #10-'A',d1
2762
        rts
2763
gthx6:
2764
        cmpi.b  #'a',d1
2765
        blo.s           gthx3
2766
        cmpi.b  #'f',d1
2767
        bhi.s           gthx3
2768
        addi.b  #10-'a',d1
2769
        rts
2770
gthx3:
2771
        moveq   #-1,d1          ; not a hex number
2772
        rts
2773
 
2774
;------------------------------------------------------------------------------
2775
;------------------------------------------------------------------------------
2776
 
2777
DisplayTwoSpaces:
2778
        move.l  d1,-(a7)
2779
        move.b  #' ',d1
2780
        bsr                     DisplayChar
2781
dspspc1:
2782
        bsr                     DisplayChar
2783
        move.l  (a7)+,d1
2784
        rts
2785
 
2786
DisplaySpace:
2787
        move.l  d1,-(a7)
2788
        move.b  #' ',d1
2789
        bra                     dspspc1
2790
 
2791
;------------------------------------------------------------------------------
2792
; Display the 32 bit word in D1.L
2793
;------------------------------------------------------------------------------
2794
 
2795
DisplayTetra:
2796
        swap    d1
2797
        bsr             DisplayWyde
2798
        swap    d1
2799
 
2800
;------------------------------------------------------------------------------
2801
; Display the byte in D1.W
2802
;------------------------------------------------------------------------------
2803
 
2804
DisplayWyde:
2805
        ror.w           #8,d1
2806
        bsr                     DisplayByte
2807
        rol.w           #8,d1
2808
 
2809
;------------------------------------------------------------------------------
2810
; Display the byte in D1.B
2811
;------------------------------------------------------------------------------
2812
 
2813
DisplayByte:
2814
        ror.b           #4,d1
2815
        bsr                     DisplayNybble
2816
        rol.b           #4,d1
2817
 
2818
;------------------------------------------------------------------------------
2819
; Display nybble in D1.B
2820
;------------------------------------------------------------------------------
2821
 
2822
DisplayNybble:
2823
        move.l  d1,-(a7)
2824
        andi.b  #$F,d1
2825
        addi.b  #'0',d1
2826
        cmpi.b  #'9',d1
2827
        bls.s           .0001
2828
        addi.b  #7,d1
2829
.0001:
2830
        bsr                     DisplayChar
2831
        move.l  (a7)+,d1
2832
        rts
2833
 
2834
;------------------------------------------------------------------------------
2835
;------------------------------------------------------------------------------
2836
;
2837
;DisplayHexNumber:
2838
;       move.w  #$A6A6,leds             ; diagnostics
2839
;       move.l  #VDGREG,a6
2840
;       move.w  #7,d2           ; number-1 of digits to display
2841
;disphnum1:
2842
;       move.b  d1,d0           ; get digit into d0.b
2843
;       andi.w  #$0f,d0
2844
;       cmpi.w  #$09,d0
2845
;       bls.s   disphnum2
2846
;       addi.w  #7,d0
2847
;disphnum2:
2848
;       addi.w  #$30,d0 ; convert to display char
2849
;       move.w  d2,d3           ; char count into d3
2850
;       asl.w   #3,d3           ; scale * 8
2851
;disphnum3:
2852
;       move.w  $42C(a6),d4                     ; read character queue index into d4
2853
;       cmp.w   #28,d4                                  ; allow up 28 entries to be in progress
2854
;       bhs.s   disphnum3                               ; branch if too many chars queued
2855
;       ext.w   d0                                              ; zero out high order bits
2856
;       move.w  d0,$420(a6)                     ; set char code
2857
;       move.w  #WHITE,$422(a6)         ; set fg color
2858
;       move.w  #DARK_BLUE,$424(a6)     ; set bk color
2859
;       move.w  d3,$426(a6)                     ; set x pos
2860
;       move.w  #8,$428(a6)                     ; set y pos
2861
;       move.w  #$0707,$42A(a6)         ; set font x,y extent
2862
;       move.w  #0,$42E(a6)                     ; pulse character queue write signal
2863
;       ror.l   #4,d1                                   ; rot to next digit
2864
;       dbeq    d2,disphnum1
2865
;       jmp             (a5)
2866
 
2867
;===============================================================================
2868
;    Perform ram test. (Uses checkerboard testing).
2869
;
2870
;    Local ram, which does not get tested, is used for the stack.
2871
;===============================================================================
2872
 
2873
DisplayAddr:
2874
        move.l a0,d1
2875
        lsr.l #8,d1
2876
        lsr.l #8,d1
2877
        lsr.l #4,d1
2878
        subi.w #512,d1
2879
        bin2bcd d1
2880
        bsr     DisplayWyde
2881
        move.b #CR,d1
2882
        bra DisplayChar
2883
        btst #$83,d0
2884
 
2885
cmdTestRAM:
2886
ramtest:
2887
        move.w  #$A5A5,leds             ; diagnostics
2888
  move.l #$aaaaaaaa,d3
2889
  move.l #$55555555,d4
2890
  bsr ramtest0
2891
  ; switch checkerboard pattern and repeat test.
2892
  exg d3,d4
2893
  bsr ramtest0
2894
        ; Save last ram address in end of memory pointer.
2895
rmtst5:
2896
        moveq #37,d0                                    ; lock semaphore
2897
        moveq #MEMORY_SEMA,d1
2898
        trap #15
2899
  move.l a0,memend
2900
        ; Create very first memory block.
2901
  suba.l #12,a0
2902
  move.l a0,$20000004           ; length of block
2903
  move.l #$46524545,$20000000
2904
        moveq #38,d0                                    ; unlock semaphore
2905
        moveq #MEMORY_SEMA,d1
2906
        trap #15
2907
  rts
2908
 
2909
ramtest0:
2910
        move.l d3,d0
2911
  movea.l #$20000000,a0
2912
;-----------------------------------------------------------
2913
;   Write checkerboard pattern to ram then read it back to
2914
; find the highest usable ram address (maybe). This address
2915
; must be lower than the start of the rom (0xe00000).
2916
;-----------------------------------------------------------
2917
ramtest1:
2918
  move.l d3,(a0)+
2919
  move.l d4,(a0)+
2920
  move.l a0,d1
2921
  tst.w d1
2922
  bne.s rmtst1
2923
  bsr DisplayAddr
2924
  bsr CheckForCtrlC
2925
rmtst1:
2926
  cmpa.l #$3FFFFFF8,a0
2927
  blo.s ramtest1
2928
  bsr   CRLF
2929
;------------------------------------------------------
2930
;   Save maximum useable address for later comparison.
2931
;------------------------------------------------------
2932
ramtest6:
2933
        move.w  #$A7A7,leds             ; diagnostics
2934
  movea.l a0,a2
2935
  movea.l #$20000000,a0
2936
;--------------------------------------------
2937
;   Read back checkerboard pattern from ram.
2938
;--------------------------------------------
2939
ramtest2
2940
  move.l (a0)+,d5
2941
  move.l (a0)+,d6
2942
  cmpa.l a2,a0
2943
  bhs.s ramtest3
2944
  move.l a0,d1
2945
  tst.w d1
2946
  bne.s rmtst2
2947
  bsr   DisplayAddr
2948
        bsr CheckForCtrlC
2949
rmtst2
2950
  cmp.l d3,d5
2951
  bne.s rmtst3
2952
  cmp.l d4,d6
2953
  beq.s ramtest2
2954
;----------------------------------
2955
; Report error in ram.
2956
;----------------------------------
2957
rmtst3
2958
        bsr CRLF
2959
        moveq   #'E',d1
2960
        bsr DisplayChar
2961
        bsr DisplaySpace
2962
        move.l a0,d1
2963
        bsr DisplayTetra
2964
        bsr DisplaySpace
2965
        move.l d5,d1
2966
        bsr DisplayTetra
2967
        bsr CheckForCtrlC
2968
        bra ramtest2
2969
ramtest3
2970
        rts
2971
 
2972
;==============================================================================
2973
; Load an S19 format file
2974
;==============================================================================
2975
 
2976
cmdLoadS19:
2977
        bsr                     CRLF
2978
        bra                     ProcessRec
2979
NextRec:
2980
        bsr                     sGetChar
2981
        cmpi.b  #LF,d1
2982
        bne                     NextRec
2983
        move.b  #'.',d1
2984
        bsr                     DisplayChar
2985
ProcessRec:
2986
        bsr                     CheckForCtrlC   ; check for CTRL-C once per record
2987
        bsr                     sGetChar
2988
        cmpi.b  #CR,d1
2989
        beq.s           ProcessRec
2990
        clr.b           S19Checksum
2991
        move.b  d1,d4
2992
        cmpi.b  #CTRLZ,d4                       ; CTRL-Z ?
2993
        beq                     Monitor
2994
        cmpi.b  #'S',d4                         ; All records must begin with an 'S'
2995
        bne.s           NextRec
2996
        bsr                     sGetChar
2997
        move.b  d1,d4
2998
        cmpi.b  #'0',d4                         ; Record type must be between '0' and '9'
2999
        blo.s           NextRec
3000
        cmpi.b  #'9',d4                         ; d4 = record type
3001
        bhi.s           NextRec
3002
        bsr                     sGetChar                        ; get byte count for record
3003
        bsr                     AsciiToHexNybble
3004
        move.b  d1,d2
3005
        bsr                     sGetChar
3006
        bsr                     AsciiToHexNybble
3007
        lsl.b           #4,d2
3008
        or.b            d2,d1                                   ; d1 = byte count
3009
        move.b  d1,d3                                   ; d3 = byte count
3010
        add.b           d3,S19Checksum
3011
        cmpi.b  #'0',d4                         ; manufacturer ID record, ignore
3012
        beq                     NextRec
3013
        cmpi.b  #'1',d4
3014
        beq                     ProcessS1
3015
        cmpi.b  #'2',d4
3016
        beq                     ProcessS2
3017
        cmpi.b  #'3',d4
3018
        beq                     ProcessS3
3019
        cmpi.b  #'5',d4                         ; record count record, ignore
3020
        beq                     NextRec
3021
        cmpi.b  #'7',d4
3022
        beq                     ProcessS7
3023
        cmpi.b  #'8',d4
3024
        beq                     ProcessS8
3025
        cmpi.b  #'9',d4
3026
        beq                     ProcessS9
3027
        bra                     NextRec
3028
 
3029
pcssxa:
3030
        move.l  a1,d1
3031
        bsr                     DisplayTetra
3032
        move.b  #CR,d1
3033
        bsr                     DisplayChar
3034
        andi.w  #$ff,d3
3035
        subi.w  #1,d3                   ; one less for dbra
3036
.0001:
3037
        clr.l           d2
3038
        bsr                     sGetChar
3039
        bsr                     AsciiToHexNybble
3040
        lsl.l           #4,d2
3041
        or.b            d1,d2
3042
        bsr                     sGetChar
3043
        bsr                     AsciiToHexNybble
3044
        lsl.l           #4,d2
3045
        or.b            d1,d2
3046
        add.b           d2,S19Checksum
3047
        move.b  d2,(a1)+                        ; move byte to memory
3048
        dbra            d3,.0001
3049
        ; Get the checksum byte
3050
        clr.l           d2
3051
        bsr                     sGetChar
3052
        bsr                     AsciiToHexNybble
3053
        lsl.l           #4,d2
3054
        or.b            d1,d2
3055
        bsr                     sGetChar
3056
        bsr                     AsciiToHexNybble
3057
        lsl.l           #4,d2
3058
        or.b            d1,d2
3059
        eor.b           #$FF,d2
3060
        cmp.b           S19Checksum,d2
3061
        beq                     NextRec
3062
        move.b  #'E',d1
3063
        bsr                     DisplayChar
3064
        bra                     NextRec
3065
 
3066
ProcessS1:
3067
        bsr                     S19Get16BitAddress
3068
        bra                     pcssxa
3069
ProcessS2:
3070
        bsr                     S19Get24BitAddress
3071
        bra                     pcssxa
3072
ProcessS3:
3073
        bsr                     S19Get32BitAddress
3074
        bra                     pcssxa
3075
ProcessS7:
3076
        bsr                     S19Get32BitAddress
3077
        move.l  a1,S19StartAddress
3078
        bsr                     _KeybdInit
3079
        bra                     Monitor
3080
ProcessS8:
3081
        bsr                     S19Get24BitAddress
3082
        move.l  a1,S19StartAddress
3083
        bsr                     _KeybdInit
3084
        bra                     Monitor
3085
ProcessS9:
3086
        bsr                     S19Get16BitAddress
3087
        move.l  a1,S19StartAddress
3088
        bsr                     _KeybdInit
3089
        bra                     Monitor
3090
 
3091
S19Get16BitAddress:
3092
        clr.l           d2
3093
        bsr                     sGetChar
3094
        bsr                     AsciiToHexNybble
3095
        move.b  d1,d2
3096
        bra                     S1932b
3097
 
3098
S19Get24BitAddress:
3099
        clr.l           d2
3100
        bsr                     sGetChar
3101
        bsr                     AsciiToHexNybble
3102
        move.b  d1,d2
3103
        bra                     S1932a
3104
 
3105
S19Get32BitAddress:
3106
        clr.l           d2
3107
        bsr                     sGetChar
3108
        bsr                     AsciiToHexNybble
3109
        move.b  d1,d2
3110
        bsr                     sGetChar
3111
        bsr                     AsciiToHexNybble
3112
        lsl.l           #4,d2
3113
        or.b            d1,d2
3114
        bsr                     sGetChar
3115
        bsr                     AsciiToHexNybble
3116
        lsl.l           #4,d2
3117
        or.b            d1,d2
3118
S1932a:
3119
        bsr                     sGetChar
3120
        bsr                     AsciiToHexNybble
3121
        lsl.l           #4,d2
3122
        or.b            d1,d2
3123
        bsr                     sGetChar
3124
        bsr                     AsciiToHexNybble
3125
        lsl.l           #4,d2
3126
        or.b            d1,d2
3127
S1932b:
3128
        bsr                     sGetChar
3129
        bsr                     AsciiToHexNybble
3130
        lsl.l           #4,d2
3131
        or.b            d1,d2
3132
        bsr                     sGetChar
3133
        bsr                     AsciiToHexNybble
3134
        lsl.l           #4,d2
3135
        or.b            d1,d2
3136
        bsr                     sGetChar
3137
        bsr                     AsciiToHexNybble
3138
        lsl.l           #4,d2
3139
        or.b            d1,d2
3140
        clr.l           d4
3141
        move.l  d2,a1
3142
        ; Add bytes from address value to checksum
3143
        add.b           d2,S19Checksum
3144
        lsr.l           #8,d2
3145
        add.b           d2,S19Checksum
3146
        lsr.l           #8,d2
3147
        add.b           d2,S19Checksum
3148
        lsr.l           #8,d2
3149
        add.b           d2,S19Checksum
3150
        rts
3151
 
3152
;------------------------------------------------------------------------------
3153
; Get a character from auxillary input. Waiting for a character is limited to
3154
; 32000 tries. If a character is not available within the limit, then a return
3155
; to the monitor is done.
3156
;
3157
;       Parameters:
3158
;               none
3159
; Returns:
3160
;               d1 = character from receive buffer or -1 if no char available
3161
;------------------------------------------------------------------------------
3162
 
3163
sGetChar:
3164
        movem.l d0/d2,-(a7)
3165
        move.w  #32000,d2
3166
.0001:
3167
        moveq           #36,d0                          ; serial get char from buffer
3168
        trap            #15
3169
        tst.w           d1                                              ; was there a char available?
3170
        bpl.s           .0002
3171
        dbra            d2,.0001                        ; no - try again
3172
        movem.l (a7)+,d0/d2
3173
.0003:
3174
        bsr                     _KeybdInit
3175
        bra                     Monitor                         ; ran out of tries
3176
.0002:
3177
        movem.l (a7)+,d0/d2
3178
        cmpi.b  #CTRLZ,d1                       ; receive end of file?
3179
        beq                     .0003
3180
        rts
3181
 
3182
AudioInputTest:
3183
        rts
3184
BouncingBalls:
3185
        rts
3186
GraphicsDemo:
3187
        rts
3188
ClearScreen:
3189
        bra             clear_screen
3190
        rts
3191
 
3192
;------------------------------------------------------------------------------
3193
; Reverse the order of bytes in d1.
3194
;------------------------------------------------------------------------------
3195
 
3196
rbo:
3197
        rol.w           #8,d1
3198
        swap            d1
3199
        rol.w           #8,d1
3200
        rts
3201
 
3202
;==============================================================================
3203
; Serial I/O routines
3204
;==============================================================================
3205
 
3206
;------------------------------------------------------------------------------
3207
; Initialize the serial port an enhanced 6551 circuit.
3208
;
3209
; Select internal baud rate clock divider for 9600 baud
3210
; Reset fifos, set threshold to 3/4 full on transmit and 3/4 empty on receive
3211
; Note that the byte order is swapped.
3212
;------------------------------------------------------------------------------
3213
 
3214
SerialInit:
3215
        clr.w           SerHeadRcv                                      ; clear receive buffer indexes
3216
        clr.w           SerTailRcv
3217
        clr.b           SerRcvXon                                               ; and Xon,Xoff flags
3218
        clr.b           SerRcvXoff
3219
        move.l  #$09000000,d0                           ; dtr,rts active, rxint enabled, no parity
3220
        move.l  d0,ACIA+ACIA_CMD
3221
;       move.l  #$1E00F700,d0                           ; fifos enabled
3222
        move.l  #$1E000000,d0                           ; fifos disabled
3223
        move.l  d0,ACIA+ACIA_CTRL
3224
        rts
3225
;       move.l  #$0F000000,d0                           ; transmit a break for a while
3226
;       move.l  d0,ACIA+ACIA_CMD
3227
;       move.l  #300000,d2                                      ; wait 100 ms
3228
;       bra                     .0001
3229
;.0003:
3230
;       swap            d2
3231
;.0001:
3232
;       nop
3233
;       dbra            d2,.0001
3234
;.0002:
3235
;       swap            d2
3236
;       dbra            d2,.0003
3237
;       move.l  #$07000000,d0                           ; clear break
3238
;       move.l  d0,ACIA+ACIA_CMD
3239
;       rts
3240
 
3241
;------------------------------------------------------------------------------
3242
; SerialGetChar
3243
;
3244
; Check the serial port buffer to see if there's a char available. If there's
3245
; a char available then return it. If the buffer is almost empty then send an
3246
; XON.
3247
;
3248
; Stack Space:
3249
;               2 long words
3250
; Parameters:
3251
;               none
3252
; Modifies:
3253
;               d0,a0
3254
; Returns:
3255
;               d1 = character or -1
3256
;------------------------------------------------------------------------------
3257
 
3258
SerialGetChar:
3259
        move.l          d2,-(a7)
3260
        movec                   coreno,d0
3261
        swap                    d0
3262
        moveq                   #SERIAL_SEMA,d1
3263
        bsr                             LockSemaphore
3264
        bsr                             SerialRcvCount                  ; check number of chars in receive buffer
3265
        cmpi.w          #8,d0                                                           ; less than 8?
3266
        bhi                             .sgc2
3267
        tst.b                   SerRcvXon                                               ; skip sending XON if already sent
3268
        bne                     .sgc2                           ; XON already sent?
3269
        move.b          #XON,d1                                                 ; if <8 send an XON
3270
        clr.b                   SerRcvXoff                                      ; clear XOFF status
3271
        move.b          d1,SerRcvXon                            ; flag so we don't send it multiple times
3272
        bsr                             SerialPutChar                           ; send it
3273
.sgc2:
3274
        move.w          SerHeadRcv,d1                           ; check if anything is in buffer
3275
        cmp.w                   SerTailRcv,d1
3276
        beq                             .NoChars                                                ; no?
3277
        lea                             SerRcvBuf,a0
3278
        move.b          (a0,d1.w),d1                            ; get byte from buffer
3279
        addi.w          #1,SerHeadRcv
3280
        andi.w          #$FFF,SerHeadRcv                ; 4k wrap around
3281
        andi.l          #$FF,d1
3282
        bra                             .Xit
3283
.NoChars:
3284
        moveq                   #-1,d1
3285
.Xit:
3286
        exg                             d1,d2
3287
        movec                   coreno,d0
3288
        swap                    d0
3289
        moveq                   #SERIAL_SEMA,d1
3290
        bsr                             UnlockSemaphore
3291
        exg                             d2,d1
3292
        move.l          (a7)+,d2
3293
        rts
3294
 
3295
;------------------------------------------------------------------------------
3296
; SerialPeekChar
3297
;
3298
; Check the serial port buffer to see if there's a char available. If there's
3299
; a char available then return it. But don't update the buffer indexes. No need
3300
; to send an XON here.
3301
;
3302
; Stack Space:
3303
;               0 words
3304
; Parameters:
3305
;               none
3306
; Modifies:
3307
;               d0,d2,a0
3308
; Returns:
3309
;               d1 = character or -1
3310
;------------------------------------------------------------------------------
3311
 
3312
SerialPeekChar:
3313
        movec           coreno,d0
3314
        swap            d0
3315
        moveq           #SERIAL_SEMA,d1
3316
        bsr                     LockSemaphore
3317
        move.w  SerHeadRcv,d2           ; check if anything is in buffer
3318
        cmp.w           SerTailRcv,d2
3319
        beq                     .NoChars                                ; no?
3320
        lea                     SerRcvBuf,a0
3321
        move.b  (a0,d2.w),d2            ; get byte from buffer
3322
        bra                     .Xit
3323
.NoChars:
3324
        moveq           #-1,d2
3325
.Xit:
3326
        movec           coreno,d0
3327
        swap            d0
3328
        moveq           #SERIAL_SEMA,d1
3329
        bsr                     LockSemaphore
3330
        move            d2,d1
3331
        rts
3332
 
3333
;------------------------------------------------------------------------------
3334
; SerialPeekChar
3335
;               Get a character directly from the I/O port. This bypasses the input
3336
; buffer.
3337
;
3338
; Stack Space:
3339
;               0 words
3340
; Parameters:
3341
;               none
3342
; Modifies:
3343
;               d
3344
; Returns:
3345
;               d1 = character or -1
3346
;------------------------------------------------------------------------------
3347
 
3348
SerialPeekCharDirect:
3349
        move.b  ACIA+ACIA_STAT,d1       ; get serial status
3350
        btst            #3,d1                                                   ; look for Rx not empty
3351
        beq.s           .0001
3352
        moveq.l #0,d1                                                   ; clear upper bits of return value
3353
        move.b  ACIA+ACIA_RX,d1         ; get data from ACIA
3354
        rts                                                                                             ; return
3355
.0001:
3356
        moveq           #-1,d1
3357
        rts
3358
 
3359
;------------------------------------------------------------------------------
3360
; SerialPutChar
3361
;    Put a character to the serial transmitter. This routine blocks until the
3362
; transmitter is empty.
3363
;
3364
; Stack Space
3365
;               0 words
3366
; Parameters:
3367
;               d1.b = character to put
3368
; Modifies:
3369
;               none
3370
;------------------------------------------------------------------------------
3371
 
3372
SerialPutChar:
3373
        movem.l d0/d1,-(a7)                             ; push d0,d1
3374
.0001:
3375
        move.b  ACIA+ACIA_STAT,d0       ; wait until the uart indicates tx empty
3376
        btst            #4,d0                                                   ; bit #4 of the status reg
3377
        beq.s           .0001                                   ; branch if transmitter is not empty
3378
        move.b  d1,ACIA+ACIA_TX         ; send the byte
3379
        movem.l (a7)+,d0/d1                             ; pop d0,d1
3380
        rts
3381
 
3382
;------------------------------------------------------------------------------
3383
; Reverse the order of bytes in d1.
3384
;------------------------------------------------------------------------------
3385
 
3386
SerialRbo:
3387
        rol.w           #8,d1
3388
        swap            d1
3389
        rol.w           #8,d1
3390
        rts
3391
 
3392
;------------------------------------------------------------------------------
3393
; Calculate number of character in input buffer
3394
;
3395
; Returns:
3396
;               d0 = number of bytes in buffer.
3397
;------------------------------------------------------------------------------
3398
 
3399
SerialRcvCount:
3400
        move.w  SerTailRcv,d0
3401
        sub.w           SerHeadRcv,d0
3402
        bge                     .0001
3403
        move.w  #$1000,d0
3404
        sub.w           SerHeadRcv,d0
3405
        add.w           SerTailRcv,d0
3406
.0001:
3407
        rts
3408
 
3409
;------------------------------------------------------------------------------
3410
; Serial IRQ routine
3411
;
3412
; Keeps looping as long as it finds characters in the ACIA recieve buffer/fifo.
3413
; Received characters are buffered. If the buffer becomes full, new characters
3414
; will be lost.
3415
;
3416
; Parameters:
3417
;               none
3418
; Modifies:
3419
;               none
3420
; Returns:
3421
;               d1 = -1 if IRQ handled, otherwise zero
3422
;------------------------------------------------------------------------------
3423
 
3424
SerialIRQ:
3425
        move.w  #$2300,sr                                               ; disable lower level IRQs
3426
        movem.l d0/d1/d2/a0,-(a7)
3427
        movec           coreno,d0
3428
        swap            d0
3429
        moveq           #SERIAL_SEMA,d1
3430
        bsr                     LockSemaphore
3431
sirqNxtByte:
3432
        move.b  ACIA+ACIA_STAT,d1               ; check the status
3433
        btst            #3,d1                                                           ; bit 3 = rx full
3434
        beq                     notRxInt
3435
        move.b  ACIA+ACIA_RX,d1
3436
sirq0001:
3437
        move.w  SerTailRcv,d0                           ; check if recieve buffer full
3438
        addi.w  #1,d0
3439
        andi.w  #$FFF,d0
3440
        cmp.w           SerHeadRcv,d0
3441
        beq                     sirqRxFull
3442
        move.w  d0,SerTailRcv                           ; update tail pointer
3443
        subi.w  #1,d0                                                           ; backup
3444
        andi.w  #$FFF,d0
3445
        lea                     SerRcvBuf,a0                            ; a0 = buffer address
3446
        move.b  d1,(a0,d0.w)                            ; store recieved byte in buffer
3447
        tst.b           SerRcvXoff                                      ; check if xoff already sent
3448
        bne                     sirqNxtByte
3449
        bsr                     SerialRcvCount                  ; if more than 4080 chars in buffer
3450
        cmpi.w  #4080,d0
3451
        blo                     sirqNxtByte
3452
        move.b  #XOFF,d1                                                ; send an XOFF
3453
        clr.b           SerRcvXon                                               ; clear XON status
3454
        move.b  d1,SerRcvXoff                           ; set XOFF status
3455
        bsr                     SerialPutChar                           ; send XOFF
3456
        bra                     sirqNxtByte                     ; check the status for another byte
3457
sirqRxFull:
3458
notRxInt:
3459
        movec           coreno,d0
3460
        swap            d0
3461
        moveq           #SERIAL_SEMA,d1
3462
        bsr                     UnlockSemaphore
3463
        movem.l (a7)+,d0/d1/d2/a0
3464
        rte
3465
 
3466
nmeSerial:
3467
        dc.b            "Serial",0
3468
 
3469 3 robfinch
;===============================================================================
3470
; Generic I2C routines
3471
;===============================================================================
3472 2 robfinch
 
3473 3 robfinch
        even
3474
; i2c
3475
i2c_setup:
3476
;               lea             I2C,a6
3477
;               move.w  #19,I2C_PREL(a6)        ; setup prescale for 400kHz clock
3478
;               move.w  #0,I2C_PREH(a6)
3479
init_i2c:
3480
        lea     I2C2,a6
3481
        move.b #19,I2C_PREL(a6) ; setup prescale for 400kHz clock, 40MHz master
3482
        move.b #0,I2C_PREH(a6)
3483
        rts
3484
 
3485
; Wait for I2C transfer to complete
3486
;
3487
; Parameters
3488
;       a6 - I2C controller base address
3489
 
3490
i2c_wait_tip:
3491
        move.l d0,-(a7)
3492
.0001
3493
        move.b I2C_STAT(a6),d0          ; wait for tip to clear
3494
        btst #1,d0
3495
        bne.s   .0001
3496
        move.l (a7)+,d0
3497
        rts
3498
 
3499
; Parameters
3500
;       d0.b - data to transmit
3501
;       d1.b - command value
3502
;       a6       - I2C controller base address
3503
;
3504
i2c_wr_cmd:
3505
        move.b d0,I2C_TXR(a6)
3506
        move.b d1,I2C_CMD(a6)
3507
        bsr     i2c_wait_tip
3508
        move.b I2C_STAT(a6),d0
3509
        rts
3510
 
3511
i2c_xmit1:
3512
        move.l d0,-(a7)
3513
        move.b #1,I2C_CTRL(a6)          ; enable the core
3514
        moveq   #$76,d0                         ; set slave address = %0111011
3515
        move.w #$90,d1                          ; set STA, WR
3516
        bsr i2c_wr_cmd
3517
        bsr     i2c_wait_rx_nack
3518
        move.l (a7)+,d0
3519
        move.w #$50,d1                          ; set STO, WR
3520
        bsr i2c_wr_cmd
3521
        bsr     i2c_wait_rx_nack
3522
 
3523
i2c_wait_rx_nack:
3524
        move.l d0,-(a7)
3525
.0001
3526
        move.b I2C_STAT(a6),d0          ; wait for RXack = 0
3527
        btst #7,d0
3528
        bne.s   .0001
3529
        move.l (a7)+,d0
3530
        rts
3531
 
3532
;===============================================================================
3533
; Realtime clock routines
3534
;===============================================================================
3535
 
3536
rtc_read:
3537
        movea.l #I2C2,a6
3538
        lea     RTCBuf,a5
3539
        move.b  #$80,I2C_CTRL(a6)       ; enable I2C
3540
        move.b  #$DE,d0                         ; read address, write op
3541
        move.b  #$90,d1                         ; STA + wr bit
3542
        bsr     i2c_wr_cmd
3543
        tst.b   d0
3544
        bmi     .rxerr
3545
        move.b #$00,d0                          ; address zero
3546
        move.b #$10,d1                          ; wr bit
3547
        bsr     i2c_wr_cmd
3548
        tst.b   d0
3549
        bmi     .rxerr
3550
        move.b #$DF,d0                          ; read address, read op
3551
        move.b #$90,d1                          ; STA + wr bit
3552
        bsr i2c_wr_cmd
3553
        tst.b   d0
3554
        bmi     .rxerr
3555
 
3556
        move.w #$20,d2
3557
.0001
3558
        move.b #$20,I2C_CMD(a6) ; rd bit
3559
        bsr     i2c_wait_tip
3560
        bsr     i2c_wait_rx_nack
3561
        move.b I2C_STAT(a6),d0
3562
        tst.b   d0
3563
        bmi     .rxerr
3564
        move.b I2C_RXR(a6),d0
3565
        move.b d0,(a5,d2.w)
3566
        addi.w #1,d2
3567
        cmpi.w #$5F,d2
3568
        bne     .0001
3569
        move.b #$68,I2C_CMD(a6) ; STO, rd bit + nack
3570
        bsr i2c_wait_tip
3571
        bsr i2c_wait_rx_nack
3572
        move.b I2C_STAT(a6),d0
3573
        tst.b   d0
3574
        bmi     .rxerr
3575
        move.b I2C_RXR(a6),d0
3576
        move.b d0,(a5,d2.w)
3577
        move.b #0,I2C_CTRL(a6)          ; disable I2C and return 0
3578
        moveq   #0,d0
3579
        rts
3580
.rxerr
3581
        move.b #0,I2C_CTRL(a6)          ; disable I2C and return status
3582
        rts
3583
 
3584
rtc_write:
3585
        movea.l #I2C2,a6
3586
        lea     RTCBuf,a5
3587
        move.b #$80,I2C_CTRL(a6)        ; enable I2C
3588
        move.b #$DE,d0                          ; read address, write op
3589
        move.b #$90,d1                          ; STA + wr bit
3590
        bsr     i2c_wr_cmd
3591
        tst.b   d0
3592
        bmi     .rxerr
3593
        move.b #$00,d0                          ; address zero
3594
        move.b #$10,d1                          ; wr bit
3595
        bsr     i2c_wr_cmd
3596
        tst.b   d0
3597
        bmi     .rxerr
3598
        move.w #$20,d2
3599
.0001
3600
        move.b (a5,d2.w),d0
3601
        move.b #$10,d1
3602
        bsr     i2c_wr_cmd
3603
        tst.b   d0
3604
        bmi     .rxerr
3605
        addi.w #1,d2
3606
        cmpi.w #$5F,d2
3607
        bne.s   .0001
3608
        move.b (a5,d2.w),d0
3609
        move.b #$50,d1                          ; STO, wr bit
3610
        bsr     i2c_wr_cmd
3611
        tst.b   d0
3612
        bmi     .rxerr
3613
        move.b #0,I2C_CTRL(a6)          ; disable I2C and return 0
3614
        moveq   #0,d0
3615
        rts
3616
.rxerr:
3617
        move.b #0,I2C_CTRL(a6)          ; disable I2C and return status
3618
        rts
3619
 
3620
msgRtcReadFail:
3621
        dc.b    "RTC read/write failed.",$0A,$0D,$00
3622
 
3623
        even
3624
 
3625 2 robfinch
;------------------------------------------------------------------------------
3626
;------------------------------------------------------------------------------
3627
        even
3628
 
3629
bus_err:
3630
.0001:
3631
        nop
3632
        bra                     .0001
3633
 
3634
trap3:
3635
        ; First save all registers
3636
        movem.l         d0/d1/d2/d3/d4/d5/d6/d7/a0/a1/a2/a3/a4/a5/a6/a7,Regsave
3637
        move.w          (a7)+,Regsave+$40
3638
        move.l          (a7)+,Regsave+$44
3639
        move.l          #$40FFC,a7                      ; reset stack pointer
3640
        move.w          #$2500,sr                               ; enable interrupts
3641
        move.w          NumSetBreakpoints,d0
3642
        subi.w          #1,d0
3643
        lea                             Breakpoints,a0
3644
        move.l          Regsave+$44,d1
3645
.0001:
3646
        cmp.l                   (a0)+,d1
3647
        beq.s                   ProcessBreakpoint
3648
        dbra                    d0,.0001
3649
        bra                             Monitor                                 ; not a breakpoint
3650
ProcessBreakpoint:
3651
        bsr                             DisarmAllBreakpoints
3652
        bra                             cmdDumpRegs
3653
 
3654
;------------------------------------------------------------------------------
3655
; DisarmAllBreakpoints, used when entering the monitor.
3656
;------------------------------------------------------------------------------
3657
 
3658
DisarmAllBreakpoints:
3659
        movem.l d0/a0/a1/a2,-(a7)                       ; stack some regs
3660
        move.w  NumSetBreakpoints,d0    ; d0 = number of breakpoints that are set
3661
        cmpi.w  #numBreakpoints,d0              ; check for valid number
3662
        bhs.s           .0001
3663
        lea                     Breakpoints,a2                          ; a2 = pointer to breakpoint address table
3664
        lea                     BreakpointWords,a0              ; a0 = pointer to breakpoint instruction word table
3665
        bra.s           .0003                                                                   ; enter loop at bottom
3666
.0002:
3667
        move.l  (a2)+,a1                                                        ; a1 = address of breakpoint
3668
        move.w  (a0)+,(a1)                                              ; copy instruction word back to code
3669
.0003:
3670
        dbra            d0,.0002
3671
        movem.l (a7)+,d0/a0/a1/a2                       ; restore regs
3672
.0001:
3673
        rts
3674
 
3675
;------------------------------------------------------------------------------
3676
; ArmAllBreakpoints, used when entering the monitor.
3677
;------------------------------------------------------------------------------
3678
 
3679
ArmAllBreakpoints:
3680
        movem.l         d0/a0/a1/a2,-(a7)                       ; stack some regs
3681
        move.w          NumSetBreakpoints,d0    ; d0 = number of breakpoints
3682
        cmpi.w          #numBreakpoints,d0              ; is the number valid?
3683
        bhs.s                   .0001
3684
        lea                             Breakpoints,a2                          ; a2 = pointer to breakpoint address table
3685
        lea                             BreakpointWords,a0              ; a0 = pointer to instruction word table
3686
        bra.s                   .0003                                                                   ; enter loop at bottom
3687
.0002:
3688
        move.l          (a2)+,a1                                                        ; a1 = address of breakpoint
3689
        move.w          (a1),(a0)                                                       ; copy instruction word to table
3690
        move.w          #$4E43,(a0)+                                    ; set instruction = TRAP3
3691
.0003:
3692
        dbra                    d0,.0002
3693
        movem.l         (a7)+,d0/a0/a1/a2                       ; restore regs
3694
.0001:
3695
        rts
3696
 
3697
;------------------------------------------------------------------------------
3698
;------------------------------------------------------------------------------
3699
 
3700
ArmBreakpoint:
3701
        movem.l         d0/d1/d2/a0/a1/a2,-(a7)
3702
        move.w          NumSetBreakpoints,d0    ; d0 = number of breakpoints
3703
        cmpi.w          #numBreakpoints,d0              ; check if too many
3704
        bhs.s                   .0001
3705
        addi.w          #1,NumSetBreakpoints    ; increment number of breakpoints
3706
        move.l          d0,d2
3707
        bsr                             ignBlanks
3708
        bsr                             GetHexNumber
3709
        beq.s                   .0001                                                                   ; was there an address?
3710
        btst                    #0,d1                                                                   ; address value must be even
3711
        bne.s                   .0001
3712
        ; See if the breakpoint is in the table already
3713
        lea                             Breakpoints,a1                          ; a1 points to breakpoint table
3714
        move.w          #numBreakpoints-1,d2
3715
.0002:
3716
        cmp.l                   (a1)+,d1
3717
        beq.s                   .0003                                                                   ; breakpoint is in table already
3718
        dbra                    d2,.0002
3719
        ; Add breakpoint to table
3720
        ; Search for empty entry
3721
        lea                             Breakpoints,a1                          ; a1 = pointer to breakpoint address table
3722
        clr.w                   d2                                                                              ; d2 = count
3723
.0006:
3724
        tst.l                   (a1)                                                                    ; is the entry empty?
3725
        beq.s                   .0005                                                                   ; branch if found empty entry
3726
        lea                             4(a1),a1                                                        ; point to next entry
3727
        addi.w          #1,d2                                                                   ; increment count
3728
        cmpi.w          #numBreakpoints,d2              ; safety: check against max number
3729
        blo.s                   .0006
3730
        bra.s                   .0001                                                                   ; what? no empty entries found, table corrupt?
3731
.0005:
3732
        asl.w                   #2,d2                                                                   ; d2 = long word index
3733
        move.l          d1,(a1,d2.w)                                    ; move breakpoint address to table
3734
        move.l          d1,a2
3735
        lsr.w                   #1,d2                                                                   ; d2 = word index
3736
.0004:
3737
        lea                             BreakpointWords,a1
3738
        move.w          (a2),(a1,d2.w)                          ; copy instruction word to table
3739
        move.w          #$4E43,(a2)                                             ; replace word with TRAP3
3740
.0001:
3741
        movem.l         (a7)+,d0/d1/d2/a0/a1/a2
3742
        rts
3743
.0003:
3744
        move.l          -4(a1),a2                                                       ; a2 = pointer to breakpoint address from table
3745
        cmpi.w          #$4E43,(a2)                                             ; see if breakpoint already armed
3746
        beq.s                   .0001
3747
        asl.l                   #1,d2                                                                   ; d2 = word index
3748
        bra.s                   .0004
3749
 
3750
 
3751
;------------------------------------------------------------------------------
3752
;------------------------------------------------------------------------------
3753
 
3754
DisarmBreakpoint:
3755
        movem.l         d0/d1/d2/a0/a1/a2,-(a7)
3756
        move.w          NumSetBreakpoints,d0    ; d0 = number of breakpoints
3757
        cmpi.w          #numBreakpoints,d0              ; check if too many
3758
        bhi.s                   .0001
3759
        move.l          d0,d2
3760
        bsr                             ignBlanks
3761
        bsr                             GetHexNumber
3762
        beq.s                   .0001                                                                   ; was there an address?
3763
        btst                    #0,d1                                                                   ; address value must be even
3764
        bne.s                   .0001
3765
        ; See if the breakpoint is in the table already
3766
        lea                             Breakpoints,a1                          ; a1 points to breakpoint table
3767
        subi.w          #1,d2
3768
.0002:
3769
        cmp.l                   (a1)+,d1
3770
        beq.s                   .0003                                                                   ; breakpoint is in table already
3771
        dbra                    d2,.0002
3772
        bra                             .0001                                                                   ; breakpoint was not in table
3773
.0003:
3774
        ; Remove breakpoint from table
3775
        subi.w          #1,NumSetBreakpoints    ; decrement number of breakpoints
3776
        move.l          -4(a1),a2                                                       ; a2 = pointer to breakpoint address from table
3777
        clr.l                   -4(a1)                                                          ; empty out breakpoint
3778
        lea                             BreakpointWords,a1
3779
        asl.l                   #1,d2                                                                   ; d2 = word index
3780
        move.w          (a1,d2.w),(a2)                          ; copy instruction from table back to code
3781
.0001:
3782
        movem.l         (a7)+,d0/d1/d2/a0/a1/a2
3783
        rts
3784
 
3785
;------------------------------------------------------------------------------
3786
;------------------------------------------------------------------------------
3787
 
3788
ListBreakpoints:
3789
        bsr                     CRLF
3790
        move.w  #numBreakpoints,d2
3791
        lea                     Breakpoints,a1
3792
.0001:
3793
        move.l  (a1)+,d1
3794
        bsr                     DisplayTetra
3795
        bsr                     CRLF
3796
        dbra            d2,.0001
3797
        bra                     Monitor
3798
 
3799
;------------------------------------------------------------------------------
3800
;------------------------------------------------------------------------------
3801
 
3802
ClearBreakpointList:
3803
        move.w  #numBreakpoints,d2
3804
        lea                     Breakpoints,a1
3805
.0001:
3806
        clr.l           (a1)+
3807
        dbra            d2,.0001
3808
        rts
3809
 
3810
;------------------------------------------------------------------------------
3811
; SendMsg
3812
; 00100xy0
3813
;
3814
; Parameters:
3815
;               d1 = target core number
3816
;               d2 = argument 1
3817
;               d3 = argument 2
3818
;               d4 = argument 3
3819
;
3820
;------------------------------------------------------------------------------
3821
 
3822
SendMsg:
3823
        movem.l d5/a1,-(a7)
3824
        lsl.w           #8,d1
3825
        movec           coreno,d5
3826
        lsl.w           #4,d5
3827
        or.w            d5,d1
3828
        lea                     $00100000,a1
3829
        tst.l           0(a1,d1.w)
3830
        bne                     .msgFull
3831
        movec           coreno,d5
3832
        move.l  d5,0(a1,d1.w)
3833
        move.l  d2,4(a1,d1.w)
3834
        move.l  d3,8(a1,d1.w)
3835
        move.l  d4,12(a1,d1.w)
3836
        movem.l (a7)+,d5/a1
3837
        moveq           #0,d1
3838
        rts
3839
.msgFull:
3840
        movem.l (a7)+,d5/a1
3841
        moveq           #-1,d1
3842
        rts
3843
 
3844
;------------------------------------------------------------------------------
3845
; ReceiveMsg
3846
;               Scan the message table for messages and dispatch them.
3847
; 00100xy0
3848
;
3849
; Parameters:
3850
;------------------------------------------------------------------------------
3851
 
3852
ReceiveMsg:
3853
        movem.l         d1/d2/d3/d4/d5/d6/d7/a1,-(a7)
3854
        lea                             $00100000,a1
3855
        movec                   coreno,d5
3856
        lsl.w                   #8,d5
3857
        moveq                   #2,d6
3858
.nextCore:
3859
        move.w          d6,d7
3860
        lsl.w                   #4,d7
3861
        add.w                   d5,d7
3862
        tst.l                   0(a1,d7.w)                      ; Is there a message from core d6?
3863
        beq                             .noMsg
3864
        move.l          0(a1,d7.w),d1
3865
        move.l          4(a1,d7.w),d2
3866
        move.l          8(a1,d7.w),d3
3867
        move.l          12(a1,d7.w),d4
3868
        clr.l                   0(a1,d7.w)                      ; indicate message was received
3869
        bsr                             DispatchMsg
3870
.noMsg:
3871
        addq                    #1,d6
3872
        cmp.w                   #9,d6
3873
        bls                             .nextCore
3874
        movem.l         (a7)+,d1/d2/d3/d4/d5/d6/d7/a1
3875
        rts
3876
 
3877
;------------------------------------------------------------------------------
3878
;------------------------------------------------------------------------------
3879
 
3880
DispatchMsg:
3881
        rts
3882
 
3883
 
3884
;------------------------------------------------------------------------------
3885
;------------------------------------------------------------------------------
3886
 
3887
InitIRQ:
3888
        moveq           #6,d0
3889
        lea                     KeybdIRQ,a0
3890
        bsr                     InstallIRQ
3891
        lea                     TickIRQ,a0
3892
        bsr                     InstallIRQ
3893
        moveq           #3,d0
3894
        lea                     SerialIRQ,a0
3895
        ; fall through
3896
 
3897
;------------------------------------------------------------------------------
3898
; Install an IRQ handler.
3899
;
3900
; Parameters:
3901
;               d0 = IRQ level
3902
;               a0 = pointer to IRQ routine
3903
; Returns:
3904
;               d1 = -1 if successfully added, 0 otherwise
3905
;               nf = 1, zf = 0 if successfully added, otherwise nf = 0, zf = 1
3906
;------------------------------------------------------------------------------
3907
 
3908
InstallIRQ:
3909
        move.l  d0,-(a7)                                        ; save working register
3910
        lea                     InstalledIRQ,a1         ; a1 points to installed IRQ list
3911
        lsl.w           #5,d0                                                   ; multiply by 8 long words per IRQ level
3912
.nextSpot:
3913
        cmpa.l  (a1,d0.w),a0                    ; Is the IRQ already installed?
3914
        beq.s           .found
3915
        tst.l           (a1,d0.w)                                       ; test for an empty spot
3916
        beq.s           .foundSpot
3917
        addi.w  #4,d0                                                   ; increment to next slot
3918
        move.w  d0,d1
3919
        andi.w  #$1F,d1                                         ; check to see if spots exhausted
3920
        beq.s           .noEmpties
3921
        bra.s           .nextSpot
3922
.foundSpot:
3923
        move.l  a0,(a1,d0.w)                    ; add IRQ routine to table
3924
.found:
3925
        move.l  (a7)+,d0
3926
        moveq           #-1,d1                                          ; return success
3927
        rts
3928
.noEmpties:
3929
        move.l  (a7)+,d0
3930
        moveq           #0,d1                                                   ; return failed to add
3931
        rts
3932
 
3933
 
3934
;------------------------------------------------------------------------------
3935
;------------------------------------------------------------------------------
3936
 
3937
TickIRQ:
3938
        move.w  #$2600,sr                                       ; disable lower level IRQs
3939
        movem.l d1/d2/a0,-(a7)
3940
        ; ToDo: detect a tick interrupt
3941
;       move.l  PLIC+$00,d1
3942
;       rol.l           #8,d1
3943
;       cmpi.b  #29,d1
3944
;       bne.s           .notTick
3945
        movec           coreno,d1                                       ; d1 = core number
3946
        cmpi.b  #2,d1
3947
        bne.s           .0001
3948
        move.l  #$1D000000,PLIC+$14     ; reset edge sense circuit
3949
.0001:
3950
        move.l  TextScr,a0                              ; a0 = screen address
3951
        move.l  (a0),d2
3952
        rol.w           #8,d2                                                   ; reverse byte order of d2
3953
        swap            d2
3954
        rol.w           #8,d2
3955
        addi.b  #'0',d1                                         ; binary to ascii core number
3956
        add.b           d2,d1
3957
        rol.w           #8,d1                                                   ; put bytes back in order
3958
        swap            d1
3959
        rol.w           #8,d1
3960
        move.l  d1,4(a0)                                        ; update onscreen IRQ flag
3961
        addi.l  #1,(a0)                                         ; flashy colors
3962
; addi.l        #1,40(a0)                                       ; nice effect
3963
        bsr                     ReceiveMsg
3964
        movem.l (a7)+,d1/d2/a0
3965
        rte
3966
;.notTick:
3967
;       movem.l (a7)+,d1/a0
3968
;       rte
3969
;------------------------------------------------------------------------------
3970
;------------------------------------------------------------------------------
3971
 
3972
irq3_rout:
3973
        movem.l d0/d1/a0/a1,-(a7)
3974
        lea                     InstalledIRQ+8*4*3,a0
3975
        bra                     irq_rout
3976
 
3977
irq6_rout:
3978
        movem.l d0/d1/a0/a1,-(a7)
3979
        lea                     InstalledIRQ+8*4*6,a0
3980
irq_rout:
3981
        moveq           #7,d0
3982
.nextHandler:
3983
        move.l  (a0)+,a1
3984
        beq.s           .0003
3985
        jsr                     (a1)
3986
        tst.l           d1                                                              ; was IRQ handled?
3987
        bmi.s           .0002                                                   ; first one to return handled quits loop
3988
.0003:
3989
        dbra            d0,.nextHandler
3990
.0002:
3991
        movem.l (a7)+,d0/d1/a0/a1       ; return
3992
 
3993
SpuriousIRQ:
3994
        rte
3995
 
3996
;       bsr                     KeybdIRQ
3997
;       tst.l           d1                                                              ; handled by KeybdIRQ?
3998
;       bmi.s           .0002                                                   ; if yes, go return
3999
;.0001:
4000
;       move.l  #$1D000000,PLIC+$14     ; reset edge sense circuit
4001
;       move.l  TextScr,a0                              ; a0 = screen address
4002
;       addi.l  #1,40(a0)                                       ; update onscreen IRQ flag
4003
;.0002:
4004
;       movem.l (a7)+,d0/d1/a0/a1       ; return
4005
;       rte
4006
 
4007
nmi_rout:
4008
        movem.l d0/d1/a0,-(a7)
4009
        move.b  #'N',d1
4010
        bsr                     DisplayChar
4011
        movem.l (a7)+,d0/d1/a0          ; return
4012
        rte
4013
 
4014
brdisp_trap:
4015
        movem.l d0/d1/d2/d3/d4/d5/d6/d7/a0/a1/a2/a3/a4/a5/a6/a7,Regsave
4016
        move.w  (a7)+,Regsave+$40
4017
        move.l  (a7)+,Regsave+$44
4018
        move.l  #$40FFC,a7                      ; reset stack pointer
4019
        move.w  #$2500,sr                               ; enable interrupts
4020
        lea                     msg_bad_branch_disp,a1
4021
        bsr                     DisplayString
4022
        bsr                     DisplaySpace
4023
        move.l  Regsave+$44,d1  ; exception address
4024
        bsr                     DisplayTetra            ; and display it
4025
;       move.l  (sp)+,d1                                ; pop format word 68010 mode only
4026
        bra                     cmdDumpRegs
4027
 
4028
illegal_trap:
4029
        addq            #2,sp                                           ; get rid of sr
4030
        move.l  (sp)+,d1                                ; pop exception address
4031
        bsr                     DisplayTetra            ; and display it
4032
        lea                     msg_illegal,a1  ; followed by message
4033
        bsr                     DisplayString
4034
.0001:
4035
        bra                     .0001
4036
        bra                     Monitor
4037
 
4038
io_irq:
4039
        addq #2,sp
4040
        move.l (sp)+,d1
4041
        bsr DisplayTetra
4042
        lea msg_io_access,a1
4043
        bsr DisplayString
4044
        bra cmdDumpRegs
4045
 
4046
; -----------------------------------------------------------------------------
4047
; -----------------------------------------------------------------------------
4048
 
4049
msg_start:
4050
        dc.b    "Femtiki rf68k Multi-core OS Starting",LF,CR,0
4051
;       dc.b    "rf68k System Starting",CR,LF,0
4052
msg_core_start:
4053
        dc.b    " core starting",CR,LF,0
4054
msg_illegal:
4055
        dc.b    " illegal opcode",CR,LF,0
4056
msg_bad_branch_disp:
4057
        dc.b    " branch selfref: ",0
4058
msg_test_done:
4059
        dc.b    " CPU test done.",0
4060
msg_io_access
4061
        dc.b " unpermitted access to I/O",0
4062
 
4063
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.