[Contents] [index] [Help] [Retrace] [browse <] [Browse >]

When your AUTOCONFIG hardware board is configured by the expansion
initialization routine, its expansionrom structure is copied into the
ExpansionRom subfield of a configdev structure.  this configdev structure
will be linked to the expansion.library's private list of configured
boards.

After the board is configured, the er_Type field of its expansionrom
structure is checked.  The DIAGVALID bit set declares that there is a
valid DiagArea (a ROM/diagnostic area) on this board.  If there is a valid
DiagArea, expansion next tests the er_InitDiagVec vector in its copy of
the ExpansionRom structure.  This offset is added to the base address of
the configured board; the resulting address points to the start of this
board's DiagArea.

    struct ExpansionRom
    {
        UBYTE   er_Type;          /* <-- if ERTB_DIAGVALID set */
        UBYTE   er_Product;
        UBYTE   er_Flags;
        UBYTE   er_Reserved03;
        UWORD   er_Manufacturer;
        ULONG   er_SerialNumber;
        UWORD   er_InitDiagVec;   /* <-- then er_InitDiagVec      */
        UBYTE   er_Reserved0c;    /*     is added to cd_BoardAddr */
        UBYTE   er_Reserved0d;    /*     and points to DiagArea   */
        UBYTE   er_Reserved0e;
        UBYTE   er_Reserved0f;
    };

Now expansion knows that there is a diagarea, and knows where it is.

     struct DiagArea
     {
         UBYTE   da_Config;        /* <-- if DAC_CONFIGTIME is set */
         UBYTE   da_Flags;
         UWORD   da_Size;          /* <-- then da_Size bytes will  */
         UWORD   da_DiagPoint;     /*     be copied into RAM       */
         UWORD   da_BootPoint;
         UWORD   da_Name;
         UWORD   da_Reserved01;
         UWORD   da_Reserved02;
     };

    /* da_Config definitions */
    #define DAC_BUSWIDTH    0xC0  /* two bits for bus width */
    #define DAC_NIBBLEWIDE  0x00
    #define DAC_BYTEWIDE    0x40  /* invalid for 1.3 - see note below */
    #define DAC_WORDWIDE    0x80

    #define DAC_BOOTTIME    0x30  /* two bits for when to boot */
    #define DAC_NEVER       0x00  /* obvious */
    #define DAC_CONFIGTIME  0x10  /* call da_BootPoint when first
                                     configging the device */
    #define DAC_BINDTIME    0x20  /* run when binding drivers to boards */

Next, expansion tests the first byte of the DiagArea structure to
determine if the CONFIGTIME bit is set.  If this bit is set, it checks the
da_BootPoint offset vector to make sure that a valid bootstrap routine
exists.  If so, expansion copies da_Size bytes into RAM memory, starting
at beginning of the DiagArea structure.

The copy will include the DiagArea structure itself, and typically will
also include the da_DiagPoint ROM/diagnostic routine, a resident structure
(romtag), a device driver (or at least the device initialization tables or
structures which need patching), and the da_BootPoint routine.  In
addition, the bootnode and parameter packet for makedosnode() may be
included in the copy area for Diag-time patching.  Strings such as DOS and
Exec device names, library names, and the romtag ID string may also be
included in the copy area so that both position-independent ROM code and
position-independent routines in the copy area may reference them PC
relative.

The copy will be made either nibblewise, or wordwise, according to the
BUSWIDTH subfield of da_Config. Note that the da_BootPoint offset must be
non-NULL, or else no copy will occur. (Note - under 1.3, DAC_BYTEWIDE is
not supported. Byte wide ROMs must use DAC_NIBBLEWIDE and drivers must
supply additional code to re-copy their DiagArea)

The following illustrates an example Diag copy area, and specifies the
various fields which should be coded as relative offsets for later
patching by your DiagPoint routine.


                      Example DiagArea Copy in RAM

DiagStart:          ; a struct DiagArea
            CCFF    ; da_Config, da_Flags
            SIZE    ; da_Size         - coded as EndCopy-DiagStart
            DIAG    ; da_DiagPoint    - coded as DiagEntry-DiagStart
            BOOT    ; da_BootPoint    - coded as BootEntry-DiagStart
            NAME    ; da_Name         - coded as DevName-DiagStart
            0000    ; da_Reserved01   - Above fields above are supposed
            0000    ; da_Reserved02     to be relative. No patching needed

Romtag:     rrrr    ; a struct Resident ("Romtag")
            ...       RT_MATCHTAG, RT_ENDSKIP, RT_NAME and  RT_IDSTRING
            ...       addresses are coded relatively as label-DiagStart.
            ...       The RT_INIT vector is coded as a relative offset
            ...       from the start of the ROM.  DiagEntry patches these.

DevName:    ssss..0 ; The name string for the exec device
IdString:   iiii..0 ; The ID string for the Romtag

BootEntry:  BBBB    ; Boot-time code
            ...

DiagEntry:  DDDD    ; Diag-time code (position independent)
            ...       When called, performs patching of the relative-
                      coded addresses which need to be absolute.
OtherData:
            dddd    ; Device node or structs/tables (patch names, vectors)
            bbbb    ; BootNode (patch ln_Name and bn_DeviceNode)
            pppp    ; MakeDosNode packet (patch dos and exec names)

            ssss    ; other name, ID, and library name strings
            ...
