home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / emulation / qlsource / romsrc / flp / flp1_asm < prev    next >
Encoding:
Text File  |  1998-02-24  |  68.0 KB  |  2,980 lines

  1. */beginfile FLP1_asm
  2. ; --------------------------------------------------------------
  3. ; FLP1_asm - floppy disk device driver for QDOS
  4. ;      - last modified 24/02/98
  5.  
  6. ; Floppy disk driver for CST    (c) 1984  Tony Tebby      QJUMP
  7. ; Modified for CST maintenance  (c) 1986  David Oliver  CST.
  8. ; Modified for Amiga floppies   (c) 1989  Rainer Kowallik
  9. ;                      Public Domain
  10. ; --------------------------------------------------------------
  11.  
  12. ; keys for floppy disc system
  13.  
  14. fs_next    equ    $18
  15. fs_acces equ    $1c
  16. fs_drive equ    $1d
  17. fs_filnr equ    $1e
  18. fs_nblok equ    $20
  19. fs_nbyte equ    $22
  20. fs_eblok equ    $24
  21. fs_ebyte equ    $26
  22. fs_cblok equ    $28
  23. fs_updt    equ    $2c
  24.  
  25. fs_fname equ    $32
  26. fs_spare equ    $58
  27. fs_end    equ    $a0
  28.  
  29. fs.nmlen equ    $24
  30. fs.hdlen equ    $40
  31.  
  32. ; floppy disk physical layer
  33.  
  34. fdd_xilk equ    $00        ; link for external
  35.                 ; interrupt 2
  36. fdd_pllk equ    $08        ; link for polling interrupt
  37. fdd_shlk equ    $10        ; link for schedular
  38. fdd_ddlk equ    $18        ; link for directory devices
  39. fdd_iolk equ    $1c        ; link to io routine
  40. ;
  41. fdd_name equ    $3e        ; 4*b name (ends with 0)
  42. fdd_side equ    $42        ; b side number
  43. fdd_driv equ    $43        ; b drive number
  44. fdd_sadd equ    $44        ; b side number to add to
  45.                 ; read/write command
  46. fdd_pend equ    $45        ; b flag for pending ops (<0
  47.                 ; start drive, >0 do not
  48.                 ; start)
  49. fdd_fint equ    $46        ; b set if forced interrupt
  50. fdd_nset equ    $47        ; b set if name set
  51. fdd_step equ    $48        ; 4*b step rates per drive
  52.                 ; (-1 is not set)
  53. fdd_slen equ    $4c        ; 4*b sector length per
  54.                 ; drive (0=128)
  55.  
  56. fdd_wprt equ    $50        ; 4*b write protect per
  57.                 ; drive (also 40/80 if +ve)
  58. fdd_sden equ    $54        ; 4*b single density flag
  59.                 ; per drive
  60. fdd_rbeg equ    $58        ; w number of bytes to skip
  61.                 ; at beginning of record
  62. fdd_rend equ    $5a        ; w number of bytes to skip
  63.                 ; at end of record
  64. fdd_time equ    $5c        ; b time_out for watchdog
  65.                 ; (set by any action)
  66. fdd_rnup equ    $5d        ; b run-up counter
  67. fdd_rndn equ    $5e        ; b run_down counter
  68. fdd_wait equ    $5f        ; b timer for pending ops.
  69. fdd_scty equ    $60        ; b security level
  70. fdd_ntrk equ    $61        ; b number of tracks
  71. fdd_stim equ    $62        ; b start up time
  72. fdd_sord equ    $63        ; b step rate order 0 =
  73.                 ; 6,12,20,30, 2=6,12,2,3
  74. fdd_chck equ    $64        ; 4*b -ve if drive has been
  75.                 ; checked since
  76.                 ; stopped/deselected
  77. fdd_pact equ    $68        ; b flag, if polled task is
  78.                 ; already active
  79. fdd_end    equ    $6A
  80.  
  81. fs_drivr equ    $10
  82. fs_drivn equ    $14
  83.  
  84. fs_mname equ    $16        ; medium name
  85. fs_files equ    $22        ; number of files open
  86.  
  87. fd_estat equ    $23        ; error status 0=ok, -1=bad,
  88.                 ; 1=ignore
  89. fd_fail    equ    $24        ; failure count
  90. fd_mupdt equ    $25        ; map updated
  91. fd_sflag equ    $26        ; sector read/write flag
  92. fd_mwrit equ    $27        ; map to be written
  93. fd_pend    equ    $28        ; pending operation list
  94. fd.npend equ    $0A        ; 10 ops max
  95. fd_mhead equ    $50        ; medium header
  96. fd_fmtid equ    $50        ; format ID
  97. fd.fmtid equ    'QL5A'
  98. fd_mdnam equ    $54        ; ... medium name
  99. fd_mdupd equ    $60        ; ... count of updates
  100. fd_mfree equ    $64        ; ... free sectors in map
  101. fd_mgood equ    $66        ; ... good sectors in map
  102. fd_mtotl equ    $68        ; ... total sectors in map
  103. fd_mstrk equ    $6a        ; ... sectors per track
  104. fd_mscyl equ    $6c        ; ... sectors per cylinders
  105. fd_mtrak equ    $6e        ; ... number of tracks
  106.                 ; (cylinders)
  107. fd_mallc equ    $70        ; ... sectors per group
  108. fd_meodr equ    $72        ; ... current end of
  109.                 ; directory (block/byte
  110.                 ; format)
  111. fd_msoff equ    $76        ; ... sector offset
  112. fd_mlgph equ    $78        ; ... logical to physical
  113.                 ; sector translate
  114. fd_mphlg equ    $8a        ; ... physical to logical
  115.                 ; sector translate
  116.  
  117. fd_map    equ    $b0        ; sector map in 3 byte
  118.                 ; entries
  119. fd_end    equ    fd_mhead+3*512
  120.  
  121. fd_delen equ    $00
  122. fd_deacs equ    $04
  123. fd_detyp equ    $05
  124. fd_deinf equ    $06
  125. fd_denam equ    $0e
  126. fd_deupd equ    $34
  127. fd_deend equ    $40
  128. fd.desft equ    $6        ; shift to convert entry
  129.                 ; number to position
  130.  
  131. fds..bsy equ    0        ; status busy bit
  132. fds..drq equ    1        ; status data request bit
  133. fds..ind equ    1        ; status index pin bit
  134. fds..lst equ    2        ; status lost data bit
  135. fds..tr0 equ    2        ; status track 0 bit
  136. fds..crc equ    3        ; status crc error bit
  137. fds..rnf equ    4        ; status record not found
  138.                 ; bit
  139. fds..spn equ    5        ; status spun up bit
  140. fds..wpr equ    6        ; status write protect bit
  141. fds..mot equ    7        ; status motor on bit (1770)
  142. fds..nrd equ    7        ; status not ready bit
  143.                 ; (2793)
  144.  
  145. fds.bsy    equ    %00000001    ; busy
  146. fds.drq    equ    %00000010    ; data request
  147. fds.ind    equ    %00000010    ; index pin
  148. fds.rwok equ    %01011100    ; read/write ok mask
  149. fds.raok equ    %00011000    ; read address ok mask
  150.  
  151. ; --------------------------------------------------------------
  152. ; Keys for CST QDisc controller (specific).
  153.  
  154. fd_statr equ    0        ; ... assumed 0!!!
  155. fd_comdr equ    0        ; ... assumed 0!!!
  156. fd_trakr equ    2
  157. fd_sectr equ    1
  158. fd_datar equ    3
  159. fd_ctrlr equ    8
  160.  
  161. fdf.rate equ    %00000000    ; 6 ms step rate
  162. fdf.slow equ    %00000011    ; 30 ms step rate
  163. fdf.prec equ    %00000010    ; precompensate no tracks
  164. fdf.veri equ    %00000100
  165. fdf.setl equ    %00000000    ; no settling time
  166. fdf.strt equ    %00001000    ; no 6 cycle start up
  167.  
  168. fdc.rest equ    %00000000+fdf.strt+fdf.rate
  169. fdc.seek equ    %00010000+fdf.strt+fdf.rate
  170. fdc.stin equ    %01010000+fdf.strt+fdf.rate
  171. fdc.read equ    $ffffff00+%10000000+fdf.strt+fdf.setl
  172. fdc.writ equ    $ffffff00+%10100000+fdf.strt+fdf.setl+fdf.prec
  173. fdc.radd equ    $ffffff00+%11000000+fdf.strt+fdf.setl
  174. fdc.fint equ    $ffffff00+%11010000
  175. fdc.rtrk equ    $ffffff00+%11100000+fdf.strt+fdf.setl
  176. fdc.wtrk equ    $ffffff00+%11110000+fdf.strt+fdf.setl+fdf.prec
  177.  
  178. fdd.rnup equ    30        ; write run up time
  179. fdd.wait equ    50        ; wait for write time
  180. fdd.rndn equ    20        ; run down after motor off
  181.  
  182. fd.ndriv equ    2        ; max number of drives
  183. fd.singl equ    'S'
  184.  
  185. fdc.add    equ    %00010000    ; constant to write to
  186.                 ; control register
  187. fdc.init equ    %00010010    ; initial control reg value
  188.                 ; (drive one selected)
  189. fdc.desl equ    %00000000    ; deselected control reg
  190.                 ; value
  191. fdc.oops equ    %00000000    ; error control reg value no
  192.                 ; drive, no motor
  193. fdc.sing equ    %00001000    ; constant to add for single
  194.                 ; density
  195. fdd.name equ    'FLP0'
  196.  
  197. ; --------------------------------------------------------------
  198. rom_base
  199.     dc.l    $4afb0001
  200.     dc.w    proc_tab-rom_base
  201.     dc.w    rom_init-rom_base
  202.     dc.b    0,27,'FLP device driver v1.17:05',$a,0
  203.     dc.w    0
  204. ; --------------------------------------------------------------
  205.  
  206. fds_fo_mess dc.b    0,18,' files still open',$a
  207.     ds.w    0
  208.  
  209. fds_rw_mess dc.b    0,19,' read/write failed',$a
  210.     ds.w    0
  211. ; --------------------------------------------------------------
  212. rom_init
  213.  
  214.     bra.l    fd_init
  215.  
  216. ; --------------------------------------------------------------
  217. proc_tab
  218.     ifd    extras
  219.  
  220.     dc.w    13        ; 7 procedures
  221.  
  222.     dc.w    flp_sec-*    ; FLP_SEC security_level
  223.     dc.b    7,'FLP_SEC'    ; (0 to 2)
  224.     dc.w    flp_start-*    ; FLP_START start_up_time
  225.     dc.b    9,'FLP_START'    ; (in 20 ms)
  226.     dc.w    flp_track-*    ; FLP_TRACK nr_of_tracks
  227.     dc.b    9,'FLP_TRACK'
  228.  
  229.     endc
  230.  
  231.     ifnd    extras
  232.  
  233.     dc.w    8        ; 4 procedures
  234.  
  235.     endc
  236.  
  237.     dc.w    flp_use-*
  238.     dc.b    7,'FLP_USE'
  239.     dc.w    prog_use-*
  240.     dc.b    8,'PROG_USE',0
  241.     dc.w    data_use-*
  242.     dc.b    8,'DATA_USE',0
  243.     dc.w    dest_use-*
  244.     dc.b    8,'DEST_USE',0
  245.     dc.w    spl_use-*
  246.     dc.b    7,'SPL_USE'
  247.     dc.w    0        ; end of procedures
  248.  
  249.     dc.w    3        ; no functions
  250.     dc.w    prog_d$-*
  251.     dc.b    6,'PROGD$',0
  252.     dc.w    data_d$-*
  253.     dc.b    6,'DATAD$',0
  254.     dc.w    dest_d$-*
  255.     dc.b    6,'DESTD$',0
  256.     dc.w    0        ; end of functions
  257.  
  258.  
  259. ; --------------------------------------------------------------
  260. fd_init
  261.     movem.l    a0/a3,-(sp)
  262.  
  263.     BSR    user_ini
  264.  
  265.     moveq    #fdd_end,d1
  266.     moveq    #MT.ALCHP,d0
  267.     moveq    #0,d2
  268.     trap    #1
  269.  
  270.     lea    fd_poll(pc),a2
  271.     move.l    a2,fdd_pllk+4(a0) ; !
  272.  
  273.     lea    fdd_iolk(a0),a3
  274.     lea    fd_io(pc),a2
  275.     move.l    a2,(a3)+     ; input/output... at $1c
  276.     lea    fd_opn(pc),a2
  277.     move.l    a2,(a3)+     ; open... at $20
  278.     lea    fd_clos(pc),a2
  279.     move.l    a2,(a3)+     ; close... at $24
  280.     lea    fd_slave(pc),a2    ; slave
  281.     move.l    a2,(a3)+
  282.     addq.l    #8,a3        ; two spare
  283.     lea    fd_format(pc),a2    ; format
  284.     move.l    a2,(a3)+
  285.     move.l    #fd_end,(a3)+    ; length
  286.     move.w    #3,(a3)+
  287.     move.l    #'MDV0',(a3)+
  288.     addq.l    #6,a3        ; side/drive/side
  289.                 ; add/empty/fint/name set
  290.     subq.l    #1,(a3)+     ; all step rates unset
  291.     move.l    #$02020202,(a3)    ; 512 byte sectors
  292.  
  293.     addq.b    #1,fdd_scty(a0)    ; set security level
  294.     move.b    #fdd.rnup,fdd_stim(a0) ; and default motor
  295.                      ; start time
  296.     move.l    a0,a3
  297.  
  298.     lea    fdd_pllk(a3),a0    ; link into
  299.     moveq    #MT.LPOLL,d0    ; polling list !
  300.     trap    #1
  301.  
  302.     lea    fdd_ddlk(a3),a0    ; link into
  303.     moveq    #MT.LDD,d0    ; dd driver list
  304.     trap    #1
  305. *
  306. * now start up drive 1
  307. *
  308.     trap    #0            supervisor mode
  309.     or.w    #$0700,sr        no interrupts
  310.     moveq    #1,d1            select drive one
  311.     bsr.l    fd_select
  312.     bsr.l    fd_ckrdy
  313. *
  314.     and.w    #$d8ff,sr        user mode
  315.     beq.s    fdini_arel
  316.     move.l    #fdd.name,fdd_name(a3)    ... none there, forget about MDV
  317.     st    fdd_nset(a3)
  318.  
  319. fdini_arel
  320.     st    fdd_driv(a3)    ; set silly drive number
  321.     clr.l    fdd_chck(a3)    ; mark drives not selected
  322.     bsr.l    fd_arel
  323.  
  324.     moveq    #MT.ALCHP,d0    ; make space for defaults
  325.     moveq    #3*36,d1     ; ** 1.17 **
  326.     moveq    #0,d2
  327.     trap    #1
  328.     move.l    a0,a4        ; save pointer
  329.     moveq    #MT.INF,d0    ; find the system variables
  330.     trap    #1
  331.     lea    SV_PROGD(a0),a0    ; and set the pointers to
  332.                 ; the defaults
  333.     move.l    #$00050000+'FL',d1
  334.     move.l    #'P1_ ',d2
  335.     move.l    a4,(a0)+     ; program default FLP1_
  336.     move.l    d1,(a4)+
  337.     move.l    d2,(a4)
  338.     add.w    #32,a4
  339.     move.l    a4,(A0)+     ; data default FLP1_
  340.     move.l    d1,(a4)+
  341.     move.l    d2,(a4)
  342. ;     add.w     #1,(a4)      ; Data default now FLP2_
  343.     add.w    #32,a4
  344.     move.l    a4,(a0)+     ; spool default PAR
  345.     move.l    #$00030000+'PA',(a4)+
  346.     move.b    #'R',(a4)+
  347.  
  348.     movem.l    (sp)+,a0/a3
  349.     rts
  350.  
  351. ; --------------------------------------------------------------
  352. ; internal adaption to user routines
  353. ; --------------------------------------------------------------
  354. fd_selct:
  355.     move.b    d1,fdd_driv(a3)
  356.     bra.l    fd_select
  357. fd_side1:
  358.     move.b    d1,fdd_side(a3)
  359.     bra.l    fd_side
  360. fd_crdy:
  361.     bsr    fd_ckrdy
  362.     tst.b    d0
  363.     beq.s    crdy_rts
  364.     move.w    d0,-(a7)
  365.     bsr    fd_restore
  366.     move.w    (a7)+,d0
  367.     tst.b    d0
  368. crdy_rts rts
  369. ; --------------------------------------------------------------
  370. ; Floppy disc utilities, read, write, seek     1984 Tony Tebby
  371. ; 1770/1793 version
  372.  
  373. ;       d1 c s  track or sector to seek
  374. ;      length of read/write -1
  375. ;       a1 cr   pointer to data buffer
  376. ;       a2  r   ptr to data reg (read/write/write track only)
  377. ;       a3 c p  pointer to physical definition
  378. ;       a4 c p  pointer to status/command register
  379. ;       !!!!! a4 and a2 are not used in the AMIGA routines !!!!
  380.  
  381. ; seek using 40/80 flag
  382.  
  383. fd_seek40
  384.     moveq    #0,d0        ; get drive number
  385.     move.b    fdd_driv(a3),d0
  386.     tst.b    fdd_wprt-1(a3,d0.w) ; is it 40 in 80?
  387.     ble    fd_seek        ; ... no
  388.     move.b    d1,-(sp)     ; save real track
  389.     add.b    d1,d1        ; seek twice as far
  390. ; move.b fd_trakr(a4),d0
  391. ; add.b    d0,fd_trakr(a4)
  392.     bsr    fd_seek
  393.     move.b    (sp)+,d1     ; \\fd_trakr(a4)       set
  394.                 ; real track
  395.     rts
  396.  
  397. ; seek to track
  398.  
  399. fd_seekr
  400.     BRA    fd_seek        ; otherwise use fd_seek
  401.                 ; anyway
  402. fd_poll
  403.     tst.b    fdd_wait(a3)    ; are we waiting for do all
  404.                 ; pending
  405.     blt.s    fdp_rts        ; ... waitng for ever
  406.     beq.s    fdp_pend     ; ... no
  407.     subq.b    #1,fdd_wait(a3)    ; ... yes, decrement wait
  408. fdp_rts
  409.     rts
  410. fdp_pend
  411.     tst.b    fdd_pend(a3)    ; are there any pending
  412.                 ; operations?
  413.     beq.s    fdp_rts        ; ... no
  414.     bsr.l    fd_do_all    ; do operations
  415.     bsr    FLUSHALL
  416.     rts
  417.  
  418. ; --------------------------------------------------------------
  419. ; Allocation routines for floppy disk IO
  420. ;  1984 Tony Tebby  QJUMP
  421.  
  422. ; routine to find the slave block for a sector
  423.  
  424. fdb_find
  425.     move.l    fs_cblok(a0),a4    ; get pointer to current
  426.                 ; block
  427.     move.l    a4,d0        ; is it set?
  428.     bne.s    fdb_fstrt
  429.     move.l    SV_BTBAS(a6),a4    ; start at base of tables
  430. fdb_fstrt
  431.     move.l    a4,a5        ; ... and keep a copy
  432.  
  433. fdb_check
  434.     moveq    #BT.INUSE,d0    ; set mask of in use bits
  435.     and.b    BT_STAT(a4),d0    ; check if this block is in
  436.                 ; use
  437.     beq.s    fdb_next     ; ... no
  438.     moveq    #$fffffff1,d0    ; set mask of drive id
  439.     and.b    BT_STAT(a4),d0    ; get drive id
  440.     cmp.b    d0,d6        ; is it the right drive
  441.     bne.s    fdb_next     ; ... no
  442.     moveq    #0,d0        ; preset error flag
  443.     cmp.l    BT_FILNR(a4),d5    ; is it the right file/block
  444.     beq.s    fdb_rts        ; ... yes
  445.  
  446. fdb_next
  447.     addq.l    #BT_END,a4    ; move to next entry in
  448.                 ; slave block tables
  449.     cmp.l    SV_BTTOP(a6),a4    ; ... is it off top
  450.     blt.s    fdb_last     ; ... no
  451.     move.l    SV_BTBAS(a6),a4    ; ... yes - start again at
  452.                 ; bottom
  453. fdb_last
  454.     cmp.l    a4,a5        ; have we been right the way
  455.                 ; round
  456.     bne.s    fdb_check    ; ... no - look at this next
  457.                 ; entry
  458. ; sector is not in slave blocks
  459.  
  460.     bsr.s    fdas_get     ; ... find the sector
  461.     bne.s    fdb_rts
  462.     bsr.s    fdb_new        ; ... allocate a new block
  463.     bne.s    fdb_rts
  464.     move.w    d2,BT_SECTR(a4)    ; ... set the sector number
  465.  
  466.     tst.w    d3        ; is operation send
  467.     bge.s    fdb_read     ; ... no
  468.     tst.w    d4        ; is this a first byte in a
  469.                 ; block?
  470.     bne.s    fdb_read     ; ... no
  471.     move.l    d7,d0        ; is end
  472.     sub.l    a1,d0        ; ... less start
  473.     sub.l    #$200,d0     ; >= one sector?
  474.     blt.s    fdb_read     ; ... no
  475.     bset    #BT..ACCS,BT_STAT(a4) ; ... yes, all will be
  476.                     ; overwritten
  477.     bra.s    fdb_ok
  478.  
  479. fdb_read
  480.     or.b    #BT.RREQ,BT_STAT(a4) ; tell fd to read it
  481.     bsr.l    fds_read     ; read it - now!
  482.     beq.s    fdb_ok        ; ... done
  483.  
  484. fdb_ncs
  485.     moveq    #ERR.NC,d0    ; not complete
  486. fdb_rts
  487.     rts
  488.  
  489. ; find a new block
  490.  
  491. fdb_new
  492.     move.l    SV_BTPNT(a6),a4    ; get current slave block
  493.                 ; pointer
  494.     move.l    a4,a5        ; ... save it
  495. fdb_nnext
  496.     addq.l    #8,a4        ; move to next
  497.     cmp.l    SV_BTTOP(a6),a4    ; off end yet?
  498.     blt.s    fdb_nchk     ; ... no
  499.     move.l    SV_BTBAS(a6),a4    ; ... yes, reset to base
  500. fdb_nchk
  501.     moveq    #%00001111,d1    ; mask out drive bits
  502.     and.b    BT_STAT(a4),d1
  503.     subq.b    #BT.EMPTY,d1    ; and check for empty
  504.     beq.s    fdb_nset     ; ... yes
  505.     subq.b    #BT.TRUE-BT.EMPTY,d1 ; ... not empty, check
  506.                    ; for true copy
  507.     beq.s    fdb_nset     ; ... yes true copy, reuse
  508.                 ; it
  509.     cmp.l    a5,a4        ; have we gone through all
  510.                 ; blocks
  511.     bne.s    fdb_nnext    ; ... no
  512.     bsr.l    fd_slave     ; $$$$$$$$$$$$$ temporary
  513.     bra.s    fdb_ncs        ; ... yes
  514.  
  515. fdb_nset
  516.     move.l    a4,fs_cblok(a0)    ; set current block
  517.     move.l    a4,SV_BTPNT(a6)    ; set block pointer
  518.     move.b    d6,BT_STAT(a4)    ; set empty
  519.     move.l    d5,BT_FILNR(a4)    ; ... set the file/block
  520. fdb_ok
  521.     moveq    #0,d0        ; no errors
  522.     rts
  523.  
  524. ; routine to find a sector group in the map
  525.  
  526. fdas_get
  527.     move.l    a4,-(sp)
  528.     lea    fd_map+2(a2),a5    ; get start of map+2
  529.     lea    fd_end(a2),a4    ; and end of map
  530.     bsr.s    fdas_comp
  531.     move.l    d0,d2        ; set sector number MOD
  532.                 ; alloc in top end
  533.     clr.w    d2
  534. fdasg_loop
  535.     cmp.b    (a5),d1        ; group matches?
  536.     bne.s    fdasg_lend
  537.     ror.l    #8,d1
  538.     cmp.b    -1(a5),d1    ; and next bit of file/group
  539.                 ; ?
  540.     bne.s    fdasg_l1
  541.     ror.l    #8,d1
  542.     cmp.b    -2(a5),d1    ; and last bit?
  543.     beq.s    fdasg_done
  544.     rol.l    #8,d1        ; restore comparison
  545.                 ; register
  546. fdasg_l1
  547.     rol.l    #8,d1
  548. fdasg_lend
  549.     addq.w    #1,d2        ; next group
  550.     addq.l    #3,a5
  551.     cmp.l    a4,a5        ; off end yet?
  552.     blt.s    fdasg_loop    ; ... no
  553.     moveq    #ERR.FE,d0    ; oops, not found
  554. fdasg_done
  555.     subq.l    #2,a5        ; set a5 to point to start
  556.     move.l    (sp)+,a4
  557.     rts
  558.  
  559. ; routine to calculate compressed form of file/group
  560.  
  561. fdas_comp
  562.     move.l    d5,d1        ; get file / block in d1
  563.     moveq    #0,d0        ; and convert to file /
  564.                 ; group
  565.     move.w    d1,d0
  566.     divu    fd_mallc(a2),d0
  567.     move.w    d0,d1
  568.     lsl.w    #4,d1        ; and stick them together
  569.     lsr.l    #4,d1
  570.     rts
  571.  
  572. ; routine to allocate a new sector
  573.  
  574. fdas_new
  575.     tst.w    d5        ; is this first sector?
  576.     beq.s    fdas_first    ; ... yes
  577.     subq.w    #1,d5        ; ... no, first find
  578.                 ; previous sector
  579.     bsr.s    fdas_get
  580.     bne.s    fdas_rts
  581.     addq.w    #1,d5        ; now set this sector
  582.     bsr.s    fdas_comp    ; compressed form in d1
  583.     swap    d0
  584.     tst.w    d0        ; block MOD alloc is zero?
  585.     bne.s    fdas_ok        ; ... no, then we've got new
  586.                 ; sector in old group
  587.     bsr.s    fdas_look    ; look for empty hole
  588.     beq.s    fdas_set     ; ... found
  589.     bra.s    fdas_retry    ; try again from start of
  590.                 ; disk
  591. fdas_first
  592.     bsr.s    fdas_comp    ; set compressed form in d1
  593.     moveq    #0,d2
  594.     move.w    fd_mscyl(a2),d2    ; ... no, keep clear of
  595.                 ; track 0
  596.     divu    fd_mallc(a2),d2
  597.     bsr.s    fdas_try     ; try once
  598.     beq.s    fdas_rts     ; ... ok
  599.  
  600. fdas_retry
  601.     moveq    #0,d2        ; try from start
  602. fdas_try
  603.     lea    fd_map(a2),a5    ; base of map
  604.     add.w    d2,a5        ; + sector offset
  605.     add.w    d2,a5
  606.     add.w    d2,a5
  607.     bsr.s    fdas_look    ; looking for an empty
  608.                 ; sector
  609.     bne.s    fdas_rts
  610. fdas_set
  611.     swap    d1
  612.     move.b    d1,(a5)+     ; set file/block in sector
  613.                 ; table
  614.     rol.l    #8,d1
  615.     move.b    d1,(a5)+
  616.     rol.l    #8,d1
  617.     move.b    d1,(a5)+
  618.  
  619.     move.w    fd_mallc(a2),d0
  620.     sub.w    d0,fd_mfree(a2)    ; one fewer free allocation
  621.                 ; blocks
  622.  
  623.     st    fd_mupdt(a2)    ; map updated
  624. fdas_ok
  625.     moveq    #0,d0
  626. fdas_rts
  627.     rts
  628.  
  629. ; look for an empty sector
  630.  
  631. fdas_look
  632.     move.l    a4,-(sp)     ; save a4
  633.     lea    fd_end(a2),a4    ; and set end pointer
  634.     moveq    #$fffffffd,d0
  635. fdasl_loop
  636.     cmp.b    (a5),d0        ; free?
  637.     beq.s    fdasl_done    ; ... yes
  638.     addq.w    #1,d2        ; next sector group
  639.     addq.l    #3,a5
  640.     cmp.l    a4,a5        ; off end?
  641.     blt.s    fdasl_loop
  642.     moveq    #ERR.DF,d0    ; no empty groups
  643. fdasl_done
  644.     move.l    (sp)+,a4
  645.     rts
  646. ; --------------------------------------------------------------
  647. ; Check all aspects of a drive    V0.3    1985  Tony Tebby
  648. ; Modified for maintenance by CST V 1.17  1986  David Oliver
  649.  
  650. ; write error messages
  651.  
  652. fds_err_mess
  653.     move.l    a1,-(sp)
  654.     lea    fs_mname-2(a2),a1
  655.     move.w    (a1),-(sp)
  656.     move.w    #10,(a1)
  657.     bsr.s    fds_w_mess
  658.     move.w    (sp)+,fs_mname-2(a2)
  659.     move.l    (sp)+,a1
  660. fds_w_mess
  661.     movem.l    d3/a0/a2,-(sp)
  662.     sub.l    a0,a0
  663.     move.w    UT.MTEXT,a2
  664.     jsr    (a2)
  665.     movem.l    (sp)+,d3/a0/a2
  666.     rts
  667.  
  668. ; Check drive set registers and select
  669.  
  670. ; called internally and from SECTIO and FORMT
  671.  
  672. ;       d2  r   current drive running
  673. ;       d4  r   drive required
  674. ;       a2 c p  drive definition block
  675. ;       a3 c p  device linkage block
  676. ;       a4  r   disk control chip address
  677.  
  678. ;       smashes d0,d1,d2,d4,a4
  679.  
  680. fd_ck_sel
  681.     bsr.s    fdc_rset     ; set up registers etc.
  682. fdc_sel
  683.     move.b    d4,d1
  684.     cmp.b    d1,d2        ; is selection required
  685.     bne.l    fd_selct     ; ... yes
  686.     rts
  687.  
  688. fdc_rset
  689.     bsr.l    fd_ahold     ; hold up asynchronous task
  690.     clr.w    d4
  691.     move.b    fs_drivn(a2),d4    ; set drive number required
  692.     move.b    fdd_driv(a3),d2    ; save drive number running
  693.     rts
  694.  
  695. ; check drive for read/write ops
  696.  
  697. ;       d5 c p  read/write flag
  698. ;       a2 c p  drive definition block
  699. ;       a3 c p  device linkage block
  700.  
  701. fd_ck_rw
  702.     movem.l    d1-d5/a0/a1/a4,-(sp) ; save registers
  703.  
  704.     move.l    a7,d4        ;*/begininsert
  705.     trap    #0
  706.     move.w    sr,-(sp)
  707.     subq.l    #2,d4
  708.     cmpa.l    d4,a7
  709.     beq.s    fd_ck_rw_sv
  710.     bclr    #5,0(a7)     ;User mode upon return
  711. fd_ck_rw_sv:            ;*/endinsert
  712.     or.w    #$0700,sr    ; disable interrupts
  713.  
  714.     moveq    #0,d4        ; changed medium not
  715.                 ; permitted
  716.     bsr.s    fdc_rset     ; set registers
  717.     tst.b    fdd_scty(a3)    ; which security level?
  718.     blt.s    fdc_rwerr    ; ... low, only check if it
  719.                 ; has errored
  720.     bgt.s    fdc_rwdc     ; ... high, check if not
  721.                 ; checked
  722.     tst.b    d5        ; ... middling, is it write?
  723.     beq.s    fdc_rwerr    ; ... read, only check if ot
  724.                 ; has errored
  725. fdc_rwdc
  726.     tst.b    fdd_chck-1(a3,d4.l) ; is drive already
  727.                   ; checked?
  728.     beq.s    chk_do        ; ... no, check it
  729. fdc_rwerr
  730.     tst.b    fd_estat(a2)    ; has it errored?
  731.     bra.s    chk_do        ; ... yes, check it
  732.  
  733. ; check drive find track
  734.  
  735.     cmp.b    d4,d2        ; is drive changed?
  736.     beq.s    fdc_ok1        ; ... no
  737.     bsr.s    fdc_sel        ; ... yes, select
  738. ; bne.s     fdc_fe1
  739.     bsr.l    fd_raddr     ; read address
  740. fdc_fe1
  741. ; bne.l     fdc_fe
  742. ; move.b  d1,fd_trakr(a4) ; set track number
  743. fdc_ok1
  744.     bra.l    fdc_exok
  745.  
  746. ; check drive for open
  747.  
  748. fd_ck_op
  749.     movem.l    d1-d5/a0/a1/a4,-(sp) ; save registers
  750.  
  751.     move.l    a7,d4        ;*/begininsert
  752.     trap    #0
  753.     move.w    sr,-(sp)
  754.     subq.l    #2,d4
  755.     cmpa.l    d4,a7
  756.     beq.s    fd_ck_op_sv
  757.     bclr    #5,0(a7)     ;User mode upon return
  758. fd_ck_op_sv:            ;*/endinsert
  759.     or.w    #$0700,sr    ; disable interrupts
  760.  
  761.     moveq    #1,d4
  762.     tst.b    fs_files(a2)    ; any files open?
  763.     bne.s    ck_op_rset    ; ... yes
  764.     ror.l    #1,d4        ; ... no, set msb to flag
  765.                 ; change ok
  766. ck_op_rset
  767.     bsr.s    fdc_rset     ; set registers
  768. ; cmp.b    d2,d4    ; is required drive running?
  769. ; beq.s    fdc_operr;... yes, only check if errored
  770.     tst.b    fdd_scty(a3)    ; which security level?
  771.     bgt.s    chk_do        ; ... high, always check
  772.     beq.s    fdc_ck_ck    ; ... middling, check if not
  773.                 ; already checked
  774.     tst.l    d4        ; ... low, only check if
  775.                 ; there are no f open
  776.     bge.s    fdc_ok1        ; ... files open
  777. fdc_ck_ck
  778.     tst.b    fdd_chck-1(a3,d4.w) ; has drive been checked?
  779.     beq.s    chk_do        ; ... no
  780. fdc_operr
  781.     tst.b    fd_estat(a2)    ; has it errored?
  782.     beq.s    fdc_ok1        ; ... no
  783.  
  784. ; drive does require checking
  785.  
  786. chk_do
  787.     bsr.l    fdc_sel        ; select drive
  788.     bsr.l    fd_crdy        ; check if drive has disk in
  789. fdc_est1
  790.     bne.l    fdc_estat    ; ... no
  791.     bsr.l    fdc_check    ; check if disk changed
  792.     blt.s    fdc_est1     ; ... bad
  793.     st    fdd_chck-1(a3,d4.w) ; ... checked
  794.     beq.s    fdc_wprot    ; ... not changed
  795.     tst.l    d4        ; is changed disk ok?
  796.     bge.l    fdc_fo        ; ... no
  797.  
  798.     lea    fd_pend(a2),a1    ; changed disk
  799.     moveq    #fd.npend-1,d0    ; ... clear out pending
  800.                 ; list!!!
  801. fdc_pdclr
  802.     clr.L    (a1)+        ; ensure pending list is
  803.                 ; empty
  804.     dbra    d0,fdc_pdclr
  805.  
  806.     move.l    SV_BTBAS(a6),a1
  807. fdc_sbclr
  808.     moveq    #$fffffff1,d0    ; mask out all odd bits
  809.     and.b    BT_STAT(a1),d0    ; is this a block for this
  810.                 ; drive?
  811.     cmp.b    d0,d6
  812.     bne.s    fdc_sbnxt    ; ... no
  813.     move.b    #BT.EMPTY,BT_STAT(a1) ; ... yes, clear it
  814. fdc_sbnxt
  815.     addq.l    #8,a1        ; next block
  816.     cmp.l    SV_BTTOP(a6),a1
  817.     blt.s    fdc_sbclr
  818.  
  819.     moveq    #0,d5        ; read sectors
  820.     bsr.l    fd_do_ms     ; ... of map
  821.     bne.s    fdc_bad_map    ; ... oops
  822.  
  823.     lea    fd_mdnam(a2),a1    ; transfer medium name
  824.     lea    fs_mname(a2),a0
  825.     move.l    (a1)+,(a0)+
  826.     move.l    (a1)+,(a0)+
  827.     move.l    (a1)+,(a0)+
  828.  
  829. ; check for 40 track in 80 track drive and double sided in
  830. ; single sided drive
  831.  
  832.     move.w    fd_mstrk(a2),d1    ; is sectors/track
  833.     sub.w    fd_mscyl(a2),d1    ; ... the same as
  834.                 ; sectors/cylinder
  835.     beq.s    fdc_40_side    ; ... yes, read from side 0
  836.     moveq    #1,d1        ; ... no, read from side 1
  837. fdc_40_side
  838.     bsr.l    fd_side1     ; set side
  839.     moveq    #2,d1        ; goto track 2
  840.     bsr.l    fd_seek
  841. ; !!!!    bsr  fd_raddr    ; read address
  842. ; bne.s    fdc_bad_map
  843.     subq.b    #2,d1        ; track should be 2
  844.     beq.s    fdc_40_ok
  845.     addq.b    #1,d1        ; was it 1?
  846.     bne.s    fdc_bad_map    ; ... no, give up
  847.     moveq    #1,d1        ; ... yes, 40 on 80 track
  848. fdc_40_ok
  849.     move.b    d1,fdd_wprt-1(a3,d4.w) ; set write protect
  850.                      ; positive or zero
  851.     bsr.l    fd_restore    ; restore drive
  852.  
  853. ; test write protect
  854.  
  855. fdc_wprot
  856.     tst.b    fdd_wprt-1(a3,d4.w) ; is it a 40 track in an
  857.                   ; 80?
  858.     bgt.s    fdc_exok     ; ... yes so implicitly
  859.                 ; write protected
  860.     BSR    fd_wpro
  861.     TST.B    D0
  862.     sne    fdd_wprt-1(a3,d4.w) ; set if it is write
  863.                   ; protected
  864. fdc_exok
  865.     moveq    #0,d0
  866. fdc_rst
  867.     move.w    (sp)+,sr
  868.     movem.l    (sp)+,d1-d5/a0/a1/a4
  869.     tst.l    d0
  870.     rts
  871.  
  872. fdc_bad_map
  873.     clr.l    fd_mhead(a2)    ; set map header to not
  874.                 ; correct format
  875. fdc_estat
  876. fdc_fe
  877.     st    fd_estat(a2)    ; set error occurred
  878.     bsr.l    fd_arel        ; release
  879.     moveq    #ERR.FE,d0
  880.     bra.s    fdc_rst
  881. fdc_fo
  882.     lea    fds_fo_mess(pc),a1
  883.     bsr.l    fds_err_mess
  884.     bra.s    fdc_estat
  885.  
  886. ; check if drive defined / disk changed
  887.  
  888. fdc_check
  889.     BSR    fd_chng
  890.     TST.B    D0
  891.     BNE.S    fdc_name
  892.     MOVEQ    #0,D0        ; signal ok if no change
  893.     RTS
  894.  
  895. ; Check if the name has changed
  896.  
  897. fdc_name
  898.     sf    fd_estat(a2)    ; clear error status
  899.     move.w    d4,d1
  900.     sf    fd_mlgph(a2)    ; set sector zero
  901.                 ; translation to zero
  902.     tst.l    fd_mstrk(a2)    ; is sector allocation set?
  903.     bne.s    fdc_ckd1
  904.     subq.l    #1,fd_mstrk(a2)    ; ensure that first fetch
  905.                 ; does not div check
  906. fdc_ckd1
  907.     sub.w    #$14,sp        ; use stack to read name etc
  908.     move.l    sp,a1
  909.     move.l    fdd_rbeg(a3),-(sp) ; save current read limits
  910.     move.l    #$200-$14,fdd_rbeg(a3) ; number of bytes to
  911.                      ; skip at end of read
  912.     moveq    #0,d1
  913.     moveq    #0,d5
  914.     bsr.l    fd_do_d1     ; and read it
  915.     sne    d0        ; save error return
  916.     move.l    (sp)+,fdd_rbeg(a3) ; reset record read limits
  917.     tst.b    d0        ; test error return
  918.     bne.s    fdc_fe14     ; ... oops
  919.     move.l    sp,a1
  920.     cmp.l    #fd.fmtid,(a1)    ; is it correctly formatted?
  921.     bne.s    fdc_fe14     ; ... no
  922.     lea    fd_mhead(a2),a0    ; check against previous
  923.                 ; header
  924.     moveq    #4,d1
  925. fdc_ckdloop
  926.     cmp.l    (a1)+,(a0)+
  927.     dbne    d1,fdc_ckdloop
  928.     beq.s    fdc_ex14     ; ... name the same
  929.     moveq    #1,d0        ; ... name changed
  930.     bra.s    fdc_ex14
  931. fdc_fe14
  932.     moveq    #ERR.FE,d0    ; ... bad medium
  933. fdc_ex14
  934.     add.w    #$14,sp
  935.     rts
  936. ; --------------------------------------------------------------
  937. ; Find the floppy disc definition block  V0.1
  938. ;  1985  Tony Tebby  QJUMP
  939.  
  940. flp_find
  941.     moveq    #MT.INF,d0    ; find system vars
  942.     trap    #1
  943.     move.l    SV_DDLST(a0),a0    ; ... and linked list of
  944.                 ; directory drivers
  945.     lea    fd_io(pc),a2    ; set entry point for io
  946.                 ; routines
  947. flf_look
  948.     cmp.l    fdd_iolk-fdd_ddlk(a0),a2 ; the right driver?
  949.     beq.s    flf_rts        ; ... yes
  950.     move.l    (a0),a0        ; ... no, try the next
  951.     move.l    a0,d1        ; ... the last?
  952.     bne.s    flf_look
  953.  
  954.     addq.l    #4,sp        ; remove return address
  955. flf_bp
  956.     moveq    #ERR.BP,d0    ; bad, bad, bad
  957. flf_rts
  958.     rts
  959. ; --------------------------------------------------------------
  960. ; Open a file on floppy disk   v0.6  1984  Tony Tebby   QJUMP
  961. ; Modified for CST maintenance V 1.15   1986  David Oliver CST
  962.  
  963. fd_opn
  964.     BSET    #7,fdd_nset(a3)    ; is name set?
  965.     bne.s    fd_opn1
  966.     move.l    #fdd.name,fdd_name(a3) ; set to FLP
  967. fd_opn1
  968.     move.b    fs_drive(a0),d6    ; a2 for phys def and d6 for
  969.                 ; empty slave block
  970.     bsr.l    fd_phys_def
  971.  
  972.     lea    fs_fname(a0),a4
  973.     moveq    #$ffffffdf,d0    ; make second character of
  974.                 ; name UC
  975.     and.l    (a4)+,d0
  976.     cmp.l    #$00042a44,d0    ; is it a '*D..' file name
  977.     bne.s    fdo_normal
  978.     tst.b    fs_files(a2)    ; any files open
  979.     bne.s    fdo_iu        ; ... yes, give up
  980.  
  981.     moveq    #-$33,d5     ; check digit following
  982.     add.b    (a4)+,d5
  983.     bgt.s    fdo_nf1        ; ... greater than 3
  984.     addq.b    #3,d5
  985.     blt.s    fdo_nf1        ; ... less than 0
  986.     bclr    #5,(a4)        ; make next upper case
  987.     cmp.b    #'D',(a4)    ; is it double density
  988.     sne    d6        ; (density flag)
  989.     beq.s    fdo_dset     ; ... yes
  990.     cmp.b    #fd.singl,(a4)    ; is it single density
  991.     bne.s    fdo_nf1
  992. fdo_dset
  993.     st    fd_sflag(a2)    ; say that it is sector
  994.                 ; read/writes
  995.     clr.l    fs_nblok(a0)    ; set sector/side/track 0
  996.     bsr.l    fd_ck_sel    ; select
  997.     move.b    d6,fdd_sden-1(a3,d4.w) ; set density
  998.     clr.b    fdd_wprt-1(a3,d4.w) ; set no protection / not
  999.                   ; 40 on 80
  1000.     move.b    d5,fdd_slen-1(a3,d4.w) ; set sector length
  1001.     bsr.l    fd_restore    ; ... and restore
  1002.     moveq    #0,d0
  1003. fdo_arel
  1004.     bra.l    fd_arel        ; release asynch tasks
  1005.  
  1006. fdo_iu
  1007.     moveq    #ERR.IU,d0
  1008.     rts
  1009.  
  1010. fdo_normal
  1011.     tst.b    fd_sflag(a2)    ; check if in use for sector
  1012.                 ; read/writes
  1013.     bne.s    fdo_iu
  1014.  
  1015.     bsr.l    fd_ck_op     ; check for medium changed
  1016. fdo_nf1
  1017.     bne.s    fdo_nf        ; ... no medium
  1018.     bsr.s    fdo_arel     ; release interrupt task
  1019.  
  1020.     moveq    #1,d0        ; check read only access for
  1021.                 ; delete, new and over
  1022.     add.b    fs_acces(a0),d0
  1023.     moveq    #%00011001,d1
  1024.     btst    d0,d1
  1025.     beq.s    fdo_a4        ; ro permitted
  1026.     bsr.l    fdio_fro     ; check just the RO flag
  1027.     bne.s    fdo_err        ; ... oops
  1028. fdo_a4
  1029.     lea    fs_spare(a0),a4    ; use spare for io
  1030.     moveq    #fd_deend,d2    ; length of entry
  1031.     move.l    d2,fs_nblok(a0)    ; set start pointer
  1032.     move.l    fd_meodr(a2),fs_eblok(a0) ; set end of file
  1033.                         ; for directory
  1034.     cmp.b    #IO.DIR,fs_acces(a0) ; if open directory
  1035.     beq.l    fdo_dir        ; ... done
  1036.  
  1037.     moveq    #0,d4        ; first empty slot
  1038.     moveq    #0,d5        ; first file number
  1039.     lea    fd_denam+2(a4),a5 ; set up for compare
  1040.  
  1041. fdo_find
  1042.     addq.w    #1,d5        ; next file
  1043.     bsr.l    fdo_read     ; read directory entry
  1044.     bne.s    fdo_derr     ; ... not there
  1045.     tst.l    fd_delen(a4)    ; is entry vacant?
  1046.     beq.s    fdo_empty    ; ... yes
  1047.     lea    fs_fname(a0),a1    ; set address of name
  1048.     move.w    (a1)+,d3     ; and length
  1049.     bsr.l    fdut_cmps    ; and compare against (a5)
  1050.     bne.s    fdo_find     ; ... it was not the same
  1051.     bra    fdo_found    ; ... it was the same
  1052. fdo_empty
  1053.     tst.w    d4        ; have we already found an
  1054.                 ; empty entry?
  1055.     bne.s    fdo_find     ; ... yes
  1056.     move.w    d5,d4        ; ... no, save the pointer
  1057.                 ; to this one
  1058.     bra.s    fdo_find
  1059. fdo_nf
  1060.     moveq    #ERR.NF,d0
  1061. fdo_err
  1062.     rts
  1063. fdo_df
  1064.     moveq    #ERR.DF,d0
  1065.     rts
  1066.  
  1067. ; error reading directory
  1068.  
  1069. fdo_derr
  1070.     cmp.l    #ERR.EF,d0    ; end of file is ok
  1071.     bne    fdo_exit     ; ... anything else is not
  1072.  
  1073. ; file not found
  1074.  
  1075.     move.b    fs_acces(a0),d0    ; is it delete?
  1076.     blt    fdo_ok        ; ... not found is ok
  1077.     subq.b    #IO.NEW,d0    ; is it new or overwrite?
  1078.     blt.s    fdo_nf        ; ... no!
  1079.     moveq    #0,d6        ; genuine new file (eof is
  1080.                 ; zero)
  1081.     tst.w    fd_mfree(a2)    ; any free sectors for new
  1082.                 ; file?
  1083.     beq.s    fdo_df        ; ... no!
  1084.     tst.w    d4        ; was an empty entry found
  1085.     beq.s    fdo_new        ; ... no put the new entry
  1086.                 ; at the end
  1087.  
  1088. fdo_sdir
  1089.     move.w    d4,d5        ; set the file number
  1090.     lsl.l    #fd.desft,d4    ; and calculate the byte
  1091.                 ; position
  1092.     lsl.l    #7,d4        ; ... and so block/byte
  1093.     lsr.w    #7,d4
  1094.     move.l    d4,fs_nblok(a0)    ; set next pointer
  1095.  
  1096. ; new entry at eof or (d4)
  1097.  
  1098. fdo_new
  1099.     move.l    a4,a5        ; create new entry in spare
  1100.                 ; bit
  1101.     move.l    d2,(a5)+     ; length
  1102.     clr.w    (a5)+        ; attribute flags
  1103.     clr.l    (a5)+        ; data space
  1104.     clr.l    (a5)+        ; extra inf
  1105.     moveq    #18,d0        ; copy 19 words (1 word + 36
  1106.                 ; bytes)
  1107.     lea    fs_fname(a0),a1    ; of name
  1108. fdo_name
  1109.     move.w    (a1)+,(a5)+
  1110.     dbra    d0,fdo_name
  1111.  
  1112.     movem.l    a0/d0-d2,-(sp)
  1113.     moveq    #MT.RCLCK,d0    ; get date
  1114.     trap    #1
  1115.  
  1116.     move.l    d1,(a5)+     ; date of last update
  1117.     clr.l    (a5)+
  1118.     move.l    d1,(a5)+     ; backup date (written once)
  1119.  
  1120.     movem.l    (sp)+,a0/d0-d2
  1121.  
  1122.     bsr.s    fdo_write    ; write directory header
  1123.  
  1124.     clr.l    $3C(a4)        ; leave date of 1st update
  1125.  
  1126.     move.l    fs_eblok(a0),fd_meodr(a2) ; reset dir len
  1127.  
  1128.     clr.l    fs_nblok(a0)    ; preset file
  1129.     move.l    d6,fs_eblok(a0)
  1130.     move.w    d5,fs_filnr(a0)
  1131.     bsr.s    fdo_write    ; and write header (never to
  1132.                 ; be updated)
  1133.     bra.s    fdo_exit
  1134.  
  1135. fdo_found
  1136.     move.b    fs_acces(a0),d0    ; check access key
  1137.     blt.s    fdo_del        ; ... delete
  1138.     cmp.b    #IO.NEW,d0    ; new or overwrite?
  1139.     beq.s    fdo_ex        ; ... oops
  1140.     bgt.s    fdo_over     ; ... overwrite
  1141.     move.l    fd_delen(a4),d1    ; find end of file
  1142.     lsl.l    #7,d1        ; ... in block/byte form
  1143.     lsr.w    #7,d1
  1144.     move.w    d5,fs_filnr(a0)    ; set file number
  1145.     move.l    d2,fs_nblok(a0)    ; set next
  1146.     move.l    d1,fs_eblok(a0)    ; set end of file
  1147. fdo_ok
  1148.     moveq    #0,d0
  1149. fdo_exit
  1150.     rts
  1151. fdo_ex
  1152.     moveq    #ERR.EX,d0
  1153.     rts
  1154.  
  1155. ; open directory
  1156.  
  1157. fdo_dir
  1158.     clr.w    fs_fname(a0)
  1159.     bra.s    fdo_ok
  1160.  
  1161. ; overwrite file
  1162.  
  1163. fdo_over
  1164.     move.w    d5,d4        ; use existing entry as
  1165.                 ; empty entry
  1166.     moveq    #fd_deend,d6    ; end of file at end of
  1167.                 ; header
  1168.     bsr    fdo_sdir     ; open as if new
  1169.     bra.s    fd_trun1     ; and truncate
  1170.  
  1171. ; delete file
  1172.  
  1173. fdo_del
  1174.     moveq    #0,d4
  1175.     bsr.l    fdo_trunc    ; truncate to zero
  1176.  
  1177.     lsl.l    #fd.desft,d5    ; get byte position of
  1178.                 ; directory entry
  1179.     lsl.l    #7,d5        ; and so block/byte
  1180.     lsr.w    #7,d5
  1181.     move.l    d5,fs_nblok(a0)
  1182.     moveq    #$40,d0        ; clear $40 bytes
  1183.     lea    $40+fs_spare(a0),a4 ; in spare
  1184. fdd_clr
  1185.     clr.l    -(a4)
  1186.     subq.w    #4,d0
  1187.     bgt.s    fdd_clr
  1188.  
  1189.     bsr.s    fdo_write    ; and write it
  1190.     bra.l    fd_msave     ; and write map
  1191.  
  1192. ; open file read/write utilities
  1193.  
  1194. fdo_read
  1195.     moveq    #IO.FSTRG,d0
  1196.     bra.s    fdo_rdwr
  1197. fdo_write
  1198.     moveq    #IO.SSTRG,d0
  1199. fdo_rdwr
  1200.     move.l    a4,a1
  1201.     bra.l    fd_ior
  1202.  
  1203. ; compare string (a5) against (a1), lengths in -2(a5) and d3
  1204. ; smashes d0,d1,d3
  1205.  
  1206. fdut_cmps
  1207.     cmp.w    -2(a5),d3    ; number of characters the
  1208.                 ; same?
  1209.     bne.s    fdut_rts
  1210.     bra.s    fdut_clend
  1211. fdut_cloop
  1212.     bsr.s    fdut_uc        ; get upper case char
  1213.     move.b    d1,d0
  1214.     bsr.s    fdut_uc        ; and the other
  1215.     cmp.b    d1,d0        ; are they different?
  1216. fdut_clend
  1217.     dbne    d3,fdut_cloop
  1218. fdut_rts
  1219.     rts
  1220. fdut_uc
  1221.     exg    a5,a1        ; swap registers
  1222.     move.b    0(a5,d3.w),d1    ; get char
  1223.     cmp.b    #'a',d1        ; between 'a'
  1224.     blt.s    fdut_uc_rts    ; ... no
  1225.     cmp.b    #'z',d1        ; and 'z'
  1226.     bgt.s    fdut_uc_rts    ; ... no
  1227.     sub.b    #$20,d1
  1228. fdut_uc_rts
  1229.     rts
  1230.  
  1231. ; truncate file d5 to block group d4: remove sectors from map
  1232.  
  1233. fd_trunc
  1234.     bsr.l    fdio_ckro    ; check if read only
  1235.     bne.s    fdut_rts
  1236. fd_trun1
  1237.     move.l    fs_nblok(a0),d4    ; get new end of file
  1238.     move.l    d4,fs_eblok(a0)    ; and set it
  1239.     subq.l    #1,d4        ; and get block holding last
  1240.                 ; byte
  1241.     clr.w    d4
  1242.     swap    d4        ; into d4
  1243.     move.w    d4,d0        ; block?
  1244.     addq.w    #1,d0
  1245.     divu    fd_mallc(a2),d4    ; ... no, block group
  1246.     addq.w    #1,d4
  1247.     swap    d4
  1248.     move.w    d0,d4
  1249.     swap    d4
  1250.     move.w    fs_filnr(a0),d5    ; set file number
  1251.  
  1252. fdo_trunc
  1253.     lea    fd_map(a2),a4    ; bottom of sector map
  1254.     lea    fd_end(a2),a5    ; top of sector map
  1255. fdt_mloop
  1256.     moveq    #0,d0
  1257.     move.b    (a4),d0
  1258.     lsl.w    #8,d0
  1259.     move.b    1(a4),d0
  1260.     ror.l    #4,d0
  1261.     cmp.w    d0,d5        ; is this the right file
  1262.                 ; number?
  1263.     bne.s    fdt_mnext    ; ... no
  1264.     swap    d0
  1265.     lsr.w    #4,d0
  1266.     move.b    2(a4),d0
  1267.     cmp.w    d0,d4        ; is the block off the end
  1268.                 ; of file?
  1269.     bhi.s    fdt_mnext    ; ... no
  1270.     move.b    #$fd,(a4)    ; free the sector
  1271.     move.w    fd_mallc(a2),d0
  1272.     add.w    d0,fd_mfree(a2)    ; ... one more free
  1273.     st    fd_mupdt(a2)    ; map updated
  1274. fdt_mnext
  1275.     addq.l    #3,a4        ; next sector
  1276.     cmp.l    a5,a4        ; last sector?
  1277.     blt.s    fdt_mloop    ; ... no
  1278.  
  1279. ; clear out the slave blocks
  1280.  
  1281.     swap    d4
  1282.     move.b    fs_drive(a0),d1    ; get drive id
  1283.     lsl.b    #4,d1        ; id /
  1284.     addq.b    #1,d1        ; file block
  1285.  
  1286.     move.l    SV_BTBAS(a6),a4    ; get pointer to base of
  1287.                 ; slave block area
  1288. fdt_bloop
  1289.     moveq    #$fffffff1,d0    ; mask out all but drive id
  1290.                 ; and file system flag
  1291.     and.b    BT_STAT(a4),d0    ; from status
  1292.     cmp.b    d0,d1        ; is the the right drive?
  1293.     bne.s    fdt_bnext    ; ... no
  1294.     cmp.w    BT_FILNR(a4),d5    ; is it the right file?
  1295.     bne.s    fdt_bnext    ; ... no
  1296.     cmp.w    BT_BLOCK(a4),d4    ; is it off the end?
  1297.     bhi.s    fdt_bnext    ; ... no
  1298.     move.b    #BT.EMPTY,BT_STAT(a4)
  1299. fdt_bnext
  1300.     addq.l    #8,a4        ; move to next block
  1301.     cmp.l    SV_BTTOP(a6),a4    ; off top?
  1302.     blt.s    fdt_bloop    ; ... no
  1303.  
  1304.     st    fs_updt(a0)    ; file updated
  1305.     moveq    #0,d0        ; and no error
  1306.     rts
  1307. ; --------------------------------------------------------------
  1308. ;  Close a file on floppy disk      1984   Tony Tebby  QJUMP
  1309.  
  1310. fd_clos
  1311.     move.b    fs_drive(a0),d6    ; get drive number
  1312.     bsr.l    fd_phys_def    ; ... and all else
  1313.  
  1314.     tst.b    fd_sflag(a2)    ; was it direct sector IO?
  1315.     beq.s    fdc_flush    ; ... no
  1316.  
  1317.     moveq    #0,d0        ; ... yes
  1318.     move.b    fs_drivn(a2),d0    ; set drive number
  1319.     move.b    #$02,fdd_slen-1(a3,d0.w) ; reset to 512 byte
  1320.                        ; sectors
  1321.     clr.b    fdd_sden-1(a3,d0.w) ; and to double density
  1322.     clr.b    fdd_chck-1(a3,d0.w) ; mark drive not selected
  1323.     clr.l    fd_mhead(a2)    ; drive not previously used
  1324.     sf    fs_files(a2)    ; no files open
  1325.     sf    fd_sflag(a2)    ; normal operation
  1326.     bra.s    fdc_unlk
  1327.  
  1328. fdc_flush
  1329.     moveq    #FS.FLUSH,d0    ; flush out everything
  1330.     bsr.l    fd_ior
  1331.     subq.b    #1,fs_files(a2)    ; ... one fewer files
  1332.  
  1333. fdc_unlk
  1334.     clr.l    fdd_chck(a3)    ; mark drives not selected
  1335.     move.l    a0,-(sp)     ; save base address of
  1336.                 ; channel
  1337.     lea    fs_next(a0),a0    ; and point to next
  1338.     lea    SV_FSLST(a6),a1    ; start of linked list of
  1339.                 ; channels
  1340.     move.w    UT.UNLNK,a2    ; and unlink this one
  1341.     jsr    (a2)
  1342.     move.l    (sp)+,a0     ; restore base address of
  1343.                 ; channel
  1344.     move.w    MM.RECHP,a2    ; and remove
  1345.     jmp    (a2)
  1346. ; --------------------------------------------------------------
  1347. ; IO routines for the floppy disc system  V1.02
  1348. ;  1985  Tony Tebby  QJUMP
  1349.  
  1350. ;       d0   s scratch / error return
  1351. ;       d1 cr  input/output byte
  1352. ;       d2 c s number of bytes to transfer / scratch
  1353. ;       d6   s drive id * 16 + 1
  1354. ;       a0 cr  pointer to channel definition
  1355. ;       a1 crs pointer to read/write buffer
  1356. ;       a3 cr  pointer to linkage block
  1357. ;       a2   s pointer to physical definition
  1358. ;       a4   s pointer to slave block tables
  1359. ;       a5   s
  1360.  
  1361. ; scatter load from floppy disk
  1362.  
  1363. fd_load
  1364.     move.l    a1,-(sp)
  1365.     bsr.l    fd_flush     ; ensure medium is up to
  1366.                 ; date (no write ops)
  1367.     move.l    (sp)+,a1
  1368.     bne.l    fdl_rts
  1369.  
  1370.     move.l    fs_eblok(a0),d7    ; get length
  1371.     lsl.w    #7,d7        ; ... convert to byte form
  1372.     lsr.l    #7,d7
  1373.     moveq    #fs.hdlen,d0
  1374.     sub.l    d0,d7        ; address offset
  1375.     beq.l    fdl_ok
  1376.     add.l    a1,d7        ; end address of load
  1377.     move.l    a1,a4        ; start address of load
  1378.  
  1379.     moveq    #0,d3        ; start looking at track 0
  1380. fdl_tr_loop
  1381.     moveq    #0,d4        ; start at physical sector 0
  1382.                 ; (offset)
  1383. fdl_se_loop
  1384.     move.l    d4,d1        ; set pointer to
  1385.                 ; physical/logical xlate
  1386.     add.b    #fd_mphlg,d1
  1387.     move.b    0(a2,d1.w),d1    ; logical sector in cylinder
  1388.     move.w    d3,d0        ; track * nr of sectors
  1389.     mulu    fd_mscyl(a2),d0    ; (upper end d0=0)
  1390.     add.w    d0,d1        ; logical sector on drive
  1391.  
  1392.     move.l    d1,d2
  1393.     divu    fd_mallc(a2),d2    ; position in map (upper end
  1394.                 ; is posn in group)
  1395.     move.w    d2,d0
  1396.     add.w    d2,d2
  1397.     add.w    d0,d2        ; address in map
  1398.  
  1399.     lea    fd_map(a2),a1
  1400.     add.w    d2,a1
  1401.     move.b    (a1)+,d0     ; get 12 bits of map
  1402.     lsl.w    #8,d0
  1403.     move.b    (a1)+,d0
  1404.     ror.l    #4,d0
  1405.     cmp.w    fs_filnr(a0),d0    ; is the file the same?
  1406.     bne.s    fdl_se_next    ; ... no
  1407.     swap    d0        ; ... yes
  1408.     lsr.w    #4,d0
  1409.     move.b    (a1)+,d0     ; get group number
  1410.     mulu    fd_mallc(a2),d0    ; as sector number
  1411.     swap    d2
  1412.     add.w    d2,d0        ; + sector within group
  1413.     lsl.l    #8,d0
  1414.     add.l    d0,d0        ; gives address from base of
  1415.                 ; load
  1416.  
  1417.     bne.s    fdl_sa1        ; not the first sector
  1418.     move.w    #fs.hdlen,fdd_rbeg(a3) ; first sector includes
  1419.                      ; header
  1420.     lea    (a4),a1
  1421.     bra.s    fdl_ckend
  1422. fdl_sa1
  1423.     lea    -fs.hdlen(a4,d0.l),a1 ; set start address
  1424.                     ; (less header)
  1425. fdl_ckend
  1426.     cmp.l    d7,a1        ; is start of sector off end
  1427.                 ; of file?
  1428.     bge.s    fdl_se_next    ; ... yes
  1429.     add.l    a4,d0
  1430.     add.l    #$200-fs.hdlen,d0
  1431.     sub.l    d7,d0        ; is end of sector off end
  1432.                 ; of file?
  1433.     ble.s    fdl_read     ; ... no
  1434.     move.w    d0,fdd_rend(a3)    ; ... yes, skip bytes at the
  1435.                 ; end
  1436. fdl_read
  1437.     moveq    #0,d5
  1438.     bsr.l    fd_do_sd1    ; read sector
  1439.     sne    d0        ; save error return
  1440.     clr.l    fdd_rbeg(a3)    ; and clear part read flags
  1441.     tst.b    d0
  1442.     bne.l    fdio_fe        ; ... oops
  1443.  
  1444. fdl_se_next
  1445.     addq.l    #1,d4        ; next physical sector
  1446.     cmp.w    fd_mscyl(a2),d4    ; off end?
  1447.     blt.l    fdl_se_loop    ; ... no
  1448.  
  1449.     addq.l    #1,d3        ; next track (cylinder)
  1450.     cmp.w    fd_mtrak(a2),d3    ; off end?
  1451.     blt.l    fdl_tr_loop    ; ... no
  1452.  
  1453.     move.l    d7,a1
  1454. fdl_ok
  1455.     moveq    #0,d0
  1456. fdl_rts
  1457.     rts
  1458.  
  1459. ; rename a file (atomic)
  1460.  
  1461. fd_renam
  1462.     bsr.l    fdio_ckro    ; check read only
  1463.     bne.s    fdrn_rts1
  1464.     move.w    (a1)+,d4
  1465.     subq.w    #5,d4        ; is name too short?
  1466.     bls.s    fd_bn
  1467.     cmp.w    #fs.nmlen+5,d4    ; is name too long?
  1468.     bhi.s    fd_bn        ; ... yes
  1469.     move.l    #$dfdfdfff,d0    ; mask out lc bits from name
  1470.     and.l    (a1)+,d0
  1471.     sub.b    fs_drivn(a2),d0    ; and take away drive number
  1472.     cmp.l    fdd_name(a3),d0    ; is it now FLP0?
  1473.     bne.s    fd_bn        ; ... no, bad
  1474.     cmp.b    #'_',(a1)+    ; is it FLP0_?
  1475.     beq.s    fdrn_1        ; ... yes, good
  1476. fd_bn
  1477.     moveq    #ERR.BN,d0
  1478. fdrn_rts1
  1479.     rts
  1480. fdrn_1
  1481.     lea    fs_spare(a0),a4    ; set up working addresses
  1482.     lea    fd_denam+2(a4),a5
  1483.     move.l    a1,d7        ; and the new name pointer
  1484.     move.w    fs_filnr(a0),d5    ; save the file number
  1485.     clr.w    fs_filnr(a0)    ; and clear it
  1486. fdrn_dup
  1487.     addq.w    #1,fs_filnr(a0)    ; look at next file
  1488.     moveq    #FS.HEADR,d0
  1489.     moveq    #fd_deend,d2
  1490.     move.l    a4,a1        ; use spare area to ...
  1491.     bsr.s    fd_ior        ; read the next header
  1492.     beq.s    fdrn_cname    ; found
  1493.     cmp.w    #ERR.EF,d0    ; end of directory?
  1494.     beq.s    fdrn_sname    ; ... off end
  1495.     bra.s    fdrn_rest
  1496. fdrn_cname
  1497.     move.w    d4,d3        ; set length
  1498.     move.l    d7,a1        ; and new name pointer
  1499.     bsr.l    fdut_cmps    ; compare the strings
  1500.     bne.s    fdrn_dup     ; not the same, try the next
  1501.  
  1502.     moveq    #ERR.EX,d0    ; otherwise error exists
  1503. fdrn_rest
  1504.     move.w    d5,fs_filnr(a0)    ; restore the file number
  1505.     rts
  1506.  
  1507. fdrn_sname
  1508.     lea    fs_fname+fs.nmlen+2(a0),a2 ; set up to clear
  1509.                     ; the name
  1510.     moveq    #fs.nmlen/2,d0
  1511. fdrn_clr
  1512.     clr.w    -(a2)
  1513.     dbra    d0,fdrn_clr
  1514.     move.l    a2,a1        ; save start pointer
  1515.  
  1516.     move.l    d7,a5        ; now set the new filename
  1517.                 ; in channel
  1518.     move.w    d4,(a2)+     ; set length
  1519. fdrn_snlp
  1520.     move.b    (a5)+,(a2)+    ; copy a char at a time
  1521.     sub.w    #1,d4
  1522.     bgt.s    fdrn_snlp
  1523.  
  1524.     move.w    d5,fs_filnr(a0)    ; restore the file number
  1525.     moveq    #fd_denam,d1    ; offset of name in header
  1526.     moveq    #fs.nmlen+2,d2
  1527.     move.b    fs_updt(a0),-(sp) ; rename does not set update
  1528.                 ; flag
  1529.     bsr.s    fd_ihds
  1530.     move.b    (sp)+,fs_updt(a0)
  1531.     rts
  1532.  
  1533. ; internal header set
  1534.  
  1535. fd_ihds
  1536.     moveq    #-1,d0
  1537.  
  1538. ; routine version of fd_io for internal calls from fd_op & fd_cl
  1539.  
  1540. fd_ior
  1541.     movem.l    d0/d2-d7/a4/a5,-(sp)
  1542. fdior_loop
  1543.     movem.l    (sp),d0/d2    ; restore d0/d2
  1544.                 ; operation/count
  1545.     moveq    #1,d3        ; all calls are treated as
  1546.                 ; initial entry
  1547.     bsr.s    fd_io
  1548.     addq.l    #-ERR.NC,d0    ; is it ERR.NC?
  1549.     beq.s    fdior_loop    ; ... yes try again
  1550.     subq.l    #-ERR.NC,d0    ; restore error code
  1551.     addq.l    #4,sp        ; and skip action
  1552.     movem.l    (sp)+,d2-d7/a4/a5
  1553.     rts
  1554. fd_io
  1555.  
  1556. ; set up address of physical definition
  1557.  
  1558.     move.b    fs_drive(a0),d6
  1559.     bsr.l    fd_phys_def
  1560.  
  1561.     tst.b    fd_sflag(a2)    ; is it sector reads?
  1562.     bne.l    fd_sectio
  1563.  
  1564. ; clear the error status
  1565.  
  1566.     move.l    d0,d4        ; save action
  1567.     tst.b    fd_estat(a2)    ; has it errored?
  1568.     beq.s    fdio_action    ; no
  1569.     tst.b    d3        ; initial entry?
  1570.     bne.s    fdio_fe2     ; no, (or internal)
  1571.     bsr.l    fd_ck_rw     ; check the drive again
  1572. fdio_fe2
  1573.     bne.l    fdio_fe        ; not ok
  1574.  
  1575. ; look at action
  1576.  
  1577. fdio_action
  1578.     move.l    d4,d0        ; is it internal header set?
  1579.     blt.l    fd_hdsx        ; ... yes
  1580.     cmp.b    #FS.CHECK,d0    ; is it a file operation?
  1581.     bcs.l    fd_serw        ; ... no, simple serial
  1582.     cmp.b    #FS.TRUNC,d0    ; is it valid?
  1583.     bhi.s    fdio_bp        ; ... no
  1584.  
  1585.     add.w    d0,d0
  1586.     move.w    fd_op_tab-2*FS.CHECK(pc,d0.w),d0 ; branch to
  1587.                           ; file op.
  1588.     jmp    fd_op_tab(pc,d0.w)
  1589. fd_op_tab
  1590.     dc.w    fd_check-fd_op_tab
  1591.     dc.w    fd_flush-fd_op_tab
  1592.     dc.w    fd_posab-fd_op_tab
  1593.     dc.w    fd_posre-fd_op_tab
  1594.     dc.w    fdio_bp-fd_op_tab
  1595.     dc.w    fd_mdinf-fd_op_tab
  1596.     dc.w    fd_heads-fd_op_tab
  1597.     dc.w    fd_headr-fd_op_tab
  1598.     dc.w    fd_load-fd_op_tab
  1599.     dc.w    fd_save-fd_op_tab
  1600.     dc.w    fd_renam-fd_op_tab
  1601.     dc.w    fd_trunc-fd_op_tab
  1602. err_bp
  1603. fdio_bp
  1604.     moveq    #ERR.BP,d0
  1605.     rts
  1606.  
  1607. fd_check
  1608. fd_cf_ok
  1609.     moveq    #0,d0
  1610. fd_cf_rts
  1611.     rts
  1612. fd_flush
  1613.     tst.b    fs_updt(a0)    ; is the file updated?
  1614.     beq.s    fd_cf_ok     ; ... no, done
  1615.  
  1616.     move.l    fs_eblok(a0),d0    ; find end of file
  1617.     lsl.w    #7,d0        ; in block/byte form
  1618.     lsr.l    #7,d0
  1619.  
  1620.     lea    fs_spare(a0),a1    ; put in spare
  1621.     move.l    d0,(a1)
  1622.     moveq    #0,d1        ; write to start of header
  1623.     moveq    #4,d2        ; 4 bytes
  1624.     bsr    fd_ihds        ;*/mend bsr hdsx - set header
  1625.     bne.s    fd_cf_rts
  1626.     move.l    a0,-(sp)
  1627.     moveq    #MT.RCLCK,d0    ; get date
  1628.     trap    #1
  1629.     move.l    (sp)+,a0
  1630.     move.l    d1,(a1)
  1631.     moveq    #fd_deupd,d1    ; put in update date
  1632.     moveq    #4,d2        ; 4 bytes
  1633.     bsr    fd_ihds        ;*/mend bsr hdsx - set header
  1634.     bne.s    fd_cf_rts
  1635.  
  1636.     sf    fs_updt(a0)    ; now not updated
  1637.     bsr.l    fd_msave     ; slave and update map
  1638.     bra.s    fd_cf_ok
  1639.  
  1640. fd_posab
  1641.     bsr.l    fd_spt        ; set pointer
  1642.     bra.s    fd_pos
  1643. fd_posre
  1644.     tst.l    d3        ; do not move pointer if it
  1645.                 ; is re-entry
  1646.     blt.s    fd_pos
  1647.     bsr.l    fd_apt        ; adjust pointer
  1648. fd_pos
  1649.     moveq    #IO.PEND,d0    ; do a pending to prefetch
  1650.     bra.s    fd_ser_1
  1651.  
  1652. fd_mdinf
  1653.     lea    fs_mname(a2),a5    ; copy name
  1654.     move.l    (a5)+,(a1)+
  1655.     move.l    (a5)+,(a1)+
  1656.     move.w    (a5)+,(a1)+
  1657.  
  1658.     move.l    fd_mfree(a2),d1    ; set free/good sectors
  1659.     moveq    #0,d0
  1660.     rts
  1661. fd_save
  1662.     moveq    #IO.SSTRG,d0    ; use send string
  1663. fd_ser_1
  1664.     bra.l    fd_serio
  1665.  
  1666. ; read and set header calls are assumed to complete in one
  1667. ; operation as the header is all in one block
  1668.  
  1669. fd_headr
  1670.     moveq    #IO.FSTRG,d5    ; to read header - read
  1671.                 ; string
  1672.     cmp.w    #fd_deend,d2    ; max length is header
  1673.                 ; length
  1674.     bgt.s    fdio_or
  1675.     move.l    a1,-(sp)     ; save pointer to start
  1676.     bsr.s    fd_head_do    ; read header from directory
  1677.     move.l    (sp)+,a2     ; get start pointer
  1678.     sub.l    #fd_deend,(a2)    ; and take away header
  1679.                 ; length
  1680.     rts
  1681. fdio_or
  1682.     moveq    #ERR.OR,d0    ; ... oops
  1683.     rts
  1684.  
  1685. ; internal set header
  1686.  
  1687. fd_hdsx
  1688.     moveq    #IO.SSTRG,d5    ; send string
  1689.     bra.s    fd_dir_do
  1690.  
  1691. fd_heads
  1692.     moveq    #IO.SSTRG,d5    ; to set header - send
  1693.                 ; string
  1694.     moveq    #$e,d2        ; of 14 bytes
  1695. fd_head_do
  1696.     moveq    #0,d1        ; header starts at first
  1697.                 ; entry
  1698.  
  1699. fd_dir_do
  1700.     moveq    #0,d4        ; get file number
  1701.     move.w    fs_filnr(a0),d4
  1702.     beq.l    fdio_bp        ; ... cant do header of dir
  1703.     move.w    d4,-(sp)     ; save it
  1704.     move.l    fs_eblok(a0),-(sp) ; and eof
  1705.     move.l    fs_nblok(a0),-(sp) ; and next
  1706.     clr.w    fs_filnr(a0)    ; set file zero
  1707.     move.l    fd_meodr(a2),fs_eblok(a0) ; and eof
  1708.                         ; (directory)
  1709.     subq.w    #1,d4
  1710.     lsl.l    #fd.desft,d4    ; and next (64xnumber-1)
  1711.     add.l    d4,d1        ; plus offset from start
  1712.     bsr.l    fd_spt        ; set pointer
  1713.  
  1714.     move.l    d5,d0        ; set action
  1715.     moveq    #0,d1        ; ... nothing moved so far
  1716.     bsr.s    fd_serw        ; and do serial op
  1717.  
  1718.     move.l    (sp)+,fs_nblok(a0) ; restore next
  1719.     move.l    (sp)+,fs_eblok(a0) ; and eof
  1720.     move.w    (sp)+,fs_filnr(a0) ; and file number
  1721.     tst.l    d0
  1722.     rts
  1723. ; --------------------------------------------------------------
  1724. ;  Serial IO operations for floppy disk  1984  Tony Tebby QJUMP
  1725.  
  1726. ;       d0   s scratch / error return
  1727. ;       d1 cr  input/output byte
  1728. ;       d2 c s number of bytes to transfer / scratch
  1729. ;       d3   s action -ve send, 0 check, +ve fetch
  1730. ;        ($a fetch line)
  1731. ;       d4   s block number msw, byte number lsw
  1732. ;       d5   s file number msw, block number lsw
  1733. ;       d6 cr  drive id * 16 + 1
  1734. ;       a0 cr  pointer to channel definition
  1735. ;       a1 crs pointer to read/write buffer
  1736. ;       a3 cr  pointer to linkage block
  1737. ;       a2   s pointer to physical definition
  1738. ;       a4   s pointer to slave block tables
  1739. ;       a5   s
  1740.  
  1741. fdio_ckro
  1742.     move.b    fs_acces(a0),d3    ; check for access
  1743.     subq.b    #IO.SHARE,d3    ; is it share?
  1744.     beq.s    fdio_ro        ; ... yes
  1745.     subq.b    #IO.DIR-IO.SHARE,d3 ; is it dir?
  1746.     beq.s    fdio_ro
  1747. fdio_fro
  1748.     moveq    #0,d3        ; get drive number
  1749.     move.b    fs_drivn(a2),d3
  1750.     tst.b    fdd_wprt-1(a3,d3.w) ; is it write protected?
  1751.     beq.s    fdio_rt1     ; ... no
  1752. fdio_ro
  1753.     moveq    #ERR.RO,d0    ; read only
  1754. fdio_rt1
  1755.     rts
  1756.  
  1757. fd_serw
  1758.     ext.l    d1        ; normal io calls use bottom
  1759.                 ; word of D2
  1760.     ext.l    d2
  1761. fd_serio
  1762.     cmp.b    #IO.SSTRG,d0    ; is operation serial?
  1763.     bhi.l    err_bp
  1764.     moveq    #0,d7        ; set d7 to end of string to
  1765.                 ; be read
  1766.     tst.l    d3        ; is it reentry?
  1767.     bge.s    fd_ser_do    ; ... no
  1768.     sub.l    d1,d7        ; ... yes, take away bytes
  1769.                 ; read
  1770. fd_ser_do
  1771.     subq.b    #IO.EDLIN,d0    ; check operation
  1772. fdio_bpe
  1773.     beq.l    err_bp        ; ... oops
  1774.     blt.s    fdio_fetch    ; ... it's a read
  1775.     bsr.s    fdio_ckro    ; ... it's a write, check
  1776.                 ; read only
  1777.     bne.s    fdio_rt1     ; ... no
  1778.  
  1779. fdio_send
  1780.     moveq    #-1,d3        ; a send operation
  1781.     subq.b    #6-IO.EDLIN,d0    ; which send?
  1782.     beq.s    fdio_bpe     ; ... undefined
  1783.     blt.s    fdio_byte    ; sbyte
  1784.     bgt.s    fdio_string    ; sstrg
  1785.  
  1786. fdio_fetch
  1787.     moveq    #0,d3        ; a fetch, assume pending
  1788.     addq.b    #IO.EDLIN,d0    ; restore key
  1789.     beq.s    fdio_byte    ; ... zero is pending
  1790.     moveq    #$a,d3        ; now assume fline
  1791.                 ; (terminator $a)
  1792.     subq.b    #IO.FLINE,d0
  1793.     beq.s    fdio_string    ; ... it is
  1794.     blt.s    fdio_fbyte    ; ... no, it's byte
  1795.     lsl.w    #8,d3        ; ... no, it's a string
  1796.  
  1797. fdio_string
  1798.     add.l    a1,d7        ; find start of string
  1799.     move.l    d7,-(sp)     ; and save it
  1800.     add.l    d2,d7        ; find end of string
  1801.     bsr.s    fdio_buf
  1802.     move.l    a1,d1        ; find length written
  1803.     sub.l    (sp)+,d1
  1804.     rts
  1805.  
  1806. fdio_fbyte
  1807.     lsl.w    #8,d3        ; lsbyte =0
  1808. fdio_byte
  1809.     move.l    d1,-(sp)     ; put pointer/write byte on
  1810.                 ; stack
  1811.     lea    3(sp),a1     ; ... and point to byte
  1812.     move.l    a1,d7        ; fetch / write 1 byte
  1813.     addq.l    #1,d7
  1814.     bsr.s    fdio_buf
  1815.     move.l    (sp)+,d1     ; get byte read/restore
  1816.                 ; pointer
  1817.     rts
  1818.  
  1819. ;       buffer/unbuffer strings, start a1 end d7
  1820.  
  1821. fdio_buf
  1822.     tst.b    fd_estat(a2)    ; is medium ok?
  1823.     bne.s    fdio_fe        ; ... oops
  1824.     move.l    fs_filnr(a0),d5    ; get file number/block
  1825.                 ; number
  1826.     move.l    fs_nblok(a0),d4    ; get block number/byte
  1827.                 ; number
  1828.     cmp.l    fs_eblok(a0),d4    ; end of file?
  1829.     blt.s    fd_get_block    ; no, get the slave block
  1830.                 ; for this operation
  1831.  
  1832.     bgt.s    fdio_ef        ; yes, pointer is beyond eof
  1833.     tst.b    d3        ; is operation fetch or
  1834.                 ; inquire?
  1835.     blt.s    fdio_eof     ; ... no
  1836. fdio_ef
  1837.     moveq    #ERR.EF,d0    ; end of file
  1838.     rts
  1839. fdio_fe
  1840.     moveq    #ERR.FE,d0    ; file error
  1841. fdio_rts
  1842.     rts
  1843.  
  1844. fdio_eof
  1845.     tst.w    d4        ; the first byte in a new
  1846.                 ; block?
  1847.     beq.s    fdio_ext_block    ; ... yes
  1848.  
  1849. fd_get_block
  1850.     bsr.l    fdb_find     ; get the slave block for
  1851.                 ; this sector
  1852.     bne.s    fdio_rts     ; ... no room (or error)
  1853. ; put prefetch here
  1854.     bra.s    fdio_cblk
  1855.  
  1856. fdio_ext_block
  1857.     cmp.l    a1,d7        ; is there actually anything
  1858.                 ; to go in block?
  1859.     bls.l    fdio_ok        ; ... no so exit
  1860.     bsr.l    fdb_new        ; find space for a new block
  1861.     bne.s    fdio_rts
  1862.     bsr.l    fdas_new     ; find new sector
  1863.     bne.s    fdio_rts
  1864.     move.w    d2,BT_SECTR(a4)    ; set sector number
  1865.     or.b    #BT.TRUE,BT_STAT(a4) ; ... and say it is a
  1866.                    ; true buffer
  1867. fdio_cblk
  1868.     move.l    a4,fs_cblok(a0)    ; ... set pointer to this
  1869.                 ; slave block
  1870.     btst    #BT..ACCS,BT_STAT(a4) ; are contents
  1871.                     ; accessible
  1872.     beq.l    fdb_ncs        ; ... not complete
  1873.  
  1874.     tst.w    d3        ; was it just IO.PEND?
  1875.     beq.s    fdio_ok        ; ... yes, done
  1876.  
  1877.     move.l    a4,d0        ; get address of next block
  1878.     sub.l    SV_BTBAS(a6),d0    ; - base of tables
  1879.     lsl.l    #6,d0        ; * 512/8
  1880.     move.l    d0,a5
  1881.     add.l    a6,a5        ; + base of sysvar
  1882.     add.w    d4,a5        ; + byte pointer
  1883.  
  1884.     tst.w    d3        ; fetch bytes?
  1885.     bgt.s    fdio_get     ; ... yes
  1886.  
  1887. fdio_put
  1888.     cmp.l    a1,d7        ; end of string?
  1889.     bls.s    fdio_pexit
  1890.     move.b    (a1)+,(a5)+    ; put a byte in the block
  1891.  
  1892.     addq.w    #1,d4        ; add 1 to byte pointer
  1893.     btst    #9,d4        ; off end of block?
  1894.     beq.s    fdio_put     ; ... no
  1895.     addq.w    #1,d5        ; add 1 to block
  1896.     add.l    #$fe00,d4    ; add 1 to block, take 512
  1897.                 ; off byte
  1898. fdio_pexit
  1899.     st    fs_updt(a0)    ; mark file updated
  1900.     bsr.s    fdio_swrit    ; set pending op to write
  1901.  
  1902.     cmp.l    fs_eblok(a0),d4    ; is this new eof?
  1903.     blt.s    fdio_sptr    ; ... no
  1904.     move.l    d4,fs_eblok(a0)    ; ... yes, update eof
  1905.     bra.s    fdio_sptr
  1906.  
  1907. fdio_get
  1908.     moveq    #0,d0        ; we need to compare words
  1909. fdio_gloop
  1910.     cmp.l    a1,d7        ; end of string?
  1911.     bls.s    fdio_sptr    ; ... yes
  1912.     cmp.l    fs_eblok(a0),d4    ; beyond end of file?
  1913.     bge.s    fd_ex_eof    ; ... yes
  1914.     move.b    (a5)+,d0     ; get a byte
  1915.     move.b    d0,(a1)+     ; and put it in buffer
  1916.     cmp.w    d0,d3        ; is it terminating
  1917.                 ; character?
  1918.     bne.s    fdio_gnext    ; ... no,
  1919.     move.l    a1,d7        ; reset end pointer to stop
  1920.                 ; loop
  1921. fdio_gnext
  1922.     addq.w    #1,d4        ; add 1 to byte pointer
  1923.     btst    #9,d4        ; off end of block?
  1924.     beq.s    fdio_gloop    ; ... no
  1925.     addq.w    #1,d5        ; add 1 to block
  1926.     add.l    #$fe00,d4    ; add 1 to block, take 512
  1927.                 ; off byte
  1928. fdio_sptr
  1929.     move.l    d4,fs_nblok(a0)    ; set next block / byte
  1930.                 ; pointer
  1931.     cmp.l    a1,d7        ; any more bytes to
  1932.                 ; transfer?
  1933.     bhi.l    fdio_buf     ; ... yes, go back to Buffer
  1934.                 ; to get new slave
  1935.  
  1936.     cmp.w    #$a,d3        ; was it fetch line?
  1937.     bne.s    fdio_ok        ; ... no
  1938.     cmp.b    d0,d3        ; was new line read?
  1939.     beq.s    fdio_ok        ; ... yes
  1940. fdio_bo
  1941.     moveq    #ERR.BO,d0    ; buffer overflow
  1942.     rts
  1943. fdio_ok
  1944.     moveq    #0,d0
  1945.     rts
  1946. fd_ex_eof
  1947.     move.l    d4,fs_nblok(a0)    ; set current block / byte
  1948.                 ; pointer
  1949.     bra.l    fdio_ef
  1950.  
  1951. ; routines to initiate slaving
  1952.  
  1953. fdio_swrit
  1954.     moveq    #BT.UPDT,d0    ; get update bits
  1955.     or.b    d6,d0        ; put drive id in
  1956.     move.b    d0,BT_STAT(a4)    ; set status
  1957.  
  1958.     sub.l    SV_BTBAS(a6),a4    ; calculate slave block
  1959.                 ; pointer
  1960.     lea    fd_pend(a2),a5
  1961.     moveq    #fd.npend-1,d0
  1962. fd_sw_dup
  1963.     cmp.L    (a5)+,a4     ; check for block already in
  1964.                 ; list
  1965.     beq.s    fd_sw_rts    ; ... it is, all is OK
  1966.     dbra    d0,fd_sw_dup
  1967.  
  1968.     lea    fd_pend(a2),a5
  1969.     moveq    #fd.npend-1,d0
  1970. fd_sw_empty
  1971.     tst.L    (a5)+        ; check for hole in list
  1972.     beq.s    fd_sw_set    ; ... found one
  1973.     dbra    d0,fd_sw_empty
  1974.  
  1975.     bsr.l    fd_slavr     ; list is full, empty it
  1976.     lea    fd_pend+4(a2),a5
  1977. fd_sw_set
  1978.     move.L    a4,-(a5)     ; put this block into list
  1979.     st    fdd_pend(a3)    ; and set pending operation
  1980. fd_sw_rts
  1981.     rts
  1982. ; --------------------------------------------------------------
  1983. ; Routines for slaving           V2.1    1984 Tony Tebby QJUMP
  1984. ; Modified for maintenance by CST V 1.15  1986 David Oliver CST
  1985.  
  1986. ; internal forced slaving (from formt/serio)
  1987.  
  1988. fd_slavf
  1989.     tst.b    fdd_pend(a3)
  1990.     beq.s    fd_slrts
  1991. fd_slavr
  1992.     bsr.s    fd_slave
  1993. fd_slavw
  1994.     tst.b    fdd_pend(a3)
  1995.     bne.s    fd_slavw
  1996. fd_slrts
  1997.     rts
  1998.  
  1999. ; external slaving entry
  2000.  
  2001. fd_slave
  2002.     sf    fdd_wait(a3)    ; do not wait
  2003.     st    fdd_pend(a3)    ; force pending operations
  2004.     bsr    fd_do_all
  2005.     bsr    FLUSHALL
  2006.     rts
  2007.  
  2008. ; hold asynch task
  2009.  
  2010. fd_ahold
  2011.     st    fdd_wait(a3)    ; hold up
  2012.     rts
  2013.  
  2014. ; release asynch task
  2015.  
  2016. fd_arel
  2017.     move.b    #fdd.wait,fdd_wait(a3)
  2018.     st    fdd_time(a3)
  2019.     BCLR    #7,fdd_pact(a3)
  2020.     rts
  2021.  
  2022. ; save the map
  2023.  
  2024. fd_msave
  2025.     tst.b    fd_mupdt(a2)    ; is map updated?
  2026.     beq.s    fds_ms_rts
  2027.     st    fd_mwrit(a2)    ; mark map to be written
  2028.     st    fdd_pend(a3)    ; ... force pending ops
  2029.     bsr    fd_do_all
  2030.     bsr    FLUSHALL
  2031.     tst.b    fdd_scty(a3)    ; check security level
  2032.     bgt.s    fd_slavr     ; clear out all
  2033. fds_ms_rts
  2034.     rts
  2035.  
  2036. ; do a read operation directly, a4 is pointer to slave block
  2037.  
  2038. fds_read
  2039.     movem.l    d5/a1,-(sp)
  2040.     moveq    #0,d5        ; do a read operation
  2041.     bsr.l    fd_do_a4
  2042.     movem.l    (sp)+,d5/a1    ; restore the registers
  2043.     rts
  2044. ; --------------------------------------------------------------
  2045. ; Sector IO  (position read/write)    V0.3  1985 Tony Tebby QJUMP
  2046. ; Modified for maintenance by CST V 1.15  1986 David Oliver CST
  2047.  
  2048. fd_sectio
  2049.     subq.b    #IO.FSTRG,d0    ; is it fetch string?
  2050.     beq.s    sio_read
  2051.     subq.b    #IO.SSTRG-IO.FSTRG,d0 ; is it send string?
  2052.     beq.s    sio_write
  2053.     sub.b    #FS.POSAB-IO.SSTRG,d0 ; is it position?
  2054.     beq.l    sio_posab
  2055.     subq.b    #FS.POSRE-FS.POSAB,d0
  2056.     beq.l    sio_posre
  2057.     moveq    #ERR.BP,d0    ; ... no
  2058.     rts
  2059.  
  2060. ; read a sector
  2061.  
  2062. sio_read
  2063.     move.l    a1,-(sp)     ; save pointer
  2064.  
  2065.     lea    fd_read(pc),a5    ; load address of read
  2066.                 ; routine
  2067.  
  2068.     bclr    #1,d2        ; is there a word length at
  2069.                 ; the start?
  2070.     beq.s    sio_set
  2071.  
  2072.     moveq    #0,d0        ; find the drive
  2073.     move.b    fs_drivn(a2),d0
  2074.     move.b    fdd_slen-1(a3,d0.w),d0 ; ... thus sector
  2075.                      ; length
  2076.     clr.w    (a1)
  2077.     bset    d0,(a1)        ; set length * 2
  2078.     lsr.w    (a1)+        ; set length
  2079.     bra.s    sio_length
  2080.  
  2081. ; write a sector
  2082.  
  2083. sio_write
  2084.     move.l    a1,-(sp)     ; save pointer
  2085.     lea    fd_write(pc),a5
  2086.     bclr    #1,d2        ; is there a word length at
  2087.                 ; the start?
  2088.     beq.s    sio_set
  2089.     addq.l    #2,a1        ; skip it
  2090. sio_length
  2091.     tst.w    d2        ; was it just length?
  2092.     beq.s    sio_a1_ok
  2093.  
  2094. ; set up for read/write
  2095.  
  2096. sio_set
  2097.     bsr.l    fd_ck_sel    ; select it and set
  2098.                 ; registers
  2099.  
  2100.     move.l    a7,d4        ;*/begininsert
  2101.     trap    #0
  2102.     move.w    sr,-(sp)
  2103.     subq.l    #2,d4
  2104.     cmpa.l    d4,a7
  2105.     beq.s    sio_set_sv
  2106.     bclr    #5,0(a7)     ;User mode upon return
  2107. sio_set_sv:            ;*/endinsert
  2108.     or.w    #$0700,sr     ; ... no interrupts
  2109.  
  2110.     move.b    fs_nblok+2(a0),d1 ; set side
  2111.     bsr.l    fd_side1
  2112. ; move.b fs_spare(a0),fd_trakr(a4)    ; set old track
  2113.     move.w    fs_nblok(a0),d1    ; set new track
  2114.     move.b    d1,fs_spare(a0)    ; and save it
  2115.     bsr.l    fd_seekr     ; seek or restore
  2116.     bne.s    sio_fe1
  2117. ; move.b d1,fd_trakr(a4)    ; and set the track we are on!!!
  2118.     move.b    fs_nblok+3(a0),d1 ; read/write sector
  2119.     subq.b    #1,d1        ; ... allowing for internal
  2120.                 ; offset
  2121.     move.b    d1,d6        ; save pointers
  2122.     move.l    a1,d7
  2123.     jsr    (a5)        ; do it
  2124.     TST.B    D2
  2125.     beq.s    sio_fe1        ; ... ok
  2126.     move.b    d6,d1        ; ... bad, restore pointers
  2127.     move.l    d7,a1
  2128.     jsr    (a5)        ; and do again
  2129. sio_fe1
  2130.     sne    d0
  2131.     bsr.l    fd_arel        ; release asynchronous task
  2132.     tst.b    d0
  2133.     beq.s    sio_a1_ok    ; check for errors
  2134. sio_fe
  2135.     lea    fds_rw_mess(pc),a2 ; set error message
  2136.     move.l    a2,d0
  2137.     bset    #31,d0
  2138.     bra.s    sio_a1
  2139. sio_a1_ok
  2140.     moveq    #0,d0
  2141. sio_a1
  2142.     move.l    a1,d1        ; set d1 to difference in a1
  2143.     move.w    (sp)+,sr     ; restore interrupts
  2144.     sub.l    (sp)+,d1
  2145.     rts
  2146.  
  2147. ; set the file position
  2148.  
  2149. sio_posab
  2150.     move.l    d1,fs_nblok(a0)    ; set position
  2151. sio_posre
  2152.     move.l    fs_nblok(a0),d1    ; read position
  2153.     moveq    #0,d0
  2154.     rts
  2155. ; --------------------------------------------------------------
  2156. ; Physical layer for floppy disc    V2.1  1985 Tony Tebby QJUMP
  2157. ; Modified for maintenance by CST. V1.14  1986 David Oliver CST
  2158.  
  2159. ; do all pending write operations
  2160.  
  2161. ;       d6   s  empty status for drive
  2162. ;       a2   s  pointer to physical definition
  2163. ;       a3 c p  pointer to linkage block
  2164.  
  2165. ;       smashes d0,d1,d2,d3,d6,a1,a2,a4
  2166.  
  2167. fd_do_all:
  2168.     MOVEM.L    D0-D3/A1-A2/A4/A6,-(A7)
  2169.     BSR.S    HILF_DO_ALL
  2170.     MOVEM.L    (A7)+,D0-D3/A1-A2/A4/A6
  2171.     RTS
  2172. HILF_DO_ALL:
  2173.     move.l    a5,-(sp)
  2174.     move.b    fdd_driv(a3),d1
  2175.     bsr.l    fd_selct
  2176.     moveq    #$f,d6        ; look at all 16 drives
  2177. fd_do_drive
  2178.     bsr.s    fd_phys_def
  2179.     lea    fdd_ddlk(a3),a1
  2180.     cmp.l    fs_drivr(a2),a1    ; is this the right type of
  2181.                 ; device?
  2182.     bne.s    fd_do_ndrive
  2183.     bsr.s    fd_do_1        ; all ops for this drive
  2184. fd_do_ndrive
  2185.     lsr.w    #4,d6        ; restore drive number
  2186.     dbra    d6,fd_do_drive    ; next drive
  2187.     sf    fdd_pend(a3)    ; clear pending flag
  2188.     bsr.l    fd_arel        ; and reset the timers
  2189.     move.l    (sp)+,a5
  2190.     rts
  2191.  
  2192. ; do write operations for one drive
  2193. ;       d5   s  -1 (write)
  2194. ;       d6 c p  empty status for drive
  2195.  
  2196. ;       smashes d0,d1,d2,d3,d5,a1,a4,a5
  2197.  
  2198. fd_do_1
  2199.     lea    fd_pend(a2),a5    ; get address of pending
  2200.                 ; list
  2201.     moveq    #fd.npend-1,d3    ; max number of pending
  2202.                 ; operations
  2203. fd_do_loop
  2204.     move.L    (a5),d0        ; get slave block offset
  2205.     beq.s    fd_do_map    ; ... no more operations
  2206.     move.l    SV_BTBAS(a6),a4    ; base of sb tables
  2207.     add.L    d0,a4        ; + offset
  2208.     btst    #BT..WREQ,BT_STAT(a4) ; is a write operation
  2209.                     ; required?
  2210.     beq.s    fd_do_lend    ; ... no (so why is it in
  2211.                 ; the list?)
  2212.     moveq    #-1,d5        ; set write operation
  2213.     bsr.s    fd_do_a4     ; ... and do it
  2214. fd_do_lend
  2215.     clr.L    (a5)+        ; clear pending
  2216.     dbra    d3,fd_do_loop
  2217. fd_do_map
  2218.     tst.b    fd_mwrit(a2)    ; is map required to be
  2219.                 ; written?
  2220.     beq.s    fd_do_rts
  2221.     sf    fd_mwrit(a2)    ; clear flag
  2222.     bsr.l    fd_ck_rw     ; check read/write ok
  2223.     bne.s    fd_do_rts
  2224.  
  2225.     addq.l    #1,fd_mdupd(a2)    ; increment update count
  2226. fd_do_mw
  2227.     moveq    #-1,d0        ; write sectors
  2228. fd_do_ms
  2229.     lea    fd_mhead(a2),a1    ; set address to save map
  2230.                 ; from
  2231.     moveq    #0,d3        ; put sector 0
  2232. fdp_msloop
  2233.     move.l    d3,d1
  2234.     MOVEM.L    A1,-(A7)     ; save pointer to map
  2235.     bsr.s    fd_do_d1     ; (number in d1)
  2236.     MOVEM.L    (A7)+,A1     ; restore pointer to map
  2237.     TST.B    D0
  2238.     bne.s    fd_do_mw
  2239.     ADD.L    #512,A1        ; point to next sector of
  2240.                 ; map
  2241.     addq.l    #1,d3        ; next sector number in d3
  2242.     cmp.b    #3,d3
  2243.     blt.s    fdp_msloop
  2244.     sf    fd_mupdt(a2)    ; say map is up to date
  2245. fd_do_rts
  2246.     rts
  2247.  
  2248. ; set physical definitions
  2249. ;       d6 c r  drive id / empty status for drive
  2250. ;       a2   r  address of physical definition block for drive
  2251.  
  2252. fd_phys_def
  2253.     ext.w    d6
  2254.     lsl.w    #2,d6
  2255.     lea    SV_FSDEF(a6),a2
  2256.     move.l    0(a2,d6.w),a2
  2257.     lsl.w    #2,d6
  2258.     addq.w    #BT.EMPTY,d6
  2259.     rts
  2260.  
  2261. ; read or write one sector using slave blocks
  2262. ;       d5 c p  =0 read, <>0 write
  2263. ;       d6 c p  empty status for drive
  2264. ;       a1   s  pointer to read/write buffer
  2265. ;       a2   p  pointer to physical definition block
  2266. ;       a3   p  pointer to linkage block
  2267. ;       a4 c p  pointer to slave block tables
  2268.  
  2269. ;       smashes d0,d1,d2,a1
  2270.  
  2271. fd_do_a4
  2272.     move.l    a4,d0        ; calculate base of block
  2273.     sub.l    SV_BTBAS(a6),d0
  2274.     lsl.l    #6,d0
  2275.     lea    0(a6,d0.l),a1    ; in a1
  2276.  
  2277.     move.w    BT_SECTR(a4),d1    ; set sector number
  2278.     mulu    fd_mallc(a2),d1
  2279.     moveq    #0,d0        ; plus block MOD alloc
  2280.     move.w    BT_BLOCK(a4),d0
  2281.     divu    fd_mallc(a2),d0
  2282.     swap    d0
  2283.     add.w    d0,d1
  2284.     bsr.s    fd_do_sd1
  2285.     beq.s    fd_do_ok
  2286.  
  2287.     and.b    #BT.NACTN,BT_STAT(a4) ; clear actions but do
  2288.                     ; not set access
  2289.     lea    fds_rw_mess(pc),a1 ; write message
  2290.     bsr.l    fds_err_mess
  2291.     move.b    #1,fd_estat(a2)    ; and set status read/write
  2292.                 ; failure
  2293.     rts
  2294.  
  2295. fd_do_ok
  2296.     move.b    d6,BT_STAT(a4)    ; set status
  2297.     bset    #BT..ACCS,BT_STAT(a4) ; ... ok
  2298.     moveq    #0,d0
  2299.     rts
  2300.  
  2301. ; select and do one read/write
  2302.  
  2303. fd_do_sd1
  2304.     bsr.l    fd_ck_rw     ; select (and hold)
  2305.     bne.s    fd_do_rts    ; (released on error)
  2306.  
  2307. ; do one read/write
  2308.  
  2309. fd_do_d1
  2310.     clr.w    -(sp)        ; clear failure count
  2311. fd_do_again
  2312.     movem.l    d1/d3/a2/a4/a5,-(sp) ; save registers
  2313.     move.l    a1,a5        ; save BUffer pointer
  2314.     ext.l    d1
  2315.     divu    fd_mscyl(a2),d1    ; get track
  2316.     move.w    d1,-(sp)
  2317.     move.w    d1,d3
  2318.     mulu    fd_msoff(a2),d3    ; get track*offset
  2319.     clr.w    d1
  2320.     swap    d1
  2321.     move.b    fd_mlgph(a2,d1.w),d1 ; and sector/side
  2322.     bclr    #7,d1
  2323.     sne    d2        ; side
  2324.     add.w    d3,d1        ; sector
  2325.     divu    fd_mstrk(a2),d1
  2326.     swap    d1        ; MOD mscyl
  2327.     move.w    d1,-(sp)
  2328.  
  2329.     moveq    #1,d1
  2330.     and.w    d2,d1
  2331.     bsr.l    fd_side1     ; set side
  2332.     move.w    2(sp),d1     ; get track
  2333. ;   cmp.b   fd_trakr(a4),d1 is it the right track?
  2334. ;   beq.s   fd_do_rw
  2335.     bsr.l    fd_seek40
  2336.  
  2337. fd_do_rw
  2338.  
  2339.     move.l    a7,d1        ;*/begininsert
  2340.     trap    #0
  2341.     move.w    sr,-(sp)
  2342.     subq.l    #2,d1
  2343.     cmpa.l    d1,a7
  2344.     beq.s    fd_do_rw_sv
  2345.     bclr    #5,0(a7)     ;User mode upon return
  2346. fd_do_rw_sv:            ;*/endinsert
  2347.     or.w    #$0700,sr    ; disable interrupts
  2348.  
  2349.     moveq    #$1f,d1        ; get physical sector (-1)
  2350.     and.w    2(sp),d1
  2351.     tst.b    d5
  2352.     beq.s    fd_do_rd
  2353.     bsr.l    fd_write     ; write
  2354.     bra.s    fd_do_rint
  2355. fd_do_rd
  2356.     bsr.l    fd_read
  2357. fd_do_rint
  2358.     move.w    (sp)+,sr     ; restore interrupts
  2359.     movem.l    (sp)+,d0/d1/d3/a2/a4/a5 ; remove 4 bytes from
  2360.                       ; sp and restore regs
  2361.     move.b    d2,d0        ; get error return
  2362.     ble.s    fd_do_x8     ; operation ok or timed out
  2363. ; subq.b #1,d2        ; seek error?
  2364. ; bne.s    fd_inc_fail ;... not a seek error
  2365. ; tst.b    (sp)        ;... seek error, first one?
  2366. ; beq.s    fd_inc_fail ;... yes
  2367.  
  2368. fd_inc_fail
  2369. ; addq.b #1,(sp)        ;increment failure count
  2370. ; cmp.b    #3,(sp)
  2371. ; ble.l    fd_do_again    ;and retry up to three times
  2372.     NOP
  2373.  
  2374. fd_do_x8
  2375.     bsr.l    fd_arel        ; release asynch task
  2376.     addq.l    #2,sp        ; remove failure count
  2377.  
  2378.     tst.b    d0        ; and test error return
  2379.  
  2380.     rts
  2381. ; --------------------------------------------------------------
  2382. ; Set the next byte pointers     1985  Tony Tebby   QJUMP
  2383. ;
  2384. ;       d0   s  scratch
  2385. ;       d1 cr   byte pointer to file (returned absolute)
  2386. ;       a0 c p  channel definition block
  2387.  
  2388. ; adjust pointer by d1
  2389.  
  2390. fd_apt
  2391.     move.l    fs_nblok(a0),d0    ; get current pointer
  2392.  
  2393. ; calculate pointer
  2394.  
  2395. fd_cpt
  2396.     lsl.w    #7,d0        ; in byte pointer form
  2397.     lsr.l    #7,d0
  2398.     sub.l    #fd_deend,d0    ; relative to start
  2399.     add.l    d0,d1        ; add to offset
  2400.     bvs.s    fd_pt_eof
  2401.  
  2402. ; set pointer to d1
  2403.  
  2404. fd_spt
  2405.     move.l    d1,d0        ; preserve updated address
  2406.                 ; (in d1)
  2407.     bmi.s    fd_pt_bof    ; ... it's off the beginning
  2408.     add.l    #fd_deend,d0
  2409.     bvs.s    fd_pt_eof
  2410.     asl.l    #6,d0        ; shift most of the way
  2411.     bvs.s    fd_pt_eof    ; ... to check for sign
  2412.                 ; change
  2413.     add.l    d0,d0        ; and the last little bit
  2414.     lsr.w    #7,d0        ; ... it's now in block/byte
  2415.                 ; form
  2416.     cmp.l    fs_eblok(a0),d0    ; but is it within the file?
  2417.     ble.s    fd_setnb     ; ... yes
  2418. fd_pt_eof
  2419.     moveq    #0,d1        ; if off the end of file
  2420.     move.l    fs_eblok(a0),d0    ; ... set it to eof
  2421.     bra.s    fd_cpt
  2422. fd_pt_bof
  2423.     moveq    #fd_deend,d0    ; beginning of file is at
  2424.                 ; end of header
  2425.     moveq    #0,d1        ; but appears to be zero
  2426. fd_setnb
  2427.     move.l    d0,fs_nblok(a0)
  2428.     rts
  2429. ; --------------------------------------------------------------
  2430. ; Format medium. Changed in some aspects to support amiga
  2431. ; hardware
  2432. ; at increased speed.
  2433. ; --------------------------------------------------------------
  2434. ; Format procedure for floppy disks  V2.3    1985  Tony Tebby
  2435. ;
  2436. ;       d1 cr   drive number / good sectors
  2437. ;       d2  r   total sectors
  2438. ;       a0 c    medium name
  2439. ;       a3 c    linkage block
  2440.  
  2441. fdf.group equ    3
  2442.  
  2443. fd_format
  2444.     move.l    a0,a5        ; save call params
  2445.     move.w    d1,d6
  2446.  
  2447.     move.l    a3,-(sp)     ; save base of linkage block
  2448.     moveq    #MT.ALCHP,d0    ; and allocate space
  2449.     move.l    #fd_end+$200,d1    ; $28+3*512 bytes + one
  2450.                 ; sector
  2451.     moveq    #0,d2
  2452.     trap    #1
  2453.     move.l    (sp)+,a3
  2454.     tst.l    d0
  2455.     beq.s    fdf_set        ; ... ok
  2456.     rts    ...        ; oops
  2457. fdf_set
  2458.  
  2459.     move.l    a7,d1        ;*/begininsert
  2460.     trap    #0
  2461.     move.w    sr,-(sp)
  2462.     subq.l    #2,d1
  2463.     cmpa.l    d1,a7
  2464.     beq.s    fdf_set_sv
  2465.     bclr    #5,0(a7)     ;User mode upon return
  2466. fdf_set_sv:            ;*/endinsert
  2467.     or.w    #$0700,sr    ; disable interrupts
  2468.  
  2469.     bsr.l    fd_slavf     ; do all pending ops and
  2470.                 ; stop interrupt task
  2471.     move.l    a0,a2        ; set base of pseudo
  2472.                 ; definition block
  2473.     move.b    d6,fs_drivn(a2)    ; set drive number
  2474.     move.l    #$90009,-(sp)    ; ... and set number of
  2475.                 ; sectors track/cylinder
  2476.     bsr.l    fd_ck_sel    ; select (and hold) drive,
  2477.                 ; set registers
  2478.     sf    fdd_wprt-1(a3,d6.w) ; clear 40/80 flag
  2479.     sf    fdd_chck-1(a3,d6.w) ; clear the checked flag
  2480.  
  2481.     bsr.l    fd_restore    ; and restore drive
  2482.  
  2483.     moveq    #0,d4
  2484.     move.b    fdd_ntrk(a3),d4    ; get number of tracks
  2485.     bne.s    fdf_sets     ; ... it is set
  2486.     moveq    #80,d4        ; 80 track on amiga
  2487.  
  2488. ; set number of sides
  2489.  
  2490. fdf_sets
  2491.     cmp.w    #5+10,(a5)    ; is name at least 11
  2492.                 ; characters long?
  2493.     ble.s    fdf_chkt     ; ... no
  2494.     cmp.b    #'*',2+5+10(a5)    ; is it forced single sided?
  2495.                 ; (11th character=*)
  2496.     beq.s    fdf_blank    ; ... yes
  2497.  
  2498. ; check number of tracks
  2499.  
  2500. fdf_chkt
  2501.     lsl.w    (sp)        ; increment number of sides
  2502.                 ; on amiga
  2503.  
  2504. ; set up blank map
  2505.  
  2506. fdf_blank
  2507.     move.w    #$5ff,d0     ; fill medium header buffer
  2508.                 ; with $ff
  2509.     lea    fd_mhead+$600(a0),a1
  2510. fdf_bloop
  2511.     st    -(a1)
  2512.     dbra    d0,fdf_bloop
  2513.  
  2514.     move.l    #'QL5A',(a1)+
  2515.  
  2516.     move.w    (a5)+,d0     ; length of medium name
  2517.     addq.l    #5,a5        ; less fdkn_
  2518.     subq.w    #5,d0
  2519.     moveq    #10,d1
  2520.     sub.w    d0,d1        ; >10?
  2521.     bge.s    fdf_snend
  2522.     moveq    #9,d0        ; yes, take first 10
  2523. fdf_snloop
  2524.     move.b    (a5)+,(a1)+    ; copy it into map
  2525. fdf_snend
  2526.     dbra    d0,fdf_snloop
  2527.  
  2528.     bra.s    fdf_spend
  2529. fdf_sploop
  2530.     move.b    #' ',(a1)+    ; now pad with spaces
  2531. fdf_spend
  2532.     subq.w    #1,d1
  2533.     bge.s    fdf_sploop
  2534.  
  2535.     move.w    SV_RAND(a6),(a1)+ ; random number
  2536.     clr.l    (a1)+        ; update count
  2537.     move.w    (sp),d1        ; calculate total sectors
  2538.     mulu    d4,d1
  2539.     move.w    d1,(a1)        ; number of sectors
  2540.     subq.w    #6,(a1)+     ; (6 taken)
  2541.     move.w    d1,(a1)+     ; good
  2542.     move.w    d1,(a1)+     ; total
  2543.     move.w    2(sp),(a1)+    ; sectors per track
  2544.     move.w    (sp),(a1)+    ; sectors per cylinder
  2545.     move.w    d4,(a1)+     ; number of tracks
  2546.     move.w    #fdf.group,(a1)+    ; sectors per allocation
  2547.                 ; group
  2548.     move.l    #fd_deend,(a1)+    ; length of directory
  2549.     moveq    #18,d0
  2550.     lea    fdf_9trans(pc),a5 ; set sector translate
  2551.                 ; tables for amiga
  2552. fdf_stran
  2553.     move.w    (a5)+,(a1)+
  2554.     dbra    d0,fdf_stran
  2555.  
  2556. ; now format and check all the tracks
  2557.  
  2558.     moveq    #0,d6        ; start at track 0
  2559.     move.w    (sp),d4        ; number of sectors /
  2560.                 ; cylinder
  2561.     lea    fd_map(a0),a5    ; set address of map
  2562. fdf_tr_loop
  2563.     moveq    #0,d7        ; side 1
  2564.     bsr.s    fdf_fmt_chk    ; format and check
  2565. fdf_tr_s0
  2566.     moveq    #1,d7        ; side 0
  2567.     bsr.s    fdf_fmt_chk    ; format and check
  2568.     moveq    #$fffffffd,d0    ; ... good cylinder, mark
  2569.                 ; vacant
  2570. fdf_mset
  2571.     moveq    #0,d1        ; set number of map entries
  2572.                 ; per cylinder
  2573.     move.w    d4,d1
  2574.     divu    #fdf.group,d1
  2575. fdf_msloop
  2576.     move.b    d0,(a5)        ; and set all good or bad
  2577.     addq.l    #3,a5
  2578.     subq.w    #1,d1
  2579.     bgt.s    fdf_msloop
  2580.  
  2581.     addq.w    #1,d6        ; move on one track
  2582.     cmp.w    fd_mtrak(a0),d6    ; end of map?
  2583.     blt.s    fdf_tr_loop    ; ... no
  2584.  
  2585.     lea    fd_map(a0),a5
  2586.     cmp.l    #$fdfffffd,(a5)    ; are the first two groups
  2587.                 ; free?
  2588.     bne.s    fdf_ff        ; ... no
  2589.  
  2590.     move.w    #$f800,(a5)+    ; set it to medium header /
  2591.                 ; directory
  2592.     clr.l    (a5)
  2593.  
  2594.     lea    (a0),a2        ; set pseudo definition
  2595.                 ; block pointer
  2596.     bsr.l    fd_do_mw     ; write map sectors
  2597.     bne.s    fdf_ff        ; ... oops
  2598.     moveq    #0,d0
  2599.     bra.s    fdf_exit
  2600.  
  2601. ; error returns
  2602.  
  2603. fdf_ff
  2604.     moveq    #ERR.FF,d0
  2605. fdf_exit
  2606.     bsr.l    fd_dskcng    ; force a disc change signal
  2607.                 ; from drive
  2608.     st    fdd_driv(a3)    ; change the drive so next
  2609.                 ; open reads header
  2610.     bsr.l    fd_arel        ; release asynch tasks
  2611.     move.l    fd_mgood(a0),d7    ; save sector counts
  2612.     move.l    d0,d4        ; save error flag
  2613.     moveq    #MT.RECHP,d0    ; return space to common
  2614.                 ; heap
  2615.     trap    #1
  2616.     move.l    d4,d0        ; restore error flag
  2617.     move.w    d7,d2        ; set sector counts
  2618.     swap    d7
  2619.     move.w    d7,d1
  2620.     addq.l    #4,sp
  2621.     move.w    (a7)+,sr
  2622.     rts
  2623.  
  2624. ; subroutine to format and write a track
  2625.  
  2626. fdf_fmt_chk
  2627.     bsr.s    fdf_sk_trk    ; seek and write track
  2628.     bne.s    fdf_wr_err    ; ... oops
  2629.     moveq    #0,d5
  2630. fdf_read
  2631.     move.b    d5,d1        ; read next sector
  2632.     lea    fd_end(a0),a1    ; ... into spare bit at end
  2633.     bsr.l    fd_read
  2634.     bne.s    fdf_rd_err    ; ... oops
  2635.     addq.w    #1,d5
  2636.     cmp.b    #9,d5        ; last?
  2637.     blt.s    fdf_read     ; ... no
  2638.  
  2639. ;     movem.l  d0/a0,-(a7)     ; temporary aberration
  2640. ;     move.l     #0,a0
  2641. ;     move.l     #$00010000+'. ',d0 ; signal OK
  2642. ;     bsr     IOD0
  2643. ;     movem.l  (a7)+,d0/a0
  2644.  
  2645.     rts            ; all ok
  2646.  
  2647. ; read / verify failed
  2648.  
  2649. fdf_rd_err
  2650. ;     movem.l  d0/a0,-(a7)     ; temporary aberration
  2651. ;     move.l     #0,a0
  2652. ;     move.l     #$00010000+'R ',d0 ; signal read error
  2653. ;     bsr     IOD0
  2654. ;     movem.l  (a7)+,d0/a0
  2655.  
  2656.     addq.l    #4,sp        ; remove return
  2657.     moveq    #$fffffffe,d0    ; bad track
  2658.     sub.w    d4,fd_mfree(a0)    ; decrement sector counts
  2659.     sub.w    d4,fd_mgood(a0)
  2660.     bra    fdf_mset     ; and set map entries
  2661.  
  2662. ; write track failed
  2663.  
  2664. fdf_wr_err
  2665. ;     movem.l  d0/a0,-(a7)     ; temporary aberration
  2666. ;     move.l     #0,a0
  2667. ;     move.l     #$00010000+'W ',d0 ; signal write error
  2668. ;     bsr     IOD0
  2669. ;     movem.l  (a7)+,d0/a0
  2670.  
  2671.     addq.l    #4,sp        ; remove return
  2672.     bra    fdf_ff        ; format failed (short?)
  2673. ; write a track
  2674.  
  2675. fdf_sk_trk
  2676.     move.b    d6,d1        ; seek to track
  2677.     bsr.l    fd_seek
  2678. fdf_track
  2679.     move.b    d7,d1        ; select side in d1
  2680.     bsr.l    fd_side
  2681.  
  2682.     bsr.l    fd_ftrack
  2683.  
  2684. fdf_trkx
  2685.     tst.b    d0
  2686.  
  2687.     rts
  2688.  
  2689. fdf_9trans
  2690.     dc.w    5
  2691.     dc.b    $00,$03,$06,$01,$04,$07,$02,$05,$08
  2692.     dc.b    $80,$83,$86,$81,$84,$87,$82,$85,$88
  2693.     dc.b    $00,$03,$06,$01,$04,$07,$02,$05,$08
  2694.     dc.b    $09,$0c,$0f,$0a,$0d,$10,$0b,$0e,$11
  2695.  
  2696. ; --------------------------------------------------------------
  2697. ;
  2698. ;      BASIC extensions start here
  2699. ;
  2700. ; --------------------------------------------------------------
  2701. prog_use
  2702.     moveq    #$00,d5
  2703.     bra.s    xxx_use
  2704.  
  2705. data_use
  2706.     moveq    #$04,d5
  2707.     bra.s    xxx_use
  2708.  
  2709. dest_use
  2710.     moveq    #$08,d5
  2711.     bra.s    xxx_use
  2712.  
  2713. spl_use
  2714.     move.w    #$88,d5
  2715.  
  2716. xxx_use
  2717.     bsr.l    ut_stos        ; get a string
  2718.     bne.s    xxx_rts        ; ... oops
  2719.     cmp.w    #30,0(a6,a1.l)    ; <=30 characters long
  2720.     bgt    flp_bp        ; ... oops
  2721.  
  2722.     moveq    #MT.INF,d0    ; find the system variables
  2723.     trap    #1
  2724.     lea    SV_PROGD(a0),a0    ; and set the pointers to
  2725.                 ; the defaults
  2726.     move.w    d5,d0
  2727.     andi.b    #$7F,d0
  2728.     move.l    0(a0,d0.w),a4
  2729.  
  2730.     move.w    0(a6,a1.l),d1
  2731.     addq.l    #2,a1
  2732.     move.w    d1,(a4)+
  2733.  
  2734.     tst.b    d5
  2735.     bmi.s    xxx_dec
  2736.  
  2737.     lea    -1(a1,d1.w),a2
  2738.     cmpi.b    #'_',0(a6,a2.l)
  2739.  
  2740.     beq.s    xxx_dec
  2741.  
  2742.     cmpi.w    #30,d1
  2743.     beq    flp_bp        ; name too long
  2744.  
  2745.     move.b    #'_',0(a4,d1.w)    ; append underline
  2746.  
  2747.     addq.w    #1,d1
  2748.     move.w    d1,-2(a4)    ; increment length
  2749.     subq.w    #1,d1
  2750.  
  2751.     bra.s    xxx_dec
  2752.  
  2753. xxx_lup
  2754.     move.b    0(a6,a1.l),d0
  2755.     addq.l    #1,a1
  2756.     move.b    d0,(a4)+
  2757.  
  2758. xxx_dec
  2759.     dbra    d1,xxx_lup
  2760.  
  2761.     moveq    #0,d0
  2762.  
  2763. xxx_rts
  2764.     rts
  2765.  
  2766. prog_d$
  2767.     moveq    #0,d5
  2768.     bra.s    xxx_d$
  2769.  
  2770. data_d$
  2771.     moveq    #4,d5
  2772.     bra.s    xxx_d$
  2773.  
  2774. dest_d$
  2775.     moveq    #8,d5
  2776.     bra.s    xxx_d$
  2777.  
  2778. spl_d$
  2779.     moveq    #8,d5
  2780.  
  2781. xxx_d$
  2782.     cmp.l    a3,a5
  2783.     bne    flp_bp        ; ... oops
  2784.  
  2785.     moveq    #MT.INF,d0    ; find the system variables
  2786.     trap    #1
  2787.     lea    SV_PROGD(a0),a0    ; and set the pointers to
  2788.                 ; the defaults
  2789.     move.l    0(a0,d5),a4
  2790.  
  2791.     move.w    (a4)+,d4
  2792.  
  2793.     move.l    d4,d1
  2794.     addq.l    #1,d1
  2795.     and.b    #$FE,d1
  2796.     move.w    BV.CHRIX,a2
  2797.     jsr    (a2)
  2798.  
  2799.     sub.l    d1,BV_RIP(a6)
  2800.     move.l    BV_RIP(a6),a1
  2801.  
  2802.     move.w    d4,0(a6,a1.l)
  2803.     addq.l    #2,a1
  2804.     bra.s    xxx_dec$
  2805.  
  2806. xxx_lup$
  2807.     move.b    (a4)+,d0
  2808.     move.b    d0,0(a6,a1.l)
  2809.     addq.l    #1,a1
  2810.  
  2811. xxx_dec$
  2812.     dbra    d4,xxx_lup$
  2813.  
  2814.     move.l    BV_RIP(a6),a1
  2815.     moveq    #1,d4
  2816.     moveq    #0,d0
  2817.     rts
  2818.  
  2819. ; Set the name of the floppy disk system  1985 Tony Tebby QJUMP
  2820. ;       bra.s   dev_use        * Go to it.        ** 1.17 **
  2821.  
  2822. flp_use
  2823.     lea    fd_io(pc),a4    ; Get entry point for io
  2824.                 ; routines       ** 1.17 **
  2825. dev_use
  2826.     bsr.l    ut_stos        ; get a string
  2827.     bne.s    flp_rts        ; ... oops
  2828.     subq.w    #3,0(a6,a1.l)    ; 3 characters long
  2829.     bne.s    flp_bp        ; ... oops
  2830.     move.l    2(a6,a1.l),d6    ; get new name
  2831.     and.l    #$5f5f5f00,d6    ; in upper case
  2832.     add.b    #'0',d6        ; ending with '0'
  2833.  
  2834.     moveq    #MT.INF,d0    ; find system vars
  2835.     trap    #1
  2836.     move.l    SV_DDLST(a0),a0    ; ... and linked list of
  2837.                 ; directory drivers
  2838.  
  2839. flp_look
  2840.     cmp.l    fdd_iolk-fdd_ddlk(a0),a4 ; the right driver?
  2841.                        ;    ** 1.17 **
  2842.     beq.s    flp_set        ; ... yes
  2843.     move.l    (a0),a0        ; ... no, try the next
  2844.     move.l    a0,d1        ; ... the last?
  2845.     bne.s    flp_look
  2846. flp_bp
  2847.     moveq    #ERR.BP,d0
  2848. flp_rts
  2849.     rts
  2850. flp_set
  2851.     move.l    d6,fdd_name-fdd_ddlk(a0) ; set new name
  2852.     BSET    #7,fdd_nset-fdd_ddlk(a0) ; flag name as set
  2853.     rts
  2854.  
  2855.     ifd    extras
  2856.  
  2857. ; --------------------------------------------------------------
  2858. flp_opt
  2859.     move.w    CA.GTINT,a2
  2860.     jsr    (a2)
  2861.     bne.s    flo_rts
  2862.     subq.w    #1,d3
  2863.     blt.s    flo_rts
  2864.     bsr    flp_find
  2865.     movem.w    0(a6,a1.l),d4/d5/d6 ; get 3 parameters
  2866.  
  2867.     subq.b    #1,d4
  2868.     move.b    d4,fdd_scty-fdd_ddlk(a0) ; set security level
  2869.  
  2870.     subq.w    #1,d3
  2871.     blt.s    flo_rts
  2872.     move.b    d5,fdd_stim-fdd_ddlk(a0) ; set start up time
  2873.  
  2874.     subq.w    #1,d3
  2875.     blt.s    flo_rts
  2876.     move.b    d6,fdd_ntrk-fdd_ddlk(a0) ; set number of
  2877.                        ; tracks
  2878. flo_rts
  2879.     rts
  2880. flp_sec
  2881.     moveq    #fdd_scty-fdd_ddlk,d7 ; set security level
  2882.     bsr.s    flo_int
  2883.     subq.b    #1,(a0)        ; -1 to 1
  2884.     rts
  2885.  
  2886. flp_start
  2887.     moveq    #fdd_stim-fdd_ddlk,d7 ; set start up time
  2888.     bra.s    flo_dcall
  2889.  
  2890. flp_track
  2891.     moveq    #fdd_ntrk-fdd_ddlk,d7 ; set number of tracks
  2892. flo_dcall
  2893.     bsr.s    flo_int
  2894.     rts
  2895.  
  2896. flo_int
  2897.     move.l    (sp)+,a4     ; remove return address
  2898.     move.w    CA.GTINT,a2    ; get an integer
  2899.     jsr    (a2)
  2900.     bne.s    flo_rts
  2901.     subq.w    #1,d3        ; just one
  2902.     bne    flf_bp
  2903.     bsr    flp_find     ; find the definition block
  2904.     add.w    d7,a0        ; and the item to set
  2905.     move.b    1(a6,a1.l),(a0)    ; and set the byte
  2906.     jmp    (a4)
  2907.  
  2908.     endc
  2909.  
  2910. ; --------------------------------------------------------------
  2911. ; Get a string on the stack V0.2  1985 Tony Tebby QJUMP
  2912. ; Modified to accept numbers and expressions
  2913. ; (C) 1986 David Oliver CST V 4.00
  2914.  
  2915. ut_stos
  2916.     tst.w    2(a6,a3.l)    ; Get name of parameter. If
  2917.                 ; none, it must be exprssn.
  2918.     bmi.s    get_string    ; ... so convert the value
  2919.                 ; to a string.  ** 4.00 **
  2920.     moveq    #$0f,d0        ; extract type of parameter.
  2921.     and.b    1(a6,a3.l),d0
  2922.     subq.b    #1,d0        ; is it a string?
  2923.     bne.s    ut_gtnam     ; ... no, get the name
  2924.                 ; instead
  2925. get_string
  2926.     move.l    a5,-(sp)     ; ... yes, save the top
  2927.                 ; pointer
  2928.     lea    8(a3),a5     ; get just one string
  2929.     move.w    CA.GTSTR,a2
  2930.     jsr    (a2)
  2931.     move.l    (sp)+,a5     ; restore top pointer
  2932.     bne.s    utils_rts
  2933.     moveq    #3,d1        ; get total length of string
  2934.     add.w    0(a6,a1.l),d1
  2935.     bclr    #0,d1
  2936.     add.l    d1,BV_RIP(a6)    ; and reset ri stack pointer
  2937.     bra.s    utils_ok
  2938. ut_gtnam
  2939.     moveq    #ERR.BP,d0    ; assume bad parameter
  2940.     moveq    #0,d1
  2941.     move.w    2(a6,a3.l),d1    ; get the pointer to the
  2942.                 ; real entry
  2943.     bmi.s    utils_rts    ; ... expression is no good
  2944.     lsl.l    #3,d1        ; in multiples of 8 bytes
  2945.     add.l    BV_NTBAS(a6),d1
  2946. ut_ntnam
  2947.     moveq    #0,d6
  2948.     move.w    2(a6,d1.l),d6    ; thus the pointer to the
  2949.                 ; name
  2950.     add.l    BV_NLBAS(a6),d6
  2951.     moveq    #0,d1        ; get the length of the name
  2952.                 ; as a long word
  2953.     move.b    0(a6,d6.l),d1
  2954.     addq.l    #1,d1        ; rounded up
  2955.     bclr    #0,d1
  2956.     move.w    d1,d4        ; and save it
  2957.     addq.l    #2,d1        ; space required is +2 bytes
  2958.     move.w    BV.CHRIX,a2    ; on ri stack
  2959.     jsr    (a2)
  2960.     move.l    BV_RIP(a6),a1
  2961.  
  2962.     add.w    d4,d6        ; move to end of string
  2963.                 ; (ish)
  2964. ut_nam_loop
  2965.     subq.l    #1,a1        ; and copy one byte at a
  2966.                 ; time
  2967.     move.b    0(a6,d6.l),0(a6,a1.l)
  2968.     subq.l    #1,d6
  2969.     dbra    d4,ut_nam_loop    ; including the (byte) name
  2970.                 ; length
  2971.     subq.l    #1,a1        ; put a zero on to make it a
  2972.                 ; word
  2973.     clr.b    0(a6,a1.l)
  2974. utils_ok
  2975.     moveq    #0,d0
  2976. utils_rts
  2977.     rts
  2978. ; --------------------------------------------------------------
  2979. */endfile
  2980.