home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / tools / misc / ppazip / src / ppazip5.asm < prev   
Encoding:
Assembly Source File  |  1998-03-09  |  51.0 KB  |  1,909 lines

  1. ;============================================================================
  2. ;                        Parallel Port Zip Driver
  3. ;============================================================================
  4. ;
  5. ; 15-Jan-1998 v0.0 created by Bruce Abbott
  6. ;
  7. ;  8-Feb-1998 v0.1 - now obtaining joystick port via gameport.device
  8. ;
  9. ; 10-Feb-1998 v0.2 - fixed bug in timedelay (was not freeing memory).
  10. ;
  11. ; 11-Feb-1998 v0.3 - Split large data transfers into 128K blocks, rather
  12. ;                    than using MaxTransfer setting in mountlist. This
  13. ;                    circumvents a bug in CrossDOSFileSystem v39.4
  14. ;
  15. ; 21-Feb-1998 v0.4 - Using TEST_UNIT_READY and READ_SENSE commands to
  16. ;                    determine if r/w error is actually no disk in drive.
  17. ;
  18. ;                  - Increased timeouts up to 3 seconds (greater than
  19. ;                    maximum drive spinup time).
  20. ;
  21. ;                  - Reduced Timer overhead. Now only opening timer.device
  22. ;                    once, instead of on every time delay. Allocated ioreqs
  23. ;                    static instead of using AllocMem.
  24. ;
  25. ;  9-Mar-1998 v0.5 - Using 10 byte SCSI read/write commands. Now can
  26. ;                    do large transfers (>128K) directly.
  27. ;
  28. ;
  29. ; ToDo: - diskchange
  30. ;       - SCSI direct
  31. ;
  32.  
  33. VERSION     EQU   0
  34. REVISION    EQU   5
  35.  
  36. ; opt d+
  37.  
  38. ;debug = 1
  39.  
  40.  output devs:ppazip.device
  41.  
  42.    include amiga.i   ; 1.3 includes
  43.    include scsi.i    ; standard SCSI stuff
  44.  
  45.    include debugs.i  ; serial debug messages
  46.  
  47.  
  48. EXEC macro
  49.   move.l  a6,-(sp)
  50.   move.l  execbase(pc),a6
  51.   jsr     _LVO\1(a6)
  52.   move.l  (sp)+,a6
  53.   ENDM
  54.  
  55.  
  56. ; set control port mode without disturbing serial bits
  57.  
  58. setmode MACRO ; \1 = mode
  59.   move.w  #$4000,_intena
  60.   move.b  ctrlport,d0
  61.   and.b   #~PPBITS,d0
  62.   or.b    #\1,d0
  63.   move.b  d0,ctrlport
  64.   move.w  #$c000,_intena
  65.   ENDM
  66.  
  67.  
  68.  
  69. ; ZIP needs a rest after some operations
  70.  
  71. delay MACRO   \1=time
  72.   IFC "","\1"
  73.     rept 5
  74.      tst.b   $bfe001       ; minimum delay between zip accesses
  75.     endr
  76.   ELSEIF
  77.    move.w  d0,-(sp)
  78.    IFLT    2000,\1
  79.      move.w  #\1-1,d0
  80. .deloop\@:
  81.      tst.b   $bfe001       ; loop for short time delay
  82.      dbf     d0,.deloop\@
  83.    ELSEIF
  84.      move.l  #\1,d0
  85.      bsr     timedelay     ; sleep for long time delay
  86.    ENDC
  87.    move.w  (sp)+,d0
  88.   ENDC
  89.   ENDM
  90.  
  91. ; wait timeouts
  92.  
  93. COMD_TIMEOUT = 3000000
  94. CNCT_TIMEOUT = 30000
  95. STAT_TIMEOUT = 3000000
  96. MESG_TIMEOUT = 30000
  97. SLCT_TIMEOUT = 100000
  98. DATA_TIMEOUT = 250000
  99. STRT_TIMEOUT = 3000000
  100.  
  101.  
  102. ; select timeout
  103.  
  104. SEL_TIMEOUT  = 30000
  105.  
  106.  
  107. _intena=$dff09a
  108.  
  109. ; CIA registers
  110.  
  111. dataport  = $bfe101
  112. dirport   = $bfe301
  113. ctrlport  = $bfd000
  114. ctrldir   = $bfd200
  115.  
  116. jport     = $bfe001
  117. jdir      = $bfe201
  118.  
  119. ; control register values
  120.  
  121. BSY    = $01          ; Printer Busy
  122. POUT   = $02          ; Paper Out
  123. SEL    = $04          ; Printer Selected
  124.  
  125. PPBITS = BSY|POUT|SEL
  126.  
  127. ;          parallel port         zip
  128.  
  129. PPINIT   =  POUT+SEL         ;  init=0
  130. PPOUT    =  BSY+POUT         ;  selin=0
  131. PPIN     =  BSY+SEL          ;  strobe=0
  132. PPHOST   =  POUT             ;  init,selin=0
  133. PPSTAT   =  BSY+SEL+POUT     ;  all high
  134.  
  135. ; joystick fire used for strobe/ack pulse
  136.  
  137. NO_XT   =  $80               ; zip AutofeedXT = up
  138. AFDXT   =  $00               ;  ''     ''     = down
  139.  
  140. ; status register values
  141.  
  142. statport  = $dff00c          ; joystick port
  143.  
  144.  
  145. STATMASK    = $0303          ; which joy bits to test
  146.  
  147. POUTBIT     = 0              ; set at end of xfer
  148. BUSYBIT     = 1              ; set when zip is busy
  149. ACKBIT      = 8              ; set when action completed
  150. SELBIT      = 9              ; set when zip wants to send data
  151.  
  152. ;--------------------------------------------------------
  153. ;            status values (busy always low)
  154. ;--------------------------------------------------------
  155. ;         Value       Meaning         pin(s) high
  156. ;
  157. NONE    = $0000    ;     -               -
  158. WRITE   = $0100    ; write block        ack
  159. READ    = $0300    ; read block         ack+sel
  160. COMAND  = $0101    ; write command      ack+pout
  161. STATUS  = $0301    ; read stat byte     ack+pout+sel
  162.  
  163.  
  164. ; SCSI rd/wr error code bits
  165.  
  166. SelectErrorBit = 31
  167. PhaseErrorBit  = 30
  168. TimeOutBit     = 29
  169. EarlyStatusBit = 28
  170.  
  171.  
  172. MYPROCSTACKSIZE   = $800
  173. MYPROCPRI         =    5
  174. MYDEV_END         =   29
  175. MD_NUMUNITS       =    1
  176.  
  177.    STRUCTURE MyDev,LIB_SIZE
  178.    ULONG   md_SegList
  179.    UBYTE   md_Flags
  180.    UBYTE   md_
  181.    STRUCT  md_Units,4*MD_NUMUNITS
  182.    LABEL   MyDev_Sizeof
  183.  
  184.    STRUCTURE MyDevMsg,MN_SIZE
  185.    APTR    mdm_Device
  186.    APTR    mdm_Unit
  187.    LABEL   MyDevMsg_Sizeof
  188.  
  189.    STRUCTURE MyDevUnit,UNIT_SIZE
  190.    UBYTE   mdu_UnitNum
  191.    UBYTE   mdu_SigBit            ; Signal bit allocated for interrupts
  192.    APTR    mdu_Device
  193.    STRUCT  mdu_stack,MYPROCSTACKSIZE
  194.    STRUCT  mdu_is,IS_SIZE        ; Interrupt structure
  195.    STRUCT  mdu_tcb,TC_SIZE       ; TCB for disk task
  196.    STRUCT  mdu_Msg,MyDevMsg_Sizeof
  197.    ULONG   mdu_SigMask           ; Signal these bits on interrupt
  198.    LABEL   MyDevUnit_Sizeof
  199.  
  200. ;------ state bit for unit stopped
  201.    BITDEF   MDU,STOPPED,2
  202. ;------ is media ready for access? ------
  203.    BITDEF   MDU,READY,3
  204.  
  205.  
  206. FirstAddress:
  207.    moveq   #0,d0
  208.    rts
  209.  
  210. MYPRI       EQU   10
  211.  
  212.  
  213. initDDescrip:
  214.      DC.W    RTC_MATCHWORD      ; UWORD RT_MATCHWORD
  215.      DC.L    initDDescrip       ; APTR  RT_MATCHTAG
  216.      DC.L    EndCode            ; APTR  RT_ENDSKIP
  217.      DC.B    RTF_AUTOINIT       ; UBYTE RT_FLAGS
  218.      DC.B    VERSION            ; UBYTE RT_VERSION
  219.      DC.B    NT_DEVICE          ; UBYTE RT_TYPE
  220.      DC.B    MYPRI              ; BYTE  RT_PRI
  221.      DC.L    myName             ; APTR  RT_NAME
  222.      DC.L    idString           ; APTR  RT_IDSTRING
  223.      DC.L    Init               ; APTR  RT_INIT
  224.                                 ; LABEL RT_SIZE
  225.  
  226. ;  intialization
  227.  
  228. mdu_Init:
  229.    INITBYTE   MP_FLAGS,PA_IGNORE
  230.    INITBYTE   LN_TYPE,NT_DEVICE
  231.    INITLONG   LN_NAME,myName
  232.    INITBYTE   mdu_Msg+LN_TYPE,NT_MSGPORT ; Unit starts with MsgPort
  233.    INITLONG   mdu_Msg+LN_NAME,myName
  234.    INITLONG   mdu_tcb+LN_NAME,myName
  235.    INITBYTE   mdu_tcb+LN_TYPE,NT_TASK
  236.    INITBYTE   mdu_tcb+LN_PRI,MYPROCPRI
  237.    INITBYTE   mdu_is+LN_PRI,4            ; Int priority 4
  238.    IFD        INTRRUPT
  239.    INITLONG   mdu_is+IS_CODE,myintr      ; Interrupt routine addr
  240.    ENDC
  241.    INITLONG   mdu_is+LN_NAME,myName
  242.    DC.L   0
  243.  
  244.  
  245. Init:
  246.    DC.L   MyDev_Sizeof      ; data space size
  247.    DC.L   funcTable         ; pointer to function initializers
  248.    DC.L   dataTable         ; pointer to data initializers
  249.    DC.L   initRoutine       ; routine to run
  250.  
  251.  
  252. funcTable:
  253.  
  254.    ;------ standard system routines
  255.    dc.l   Open
  256.    dc.l   CloseDev
  257.    dc.l   Expunge
  258.    dc.l   Null
  259.  
  260.    ;------ my device definitions
  261.    dc.l   BeginIO
  262.    dc.l   AbortIO
  263.  
  264.    ;------ function table end marker
  265.    dc.l   -1
  266.  
  267.  
  268. dataTable:
  269.    INITBYTE   LH_TYPE,NT_DEVICE
  270.    INITLONG   LN_NAME,myName
  271.    INITBYTE   LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
  272.    INITWORD   LIB_VERSION,VERSION
  273.    INITWORD   LIB_REVISION,REVISION
  274.    INITLONG   LIB_IDSTRING,idString
  275.    DC.L   0
  276.  
  277.  
  278. ; a0 = seglist, d0 = device data, a6 = execbase
  279.  
  280. initRoutine:
  281.    move.l   a5,-(sp)                  ; Preserve ALL modified registers
  282.    lea      execbase(pc),a5
  283.    move.l   a6,(a5)                   ; save a pointer to exec
  284.    move.l   d0,a5
  285.    move.l   a0,md_SegList(a5)         ; save a pointer to our loaded code
  286. init_end:
  287.    move.l   (sp)+,a5                  ; Restore All modified registers
  288.    rts
  289.  
  290. ;------------------------------------------------------------------------
  291. ;     opendevice ( device:a6, ioreq:a1, unitnum:d0, flags:d1 )
  292. ;------------------------------------------------------------------------
  293. ;
  294. Open:
  295.    movem.l d2/a2-a4,-(sp)
  296.    move.l  a1,a2                         ; a2 = ioreq
  297.    move.l  d0,d2                         ; d2 = unit number
  298.    cmp.l   #MD_NUMUNITS,d0
  299.    bhs     Open_Error                    ; unit number out of range ?
  300.    lsl.l   #2,d0
  301.    lea.l   md_Units(a6,d0.l),a4
  302.    move.l  (a4),a3
  303.    move.l  a3,d0                         ; unit already initialised ?
  304.    bne     Open_OK
  305.    bsr     InitUnit                      ; try and conjure up a unit
  306.    move.l  (a4),d0
  307.    beq.s   Open_Error                    ; got a unit ?
  308.    move.l  d0,a3
  309.    bsr     OpenTimer                     ; open timer device
  310.    bsr     getparallelport
  311.    tst.l   d0                            ; try to obtain printer port
  312.    bne.s   Open_Error
  313.    bsr     GetGamePort                   ; try to obtain joystick port
  314.    tst.l   d0
  315.    bne.s   Open_Error
  316.    bsr     pp_init
  317.    tst.l   d0                            ; try to initialize zip drive
  318.    bmi.s   Open_error
  319.    bra.s   Open_OK
  320. Open_Error:
  321.    bug     <"OpenDevice failed!",10>
  322.    moveq   #IOERR_OPENFAIL,d0
  323.    move.b  d0,io_error(a2)
  324.    bra.s   Open_End
  325. Open_OK:                                 ; unit pointer in a3
  326.    move.l  a3,io_unit(a2)
  327.    addq.w  #1,lib_opencnt(a6)            ; mark us as having another opener
  328.    addq.w  #1,unit_opencnt(a3)
  329.    bclr    #LIBB_DELEXP,md_Flags(a6)     ; prevent delayed expunges
  330.    bug     <"OpenDevice OK",10>
  331.    moveq   #0,d0
  332. Open_End:
  333.    movem.l (sp)+,d2/a2-a4
  334.    rts
  335.  
  336.  
  337.  
  338. CloseDev:      ; ( device:a6, iob:a1 )
  339.    movem.l d1/a2-a3,-(sp)
  340.    move.l  a1,a2
  341.    move.l  io_unit(a2),a3
  342.    ;------ make sure the iob is not used again
  343.    moveq.l #-1,d0
  344.    move.l  d0,io_unit(a2)
  345.    move.l  d0,io_device(a2)
  346.    ;------ see if the unit is still in use
  347.    subq.w  #1,unit_opencnt(a3)
  348.    bne.s   Close_Device
  349.    bsr     ExpungeUnit
  350. Close_Device:
  351.    ;------ mark us as having one fewer openers
  352.    moveq.l #0,d0
  353.    subq.w  #1,lib_opencnt(a6)
  354.    ;------ see if there is anyone left with us open
  355.    bne.s   Close_End
  356.    ;------ see if we have a delayed expunge pending
  357.    btst    #LIBB_DELEXP,md_Flags(a6)
  358.    beq.s   Close_End
  359.    ;------ do the expunge
  360.    bsr     Expunge
  361. Close_End:
  362.    movem.l (sp)+,d1/a2-a3
  363.    rts
  364.  
  365.  
  366. Expunge:   ; ( device: a6 )
  367.    movem.l  d1/d2/a5/a6,-(sp)          ; save ALL modified registers
  368.    move.l   a6,a5
  369.    move.l   execbase(pc),a6
  370.    tst.w    lib_opencnt(a5)            ; see if anyone has us open
  371.    beq      closed
  372.    bset     #LIBB_DELEXP,md_Flags(a5)  ; it is still open. delay expunge
  373.    moveq    #0,d0
  374.    bra.s    Expunge_End
  375. closed:
  376.    move.l   md_SegList(a5),d2          ; seglist in d2
  377.    move.l   a5,a1
  378.    EXEC     Remove                     ; unlink from device list
  379.    ;
  380.    ; device specific closings here...
  381.    ;
  382.    move.b   #$03,jdir                  ; reset joystick FIRE to input mode
  383.    setmode  PPSTAT
  384.    move.b   #$c0,ctrldir               ; restore parallel port
  385.    move.b   #$00,dirport
  386.    bsr      freeParallelport           ; free parallel port
  387.    bsr      freegameport               ; free joystick port
  388.    moveq    #0,d0
  389.    moveq    #0,d1
  390.    move.l   a5,a1
  391.    move.w   lib_negsize(a5),d1
  392.    sub.w    d1,a1
  393.    add.w    lib_possize(a5),d0
  394.    add.l    d1,d0                      ; free device memory
  395.    EXEC     FreeMem
  396.    move.l   d2,d0                      ; return seglist for unloading
  397. Expunge_End:
  398.    movem.l  (sp)+,d1/d2/a5/a6
  399.    rts
  400.  
  401.  
  402. Null:
  403.    moveq   #0,d0
  404.    rts
  405.  
  406.  
  407. InitUnit:   ; ( d2:unit number, a6:devptr )
  408.    movem.l  d2-d4/a2/a3,-(sp)
  409.    move.l   #MyDevUnit_Sizeof,d0
  410.    move.l   #MEMF_PUBLIC!MEMF_CLEAR,d1
  411.    EXEC     AllocMem                       ; allocate unit memory
  412.    tst.l    d0
  413.    beq      InitUnit_End
  414.    move.l   d0,a3                          ; a3 = unit
  415.    move.b   d2,mdu_UnitNum(a3)             ; initialize unit number
  416.    move.l   a6,mdu_Device(a3)              ; initialize device pointer
  417.    lea      mdu_stack(a3),a0               ; Low end of stack
  418.    move.l   a0,mdu_tcb+tc_splower(a3)
  419.    lea      MYPROCSTACKSIZE(a0),a0         ; High end of stack
  420.    move.l   a0,mdu_tcb+tc_spupper(a3)
  421.    move.l   a3,-(a0)                       ; argument -- unit ptr
  422.    move.l   a0,mdu_tcb+tc_spreg(a3)
  423.    lea      mp_msglist(a3),a0              ; initialize the unit's list
  424.    NEWLIST  a0
  425.    lea      mdu_tcb(a3),a0
  426.    move.l   a0,mp_sigtask(a3)
  427.    moveq.l  #0,d0                          ; Don't need to re-zero it
  428.    move.l   a3,a2
  429.    lea      mdu_Init,A1                    ; Initialize the UNIT
  430.    EXEC     InitStruct
  431.    move.l   a3,mdu_is+is_data(a3)          ; set intserver unit address
  432.    lea      mdu_tcb(a3),a1
  433.    lea      Proc_Begin(PC),a2
  434.    move.l   a3,-(sp)                       ; Preserve UNIT pointer
  435.    lea      -1,a3                          ; generate address error
  436.    moveq    #0,d0                          ; if task ever "returns"
  437.    EXEC     AddTask                        ; Startup the task
  438.    move.l   (sp)+,a3                       ; restore UNIT pointer
  439.    move.l   d2,d0                          ; unit number
  440.    lsl.l    #2,d0
  441.    move.l   a3,md_Units(a6,d0.l)           ; put unit into array
  442.    bra.s    InitUnit_End
  443.    ;------ got an error.  free the unit structure that we allocated.
  444. InitUnit_FreeUnit:
  445.    bsr     FreeUnit
  446. InitUnit_End:
  447.    movem.l   (sp)+,d2-d4/a2/a3
  448.    rts
  449.  
  450. FreeUnit:   ; ( a3:unitptr, a6:deviceptr )
  451.    move.l   a3,a1
  452.    move.l   #MyDevUnit_Sizeof,d0
  453.    EXEC     FreeMem
  454.    rts
  455.  
  456.  
  457. ExpungeUnit:   ; ( a3:unitptr, a6:deviceptr )
  458.    move.l  d2,-(sp)
  459.    lea     mdu_tcb(a3),a1
  460.    EXEC    RemTask
  461.    ;------ save the unit number
  462.    moveq   #0,d2
  463.    move.b  mdu_UnitNum(a3),d2
  464.    ;------ free the unit structure.
  465.    bsr     FreeUnit
  466.    ;------ clear out the unit vector in the device
  467.    lsl.l   #2,d2
  468.    clr.l   md_Units(a6,d2.l)
  469.    move.l  (sp)+,d2
  470.    rts
  471.  
  472.  
  473.  
  474. cmdtable:
  475.    DC.L   Invalid      ; 0  $00000001
  476.    DC.L   MyReset      ; 1  $00000002
  477.    DC.L   IORead       ; 2  $00000004
  478.    DC.L   IOWrite      ; 3  $00000008
  479.    DC.L   Update       ; 4  $00000010
  480.    DC.L   Clear        ; 5  $00000020
  481.    DC.L   MyStop       ; 6  $00000040
  482.    DC.L   Start        ; 7  $00000080
  483.    DC.L   Flush        ; 8  $00000100
  484.    DC.L   Motor        ; 9  $00000200  motor             (NO-OP)
  485.    DC.L   Seek         ; 10 $00000400  seek              (NO-OP)
  486.    DC.L   Format       ; 11 $00000800  format -> WRITE
  487.    DC.L   MyRemove     ; 12 $00001000  remove            (NO-OP)
  488.    DC.L   ChangeNum    ; 13 $00002000  changenum         (Returns 0)
  489.    DC.L   ChangeState  ; 14 $00004000  changestate
  490.    DC.L   ProtStatus   ; 15 $00008000  protstatus        (Returns 0)
  491.    DC.L   RawRead      ; 16 Not supported                (INVALID)
  492.    DC.L   RawWrite     ; 17 Not supported                (INVALID)
  493.    DC.L   GetDriveType ; 18 Get drive type               (Returns 1)
  494.    DC.L   GetNumTracks ; 19 Get number of tracks         (Returns NUMTRKS)
  495.    DC.L   AddChangeInt ; 20 Add disk change interrupt    (NO-OP)
  496.    DC.L   RemChangeInt ; 21 Remove disk change interrupt (NO-OP)
  497.    DC.L   Invalid
  498.    DC.L   Invalid
  499.    DC.L   Invalid
  500.    DC.L   Invalid
  501.    DC.L   Invalid
  502.    DC.L   Invalid
  503.    DC.L   Invalid      ; 29 SCSIdirect
  504. cmdtable_end:
  505.  
  506. ; this define is used to tell which commands should not be queued
  507. ; command zero is bit zero.
  508. ; The immediate commands are Invalid, Reset, Stop, Start, Flush
  509. ;
  510. IMMEDIATES      EQU     $000001c3  ; flush/start/stop/reset/invalid
  511.  
  512. ; BeginIO starts all incoming io.  The IO is either queued up for the
  513. ; unit task or processed immediately.
  514. ;
  515.  
  516. BeginIO:        ; ( iob: a1, device:a6 )
  517.         movem.l d0/d1/a0/a1/a3,-(sp)
  518.         ;------ bookkeeping
  519.         move.l  io_unit(a1),a3
  520.         ;------ see if the io command is within range
  521.         move.w  io_command(a1),d0
  522.         cmp.w   #MYDEV_END,d0
  523.         bcc     BeginIO_NoCmd
  524.         DISABLE    a0
  525.         ;------ process all immediate commands no matter what
  526.         move.w  #IMMEDIATES,d1
  527.         btst    d0,d1
  528.         bne.s   BeginIO_Immediate
  529.         ;------ see if the unit is STOPPED.  If so, queue the msg.
  530.         btst    #MDUB_STOPPED,unit_flags(a3)
  531.         bne.s   BeginIO_QueueMsg
  532.         ;------ this is not an immediate command.
  533.         bset    #UNITB_ACTIVE,unit_flags(a3)  ; see if the device is busy.
  534.         beq.s   BeginIO_Immediate
  535.         ;------ we need to queue the device.  mark us as needing attention.
  536. BeginIO_QueueMsg:
  537.         bset    #UNITB_INTASK,unit_flags(a3)  ; we are now busy!
  538.         bclr    #IOB_QUICK,io_flags(a1)
  539.         ENABLE  a0
  540.         move.l  a3,a0
  541.         EXEC    PutMsg                 ; put ioreq on unit's messagelist
  542.         bra     BeginIO_End
  543. BeginIO_NoCmd:
  544.         move.b  #IOERR_NOCMD,io_error(a1)
  545.         bra.s   BeginIO_End
  546. BeginIO_Immediate:
  547.         ENABLE  a0
  548.         bsr     PerformIO              ; do IO command immediately
  549. BeginIO_End:
  550.         movem.l (sp)+,d0/d1/a0/a1/a3
  551.         rts
  552.  
  553. ;
  554. ; PerformIO actually dispatches an io request.  It expects a3 to already
  555. ; have the unit pointer in it.  a6 has the device pointer (as always).
  556. ; a1 has the iorequest.  Bounds checking has already been done on
  557. ; the io request.
  558. ;
  559.  
  560. PerformIO:      ; ( iob:a1, unitptr:a3, devptr:a6 )
  561.         clr.b   io_error(a1)            ; No error so far
  562.         moveq   #0,d0
  563.         move.w  io_command(a1),d0
  564. ;        bug     <"cmd %02ld off=%08lx len=%08lx",10>,d0,io_offset(a1),io_length(a1)
  565.         lsl.w   #2,d0                   ; Multiply by 4 to get table offset
  566.         lea     cmdtable(pc),a0
  567.         move.l  0(a0,d0.w),a0
  568.         jmp     (a0)
  569.  
  570. ;
  571. ; TermIO sends the IO request back to the user.  It knows not to mark
  572. ; the device as inactive if this was an immediate request or if the
  573. ; request was started from the server task.
  574. ;
  575.  
  576. TermIO: ; ( iob:a1, unitptr:a3, devptr:a6 )
  577.         move.w  IO_COMMAND(a1),d0
  578.         move.w  #IMMEDIATES,d1
  579.         btst    d0,d1
  580.         bne.s   TermIO_Immediate
  581.         ;------ we may need to turn the active bit off.
  582.         btst    #UNITB_INTASK,UNIT_FLAGS(a3)
  583.         bne.s   TermIO_Immediate
  584.         ;------ the task does not have more work to do
  585.         bclr    #UNITB_ACTIVE,UNIT_FLAGS(a3)
  586. TermIO_Immediate:
  587.         ;------ if the quick bit is still set then we don't need to reply
  588.         ;------ msg -- just return to the user.
  589.         btst    #IOB_QUICK,IO_FLAGS(a1)
  590.         bne.s   TermIO_End
  591.         EXEC    ReplyMsg
  592. TermIO_End:
  593.         rts
  594.  
  595. AbortIO:
  596. RawRead:
  597. RawWrite:
  598. Invalid:
  599. GetNumTracks:
  600.    move.b   #IOERR_NOCMD,IO_ERROR(a1)
  601.    bra      TermIO
  602.  
  603.  
  604. Motor:
  605.    tst.l    io_length(a1)              ; motor off ?
  606.    bne.s    .done
  607.    move.l   io_unit(a1),a0
  608.    bclr     #MDUB_READY,unit_flags(a0) ; media may not be ready
  609. .done:
  610.    clr.l    io_actual(a1)
  611.    bra      TermIO
  612.  
  613.  
  614. MyReset:
  615. AddChangeInt:
  616. RemChangeInt:
  617. MyRemove:
  618. Seek:
  619. Remove:
  620. ChangeNum:
  621. UpDate:
  622. Clear:
  623. ProtStatus:
  624.    clr.l   IO_ACTUAL(a1)   ; Indicate drive isn't protected
  625.    bra     TermIO
  626.  
  627. GetDriveType:
  628.    move.l  #1,IO_ACTUAL(a1)      ; Make it look like 3.5"
  629.    bra     TermIO
  630.  
  631.  
  632. ; check to see if drive has a disk in it
  633.  
  634. ChangeState:
  635.    bsr     DoStart                     ; try to start media access
  636.    tst.l   d0                          ; error ?
  637.    bmi.s   .nodisk
  638.    tst.b   d0                          ; OK ?
  639.    beq.s   .diskin
  640.    cmp.b   #$02,d0                     ; check condition ?
  641.    bne.s   .nodisk
  642. .check:
  643.    bsr     DoSense                     ; read sense info
  644.    move.b  buffer+sns_skey,d0
  645.    and.b   #SDM_SKEY,d0
  646.    cmp.b   #SK_NOT_READY,d0            ; drive not ready ?
  647.    beq.s   .nodisk
  648. .diskin:
  649.    clr.l   io_actual(a1)
  650.    move.l  io_unit(a1),a0
  651.    bset    #MDUB_READY,unit_flags(a0)  ; drive has a disk in
  652.    bra.s   .done
  653. .nodisk:
  654.    move.l  #1,io_actual(a1)
  655.    move.l  io_unit(a1),a0
  656.    bclr    #MDUB_READY,unit_flags(a0)  ; drive is empty
  657. .done:
  658.    bra     Termio
  659.  
  660.  
  661. IORead:
  662. IOWrite:
  663. Format:
  664.    movem.l d2-d7/a2,-(sp)
  665.    clr.l   io_actual(a1)        ; no data moved yet
  666.    move.l  io_data(a1),a2       ; a2 = current position in data buffer
  667.    move.l  io_offset(a1),d6     ; d6 = current offset
  668.    move.l  io_length(a1),d5     ; d5 = io_length
  669.    beq     .done
  670.    move.l  d6,d0
  671.    and.w   #$01ff,d0            ; check for whole sectors
  672.    bne     .secerror
  673. .doblock:
  674.    moveq   #0,d7                ; retries=0
  675.    move.l  d5,d4
  676.    sub.l   io_actual(a1),d4
  677.    cmp.l   #$1fffe00,d4         ; d4 = current blocksize
  678.    bls.s   .doscsi
  679.    move.l  #$1fffe00,d4         ; limit to 32 MegaBytes
  680. .doscsi:
  681.    move.l  a2,a0
  682.    move.l  d6,d0
  683.    move.l  d4,d1
  684.    bsr     SCSI_ReadWrite       ; do SCSI read/write
  685.    swap    d0
  686.    tst.w   d0                   ; any errors ?
  687.    beq     .next
  688.    bsr     DoSense
  689.    move.b  buffer+sns_skey,d0
  690.    and.b   #SDM_SKEY,d0
  691.    cmp.b   #SK_NOT_READY,d0
  692.    beq.s   .diskout
  693. .retry:
  694.    addq.w  #1,d7
  695.    cmp.w   #5,d7
  696.    blo     .doscsi              ; try again
  697. .rwerror
  698.    move.b  #TDERR_NotSpecified,io_error(a1)
  699.    bra.s   .done
  700. .diskout:
  701.    bug     <"disk removed!",10>
  702.    move.b  #TDERR_DiskChanged,io_error(a1)
  703.    move.l  io_unit(a1),a0
  704.    bclr    #MDUB_READY,unit_flags(a0)
  705.    bra.s   .done
  706. .next:
  707.    add.l   d4,a2                ; data+block
  708.    add.l   d4,d6                ; offset+block
  709.    move.l  io_actual(a1),d0
  710.    add.l   d4,d0                ; actual+block
  711.    move.l  d0,io_actual(a1)
  712.    cmp.l   d5,d0                ; all done?
  713.    blo     .doblock
  714. .ok:
  715.    move.l  io_unit(a1),a0
  716.    bset    #MDUB_READY,unit_flags(a0)
  717.    clr.b   io_error(a1)
  718.    bra.s   .done
  719. .secerror:
  720.    move.b  #IOERR_BADLENGTH,io_error(a1)
  721. .done:
  722.    movem.l (sp)+,d2-d7/a2
  723.    bra     TermIO
  724.  
  725.  
  726. MyStop:
  727.    bset    #MDUB_STOPPED,UNIT_FLAGS(a3)
  728.    bra     TermIO
  729.  
  730. Start:
  731.    bsr     InternalStart
  732.    bra     TermIO
  733.  
  734. InternalStart:
  735.    move.l  a1,-(sp)
  736.    bclr    #MDUB_STOPPED,UNIT_FLAGS(a3)
  737.    moveq   #0,d0
  738.    move.b  MP_SIGBIT(a3),d1
  739.    bset    d1,d0
  740.    EXEC    Signal                      ; kick the task to start it moving
  741.    move.l  (sp)+,a1
  742.    rts
  743.  
  744.  
  745. Flush:
  746.    movem.l d2/a1,-(sp)
  747.    bset    #MDUB_STOPPED,UNIT_FLAGS(a3)
  748.    sne     d2
  749. Flush_Loop:
  750.    move.l  a3,a0
  751.    EXEC    GetMsg
  752.    tst.l   d0
  753.    beq.s   Flush_End
  754.    move.l  d0,a1
  755.    move.b  #IOERR_ABORTED,IO_ERROR(a1)
  756.    EXEC    ReplyMsg
  757.    bra.s   Flush_Loop
  758. Flush_End:
  759.    move.l  d2,d0
  760.    movem.l (sp)+,d2/a1
  761.    tst.b   d0
  762.    beq.s   .termio
  763.    bsr     InternalStart
  764. .termio
  765.    bra     TermIO
  766.  
  767. ;-----------------------------------
  768. ;  Init Signalling Message Port
  769. ;-----------------------------------
  770. ;
  771. ; error = InitPort(port)
  772. ;   d0              a0
  773. ;
  774. InitPort:
  775.   movem.l d2/a2,-(sp)
  776.   move.l  a0,a2
  777.   moveq.l #-1,d0
  778.   exec    AllocSignal                  ; obtain sigbit
  779.   move.l  d0,d2
  780.   bmi.s   .error
  781.   sub.l   a1,a1
  782.   exec    FindTask                     ; find our task
  783.   move.l  d0,MP_SIGTASK(a2)
  784.   move.b  d2,MP_SIGBIT(a2)
  785.   move.b  #NT_MSGPORT,LN_TYPE(a2)
  786.   move.b  #PA_SIGNAL,MP_FLAGS(a2)
  787.   lea     MP_MSGLIST(a2),a1
  788.   lea     4(a1),a0
  789.   move.l  a0,lh_head(a1)               ; init messagelist
  790.   clr.l   lh_tail(a1)
  791.   move.l  a1,lh_tailpred(a1)
  792.   moveq   #0,d0
  793.   bra.s   .done
  794. .error:
  795.   moveq   #-1,d0
  796. .done:
  797.   movem.l (sp)+,d2/a2
  798.   rts
  799.  
  800.  
  801. ;-----------------------------------
  802. ;   Free Message Port Resources
  803. ;-----------------------------------
  804. ; FreePort(port)
  805. ;           a0
  806. ;
  807. FreePort:
  808.   clr.l   mp_sigtask(a0)
  809.   move.b  mp_sigbit(a0),d0
  810.   bmi.s   .done
  811.   EXEC    FreeSignal
  812. .done:
  813.   rts
  814.  
  815.  
  816. ; -------------------------- our process -------------------------------
  817.  
  818.    cnop    0,4                 ; long word align
  819.    dc.l    16                  ; segment length -- any number will do
  820. myproc_seglist:
  821.    dc.l    0                   ; pointer to next segment
  822. Proc_Begin:
  823.    move.l  4(sp),a3            ; a3 = Unit
  824.    moveq   #-1,d0
  825.    EXEC    AllocSignal         ; allocate sigbit for unit port
  826.    move.b  d0,mp_sigbit(a3)
  827.    moveq   #0,d7               ; d7 = signals to wait for
  828.    bset    d0,d7
  829.    lea     timereq(pc),a1
  830.    tst.l   io_device(a1)       ; timer.device available ?
  831.    bne.s   Proc_MainLoop
  832.    move.l  a3,mn_replyport(a1)
  833.    bsr     Start_Timer             ; start timer for diskchange polling
  834. Proc_MainLoop:
  835.    move.l  d7,d0
  836.    EXEC    Wait                    ; wait for next unit and/or timer ioreq
  837. Proc_CheckStatus:
  838.    btst    #MDUB_STOPPED,unit_flags(a3)
  839.    bne.s   Proc_MainLoop                 ; is device stopped ?
  840.    bset    #UNITB_ACTIVE,unit_flags(a3)
  841.    bne.s   Proc_MainLoop                 ; device is in use
  842. Proc_NextMessage:
  843.    move.l  a3,a0
  844.    EXEC    GetMsg                        ; get next message
  845.    tst.l   d0
  846.    beq.s   Proc_Unlock                   ; got all messages ?
  847.    lea     TimeReq(pc),a0
  848.    cmp.l   a0,d0                         ; is it a timer request ?
  849.    bne.s   Proc_IO
  850.    bsr     ReportChangeState             ; check for diskchange
  851.    bsr     Start_Timer                   ; restart timer
  852.    bra.s   Proc_NextMessage
  853. Proc_IO:
  854.    move.l  d0,a1
  855.    move.l  mdu_Device(a3),a6
  856.    bsr     PerformIO                     ; process the ioreq
  857.    bra.s   Proc_NextMessage
  858. Proc_Unlock:
  859.    and.b   #~(UNITF_ACTIVE!UNITF_INTASK),UNIT_FLAGS(a3)
  860.    bra     Proc_MainLoop
  861.  
  862.  
  863. ;========================= device-specific code ======================
  864.  
  865. ;---------------------------------------------------------------------
  866. ;                       Open Timer Device
  867. ;---------------------------------------------------------------------
  868. ;
  869. OpenTimer:
  870.   lea      replyport(pc),a0
  871.   bsr      InitPort                      ; init replyport
  872.   moveq    #UNIT_MICROHZ,d0
  873.   moveq    #0,d1
  874.   lea      timername(pc),a0
  875.   lea      delayreq(pc),a1
  876.   EXEC     OpenDevice                    ; open timer device
  877.   tst.l    d0
  878.   bne.s    .done
  879.   lea      delayreq(pc),a0
  880.   lea      timereq(pc),a1
  881.   move.l   io_device(a0),io_device(a1)   ; copy device/unit
  882.   move.l   io_unit(a0),io_unit(a1)
  883. .done:
  884.   bug      <"OpenTimer: error=%ld",10>,d0
  885.   rts
  886.  
  887. ;---------------------------------------------------------------------
  888. ;               Start Timer for DiskChange Polling
  889. ;---------------------------------------------------------------------
  890. ;
  891. ; error = Start_Timer()
  892. ;
  893. Start_timer:
  894.   lea      timereq(pc),a1
  895.   move.l   #2,iotv_time+tv_secs(a1)         ; signal after 2 seconds
  896.   move.l   #0,iotv_time+tv_micro(a1)
  897.   move.w   #TR_ADDREQUEST,io_command(a1)
  898.   EXEC     SendIO
  899.   rts
  900.  
  901. ;---------------------------------------------------------------------
  902. ;                       Report DiskChanges
  903. ;---------------------------------------------------------------------
  904. ;
  905. ReportChangeState:
  906.   rts
  907.  
  908.  
  909. ;------------------------------------------------------
  910. ;                     Time Delay
  911. ;------------------------------------------------------
  912. ; in: d0 = delay in uS
  913. ;
  914. ; NOTE:  - long delays must be single-threaded
  915. ;
  916. timedelay:
  917.   movem.l  d0-d2/a0/a1/a6,-(sp)
  918.   tst.l    d0                            ; no do weird delay time!
  919.   ble      .done
  920.   lea      delayreq(pc),a1
  921.   tst.l    io_device(a1)                 ; timer device open ?
  922.   beq      .delayloop
  923.   moveq    #0,d1
  924.   move.l   #1000000,d2
  925. .divide:
  926.   sub.l    d2,d0
  927.   bmi.s    .set
  928.   addq.l   #1,d1                         ; calculate seconds, microseconds
  929.   bra.s    .divide
  930. .set:
  931.   add.l    d2,d0
  932.   move.l   d1,iotv_time+tv_secs(a1)
  933.   move.l   d0,iotv_time+tv_micro(a1)
  934.   move.w   #TR_ADDREQUEST,io_command(a1)
  935.   lea      replyport(pc),a0
  936.   bsr      InitPort                      ; init replyport
  937.   tst.l    d0
  938.   bne.s    .error
  939.   lea      delayreq(pc),a1
  940.   EXEC     DoIO                          ; do time delay
  941.   lea      replyport(pc),a0
  942.   bsr      freeport                      ; free replyport's sigbit
  943.   bra.s    .done
  944. .error:
  945.   bug      <"no spare sigbits!",10>      ; eek!
  946. .delayloop:
  947.   tst.b    $bfe001                       ; busy loop
  948.   subq.l   #1,d0
  949.   bne.s    .delayloop
  950. .done:
  951.   movem.l  (sp)+,d0-d2/a0/a1/a6
  952.   rts
  953.  
  954.  
  955. ;-------------------------------------------------------------
  956. ;            Get Exclusive use of Joystick Port
  957. ;-------------------------------------------------------------
  958. ;
  959. GetGamePort:
  960.   moveq   #0,d0                          ; no error yet
  961.   lea     joytype(pc),a0
  962.   cmp.b   #GPCT_ALLOCATED,(a0)
  963.   beq     .done                          ; have we got it already ?
  964. .open:
  965.   lea     gameio(pc),a1
  966.   lea     gamename(pc),a0
  967.   moveq   #1,d0                          ; unit 1 = joystick port
  968.   moveq   #0,d1
  969.   EXEC    OpenDevice                     ; open gameport.device
  970.   tst.l   d0
  971.   bne     .nodevice
  972.   EXEC    Forbid                         ; prevent task switching
  973.   lea     gameio(pc),a1
  974.   move.w  #GPD_ASKCTYPE,io_command(a1)
  975.   moveq   #1,d0                          ; 1 byte for joytype
  976.   move.l  d0,io_length(a1)
  977.   lea     joytype(pc),a0
  978.   move.l  a0,io_data(a1)
  979.   move.b  #IOF_QUICK,io_flags(a1)
  980.   EXEC    DoIO                           ; read controller type
  981.   lea     joytype(pc),a0
  982.   moveq   #-1,d0                         ; error if already allocated
  983.   cmp.b   #GPCT_NOCONTROLLER,(a0)
  984.   bne.s   .permit                        ; already allocated ?
  985.   lea     gameio(pc),a1
  986.   move.w  #GPD_SETCTYPE,io_command(a1)
  987.   moveq   #1,d0
  988.   move.l  d0,io_length(a1)
  989.   move.b  #GPCT_ALLOCATED,(a0)           ; allocate gameport
  990.   move.l  a0,io_data(a1)
  991.   move.b  #IOF_QUICK,io_flags(a1)
  992.   EXEC    DoIO                           ; set controller type
  993.   moveq   #0,d0                          ; OK
  994. .permit:
  995.   EXEC    Permit                         ; allow task switching
  996.   tst.l   d0
  997.   beq.s   .done                          ; got it ?
  998. .error:
  999.   clr.b   (a0)                           ; no joytype
  1000.   lea     nojoytext(pc),a0
  1001.   bsr     AutoRequest                    ; 'joystick port in use' requester
  1002.   tst.l   d0
  1003.   bne     .open                          ; again if user selected 'retry'
  1004. .nodevice:
  1005.   moveq   #-1,d0
  1006. .done:
  1007.   rts
  1008.  
  1009.  
  1010.  
  1011. ;------------------------------------------------------
  1012. ;                 Free Joystick Port
  1013. ;------------------------------------------------------
  1014. ;
  1015. FreeGamePort:
  1016.   lea     gameio(pc),a1
  1017.   tst.l   io_device(a1)                  ; got the device ?
  1018.   beq.s   .done
  1019.   move.w  #GPD_SETCTYPE,io_command(a1)
  1020.   moveq   #1,d0
  1021.   move.l  d0,io_length(a1)
  1022.   lea     joytype(pc),a0
  1023.   move.b  #GPCT_NOCONTROLLER,(a0)        ; gameport not allocated
  1024.   move.l  a0,io_data(a1)
  1025.   move.b  #IOF_QUICK,io_flags(a1)
  1026.   EXEC    doio                           ; set controller type
  1027.   lea     gameio(pc),a1
  1028.   EXEC    closedevice                    ; close gameport.device
  1029. .done:
  1030.   rts
  1031.  
  1032. ;------------------------------------------------------
  1033. ;        Get Exclusive use of Parallel Port
  1034. ;------------------------------------------------------
  1035. ; Error = getparallelport()
  1036. ;  D0
  1037. ;
  1038. GetParallelPort:
  1039.   move.l  a6,-(sp)
  1040.   lea     miscname(pc),a1
  1041.   EXEC    openresource               ; open misc.resource
  1042.   move.l  d0,miscbase
  1043.   beq.s   .nosys
  1044. .getpar:
  1045.   move.l  miscbase(pc),a6
  1046.   moveq   #MR_PARALLELBITS,d0        ; give us the parallel bits
  1047.   lea     myname(pc),a1
  1048.   jsr     MR_Allocmiscresource(a6)
  1049.   tst.l   d0
  1050.   bne.s   .error
  1051.   moveq   #MR_PARALLELPORT,d0
  1052.   lea     myname(pc),a1
  1053.   jsr     MR_Allocmiscresource(a6)   ; give us the parallel port
  1054.   tst.l   d0
  1055.   beq.s   .done                      ; did we get the port ?
  1056.   moveq   #MR_PARALLELBITS,d0
  1057.   jsr     MR_Freemiscresource(a6)
  1058. .error:
  1059.   lea     NoPortText(pc),a0
  1060.   bsr     AutoRequest
  1061.   tst.l   d0
  1062.   bne.s   .getpar
  1063. .nosys:
  1064.   moveq   #-1,D0                     ; error
  1065. .done:
  1066.   move.l  (sp)+,a6
  1067.   rts
  1068.  
  1069. ;===========================================
  1070. ;    display a retry/cancel requester
  1071. ;===========================================
  1072. ;  in: a0 = message text
  1073. ;
  1074. ; out: d0 = choice
  1075. ;
  1076. AutoRequest:
  1077.   movem.l d2/d3/a2/a3/a6,-(sp)
  1078.   moveq   #0,d2                      ; default choice = cancel
  1079.   move.l  a0,a2
  1080.   lea     Intuiname(pc),a1
  1081.   moveq   #0,d0
  1082.   EXEC    OpenLibrary                ; open intuition library
  1083.   tst.l   d0
  1084.   beq.s   .nosys
  1085.   move.l  d0,a6
  1086.   moveq   #0,d0
  1087.   move.l  d0,d1
  1088.   move.l  d0,a0
  1089.   move.l  #300,d2
  1090.   move.l  #70,d3
  1091.   move.l  a2,a1
  1092.   lea     yestext(pc),a2
  1093.   lea     notext(pc),a3
  1094.   jsr     _LVOAutoRequest(a6)        ; create requester and wait for choice
  1095.   move.l  d0,d2
  1096.   move.l  a6,a0
  1097.   EXEC    CloseLibrary
  1098. .nosys:
  1099.   move.l  d2,d0                      ; return choice
  1100.   movem.l (sp)+,d2/d3/a2/a3/a6
  1101.   rts
  1102.  
  1103.  
  1104. ;------------------------------------------------------
  1105. ;               Free Parallel Port
  1106. ;------------------------------------------------------
  1107. FreeParallelPort:
  1108.   move.l  a6,-(sp)
  1109.   move.l  miscbase(pc),d0
  1110.   beq.s   .done
  1111.   move.l  d0,a6
  1112.   moveq   #MR_PARALLELBITS,d0
  1113.   jsr     MR_Freemiscresource(A6)
  1114.   moveq   #MR_PARALLELPORT,d0
  1115.   jsr     MR_Freemiscresource(A6)
  1116. .done:
  1117.   move.l  (sp)+,a6
  1118.   rts
  1119.  
  1120.  
  1121.  
  1122. ;--------------------------------------------------------
  1123. ;              do SCSI Read/Write/Format
  1124. ;--------------------------------------------------------
  1125. ;
  1126. ;  in:  a0 = buffer
  1127. ;       d0 = offset
  1128. ;       d1 = length
  1129. ;
  1130. ;  out: d0 = status information
  1131. ;
  1132. ;       bits 31-24 = error flags
  1133. ;            23-16 = status port (if phase error)
  1134. ;             15-8 = message byte
  1135. ;              7-0 = status byte
  1136. ;
  1137. SCSI_ReadWrite:
  1138.     movem.l d2-d4/a1/a2/a6,-(sp)
  1139.     move.l  a0,a2                  ; a2 = buffer
  1140.     move.l  d1,d4                  ; d4 = length
  1141.     moveq   #0,d2                  ; status = OK
  1142.     lea     cmdbuf(pc),a0          ; a0 = SCSI command block
  1143.     clr.b   1(a0)
  1144.     lsr.l   #8,d0                  ; startsec = offset/512
  1145.     lsr.l   #1,d0
  1146.     move.l  d0,2(a0)               ; put startsec into command block
  1147.     clr.b   6(a0)
  1148.     move.l  d4,d0
  1149.     lsr.l   #1,d0                  ; numsects=length/512
  1150.     lsr.l   #8,d0
  1151.     move.b  d0,8(a0)
  1152.     lsr.w   #8,d0                  ; put numsects into command block
  1153.     move.b  d0,7(a0)
  1154.     clr.b   9(a0)
  1155.     cmp.w   #CMD_READ,io_command(a1)
  1156.     bne.s   .write
  1157. .read:
  1158.     move.b  #$28,(a0)              ; scsi READ(10) command
  1159.     bra.s   .docmd
  1160. .write:
  1161.     move.b  #$2a,(a0)              ; scsi WRITE(10) command
  1162. .docmd:
  1163.     bsr     connect                ; SCSI connect
  1164.     bsr     pp_select
  1165.     tst.l   d0                     ; select SCSI target
  1166.     bne.s   .selecterror
  1167.     move.l  #SLCT_TIMEOUT,d0
  1168.     bsr     pp_wait                ; wait for command phase
  1169.     tst.l   d0
  1170.     bmi     .badphase
  1171.     bsr     pp_command             ; send command string
  1172.     tst.l   d0
  1173.     bmi     .badphase
  1174.     move.l  #DATA_TIMEOUT,d0
  1175.     bsr     pp_wait
  1176.     cmp.w   #READ,d0               ; data phase (read) ?
  1177.     beq     .rd
  1178.     cmp.w   #WRITE,d0              ; data phase (write) ?
  1179.     beq     .wr
  1180.     cmp.w   #STATUS,d0             ; status phase?
  1181.     bne     .badphase
  1182.     bset    #EarlyStatusBit,d2     ; rd/wr not accepted!
  1183.     bra     .getstatbyte
  1184. .selecterror:
  1185.     bset    #SelectErrorBit,d2     ; failed to select drive
  1186.     bra     .done
  1187. .rd move.l  d4,d0
  1188.     move.l  a2,a0
  1189.     bsr     getblock               ; read data block
  1190.     bra.s   .xfrdone
  1191. .wr move.l  d4,d0
  1192.     move.l  a2,a0                  ; write data block
  1193.     bsr     putblock
  1194. .xfrdone:
  1195.     moveq   #0,d3
  1196. .waitstat:
  1197.     move.l  #STAT_TIMEOUT,d0
  1198.     bsr     pp_wait                ; wait until r/w completed
  1199.     tst.l   d0
  1200.     bmi     .timeout
  1201.     cmp.w   #STATUS,d0             ; status phase ?
  1202.     beq     .getstatbyte
  1203.     addq.l  #1,d3                  ; try again
  1204.     cmp.w   #1000,d3               ; exceeded max tries?
  1205.     blo.s   .waitstat
  1206.     bug     <"Unexpected Phase %03lx",10>,d0
  1207.     cmp.w   #READ,d0
  1208.     bne.s   .badphase
  1209.     moveq   #0,d1
  1210. .getjunk:
  1211.     bsr     getbyte
  1212.     move.l  #STAT_TIMEOUT,d0
  1213.     bsr     pp_wait
  1214.     tst.l   d0
  1215.     bmi.s   .badphase
  1216.     addq.l  #1,d1
  1217.     cmp.w   #STATUS,d0
  1218.     bne.s   .getjunk
  1219.     bug     <"read %ld extra bytes",10>,d1
  1220.     bsr     getbyte
  1221.     move.l  #MESG_TIMEOUT,d0
  1222.     bsr     pp_wait                ; wait for message byte
  1223.     tst.l   d0
  1224.     bmi.s   .badphase
  1225.     bsr     getbyte
  1226. .badphase:
  1227.     bset    #PhaseErrorBit,d2      ; invalid phase
  1228.     swap    d2
  1229.     move.b  d0,d2                  ; return status port bits
  1230.     swap    d2
  1231.     bra     .done
  1232. .getstatbyte:
  1233.     bsr     getbyte                ; get status byte
  1234.     move.b  d0,d2
  1235. .waitmsg:
  1236.     move.l  #MESG_TIMEOUT,d0
  1237.     bsr     pp_wait                ; wait for message byte
  1238.     tst.l   d0
  1239.     bge.s   .msg
  1240. .timeout:
  1241.     bset    #TimeOutBit,d2         ; timed out waiting for msg
  1242.     bra.s   .done
  1243. .msg:
  1244.     bsr     getbyte                ; get message byte
  1245.     lsl.w   #8,d0
  1246.     or.w    d0,d2
  1247. .done:
  1248.     bsr     disconnect             ; SCSI disconnect
  1249.     move.l  d2,d0
  1250.     movem.l (sp)+,d2-d4/a1/a2/a6
  1251.     rts
  1252.  
  1253.  
  1254. ;--------------------------------------------------------------
  1255. ;               Send a SCSI command string
  1256. ;--------------------------------------------------------------
  1257. ;
  1258. pp_command:
  1259.     lea     cmdbuf(pc),a0
  1260. .cmdloop
  1261.     moveq   #0,d0
  1262.     move.b  (a0)+,d0
  1263.     move.b  d0,dataport           ; send command byte
  1264.     delay
  1265.     move.b  #AFDXT,jport
  1266.     delay                         ; pulse autofeedxt
  1267.     move.b  #NO_XT,jport
  1268.     delay
  1269.     move.l  #COMD_TIMEOUT,d0
  1270.     bsr     pp_wait               ; wait for command byte accepted
  1271.     tst.l   d0
  1272.     bmi.s   .done
  1273.     cmp.w   #COMAND,d0
  1274.     beq     .cmdloop
  1275. .done:
  1276.     rts
  1277.  
  1278.  
  1279. ;--------------------------------------------------------------
  1280. ;          Select ZIP drive as SCSI device 6
  1281. ;--------------------------------------------------------------
  1282. pp_select:
  1283.     move.l  d2,-(sp)
  1284.     move.w  #SEL_TIMEOUT,d2
  1285. .wait:
  1286.     bsr     getstat
  1287.     btst    #ACKBIT,d0             ; wait until not selected
  1288.     beq.s   .select
  1289. .waitns:
  1290.     dbf     d2,.wait
  1291.     bra     .error                 ; error if timed out
  1292. .select:
  1293.     setmode PPOUT
  1294.     delay
  1295.     move.b  #1<<6,dataport         ; send target SCSI address
  1296.     delay
  1297.     move.b  #AFDXT,jport
  1298.     delay                          ; pulse autofeedxt
  1299.     move.b  #NO_XT,jport
  1300.     delay
  1301.     move.b  #$80,dataport
  1302.     delay
  1303.     setmode PPHOST                 ; send 'select target' ctrl byte
  1304.     delay
  1305.     move.w  #SEL_TIMEOUT,d2
  1306. .waitdrive:
  1307.     bsr     getstat
  1308.     btst    #ACKBIT,d0             ; wait until selected
  1309.     bne.s   .good
  1310.     dbf     d2,.waitdrive
  1311. .error:                            ; error if timed out
  1312.     moveq   #-1,d2
  1313.     bra.s   .done
  1314. .good:
  1315.     moveq   #0,d2
  1316. .done:
  1317.     setmode PPOUT
  1318.     delay
  1319.     move.l  d2,d0
  1320.     move.l  (sp)+,d2
  1321.     rts
  1322.  
  1323.  
  1324.  
  1325. ;----------------------------------
  1326. ;    send SCSI connect request
  1327. ;----------------------------------
  1328. ;
  1329. connect:
  1330.      move.l  d0,-(sp)
  1331.      moveq   #$00,d0
  1332.      bsr     conbyte
  1333.      moveq   #$3c,d0
  1334.      bsr     conbyte
  1335.      moveq   #$20,d0
  1336.      bsr     conbyte
  1337.      move.b  #$8f,d0
  1338.      bsr     conbyte
  1339.      move.l  (sp)+,d0
  1340.      rts
  1341.  
  1342.  
  1343. ;----------------------------------
  1344. ;      send a connect byte
  1345. ;----------------------------------
  1346. ;
  1347. ;   d0 = connect byte
  1348. ;
  1349. conbyte:
  1350.      move.b  d0,dataport
  1351.      delay
  1352.      setmode PPSTAT
  1353.      delay
  1354.      move.b  #AFDXT,jport
  1355.      delay
  1356.      move.b  #NO_XT,jport
  1357.      delay
  1358.      setmode PPOUT
  1359.      delay
  1360.      rts
  1361.  
  1362.  
  1363. ;----------------------------------
  1364. ;  send SCSI disconnect request
  1365. ;----------------------------------
  1366. ;
  1367. disconnect:
  1368.      move.l  d0,-(sp)
  1369.      moveq   #$00,d0
  1370.      bsr     disbyte
  1371.      moveq   #$3c,d0
  1372.      bsr     disbyte
  1373.      moveq   #$20,d0
  1374.      bsr     disbyte
  1375.      moveq   #$0f,d0
  1376.      bsr     disbyte
  1377.      move.l  (sp)+,d0
  1378.      rts
  1379.  
  1380. ;---------------------------------
  1381. ;     send a disconnect byte
  1382. ;---------------------------------
  1383. ;
  1384. ; d0 = disconnect byte
  1385. ;
  1386. disbyte:
  1387.      move.b  d0,dataport
  1388.      delay
  1389.      setmode PPOUT
  1390.      delay
  1391.      move.b  #AFDXT,jport
  1392.      delay
  1393.      move.b  #NO_XT,jport
  1394.      delay
  1395.      setmode PPSTAT
  1396.      delay
  1397.      setmode PPOUT
  1398.      delay
  1399.      rts
  1400.  
  1401. ;------------------------------------------------------------
  1402. ;            Get status bits from joystick port
  1403. ;------------------------------------------------------------
  1404. ;
  1405. getstat:
  1406.      moveq   #0,d0
  1407.      move.w  statport,d0
  1408.      and.w   #STATMASK,d0
  1409.      bchg    #9,d0           ; invert SEL
  1410.      bne.s   .1
  1411.      bchg    #8,d0           ; invert ACK
  1412. .1   bchg    #1,d0           ; invert BUSY
  1413.      bne.s   .done
  1414.      bchg    #0,d0           ; invert POUT
  1415. .done:
  1416.      rts
  1417.  
  1418.  
  1419. ;----------------------------------------------------------------
  1420. ;                    Wait for status bits
  1421. ;----------------------------------------------------------------
  1422. ;
  1423. ;  in: d0 = max time to wait for ready bit
  1424. ;
  1425. ;
  1426. ;  out: d0 = status information.
  1427. ;
  1428. ;        WRITE  = ZIP wants more data
  1429. ;        READ   = ZIP wants to send more data
  1430. ;        COMAND = ZIP wants another command byte
  1431. ;        STATUS = end of transfer, ZIP is sending status byte
  1432. ;        -1     = timeout
  1433. ;
  1434. pp_wait:
  1435.       movem.l d1/d2,-(sp)
  1436.       move.l  d0,d2              ; d2 = max time to wait
  1437.       moveq   #0,d1              ; d1 = timeout counter
  1438. .wait bsr     getstat
  1439.       btst    #BUSYBIT,d0        ; wait until zip is not busy
  1440.       beq.s   .done
  1441.       cmp.l   #5000,d1
  1442.       blo.s   .short
  1443.       delay   5000               ; go to sleep for 5mS
  1444.       add.l   #4990,d1
  1445. .short:
  1446.       add.l   #10,d1             ; timed out ?
  1447.       cmp.l   d2,d1
  1448.       bls.s   .wait
  1449. .timeout:
  1450.       bug     <"pp_wait(%ld) timeout!",10>,d2
  1451.       moveq   #-1,d0             ; return error code -1
  1452. .done movem.l (sp)+,d1/d2
  1453.       rts
  1454.  
  1455.  
  1456. ;------------------------------------------
  1457. ;  Initialise parallel port and ZIP drive
  1458. ;------------------------------------------
  1459. pp_init:
  1460.      move.l  a1,-(sp)
  1461.      move.b  #$ff,dirport
  1462.      move.b  #$ff,dataport
  1463.      setmode PPOUT
  1464.      move.b  #$c7,ctrldir
  1465.      move.b  #$80,jport
  1466.      move.b  #$83,jdir
  1467.      setmode PPINIT
  1468.      delay   1000                    ; send /init
  1469.      setmode PPOUT
  1470.      delay   100
  1471.      bsr     disconnect
  1472.      bsr     connect
  1473.      move.b  #AFDXT,jport
  1474.      delay
  1475.      move.b  #NO_XT,jport
  1476.      delay
  1477.      move.b  #$40,dataport           ; reset SCSI bus
  1478.      delay
  1479.      setmode PPHOST
  1480.      delay   30
  1481.      setmode PPOUT
  1482.      delay   1000
  1483.      bsr     disconnect
  1484.      delay   1000
  1485.      bsr     DoSense                 ; SCSI read sense info
  1486.      tst.l   d0
  1487.      bmi.s   .error
  1488.      bsr     DoStart                 ; Start Media Access
  1489.      tst.l   d0
  1490.      bmi.s   .error
  1491.      bsr     DoSense                 ; SCSI read sense info
  1492.      tst.l   d0
  1493.      bpl.s   .done
  1494. .error:
  1495.      bug     <"Init failed, check your hardware!",10>
  1496.      moveq   #-1,d0
  1497. .done:
  1498.      move.l  (sp)+,a1
  1499.      rts
  1500.  
  1501.  
  1502. ;----------------------------------------------------------------
  1503. ;                Do SCSI 'Check Unit Ready'
  1504. ;----------------------------------------------------------------
  1505. ;
  1506. DoCheck:
  1507.      lea     cmdbuf(pc),a0
  1508.      move.l  #$00000000,(a0)       ; TEST_UNIT_READY
  1509.      move.w  #$0000,4(a0)
  1510.      bra     DoSCSI
  1511.  
  1512.  
  1513. ;----------------------------------------------------------------
  1514. ;                Do SCSI 'Start Unit'
  1515. ;----------------------------------------------------------------
  1516. ;
  1517. DoStart:
  1518.      lea     cmdbuf(pc),a0
  1519.      move.l  #$1b000000,(a0)       ; START_STOP_UNIT
  1520.      move.w  #$0100,4(a0)          ; start
  1521.      bra.s   DoSCSI
  1522.  
  1523.  
  1524. ;----------------------------------------------------------------
  1525. ;                Do SCSI 'Read Sense data'
  1526. ;----------------------------------------------------------------
  1527. ;
  1528. DoSense:
  1529.      lea     cmdbuf(pc),a0
  1530.      move.l  #$03000000,(a0)       ; READ_SENSE
  1531.      move.w  #$4000,4(a0)          ;
  1532.      bra.s   DoSCSI
  1533.  
  1534. ;----------------------------------------------------------------
  1535. ;                Do SCSI 'Read Equiry data'
  1536. ;----------------------------------------------------------------
  1537. ;
  1538. DoEnquiry:
  1539.      lea     cmdbuf(pc),a0         ; a0 = SCSI command block
  1540.      move.l  #$12000000,(a0)       ; ENQUIRY
  1541.      move.w  #$9300,4(a0)          ;
  1542.  
  1543. ;----------------------------------------------------------------
  1544. ;                Do Internal SCSI Command
  1545. ;----------------------------------------------------------------
  1546. ;
  1547. DoSCSI:
  1548.      move.l  d2,-(sp)
  1549.      moveq   #0,d2                 ; d2 = return code
  1550.      bsr     connect
  1551.      bsr     pp_select             ; select target SCSI address
  1552.      tst.l   d0
  1553.      bne     .failed
  1554.      move.l  #SLCT_TIMEOUT,d0
  1555.      bsr     pp_wait               ; wait for drive ready
  1556.      tst.l   d0
  1557.      bmi     .failed
  1558.      bsr     pp_command            ; send SCSI command
  1559.      tst.l   d0                    ; command sent OK ?
  1560.      bpl.s   .nextphase
  1561.      lea     cmdbuf(pc),a0
  1562.      cmp.b   #$1b,(a0)             ; start unit ?
  1563.      bne     .failed
  1564.      move.l  #STRT_TIMEOUT,d0
  1565.      bsr     pp_wait               ; wait up to 3 seconds
  1566.      tst.l   d0
  1567.      bpl.s   .status
  1568.      bra     .failed
  1569. .nextphase:
  1570.      cmp.w   #READ,d0              ; now in READ phase ?
  1571.      bne     .status
  1572.      lea     buffer,a0
  1573.      bsr     getbytes              ; read data into buffer
  1574.      move.l  #DATA_TIMEOUT,d0
  1575.      bsr     pp_wait               ; wait for end data phase
  1576.      tst.l   d0
  1577.      bmi.s   .failed
  1578. .status:
  1579.      cmp.w   #STATUS,d0            ; want to read status byte ?
  1580.      bne.s   .failed
  1581.      bsr     getbyte               ; get status byte
  1582.      move.b  d0,d2                 ; d2 = status byte
  1583.      move.l  #MESG_TIMEOUT,d0
  1584.      bsr     pp_wait
  1585.      tst.l   d0
  1586.      bmi.s   .failed
  1587.      bsr     getbyte               ; get message byte
  1588.      bra.s   .done
  1589. .failed:
  1590.      moveq   #-1,d2
  1591. .done:
  1592.      move.l  d2,d0
  1593.      move.l  (sp)+,d2
  1594.      rts
  1595.  
  1596.  
  1597.  
  1598. ;--------------------------------------------------------------------
  1599. ;                     output a block
  1600. ;--------------------------------------------------------------------
  1601. ;
  1602. ;    putblock(buffer,len)
  1603. ;               a0    d0
  1604. putblock:
  1605.       movem.l d1-d2/a1-a2,-(sp)
  1606.       lea     dataport,a1
  1607.       lea     jport,a2
  1608.       move.b  #AFDXT,d1
  1609.       move.b  #NO_XT,d2
  1610. .loop move.b  (a0)+,(a1)
  1611.       move.b  d1,(a2)
  1612.       move.b  d2,(a2)
  1613.       subq.l  #1,d0
  1614.       bne.s   .loop
  1615. .done movem.l (sp)+,d1-d2/a1-a2
  1616.       rts
  1617.  
  1618.  
  1619. ;--------------------------------------------------------------------
  1620. ;                      output a single byte
  1621. ;--------------------------------------------------------------------
  1622. ;      putbyte(byte)
  1623. ;               d0
  1624. putbyte:
  1625.       move.b  d0,dataport
  1626.       delay
  1627.       move.b  #AFDXT,jport
  1628.       delay
  1629.       move.b  #NO_XT,jport
  1630.       delay
  1631.       rts
  1632.  
  1633.  
  1634. ;--------------------------------------------------------------------
  1635. ;                         read a block
  1636. ;---------------------------------------------------------------------
  1637. ;    getblock(buffer,len)
  1638. ;               a0    d0
  1639. getblock:
  1640.       movem.l d1-d3/a1-a2,-(sp)
  1641.       move.l  d0,d3
  1642.       lea     dataport,a1
  1643.       lea     jport,a2
  1644.       move.b  #AFDXT,d1
  1645.       move.b  #NO_XT,d2
  1646.       move.b  #$00,dirport          ; port direction set to input
  1647.       setmode PPIN
  1648.       delay
  1649. .loop:
  1650.       move.b  (a1),(a0)+            ; get byte
  1651.       move.b  d1,(a2)
  1652.       move.b  d2,(a2)               ; 'data accepted' pulse
  1653.       move.b  (a1),(a0)+            ; get byte
  1654.       move.b  d1,(a2)
  1655.       move.b  d2,(a2)               ; 'data accepted' pulse
  1656.       move.b  (a1),(a0)+            ; get byte
  1657.       move.b  d1,(a2)
  1658.       move.b  d2,(a2)               ; 'data accepted' pulse
  1659.       move.b  (a1),(a0)+            ; get byte
  1660.       move.b  d1,(a2)
  1661.       move.b  d2,(a2)               ; 'data accepted' pulse
  1662.       move.b  (a1),(a0)+            ; get byte
  1663.       move.b  d1,(a2)
  1664.       move.b  d2,(a2)               ; 'data accepted' pulse
  1665.       move.b  (a1),(a0)+            ; get byte
  1666.       move.b  d1,(a2)
  1667.       move.b  d2,(a2)               ; 'data accepted' pulse
  1668.       move.b  (a1),(a0)+            ; get byte
  1669.       move.b  d1,(a2)
  1670.       move.b  d2,(a2)               ; 'data accepted' pulse
  1671.       move.b  (a1),(a0)+            ; get byte
  1672.       move.b  d1,(a2)
  1673.       move.b  d2,(a2)               ; 'data accepted' pulse
  1674.       subq.l  #8,d3
  1675.       bne.s   .loop
  1676. .done:
  1677.       setmode PPSTAT
  1678.       move.b  #$ff,dirport          ; port direction set to output
  1679.       delay
  1680.       setmode PPOUT
  1681.       delay
  1682.       movem.l (sp)+,d1-d3/a1-a2
  1683.       rts
  1684.  
  1685.  
  1686. ;---------------------------------------------------------------------
  1687. ;                       read some bytes
  1688. ;---------------------------------------------------------------------
  1689. ;    numbytes=getbytes(buffer)
  1690. ;      d0                a0
  1691. getbytes:
  1692.       move.l  d2,-(sp)
  1693.       moveq   #0,d2
  1694. .loop bsr     getbyte
  1695.       move.b  d0,(a0)+
  1696.       addq.l  #1,d2
  1697.       bsr     getstat
  1698.       cmp.w   #READ,d0
  1699.       bne.s   .done
  1700.       cmp.w   #512,d2
  1701.       blo.s   .loop
  1702. .done:
  1703.       move.l  d2,d0
  1704.       move.l  (sp)+,d2
  1705.       rts
  1706.  
  1707.  
  1708. ;---------------------------------------------------------------------
  1709. ;                     read a single byte
  1710. ;---------------------------------------------------------------------
  1711. ;      d0 = getbyte()
  1712. ;
  1713. getbyte:
  1714.       move.b  #$00,dirport          ; port direction set to input
  1715.       setmode PPIN
  1716.       delay
  1717.       move.b  dataport,d1           ; get byte
  1718.       delay
  1719.       move.b  #AFDXT,jport
  1720.       delay                         ; 'data accepted' pulse
  1721.       move.b  #NO_XT,jport
  1722.       setmode PPSTAT
  1723.       move.b  #$ff,dirport          ; port direction set to output
  1724.       delay
  1725.       setmode PPOUT
  1726.       delay
  1727.       move.l  d1,d0
  1728.       rts
  1729.  
  1730.  
  1731.  
  1732. ; ---------------- static data -------------------
  1733.  
  1734. MyName:
  1735.    dc.b 'ppazip.device',0
  1736. idString:
  1737.    dc.b 'ppazip '
  1738.    dc.b (VERSION+"0"),'.',(REVISION+"0"),' '
  1739.    dc.b __DATE
  1740.    dc.b ' by Bruce Abbott',10,0
  1741. miscname
  1742.    dc.b 'misc.resource',0
  1743. intuiname:
  1744.    dc.b 'intuition.library',0
  1745. timername:
  1746.    dc.b 'timer.device',0
  1747. gamename:
  1748.    dc.b 'gameport.device',0
  1749.    even
  1750.  
  1751. Yestext:
  1752.   dc.b 2,1
  1753.   dc.b 1
  1754.   dc.b 0
  1755.   dc.w 6,4
  1756.   dc.l 0
  1757.   dc.l .Text
  1758.   dc.l 0
  1759.  
  1760. .Text:
  1761.   dc.b  "RETRY",0
  1762.   even
  1763.  
  1764. Notext:
  1765.   dc.b 2,1
  1766.   dc.b 1
  1767.   dc.b 0
  1768.   dc.w 6,4
  1769.   dc.l 0
  1770.   dc.l .Text
  1771.   dc.l 0
  1772.  
  1773. .Text:
  1774.   dc.b  "CANCEL",0
  1775.   even
  1776.  
  1777.  
  1778. NoPortText:
  1779.   dc.b  3,1
  1780.   dc.b  1
  1781.   dc.b  0
  1782.   dc.w  10,20
  1783.   dc.l  0
  1784.   dc.l  .txt
  1785.   dc.l  0
  1786. .txt:
  1787.   dc.b  'ppazip: parallel port in use!',0
  1788.  
  1789. NoJoyText:
  1790.   dc.b  3,1
  1791.   dc.b  1
  1792.   dc.b  0
  1793.   dc.w  10,20
  1794.   dc.l  0
  1795.   dc.l  .txt
  1796.   dc.l  0
  1797. .txt:
  1798.   dc.b  'ppazip: joystick port in use!',0
  1799.  
  1800.   even
  1801.  
  1802.  
  1803.  
  1804. EndCode:
  1805.  
  1806. ; ---------------- variable data -----------------
  1807.  
  1808. execbase:
  1809.    dc.l  0     ; cached execbase
  1810. miscbase:
  1811.    dc.l  0     ; misc resource
  1812.  
  1813.  
  1814. ; ---- IO Request for DiskChange Polling ----
  1815. ;
  1816. ; NOTE: used only by our task
  1817. ;
  1818. TimeReq:
  1819.    dc.l 0           ; ln_head  }         }
  1820.    dc.l 0           ; ln_pred  }         }
  1821.    dc.b NT_MESSAGE  ; ln_type  } mp_node }
  1822.    dc.b 0           ; ln_pri   }         } io_message
  1823.    dc.l 0           ; ln_name  }         }
  1824.    dc.l 0           ; mn_replyport       }
  1825.    dc.w iotv_size   ; mn_length          }
  1826.    dc.l 0           ;                      io_device
  1827.    dc.l 0           ;                      io_unit
  1828.    dc.w 0           ;                      io_command
  1829.    dc.b 0           ;                      io_flags
  1830.    dc.b 0           ;                      io_error
  1831.    dc.l 0           ;                      tv_secs
  1832.    dc.l 0           ;                      tv_micros
  1833.  
  1834.  
  1835.  
  1836. ; ---- IO Request for Time Delay ----
  1837. ;
  1838. ; NOTE: may be used by calling tasks
  1839. ;
  1840. DelayReq:
  1841.    dc.l 0           ; ln_head  }         }
  1842.    dc.l 0           ; ln_pred  }         }
  1843.    dc.b NT_MESSAGE  ; ln_type  } mp_node }
  1844.    dc.b 0           ; ln_pri   }         } io_message
  1845.    dc.l 0           ; ln_name  }         }
  1846.    dc.l replyport   ; mn_replyport       }
  1847.    dc.w iotv_size   ; mn_length          }
  1848.    dc.l 0           ;                      io_device
  1849.    dc.l 0           ;                      io_unit
  1850.    dc.w 0           ;                      io_command
  1851.    dc.b 0           ;                      io_flags
  1852.    dc.b 0           ;                      io_error
  1853.    dc.l 0           ;                      tv_secs
  1854.    dc.l 0           ;                      tv_micros
  1855.  
  1856.  
  1857. ; ---- IO Request for Obtaining Joystick Port ----
  1858.  
  1859. gameio:
  1860.    dc.l 0           ; ln_head  }         }
  1861.    dc.l 0           ; ln_pred  }         }
  1862.    dc.b NT_MESSAGE  ; ln_type  } mp_node }
  1863.    dc.b 0           ; ln_pri   }         } io_message
  1864.    dc.l 0           ; ln_name  }         }
  1865.    dc.l replyport   ; mn_replyport       }
  1866.    dc.w iostd_size  ; mn_length          }
  1867.    dc.l 0           ;                      io_device
  1868.    dc.l 0           ;                      io_unit
  1869.    dc.w 0           ;                      io_command
  1870.    dc.b 0           ;                      io_flags
  1871.    dc.b 0           ;                      io_error
  1872.  
  1873.  
  1874.  
  1875. ; ----  Signalling Message Port ----
  1876. ;
  1877. ; NOTE: may be used by calling tasks
  1878. ;
  1879. ReplyPort:
  1880.    dc.l 0           ; ln_head      }
  1881.    dc.l 0           ; ln_pred      }
  1882.    dc.b NT_MSGPORT  ; ln_type      } mp_node
  1883.    dc.b 0           ; ln_pri       }
  1884.    dc.l 0           ; ln_name      }
  1885.    dc.b PA_SIGNAL   ;                mp_flags
  1886.    dc.b 0           ;                mp_sigbit
  1887.    dc.l 0           ;                mp_sigtask
  1888. .h dc.l .t          ; lh_head      }
  1889. .t dc.l 0           ; lh_tail      }
  1890.    dc.l .h          ; lh_tailpred  } mp_msglist
  1891.    dc.b 0           ; lh_type      }
  1892.    dc.b 0           ; lh_pad       }
  1893.  
  1894.  
  1895. joytype:
  1896.    dc.b  0     ; joystick controller type
  1897.    even
  1898.  
  1899. cmdbuf:
  1900.    ds.b 12
  1901.    even
  1902.  
  1903.     BSS
  1904.  
  1905. buffer:
  1906.    ds.b  512
  1907.  
  1908.    END
  1909.