        TITLE   *** SDOS DRIVERS FOR Smoke Signal Broadcasting (C) 1981 SOFTWARE DYNAMICS ***
        PCC     1
        NAME    SDOSDRIVERS
        PSR     0                      don't print skipped records
        PCA     0                      don't print conditional assembly records
        PCC     0
*
*       BY SOFTWARE DYNAMICS
*       AND A CAST OF THOUSANDS!
*
EDITDATE        EQU     $1120          /83 MMDD IN HEX FORMAT
EDITYEAR        EQU     $1983
*
*
*********************************************************************
*   I/O PACKAGE STRUCTURE
*   The I/O package is organized in the following fashion:
*
*   Low addresses: !                   !
*                  !  Read-only code,  !
*                  !   tables, etc.    !
*                  !-------------------!
*                  !                   !
*                  !  Interrupt poll   !
*                  !     chains        !
*                  !   (readonly)      !
*                  !                   !
*                  !-------------------!
*                  !                   !
*                  !  Working storage, !
*                  !  DCBs, TCBs, etc. !
*                  !                   !
*                  !-------------------!
*                  !                   !
*                  !    Disk Buffer    !
*                  !       Pool        !
*                  !    I/O Driver     !
*                  !    Reset code     !
*                  !    (once-only)    !
*                  !                   !
*                  !-------------------!
*                  !                   !
*                  !   VT Drivers      !
*                  !      SDOS         !
*                  !     ....          !
*
        PAGE
*       To make this arrangement possible, each I/O package source is
*       organized in the following way:
*               IOxxxxx.DO      is a file containing a configuration
*                               for machine xxxxx
*               IOxxxxx.ASM     is a file containing an I/O package "shell"
*               IOyyyyy.ASM     is a file containing ALL driver-related code
*                               tables, etc. for the hardware device yyyyyy
*
*       Each I/O package shell uses conditional assembly switches to conditionally
*       INCLUDE IOyyyyy.ASM in a particular configuration.  The IOyyyyy.ASM
*       file is actually INCLUDEd 4 times, once for each of the 4 areas of
*       the I/O package shown above.  The following conditional switches
*       are used by the driver source module to distinguish between areas:
*               IODRIVERBODY    selects the read-only code portion
*               IODRIVERPOLL    selects the Interrupt poll chain portion
*               IODRIVERRAM     selects read/write storage of driver
*               IODRIVERINIT    selects the once-only I/O driver initializing code
*
*       Note: the driver source module should define all equates and (DCB)
*       table displacements when the conditional switch IODRIVERBODY is enabled.
*
*       A Typical shell has the following source form:
*
*       *       SET DEFAULTS
*               IFUND   xxxx
*               IFUND   yyyy
*               ...
*       *       BUILD READ-ONLY CODE
*       IODRIVERBODY    SET     1
*       IODRIVERPOLL    SET     0
*       IODRIVERRAM     SET     0
*       IODRIVERINIT    SET     0
*               IF      xxxx
*               INCLUDE IOxxxx.ASM
*               FIN
*               IF      yyyy
*               INCLUDE IOyyyy.ASM
*               FIN
*               ...
*       PATCHSPACE      RTP     zzzz
*               SWI
*       *****   Build Interrupt Poll Chains
*       IODRIVERBODY    SET     0
*       IODRIVERPOLL    SET     1
*               IF      xxxx    Note: order of poll routines may be different
*                                     than bodies
*               INCLUDE IOxxxx.ASM
*               FIN
        PAGE
*               IF      yyyy
*               INCLUDE IOyyyy.ASM
*               FIN
*               ...
*       *****   Build Working Storage
*       IODRIVERPOLL    SET     0
*       IODRIVERRAM     SET     1
*               IF      xxxx
*               INCLUDE IOxxxx.ASM
*               FIN
*               IF      xxxx
*               IF      yyyy
*               INCLUDE IOyyyy.AMS
*               FIN
*               ...
*       *****   Build Driver Reset routines
*       IODRIVERRAM     SET     0
*       IODRIVERINIT    SET     1
*               IF      xxxx
*               INCLUDE IOxxxx.ASM
*               FIN
*               IF      yyyy
*               INCLUDE IOyyyy.ASM
*               FIN
*               ...
*       *****   Finish out disk buffer pool, etc
*               ...
*               END
                PAGE