EndCopy:


Now the ROM "image" exists in RAM memory.  Expansion stores the ULONG
address of that "image" in the UBYTES er_Reserved0c, 0d, 0e and 0f.  The
address is stored with the most significant byte in er_Reserved0c, the
next to most significant byte in er_Reserved0d, the next to least
significant byte in er_Reserved0e, and the least significant byte in
er_Reserved0f - i.e., it is stored as a longword at the address
er_Reserved0c.

Expansion finally checks the da_DiagPoint offset vector, and if valid
executes the ROM/diagnostic routine contained as part of the ROM "image".
This diagnostic routine is responsible for patching the ROM image so that
required absolute addresses are relocated to reflect the actual location
of code and strings, as well as performing any diagnostic functions
essential to the operation of its associated AUTOCONFIG board. The
structures which require patching are located within the copy area so that
they can be patched at this time. Patching is required because many of the
structures involved require absolute pointers to such things as name
strings and code, but the absolute locations of the board and the RAM copy
area are not known when code the structures.

The patching may be accomplished by coding pointers which require absolute
addresses instead as relative offsets from either the start of the
DiagArea structure, or the start of the board's ROM (depending on whether
the final absolute pointer will point to a RAM or ROM location). The Diag
routine is passed both the actual base address of the board, and the
address of the Diag copy area in RAM. The routine can then patch the
structures in the Diag copy area by adding the appropriate address to
resolve each pointer.

Example DiagArea and Diag patching routine:

     diag.asm 

Your da_DiagPoint ROM/diagnostic routine should return a non-zero value to
indicate success;  otherwise the ROM "image" will be unloaded from memory,
and its address will be replaced with NULL bytes in locations
er_Reserved0c, 0d, 0e and 0f.

Now that the ROM "image" has been copied into RAM, validated, and linked
to board's configdev structure, the expansion module is free to configure
all other boards on the utility.library's private list of boards.

It may help to see just how a card's ROM AUTOCONFIG information
corresponds to the ExpansionRom structure.  This chart shows the contents
of on-card memory for a fictional expansion card.  Note that the
ExpansionRom.Flags field ($3F in addresses $08/$0A below) is shown
interpreted in its inverted form of $3F.  Once the value is uninverted to
become $C0, you should use the #defines in <libraries/configregs.h> to
interpret it.


Table 32-1: Sample Zorro II AUTOCONFIG ROM Information Viewed as a Hex Dump


            FLAG AND FIELD DEFINITIONS                THIS BOARD
    -----------------------------------------------------------------
              1xxx chained                          11 = Normal type
              x111 size                             Don't addmem
              000=8meg,001=64K,010=128K,etc.        ROM Vector Valid
     11xx type     /        1xxx nopref             Not chained
     xx1x addmem  /         x1xx canshut            Size 256K
     xxx1 ROM    /          xx11 reserved           Product#=~$FE=1
        \       / ~Prod#      /                     Flags=~$3F=$C0
         \     /   /  \      /  res. reserved       Prefer exp space
    0000: D0003000 F000E000 3000F000 F000F000       Can't be shut up
    -----------------------------------------------------------------
          ~Manufacturer#    ~HiWord Serial#    Manu#=~$F824=$7DB=2011
           /   /  \   \      /   /  \   \      HiSer=~$FFDA=$0025=37
    0010: F0008000 20004000 F000F000 D000A000
    -----------------------------------------------------------------
          ~LoWord Serial#    ~Rom Vector       LoSer=~$FFFE=$0001=1
           /   /  \ \      /   /  \   \      Rom Vector=~$FF7F=$80
    0020: F000F000 F000E000 F000F000 7000F000        from board base
    -----------------------------------------------------------------


The AUTOCONFIG information from the above card would appear as follows in
an ExpansionRom structure:


        Nibble Pairs        ExpansionRom Field    Value
        ------------        ------------------    -----
        00/02               er_Type               $D3
        04/06               er_Product            $01 = 1
        08/0A               er_Flags              $C0
        10/12 and 14/16     er_Manufacturer       $07DB = 2011
        18/1A thru 24/26    er_SerialNumber       $00250001
        28/2A and 2C/2E     er_InitDiagVec        $0080


If a card contains a ROM driver (Rom Vector valid), and the vector is at
offset $80 (as in this example) the DiagArea structure will appear at
offset $0080 from the base address of the board.  This example card's
resident structure (romtag) directly follows its diagarea structure.


       WORDWIDE+CONFIGTIME              ROMTAG
        \ flags    DiagPt   Devname     starts
         \ \ DAsize  / BootPt /          here       DiagPt, BootPt,
          \ \  /\   /\  /\   /\ res. res. /\        DevName relative
    0080: 90000088 004A0076 00280000 00004AFC       to Diag struct
    -----------------------------------------------------------------
                       COLDSTART  NT_DEVICE         backptr,endskip,
                           \ ver  /priority         and DevName coded
          backptr  endskip  \ \  / /  DevName       relative, patched
    0090: 0000000E 00000088 01250314 00000028       at Diag time
    -----------------------------------------------------------------
                                                    ID and InitEntry
          IDstring InitEntry                        coded relative,
    00A0: 00000033 00000116                         patched at Diag
    -----------------------------------------------------------------