**************************************************************************** * * * Amiga cia.resource version 33.22 (29 Mar 1986) disassembly * * this version of the resource was contained in Kickstart 1.2 * * * * disassembled and commented by Pavel Zima on 9 Jul 2016 * * * * following text supposes knowledge of 68k assembly language and * * structures of Amiga operating system * * * * this little work was inspired by disassembly of AmigaOS 1.2 Exec by * * Markus Wandel (http://wandel.ca/homepage/execdis/exec_disassembly.txt) * * or downloadable from Aminet (aminet.net) * * structure and appearance is from that reason similar * * * **************************************************************************** ---------------------------------------------------------------------------- cia.resource functions ---------------------------------------------------------------------------- FC4578 init code FC4610 interrupt service routine FC4690 AddICRVector (-6) FC46E6 RemICRVector (-12) FC470A AbleICR (-18) FC4728 SetICR (-24) ---------------------------------------------------------------------------- cia.resource base ---------------------------------------------------------------------------- ; this is content of cia resource base structure as it is ; in RAM, there are two instances for this resource one for ; CIA-A and the other for CIA-B ; standard node $0000 ds.l 1 LN_SUCC $0004 ds.l 1 LN_PRED $0008 ds.b 1 LN_TYPE (NT_RESOURCE) $0009 ds.b 1 LN_PRI (0) $000A ds.l 1 LN_NAME ("ciaa.resource") ; the second instance of this resource has "ciab.resource" here ; library structure ; version, revision and idstring are not set $000E ds.b 1 LIB_FLAGS (0) $000F ds.b 1 LIB_pad $0010 ds.w 1 LIB_NEGSIZE (24) $0012 ds.w 1 LIB_POSSIZE ($7C) $0014 ds.w 1 LIB_VERSION (0) $0016 ds.w 1 LIB_REVISION (0) $0018 ds.l 1 LIB_IDSTRING (0) $001C ds.l 1 LIB_SUM $0020 ds.w 1 LIB_OPENCNT ; resource variables $0022 ds.l 1 CIA hardware base address ($bfe001 or $bfd000) $0026 ds.w 1 interrupt bit in INTREQ $0008 (PORTS) or $2000 (EXTER) $0028 ds.b 1 INT MASK (enabled interrupts) $0029 ds.b 1 INT DATA (caused but not yet serviced interrupts) ; interrupt structure $002A ds.l 1 LN_SUCC = IS_NODE $002E ds.l 1 LN_PRED $0032 ds.b 1 LN_TYPE (NT_INTERRUPT) $0033 ds.b 1 LN_PRI (0) $0034 ds.l 1 LN_NAME $0038 ds.l 1 IS_DATA cia.resource base $003C ds.l 1 IS_CODE interrupt code ; 5 interrupt vectors, one for each interrupt source $0040 struct IntVector TA $004C struct IntVector TB $0058 struct IntVector ALRM $0064 struct IntVector SP $0070 struct IntVector FLG $007C SIZE ; size of the structure ---------------------------------------------------------------------------- cia.resource ROM tag ---------------------------------------------------------------------------- ; this is the disassembly of Kickstart 1.2 ROM at addresses ; $FC4502 - $FC478F, this address range is preceded by ; audio.device and followed by disk.resource FC450C 4AFC RTC_MATCHWORD (start of ROMTAG marker) FC450E 00FC450C RT_MATCHTAG (pointer RTC_MATCHWORD) FC4512 00FC4790 RT_ENDSKIP (pointer to end of code) FC4516 01 RT_FLAGS (RTF_COLDSTART) FC4517 21 RT_VERSION (version number) FC4518 08 RT_TYPE (NT_RESOURCE) FC4519 78 RT_PRI (priority = 120) FC451A 00FC4526 RT_NAME (pointer to name) FC451E 00FC4550 RT_IDSTRING (pointer to ID string) FC4522 00FC4578 RT_INIT (execution address) ; the priority (120) is quite high, cia.resource is the fifth initialized ; resident module, just after exec.library, expansion.library, ; potgo.resource and keymap.resource ---------------------------------------------------------------------------- names, version ---------------------------------------------------------------------------- ; there are two more names here, one for CIA-A instance and the other ; for CIA-B instance of this resouce ; LIB_IDSTRING is not set and thus the id string is used in ROM tag only FC4526 "cia.resource", 00, 00 FC4534 "ciaa.resource", 00 FC4542 "ciab.resource", 00 FC4550 "cia 33.22 (29 Mar 1986)", CR, LF, 00 FC456A 0000 ; padding ---------------------------------------------------------------------------- offset table, 4 entries ---------------------------------------------------------------------------- ; as used in MakeLibrary FC456C FFFF FC456E 0124 ; AddICRVector offset -6 FC4570 017A ; RemICRVector offset -12 FC4572 019E ; AbleICR offset -18 FC4574 01BC ; SetICR offset -24 FC4576 FFFF ---------------------------------------------------------------------------- init routine ---------------------------------------------------------------------------- ; as the RTF_AUTOINIT bit in RT_FLAGS is not set the InitResident calls ; resource's own initialization routine below FC4578 move.l A2,-(SP) ; saves A2 FC457A bsr.s $FC45E2 ; makes library (CIA-A) FC457C move.l #$BFE001,$22(A2) ; base+$22.l = $bfe001 (CIA-A address) FC4584 move.w #8,$26(A2) ; base+$26.w = 8 (bit 3 - PORTS) FC458A move.l #$FC461C,$12(A1) ; base+$3C.l = interrupt code for CIA-A FC4592 moveq #3,D0 FC4594 jsr -$A8(A6) ; AddIntServer, interrupt = base+$2a.l, IntNumber = 3 FC4598 lea $FC4534(PC),A0 ; A0 = "ciaa.resource" FC459C bsr.s $FC45D2 ; sets names and adds resource FC459E bsr.s $FC45E2 ; makes library (CIA-B) FC45A0 lea $BFD000,A0 FC45A6 move.l A0,$22(A2) ; base+$22.l = $bfd000 (CIA-B address) FC45AA moveq #$FFFFFFC0,D0 FC45AC or.b D0,$0200(A0) ; /DTR and /RTS in output mode FC45B0 or.b D0,0(A0) ; /DTR and /RTS inactive (high) FC45B4 move.w #$2000,$26(A2) ; base+$26.w = $2000 (bit 13 - EXTER) FC45BA move.l #$FC4610,$12(A1) ; base+$3C.l = interrupt code for CIA-B FC45C2 moveq #$0D,D0 FC45C4 jsr -$A8(A6) ; AddIntServer, interrupt = base+$2a.l, IntNumber = 13 FC45C8 lea $FC4542(PC),A0 ; A0 = "ciab.resource" FC45CC bsr.s $FC45D2 ; sets names and adds resource FC45CE move.l (SP)+,A2 ; restores A2 and returns FC45D0 rts FC45D2 move.l A0,$0A(A1) ; name of the resource node FC45D6 move.l A0,$0A(A2) ; name of the interrupt node FC45DA move.l A2,A1 ; resource to be added FC45DC jsr -$01E6(A6) ; AddResource FC45E0 rts FC45E2 lea $FC456C(PC),A0 ; table of vectors FC45E6 sub.l A1,A1 ; structure = 0 FC45E8 sub.l A2,A2 ; init = 0 FC45EA moveq #$7C,D0 ; dataSize FC45EC jsr -$54(A6) ; MakeLibrary FC45F0 move.l D0,A2 ; A2 = base of resource FC45F2 move.b #8,8(A2) ; LN_TYPE = NT_RESOURCE FC45F8 clr.b 9(A2) ; LN_PRI = 0 FC45FC lea $2A(A2),A1 ; A1 = base+$2A (struct Interrupt) FC4600 move.b #2,8(A1) ; base+$32.b = 2 (LN_TYPE = NT_INTERRUPT) FC4606 clr.b 9(A1) ; base+$33.b = 0 (LN_PRI = 0) FC460A move.l A2,$0E(A1) ; base+$38.l = IS_DATA (base) FC460E rts ---------------------------------------------------------------------------- iterrupt code A5 = code (this routine), A1 = data (cia.resource base) ---------------------------------------------------------------------------- FC4610 movem.l D2/A2,-(SP) ; entry point for interrupt code for CIA-B FC4614 move.b $BFDD00,D2 ; D2 = ICR FC461A bra.s $FC4626 FC461C movem.l D2/A2,-(SP) ; entry point for interrupt code for CIA-A FC4620 move.b $BFED01,D2 ; D2 = ICR FC4626 bclr #7,D2 FC462A or.b $29(A1),D2 ; ORs it with INT DATA (previous state) FC462E move.b D2,$29(A1) ; stores updated INT DATA FC4632 and.b $28(A1),D2 ; ANDs it with INT MASK FC4636 beq.s $FC4658 ; none of issued interrupts is enabled => end FC4638 move.l A1,A2 ; prepares data into A2 FC463A eor.b D2,$29(A2) ; clears bits which we are just going to process FC463E lsr.b #1,D2 ; bit 0 set? FC4640 bcs.s $FC465E ; yes => call int. vector FC4642 lsr.b #1,D2 ; bit 1 set? FC4644 bcs.s $FC4668 ; yes => call int. vector FC4646 beq.s $FC4658 ; nothing left => finish FC4648 lsr.b #1,D2 ; bit 2 set? FC464A bcs.s $FC4672 ; yes => call int. vector FC464C beq.s $FC4658 ; nothing left => finish FC464E lsr.b #1,D2 ; bit 3 set? FC4650 bcs.s $FC467C ; yes => call int. vector FC4652 beq.s $FC4658 ; nothing left => finish FC4654 lsr.b #1,D2 ; bit 4 set? FC4656 bcs.s $FC4686 ; yes => call int. vector FC4658 movem.l (SP)+,D2/A2 ; and finish FC465C rts FC465E movem.l $40(A2),A1/A5 ; get IV_DATA and IV_CODE for TA FC4664 jsr (A5) ; call IV_CODE FC4666 bra.s $FC4642 ; process further bits FC4668 movem.l $4C(A2),A1/A5 ; get IV_DATA and IV_CODE for TB FC466E jsr (A5) ; call IV_CODE FC4670 bra.s $FC4648 ; process further bits FC4672 movem.l $58(A2),A1/A5 ; get IV_DATA and IV_CODE for ALRM FC4678 jsr (A5) ; call IV_CODE FC467A bra.s $FC464E ; process further bits FC467C movem.l $64(A2),A1/A5 ; get IV_DATA and IV_CODE for SP FC4682 jsr (A5) ; call IV_CODE FC4684 bra.s $FC4654 ; process further bits FC4686 movem.l $70(A2),A1/A5 ; get IV_DATA and IV_CODE for FLG FC468C jsr (A5) ; call IV_CODE FC468E bra.s $FC4658 ; go to finish ---------------------------------------------------------------------------- interrupt = AddICRVector(iCRbit, interrupt) D0 D0 A1 ---------------------------------------------------------------------------- FC4690 moveq #0,D1 FC4692 move.b D0,D1 ; interrupt bit number into D1 FC4694 mulu #$0C,D1 ; D1 = D1 * IV_SIZE FC4698 move.l $0004,A0 ; Disable FC469C move.w #$4000,$DFF09A FC46A4 addq.b #1,$0126(A0) FC46A8 lea $40(A6,D1.w),A0 ; A0 = int. vector to be added to FC46AC move.l 8(A0),D1 ; old IV_NODE into D1 FC46B0 bne.s $FC46E2 ; not zero? vector already in use FC46B2 move.l A1,8(A0) ; puts IS_NODE into IV_NODE FC46B6 move.l $12(A1),4(A0) ; puts IS_CODE into IV_CODE FC46BC move.l $0E(A1),0(A0) ; puts IS_DATA into IV_DATA FC46C2 move.w #$80,D1 ; enables this interrupt FC46C6 bset D0,D1 ; sets the particular interrupt bit FC46C8 move.w D1,D0 ; puts it into D0 FC46CA bsr.s $FC470A ; calls AbleICR FC46CC moveq #0,D0 ; zero = success FC46CE move.l $0004,A0 ; Enable FC46D2 subq.b #1,$0126(A0) FC46D6 bge.s $FC46E0 FC46D8 move.w #$C000,$DFF09A FC46E0 rts FC46E2 move.l D1,D0 ; returns IV_NODE in use FC46E4 bra.s $FC46CE ; and go to end ---------------------------------------------------------------------------- RemICRVector(iCRbit, interrupt) D0 A1 ---------------------------------------------------------------------------- FC46E6 moveq #0,D1 FC46E8 move.b D0,D1 ; interrupt bit number into D1 FC46EA mulu #$0C,D1 ; D1 = D1 * IV_SIZE FC46EE move.l $0004,A0 ; Disable FC46F2 move.w #$4000,$DFF09A FC46FA addq.b #1,$0126(A0) FC46FE lea $40(A6,D1.w),A0 ; A0 = int. vector to be removed from FC4702 clr.l 8(A0) ; IV_NODE = 0 FC4706 moveq #0,D1 FC4708 bra.s $FC46C6 ; and disables particular interrupt ---------------------------------------------------------------------------- oldMask = AbleICR(mask) D0 D0 ---------------------------------------------------------------------------- FC470A move.l $0004,A0 ; Disable FC470E move.w #$4000,$DFF09A FC4716 addq.b #1,$0126(A0) FC471A move.l $22(A6),A0 ; CIA address FC471E move.b D0,$0D00(A0) ; puts the mask into ICR FC4722 lea $28(A6),A1 ; A1 = INT MASK FC4726 bra.s $FC474C ; further process INT MASK variable ---------------------------------------------------------------------------- oldMask = SetICR(mask) D0 D0 ---------------------------------------------------------------------------- FC4728 move.l $0004,A0 ; Disable FC472C move.w #$4000,$DFF09A FC4734 addq.b #1,$0126(A0) FC4738 move.l $22(A6),A0 ; CIA address FC473C move.b $0D00(A0),D1 ; ICR into D1 FC4740 bclr #7,D1 ; clears IR bit FC4744 or.b D1,$29(A6) ; ORs it with INT DATA FC4748 lea $29(A6),A1 FC474C moveq #0,D1 FC474E move.b (A1),D1 ; old INT MASK / INT DATA FC4750 tst.b D0 ; will be changed? FC4752 beq.s $FC4762 ; no => finish FC4754 bclr #7,D0 ; clears the set/clr bit FC4758 bne.s $FC4760 ; whe add bits to INT MASK / INT DATA FC475A not.b D0 ; we will remove bits from INT MASK / INT DATA FC475C and.b D0,(A1) FC475E bra.s $FC4762 ; skip adding new bits FC4760 or.b D0,(A1) ; add new bits FC4762 move.b $28(A6),D0 ; INT MASK AND it with FC4766 and.b $29(A6),D0 ; INT DATA => any interrupt to be requested? FC476A beq.s $FC477A ; no => finish FC476C move.w $26(A6),D0 ; yes => sets interrupt in INTREQ FC4770 or.w #$8000,D0 FC4774 move.w D0,$DFF09C FC477A move.l $0004,A0 ; Enable FC477E subq.b #1,$0126(A0) FC4782 bge.s $FC478C FC4784 move.w #$C000,$DFF09A FC478C move.l D1,D0 FC478E rts