YES             EQU     1
NO              EQU     0
IOPKDEFS        EQU     1              I WANT THE I/O PACKAGE DEFS!
                IFUND   M6800
M6800           EQU     YES
                FIN     M6800
                IFUND   M6809
M6809           EQU     &M6800
                FIN     M6809
                IFUND   LIST.ALL
LIST.ALL        EQU     YES
                FIN     LIST.ALL
                IFUND   LIST.SDOSDEFS
LIST.SDOSDEFS   EQU     LIST.ALL
                FIN     LIST.SDOSDEFS
                IFUND   LIST.SDOSIOVTDEFS
LIST.SDOSIOVTDEFS       EQU     LIST.ALL
                FIN     LIST.SDOSIOVTDEFS
                IFUND   LIST.VIRTUALTERMINAL
LIST.VIRTUALTERMINAL    EQU     LIST.ALL
                FIN     LIST.VIRTUALTERMINAL
                IFUND   LIST.IOPACKAGE
LIST.IOPACKAGE  EQU     LIST.ALL
                FIN     LIST.IOPACKAGE
                IFUND   LIST.CLOCK
LIST.CLOCK      EQU     LIST.ALL
                FIN     LIST.CLOCK
                IFUND   LIST.SSBFD
LIST.SSBFD      EQU     LIST.ALL
                FIN
                IFUND   LIST.SSBWD
LIST.SSBWD      EQU     LIST.ALL
                FIN
                IFUND   LIST.SSBSD
LIST.SSBSD      EQU     LIST.ALL
                FIN
                IFUND   LIST.MT
LIST.MT         EQU     LIST.ALL
                FIN
                PAGE    I/O PACKAGE DEFAULT SWITCHES
                IFUND   WINCHESTERISDEFAULTDISK
WINCHESTERISDEFAULTDISK EQU            1
                FIN     WINCHESTERISDEFAULTDISK
K               EQU     1024           # BYTES PER "K" OF MEMORY
                IFUND   MEMSIZE SPECIFIES MEMORY SIZE IN "K" BYTES
MEMSIZE         EQU     60             DEFAULT FOR SSB Cheiftain
                FIN     MEMSIZE
                IFUND   NIOCHANNELS
NIOCHANNELS     EQU     8*8+3
                FIN     NIOCHANNELS
                IFUND   CODE
CODE            EQU     $5800
                FIN     CODE
                IFUND   SDOS
SDOS            EQU     $C200
                FIN     SDOS
                IFUND   DRIVERBASE
                IF      CODE<<SDOS
DRIVERBASE      EQU     CODE
                ELSE
DRIVERBASE      EQU     SDOS-3
                FIN     CODE<<SDOS
                FIN     DRIVERBASE
                IFUND   ATTNCHECK
ATTNCHECK       EQU     SDOS+SDOS:VTATTNCHECK
                FIN     ATTNCHECK
TICKSPERSECOND  EQU     60             Official SDOS clock tick rate
                LIST    LIST.SDOSDEFS
                INCLUDE SDOS11DEFS.ASM
                LIST    LIST.SDOSIOVTDEFS
                INCLUDE SDOSIOVTDEFS.ASM
                LIST    LIST.IOPACKAGE
        PAGE
                IFUND   INTERRUPTSTACKSIZE
*               ??? is all this stack space really needed? (see sdos11defs.asm)
INTERRUPTSTACKSIZE      EQU     MINSTACK+7+7+7+7        7 FOR EACH POSSIBLE
*               NESTED INTERRUPT RESULTING FROM A DEVICE
                FIN     INTERRUPTSTACKSIZE
                IFUND   VT:DRIVERESTIMATEDSIZE
VT:DRIVERESTIMATEDSIZE  EQU            $1800
                FIN     VT:DRIVERESTIMATEDSIZE
                IFUND   VTDRIVER
VTDRIVER        EQU     SDOS-SDOS:EXTENSIONSIZE-VT:DRIVERESTIMATEDSIZE
                FIN
