; ; File: ADBDriver.aii ; ; Contains: IOP code for IOP Based ADB driver ; ; Written by: Gary G. Davidian 10-Jul-88 ; ; Copyright: © 1988-1990 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <2> 1/2/90 GGD NEEDED FOR ZONE-5: General source cleanup, no code changes. ; <1.5> 11/19/89 GGD NEEDED FOR ZONE-5 Added conditional assembly option ; 'ForceWorstCase' to cause ADB to use more processor time, to ; stress test the worst case paths of the SWIM Driver. Added ; facility to control auto-polling on a device address basis so ; that the ADB Manager can select to only poll addresses that have ; device table entries. ; <1.4> 11/2/89 GGD NEEDED FOR ZONE-5 Changed the ADB Polling rate from 13.5ms to ; 11.0ms to be closer to a floppy disk sector time, and to be ; consistent with the Mac II ADB Micro poll rate. ; <1.3> 9/21/89 GGD Added ADBActivity indicator so that the disk driver can give ADB ; more priority if there was recent activity. Corrected timing ; calculation in Attn pulse (off by 5µs). ; <1.2> 7/8/89 CCH No changes. Testing in-file comments for ".aii" suffix files. ; <1.1> 6/15/89 GGD Updated to use equates for the latest rev of the IOP chip, ; re-formated tab stops in source. ; <1.0> 11/9/88 CCH Adding to EASE. ; 7/10/88 GGD Created today. ; ; To Do: ; eject title 'IOP ADB Driver' ; File: ADBDriver.aii - IOP code for IOP Based ADB driver. ; ;_______________________________________________________________________ ; ; Copyright © Apple Computer, Inc. 1988-1989 ; ; written by Gary G. Davidian 10-Jul-88 ; ; This module implements the IOP side of the IOP based Apple Desktop Bus ; Driver. It performs the low level ADB transactions as well as automatic ; polling of the last device, and automatic service request polling (in ; Most Recently Used order). The Host CPU will only be interrupted, with ; a single interrupt per transaction, when there is some device input to ; be processed. ; ; This driver co-exists on the IOP that also has the SWIM Driver, and the ; SWIM chip is used to drive and receive the ADB bus. ; ; NOTE: This code was optimized for space, and also contains many cycle ; counted timing dependent routines. This may detract from its ; readability at times, but keep in mind that this code replaces a ; considerable amount of hardware and saves $$$ (profit sharing). ; ; MODIFICATION HISTORY: ; ; <10Jul88> GGD Created today. ; ;_______________________________________________________________________ machine m65C02 codechk off datachk off longa off longi off print nomdir,nogen print off include 'IOPDefs.aii' include 'SWIMDefs.aii' print on hasAltADB equ 1 ; include alternate SWIM based ADB also ForceWorstCase equ 0 ; don't simulate worst case data length <1.5> ; Polling rate definitions ; These two time constants are used to control auto polling, and service request ; polling. Explicit commands are serviced immediatly, which may mean that if they ; are issued at a very high frequency, they may utilize more than 50% of the bus ; bandwith, and may prevent the processors in the devices from having time to ; service their device (this is the way that it is done on other machines). ; During normal AutoPolling, this situation will not occur. But it can occur during ; Service Request polling. ; ; AutoPollRate is the MINIMUM time from the START of a command to the START of ; the next command when auto polling. ; ; SRQPollDelay is the MINIMUM time from the END of a command to the START of ; the next command. This is used when polling for a device that issued a service ; request. AutoPollRate equ (11000*TMPB1second)/1000000 ; 11.000 MS auto poll interval <1.4> SRQPollDelay equ (00500*TMPB1second)/1000000 ; 0.500 MS delay before SRQ polls ; ADB transaction related definitions NumADBAddrs equ 16 ; 16 addresses, 0..15 ADBCmdMask equ $0F ; mask for command/reg portion of ADB command ADBAddrMask equ $F0 ; mask for address portion of ADB command ResetCmd equ $00 ; ADB Bus Reset command TalkR0Cmd equ $0C ; ADB command Talk Reg 0 MinDataLen equ 2 ; Data length can be 0, 2..8 bytes MaxDataLen equ 8 ; Data length can be 0, 2..8 bytes ; Message Format ADBMsg record 0,increment ; format CPU <-> IOP messages Flags ds.b 1 ; modifier/status flags (see below) DataCount ds.b 1 ; number of bytes of ADBData (0..8) (cmd not included) ADBCmd ds.b 1 ; ADB command to send / command that replied ADBData ds.b MaxDataLen ; ADB Data to be sent with command, or data received ds.b 1 ; input data buffer (needs 1 extra byte) endr ; ADBMsg.Flags bit definitions ExplicitCmd equ %10000000 ; message contains an explicit commmand AutoPollEnable equ %01000000 ; auto polling and srq polling enabled SetPollEnables equ %00100000 ; Update auto-enable bit mask from ADBData field ServiceRequest equ %00000100 ; service request detected TimedOut equ %00000010 ; addressed device did not return data ; Low level message passing state and data buffer assignments ADBXmtMsgState equ XMTMsg3State ADBRcvMsgState equ RCVMsg3State ADBXmtMsgData equ XMTMsg3Data ADBRcvMsgData equ RCVMsg3Data ; Page zero variables seg 'zdata' ADBVarsZ record export ADBActivity ; export activity status for disk driver ADBActivity ds.b 1 ; status of last 8 transactions ADBFlags ds.b 1 ; status information ByteCount ds.b 1 ; number of bytes to send / bytes received PollingTMPB ds.b 1 ; index of Polling Timer Param Block MRUAddr ds.b 1 ; ADB address most recently received from LRUAddr ds.b 1 ; ADB address least recently received from AutoPollAddr ds.b 1 ; ADB address to auto poll MsgPtr ds.w 1 ; pointer to xmt/rcv message buffer Temp ds.b 1 ; general purpose temporary SRQcount ds.b 1 ; number of devices searched during SRQ poll endr ; Other Driver variables seg 'data' ADBVars record XmtCmdAndData ds.b 1 ; command byte (must precede SendBuffer) ds.b MaxDataLen ; output data buffer MRUList ds.b NumADBAddrs ; list of ADB addrs in MRU order DisableFlags ds.b NumADBAddrs ; if <> 0 then don't auto-poll this address endr ReceiveBuffer equ ADBXmtMsgData+ADBMsg.ADBData ; rcv directly into msg buffer seg 'code' ADBDrvr proc export export HandleRCVMsg3 ; ADB driver requests use MSG 3 export HandleXMTMsg3 ; ADB driver requests use MSG 3 export InitADBDrvr ; ADB driver initialization import GetTMPB import CancelTMPBTimer import StartTMPBTimer import WaitTMPBDone import CheckTMPBdone import TMPBtimeH import TMPBtimeL with ADBVarsZ,ADBVars ; globals used throughout driver title 'IOP ADB Driver - Initialization' ;_______________________________________________________________________ ; ; Routine: jsr InitADBDrvr ; Inputs: none ; Outputs: none ; Destroys: A, X, Y, n, z, c ; Calls: GetTMPB ; Called by: SWIMIOP driver initialization ; ; Function: Initializes the IOP based ADB Driver variables. ; ;_______________________________________________________________________ InitADBDrvr if hasAltADB then jsr CheckForAltADB ; patch in SWIM based ADB if present endif jsr GetTMPB ; get a timer parameter block pointer sty ADBRcvMsgData ; get high byte of message pointer ldy ADBRcvMsgData\ +ADBMsg.DataCount ; get the xmt byte count lda ADBRcvMsgData\ +ADBMsg.Flags ; get the new flags jsr CopyMsg ; copy the message lda #MessageCompleted ; message completed state sta ADBRcvMsgState ; indicate that it is done lda #MsgCompletedINT ; get the interrupt bit sta HostControl ; interrupt the main CPU bra ADBAction ; go run a command ;_______________________________________________________________________ ; ; Routine: jsr HandleXMTMsg3 ; Inputs: none ; Outputs: none ; Destroys: A, X, Y, n, v, z, c ; Calls: CopyMsg, ADBAction (branched to) ; Called by: IOPKernel.HandleHSTInt ; ; Function: Handles receiving messages replies from the host, by copying ; the request information, and updating the message state to ; indicate that the message reply has been accepted. ; ADBAction is then called to actually process the command. ; ;_______________________________________________________________________ HandleXMTMsg3 ldx #>ADBXmtMsgData ; get high byte of message pointer ldy ADBXmtMsgData\ +ADBMsg.DataCount ; get the xmt byte count lda ADBXmtMsgData\ +ADBMsg.Flags ; get the new flags jsr CopyMsg ; copy the message assert Idle=0 * lda #Idle ; Indicate that response was received stz ADBXmtMsgState ; set the new message state bra ADBAction ; go run a command title 'IOP ADB Driver - Polling Request Handling' ;_______________________________________________________________________ ; ; Routine: jmp StartSRQPoll ; Inputs: none ; Outputs: none ; Destroys: A, X, n, z, c ; Calls: CancelPollTimer, StartPolling (branched to) ; Called by: ADBAction ; ; Function: Handles service request polling, by setting up a Talk R0 ; command for the next device in MRU (Most Recently Used) order. ; It will delay for a short time before issuing the request ; so that devices on the ADB bus, and the IOP itself will not be ; saturated by this polling. ; ;_______________________________________________________________________ StartSRQPoll ldx >8)=(AutoPollRate>>8) lda #>AutoPollRate ; get high byte of poll rate sta TMPBtimeH,y ; store high into the TMPB jsr StartTMPBTimer ; start the timer ldy NewMessageSent lda #NewMsgSentINT ; prepare to interrupt the host sta HostControl ; interrupt the host lda #ExplicitCmd ; prepare to clear explicit bit trb 255 then aerror 'Wait value too large' else lda #&q jsr &Routine&r endif endm if hasAltADB then PatchBase endif SetBusPlus6 nop ; add 6 clocks before loop SetBusPlus4 nop ; add 4 clocks before loop SetBusPlus2 nop ; add 2 clocks before loop * lda #1 ; ( 2) * jsr SetBusHighPlus0 ; ( 8) SetBusPlus0 dea ; (10) decrement loop counter SetBusPlus3 bne SetBusPlus0 ; (12) loop until A=0 SetBus lda rADBoutReg ; (16) read output register bcs @SetHigh ; (18) (19) ADBoutLow ; (20) modify to set bus low bra @SetBusOutput ; (23) @SetHigh ADBoutHigh ; (21) modify to set bus high nop ; (23) @SetBusOutput sta wADBoutReg ; (27) set the bus high or low lda #ADBinMask ; ( 2) prepare check bus fighting bit ADBinReg ; ( 6) test the bus rts ; (12) all done if hasAltADB then gbla &FixrADBoutReg1,&FixOutLowOp1,&FixOutLowData1,&FixOutHighOp1 gbla &FixOutHighData1,&FixwADBoutReg1,&FixADBinMask1,&FixADBinReg1 &FixrADBoutReg1 seta SetBus+1-PatchBase &FixOutLowOp1 seta SetBus+5-PatchBase &FixOutLowData1 seta SetBus+6-PatchBase &FixOutHighOp1 seta @SetHigh+0-PatchBase &FixOutHighData1 seta @SetHigh+1-PatchBase &FixwADBoutReg1 seta @SetBusOutput+1-PatchBase &FixADBinMask1 seta @SetBusOutput+4-PatchBase &FixADBinReg1 seta @SetBusOutput+6-PatchBase endif title 'IOP ADB Driver - ADB Request Transaction' ;_______________________________________________________________________ ; ; Routine: jsr ADBrequest ; Inputs: XmtCmdAndData - Command byte, followed by data, if any ; ByteCount - number of data bytes to send (0..8) ; Outputs: ReceiveBuffer - data received from device ; ByteCount - number of data bytes received (0..8) ; ADBFlags.ServiceRequest - set if SRQ detected, else 0 ; ADBFlags.TimedOut - set if no reply data received, else 0 ; Destroys: A, X, Y, n, v, z. c ; Calls: SetBus, SetBusAfter, SendBytes, @ReceiveReply (branched to) ; Called by: ADBAction ; ; Function: Performs the low level ADB transmission, sending attention, ; sync, command byte, and stop bit. Detects and records ; service requests after command byte's stop bit. Data is ; sent if ByteCount is non-zero, preceded by a start bit, ; and followed by a stop bit. ; ;_______________________________________________________________________ ADBrequest if ForceWorstCase then ; simulate worst case data length <1.5> ldy #10*8 ; 10 byte times @ 8 bits per byte @delay sec ; leave bus high setbusafter (Tcyc*130/100) ; worst case bit time dey ; update bits remaining count bne @delay ; loop through all bits endif ; <1.5> clc ; prepare to set bus low for attention pulse jsr SetBus ; ( 12) attn is low for Tattn lda = low ldx