;*********************************************************************
;*                       Origin and Purpose                          *
;*                                                                   *
;* This device represents things I would liked to have known when    *
;* starting out writing devices.  I found it hard to get firm data   *
;* on device design, and collected everything I could find into this *
;* file.  Sure it has lots of comments, but it makes a great basic   *
;* skeleton or classroom presentation.                               *
;*                                                                   *
;* I apologize in advance for any bugs, oversights or errors.  As    *
;* always, corrections and design tips are welcome.                  *
;*                                                                   *
;* Send comments, flames, etc. to the following:                     *
;*                                                                   *
;*                             Tau Productions                       *
;*                             Jeff Rush                             *
;*                             BIX: jrush                            *
;*                             BBS: (214) 231-1372 Rising Star       *
;*                             Fidonet: 1:124/4206 (Dallas, Tx)      *
;*                                                                   *
;* All changes I made are hereby in the Public Domain.  Commodore    *
;* retains its copyright, if any, of the original code in the Rom    *
;* Kernel manuals since this is a derivative work.  -Jeff Rush       *
;*                                                                   *
;*********************************************************************
;*                           History                                 *
;*                                                                   *
;* 20Sep89 jrr Original crib from Amiga Rom Kernel Manual.           *
;* 23Jul90 jrr Extensive descriptive prose added.                    *
;*                                                                   *
;*********************************************************************
        TITLE   Example Device Driver for Tutorial Use
        SMALLOBJ    ; Use PC-Relative Addressing
        OPTIMON     ; Enable C.A.P.E. 68K Optimizations

        SECTION TheOnlySection

        ;************
        ;* Includes *
        ;************
        NOLIST
        INCLUDE "exec/types.i"
        INCLUDE "exec/devices.i"
        INCLUDE "exec/initializers.i"
        INCLUDE "exec/memory.i"
        INCLUDE "exec/resident.i"
        INCLUDE "exec/io.i"
        INCLUDE "exec/ables.i"
        INCLUDE "exec/errors.i"
        INCLUDE "exec/tasks.i"
        INCLUDE "exec/semaphores.i"
        INCLUDE "hardware/intbits.i"

        INCLUDE "asmsupp.i"

        INCLUDE "Example.i"     ; Device-Specific Definitions
        LIST

        ;*************
        ;* Constants *
        ;*************
VERSION     EQU 1       ; Version of This Device
REVISION    EQU 1       ; Revision of This Device

        ;******************
        ;* Public Symbols *
        ;******************
        ; This Name is for Debugging Use, to Annotate Serial-Debug Output
        IFNE    INFO_LEVEL      ; If Any Debugging Enabled at All
        XDEF    subSysName
        ENDC

        XDEF    CmdTable    ; Device Global Command Dispatch Table
        XDEF    MyName      ; Name of This Device (for Tagging Ports and Tasks)

        ;********************
        ;* External Symbols *
        ;********************

        ; Defined in Ex_Support.Asm
        XREF    EndCode         ; Label at End of Device Code

        ; Defined in Ex_EntryPts.Asm
        XREF    LoadInitRoutine ; Initialization when Device First Loads into Memory
        XREF    DevOpen         ; Unit Allocation for Each Time Device is Opened
        XREF    DevClose        ; Unit Deallocation for Each Time Device is Opened
        XREF    DevExpunge      ; Remove Device from Memory if No One is Using It
        XREF    DevNull         ; Reserved for Future Expansion
        XREF    DevBeginIO      ; Initiate an I/O Request either Now or Put in Queue
        XREF    DevAbortIO      ; Abort an I/O Request either Active or in Queue

        ; Defined in Ex_StdCmds.Asm
        XREF    CmdInvalid      ; Handle an Unknown or Out-of-Range Command
        XREF    CmdReset        ; Reset the Device
        XREF    CmdRead         ; Read Data from the Device for Caller
        XREF    CmdWrite        ; Write Data into the Device from Caller
        XREF    CmdUpdate       ; Force Outbound Data from Caches onto Device
        XREF    CmdClear        ; Discard All Pending Unread Data inside Device
        XREF    CmdStop         ; Suspend Device Operations
        XREF    CmdStart        ; Resume Device Operations
        XREF    CmdFlush        ; Discard All Queued but Unprocessed I/O Requests