*
*       SDOS-TO-IOPACKAGE COMMUNICATION REGION
*
        ORG     SDOS+1
****    FCB     $10                    SDOS VERSION NUMBER
        FDB     0                      LAST ERROR ENCOUNTERED
        FDB     CNFGTABLE              TELL SDOS WHERE ALL THE GOODIES ARE
        FDB     0                      SERIAL NUMBER
        FDB     0                      IOBLOCKPTR
        FDB     0                      IOCB POINTER (FOR FILE-TYPE DEVICE DRIVERS)
        FCB     0,0,0                  SET CLOCK TO "MIDNITE"
        FCB     0                      DAY, LET COMMAND INTERPRETER KNOW
        FCB     0                      MONTH, THAT THE TIME HASN'T BEEN SET
        FCB     EDITYEAR&$FF           YEAR
        PAGE    READ ONLY CODE SECTION
        ORG     DRIVERBASE
SYSCALLIO       JMP     SYSCALLIO      SDOS SETS JMP ADDR TO ITS ENTRY POINT
*
NEXTTIMEOUT     SET     0
NEXTDISKDCB     SET     0
NEXTDEVICEDCB   SET     0
NEXT5INCHDRIVE  SET     0
NEXT8INCHDRIVE  SET     0
NTIMEOUTS       SET     0
NDISKDCBS       SET     0
NEXTTCB         SET     0              SET UP END OF TASK CHAIN
*
IODRIVERBODY    SET     1
IODRIVERPOLL    SET     0
IODRIVERRAM     SET     0
IODRIVERINIT    SET     0
*
CNFGTABLE
        FDB     DISKDCBS               DEFAULT DISK MUST BE FIRST
        FDB     TTYDCB                 CONSOLE MUST BE FIRST
        FDB     IOCBPOINTERS
        FCB     NIOCHANNELS
        FDB     DSKBUFFERPOOL
        FDB     DSKPOOLSIZE
        FDB     ATTNCHECK
        FDB     DEBUGSYSCALL
        FDB     DRIVERBASE
        FDB     INTSETUP
INTDISABLE
        SEI
        RTS
INTENABLE
        CLI
        RTS
INTRTI  RTI                            INT RTI
        NOP
        NOP
        FDB     INTERRUPTSTACKEND-1
        FDB     INTERRUPTDEVICEPOLL    ROUTINE TO DETERMINE INTERRUPTING DEVICE
        FDB     TASKQUEUE
        FDB     TIMEOUTQUEUE
        FDB     PROFILECHAIN
        FDB     DEBUGINTERRUPT         WITH CONTEXT BLOCK ON STACK
        FDB     PRIMITIVETABLE         TIMESHARE PRIMITIVE VECTOR
*
DEBUGSYSCALL                           ;PUSH REST OF CONTEXT BLOCK
        ORCC    #$D0                   DISABLE INTS, ENSURE 'E' FLAG SET
        PSHS    CC,D,DP,X,Y,U          (PC ALREADY PUSHED)
DEBUGINTERRUPT
        JMP     [$FFFC]                FAKE AN NMI INTERRUPT
*
ILLDEVICEOP
        JSR     SDOS+SDOS:ERROR
        FDB     ERR:ILLDEVICEOP
*
ERRETX  JSR     SDOS+SDOS:ERRORSAVE
        JMP     SDOS+SDOS:ERRORED
*
PATCHSPACE                             ;PATCH SPACE FOR KLUGES
        RPT     200
        SWI
*
        LIST    LIST.VIRTUALTERMINAL
        page    VT DRIVER CONFIGURATION
*       NOTE: iovtconfig contains switches to enable parts of IOVTDPBS file
        INCLUDE IOSSBCNFG.ASM
        PAGE    *** Virtual Terminal Configuration ***
        INCLUDE IOVTDPBS.ASM
        LIST    LIST.MT
        INCLUDE IOSSBMT.ASM
        LIST    LIST.CLOCK
        INCLUDE IOSSBCLOCK.ASM
        LIST    LIST.SSBFD
        INCLUDE IOSSBFD.ASM
        LIST    LIST.SSBWD
        INCLUDE IOSSBWD.ASM
        LIST    LIST.SSBSD
        INCLUDE IOSSBSD.ASM
        LIST    LIST.IOPACKAGE
        PAGE    *** INTERRUPT POLL CHAINS ***
