[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

**
** Sample autoboot code fragment
**
** These are the calling conventions for the Diag routine
**
** A7 -- points to at least 2K of stack
** A6 -- ExecBase
** A5 -- ExpansionBase
** A3 -- your board's ConfigDev structure
** A2 -- Base of diag/init area that was copied
** A0 -- Base of your board
**
** Your Diag routine should return a non-zero value in D0 for success.
** If this value is NULL, then the diag/init area that was copied
** will be returned to the free memory pool.
**

            INCLUDE "exec/types.i"
            INCLUDE "exec/nodes.i"
            INCLUDE "exec/resident.i"
            INCLUDE "libraries/configvars.i"

            ; LVO's resolved by linking with library amiga.lib
            XREF   _LVOFindResident

ROMINFO     EQU      1
ROMOFFS     EQU     $0

* ROMINFO defines whether you want the AUTOCONFIG information in
* the beginning of your ROM (set to 0 if you instead have PALS
* providing the AUTOCONFIG information instead)
*
* ROMOFFS is the offset from your board base where your ROMs appear.
* Your ROMs might appear at offset 0 and contain your AUTOCONFIG
* information in the high nibbles of the first $40 words ($80 bytes).
* Or, your autoconfig ID information may be in a PAL, with your
* ROMs possibly being addressed at some offset (for example $2000)
* from your board base.  This ROMOFFS constant will be used as an
* additional offset from your configured board address when patching
* structures which require absolute pointers to ROM code or data.

*----- We'll store Version and Revision in serial number
VERSION 	EQU	37		; also the high word of serial number
REVISION	EQU	1		; also the low word of serial number

* See the Addison-Wesley Amiga Hardware Manual for more info.

MANUF_ID	EQU	2011		; CBM assigned (2011 for hackers only)
PRODUCT_ID	EQU	1		; Manufacturer picks product ID

BOARDSIZE	EQU	$40000          ; How much address space board decodes
SIZE_FLAG	EQU	3		; Autoconfig 3-bit flag for BOARDSIZE
					;   0=$800000(8meg)  4=$80000(512K)
					;   1=$10000(64K)    5=$100000(1meg)
					;   2=$20000(128K)   6=$200000(2meg)
					;   3=$40000(256K)   7=$400000(4meg)
            CODE

*******  RomStart  ***************************************************
**********************************************************************

RomStart:

	IFGT    ROMINFO
;
;   ExpansionRom structure
;
;   Note - If you implement your ExpansionRom and ExpansionControl
;   with PALS, then you can comment out everything until DiagStart:
;   (ie. Make ROMID EQU 0)

*    ; High nibbles of first two words ($00,$02) are er_Type (not inverted)
						; er_Type
		dc.w	$D000			;   11xx normal board type
						;   xx0x not in memory free list
						;   xxx1 Diag valid (has driver)
		dc.w	(SIZE_FLAG<<12)&$7000	;   0xxx not chained
						;   xnnn flags board size

*    ; High nibbles of next two words are er_Product
*    ; These are inverted (~), as are all other words except $40 and $42

						; er_Product
		dc.w	(~(PRODUCT_ID<<8))&$f000,(~(PRODUCT_ID<<12))&$f000

						; er_Flags
		dc.w	(~$C000)&$f000		;   ~1xxx board is moveable
						;   ~x1xx board can't be shut up
		dc.w	(~0)&$f000		;

		dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved03

						; er_Manufacturer
		dc.w	(~(MANUF_ID))&$f000,(~(MANUF_ID<<4))&$f000
		dc.w	(~(MANUF_ID<<8))&$f000,(~(MANUF_ID<<12))&$f000

						; er_SerialNumber
		dc.w	(~(VERSION))&$f000,(~(VERSION<<4))&$f000
		dc.w	(~(VERSION<<8))&$f000,(~(VERSION<<12))&$f000
		dc.w	(~(REVISION))&$f000,(~(REVISION<<4))&$f000
		dc.w	(~(REVISION<<8))&$f000,(~(REVISION<<12))&$f000

						; er_InitDiagVec
		dc.w	(~((DiagStart-RomStart)))&$f000
		dc.w	(~((DiagStart-RomStart)<<4))&$f000
		dc.w	(~((DiagStart-RomStart)<<8))&$f000
		dc.w	(~((DiagStart-RomStart)<<12))&$f000

		dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0c
		dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0d
		dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0e
		dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0f

	IFNE	*-RomStart-$40
	FAIL	"ExpansionRom structure not the right size"
	ENDC

		;Note: nibbles $40 and $42 are not to be inverted
		dc.w	(0)&$f000,(0)&$f000	; ec_Interrupt (no interrupts)
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved11
		dc.w	(~0)&$f000,(~0)&$f000	; ec_BaseAddress (write only)
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Shutup (write only)
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved14
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved15
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved16
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved17
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved18
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved19
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1a
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1b
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1c
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1d
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1e
		dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1f

	IFNE	*-RomStart-$80
	FAIL	"Expansion Control structure not the right size"
	ENDC

	ENDC	;ROMINFO

*******  DiagStart  **************************************************
DiagStart:  ; This is the DiagArea structure whose relative offset from
            ; your board base appears as the Init Diag vector in your
            ; autoconfig ID information.  This structure is designed
            ; to use all relative pointers (no patching needed).
            dc.b    DAC_WORDWIDE+DAC_CONFIGTIME    ; da_Config
            dc.b    0                              ; da_Flags
            dc.w    EndCopy-DiagStart              ; da_Size
            dc.w    DiagEntry-DiagStart            ; da_DiagPoint
            dc.w    BootEntry-DiagStart            ; da_BootPoint
            dc.w    DevName-DiagStart              ; da_Name
            dc.w    0                              ; da_Reserved01
            dc.w    0                              ; da_Reserved02

*******  Resident Structure  *****************************************
Romtag:
            dc.w    RTC_MATCHWORD      ; UWORD RT_MATCHWORD
rt_Match:   dc.l    Romtag-DiagStart   ; APTR  RT_MATCHTAG
rt_End:     dc.l    EndCopy-DiagStart  ; APTR  RT_ENDSKIP
            dc.b    RTW_COLDSTART      ; UBYTE RT_FLAGS
            dc.b    VERSION            ; UBYTE RT_VERSION
            dc.b    NT_DEVICE          ; UBYTE RT_TYPE
            dc.b    20                 ; BYTE  RT_PRI
rt_Name:    dc.l    DevName-DiagStart  ; APTR  RT_NAME
rt_Id:      dc.l    IdString-DiagStart ; APTR  RT_IDSTRING
rt_Init:    dc.l    Init-RomStart      ; APTR  RT_INIT


******* Strings referenced in Diag Copy area  ************************
DevName:    dc.b    'abc.device',0                      ; Name string
IdString    dc.b    'abc ',48+VERSION,'.',48+REVISION   ; Id string

DosName:    dc.b    'dos.library',0                ; DOS library name

DosDevName: dc.b    'ABC',0        ; dos device name for MakeDosNode()
                                   ;   (dos device will be ABC:)

            ds.w    0              ; word align

*******  DiagEntry  **************************************************
**********************************************************************
*
*   success = DiagEntry(BoardBase,DiagCopy, configDev)
*   d0                  a0         a2                  a3
*
*   Called by expansion architecture to relocate any pointers
*   in the copied diagnostic area.   We will patch the romtag.
*   If you have pre-coded your MakeDosNode packet, BootNode,
*   or device initialization structures, they would also need
*   to be within this copy area, and patched by this routine.
*
**********************************************************************

DiagEntry:
            lea      patchTable-RomStart(a0),a1   ; find patch table
            adda.l   #ROMOFFS,a1                  ; adjusting for ROMOFFS

* Patch relative pointers to labels within DiagCopy area
* by adding Diag RAM copy address.  These pointers were coded as
* long relative offsets from base of the DiagArea structure.
*
dpatches:
            move.l   a2,d1           ;d1=base of ram Diag copy
dloop:
            move.w   (a1)+,d0        ;d0=word offs. into Diag needing patch
            bmi.s    bpatches        ;-1 is end of word patch offset table
            add.l    d1,0(a2,d0.w)   ;add DiagCopy addr to coded rel. offset
            bra.s    dloop

* Patches relative pointers to labels within the ROM by adding
* the board base address + ROMOFFS.  These pointers were coded as
* long relative offsets from RomStart.
*
bpatches:
            move.l   a0,d1           ;d1 = board base address
            add.l    #ROMOFFS,d1     ;add offset to where your ROMs are
rloop:
            move.w   (a1)+,d0        ;d0=word offs. into Diag needing patch
            bmi.s   endpatches       ;-1 is end of patch offset table
            add.l   d1,0(a2,d0.w)    ;add ROM address to coded relative offset
            bra.s   rloop

endpatches:
            moveq.l #1,d0           ; indicate "success"
            rts


*******  BootEntry  **************************************************
**********************************************************************

BootEntry:  lea     DosName(PC),a1          ; 'dos.library',0
            jsr     _LVOFindResident(a6)    ; find the DOS resident tag
            move.l  d0,a0                   ; in order to bootstrap
            move.l  RT_INIT(A0),a0          ; set vector to DOS INIT
            jsr     (a0)                    ; and initialize DOS
            rts

*
* End of the Diag copy area which is copied to RAM
*
EndCopy:
*************************************************************************

*************************************************************************
*
*   Beginning of ROM driver code and data that is accessed only in
*   the ROM space.  This must all be position-independent.
*

patchTable:
* Word offsets into Diag area where pointers need Diag copy address added
            dc.w   rt_Match-DiagStart
            dc.w   rt_End-DiagStart
            dc.w   rt_Name-DiagStart
            dc.w   rt_Id-DiagStart
            dc.w   -1

* Word offsets into Diag area where pointers need boardbase+ROMOFFS added
            dc.w   rt_Init-DiagStart
            dc.w   -1

*******  Romtag InitEntry  **********************************************
*************************************************************************

Init:       ; After Diag patching, our romtag will point to this
            ; routine in ROM so that it can be called at Resident
            ; initialization time.
            ; This routine will be similar to a normal expansion device
            ; initialization routine, but will MakeDosNode then set up a
            ; BootNode, and Enqueue() on eb_MountList.
            ;
            rts

            ; Rest of your position-independent device code goes here.

            END