;*********************************************************************
;*                    First Executable Location                      *
;*********************************************************************
        MOVEQ   #-1,D0  ; Return Failure Result Code
        RTS             ; (In case user tried to execute us as a program)

;*********************************************************************
;*                        ROMTAG Structure                           *
;*                                                                   *
;* This ROMTAG is used by Exec to construct a device node in memory  *
;* when the device code is loaded.  The setup sequence appears to be *
;* as follows: (Assuming a standard AUTOINIT-flag environment)       *
;*                                                                   *
;*  1) Exec receives a request to open a device.                     *
;*  2) Exec realizes it is not in memory at this time.               *
;*  3) Exec locates it on disk in the global directory DEVS:.        *
;*  4) Exec scatter-loads it into memory as a Segment List (seglist) *
;*  5) Exec scans the first hunk loaded for a ROMTAG signature and   *
;*     invokes an InitResident() Exec function on it. InitResident() *
;*     performs steps 6, 7 and 8 below.                              *
;*  6) Exec examines the Initialization Table pointed to in the      *
;*     ROMTAG and allocates a device node structure of the correct   *
;*     size in memory.  This is performed by the Exec function       *
;*     MakeLibrary() which also performs step 7 below.               *
;*  7) Continuing to use the Initialization Table, Exec then         *
;*     a) copies the function vector table into the device node,     *
;*        using MakeFunctions().                                     *
;*     b) initializes the device's global data space according       *
;*        to the INITSTRUCTs detailed in the DataTable, using the    *
;*        function InitStruct().                                     *
;*     c) calls the loadtime initialization code (if the code ptr is *
;*        non-NULL).                                                 *
;*  8) If the loadtime initialization code returns a zero (NULL) in  *
;*     D0, Exec  unloads the device and fails the caller's original  *
;*     open request.  Otherwise the loadtime initialization code     *
;*     returns the address of the device node structure.             *
;*  9) Exec then links the device node into the global system list   *
;*     of known Exec devices.                                        *
;* 10) Lastly, Exec invokes the device's open routine using the      *
;*     vector table setup earlier in the device node.                *
;*                                                                   *
;* In the case of an OpenDevice() request where the device is        *
;* already in memory, either because someone else has it open or     *
;* because someone used it recently, only step 10 above is executed. *
;*                                                                   *
;* High Memory                                                       *
;*                 +-----------------------------------+             *
;*                 | Device's Global Data Area         |             *
;*                 | (Contents specific to device)     |             *
;*                 +-----------------------------------+             *
;*  Device Ptr ===>| Library Node Structure:           |             *
;*                 |   Version, Revision               |             *
;*                 |   Various Flags                   |             *
;*                 |   NegSize                         |             *
;*                 |   PosSize                         |             *
;*                 |   IdString                        |             *
;*                 |   OpenCnt                         |             *
;*                 +-----------------------------------+             *
;*                 | Vector (Jump) Table:              |             *
;*                 |   OPEN     (Device Ptr Offset -6) |             *
;*                 |   CLOSE    (  "     "    "   -12) |             *
;*                 |   EXPUNGE  (  "     "    "   -18) |             *
;*                 |   NULLFUNC (  "     "    "   -24) |             *
;*                 |   BEGINIO  (  "     "    "   -30) |             *
;*                 |   ABORTIO  (  "     "    "   -36) |             *
;*                 +-----------------------------------+             *
;* Low Memory                                                        *
;*********************************************************************
MyRomTag:
        DC.W    RTC_MATCHWORD   ; UWORD RT_MATCHWORD (Signature)
        DC.L    MyRomTag        ; APTR  RT_MATCHTAG  (Back Ptr to Myself)
        DC.L    EndCode         ; APTR  RT_ENDSKIP   (Ptr to End of This Hunk)
        DC.B    RTF_AUTOINIT    ; UBYTE RT_FLAGS     (Flags)
        DC.B    VERSION         ; UBYTE RT_VERSION   (Major Version#)
        DC.B    NT_DEVICE       ; UBYTE RT_TYPE      (Type of Module)
        DC.B    0               ; BYTE  RT_PRI       (Initialization Priority)
        DC.L    MyName          ; APTR  RT_NAME      (Ptr to Node Name)
        DC.L    MyID            ; APTR  RT_IDSTRING  (Ptr to ID String)
        DC.L    InitTable       ; APTR  RT_INIT      (Ptr to Initialization Table)

        ; This Name is for Debugging Use, to Annotate Serial-Debug Output
        IFNE    INFO_LEVEL  ;If any debugging enabled at all
subSysName:
        DC.B    'Example',0
        ENDC

MyID:   DC.B    'Example 1.2 (25 Jul 1990)',13,10,0

MyName: DC.B    'Example.device',0                  ; Name of My Device

        ;*****************************************************************
        ;* The Romtag specified above states that we were RTF_AUTOINIT.  *
        ;* This means that the RT_INIT structure member points to one of *
        ;* these tables below.  If the AUTOINIT bit was not set then     *
        ;* RT_INIT would point to a routine to run.                      *
        ;*****************************************************************
        CNOP    0,4               ; Force Long Word Alignment
InitTable:
        DC.L    MyDev_Sizeof      ; Size of My Device's Global Data Space
        DC.L    CodeTable         ; Ptr to Table of Function Vectors
        DC.L    DataTable         ; Ptr to Table of Data Initializers
        DC.L    LoadInitRoutine   ; Loadtime Initialization Routine to Execute

CodeTable:      ; These Function Pointers are Order-Dependent
        DC.L    DevOpen           ; Open a Unit of the Device
        DC.L    DevClose          ; Close a Unit of the Device
        DC.L    DevExpunge        ; Expunge (Remove from Memory) the Device
        DC.L    DevNull           ; Reserved¨for Future Use
        DC.L    DevBeginIO        ; Begin (either now or put in queue) an I/O Request
        DC.L    DevAbortIO        ; Abort an Existing I/O Request
        DC.L    -1                ; End of Table

        ;***********************************************************************
        ;* The data table initializes static data structures. The format is    *
        ;* specified in exec/InitStruct routine's manual pages.  The INITBYTE/ *
        ;* INITWORD/INITLONG macros are in the file "exec/initializers.i". The *
        ;* first argument is the offset from the device base for this byte/    *
        ;* word/long. The second argument is the value to put in that cell.    *
        ;***********************************************************************
        CNOP    0,4               ; Force Long Word Alignment
DataTable:
        INITBYTE   LN_TYPE,NT_DEVICE        ; Set Node Type to 'Device'
        INITLONG   LN_NAME,MyName           ; Set Node Name Ptr to My Name
        INITBYTE   LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
        INITWORD   LIB_VERSION,VERSION      ; Set Device Major Version
        INITWORD   LIB_REVISION,REVISION    ; Set Device Minor Version
        INITLONG   LIB_IDSTRING,MyID        ; Set ID String Ptr to My ID
        DC.L       0                        ; End of Table

        ;******************************************
        ;* Device-Specific Command Dispatch Table *
        ;******************************************
CmdTable:
        DC.L    CmdInvalid    ;$00000001  ;0  CMD_INVALID     Signal Invalid Command
        DC.L    CmdReset      ;$00000002  ;1  CMD_RESET       Reset Device to Initialized State
        DC.L    CmdRead       ;$00000004  ;2  CMD_READ        Read Data from Device
        DC.L    CmdWrite      ;$00000008  ;3  CMD_WRITE       Write Data to Device
        DC.L    CmdUpdate     ;$00000010  ;4  CMD_UPDATE      Flush Device Caches Out
        DC.L    CmdClear      ;$00000020  ;5  CMD_CLEAR       Discard Queued Input Data
        DC.L    CmdStop       ;$00000040  ;6  CMD_STOP        Restart Device Operations
        DC.L    CmdStart      ;$00000080  ;7  CMD_START       Suspend Device Operations
        DC.L    CmdFlush      ;$00000100  ;8  CMD_FLUSH       Discard Queued Write Requests

;*********************************************************************
;*                                                                   *
;*********************************************************************
        END