IODRIVERBODY    SET     0
IODRIVERPOLL    SET     1
*
*       There are two parts to the poll chain. The first part gets
*       control directly from the IRQ vector before the stack switch
*       from user stack to interrupt stack. At the end of the first part,
*       a 'JMP SDOS+SDOS:IOINT' is executed to perform the stack switch.
*       SDOS switches stacks, then jumps indirect through the
*       CNFGTABLE+CNFG:IOINTPOLL entry in the configuration table, where
*       execution of the second part of the poll chain follows.
*
*       There are some considerations and restrictions that need to be
*       discussed here. First of all, there are two parts to the poll
*       chain for execution efficiency reasons. Devices that have
*       a very frequent interrupt rate (such as 4 terminals pumping
*       9600 baud out the door = 4000 ints/sec) are spared the overhead
*       of a stack switch and unswitch on every interrupt. The virtual
*       terminal driver is one example of such a device driver, and
*       there is no limitation prohibiting other drivers to have
*       their poll logic in the first part as well. However, such devices
*       could be operating on the user stack and are restricted to not
*       using more than 8 bytes in addition to the context block pushed
*       by the IRQ. Exit is via RTI. These drivers are prohibited from
*       calling the re-schedule interrupt exit (JMP SDOS+SDOS:RESCHEDULE)
*       unless they switch stacks first, in which case they might as
*       well be in the second part of the poll chain (after the stacks
*       are switched by SDOS).
*
*       Devices on the second part of the poll chain operate on the
*       interrupt stack which has no depth restriction, other than
*       maximum stack must not be exceeded (make it bigger in the I/O
*       package if necessary). Exit is via 'JMP SDOS+SDOS:RTI' if no event
*       occured, or 'JMP SDOS+SDOS:RESCHEDULE' if an event occured.
*       Since drivers operating in the second part of the poll chain
*       are running with stacks switched, an RTI is strictly not allowed.
*       For example, in a disk driver, a seek complete interrupt is not
*       an (interesting) event as far as the task is concerned, but read
*       or write complete is, and although a 'JMP SDOS+SDOS:RTI' in both
*       cases will not harm, 'JMP SDOS+SDOS:RESCHEDULE' will expidite
*       rescheduling when the interesting event just occured (it helps
*       the scheduler discover a little sooner that a task waiting for
*       I/O complete is ready to run).
*
IRQINT  ; Come here directly from interrupt, stacks not switched, exit via RTI
        LIST    LIST.VIRTUALTERMINAL
        INCLUDE IOSSBCNFG.ASM          POLL CHAIN FOR VT DEVICES
        LIST    LIST.IOPACKAGE
        JMP     SDOS+SDOS:IOINT        Let SDOS switch the stacks
INTERRUPTDEVICEPOLL ; Stack is switched, exit via SDOS:RTI or SDOS:RESCHEDULE
        LIST    LIST.SSBFD
        INCLUDE IOSSBFD.ASM
        LIST    LIST.SSBWD
        INCLUDE IOSSBWD.ASM
        LIST    LIST.CLOCK
        INCLUDE IOSSBCLOCK.ASM
        LIST    LIST.IOPACKAGE
        LDX     BADINTERRUPTCOUNT      CAN'T FIGURE OUT WHO IT IS...
        INX                            BUMP CRAZY INTERRRUPT COUNTER
        STX     BADINTERRUPTCOUNT
        JMP     SDOS+SDOS:RTI          AND HOPE IT WENT AWAY !
        EQU     *-DRIVERBASE           SIZE OF READ-ONLY CODE
        PAGE    *** WORKING STORAGE ***
IODRIVERPOLL    SET     0
IODRIVERRAM     SET     1
BADINTERRUPTCOUNT       FDB     0      # OF INTERRUPTS FROM UNKNOWN DEVICES
*
        LIST    LIST.CLOCK
        INCLUDE IOSSBCLOCK.ASM
        LIST    LIST.VIRTUALTERMINAL
        INCLUDE IOSSBCNFG.ASM          VIRTUAL TERMINAL DCBS, ETC.
