home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / diskutil / tapebios / tapebios.s < prev    next >
Encoding:
Text File  |  1993-08-06  |  29.6 KB  |  744 lines

  1. *************************************************************************
  2. *                                    *
  3. *  This is a GENERIC tape driver, for most SCSI compliant Tape Drives.    *
  4. *  Written by Alan Hourihane, current version 1.5 (13/3/91)        *
  5. *                                    *
  6. *************************************************************************
  7.  
  8. VERSION         equ $00010005        * Version 1.5
  9. rvalid            equ $426        * Resvalid
  10. rvector         equ $42a        * Reset Vector
  11. RMAGIC            equ $31415926        * Reset magic value
  12. PCOOKIE         equ $5a0        * Cookie Pointer
  13. NOCOOK            equ 20            * Twenty New Cookies.
  14. wdc            equ $ffff8604        * WD Controller
  15. port            equ $fffffa01        * DMA port (FDC/HDC bit 5)
  16. dma            equ $ffff8609        * DMA control register
  17. flock            equ $43e        * Resource Lock flag location
  18. INQUIRE            equ 12            * Inquire function
  19.  
  20. *************************************************************************
  21. * Start of code. But jump straight away to installation phase.        *
  22. *************************************************************************
  23.  
  24. start:        bra.w    install     * Jump to Initialization point.
  25.  
  26. *************************************************************************
  27. * This section contains the details for the XBRA id installation    *
  28. *************************************************************************
  29.  
  30.         dc.b    "XBRATAPE"    * The XBRA id 'TAPE'.
  31. oldtrap10:    dc.l    0        * The old TRAP #10 vector is
  32.                     * placed here after installation.
  33.  
  34. *************************************************************************
  35. *  New TRAP #10 Handler, then jump to old TRAP #10 if call not for us.    *
  36. *************************************************************************
  37.  
  38. newtrap10:    move.w    (sp),d0     * New TRAP #10 entry point.
  39.         btst    #13,d0        * Test for supervisor mode.
  40.         bne.b    nousp        * 
  41.         move    usp,a0        * Get User Stack Pointer.
  42.         bra.b    dousp        *
  43. nousp:        movea.l sp,a0        * Point to incomming arguments
  44.         addq.l    #6,a0        *
  45. dousp:        cmpi.w    #$ACE,(a0)    * Is this function call for us ?
  46.         beq.b    tape_io     * Yes go to it.
  47. do_10:        movea.l oldtrap10,a0    * Get old TRAP #10 entry address
  48. systrap10:    jmp    (a0)        * Go to old vector handler
  49.     
  50. *************************************************************************
  51. * If we got here, then we need to perform some sort of TAPE I/O.    *
  52. *************************************************************************
  53.  
  54. tape_io:                * We're ready for TAPE I/O.
  55.  
  56. timeout:    move.w    #0,d0        * Timeout for next TAPE call.
  57.                     * Changed when install complete.
  58.                     * 0 to 65535 maximum.
  59.     
  60. subtime:    tst.w    d0        * Has timeout value been reached.
  61.         beq    continue    * Execute streamer command, if zero.
  62.         sub.w    #1,d0        * Decrease timeout value.
  63.         bra    subtime     * Subtract again.
  64.         
  65. continue:    move.l    $8(a0),nblock    * Get and save number of blocks.
  66.         move.l    $4(a0),bufadr    * Get and save buffer address.
  67.         move.w    $2(a0),d0    * Get and save read/write flag.
  68.         tst.w    d0        * < 0 (i.e. is it a valid function) 
  69.         bmi.s    error        * Not valid, return error.
  70.         cmp.w    #12,d0        * > 12 (i.e. is it a valid function)
  71.         bgt.s    error        * Not valid, return error.
  72.         lsl.w    #2,d0        * Convert to long table offsets.
  73.         lea    jmptbl,a0    * Get jump table base.
  74.         move.l    0(a0,d0.w),a0    * Get function address from table.
  75.         jmp    (a0)        * Perform function as requested.
  76.  
  77. error:        rte            * Return with error function.
  78.  
  79. jmptbl:     dc.l    t_ready     * Test Unit Ready.
  80.         dc.l    t_read        * Read tape.
  81.         dc.l    t_write     * Write tape.
  82.         dc.l    t_rewind    * Rewind tape.
  83.         dc.l    t_load        * Load tape.
  84.         dc.l    t_unload    * Unload tape.
  85.         dc.l    t_filmk     * Write File marks.
  86.         dc.l    t_rsense    * Request Sense.
  87.         dc.l    t_mselect    * Mode Select.
  88.         dc.l    t_msense    * Mode Sense.
  89.         dc.l    t_space     * Space command.
  90.         dc.l    t_erase     * Erase tape.
  91.         dc.l    t_inquire    * Inquiry.
  92.  
  93. *************************************************************************
  94. *                                    *
  95. * The following functions are the jump table commands to perform the    *
  96. * specific functions required on the tape drive. The code sets up the    *
  97. * necessary data packets that need to be sent across the DMA bus.    *
  98. *                                    *
  99. *************************************************************************
  100.  
  101. *************************************************************************      
  102. * Perform a TEST UNIT READY command.                    *
  103. *************************************************************************
  104.  
  105. t_ready:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  106.         lea    cdb,a0        * Pop command block into A0.
  107.         move.b    #0,(a0)+    * 'SCSI command for READY' 
  108.         clr.b    (a0)+        * Command block, must be zero.
  109.         clr.b    (a0)+        * ....
  110.         clr.b    (a0)+        * ...
  111.         clr.b    (a0)+        * ..
  112.         clr.b    (a0)        * Flag = 0, Link = 0.
  113.         move.w    #1,dmacnt    * DMA count.
  114.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  115.         bsr    dout        * Branch to DATA OUT phase code.
  116.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  117.         rte            * Return from TRAP #10.
  118.         
  119. *************************************************************************
  120. * Perform a READ command.                        *
  121. *************************************************************************
  122.  
  123. t_read:     movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  124.         lea    cdb,a0        * Pop command block into A0.
  125.         move.b    #8,(a0)+    * 'SCSI command for READ'
  126.         move.b    #1,(a0)+    * Fixed = 1.
  127.         move.b    nblock+1,(a0)+    * Transfer Length (MSB)
  128.         move.b    nblock+2,(a0)+    * Transfer Length
  129.         move.b    nblock+3,(a0)+    * Transfer Length (LSB)
  130.         clr.b    (a0)        * Flag = 0, Link = 0.
  131.         move.w    nblock+2,d0    * Get 16 bit block read count.
  132.         move.w    d0,dmacnt    * Value for dma block transfer.
  133.         bsr    din        * Branch to DATA IN phase code.
  134.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  135.         rte            * Return from TRAP #10.
  136.         
  137. *************************************************************************
  138. * Perform a WRITE command.                        *
  139. *************************************************************************
  140.        
  141. t_write:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  142.         lea    cdb,a0        * Pop command block into A0.
  143.         move.b    #$A,(a0)+    * 'SCSI command for WRITE'
  144.         move.b    #1,(a0)+    * Fixed = 1.
  145.         move.b    nblock+1,(a0)+    * Transfer Length (MSB)
  146.         move.b    nblock+2,(a0)+    * Transfer Length
  147.         move.b    nblock+3,(a0)+    * Transfer Length (LSB)
  148.         clr.b    (a0)        * Flag = 0, Link = 0.
  149.         move.w    nblock+2,d0    * Get 16 bit block write count.
  150.         move.w    d0,dmacnt    * Value for dma block transfer.
  151.         bsr    dout        * Branch to DATA OUT phase code.
  152.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  153.         rte            * Return from TRAP #10.
  154.     
  155. *************************************************************************
  156. * Perform a REWIND command.                        *
  157. *************************************************************************
  158.  
  159. t_rewind:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  160.         lea    cdb,a0        * Pop command block into A0.
  161.         move.b    #1,(a0)+    * 'SCSI command for REWIND'
  162.         clr.b    (a0)+        * Immed = 0.
  163.         clr.b    (a0)+        * Command block, must be zero.
  164.         clr.b    (a0)+        * ...
  165.         clr.b    (a0)+        * ..
  166.         clr.b    (a0)        * Flag = 0, Link = 0.
  167.         move.w    #1,dmacnt    * DMA count.
  168.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  169.         bsr    dout        * Branch to DATA OUT phase code.
  170.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  171.         rte            * Return from TRAP #10.
  172.     
  173. *************************************************************************
  174. * Perform an LOAD command.                        *
  175. *************************************************************************
  176.        
  177. t_load:     movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  178.         lea    cdb,a0        * Pop command block into A0.
  179.         move.b    #$1b,(a0)+    * 'SCSI command for LOAD'
  180.         clr.b    (a0)+        * Immed = 0.
  181.         clr.b    (a0)+        * Command block, must be zero.
  182.         clr.b    (a0)+        * ..
  183.         move.b    nblock+3,d0    * Re-Ten, 0 or 2 for retension.
  184.         lsl.b    #1,d0        * ...
  185.         and.b    #2,d0        * ..
  186.         or.b    #1,d0        * Load = 1.
  187.         move.b    d0,(a0)+    * ..
  188.         clr.b    (a0)        * Flag = 0, Link = 0.
  189.         move.w    #1,dmacnt    * DMA count.
  190.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  191.         bsr    dout        * Branch to DATA OUT phase code.
  192.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  193.         rte            * Return from TRAP #10.
  194.  
  195. *************************************************************************
  196. * Perform a MODE SELECT command.                    *
  197. *************************************************************************
  198.  
  199. t_mselect:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  200.         lea    cdb,a0        * Pop command block into A0.
  201.         move.b    #$15,(a0)+    * 'SCSI command for MODE SELECT'
  202.         clr.b    (a0)+        * Command block, must be zero.
  203.         clr.b    (a0)+        * ...
  204.         clr.b    (a0)+        * ..
  205.         move.b    nblock+3,(a0)+    * Parameter List Length.
  206.         clr.b    (a0)        * Flag = 0, Link = 0.
  207.         move.w    #1,dmacnt    * DMA count.
  208.         bsr    dout        * Branch to DATA OUT phase code.
  209.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  210.         rte            * Return from TRAP #10.
  211.         
  212. *************************************************************************
  213. * Perform a MODE SENSE command.                     *
  214. *************************************************************************
  215.  
  216. t_msense:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  217.         lea    cdb,a0        * Pop command block into A0.
  218.         move.b    #$1A,(a0)+    * 'SCSI command for MODE SENSE'
  219.         clr.b    (a0)+        * Command block, must be zero.
  220.         clr.b    (a0)+        * ...
  221.         clr.b    (a0)+        * ..
  222.         move.b    nblock+3,(a0)+    * Parameter List Length.
  223.         clr.b    (a0)        * Flag = 0, Link = 0.
  224.         move.w    #1,dmacnt    * DMA count.
  225.         bsr    din        * Branch to DATA IN phase code.
  226.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  227.         rte            * Return from TRAP #10.
  228.  
  229. *************************************************************************
  230. * Perform an UNLOAD command.                        *
  231. *************************************************************************
  232.        
  233. t_unload:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  234.         lea    cdb,a0        * Pop command block into A0.
  235.         move.b    #$1b,(a0)+    * 'SCSI command for UNLOAD'
  236.         clr.b    (a0)+        * Immed = 0.
  237.         clr.b    (a0)+        * Command block, must be zero.
  238.         clr.b    (a0)+        * ..
  239.         move.b    nblock+3,d0    * Re-Ten, 0 or 2 for retension.
  240.         lsl.b    #1,d0        * ...
  241.         and.b    #2,d0        * Load = 0.
  242.         move.b    d0,(a0)+    * ..
  243.         clr.b    (a0)        * Flag = 0, Link = 0.
  244.         move.w    #1,dmacnt    * DMA count.
  245.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  246.         bsr    dout        * Branch to DATA OUT phase code.
  247.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  248.         rte            * Return from TRAP #10.
  249.         
  250. *************************************************************************
  251. * Perform a WRITE FILEMARKS command.                    *
  252. *************************************************************************
  253.  
  254. t_filmk:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  255.         lea    cdb,a0        * Pop command block into A0.
  256.         move.b    #$10,(a0)+    * 'SCSI command for WRITE FILEMARK'
  257.         clr.b    (a0)+        * Command block, must be zero.
  258.         move.b    nblock+1,(a0)+    * Number of Filemarks (MSB)
  259.         move.b    nblock+2,(a0)+    * Number of Filemarks
  260.         move.b    nblock+3,(a0)+    * Number of Filemarks (LSB)
  261.         clr.b    (a0)        * Str = 0, Flag = 0, Link = 0.
  262.         move.w    #1,dmacnt    * DMA count.
  263.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  264.         bsr    dout        * Branch to DATA OUT phase code.
  265.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  266.         rte            * Return from TRAP #10.
  267.         
  268. *************************************************************************
  269. * Perform a REQUEST SENSE command.                    *
  270. *************************************************************************
  271.  
  272. t_rsense:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  273.         lea    cdb,a0        * Pop command block into A0.
  274.         move.b    #3,(a0)+    * 'SCSI command for REQUEST SENSE'
  275.         clr.b    (a0)+        * Command block, must be zero.
  276.         clr.b    (a0)+        * ...
  277.         clr.b    (a0)+        * ..
  278.         move.b    nblock+3,(a0)+    * Allocation Length.
  279.         clr.b    (a0)        * Flag = 0, Link = 0.
  280.         move.w    #1,dmacnt    * DMA count.
  281.         bsr    din        * Branch to DATA IN phase code.
  282.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  283.         rte            * Return from TRAP #10.
  284.  
  285. *************************************************************************
  286. * Perform a SPACE command.                        *
  287. *************************************************************************
  288.        
  289. t_space:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  290.         lea    cdb,a0        * Pop command block into A0.
  291.         move.b    #$11,(a0)+    * 'SCSI command for SPACE'
  292.         move.b    nblock,(a0)+    * Code bits (bits 0 and 1).
  293.         move.b    nblock+1,(a0)+    * Count (MSB).
  294.         move.b    nblock+2,(a0)+    * Count.
  295.         move.b    nblock+3,(a0)+    * Count (LSB).
  296.         clr.b    (a0)        * Flag = 0, Link = 0.
  297.         move.w    #1,dmacnt    * DMA count.
  298.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  299.         bsr    dout        * Branch to DATA OUT phase code.
  300.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  301.         rte            * Return from TRAP #10.
  302.  
  303. *************************************************************************
  304. * Perform an ERASE command.                        *
  305. *************************************************************************
  306.        
  307. t_erase:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  308.         lea    cdb,a0        * Pop command block into A0.
  309.         move.b    #$19,(a0)+    * 'SCSI command for ERASE'
  310.         move.b    #1,(a0)+    * Long = 1.
  311.         clr.b    (a0)+        * Command block, must be zero.
  312.         clr.b    (a0)+        * ...
  313.         clr.b    (a0)+        * ..
  314.         clr.b    (a0)        * Flag = 0, Link = 0.
  315.         move.w    #1,dmacnt    * DMA count.
  316.         move.l    #lbuf,bufadr    * Get local scratch buffer address.
  317.         bsr    dout        * Branch to DATA OUT phase code.
  318.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  319.         rte            * Return from TRAP #10.
  320.  
  321. *************************************************************************
  322. * Perform an INQUIRY command.                        *
  323. *************************************************************************
  324.  
  325. t_inquire:    movem.l a1/d1,-(sp)    * Save A1 and D1 registers.
  326.         lea    cdb,a0        * Pop command block into A0.
  327.         move.b    #$12,(a0)+    * 'SCSI command for INQUIRY'
  328.         clr.b    (a0)+        * Command block, must be zero.
  329.         clr.b    (a0)+        * ...
  330.         clr.b    (a0)+        * ..
  331.         move.b    nblock+3,(a0)+    * Allocation Length.
  332.         clr.b    (a0)        * Flag = 0, Link = 0.
  333.         move.w    #1,dmacnt    * DMA count.
  334.         bsr    din        * Branch to DATA IN phase code.
  335.         movem.l (sp)+,a1/d1    * Restore A1 and D1 registers.
  336.         rte            * Return from TRAP #10.
  337.  
  338. *************************************************************************
  339. * End of the jump table offset code.                    *
  340. * Next, follows the code to send the data to and from the tape device.    *
  341. *************************************************************************
  342.  
  343. *************************************************************************
  344. * Issue command and RECEIVE data from SCSI device            *
  345. *************************************************************************
  346.  
  347. din:        move.l    #wdc,a0     * Load WD Controller address to A0.
  348.         bsr.w    sendcdb     * Setup DMA and send DCB to controller.
  349.         bmi.w    tout        * controller/DMA time-out
  350.         move.w    #$190,2(a0)    *
  351.         nop            *
  352.         nop            *
  353.         move.w    #$90,2(a0)    *
  354.         nop            *
  355.         nop            *
  356.         move.w    dmacnt,(a0)    *
  357.         clr.l    d1        *
  358.         move.w    #$8A,2(a0)    *
  359.         move.b    (a1),d1     * Get last byte of CDB
  360.         swap    d1        *
  361.         move.l    d1,(a0)     * last byte of CDB (initiate)
  362.         move.w    #$8A,d1     *
  363.         bra.b    exec        *
  364.         
  365. *************************************************************************
  366. * Issue command and SEND data to SCSI device.                *
  367. *************************************************************************
  368.  
  369. dout:        move.l    #wdc,a0     *
  370.         bsr.w    sendcdb     * setup DMA and send DCB to controller
  371.         move.w    #$90,2(a0)    *
  372.         nop            *
  373.         nop            *
  374.         move.w    #$190,2(a0)    *
  375.         nop            *
  376.         nop            *
  377.         move.w    dmacnt,(a0)    * DMA block count setup
  378.         clr.l    d1        *
  379.         move.w    #$18A,2(a0)    *
  380.         move.b    (a1),d1     * Get last byte of CDB
  381.         swap    d1        *
  382.         move.w    #$100,d1    *
  383.         move.l    d1,(a0)     * last byte of CDB (initiate)
  384.         move.w    #$18A,d1    *
  385.  
  386. exec:        bsr.w    wait        * go wait for complete intr.
  387.         bmi.b    tout        * loop timed out --->
  388.         move.w    d1,2(a0)    *
  389.         nop            *
  390.         move.w    (a0),d0     * get HDC/DMA status in d0
  391.         and.w    #$FF,d0     * Strip all but HDC bits
  392.         bra.s    ndto        *
  393.  
  394. tout:        move.w    #-2,d0        * Device time-out
  395.  
  396. ndto:        move.w    #$80,2(a0)    *
  397.         nop            *
  398.         tst.w    (a0)        *
  399.         clr.w    flock        * clear Floppy VBI
  400.         rts            *
  401.  
  402. *************************************************************************
  403. * Set parameters (Set DMA, and send first 5 bytes of DCB).        *
  404. *************************************************************************
  405.  
  406. sendcdb:    st    flock        * Set flock
  407.         move.b    bufadr+3,dma+4    * Set DMA buffer address LOW
  408.         move.b    bufadr+2,dma+2    * Set DMA buffer address MED
  409.         move.b    bufadr+1,dma    * Set DMA buffer address HIGH
  410.         move.w    #$88,2(a0)    * Set HDC access, (Device Select ?)
  411.  
  412.         lea    cdb,a1        * Get Base address of CDB
  413.         clr.l    d0        *
  414.         move.b    acsi,d0     * Place DEVICE ID in upper 3 bits of cmd
  415.         and.b    #$e0,d0     * make sure only top 3 bits
  416.         or.b    (a1)+,d0    * and put 1st byte of CDB in also
  417.         swap    d0        *
  418.         move.w    #$8A,d0     * put in ST's needed direction and addr
  419.         move.l    d0,(a0)     * DCB byte #0 (Command + Device Number)
  420.  
  421.         move.w    #3,d1        * all but last byte but last byte of CDB
  422.         move.w    #$8A,2(a0)    * Issue first byte (not included in CDBSIZ)
  423.         bsr    swait        *
  424.         bmi    parmo        *
  425.  
  426. scdbl:        clr.l    d0        * Now send all but last byte ....
  427.         move.b    (a1)+,d0    * Get Next Byte
  428.         swap    d0        *
  429.         move.w    #$8A,d0     *
  430.         move.l    d0,(a0)     * Send Next DCB byte
  431.         bsr.w    swait        * wait for intr
  432.         bmi.b    parmo        * Timeout exit
  433.         dbf    d1,scdbl    * 
  434. parmo:        rts            * Return to caller.
  435.  
  436. *************************************************************************
  437. * Wait for Command Complete                        *
  438. *************************************************************************
  439.  
  440. wait:        move.l    #$4000000,d0    * Init long wait (approx 2 mins)
  441.         bra.b    waitl        * Goto wait loop
  442. swait:        move.l    #$100000,d0    * Init short wait (approx 20 secs)
  443. waitl:        subq.l    #1,d0        * Wait loop - decrement time-out counter
  444.         bmi.b    waito        * Rollover means time-out!
  445.         btst    #$5,port    * Interrupt yet, HDC/FDC (bit 5).
  446.         bne.b    waitl        * Not yet , keep waiting till intr or time-out
  447.         clr.l    d0        * Clear CPU's N flag = interrupt received.
  448. waito:        rts            * Return to caller.
  449.  
  450. *************************************************************************
  451. * UNJAR code, for those versions of TOS that don't clear COOKIE JAR's    *
  452. *************************************************************************
  453.  
  454.         dc.b    "XBRAUJAR"    * XBRA id for UJAR - Unjar Code.
  455. vecsave:    ds.l    1        * Space for vector save.
  456. rhand:        clr.l    PCOOKIE     * Clear pointer to cookie jar.
  457.         move.l    vecsave,rvector * Move vecsave to Reset vector.
  458.         move.l    valsave,rvalid    * Move valsave to Reset value.
  459.         jmp    (a6)        * Jump to reset routine.
  460. valsave:    ds.l    1        * Space for value save.
  461.         
  462. *************************************************************************
  463. * Space for necessary DATA, during TRAP #10 call.            *
  464. *************************************************************************
  465.  
  466. nblock: dc.l    0            * 
  467. bufadr: dc.l    0            * Buffer Address.
  468. dmacnt: dc.w    0            * DMA count.
  469. acsi:    dc.w    0            * ACSI address of Tape Streamer.
  470. cdb:    ds.b    6            * 
  471. lbuf:    ds.b    512            * Local 512 byte DMA buffer.
  472.  
  473. *************************************************************************
  474. * End of Resident trap code. After install, approximately 2KB.        *
  475. *************************************************************************
  476.  
  477. *************************************************************************
  478. * Installation Code.                            *
  479. *************************************************************************
  480.  
  481. install:    move.l    a7,a5        * Store stack to determine basepage.
  482.         move.l    4(a5),a5    * BasePage is now in A5.
  483.         move.l    12(a5),d0    * Text segment length stands in A0.
  484.         add.l    20(a5),d0    * Add to that the length of the data,
  485.         add.l    28(a5),d0    * And the BSS segments,
  486.         add.l    #$500,d0    * And the amount needed for stack.
  487.         move.l    d0,d1        *
  488.         add.l    a5,d1        * Length + address of basepage.
  489.         and.l    #-2,d1        * Be sure stack starts on even address.
  490.         move.l    d1,a7        * Now put stack where we want it.
  491.         move.l    d0,-(sp)    * Size of reserved area.
  492.         move.l    a5,-(sp)    * Start of reserved area.
  493.         clr.w    -(sp)        * Dummy.
  494.         move.w    #$4A,-(sp)    * Setblock function call.
  495.         trap    #1        * Call TRAP #1, to activate.
  496.         add.l    #12,-(sp)    * Tidy stack.
  497.         clr.l    -(sp)        * User stack becomes supervisor stack.
  498.         move.w    #$20,-(sp)    * Supervisor mode.
  499.         trap    #$1        * Call TRAP #1, to activate.
  500.         addq.l    #6,sp        * Tidy stack.
  501.         move.l    d0,stkp     * Save old stack pointer to stkp.
  502.         move.l    (PCOOKIE),a6    * Find COOKIE JAR pointer.
  503.         move.l    a6,d0        * Move pointer to data register.
  504.         tst.l    d0        * Test, Is there a cookie jar ?
  505.         beq    createjar    * No, so create one, then continue.
  506. doinst:     clr.l    d6        * Clear cookie counter.
  507. isit:        move.l    (a6)+,d7    * Get a cookie name.
  508.         add.l    #4,a6        * Skip value, Go to next cookie.
  509.         add.l    #1,d6        * Add one to cookie counter.
  510.         cmp.l    #'TAPE',d7    * Test, Is TapeBIOS already installed.
  511.         beq    already     * Yes, Tell user and abort.
  512.         tst.l    d7        * Test, Have we hit the zero cookie.
  513.         bne isit        * No, Go again.
  514.         sub.l    #4,a6        * Go back to name pointer.
  515.         move.l    (a6),d7     * Get number of cookies in jar.
  516.         cmp.l    d7,d6        * Test, Is cookie jar full.
  517.         beq copyjar        * Yes, Install new jar.
  518.         
  519. jardone:    move.w    #0,-(sp)    * Open TAPEBIOS.INF for read
  520.         pea    tapeinf     * Push name onto stack.
  521.         move.w    #$3d,-(sp)    * Function call for open.
  522.         trap    #1        * Call TRAP #1, to open.
  523.         addq.l    #8,sp        * Tidy stack.
  524.         tst.l    d0        * Test, Any problems opening file.
  525.         bmi    tinfopen    * Yes, tell user and abort.
  526.         move    d0,fhandle    * Save file handle.
  527.         pea    tapebuf     * Push buffer address onto stack.
  528.         move.l    #7,-(sp)    * Get 7 bytes from TAPEBIOS.INF
  529.         move.w    fhandle,-(sp)    * Push file handle onto stack.
  530.         move.w    #$3f,-(sp)    * Function call for read.
  531.         trap    #1        * Call TRAP #1, to read.
  532.         add.l    #12,-(sp)    * Tidy stack.
  533.         cmp.l    #7,d0        * Did we get the 7 bytes.
  534.         bne    tapeinferr    * No, so tell user and abort.
  535.         move.w    fhandle,-(sp)    * Push file handle onto stack.
  536.         move.w    #$3e,-(sp)    * Function call for close.
  537.         trap    #1        * Call TRAP #1, to close.
  538.         addq.l    #4,sp        * Tidy stack.
  539.         tst.l    d0        * Did we close TAPEBIOS.INF OK.
  540.         bmi    tinfclose    * No, tell user and abort.
  541.     
  542.         move.b    tapebuf,d0    * Get the SCSI ID number of device.
  543.         sub.b    #'0',d0     * Change from ASCII to binary value.
  544.         bmi    ivdid        * < 0 (i.e. invalid ID)
  545.         cmp.b    #7,d0        * Compare with ID with 7.
  546.         bhi    ivdid        * > 7 (i.e. invalid ID)
  547.         lsl.b    #5,d0        * Move bits to proper location.
  548.         move.b    d0,acsi     * And save for driver calls later.
  549.         clr.l    d1        * Clear D1 register.
  550.         clr.l    d0        * Clear D0 register.
  551.         move.b    tapebuf+2,d0    * Get first digit.
  552.         sub.b    #'0',d0     * Change from ASCII to binary value.
  553.         mulu    #10000,d0    * Multiply by 10000.
  554.         move.b    tapebuf+3,d1    * Get second digit.
  555.         sub.b    #'0',d1     * Change from ASCII to binary value.
  556.         mulu    #1000,d1    * Multiply by 1000.
  557.         add.l    d1,d0        * Add d1 to d0.
  558.         clr.l    d1        * Clear D1 register.
  559.         move.b    tapebuf+4,d1    * Get third digit.
  560.         sub.b    #'0',d1     * Change from ASCII to binary value.
  561.         mulu    #100,d1     * Multiply by 100.
  562.         add.l    d1,d0        * Add d1 to d0.
  563.         clr.l    d1        * Clear D1 register.
  564.         move.b    tapebuf+5,d1    * Get fourth digit.
  565.         sub.b    #'0',d1     * Change from ASCII to binary value.
  566.         mulu    #10,d1        * Multiply by 10.
  567.         add.l    d1,d0        * Add d1 to d0.
  568.         clr.l    d1        * Clear D1 register.
  569.         move.b    tapebuf+6,d1    * Get fifth digit.
  570.         sub.b    #'0',d1     * Change from ASCII to binary value.
  571.         add.l    d1,d0        * Add d1 to d0.
  572.         move.w    d0,timeout+2    * Pop new timeout value into loop.
  573.         move.l    $a8,oldtrap10    * Save old TRAP #10 vector.
  574.         move.l    #newtrap10,$a8    * Install our new TapeBIOS vector.
  575.     
  576.         move.l    #64,-(sp)    * Get 64 bytes of Inquiry Data.
  577.         move.l    #ibuffer,-(sp)    * Pop data buffer onto stack.
  578.         move.w    #INQUIRE,-(sp)    * Choose INQUIRE command.
  579.         move.w    #$ACE,-(sp)    * TapeBIOS function call.
  580.         trap    #10        * Call TRAP #10, to activate.
  581.         add.l    #12,sp        * Tidy stack.
  582.         tst.w    d0        * Did inquire fail.
  583.         bne    failinq     * Yes, tell user and abort.
  584.     
  585.         cmp.b    #1,(ibuffer)    * Is the SCSI ID chosen a sequential device.
  586.         bne    notsequent    * Apparently Not, Abort install.
  587.         
  588.         move.l    (PCOOKIE),a6    * Get COOKIE JAR pointer.
  589. anothcook:    move.l    (a6)+,d7    * Get cookie name.
  590.         move.l    (a6)+,d6    * Get cookie value.
  591.         tst.l    d7        * Have we hit the zero cookie.
  592.         bne    anothcook    * No, so get another cookie.
  593.         sub.l    #8,a6        * Go back to current cookie.
  594.         move.l    #'TAPE',(a6)+    * Install TAPE cookie.
  595.         move.l    #VERSION,(a6)+    * Install version number.
  596.         move.l    #0,(a6)+    * Put zero cookie back.
  597.         move.l    d6,(a6)     * Put number of cookies back.
  598.         move.b tapebuf,greet+41 * Pop SCSI ID into greeting message.
  599.         move.l    #greet,-(sp)    * Pop Greeting message onto stack.
  600.         move.w    #9,-(sp)    * Use print line function.
  601.         trap    #1        * Call TRAP #1, to print it.
  602.         addq.l    #6,sp        * Tidy stack.
  603.         move.w    #23,d6        * 24 bytes of device name.
  604.         move.l    #ibuffer,a5    * Move inquiry buffer to A5.
  605.         add.l    #8,a5        * Jump to device name.
  606. devicename:    clr.w    d7        * Clear D7 register.
  607.         move.b    (a5)+,d7    * Move character to D7.
  608.         move.w    d7,-(sp)    * Pop D7 into stack.
  609.         move.w    #2,-(sp)    * Use Conout function.
  610.         trap    #1        * Call TRAP #1, to print character.
  611.         addq.l    #4,sp        * Tidy stack.
  612.         dbra d6,devicename    * Print out Full Device Name.
  613.         move.l    #greet2,-(sp)    * Print a CR,LF.
  614.         move.w    #9,-(sp)    * Use print line function.
  615.         trap    #1        * Call TRAP #1, to print it.
  616.         addq.l    #6,sp        * Tidy stack.
  617.     
  618.         move.l    stkp,-(sp)    * Move User stack pointer to stack.
  619.         move.w    #$20,-(sp)    * User Mode.
  620.         trap    #1        * Call TRAP #1, to activate.
  621.         addq.l    #6,sp        * Tidy stack.
  622.         clr.w    -(sp)        * Terminate with zero status
  623.         move.l    #install,d0    * Calculate driver code size.
  624.         sub.l    #start,d0    * ..
  625.         move.l    d0,-(sp)    * Keep TapeBIOS memory resident.
  626.         move.w    #$31,-(sp)    * Ptermres call
  627.         trap    #1        * Call TRAP #1, to terminate.
  628.         
  629. *************************************************************************
  630. * End of main installation code.                    *
  631. * Next, are some routines called by the installation procedure.     *                            *
  632. *************************************************************************
  633.  
  634. malloc:     move.l    (mem),d4    * No of Cookies.
  635.         mulu    #8,d4        * Multiply by 8.
  636.         move.l    d4,-(sp)    * No of bytes to reserve.
  637.         move.w    #$48,-(sp)    * Malloc function call.
  638.         trap    #1        * Call TRAP #1, to activate.
  639.         addq.l    #6,sp        * Tidy stack.
  640.         tst.l    d0        * Error or address of memory ?
  641.         bmi    mallerr     * Malloc Error, abort install.
  642.         rts            * Return to caller.       
  643.  
  644. createjar:    move.l    rvalid,valsave    * Save reset value.
  645.         move.l    rvector,vecsave * Save reset vector.
  646.         move.l    #rhand,rvector    * Install new Reset Vector.
  647.         move.l    #RMAGIC,rvalid    * Pop new ResetMAGIC value in.
  648.         move.l    #NOCOOK,mem    * Space to reserve for New jar.
  649.         bsr    malloc        * Malloc that memory.
  650.         move.l    d0,PCOOKIE    * Install New Cookie Jar.
  651.         move.l    d0,a5        * Move data reg to address reg.
  652.         move.l    #0,(a5)+    * Install zero cookie.
  653.         move.l    #NOCOOK,(a5)    * Install Number of New cookies.
  654.         bra    doinst        * Ok, continue install.
  655.     
  656. copyjar:    move.l    rvalid,valsave    * Save reset value
  657.         move.l    rvector,vecsave * Save reset vector value
  658.         move.l    #rhand,rvector    * Install new resvector
  659.         move.l    #RMAGIC,rvalid    * Pop new resmagic value in.
  660.         add.l    #NOCOOK,d7    * Increase jar.
  661.         move.l    d7,mem        * Space to reserve for New jar.
  662.         bsr    malloc        * Malloc that memory.
  663.         move.l    (PCOOKIE),a6    * Get Cookie Jar pointer.
  664.         move.l    d0,a5        * Move data reg to address reg.
  665.         
  666. copymore:    tst.l    (a6)        * Is this the zero cookie.
  667.         beq    endcopy     * Yes, so end copy.
  668.         move.l    (a6)+,(a5)+    * Copy cookie name.
  669.         move.l    (a6)+,(a5)+    * Copy cookie value.
  670.         bra    copymore    * Copy again ?
  671.         
  672. endcopy:    move.l    #0,(a5)+    * Install the zero cookie.
  673.         move.l    (mem),(a5)    * Install Number of New cookies.
  674.         move.l    d0,PCOOKIE    * Install new pointer to jar.
  675.         bra    jardone     * Continue Install Procedure.
  676.  
  677. failinq:    move.l    #finq,-(sp)    * Fail inquiry message.
  678.         move.l    (oldtrap10),$a8 * Put old TRAP #10 vector back.
  679.         bra.s    pae        * Go and print message.
  680.     
  681. notsequent:    move.l    #nseq,-(sp)    * Not sequential device message.
  682.         move.l    (oldtrap10),$a8 * Put old TRAP #10 vector back.
  683.         bra.s    pae        * Go and print message.
  684.  
  685. tinfopen:    move.w    fhandle,-(sp)    * Push file handle onto stack.
  686.         move.w    #$3e,-(sp)    * Close file.
  687.         trap    #1        * Call TRAP #1, to activate.
  688.         addq.l    #4,sp        * Tidy stack.
  689.         move.l    #eof,-(sp)    * Error opening file message.
  690.         bra.s    pae        * Go and print message.
  691.         
  692. tapeinferr:    move.w    fhandle,-(sp)    * Push file handle onto stack.
  693.         move.w    #$3e,-(sp)    * Close file.
  694.         trap    #1        * Call TRAP #1, to activate.
  695.         addq.l    #4,sp        * Tidy stack.
  696.         move.l    #erf,-(sp)    * Error reading file message.
  697.         bra.s    pae        * Go and print message.
  698.          
  699. tinfclose:    move.l    #ecf,-(sp)    * Error closing file message.
  700.         bra.s    pae        * Go and print message.
  701.         
  702. ivdid:        move.l    #ividm,-(sp)    * Invalid device ID message.
  703.         bra.s    pae        * Go and print message.
  704.         
  705. mallerr:    move.l    #merr,-(sp)    * Malloc Memory error message.
  706.         bra.s    pae        * Go and print message.
  707.         
  708. already:    move.l    #ari,-(sp)    * Already installed message.
  709.  
  710. pae:        move.w    #9,-(sp)    * Print line function call.
  711.         trap    #1        * Call TRAP #1, to activate.
  712.         addq.l    #6,sp        * Tidy stack.
  713.         move.l    stkp,-(sp)    * Pop User stack pointer onto stack.
  714.         move.w    #$20,-(sp)    * Call User mode.
  715.         trap    #$1        * Call TRAP #1, to activate.
  716.         addq.l    #6,sp        * Tidy stack.
  717.         clr.w    -(sp)        * Use terminate function call.
  718.         trap    #1        * Call TRAP #1, to quit.
  719.  
  720. *************************************************************************
  721. * DATA segment.                             *
  722. *************************************************************************
  723.  
  724. greet:        dc.b    'TapeBIOS Driver Ver 1.5 Installed for ID#X, Copyright 1991,1992 A. Hourihane.',13,10,'Tape Device Online is the ',0
  725. greet2:     dc.b    13,10,0
  726. merr:        dc.b    '*** Memory allocation failure, Installation ABORTED ***',13,10,0 
  727. nseq:        dc.b    '*** SCSI ID specified is not a tape drive, Installation ABORTED ***',13,10,0
  728. ari:        dc.b    '*** Tape Driver is already resident, Installation ABORTED ***',13,10,0
  729. ecf:        dc.b    '*** Error closing TAPEBIOS.INF, Installation ABORTED ***',13,10,0
  730. erf:        dc.b    '*** Error reading TAPEBIOS.INF, Installation ABORTED ***',13,10,0    
  731. ividm:        dc.b    '*** Invalid Device ID, Installation ABORTED ***',13,10,0
  732. eof:        dc.b    '*** Error opening TAPEBIOS.INF, Installation ABORTED ***',13,10,0
  733. finq:        dc.b    '*** Failed Inquiry on SCSI ID specified, Installation ABORTED ***',13,10,0
  734.  
  735. ibuffer:    ds.l    64        * Inquiry Buffer.
  736. stkp:        ds.l    1        * Store for old stack pointer.
  737. tapebuf:    ds.w    5        * Store for TAPEBIOS.INF file data.
  738. fhandle:    ds.w    1        * Store for file handle.    
  739. mem:        ds.l    1        * Store for malloc reserve.
  740.  
  741. tapeinf:    dc.b    'TAPEBIOS.INF', 0
  742.  
  743.         end
  744.