**** THE FOLLOWING LINE SHOULD BE GENERATED BY "MAKECONFIG" BUT ISN'T!
NEXTTCB SET     TTYTCB                 = HEAD OF VT DEVICES TCB CHAIN
        LIST    LIST.SSBSD
        INCLUDE IOSSBSD.ASM
        IF      WINCHESTERISDEFAULTDISK
        LIST    LIST.SSBFD
        INCLUDE IOSSBFD.ASM
        LIST    LIST.SSBWD
        INCLUDE IOSSBWD.ASM
        ELSE
        LIST    LIST.SSBWD
        INCLUDE IOSSBWD.ASM
        LIST    LIST.SSBFD
        INCLUDE IOSSBFD.ASM
        FIN     WINCHESTERISDEFAULTDISK
        LIST    LIST.IOPACKAGE
DISKDCBS        EQU     NEXTDISKDCB
NDRIVES         EQU     NDISKDCBS
DEVICEDCBS      EQU     NEXTDEVICEDCB
TIMEOUTQUEUE    EQU     NEXTTIMEOUT
NTIMEOUTBLOCKS  EQU     NTIMEOUTS
TASKQUEUE       EQU     NEXTTCB
PROFILECHAIN    EQU     NEXTDPB
.5INCHCHAINHEAD EQU     NEXT5INCHDRIVE
.8INCHCHAINHEAD EQU     NEXT8INCHDRIVE
        PAGE    FCBS, IOCBS, INTERRUPT STACK
*
*       FCBS (MUST PRECEDE IOCBS)
*
FCBS    RPT     FCB:SIZE*(NIOCHANNELS+2*NDRIVES+NMAGICFCBS)
        FCB     0
*
*       IOCBS
*
IOCBS   RPT     IOCB:SIZE*NIOCHANNELS
        FCB     0
IOCBPOINTERS
        RPT     NIOCHANNELS
        FDB     IOCBS+IOCB:SIZE*(*-IOCBPOINTERS)/2
        PGEN    0
*
INTERRUPTSTACK                         ; STACK SPACE FOR INTERRUPT ROUTINES
        RPT     INTERRUPTSTACKSIZE
        FCB     0
*
INTSETUP
        LDD     #IRQINT                = WHERE TO GO ON INTERRUPT
        LDX     $FFF8                  = IRQ VECTOR, POINTS TO JMP IN RAM
        STD     1,X                    SET UP JUMP TARGET = INTERRUPTTO
        LDA     #$7E
        STA     0,X
        RTS
INTERRUPTSTACKEND                      ; INTSETUP INCLUDED IN STACK
        PAGE    *** DRIVER INIT (ONCE-ONLY) CODE ***
IODRIVERRAM     SET     0
IODRIVERINIT    SET     1
DSKBUFFERPOOL   EQU     *
        LIST    LIST.CLOCK
        INCLUDE IOSSBCLOCK.ASM
        LIST    LIST.VIRTUALTERMINAL
        INCLUDE IOSSBCNFG.ASM          RESET ROUTINES FOR VT DEVICES
        LIST    LIST.SSBFD
        INCLUDE IOSSBFD.ASM
        LIST    LIST.SSBWD
        INCLUDE IOSSBWD.ASM
        LIST    LIST.SSBSD
        INCLUDE IOSSBSD.ASM
        LIST    LIST.IOPACKAGE
        PAGE
        IF      CODE<<VTDRIVER
        IF      *>/VTDRIVER
        ? DRIVERS TOO BIG ?
        ELSE
        RMB     VTDRIVER-*
        FIN     *>/VTDRIVER
        ELSE
        IF      *>/MEMSIZE*K
        ? DRIVERS TOO BIG ?
        FIN     *>/MEMSIZE*K
        RMB     MEMSIZE*K-*
        FIN     CODE<<VTDRIVER
DSKPOOLSIZE     EQU     *-DSKBUFFERPOOL
ENDOFIOPACKAGE  EQU     *              SO I CAN SEE WHERE THE END IS...
        EQU     *-CODE                 SO I CAN SEE HOW BIG THE WORLD IS
        END
